From 800a3faa71d1b467adcda36c8903d229a8d11b00 Mon Sep 17 00:00:00 2001 From: Anna Veselova <47113149+aveselova@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:22:42 -0600 Subject: [PATCH] SERVER-109200: Upgrade MozJS to esr140.3 (#44151) Co-authored-by: Erin Zhu Co-authored-by: Lee Maguire GitOrigin-RevId: e9c2c8cb36c2aeae7a7150326154b8e676122057 --- README.third_party.md | 2 +- ...kports_required_for_multiversion_tests.yml | 4 + .../accumulator_js_size_limits.js | 12 +- jstests/core/query/js/js_global_scope.js | 2 + .../query/agg/agg_merge_explain_size_limit.js | 2 +- .../sharding/query/javascript_heap_limit.js | 25 + sbom.json | 12 +- src/mongo/scripting/engine.h | 2 + src/mongo/scripting/mozjs/engine.cpp | 8 + src/mongo/scripting/mozjs/engine.h | 3 + src/mongo/scripting/mozjs/engine.idl | 8 + src/mongo/scripting/mozjs/exception.cpp | 1 + src/mongo/scripting/mozjs/implscope.cpp | 16 +- .../scripting/mozjs/jscustomallocator.cpp | 82 +- .../mozjs/jscustomallocator_test.cpp | 10 +- src/mongo/scripting/mozjs/module_loader.cpp | 55 +- src/mongo/scripting/mozjs/wraptype.h | 18 +- src/third_party/mozjs/BUILD.bazel | 18 +- src/third_party/mozjs/extract.sh | 28 +- .../mozjs/extract/js/public/AllocPolicy.h | 51 +- .../extract/js/public/CharacterEncoding.h | 20 - .../mozjs/extract/js/public/Class.h | 5 - .../js/public/CompilationAndEvaluation.h | 14 +- .../mozjs/extract/js/public/CompileOptions.h | 99 +- .../mozjs/extract/js/public/ContextOptions.h | 42 - .../mozjs/extract/js/public/Conversions.h | 16 +- .../mozjs/extract/js/public/Debug.h | 178 +- .../extract/js/public/EnvironmentChain.h | 67 + .../mozjs/extract/js/public/ErrorReport.h | 30 + .../mozjs/extract/js/public/GCAPI.h | 69 +- .../mozjs/extract/js/public/GCHashTable.h | 15 + .../mozjs/extract/js/public/GCPolicyAPI.h | 34 + .../mozjs/extract/js/public/GCVector.h | 2 +- .../mozjs/extract/js/public/HeapAPI.h | 256 +- .../mozjs/extract/js/public/HelperThreadAPI.h | 4 + src/third_party/mozjs/extract/js/public/Id.h | 11 +- .../mozjs/extract/js/public/Initialization.h | 1 - .../mozjs/extract/js/public/JSON.h | 7 + .../mozjs/extract/js/public/JitCodeAPI.h | 97 - .../mozjs/extract/js/public/MapAndSet.h | 6 + .../mozjs/extract/js/public/MemoryMetrics.h | 65 +- .../mozjs/extract/js/public/Modules.h | 38 +- .../extract/js/public/NativeStackLimits.h | 52 + .../js/public/ObjectWithStashedPointer.h | 72 + .../mozjs/extract/js/public/Prefs.h | 20 - .../mozjs/extract/js/public/Principals.h | 56 +- .../mozjs/extract/js/public/Printer.h | 149 +- .../js/public/ProfilingFrameIterator.h | 4 +- .../mozjs/extract/js/public/ProfilingStack.h | 10 +- .../mozjs/extract/js/public/Promise.h | 91 +- .../mozjs/extract/js/public/PropertySpec.h | 2 +- .../mozjs/extract/js/public/ProtoKey.h | 213 +- .../mozjs/extract/js/public/Proxy.h | 55 +- .../mozjs/extract/js/public/Realm.h | 10 + .../mozjs/extract/js/public/RealmOptions.h | 6 + .../mozjs/extract/js/public/RefCounted.h | 6 +- .../mozjs/extract/js/public/RegExpFlags.h | 4 +- .../mozjs/extract/js/public/RootingAPI.h | 282 +- .../mozjs/extract/js/public/SliceBudget.h | 4 +- .../mozjs/extract/js/public/Stack.h | 42 +- .../mozjs/extract/js/public/String.h | 113 +- .../mozjs/extract/js/public/StructuredClone.h | 23 +- .../mozjs/extract/js/public/Symbol.h | 31 +- .../mozjs/extract/js/public/TraceKind.h | 33 +- .../mozjs/extract/js/public/TracingAPI.h | 8 +- .../mozjs/extract/js/public/Transcoding.h | 53 +- .../mozjs/extract/js/public/TypeDecls.h | 16 - .../mozjs/extract/js/public/UbiNode.h | 20 + .../mozjs/extract/js/public/Utility.h | 58 +- .../mozjs/extract/js/public/Value.h | 107 +- .../mozjs/extract/js/public/WasmFeatures.h | 36 +- .../mozjs/extract/js/public/Wrapper.h | 3 + .../js/public/experimental/BindingAllocs.h | 31 + .../js/public/experimental/JSStencil.h | 61 +- .../js/public/experimental/LoggingInterface.h | 98 + .../js/public/experimental/TypedData.h | 7 +- .../extract/js/public/friend/ErrorNumbers.msg | 243 +- .../extract/js/public/friend/JSMEnvironment.h | 4 +- .../js/public/friend/UsageStatistics.h | 59 +- .../mozjs/extract/js/public/shadow/String.h | 2 + .../mozjs/extract/js/src/GeneratePrefs.py | 33 +- .../mozjs/extract/js/src/NamespaceImports.h | 10 +- .../mozjs/extract/js/src/aclocal.m4 | 31 - .../mozjs/extract/js/src/builtin/.eslintrc.js | 175 - .../extract/js/src/builtin/.eslintrc.mjs | 178 + .../mozjs/extract/js/src/builtin/Array.cpp | 633 +- .../mozjs/extract/js/src/builtin/Array.h | 88 +- .../mozjs/extract/js/src/builtin/Array.js | 26 +- .../js/src/builtin/AsyncDisposableStack.js | 54 + .../builtin/AsyncDisposableStackObject.cpp | 391 + .../src/builtin/AsyncDisposableStackObject.h | 47 + .../extract/js/src/builtin/AtomicsObject.cpp | 991 +- .../extract/js/src/builtin/AtomicsObject.h | 62 +- .../mozjs/extract/js/src/builtin/BigInt.cpp | 41 +- .../mozjs/extract/js/src/builtin/Boolean.cpp | 21 +- .../extract/js/src/builtin/DataViewObject.cpp | 48 +- .../extract/js/src/builtin/DisposableStack.js | 43 + .../js/src/builtin/DisposableStackObject.cpp | 373 + .../js/src/builtin/DisposableStackObject.h | 49 + .../src/builtin/DisposableStackObjectBase.cpp | 319 + .../src/builtin/DisposableStackObjectBase.h | 69 + .../mozjs/extract/js/src/builtin/Eval.cpp | 71 +- .../builtin/FinalizationRegistryObject.cpp | 61 +- .../src/builtin/FinalizationRegistryObject.h | 6 +- .../mozjs/extract/js/src/builtin/Iterator.js | 379 +- .../mozjs/extract/js/src/builtin/JSON.cpp | 387 +- .../mozjs/extract/js/src/builtin/JSON.h | 4 +- .../mozjs/extract/js/src/builtin/Map.js | 53 +- .../extract/js/src/builtin/MapObject-inl.h | 114 + .../extract/js/src/builtin/MapObject.cpp | 1759 +- .../mozjs/extract/js/src/builtin/MapObject.h | 321 +- .../extract/js/src/builtin/ModuleObject.cpp | 264 +- .../extract/js/src/builtin/ModuleObject.h | 30 +- .../mozjs/extract/js/src/builtin/Object.cpp | 147 +- .../src/builtin/OrderedHashTableObject-inl.h | 19 + .../js/src/builtin/OrderedHashTableObject.h | 1543 ++ .../js/src/builtin/ParseRecordObject.cpp | 69 +- .../js/src/builtin/ParseRecordObject.h | 68 +- .../extract/js/src/builtin/Profilers.cpp | 17 +- .../mozjs/extract/js/src/builtin/Profilers.h | 2 +- .../mozjs/extract/js/src/builtin/Promise.cpp | 507 +- .../mozjs/extract/js/src/builtin/Promise.h | 23 + .../extract/js/src/builtin/RawJSONObject.cpp | 11 +- .../extract/js/src/builtin/RecordObject.cpp | 77 - .../extract/js/src/builtin/RecordObject.h | 31 - .../mozjs/extract/js/src/builtin/Reflect.cpp | 23 +- .../extract/js/src/builtin/ReflectParse.cpp | 69 +- .../mozjs/extract/js/src/builtin/RegExp.cpp | 538 +- .../mozjs/extract/js/src/builtin/RegExp.h | 18 +- .../mozjs/extract/js/src/builtin/RegExp.js | 104 +- .../js/src/builtin/SelfHostingDefines.h | 70 +- .../mozjs/extract/js/src/builtin/Set.js | 2 +- .../extract/js/src/builtin/ShadowRealm.cpp | 21 +- .../mozjs/extract/js/src/builtin/String.cpp | 525 +- .../mozjs/extract/js/src/builtin/String.h | 4 +- .../mozjs/extract/js/src/builtin/String.js | 128 +- .../mozjs/extract/js/src/builtin/Symbol.cpp | 23 +- .../js/src/builtin/TestingFunctions.cpp | 971 +- .../extract/js/src/builtin/TestingUtility.cpp | 6 +- .../extract/js/src/builtin/TestingUtility.h | 9 +- .../mozjs/extract/js/src/builtin/Tuple.js | 711 - .../extract/js/src/builtin/TupleObject.cpp | 104 - .../extract/js/src/builtin/TupleObject.h | 34 - .../extract/js/src/builtin/TypedArray.js | 740 +- .../mozjs/extract/js/src/builtin/Utilities.js | 3 - .../mozjs/extract/js/src/builtin/WeakMap.js | 50 + .../js/src/builtin/WeakMapObject-inl.h | 44 +- .../extract/js/src/builtin/WeakMapObject.cpp | 179 +- .../extract/js/src/builtin/WeakMapObject.h | 17 +- .../extract/js/src/builtin/WeakRefObject.cpp | 21 +- .../extract/js/src/builtin/WeakSetObject.cpp | 119 +- .../extract/js/src/builtin/WeakSetObject.h | 13 +- .../js/src/builtin/WrappedFunctionObject.cpp | 2 +- .../mozjs/extract/js/src/builtin/embedjs.py | 2 +- .../extract/js/src/builtin/intl/Collator.cpp | 18 +- .../js/src/builtin/intl/CommonFunctions.cpp | 10 +- .../js/src/builtin/intl/CommonFunctions.h | 6 + .../js/src/builtin/intl/CommonFunctions.js | 7 + .../src/builtin/intl/CurrencyDataGenerated.js | 2 +- .../js/src/builtin/intl/DateTimeFormat.cpp | 1341 +- .../js/src/builtin/intl/DateTimeFormat.h | 66 +- .../js/src/builtin/intl/DateTimeFormat.js | 228 +- .../js/src/builtin/intl/DisplayNames.cpp | 33 +- .../js/src/builtin/intl/DurationFormat.cpp | 186 + .../js/src/builtin/intl/DurationFormat.h | 50 + .../js/src/builtin/intl/DurationFormat.js | 1623 ++ .../js/src/builtin/intl/FormatBuffer.h | 18 +- .../js/src/builtin/intl/IntlObject.cpp | 79 +- .../js/src/builtin/intl/LanguageTag.cpp | 4 +- .../js/src/builtin/intl/ListFormat.cpp | 17 +- .../extract/js/src/builtin/intl/Locale.cpp | 44 +- .../js/src/builtin/intl/NumberFormat.cpp | 13 +- .../js/src/builtin/intl/NumberFormat.js | 129 +- .../js/src/builtin/intl/NumberingSystems.yaml | 8 + .../builtin/intl/NumberingSystemsGenerated.h | 8 + .../js/src/builtin/intl/PluralRules.cpp | 34 +- .../src/builtin/intl/RelativeTimeFormat.cpp | 16 +- .../extract/js/src/builtin/intl/Segmenter.cpp | 45 +- .../js/src/builtin/intl/SharedIntlData.cpp | 7 +- .../js/src/builtin/intl/SharedIntlData.h | 7 +- .../js/src/builtin/intl/StringAsciiChars.h | 4 +- .../src/builtin/intl/TimeZoneDataGenerated.h | 81 +- .../js/src/builtin/intl/TimeZoneMapping.yaml | 157 + .../js/src/builtin/intl/make_intl_data.py | 897 +- .../js/src/builtin/temporal/Calendar.cpp | 8203 +++++----- .../js/src/builtin/temporal/Calendar.h | 981 +- .../src/builtin/temporal/CalendarFields.cpp | 654 + .../js/src/builtin/temporal/CalendarFields.h | 387 + .../js/src/builtin/temporal/Duration.cpp | 5432 +++---- .../js/src/builtin/temporal/Duration.h | 257 +- .../extract/js/src/builtin/temporal/Era.h | 298 + .../js/src/builtin/temporal/Instant.cpp | 643 +- .../extract/js/src/builtin/temporal/Instant.h | 82 +- .../js/src/builtin/temporal/MonthCode.h | 496 + .../js/src/builtin/temporal/PlainDate.cpp | 2457 +-- .../js/src/builtin/temporal/PlainDate.h | 235 +- .../js/src/builtin/temporal/PlainDateTime.cpp | 2086 +-- .../js/src/builtin/temporal/PlainDateTime.h | 223 +- .../js/src/builtin/temporal/PlainMonthDay.cpp | 791 +- .../js/src/builtin/temporal/PlainMonthDay.h | 95 +- .../js/src/builtin/temporal/PlainTime.cpp | 1129 +- .../js/src/builtin/temporal/PlainTime.h | 112 +- .../src/builtin/temporal/PlainYearMonth.cpp | 1288 +- .../js/src/builtin/temporal/PlainYearMonth.h | 90 +- .../js/src/builtin/temporal/Temporal.cpp | 387 +- .../js/src/builtin/temporal/Temporal.h | 75 +- .../src/builtin/temporal/TemporalFields.cpp | 1052 -- .../js/src/builtin/temporal/TemporalFields.h | 353 - .../js/src/builtin/temporal/TemporalNow.cpp | 391 +- .../src/builtin/temporal/TemporalParser.cpp | 1828 +-- .../js/src/builtin/temporal/TemporalParser.h | 80 +- .../js/src/builtin/temporal/TemporalTypes.h | 472 +- .../js/src/builtin/temporal/TimeZone.cpp | 2584 +-- .../js/src/builtin/temporal/TimeZone.h | 611 +- .../js/src/builtin/temporal/ToString.cpp | 288 +- .../js/src/builtin/temporal/ToString.h | 24 +- .../js/src/builtin/temporal/Wrapped.cpp | 22 - .../extract/js/src/builtin/temporal/Wrapped.h | 169 - .../js/src/builtin/temporal/ZonedDateTime.cpp | 3563 ++--- .../js/src/builtin/temporal/ZonedDateTime.h | 174 +- .../extract/js/src/builtin/temporal/moz.build | 44 +- .../mozjs/extract/js/src/debugger/DebugAPI.h | 6 + .../extract/js/src/debugger/DebugScript.cpp | 4 +- .../extract/js/src/debugger/DebugScript.h | 3 +- .../extract/js/src/debugger/Debugger.cpp | 504 +- .../mozjs/extract/js/src/debugger/Debugger.h | 56 +- .../js/src/debugger/DebuggerMemory.cpp | 14 +- .../extract/js/src/debugger/Environment.cpp | 13 +- .../js/src/debugger/ExecutionTracer.cpp | 516 + .../extract/js/src/debugger/ExecutionTracer.h | 477 + .../mozjs/extract/js/src/debugger/Frame.cpp | 178 +- .../mozjs/extract/js/src/debugger/Frame.h | 6 + .../mozjs/extract/js/src/debugger/Object.cpp | 90 +- .../mozjs/extract/js/src/debugger/Script.cpp | 51 +- .../mozjs/extract/js/src/debugger/Source.cpp | 23 +- .../mozjs/extract/js/src/debugger/moz.build | 3 + .../js/src/devtools/automation/autospider.py | 97 +- .../smoosh-jittest-known-failure.txt | 4 - .../smoosh-jstests-known-failure-and-slow.txt | 81 - .../smoosh-jstests-known-failure.txt | 73 - .../devtools/automation/variants/arm64-sim | 6 +- .../devtools/automation/variants/compacting | 8 +- .../src/devtools/automation/variants/fuzzilli | 4 +- .../src/devtools/automation/variants/fuzzing | 6 +- .../js/src/devtools/automation/variants/gdb | 4 +- .../js/src/devtools/automation/variants/msan | 6 +- .../devtools/automation/variants/nonunified | 3 - .../js/src/devtools/automation/variants/plain | 6 +- .../devtools/automation/variants/rootanalysis | 8 +- .../src/devtools/automation/variants/rtdebug | 8 - .../src/devtools/automation/variants/smoosh | 8 - .../devtools/automation/variants/smooshdebug | 8 - .../automation/variants/temporaldebug | 7 - .../js/src/devtools/automation/variants/tsan | 8 +- .../js/src/devtools/automation/variants/wasi | 4 +- .../devtools/automation/variants/wasi-intl | 4 +- .../src/devtools/automation/variants/wasi-pbl | 4 +- .../extract/js/src/devtools/gc/gc-test.py | 2 +- .../extract/js/src/devtools/iongraph/iongraph | 64 +- .../js/src/devtools/rootAnalysis/analyze.py | 8 +- .../src/devtools/rootAnalysis/annotations.js | 13 +- .../js/src/devtools/rootAnalysis/explain.py | 4 +- .../devtools/rootAnalysis/mach_commands.py | 10 +- .../devtools/rootAnalysis/mozconfig.haz_shell | 2 - .../js/src/devtools/rootAnalysis/run-test.py | 2 +- .../src/devtools/rootAnalysis/t/graph/test.py | 4 +- .../rootAnalysis/t/hazards/source.cpp | 10 + .../devtools/rootAnalysis/t/hazards/test.py | 7 + .../js/src/devtools/rootAnalysis/t/testlib.py | 19 +- .../devtools/rootAnalysis/t/types/source.cpp | 8 +- .../src/devtools/rootAnalysis/t/types/test.py | 1 - .../rootAnalysis/t/virtual/source.cpp | 2 +- .../mozjs/extract/js/src/ds/BitArray.h | 2 +- .../mozjs/extract/js/src/ds/Bitmap.h | 2 +- .../mozjs/extract/js/src/ds/InlineTable.h | 307 +- .../mozjs/extract/js/src/ds/LifoAlloc.cpp | 14 +- .../mozjs/extract/js/src/ds/LifoAlloc.h | 24 +- .../extract/js/src/ds/OrderedHashTable.h | 1150 -- .../mozjs/extract/js/src/ds/PriorityQueue.h | 47 +- .../extract/js/src/ds/SinglyLinkedList.h | 115 +- .../mozjs/extract/js/src/ds/SlimLinkedList.h | 439 + .../extract/js/src/frontend/AsyncEmitter.h | 2 +- .../js/src/frontend/BytecodeCompiler.cpp | 755 +- .../js/src/frontend/BytecodeCompiler.h | 64 +- .../js/src/frontend/BytecodeEmitter.cpp | 886 +- .../extract/js/src/frontend/BytecodeEmitter.h | 68 +- .../extract/js/src/frontend/BytecodeSection.h | 6 +- .../js/src/frontend/CompilationStencil.h | 259 +- .../extract/js/src/frontend/CompileScript.cpp | 186 - .../js/src/frontend/DecoratorEmitter.cpp | 3 +- .../js/src/frontend/DecoratorEmitter.h | 2 +- .../extract/js/src/frontend/ElemOpEmitter.cpp | 45 +- .../extract/js/src/frontend/ElemOpEmitter.h | 69 +- .../extract/js/src/frontend/EmitterScope.cpp | 72 +- .../extract/js/src/frontend/EmitterScope.h | 45 +- .../frontend/ExpressionStatementEmitter.cpp | 2 - .../extract/js/src/frontend/FoldConstants.cpp | 66 +- .../extract/js/src/frontend/FoldConstants.h | 5 +- .../extract/js/src/frontend/ForOfEmitter.cpp | 62 +- .../extract/js/src/frontend/ForOfEmitter.h | 10 +- .../js/src/frontend/ForOfLoopControl.cpp | 50 +- .../js/src/frontend/ForOfLoopControl.h | 15 +- .../extract/js/src/frontend/Frontend2.cpp | 703 - .../mozjs/extract/js/src/frontend/Frontend2.h | 61 - .../js/src/frontend/FrontendContext.cpp | 78 +- .../js/src/frontend/FullParseHandler.h | 39 +- .../js/src/frontend/GenerateReservedWords.py | 26 +- .../js/src/frontend/LexicalScopeEmitter.cpp | 14 +- .../js/src/frontend/LexicalScopeEmitter.h | 7 +- .../js/src/frontend/NameAnalysisTypes.h | 7 +- .../extract/js/src/frontend/NameCollections.h | 27 +- .../extract/js/src/frontend/NameFunctions.cpp | 4 +- .../extract/js/src/frontend/NameOpEmitter.cpp | 189 +- .../extract/js/src/frontend/NameOpEmitter.h | 6 + .../extract/js/src/frontend/ObjLiteral.cpp | 101 +- .../extract/js/src/frontend/ObjectEmitter.cpp | 7 +- .../extract/js/src/frontend/ObjectEmitter.h | 2 +- .../extract/js/src/frontend/ParseContext.h | 6 +- .../mozjs/extract/js/src/frontend/ParseNode.h | 19 +- .../mozjs/extract/js/src/frontend/Parser.cpp | 404 +- .../mozjs/extract/js/src/frontend/Parser.h | 27 +- .../extract/js/src/frontend/ParserAtom.cpp | 29 +- .../extract/js/src/frontend/ParserAtom.h | 4 +- .../js/src/frontend/PrivateOpEmitter.cpp | 15 +- .../js/src/frontend/PrivateOpEmitter.h | 8 +- .../extract/js/src/frontend/PropOpEmitter.cpp | 13 +- .../extract/js/src/frontend/PropOpEmitter.h | 71 +- .../extract/js/src/frontend/SharedContext.h | 14 +- .../mozjs/extract/js/src/frontend/Stencil.cpp | 746 +- .../mozjs/extract/js/src/frontend/Stencil.h | 112 +- .../extract/js/src/frontend/StencilXdr.cpp | 135 +- .../extract/js/src/frontend/StencilXdr.h | 13 +- .../extract/js/src/frontend/SwitchEmitter.cpp | 5 +- .../js/src/frontend/SyntaxParseHandler.h | 10 +- .../mozjs/extract/js/src/frontend/Token.h | 5 +- .../mozjs/extract/js/src/frontend/TokenKind.h | 4 +- .../extract/js/src/frontend/TokenStream.cpp | 13 +- .../extract/js/src/frontend/TryEmitter.cpp | 11 +- .../extract/js/src/frontend/TryEmitter.h | 29 +- .../extract/js/src/frontend/TypedIndex.h | 2 +- .../extract/js/src/frontend/UsingEmitter.cpp | 1447 +- .../extract/js/src/frontend/UsingEmitter.h | 246 +- .../extract/js/src/frontend/WhileEmitter.cpp | 2 +- .../extract/js/src/frontend/WhileEmitter.h | 4 +- .../js/src/frontend/align_stack_comment.py | 14 +- .../mozjs/extract/js/src/frontend/moz.build | 9 - .../js/src/fuzz-tests/differential-parsing.js | 148 - .../js/src/fuzz-tests/gluesmith/Cargo.toml | 3 +- .../extract/js/src/fuzz-tests/testWasm.cpp | 22 +- .../mozjs/extract/js/src/fuzz-tests/tests.cpp | 10 +- .../mozjs/extract/js/src/gc/AllocKind.h | 173 +- .../mozjs/extract/js/src/gc/Allocator-inl.h | 80 +- .../mozjs/extract/js/src/gc/Allocator.cpp | 432 +- .../mozjs/extract/js/src/gc/Allocator.h | 112 +- .../mozjs/extract/js/src/gc/ArenaList-inl.h | 192 +- .../mozjs/extract/js/src/gc/ArenaList.h | 161 +- .../mozjs/extract/js/src/gc/AtomMarking.cpp | 59 +- .../mozjs/extract/js/src/gc/AtomMarking.h | 20 +- .../mozjs/extract/js/src/gc/Barrier.cpp | 34 +- .../mozjs/extract/js/src/gc/Barrier.h | 12 +- .../extract/js/src/gc/BufferAllocator-inl.h | 148 + .../extract/js/src/gc/BufferAllocator.cpp | 2822 ++++ .../mozjs/extract/js/src/gc/BufferAllocator.h | 526 + .../mozjs/extract/js/src/gc/Cell.h | 94 +- .../mozjs/extract/js/src/gc/Compacting.cpp | 285 +- .../js/src/gc/FinalizationObservers.cpp | 22 +- .../mozjs/extract/js/src/gc/GC-inl.h | 41 +- .../mozjs/extract/js/src/gc/GC.cpp | 696 +- src/third_party/mozjs/extract/js/src/gc/GC.h | 12 +- .../mozjs/extract/js/src/gc/GCAPI.cpp | 15 +- .../mozjs/extract/js/src/gc/GCContext.h | 6 + .../mozjs/extract/js/src/gc/GCEnum.h | 8 +- .../mozjs/extract/js/src/gc/GCInternals.h | 38 +- .../mozjs/extract/js/src/gc/GCMarker.h | 120 +- .../mozjs/extract/js/src/gc/GCParallelTask.h | 4 +- .../mozjs/extract/js/src/gc/GCRuntime.h | 277 +- .../extract/js/src/gc/GenerateStatsPhases.py | 4 +- .../mozjs/extract/js/src/gc/Heap-inl.h | 247 +- .../mozjs/extract/js/src/gc/Heap.cpp | 370 +- .../mozjs/extract/js/src/gc/Heap.h | 303 +- .../mozjs/extract/js/src/gc/Marking-inl.h | 6 +- .../mozjs/extract/js/src/gc/Marking.cpp | 385 +- .../mozjs/extract/js/src/gc/Memory.cpp | 167 +- .../mozjs/extract/js/src/gc/Memory.h | 30 +- .../mozjs/extract/js/src/gc/Nursery-inl.h | 139 +- .../mozjs/extract/js/src/gc/Nursery.cpp | 486 +- .../mozjs/extract/js/src/gc/Nursery.h | 182 +- .../extract/js/src/gc/NurseryAwareHashMap.h | 3 +- .../mozjs/extract/js/src/gc/ObjectKind-inl.h | 93 +- .../extract/js/src/gc/ParallelMarking.cpp | 57 +- .../mozjs/extract/js/src/gc/ParallelMarking.h | 8 +- .../mozjs/extract/js/src/gc/ParallelWork.h | 6 +- .../mozjs/extract/js/src/gc/Pretenuring.cpp | 6 +- .../mozjs/extract/js/src/gc/Pretenuring.h | 66 +- .../mozjs/extract/js/src/gc/PublicIterators.h | 7 +- .../mozjs/extract/js/src/gc/RootMarking.cpp | 3 +- .../mozjs/extract/js/src/gc/Scheduling.cpp | 31 +- .../mozjs/extract/js/src/gc/Scheduling.h | 40 +- .../mozjs/extract/js/src/gc/Statistics.cpp | 153 +- .../mozjs/extract/js/src/gc/Statistics.h | 48 +- .../js/src/gc/StatsPhasesGenerated.inc | 10 +- .../mozjs/extract/js/src/gc/StoreBuffer-inl.h | 9 +- .../mozjs/extract/js/src/gc/StoreBuffer.cpp | 42 +- .../mozjs/extract/js/src/gc/StoreBuffer.h | 90 +- .../mozjs/extract/js/src/gc/Sweeping.cpp | 633 +- .../mozjs/extract/js/src/gc/Tenuring.cpp | 960 +- .../mozjs/extract/js/src/gc/Tenuring.h | 38 +- .../extract/js/src/gc/TraceMethods-inl.h | 14 - .../mozjs/extract/js/src/gc/Tracer.cpp | 3 +- .../mozjs/extract/js/src/gc/Tracer.h | 18 + .../mozjs/extract/js/src/gc/Verifier.cpp | 392 +- .../mozjs/extract/js/src/gc/WeakMap-inl.h | 140 +- .../mozjs/extract/js/src/gc/WeakMap.cpp | 62 +- .../mozjs/extract/js/src/gc/WeakMap.h | 234 +- .../mozjs/extract/js/src/gc/WeakMapPtr.cpp | 7 +- .../mozjs/extract/js/src/gc/Zone.cpp | 76 +- .../mozjs/extract/js/src/gc/Zone.h | 71 +- .../mozjs/extract/js/src/gc/moz.build | 11 +- .../extract/js/src/ics/remove-duplicates.py | 22 + .../js/src/intgemm/IntegerGemmIntrinsic.cpp | 179 +- .../js/src/intgemm/IntegerGemmIntrinsic.h | 2 +- .../extract/js/src/irregexp/RegExpAPI.cpp | 31 +- .../irregexp/RegExpNativeMacroAssembler.cpp | 95 +- .../src/irregexp/RegExpNativeMacroAssembler.h | 20 +- .../extract/js/src/irregexp/RegExpShim.cpp | 52 +- .../extract/js/src/irregexp/RegExpShim.h | 166 +- .../js/src/irregexp/import-irregexp.py | 9 +- .../js/src/irregexp/imported/regexp-ast.cc | 4 +- .../js/src/irregexp/imported/regexp-ast.h | 28 +- .../imported/regexp-bytecode-generator.cc | 31 +- .../imported/regexp-bytecode-generator.h | 9 +- .../imported/regexp-bytecode-peephole.cc | 8 +- .../imported/regexp-bytecode-peephole.h | 6 +- .../imported/regexp-compiler-tonode.cc | 43 +- .../src/irregexp/imported/regexp-compiler.cc | 386 +- .../src/irregexp/imported/regexp-compiler.h | 16 +- .../irregexp/imported/regexp-dotprinter.cc | 1 + .../js/src/irregexp/imported/regexp-error.h | 1 - .../irregexp/imported/regexp-interpreter.cc | 142 +- .../irregexp/imported/regexp-interpreter.h | 41 +- .../imported/regexp-macro-assembler-tracer.cc | 60 +- .../imported/regexp-macro-assembler-tracer.h | 13 +- .../imported/regexp-macro-assembler.cc | 55 +- .../imported/regexp-macro-assembler.h | 25 +- .../js/src/irregexp/imported/regexp-nodes.h | 64 +- .../js/src/irregexp/imported/regexp-parser.cc | 52 +- .../js/src/irregexp/imported/regexp-parser.h | 3 +- .../js/src/irregexp/imported/regexp-stack.cc | 6 +- .../js/src/irregexp/imported/regexp-stack.h | 32 +- .../extract/js/src/irregexp/imported/regexp.h | 162 +- .../mozjs/extract/js/src/irregexp/moz.yaml | 4 +- .../extract/js/src/jit/ABIArgGenerator.h | 2 + .../extract/js/src/jit/ABIFunctionList-inl.h | 247 +- .../extract/js/src/jit/ABIFunctionType.h | 4 +- .../extract/js/src/jit/ABIFunctionType.yaml | 38 + .../extract/js/src/jit/AliasAnalysis.cpp | 1 + .../mozjs/extract/js/src/jit/AliasAnalysis.h | 5 +- .../js/src/jit/AlignmentMaskAnalysis.cpp | 1 + .../mozjs/extract/js/src/jit/Assembler.h | 2 - .../mozjs/extract/js/src/jit/AtomicOp.h | 127 +- .../extract/js/src/jit/AtomicOperations.h | 5 +- .../extract/js/src/jit/AutoWritableJitCode.h | 24 +- .../js/src/jit/BacktrackingAllocator.cpp | 1996 ++- .../js/src/jit/BacktrackingAllocator.h | 346 +- .../mozjs/extract/js/src/jit/Bailouts.cpp | 6 +- .../extract/js/src/jit/BaselineBailouts.cpp | 25 +- .../js/src/jit/BaselineCacheIRCompiler.cpp | 387 +- .../js/src/jit/BaselineCacheIRCompiler.h | 13 +- .../extract/js/src/jit/BaselineCodeGen.cpp | 1439 +- .../extract/js/src/jit/BaselineCodeGen.h | 110 +- .../extract/js/src/jit/BaselineCompileQueue.h | 71 + .../js/src/jit/BaselineCompileTask.cpp | 160 + .../extract/js/src/jit/BaselineCompileTask.h | 132 + .../js/src/jit/BaselineDebugModeOSR.cpp | 9 +- .../extract/js/src/jit/BaselineDebugModeOSR.h | 3 + .../extract/js/src/jit/BaselineFrame.cpp | 6 +- .../mozjs/extract/js/src/jit/BaselineFrame.h | 10 +- .../extract/js/src/jit/BaselineFrameInfo.h | 8 +- .../mozjs/extract/js/src/jit/BaselineIC.cpp | 175 +- .../mozjs/extract/js/src/jit/BaselineIC.h | 15 +- .../mozjs/extract/js/src/jit/BaselineICList.h | 6 +- .../mozjs/extract/js/src/jit/BaselineJIT.cpp | 335 +- .../mozjs/extract/js/src/jit/BaselineJIT.h | 26 +- .../extract/js/src/jit/BranchHinting.cpp | 2 +- .../mozjs/extract/js/src/jit/BranchHinting.h | 2 +- .../extract/js/src/jit/BytecodeAnalysis.cpp | 10 +- .../extract/js/src/jit/BytecodeAnalysis.h | 9 + .../mozjs/extract/js/src/jit/CacheIR.cpp | 3749 +++-- .../mozjs/extract/js/src/jit/CacheIR.h | 86 +- .../mozjs/extract/js/src/jit/CacheIRAOT.cpp | 146 + .../mozjs/extract/js/src/jit/CacheIRAOT.h | 47 + .../extract/js/src/jit/CacheIRCompiler.cpp | 1616 +- .../extract/js/src/jit/CacheIRCompiler.h | 7 + .../extract/js/src/jit/CacheIRGenerator.h | 139 +- .../mozjs/extract/js/src/jit/CacheIROps.yaml | 355 +- .../extract/js/src/jit/CacheIRSpewer.cpp | 265 +- .../mozjs/extract/js/src/jit/CacheIRSpewer.h | 33 +- .../mozjs/extract/js/src/jit/CacheIRWriter.h | 35 +- .../extract/js/src/jit/CodeGenerator.cpp | 6881 ++++---- .../mozjs/extract/js/src/jit/CodeGenerator.h | 238 +- .../mozjs/extract/js/src/jit/CompactBuffer.h | 5 + .../js/src/jit/CompilationDependencyTracker.h | 85 + .../mozjs/extract/js/src/jit/CompileInfo.h | 12 +- .../extract/js/src/jit/CompileWrappers.cpp | 26 +- .../extract/js/src/jit/CompileWrappers.h | 13 +- .../extract/js/src/jit/DominatorTree.cpp | 337 + .../mozjs/extract/js/src/jit/DominatorTree.h | 20 + .../extract/js/src/jit/EdgeCaseAnalysis.cpp | 3 +- .../extract/js/src/jit/EdgeCaseAnalysis.h | 4 +- .../js/src/jit/EffectiveAddressAnalysis.cpp | 1 + .../js/src/jit/EffectiveAddressAnalysis.h | 4 +- .../extract/js/src/jit/ExecutableAllocator.h | 12 +- .../mozjs/extract/js/src/jit/FlushICache.cpp | 62 +- .../mozjs/extract/js/src/jit/FlushICache.h | 13 +- .../js/src/jit/FoldLinearArithConstants.cpp | 3 +- .../js/src/jit/FoldLinearArithConstants.h | 3 +- .../js/src/jit/GenerateABIFunctionType.py | 35 +- .../js/src/jit/GenerateAtomicOperations.py | 44 +- .../js/src/jit/GenerateCacheIRFiles.py | 80 +- .../extract/js/src/jit/GenerateLIRFiles.py | 563 +- .../extract/js/src/jit/GenerateMIRFiles.py | 20 +- .../mozjs/extract/js/src/jit/ICStubSpace.h | 2 +- .../extract/js/src/jit/InlinableNatives.cpp | 54 +- .../extract/js/src/jit/InlinableNatives.h | 52 +- .../mozjs/extract/js/src/jit/InlineList.h | 174 +- .../js/src/jit/InstructionReordering.cpp | 12 +- .../js/src/jit/InstructionReordering.h | 2 +- .../js/src/jit/InterpreterEntryTrampoline.cpp | 7 +- .../js/src/jit/InvalidationScriptSet.h | 36 + .../mozjs/extract/js/src/jit/Ion.cpp | 325 +- .../mozjs/extract/js/src/jit/Ion.h | 1 - .../mozjs/extract/js/src/jit/IonAnalysis.cpp | 601 +- .../mozjs/extract/js/src/jit/IonAnalysis.h | 74 +- .../extract/js/src/jit/IonCacheIRCompiler.cpp | 85 +- .../extract/js/src/jit/IonCompileTask.cpp | 33 +- .../mozjs/extract/js/src/jit/IonCompileTask.h | 6 + .../mozjs/extract/js/src/jit/IonIC.cpp | 53 +- .../mozjs/extract/js/src/jit/IonIC.h | 1 + .../js/src/jit/IonOptimizationLevels.cpp | 118 +- .../js/src/jit/IonOptimizationLevels.h | 64 +- .../mozjs/extract/js/src/jit/IonTypes.h | 42 +- .../extract/js/src/jit/JSJitFrameIter.cpp | 31 +- .../mozjs/extract/js/src/jit/JSJitFrameIter.h | 24 +- .../mozjs/extract/js/src/jit/JSONSpewer.cpp | 24 +- .../mozjs/extract/js/src/jit/JSONSpewer.h | 9 +- .../mozjs/extract/js/src/jit/Jit.cpp | 1 - .../mozjs/extract/js/src/jit/JitCode.h | 5 + .../mozjs/extract/js/src/jit/JitContext.cpp | 6 +- .../mozjs/extract/js/src/jit/JitContext.h | 12 + .../mozjs/extract/js/src/jit/JitFrames.cpp | 289 +- .../mozjs/extract/js/src/jit/JitFrames.h | 27 +- .../mozjs/extract/js/src/jit/JitOptions.cpp | 47 +- .../mozjs/extract/js/src/jit/JitOptions.h | 13 +- .../mozjs/extract/js/src/jit/JitRuntime.h | 25 +- .../mozjs/extract/js/src/jit/JitScript.cpp | 48 +- .../mozjs/extract/js/src/jit/JitScript.h | 84 +- .../mozjs/extract/js/src/jit/JitSpewer.cpp | 57 +- .../mozjs/extract/js/src/jit/JitSpewer.h | 35 +- .../mozjs/extract/js/src/jit/JitZone.h | 151 +- .../mozjs/extract/js/src/jit/JitcodeMap.cpp | 47 +- .../mozjs/extract/js/src/jit/JitcodeMap.h | 48 +- .../mozjs/extract/js/src/jit/KnownClass.cpp | 1 + .../mozjs/extract/js/src/jit/LICM.cpp | 2 +- .../mozjs/extract/js/src/jit/LICM.h | 2 +- .../mozjs/extract/js/src/jit/LIR.cpp | 63 +- .../mozjs/extract/js/src/jit/LIR.h | 507 +- .../mozjs/extract/js/src/jit/LIROps.yaml | 3282 ++-- .../mozjs/extract/js/src/jit/Label.h | 4 +- .../mozjs/extract/js/src/jit/Linker.cpp | 2 +- .../mozjs/extract/js/src/jit/Lowering.cpp | 1612 +- .../mozjs/extract/js/src/jit/Lowering.h | 2 - .../mozjs/extract/js/src/jit/MIR-wasm.cpp | 1060 ++ .../mozjs/extract/js/src/jit/MIR-wasm.h | 3228 ++++ .../mozjs/extract/js/src/jit/MIR.cpp | 2424 ++- .../mozjs/extract/js/src/jit/MIR.h | 3833 +---- .../mozjs/extract/js/src/jit/MIRGenerator.h | 12 +- .../mozjs/extract/js/src/jit/MIRGraph.cpp | 7 +- .../mozjs/extract/js/src/jit/MIRGraph.h | 49 +- .../mozjs/extract/js/src/jit/MIROps.yaml | 751 +- .../extract/js/src/jit/MacroAssembler-inl.h | 112 +- .../extract/js/src/jit/MacroAssembler.cpp | 2775 +++- .../mozjs/extract/js/src/jit/MacroAssembler.h | 1012 +- .../mozjs/extract/js/src/jit/MoveEmitter.h | 2 - .../extract/js/src/jit/OffthreadSnapshot.h | 45 + .../mozjs/extract/js/src/jit/PerfSpewer.cpp | 529 +- .../mozjs/extract/js/src/jit/PerfSpewer.h | 132 +- .../js/src/jit/ProcessExecutableMemory.cpp | 9 +- .../extract/js/src/jit/RangeAnalysis.cpp | 155 +- .../mozjs/extract/js/src/jit/RangeAnalysis.h | 53 +- .../mozjs/extract/js/src/jit/Recover.cpp | 478 +- .../mozjs/extract/js/src/jit/Recover.h | 171 + .../extract/js/src/jit/RegExpStubConstants.h | 1 + .../extract/js/src/jit/RegisterAllocator.cpp | 150 +- .../extract/js/src/jit/RegisterAllocator.h | 27 +- .../mozjs/extract/js/src/jit/RegisterSets.h | 33 +- .../mozjs/extract/js/src/jit/Registers.h | 15 +- .../mozjs/extract/js/src/jit/Safepoints.cpp | 116 +- .../extract/js/src/jit/ScalarReplacement.cpp | 395 +- .../extract/js/src/jit/ScalarReplacement.h | 2 +- .../extract/js/src/jit/SharedICHelpers-inl.h | 2 +- .../extract/js/src/jit/SharedICHelpers.h | 2 +- .../extract/js/src/jit/SharedICRegisters.h | 2 - .../extract/js/src/jit/ShuffleAnalysis.cpp | 1 + .../extract/js/src/jit/SimpleAllocator.cpp | 1279 ++ .../extract/js/src/jit/SimpleAllocator.h | 369 + .../mozjs/extract/js/src/jit/Simulator.h | 2 - .../mozjs/extract/js/src/jit/Sink.cpp | 3 +- .../mozjs/extract/js/src/jit/Sink.h | 2 +- .../mozjs/extract/js/src/jit/Snapshots.cpp | 128 +- .../mozjs/extract/js/src/jit/Snapshots.h | 95 +- .../mozjs/extract/js/src/jit/SparseBitSet.h | 190 + .../extract/js/src/jit/StackSlotAllocator.h | 67 +- .../mozjs/extract/js/src/jit/Trampoline.cpp | 6 +- .../extract/js/src/jit/TrampolineNatives.cpp | 1 - .../extract/js/src/jit/TrialInlining.cpp | 4 + .../mozjs/extract/js/src/jit/TypePolicy.cpp | 104 +- .../mozjs/extract/js/src/jit/TypePolicy.h | 26 +- .../mozjs/extract/js/src/jit/UnrollLoops.cpp | 2049 +++ .../mozjs/extract/js/src/jit/UnrollLoops.h | 24 + .../extract/js/src/jit/VMFunctionList-inl.h | 55 +- .../mozjs/extract/js/src/jit/VMFunctions.cpp | 464 +- .../mozjs/extract/js/src/jit/VMFunctions.h | 40 +- .../extract/js/src/jit/ValueNumbering.cpp | 10 +- .../mozjs/extract/js/src/jit/ValueNumbering.h | 10 +- .../mozjs/extract/js/src/jit/WarpBuilder.cpp | 228 +- .../mozjs/extract/js/src/jit/WarpBuilder.h | 72 +- .../extract/js/src/jit/WarpBuilderShared.cpp | 10 +- .../extract/js/src/jit/WarpBuilderShared.h | 11 +- .../js/src/jit/WarpCacheIRTranspiler.cpp | 709 +- .../mozjs/extract/js/src/jit/WarpOracle.cpp | 79 +- .../mozjs/extract/js/src/jit/WarpOracle.h | 3 + .../mozjs/extract/js/src/jit/WarpSnapshot.cpp | 98 +- .../mozjs/extract/js/src/jit/WarpSnapshot.h | 88 +- .../mozjs/extract/js/src/jit/WasmBCE.cpp | 7 +- .../mozjs/extract/js/src/jit/WasmBCE.h | 2 +- .../js/src/jit/arm/Architecture-arm.cpp | 279 +- .../extract/js/src/jit/arm/Architecture-arm.h | 239 +- .../extract/js/src/jit/arm/Assembler-arm.cpp | 88 +- .../extract/js/src/jit/arm/Assembler-arm.h | 63 +- .../js/src/jit/arm/CodeGenerator-arm.cpp | 835 +- .../js/src/jit/arm/CodeGenerator-arm.h | 64 +- .../mozjs/extract/js/src/jit/arm/LIR-arm.h | 438 +- .../extract/js/src/jit/arm/Lowering-arm.cpp | 296 +- .../extract/js/src/jit/arm/Lowering-arm.h | 28 +- .../js/src/jit/arm/MacroAssembler-arm-inl.h | 633 +- .../js/src/jit/arm/MacroAssembler-arm.cpp | 457 +- .../js/src/jit/arm/MacroAssembler-arm.h | 57 +- .../extract/js/src/jit/arm/MoveEmitter-arm.h | 2 +- .../extract/js/src/jit/arm/Simulator-arm.cpp | 137 +- .../extract/js/src/jit/arm/Simulator-arm.h | 15 +- .../js/src/jit/arm/disasm/Constants-arm.h | 3 + .../js/src/jit/arm/disasm/Disasm-arm.cpp | 45 + .../js/src/jit/arm64/Architecture-arm64.h | 28 +- .../js/src/jit/arm64/Assembler-arm64.cpp | 1 + .../js/src/jit/arm64/Assembler-arm64.h | 13 +- .../js/src/jit/arm64/CodeGenerator-arm64.cpp | 851 +- .../js/src/jit/arm64/CodeGenerator-arm64.h | 59 +- .../extract/js/src/jit/arm64/LIR-arm64.h | 296 +- .../js/src/jit/arm64/Lowering-arm64.cpp | 260 +- .../extract/js/src/jit/arm64/Lowering-arm64.h | 28 +- .../src/jit/arm64/MacroAssembler-arm64-inl.h | 402 +- .../js/src/jit/arm64/MacroAssembler-arm64.cpp | 220 +- .../js/src/jit/arm64/MacroAssembler-arm64.h | 205 +- .../js/src/jit/arm64/MoveEmitter-arm64.h | 2 +- .../js/src/jit/arm64/vixl/Assembler-vixl.cpp | 14 +- .../js/src/jit/arm64/vixl/Assembler-vixl.h | 1 + .../src/jit/arm64/vixl/Cpu-Features-vixl.cpp | 6 +- .../js/src/jit/arm64/vixl/Cpu-vixl.cpp | 5 - .../js/src/jit/arm64/vixl/Decoder-vixl.cpp | 1 - .../jit/arm64/vixl/MacroAssembler-vixl.cpp | 31 +- .../src/jit/arm64/vixl/MacroAssembler-vixl.h | 2 +- .../src/jit/arm64/vixl/MozAssembler-vixl.cpp | 3 + .../src/jit/arm64/vixl/MozSimulator-vixl.cpp | 51 + .../js/src/jit/arm64/vixl/Simulator-vixl.cpp | 30 +- .../js/src/jit/arm64/vixl/Simulator-vixl.h | 15 + .../js/src/jit/loong64/Assembler-loong64.cpp | 1 + .../js/src/jit/loong64/Assembler-loong64.h | 7 +- .../src/jit/loong64/CodeGenerator-loong64.cpp | 780 +- .../src/jit/loong64/CodeGenerator-loong64.h | 64 +- .../extract/js/src/jit/loong64/LIR-loong64.h | 291 +- .../js/src/jit/loong64/Lowering-loong64.cpp | 294 +- .../js/src/jit/loong64/Lowering-loong64.h | 26 +- .../jit/loong64/MacroAssembler-loong64-inl.h | 349 +- .../jit/loong64/MacroAssembler-loong64.cpp | 354 +- .../src/jit/loong64/MacroAssembler-loong64.h | 73 +- .../js/src/jit/loong64/Simulator-loong64.cpp | 23 +- .../js/src/jit/loong64/Simulator-loong64.h | 4 + .../mips-shared/Architecture-mips-shared.cpp | 34 +- .../mips-shared/Architecture-mips-shared.h | 26 +- .../jit/mips-shared/Assembler-mips-shared.h | 14 +- .../AtomicOperations-mips-shared.h | 351 +- .../mips-shared/BaselineIC-mips-shared.cpp | 37 - .../mips-shared/CodeGenerator-mips-shared.cpp | 692 +- .../mips-shared/CodeGenerator-mips-shared.h | 30 +- .../js/src/jit/mips-shared/LIR-mips-shared.h | 336 +- .../jit/mips-shared/Lowering-mips-shared.cpp | 368 +- .../jit/mips-shared/Lowering-mips-shared.h | 24 +- .../MacroAssembler-mips-shared-inl.h | 159 +- .../MacroAssembler-mips-shared.cpp | 449 +- .../mips-shared/MacroAssembler-mips-shared.h | 60 +- .../mips-shared/MoveEmitter-mips-shared.cpp | 4 - .../js/src/jit/mips32/Architecture-mips32.cpp | 94 - .../js/src/jit/mips32/Architecture-mips32.h | 282 - .../js/src/jit/mips32/Assembler-mips32.cpp | 369 - .../js/src/jit/mips32/Assembler-mips32.h | 270 - .../src/jit/mips32/CodeGenerator-mips32.cpp | 508 - .../js/src/jit/mips32/CodeGenerator-mips32.h | 60 - .../extract/js/src/jit/mips32/LIR-mips32.h | 197 - .../js/src/jit/mips32/Lowering-mips32.cpp | 257 - .../js/src/jit/mips32/Lowering-mips32.h | 54 - .../jit/mips32/MacroAssembler-mips32-inl.h | 1027 -- .../src/jit/mips32/MacroAssembler-mips32.cpp | 2820 ---- .../js/src/jit/mips32/MacroAssembler-mips32.h | 823 - .../js/src/jit/mips32/MoveEmitter-mips32.cpp | 152 - .../js/src/jit/mips32/MoveEmitter-mips32.h | 31 - .../src/jit/mips32/SharedICRegisters-mips32.h | 42 - .../js/src/jit/mips32/Simulator-mips32.cpp | 3629 ----- .../js/src/jit/mips32/Simulator-mips32.h | 526 - .../js/src/jit/mips32/Trampoline-mips32.cpp | 943 -- .../js/src/jit/mips64/Assembler-mips64.cpp | 1 + .../js/src/jit/mips64/Assembler-mips64.h | 1 + .../src/jit/mips64/CodeGenerator-mips64.cpp | 244 +- .../js/src/jit/mips64/CodeGenerator-mips64.h | 42 +- .../extract/js/src/jit/mips64/LIR-mips64.h | 58 +- .../js/src/jit/mips64/Lowering-mips64.cpp | 30 +- .../js/src/jit/mips64/Lowering-mips64.h | 3 - .../jit/mips64/MacroAssembler-mips64-inl.h | 164 +- .../src/jit/mips64/MacroAssembler-mips64.cpp | 466 +- .../js/src/jit/mips64/MacroAssembler-mips64.h | 127 +- .../js/src/jit/mips64/Simulator-mips64.cpp | 18 +- .../js/src/jit/mips64/Simulator-mips64.h | 4 + .../mozjs/extract/js/src/jit/moz.build | 52 +- .../js/src/jit/none/Architecture-none.h | 22 +- .../extract/js/src/jit/none/Assembler-none.h | 1 + .../js/src/jit/none/CodeGenerator-none.h | 29 +- .../mozjs/extract/js/src/jit/none/LIR-none.h | 87 - .../extract/js/src/jit/none/Lowering-none.h | 24 +- .../js/src/jit/none/MacroAssembler-none.h | 20 +- .../js/src/jit/none/MoveEmitter-none.h | 2 +- .../js/src/jit/riscv64/Assembler-riscv64.cpp | 20 +- .../js/src/jit/riscv64/Assembler-riscv64.h | 35 +- .../src/jit/riscv64/CodeGenerator-riscv64.cpp | 773 +- .../src/jit/riscv64/CodeGenerator-riscv64.h | 65 +- .../extract/js/src/jit/riscv64/LIR-riscv64.h | 291 +- .../js/src/jit/riscv64/Lowering-riscv64.cpp | 301 +- .../js/src/jit/riscv64/Lowering-riscv64.h | 27 +- .../jit/riscv64/MacroAssembler-riscv64-inl.h | 292 +- .../jit/riscv64/MacroAssembler-riscv64.cpp | 293 +- .../src/jit/riscv64/MacroAssembler-riscv64.h | 60 +- .../js/src/jit/riscv64/Register-riscv64.h | 1 + .../jit/riscv64/SharedICHelpers-riscv64-inl.h | 1 + .../js/src/jit/riscv64/Simulator-riscv64.cpp | 58 +- .../js/src/jit/shared/Assembler-shared.cpp | 2 +- .../js/src/jit/shared/Assembler-shared.h | 98 +- .../AtomicOperations-feeling-lucky-gcc.h | 4 + .../AtomicOperations-feeling-lucky-msvc.h | 6 +- .../shared/AtomicOperations-shared-jit.cpp | 150 +- .../jit/shared/AtomicOperations-shared-jit.h | 8 +- .../src/jit/shared/CodeGenerator-shared-inl.h | 45 +- .../src/jit/shared/CodeGenerator-shared.cpp | 201 +- .../js/src/jit/shared/CodeGenerator-shared.h | 61 +- .../js/src/jit/shared/IonAssemblerBuffer.h | 6 +- .../IonAssemblerBufferWithConstantPools.h | 12 +- .../extract/js/src/jit/shared/LIR-shared.h | 3496 +--- .../js/src/jit/shared/Lowering-shared-inl.h | 42 +- .../js/src/jit/shared/Lowering-shared.cpp | 17 +- .../js/src/jit/shared/Lowering-shared.h | 10 +- .../js/src/jit/wasm32/Architecture-wasm32.h | 22 +- .../src/jit/wasm32/CodeGenerator-wasm32.cpp | 32 - .../js/src/jit/wasm32/CodeGenerator-wasm32.h | 29 +- .../extract/js/src/jit/wasm32/LIR-wasm32.h | 87 - .../js/src/jit/wasm32/Lowering-wasm32.h | 24 +- .../jit/wasm32/MacroAssembler-wasm32-inl.h | 212 +- .../src/jit/wasm32/MacroAssembler-wasm32.cpp | 86 +- .../js/src/jit/wasm32/MacroAssembler-wasm32.h | 21 +- .../js/src/jit/wasm32/MoveEmitter-wasm32.h | 2 +- .../extract/js/src/jit/x64/Assembler-x64.cpp | 2 + .../extract/js/src/jit/x64/Assembler-x64.h | 3 + .../js/src/jit/x64/BaseAssembler-x64.h | 2 +- .../js/src/jit/x64/CodeGenerator-x64.cpp | 442 +- .../js/src/jit/x64/CodeGenerator-x64.h | 18 +- .../mozjs/extract/js/src/jit/x64/LIR-x64.h | 79 +- .../extract/js/src/jit/x64/Lowering-x64.cpp | 169 +- .../extract/js/src/jit/x64/Lowering-x64.h | 7 +- .../js/src/jit/x64/MacroAssembler-x64-inl.h | 260 +- .../js/src/jit/x64/MacroAssembler-x64.cpp | 151 +- .../js/src/jit/x64/MacroAssembler-x64.h | 71 +- .../jit/x86-shared/Assembler-x86-shared.cpp | 20 +- .../src/jit/x86-shared/Assembler-x86-shared.h | 84 +- .../x86-shared/AssemblerBuffer-x86-shared.cpp | 3 +- .../x86-shared/AssemblerBuffer-x86-shared.h | 4 + .../jit/x86-shared/BaseAssembler-x86-shared.h | 58 +- .../x86-shared/CodeGenerator-x86-shared.cpp | 776 +- .../jit/x86-shared/CodeGenerator-x86-shared.h | 95 +- .../src/jit/x86-shared/Constants-x86-shared.h | 2 +- .../src/jit/x86-shared/Encoding-x86-shared.h | 4 + .../js/src/jit/x86-shared/LIR-x86-shared.h | 186 +- .../jit/x86-shared/Lowering-x86-shared.cpp | 296 +- .../src/jit/x86-shared/Lowering-x86-shared.h | 28 +- .../MacroAssembler-x86-shared-inl.h | 194 +- .../x86-shared/MacroAssembler-x86-shared.cpp | 502 +- .../x86-shared/MacroAssembler-x86-shared.h | 253 +- .../extract/js/src/jit/x86/Assembler-x86.cpp | 1 + .../extract/js/src/jit/x86/Assembler-x86.h | 3 + .../js/src/jit/x86/BaseAssembler-x86.h | 2 +- .../js/src/jit/x86/CodeGenerator-x86.cpp | 604 +- .../js/src/jit/x86/CodeGenerator-x86.h | 16 +- .../mozjs/extract/js/src/jit/x86/LIR-x86.h | 220 +- .../extract/js/src/jit/x86/Lowering-x86.cpp | 219 +- .../extract/js/src/jit/x86/Lowering-x86.h | 9 +- .../js/src/jit/x86/MacroAssembler-x86-inl.h | 546 +- .../js/src/jit/x86/MacroAssembler-x86.cpp | 104 +- .../js/src/jit/x86/MacroAssembler-x86.h | 46 +- .../mozjs/extract/js/src/jsapi.cpp | 208 +- src/third_party/mozjs/extract/js/src/jsapi.h | 12 +- .../mozjs/extract/js/src/jsast.tbl | 5 - .../mozjs/extract/js/src/jsdate.cpp | 2655 ++- src/third_party/mozjs/extract/js/src/jsdate.h | 37 +- .../mozjs/extract/js/src/jsexn.cpp | 41 +- src/third_party/mozjs/extract/js/src/jsexn.h | 14 + .../mozjs/extract/js/src/jsfriendapi.cpp | 19 +- .../mozjs/extract/js/src/jsfriendapi.h | 19 +- .../mozjs/extract/js/src/jsmath.cpp | 245 +- src/third_party/mozjs/extract/js/src/jsmath.h | 7 +- .../mozjs/extract/js/src/jsnum.cpp | 522 +- src/third_party/mozjs/extract/js/src/jsnum.h | 63 +- .../mozjs/extract/js/src/jspubtd.h | 10 - .../extract/js/src/mfbt/Unified_cpp_mfbt0.cpp | 18 +- .../mozjs/extract/js/src/moz.build | 59 +- .../extract/js/src/proxy/DeadObjectProxy.h | 5 +- .../mozjs/extract/js/src/proxy/Proxy.cpp | 11 +- .../js/src/proxy/ScriptedProxyHandler.h | 4 +- .../mozjs/extract/js/src/proxy/Wrapper.cpp | 6 +- .../mozjs/extract/js/src/selfhosted.out.h | 6 +- .../js/src/threading/ProtectedData.cpp | 5 +- .../extract/js/src/threading/ProtectedData.h | 41 +- .../mozjs/extract/js/src/util/CaseFolding.txt | 38 +- .../js/src/util/DerivedCoreProperties.txt | 1009 +- .../mozjs/extract/js/src/util/Identifier.cpp | 4 +- .../mozjs/extract/js/src/util/Identifier.h | 4 +- .../mozjs/extract/js/src/util/NativeStack.cpp | 16 +- .../mozjs/extract/js/src/util/Poison.h | 3 +- .../extract/js/src/util/SpecialCasing.txt | 22 +- .../extract/js/src/util/StringBuffer.cpp | 214 - .../extract/js/src/util/StringBuilder.cpp | 266 + .../util/{StringBuffer.h => StringBuilder.h} | 169 +- .../mozjs/extract/js/src/util/Text.cpp | 2 +- .../mozjs/extract/js/src/util/Text.h | 16 +- .../mozjs/extract/js/src/util/Unicode.cpp | 400 +- .../mozjs/extract/js/src/util/UnicodeData.txt | 5210 +++++- .../mozjs/extract/js/src/util/UnicodeNonBMP.h | 6 +- .../mozjs/extract/js/src/util/Utility.cpp | 10 +- .../mozjs/extract/js/src/util/moz.build | 2 +- .../mozjs/extract/js/src/vm/Activation-inl.h | 30 - .../mozjs/extract/js/src/vm/Activation.cpp | 37 - .../mozjs/extract/js/src/vm/Activation.h | 30 - .../extract/js/src/vm/ArgumentsObject.cpp | 27 +- .../extract/js/src/vm/ArrayBufferObject.cpp | 670 +- .../extract/js/src/vm/ArrayBufferObject.h | 97 +- .../js/src/vm/ArrayBufferViewObject.cpp | 3 +- .../mozjs/extract/js/src/vm/ArrayObject-inl.h | 5 + .../mozjs/extract/js/src/vm/ArrayObject.h | 32 +- .../mozjs/extract/js/src/vm/AsyncFunction.cpp | 11 +- .../extract/js/src/vm/AsyncIteration.cpp | 111 +- .../mozjs/extract/js/src/vm/AtomsTable.h | 4 +- .../mozjs/extract/js/src/vm/BigIntType.cpp | 622 +- .../mozjs/extract/js/src/vm/BigIntType.h | 42 +- .../extract/js/src/vm/BoundFunctionObject.cpp | 5 +- .../extract/js/src/vm/BoundFunctionObject.h | 2 +- .../extract/js/src/vm/BuiltinObjectKind.cpp | 54 +- .../extract/js/src/vm/BuiltinObjectKind.h | 7 +- .../extract/js/src/vm/BytecodeLocation.h | 22 +- .../mozjs/extract/js/src/vm/BytecodeUtil.cpp | 97 +- .../mozjs/extract/js/src/vm/BytecodeUtil.h | 4 +- .../mozjs/extract/js/src/vm/Caches.h | 169 +- .../extract/js/src/vm/CharacterEncoding.cpp | 29 +- .../mozjs/extract/js/src/vm/CodeCoverage.cpp | 7 +- .../mozjs/extract/js/src/vm/CodeCoverage.h | 6 +- .../extract/js/src/vm/CommonPropertyNames.h | 48 +- .../mozjs/extract/js/src/vm/Compartment-inl.h | 55 - .../mozjs/extract/js/src/vm/Compartment.cpp | 50 +- .../mozjs/extract/js/src/vm/Compartment.h | 10 +- .../js/src/vm/CompilationAndEvaluation.cpp | 205 +- .../mozjs/extract/js/src/vm/CompletionKind.h | 13 + .../mozjs/extract/js/src/vm/Compression.cpp | 9 +- .../js/src/vm/ConcurrentDelazification.cpp | 42 +- .../js/src/vm/ConcurrentDelazification.h | 15 +- .../js/src/vm/ConstantCompareOperand.h | 107 + .../mozjs/extract/js/src/vm/DateObject.h | 63 + .../mozjs/extract/js/src/vm/DateTime.cpp | 17 +- .../mozjs/extract/js/src/vm/DateTime.h | 67 +- .../extract/js/src/vm/DisposableRecord-inl.h | 36 + .../extract/js/src/vm/DisposableRecord.cpp | 44 + .../extract/js/src/vm/DisposableRecord.h | 53 + .../extract/js/src/vm/EnvironmentObject-inl.h | 4 +- .../extract/js/src/vm/EnvironmentObject.cpp | 443 +- .../extract/js/src/vm/EnvironmentObject.h | 473 +- .../extract/js/src/vm/EqualityOperations.cpp | 127 +- .../extract/js/src/vm/EqualityOperations.h | 11 +- .../mozjs/extract/js/src/vm/ErrorObject.cpp | 391 +- .../mozjs/extract/js/src/vm/Float16.h | 221 +- .../mozjs/extract/js/src/vm/ForOfIterator.cpp | 28 +- .../mozjs/extract/js/src/vm/FrameIter.cpp | 9 +- .../mozjs/extract/js/src/vm/FrameIter.h | 10 +- .../mozjs/extract/js/src/vm/GeckoProfiler.cpp | 72 +- .../mozjs/extract/js/src/vm/GeckoProfiler.h | 23 +- .../extract/js/src/vm/GeneratorObject.cpp | 13 +- .../mozjs/extract/js/src/vm/GetterSetter.h | 6 +- .../mozjs/extract/js/src/vm/GlobalObject.cpp | 151 +- .../mozjs/extract/js/src/vm/GlobalObject.h | 200 +- .../extract/js/src/vm/HelperThreadState.h | 160 +- .../extract/js/src/vm/HelperThreadTask.h | 21 +- .../mozjs/extract/js/src/vm/HelperThreads.cpp | 2457 +-- .../mozjs/extract/js/src/vm/HelperThreads.h | 90 +- .../extract/js/src/vm/Initialization.cpp | 12 +- .../extract/js/src/vm/InlineCharBuffer-inl.h | 165 - .../mozjs/extract/js/src/vm/Interpreter-inl.h | 97 +- .../mozjs/extract/js/src/vm/Interpreter.cpp | 737 +- .../mozjs/extract/js/src/vm/Interpreter.h | 41 +- .../extract/js/src/vm/InvalidatingFuse.cpp | 59 +- .../extract/js/src/vm/InvalidatingFuse.h | 17 +- .../mozjs/extract/js/src/vm/Iteration.cpp | 317 +- .../mozjs/extract/js/src/vm/Iteration.h | 19 + .../mozjs/extract/js/src/vm/JSAtomState.h | 4 +- .../mozjs/extract/js/src/vm/JSAtomUtils-inl.h | 43 +- .../mozjs/extract/js/src/vm/JSAtomUtils.cpp | 77 +- .../mozjs/extract/js/src/vm/JSAtomUtils.h | 16 +- .../mozjs/extract/js/src/vm/JSContext.cpp | 120 +- .../mozjs/extract/js/src/vm/JSContext.h | 90 +- .../mozjs/extract/js/src/vm/JSFunction-inl.h | 5 +- .../mozjs/extract/js/src/vm/JSFunction.cpp | 165 +- .../mozjs/extract/js/src/vm/JSFunction.h | 80 +- .../mozjs/extract/js/src/vm/JSONParser.cpp | 228 +- .../mozjs/extract/js/src/vm/JSONParser.h | 86 +- .../mozjs/extract/js/src/vm/JSONPrinter.cpp | 2 +- .../mozjs/extract/js/src/vm/JSONPrinter.h | 6 +- .../mozjs/extract/js/src/vm/JSObject-inl.h | 98 +- .../mozjs/extract/js/src/vm/JSObject.cpp | 655 +- .../mozjs/extract/js/src/vm/JSObject.h | 70 +- .../mozjs/extract/js/src/vm/JSScript-inl.h | 4 + .../mozjs/extract/js/src/vm/JSScript.cpp | 195 +- .../mozjs/extract/js/src/vm/JSScript.h | 120 +- .../mozjs/extract/js/src/vm/JitActivation.cpp | 20 +- .../mozjs/extract/js/src/vm/JitActivation.h | 2 +- .../mozjs/extract/js/src/vm/List.cpp | 4 +- .../mozjs/extract/js/src/vm/Logging.cpp | 19 + .../mozjs/extract/js/src/vm/Logging.h | 138 + .../mozjs/extract/js/src/vm/MemoryMetrics.cpp | 57 +- .../mozjs/extract/js/src/vm/ModuleBuilder.h | 17 +- .../mozjs/extract/js/src/vm/Modules.cpp | 191 +- .../mozjs/extract/js/src/vm/MutexIDs.h | 13 +- .../extract/js/src/vm/NativeObject-inl.h | 27 +- .../mozjs/extract/js/src/vm/NativeObject.cpp | 683 +- .../mozjs/extract/js/src/vm/NativeObject.h | 120 +- .../extract/js/src/vm/ObjectOperations-inl.h | 12 - .../js/src/vm/ObjectWithStashedPointer.cpp | 78 + .../src/vm/OffThreadPromiseRuntimeState.cpp | 372 +- .../js/src/vm/OffThreadPromiseRuntimeState.h | 207 +- .../mozjs/extract/js/src/vm/Opcodes.h | 253 +- .../mozjs/extract/js/src/vm/PIC.cpp | 453 - src/third_party/mozjs/extract/js/src/vm/PIC.h | 268 - .../mozjs/extract/js/src/vm/PlainObject-inl.h | 13 +- .../mozjs/extract/js/src/vm/PlainObject.cpp | 2 +- .../js/src/vm/PortableBaselineInterpret.cpp | 13300 ++++++++++------ .../js/src/vm/PortableBaselineInterpret.h | 25 +- .../mozjs/extract/js/src/vm/Printer.cpp | 224 +- .../mozjs/extract/js/src/vm/PromiseLookup.cpp | 273 - .../mozjs/extract/js/src/vm/PromiseLookup.h | 163 - .../mozjs/extract/js/src/vm/PropMap.cpp | 5 + .../mozjs/extract/js/src/vm/PropMap.h | 8 + .../mozjs/extract/js/src/vm/PropertyResult.h | 18 +- .../mozjs/extract/js/src/vm/ProxyObject.cpp | 9 +- .../mozjs/extract/js/src/vm/Realm.cpp | 132 +- .../mozjs/extract/js/src/vm/Realm.h | 95 +- .../mozjs/extract/js/src/vm/RealmFuses.cpp | 456 +- .../mozjs/extract/js/src/vm/RealmFuses.h | 255 +- .../extract/js/src/vm/RecordTupleShared.cpp | 134 - .../mozjs/extract/js/src/vm/RecordType.cpp | 538 - .../mozjs/extract/js/src/vm/RecordType.h | 78 - .../mozjs/extract/js/src/vm/RegExpObject.cpp | 82 +- .../mozjs/extract/js/src/vm/RegExpObject.h | 4 +- .../mozjs/extract/js/src/vm/RegExpShared.h | 52 +- .../mozjs/extract/js/src/vm/Runtime.cpp | 75 +- .../mozjs/extract/js/src/vm/Runtime.h | 53 +- .../mozjs/extract/js/src/vm/SavedFrame.h | 10 +- .../mozjs/extract/js/src/vm/SavedStacks.cpp | 120 +- .../mozjs/extract/js/src/vm/SavedStacks.h | 9 +- .../mozjs/extract/js/src/vm/Scope.cpp | 52 +- .../mozjs/extract/js/src/vm/Scope.h | 36 +- .../mozjs/extract/js/src/vm/SelfHosting.cpp | 819 +- .../mozjs/extract/js/src/vm/SelfHosting.h | 12 - .../mozjs/extract/js/src/vm/Shape.cpp | 70 +- .../mozjs/extract/js/src/vm/Shape.h | 2 - .../mozjs/extract/js/src/vm/ShapeZone.cpp | 13 + .../mozjs/extract/js/src/vm/ShapeZone.h | 14 + .../extract/js/src/vm/SharedArrayObject.cpp | 323 +- .../extract/js/src/vm/SharedArrayObject.h | 72 +- .../mozjs/extract/js/src/vm/SharedMem.h | 5 + .../js/src/vm/SharedScriptDataTableHolder.cpp | 5 +- .../mozjs/extract/js/src/vm/Stack.cpp | 13 +- .../mozjs/extract/js/src/vm/Stack.h | 3 +- .../mozjs/extract/js/src/vm/StaticStrings.h | 2 +- .../mozjs/extract/js/src/vm/StencilCache.cpp | 69 - .../mozjs/extract/js/src/vm/StencilCache.h | 197 - .../mozjs/extract/js/src/vm/StencilObject.cpp | 6 +- .../mozjs/extract/js/src/vm/StringType-inl.h | 314 +- .../mozjs/extract/js/src/vm/StringType.cpp | 830 +- .../mozjs/extract/js/src/vm/StringType.h | 507 +- .../extract/js/src/vm/StructuredClone.cpp | 175 +- .../mozjs/extract/js/src/vm/SymbolType.cpp | 2 +- .../mozjs/extract/js/src/vm/SymbolType.h | 1 - .../mozjs/extract/js/src/vm/ThrowMsgKind.cpp | 4 +- .../mozjs/extract/js/src/vm/ThrowMsgKind.h | 2 +- .../mozjs/extract/js/src/vm/Time.cpp | 3 +- .../mozjs/extract/js/src/vm/ToSource.cpp | 43 +- .../mozjs/extract/js/src/vm/TupleType.cpp | 638 - .../mozjs/extract/js/src/vm/TupleType.h | 87 - .../extract/js/src/vm/TypedArrayObject-inl.h | 656 +- .../extract/js/src/vm/TypedArrayObject.cpp | 1998 ++- .../extract/js/src/vm/TypedArrayObject.h | 41 +- .../mozjs/extract/js/src/vm/UbiNode.cpp | 3 + .../mozjs/extract/js/src/vm/UbiNodeCensus.cpp | 4 +- .../mozjs/extract/js/src/vm/Uint8Clamped.h | 173 +- .../mozjs/extract/js/src/vm/UsingHint.h | 27 + .../mozjs/extract/js/src/vm/Value.cpp | 14 - .../mozjs/extract/js/src/vm/Watchtower.cpp | 402 +- .../mozjs/extract/js/src/vm/Watchtower.h | 56 +- .../mozjs/extract/js/src/vm/jsopcode.py | 61 +- .../extract/js/src/vm/make_opcode_doc.py | 26 +- .../mozjs/extract/js/src/wasm/AsmJS.cpp | 399 +- .../mozjs/extract/js/src/wasm/AsmJS.h | 33 +- .../js/src/wasm/GenerateBuiltinModules.py | 20 +- .../mozjs/extract/js/src/wasm/WasmAnyRef.cpp | 4 +- .../mozjs/extract/js/src/wasm/WasmAnyRef.h | 22 +- .../extract/js/src/wasm/WasmBCClass-inl.h | 20 +- .../mozjs/extract/js/src/wasm/WasmBCClass.h | 207 +- .../extract/js/src/wasm/WasmBCCodegen-inl.h | 2 +- .../mozjs/extract/js/src/wasm/WasmBCDefs.h | 11 - .../mozjs/extract/js/src/wasm/WasmBCFrame.cpp | 5 +- .../mozjs/extract/js/src/wasm/WasmBCFrame.h | 48 +- .../extract/js/src/wasm/WasmBCMemory.cpp | 207 +- .../extract/js/src/wasm/WasmBCRegMgmt-inl.h | 6 - .../extract/js/src/wasm/WasmBCStkMgmt-inl.h | 39 +- .../js/src/wasm/WasmBaselineCompile.cpp | 1590 +- .../extract/js/src/wasm/WasmBaselineCompile.h | 2 +- .../mozjs/extract/js/src/wasm/WasmBinary.cpp | 103 +- .../mozjs/extract/js/src/wasm/WasmBinary.h | 105 +- .../extract/js/src/wasm/WasmBinaryTypes.h | 117 + .../extract/js/src/wasm/WasmBuiltinModule.cpp | 111 +- .../extract/js/src/wasm/WasmBuiltinModule.h | 26 +- .../js/src/wasm/WasmBuiltinModule.yaml | 57 +- .../extract/js/src/wasm/WasmBuiltins.cpp | 594 +- .../mozjs/extract/js/src/wasm/WasmBuiltins.h | 29 +- .../extract/js/src/wasm/WasmCode-platform.cpp | 23 +- .../mozjs/extract/js/src/wasm/WasmCode.cpp | 1971 ++- .../mozjs/extract/js/src/wasm/WasmCode.h | 1358 +- .../js/src/wasm/WasmCodegenConstants.h | 23 +- .../extract/js/src/wasm/WasmCodegenTypes.cpp | 241 +- .../extract/js/src/wasm/WasmCodegenTypes.h | 1045 +- .../mozjs/extract/js/src/wasm/WasmCompile.cpp | 570 +- .../mozjs/extract/js/src/wasm/WasmCompile.h | 36 +- .../extract/js/src/wasm/WasmCompileArgs.h | 308 +- .../mozjs/extract/js/src/wasm/WasmConstants.h | 108 +- .../mozjs/extract/js/src/wasm/WasmDebug.cpp | 136 +- .../mozjs/extract/js/src/wasm/WasmDebug.h | 66 +- .../extract/js/src/wasm/WasmDebugFrame.cpp | 8 +- .../mozjs/extract/js/src/wasm/WasmDump.cpp | 902 +- .../mozjs/extract/js/src/wasm/WasmDump.h | 240 +- .../mozjs/extract/js/src/wasm/WasmExprType.h | 31 +- .../extract/js/src/wasm/WasmFeatures.cpp | 9 +- .../mozjs/extract/js/src/wasm/WasmFeatures.h | 4 +- .../mozjs/extract/js/src/wasm/WasmFrame.h | 5 + .../extract/js/src/wasm/WasmFrameIter.cpp | 451 +- .../mozjs/extract/js/src/wasm/WasmFrameIter.h | 199 +- .../mozjs/extract/js/src/wasm/WasmGC.cpp | 35 +- .../mozjs/extract/js/src/wasm/WasmGC.h | 180 +- .../extract/js/src/wasm/WasmGcObject-inl.h | 67 +- .../extract/js/src/wasm/WasmGcObject.cpp | 42 +- .../mozjs/extract/js/src/wasm/WasmGcObject.h | 88 +- .../extract/js/src/wasm/WasmGenerator.cpp | 1512 +- .../mozjs/extract/js/src/wasm/WasmGenerator.h | 208 +- .../extract/js/src/wasm/WasmHeuristics.h | 324 + .../extract/js/src/wasm/WasmInitExpr.cpp | 62 +- .../mozjs/extract/js/src/wasm/WasmInitExpr.h | 21 +- .../extract/js/src/wasm/WasmInstance-inl.h | 16 +- .../extract/js/src/wasm/WasmInstance.cpp | 1445 +- .../mozjs/extract/js/src/wasm/WasmInstance.h | 178 +- .../extract/js/src/wasm/WasmInstanceData.h | 168 +- .../extract/js/src/wasm/WasmIonCompile.cpp | 6563 +++++--- .../extract/js/src/wasm/WasmIonCompile.h | 6 +- .../mozjs/extract/js/src/wasm/WasmJS.cpp | 1696 +- .../mozjs/extract/js/src/wasm/WasmJS.h | 52 +- .../mozjs/extract/js/src/wasm/WasmLog.cpp | 35 +- .../mozjs/extract/js/src/wasm/WasmMemory.cpp | 254 +- .../mozjs/extract/js/src/wasm/WasmMemory.h | 39 +- .../extract/js/src/wasm/WasmMetadata.cpp | 335 + .../mozjs/extract/js/src/wasm/WasmMetadata.h | 494 + .../mozjs/extract/js/src/wasm/WasmModule.cpp | 422 +- .../mozjs/extract/js/src/wasm/WasmModule.h | 95 +- .../extract/js/src/wasm/WasmModuleTypes.cpp | 55 +- .../extract/js/src/wasm/WasmModuleTypes.h | 351 +- .../mozjs/extract/js/src/wasm/WasmOpIter.cpp | 1286 +- .../mozjs/extract/js/src/wasm/WasmOpIter.h | 662 +- .../mozjs/extract/js/src/wasm/WasmPI.cpp | 1205 +- .../mozjs/extract/js/src/wasm/WasmPI.h | 62 +- .../mozjs/extract/js/src/wasm/WasmProcess.cpp | 356 +- .../mozjs/extract/js/src/wasm/WasmProcess.h | 18 +- .../mozjs/extract/js/src/wasm/WasmRealm.cpp | 19 +- .../extract/js/src/wasm/WasmSerialize.cpp | 992 +- .../mozjs/extract/js/src/wasm/WasmSerialize.h | 1 + .../mozjs/extract/js/src/wasm/WasmShareable.h | 66 +- .../js/src/wasm/WasmSignalHandlers.cpp | 64 +- .../js/src/wasm/WasmStaticTypeDefs.cpp | 29 +- .../extract/js/src/wasm/WasmStaticTypeDefs.h | 5 + .../mozjs/extract/js/src/wasm/WasmStubs.cpp | 807 +- .../mozjs/extract/js/src/wasm/WasmStubs.h | 36 +- .../extract/js/src/wasm/WasmSummarizeInsn.cpp | 289 + .../extract/js/src/wasm/WasmSummarizeInsn.h | 2 +- .../mozjs/extract/js/src/wasm/WasmTable.cpp | 127 +- .../mozjs/extract/js/src/wasm/WasmTable.h | 38 +- .../mozjs/extract/js/src/wasm/WasmTypeDecls.h | 23 +- .../mozjs/extract/js/src/wasm/WasmTypeDef.cpp | 25 +- .../mozjs/extract/js/src/wasm/WasmTypeDef.h | 259 +- .../mozjs/extract/js/src/wasm/WasmUtility.h | 14 +- .../mozjs/extract/js/src/wasm/WasmValType.cpp | 213 +- .../mozjs/extract/js/src/wasm/WasmValType.h | 220 +- .../extract/js/src/wasm/WasmValidate.cpp | 2699 +++- .../mozjs/extract/js/src/wasm/WasmValidate.h | 253 +- .../mozjs/extract/js/src/wasm/WasmValue.cpp | 155 +- .../mozjs/extract/js/src/wasm/WasmValue.h | 74 +- .../smoosh-jstests-slow.txt => wasm/test.js} | 0 .../mozjs/extract/js/src/xsum/LICENSE | 23 + .../mozjs/extract/js/src/xsum/README.md | 15 + .../mozjs/extract/js/src/xsum/moz.build | 20 + .../mozjs/extract/js/src/xsum/xsum.cpp | 1043 ++ .../mozjs/extract/js/src/xsum/xsum.h | 141 + .../mozjs/extract/mfbt/Alignment.h | 42 - src/third_party/mozjs/extract/mfbt/Array.h | 9 +- .../mozjs/extract/mfbt/ArrayUtils.h | 72 +- .../mozjs/extract/mfbt/Assertions.h | 149 +- src/third_party/mozjs/extract/mfbt/Atomics.h | 38 +- .../mozjs/extract/mfbt/Attributes.h | 85 +- src/third_party/mozjs/extract/mfbt/BitSet.h | 147 +- src/third_party/mozjs/extract/mfbt/Buffer.h | 2 +- src/third_party/mozjs/extract/mfbt/Casting.h | 131 +- .../mozjs/extract/mfbt/ChaosMode.cpp | 4 +- .../mozjs/extract/mfbt/ChaosMode.h | 22 +- .../mozjs/extract/mfbt/Compression.h | 218 - .../mozjs/extract/mfbt/DefineEnum.h | 67 +- .../mozjs/extract/mfbt/DoublyLinkedList.h | 32 + src/third_party/mozjs/extract/mfbt/EnumSet.h | 45 +- .../mozjs/extract/mfbt/EnumTypeTraits.h | 1 + .../mozjs/extract/mfbt/EnumeratedArray.h | 9 +- .../mozjs/extract/mfbt/FloatingPoint.h | 32 +- .../mozjs/extract/mfbt/HashTable.h | 29 + .../mozjs/extract/mfbt/JSONWriter.h | 8 +- .../mozjs/extract/mfbt/LinkedList.h | 22 +- src/third_party/mozjs/extract/mfbt/Literals.h | 8 +- .../mozjs/extract/mfbt/MathAlgorithms.h | 51 +- src/third_party/mozjs/extract/mfbt/Maybe.h | 25 +- .../mozjs/extract/mfbt/MaybeStorageBase.h | 6 +- .../mozjs/extract/mfbt/NeverDestroyed.h | 4 +- .../mozjs/extract/mfbt/PodOperations.h | 44 +- src/third_party/mozjs/extract/mfbt/Poison.cpp | 7 +- .../mozjs/extract/mfbt/RefCounted.cpp | 36 + .../mozjs/extract/mfbt/RefCounted.h | 44 +- src/third_party/mozjs/extract/mfbt/RefPtr.h | 4 +- .../mozjs/extract/mfbt/SegmentedVector.h | 4 +- src/third_party/mozjs/extract/mfbt/Span.h | 33 +- .../mozjs/extract/mfbt/StringBuffer.h | 85 +- src/third_party/mozjs/extract/mfbt/Try.h | 63 +- .../mozjs/extract/mfbt/TsanOptions.h | 95 - .../mozjs/extract/mfbt/UniquePtr.h | 17 +- .../extract/mfbt/UniquePtrExtensions.cpp | 21 + .../mozjs/extract/mfbt/UniquePtrExtensions.h | 40 +- src/third_party/mozjs/extract/mfbt/Utf8.cpp | 10 +- src/third_party/mozjs/extract/mfbt/Variant.h | 19 +- src/third_party/mozjs/extract/mfbt/Vector.h | 2 +- .../mozjs/extract/mfbt/WasiAtomic.h | 3 +- .../mozjs/extract/mfbt/WrappingOperations.h | 5 +- .../mozjs/extract/mfbt/lz4/LICENSE | 24 - .../mozjs/extract/mfbt/lz4/README.md | 169 - .../mozjs/extract/mfbt/lz4/README.mozilla | 18 - src/third_party/mozjs/extract/mfbt/moz.build | 24 +- .../extract/modules/fdlibm/math_private.h | 2 + .../mozglue/misc/AutoProfilerLabel.cpp | 3 +- .../extract/mozglue/misc/AwakeTimeStamp.cpp | 30 +- .../extract/mozglue/misc/LoggingCore.cpp | 18 + .../mozjs/extract/mozglue/misc/Now.cpp | 114 + .../extract/mozglue/misc/PreXULSkeletonUI.cpp | 409 +- .../extract/mozglue/misc/ProcessType.cpp | 20 +- .../mozjs/extract/mozglue/misc/SIMD.cpp | 13 + .../mozjs/extract/mozglue/misc/SIMD_avx2.cpp | 23 +- .../mozjs/extract/mozglue/misc/SSE.cpp | 30 +- .../mozjs/extract/mozglue/misc/StackWalk.cpp | 404 +- .../mozjs/extract/mozglue/misc/TimeStamp.cpp | 2 +- .../extract/mozglue/misc/TimeStamp_darwin.cpp | 3 +- .../extract/mozglue/misc/TimeStamp_posix.cpp | 17 +- .../mozglue/misc/TimeStamp_windows.cpp | 3 +- .../mozjs/extract/mozglue/misc/Uptime.cpp | 105 +- .../mozglue/misc/WindowsDiagnostics.cpp | 16 +- .../{mfbt => mozglue/static}/Compression.cpp | 0 .../{mfbt => mozglue/static}/lz4/lz4.c | 305 +- .../{mfbt => mozglue/static}/lz4/lz4.h | 180 +- .../{mfbt => mozglue/static}/lz4/lz4file.c | 192 +- .../{mfbt => mozglue/static}/lz4/lz4file.h | 4 +- .../{mfbt => mozglue/static}/lz4/lz4frame.c | 300 +- .../{mfbt => mozglue/static}/lz4/lz4frame.h | 265 +- .../static}/lz4/lz4frame_static.h | 0 .../{mfbt => mozglue/static}/lz4/lz4hc.c | 1311 +- .../{mfbt => mozglue/static}/lz4/lz4hc.h | 85 +- .../{mfbt => mozglue/static}/lz4/xxhash.c | 7 +- .../{mfbt => mozglue/static}/lz4/xxhash.h | 1315 +- src/third_party/mozjs/get-sources.sh | 11 +- .../mozjs/include/AwakeTimeStamp.h | 14 +- .../mozjs/include/BaseProfilingCategory.h | 77 + src/third_party/mozjs/include/LoggingCore.h | 49 + src/third_party/mozjs/include/NativeNt.h | 12 +- src/third_party/mozjs/include/Now.h | 25 + .../mozjs/include/PreXULSkeletonUI.h | 64 +- src/third_party/mozjs/include/ProcessType.h | 19 + .../mozjs/include/ProfilingCategoryList.h | 150 + src/third_party/mozjs/include/SIMD.h | 9 + .../mozjs/include/StackWalk_windows.h | 22 +- src/third_party/mozjs/include/TimeStamp.h | 1 + .../mozjs/include/WindowsDiagnostics.h | 12 +- .../mozjs/include/WindowsDpiAwareness.h | 6 +- .../mozjs/include/WindowsUnwindInfo.h | 2 +- .../mozjs/include/gc/StatsPhasesGenerated.h | 8 +- .../mozjs/include/js/AllocPolicy.h | 51 +- .../mozjs/include/js/CharacterEncoding.h | 20 - src/third_party/mozjs/include/js/Class.h | 5 - .../include/js/CompilationAndEvaluation.h | 14 +- .../mozjs/include/js/CompileOptions.h | 99 +- .../mozjs/include/js/ContextOptions.h | 42 - .../mozjs/include/js/Conversions.h | 16 +- src/third_party/mozjs/include/js/Debug.h | 178 +- .../mozjs/include/js/EnvironmentChain.h | 67 + .../mozjs/include/js/ErrorReport.h | 30 + src/third_party/mozjs/include/js/GCAPI.h | 69 +- .../mozjs/include/js/GCHashTable.h | 15 + .../mozjs/include/js/GCPolicyAPI.h | 34 + src/third_party/mozjs/include/js/GCVector.h | 2 +- src/third_party/mozjs/include/js/HeapAPI.h | 256 +- .../mozjs/include/js/HelperThreadAPI.h | 4 + src/third_party/mozjs/include/js/Id.h | 11 +- .../mozjs/include/js/Initialization.h | 1 - src/third_party/mozjs/include/js/JSON.h | 7 + src/third_party/mozjs/include/js/JitCodeAPI.h | 97 - src/third_party/mozjs/include/js/MapAndSet.h | 6 + .../mozjs/include/js/MemoryMetrics.h | 65 +- src/third_party/mozjs/include/js/Modules.h | 38 +- .../mozjs/include/js/NativeStackLimits.h | 52 + .../include/js/ObjectWithStashedPointer.h | 72 + src/third_party/mozjs/include/js/Prefs.h | 20 - .../mozjs/include/js/PrefsGenerated.h | 266 +- src/third_party/mozjs/include/js/Principals.h | 56 +- src/third_party/mozjs/include/js/Printer.h | 149 +- .../mozjs/include/js/ProfilingCategoryList.h | 9 + .../mozjs/include/js/ProfilingFrameIterator.h | 4 +- .../mozjs/include/js/ProfilingStack.h | 10 +- src/third_party/mozjs/include/js/Promise.h | 91 +- .../mozjs/include/js/PropertySpec.h | 2 +- src/third_party/mozjs/include/js/ProtoKey.h | 213 +- src/third_party/mozjs/include/js/Proxy.h | 55 +- src/third_party/mozjs/include/js/Realm.h | 10 + .../mozjs/include/js/RealmOptions.h | 6 + src/third_party/mozjs/include/js/RefCounted.h | 6 +- .../mozjs/include/js/RegExpFlags.h | 4 +- src/third_party/mozjs/include/js/RootingAPI.h | 282 +- .../mozjs/include/js/SliceBudget.h | 4 +- src/third_party/mozjs/include/js/Stack.h | 42 +- src/third_party/mozjs/include/js/String.h | 113 +- .../mozjs/include/js/StructuredClone.h | 23 +- src/third_party/mozjs/include/js/Symbol.h | 31 +- src/third_party/mozjs/include/js/TraceKind.h | 33 +- src/third_party/mozjs/include/js/TracingAPI.h | 8 +- .../mozjs/include/js/Transcoding.h | 53 +- src/third_party/mozjs/include/js/TypeDecls.h | 16 - src/third_party/mozjs/include/js/UbiNode.h | 20 + src/third_party/mozjs/include/js/Utility.h | 58 +- src/third_party/mozjs/include/js/Value.h | 107 +- .../mozjs/include/js/WasmFeatures.h | 36 +- src/third_party/mozjs/include/js/Wrapper.h | 3 + .../include/js/experimental/BindingAllocs.h | 31 + .../mozjs/include/js/experimental/JSStencil.h | 61 +- .../js/experimental/LoggingInterface.h | 98 + .../mozjs/include/js/experimental/TypedData.h | 7 +- .../mozjs/include/js/friend/ErrorNumbers.msg | 243 +- .../mozjs/include/js/friend/JSMEnvironment.h | 4 +- .../mozjs/include/js/friend/UsageStatistics.h | 59 +- .../mozjs/include/js/shadow/String.h | 2 + src/third_party/mozjs/include/jsapi.h | 12 +- src/third_party/mozjs/include/jsfriendapi.h | 19 +- src/third_party/mozjs/include/jspubtd.h | 10 - src/third_party/mozjs/include/malloc_decls.h | 77 +- .../mozjs/include/mozilla/Alignment.h | 42 - src/third_party/mozjs/include/mozilla/Array.h | 9 +- .../mozjs/include/mozilla/ArrayUtils.h | 72 +- .../mozjs/include/mozilla/Assertions.h | 149 +- .../mozjs/include/mozilla/Atomics.h | 38 +- .../mozjs/include/mozilla/Attributes.h | 85 +- .../mozjs/include/mozilla/AwakeTimeStamp.h | 14 +- .../mozilla/BaseAndGeckoProfilerDetail.h | 67 + .../include/mozilla/BaseProfileJSONWriter.h | 618 + .../include/mozilla/BaseProfilerCounts.h | 281 + .../include/mozilla/BaseProfilerDetail.h | 285 + .../include/mozilla/BaseProfilerLabels.h | 178 + .../include/mozilla/BaseProfilerMarkerTypes.h | 142 + .../include/mozilla/BaseProfilerMarkers.h | 268 + .../mozilla/BaseProfilerMarkersDetail.h | 743 + .../BaseProfilerMarkersPrerequisites.h | 1131 ++ .../include/mozilla/BaseProfilerRAIIMacro.h | 15 + .../mozjs/include/mozilla/BaseProfilerState.h | 429 + .../mozjs/include/mozilla/BaseProfilerUtils.h | 227 + .../mozjs/include/mozilla/BitSet.h | 147 +- .../mozjs/include/mozilla/Buffer.h | 2 +- .../mozjs/include/mozilla/Casting.h | 131 +- .../mozjs/include/mozilla/ChaosMode.h | 22 +- .../mozjs/include/mozilla/Compression.h | 44 +- .../mozjs/include/mozilla/DefineEnum.h | 67 +- .../mozjs/include/mozilla/DoublyLinkedList.h | 32 + .../mozjs/include/mozilla/EnumSet.h | 45 +- .../mozjs/include/mozilla/EnumTypeTraits.h | 1 + .../mozjs/include/mozilla/EnumeratedArray.h | 9 +- .../mozjs/include/mozilla/FailureLatch.h | 217 + .../mozjs/include/mozilla/FloatingPoint.h | 32 +- src/third_party/mozjs/include/mozilla/Flow.h | 91 + .../mozjs/include/mozilla/HashTable.h | 29 + .../mozjs/include/mozilla/JSONWriter.h | 8 +- .../mozjs/include/mozilla/LinkedList.h | 22 +- .../mozjs/include/mozilla/Literals.h | 39 + .../mozjs/include/mozilla/LoggingCore.h | 49 + .../mozjs/include/mozilla/MPSCQueue.h | 374 + .../mozjs/include/mozilla/MathAlgorithms.h | 51 +- src/third_party/mozjs/include/mozilla/Maybe.h | 25 +- .../mozjs/include/mozilla/MaybeStorageBase.h | 6 +- .../mozjs/include/mozilla/ModuloBuffer.h | 618 + .../mozjs/include/mozilla/NativeNt.h | 12 +- .../mozjs/include/mozilla/NeverDestroyed.h | 66 + src/third_party/mozjs/include/mozilla/Now.h | 25 + .../mozjs/include/mozilla/PodOperations.h | 44 +- .../mozjs/include/mozilla/PowerOfTwo.h | 322 + .../mozjs/include/mozilla/PreXULSkeletonUI.h | 64 +- .../mozjs/include/mozilla/ProcessType.h | 19 + .../include/mozilla/ProfileBufferChunk.h | 547 + .../mozilla/ProfileBufferChunkManager.h | 134 + .../mozilla/ProfileBufferChunkManagerSingle.h | 172 + .../ProfileBufferChunkManagerWithLocalLimit.h | 444 + .../ProfileBufferControlledChunkManager.h | 203 + .../include/mozilla/ProfileBufferEntryKinds.h | 104 + .../mozilla/ProfileBufferEntrySerialization.h | 1184 ++ .../include/mozilla/ProfileBufferIndex.h | 97 + .../include/mozilla/ProfileChunkedBuffer.h | 1560 ++ .../mozilla/ProfileChunkedBufferDetail.h | 401 + .../include/mozilla/ProfilerBufferSize.h | 60 + .../mozjs/include/mozilla/ProgressLogger.h | 500 + .../mozjs/include/mozilla/ProportionValue.h | 235 + .../mozjs/include/mozilla/RefCounted.h | 44 +- .../mozjs/include/mozilla/RefPtr.h | 4 +- src/third_party/mozjs/include/mozilla/SIMD.h | 9 + .../mozjs/include/mozilla/SegmentedVector.h | 4 +- src/third_party/mozjs/include/mozilla/Span.h | 33 +- .../mozjs/include/mozilla/StackWalk_windows.h | 22 +- .../mozjs/include/mozilla/StringBuffer.h | 318 + .../mozjs/include/mozilla/TimeStamp.h | 1 + src/third_party/mozjs/include/mozilla/Try.h | 63 +- .../mozjs/include/mozilla/UniquePtr.h | 17 +- .../include/mozilla/UniquePtrExtensions.h | 40 +- .../mozjs/include/mozilla/Variant.h | 19 +- .../mozjs/include/mozilla/Vector.h | 2 +- .../include/mozilla/WindowsDiagnostics.h | 12 +- .../include/mozilla/WindowsDpiAwareness.h | 6 +- .../mozjs/include/mozilla/WindowsUnwindInfo.h | 2 +- .../include/mozilla/WrappingOperations.h | 5 +- .../mozjs/include/mozilla/leb128iterator.h | 207 + .../mozjs/include/mozjemalloc_types.h | 65 +- src/third_party/mozjs/include/mozmemory.h | 2 + .../mozjs/include/mozmemory_wrap.h | 3 + .../include/wasm/WasmBuiltinModuleGenerated.h | 56 +- .../mozjs/mongo_sources/jscustomallocator.h | 32 +- .../mongo_sources/jscustomallocator_oom.h | 33 +- .../mongoErrorReportToString.cpp | 2 +- .../linux/build/Unified_cpp_js_src16.cpp | 18 +- .../linux/build/Unified_cpp_js_src17.cpp | 24 +- .../linux/build/Unified_cpp_js_src21.cpp | 18 +- .../linux/build/Unified_cpp_js_src22.cpp | 18 +- .../linux/build/Unified_cpp_js_src23.cpp | 18 +- .../linux/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../linux/build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../linux/build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../aarch64/linux/build/js-confdefs.h | 22 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../linux/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../include/jit/AtomicOperationsGenerated.h | 27 +- .../linux/include/jit/CacheIROpsGenerated.h | 1824 ++- .../linux/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../linux/include/jit/MIROpsGenerated.h | 556 +- .../aarch64/linux/include/js-confdefs.h | 22 +- .../aarch64/linux/include/js-config.h | 18 +- .../aarch64/linux/include/selfhosted.out.h | 6 +- .../macOS/build/Unified_cpp_js_src16.cpp | 18 +- .../macOS/build/Unified_cpp_js_src17.cpp | 24 +- .../macOS/build/Unified_cpp_js_src21.cpp | 18 +- .../macOS/build/Unified_cpp_js_src22.cpp | 18 +- .../macOS/build/Unified_cpp_js_src23.cpp | 18 +- .../macOS/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../macOS/build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../macOS/build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../aarch64/macOS/build/js-confdefs.h | 19 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../macOS/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../include/jit/AtomicOperationsGenerated.h | 27 +- .../macOS/include/jit/CacheIROpsGenerated.h | 1824 ++- .../macOS/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../macOS/include/jit/MIROpsGenerated.h | 556 +- .../aarch64/macOS/include/js-confdefs.h | 19 +- .../aarch64/macOS/include/js-config.h | 18 +- .../aarch64/macOS/include/selfhosted.out.h | 6 +- .../linux/build/Unified_cpp_js_src16.cpp | 18 +- .../linux/build/Unified_cpp_js_src17.cpp | 24 +- .../linux/build/Unified_cpp_js_src21.cpp | 18 +- .../linux/build/Unified_cpp_js_src22.cpp | 18 +- .../linux/build/Unified_cpp_js_src23.cpp | 18 +- .../linux/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../linux/build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../linux/build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../ppc64le/linux/build/js-confdefs.h | 19 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../linux/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../linux/include/jit/CacheIROpsGenerated.h | 1824 ++- .../linux/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../linux/include/jit/MIROpsGenerated.h | 556 +- .../ppc64le/linux/include/js-confdefs.h | 19 +- .../ppc64le/linux/include/js-config.h | 18 +- .../ppc64le/linux/include/selfhosted.out.h | 6 +- .../linux/build/Unified_cpp_js_src16.cpp | 18 +- .../linux/build/Unified_cpp_js_src17.cpp | 24 +- .../linux/build/Unified_cpp_js_src21.cpp | 18 +- .../linux/build/Unified_cpp_js_src22.cpp | 18 +- .../linux/build/Unified_cpp_js_src23.cpp | 18 +- .../linux/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../linux/build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../linux/build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../platform/s390x/linux/build/js-confdefs.h | 19 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../linux/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../linux/include/jit/CacheIROpsGenerated.h | 1824 ++- .../s390x/linux/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../s390x/linux/include/jit/MIROpsGenerated.h | 556 +- .../s390x/linux/include/js-confdefs.h | 19 +- .../platform/s390x/linux/include/js-config.h | 18 +- .../s390x/linux/include/selfhosted.out.h | 6 +- .../linux/build/Unified_cpp_js_src16.cpp | 18 +- .../linux/build/Unified_cpp_js_src17.cpp | 24 +- .../linux/build/Unified_cpp_js_src21.cpp | 18 +- .../linux/build/Unified_cpp_js_src22.cpp | 18 +- .../linux/build/Unified_cpp_js_src23.cpp | 18 +- .../linux/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../linux/build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../linux/build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../platform/x86_64/linux/build/js-confdefs.h | 20 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../linux/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../include/jit/AtomicOperationsGenerated.h | 27 +- .../linux/include/jit/CacheIROpsGenerated.h | 1824 ++- .../linux/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../linux/include/jit/MIROpsGenerated.h | 556 +- .../x86_64/linux/include/js-confdefs.h | 20 +- .../platform/x86_64/linux/include/js-config.h | 18 +- .../x86_64/linux/include/selfhosted.out.h | 6 +- .../macOS/build/Unified_cpp_js_src16.cpp | 18 +- .../macOS/build/Unified_cpp_js_src17.cpp | 24 +- .../macOS/build/Unified_cpp_js_src21.cpp | 18 +- .../macOS/build/Unified_cpp_js_src22.cpp | 18 +- .../macOS/build/Unified_cpp_js_src23.cpp | 18 +- .../macOS/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../macOS/build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../macOS/build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../platform/x86_64/macOS/build/js-confdefs.h | 19 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../macOS/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../include/jit/AtomicOperationsGenerated.h | 27 +- .../macOS/include/jit/CacheIROpsGenerated.h | 1824 ++- .../macOS/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../macOS/include/jit/MIROpsGenerated.h | 556 +- .../x86_64/macOS/include/js-confdefs.h | 19 +- .../platform/x86_64/macOS/include/js-config.h | 18 +- .../x86_64/macOS/include/selfhosted.out.h | 6 +- .../windows/build/Unified_cpp_js_src16.cpp | 18 +- .../windows/build/Unified_cpp_js_src17.cpp | 24 +- .../windows/build/Unified_cpp_js_src21.cpp | 18 +- .../windows/build/Unified_cpp_js_src22.cpp | 18 +- .../windows/build/Unified_cpp_js_src23.cpp | 18 +- .../windows/build/Unified_cpp_js_src24.cpp | 9 - .../frontend/Unified_cpp_js_src_frontend1.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend2.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend3.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend4.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend5.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend6.cpp | 18 +- .../frontend/Unified_cpp_js_src_frontend7.cpp | 9 - .../build/gc/Unified_cpp_js_src_gc0.cpp | 18 +- .../build/gc/Unified_cpp_js_src_gc1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit1.cpp | 18 +- .../build/jit/Unified_cpp_js_src_jit10.cpp | 72 +- .../build/jit/Unified_cpp_js_src_jit11.cpp | 78 +- .../build/jit/Unified_cpp_js_src_jit12.cpp | 90 +- .../build/jit/Unified_cpp_js_src_jit13.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit14.cpp | 42 +- .../build/jit/Unified_cpp_js_src_jit15.cpp | 37 + .../build/jit/Unified_cpp_js_src_jit2.cpp | 24 +- .../build/jit/Unified_cpp_js_src_jit3.cpp | 36 +- .../build/jit/Unified_cpp_js_src_jit4.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit5.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit6.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit7.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit8.cpp | 54 +- .../build/jit/Unified_cpp_js_src_jit9.cpp | 72 +- .../x86_64/windows/build/js-confdefs.h | 23 +- .../build/util/Unified_cpp_js_src_util1.cpp | 6 +- .../build/wasm/Unified_cpp_js_src_wasm4.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm5.cpp | 18 +- .../build/wasm/Unified_cpp_js_src_wasm6.cpp | 9 + .../windows/include/gc/StatsPhasesGenerated.h | 8 +- .../include/jit/ABIFunctionTypeGenerated.h | 342 +- .../windows/include/jit/CacheIROpsGenerated.h | 1824 ++- .../windows/include/jit/LIROpsGenerated.h | 10666 ++++++++----- .../windows/include/jit/MIROpsGenerated.h | 556 +- .../x86_64/windows/include/js-confdefs.h | 23 +- .../x86_64/windows/include/js-config.h | 18 +- .../x86_64/windows/include/selfhosted.out.h | 6 +- 1688 files changed, 238147 insertions(+), 152660 deletions(-) create mode 100644 src/third_party/mozjs/extract/js/public/EnvironmentChain.h delete mode 100644 src/third_party/mozjs/extract/js/public/JitCodeAPI.h create mode 100644 src/third_party/mozjs/extract/js/public/NativeStackLimits.h create mode 100644 src/third_party/mozjs/extract/js/public/ObjectWithStashedPointer.h create mode 100644 src/third_party/mozjs/extract/js/public/experimental/BindingAllocs.h create mode 100644 src/third_party/mozjs/extract/js/public/experimental/LoggingInterface.h delete mode 100644 src/third_party/mozjs/extract/js/src/aclocal.m4 delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/.eslintrc.js create mode 100644 src/third_party/mozjs/extract/js/src/builtin/.eslintrc.mjs create mode 100644 src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStack.js create mode 100644 src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.cpp create mode 100644 src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/DisposableStack.js create mode 100644 src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.cpp create mode 100644 src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.cpp create mode 100644 src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/MapObject-inl.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject-inl.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject.h delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/RecordObject.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/RecordObject.h delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/Tuple.js delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/TupleObject.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/TupleObject.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.cpp create mode 100644 src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.js create mode 100644 src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneMapping.yaml create mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.cpp create mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/Era.h create mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/MonthCode.h delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.h delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.h create mode 100644 src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.cpp create mode 100644 src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.h delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jittest-known-failure.txt delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure-and-slow.txt delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure.txt delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/variants/rtdebug delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/variants/smoosh delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/variants/smooshdebug delete mode 100644 src/third_party/mozjs/extract/js/src/devtools/automation/variants/temporaldebug delete mode 100644 src/third_party/mozjs/extract/js/src/ds/OrderedHashTable.h create mode 100644 src/third_party/mozjs/extract/js/src/ds/SlimLinkedList.h delete mode 100644 src/third_party/mozjs/extract/js/src/frontend/CompileScript.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/frontend/Frontend2.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/frontend/Frontend2.h delete mode 100644 src/third_party/mozjs/extract/js/src/fuzz-tests/differential-parsing.js create mode 100644 src/third_party/mozjs/extract/js/src/gc/BufferAllocator-inl.h create mode 100644 src/third_party/mozjs/extract/js/src/gc/BufferAllocator.cpp create mode 100644 src/third_party/mozjs/extract/js/src/gc/BufferAllocator.h create mode 100755 src/third_party/mozjs/extract/js/src/ics/remove-duplicates.py create mode 100644 src/third_party/mozjs/extract/js/src/jit/BaselineCompileQueue.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/BaselineCompileTask.cpp create mode 100644 src/third_party/mozjs/extract/js/src/jit/BaselineCompileTask.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/CacheIRAOT.cpp create mode 100644 src/third_party/mozjs/extract/js/src/jit/CacheIRAOT.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/CompilationDependencyTracker.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/DominatorTree.cpp create mode 100644 src/third_party/mozjs/extract/js/src/jit/DominatorTree.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/InvalidationScriptSet.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/MIR-wasm.cpp create mode 100644 src/third_party/mozjs/extract/js/src/jit/MIR-wasm.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/OffthreadSnapshot.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/SimpleAllocator.cpp create mode 100644 src/third_party/mozjs/extract/js/src/jit/SimpleAllocator.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/SparseBitSet.h create mode 100644 src/third_party/mozjs/extract/js/src/jit/UnrollLoops.cpp create mode 100644 src/third_party/mozjs/extract/js/src/jit/UnrollLoops.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips-shared/BaselineIC-mips-shared.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Architecture-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Architecture-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Assembler-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Assembler-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/CodeGenerator-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/CodeGenerator-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/LIR-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Lowering-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Lowering-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/MacroAssembler-mips32-inl.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/MacroAssembler-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/MacroAssembler-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/MoveEmitter-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/MoveEmitter-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/SharedICRegisters-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Simulator-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Simulator-mips32.h delete mode 100644 src/third_party/mozjs/extract/js/src/jit/mips32/Trampoline-mips32.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/util/StringBuffer.cpp create mode 100644 src/third_party/mozjs/extract/js/src/util/StringBuilder.cpp rename src/third_party/mozjs/extract/js/src/util/{StringBuffer.h => StringBuilder.h} (72%) create mode 100644 src/third_party/mozjs/extract/js/src/vm/ConstantCompareOperand.h create mode 100644 src/third_party/mozjs/extract/js/src/vm/DisposableRecord-inl.h create mode 100644 src/third_party/mozjs/extract/js/src/vm/DisposableRecord.cpp create mode 100644 src/third_party/mozjs/extract/js/src/vm/DisposableRecord.h delete mode 100644 src/third_party/mozjs/extract/js/src/vm/InlineCharBuffer-inl.h create mode 100644 src/third_party/mozjs/extract/js/src/vm/Logging.cpp create mode 100644 src/third_party/mozjs/extract/js/src/vm/Logging.h create mode 100644 src/third_party/mozjs/extract/js/src/vm/ObjectWithStashedPointer.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/PIC.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/PIC.h delete mode 100644 src/third_party/mozjs/extract/js/src/vm/PromiseLookup.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/PromiseLookup.h delete mode 100644 src/third_party/mozjs/extract/js/src/vm/RecordTupleShared.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/RecordType.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/RecordType.h delete mode 100644 src/third_party/mozjs/extract/js/src/vm/StencilCache.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/StencilCache.h delete mode 100644 src/third_party/mozjs/extract/js/src/vm/TupleType.cpp delete mode 100644 src/third_party/mozjs/extract/js/src/vm/TupleType.h create mode 100644 src/third_party/mozjs/extract/js/src/vm/UsingHint.h create mode 100644 src/third_party/mozjs/extract/js/src/wasm/WasmBinaryTypes.h create mode 100644 src/third_party/mozjs/extract/js/src/wasm/WasmHeuristics.h create mode 100644 src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.cpp create mode 100644 src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.h rename src/third_party/mozjs/extract/js/src/{devtools/automation/smoosh-jstests-slow.txt => wasm/test.js} (100%) create mode 100644 src/third_party/mozjs/extract/js/src/xsum/LICENSE create mode 100644 src/third_party/mozjs/extract/js/src/xsum/README.md create mode 100644 src/third_party/mozjs/extract/js/src/xsum/moz.build create mode 100644 src/third_party/mozjs/extract/js/src/xsum/xsum.cpp create mode 100644 src/third_party/mozjs/extract/js/src/xsum/xsum.h delete mode 100644 src/third_party/mozjs/extract/mfbt/Compression.h create mode 100644 src/third_party/mozjs/extract/mfbt/RefCounted.cpp delete mode 100644 src/third_party/mozjs/extract/mfbt/TsanOptions.h delete mode 100644 src/third_party/mozjs/extract/mfbt/lz4/LICENSE delete mode 100644 src/third_party/mozjs/extract/mfbt/lz4/README.md delete mode 100644 src/third_party/mozjs/extract/mfbt/lz4/README.mozilla create mode 100644 src/third_party/mozjs/extract/mozglue/misc/LoggingCore.cpp create mode 100644 src/third_party/mozjs/extract/mozglue/misc/Now.cpp rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/Compression.cpp (100%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4.c (91%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4.h (88%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4file.c (67%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4file.h (98%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4frame.c (89%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4frame.h (84%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4frame_static.h (100%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4hc.c (64%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/lz4hc.h (93%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/xxhash.c (91%) rename src/third_party/mozjs/extract/{mfbt => mozglue/static}/lz4/xxhash.h (88%) create mode 100644 src/third_party/mozjs/include/BaseProfilingCategory.h create mode 100644 src/third_party/mozjs/include/LoggingCore.h create mode 100644 src/third_party/mozjs/include/Now.h create mode 100644 src/third_party/mozjs/include/ProfilingCategoryList.h create mode 100644 src/third_party/mozjs/include/js/EnvironmentChain.h delete mode 100644 src/third_party/mozjs/include/js/JitCodeAPI.h create mode 100644 src/third_party/mozjs/include/js/NativeStackLimits.h create mode 100644 src/third_party/mozjs/include/js/ObjectWithStashedPointer.h create mode 100644 src/third_party/mozjs/include/js/experimental/BindingAllocs.h create mode 100644 src/third_party/mozjs/include/js/experimental/LoggingInterface.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseAndGeckoProfilerDetail.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfileJSONWriter.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerCounts.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerDetail.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerLabels.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerMarkerTypes.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerMarkers.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerMarkersDetail.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerMarkersPrerequisites.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerRAIIMacro.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerState.h create mode 100644 src/third_party/mozjs/include/mozilla/BaseProfilerUtils.h create mode 100644 src/third_party/mozjs/include/mozilla/FailureLatch.h create mode 100644 src/third_party/mozjs/include/mozilla/Flow.h create mode 100644 src/third_party/mozjs/include/mozilla/Literals.h create mode 100644 src/third_party/mozjs/include/mozilla/LoggingCore.h create mode 100644 src/third_party/mozjs/include/mozilla/MPSCQueue.h create mode 100644 src/third_party/mozjs/include/mozilla/ModuloBuffer.h create mode 100644 src/third_party/mozjs/include/mozilla/NeverDestroyed.h create mode 100644 src/third_party/mozjs/include/mozilla/Now.h create mode 100644 src/third_party/mozjs/include/mozilla/PowerOfTwo.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferChunk.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferChunkManager.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerSingle.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerWithLocalLimit.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferControlledChunkManager.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferEntryKinds.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferEntrySerialization.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileBufferIndex.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileChunkedBuffer.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfileChunkedBufferDetail.h create mode 100644 src/third_party/mozjs/include/mozilla/ProfilerBufferSize.h create mode 100644 src/third_party/mozjs/include/mozilla/ProgressLogger.h create mode 100644 src/third_party/mozjs/include/mozilla/ProportionValue.h create mode 100644 src/third_party/mozjs/include/mozilla/StringBuffer.h create mode 100644 src/third_party/mozjs/include/mozilla/leb128iterator.h create mode 100644 src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit15.cpp create mode 100644 src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp create mode 100644 src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit15.cpp create mode 100644 src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit15.cpp create mode 100644 src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit15.cpp create mode 100644 src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp create mode 100644 src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit15.cpp diff --git a/README.third_party.md b/README.third_party.md index f007f9c3f55..17bf8cae50f 100644 --- a/README.third_party.md +++ b/README.third_party.md @@ -50,7 +50,7 @@ a notice will be included in | [libunwind] | MIT | 1.8.1 | | ✗ | | [linenoise] | BSD-2-Clause | 6cdc775807e57b2c3fd64bd207814f8ee1fe35f3 | | ✗ | | [MongoDB C Driver] | Apache-2.0 | 1.28.1 | ✗ | ✗ | -| [Mozilla Firefox ESR] | MPL-2.0 | 128.11.0esr | | ✗ | +| [Mozilla Firefox ESR] | MPL-2.0 | 140.3.0esr | | ✗ | | [MurmurHash3] | Public Domain | a6bd3ce7be8ad147ea820a7cf6229a975c0c96bb | | ✗ | | [nlohmann/json] | MIT | 3.11.3 | ✗ | | | [node] | ISC | 22.1.0 | | | diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index fe3127e9a67..fc1fe0913be 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -107,6 +107,8 @@ last-continuous: ticket: SERVER-114126 - test_file: jstests/replsets/rollback_index_build_start_abort.js ticket: SERVER-103955 + - test_file: jstests/sharding/query/javascript_heap_limit.js + ticket: SERVER-109200 suites: null last-lts: all: @@ -716,4 +718,6 @@ last-lts: ticket: SERVER-114126 - test_file: jstests/replsets/rollback_index_build_start_abort.js ticket: SERVER-103955 + - test_file: jstests/sharding/query/javascript_heap_limit.js + ticket: SERVER-109200 suites: null diff --git a/jstests/aggregation/accumulators/accumulator_js_size_limits.js b/jstests/aggregation/accumulators/accumulator_js_size_limits.js index f5fdc3b3e66..aa3e6d87e37 100644 --- a/jstests/aggregation/accumulators/accumulator_js_size_limits.js +++ b/jstests/aggregation/accumulators/accumulator_js_size_limits.js @@ -145,20 +145,20 @@ const largeAccumulator = { }; res = coll .aggregate([ - {$addFields: {a: {$range: [0, 1000000]}}}, + {$addFields: {a: {$range: [0, 250000]}}}, {$unwind: "$a"}, // Create a number of documents to be executed by the accumulator. {$group: {_id: "$groupBy", count: largeAccumulator}}, ]) .toArray(); assert.sameMembers(res, [ - {_id: 1, count: 1000000}, - {_id: 2, count: 1000000}, + {_id: 1, count: 250000}, + {_id: 2, count: 250000}, ]); // With $bucket. res = coll .aggregate([ - {$addFields: {a: {$range: [0, 1000000]}}}, + {$addFields: {a: {$range: [0, 250000]}}}, {$unwind: "$a"}, // Create a number of documents to be executed by the accumulator. { $bucket: {groupBy: "$groupBy", boundaries: [1, 2, 3], output: {count: largeAccumulator}}, @@ -166,6 +166,6 @@ res = coll ]) .toArray(); assert.sameMembers(res, [ - {_id: 1, count: 1000000}, - {_id: 2, count: 1000000}, + {_id: 1, count: 250000}, + {_id: 2, count: 250000}, ]); diff --git a/jstests/core/query/js/js_global_scope.js b/jstests/core/query/js/js_global_scope.js index 68064be0f2c..3cda56a3073 100644 --- a/jstests/core/query/js/js_global_scope.js +++ b/jstests/core/query/js/js_global_scope.js @@ -38,6 +38,7 @@ const expectedGlobalVars = [ "Error", "EvalError", "FinalizationRegistry", + "Float16Array", "Float32Array", "Float64Array", "Function", @@ -48,6 +49,7 @@ const expectedGlobalVars = [ "Int32Array", "Int8Array", "InternalError", + "Iterator", "JSON", "MD5", "Map", diff --git a/jstests/sharding/query/agg/agg_merge_explain_size_limit.js b/jstests/sharding/query/agg/agg_merge_explain_size_limit.js index dfec3e28aeb..b90edb31c8f 100644 --- a/jstests/sharding/query/agg/agg_merge_explain_size_limit.js +++ b/jstests/sharding/query/agg/agg_merge_explain_size_limit.js @@ -40,7 +40,7 @@ st.shardColl(coll, {_id: 1}, {_id: 0}, {_id: 0}); explain: { aggregate: coll.getName(), pipeline: [ - {$addFields: {a: {$range: [0, 1000000]}}}, + {$addFields: {a: {$range: [0, 250000]}}}, {$unwind: "$a"}, // Create a number of documents to be executed by the accumulator. {$group: {_id: "$groupBy", count: largeAccumulator}}, ], diff --git a/jstests/sharding/query/javascript_heap_limit.js b/jstests/sharding/query/javascript_heap_limit.js index 4cc5cc576f2..faadf547abd 100644 --- a/jstests/sharding/query/javascript_heap_limit.js +++ b/jstests/sharding/query/javascript_heap_limit.js @@ -39,6 +39,12 @@ function setHeapSizeLimitMB({queryLimit, globalLimit}) { }); } +function setLegacyMemoryTracking({useLegacy}) { + st.forEachConnection((conn) => { + assert.commandWorked(conn.getDB("test").adminCommand({setParameter: 1, jsUseLegacyMemoryTracking: useLegacy})); + }); +} + function allocateLargeString() { const arraySize = 1000000; let str = new Array(arraySize).fill(0); @@ -116,6 +122,8 @@ const findWithWhere = { * part of an aggregation pipeline. */ function runCommonTests(db) { + setLegacyMemoryTracking({db: db, useLegacy: false}); + // All commands are expected to work with a sufficient JS heap size. setHeapSizeLimitMB({db: db, queryLimit: sufficentHeapSizeMB, globalLimit: sufficentHeapSizeMB}); assert.commandWorked(db.runCommand(aggregateWithJSFunction)); @@ -135,6 +143,13 @@ function runCommonTests(db) { assert.commandFailedWithCode(db.runCommand(aggregateWithJSFunction), ErrorCodes.JSInterpreterFailure); assert.commandFailedWithCode(db.runCommand(aggregateWithInternalJsReduce), ErrorCodes.JSInterpreterFailure); assert.commandFailedWithCode(db.runCommand(aggregateWithUserDefinedAccumulator), ErrorCodes.JSInterpreterFailure); + + // Enabling legacy memory tracking doesn't count large buffers, so queries should pass that otherwise fail + setLegacyMemoryTracking({db: db, useLegacy: true}); + setHeapSizeLimitMB({db: db, queryLimit: tooSmallHeapSizeMB, globalLimit: tooSmallHeapSizeMB}); + assert.commandWorked(db.runCommand(aggregateWithJSFunction)); + assert.commandWorked(db.runCommand(aggregateWithInternalJsReduce)); + assert.commandWorked(db.runCommand(aggregateWithUserDefinedAccumulator)); } /** @@ -142,6 +157,8 @@ function runCommonTests(db) { * only evaluated on mongod, not on mongos. */ function runShardTests(db) { + setLegacyMemoryTracking({db: db, useLegacy: false}); + // All commands are expected to work with a sufficient JS heap size. setHeapSizeLimitMB({db: db, queryLimit: sufficentHeapSizeMB, globalLimit: sufficentHeapSizeMB}); assert.commandWorked(db.runCommand(findWithJavaScriptFunction)); @@ -168,6 +185,14 @@ function runShardTests(db) { // TODO SERVER-45454: Uncomment when $where is executed via aggregation JavaScript expression. // assert.commandFailedWithCode(db.runCommand(findWithWhere), ErrorCodes.JSInterpreterFailure); assert.commandFailedWithCode(db.runCommand(mapReduce), ErrorCodes.JSInterpreterFailure); + + // Enabling legacy memory tracking doesn't count large buffers, so queries should pass that otherwise fail + setLegacyMemoryTracking({db: db, useLegacy: true}); + setHeapSizeLimitMB({db: db, queryLimit: tooSmallHeapSizeMB, globalLimit: tooSmallHeapSizeMB}); + assert.commandWorked(db.runCommand(findWithJavaScriptFunction)); + // TODO SERVER-45454: Uncomment when $where is executed via aggregation JavaScript expression. + // assert.commandWorked(db.runCommand(findWithWhere)); + assert.commandWorked(db.runCommand(mapReduce)); } // Test command invocations that can execute JavaScript on either mongos or mongod. diff --git a/sbom.json b/sbom.json index d486a1f01bc..4fb7dc5e4e6 100644 --- a/sbom.json +++ b/sbom.json @@ -71,7 +71,7 @@ "components": [ { "type": "library", - "bom-ref": "pkg:deb/debian/firefox-esr@128.11.0esr-1?arch=source", + "bom-ref": "pkg:deb/debian/firefox-esr@140.3.0esr-1?arch=source", "supplier": { "name": "Mozilla Corporation", "url": [ @@ -81,7 +81,7 @@ "author": "Mozilla Corporation", "group": "mozilla", "name": "Mozilla Firefox ESR", - "version": "128.11.0esr", + "version": "140.3.0esr", "description": "The C++-only SpiderMonkey component of FireFox ESR used by MongoDB.", "licenses": [ { @@ -91,8 +91,8 @@ } ], "copyright": "Mozilla Corporation", - "cpe": "cpe:2.3:a:mozilla:firefox:128.11.0:*:*:*:esr:*:*:*", - "purl": "pkg:deb/debian/firefox-esr@128.11.0esr-1?arch=source", + "cpe": "cpe:2.3:a:mozilla:firefox:140.3.0:*:*:*:esr:*:*:*", + "purl": "pkg:deb/debian/firefox-esr@140.3.0esr-1?arch=source", "externalReferences": [ { "url": "https://github.com/mozilla-firefox/firefox.git", @@ -2628,7 +2628,7 @@ "pkg:github/libunwind/libunwind@v1.8.1", "pkg:github/antirez/linenoise@6cdc775807e57b2c3fd64bd207814f8ee1fe35f3", "pkg:github/mongodb/mongo-c-driver@1.28.1", - "pkg:deb/debian/firefox-esr@128.11.0esr-1?arch=source", + "pkg:deb/debian/firefox-esr@140.3.0esr-1?arch=source", "pkg:github/nodejs/node@22.1.0?download_url=https%3A%2F%2Fgithub.com%2Fnodejs%2Fnode%2Fblob%2F8b45c5d26a829bcd3280401dbc1874bcd1302289%2Fsrc%2Fnode_i18n.cc%23L825%23src%2Fnode_i18n.cc%3AGetStringWidth#src/node_i18n.cc", "pkg:pypi/ocspbuilder@0.10.2", "pkg:pypi/ocspresponder@0.5.0", @@ -2768,7 +2768,7 @@ "dependsOn": [] }, { - "ref": "pkg:deb/debian/firefox-esr@128.11.0esr-1?arch=source", + "ref": "pkg:deb/debian/firefox-esr@140.3.0esr-1?arch=source", "dependsOn": [] }, { diff --git a/src/mongo/scripting/engine.h b/src/mongo/scripting/engine.h index 719bd106dc7..270f28d0986 100644 --- a/src/mongo/scripting/engine.h +++ b/src/mongo/scripting/engine.h @@ -266,6 +266,8 @@ public: virtual int getJSHeapLimitMB() const = 0; virtual void setJSHeapLimitMB(int limit) = 0; + virtual bool getJSUseLegacyMemoryTracking() const = 0; + virtual void setJSUseLegacyMemoryTracking(bool shouldUseLegacy) = 0; virtual std::string getLoadPath() const = 0; virtual void setLoadPath(const std::string& loadPath) = 0; diff --git a/src/mongo/scripting/mozjs/engine.cpp b/src/mongo/scripting/mozjs/engine.cpp index 8b7beb20ed7..027a186fc1b 100644 --- a/src/mongo/scripting/mozjs/engine.cpp +++ b/src/mongo/scripting/mozjs/engine.cpp @@ -140,6 +140,14 @@ void MozJSScriptEngine::setJSHeapLimitMB(int limit) { gJSHeapLimitMB.store(limit); } +bool MozJSScriptEngine::getJSUseLegacyMemoryTracking() const { + return gJSUseLegacyMemoryTracking.load(); +} + +void MozJSScriptEngine::setJSUseLegacyMemoryTracking(bool shouldUseLegacy) { + gJSUseLegacyMemoryTracking.store(shouldUseLegacy); +} + std::string MozJSScriptEngine::getLoadPath() const { return _loadPath; } diff --git a/src/mongo/scripting/mozjs/engine.h b/src/mongo/scripting/mozjs/engine.h index 439ba9e1d9e..e0839e66646 100644 --- a/src/mongo/scripting/mozjs/engine.h +++ b/src/mongo/scripting/mozjs/engine.h @@ -69,6 +69,9 @@ public: int getJSHeapLimitMB() const override; void setJSHeapLimitMB(int limit) override; + bool getJSUseLegacyMemoryTracking() const override; + void setJSUseLegacyMemoryTracking(bool shouldUseLegacyEngine) override; + std::string getLoadPath() const override; void setLoadPath(const std::string& loadPath) override; diff --git a/src/mongo/scripting/mozjs/engine.idl b/src/mongo/scripting/mozjs/engine.idl index 49144a63dea..d003b05a86c 100644 --- a/src/mongo/scripting/mozjs/engine.idl +++ b/src/mongo/scripting/mozjs/engine.idl @@ -46,3 +46,11 @@ server_parameters: cpp_varname: gJSHeapLimitMB default: 1100 redact: false + + jsUseLegacyMemoryTracking: + description: "fallback to use legacy memory tracking" + set_at: [startup, runtime] + cpp_vartype: Atomic + cpp_varname: gJSUseLegacyMemoryTracking + default: false + redact: false diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp index d9caa3b7644..f314f9e1ba2 100644 --- a/src/mongo/scripting/mozjs/exception.cpp +++ b/src/mongo/scripting/mozjs/exception.cpp @@ -61,6 +61,7 @@ void mongoToJSException(JSContext* cx) { JS_SetPendingException(cx, val); } } else { + JS::ReportUncatchableException(cx); // If a JSAPI callback returns false without setting a pending exception, SpiderMonkey will // treat it as an uncatchable error. auto scope = getScope(cx); diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp index 31300468990..4b1cdcba27b 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -366,9 +366,13 @@ void MozJSImplScope::_gcCallback(JSContext* rt, LOGV2_INFO(22787, "MozJS GC heap stats", "phase"_attr = (status == JSGC_BEGIN ? "prologue" : "epilogue"), - "reason"_attr = reason, + "reason"_attr = ExplainGCReason(reason), "total"_attr = mongo::sm::get_total_bytes(), - "limit"_attr = mongo::sm::get_max_bytes()); + "limit"_attr = mongo::sm::get_max_bytes(), + "gc total"_attr = js::GetGCHeapUsage(rt), + "gc bytes"_attr = JS_GetGCParameter(rt, JSGC_BYTES), + "gc total chunks"_attr = JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS), + "gc unused chunks"_attr = JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)); } #if __has_feature(address_sanitizer) @@ -440,7 +444,13 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine, "JavaScript may not be able to initialize with a heap limit less than 10MB."); } size_t mallocMemoryLimit = 1024ul * 1024 * jsHeapLimit; - mongo::sm::reset(mallocMemoryLimit); + + /* + * Flag to disable newer memory tracking logic that accounts for mmap-ed memory + */ + const auto useLegacyMemoryTracking = engine->getJSUseLegacyMemoryTracking(); + + mongo::sm::reset(mallocMemoryLimit, !useLegacyMemoryTracking); { stdx::unique_lock lk(gRuntimeCreationMutex); diff --git a/src/mongo/scripting/mozjs/jscustomallocator.cpp b/src/mongo/scripting/mozjs/jscustomallocator.cpp index ec853d4f521..31ef54b8c91 100644 --- a/src/mongo/scripting/mozjs/jscustomallocator.cpp +++ b/src/mongo/scripting/mozjs/jscustomallocator.cpp @@ -28,6 +28,7 @@ */ #include "mongo/config.h" // IWYU pragma: keep +#include "mongo/logv2/log.h" #include "mongo/scripting/mozjs/implscope.h" #include @@ -49,6 +50,8 @@ #error "Unsupported platform" #endif +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery + /** * This shim interface (which controls dynamic allocation within SpiderMonkey), * consciously uses std::malloc and friends over mongoMalloc. It does this @@ -71,24 +74,57 @@ namespace { * maximum number of bytes we will consider handing out. They are set by * MozJSImplScope on start up. */ -thread_local size_t total_bytes = 0; +thread_local size_t malloc_bytes = 0; thread_local size_t max_bytes = 0; +// Allow disabling mmap tracking as a fallback in case counted memory goes too high +thread_local bool track_mmap_bytes = true; } // namespace size_t get_total_bytes() { - return total_bytes; + return get_malloc_bytes() + get_mmap_bytes(); } -void reset(size_t bytes) { - total_bytes = 0; +size_t get_malloc_bytes() { + return malloc_bytes; +} + +size_t get_mmap_bytes() { + return track_mmap_bytes ? js::gc::GetProfilerMemoryCounts().bytes : 0; +} + +void reset(size_t bytes, bool track_mmap) { + malloc_bytes = 0; max_bytes = bytes; + track_mmap_bytes = track_mmap; } size_t get_max_bytes() { return max_bytes; } +void signal_oom() { + auto scope = mongo::mozjs::MozJSImplScope::getThreadScope(); + if (scope) { + scope->setOOM(); + } +} + +void check_oom_on_mmap_allocation(size_t bytes) { + // called after an mmap allocation to check whether an oom signal is required + // if track_mmap_bytes is disabled we fall back to legacy logic and completely bypass this path + size_t mb = get_max_bytes(); + size_t tb = get_total_bytes(); + if (track_mmap_bytes && mb > 0 && get_total_bytes() + bytes > mb) { + LOGV2(10920001, + "Out of memory on MozJS mmap allocation", + "bytes"_attr = bytes, + "totalBytes"_attr = tb, + "maxBytes"_attr = mb); + signal_oom(); + } +} + size_t get_current(void* ptr); /** @@ -99,7 +135,8 @@ size_t get_current(void* ptr); template void* wrap_alloc(T&& func, void* ptr, size_t bytes) { size_t mb = get_max_bytes(); - size_t tb = get_total_bytes(); + size_t mlb = get_malloc_bytes(); + size_t mmb = get_mmap_bytes(); // During a GC cycle, GC::purgeRuntime() is called, which tries to free unused items in the // SharedImmutableStringsCache while holding its corresponding mutex. Our js_free implementation @@ -109,13 +146,22 @@ void* wrap_alloc(T&& func, void* ptr, size_t bytes) { // for the SharedImmutableStringsCache (order 600). This triggered a failure of a MOZ_ASSERT // which enforces correct lock ordering in the JS engine. For this reason, we avoid checking // for an OOM here if we are requesting zero bytes (i.e freeing memory). + if (mb && bytes && (mlb + mmb + bytes > mb)) { + bool oomUnsafe = js::AutoEnterOOMUnsafeRegion::isInOOMUnsafeRegion(); + LOGV2(10920000, + "Out of memory on MozJS malloc allocation", + "bytes"_attr = bytes, + "totalBytes"_attr = mlb + mmb, + "maxBytes"_attr = mb, + "isInOOMUnsafeRegion"_attr = oomUnsafe); + signal_oom(); - if (mb && bytes && (tb + bytes > mb)) { - auto scope = mongo::mozjs::MozJSImplScope::getThreadScope(); - if (scope) { - scope->setOOM(); + // In some contexts MozJS has no safe recovery from OOM and crashes the process to avoid + // unsafe behavior. In that case allow the allocation to proceed and go over the allowed + // memory limit. Otherwise fail immediately. + if (!oomUnsafe) { + return nullptr; } - return nullptr; } void* p = func(ptr, bytes); @@ -147,7 +193,7 @@ void* wrap_alloc(T&& func, void* ptr, size_t bytes) { return nullptr; } - total_bytes += mongo::sm::get_current(p); + malloc_bytes += mongo::sm::get_current(p); return p; } @@ -171,9 +217,12 @@ size_t get_current(void* ptr) { } // namespace mongo JS_PUBLIC_DATA arena_id_t js::MallocArena; +JS_PUBLIC_DATA arena_id_t js::BackgroundMallocArena; JS_PUBLIC_DATA arena_id_t js::ArrayBufferContentsArena; JS_PUBLIC_DATA arena_id_t js::StringBufferArena; +thread_local size_t js::AutoEnterOOMUnsafeRegion::isInOomUnsafeRegion_ = 0; + void* mongo_arena_malloc(size_t bytes) { return std::malloc(bytes); } @@ -195,11 +244,11 @@ void* mongo_arena_realloc(void* p, size_t bytes) { void* ptr = std::realloc(p, bytes); if (!ptr) { - // on failure the old ptr isn't freed, no need to adjust total_bytes + // on failure the old ptr isn't freed, no need to adjust malloc_bytes return nullptr; } - mongo::sm::total_bytes -= std::min(mongo::sm::total_bytes, current); + mongo::sm::malloc_bytes -= std::min(mongo::sm::malloc_bytes, current); return ptr; } @@ -208,7 +257,7 @@ void* mongo_free(void* ptr) { // buffer, so this may result in undercounting size_t current = mongo::sm::get_current(ptr); - mongo::sm::total_bytes -= std::min(mongo::sm::total_bytes, current); + mongo::sm::malloc_bytes -= std::min(mongo::sm::malloc_bytes, current); std::free(ptr); return nullptr; @@ -272,8 +321,9 @@ void js_free(void* p) { void js::InitMallocAllocator() { MallocArena = 0; - ArrayBufferContentsArena = 1; - StringBufferArena = 2; + BackgroundMallocArena = 1; + ArrayBufferContentsArena = 2; + StringBufferArena = 3; } void js::ShutDownMallocAllocator() {} diff --git a/src/mongo/scripting/mozjs/jscustomallocator_test.cpp b/src/mongo/scripting/mozjs/jscustomallocator_test.cpp index de4a498ff84..f1e351246db 100644 --- a/src/mongo/scripting/mozjs/jscustomallocator_test.cpp +++ b/src/mongo/scripting/mozjs/jscustomallocator_test.cpp @@ -47,7 +47,7 @@ namespace mozjs { class JSCustomAllocatorTest : public unittest::Test { protected: void setUp() override { - mongo::sm::reset(0); + mongo::sm::reset(0, false); // Note: get_total_bytes() is an estimate and won't exactly count allocated bytes, // test should only compare to 0 @@ -55,13 +55,13 @@ protected: } void tearDown() override { - mongo::sm::reset(0); + mongo::sm::reset(0, false); } }; TEST_F(JSCustomAllocatorTest, MallocUpToLimit) { - mongo::sm::reset(100); + mongo::sm::reset(100, false); ASSERT_EQUALS(mongo::sm::get_total_bytes(), 0); void* ptr1 = js_malloc(20); @@ -85,7 +85,7 @@ TEST_F(JSCustomAllocatorTest, MallocUpToLimit) { } TEST_F(JSCustomAllocatorTest, ReallocUpToLimit) { - mongo::sm::reset(100); + mongo::sm::reset(100, false); ASSERT_EQUALS(mongo::sm::get_total_bytes(), 0); void* ptr1 = js_malloc(20); @@ -104,7 +104,7 @@ TEST_F(JSCustomAllocatorTest, ReallocUpToLimit) { TEST_F(JSCustomAllocatorTest, CallocUpToLimit) { - mongo::sm::reset(100); + mongo::sm::reset(100, false); ASSERT_EQUALS(mongo::sm::get_total_bytes(), 0); void* ptr1 = js_calloc(10, 2); diff --git a/src/mongo/scripting/mozjs/module_loader.cpp b/src/mongo/scripting/mozjs/module_loader.cpp index 4436a5348aa..3632eaa3225 100644 --- a/src/mongo/scripting/mozjs/module_loader.cpp +++ b/src/mongo/scripting/mozjs/module_loader.cpp @@ -98,14 +98,21 @@ JSObject* ModuleLoader::loadRootModule(JSContext* cx, const std::string& path, boost::optional source) { JS::RootedString baseUrl(cx, JS_NewStringCopyN(cx, _baseUrl.c_str(), _baseUrl.size())); + if (!baseUrl) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create baseUrl"); + } JS::RootedObject info(cx, createScriptPrivateInfo(cx, baseUrl, source)); if (!info) { - return nullptr; + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create info"); } JS::RootedValue referencingPrivate(cx, JS::ObjectValue(*info)); JS::RootedString specifier(cx, JS_NewStringCopyN(cx, path.c_str(), path.size())); - JS::RootedObject moduleRequest(cx, JS::CreateModuleRequest(cx, specifier)); + if (!specifier) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create specifier"); + } + JS::RootedObject moduleRequest( + cx, JS::CreateModuleRequest(cx, specifier, JS::ModuleType::JavaScript)); if (!moduleRequest) { return nullptr; } @@ -148,7 +155,13 @@ bool ModuleLoader::importModuleDynamically(JSContext* cx, JS::HandleObject moduleRequest, JS::HandleObject promise) { JS::RootedString baseUrl(cx, JS_NewStringCopyN(cx, _baseUrl.c_str(), _baseUrl.size())); + if (!baseUrl) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create baseUrl"); + } JS::RootedObject info(cx, createScriptPrivateInfo(cx, baseUrl)); + if (!info) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create info"); + } JS::RootedValue newReferencingPrivate(cx, JS::ObjectValue(*info)); // The dynamic `import` method returns a Promise, and thus allows us to perform module loading @@ -160,15 +173,18 @@ bool ModuleLoader::importModuleDynamically(JSContext* cx, JS::Rooted path(cx, resolveAndNormalize(cx, moduleRequest, newReferencingPrivate)); if (!path) { + LOGV2_ERROR(716284, "Failed to resolve and normalize path"); return false; } JS::RootedObject module(cx, loadAndParse(cx, path, newReferencingPrivate)); if (!module) { + LOGV2_ERROR(716285, "Failed to load and parse module"); return false; } if (!JS::ModuleLink(cx, module)) { + LOGV2_ERROR(716286, "Failed to link module"); return false; } @@ -177,6 +193,10 @@ bool ModuleLoader::importModuleDynamically(JSContext* cx, JSObject* evaluationObject = ok ? &rval.toObject() : nullptr; JS::RootedObject evaluationPromise(cx, evaluationObject); + if (!evaluationPromise) { + LOGV2_ERROR(716287, "Failed to create evaluation promise"); + return false; + } return JS::FinishDynamicModuleImport( cx, evaluationPromise, newReferencingPrivate, moduleRequest, promise); } @@ -239,8 +259,18 @@ JSString* ModuleLoader::resolveAndNormalize(JSContext* cx, return nullptr; } - boost::filesystem::path specifierPath(JS_EncodeStringToUTF8(cx, specifierString).get()); - auto refAbsPath = boost::filesystem::path(JS_EncodeStringToUTF8(cx, refPath).get()); + JS::UniqueChars specifierChars = JS_EncodeStringToUTF8(cx, specifierString); + uassert(ErrorCodes::JSInterpreterFailure, + "Failed to UTF-8 encode module specifier", + specifierChars); + boost::filesystem::path specifierPath(specifierChars.get()); + + JS::UniqueChars refPathChars = JS_EncodeStringToUTF8(cx, refPath); + uassert(ErrorCodes::JSInterpreterFailure, + "Failed to UTF-8 encode referencing module path", + refPathChars); + boost::filesystem::path refAbsPath(refPathChars.get()); + if (is_directory(specifierPath)) { JS_ReportErrorUTF8(cx, "Directory import '%s' is not supported, imported from %s", @@ -513,10 +543,19 @@ JSObject* ModuleLoader::createScriptPrivateInfo(JSContext* cx, JS::LossyUTF8CharsToNewTwoByteCharsZ( cx, JS::UTF8Chars(source->data(), len), &len, js::MallocArena) .get()); + if (!ucbuf) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create ucbuf"); + } JS::RootedString sourceValue(cx, JS_NewUCStringCopyN(cx, ucbuf.get(), len)); + + if (!sourceValue) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create sourceValue"); + } + + if (!JS_DefineProperty(cx, info, "source", sourceValue, JSPROP_ENUMERATE)) { - return nullptr; + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create source property"); } } @@ -575,7 +614,11 @@ std::string ModuleLoader::resolveBaseUrl(JSContext* cx, const std::string& loadP } JS::RootedString baseUrlString(cx, baseUrlValue.toString()); - auto baseUrl = std::string{JS_EncodeStringToUTF8(cx, baseUrlString).get()}; + JS::UniqueChars baseUrlChars = JS_EncodeStringToUTF8(cx, baseUrlString); + uassert(ErrorCodes::JSInterpreterFailure, + "Failed to UTF-8 encode baseUrl from jsconfig.json", + baseUrlChars); // returns nullptr on OOM/encoding errors + std::string baseUrl{baseUrlChars.get()}; boost::system::error_code ec; auto resolvedPath = diff --git a/src/mongo/scripting/mozjs/wraptype.h b/src/mongo/scripting/mozjs/wraptype.h index 22569469a2b..9c75f54cc73 100644 --- a/src/mongo/scripting/mozjs/wraptype.h +++ b/src/mongo/scripting/mozjs/wraptype.h @@ -279,9 +279,12 @@ public: JS::RootedObject proto(_context); JS::RealmOptions options; - _proto.init(_context, - _assertPtr(JS_NewGlobalObject( - _context, &_jsclass, nullptr, JS::DontFireOnNewGlobalHook, options))); + JSObject* global = JS_NewGlobalObject( + _context, &_jsclass, nullptr, JS::DontFireOnNewGlobalHook, options); + if (!global) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to create global object"); + } + _proto.init(_context, global); JSAutoRealm ac(_context, _proto); _installFunctions(_proto, T::freeFunctions); @@ -579,6 +582,15 @@ private: } JSObject* _assertPtr(JSObject* ptr) { + + // If we don’t even have a realm/global yet, calling throwCurrentJSException() + // would recurse into JSContext::getPendingException(), which expects a + // compartment and will crash. Instead, translate to a plain uassert with context. + if (!JS::CurrentGlobalOrNull(_context)) { + uasserted(ErrorCodes::JSInterpreterFailure, + "Failed to create JS object: no global realm initialized"); + } + if (!ptr) throwCurrentJSException( _context, ErrorCodes::JSInterpreterFailure, "Failed to JS_NewX"); diff --git a/src/third_party/mozjs/BUILD.bazel b/src/third_party/mozjs/BUILD.bazel index 363aa0ce674..b9a2b49d6aa 100644 --- a/src/third_party/mozjs/BUILD.bazel +++ b/src/third_party/mozjs/BUILD.bazel @@ -59,6 +59,7 @@ mongo_cc_library( srcs = [ "extract/js/src/builtin/RegExp.cpp", "extract/js/src/frontend/Parser.cpp", + "extract/js/src/gc/Memory.cpp", "extract/js/src/gc/StoreBuffer.cpp", "extract/js/src/irregexp/RegExpNativeMacroAssembler.cpp", "extract/js/src/irregexp/imported/regexp-ast.cc", @@ -70,19 +71,21 @@ mongo_cc_library( "extract/js/src/vm/Interpreter.cpp", "extract/js/src/vm/ProfilingStack.cpp", "extract/js/src/wasm/WasmCode-platform.cpp", - "extract/mfbt/lz4/lz4.c", - "extract/mfbt/lz4/lz4frame.c", - "extract/mfbt/lz4/lz4hc.c", - "extract/mfbt/lz4/xxhash.c", + "extract/js/src/xsum/xsum.cpp", "extract/mozglue/misc/AutoProfilerLabel.cpp", "extract/mozglue/misc/AwakeTimeStamp.cpp", "extract/mozglue/misc/Debug.cpp", "extract/mozglue/misc/MmapFaultHandler.cpp", + "extract/mozglue/misc/Now.cpp", "extract/mozglue/misc/Printf.cpp", "extract/mozglue/misc/SIMD.cpp", "extract/mozglue/misc/StackWalk.cpp", "extract/mozglue/misc/TimeStamp.cpp", "extract/mozglue/misc/Uptime.cpp", + "extract/mozglue/static/lz4/lz4.c", + "extract/mozglue/static/lz4/lz4frame.c", + "extract/mozglue/static/lz4/lz4hc.c", + "extract/mozglue/static/lz4/xxhash.c", "mongo_sources/freeOpToJSContext.cpp", "mongo_sources/mongoErrorReportToString.cpp", ] + select({ @@ -161,6 +164,7 @@ mongo_cc_library( "extract/mfbt/**/*.h", "extract/modules/fdlibm/**/*.h", "mongo_sources/**/*.h", + "extract/mozglue/static/lz4/*.h", ]) + PLATFORM_SRCS, hdrs = glob(["include/**/*.h"]), copts = PLATFORM_COPTS + [ @@ -241,11 +245,15 @@ mongo_cc_library( # C5101: use of preprocessor directive in function-like macro # argument list is undefined behavior "/wd5101", + + # Enable extern constexpr variables + "/Zc:externConstexpr", ], "//conditions:default": [ "-Wno-sign-compare", # Disable warnings for third party libraries as no action will be taken to fix them # and they just clutter the output logs + "-Wno-unused-value", "-Wno-unused-variable", "-Wno-implicit-fallthrough", # Bazel doesn't differentiate between compile flags for C and C++. @@ -310,6 +318,7 @@ mongo_cc_library( "@platforms//os:macos": ["-Wl,-undefined,dynamic_lookup"], "@platforms//os:windows": [ "ntdll.lib", + "mincore.lib", ], "//conditions:default": [""], }), @@ -345,6 +354,7 @@ mongo_cc_library( "**/*.tbl", ]), deps = [ + "//src/third_party/fmt", "//src/third_party/icu4c-57.1/source:icu_i18n", "//src/third_party/zlib", ], diff --git a/src/third_party/mozjs/extract.sh b/src/third_party/mozjs/extract.sh index 46ada4e010e..110037387fe 100755 --- a/src/third_party/mozjs/extract.sh +++ b/src/third_party/mozjs/extract.sh @@ -27,7 +27,6 @@ CFLAGS="$CFLAGS -D__STDC_FORMAT_MACROS" \ --enable-optimize \ --disable-js-shell \ --disable-tests \ - --disable-new-pass-manager \ --disable-wasm-moz-intgemm # we have to run make to generate a byte code version of the self hosted js and @@ -112,7 +111,7 @@ done # this is all of the EXPORTS.js files from the moz.build mkdir -p include/js -for i in 'AllocationLogging.h' 'AllocationRecording.h' 'AllocPolicy.h' 'Array.h' 'ArrayBuffer.h' 'ArrayBufferMaybeShared.h' 'BigInt.h' 'BuildId.h' 'CallAndConstruct.h' 'CallArgs.h' 'CallNonGenericMethod.h' 'CharacterEncoding.h' 'Class.h' 'ColumnNumber.h' 'ComparisonOperators.h' 'CompilationAndEvaluation.h' 'CompileOptions.h' 'Context.h' 'ContextOptions.h' 'Conversions.h' 'Date.h' 'Debug.h' 'Equality.h' 'ErrorInterceptor.h' 'ErrorReport.h' 'Exception.h' 'ForOfIterator.h' 'GCAnnotations.h' 'GCAPI.h' 'GCHashTable.h' 'GCPolicyAPI.h' 'GCTypeMacros.h' 'GCVariant.h' 'GCVector.h' 'GlobalObject.h' 'HashTable.h' 'HeapAPI.h' 'HelperThreadAPI.h' 'Id.h' 'Initialization.h' 'Interrupt.h' 'Iterator.h' 'JitCodeAPI.h' 'JSON.h' 'LocaleSensitive.h' 'MapAndSet.h' 'MemoryCallbacks.h' 'MemoryFunctions.h' 'MemoryMetrics.h' 'Modules.h' 'Object.h' 'Prefs.h' 'Principals.h' 'Printer.h' 'Printf.h' 'ProfilingCategory.h' 'ProfilingFrameIterator.h' 'ProfilingStack.h' 'Promise.h' 'PropertyAndElement.h' 'PropertyDescriptor.h' 'PropertySpec.h' 'ProtoKey.h' 'Proxy.h' 'Realm.h' 'RealmIterators.h' 'RealmOptions.h' 'RefCounted.h' 'RegExp.h' 'RegExpFlags.h' 'Result.h' 'RootingAPI.h' 'SavedFrameAPI.h' 'ScalarType.h' 'ScriptPrivate.h' 'ShadowRealmCallbacks.h' 'SharedArrayBuffer.h' 'SliceBudget.h' 'SourceText.h' 'StableStringChars.h' 'Stack.h' 'StreamConsumer.h' 'String.h' 'StructuredClone.h' 'SweepingAPI.h' 'Symbol.h' 'TelemetryTimers.h' 'TraceKind.h' 'TracingAPI.h' 'Transcoding.h' 'TypeDecls.h' 'UbiNode.h' 'UbiNodeBreadthFirst.h' 'UbiNodeCensus.h' 'UbiNodeDominatorTree.h' 'UbiNodePostOrder.h' 'UbiNodeShortestPaths.h' 'UbiNodeUtils.h' 'UniquePtr.h' 'Utility.h' 'Value.h' 'ValueArray.h' 'Vector.h' 'WaitCallbacks.h' 'Warnings.h' 'WasmFeatures.h' 'WasmModule.h' 'WeakMap.h' 'WeakMapPtr.h' 'Wrapper.h' 'WrapperCallbacks.h' 'Zone.h' ; do +for i in 'AllocationLogging.h' 'AllocationRecording.h' 'AllocPolicy.h' 'Array.h' 'ArrayBuffer.h' 'ArrayBufferMaybeShared.h' 'BigInt.h' 'BuildId.h' 'CallAndConstruct.h' 'CallArgs.h' 'CallNonGenericMethod.h' 'CharacterEncoding.h' 'Class.h' 'ColumnNumber.h' 'ComparisonOperators.h' 'CompilationAndEvaluation.h' 'CompileOptions.h' 'Context.h' 'ContextOptions.h' 'Conversions.h' 'Date.h' 'Debug.h' 'EnvironmentChain.h' 'Equality.h' 'ErrorInterceptor.h' 'ErrorReport.h' 'Exception.h' 'ForOfIterator.h' 'GCAnnotations.h' 'GCAPI.h' 'GCHashTable.h' 'GCPolicyAPI.h' 'GCTypeMacros.h' 'GCVariant.h' 'GCVector.h' 'GlobalObject.h' 'HashTable.h' 'HeapAPI.h' 'HelperThreadAPI.h' 'Id.h' 'Initialization.h' 'Interrupt.h' 'Iterator.h' 'JSON.h' 'LocaleSensitive.h' 'MapAndSet.h' 'MemoryCallbacks.h' 'MemoryFunctions.h' 'MemoryMetrics.h' 'Modules.h' 'NativeStackLimits.h' 'Object.h' 'ObjectWithStashedPointer.h' 'Prefs.h' 'Principals.h' 'Printer.h' 'Printf.h' 'ProfilingCategory.h' 'ProfilingFrameIterator.h' 'ProfilingStack.h' 'Promise.h' 'PropertyAndElement.h' 'PropertyDescriptor.h' 'PropertySpec.h' 'ProtoKey.h' 'Proxy.h' 'Realm.h' 'RealmIterators.h' 'RealmOptions.h' 'RefCounted.h' 'RegExp.h' 'RegExpFlags.h' 'Result.h' 'RootingAPI.h' 'SavedFrameAPI.h' 'ScalarType.h' 'ScriptPrivate.h' 'ShadowRealmCallbacks.h' 'SharedArrayBuffer.h' 'SliceBudget.h' 'SourceText.h' 'StableStringChars.h' 'Stack.h' 'StreamConsumer.h' 'String.h' 'StructuredClone.h' 'SweepingAPI.h' 'Symbol.h' 'TelemetryTimers.h' 'TraceKind.h' 'TracingAPI.h' 'Transcoding.h' 'TypeDecls.h' 'UbiNode.h' 'UbiNodeBreadthFirst.h' 'UbiNodeCensus.h' 'UbiNodeDominatorTree.h' 'UbiNodePostOrder.h' 'UbiNodeShortestPaths.h' 'UbiNodeUtils.h' 'UniquePtr.h' 'Utility.h' 'Value.h' 'ValueArray.h' 'Vector.h' 'WaitCallbacks.h' 'Warnings.h' 'WasmFeatures.h' 'WasmModule.h' 'WeakMap.h' 'WeakMapPtr.h' 'Wrapper.h' 'WrapperCallbacks.h' 'Zone.h' ; do cp extract/js/public/$i include/js/ done @@ -121,11 +120,12 @@ cp extract/js/src/_build/js/public/PrefsGenerated.h include/js/ for i in 'ProfilingCategoryList.h' ; do cp extract/js/src/_build/mozglue/baseprofiler/public/$i include/js/ + cp extract/js/src/_build/dist/include/$i include done # this is all of the EXPORTS.js.experimental files from the moz.build mkdir -p include/js/experimental -for i in 'CodeCoverage.h' 'CompileScript.h' 'CTypes.h' 'Intl.h' 'JitInfo.h' 'JSStencil.h' 'PCCountProfiling.h' 'SourceHook.h' 'TypedData.h' ; do +for i in 'BindingAllocs.h' 'CodeCoverage.h' 'CompileScript.h' 'CTypes.h' 'Intl.h' 'JitInfo.h' 'JSStencil.h' 'LoggingInterface.h' 'PCCountProfiling.h' 'SourceHook.h' 'TypedData.h' ; do cp extract/js/public/experimental/$i include/js/experimental/ done @@ -143,7 +143,7 @@ done # this is all of the EXPORTS.mozilla files from the moz.build's (i.e mfbt) mkdir -p include/mozilla -for i in 'Algorithm.h' 'Alignment.h' 'AllocPolicy.h' 'AlreadyAddRefed.h' 'Array.h' 'ArrayUtils.h' 'Assertions.h' 'AtomicBitfields.h' 'Atomics.h' 'Attributes.h' 'BinarySearch.h' 'BitSet.h' 'BloomFilter.h' 'Buffer.h' 'BufferList.h' 'Casting.h' 'ChaosMode.h' 'Char16.h' 'CheckedInt.h' 'CompactPair.h' 'Compiler.h' 'Compression.h' 'DbgMacro.h' 'DebugOnly.h' 'DefineEnum.h' 'DoublyLinkedList.h' 'EndianUtils.h' 'EnumeratedArray.h' 'EnumeratedRange.h' 'EnumSet.h' 'EnumTypeTraits.h' 'fallible.h' 'FastBernoulliTrial.h' 'FloatingPoint.h' 'FStream.h' 'FunctionRef.h' 'FunctionTypeTraits.h' 'Fuzzing.h' 'HashFunctions.h' 'HashTable.h' 'HelperMacros.h' 'InitializedOnce.h' 'IntegerRange.h' 'IntegerTypeTraits.h' 'JSONWriter.h' 'JsRust.h' 'Latin1.h' 'Likely.h' 'LinkedList.h' 'MacroArgs.h' 'MacroForEach.h' 'MathAlgorithms.h' 'Maybe.h' 'MaybeOneOf.h' 'MaybeStorageBase.h' 'MemoryChecking.h' 'MemoryReporting.h' 'MoveOnlyFunction.h' 'MruCache.h' 'NonDereferenceable.h' 'NotNull.h' 'Opaque.h' 'OperatorNewExtensions.h' 'PairHash.h' 'Path.h' 'PodOperations.h' 'Poison.h' 'RandomNum.h' 'Range.h' 'RangedArray.h' 'RangedPtr.h' 'ReentrancyGuard.h' 'RefCounted.h' 'RefCountType.h' 'RefPtr.h' 'Result.h' 'ResultExtensions.h' 'ResultVariant.h' 'ReverseIterator.h' 'RollingMean.h' 'Saturate.h' 'ScopeExit.h' 'SegmentedVector.h' 'SHA1.h' 'SharedLibrary.h' 'SmallPointerArray.h' 'Span.h' 'SplayTree.h' 'SPSCQueue.h' 'StaticAnalysisFunctions.h' 'TaggedAnonymousMemory.h' 'Tainting.h' 'TemplateLib.h' 'TextUtils.h' 'ThreadLocal.h' 'ThreadSafety.h' 'ThreadSafeWeakPtr.h' 'ToString.h' 'Try.h' 'TypedEnumBits.h' 'Types.h' 'UniquePtr.h' 'UniquePtrExtensions.h' 'Unused.h' 'Utf8.h' 'Variant.h' 'Vector.h' 'WeakPtr.h' 'WindowsVersion.h' 'WrappingOperations.h' 'XorShift128PlusRNG.h' ; do +for i in 'Algorithm.h' 'Alignment.h' 'AllocPolicy.h' 'AlreadyAddRefed.h' 'Array.h' 'ArrayUtils.h' 'Assertions.h' 'AtomicBitfields.h' 'Atomics.h' 'Attributes.h' 'BinarySearch.h' 'BitSet.h' 'BloomFilter.h' 'Buffer.h' 'BufferList.h' 'Casting.h' 'ChaosMode.h' 'Char16.h' 'CheckedInt.h' 'CompactPair.h' 'Compiler.h' 'DbgMacro.h' 'DebugOnly.h' 'DefineEnum.h' 'DoublyLinkedList.h' 'EndianUtils.h' 'EnumeratedArray.h' 'EnumeratedRange.h' 'EnumSet.h' 'EnumTypeTraits.h' 'fallible.h' 'FastBernoulliTrial.h' 'FloatingPoint.h' 'FStream.h' 'FunctionRef.h' 'FunctionTypeTraits.h' 'Fuzzing.h' 'HashFunctions.h' 'HashTable.h' 'HelperMacros.h' 'InitializedOnce.h' 'IntegerRange.h' 'IntegerTypeTraits.h' 'JSONWriter.h' 'JsRust.h' 'Latin1.h' 'Likely.h' 'LinkedList.h' 'Literals.h' 'MacroArgs.h' 'MacroForEach.h' 'MathAlgorithms.h' 'Maybe.h' 'MaybeOneOf.h' 'MaybeStorageBase.h' 'MemoryChecking.h' 'MemoryReporting.h' 'MoveOnlyFunction.h' 'MPSCQueue.h' 'MruCache.h' 'NeverDestroyed.h' 'NonDereferenceable.h' 'NotNull.h' 'Opaque.h' 'OperatorNewExtensions.h' 'PairHash.h' 'Path.h' 'PodOperations.h' 'Poison.h' 'RandomNum.h' 'Range.h' 'RangedArray.h' 'RangedPtr.h' 'ReentrancyGuard.h' 'RefCounted.h' 'RefCountType.h' 'RefPtr.h' 'Result.h' 'ResultExtensions.h' 'ResultVariant.h' 'ReverseIterator.h' 'RollingMean.h' 'Saturate.h' 'ScopeExit.h' 'SegmentedVector.h' 'SHA1.h' 'SharedLibrary.h' 'SmallPointerArray.h' 'Span.h' 'SplayTree.h' 'SPSCQueue.h' 'StaticAnalysisFunctions.h' 'StringBuffer.h' 'TaggedAnonymousMemory.h' 'Tainting.h' 'TemplateLib.h' 'TextUtils.h' 'ThreadLocal.h' 'ThreadSafety.h' 'ThreadSafeWeakPtr.h' 'ToString.h' 'Try.h' 'TypedEnumBits.h' 'Types.h' 'UniquePtr.h' 'UniquePtrExtensions.h' 'Unused.h' 'Utf8.h' 'Variant.h' 'Vector.h' 'WeakPtr.h' 'WrappingOperations.h' 'XorShift128PlusRNG.h' 'WindowsVersion.h' ; do cp extract/mfbt/$i include/mozilla/ done @@ -158,6 +158,15 @@ for i in 'AutoProfilerLabel.h' 'PlatformConditionVariable.h' 'PlatformMutex.h' ' cp extract/js/src/_build/dist/include/mozilla/$i include/mozilla done +#exports in baseprofiler +for i in 'BaseProfilingCategory.h' ; do + cp extract/js/src/_build/dist/include/$i include +done +# exports.mozilla from baseprofiler +for i in 'BaseAndGeckoProfilerDetail.h' 'BaseProfileJSONWriter.h' 'BaseProfilerCounts.h' 'BaseProfilerDetail.h' 'BaseProfilerLabels.h' 'BaseProfilerMarkers.h' 'BaseProfilerMarkersDetail.h' 'BaseProfilerMarkersPrerequisites.h' 'BaseProfilerMarkerTypes.h' 'BaseProfilerRAIIMacro.h' 'BaseProfilerState.h' 'BaseProfilerUtils.h' 'FailureLatch.h' 'Flow.h' 'leb128iterator.h' 'ModuloBuffer.h' 'PowerOfTwo.h' 'ProfileBufferChunk.h' 'ProfileBufferChunkManager.h' 'ProfileBufferChunkManagerSingle.h' 'ProfileBufferChunkManagerWithLocalLimit.h' 'ProfileBufferControlledChunkManager.h' 'ProfileBufferEntryKinds.h' 'ProfileBufferEntrySerialization.h' 'ProfileBufferIndex.h' 'ProfileChunkedBuffer.h' 'ProfileChunkedBufferDetail.h' 'ProfilerBufferSize.h' 'ProgressLogger.h' 'ProportionValue.h'; do + cp extract/js/src/_build/dist/include/mozilla/$i include/mozilla +done + mkdir -p include/mozilla/glue cp extract/js/src/_build/dist/include/mozilla/glue/Debug.h include/mozilla/glue @@ -171,6 +180,14 @@ mkdir -p extract/mozglue/misc cp mozilla-release/mozglue/misc/*.cpp extract/mozglue/misc cp mozilla-release/mozglue/misc/StackWalk_windows.h include/mozilla/ +cp mozilla-release/mozglue/static/*.h include/mozilla +mkdir -p extract/mozglue/static +cp mozilla-release/mozglue/static/*.cpp extract/mozglue/static + +mkdir -p extract/mozglue/static/lz4 +cp mozilla-release/mozglue/static/lz4/*.h extract/mozglue/static/lz4 +cp mozilla-release/mozglue/static/lz4/*.c extract/mozglue/static/lz4 + mkdir -p include/vtune touch include/vtune/VTuneWrapper.h @@ -226,7 +243,6 @@ extract/js/src/_build/mozglue/misc/backend.mk extract/js/src/_build/mozglue/misc/.deps/ extract/js/src/_build/mozglue/misc/Makefile extract/js/src/_build/mozinfo.json -extract/js/src/_build/old-configure.vars extract/js/src/_build/testing/ extract/js/src/_build/_tests/mozbase/ extract/js/src/_build/third_party/ @@ -235,8 +251,6 @@ __XARGS_RM__ xargs rm -r<<__XARGS_RM__ extract/js/src/build extract/js/src/devtools/vprof/manifest.mk -extract/js/src/old-configure -extract/js/src/old-configure.in extract/js/src/wasm/moz.build extract/js/src/js-confdefs.h.in extract/js/src/js-config.h.in diff --git a/src/third_party/mozjs/extract/js/public/AllocPolicy.h b/src/third_party/mozjs/extract/js/public/AllocPolicy.h index 72c449293c5..880527e8cb0 100644 --- a/src/third_party/mozjs/extract/js/public/AllocPolicy.h +++ b/src/third_party/mozjs/extract/js/public/AllocPolicy.h @@ -25,8 +25,7 @@ class FrontendContext; enum class AllocFunction { Malloc, Calloc, Realloc }; -/* Base class allocation policies providing allocation methods. */ -class AllocPolicyBase { +class ArenaAllocPolicyBase { public: template T* maybe_pod_arena_malloc(arena_id_t arenaId, size_t numElems) { @@ -54,7 +53,11 @@ class AllocPolicyBase { size_t newSize) { return maybe_pod_arena_realloc(arenaId, p, oldSize, newSize); } +}; +/* Base class allocation policies providing allocation methods. */ +class AllocPolicyBase : public ArenaAllocPolicyBase { + public: template T* maybe_pod_malloc(size_t numElems) { return maybe_pod_arena_malloc(js::MallocArena, numElems); @@ -86,6 +89,44 @@ class AllocPolicyBase { } }; +/* + * Base class allocation policies providing allocation methods for allocations + * off the main thread. + */ +class BackgroundAllocPolicyBase : ArenaAllocPolicyBase { + public: + template + T* maybe_pod_malloc(size_t numElems) { + return maybe_pod_arena_malloc(js::BackgroundMallocArena, numElems); + } + template + T* maybe_pod_calloc(size_t numElems) { + return maybe_pod_arena_calloc(js::BackgroundMallocArena, numElems); + } + template + T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) { + return maybe_pod_arena_realloc(js::BackgroundMallocArena, p, oldSize, + newSize); + } + template + T* pod_malloc(size_t numElems) { + return pod_arena_malloc(js::BackgroundMallocArena, numElems); + } + template + T* pod_calloc(size_t numElems) { + return pod_arena_calloc(js::BackgroundMallocArena, numElems); + } + template + T* pod_realloc(T* p, size_t oldSize, size_t newSize) { + return pod_arena_realloc(js::BackgroundMallocArena, p, oldSize, newSize); + } + + template + void free_(T* p, size_t numElems = 0) { + js_free(p); + } +}; + /* Policy for using system memory functions and doing no error reporting. */ class SystemAllocPolicy : public AllocPolicyBase { public: @@ -93,6 +134,12 @@ class SystemAllocPolicy : public AllocPolicyBase { bool checkSimulatedOOM() const { return !js::oom::ShouldFailWithOOM(); } }; +class BackgroundSystemAllocPolicy : public BackgroundAllocPolicyBase { + public: + void reportAllocOverflow() const {} + bool checkSimulatedOOM() const { return !js::oom::ShouldFailWithOOM(); } +}; + MOZ_COLD JS_PUBLIC_API void ReportOutOfMemory(JSContext* cx); MOZ_COLD JS_PUBLIC_API void ReportOutOfMemory(FrontendContext* fc); diff --git a/src/third_party/mozjs/extract/js/public/CharacterEncoding.h b/src/third_party/mozjs/extract/js/public/CharacterEncoding.h index 9d1df4664b4..2f5c8ca0197 100644 --- a/src/third_party/mozjs/extract/js/public/CharacterEncoding.h +++ b/src/third_party/mozjs/extract/js/public/CharacterEncoding.h @@ -261,13 +261,6 @@ extern JS_PUBLIC_API TwoByteCharsZ UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars& utf8, size_t* outlen, arena_id_t destArenaId); -/* - * Like UTF8CharsToNewTwoByteCharsZ, but for ConstUTF8CharsZ. - */ -extern JS_PUBLIC_API TwoByteCharsZ -UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, - size_t* outlen, arena_id_t destArenaId); - /* * The same as UTF8CharsToNewTwoByteCharsZ(), except that any malformed UTF-8 * characters will be replaced by \uFFFD. No exception will be thrown for @@ -277,10 +270,6 @@ extern JS_PUBLIC_API TwoByteCharsZ LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars& utf8, size_t* outlen, arena_id_t destArenaId); -extern JS_PUBLIC_API TwoByteCharsZ -LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, - size_t* outlen, arena_id_t destArenaId); - /* * Returns the length of the char buffer required to encode |s| as UTF8. * Does not include the null-terminator. @@ -329,15 +318,6 @@ extern JS_PUBLIC_API Latin1CharsZ UTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars& utf8, size_t* outlen, arena_id_t destArenaId); -/* - * Return a null-terminated Latin-1 string copied from the input string, - * storing its length (excluding null terminator) in |*outlen|. Non-Latin-1 - * codepoints are replaced by '?'. Returns Latin1CharsZ() on failure. - */ -extern JS_PUBLIC_API Latin1CharsZ -LossyUTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars& utf8, - size_t* outlen, arena_id_t destArenaId); - /* * Returns true if all characters in the given null-terminated string are * ASCII, i.e. < 0x80, false otherwise. diff --git a/src/third_party/mozjs/extract/js/public/Class.h b/src/third_party/mozjs/extract/js/public/Class.h index 0c9833cbcfa..5875af2c07f 100644 --- a/src/third_party/mozjs/extract/js/public/Class.h +++ b/src/third_party/mozjs/extract/js/public/Class.h @@ -813,11 +813,6 @@ enum class ESClass { BigInt, Function, // Note: Only JSFunction objects. -#ifdef ENABLE_RECORD_TUPLE - Record, - Tuple, -#endif - /** None of the above. */ Other }; diff --git a/src/third_party/mozjs/extract/js/public/CompilationAndEvaluation.h b/src/third_party/mozjs/extract/js/public/CompilationAndEvaluation.h index fee0aecbb09..c8e64b007d2 100644 --- a/src/third_party/mozjs/extract/js/public/CompilationAndEvaluation.h +++ b/src/third_party/mozjs/extract/js/public/CompilationAndEvaluation.h @@ -27,6 +27,7 @@ union Utf8Unit; namespace JS { +class JS_PUBLIC_API EnvironmentChain; class JS_PUBLIC_API InstantiateOptions; class JS_PUBLIC_API ReadOnlyCompileOptions; @@ -84,12 +85,12 @@ extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx, * objects that should end up on the script's scope chain. */ extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx, - JS::HandleObjectVector envChain, + const JS::EnvironmentChain& envChain, JS::Handle script, JS::MutableHandle rval); extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx, - JS::HandleObjectVector envChain, + const JS::EnvironmentChain& envChain, JS::Handle script); namespace JS { @@ -108,7 +109,8 @@ extern JS_PUBLIC_API bool Evaluate(JSContext* cx, * the global object on it; that's implicit. It needs to contain the other * objects that should end up on the script's scope chain. */ -extern JS_PUBLIC_API bool Evaluate(JSContext* cx, HandleObjectVector envChain, +extern JS_PUBLIC_API bool Evaluate(JSContext* cx, + const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, SourceText& srcBuf, MutableHandle rval); @@ -173,7 +175,7 @@ extern JS_PUBLIC_API JSScript* CompileUtf8Path( * global must not be explicitly included in the scope chain. */ extern JS_PUBLIC_API JSFunction* CompileFunction( - JSContext* cx, HandleObjectVector envChain, + JSContext* cx, const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, const char* name, unsigned nargs, const char* const* argnames, SourceText& srcBuf); @@ -185,7 +187,7 @@ extern JS_PUBLIC_API JSFunction* CompileFunction( * global must not be explicitly included in the scope chain. */ extern JS_PUBLIC_API JSFunction* CompileFunction( - JSContext* cx, HandleObjectVector envChain, + JSContext* cx, const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, const char* name, unsigned nargs, const char* const* argnames, SourceText& srcBuf); @@ -194,7 +196,7 @@ extern JS_PUBLIC_API JSFunction* CompileFunction( * Rust-friendly ergonomics. */ extern JS_PUBLIC_API JSFunction* CompileFunctionUtf8( - JSContext* cx, HandleObjectVector envChain, + JSContext* cx, const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, const char* name, unsigned nargs, const char* const* argnames, const char* utf8, size_t length); diff --git a/src/third_party/mozjs/extract/js/public/CompileOptions.h b/src/third_party/mozjs/extract/js/public/CompileOptions.h index 01a84b23986..e0c10b8d5b8 100644 --- a/src/third_party/mozjs/extract/js/public/CompileOptions.h +++ b/src/third_party/mozjs/extract/js/public/CompileOptions.h @@ -62,7 +62,10 @@ #include "js/CharacterEncoding.h" // JS::ConstUTF8CharsZ #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin -#include "js/TypeDecls.h" // JS::MutableHandle (fwd) +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +# include "js/Prefs.h" // JS::Prefs::* +#endif +#include "js/TypeDecls.h" // JS::MutableHandle (fwd) namespace js { class FrontendContext; @@ -124,22 +127,29 @@ class JS_PUBLIC_API PrefableCompileOptions { public: PrefableCompileOptions() : importAttributes_(false), - importAttributesAssertSyntax_(false), sourcePragmas_(true), - throwOnAsmJSValidationFailure_(false) {} +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + explicitResourceManagement_( + JS::Prefs::experimental_explicit_resource_management()), +#endif + throwOnAsmJSValidationFailure_(false) { + } bool importAttributes() const { return importAttributes_; } PrefableCompileOptions& setImportAttributes(bool enabled) { importAttributes_ = enabled; return *this; } - bool importAttributesAssertSyntax() const { - return importAttributesAssertSyntax_; + +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + bool explicitResourceManagement() const { + return explicitResourceManagement_; } - PrefableCompileOptions& setImportAttributesAssertSyntax(bool enabled) { - importAttributesAssertSyntax_ = enabled; + PrefableCompileOptions& setExplicitResourceManagement(bool enabled) { + explicitResourceManagement_ = enabled; return *this; } +#endif // Enable/disable support for parsing '//(#@) source(Mapping)?URL=' pragmas. bool sourcePragmas() const { return sourcePragmas_; } @@ -176,9 +186,11 @@ class JS_PUBLIC_API PrefableCompileOptions { void dumpWith(Printer& print) const { # define PrintFields_(Name) print(#Name, Name) PrintFields_(importAttributes_); - PrintFields_(importAttributesAssertSyntax_); PrintFields_(sourcePragmas_); PrintFields_(throwOnAsmJSValidationFailure_); +# ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + PrintFields_(explicitResourceManagement_); +# endif # undef PrintFields_ switch (asmJSOption_) { @@ -204,11 +216,16 @@ class JS_PUBLIC_API PrefableCompileOptions { private: // ==== Syntax-related options. ==== bool importAttributes_ : 1; - bool importAttributesAssertSyntax_ : 1; // The context has specified that source pragmas should be parsed. bool sourcePragmas_ : 1; +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // The context has specified that explicit resource management syntax + // should be parsed. + bool explicitResourceManagement_ : 1; +#endif + // ==== asm.js options. ==== bool throwOnAsmJSValidationFailure_ : 1; @@ -315,16 +332,6 @@ class JS_PUBLIC_API TransitiveCompileOptions { // called. There is currently no mechanism to release the data sooner. bool usePinnedBytecode = false; - // De-optimize ES module's top-level `var`s, in order to define all of them - // on the ModuleEnvironmentObject, instead of local slot. - // - // This is used for providing all global variables in Cu.import return value - // (see bug 1766761 for more details), and this is temporary solution until - // ESM-ification finishes. - // - // WARNING: This option will eventually be removed. - bool deoptimizeModuleGlobalVars = false; - PrefableCompileOptions prefableOptions_; /** @@ -390,10 +397,12 @@ class JS_PUBLIC_API TransitiveCompileOptions { } bool importAttributes() const { return prefableOptions_.importAttributes(); } - bool importAttributesAssertSyntax() const { - return prefableOptions_.importAttributesAssertSyntax(); - } bool sourcePragmas() const { return prefableOptions_.sourcePragmas(); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + bool explicitResourceManagement() const { + return prefableOptions_.explicitResourceManagement(); + } +#endif bool throwOnAsmJSValidationFailure() const { return prefableOptions_.throwOnAsmJSValidationFailure(); } @@ -435,7 +444,6 @@ class JS_PUBLIC_API TransitiveCompileOptions { PrintFields_(topLevelAwait); PrintFields_(borrowBuffer); PrintFields_(usePinnedBytecode); - PrintFields_(deoptimizeModuleGlobalVars); PrintFields_(introductionType); PrintFields_(introductionLineno); PrintFields_(introductionOffset); @@ -709,13 +717,16 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final return *this; } + void warnAboutConflictingDelazification() const; CompileOptions& setEagerDelazificationStrategy( DelazificationOption strategy) { - // forceFullParse is at the moment considered as a non-overridable strategy. - MOZ_RELEASE_ASSERT(eagerDelazificationStrategy_ != - DelazificationOption::ParseEverythingEagerly || - strategy == - DelazificationOption::ParseEverythingEagerly); + const auto PEE = DelazificationOption::ParseEverythingEagerly; + if (eagerDelazificationStrategy_ == PEE && strategy != PEE) { + // Parse Everything Eagerly cannot be replaced, do noting. + warnAboutConflictingDelazification(); + return *this; + } + eagerDelazificationStrategy_ = strategy; return *this; } @@ -746,17 +757,22 @@ class JS_PUBLIC_API InstantiateOptions { bool hideScriptFromDebugger = false; bool deferDebugMetadata = false; - InstantiateOptions() = default; + DelazificationOption eagerDelazificationStrategy_ = + DelazificationOption::OnDemandOnly; + + InstantiateOptions(); explicit InstantiateOptions(const ReadOnlyCompileOptions& options) : skipFilenameValidation(options.skipFilenameValidation_), hideScriptFromDebugger(options.hideScriptFromDebugger_), - deferDebugMetadata(options.deferDebugMetadata_) {} + deferDebugMetadata(options.deferDebugMetadata_), + eagerDelazificationStrategy_(options.eagerDelazificationStrategy()) {} void copyTo(CompileOptions& options) const { options.skipFilenameValidation_ = skipFilenameValidation; options.hideScriptFromDebugger_ = hideScriptFromDebugger; options.deferDebugMetadata_ = deferDebugMetadata; + options.setEagerDelazificationStrategy(eagerDelazificationStrategy_); } bool hideFromNewScriptInitial() const { @@ -772,6 +788,29 @@ class JS_PUBLIC_API InstantiateOptions { MOZ_ASSERT(skipFilenameValidation == false); MOZ_ASSERT(hideScriptFromDebugger == false); MOZ_ASSERT(deferDebugMetadata == false); + MOZ_ASSERT(eagerDelazificationStrategy_ == + DelazificationOption::OnDemandOnly); + } + + // Assert that all fields have values compatible with the default value. + // + // This can be used in the same way as assertDefault, in case the + // setForceFullParse() is used on the original compile options. + void assertCompatibleWithDefault() const { + MOZ_ASSERT(skipFilenameValidation == false); + MOZ_ASSERT(hideScriptFromDebugger == false); + MOZ_ASSERT(deferDebugMetadata == false); + + // The instantiation step uses the eagerDelazificationStrategy_ field + // only for TransitiveCompileOptions::populateDelazificationCache(). + // + // Both the default OnDemandOnly and + // the ParseEverythingEagerly from setForceFullParse() returns + // false, and they're are compatible. + MOZ_ASSERT(eagerDelazificationStrategy_ == + DelazificationOption::OnDemandOnly || + eagerDelazificationStrategy_ == + DelazificationOption::ParseEverythingEagerly); } #endif }; diff --git a/src/third_party/mozjs/extract/js/public/ContextOptions.h b/src/third_party/mozjs/extract/js/public/ContextOptions.h index 0ac79c0ec70..c619e6760b7 100644 --- a/src/third_party/mozjs/extract/js/public/ContextOptions.h +++ b/src/third_party/mozjs/extract/js/public/ContextOptions.h @@ -24,7 +24,6 @@ class JS_PUBLIC_API ContextOptions { ContextOptions() : wasm_(true), wasmForTrustedPrinciples_(true), - wasmVerbose_(false), wasmBaseline_(true), wasmIon_(true), testWasmAwaitTier2_(false), @@ -34,10 +33,6 @@ class JS_PUBLIC_API ContextOptions { asyncStackCaptureDebuggeeOnly_(false), throwOnDebuggeeWouldRun_(true), dumpStackOnDebuggeeWouldRun_(false), -#ifdef JS_ENABLE_SMOOSH - trackNotImplemented_(false), - trySmoosh_(false), -#endif fuzzing_(false) { } // clang-format on @@ -71,12 +66,6 @@ class JS_PUBLIC_API ContextOptions { return *this; } - bool wasmVerbose() const { return wasmVerbose_; } - ContextOptions& setWasmVerbose(bool flag) { - wasmVerbose_ = flag; - return *this; - } - bool wasmBaseline() const { return wasmBaseline_; } ContextOptions& setWasmBaseline(bool flag) { wasmBaseline_ = flag; @@ -122,14 +111,6 @@ class JS_PUBLIC_API ContextOptions { return *this; } - bool importAttributesAssertSyntax() const { - return compileOptions_.importAttributesAssertSyntax(); - } - ContextOptions& setImportAttributesAssertSyntax(bool enabled) { - compileOptions_.setImportAttributesAssertSyntax(enabled); - return *this; - } - // Override to allow disabling the eval restriction security checks for // this context. bool disableEvalSecurityChecks() const { return disableEvalSecurityChecks_; } @@ -173,24 +154,6 @@ class JS_PUBLIC_API ContextOptions { return *this; } -#ifdef JS_ENABLE_SMOOSH - // Track Number of Not Implemented Calls by writing to a file - bool trackNotImplemented() const { return trackNotImplemented_; } - ContextOptions& setTrackNotImplemented(bool flag) { - trackNotImplemented_ = flag; - return *this; - } - - // Try compiling SmooshMonkey frontend first, and fallback to C++ - // implementation when it fails. - bool trySmoosh() const { return trySmoosh_; } - ContextOptions& setTrySmoosh(bool flag) { - trySmoosh_ = flag; - return *this; - } - -#endif // JS_ENABLE_SMOOSH - bool fuzzing() const { return fuzzing_; } // Defined out-of-line because it depends on a compile-time option ContextOptions& setFuzzing(bool flag); @@ -209,7 +172,6 @@ class JS_PUBLIC_API ContextOptions { // WASM options. bool wasm_ : 1; bool wasmForTrustedPrinciples_ : 1; - bool wasmVerbose_ : 1; bool wasmBaseline_ : 1; bool wasmIon_ : 1; bool testWasmAwaitTier2_ : 1; @@ -223,10 +185,6 @@ class JS_PUBLIC_API ContextOptions { bool asyncStackCaptureDebuggeeOnly_ : 1; bool throwOnDebuggeeWouldRun_ : 1; bool dumpStackOnDebuggeeWouldRun_ : 1; -#ifdef JS_ENABLE_SMOOSH - bool trackNotImplemented_ : 1; - bool trySmoosh_ : 1; -#endif bool fuzzing_ : 1; // Compile options. diff --git a/src/third_party/mozjs/extract/js/public/Conversions.h b/src/third_party/mozjs/extract/js/public/Conversions.h index 63a9c5111ee..c12a6caae10 100644 --- a/src/third_party/mozjs/extract/js/public/Conversions.h +++ b/src/third_party/mozjs/extract/js/public/Conversions.h @@ -272,17 +272,6 @@ inline JSObject* ToObject(JSContext* cx, HandleValue v) { return js::ToObjectSlow(cx, v, false); } -#ifdef ENABLE_RECORD_TUPLE -inline JSObject* ToObjectOrGetObjectPayload(JSContext* cx, HandleValue v) { - detail::AssertArgumentsAreSane(cx, v); - - if (v.hasObjectPayload()) { - return &v.getObjectPayload(); - } - return js::ToObjectSlow(cx, v, false); -} -#endif - /** * Convert a double value to UnsignedInteger (an unsigned integral type) using * ECMAScript-style semantics (that is, in like manner to how ECMAScript's @@ -372,8 +361,9 @@ inline UnsignedInteger ToUnsignedInteger(double d) { } // Compute the congruent value in the signed range. - return (bits & mozilla::FloatingPoint::kSignBit) ? ~result + 1 - : result; + return (bits & mozilla::FloatingPoint::kSignBit) + ? UnsignedInteger(~result) + 1 + : result; } template diff --git a/src/third_party/mozjs/extract/js/public/Debug.h b/src/third_party/mozjs/extract/js/public/Debug.h index 837ae2a1819..6417f500a94 100644 --- a/src/third_party/mozjs/extract/js/public/Debug.h +++ b/src/third_party/mozjs/extract/js/public/Debug.h @@ -11,7 +11,9 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/BaseProfilerUtils.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/Vector.h" #include @@ -29,6 +31,136 @@ class Debugger; extern JS_PUBLIC_API bool JS_DefineDebuggerObject(JSContext* cx, JS::HandleObject obj); +// If the JS execution tracer is running, this will generate a +// ENTRY_KIND_LABEL_ENTER entry with the specified label. +// The consumer of the trace can then, for instance, correlate all code running +// after this entry and before the corresponding ENTRY_KIND_LABEL_LEAVE with the +// provided label. +// If the tracer is not running, this does nothing. +extern JS_PUBLIC_API void JS_TracerEnterLabelLatin1(JSContext* cx, + const char* label); +extern JS_PUBLIC_API void JS_TracerEnterLabelTwoByte(JSContext* cx, + const char16_t* label); + +extern JS_PUBLIC_API bool JS_TracerIsTracing(JSContext* cx); + +// If the JS execution tracer is running, this will generate a +// ENTRY_KIND_LABEL_LEAVE entry with the specified label. +// It is up to the consumer to decide what to do with a ENTRY_KIND_LABEL_LEAVE +// entry is encountered without a corresponding ENTRY_KIND_LABEL_ENTER. +// If the tracer is not running, this does nothing. +extern JS_PUBLIC_API void JS_TracerLeaveLabelLatin1(JSContext* cx, + const char* label); +extern JS_PUBLIC_API void JS_TracerLeaveLabelTwoByte(JSContext* cx, + const char16_t* label); + +#ifdef MOZ_EXECUTION_TRACING + +// This will begin execution tracing for the JSContext, i.e., this will begin +// recording every entrance into / exit from a function for the given context. +// The trace can be read via JS_TracerSnapshotTrace, and populates the +// ExecutionTrace struct defined below. +// +// This throws if the code coverage is active for any realm in the context. +extern JS_PUBLIC_API bool JS_TracerBeginTracing(JSContext* cx); + +// This ends execution tracing for the JSContext, discards the tracing +// buffers, and clears some caches used for tracing. JS_TracerSnapshotTrace +// should be called *before* JS_TracerEndTracing if you want to read the trace +// data for this JSContext. +extern JS_PUBLIC_API bool JS_TracerEndTracing(JSContext* cx); + +namespace JS { + +// This is populated by JS_TracerSnapshotTrace and just represent a minimal +// structure for natively representing an execution trace across a range of +// JSContexts (see below). The core of the trace is an array of events, each of +// which is a tagged union with data corresponding to that event. Events can +// also point into various tables, and store all of their string data in a +// contiguous UTF-8 stringBuffer (each string is null-terminated within the +// buffer.) +struct ExecutionTrace { + enum class EventKind : uint8_t { + FunctionEnter = 0, + FunctionLeave = 1, + LabelEnter = 2, + LabelLeave = 3, + + // NOTE: the `Error` event has no TracedEvent payload, and will always + // represent the end of the trace when encountered. + Error = 4, + }; + + enum class ImplementationType : uint8_t { + Interpreter = 0, + Baseline = 1, + Ion = 2, + Wasm = 3, + }; + + struct TracedEvent { + EventKind kind; + union { + // For FunctionEnter / FunctionLeave + struct { + ImplementationType implementation; + + // 1-origin line number of the function + uint32_t lineNumber; + + // 1-origin column of the function + uint32_t column; + + // Keys into the thread's scriptUrls HashMap. This key can be missing + // from the HashMap, although ideally that situation is rare (it is + // more likely in long running traces with *many* unique functions + // and/or scripts) + uint32_t scriptId; + + // ID to the realm that the frame was in. It's used for finding which + // frame comes from which window/page. + uint64_t realmID; + + // Keys into the thread's atoms HashMap. This key can be missing from + // the HashMap as well (see comment above scriptId) + uint32_t functionNameId; + } functionEvent; + + // For LabelEnter / LabelLeave + struct { + size_t label; // Indexes directly into the trace's stringBuffer + } labelEvent; + }; + // Milliseconds since process creation + double time; + }; + + struct TracedJSContext { + mozilla::baseprofiler::BaseProfilerThreadId id; + + // Maps ids to indices into the trace's stringBuffer + mozilla::HashMap scriptUrls; + + // Similar to scriptUrls + mozilla::HashMap atoms; + + mozilla::Vector events; + }; + + mozilla::Vector stringBuffer; + + // This will be populated with an entry for each context which had tracing + // enabled via JS_TracerBeginTracing. + mozilla::Vector contexts; +}; +} // namespace JS + +// Captures the trace for all JSContexts in the process which are currently +// tracing. +extern JS_PUBLIC_API bool JS_TracerSnapshotTrace(JS::ExecutionTrace& trace); + +#endif /* MOZ_EXECUTION_TRACING */ + namespace JS { namespace dbg { @@ -302,52 +434,6 @@ JS_PUBLIC_API bool IsDebugger(JSObject& obj); JS_PUBLIC_API bool GetDebuggeeGlobals(JSContext* cx, JSObject& dbgObj, MutableHandleObjectVector vector); -// Hooks for reporting where JavaScript execution began. -// -// Our performance tools would like to be able to label blocks of JavaScript -// execution with the function name and source location where execution began: -// the event handler, the callback, etc. -// -// Construct an instance of this class on the stack, providing a JSContext -// belonging to the runtime in which execution will occur. Each time we enter -// JavaScript --- specifically, each time we push a JavaScript stack frame that -// has no older JS frames younger than this AutoEntryMonitor --- we will -// call the appropriate |Entry| member function to indicate where we've begun -// execution. - -class MOZ_STACK_CLASS JS_PUBLIC_API AutoEntryMonitor { - JSContext* cx_; - AutoEntryMonitor* savedMonitor_; - - public: - explicit AutoEntryMonitor(JSContext* cx); - ~AutoEntryMonitor(); - - // SpiderMonkey reports the JavaScript entry points occuring within this - // AutoEntryMonitor's scope to the following member functions, which the - // embedding is expected to override. - // - // It is important to note that |asyncCause| is owned by the caller and its - // lifetime must outlive the lifetime of the AutoEntryMonitor object. It is - // strongly encouraged that |asyncCause| be a string constant or similar - // statically allocated string. - - // We have begun executing |function|. Note that |function| may not be the - // actual closure we are running, but only the canonical function object to - // which the script refers. - virtual void Entry(JSContext* cx, JSFunction* function, - HandleValue asyncStack, const char* asyncCause) = 0; - - // Execution has begun at the entry point of |script|, which is not a - // function body. (This is probably being executed by 'eval' or some - // JSAPI equivalent.) - virtual void Entry(JSContext* cx, JSScript* script, HandleValue asyncStack, - const char* asyncCause) = 0; - - // Execution of the function or script has ended. - virtual void Exit(JSContext* cx) {} -}; - // Returns true if there's any debugger attached to the given context where // the debugger's "shouldAvoidSideEffects" property is true. // diff --git a/src/third_party/mozjs/extract/js/public/EnvironmentChain.h b/src/third_party/mozjs/extract/js/public/EnvironmentChain.h new file mode 100644 index 00000000000..7d37184b521 --- /dev/null +++ b/src/third_party/mozjs/extract/js/public/EnvironmentChain.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_EnvironmentChain_h +#define js_EnvironmentChain_h + +#include "mozilla/Attributes.h" // MOZ_RAII + +#include // size_t + +#include "jstypes.h" // JS_PUBLIC_API + +#include "js/GCVector.h" // JS::RootedVector + +struct JS_PUBLIC_API JSContext; +class JS_PUBLIC_API JSObject; + +namespace JS { + +enum class SupportUnscopables : bool { No = false, Yes = true }; + +/** + * JS::EnvironmentChain stores a list of objects to put on the environment + * chain. + * + * Internally the engine will create a non-syntactic 'with' environment for each + * of these objects. Note that 'with' environments aren't optimized well so you + * should use this class only if you really have to. + * + * The SupportUnscopables enum class controls whether these non-syntactic 'with' + * environments support Symbol.unscopables similar to syntactic 'with' + * statements in JS. + * + * Passing SupportUnscopables::No is better for performance because it lets us + * skip the Symbol.unscopables property lookup. Some Web APIs require supporting + * Symbol.unscopables though. In Firefox, SupportUnscopables::Yes is used for + * event handlers. + */ +class MOZ_RAII JS_PUBLIC_API EnvironmentChain { + JS::RootedObjectVector chain_; + SupportUnscopables supportUnscopables_; + + public: + EnvironmentChain(JSContext* cx, SupportUnscopables supportUnscopables) + : chain_(cx), supportUnscopables_(supportUnscopables) {} + + EnvironmentChain(const EnvironmentChain&) = delete; + void operator=(const EnvironmentChain&) = delete; + + [[nodiscard]] bool append(JSObject* obj) { return chain_.append(obj); } + bool empty() const { return chain_.empty(); } + size_t length() const { return chain_.length(); } + + RootedObjectVector& chain() { return chain_; } + const RootedObjectVector& chain() const { return chain_; } + + void setSupportUnscopables(SupportUnscopables supportUnscopables) { + supportUnscopables_ = supportUnscopables; + } + SupportUnscopables supportUnscopables() const { return supportUnscopables_; } +}; + +} // namespace JS + +#endif /* js_EnvironmentChain_h */ diff --git a/src/third_party/mozjs/extract/js/public/ErrorReport.h b/src/third_party/mozjs/extract/js/public/ErrorReport.h index 9bf824dea26..4975cdf8692 100644 --- a/src/third_party/mozjs/extract/js/public/ErrorReport.h +++ b/src/third_party/mozjs/extract/js/public/ErrorReport.h @@ -62,24 +62,40 @@ enum ErrorArgumentsType { * using the generalized error reporting mechanism. (One side effect of this * type is to not prepend 'Error:' to warning messages.) This value can go away * if we ever decide to use an entirely separate mechanism for warnings. + * + * The errors and warnings are arranged in alphabetically within their + * respective categories as defined in the comments below. */ enum JSExnType { + // Generic Errors JSEXN_ERR, JSEXN_FIRST = JSEXN_ERR, + // Internal Errors JSEXN_INTERNALERR, + // ECMAScript Errors JSEXN_AGGREGATEERR, JSEXN_EVALERR, JSEXN_RANGEERR, JSEXN_REFERENCEERR, +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + JSEXN_SUPPRESSEDERR, +#endif JSEXN_SYNTAXERR, JSEXN_TYPEERR, JSEXN_URIERR, + // Debugger Errors JSEXN_DEBUGGEEWOULDRUN, + // WASM Errors JSEXN_WASMCOMPILEERROR, JSEXN_WASMLINKERROR, JSEXN_WASMRUNTIMEERROR, +#ifdef ENABLE_WASM_JSPI + JSEXN_WASMSUSPENDERROR, +#endif JSEXN_ERROR_LIMIT, + // Warnings JSEXN_WARN = JSEXN_ERROR_LIMIT, + // Error Notes JSEXN_NOTE, JSEXN_LIMIT }; @@ -540,6 +556,20 @@ extern JS_PUBLIC_API bool CreateError( JSErrorReport* report, HandleString message, Handle> cause, MutableHandleValue rval); +/** + * An uncatchable exception is used to terminate execution by returning false + * or nullptr without reporting a pending exception on the context. These + * exceptions are called "uncatchable" because try-catch can't be used to catch + * them. + * + * This is mainly used to terminate JS execution from the interrupt handler. + * + * If the context has a pending exception, this function will clear it. Also, in + * debug builds, it sets a flag on the context to improve exception handling + * assertions in the engine. + */ +extern JS_PUBLIC_API void ReportUncatchableException(JSContext* cx); + } /* namespace JS */ #endif /* js_ErrorReport_h */ diff --git a/src/third_party/mozjs/extract/js/public/GCAPI.h b/src/third_party/mozjs/extract/js/public/GCAPI.h index fcaeb7262ed..1d3a33f63d1 100644 --- a/src/third_party/mozjs/extract/js/public/GCAPI.h +++ b/src/third_party/mozjs/extract/js/public/GCAPI.h @@ -28,7 +28,6 @@ namespace js { namespace gc { class GCRuntime; } // namespace gc -class JS_PUBLIC_API SliceBudget; namespace gcstats { struct Statistics; } // namespace gcstats @@ -36,6 +35,8 @@ struct Statistics; namespace JS { +class JS_PUBLIC_API SliceBudget; + // Options used when starting a GC. enum class GCOptions : uint32_t { // Normal GC invocation. @@ -261,14 +262,6 @@ typedef enum JSGCParamKey { */ JSGC_MIN_EMPTY_CHUNK_COUNT = 21, - /** - * We never keep more than this many unused chunks in the free chunk pool. - * - * Pref: javascript.options.mem.gc_max_empty_chunk_count - * Default: MaxEmptyChunkCount - */ - JSGC_MAX_EMPTY_CHUNK_COUNT = 22, - /** * Whether compacting GC is enabled. * @@ -488,6 +481,33 @@ typedef enum JSGCParamKey { */ JSGC_SLICE_NUMBER = 54, + /** + * Whether the nursery is enabled. + * + * Pref: javascript.options.mem.gc_generational + * Default: true + */ + JSGC_NURSERY_ENABLED = 55, + + /* + * Whether we are in high frequency GC mode, where the time between + * collections is less than that specified by JSGC_HIGH_FREQUENCY_TIME_LIMIT. + */ + JSGC_HIGH_FREQUENCY_MODE = 56, + + /** + * The engine attempts to keep nursery collection time less than this limit by + * restricting the size of the nursery. + * + * This only happens in optimized builds. It does not happen during pageload + * (as indicated by js::gc::SetPerformanceHint). + * + * Setting this to zero disables this feature. + * + * Default: 4 + * Pref: javascript.options.mem.nursery_max_time_goal_ms + */ + JSGC_NURSERY_MAX_TIME_GOAL_MS = 57, } JSGCParamKey; /* @@ -505,7 +525,7 @@ typedef void (*JSTraceDataOp)(JSTracer* trc, void* data); * While tracing this should check the budget and return false if it has been * exceeded. When passed an unlimited budget it should always return true. */ -typedef bool (*JSGrayRootsTracer)(JSTracer* trc, js::SliceBudget& budget, +typedef bool (*JSGrayRootsTracer)(JSTracer* trc, JS::SliceBudget& budget, void* data); typedef enum JSGCStatus { JSGC_BEGIN, JSGC_END } JSGCStatus; @@ -651,7 +671,7 @@ namespace JS { D(DOCSHELL, 54) \ D(HTML_PARSER, 55) \ D(DOM_TESTUTILS, 56) \ - D(PREPARE_FOR_PAGELOAD, 57) \ + D(PREPARE_FOR_PAGELOAD, LAST_FIREFOX_REASON) \ \ /* Reasons reserved for embeddings. */ \ D(RESERVED1, FIRST_RESERVED_REASON) \ @@ -666,6 +686,7 @@ namespace JS { enum class GCReason { FIRST_FIREFOX_REASON = 33, + LAST_FIREFOX_REASON = 57, FIRST_RESERVED_REASON = 90, #define MAKE_REASON(name, val) name = val, @@ -692,6 +713,18 @@ extern JS_PUBLIC_API const char* ExplainGCReason(JS::GCReason reason); */ extern JS_PUBLIC_API bool InternalGCReason(JS::GCReason reason); +/** + * Get a statically allocated C string explaining the given Abort reason. + * Input is the integral value of the enum. + */ +extern JS_PUBLIC_API const char* ExplainGCAbortReason(uint32_t reason); + +/** + * Get a statically allocated C string describing the Phase. + * Input is the integral value of the enum. + */ +extern JS_PUBLIC_API const char* GetGCPhaseName(uint32_t phase); + /* * Zone GC: * @@ -778,7 +811,7 @@ extern JS_PUBLIC_API void NonIncrementalGC(JSContext* cx, JS::GCOptions options, extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx, JS::GCOptions options, GCReason reason, - const js::SliceBudget& budget); + const JS::SliceBudget& budget); /** * Perform a slice of an ongoing incremental collection. When this function @@ -789,7 +822,7 @@ extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx, * shorter than the requested interval. */ extern JS_PUBLIC_API void IncrementalGCSlice(JSContext* cx, GCReason reason, - const js::SliceBudget& budget); + const JS::SliceBudget& budget); /** * Return whether an incremental GC has work to do on the foreground thread and @@ -957,7 +990,7 @@ typedef void (*DoCycleCollectionCallback)(JSContext* cx); extern JS_PUBLIC_API DoCycleCollectionCallback SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback); -using CreateSliceBudgetCallback = js::SliceBudget (*)(JS::GCReason reason, +using CreateSliceBudgetCallback = JS::SliceBudget (*)(JS::GCReason reason, int64_t millis); /** @@ -971,14 +1004,6 @@ using CreateSliceBudgetCallback = js::SliceBudget (*)(JS::GCReason reason, extern JS_PUBLIC_API void SetCreateGCSliceBudgetCallback( JSContext* cx, CreateSliceBudgetCallback cb); -/** - * Incremental GC defaults to enabled, but may be disabled for testing or in - * embeddings that have not yet implemented barriers on their native classes. - * There is not currently a way to re-enable incremental GC once it has been - * disabled on the runtime. - */ -extern JS_PUBLIC_API void DisableIncrementalGC(JSContext* cx); - /** * Returns true if incremental GC is enabled. Simply having incremental GC * enabled is not sufficient to ensure incremental collections are happening. diff --git a/src/third_party/mozjs/extract/js/public/GCHashTable.h b/src/third_party/mozjs/extract/js/public/GCHashTable.h index 5d9b0e9c771..7e71d0a5dfd 100644 --- a/src/third_party/mozjs/extract/js/public/GCHashTable.h +++ b/src/third_party/mozjs/extract/js/public/GCHashTable.h @@ -646,6 +646,21 @@ class WeakCache> final bool needsIncrementalBarrier() const override { return barrierTracer; } + // Steal the contents of this weak cache. + Set stealContents() { + // This operation is not currently allowed while barriers are in place + // since it doesn't make sense to steal the contents while we are + // sweeping. + MOZ_ASSERT(!barrierTracer); + + auto rval = std::move(set); + // Ensure set is in a specified (empty) state after the move + set.clear(); + + // Return set; no move to avoid invalidating NRVO. + return rval; + } + private: static bool entryNeedsSweep(JSTracer* barrierTracer, const Entry& prior) { Entry entry(prior); diff --git a/src/third_party/mozjs/extract/js/public/GCPolicyAPI.h b/src/third_party/mozjs/extract/js/public/GCPolicyAPI.h index ad0b0fc941b..6ec149da4fd 100644 --- a/src/third_party/mozjs/extract/js/public/GCPolicyAPI.h +++ b/src/third_party/mozjs/extract/js/public/GCPolicyAPI.h @@ -165,6 +165,10 @@ struct GCPolicy> { static bool traceWeak(JSTracer* trc, JS::Heap* thingp) { return !*thingp || js::gc::TraceWeakEdge(trc, thingp); } + static bool needsSweep(JSTracer* trc, const JS::Heap* thingp) { + T* thing = const_cast(thingp->unsafeAddress()); + return thing && js::gc::EdgeNeedsSweepUnbarrieredSlow(thing); + } }; // GCPolicy> forwards the contained pointer to GCPolicy. @@ -255,6 +259,36 @@ struct GCPolicy> { static bool isValid(const mozilla::Result& t) { return true; } }; +template +struct GCPolicy> { + using T = std::tuple; + static void trace(JSTracer* trc, T* tp, const char* name) { + traceFieldsFrom<0>(trc, *tp, name); + } + static bool isValid(const T& t) { return areFieldsValidFrom<0>(t); } + + private: + template + static void traceFieldsFrom(JSTracer* trc, T& tuple, const char* name) { + if constexpr (N != std::tuple_size_v) { + using F = std::tuple_element_t; + GCPolicy::trace(trc, &std::get(tuple), name); + traceFieldsFrom(trc, tuple, name); + } + } + + template + static bool areFieldsValidFrom(const T& tuple) { + if constexpr (N != std::tuple_size_v) { + using F = std::tuple_element_t; + return GCPolicy::isValid(std::get(tuple)) && + areFieldsValidFrom(tuple); + } + + return true; + } +}; + } // namespace JS #endif // GCPolicyAPI_h diff --git a/src/third_party/mozjs/extract/js/public/GCVector.h b/src/third_party/mozjs/extract/js/public/GCVector.h index 897acb71e74..7f62fa25619 100644 --- a/src/third_party/mozjs/extract/js/public/GCVector.h +++ b/src/third_party/mozjs/extract/js/public/GCVector.h @@ -160,7 +160,7 @@ class GCVector { } size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return vector.sizeOfIncludingThis(mallocSizeOf); + return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); } void trace(JSTracer* trc) { diff --git a/src/third_party/mozjs/extract/js/public/HeapAPI.h b/src/third_party/mozjs/extract/js/public/HeapAPI.h index 1c0ce355141..6b3fd9aa0cd 100644 --- a/src/third_party/mozjs/extract/js/public/HeapAPI.h +++ b/src/third_party/mozjs/extract/js/public/HeapAPI.h @@ -25,8 +25,6 @@ /* These values are private to the JS engine. */ namespace js { -class NurseryDecommitTask; - JS_PUBLIC_API bool CurrentThreadCanAccessZone(JS::Zone* zone); // To prevent false sharing, some data structures are aligned to a typical cache @@ -37,7 +35,7 @@ namespace gc { class Arena; struct Cell; -class TenuredChunk; +class ArenaChunk; class StoreBuffer; class TenuredCell; @@ -53,6 +51,7 @@ const size_t PageShift = 12; // Expected page size, so we could initialze ArenasPerPage at compile-time. // The actual system page size should be queried by SystemPageSize(). const size_t PageSize = size_t(1) << PageShift; +const size_t PageMask = PageSize - 1; constexpr size_t ArenasPerPage = PageSize / ArenaSize; const size_t ChunkShift = 20; @@ -84,7 +83,8 @@ const size_t ArenaBitmapWords = HowMany(ArenaBitmapBits, JS_BITS_PER_WORD); enum class ChunkKind : uint8_t { Invalid = 0, - TenuredHeap, + TenuredArenas, + MediumBuffers, NurseryToSpace, NurseryFromSpace }; @@ -97,13 +97,13 @@ class ChunkBase { // Initialize a tenured heap chunk. explicit ChunkBase(JSRuntime* rt) { MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0); - initBaseForTenuredChunk(rt); + initBaseForArenaChunk(rt); } - void initBaseForTenuredChunk(JSRuntime* rt) { + void initBaseForArenaChunk(JSRuntime* rt) { runtime = rt; storeBuffer = nullptr; - kind = ChunkKind::TenuredHeap; + kind = ChunkKind::TenuredArenas; nurseryChunkIndex = UINT8_MAX; } @@ -113,20 +113,33 @@ class ChunkBase { runtime(rt), kind(kind), nurseryChunkIndex(chunkIndex) { - MOZ_ASSERT(kind == ChunkKind::NurseryFromSpace || - kind == ChunkKind::NurseryToSpace); + MOZ_ASSERT(isNurseryChunk()); MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0); MOZ_ASSERT(storeBuffer); } + ChunkBase(JSRuntime* rt, ChunkKind kind) + : storeBuffer(nullptr), + runtime(rt), + kind(kind), + nurseryChunkIndex(UINT8_MAX) {} + public: ChunkKind getKind() const { - MOZ_ASSERT_IF(storeBuffer, kind == ChunkKind::NurseryToSpace || - kind == ChunkKind::NurseryFromSpace); - MOZ_ASSERT_IF(!storeBuffer, kind == ChunkKind::TenuredHeap); + MOZ_ASSERT_IF(storeBuffer, isNurseryChunk()); + MOZ_ASSERT_IF(!storeBuffer, isTenuredChunk()); return kind; } + bool isNurseryChunk() const { + return kind == ChunkKind::NurseryToSpace || + kind == ChunkKind::NurseryFromSpace; + } + + bool isTenuredChunk() const { + return kind == ChunkKind::TenuredArenas || kind == ChunkKind::MediumBuffers; + } + // The store buffer for pointers from tenured things to things in this // chunk. Will be non-null if and only if this is a nursery chunk. StoreBuffer* storeBuffer; @@ -139,12 +152,12 @@ class ChunkBase { uint8_t nurseryChunkIndex; }; -// Information about tenured heap chunks. -struct TenuredChunkInfo { +// Information about tenured heap chunks containing arenas. +struct ArenaChunkInfo { private: friend class ChunkPool; - TenuredChunk* next = nullptr; - TenuredChunk* prev = nullptr; + ArenaChunk* next = nullptr; + ArenaChunk* prev = nullptr; public: /* Number of free arenas, either committed or decommitted. */ @@ -152,6 +165,9 @@ struct TenuredChunkInfo { /* Number of free, committed arenas. */ uint32_t numArenasFreeCommitted; + + /* Whether this chunk is the chunk currently being allocated from. */ + bool isCurrentChunk = false; }; /* @@ -180,7 +196,7 @@ const size_t BitsPerPageWithHeaders = (ArenaSize + ArenaBitmapBytes) * ArenasPerPage * CHAR_BIT + ArenasPerPage + 1; const size_t ChunkBitsAvailable = - (ChunkSize - sizeof(ChunkBase) - sizeof(TenuredChunkInfo)) * CHAR_BIT; + (ChunkSize - sizeof(ChunkBase) - sizeof(ArenaChunkInfo)) * CHAR_BIT; const size_t PagesPerChunk = ChunkBitsAvailable / BitsPerPageWithHeaders; const size_t ArenasPerChunk = PagesPerChunk * ArenasPerPage; const size_t FreeCommittedBits = ArenasPerChunk; @@ -190,7 +206,7 @@ const size_t BitsPerArenaWithHeaders = (DecommitBits / ArenasPerChunk) + 1; const size_t CalculatedChunkSizeRequired = - sizeof(ChunkBase) + sizeof(TenuredChunkInfo) + + sizeof(ChunkBase) + sizeof(ArenaChunkInfo) + RoundUp(ArenasPerChunk * ArenaBitmapBytes, sizeof(uintptr_t)) + RoundUp(FreeCommittedBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT + RoundUp(DecommitBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT + @@ -205,10 +221,13 @@ static_assert(CalculatedChunkPadSize * CHAR_BIT < BitsPerArenaWithHeaders, static_assert(ArenasPerChunk == 252, "Do not accidentally change our heap's density."); +const size_t FirstArenaOffset = ChunkSize - ArenasPerChunk * ArenaSize; + // Mark bitmaps are atomic because they can be written by gray unmarking on the // main thread while read by sweeping on a background thread. The former does // not affect the result of the latter. using MarkBitmapWord = mozilla::Atomic; +static constexpr size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT; /* * Live objects are marked black or gray. Everything reachable from a JS root is @@ -227,30 +246,77 @@ enum class ColorBit : uint32_t { BlackBit = 0, GrayOrBlackBit = 1 }; enum class MarkColor : uint8_t { Gray = 1, Black = 2 }; // Mark bitmap for a tenured heap chunk. -struct alignas(TypicalCacheLineSize) MarkBitmap { - static constexpr size_t WordCount = ArenaBitmapWords * ArenasPerChunk; +template +class alignas(TypicalCacheLineSize) MarkBitmap { + static constexpr size_t ByteCount = + (ChunkSize - FirstThingOffset) / BytesPerMarkBit; + static constexpr size_t WordCount = HowMany(ByteCount, MarkBitmapWordBits); MarkBitmapWord bitmap[WordCount]; - inline void getMarkWordAndMask(const TenuredCell* cell, ColorBit colorBit, - MarkBitmapWord** wordp, uintptr_t* maskp); + public: + static constexpr size_t FirstThingAdjustmentBits = + FirstThingOffset / BytesPerMarkBit; + + static constexpr size_t FirstThingAdjustmentWords = + FirstThingAdjustmentBits / MarkBitmapWordBits; + + MOZ_ALWAYS_INLINE void getMarkWordAndMask(const void* cell, ColorBit colorBit, + MarkBitmapWord** wordp, + uintptr_t* maskp) { + // Note: the JIT pre-barrier trampolines inline this code. Update + // MacroAssembler::emitPreBarrierFastPath code too when making changes here! + + MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell); + + size_t offset = uintptr_t(cell) & ChunkMask; + MOZ_ASSERT(offset >= FirstThingOffset); + + const size_t bit = offset / BytesPerMarkBit + size_t(colorBit); + size_t word = bit / MarkBitmapWordBits - FirstThingAdjustmentWords; + MOZ_ASSERT(word < WordCount); + *wordp = &bitmap[word]; + *maskp = uintptr_t(1) << (bit % MarkBitmapWordBits); + } // The following are not exported and are defined in gc/Heap.h: - inline bool markBit(const TenuredCell* cell, ColorBit colorBit); - inline bool isMarkedAny(const TenuredCell* cell); - inline bool isMarkedBlack(const TenuredCell* cell); - inline bool isMarkedGray(const TenuredCell* cell); - inline bool markIfUnmarked(const TenuredCell* cell, MarkColor color); - inline bool markIfUnmarkedAtomic(const TenuredCell* cell, MarkColor color); - inline void markBlack(const TenuredCell* cell); - inline void markBlackAtomic(const TenuredCell* cell); + MOZ_ALWAYS_INLINE bool markBit(const void* cell, ColorBit colorBit) { + MarkBitmapWord* word; + uintptr_t mask; + getMarkWordAndMask(cell, colorBit, &word, &mask); + return *word & mask; + } + + MOZ_ALWAYS_INLINE bool isMarkedAny(const void* cell) { + return markBit(cell, ColorBit::BlackBit) || + markBit(cell, ColorBit::GrayOrBlackBit); + } + + MOZ_ALWAYS_INLINE bool isMarkedBlack(const void* cell) { + // Return true if BlackBit is set. + return markBit(cell, ColorBit::BlackBit); + } + + MOZ_ALWAYS_INLINE bool isMarkedGray(const void* cell) { + // Return true if GrayOrBlackBit is set and BlackBit is not set. + return !markBit(cell, ColorBit::BlackBit) && + markBit(cell, ColorBit::GrayOrBlackBit); + } + + inline bool markIfUnmarked(const void* cell, MarkColor color); + inline bool markIfUnmarkedThreadSafe(const void* cell, MarkColor color); + inline void markBlack(const void* cell); + inline void markBlackAtomic(const void* cell); inline void copyMarkBit(TenuredCell* dst, const TenuredCell* src, ColorBit colorBit); - inline void unmark(const TenuredCell* cell); + inline void unmark(const void* cell); + inline void unmarkOneBit(const void* cell, ColorBit colorBit); inline MarkBitmapWord* arenaBits(Arena* arena); + + inline void copyFrom(const MarkBitmap& other); + inline void clear(); }; -static_assert(ArenaBitmapBytes * ArenasPerChunk == sizeof(MarkBitmap), - "Ensure our MarkBitmap actually covers all arenas."); +using ChunkMarkBitmap = MarkBitmap; // Bitmap with one bit per page used for decommitted page set. using ChunkPageBitmap = mozilla::BitSet; @@ -258,21 +324,26 @@ using ChunkPageBitmap = mozilla::BitSet; // Bitmap with one bit per arena used for free committed arena set. using ChunkArenaBitmap = mozilla::BitSet; -// Base class containing data members for a tenured heap chunk. -class TenuredChunkBase : public ChunkBase { +// Base class for a tenured heap chunk containing fixed size arenas. +class ArenaChunkBase : public ChunkBase { public: - TenuredChunkInfo info; - MarkBitmap markBits; + ArenaChunkInfo info; + ChunkMarkBitmap markBits; ChunkArenaBitmap freeCommittedArenas; ChunkPageBitmap decommittedPages; protected: - explicit TenuredChunkBase(JSRuntime* runtime) : ChunkBase(runtime) { + explicit ArenaChunkBase(JSRuntime* runtime) : ChunkBase(runtime) { + static_assert(sizeof(markBits) == ArenaBitmapBytes * ArenasPerChunk, + "Ensure our MarkBitmap actually covers all arenas."); info.numArenasFree = ArenasPerChunk; } + void initAsCommitted(); void initAsDecommitted(); }; +static_assert(FirstArenaOffset == + RoundUp(sizeof(gc::ArenaChunkBase), ArenaSize)); /* * We sometimes use an index to refer to a cell in an arena. The index for a @@ -282,17 +353,8 @@ class TenuredChunkBase : public ChunkBase { const size_t ArenaCellIndexBytes = CellAlignBytes; const size_t MaxArenaCellIndex = ArenaSize / CellAlignBytes; -const size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT; - -constexpr size_t FirstArenaAdjustmentBits = - RoundUp(sizeof(gc::TenuredChunkBase), ArenaSize) / gc::CellBytesPerMarkBit; - -static_assert((FirstArenaAdjustmentBits % MarkBitmapWordBits) == 0); -constexpr size_t FirstArenaAdjustmentWords = - FirstArenaAdjustmentBits / MarkBitmapWordBits; - const size_t ChunkStoreBufferOffset = offsetof(ChunkBase, storeBuffer); -const size_t ChunkMarkBitmapOffset = offsetof(TenuredChunkBase, markBits); +const size_t ChunkMarkBitmapOffset = offsetof(ArenaChunkBase, markBits); // Hardcoded offsets into Arena class. const size_t ArenaZoneOffset = 2 * sizeof(uint32_t); @@ -428,6 +490,9 @@ class JS_PUBLIC_API GCCellPtr { return asCell(); } + bool operator==(const GCCellPtr other) const { return ptr == other.ptr; } + bool operator!=(const GCCellPtr other) const { return ptr != other.ptr; } + // Simplify checks to the kind. template >> bool is() const { @@ -518,55 +583,31 @@ void ApplyGCThingTyped(GCCellPtr thing, F&& f) { } /* namespace JS */ -// These are defined in the toplevel namespace instead of within JS so that -// they won't shadow other operator== overloads (see bug 1456512.) - -inline bool operator==(JS::GCCellPtr ptr1, JS::GCCellPtr ptr2) { - return ptr1.asCell() == ptr2.asCell(); -} - -inline bool operator!=(JS::GCCellPtr ptr1, JS::GCCellPtr ptr2) { - return !(ptr1 == ptr2); -} - namespace js { namespace gc { -/* static */ -MOZ_ALWAYS_INLINE void MarkBitmap::getMarkWordAndMask(const TenuredCell* cell, - ColorBit colorBit, - MarkBitmapWord** wordp, - uintptr_t* maskp) { - // Note: the JIT pre-barrier trampolines inline this code. Update - // MacroAssembler::emitPreBarrierFastPath code too when making changes here! - - MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell); - - size_t offset = uintptr_t(cell) & ChunkMask; - const size_t bit = offset / CellBytesPerMarkBit + size_t(colorBit); - size_t word = bit / MarkBitmapWordBits - FirstArenaAdjustmentWords; - MOZ_ASSERT(word < WordCount); - *wordp = &bitmap[word]; - *maskp = uintptr_t(1) << (bit % MarkBitmapWordBits); -} - namespace detail { -static MOZ_ALWAYS_INLINE ChunkBase* GetCellChunkBase(const Cell* cell) { - MOZ_ASSERT(cell); - auto* chunk = reinterpret_cast(uintptr_t(cell) & ~ChunkMask); +// `addr` must be an address within GC-controlled memory. Note that it cannot +// point just past GC-controlled memory. +static MOZ_ALWAYS_INLINE ChunkBase* GetGCAddressChunkBase(const void* addr) { + MOZ_ASSERT(addr); + auto* chunk = reinterpret_cast(uintptr_t(addr) & ~ChunkMask); MOZ_ASSERT(chunk->runtime); MOZ_ASSERT(chunk->kind != ChunkKind::Invalid); return chunk; } -static MOZ_ALWAYS_INLINE TenuredChunkBase* GetCellChunkBase( +static MOZ_ALWAYS_INLINE ChunkBase* GetCellChunkBase(const Cell* cell) { + return GetGCAddressChunkBase(cell); +} + +static MOZ_ALWAYS_INLINE ArenaChunkBase* GetCellChunkBase( const TenuredCell* cell) { MOZ_ASSERT(cell); - auto* chunk = - reinterpret_cast(uintptr_t(cell) & ~ChunkMask); + auto* chunk = reinterpret_cast(uintptr_t(cell) & ~ChunkMask); MOZ_ASSERT(chunk->runtime); - MOZ_ASSERT(chunk->kind == ChunkKind::TenuredHeap); + MOZ_ASSERT(chunk->kind == ChunkKind::TenuredArenas); return chunk; } @@ -580,17 +621,11 @@ static MOZ_ALWAYS_INLINE JS::Zone* GetTenuredGCThingZone(const void* ptr) { static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedBlack( const TenuredCell* cell) { - // Return true if BlackBit is set. - MOZ_ASSERT(cell); MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); - MarkBitmapWord* blackWord; - uintptr_t blackMask; - TenuredChunkBase* chunk = GetCellChunkBase(cell); - chunk->markBits.getMarkWordAndMask(cell, js::gc::ColorBit::BlackBit, - &blackWord, &blackMask); - return *blackWord & blackMask; + ArenaChunkBase* chunk = GetCellChunkBase(cell); + return chunk->markBits.isMarkedBlack(cell); } static MOZ_ALWAYS_INLINE bool NonBlackCellIsMarkedGray( @@ -601,16 +636,15 @@ static MOZ_ALWAYS_INLINE bool NonBlackCellIsMarkedGray( MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); MOZ_ASSERT(!TenuredCellIsMarkedBlack(cell)); - MarkBitmapWord* grayWord; - uintptr_t grayMask; - TenuredChunkBase* chunk = GetCellChunkBase(cell); - chunk->markBits.getMarkWordAndMask(cell, js::gc::ColorBit::GrayOrBlackBit, - &grayWord, &grayMask); - return *grayWord & grayMask; + ArenaChunkBase* chunk = GetCellChunkBase(cell); + return chunk->markBits.markBit(cell, ColorBit::GrayOrBlackBit); } static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedGray(const TenuredCell* cell) { - return !TenuredCellIsMarkedBlack(cell) && NonBlackCellIsMarkedGray(cell); + MOZ_ASSERT(cell); + MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); + ArenaChunkBase* chunk = GetCellChunkBase(cell); + return chunk->markBits.isMarkedGray(cell); } static MOZ_ALWAYS_INLINE bool CellIsMarkedGray(const Cell* cell) { @@ -631,15 +665,15 @@ extern JS_PUBLIC_API void AssertCellIsNotGray(const Cell* cell); extern JS_PUBLIC_API bool ObjectIsMarkedBlack(const JSObject* obj); #endif -MOZ_ALWAYS_INLINE bool CellHasStoreBuffer(const Cell* cell) { - return GetCellChunkBase(cell)->storeBuffer; +MOZ_ALWAYS_INLINE bool ChunkPtrHasStoreBuffer(const void* ptr) { + return GetGCAddressChunkBase(ptr)->storeBuffer; } } /* namespace detail */ MOZ_ALWAYS_INLINE bool IsInsideNursery(const Cell* cell) { MOZ_ASSERT(cell); - return detail::CellHasStoreBuffer(cell); + return detail::ChunkPtrHasStoreBuffer(cell); } MOZ_ALWAYS_INLINE bool IsInsideNursery(const TenuredCell* cell) { @@ -749,14 +783,6 @@ static MOZ_ALWAYS_INLINE bool GCThingIsMarkedGrayInCC(GCCellPtr thing) { extern JS_PUBLIC_API JS::TraceKind GCThingTraceKind(void* thing); -extern JS_PUBLIC_API void EnableNurseryStrings(JSContext* cx); - -extern JS_PUBLIC_API void DisableNurseryStrings(JSContext* cx); - -extern JS_PUBLIC_API void EnableNurseryBigInts(JSContext* cx); - -extern JS_PUBLIC_API void DisableNurseryBigInts(JSContext* cx); - /* * Returns true when writes to GC thing pointers (and reads from weak pointers) * must call an incremental barrier. This is generally only true when running @@ -860,6 +886,16 @@ static MOZ_ALWAYS_INLINE bool EdgeNeedsSweepUnbarriered(JSObject** objp) { return EdgeNeedsSweepUnbarrieredSlow(objp); } +/* + * Sample data about internally mapped memory. This includes all GC heap + * allocations (and excludes js_alloc allocations). + */ +struct ProfilerMemoryCounts { + size_t bytes = 0; + uint64_t operations = 0; +}; +JS_PUBLIC_API ProfilerMemoryCounts GetProfilerMemoryCounts(); + } // namespace gc } // namespace js diff --git a/src/third_party/mozjs/extract/js/public/HelperThreadAPI.h b/src/third_party/mozjs/extract/js/public/HelperThreadAPI.h index 646da69925e..36f6a341c60 100644 --- a/src/third_party/mozjs/extract/js/public/HelperThreadAPI.h +++ b/src/third_party/mozjs/extract/js/public/HelperThreadAPI.h @@ -32,6 +32,10 @@ extern JS_PUBLIC_API void SetHelperThreadTaskCallback( // Function to call from external thread pool to run a helper thread task. extern JS_PUBLIC_API void RunHelperThreadTask(HelperThreadTask* task); +// Function to get the name of the helper thread task. +extern JS_PUBLIC_API const char* GetHelperThreadTaskName( + HelperThreadTask* task); + } // namespace JS #endif // js_HelperThreadAPI_h diff --git a/src/third_party/mozjs/extract/js/public/Id.h b/src/third_party/mozjs/extract/js/public/Id.h index 087f9e61c9a..60ea2c4b49f 100644 --- a/src/third_party/mozjs/extract/js/public/Id.h +++ b/src/third_party/mozjs/extract/js/public/Id.h @@ -199,7 +199,7 @@ class PropertyKey { MOZ_ALWAYS_INLINE bool isAtom(JSAtom* atom) const { MOZ_ASSERT(PropertyKey::isNonIntAtom(atom)); - return isAtom() && toAtom() == atom; + return *this == NonIntAtom(atom); } MOZ_ALWAYS_INLINE JSAtom* toAtom() const { @@ -292,6 +292,15 @@ struct BarrierMethods { } return nullptr; } + static void writeBarriers(jsid* idp, jsid prev, jsid next) { + if (prev.isString()) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev.toString())); + } + if (prev.isSymbol()) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev.toSymbol())); + } + postWriteBarrier(idp, prev, next); + } static void postWriteBarrier(jsid* idp, jsid prev, jsid next) { MOZ_ASSERT_IF(next.isString(), !gc::IsInsideNursery(next.toString())); } diff --git a/src/third_party/mozjs/extract/js/public/Initialization.h b/src/third_party/mozjs/extract/js/public/Initialization.h index 46715b6c4f1..d8ad67e413a 100644 --- a/src/third_party/mozjs/extract/js/public/Initialization.h +++ b/src/third_party/mozjs/extract/js/public/Initialization.h @@ -118,7 +118,6 @@ inline bool JS_IsInitialized(void) { namespace JS { // Reference to a sequence of bytes. -// TODO: This type should be Span (Bug 1709135) using SelfHostedCache = mozilla::Span; // Callback function used to copy the SelfHosted content to memory or to disk. diff --git a/src/third_party/mozjs/extract/js/public/JSON.h b/src/third_party/mozjs/extract/js/public/JSON.h index feef53f755e..2cf546e9c8d 100644 --- a/src/third_party/mozjs/extract/js/public/JSON.h +++ b/src/third_party/mozjs/extract/js/public/JSON.h @@ -26,12 +26,19 @@ using JSONWriteCallback = bool (*)(const char16_t* buf, uint32_t len, * * In cases where JSON.stringify would return undefined, this function calls * |callback| with the string "null". + * + * If a length hint is passed, space will be reserved for at least that many + * characters. */ extern JS_PUBLIC_API bool JS_Stringify(JSContext* cx, JS::MutableHandle value, JS::Handle replacer, JS::Handle space, JSONWriteCallback callback, void* data); +extern JS_PUBLIC_API bool JS_StringifyWithLengthHint( + JSContext* cx, JS::MutableHandle value, + JS::Handle replacer, JS::Handle space, + JSONWriteCallback callback, void* data, size_t lengthHint); namespace JS { diff --git a/src/third_party/mozjs/extract/js/public/JitCodeAPI.h b/src/third_party/mozjs/extract/js/public/JitCodeAPI.h deleted file mode 100644 index e1cdad20836..00000000000 --- a/src/third_party/mozjs/extract/js/public/JitCodeAPI.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* SpiderMonkey API for obtaining JitCode information. */ - -#ifndef js_JitCodeAPI_h -#define js_JitCodeAPI_h - -#include "js/AllocPolicy.h" -#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin -#include "js/Initialization.h" -#include "js/Printf.h" -#include "js/Vector.h" - -namespace JS { - -enum class JitTier { Baseline, IC, Ion, Other }; - -class JitOpcodeDictionary { - typedef js::Vector StringVector; - - public: - JitOpcodeDictionary(); - - StringVector& GetBaselineDictionary() { return baselineDictionary; } - StringVector& GetIonDictionary() { return ionDictionary; } - StringVector& GetInlineCacheDictionary() { return icDictionary; } - - private: - StringVector baselineDictionary; - StringVector icDictionary; - StringVector ionDictionary; -}; - -struct JitCodeSourceInfo { - UniqueChars filename; - uint32_t offset = 0; - - // Line number (1-origin). - uint32_t lineno = 0; - // Column number in UTF-16 code units. - JS::LimitedColumnNumberOneOrigin colno; -}; - -struct JitCodeIRInfo { - uint32_t offset = 0; - uint32_t opcode = 0; - UniqueChars str; -}; - -typedef js::Vector - SourceInfoVector; -typedef js::Vector IRInfoVector; - -struct JitCodeRecord { - UniqueChars functionName; - uint64_t code_addr = 0; - uint32_t instructionSize = 0; - JitTier tier = JitTier::Other; - - SourceInfoVector sourceInfo; - IRInfoVector irInfo; -}; - -class JitCodeIterator { - void getDataForIndex(size_t iteratorIndex); - - public: - JitCodeIterator(); - ~JitCodeIterator(); - - void operator++(int) { - iteratorIndex++; - getDataForIndex(iteratorIndex); - } - - explicit operator bool() const { return data != nullptr; } - - SourceInfoVector& sourceData() { return data->sourceInfo; } - - IRInfoVector& irData() { return data->irInfo; } - - const char* functionName() const { return data->functionName.get(); } - uint64_t code_addr() const { return data->code_addr; } - uint32_t instructionSize() { return data->instructionSize; } - JitTier jit_tier() const { return data->tier; } - - private: - JitCodeRecord* data = nullptr; - size_t iteratorIndex = 0; -}; - -} // namespace JS - -#endif /* js_JitCodeAPI_h */ diff --git a/src/third_party/mozjs/extract/js/public/MapAndSet.h b/src/third_party/mozjs/extract/js/public/MapAndSet.h index 754379dc820..43530bbb729 100644 --- a/src/third_party/mozjs/extract/js/public/MapAndSet.h +++ b/src/third_party/mozjs/extract/js/public/MapAndSet.h @@ -31,6 +31,12 @@ extern JS_PUBLIC_API bool MapHas(JSContext* cx, HandleObject obj, extern JS_PUBLIC_API bool MapSet(JSContext* cx, HandleObject obj, HandleValue key, HandleValue val); +#ifdef NIGHTLY_BUILD +extern JS_PUBLIC_API bool MapGetOrInsert(JSContext* cx, HandleObject obj, + HandleValue key, HandleValue val, + MutableHandleValue rval); +#endif // #ifdef NIGHTLY_BUILD + extern JS_PUBLIC_API bool MapDelete(JSContext* cx, HandleObject obj, HandleValue key, bool* rval); diff --git a/src/third_party/mozjs/extract/js/public/MemoryMetrics.h b/src/third_party/mozjs/extract/js/public/MemoryMetrics.h index 305ab1feb0a..289558992d9 100644 --- a/src/third_party/mozjs/extract/js/public/MemoryMetrics.h +++ b/src/third_party/mozjs/extract/js/public/MemoryMetrics.h @@ -181,18 +181,17 @@ struct InefficientNonFlatteningStringHashPolicy { namespace JS { struct ClassInfo { -#define FOR_EACH_SIZE(MACRO) \ - MACRO(Objects, GCHeapUsed, objectsGCHeap) \ - MACRO(Objects, MallocHeap, objectsMallocHeapSlots) \ - MACRO(Objects, MallocHeap, objectsMallocHeapElementsNormal) \ - MACRO(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \ - MACRO(Objects, MallocHeap, objectsMallocHeapGlobalData) \ - MACRO(Objects, MallocHeap, objectsMallocHeapGlobalVarNamesSet) \ - MACRO(Objects, MallocHeap, objectsMallocHeapMisc) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsNormal) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsShared) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsWasm) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsWasmShared) \ +#define FOR_EACH_SIZE(MACRO) \ + MACRO(Objects, GCHeapUsed, objectsGCHeap) \ + MACRO(Objects, MallocHeap, objectsMallocHeapSlots) \ + MACRO(Objects, MallocHeap, objectsMallocHeapElementsNormal) \ + MACRO(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \ + MACRO(Objects, MallocHeap, objectsMallocHeapGlobalData) \ + MACRO(Objects, MallocHeap, objectsMallocHeapMisc) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsNormal) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsShared) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsWasm) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsWasmShared) \ MACRO(Objects, NonHeap, objectsNonHeapCodeWasm) ClassInfo() = default; @@ -554,7 +553,8 @@ struct UnusedGCThingSizes { MACRO(Other, GCHeapUnused, bigInt) \ MACRO(Other, GCHeapUnused, jitcode) \ MACRO(Other, GCHeapUnused, scope) \ - MACRO(Other, GCHeapUnused, regExpShared) + MACRO(Other, GCHeapUnused, regExpShared) \ + MACRO(Other, GCHeapUnused, smallBuffer) UnusedGCThingSizes() = default; UnusedGCThingSizes(UnusedGCThingSizes&& other) = default; @@ -597,6 +597,9 @@ struct UnusedGCThingSizes { case JS::TraceKind::RegExpShared: regExpShared += n; break; + case JS::TraceKind::SmallBuffer: + smallBuffer += n; + break; default: MOZ_CRASH("Bad trace kind for UnusedGCThingSizes"); } @@ -625,6 +628,36 @@ struct UnusedGCThingSizes { #undef FOR_EACH_SIZE }; +struct GCBufferStats { +#define FOR_EACH_SIZE(MACRO) \ + MACRO(Other, MallocHeap, usedBytes) \ + MACRO(Other, MallocHeap, freeBytes) \ + MACRO(Other, MallocHeap, adminBytes) + + GCBufferStats() = default; + GCBufferStats(GCBufferStats&& other) = default; + + void addSizes(const GCBufferStats& other) { FOR_EACH_SIZE(ADD_OTHER_SIZE); } + + size_t totalSize() const { + size_t n = 0; + FOR_EACH_SIZE(ADD_SIZE_TO_N); + return n; + } + + void addToTabSizes(JS::TabSizes* sizes) const { + FOR_EACH_SIZE(ADD_TO_TAB_SIZES); + } + + void addToServoSizes(JS::ServoSizes* sizes) const { + FOR_EACH_SIZE(ADD_TO_SERVO_SIZES); + } + + FOR_EACH_SIZE(DECL_SIZE_ZERO); + +#undef FOR_EACH_SIZE +}; + struct ZoneStats { #define FOR_EACH_SIZE(MACRO) \ MACRO(Other, GCHeapUsed, symbolsGCHeap) \ @@ -642,6 +675,7 @@ struct ZoneStats { MACRO(Other, MallocHeap, scopesMallocHeap) \ MACRO(Other, GCHeapUsed, regExpSharedsGCHeap) \ MACRO(Other, MallocHeap, regExpSharedsMallocHeap) \ + MACRO(Other, GCHeapUsed, smallBuffersGCHeap) \ MACRO(Other, MallocHeap, zoneObject) \ MACRO(Other, MallocHeap, regexpZone) \ MACRO(Other, MallocHeap, jitZone) \ @@ -662,6 +696,7 @@ struct ZoneStats { void addSizes(const ZoneStats& other) { MOZ_ASSERT(isTotals); FOR_EACH_SIZE(ADD_OTHER_SIZE); + gcBuffers.addSizes(other.gcBuffers); unusedGCThings.addSizes(other.unusedGCThings); stringInfo.add(other.stringInfo); shapeInfo.add(other.shapeInfo); @@ -679,6 +714,7 @@ struct ZoneStats { void addToTabSizes(JS::TabSizes* sizes) const { MOZ_ASSERT(isTotals); FOR_EACH_SIZE(ADD_TO_TAB_SIZES); + gcBuffers.addToTabSizes(sizes); unusedGCThings.addToTabSizes(sizes); stringInfo.addToTabSizes(sizes); shapeInfo.addToTabSizes(sizes); @@ -687,6 +723,7 @@ struct ZoneStats { void addToServoSizes(JS::ServoSizes* sizes) const { MOZ_ASSERT(isTotals); FOR_EACH_SIZE(ADD_TO_SERVO_SIZES); + gcBuffers.addToServoSizes(sizes); unusedGCThings.addToServoSizes(sizes); stringInfo.addToServoSizes(sizes); shapeInfo.addToServoSizes(sizes); @@ -695,6 +732,8 @@ struct ZoneStats { FOR_EACH_SIZE(DECL_SIZE_ZERO); + GCBufferStats gcBuffers; + // These string measurements are initially for all strings. At the end, // if the measurement granularity is FineGrained, we subtract the // measurements of the notable script sources and move them into diff --git a/src/third_party/mozjs/extract/js/public/Modules.h b/src/third_party/mozjs/extract/js/public/Modules.h index 4a8d45acb07..73f8586ae8d 100644 --- a/src/third_party/mozjs/extract/js/public/Modules.h +++ b/src/third_party/mozjs/extract/js/public/Modules.h @@ -36,7 +36,15 @@ union Utf8Unit; namespace JS { -enum class ModuleType : uint32_t { Unknown = 0, JavaScript, JSON }; +// This enum is used to index into an array, and we assume that we have +// sequential numbers starting at zero for the unknown type. +enum class ModuleType : uint32_t { + Unknown = 0, + JavaScript, + JSON, + + Limit = JSON, +}; /** * The HostResolveImportedModule hook. @@ -179,6 +187,15 @@ extern JS_PUBLIC_API JSObject* CompileJsonModule( JSContext* cx, const ReadOnlyCompileOptions& options, SourceText& srcBuf); +/** + * Parse the given source buffer as a JSON module in the scope of the current + * global of cx and return a synthetic module record. An error is reported if a + * UTF-8 encoding error is encountered. + */ +extern JS_PUBLIC_API JSObject* CompileJsonModule( + JSContext* cx, const ReadOnlyCompileOptions& options, + SourceText& srcBuf); + /** * Set a private value associated with a source text module record. */ @@ -197,6 +214,11 @@ extern JS_PUBLIC_API void ClearModulePrivate(JSObject* module); */ extern JS_PUBLIC_API Value GetModulePrivate(JSObject* module); +/** + * Checks if the given module is a cyclic module. + */ +extern JS_PUBLIC_API bool IsCyclicModule(JSObject* module); + /* * Perform the ModuleLink operation on the given source text module record. * @@ -267,16 +289,28 @@ extern JS_PUBLIC_API void GetRequestedModuleSourcePos( JSContext* cx, Handle moduleRecord, uint32_t index, uint32_t* lineNumber, JS::ColumnNumberOneOrigin* columnNumber); +/* + * Get the module type of a requested module. + */ +extern JS_PUBLIC_API ModuleType GetRequestedModuleType( + JSContext* cx, Handle moduleRecord, uint32_t index); + /* * Get the top-level script for a module which has not yet been executed. */ extern JS_PUBLIC_API JSScript* GetModuleScript(Handle moduleRecord); extern JS_PUBLIC_API JSObject* CreateModuleRequest( - JSContext* cx, Handle specifierArg); + JSContext* cx, Handle specifierArg, ModuleType moduleType); extern JS_PUBLIC_API JSString* GetModuleRequestSpecifier( JSContext* cx, Handle moduleRequestArg); +/* + * Get the module type of the specified module request. + */ +extern JS_PUBLIC_API ModuleType +GetModuleRequestType(JSContext* cx, Handle moduleRequestArg); + /* * Get the module record for a module script. */ diff --git a/src/third_party/mozjs/extract/js/public/NativeStackLimits.h b/src/third_party/mozjs/extract/js/public/NativeStackLimits.h new file mode 100644 index 00000000000..8b787fa3761 --- /dev/null +++ b/src/third_party/mozjs/extract/js/public/NativeStackLimits.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_public_NativeStackLimit_h +#define js_public_NativeStackLimit_h + +#include "mozilla/Assertions.h" // MOZ_ASSERT + +#include // size_t +#include // uint32_t, uintptr_t, UINTPTR_MAX +#include // std::move + +namespace JS { + +using NativeStackSize = size_t; + +using NativeStackBase = uintptr_t; + +using NativeStackLimit = uintptr_t; + +#if JS_STACK_GROWTH_DIRECTION > 0 +constexpr NativeStackLimit NativeStackLimitMin = 0; +constexpr NativeStackLimit NativeStackLimitMax = UINTPTR_MAX; +#else +constexpr NativeStackLimit NativeStackLimitMin = UINTPTR_MAX; +constexpr NativeStackLimit NativeStackLimitMax = 0; +#endif + +#ifdef __wasi__ +// We build with the "stack-first" wasm-ld option, so the stack grows downward +// toward zero. Let's set a limit just a bit above this so that we catch an +// overflow before a Wasm trap occurs. +constexpr NativeStackLimit WASINativeStackLimit = 1024; +#endif // __wasi__ + +inline NativeStackLimit GetNativeStackLimit(NativeStackBase base, + NativeStackSize size) { +#if JS_STACK_GROWTH_DIRECTION > 0 + MOZ_ASSERT(base <= size_t(-1) - size); + return base + size - 1; +#else // stack grows up + MOZ_ASSERT(base >= size); + return base - (size - 1); +#endif // stack grows down +} + +} // namespace JS + +#endif /* js_public_NativeStackLimit_h */ diff --git a/src/third_party/mozjs/extract/js/public/ObjectWithStashedPointer.h b/src/third_party/mozjs/extract/js/public/ObjectWithStashedPointer.h new file mode 100644 index 00000000000..6769c0b0f69 --- /dev/null +++ b/src/third_party/mozjs/extract/js/public/ObjectWithStashedPointer.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_public_ObjectWithStashedPointer_h +#define js_public_ObjectWithStashedPointer_h + +#include "jstypes.h" // JS_PUBLIC_API + +#include "js/RootingAPI.h" // JS::Handle + +struct JS_PUBLIC_API JSContext; +class JS_PUBLIC_API JSObject; + +namespace JS { + +namespace detail { +using UntypedFreeFunction = void (*)(void*); + +extern JS_PUBLIC_API JSObject* NewObjectWithUntypedStashedPointer( + JSContext* cx, void* ptr, UntypedFreeFunction freeFunc); + +extern JS_PUBLIC_API void* ObjectGetUntypedStashedPointer(JSContext* cx, + JSObject* obj); +} // namespace detail + +/** + * Convenience function for creating a JS object that has an embedder C++ + * pointer stashed in it. The JS object assumes ownership of the pointer. When + * the JS object is finalized, freeFunc will be called on the pointer to free + * it. + * + * The pointer is not known to the garbage collector, and not traced. If it + * points to a GC thing, the embedder is responsible for tracing it manually. + * + * freeFunc must not call any JSAPI functions that could cause a garbage + * collection. + */ +template +inline JSObject* NewObjectWithStashedPointer(JSContext* cx, T* ptr, + F freeFunc) { + using FreeFunction = void (*)(T*); + static_assert(std::is_convertible_v, + "free function is not of a compatible type"); + return detail::NewObjectWithUntypedStashedPointer( + cx, ptr, + reinterpret_cast( + static_cast(freeFunc))); +} + +/** + * As above, but without a free function for the pointer. + */ +template +inline JSObject* NewObjectWithStashedPointer(JSContext* cx, T* ptr) { + return detail::NewObjectWithUntypedStashedPointer(cx, ptr, nullptr); +} + +/** + * Retrieve the stashed pointer from an object created using + * NewObjectWithStashedPointer(). + */ +template +inline T* ObjectGetStashedPointer(JSContext* cx, JSObject* obj) { + return static_cast(detail::ObjectGetUntypedStashedPointer(cx, obj)); +} + +} // namespace JS + +#endif // js_public_ObjectWithStashedPointer_h diff --git a/src/third_party/mozjs/extract/js/public/Prefs.h b/src/third_party/mozjs/extract/js/public/Prefs.h index 60d67ff7cd9..2de11337c9c 100644 --- a/src/third_party/mozjs/extract/js/public/Prefs.h +++ b/src/third_party/mozjs/extract/js/public/Prefs.h @@ -121,26 +121,6 @@ class Prefs { }; -/** - * Specification for whether weak refs should be enabled and if so whether the - * FinalizationRegistry.cleanupSome method should be present. - */ -enum class WeakRefSpecifier { - Disabled, - EnabledWithCleanupSome, - EnabledWithoutCleanupSome -}; - -inline WeakRefSpecifier GetWeakRefsEnabled() { - if (!Prefs::weakrefs()) { - return WeakRefSpecifier::Disabled; - } - if (Prefs::experimental_weakrefs_expose_cleanupSome()) { - return WeakRefSpecifier::EnabledWithCleanupSome; - } - return WeakRefSpecifier::EnabledWithoutCleanupSome; -} - }; // namespace JS #endif /* js_Prefs_h */ diff --git a/src/third_party/mozjs/extract/js/public/Principals.h b/src/third_party/mozjs/extract/js/public/Principals.h index 609b1ecff68..bce823b3062 100644 --- a/src/third_party/mozjs/extract/js/public/Principals.h +++ b/src/third_party/mozjs/extract/js/public/Principals.h @@ -26,12 +26,21 @@ struct JSPrincipals { #ifdef JS_DEBUG /* A helper to facilitate principals debugging. */ - uint32_t debugToken; + uint32_t debugToken = 0; #endif JSPrincipals() = default; - void setDebugToken(uint32_t token) { + struct RefCount { + const int32_t value; + constexpr explicit RefCount(int32_t value) : value(value) {} + RefCount(const RefCount&) = delete; + }; + /* Initialize a JSPrincipals with the given refcount in a constexpr-compatible + * way. */ + explicit constexpr JSPrincipals(RefCount c) : refcount{c.value} {} + + void setDebugToken(int32_t token) { #ifdef JS_DEBUG debugToken = token; #endif @@ -68,23 +77,54 @@ typedef bool (*JSSubsumesOp)(JSPrincipals* first, JSPrincipals* second); namespace JS { enum class RuntimeCode { JS, WASM }; +enum class CompilationType { DirectEval, IndirectEval, Function, Undefined }; } // namespace JS /* * Used to check if a CSP instance wants to disable eval() and friends. * See JSContext::isRuntimeCodeGenEnabled() in vm/JSContext.cpp. * - * `code` is the JavaScript source code passed to eval/Function, but nullptr - * for Wasm. + * codeString, compilationType, parameterStrings, bodyString, parameterArgs, + * and bodyArg are defined in the "Dynamic Code Brand Checks" spec + * (see https://tc39.es/proposal-dynamic-code-brand-checks). * - * Returning `false` from this callback will prevent the execution/compilation - * of the code. + * An Undefined compilationType is used for cases that are not covered by that + * spec and unused parameters are null/empty. Currently, this includes Wasm + * (only check if compilation is enabled) and ShadowRealmEval (only check + * codeString). + * + * `outCanCompileStrings` is set to false if this callback prevents the + * execution/compilation of the code and to true otherwise. + * + * Return false on failure, true on success. The |outCanCompileStrings| + * parameter should not be modified in case of failure. */ -typedef bool (*JSCSPEvalChecker)(JSContext* cx, JS::RuntimeCode kind, - JS::HandleString code); +typedef bool (*JSCSPEvalChecker)( + JSContext* cx, JS::RuntimeCode kind, JS::Handle codeString, + JS::CompilationType compilationType, + JS::Handle> parameterStrings, + JS::Handle bodyString, + JS::Handle> parameterArgs, + JS::Handle bodyArg, bool* outCanCompileStrings); + +/* + * Provide a string of code from an Object argument, to be used by eval. + * See JSContext::getCodeForEval() in vm/JSContext.cpp as well as + * https://tc39.es/proposal-dynamic-code-brand-checks/#sec-hostgetcodeforeval + * + * `code` is the JavaScript object passed by the user. + * `outCode` is the JavaScript string to be actually executed, with nullptr + * meaning NO-CODE. + * + * Return false on failure, true on success. The |outCode| parameter should not + * be modified in case of failure. + */ +typedef bool (*JSCodeForEvalOp)(JSContext* cx, JS::HandleObject code, + JS::MutableHandle outCode); struct JSSecurityCallbacks { JSCSPEvalChecker contentSecurityPolicyAllows; + JSCodeForEvalOp codeForEvalGets; JSSubsumesOp subsumes; }; diff --git a/src/third_party/mozjs/extract/js/public/Printer.h b/src/third_party/mozjs/extract/js/public/Printer.h index 644ffa9176c..e7a651c024b 100644 --- a/src/third_party/mozjs/extract/js/public/Printer.h +++ b/src/third_party/mozjs/extract/js/public/Printer.h @@ -10,6 +10,7 @@ #include "mozilla/Attributes.h" #include "mozilla/glue/Debug.h" #include "mozilla/Range.h" +#include "mozilla/Vector.h" #include #include @@ -139,7 +140,7 @@ class LifoAlloc; // of chunks allocated with a LifoAlloc. class JS_PUBLIC_API GenericPrinter { protected: - bool hadOOM_; // whether reportOutOfMemory() has been called. + bool hadOOM_; // whether setPendingOutOfMemory() has been called. constexpr GenericPrinter() : hadOOM_(false) {} @@ -151,6 +152,7 @@ class JS_PUBLIC_API GenericPrinter { // still report any of the previous errors. virtual void put(const char* s, size_t len) = 0; inline void put(const char* s) { put(s, strlen(s)); } + inline void put(mozilla::Span s) { put(s.data(), s.size()); }; // Put a mozilla::Span / mozilla::Range of Latin1Char or char16_t characters // in the output. @@ -202,11 +204,11 @@ class JS_PUBLIC_API GenericPrinter { virtual size_t index() const { return 0; } // In some printers, this ensure that the content is fully written. - virtual void flush() { /* Do nothing */ - } + virtual void flush() { /* Do nothing */ } - // Report that a string operation failed to get the memory it requested. - virtual void reportOutOfMemory(); + // Set a flag that a string operation failed to get the memory it requested. + // The pending out of memory error should be handled by the consumer. + virtual void setPendingOutOfMemory(); // Return true if this Sprinter ran out of memory. virtual bool hadOutOfMemory() const { return hadOOM_; } @@ -469,7 +471,7 @@ class JS_PUBLIC_API EscapePrinter final : public GenericPrinter { } size_t index() const final { return out.index(); } void flush() final { out.flush(); } - void reportOutOfMemory() final { out.reportOutOfMemory(); } + void setPendingOutOfMemory() final { out.setPendingOutOfMemory(); } bool hadOutOfMemory() const final { return out.hadOutOfMemory(); } }; @@ -490,43 +492,118 @@ class JS_PUBLIC_API StringEscape { void convertInto(GenericPrinter& out, char16_t c); }; -// A GenericPrinter that formats everything at a nested indentation level. -class JS_PUBLIC_API IndentedPrinter final : public GenericPrinter { +class JS_PUBLIC_API WATStringEscape { + public: + bool isSafeChar(char16_t c); + void convertInto(GenericPrinter& out, char16_t c); +}; + +// A GenericPrinter that can format its output in a structured way, with nice +// formatting. +// +// Suppose you want to print wasm structs, and you want to change the +// presentation depending on the number of fields: +// +// (struct) +// (struct (field i32)) +// (struct +// (field i32) +// (field i64) +// ) +// +// All three of these can be handled identically with quite straightforward +// code: +// +// out.printf("(struct"); +// { +// StructuredPrinter::Scope _(out); +// +// for (auto field : fields) { +// out.brk(" ", "\n"); +// out.printf("(field "); +// DumpFieldType(field.type, out); +// out.printf(")"); +// } +// out.brk("", "\n"); +// +// if (fields.length() > 1) { +// out.expand(); +// } +// } +// out.printf(")"); +// +// The `brk` method can be used to emit one of two "break" characters depending +// on whether the output is "expanded" or "collapsed". The decision about which +// style to emit is made later, by conditionally calling `out.expand()`. +// Additionally, the use of `StructuredPrinter::Scope` ensures that the struct +// fields are indented *if* the output is expanded. +// +// Newlines may still be printed at any time. Newlines will force the current +// scope to be expanded, along with any parent scopes. +class JS_PUBLIC_API StructuredPrinter final : public GenericPrinter { GenericPrinter& out_; - // The number of indents to insert at the beginning of each line. - uint32_t indentLevel_; + // The number of spaces to insert for each indent. - uint32_t indentAmount_; - // Whether we have seen a line ending and should insert an indent at the - // next line fragment. + int indentAmount_; bool pendingIndent_; - // Put an indent to `out_` - void putIndent(); - // Put `s` to `out_`, inserting an indent if we need to - void putWithMaybeIndent(const char* s, size_t len); + // The index of the last expanded scope (or -1 if all scopes are collapsed). + int expandedDepth_ = -1; - public: - explicit IndentedPrinter(GenericPrinter& out, uint32_t indentLevel = 0, - uint32_t indentAmount = 2) - : out_(out), - indentLevel_(indentLevel), - indentAmount_(indentAmount), - pendingIndent_(false) {} - - // Automatically insert and remove and indent for a scope - class AutoIndent { - IndentedPrinter& printer_; - - public: - explicit AutoIndent(IndentedPrinter& printer) : printer_(printer) { - printer_.setIndentLevel(printer_.indentLevel() + 1); - } - ~AutoIndent() { printer_.setIndentLevel(printer_.indentLevel() - 1); } + struct Break { + uint32_t bufferPos; + bool isCollapsed; + const char* collapsed; + const char* expanded; }; - uint32_t indentLevel() const { return indentLevel_; } - void setIndentLevel(uint32_t indentLevel) { indentLevel_ = indentLevel; } + struct ScopeInfo { + uint32_t startPos; + int indent; + }; + + // Content is buffered while in collapsed mode in case it gets expanded later. + mozilla::Vector buffer_; + // Info about break characters in the buffer. + // Cleared when the buffer is cleared. + mozilla::Vector breaks_; + // The stack of scopes maintained by the printer. + mozilla::Vector scopes_; + + int scopeDepth() { return int(scopes_.length()) - 1; } + + void putIndent(int level = -1); + void putBreak(const Break& brk); + void putWithMaybeIndent(const char* s, size_t len, int level = -1); + + public: + explicit StructuredPrinter(GenericPrinter& out, int indentAmount = 2) + : out_(out), indentAmount_(indentAmount) { + pushScope(); + } + ~StructuredPrinter() { + popScope(); + flush(); + } + + void pushScope(); + void popScope(); + + void brk(const char* collapsed, const char* expanded); + void expand(); + bool isExpanded(); + + void flush() override; + + class Scope { + StructuredPrinter& printer_; + + public: + explicit Scope(StructuredPrinter& printer) : printer_(printer) { + printer_.pushScope(); + } + ~Scope() { printer_.popScope(); } + }; virtual void put(const char* s, size_t len) override; using GenericPrinter::put; // pick up |inline void put(const char* s);| diff --git a/src/third_party/mozjs/extract/js/public/ProfilingFrameIterator.h b/src/third_party/mozjs/extract/js/public/ProfilingFrameIterator.h index bbad2b1244c..6c5bf2c717d 100644 --- a/src/third_party/mozjs/extract/js/public/ProfilingFrameIterator.h +++ b/src/third_party/mozjs/extract/js/public/ProfilingFrameIterator.h @@ -55,7 +55,7 @@ class MOZ_NON_PARAM JS_PUBLIC_API ProfilingFrameIterator { void* endStackAddress_ = nullptr; Kind kind_; - static const unsigned StorageSpace = 8 * sizeof(void*); + static const unsigned StorageSpace = 9 * sizeof(void*); alignas(void*) unsigned char storage_[StorageSpace]; void* storage() { return storage_; } @@ -136,6 +136,8 @@ class MOZ_NON_PARAM JS_PUBLIC_API ProfilingFrameIterator { // - is weakly monotonically increasing (may be equal for successive frames) // - will compare greater than newer native and psuedo-stack frame addresses // and less than older native and psuedo-stack frame addresses + // The exception is at the point of stack switching between the main stack + // and a suspendable one (see WebAssembly JS Promise Integration proposal). void* stackAddress() const; enum FrameKind { diff --git a/src/third_party/mozjs/extract/js/public/ProfilingStack.h b/src/third_party/mozjs/extract/js/public/ProfilingStack.h index b9b96c27dc1..77f635189ef 100644 --- a/src/third_party/mozjs/extract/js/public/ProfilingStack.h +++ b/src/third_party/mozjs/extract/js/public/ProfilingStack.h @@ -8,6 +8,8 @@ #define js_ProfilingStack_h #include "mozilla/Atomics.h" +#include "mozilla/BaseProfilerMarkersPrerequisites.h" +#include "mozilla/TimeStamp.h" #include @@ -362,9 +364,11 @@ JS_PUBLIC_API void SetContextProfilingStack(JSContext* cx, JS_PUBLIC_API void EnableContextProfilingStack(JSContext* cx, bool enabled); -JS_PUBLIC_API void RegisterContextProfilingEventMarker(JSContext* cx, - void (*fn)(const char*, - const char*)); +JS_PUBLIC_API void RegisterContextProfilingEventMarker( + JSContext* cx, + void (*mark)(mozilla::MarkerCategory, const char*, const char*), + void (*interval)(mozilla::MarkerCategory, const char*, mozilla::TimeStamp, + const char*)); } // namespace js diff --git a/src/third_party/mozjs/extract/js/public/Promise.h b/src/third_party/mozjs/extract/js/public/Promise.h index 75bc7fd8370..e48e621560e 100644 --- a/src/third_party/mozjs/extract/js/public/Promise.h +++ b/src/third_party/mozjs/extract/js/public/Promise.h @@ -36,19 +36,36 @@ class JS_PUBLIC_API JobQueue { virtual ~JobQueue() = default; /** - * Ask the embedding for the incumbent global. + * Ask the embedding for the host defined data. * - * SpiderMonkey doesn't itself have a notion of incumbent globals as defined + * This is the step 5 in + * https://html.spec.whatwg.org/multipage/webappapis.html#hostmakejobcallback + * + * SpiderMonkey doesn't itself have a notion of host defined data as defined * by the HTML spec, so we need the embedding to provide this. See * dom/script/ScriptSettings.h for details. + * + * If the embedding has the host defined data, this method should return the + * host defined data via the `data` out parameter and return `true`. + * The object in the `data` out parameter can belong to any compartment. + * If the embedding doesn't need the host defined data, this method should + * set the `data` out parameter to `nullptr` and return `true`. + * If any error happens while generating the host defined data, this method + * should set a pending exception to `cx` and return `false`. */ - virtual JSObject* getIncumbentGlobal(JSContext* cx) = 0; + virtual bool getHostDefinedData(JSContext* cx, + JS::MutableHandle data) const = 0; /** * Enqueue a reaction job `job` for `promise`, which was allocated at - * `allocationSite`. Provide `incumbentGlobal` as the incumbent global for + * `allocationSite`. Provide `hostDefineData` as the host defined data for * the reaction job's execution. * + * The `hostDefinedData` value comes from `getHostDefinedData` method. + * The object is unwrapped, and it can belong to a different compartment + * than the current compartment. It can be `nullptr` if `getHostDefinedData` + * returns `nullptr`. + * * `promise` can be null if the promise is optimized out. * `promise` is guaranteed not to be optimized out if the promise has * non-default user-interaction flag. @@ -56,7 +73,7 @@ class JS_PUBLIC_API JobQueue { virtual bool enqueuePromiseJob(JSContext* cx, JS::HandleObject promise, JS::HandleObject job, JS::HandleObject allocationSite, - JS::HandleObject incumbentGlobal) = 0; + JS::HandleObject hostDefinedData) = 0; /** * Run all jobs in the queue. Running one job may enqueue others; continue to @@ -546,27 +563,65 @@ extern JS_PUBLIC_API JSObject* GetWaitForAllPromise( * on a JSContext thread when requested via DispatchToEventLoopCallback. */ class JS_PUBLIC_API Dispatchable { - protected: - // Dispatchables are created and destroyed by SpiderMonkey. - Dispatchable() = default; + public: + // Destruction of Dispatchables is public in order to be used with + // UniquePtrs. Their destruction by SpiderMonkey is enforced by + // ReleaseFailedTask. virtual ~Dispatchable() = default; - public: // ShuttingDown indicates that SpiderMonkey should abort async tasks to // expedite shutdown. enum MaybeShuttingDown { NotShuttingDown, ShuttingDown }; // Called by the embedding after DispatchToEventLoopCallback succeeds. + // Used to correctly release the unique ptr and call the run task. + static void Run(JSContext* cx, js::UniquePtr&& task, + MaybeShuttingDown maybeShuttingDown); + + // Used to correctly release the unique ptr. Relies on the + // OffThreadRuntimePromiseState to handle cleanup via iteration over the + // live() set. + static void ReleaseFailedTask(js::UniquePtr&& task); + + protected: + // Dispatchables are created exclusively by SpiderMonkey. + Dispatchable() = default; + + // These two methods must be implemented in order to correctly handle + // success and failure cases for the task. + + // Used to execute the task, run on the owning thread. + // A subclass should override this method to + // 1) execute the task as necessary and + // 2) delete the task. virtual void run(JSContext* cx, MaybeShuttingDown maybeShuttingDown) = 0; + + // Used to transfer the task back to the runtime if the embedding, upon + // taking ownership of the task, fails to dispatch and run it. This allows + // the runtime to delete the task during shutdown. This method can be called + // from any thread. + // Typically, this will be used with a UniquePtr like so: + // auto task = myTask.release(); + // task->transferToRuntime(); + virtual void transferToRuntime() = 0; }; /** - * Callback to dispatch a JS::Dispatchable to a JSContext's thread's event loop. + * Callbacks to dispatch a JS::Dispatchable to a JSContext's thread's event + * loop. * * The DispatchToEventLoopCallback set on a particular JSContext must accept * JS::Dispatchable instances and arrange for their `run` methods to be called * eventually on the JSContext's thread. This is used for cross-thread dispatch, - * so the callback itself must be safe to call from any thread. + * so the callback itself must be safe to call from any thread. It cannot + * trigger a GC. + * + * The DelayedDispatchToEventLoopCallback in addition takes a delay, and it + * must accept JS::Dispatchable instances and arrange for their `run` methods + * to be called after the delay on the JSContext's thread. + * The embeddings must have its own timeout manager to handle the delay. + * If a timeout manager is not available for given context, it should return + * false, optionally with a warning message printed. * * If the callback returns `true`, it must eventually run the given * Dispatchable; otherwise, SpiderMonkey may leak memory or hang. @@ -577,17 +632,21 @@ class JS_PUBLIC_API Dispatchable { * all subsequently submitted runnables as well. * * To establish a DispatchToEventLoopCallback, the embedding may either call - * InitDispatchToEventLoop to provide its own, or call js::UseInternalJobQueues + * InitDispatchsToEventLoop to provide its own, or call js::UseInternalJobQueues * to select a default implementation built into SpiderMonkey. This latter * depends on the embedding to call js::RunJobs on the JavaScript thread to * process queued Dispatchables at appropriate times. */ -typedef bool (*DispatchToEventLoopCallback)(void* closure, - Dispatchable* dispatchable); +typedef bool (*DispatchToEventLoopCallback)( + void* closure, js::UniquePtr&& dispatchable); -extern JS_PUBLIC_API void InitDispatchToEventLoop( - JSContext* cx, DispatchToEventLoopCallback callback, void* closure); +typedef bool (*DelayedDispatchToEventLoopCallback)( + void* closure, js::UniquePtr&& dispatchable, uint32_t delay); + +extern JS_PUBLIC_API void InitDispatchsToEventLoop( + JSContext* cx, DispatchToEventLoopCallback callback, + DelayedDispatchToEventLoopCallback delayedCallback, void* closure); /** * When a JSRuntime is destroyed it implicitly cancels all async tasks in diff --git a/src/third_party/mozjs/extract/js/public/PropertySpec.h b/src/third_party/mozjs/extract/js/public/PropertySpec.h index 0c37e598fbc..91782073c95 100644 --- a/src/third_party/mozjs/extract/js/public/PropertySpec.h +++ b/src/third_party/mozjs/extract/js/public/PropertySpec.h @@ -452,6 +452,6 @@ struct JSFunctionSpec { #define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \ JS_FNSPEC(::JS::SymbolCode::symbol, call, info, nargs, flags, selfHostedName) #define JS_FNSPEC(name, call, info, nargs, flags, selfHostedName) \ - { JSFunctionSpec::Name(name), {call, info}, nargs, flags, selfHostedName } + {JSFunctionSpec::Name(name), {call, info}, nargs, flags, selfHostedName} #endif // js_PropertySpec_h diff --git a/src/third_party/mozjs/extract/js/public/ProtoKey.h b/src/third_party/mozjs/extract/js/public/ProtoKey.h index fe8a191f06e..c335d5cb0e1 100644 --- a/src/third_party/mozjs/extract/js/public/ProtoKey.h +++ b/src/third_party/mozjs/extract/js/public/ProtoKey.h @@ -41,12 +41,6 @@ # define IF_INTL(REAL, IMAGINARY) IMAGINARY #endif -#ifdef JS_HAS_TEMPORAL_API -# define IF_TEMPORAL(REAL, IMAGINARY) REAL -#else -# define IF_TEMPORAL(REAL, IMAGINARY) IMAGINARY -#endif - #ifdef ENABLE_WASM_TYPE_REFLECTIONS # define IF_WASM_TYPE(REAL, IMAGINARY) REAL #else @@ -65,109 +59,112 @@ # define IF_NIGHTLY(REAL, IMAGINARY) IMAGINARY #endif -#define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL, REAL_IF_TEMPORAL, \ - REAL_IF_WASM_TYPE, REAL_IF_WASM_JSPI, \ - REAL_IF_NIGHTLY) \ - IMAGINARY(Null, dummy) \ - REAL(Object, OCLASP(Plain)) \ - REAL(Function, &FunctionClass) \ - IMAGINARY(BoundFunction, OCLASP(BoundFunction)) \ - REAL(Array, OCLASP(Array)) \ - REAL(Boolean, OCLASP(Boolean)) \ - REAL(JSON, CLASP(JSON)) \ - REAL(Date, OCLASP(Date)) \ - REAL(Math, CLASP(Math)) \ - REAL(Number, OCLASP(Number)) \ - REAL(String, OCLASP(String)) \ - REAL(RegExp, OCLASP(RegExp)) \ - REAL(Error, ERROR_CLASP(JSEXN_ERR)) \ - REAL(InternalError, ERROR_CLASP(JSEXN_INTERNALERR)) \ - REAL(AggregateError, ERROR_CLASP(JSEXN_AGGREGATEERR)) \ - REAL(EvalError, ERROR_CLASP(JSEXN_EVALERR)) \ - REAL(RangeError, ERROR_CLASP(JSEXN_RANGEERR)) \ - REAL(ReferenceError, ERROR_CLASP(JSEXN_REFERENCEERR)) \ - REAL(SyntaxError, ERROR_CLASP(JSEXN_SYNTAXERR)) \ - REAL(TypeError, ERROR_CLASP(JSEXN_TYPEERR)) \ - REAL(URIError, ERROR_CLASP(JSEXN_URIERR)) \ - REAL(DebuggeeWouldRun, ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \ - REAL(CompileError, ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \ - REAL(LinkError, ERROR_CLASP(JSEXN_WASMLINKERROR)) \ - REAL(RuntimeError, ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \ - REAL(ArrayBuffer, OCLASP(FixedLengthArrayBuffer)) \ - REAL(Int8Array, TYPED_ARRAY_CLASP(Int8)) \ - REAL(Uint8Array, TYPED_ARRAY_CLASP(Uint8)) \ - REAL(Int16Array, TYPED_ARRAY_CLASP(Int16)) \ - REAL(Uint16Array, TYPED_ARRAY_CLASP(Uint16)) \ - REAL(Int32Array, TYPED_ARRAY_CLASP(Int32)) \ - REAL(Uint32Array, TYPED_ARRAY_CLASP(Uint32)) \ - REAL(Float32Array, TYPED_ARRAY_CLASP(Float32)) \ - REAL(Float64Array, TYPED_ARRAY_CLASP(Float64)) \ - REAL(Uint8ClampedArray, TYPED_ARRAY_CLASP(Uint8Clamped)) \ - REAL(BigInt64Array, TYPED_ARRAY_CLASP(BigInt64)) \ - REAL(BigUint64Array, TYPED_ARRAY_CLASP(BigUint64)) \ - REAL_IF_NIGHTLY(Float16Array, TYPED_ARRAY_CLASP(Float16)) \ - REAL(BigInt, OCLASP(BigInt)) \ - REAL(Proxy, CLASP(Proxy)) \ - REAL(WeakMap, OCLASP(WeakMap)) \ - REAL(Map, OCLASP(Map)) \ - REAL(Set, OCLASP(Set)) \ - REAL(DataView, OCLASP(FixedLengthDataView)) \ - REAL(Symbol, OCLASP(Symbol)) \ - REAL(ShadowRealm, OCLASP(ShadowRealm)) \ - REAL(SharedArrayBuffer, OCLASP(FixedLengthSharedArrayBuffer)) \ - REAL_IF_INTL(Intl, CLASP(Intl)) \ - REAL_IF_INTL(Collator, OCLASP(Collator)) \ - REAL_IF_INTL(DateTimeFormat, OCLASP(DateTimeFormat)) \ - REAL_IF_INTL(DisplayNames, OCLASP(DisplayNames)) \ - REAL_IF_INTL(ListFormat, OCLASP(ListFormat)) \ - REAL_IF_INTL(Locale, OCLASP(Locale)) \ - REAL_IF_INTL(NumberFormat, OCLASP(NumberFormat)) \ - REAL_IF_INTL(PluralRules, OCLASP(PluralRules)) \ - REAL_IF_INTL(RelativeTimeFormat, OCLASP(RelativeTimeFormat)) \ - REAL_IF_INTL(Segmenter, OCLASP(Segmenter)) \ - REAL(Reflect, CLASP(Reflect)) \ - REAL(WeakSet, OCLASP(WeakSet)) \ - REAL(TypedArray, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \ - REAL(Atomics, OCLASP(Atomics)) \ - REAL(SavedFrame, &js::SavedFrame::class_) \ - REAL(Promise, OCLASP(Promise)) \ - REAL(AsyncFunction, CLASP(AsyncFunction)) \ - REAL(GeneratorFunction, CLASP(GeneratorFunction)) \ - REAL(AsyncGeneratorFunction, CLASP(AsyncGeneratorFunction)) \ - REAL(WebAssembly, OCLASP(WasmNamespace)) \ - REAL(WasmModule, OCLASP(WasmModule)) \ - REAL(WasmInstance, OCLASP(WasmInstance)) \ - REAL(WasmMemory, OCLASP(WasmMemory)) \ - REAL(WasmTable, OCLASP(WasmTable)) \ - REAL(WasmGlobal, OCLASP(WasmGlobal)) \ - REAL(WasmTag, OCLASP(WasmTag)) \ - REAL_IF_WASM_TYPE(WasmFunction, CLASP(WasmFunction)) \ - REAL_IF_WASM_JSPI(WasmSuspending, OCLASP(WasmSuspending)) \ - REAL(WasmException, OCLASP(WasmException)) \ - REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \ - REAL(WeakRef, OCLASP(WeakRef)) \ - REAL(Iterator, OCLASP(Iterator)) \ - REAL(AsyncIterator, OCLASP(AsyncIterator)) \ - REAL_IF_TEMPORAL(Temporal, OCLASP(temporal::Temporal)) \ - REAL_IF_TEMPORAL(Calendar, OCLASP(temporal::Calendar)) \ - REAL_IF_TEMPORAL(Duration, OCLASP(temporal::Duration)) \ - REAL_IF_TEMPORAL(Instant, OCLASP(temporal::Instant)) \ - REAL_IF_TEMPORAL(PlainDate, OCLASP(temporal::PlainDate)) \ - REAL_IF_TEMPORAL(PlainDateTime, OCLASP(temporal::PlainDateTime)) \ - REAL_IF_TEMPORAL(PlainMonthDay, OCLASP(temporal::PlainMonthDay)) \ - REAL_IF_TEMPORAL(PlainYearMonth, OCLASP(temporal::PlainYearMonth)) \ - REAL_IF_TEMPORAL(PlainTime, OCLASP(temporal::PlainTime)) \ - REAL_IF_TEMPORAL(TemporalNow, OCLASP(temporal::TemporalNow)) \ - REAL_IF_TEMPORAL(TimeZone, OCLASP(temporal::TimeZone)) \ - REAL_IF_TEMPORAL(ZonedDateTime, OCLASP(temporal::ZonedDateTime)) \ - IF_RECORD_TUPLE(REAL(Record, (&RecordType::class_))) \ - IF_RECORD_TUPLE(REAL(Tuple, (&TupleType::class_))) +#define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL, REAL_IF_WASM_TYPE, \ + REAL_IF_WASM_JSPI, REAL_IF_NIGHTLY) \ + IMAGINARY(Null, dummy) \ + REAL(Object, OCLASP(Plain)) \ + REAL(Function, &FunctionClass) \ + IMAGINARY(BoundFunction, OCLASP(BoundFunction)) \ + REAL(Array, OCLASP(Array)) \ + REAL(Boolean, OCLASP(Boolean)) \ + REAL(JSON, CLASP(JSON)) \ + REAL(Date, OCLASP(Date)) \ + REAL(Math, CLASP(Math)) \ + REAL(Number, OCLASP(Number)) \ + REAL(String, OCLASP(String)) \ + REAL(RegExp, OCLASP(RegExp)) \ + REAL(Error, ERROR_CLASP(JSEXN_ERR)) \ + REAL(InternalError, ERROR_CLASP(JSEXN_INTERNALERR)) \ + REAL(AggregateError, ERROR_CLASP(JSEXN_AGGREGATEERR)) \ + REAL(EvalError, ERROR_CLASP(JSEXN_EVALERR)) \ + REAL(RangeError, ERROR_CLASP(JSEXN_RANGEERR)) \ + REAL(ReferenceError, ERROR_CLASP(JSEXN_REFERENCEERR)) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT( \ + REAL(SuppressedError, ERROR_CLASP(JSEXN_SUPPRESSEDERR))) \ + REAL(SyntaxError, ERROR_CLASP(JSEXN_SYNTAXERR)) \ + REAL(TypeError, ERROR_CLASP(JSEXN_TYPEERR)) \ + REAL(URIError, ERROR_CLASP(JSEXN_URIERR)) \ + REAL(DebuggeeWouldRun, ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \ + REAL(CompileError, ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \ + REAL(LinkError, ERROR_CLASP(JSEXN_WASMLINKERROR)) \ + REAL(RuntimeError, ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \ + REAL_IF_WASM_JSPI(SuspendError, ERROR_CLASP(JSEXN_WASMSUSPENDERROR)) \ + REAL(ArrayBuffer, OCLASP(FixedLengthArrayBuffer)) \ + REAL(Int8Array, TYPED_ARRAY_CLASP(Int8)) \ + REAL(Uint8Array, TYPED_ARRAY_CLASP(Uint8)) \ + REAL(Int16Array, TYPED_ARRAY_CLASP(Int16)) \ + REAL(Uint16Array, TYPED_ARRAY_CLASP(Uint16)) \ + REAL(Int32Array, TYPED_ARRAY_CLASP(Int32)) \ + REAL(Uint32Array, TYPED_ARRAY_CLASP(Uint32)) \ + REAL(Float32Array, TYPED_ARRAY_CLASP(Float32)) \ + REAL(Float64Array, TYPED_ARRAY_CLASP(Float64)) \ + REAL(Uint8ClampedArray, TYPED_ARRAY_CLASP(Uint8Clamped)) \ + REAL(BigInt64Array, TYPED_ARRAY_CLASP(BigInt64)) \ + REAL(BigUint64Array, TYPED_ARRAY_CLASP(BigUint64)) \ + REAL(Float16Array, TYPED_ARRAY_CLASP(Float16)) \ + REAL(BigInt, OCLASP(BigInt)) \ + REAL(Proxy, CLASP(Proxy)) \ + REAL(WeakMap, OCLASP(WeakMap)) \ + REAL(Map, OCLASP(Map)) \ + REAL(Set, OCLASP(Set)) \ + REAL(DataView, OCLASP(FixedLengthDataView)) \ + REAL(Symbol, OCLASP(Symbol)) \ + REAL(ShadowRealm, OCLASP(ShadowRealm)) \ + REAL(SharedArrayBuffer, OCLASP(FixedLengthSharedArrayBuffer)) \ + REAL_IF_INTL(Intl, CLASP(Intl)) \ + REAL_IF_INTL(Collator, OCLASP(Collator)) \ + REAL_IF_INTL(DateTimeFormat, OCLASP(DateTimeFormat)) \ + REAL_IF_INTL(DisplayNames, OCLASP(DisplayNames)) \ + REAL_IF_INTL(DurationFormat, OCLASP(DurationFormat)) \ + REAL_IF_INTL(ListFormat, OCLASP(ListFormat)) \ + REAL_IF_INTL(Locale, OCLASP(Locale)) \ + REAL_IF_INTL(NumberFormat, OCLASP(NumberFormat)) \ + REAL_IF_INTL(PluralRules, OCLASP(PluralRules)) \ + REAL_IF_INTL(RelativeTimeFormat, OCLASP(RelativeTimeFormat)) \ + REAL_IF_INTL(Segmenter, OCLASP(Segmenter)) \ + REAL(Reflect, CLASP(Reflect)) \ + REAL(WeakSet, OCLASP(WeakSet)) \ + REAL(TypedArray, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \ + REAL(Atomics, OCLASP(Atomics)) \ + REAL(SavedFrame, &js::SavedFrame::class_) \ + REAL(Promise, OCLASP(Promise)) \ + REAL(AsyncFunction, CLASP(AsyncFunction)) \ + REAL(GeneratorFunction, CLASP(GeneratorFunction)) \ + REAL(AsyncGeneratorFunction, CLASP(AsyncGeneratorFunction)) \ + REAL(WebAssembly, OCLASP(WasmNamespace)) \ + REAL(WasmModule, OCLASP(WasmModule)) \ + REAL(WasmInstance, OCLASP(WasmInstance)) \ + REAL(WasmMemory, OCLASP(WasmMemory)) \ + REAL(WasmTable, OCLASP(WasmTable)) \ + REAL(WasmGlobal, OCLASP(WasmGlobal)) \ + REAL(WasmTag, OCLASP(WasmTag)) \ + REAL_IF_WASM_TYPE(WasmFunction, CLASP(WasmFunction)) \ + REAL_IF_WASM_JSPI(WasmSuspending, OCLASP(WasmSuspending)) \ + REAL(WasmException, OCLASP(WasmException)) \ + REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \ + REAL(WeakRef, OCLASP(WeakRef)) \ + REAL(Iterator, OCLASP(Iterator)) \ + REAL(AsyncIterator, OCLASP(AsyncIterator)) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT( \ + REAL(DisposableStack, OCLASP(DisposableStack))) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT( \ + REAL(AsyncDisposableStack, OCLASP(AsyncDisposableStack))) \ + REAL_IF_INTL(Temporal, OCLASP(temporal::Temporal)) \ + REAL_IF_INTL(Duration, OCLASP(temporal::Duration)) \ + REAL_IF_INTL(Instant, OCLASP(temporal::Instant)) \ + REAL_IF_INTL(PlainDate, OCLASP(temporal::PlainDate)) \ + REAL_IF_INTL(PlainDateTime, OCLASP(temporal::PlainDateTime)) \ + REAL_IF_INTL(PlainMonthDay, OCLASP(temporal::PlainMonthDay)) \ + REAL_IF_INTL(PlainYearMonth, OCLASP(temporal::PlainYearMonth)) \ + REAL_IF_INTL(PlainTime, OCLASP(temporal::PlainTime)) \ + REAL_IF_INTL(TemporalNow, OCLASP(temporal::TemporalNow)) \ + REAL_IF_INTL(ZonedDateTime, OCLASP(temporal::ZonedDateTime)) -#define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \ - JS_FOR_PROTOTYPES_( \ - REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), IF_TEMPORAL(REAL, IMAGINARY), \ - IF_WASM_TYPE(REAL, IMAGINARY), IF_WASM_JSPI(REAL, IMAGINARY), \ - IF_NIGHTLY(REAL, IMAGINARY)) +#define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \ + JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), \ + IF_WASM_TYPE(REAL, IMAGINARY), \ + IF_WASM_JSPI(REAL, IMAGINARY), \ + IF_NIGHTLY(REAL, IMAGINARY)) #define JS_FOR_EACH_PROTOTYPE(MACRO) JS_FOR_PROTOTYPES(MACRO, MACRO) diff --git a/src/third_party/mozjs/extract/js/public/Proxy.h b/src/third_party/mozjs/extract/js/public/Proxy.h index 45ba4a1376f..4c50831b612 100644 --- a/src/third_party/mozjs/extract/js/public/Proxy.h +++ b/src/third_party/mozjs/extract/js/public/Proxy.h @@ -100,6 +100,10 @@ class JS_PUBLIC_API Wrapper; * organized in the following hierarchy: * * BaseProxyHandler + * | | + * | NurseryAllocableProxyHandler + * | // allocated in the nursery; disallows + * | // overriding finalize method * | * ForwardingProxyHandler // has a target and forwards internal methods * | @@ -378,6 +382,17 @@ class JS_PUBLIC_API BaseProxyHandler { virtual bool isScripted() const { return false; } }; +class JS_PUBLIC_API NurseryAllocableProxyHandler : public BaseProxyHandler { + using BaseProxyHandler::BaseProxyHandler; + + // Don't allow overriding the default finalize method. + void finalize(JS::GCContext* gcx, JSObject* proxy) const final { + BaseProxyHandler::finalize(gcx, proxy); + } + // Can allocate in the nursery as long as we use the default finalize method. + bool canNurseryAllocate() const override { return true; } +}; + extern JS_PUBLIC_DATA const JSClass ProxyClass; inline bool IsProxy(const JSObject* obj) { @@ -463,12 +478,12 @@ constexpr ptrdiff_t ProxyReservedSlots::offsetOfPrivateSlot() { offsetof(ProxyValueArray, privateSlot); } -// All proxies share the same data layout. Following the object's shape and -// type, the proxy has a ProxyDataLayout structure with a pointer to an array -// of values and the proxy's handler. This is designed both so that proxies can -// be easily swapped with other objects (via RemapWrapper) and to mimic the -// layout of other objects (proxies and other objects have the same size) so -// that common code can access either type of object. +// All proxies share the same data layout. Following the object's shape, the +// proxy has a ProxyDataLayout structure with a pointer to an array of values +// and the proxy's handler. This is designed both so that proxies can be easily +// swapped with other objects (via RemapWrapper) and to mimic the layout of +// other objects (proxies and other objects have the same size) so that common +// code can access either type of object. // // See GetReservedOrProxyPrivateSlot below. struct ProxyDataLayout { @@ -554,9 +569,8 @@ inline void SetProxyReservedSlot(JSObject* obj, size_t n, inline void SetProxyPrivate(JSObject* obj, const JS::Value& value) { #ifdef DEBUG - if (gc::detail::ObjectIsMarkedBlack(obj)) { - JS::AssertValueIsNotGray(value); - } + JS::AssertObjectIsNotGray(obj); + JS::AssertValueIsNotGray(value); #endif JS::Value* vp = &detail::GetProxyDataLayout(obj)->values()->privateSlot; @@ -693,10 +707,9 @@ class JS_PUBLIC_API AutoWaivePolicy : public AutoEnterPolicy { } }; #else -class JS_PUBLIC_API AutoWaivePolicy { - public: - AutoWaivePolicy(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, - BaseProxyHandler::Action act) {} +class JS_PUBLIC_API AutoWaivePolicy{ + public : AutoWaivePolicy(JSContext * cx, JS::HandleObject proxy, + JS::HandleId id, BaseProxyHandler::Action act){} }; #endif @@ -741,14 +754,14 @@ constexpr unsigned CheckProxyFlags() { return Flags; } -#define PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, classSpec) \ - { \ - name, \ - JSClass::NON_NATIVE | JSCLASS_IS_PROXY | \ - JSCLASS_DELAY_METADATA_BUILDER | js::CheckProxyFlags(), \ - &js::ProxyClassOps, classSpec, &js::ProxyClassExtension, \ - &js::ProxyObjectOps \ - } +#define PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, classSpec) \ + {name, \ + JSClass::NON_NATIVE | JSCLASS_IS_PROXY | JSCLASS_DELAY_METADATA_BUILDER | \ + js::CheckProxyFlags(), \ + &js::ProxyClassOps, \ + classSpec, \ + &js::ProxyClassExtension, \ + &js::ProxyObjectOps} #define PROXY_CLASS_DEF(name, flags) \ PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, JS_NULL_CLASS_SPEC) diff --git a/src/third_party/mozjs/extract/js/public/Realm.h b/src/third_party/mozjs/extract/js/public/Realm.h index 3421a9fed3b..065b1fc1119 100644 --- a/src/third_party/mozjs/extract/js/public/Realm.h +++ b/src/third_party/mozjs/extract/js/public/Realm.h @@ -106,6 +106,8 @@ extern JS_PUBLIC_API JS::Handle GetRealmObjectPrototypeHandle( JSContext* cx); extern JS_PUBLIC_API JSObject* GetRealmFunctionPrototype(JSContext* cx); +extern JS_PUBLIC_API JS::Handle GetRealmFunctionPrototypeHandle( + JSContext* cx); extern JS_PUBLIC_API JSObject* GetRealmArrayPrototype(JSContext* cx); @@ -142,6 +144,14 @@ extern JS_PUBLIC_API JS::Realm* EnterRealm(JSContext* cx, JSObject* target); extern JS_PUBLIC_API void LeaveRealm(JSContext* cx, JS::Realm* oldRealm); +/** + * Reset the seed for Math.random() within the current realm. + * + * Enables embedders to reset the seed at controlled points, e.g. after + * resuming execution from an instance snapshot of SpiderMonkey's VM. + */ +extern JS_PUBLIC_API void ResetRealmMathRandomSeed(JSContext* cx); + } // namespace JS /* diff --git a/src/third_party/mozjs/extract/js/public/RealmOptions.h b/src/third_party/mozjs/extract/js/public/RealmOptions.h index b3ab20915a0..40c20846a84 100644 --- a/src/third_party/mozjs/extract/js/public/RealmOptions.h +++ b/src/third_party/mozjs/extract/js/public/RealmOptions.h @@ -113,6 +113,12 @@ class JS_PUBLIC_API RealmCreationOptions { // Determines whether this realm should preserve JIT code on non-shrinking // GCs. + // + // Useful for embedders who know their code is relatively stable. See + // Bug 1068697 for motivation. + // + // This is a hint not a guarantee and can be overriden by other heuristics in + // the engine. bool preserveJitCode() const { return preserveJitCode_; } RealmCreationOptions& setPreserveJitCode(bool flag) { preserveJitCode_ = flag; diff --git a/src/third_party/mozjs/extract/js/public/RefCounted.h b/src/third_party/mozjs/extract/js/public/RefCounted.h index de5a72f2d8b..1a58f892017 100644 --- a/src/third_party/mozjs/extract/js/public/RefCounted.h +++ b/src/third_party/mozjs/extract/js/public/RefCounted.h @@ -14,11 +14,7 @@ // These types implement the same interface as mozilla::(Atomic)RefCounted and // must be used instead of mozilla::(Atomic)RefCounted for everything in -// SpiderMonkey. There are two reasons: -// - Release() needs to call js_delete, not delete -// - SpiderMonkey does not have MOZILLA_INTERNAL_API defined which can lead -// to ODR violations that show up as spurious leak reports when ref-counted -// types are allocated by SpiderMonkey and released by Gecko (or vice versa). +// SpiderMonkey. This is because Release() needs to call js_delete, not delete. namespace js { diff --git a/src/third_party/mozjs/extract/js/public/RegExpFlags.h b/src/third_party/mozjs/extract/js/public/RegExpFlags.h index e4663786fcf..bf6bcb4e7b9 100644 --- a/src/third_party/mozjs/extract/js/public/RegExpFlags.h +++ b/src/third_party/mozjs/extract/js/public/RegExpFlags.h @@ -79,7 +79,7 @@ class RegExpFlags { using Flag = uint8_t; private: - Flag flags_; + Flag flags_ = 0; public: RegExpFlags() = default; @@ -159,7 +159,7 @@ inline RegExpFlags& operator^=(RegExpFlags& flags, RegExpFlags::Flag flag) { inline RegExpFlags operator&(const RegExpFlags& lhs, const RegExpFlags& rhs) { RegExpFlags result = lhs; result &= rhs; - return lhs; + return result; } inline RegExpFlags operator|(const RegExpFlags& lhs, const RegExpFlags& rhs) { diff --git a/src/third_party/mozjs/extract/js/public/RootingAPI.h b/src/third_party/mozjs/extract/js/public/RootingAPI.h index eaae2db1b7e..c252d0b9bbd 100644 --- a/src/third_party/mozjs/extract/js/public/RootingAPI.h +++ b/src/third_party/mozjs/extract/js/public/RootingAPI.h @@ -13,6 +13,7 @@ #include "mozilla/LinkedList.h" #include "mozilla/Maybe.h" +#include #include #include @@ -23,10 +24,10 @@ #include "js/GCPolicyAPI.h" #include "js/GCTypeMacros.h" // JS_FOR_EACH_PUBLIC_{,TAGGED_}GC_POINTER_TYPE #include "js/HashTable.h" -#include "js/HeapAPI.h" // StackKindCount +#include "js/HeapAPI.h" // StackKindCount +#include "js/NativeStackLimits.h" // JS::NativeStackLimit #include "js/ProfilingStack.h" #include "js/Realm.h" -#include "js/Stack.h" // JS::NativeStackLimit #include "js/TypeDecls.h" #include "js/UniquePtr.h" @@ -172,18 +173,18 @@ struct Cell; // Assignment operators on a base class are hidden by the implicitly defined // operator= on the derived class. Thus, define the operator= directly on the // class as we would need to manually pass it through anyway. -#define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \ - Wrapper& operator=(const T& p) { \ - set(p); \ - return *this; \ - } \ - Wrapper& operator=(T&& p) { \ - set(std::move(p)); \ - return *this; \ - } \ - Wrapper& operator=(const Wrapper& other) { \ - set(other.get()); \ - return *this; \ +#define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \ + Wrapper& operator=(const T& p) { \ + set(p); \ + return *this; \ + } \ + Wrapper& operator=(T&& p) { \ + set(std::move(p)); \ + return *this; \ + } \ + Wrapper& operator=(const Wrapper& other) { \ + set(other.get()); \ + return *this; \ } #define DELETE_ASSIGNMENT_OPS(Wrapper, T) \ @@ -205,11 +206,6 @@ namespace JS { JS_PUBLIC_API void HeapObjectPostWriteBarrier(JSObject** objp, JSObject* prev, JSObject* next); -JS_PUBLIC_API void HeapStringPostWriteBarrier(JSString** objp, JSString* prev, - JSString* next); -JS_PUBLIC_API void HeapBigIntPostWriteBarrier(JS::BigInt** bip, - JS::BigInt* prev, - JS::BigInt* next); JS_PUBLIC_API void HeapObjectWriteBarriers(JSObject** objp, JSObject* prev, JSObject* next); JS_PUBLIC_API void HeapStringWriteBarriers(JSString** objp, JSString* prev, @@ -244,8 +240,8 @@ struct SafelyInitialized { // doesn't offer a type trait indicating whether a class's constructor is // user-defined, which better approximates our desired semantics.) constexpr bool IsNonTriviallyDefaultConstructibleClassOrUnion = - (std::is_class_v || - std::is_union_v)&&!std::is_trivially_default_constructible_v; + (std::is_class_v || std::is_union_v) && + !std::is_trivially_default_constructible_v; static_assert(IsPointer || IsNonTriviallyDefaultConstructibleClassOrUnion, "T() must evaluate to a safely-initialized T"); @@ -281,13 +277,9 @@ inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {} * * Heap implements the following barriers: * + * - Pre-write barrier (necessary for incremental GC). * - Post-write barrier (necessary for generational GC). - * - Read barrier (necessary for incremental GC and cycle collector - * integration). - * - * Note Heap does not have a pre-write barrier as used internally in the - * engine. The read barrier is used to mark anything read from a Heap during - * an incremental GC. + * - Read barrier (necessary for cycle collector integration). * * Heap may be moved or destroyed outside of GC finalization and hence may be * used in dynamic storage such as a Vector. @@ -302,8 +294,6 @@ inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {} */ template class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { - // Please note: this can actually also be used by nsXBLMaybeCompiled, for - // legacy reasons. static_assert(js::IsHeapConstructibleType::value, "Type T must be a public GC pointer type"); @@ -316,7 +306,7 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { "Heap must be binary compatible with T."); } explicit Heap(const T& p) : ptr(p) { - postWriteBarrier(SafelyInitialized::create(), ptr); + writeBarriers(SafelyInitialized::create(), ptr); } /* @@ -325,25 +315,24 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { * breaks common usage of move semantics, so we need to define both, even * though they are equivalent. */ - explicit Heap(const Heap& other) : ptr(other.getWithoutExpose()) { - postWriteBarrier(SafelyInitialized::create(), ptr); + explicit Heap(const Heap& other) : ptr(other.unbarrieredGet()) { + writeBarriers(SafelyInitialized::create(), ptr); } - Heap(Heap&& other) : ptr(other.getWithoutExpose()) { - postWriteBarrier(SafelyInitialized::create(), ptr); + Heap(Heap&& other) : ptr(other.unbarrieredGet()) { + writeBarriers(SafelyInitialized::create(), ptr); } Heap& operator=(Heap&& other) { - set(other.getWithoutExpose()); + set(other.unbarrieredGet()); other.set(SafelyInitialized::create()); return *this; } + // Copy constructor defined by DECLARE_POINTER_ASSIGN_OPS. - ~Heap() { postWriteBarrier(ptr, SafelyInitialized::create()); } + ~Heap() { writeBarriers(ptr, SafelyInitialized::create()); } DECLARE_POINTER_CONSTREF_OPS(T); - DECLARE_POINTER_ASSIGN_OPS(Heap, T); - - const T* address() const { return &ptr; } + DECLARE_POINTER_ASSIGN_OPS(Heap, T); void exposeToActiveJS() const { js::BarrierMethods::exposeToJS(ptr); } @@ -351,32 +340,25 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { exposeToActiveJS(); return ptr; } - const T& getWithoutExpose() const { - js::BarrierMethods::readBarrier(ptr); - return ptr; - } const T& unbarrieredGet() const { return ptr; } void set(const T& newPtr) { T tmp = ptr; ptr = newPtr; - postWriteBarrier(tmp, ptr); + writeBarriers(tmp, ptr); } - - T* unsafeGet() { return &ptr; } - void unbarrieredSet(const T& newPtr) { ptr = newPtr; } + T* unsafeAddress() { return &ptr; } + const T* unsafeAddress() const { return &ptr; } + explicit operator bool() const { return bool(js::BarrierMethods::asGCThingOrNull(ptr)); } - explicit operator bool() { - return bool(js::BarrierMethods::asGCThingOrNull(ptr)); - } private: - void postWriteBarrier(const T& prev, const T& next) { - js::BarrierMethods::postWriteBarrier(&ptr, prev, next); + void writeBarriers(const T& prev, const T& next) { + js::BarrierMethods::writeBarriers(&ptr, prev, next); } T ptr; @@ -448,7 +430,7 @@ inline void AssertObjectIsNotGray(const JS::Heap& obj) {} * it has two important differences: * * 1) Pointers which are statically known to only reference "tenured" objects - * can avoid the extra overhead of SpiderMonkey's write barriers. + * can avoid the extra overhead of SpiderMonkey's post write barriers. * * 2) Objects in the "tenured" heap have stronger alignment restrictions than * those in the "nursery", so it is possible to store flags in the lower @@ -473,6 +455,9 @@ inline void AssertObjectIsNotGray(const JS::Heap& obj) {} */ template class TenuredHeap : public js::HeapOperations> { + static_assert(js::IsHeapConstructibleType::value, + "Type T must be a public GC pointer type"); + public: using ElementType = T; @@ -480,12 +465,29 @@ class TenuredHeap : public js::HeapOperations> { static_assert(sizeof(T) == sizeof(TenuredHeap), "TenuredHeap must be binary compatible with T."); } - explicit TenuredHeap(T p) : bits(0) { setPtr(p); } + + explicit TenuredHeap(T p) : bits(0) { unbarrieredSetPtr(p); } explicit TenuredHeap(const TenuredHeap& p) : bits(0) { - setPtr(p.getPtr()); + unbarrieredSetPtr(p.getPtr()); } + TenuredHeap& operator=(T p) { + setPtr(p); + return *this; + } + TenuredHeap& operator=(const TenuredHeap& other) { + preWriteBarrier(); + bits = other.bits; + return *this; + } + + ~TenuredHeap() { preWriteBarrier(); } + void setPtr(T newPtr) { + preWriteBarrier(); + unbarrieredSetPtr(newPtr); + } + void unbarrieredSetPtr(T newPtr) { MOZ_ASSERT((reinterpret_cast(newPtr) & flagsMask) == 0); MOZ_ASSERT(js::gc::IsCellPointerValidOrNull(newPtr)); if (newPtr) { @@ -526,19 +528,6 @@ class TenuredHeap : public js::HeapOperations> { explicit operator bool() const { return bool(js::BarrierMethods::asGCThingOrNull(unbarrieredGetPtr())); } - explicit operator bool() { - return bool(js::BarrierMethods::asGCThingOrNull(unbarrieredGetPtr())); - } - - TenuredHeap& operator=(T p) { - setPtr(p); - return *this; - } - - TenuredHeap& operator=(const TenuredHeap& other) { - bits = other.bits; - return *this; - } private: enum { @@ -546,6 +535,12 @@ class TenuredHeap : public js::HeapOperations> { flagsMask = (1 << maskBits) - 1, }; + void preWriteBarrier() { + if (T prev = unbarrieredGetPtr()) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev)); + } + } + uintptr_t bits; }; @@ -583,6 +578,8 @@ template class MutableHandle; template class Rooted; +template +class RootedField; template class PersistentRooted; @@ -662,6 +659,11 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleOperations> { MutableHandle& root, std::enable_if_t, int> dummy = 0); + template + inline MOZ_IMPLICIT Handle( + const RootedField& rootedField, + std::enable_if_t, int> dummy = 0); + DECLARE_POINTER_CONSTREF_OPS(T); DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr); @@ -700,6 +702,8 @@ class MOZ_STACK_CLASS MutableHandle using ElementType = T; inline MOZ_IMPLICIT MutableHandle(Rooted* root); + template + inline MOZ_IMPLICIT MutableHandle(RootedField* root); inline MOZ_IMPLICIT MutableHandle(PersistentRooted* root); private: @@ -783,7 +787,10 @@ struct PtrBarrierMethodsBase { template struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(T** vp, T* prev, T* next) { + static void writeBarriers(T** vp, T* prev, T* next) { + if (prev) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev)); + } if (next) { JS::AssertGCThingIsNotNurseryAllocable( reinterpret_cast(next)); @@ -794,6 +801,9 @@ struct BarrierMethods : public detail::PtrBarrierMethodsBase { template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { + static void writeBarriers(JSObject** vp, JSObject* prev, JSObject* next) { + JS::HeapObjectWriteBarriers(vp, prev, next); + } static void postWriteBarrier(JSObject** vp, JSObject* prev, JSObject* next) { JS::HeapObjectPostWriteBarrier(vp, prev, next); } @@ -807,11 +817,11 @@ struct BarrierMethods template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(JSFunction** vp, JSFunction* prev, - JSFunction* next) { - JS::HeapObjectPostWriteBarrier(reinterpret_cast(vp), - reinterpret_cast(prev), - reinterpret_cast(next)); + static void writeBarriers(JSFunction** vp, JSFunction* prev, + JSFunction* next) { + JS::HeapObjectWriteBarriers(reinterpret_cast(vp), + reinterpret_cast(prev), + reinterpret_cast(next)); } static void exposeToJS(JSFunction* fun) { if (fun) { @@ -823,17 +833,25 @@ struct BarrierMethods template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(JSString** vp, JSString* prev, JSString* next) { - JS::HeapStringPostWriteBarrier(vp, prev, next); + static void writeBarriers(JSString** vp, JSString* prev, JSString* next) { + JS::HeapStringWriteBarriers(vp, prev, next); + } +}; + +template <> +struct BarrierMethods + : public detail::PtrBarrierMethodsBase { + static void writeBarriers(JSScript** vp, JSScript* prev, JSScript* next) { + JS::HeapScriptWriteBarriers(vp, prev, next); } }; template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(JS::BigInt** vp, JS::BigInt* prev, - JS::BigInt* next) { - JS::HeapBigIntPostWriteBarrier(vp, prev, next); + static void writeBarriers(JS::BigInt** vp, JS::BigInt* prev, + JS::BigInt* next) { + JS::HeapBigIntWriteBarriers(vp, prev, next); } }; @@ -1145,11 +1163,19 @@ using RootedTraits = template class MOZ_RAII Rooted : public detail::RootedTraits::StackBase, public js::RootedOperations> { + // Intentionally store a pointer into the stack. +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 12) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdangling-pointer" +#endif inline void registerWithRootLists(RootedListHeads& roots) { this->stack = &roots[JS::MapTypeToRootKind::kind]; this->prev = *this->stack; *this->stack = this; } +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 12) +# pragma GCC diagnostic pop +#endif inline RootedListHeads& rootLists(RootingContext* cx) { return cx->stackRoots_; @@ -1220,7 +1246,7 @@ class MOZ_RAII Rooted : public detail::RootedTraits::StackBase, } DECLARE_POINTER_CONSTREF_OPS(T); - DECLARE_POINTER_ASSIGN_OPS(Rooted, T); + DECLARE_POINTER_ASSIGN_OPS(Rooted, T); T& get() { return ptr; } const T& get() const { return ptr; } @@ -1243,6 +1269,86 @@ struct DefineComparisonOps> : std::true_type { } // namespace detail +template +using RootedTuple = Rooted>; + +// Reference to a field in a RootedTuple. This is a drop-in replacement for an +// individual Rooted. +// +// This is very similar to a MutableHandle but with two differences: it has an +// assignment operator so doesn't require set() to be called and its address +// converts to a MutableHandle in the same way as a Rooted. +// +// The field is specified by the type parameter, optionally disambiguated by +// supplying the field index too. +// +// Used like this: +// +// RootedTuple roots(cx); +// RootedField obj(roots); +// RootedField str(roots); +// +// or: +// +// RootedTuple roots(cx); +// RootedField str(roots); +// RootedField obj1(roots); +// RootedField obj2(roots); +template +class MOZ_RAII RootedField : public js::RootedOperations> { + T* ptr; + friend class Handle; + friend class MutableHandle; + + public: + using ElementType = T; + + template + explicit RootedField(RootedTuple& rootedTuple) { + using Tuple = std::tuple; + if constexpr (N == SIZE_MAX) { + ptr = &std::get(rootedTuple.get()); + } else { + static_assert(N < std::tuple_size_v); + static_assert(std::is_same_v>); + ptr = &std::get(rootedTuple.get()); + } + } + template + explicit RootedField(RootedTuple& rootedTuple, S&& value) + : RootedField(rootedTuple) { + *ptr = std::forward(value); + } + + T& get() { return *ptr; } + const T& get() const { return *ptr; } + void set(const T& value) { + *ptr = value; + MOZ_ASSERT(GCPolicy::isValid(*ptr)); + } + void set(T&& value) { + *ptr = std::move(value); + MOZ_ASSERT(GCPolicy::isValid(*ptr)); + } + + using WrapperT = RootedField; + DECLARE_POINTER_CONSTREF_OPS(T); + DECLARE_POINTER_ASSIGN_OPS(WrapperT, T); + // DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr); + // DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr); + + private: + RootedField() = delete; + RootedField(const RootedField& other) = delete; +}; + +namespace detail { +template +struct DefineComparisonOps> : std::true_type { + static const T& get(const JS::RootedField& v) { return v.get(); } +}; +} // namespace detail + } /* namespace JS */ namespace js { @@ -1342,6 +1448,14 @@ inline Handle::Handle( ptr = reinterpret_cast(root.address()); } +template +template +inline Handle::Handle( + const RootedField& rootedField, + std::enable_if_t, int> dummy) { + ptr = reinterpret_cast(rootedField.ptr); +} + template inline MutableHandle::MutableHandle(Rooted* root) { static_assert(sizeof(MutableHandle) == sizeof(T*), @@ -1349,6 +1463,12 @@ inline MutableHandle::MutableHandle(Rooted* root) { ptr = root->address(); } +template +template +inline MutableHandle::MutableHandle(RootedField* rootedField) { + ptr = rootedField->ptr; +} + template inline MutableHandle::MutableHandle(PersistentRooted* root) { static_assert(sizeof(MutableHandle) == sizeof(T*), @@ -1480,7 +1600,7 @@ class PersistentRooted : public detail::RootedTraits::PersistentBase, } DECLARE_POINTER_CONSTREF_OPS(T); - DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T); + DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T); T& get() { return ptr; } const T& get() const { return ptr; } diff --git a/src/third_party/mozjs/extract/js/public/SliceBudget.h b/src/third_party/mozjs/extract/js/public/SliceBudget.h index 44450204840..40edd5b8181 100644 --- a/src/third_party/mozjs/extract/js/public/SliceBudget.h +++ b/src/third_party/mozjs/extract/js/public/SliceBudget.h @@ -16,7 +16,7 @@ #include "jstypes.h" -namespace js { +namespace JS { struct JS_PUBLIC_API TimeBudget { const mozilla::TimeDuration budget; @@ -140,6 +140,6 @@ class JS_PUBLIC_API SliceBudget { int describe(char* buffer, size_t maxlen) const; }; -} // namespace js +} // namespace JS #endif /* js_SliceBudget_h */ diff --git a/src/third_party/mozjs/extract/js/public/Stack.h b/src/third_party/mozjs/extract/js/public/Stack.h index 7384e92d398..bf9c845615c 100644 --- a/src/third_party/mozjs/extract/js/public/Stack.h +++ b/src/third_party/mozjs/extract/js/public/Stack.h @@ -17,44 +17,9 @@ #include "jstypes.h" // JS_PUBLIC_API +#include "js/NativeStackLimits.h" #include "js/Principals.h" // JSPrincipals, JS_HoldPrincipals, JS_DropPrincipals -#include "js/TypeDecls.h" // JSContext, Handle*, MutableHandle* - -namespace JS { - -using NativeStackSize = size_t; - -using NativeStackBase = uintptr_t; - -using NativeStackLimit = uintptr_t; - -#if JS_STACK_GROWTH_DIRECTION > 0 -constexpr NativeStackLimit NativeStackLimitMin = 0; -constexpr NativeStackLimit NativeStackLimitMax = UINTPTR_MAX; -#else -constexpr NativeStackLimit NativeStackLimitMin = UINTPTR_MAX; -constexpr NativeStackLimit NativeStackLimitMax = 0; -#endif - -#ifdef __wasi__ -// We build with the "stack-first" wasm-ld option, so the stack grows downward -// toward zero. Let's set a limit just a bit above this so that we catch an -// overflow before a Wasm trap occurs. -constexpr NativeStackLimit WASINativeStackLimit = 1024; -#endif // __wasi__ - -inline NativeStackLimit GetNativeStackLimit(NativeStackBase base, - NativeStackSize size) { -#if JS_STACK_GROWTH_DIRECTION > 0 - MOZ_ASSERT(base <= size_t(-1) - size); - return base + size - 1; -#else // stack grows up - MOZ_ASSERT(base >= size); - return base - (size - 1); -#endif // stack grows down -} - -} // namespace JS +#include "js/RootingAPI.h" /** * Set the size of the native stack that should not be exceed. To disable @@ -177,7 +142,8 @@ using StackCapture = mozilla::Variant; */ extern JS_PUBLIC_API bool CaptureCurrentStack( JSContext* cx, MutableHandleObject stackp, - StackCapture&& capture = StackCapture(AllFrames())); + StackCapture&& capture = StackCapture(AllFrames()), + HandleObject startAfter = nullptr); /** * Returns true if capturing stack trace data to associate with an asynchronous diff --git a/src/third_party/mozjs/extract/js/public/String.h b/src/third_party/mozjs/extract/js/public/String.h index 3e003f291c4..41645d2bc1d 100644 --- a/src/third_party/mozjs/extract/js/public/String.h +++ b/src/third_party/mozjs/extract/js/public/String.h @@ -11,13 +11,15 @@ #include "js/shadow/String.h" // JS::shadow::String -#include "mozilla/Assertions.h" // MOZ_ASSERT -#include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE -#include "mozilla/Likely.h" // MOZ_LIKELY -#include "mozilla/Maybe.h" // mozilla::Maybe -#include "mozilla/Range.h" // mozilla::Range -#include "mozilla/Span.h" // mozilla::Span - // std::tuple +#include "mozilla/Assertions.h" // MOZ_ASSERT +#include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE +#include "mozilla/Likely.h" // MOZ_LIKELY +#include "mozilla/Maybe.h" // mozilla::Maybe +#include "mozilla/Range.h" // mozilla::Range +#include "mozilla/RefPtr.h" // RefPtr +#include "mozilla/Span.h" // mozilla::Span + // std::tuple +#include "mozilla/StringBuffer.h" // mozilla::StringBuffer #include // std::copy_n #include // size_t @@ -102,6 +104,63 @@ extern JS_PUBLIC_API JSString* JS_NewUCStringCopyN(JSContext* cx, extern JS_PUBLIC_API JSString* JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s); +namespace JS { + +/** + * Create a new JSString possibly backed by |buffer|. The contents of |buffer| + * will be interpreted as an array of Latin1 characters. + * + * Note that the returned string is not guaranteed to use |buffer|: as an + * optimization, this API can return an inline string or a previously allocated + * string. + * + * Increments the buffer's refcount iff the JS string holds a reference to it. + */ +extern JS_PUBLIC_API JSString* NewStringFromLatin1Buffer( + JSContext* cx, RefPtr buffer, size_t length); + +/** + * Like NewStringFromLatin1Buffer, but can be used to avoid refcounting overhead + * in cases where the returned string doesn't use the buffer. The caller must + * ensure the buffer outlives this call. + */ +extern JS_PUBLIC_API JSString* NewStringFromKnownLiveLatin1Buffer( + JSContext* cx, mozilla::StringBuffer* buffer, size_t length); + +/** + * Similar to NewStringFromLatin1Buffer but for char16_t buffers. + */ +extern JS_PUBLIC_API JSString* NewStringFromTwoByteBuffer( + JSContext* cx, RefPtr buffer, size_t length); + +/** + * Similar to NewStringFromKnownLiveLatin1Buffer but for char16_t buffers. + */ +extern JS_PUBLIC_API JSString* NewStringFromKnownLiveTwoByteBuffer( + JSContext* cx, mozilla::StringBuffer* buffer, size_t length); + +/** + * Similar to NewStringFromLatin1Buffer but for UTF8 buffers. + * + * This can create a Latin1 string backed by |buffer| iff the utf8 buffer + * contains only ASCII chars. If there are non-ASCII chars, |buffer| can't be + * used so this API will copy and inflate the characters for the new JS string. + * + * Note that |length| must be the (byte) length of the UTF8 buffer. + */ +extern JS_PUBLIC_API JSString* NewStringFromUTF8Buffer( + JSContext* cx, RefPtr buffer, size_t length); + +/** + * Like NewStringFromUTF8Buffer, but can be used to avoid refcounting overhead + * in cases where the returned string doesn't use the buffer. The caller must + * ensure the buffer outlives this call. + */ +extern JS_PUBLIC_API JSString* NewStringFromKnownLiveUTF8Buffer( + JSContext* cx, mozilla::StringBuffer* buffer, size_t length); + +} // namespace JS + extern JS_PUBLIC_API JSString* JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length); @@ -430,6 +489,46 @@ MOZ_ALWAYS_INLINE bool IsExternalUCString( return true; } +/** + * If the provided string is backed by a StringBuffer for latin-1 storage, + * return true and set |*buffer| to the string buffer. + * + * Note: this function doesn't increment the buffer's refcount. The buffer + * remains valid as long as the provided string is kept alive. + */ +MOZ_ALWAYS_INLINE bool IsLatin1StringWithStringBuffer( + JSString* str, mozilla::StringBuffer** buffer) { + shadow::String* s = shadow::AsShadowString(str); + + if (!s->hasStringBuffer() || !s->hasLatin1Chars()) { + return false; + } + + void* data = const_cast(s->nonInlineCharsLatin1); + *buffer = mozilla::StringBuffer::FromData(data); + return true; +} + +/** + * If the provided string is backed by a StringBuffer for char16_t storage, + * return true and set |*buffer| to the string buffer. + * + * Note: this function doesn't increment the buffer's refcount. The buffer + * remains valid as long as the provided string is kept alive. + */ +MOZ_ALWAYS_INLINE bool IsTwoByteStringWithStringBuffer( + JSString* str, mozilla::StringBuffer** buffer) { + shadow::String* s = shadow::AsShadowString(str); + + if (!s->hasStringBuffer() || s->hasLatin1Chars()) { + return false; + } + + void* data = const_cast(s->nonInlineCharsTwoByte); + *buffer = mozilla::StringBuffer::FromData(data); + return true; +} + namespace detail { extern JS_PUBLIC_API JSLinearString* StringToLinearStringSlow(JSContext* cx, diff --git a/src/third_party/mozjs/extract/js/public/StructuredClone.h b/src/third_party/mozjs/extract/js/public/StructuredClone.h index ab151a3be56..db78536701e 100644 --- a/src/third_party/mozjs/extract/js/public/StructuredClone.h +++ b/src/third_party/mozjs/extract/js/public/StructuredClone.h @@ -10,6 +10,7 @@ #include "mozilla/Attributes.h" #include "mozilla/BufferList.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/StringBuffer.h" #include #include @@ -154,6 +155,13 @@ enum class StructuredCloneScope : uint32_t { */ DifferentProcess, + /** + * Values greater than this are temporary markers used when the actual scope + * is not yet known. The allowed scope will be resolved by the time + * readHeader() is complete. + */ + LastResolvedScope = DifferentProcess, + /** * Handle a backwards-compatibility case with IndexedDB (bug 1434308): when * reading, this means to treat legacy SameProcess data as if it were @@ -311,6 +319,11 @@ typedef void (*StructuredCloneErrorOp)(JSContext* cx, uint32_t errorid, * If this readTransfer() hook is called and produces an object, then the * read() hook will *not* be called for the same object, since the main data * will only contain a backreference to the already-read object. + * + * The clone buffer will relinquish ownership of this Transferable if and only + * if this hook returns true -- as in, the freeTransfer hook will not be called + * on this entry if this hook returns true, but it will still be called if it + * returns false. */ typedef bool (*ReadTransferStructuredCloneOp)( JSContext* cx, JSStructuredCloneReader* r, @@ -351,11 +364,13 @@ typedef bool (*TransferStructuredCloneOp)(JSContext* cx, * encountered later and the incomplete serialization is discarded. * * 2. During deserialization: before an object is Transferred to, an error - * is encountered and the incompletely deserialized clone is discarded. + * is encountered and the incompletely deserialized clone is discarded. This + * will happen with internally-implemented Transferables as well as those + * where the readTransfer hook returns false. * * 3. Serialized data that includes Transferring is never deserialized (eg when * the receiver disappears before reading in the message), and the clone data - * is destroyed. + * is destroyed. * */ typedef void (*FreeTransferStructuredCloneOp)( @@ -469,6 +484,10 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData { OwnTransferablePolicy::NoTransferables; js::SharedArrayRawBufferRefs refsHeld_; + using StringBuffers = + js::Vector, 4, js::SystemAllocPolicy>; + StringBuffers stringBufferRefsHeld_; + friend struct JSStructuredCloneWriter; friend class JS_PUBLIC_API JSAutoStructuredCloneBuffer; template diff --git a/src/third_party/mozjs/extract/js/public/Symbol.h b/src/third_party/mozjs/extract/js/public/Symbol.h index d45a58cffab..2f021cb9e78 100644 --- a/src/third_party/mozjs/extract/js/public/Symbol.h +++ b/src/third_party/mozjs/extract/js/public/Symbol.h @@ -49,21 +49,22 @@ extern JS_PUBLIC_API Symbol* GetSymbolFor(JSContext* cx, Handle key); extern JS_PUBLIC_API JSString* GetSymbolDescription(Handle symbol); /* Well-known symbols. */ -#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(MACRO) \ - MACRO(isConcatSpreadable) \ - MACRO(iterator) \ - MACRO(match) \ - MACRO(replace) \ - MACRO(search) \ - MACRO(species) \ - MACRO(hasInstance) \ - MACRO(split) \ - MACRO(toPrimitive) \ - MACRO(toStringTag) \ - MACRO(unscopables) \ - MACRO(asyncIterator) \ - MACRO(matchAll) \ - IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(dispose)) +#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(MACRO) \ + MACRO(isConcatSpreadable) \ + MACRO(iterator) \ + MACRO(match) \ + MACRO(replace) \ + MACRO(search) \ + MACRO(species) \ + MACRO(hasInstance) \ + MACRO(split) \ + MACRO(toPrimitive) \ + MACRO(toStringTag) \ + MACRO(unscopables) \ + MACRO(asyncIterator) \ + MACRO(matchAll) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(dispose)) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(asyncDispose)) enum class SymbolCode : uint32_t { // There is one SymbolCode for each well-known symbol. diff --git a/src/third_party/mozjs/extract/js/public/TraceKind.h b/src/third_party/mozjs/extract/js/public/TraceKind.h index 268db56957d..de6fb22e5fb 100644 --- a/src/third_party/mozjs/extract/js/public/TraceKind.h +++ b/src/third_party/mozjs/extract/js/public/TraceKind.h @@ -22,6 +22,9 @@ class PropMap; class RegExpShared; class Shape; class Scope; +namespace gc { +class SmallBuffer; +} // namespace gc namespace jit { class JitCode; } // namespace jit @@ -63,6 +66,7 @@ enum class TraceKind { RegExpShared, GetterSetter, PropMap, + SmallBuffer }; // GCCellPtr packs the trace kind into the low bits of the pointer for common @@ -88,20 +92,21 @@ struct MapTypeToTraceKind { // also means they can be used as a keys in WeakMap. // clang-format off -#define JS_FOR_EACH_TRACEKIND(D) \ - /* name type canBeGray inCCGraph */ \ - D(BaseShape, js::BaseShape, true, false) \ - D(JitCode, js::jit::JitCode, true, false) \ - D(Scope, js::Scope, true, true) \ - D(Object, JSObject, true, true) \ - D(Script, js::BaseScript, true, true) \ - D(Shape, js::Shape, true, false) \ - D(String, JSString, false, false) \ - D(Symbol, JS::Symbol, false, false) \ - D(BigInt, JS::BigInt, false, false) \ - D(RegExpShared, js::RegExpShared, true, true) \ - D(GetterSetter, js::GetterSetter, true, true) \ - D(PropMap, js::PropMap, false, false) +#define JS_FOR_EACH_TRACEKIND(D) \ + /* name type canBeGray inCCGraph */ \ + D(BaseShape, js::BaseShape, true, false) \ + D(JitCode, js::jit::JitCode, true, false) \ + D(Scope, js::Scope, true, true) \ + D(Object, JSObject, true, true) \ + D(Script, js::BaseScript, true, true) \ + D(Shape, js::Shape, true, false) \ + D(String, JSString, false, false) \ + D(Symbol, JS::Symbol, false, false) \ + D(BigInt, JS::BigInt, false, false) \ + D(RegExpShared, js::RegExpShared, true, true) \ + D(GetterSetter, js::GetterSetter, true, true) \ + D(PropMap, js::PropMap, false, false) \ + D(SmallBuffer, js::gc::SmallBuffer, false, false) // clang-format on // Returns true if the JS::TraceKind is represented as a node in cycle collector diff --git a/src/third_party/mozjs/extract/js/public/TracingAPI.h b/src/third_party/mozjs/extract/js/public/TracingAPI.h index 4db1b0a30ca..dfc145d9f98 100644 --- a/src/third_party/mozjs/extract/js/public/TracingAPI.h +++ b/src/third_party/mozjs/extract/js/public/TracingAPI.h @@ -48,6 +48,7 @@ enum class TracerKind { UnmarkGray, VerifyTraceProtoAndIface, CompartmentCheck, + HeapCheck }; enum class WeakMapTraceAction { @@ -135,7 +136,8 @@ class TracingContext { // currently set tracing context. class Functor { public: - virtual void operator()(TracingContext* tcx, char* buf, size_t bufsize) = 0; + virtual void operator()(TracingContext* tcx, const char* name, char* buf, + size_t bufsize) = 0; }; private: @@ -348,7 +350,7 @@ template inline void TraceEdge(JSTracer* trc, JS::Heap* thingp, const char* name) { MOZ_ASSERT(thingp); if (*thingp) { - js::gc::TraceExternalEdge(trc, thingp->unsafeGet(), name); + js::gc::TraceExternalEdge(trc, thingp->unsafeAddress(), name); } } @@ -358,7 +360,7 @@ inline void TraceEdge(JSTracer* trc, JS::TenuredHeap* thingp, MOZ_ASSERT(thingp); if (T ptr = thingp->unbarrieredGetPtr()) { js::gc::TraceExternalEdge(trc, &ptr, name); - thingp->setPtr(ptr); + thingp->unbarrieredSetPtr(ptr); } } diff --git a/src/third_party/mozjs/extract/js/public/Transcoding.h b/src/third_party/mozjs/extract/js/public/Transcoding.h index 9a5c6102ad7..61943088a87 100644 --- a/src/third_party/mozjs/extract/js/public/Transcoding.h +++ b/src/third_party/mozjs/extract/js/public/Transcoding.h @@ -19,8 +19,15 @@ #include "js/TypeDecls.h" +// Underlying opaque type. +namespace js::frontend { +struct InitialStencilAndDelazifications; +} // namespace js::frontend + namespace JS { +using Stencil = js::frontend::InitialStencilAndDelazifications; + class JS_PUBLIC_API ReadOnlyCompileOptions; using TranscodeBuffer = mozilla::Vector; @@ -79,52 +86,6 @@ inline bool IsTranscodingBytecodeAligned(const void* offset) { return IsTranscodingBytecodeOffsetAligned(size_t(offset)); } -// Finish incremental encoding started by JS::StartIncrementalEncoding. -// -// * Regular script case -// the |script| argument must be the top-level script returned from -// |JS::InstantiateGlobalStencil| with the same stencil -// -// * Module script case -// the |script| argument must be the script returned by -// |JS::GetModuleScript| called on the module returned by -// |JS::InstantiateModuleStencil| with the same stencil -// -// NOTE: |JS::GetModuleScript| doesn't work after evaluating the -// module script. For the case, use Handle variant of -// this function below. -// -// The |buffer| argument of |FinishIncrementalEncoding| is used for appending -// the encoded bytecode into the buffer. If any of these functions failed, the -// content of |buffer| would be undefined. -// -// |buffer| contains encoded CompilationStencil. -// -// If the `buffer` isn't empty, the start of the `buffer` should meet -// IsTranscodingBytecodeAligned, and the length should meet -// IsTranscodingBytecodeOffsetAligned. -// -// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means -// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, -// IsTranscodingBytecodeAligned should be guaranteed to meet by -// malloc, used by MallocAllocPolicy in mozilla::Vector. -extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx, - Handle script, - TranscodeBuffer& buffer); - -// Similar to |JS::FinishIncrementalEncoding|, but receives module obect. -// -// The |module| argument must be the module returned by -// |JS::InstantiateModuleStencil| with the same stencil that's passed to -// |JS::StartIncrementalEncoding|. -extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx, - Handle module, - TranscodeBuffer& buffer); - -// Abort incremental encoding started by JS::StartIncrementalEncoding. -extern JS_PUBLIC_API void AbortIncrementalEncoding(Handle script); -extern JS_PUBLIC_API void AbortIncrementalEncoding(Handle module); - // Check if the compile options and script's flag matches. // // JS::DecodeScript* and JS::DecodeOffThreadScript internally check this. diff --git a/src/third_party/mozjs/extract/js/public/TypeDecls.h b/src/third_party/mozjs/extract/js/public/TypeDecls.h index d82405b17c0..ea95dc4e987 100644 --- a/src/third_party/mozjs/extract/js/public/TypeDecls.h +++ b/src/third_party/mozjs/extract/js/public/TypeDecls.h @@ -47,10 +47,6 @@ typedef unsigned char Latin1Char; class JS_PUBLIC_API Symbol; class JS_PUBLIC_API BigInt; -#ifdef ENABLE_RECORD_TUPLE -class JS_PUBLIC_API RecordType; -class JS_PUBLIC_API TupleType; -#endif class JS_PUBLIC_API Value; class JS_PUBLIC_API Compartment; @@ -130,18 +126,6 @@ using MutableHandleVector = MutableHandle>; using jsid = JS::PropertyKey; -#ifdef ENABLE_RECORD_TUPLE -// This takes 1 or 2 parameters. ... is just used so that -// it's possible to omit the comma when passing a single -// param: -// IF_RECORD_TUPLE(doThis) -// IF_RECORD_TUPLE(doThis, elseThis) -# define IF_RECORD_TUPLE(x, ...) x -#else -# define IF_RECORD_TUPLE(x, ...) __VA_ARGS__ -#endif - -// Follows the same pattern as IF_RECORD_TUPLE #ifdef ENABLE_DECORATORS # define IF_DECORATORS(x, ...) x #else diff --git a/src/third_party/mozjs/extract/js/public/UbiNode.h b/src/third_party/mozjs/extract/js/public/UbiNode.h index 15edea070e4..aa187afc44c 100644 --- a/src/third_party/mozjs/extract/js/public/UbiNode.h +++ b/src/third_party/mozjs/extract/js/public/UbiNode.h @@ -1164,6 +1164,26 @@ class JS_PUBLIC_API Concrete : TracerConcrete { static const char16_t concreteTypeName[]; }; +template <> +class JS_PUBLIC_API Concrete + : TracerConcrete { + protected: + explicit Concrete(js::gc::SmallBuffer* ptr) + : TracerConcrete(ptr) {} + + public: + static void construct(void* storage, js::gc::SmallBuffer* ptr) { + new (storage) Concrete(ptr); + } + + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + + CoarseType coarseType() const final { return CoarseType::Object; } + + const char16_t* typeName() const override { return concreteTypeName; } + static const char16_t concreteTypeName[]; +}; + // The ubi::Node null pointer. Any attempt to operate on a null ubi::Node // asserts. template <> diff --git a/src/third_party/mozjs/extract/js/public/Utility.h b/src/third_party/mozjs/extract/js/public/Utility.h index 25e351d740f..d80e2cc06d3 100644 --- a/src/third_party/mozjs/extract/js/public/Utility.h +++ b/src/third_party/mozjs/extract/js/public/Utility.h @@ -43,6 +43,16 @@ extern MOZ_NORETURN MOZ_COLD JS_PUBLIC_API void JS_Assert(const char* s, # include "jscustomallocator.h" #else +/* + * MONGODB MODIFICATION: These functions are implemented by jscustomallocator + * This logic is unused when running Without JS_USE_CUSTOM_ALLOCATOR + */ +namespace mongo { +namespace sm { +JS_PUBLIC_API void check_oom_on_mmap_allocation(size_t bytes); +} // namespace sm +} // namespace mongo + namespace js { /* @@ -54,20 +64,22 @@ namespace js { * adding new thread types. */ enum ThreadType { - THREAD_TYPE_NONE = 0, // 0 - THREAD_TYPE_MAIN, // 1 - THREAD_TYPE_WASM_COMPILE_TIER1, // 2 - THREAD_TYPE_WASM_COMPILE_TIER2, // 3 - THREAD_TYPE_ION, // 4 - THREAD_TYPE_COMPRESS, // 5 - THREAD_TYPE_GCPARALLEL, // 6 - THREAD_TYPE_PROMISE_TASK, // 7 - THREAD_TYPE_ION_FREE, // 8 - THREAD_TYPE_WASM_GENERATOR_TIER2, // 9 - THREAD_TYPE_WORKER, // 10 - THREAD_TYPE_DELAZIFY, // 11 - THREAD_TYPE_DELAZIFY_FREE, // 12 - THREAD_TYPE_MAX // Used to check shell function arguments + THREAD_TYPE_NONE = 0, // 0 + THREAD_TYPE_MAIN, // 1 + THREAD_TYPE_WASM_COMPILE_TIER1, // 2 + THREAD_TYPE_WASM_COMPILE_TIER2, // 3 + THREAD_TYPE_BASELINE, // 4 + THREAD_TYPE_ION, // 5 + THREAD_TYPE_COMPRESS, // 6 + THREAD_TYPE_GCPARALLEL, // 7 + THREAD_TYPE_PROMISE_TASK, // 8 + THREAD_TYPE_ION_FREE, // 9 + THREAD_TYPE_WASM_GENERATOR_COMPLETE_TIER2, // 10 + THREAD_TYPE_WASM_COMPILE_PARTIAL_TIER2, // 11 + THREAD_TYPE_WORKER, // 12 + THREAD_TYPE_DELAZIFY, // 13 + THREAD_TYPE_DELAZIFY_FREE, // 14 + THREAD_TYPE_MAX // Used to check shell function arguments }; namespace oom { @@ -86,7 +98,7 @@ namespace oom { // Define the range of threads tested by simulated OOM testing and the // like. Testing worker threads is not supported. const ThreadType FirstThreadTypeToTest = THREAD_TYPE_MAIN; -const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_GENERATOR_TIER2; +const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_COMPILE_PARTIAL_TIER2; extern bool InitThreadType(void); extern void SetThreadType(ThreadType); @@ -95,7 +107,7 @@ extern JS_PUBLIC_API uint32_t GetThreadType(void); # else inline bool InitThreadType(void) { return true; } -inline void SetThreadType(ThreadType t){}; +inline void SetThreadType(ThreadType t) {}; inline uint32_t GetThreadType(void) { return 0; } inline uint32_t GetAllocationThreadType(void) { return 0; } inline uint32_t GetStackCheckThreadType(void) { return 0; } @@ -352,7 +364,21 @@ struct MOZ_RAII JS_PUBLIC_DATA AutoEnterOOMUnsafeRegion { namespace js { +// The following two arenas require a little bit of clarification. We have +// observed that, particularly on devices with heterogeneous CPU architectures +// where background work can run on significantly slower cores than main thread +// work, the lock contention in the allocator can be a big problem for the +// main thread. So we introduced an arena for background allocations which can +// reduce that contention. +// +// The general rule for these is: if it's easy to determine at the time of +// authorship that an allocation will be *off* the main thread, use the +// BackgroundMallocArena, and vice versa. If it is hard to determine, just make +// a guess, and that will be fine. Do not spend too much time on this, and +// don't do anything fancy at runtime to try to determine which to use. extern JS_PUBLIC_DATA arena_id_t MallocArena; +extern JS_PUBLIC_DATA arena_id_t BackgroundMallocArena; + extern JS_PUBLIC_DATA arena_id_t ArrayBufferContentsArena; extern JS_PUBLIC_DATA arena_id_t StringBufferArena; diff --git a/src/third_party/mozjs/extract/js/public/Value.h b/src/third_party/mozjs/extract/js/public/Value.h index 98f0f9273b2..c70d5b6888f 100644 --- a/src/third_party/mozjs/extract/js/public/Value.h +++ b/src/third_party/mozjs/extract/js/public/Value.h @@ -170,9 +170,6 @@ enum JSValueType : uint8_t { JSVAL_TYPE_SYMBOL = 0x07, JSVAL_TYPE_PRIVATE_GCTHING = 0x08, JSVAL_TYPE_BIGINT = 0x09, -#ifdef ENABLE_RECORD_TUPLE - JSVAL_TYPE_EXTENDED_PRIMITIVE = 0x0b, -#endif JSVAL_TYPE_OBJECT = 0x0c, // This type never appears in a Value; it's only an out-of-band value. @@ -191,9 +188,6 @@ enum class ValueType : uint8_t { Symbol = JSVAL_TYPE_SYMBOL, PrivateGCThing = JSVAL_TYPE_PRIVATE_GCTHING, BigInt = JSVAL_TYPE_BIGINT, -#ifdef ENABLE_RECORD_TUPLE - ExtendedPrimitive = JSVAL_TYPE_EXTENDED_PRIMITIVE, -#endif Object = JSVAL_TYPE_OBJECT, }; } // namespace JS @@ -214,10 +208,6 @@ enum JSValueTag : uint32_t { JSVAL_TAG_SYMBOL = JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL, JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING, JSVAL_TAG_BIGINT = JSVAL_TAG_CLEAR | JSVAL_TYPE_BIGINT, -# ifdef ENABLE_RECORD_TUPLE - JSVAL_TAG_EXTENDED_PRIMITIVE = - JSVAL_TAG_CLEAR | JSVAL_TYPE_EXTENDED_PRIMITIVE, -# endif JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT }; @@ -237,10 +227,6 @@ enum JSValueTag : uint32_t { JSVAL_TAG_SYMBOL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL, JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING, JSVAL_TAG_BIGINT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BIGINT, -# ifdef ENABLE_RECORD_TUPLE - JSVAL_TAG_EXTENDED_PRIMITIVE = - JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_EXTENDED_PRIMITIVE, -# endif JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT }; @@ -262,10 +248,6 @@ enum JSValueShiftedTag : uint64_t { JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (uint64_t(JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT), JSVAL_SHIFTED_TAG_BIGINT = (uint64_t(JSVAL_TAG_BIGINT) << JSVAL_TAG_SHIFT), -# ifdef ENABLE_RECORD_TUPLE - JSVAL_SHIFTED_TAG_EXTENDED_PRIMITIVE = - (uint64_t(JSVAL_TYPE_EXTENDED_PRIMITIVE) << JSVAL_TAG_SHIFT), -# endif JSVAL_SHIFTED_TAG_OBJECT = (uint64_t(JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) }; @@ -403,14 +385,7 @@ class JS_PUBLIC_API GenericPrinter; class JSONPrinter; static inline JS::Value PoisonedObjectValue(uintptr_t poison); -#ifdef ENABLE_RECORD_TUPLE -// Re-defined in vm/RecordTupleBoxShared.h. We cannot include that -// file because it circularly includes this one. -bool IsExtendedPrimitive(const JSObject& obj); -namespace gc { -bool MaybeForwardedIsExtendedPrimitive(const JSObject& obj); -} // namespace gc -#endif + } // namespace js namespace JS { @@ -631,23 +606,10 @@ class alignas(8) Value { void setObject(JSObject& obj) { MOZ_ASSERT(js::gc::IsCellPointerValid(&obj)); -#ifdef ENABLE_RECORD_TUPLE - MOZ_ASSERT(!js::gc::MaybeForwardedIsExtendedPrimitive(obj)); -#endif setObjectNoCheck(&obj); MOZ_ASSERT(&toObject() == &obj); } -#ifdef ENABLE_RECORD_TUPLE - void setExtendedPrimitive(JSObject& obj) { - MOZ_ASSERT(js::gc::IsCellPointerValid(&obj)); - MOZ_ASSERT(js::gc::MaybeForwardedIsExtendedPrimitive(obj)); - asBits_ = - bitsFromTagAndPayload(JSVAL_TAG_EXTENDED_PRIMITIVE, PayloadType(&obj)); - MOZ_ASSERT(&toExtendedPrimitive() == &obj); - } -#endif - void changeGCThingPayload(js::gc::Cell* cell) { MOZ_ASSERT(js::gc::IsCellPointerValid(cell)); #ifdef DEBUG @@ -813,6 +775,8 @@ class alignas(8) Value { bool isDouble() const { return detail::ValueIsDouble(asBits_); } + bool isNaN() const { return isDouble() && std::isnan(toDouble()); } + bool isNumber() const { #if defined(JS_NUNBOX32) MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR); @@ -837,16 +801,6 @@ class alignas(8) Value { #endif } -#ifdef ENABLE_RECORD_TUPLE - bool isExtendedPrimitive() const { - return toTag() == JSVAL_TAG_EXTENDED_PRIMITIVE; - } -#endif - - bool hasObjectPayload() const { - return isObject() || IF_RECORD_TUPLE(isExtendedPrimitive(), false); - } - bool isPrimitive() const { #if defined(JS_NUNBOX32) return uint32_t(toTag()) < uint32_t(detail::ValueUpperExclPrimitiveTag); @@ -910,11 +864,6 @@ class alignas(8) Value { if (MOZ_UNLIKELY(isPrivateGCThing())) { return JS::GCThingTraceKind(toGCThing()); } -#ifdef ENABLE_RECORD_TUPLE - if (isExtendedPrimitive()) { - return JS::TraceKind::Object; - } -#endif return JS::TraceKind(toTag() & 0x03); } @@ -990,24 +939,6 @@ class alignas(8) Value { #endif } -#ifdef ENABLE_RECORD_TUPLE - JSObject& toExtendedPrimitive() const { - MOZ_ASSERT(isExtendedPrimitive()); -# if defined(JS_PUNBOX64) - MOZ_ASSERT((asBits_ & detail::ValueGCThingPayloadMask) != 0); -# endif - return *unboxGCPointer(); - } -#endif - - JSObject& getObjectPayload() const { -#ifdef ENABLE_RECORD_TUPLE - return isExtendedPrimitive() ? toExtendedPrimitive() : toObject(); -#else - return toObject(); -#endif - } - js::gc::Cell* toGCThing() const { MOZ_ASSERT(isGCThing()); #if defined(JS_NUNBOX32) @@ -1224,14 +1155,6 @@ static inline Value ObjectValue(JSObject& obj) { return v; } -#ifdef ENABLE_RECORD_TUPLE -static inline Value ExtendedPrimitiveValue(JSObject& obj) { - Value v; - v.setExtendedPrimitive(obj); - return v; -} -#endif - static inline Value MagicValue(JSWhyMagic why) { Value v; v.setMagic(why); @@ -1329,6 +1252,10 @@ struct BarrierMethods { static gc::Cell* asGCThingOrNull(const JS::Value& v) { return v.isGCThing() ? v.toGCThing() : nullptr; } + static void writeBarriers(JS::Value* v, const JS::Value& prev, + const JS::Value& next) { + JS::HeapValueWriteBarriers(v, prev, next); + } static void postWriteBarrier(JS::Value* v, const JS::Value& prev, const JS::Value& next) { JS::HeapValuePostWriteBarrier(v, prev, next); @@ -1370,10 +1297,6 @@ class WrappedPtrOperations { bool isSymbol() const { return value().isSymbol(); } bool isBigInt() const { return value().isBigInt(); } bool isObject() const { return value().isObject(); } -#ifdef ENABLE_RECORD_TUPLE - bool isExtendedPrimitive() const { return value().isExtendedPrimitive(); } -#endif - bool hasObjectPayload() const { return value().hasObjectPayload(); } bool isMagic() const { return value().isMagic(); } bool isMagic(JSWhyMagic why) const { return value().isMagic(why); } bool isGCThing() const { return value().isGCThing(); } @@ -1393,12 +1316,6 @@ class WrappedPtrOperations { JS::BigInt* toBigInt() const { return value().toBigInt(); } JSObject& toObject() const { return value().toObject(); } JSObject* toObjectOrNull() const { return value().toObjectOrNull(); } -#ifdef ENABLE_RECORD_TUPLE - JSObject& toExtendedPrimitive() const { - return value().toExtendedPrimitive(); - } -#endif - JSObject& getObjectPayload() const { return value().getObjectPayload(); } JS::GCCellPtr toGCCellPtr() const { return value().toGCCellPtr(); } gc::Cell* toGCThing() const { return value().toGCThing(); } JS::TraceKind traceKind() const { return value().traceKind(); } @@ -1448,11 +1365,6 @@ class MutableWrappedPtrOperations void setBigInt(JS::BigInt* bi) { set(JS::BigIntValue(bi)); } void setObject(JSObject& obj) { set(JS::ObjectValue(obj)); } void setObjectOrNull(JSObject* arg) { set(JS::ObjectOrNullValue(arg)); } -#ifdef ENABLE_RECORD_TUPLE - void setExtendedPrimitive(JSObject& obj) { - return set(JS::ExtendedPrimitiveValue(obj)); - } -#endif void setPrivate(void* ptr) { set(JS::PrivateValue(ptr)); } void setPrivateUint32(uint32_t ui) { set(JS::PrivateUint32Value(ui)); } void setPrivateGCThing(js::gc::Cell* cell) { @@ -1481,11 +1393,8 @@ auto MapGCThingTyped(const JS::Value& val, F&& f) { MOZ_ASSERT(gc::IsCellPointerValid(str)); return mozilla::Some(f(str)); } -#ifdef ENABLE_RECORD_TUPLE - case JS::ValueType::ExtendedPrimitive: -#endif case JS::ValueType::Object: { - JSObject* obj = &val.getObjectPayload(); + JSObject* obj = &val.toObject(); MOZ_ASSERT(gc::IsCellPointerValid(obj)); return mozilla::Some(f(obj)); } diff --git a/src/third_party/mozjs/extract/js/public/WasmFeatures.h b/src/third_party/mozjs/extract/js/public/WasmFeatures.h index 30c1bcca26b..82fb41e7e58 100644 --- a/src/third_party/mozjs/extract/js/public/WasmFeatures.h +++ b/src/third_party/mozjs/extract/js/public/WasmFeatures.h @@ -42,11 +42,6 @@ #else # define WASM_RELAXED_SIMD_ENABLED 0 #endif -#ifdef ENABLE_WASM_GC -# define WASM_GC_ENABLED 1 -#else -# define WASM_GC_ENABLED 0 -#endif #ifdef ENABLE_WASM_MEMORY64 # define WASM_MEMORY64_ENABLED 1 #else @@ -57,11 +52,6 @@ #else # define WASM_MEMORY_CONTROL_ENABLED 0 #endif -#ifdef ENABLE_WASM_TAIL_CALLS -# define WASM_TAIL_CALLS_ENABLED 1 -#else -# define WASM_TAIL_CALLS_ENABLED 0 -#endif #ifdef ENABLE_WASM_JSPI # define WASM_JSPI_ENABLED 1 #else @@ -99,15 +89,6 @@ /* flag force enable */ false, \ /* flag fuzz enable */ true, \ /* preference name */ exnref) \ - FEATURE( \ - /* capitalized name */ Gc, \ - /* lower case name */ gc, \ - /* compile predicate */ WASM_GC_ENABLED, \ - /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ true, \ - /* flag force enable */ false, \ - /* flag fuzz enable */ false, \ - /* preference name */ gc) \ FEATURE( \ /* capitalized name */ JSStringBuiltins, \ /* lower case name */ jsStringBuiltins, \ @@ -153,30 +134,21 @@ /* flag force enable */ false, \ /* flag fuzz enable */ true, \ /* preference name */ multi_memory) \ - FEATURE( \ - /* capitalized name */ TailCalls, \ - /* lower case name */ tailCalls, \ - /* compile predicate */ WASM_TAIL_CALLS_ENABLED, \ - /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ true, \ - /* flag force enable */ false, \ - /* flag fuzz enable */ true, \ - /* preference name */ tail_calls) \ FEATURE( \ /* capitalized name */ JSPromiseIntegration, \ /* lower case name */ jsPromiseIntegration, \ /* compile predicate */ WASM_JSPI_ENABLED, \ - /* compiler predicate */ IonAvailable(cx), \ + /* compiler predicate */ IonPlatformSupport(), \ /* flag predicate */ true, \ /* flag force enable */ false, \ - /* flag fuzz enable */ false, \ + /* flag fuzz enable */ true, \ /* preference name */ js_promise_integration) \ FEATURE( \ /* capitalized name */ MozIntGemm, \ /* lower case name */ mozIntGemm, \ /* compile predicate */ WASM_MOZ_INTGEMM_ENABLED, \ /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ IsSimdPrivilegedContext(cx), \ + /* flag predicate */ IsPrivilegedContext(cx), \ /* flag force enable */ false, \ /* flag fuzz enable */ false, \ /* preference name */ moz_intgemm) \ @@ -196,7 +168,7 @@ /* compiler predicate */ IonAvailable(cx), \ /* flag predicate */ true, \ /* flag force enable */ false, \ - /* flag fuzz enable */ false, \ + /* flag fuzz enable */ true, \ /* preference name */ branch_hinting) // clang-format on diff --git a/src/third_party/mozjs/extract/js/public/Wrapper.h b/src/third_party/mozjs/extract/js/public/Wrapper.h index 197d76f11fc..75f1e3132dd 100644 --- a/src/third_party/mozjs/extract/js/public/Wrapper.h +++ b/src/third_party/mozjs/extract/js/public/Wrapper.h @@ -255,6 +255,9 @@ class JS_PUBLIC_API CrossCompartmentWrapper : public Wrapper { // Allocate CrossCompartmentWrappers in the nursery. virtual bool canNurseryAllocate() const override { return true; } + void finalize(JS::GCContext* gcx, JSObject* proxy) const final { + Wrapper::finalize(gcx, proxy); + } static const CrossCompartmentWrapper singleton; static const CrossCompartmentWrapper singletonWithPrototype; diff --git a/src/third_party/mozjs/extract/js/public/experimental/BindingAllocs.h b/src/third_party/mozjs/extract/js/public/experimental/BindingAllocs.h new file mode 100644 index 00000000000..d033cbda61d --- /dev/null +++ b/src/third_party/mozjs/extract/js/public/experimental/BindingAllocs.h @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Special allocation functions for DOM binding code. + * + */ + +#ifndef js_experimental_BindingAllocs_h +#define js_experimental_BindingAllocs_h + +#include "jstypes.h" + +/** + * Unlike JS_NewObject, JS_NewObjectWithGivenProtoAndUseAllocSite does not + * compute a default proto. If proto is nullptr, the JS object will have `null` + * as [[Prototype]]. + * + * If the JIT code has set an allocation site, this allocation will consume that + * allocation site. This only happens for DOM calls with Object return type. + * + * Must be called with a non-null clasp. + * + */ +extern JS_PUBLIC_API JSObject* JS_NewObjectWithGivenProtoAndUseAllocSite( + JSContext* cx, const JSClass* clasp, JS::Handle proto); + +#endif // js_experimental_BindingAllocs_h diff --git a/src/third_party/mozjs/extract/js/public/experimental/JSStencil.h b/src/third_party/mozjs/extract/js/public/experimental/JSStencil.h index 780c3e1c627..5423f28c295 100644 --- a/src/third_party/mozjs/extract/js/public/experimental/JSStencil.h +++ b/src/third_party/mozjs/extract/js/public/experimental/JSStencil.h @@ -38,6 +38,7 @@ struct CompilationStencil; struct CompilationGCOutput; struct CompilationInput; struct PreallocatedCompilationGCOutput; +struct InitialStencilAndDelazifications; } // namespace frontend } // namespace js @@ -47,7 +48,7 @@ struct PreallocatedCompilationGCOutput; namespace JS { -using Stencil = js::frontend::CompilationStencil; +using Stencil = js::frontend::InitialStencilAndDelazifications; using FrontendContext = js::FrontendContext; // Temporary storage used during instantiating Stencil. @@ -193,6 +194,7 @@ extern JS_PUBLIC_API JSObject* InstantiateModuleStencil( namespace JS { // Serialize the Stencil into the transcode buffer. +// This fails if the stencil contains asm.js. extern JS_PUBLIC_API TranscodeResult EncodeStencil(JSContext* cx, Stencil* stencil, TranscodeBuffer& buffer); @@ -205,10 +207,59 @@ extern JS_PUBLIC_API TranscodeResult DecodeStencil(JS::FrontendContext* fc, const ReadOnlyDecodeOptions& options, const TranscodeRange& range, Stencil** stencilOut); -// Register an encoder on its script source, such that all functions can be -// encoded as they are delazified. -extern JS_PUBLIC_API bool StartIncrementalEncoding(JSContext* cx, - RefPtr&& stencil); +// ************************************************************************ +// Collect delazifications +// ************************************************************************ + +// Start collecting delazifications for given script or module's source object. +// +// If the source object is already collecting delazifications, alreadyStarted is +// set to true and returns true. alreadyStarted is set to false otherwise. +extern JS_PUBLIC_API bool StartCollectingDelazifications( + JSContext* cx, JS::Handle script, Stencil* stencil, + bool& alreadyStarted); + +extern JS_PUBLIC_API bool StartCollectingDelazifications( + JSContext* cx, JS::Handle module, Stencil* stencil, + bool& alreadyStarted); + +// Finish collecting delazifications and retrieve the result. +// +// With |buffer| out-parameter, the result is encoded and appended to the +// buffer. If failed, the content of |buffer| would be undefined. +// +// If the `buffer` isn't empty, the start of the `buffer` should meet +// JS::IsTranscodingBytecodeAligned, and the length should meet +// JS::IsTranscodingBytecodeOffsetAligned. +// +// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means +// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, +// IsTranscodingBytecodeAligned should be guaranteed to meet by +// malloc, used by MallocAllocPolicy in mozilla::Vector. +extern JS_PUBLIC_API bool FinishCollectingDelazifications( + JSContext* cx, Handle script, TranscodeBuffer& buffer); + +// Similar to |JS::FinishCollectingDelazifications|, but receives module obect. +extern JS_PUBLIC_API bool FinishCollectingDelazifications( + JSContext* cx, Handle module, TranscodeBuffer& buffer); + +// Instead of transcoding to a buffer, return the JS::Stencil that reflects +// the delazification from the execution. +extern JS_PUBLIC_API bool FinishCollectingDelazifications( + JSContext* cx, Handle script, JS::Stencil** stencilOut); + +extern JS_PUBLIC_API void AbortCollectingDelazifications( + Handle script); +extern JS_PUBLIC_API void AbortCollectingDelazifications( + Handle module); + +// ************************************************************************ +// Cache +// ************************************************************************ + +// Returns true if the stencil is compatible with caching. +// This returns false if the stencil contains asm.js. +extern JS_PUBLIC_API bool IsStencilCacheable(JS::Stencil* stencil); } // namespace JS diff --git a/src/third_party/mozjs/extract/js/public/experimental/LoggingInterface.h b/src/third_party/mozjs/extract/js/public/experimental/LoggingInterface.h new file mode 100644 index 00000000000..4ee3c13f384 --- /dev/null +++ b/src/third_party/mozjs/extract/js/public/experimental/LoggingInterface.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// An experimental logging interface for connecting the JS Engine to some +// (*cough*Gecko*cough*) consumer. + +#ifndef _js_experimental_LoggingInterface_h_ +#define _js_experimental_LoggingInterface_h_ + +#include "mozilla/LoggingCore.h" + +#include "jstypes.h" +#include "fmt/format.h" +#include "js/GCAPI.h" + +struct JSContext; + +namespace JS { + +// An Opaque pointer to a LoggerType. It must be possible for this logger type +// to conform to the interface below, using the LogLevel type exported in +// mozglue LoggingCore.h +// +// There are some requirements that we cannot express through the type-system: +// +// - A Logger must outlive any caller. This is an obvious statement, but in the +// context of the JS engine means that a logger must live until after the JS +// engine is shutdown. +// - A logger cannot move. The logging interfaces assumes 1) That an +// OpaqueLogger will remain a valid handle to a logger for the entire duration +// of an initialize JS library, and 2) We are able to cache a reference to the +// log level of a particular logger (see getLevelRef below). +using OpaqueLogger = void*; + +// [SMDOC] Logging Interface +// +// The logging interface contains a set of function pointers which explain how +// to talk to an embedder provided logging system. +// +// The design of the JS Consumer of this relies heavily on these to be freely +// copyable. +struct LoggingInterface { + // Acquire a new logger for a given name. + // + // This interface has no way of indicating backwards that a logger is no + // longer needed, and as such this pointer needs to be kept alive by the + // embedding for the lifetime of the JS engine. + OpaqueLogger (*getLoggerByName)(const char* loggerName) = nullptr; + + // Print a message to a particular logger with a particular level and + // format. + void (*logPrintVA)(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + const char* aFmt, va_list ap) + MOZ_FORMAT_PRINTF(3, 0) = nullptr; + + void (*logPrintFMT)(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + fmt::string_view, fmt::format_args); + + // Return a reference to the provided OpaqueLogger's level ref; Implementation + // wise this can be a small violation of encapsulation but is intended to help + // ensure that we can build lightweight logging without egregious costs to + // simply check even if a mesage will the writen + mozilla::AtomicLogLevel& (*getLevelRef)(OpaqueLogger) = nullptr; + + // Wrapper function for calling va-version + void logPrint(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + const char* aFmt, ...) MOZ_FORMAT_PRINTF(4, 5) { + JS::AutoSuppressGCAnalysis suppress; + va_list ap; + va_start(ap, aFmt); + this->logPrintVA(aModule, aLevel, aFmt, ap); + va_end(ap); + } + + template + void logPrintFmt(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + fmt::format_string aFmt, T&&... aArgs) { + JS::AutoSuppressGCAnalysis suppress; + this->logPrintFMT(aModule, aLevel, aFmt, fmt::make_format_args(aArgs...)); + } + + // Used to ensure that before we use an interface, it's successfully been + // completely filled in. + bool isComplete() const { + return getLoggerByName && logPrintVA && getLevelRef; + } +}; + +// Install the logging interface. This will also install the interface into +// any JS loggers +extern JS_PUBLIC_API bool SetLoggingInterface(LoggingInterface& iface); + +} // namespace JS + +#endif /* _js_experimental_LoggingInterface_h_ */ diff --git a/src/third_party/mozjs/extract/js/public/experimental/TypedData.h b/src/third_party/mozjs/extract/js/public/experimental/TypedData.h index 39d691b039d..61bb1306d67 100644 --- a/src/third_party/mozjs/extract/js/public/experimental/TypedData.h +++ b/src/third_party/mozjs/extract/js/public/experimental/TypedData.h @@ -135,8 +135,6 @@ namespace js { extern JS_PUBLIC_API JSObject* UnwrapArrayBufferView(JSObject* obj); -extern JS_PUBLIC_API JSObject* UnwrapReadableStream(JSObject* obj); - namespace detail { constexpr size_t TypedArrayLengthSlot = 1; @@ -710,6 +708,11 @@ struct BarrierMethods> { static gc::Cell* asGCThingOrNull(T view) { return reinterpret_cast(view.asObjectUnbarriered()); } + static void writeBarriers(T* viewp, T prev, T next) { + BarrierMethods::writeBarriers(viewp->addressOfObject(), + prev.asObjectUnbarriered(), + next.asObjectUnbarriered()); + } static void postWriteBarrier(T* viewp, T prev, T next) { BarrierMethods::postWriteBarrier(viewp->addressOfObject(), prev.asObjectUnbarriered(), diff --git a/src/third_party/mozjs/extract/js/public/friend/ErrorNumbers.msg b/src/third_party/mozjs/extract/js/public/friend/ErrorNumbers.msg index 3155e3179e7..e01318afe3e 100644 --- a/src/third_party/mozjs/extract/js/public/friend/ErrorNumbers.msg +++ b/src/third_party/mozjs/extract/js/public/friend/ErrorNumbers.msg @@ -136,7 +136,7 @@ MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class construc MSG_DEF(JSMSG_BAD_HERITAGE, 2, JSEXN_TYPEERR, "class heritage {0} is {1}") MSG_DEF(JSMSG_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0} is not an object or null") MSG_DEF(JSMSG_CONSTRUCTOR_DISABLED, 1, JSEXN_TYPEERR, "{0} is disabled") -MSG_DEF(JSMSG_NO_DISPOSE_IN_USING, 0, JSEXN_TYPEERR, "'Symbol.dispose' property is not callable") +MSG_DEF(JSMSG_DISPOSE_NOT_CALLABLE, 0, JSEXN_TYPEERR, "'Symbol.dispose' property is not callable") MSG_DEF(JSMSG_DISPOSABLE_NOT_OBJ, 0, JSEXN_TYPEERR, "Value to be disposed is not an object") // JSON @@ -225,8 +225,11 @@ MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC, 0, JSEXN_SYNTAXERR, "await is only valid MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC_OR_MODULE, 0, JSEXN_SYNTAXERR, "await is only valid in async functions, async generators and modules") MSG_DEF(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "top level await is not supported in this context") MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)") +MSG_DEF(JSMSG_BAD_CLASS_MEMBER_DEF, 0, JSEXN_SYNTAXERR, "bad class member definition") MSG_DEF(JSMSG_BAD_COALESCE_MIXING, 0, JSEXN_SYNTAXERR, "cannot use `??` unparenthesized within `||` and `&&` expressions") MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration") +MSG_DEF(JSMSG_BAD_USING_DECL, 0, JSEXN_SYNTAXERR, "missing = in using declaration") +MSG_DEF(JSMSG_BAD_CONSTRUCTOR_DEF, 0, JSEXN_SYNTAXERR, "a class constructor definition must be a plain public method") MSG_DEF(JSMSG_BAD_CONTINUE, 0, JSEXN_SYNTAXERR, "continue must be inside loop") MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 0, JSEXN_SYNTAXERR, "invalid destructuring assignment operator") MSG_DEF(JSMSG_BAD_DESTRUCT_TARGET, 0, JSEXN_SYNTAXERR, "invalid destructuring target") @@ -239,7 +242,6 @@ MSG_DEF(JSMSG_BAD_STARTING_FOROF_LHS, 1, JSEXN_SYNTAXERR, "an expression X in ' MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand") MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side") MSG_DEF(JSMSG_BAD_LOCAL_STRING_EXPORT, 0, JSEXN_SYNTAXERR, "string exports can't be used without 'from'") -MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition") MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'") MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id") MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function") @@ -258,6 +260,7 @@ MSG_DEF(JSMSG_BRACKET_OPENED, 2, JSEXN_NOTE, "[ opened at line {0}, col MSG_DEF(JSMSG_CATCH_IDENTIFIER, 0, JSEXN_SYNTAXERR, "missing identifier in catch") MSG_DEF(JSMSG_CATCH_OR_FINALLY, 0, JSEXN_SYNTAXERR, "missing catch or finally after try") MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "catch without try") +MSG_DEF(JSMSG_CLASS_STATIC_PROTO, 0, JSEXN_SYNTAXERR, "a class may not have a static property named 'prototype'") MSG_DEF(JSMSG_COLON_AFTER_CASE, 0, JSEXN_SYNTAXERR, "missing : after case label") MSG_DEF(JSMSG_COLON_AFTER_ID, 0, JSEXN_SYNTAXERR, "missing : after property id") MSG_DEF(JSMSG_COLON_IN_COND, 0, JSEXN_SYNTAXERR, "missing : in conditional expression") @@ -282,10 +285,10 @@ MSG_DEF(JSMSG_DEPRECATED_OCTAL_LITERAL,0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal MSG_DEF(JSMSG_DEPRECATED_OCTAL_ESCAPE ,0, JSEXN_SYNTAXERR, "octal escape sequences can't be used in untagged template literals or in strict mode code") MSG_DEF(JSMSG_DEPRECATED_EIGHT_OR_NINE_ESCAPE, 0, JSEXN_SYNTAXERR, "the escapes \\8 and \\9 can't be used in untagged template literals or in strict mode code") MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_WARN, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead") +MSG_DEF(JSMSG_DUPLICATE_CONSTRUCTOR, 0, JSEXN_SYNTAXERR, "a class cannot have more than one constructor definition") MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export name '{0}'") MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}") MSG_DEF(JSMSG_DUPLICATE_LABEL, 0, JSEXN_SYNTAXERR, "duplicate label") -MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal") MSG_DEF(JSMSG_DUPLICATE_PROTO_PROPERTY, 0, JSEXN_SYNTAXERR, "property name __proto__ appears more than once in object literal") MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?") MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level of a module") @@ -328,7 +331,7 @@ MSG_DEF(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT, 0, JSEXN_SYNTAXERR, "expected n MSG_DEF(JSMSG_NO_BINDING_NAME, 0, JSEXN_SYNTAXERR, "missing binding name") MSG_DEF(JSMSG_NO_EXPORT_NAME, 0, JSEXN_SYNTAXERR, "missing export name") MSG_DEF(JSMSG_NO_IMPORT_NAME, 0, JSEXN_SYNTAXERR, "missing import name") -MSG_DEF(JSMSG_NO_VARIABLE_NAME, 0, JSEXN_SYNTAXERR, "missing variable name") +MSG_DEF(JSMSG_NO_VARIABLE_NAME, 1, JSEXN_SYNTAXERR, "missing variable name, got {0}") MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 0, JSEXN_SYNTAXERR, "missing ) after argument list") MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing ) after catch") MSG_DEF(JSMSG_PAREN_AFTER_COND, 0, JSEXN_SYNTAXERR, "missing ) after condition") @@ -388,7 +391,7 @@ MSG_DEF(JSMSG_BAD_LINE_NUMBER, 0, JSEXN_RANGEERR, "line number out of ra MSG_DEF(JSMSG_BAD_NEWTARGET, 0, JSEXN_SYNTAXERR, "new.target only allowed within functions") MSG_DEF(JSMSG_BAD_NEW_OPTIONAL, 0, JSEXN_SYNTAXERR, "new keyword cannot be used with an optional chain") MSG_DEF(JSMSG_BAD_OPTIONAL_TEMPLATE, 0, JSEXN_SYNTAXERR, "tagged template cannot be used with optional chain") -MSG_DEF(JSMSG_IMPORT_ASSERTIONS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "import assertions are not currently supported") +MSG_DEF(JSMSG_IMPORT_ATTRIBUTES_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "import attributes are not currently supported") MSG_DEF(JSMSG_ILLEGAL_PRIVATE_FIELD, 0, JSEXN_SYNTAXERR, "private fields aren't valid in this context") MSG_DEF(JSMSG_ILLEGAL_PRIVATE_NAME, 0, JSEXN_SYNTAXERR, "private names aren't valid in this context") MSG_DEF(JSMSG_INVALID_PRIVATE_NAME_PRECEDENCE, 0, JSEXN_SYNTAXERR, "invalid use of private name due to operator precedence") @@ -419,10 +422,6 @@ MSG_DEF(JSMSG_CANT_CONVERT_TO_WIDE, 0, JSEXN_ERR, "can't convert to wide stri MSG_DEF(JSMSG_CANT_CONVERT_WIDE_TO_UTF8, 0, JSEXN_ERR, "can't convert wide string to UTF-8") MSG_DEF(JSMSG_CANT_CONVERT_UTF8_TO_WIDE, 0, JSEXN_ERR, "can't convert UTF-8 to wide string") -// SmooshMonkey -MSG_DEF(JSMSG_SMOOSH_COMPILE_ERROR, 1, JSEXN_SYNTAXERR, "{0}") -MSG_DEF(JSMSG_SMOOSH_UNIMPLEMENTED, 1, JSEXN_INTERNALERR, "{0}") - // asm.js MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}") MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 1, JSEXN_TYPEERR, "asm.js link error: {0}") @@ -437,7 +436,7 @@ MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}") MSG_DEF(JSMSG_WASM_BAD_IMPORT_TYPE, 2, JSEXN_WASMLINKERROR, "import object field '{0}' is not a {1}") MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 2, JSEXN_WASMLINKERROR, "imported function '{0}.{1}' signature mismatch") MSG_DEF(JSMSG_WASM_BAD_TAG_SIG, 2, JSEXN_WASMLINKERROR, "imported tag '{0}.{1}' signature mismatch") -MSG_DEF(JSMSG_WASM_BAD_IMP_INDEX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible index type") +MSG_DEF(JSMSG_WASM_BAD_IMP_ADDRESS, 2, JSEXN_WASMLINKERROR, "imported {0} with incompatible address type {1}") MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible size") MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible maximum size") MSG_DEF(JSMSG_WASM_IMP_SHARED_REQD, 0, JSEXN_WASMLINKERROR, "imported unshared memory but shared required") @@ -464,6 +463,7 @@ MSG_DEF(JSMSG_WASM_ARRAY_IMP_LIMIT, 0, JSEXN_WASMRUNTIMEERROR, "too many arra MSG_DEF(JSMSG_WASM_ARRAY_NEW_ELEM_NOT_IMPLEMENTED, 0, JSEXN_WASMRUNTIMEERROR, "array.new_elem does not yet support the expression encoding of element segments") MSG_DEF(JSMSG_WASM_BAD_RANGE, 2, JSEXN_RANGEERR, "bad {0} {1}") MSG_DEF(JSMSG_WASM_BAD_GROW, 1, JSEXN_RANGEERR, "failed to grow {0}") +MSG_DEF(JSMSG_WASM_MAX_LT_INITIAL, 1, JSEXN_RANGEERR, "initial {0} size cannot be greater than maximum") MSG_DEF(JSMSG_WASM_TABLE_OUT_OF_BOUNDS, 0, JSEXN_WASMRUNTIMEERROR, "table index out of bounds") MSG_DEF(JSMSG_WASM_BAD_ENFORCE_RANGE, 2, JSEXN_TYPEERR, "bad {0} {1}") MSG_DEF(JSMSG_WASM_BAD_BUF_ARG, 0, JSEXN_TYPEERR, "first argument must be an ArrayBuffer or typed array object") @@ -485,15 +485,15 @@ MSG_DEF(JSMSG_WASM_BAD_ARRAYREF_VALUE, 0, JSEXN_TYPEERR, "can only pass a W MSG_DEF(JSMSG_WASM_BAD_TYPEREF_VALUE, 0, JSEXN_TYPEERR, "bad type") MSG_DEF(JSMSG_WASM_BAD_VAL_TYPE, 0, JSEXN_TYPEERR, "cannot pass value to or from JS") MSG_DEF(JSMSG_WASM_BAD_STRING_VAL_TYPE, 0, JSEXN_TYPEERR, "bad value type") -MSG_DEF(JSMSG_WASM_BAD_STRING_IDX_TYPE, 0, JSEXN_TYPEERR, "bad index type") +MSG_DEF(JSMSG_WASM_BAD_STRING_ADDR_TYPE, 0, JSEXN_TYPEERR, "bad address type") MSG_DEF(JSMSG_WASM_BAD_EXN_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Tag") MSG_DEF(JSMSG_WASM_BAD_EXN_PAYLOAD, 0, JSEXN_TYPEERR, "second argument must be an object") MSG_DEF(JSMSG_WASM_BAD_EXN_PAYLOAD_LEN, 2, JSEXN_TYPEERR, "expected {0} values but got {1}") MSG_DEF(JSMSG_WASM_BAD_EXN_TAG, 0, JSEXN_TYPEERR, "exception's tag did not match the provided exception tag") MSG_DEF(JSMSG_WASM_BAD_EXN_OPTIONS, 0, JSEXN_TYPEERR, "argument cannot be converted to an ExceptionOptions") +MSG_DEF(JSMSG_WASM_BAD_FUNCTION_TYPE, 1, JSEXN_TYPEERR, "too many function {0}") MSG_DEF(JSMSG_WASM_BAD_FUNCTION_VALUE, 0, JSEXN_TYPEERR, "second argument must be a function") MSG_DEF(JSMSG_WASM_BAD_COMPILE_OPTIONS, 0, JSEXN_TYPEERR, "argument cannot be converted to a CompileOptions") -MSG_DEF(JSMSG_WASM_UNKNOWN_BUILTIN, 0, JSEXN_TYPEERR, "unknown builtin") MSG_DEF(JSMSG_WASM_DUPLICATE_BUILTIN, 0, JSEXN_TYPEERR, "duplicate builtin") MSG_DEF(JSMSG_WASM_BAD_CODEPOINT, 0, JSEXN_WASMRUNTIMEERROR, "bad codepoint") MSG_DEF(JSMSG_WASM_NO_TRANSFER, 0, JSEXN_TYPEERR, "cannot transfer WebAssembly/asm.js ArrayBuffer") @@ -505,15 +505,22 @@ MSG_DEF(JSMSG_WASM_NONSHARED_WAIT, 0, JSEXN_WASMRUNTIMEERROR, "atomic wait o MSG_DEF(JSMSG_WASM_SUPPLY_ONLY_ONE, 2, JSEXN_TYPEERR, "exactly one of {0} and {1} must be supplied") MSG_DEF(JSMSG_WASM_MISSING_REQUIRED, 1, JSEXN_TYPEERR, "Missing required argument {0}") MSG_DEF(JSMSG_WASM_MODIFIED_GC_OBJECT, 0, JSEXN_TYPEERR, "can't modify WebAssembly GC objects") +MSG_DEF(JSMSG_WASM_ARRAYBUFFER_PAGE_MULTIPLE, 0, JSEXN_RANGEERR, "can only grow by WebAssembly page multiples") +MSG_DEF(JSMSG_WASM_ARRAYBUFFER_CANNOT_SHRINK, 0, JSEXN_RANGEERR, "cannot shrink WebAssembly memory") +MSG_DEF(JSMSG_WASM_MEMORY_NOT_RESIZABLE, 0, JSEXN_TYPEERR, "WebAssembly memory non-resizable, maximum length is not provided") + +// Wasm/asm.js deprecation warnings +MSG_DEF(JSMSG_WASM_LEGACY_EXCEPTIONS_DEPRECATED, 0, JSEXN_WARN, "The WebAssembly exception handling 'try' instruction is deprecated and should no longer be used. Please recompile to use the 'try_table' instruction instead.") +MSG_DEF(JSMSG_USE_ASM_DEPRECATED, 0, JSEXN_WARN, "asm.js is deprecated and should no longer be used. Please recompile using WebAssembly to get the best performance.") // JSPI -MSG_DEF(JSMSG_JSPI_ARG_POSITION, 0, JSEXN_TYPEERR, "Invalid argument position value") -MSG_DEF(JSMSG_JSPI_INVALID_SUSPENDER, 0, JSEXN_WASMRUNTIMEERROR, "Invalid suspender") -MSG_DEF(JSMSG_JSPI_INVALID_STATE, 0, JSEXN_WASMRUNTIMEERROR, "Invalid state") -MSG_DEF(JSMSG_JSPI_EXPECTED_SUSPENDER, 0, JSEXN_TYPEERR, "Expected externref for suspender") -MSG_DEF(JSMSG_JSPI_EXPECTED_PROMISE, 0, JSEXN_TYPEERR, "Expected externref for returned promise") -MSG_DEF(JSMSG_JSPI_SIGNATURE_MISMATCH, 0, JSEXN_TYPEERR, "Signature mismatch") -MSG_DEF(JSMSG_JSPI_SUSPENDER_LIMIT, 0, JSEXN_WASMRUNTIMEERROR, "Too many suspenders") +MSG_DEF(JSMSG_JSPI_ARG_POSITION, 0, JSEXN_TYPEERR, "Invalid argument position value") +MSG_DEF(JSMSG_JSPI_INVALID_SUSPENDER, 0, IF_WASM_JSPI(JSEXN_WASMSUSPENDERROR, JSEXN_WASMRUNTIMEERROR), "Invalid suspender") +MSG_DEF(JSMSG_JSPI_INVALID_STATE, 0, IF_WASM_JSPI(JSEXN_WASMSUSPENDERROR, JSEXN_WASMRUNTIMEERROR), "Invalid state") +MSG_DEF(JSMSG_JSPI_EXPECTED_SUSPENDER, 0, JSEXN_TYPEERR, "Expected externref for suspender") +MSG_DEF(JSMSG_JSPI_EXPECTED_PROMISE, 0, JSEXN_TYPEERR, "Expected externref for returned promise") +MSG_DEF(JSMSG_JSPI_SIGNATURE_MISMATCH, 0, JSEXN_TYPEERR, "Signature mismatch") +MSG_DEF(JSMSG_JSPI_SUSPENDER_LIMIT, 0, IF_WASM_JSPI(JSEXN_WASMSUSPENDERROR, JSEXN_WASMRUNTIMEERROR), "Too many suspenders") // Proxy MSG_DEF(JSMSG_BAD_GETPROTOTYPEOF_TRAP_RETURN,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler returned a non-object, non-null value") @@ -595,8 +602,10 @@ MSG_DEF(JSMSG_DEBUGGEE_WOULD_RUN, 2, JSEXN_DEBUGGEEWOULDRUN, "debuggee '{0} MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined") MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true") MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so") -MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'") -MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'displayURL', 'url', or 'source' property") +MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line', or 'start' and 'end', and either 'displayURL', 'url', or 'source'") +MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 1, JSEXN_TYPEERR, "findScripts query object has {0}, but no 'displayURL', 'url', or 'source' property") +MSG_DEF(JSMSG_QUERY_USE_START_AND_END_TOGETHER, 0, JSEXN_ERR, "findScripts query object's 'start' and 'end' properties must be used together") +MSG_DEF(JSMSG_QUERY_START_LINE_IS_AFTER_END, 0, JSEXN_ERR, "findScripts query object's 'start.line' property is greater than its 'end.line' property, but it must be less than or equal to 'end.line'") MSG_DEF(JSMSG_DEBUG_CANT_SET_OPT_ENV, 1, JSEXN_REFERENCEERR, "can't set '{0}' in an optimized-out environment") MSG_DEF(JSMSG_DEBUG_INVISIBLE_COMPARTMENT, 0, JSEXN_TYPEERR, "object in compartment marked as invisible to Debugger") MSG_DEF(JSMSG_DEBUG_CENSUS_BREAKDOWN, 1, JSEXN_TYPEERR, "unrecognized 'by' value in takeCensus breakdown: {0}") @@ -606,6 +615,8 @@ MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_FULFILLED, 0, JSEXN_TYPEERR, "Promise hasn't bee MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_REJECTED, 0, JSEXN_TYPEERR, "Promise hasn't been rejected") MSG_DEF(JSMSG_DEBUG_NO_BINARY_SOURCE, 0, JSEXN_ERR, "WebAssembly binary source is not available") MSG_DEF(JSMSG_DEBUG_EXCLUSIVE_FRAME_COVERAGE, 0, JSEXN_ERR, "onEnterFrame and collectCoverageInfo cannot be active at the same time") +MSG_DEF(JSMSG_DEBUG_EXCLUSIVE_EXECUTION_TRACE_COVERAGE, 0, JSEXN_ERR, "execution trace and collectCoverageInfo cannot be active at the same time") +MSG_DEF(JSMSG_NATIVE_TRACING_BUFFER_MALFORMED, 0, JSEXN_ERR, "bad data encountered while reading the native tracing buffer") // Testing functions MSG_DEF(JSMSG_TESTING_SCRIPTS_ONLY, 0, JSEXN_TYPEERR, "only works on scripts") @@ -628,7 +639,7 @@ MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 1, JSEXN_RANGEERR, "invalid locale matche MSG_DEF(JSMSG_INVALID_OPTION_VALUE, 2, JSEXN_RANGEERR, "invalid value {1} for option {0}") MSG_DEF(JSMSG_INVALID_TIME_ZONE, 1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}") MSG_DEF(JSMSG_INVALID_DATETIME_OPTION, 2, JSEXN_TYPEERR, "can't set option {0} when {1} is used") -MSG_DEF(JSMSG_INVALID_DATETIME_STYLE, 2, JSEXN_TYPEERR, "can't set option {0} in Date.{1}()") +MSG_DEF(JSMSG_INVALID_DATETIME_STYLE, 2, JSEXN_TYPEERR, "can't set option {0} for {1} formats") MSG_DEF(JSMSG_UNDEFINED_CURRENCY, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style") MSG_DEF(JSMSG_UNDEFINED_UNIT, 0, JSEXN_TYPEERR, "undefined unit in NumberFormat() with unit style") MSG_DEF(JSMSG_UNDEFINED_DATE, 2, JSEXN_TYPEERR, "undefined {0}-date in DateTimeFormat.{1}()") @@ -637,6 +648,16 @@ MSG_DEF(JSMSG_UNDEFINED_TYPE, 0, JSEXN_TYPEERR, "missing \"type\" optio MSG_DEF(JSMSG_NAN_NUMBER_RANGE, 3, JSEXN_RANGEERR, "range can't {0} with NaN in {1}.{2}()") MSG_DEF(JSMSG_INVALID_NUMBER_OPTION, 2, JSEXN_TYPEERR, "can't set option {0} when {1} is used") MSG_DEF(JSMSG_UNEQUAL_FRACTION_DIGITS, 0, JSEXN_RANGEERR, "fraction digits must be the same when roundingIncrement is used") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_NON_NUMERIC_OPTION, 2, JSEXN_RANGEERR, "invalid non-numeric value {0} for option {1}") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION, 1, JSEXN_RANGEERR, "{0} can't use \"numeric\" style with \"always\" display") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_STYLE, 1, JSEXN_RANGEERR, "{0} can't use \"always\" display when style defaults to \"numeric\"") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_DISPLAY, 1, JSEXN_RANGEERR, "{0} can't use \"numeric\" style when display defaults to \"always\"") +MSG_DEF(JSMSG_INTL_DURATION_NOT_INTEGER, 1, JSEXN_RANGEERR, "{0} isn't a valid duration value because it isn't an integer") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_SIGN, 0, JSEXN_RANGEERR, "duration elements must have the same sign") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_LIMIT, 0, JSEXN_RANGEERR, "duration elements must be below valid limits") +MSG_DEF(JSMSG_INTL_DURATION_MISSING_UNIT, 0, JSEXN_TYPEERR, "Duration-like objects must have at least one duration unit") +MSG_DEF(JSMSG_INTL_DURATION_UNEXPECTED_STRING, 0, JSEXN_RANGEERR, "duration can't be a string") +MSG_DEF(JSMSG_INVALID_FORMAT_OPTIONS, 1, JSEXN_TYPEERR, "can't format {0} using the requested options") // RegExp MSG_DEF(JSMSG_BAD_CLASS_RANGE, 0, JSEXN_SYNTAXERR, "invalid range in character class") @@ -644,6 +665,8 @@ MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 0, JSEXN_SYNTAXERR, "\\ at end of pattern MSG_DEF(JSMSG_EXEC_NOT_OBJORNULL, 0, JSEXN_TYPEERR, "RegExp exec method should return object or null") MSG_DEF(JSMSG_INVALID_DECIMAL_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid decimal escape in regular expression") MSG_DEF(JSMSG_INVALID_GROUP, 0, JSEXN_SYNTAXERR, "invalid regexp group") +MSG_DEF(JSMSG_REPEATED_FLAG, 0, JSEXN_SYNTAXERR, "repeated flag in regexp modifier") +MSG_DEF(JSMSG_INVALID_FLAG_GROUP, 0, JSEXN_SYNTAXERR, "invalid flag group") MSG_DEF(JSMSG_INVALID_IDENTITY_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid identity escape in regular expression") MSG_DEF(JSMSG_INVALID_UNICODE_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid unicode escape in regular expression") MSG_DEF(JSMSG_MISSING_PAREN, 0, JSEXN_SYNTAXERR, "unterminated parenthetical") @@ -668,6 +691,7 @@ MSG_DEF(JSMSG_INCOMPATIBLE_REGEXP_GETTER, 2, JSEXN_TYPEERR, "RegExp.prototype.{ MSG_DEF(JSMSG_INVALID_CLASS_SET_OP, 0, JSEXN_SYNTAXERR, "invalid class set operation in regular expression") MSG_DEF(JSMSG_INVALID_CHAR_IN_CLASS, 0, JSEXN_SYNTAXERR, "invalid character in class in regular expression") MSG_DEF(JSMSG_NEGATED_CLASS_WITH_STR, 0, JSEXN_SYNTAXERR, "negated character class with strings in regular expression") +MSG_DEF(JSMSG_MULTIPLE_FLAG_DASHES, 0, JSEXN_SYNTAXERR, "multiple dashes in flag group") // Typed object MSG_DEF(JSMSG_TYPEDOBJECT_SETTING_IMMUTABLE, 0, JSEXN_ERR, "setting immutable field") @@ -726,6 +750,7 @@ MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol t // Atomics and futexes MSG_DEF(JSMSG_ATOMICS_BAD_ARRAY, 0, JSEXN_TYPEERR, "invalid array type for the operation") MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 0, JSEXN_TYPEERR, "waiting is not allowed on this thread") +MSG_DEF(JSMSG_ATOMICS_PAUSE_BAD_COUNT, 0, JSEXN_TYPEERR, "Atomics.pause called with non-integral Number") // XPConnect wrappers and DOM bindings MSG_DEF(JSMSG_CANT_SET_INTERPOSED, 1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'") @@ -733,7 +758,7 @@ MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't define elemen MSG_DEF(JSMSG_CANT_DELETE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't delete elements from a Window object") MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_NAMED_PROPERTY, 1, JSEXN_TYPEERR, "can't define property {0} on window's named properties object") MSG_DEF(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY, 1, JSEXN_TYPEERR, "can't delete property {0} from window's named properties object") -MSG_DEF(JSMSG_CANT_PREVENT_EXTENSIONS, 0, JSEXN_TYPEERR, "can't prevent extensions on this proxy object") +MSG_DEF(JSMSG_CANT_PREVENT_EXTENSIONS, 0, JSEXN_TYPEERR, "can't prevent extensions on this object") MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_NC, 0, JSEXN_TYPEERR, "can't define non-configurable property on WindowProxy") MSG_DEF(JSMSG_NO_NAMED_SETTER, 2, JSEXN_TYPEERR, "{0} doesn't have a named property setter for '{1}'") MSG_DEF(JSMSG_NO_INDEXED_SETTER, 2, JSEXN_TYPEERR, "{0} doesn't have an indexed property setter for '{1}'") @@ -759,6 +784,7 @@ MSG_DEF(JSMSG_IMPORT_MAPS_NOT_A_MAP, 0, JSEXN_TYPEERR, "the top-level value need MSG_DEF(JSMSG_IMPORT_MAPS_IMPORTS_NOT_A_MAP, 0, JSEXN_TYPEERR, "the imports top-level key needs to be a JSON object") MSG_DEF(JSMSG_IMPORT_MAPS_SCOPES_NOT_A_MAP, 0, JSEXN_TYPEERR, "the scopes top-level key needs to be a JSON object") MSG_DEF(JSMSG_IMPORT_MAPS_SCOPE_VALUE_NOT_A_MAP, 1, JSEXN_TYPEERR, "the value of the scope with prefix '{0}' needs to be a JSON object") +MSG_DEF(JSMSG_IMPORT_MAPS_INTEGRITY_NOT_A_MAP, 0, JSEXN_TYPEERR, "the integrity top-level key needs to be a JSON object") // Import Attributes MSG_DEF(JSMSG_IMPORT_ATTRIBUTES_STATIC_IMPORT_UNSUPPORTED_ATTRIBUTE, 1, JSEXN_SYNTAXERR, "Unsupported import attribute: {0}") @@ -785,29 +811,6 @@ MSG_DEF(JSMSG_NOT_AN_ASYNC_GENERATOR, 0, JSEXN_TYPEERR, "Not an async generator MSG_DEF(JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.asyncIterator]() returned a non-object value") MSG_DEF(JSMSG_SUSPENDED_QUEUE_NOT_EMPTY, 0, JSEXN_INTERNALERR, "Async generator is in invalid state due to debugger interaction") -// ReadableStream -MSG_DEF(JSMSG_READABLESTREAM_UNDERLYINGSOURCE_TYPE_WRONG,0, JSEXN_RANGEERR,"'underlyingSource.type' must be \"bytes\" or undefined.") -MSG_DEF(JSMSG_READABLESTREAM_BYTES_TYPE_NOT_IMPLEMENTED, 0, JSEXN_RANGEERR,"support for 'new ReadableStream({ type: \"bytes\" })' is not yet implemented") -MSG_DEF(JSMSG_READABLESTREAM_BYOB_READER_FOR_NON_BYTE_STREAM,0,JSEXN_TYPEERR,"can't get a BYOB reader for a non-byte stream") -MSG_DEF(JSMSG_READABLESTREAM_INVALID_READER_MODE, 0, JSEXN_TYPEERR,"'mode' must be \"byob\" or undefined.") -MSG_DEF(JSMSG_NUMBER_MUST_BE_FINITE_NON_NEGATIVE, 1, JSEXN_RANGEERR, "'{0}' must be a finite, non-negative number.") -MSG_DEF(JSMSG_READABLESTREAM_LOCKED_METHOD, 1, JSEXN_TYPEERR, "'{0}' can't be called on a locked stream.") -MSG_DEF(JSMSG_READABLESTREAM_LOCKED, 0, JSEXN_TYPEERR, "A Reader may only be created for an unlocked ReadableStream.") -MSG_DEF(JSMSG_READABLESTREAM_NOT_DEFAULT_CONTROLLER, 1, JSEXN_TYPEERR, "{0} requires a ReadableStreamDefaultController.") -MSG_DEF(JSMSG_READABLESTREAMREADER_NOT_OWNED, 1, JSEXN_TYPEERR, "The ReadableStream reader method '{0}' may only be called on a reader owned by a stream.") -MSG_DEF(JSMSG_READABLESTREAMREADER_NOT_EMPTY, 1, JSEXN_TYPEERR, "The ReadableStream reader method '{0}' may not be called on a reader with read requests.") -MSG_DEF(JSMSG_READABLESTREAMREADER_RELEASED, 0, JSEXN_TYPEERR, "The ReadableStream reader was released.") -MSG_DEF(JSMSG_READABLESTREAMCONTROLLER_CLOSED, 1, JSEXN_TYPEERR, "'{0}' called on a stream already closing.") -MSG_DEF(JSMSG_READABLESTREAMCONTROLLER_NOT_READABLE, 1, JSEXN_TYPEERR, "'{0}' may only be called on a stream in the 'readable' state.") -MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_BAD_CHUNKSIZE,0, JSEXN_RANGEERR, "ReadableByteStreamController requires a positive integer or undefined for 'autoAllocateChunkSize'.") -MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_BAD_CHUNK, 1, JSEXN_TYPEERR, "{0} passed a bad chunk.") -MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_CLOSE_PENDING_PULL, 0, JSEXN_TYPEERR, "The ReadableByteStreamController cannot be closed while the buffer is being filled.") - -// Other Stream-related -MSG_DEF(JSMSG_STREAM_MISSING_HIGHWATERMARK, 0, JSEXN_TYPEERR, "'highWaterMark' must not be undefined.") -MSG_DEF(JSMSG_STREAM_INVALID_HIGHWATERMARK, 0, JSEXN_RANGEERR, "'highWaterMark' must be a non-negative, non-NaN number.") -MSG_DEF(JSMSG_STREAM_CONSUME_ERROR, 0, JSEXN_TYPEERR, "error consuming stream body") - // (wasm) Response-related MSG_DEF(JSMSG_WASM_ERROR_CONSUMING_RESPONSE, 0, JSEXN_TYPEERR, "WebAssembly: There was an error consuming the Response") MSG_DEF(JSMSG_WASM_BAD_RESPONSE_VALUE, 0, JSEXN_TYPEERR, "WebAssembly: Expected Response or Promise resolving to Response") @@ -841,15 +844,6 @@ MSG_DEF(JSMSG_NEGATIVE_LIMIT, 0, JSEXN_RANGEERR, "Ite // Set MSG_DEF(JSMSG_SET_NEGATIVE_SIZE, 0, JSEXN_RANGEERR, "Set size must be non-negative") -// Record and Tuple -MSG_DEF(JSMSG_RECORD_TUPLE_NO_OBJECT, 0, JSEXN_TYPEERR, "Record and Tuple can only contain primitive values") -MSG_DEF(JSMSG_RECORD_NO_PROTO, 0, JSEXN_SYNTAXERR, "__proto__ is not a valid literal key in records") -MSG_DEF(JSMSG_RECORD_NO_SYMBOL_KEY, 0, JSEXN_TYPEERR, "Symbols cannot be used as record keys") -MSG_DEF(JSMSG_BAD_TUPLE_INDEX, 0, JSEXN_RANGEERR, "index out of range for tuple") -MSG_DEF(JSMSG_BAD_TUPLE_OBJECT, 0, JSEXN_TYPEERR, "value of TupleObject must be a Tuple") -MSG_DEF(JSMSG_RECORD_TUPLE_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert Record or Tuple to number") - - // Shadow Realms MSG_DEF(JSMSG_NOT_SHADOW_REALM, 0, JSEXN_TYPEERR, "Object is not a ShadowRealm") MSG_DEF(JSMSG_SHADOW_REALM_EVALUATE_NOT_STRING, 0, JSEXN_TYPEERR, "a ShadowRealm can only evaluate a string") @@ -872,86 +866,109 @@ MSG_DEF(JSMSG_TEMPORAL_INVALID_UNIT_RANGE, 0, JSEXN_RANGEERR, "smallest MSG_DEF(JSMSG_TEMPORAL_INVALID_UNIT_OPTION, 2, JSEXN_RANGEERR, "{0} is not a valid {1} option in this context") MSG_DEF(JSMSG_TEMPORAL_INVALID_NUMBER, 1, JSEXN_RANGEERR, "{0} must be larger than zero") MSG_DEF(JSMSG_TEMPORAL_INVALID_INTEGER, 1, JSEXN_RANGEERR, "{0} must be an integer") -MSG_DEF(JSMSG_TEMPORAL_INVALID_OBJECT, 2, JSEXN_TYPEERR, "{0} must not be a {1} object") -MSG_DEF(JSMSG_TEMPORAL_MISSING_OPTION, 1, JSEXN_RANGEERR, "undefined {0} option") -MSG_DEF(JSMSG_TEMPORAL_MISSING_PROPERTY, 1, JSEXN_TYPEERR, "{0} property is undefined") -MSG_DEF(JSMSG_TEMPORAL_UNEXPECTED_PROPERTY, 1, JSEXN_TYPEERR, "{0} property is not undefined") +MSG_DEF(JSMSG_TEMPORAL_MISSING_OPTION, 1, JSEXN_RANGEERR, "required option {0} is undefined") +MSG_DEF(JSMSG_TEMPORAL_MISSING_PROPERTY, 1, JSEXN_TYPEERR, "required property {0} is undefined") +MSG_DEF(JSMSG_TEMPORAL_UNEXPECTED_PROPERTY, 1, JSEXN_TYPEERR, "expected property {0} to be undefined") MSG_DEF(JSMSG_TEMPORAL_MISSING_TEMPORAL_FIELDS, 0, JSEXN_TYPEERR, "object must have at least one temporal property") -MSG_DEF(JSMSG_TEMPORAL_DUPLICATE_PROPERTY, 1, JSEXN_RANGEERR, "duplicate property name \"{0}\"") -MSG_DEF(JSMSG_TEMPORAL_INVALID_PROPERTY, 1, JSEXN_RANGEERR, "invalid property name \"{0}\"") MSG_DEF(JSMSG_TEMPORAL_INSTANT_INVALID, 0, JSEXN_RANGEERR, "epoch nanoseconds too large") MSG_DEF(JSMSG_TEMPORAL_INSTANT_NONINTEGER, 1, JSEXN_RANGEERR, "Instant must be an integer, but received {0}") MSG_DEF(JSMSG_TEMPORAL_INSTANT_BAD_DURATION, 1, JSEXN_RANGEERR, "duration \"{0}\" property must be zero") MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_INVALID_IDENTIFIER, 1, JSEXN_RANGEERR, "invalid time zone: {0}") -MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_NANOS_RANGE, 1, JSEXN_RANGEERR, "nanoseconds out of range: {0}") MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_INCOMPATIBLE, 2, JSEXN_RANGEERR, "time zones \"{0}\" and \"{1}\" aren't compatible") MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_INSTANT_AMBIGUOUS, 0, JSEXN_RANGEERR, "instant is ambiguous") -MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_OFFSET_SHIFT_ONE_DAY, 0, JSEXN_RANGEERR, "time zone offset shift must not exceed a 24-hour span") MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_SIGN, 2, JSEXN_RANGEERR, "duration value \"{0}\" has a mismatched sign: {1}") -MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE, 2, JSEXN_RANGEERR, "duration value \"{0}\" is {1}") -MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME, 0, JSEXN_RANGEERR, "time duration values must be lower than 2**53 seconds") +MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE, 2, JSEXN_RANGEERR, "duration value \"{0}\" is non-finite: {1}") +MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME, 0, JSEXN_RANGEERR, "time duration values must be smaller than 2**53 seconds") MSG_DEF(JSMSG_TEMPORAL_DURATION_MISSING_UNIT, 0, JSEXN_TYPEERR, "Duration-like objects must have at least one duration unit") MSG_DEF(JSMSG_TEMPORAL_DURATION_NOT_INTEGER, 2, JSEXN_RANGEERR, "{0} isn't a valid {1} duration because it isn't an integer") MSG_DEF(JSMSG_TEMPORAL_DURATION_MISSING_UNIT_SPECIFIER, 0, JSEXN_RANGEERR, "at least one of \"smallestUnit\" and \"largestUnit\" must be present") MSG_DEF(JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, 1, JSEXN_RANGEERR, "can't compare durations when \"{0}\" is undefined") -MSG_DEF(JSMSG_TEMPORAL_DURATION_COMBINE_INVALID_SIGN, 0, JSEXN_RANGEERR, "can't combine date- and time-durations with different signs") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_ID, 1, JSEXN_RANGEERR, "invalid calendar: {0}") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_MISSING_FIELD, 1, JSEXN_TYPEERR, "missing \"{0}\" calendar field") -MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_FIELD, 1, JSEXN_RANGEERR, "invalid calendar field name \"{0}\"") -MSG_DEF(JSMSG_TEMPORAL_CALENDAR_DUPLICATE_FIELD, 1, JSEXN_RANGEERR, "duplicate calendar field \"{0}\"") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_OVERFLOW_FIELD, 2, JSEXN_RANGEERR, "calendar field \"{0}\" is too large: {1}") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, 1, JSEXN_RANGEERR, "invalid \"monthCode\" calendar field: {0}") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_ERA, 1, JSEXN_RANGEERR, "invalid \"era\" calendar field: {0}") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, 2, JSEXN_RANGEERR, "calendars \"{0}\" and \"{1}\" aren't compatible") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid iso dates") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_YEAR, 2, JSEXN_RANGEERR, "\"year\" and computed \"year\" calendar fields are inconsistent: {0} - {1}") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_MONTHCODE, 2, JSEXN_RANGEERR, "\"monthCode\" and \"month\" calendar fields are inconsistent: {0} - {1}") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR, 0, JSEXN_ERR, "internal error while computing calendar data") +MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid ISO date values") MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_INVALID_VALUE, 4, JSEXN_RANGEERR, "date value \"{0}\" not in {1}..{2}: {3}") MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID, 0, JSEXN_RANGEERR, "arguments must be valid ISO date-time values") MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_INVALID, 0, JSEXN_RANGEERR, "arguments must be valid ISO time values") MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_INVALID_VALUE, 4, JSEXN_RANGEERR, "time value \"{0}\" not in {1}..{2}: {3}") MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_MISSING_UNIT, 0, JSEXN_TYPEERR, "Time-like objects must have at least one time unit") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_CALENDAR_NOT_ISO8601, 1, JSEXN_RANGEERR, "PlainTime only supports the \"iso8601\" calendar: {0}") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid iso dates") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid iso dates") +MSG_DEF(JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID, 0, JSEXN_RANGEERR, "month-day must be valid ISO date values") +MSG_DEF(JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID, 0, JSEXN_RANGEERR, "year-month must be valid ISO date values") MSG_DEF(JSMSG_TEMPORAL_ZONED_DATE_TIME_NO_TIME_FOUND, 0, JSEXN_RANGEERR, "date-time can't be represented in the given time zone") -MSG_DEF(JSMSG_TEMPORAL_ZONED_DATE_TIME_INCORRECT_SIGN, 1, JSEXN_RANGEERR, "computed {0} has an incorrect sign") MSG_DEF(JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT, 0, JSEXN_RANGEERR, "time zone computed inconsistent instant values") -MSG_DEF(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR, 0, JSEXN_RANGEERR, "year 0 must not start with \"-\"") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR, 0, JSEXN_RANGEERR, "signed year must be followed by six digits") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_YEAR, 0, JSEXN_RANGEERR, "missing four digit year") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MONTH, 0, JSEXN_RANGEERR, "missing two digit month") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DAY, 0, JSEXN_RANGEERR, "missing two digit day") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_HOUR, 0, JSEXN_RANGEERR, "missing two digit hour") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE, 0, JSEXN_RANGEERR, "missing two digit minute") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_SECOND, 0, JSEXN_RANGEERR, "missing two digit second") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_SIGN, 0, JSEXN_RANGEERR, "missing time zone sign") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MONTH, 0, JSEXN_RANGEERR, "month must be a number from 1 to 12") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DAY, 0, JSEXN_RANGEERR, "day must be a number from 1 to 31") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_HOUR, 0, JSEXN_RANGEERR, "hour must be a number from 0 to 23") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE, 0, JSEXN_RANGEERR, "minute must be a number from 0 to 59") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SECOND, 0, JSEXN_RANGEERR, "second must be a number from 0 to 59") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND, 0, JSEXN_RANGEERR, "second must be a number from 0 to 60") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_TIMEZONE, 0, JSEXN_RANGEERR, "missing '[' before time zone annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_TIMEZONE, 0, JSEXN_RANGEERR, "missing ']' after time zone annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE, 0, JSEXN_RANGEERR, "missing time zone") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_NAME, 0, JSEXN_RANGEERR, "missing time zone name") -MSG_DEF(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT, 0, JSEXN_RANGEERR, "unexpected garbage after end of input") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DESIGNATOR, 0, JSEXN_RANGEERR, "missing duration designator 'P'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIME_DESIGNATOR, 0, JSEXN_RANGEERR, "missing time designator 'T'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS, 0, JSEXN_RANGEERR, "missing duration digits") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_MINUTES, 0, JSEXN_RANGEERR, "invalid duration minutes after fractional hours") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_SECONDS, 0, JSEXN_RANGEERR, "invalid duration seconds after fractional hours or minutes") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_KEY, 0, JSEXN_RANGEERR, "invalid annotation key") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_VALUE, 0, JSEXN_RANGEERR, "invalid annotation value") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_CALENDAR_NAME, 0, JSEXN_RANGEERR, "invalid calendar name") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_ANNOTATION, 0, JSEXN_RANGEERR, "missing ']' before annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_ANNOTATION, 0, JSEXN_RANGEERR, "missing ']' after annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_ASSIGNMENT_IN_ANNOTATION, 0, JSEXN_RANGEERR, "missing '=' in annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_CRITICAL_ANNOTATION, 0, JSEXN_RANGEERR, "unexpected critical annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DATE_TIME_SEPARATOR, 0, JSEXN_RANGEERR, "missing date-time separator 'T'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_MONTH_DAY, 0, JSEXN_RANGEERR, "time is ambiguous with a month-day") -MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_YEAR_MONTH, 0, JSEXN_RANGEERR, "time is ambiguous with a year-month") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR, 0, JSEXN_RANGEERR, "unexpected UTC designator 'Z'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME, 0, JSEXN_RANGEERR, "unexpected UTC designator 'Z' without a bracketed time zone") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MONTH_DAY_CALENDAR_NOT_ISO8601, 0, JSEXN_RANGEERR, "Month-Day formats only support the \"iso8601\" calendar") -MSG_DEF(JSMSG_TEMPORAL_PARSER_YEAR_MONTH_CALENDAR_NOT_ISO8601, 0, JSEXN_RANGEERR, "Year-Month formats only support the \"iso8601\" calendar") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE, 0, JSEXN_RANGEERR, "time zone offset must not contain seconds precision") +MSG_DEF(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR, 1, JSEXN_RANGEERR, "can't parse {0}: year 0 must not start with \"-\"") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR, 1, JSEXN_RANGEERR, "can't parse {0}: signed year must be followed by six digits") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_YEAR, 1, JSEXN_RANGEERR, "can't parse {0}: missing four digit year") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MONTH, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit month") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DAY, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit day") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_HOUR, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit hour") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit minute") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_SECOND, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit second") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_SIGN, 1, JSEXN_RANGEERR, "can't parse {0}: missing time zone sign") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MONTH, 1, JSEXN_RANGEERR, "can't parse {0}: month must be a number from 1 to 12") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DAY, 1, JSEXN_RANGEERR, "can't parse {0}: day must be a number from 1 to 31") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_HOUR, 1, JSEXN_RANGEERR, "can't parse {0}: hour must be a number from 0 to 23") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE, 1, JSEXN_RANGEERR, "can't parse {0}: minute must be a number from 0 to 59") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SECOND, 1, JSEXN_RANGEERR, "can't parse {0}: second must be a number from 0 to 59") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND, 1, JSEXN_RANGEERR, "can't parse {0}: second must be a number from 0 to 60") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: missing '[' before time zone annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: missing ']' after time zone annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: missing time zone") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_NAME, 1, JSEXN_RANGEERR, "can't parse {0}: missing time zone name") +MSG_DEF(JSMSG_TEMPORAL_PARSER_UNEXPECTED_CHARACTERS_AT_END, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected characters at end of string") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing duration designator 'P'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIME_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing time designator 'T'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS, 1, JSEXN_RANGEERR, "can't parse {0}: missing duration digits") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_UNIT_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing duration unit designator") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_MINUTES, 1, JSEXN_RANGEERR, "can't parse {0}: invalid duration minutes after fractional hours") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_SECONDS, 1, JSEXN_RANGEERR, "can't parse {0}: invalid duration seconds after fractional hours or minutes") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_KEY, 1, JSEXN_RANGEERR, "can't parse {0}: invalid annotation key") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_VALUE, 1, JSEXN_RANGEERR, "can't parse {0}: invalid annotation value") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: missing '[' before annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: missing ']' after annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_ASSIGNMENT_IN_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: missing '=' in annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_CRITICAL_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected critical annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DATE_TIME_SEPARATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing date-time separator 'T'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_MONTH_DAY, 1, JSEXN_RANGEERR, "can't parse {0}: time is ambiguous with a month-day") +MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_YEAR_MONTH, 1, JSEXN_RANGEERR, "can't parse {0}: time is ambiguous with a year-month") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected UTC designator 'Z'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected UTC designator 'Z' without a bracketed time zone") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MONTH_DAY_CALENDAR_NOT_ISO8601, 1, JSEXN_RANGEERR, "can't parse {0}: Month-Day formats only support the \"iso8601\" calendar") +MSG_DEF(JSMSG_TEMPORAL_PARSER_YEAR_MONTH_CALENDAR_NOT_ISO8601, 1, JSEXN_RANGEERR, "can't parse {0}: Year-Month formats only support the \"iso8601\" calendar") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: time zone offset must not contain seconds precision") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INCONSISTENT_DATE_SEPARATOR, 1, JSEXN_RANGEERR, "can't parse {0}: date separator '-' must be consistent") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR, 1, JSEXN_RANGEERR, "can't parse {0}: time separator ':' must be consistent") +MSG_DEF(JSMSG_TEMPORAL_PARSER_EMPTY_STRING, 1, JSEXN_RANGEERR, "can't parse empty string as {0}") + +// Explicit Resource Management + +// TODO: Improve the messaging for suppressed errors (Bug 1906150) +MSG_DEF(JSMSG_ERROR_WAS_SUPPRESSED, 0, IF_EXPLICIT_RESOURCE_MANAGEMENT(JSEXN_SUPPRESSEDERR, JSEXN_INTERNALERR), "An error is suppressed because another error happened while disposing an object") + +// DisposableStack +MSG_DEF(JSMSG_DISPOSABLE_STACK_DISPOSED, 0, JSEXN_REFERENCEERR, "DisposableStack has already been disposed") + +// Iterator.range +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_START, 0, JSEXN_TYPEERR, "The 'start' argument must be a number or BigInt") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_START_RANGEERR, 0, JSEXN_RANGEERR, "The 'start' argument cannot be NaN") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_END_RANGEERR, 0, JSEXN_RANGEERR, "The 'end' argument cannot be NaN") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_END, 0, JSEXN_TYPEERR, "The 'end' argument must be a number or BigInt") +MSG_DEF(JSMSG_ITERATOR_RANGE_START_INFINITY, 0, JSEXN_RANGEERR, "The 'start' argument must be a finite number") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NAN, 0, JSEXN_RANGEERR, "The 'step' argument must not be NaN") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NOT_NUMBER, 0, JSEXN_TYPEERR, "The 'step' argument must be a number") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NOT_FINITE, 0, JSEXN_RANGEERR, "The 'step' argument must be a finite number") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_ZERO, 0, JSEXN_RANGEERR, "The 'step' argument must not be zero when 'start' is not equal to 'end'") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_STEP, 0, JSEXN_TYPEERR, "The 'step' or options argument must be a valid number, BigInt, or an Object with valid properties") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NOT_BIGINT, 0, JSEXN_TYPEERR, "The 'step' argument must be a BigInt when iterating over BigInt ranges") + +// Math.sumPrecise +MSG_DEF(JSMSG_SUMPRECISE_TOO_MANY_VALUES, 0, JSEXN_RANGEERR, "too many values passed to Math.sumPrecise") +MSG_DEF(JSMSG_SUMPRECISE_EXPECTED_NUMBER, 0, JSEXN_TYPEERR, "values passed to Math.sumPrecise must be numbers") //clang-format on diff --git a/src/third_party/mozjs/extract/js/public/friend/JSMEnvironment.h b/src/third_party/mozjs/extract/js/public/friend/JSMEnvironment.h index ad16f2ba626..36d3337c971 100644 --- a/src/third_party/mozjs/extract/js/public/friend/JSMEnvironment.h +++ b/src/third_party/mozjs/extract/js/public/friend/JSMEnvironment.h @@ -45,6 +45,8 @@ namespace JS { +class JS_PUBLIC_API EnvironmentChain; + /** * Allocate a new environment in the current compartment that is compatible with * JSM shared loading. @@ -68,7 +70,7 @@ extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(JSContext* cx, // temporarily placed on the environment chain. extern JS_PUBLIC_API bool ExecuteInJSMEnvironment( JSContext* cx, Handle script, Handle jsmEnv, - Handle> targetObj); + const EnvironmentChain& targetObj); // Used by native methods to determine the JSMEnvironment of caller if possible // by looking at stack frames. Returns nullptr if top frame isn't a scripted diff --git a/src/third_party/mozjs/extract/js/public/friend/UsageStatistics.h b/src/third_party/mozjs/extract/js/public/friend/UsageStatistics.h index 2560dcbbb9f..43862ecc067 100644 --- a/src/third_party/mozjs/extract/js/public/friend/UsageStatistics.h +++ b/src/third_party/mozjs/extract/js/public/friend/UsageStatistics.h @@ -17,12 +17,12 @@ struct JS_PUBLIC_API JSContext; class JS_PUBLIC_API JSObject; /* - * Telemetry reasons passed to the accumulate telemetry callback. + * Legacy telemetry metrics passed to the accumulate telemetry callback. * * It's OK for these enum values to change as they will be mapped to a fixed * member of the mozilla::Telemetry::HistogramID enum by the callback. */ -#define FOR_EACH_JS_METRIC(_) \ +#define FOR_EACH_JS_LEGACY_METRIC(_) \ _(GC_REASON_2, Enumeration) \ _(GC_IS_COMPARTMENTAL, Boolean) \ _(GC_ZONE_COUNT, QuantityDistribution) \ @@ -60,9 +60,6 @@ class JS_PUBLIC_API JSObject; _(GC_TIME_BETWEEN_S, TimeDuration_S) \ _(GC_TIME_BETWEEN_SLICES_MS, TimeDuration_MS) \ _(GC_SLICE_COUNT, QuantityDistribution) \ - _(DESERIALIZE_BYTES, MemoryDistribution) \ - _(DESERIALIZE_ITEMS, QuantityDistribution) \ - _(DESERIALIZE_US, TimeDuration_US) \ _(GC_EFFECTIVENESS, MemoryDistribution) \ _(GC_PARALLEL_MARK, Boolean) \ _(GC_PARALLEL_MARK_SPEEDUP, Integer) \ @@ -70,6 +67,20 @@ class JS_PUBLIC_API JSObject; _(GC_PARALLEL_MARK_INTERRUPTIONS, Integer) \ _(GC_TASK_START_DELAY_US, TimeDuration_US) +/* + * Append any glean only telemetry metrics to the following list. + * However, unlike the legacy list, each glean metric must be manually added + * to the switch statement in AccumulateTelemetryCallback(). + */ +#define FOR_EACH_JS_GLEAN_METRIC(_) \ + _(ION_COMPILE_TIME, TimeDuration_US) \ + _(GC_GLEAN_SLOW_PHASE, Enumeration) \ + _(GC_GLEAN_SLOW_TASK, Enumeration) + +#define FOR_EACH_JS_METRIC(_) \ + FOR_EACH_JS_LEGACY_METRIC(_) \ + FOR_EACH_JS_GLEAN_METRIC(_) + // clang-format off #define ENUM_DEF(NAME, _) NAME, enum class JSMetric { @@ -84,21 +95,29 @@ using JSAccumulateTelemetryDataCallback = void (*)(JSMetric, uint32_t); extern JS_PUBLIC_API void JS_SetAccumulateTelemetryCallback( JSContext* cx, JSAccumulateTelemetryDataCallback callback); -#define FOR_EACH_JS_USE_COUNTER(_) \ - _(ASMJS, AsmJS) \ - _(WASM, Wasm) \ - _(WASM_LEGACY_EXCEPTIONS, WasmLegacyExceptions) \ - _(SUBCLASSING_ARRAY_TYPE_II, SubclassingArrayTypeII) \ - _(SUBCLASSING_ARRAY_TYPE_III, SubclassingArrayTypeIII) \ - _(SUBCLASSING_PROMISE_TYPE_II, SubclassingPromiseTypeII) \ - _(SUBCLASSING_PROMISE_TYPE_III, SubclassingPromiseTypeIII) \ - _(SUBCLASSING_TYPEDARRAY_TYPE_II, SubclassingTypedArrayTypeII) \ - _(SUBCLASSING_TYPEDARRAY_TYPE_III, SubclassingTypedArrayTypeIII) \ - _(SUBCLASSING_ARRAYBUFFER_TYPE_III, SubclassingArrayBufferTypeIII) \ - _(SUBCLASSING_SHAREDARRAYBUFFER_TYPE_III, \ - SubclassingSharedArrayBufferTypeIII) \ - _(SUBCLASSING_REGEXP_TYPE_III, SubclassingRegExpTypeIII) \ - _(SUBCLASSING_REGEXP_TYPE_IV, SubclassingRegExpTypeIV) +#define FOR_EACH_JS_USE_COUNTER(_) \ + _(ASMJS, AsmJS) \ + _(WASM, Wasm) \ + _(WASM_LEGACY_EXCEPTIONS, WasmLegacyExceptions) \ + _(ISHTMLDDA_FUSE, IsHTMLDDAFuse) \ + _(OPTIMIZE_GET_ITERATOR_FUSE, OptimizeGetIteratorFuse) \ + _(THENABLE_USE, ThenableUse) \ + _(THENABLE_USE_PROTO, ThenableUseProto) \ + _(THENABLE_USE_STANDARD_PROTO, ThenableUseStandardProto) \ + _(THENABLE_USE_OBJECT_PROTO, ThenableUseObjectProto) \ + _(LEGACY_LANG_SUBTAG, LegacyLangSubtag) \ + _(IC_STUB_TOO_LARGE, ICStubTooLarge) \ + _(IC_STUB_OOM, ICStubOOM) \ + _(ERRORSTACK_GETTER, ErrorStackGetter) \ + _(ERRORSTACK_GETTER_NO_ERRORDATA, ErrorStackGetterNoErrorData) \ + _(ERRORSTACK_SETTER, ErrorStackSetter) \ + _(ERRORSTACK_SETTER_NONSTRING, ErrorStackSetterNonString) \ + _(ERRORSTACK_SETTER_NO_ERRORDATA, ErrorStackSetterNoErrorData) \ + _(DATEPARSE, DateParse) \ + _(DATEPARSE_IMPL_DEF, DateParseImplDef) \ + _(OPTIMIZE_ARRAY_SPECIES_FUSE, OptimizeArraySpeciesFuse) \ + _(OPTIMIZE_PROMISE_LOOKUP_FUSE, OptimizePromiseLookupFuse) \ + _(REGEXP_SYMBOL_PROTOCOL_ON_PRIMITIVE, RegExpSymbolProtocolOnPrimitive) /* * Use counter names passed to the accumulate use counter callback. diff --git a/src/third_party/mozjs/extract/js/public/shadow/String.h b/src/third_party/mozjs/extract/js/public/shadow/String.h index cae853cc5d9..6e144319993 100644 --- a/src/third_party/mozjs/extract/js/public/shadow/String.h +++ b/src/third_party/mozjs/extract/js/public/shadow/String.h @@ -35,6 +35,7 @@ struct String { static constexpr uint32_t LINEAR_BIT = js::Bit(4); static constexpr uint32_t INLINE_CHARS_BIT = js::Bit(6); static constexpr uint32_t LATIN1_CHARS_BIT = js::Bit(10); + static constexpr uint32_t HAS_STRING_BUFFER_BIT = js::Bit(12); static constexpr uint32_t EXTERNAL_FLAGS = LINEAR_BIT | js::Bit(8); static constexpr uint32_t TYPE_FLAGS_MASK = js::BitMask(10) - js::BitMask(3); static constexpr uint32_t PERMANENT_ATOM_MASK = ATOM_BIT | js::Bit(8); @@ -68,6 +69,7 @@ struct String { bool isLinear() const { return flags() & LINEAR_BIT; } bool hasLatin1Chars() const { return flags() & LATIN1_CHARS_BIT; } + bool hasStringBuffer() const { return flags() & HAS_STRING_BUFFER_BIT; } // For hot code, prefer other type queries. bool isExternal() const { diff --git a/src/third_party/mozjs/extract/js/src/GeneratePrefs.py b/src/third_party/mozjs/extract/js/src/GeneratePrefs.py index b28114c2599..2a16c7a6e80 100644 --- a/src/third_party/mozjs/extract/js/src/GeneratePrefs.py +++ b/src/third_party/mozjs/extract/js/src/GeneratePrefs.py @@ -4,8 +4,9 @@ # This script generates js/public/PrefsGenerated.h from StaticPrefList.yaml +import io + import buildconfig -import six import yaml from mozbuild.preprocessor import Preprocessor @@ -39,7 +40,7 @@ def load_yaml(yaml_path): if buildconfig.substs.get("MOZ_DEBUG"): pp.context["DEBUG"] = "1" - pp.out = six.StringIO() + pp.out = io.StringIO() pp.do_filter("substitution") pp.do_include(yaml_path) contents = pp.out.getvalue() @@ -56,7 +57,7 @@ def get_cpp_type(type): return "uint32_t" if type in ("int32_t", "RelaxedAtomicInt32"): return "int32_t" - raise Exception("Unexpected type: {}".format(type)) + raise Exception(f"Unexpected type: {type}") # Returns a C++ expression for the default pref value. Booleans in the YAML file @@ -116,10 +117,10 @@ def generate_prefs_header(c_out, yaml_path): # after startup. field_type = type if not is_startup_pref: - field_type = "mozilla::Atomic<{}, mozilla::Relaxed>".format(field_type) - class_fields.append("static {} {}_;".format(field_type, cpp_name)) + field_type = f"mozilla::Atomic<{field_type}, mozilla::Relaxed>" + class_fields.append(f"static {field_type} {cpp_name}_;") class_fields_inits.append( - "{} JS::Prefs::{}_{{{}}};".format(field_type, cpp_name, init_value) + f"{field_type} JS::Prefs::{cpp_name}_{{{init_value}}};" ) is_startup_pref_bool = "true" if is_startup_pref else "false" @@ -127,9 +128,7 @@ def generate_prefs_header(c_out, yaml_path): # Generate a MACRO invocation like this: # MACRO("arraybuffer_transfer", arraybuffer_transfer, bool, setAtStartup_arraybuffer_transfer, true) macro_entries.append( - 'MACRO("{}", {}, {}, {}, {})'.format( - name, cpp_name, type, setter_name, is_startup_pref_bool - ) + f'MACRO("{name}", {cpp_name}, {type}, {setter_name}, {is_startup_pref_bool})' ) # Generate a C++ statement to set the JS pref based on Gecko's StaticPrefs: @@ -138,9 +137,7 @@ def generate_prefs_header(c_out, yaml_path): if pref.get("do_not_use_directly", False): browser_pref_cpp_name += "_DoNotUseDirectly" - statement = "JS::Prefs::{}(mozilla::StaticPrefs::{}());".format( - setter_name, browser_pref_cpp_name - ) + statement = f"JS::Prefs::{setter_name}(mozilla::StaticPrefs::{browser_pref_cpp_name}());" browser_set_statements.append(statement) # For non-startup prefs, also generate code to update the pref after startup. @@ -150,25 +147,23 @@ def generate_prefs_header(c_out, yaml_path): contents = "" contents += "#define JS_PREF_CLASS_FIELDS \\\n" - contents += "".join(map(lambda s: " {}\\\n".format(s), class_fields)) + contents += "".join(map(lambda s: f" {s}\\\n", class_fields)) contents += "\n\n" contents += "#define JS_PREF_CLASS_FIELDS_INIT \\\n" - contents += "".join(map(lambda s: " {}\\\n".format(s), class_fields_inits)) + contents += "".join(map(lambda s: f" {s}\\\n", class_fields_inits)) contents += "\n\n" contents += "#define FOR_EACH_JS_PREF(MACRO) \\\n" - contents += "".join(map(lambda s: " {}\\\n".format(s), macro_entries)) + contents += "".join(map(lambda s: f" {s}\\\n", macro_entries)) contents += "\n\n" contents += "#define SET_JS_PREFS_FROM_BROWSER_PREFS \\\n" - contents += "".join(map(lambda s: " {}\\\n".format(s), browser_set_statements)) + contents += "".join(map(lambda s: f" {s}\\\n", browser_set_statements)) contents += "\n\n" contents += "#define SET_NON_STARTUP_JS_PREFS_FROM_BROWSER_PREFS \\\n" - contents += "".join( - map(lambda s: " {}\\\n".format(s), browser_set_non_startup_statements) - ) + contents += "".join(map(lambda s: f" {s}\\\n", browser_set_non_startup_statements)) contents += "\n\n" c_out.write( diff --git a/src/third_party/mozjs/extract/js/src/NamespaceImports.h b/src/third_party/mozjs/extract/js/src/NamespaceImports.h index 6a94263c8ca..4a7c886d208 100644 --- a/src/third_party/mozjs/extract/js/src/NamespaceImports.h +++ b/src/third_party/mozjs/extract/js/src/NamespaceImports.h @@ -50,9 +50,6 @@ using JS::NullValue; using JS::NumberValue; using JS::ObjectOrNullValue; using JS::ObjectValue; -#ifdef ENABLE_RECORD_TUPLE -using JS::ExtendedPrimitiveValue; -#endif using JS::PrivateGCThingValue; using JS::PrivateUint32Value; using JS::PrivateValue; @@ -96,12 +93,14 @@ using JS::NativeImpl; using JS::Rooted; using JS::RootedBigInt; +using JS::RootedField; using JS::RootedFunction; using JS::RootedId; using JS::RootedObject; using JS::RootedScript; using JS::RootedString; using JS::RootedSymbol; +using JS::RootedTuple; using JS::RootedValue; using JS::PersistentRooted; @@ -152,11 +151,6 @@ using JS::Zone; using JS::BigInt; -#ifdef ENABLE_RECORD_TUPLE -using JS::RecordType; -using JS::TupleType; -#endif - } /* namespace js */ #endif /* NamespaceImports_h */ diff --git a/src/third_party/mozjs/extract/js/src/aclocal.m4 b/src/third_party/mozjs/extract/js/src/aclocal.m4 deleted file mode 100644 index e105de9c8ce..00000000000 --- a/src/third_party/mozjs/extract/js/src/aclocal.m4 +++ /dev/null @@ -1,31 +0,0 @@ -dnl -dnl Local autoconf macros used with mozilla -dnl The contents of this file are under the Public Domain. -dnl - -builtin(include, ../../build/autoconf/hooks.m4)dnl -builtin(include, ../../build/autoconf/config.status.m4)dnl -builtin(include, ../../build/autoconf/toolchain.m4)dnl -builtin(include, ../../build/autoconf/altoptions.m4)dnl -builtin(include, ../../build/autoconf/mozprog.m4)dnl -builtin(include, ../../build/autoconf/mozheader.m4)dnl -builtin(include, ../../build/autoconf/compiler-opts.m4)dnl -builtin(include, ../../build/autoconf/arch.m4)dnl -builtin(include, ../../build/autoconf/clang-plugin.m4)dnl -builtin(include, ../../build/autoconf/sanitize.m4)dnl - -define([__MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE])) -define([AC_INIT_PREPARE], -[if test -z "$srcdir"; then - srcdir=`dirname "[$]0"` -fi -srcdir="$srcdir/../.." -__MOZ_AC_INIT_PREPARE($1) -]) - -MOZ_PROG_CHECKMSYS() -dnl This won't actually read the mozconfig, but data that configure.py -dnl will have placed for us to read. Configure.py takes care of not reading -dnl the mozconfig where appropriate but can still give us some variables -dnl to read. -MOZ_READ_MOZCONFIG(.) diff --git a/src/third_party/mozjs/extract/js/src/builtin/.eslintrc.js b/src/third_party/mozjs/extract/js/src/builtin/.eslintrc.js deleted file mode 100644 index 76aad2f6fd4..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/.eslintrc.js +++ /dev/null @@ -1,175 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -module.exports = { - plugins: ["spidermonkey-js"], - - overrides: [ - { - files: ["*.js"], - excludedFiles: ".eslintrc.js", - processor: "spidermonkey-js/processor", - env: { - // Disable all built-in environments. - node: false, - browser: false, - builtin: false, - - // We need to explicitly disable the default environments added from - // "tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js". - es2021: false, - "mozilla/privileged": false, - "mozilla/specific": false, - - // Enable SpiderMonkey's self-hosted environment. - "spidermonkey-js/environment": true, - }, - - parserOptions: { - ecmaVersion: "latest", - sourceType: "script", - - // Self-hosted code defaults to strict mode. - ecmaFeatures: { - impliedStrict: true, - }, - - // Strict mode has to be enabled separately for the Babel parser. - babelOptions: { - parserOpts: { - strictMode: true, - }, - }, - }, - - rules: { - // We should fix those at some point, but we use this to detect NaNs. - "no-self-compare": "off", - "no-lonely-if": "off", - // Disabled until we can use let/const to fix those erorrs, and undefined - // names cause an exception and abort during runtime initialization. - "no-redeclare": "off", - // Disallow use of |void 0|. Instead use |undefined|. - "no-void": ["error", { allowAsStatement: true }], - // Disallow loose equality because of objects with the [[IsHTMLDDA]] - // internal slot, aka |document.all|, aka "objects emulating undefined". - eqeqeq: "error", - // All self-hosted code is implicitly strict mode, so there's no need to - // add a strict-mode directive. - strict: ["error", "never"], - // Disallow syntax not supported in self-hosted code. - "no-restricted-syntax": [ - "error", - { - selector: "ClassDeclaration", - message: "Class declarations are not allowed", - }, - { - selector: "ClassExpression", - message: "Class expressions are not allowed", - }, - { - selector: "Literal[regex]", - message: "Regular expression literals are not allowed", - }, - { - selector: "CallExpression > MemberExpression.callee", - message: - "Direct method calls are not allowed, use callFunction() or callContentFunction()", - }, - { - selector: "NewExpression > MemberExpression.callee", - message: - "Direct method calls are not allowed, use constructContentFunction()", - }, - { - selector: "YieldExpression[delegate=true]", - message: - "yield* is not allowed because it can run user-modifiable iteration code", - }, - { - selector: "ForOfStatement > :not(CallExpression).right", - message: - "for-of loops must use allowContentIter(), allowContentIterWith(), or allowContentIterWithNext()", - }, - { - selector: - "ForOfStatement > CallExpression.right > :not(Identifier[name='allowContentIter'], Identifier[name='allowContentIterWith'], Identifier[name='allowContentIterWithNext']).callee", - message: - "for-of loops must use allowContentIter(), allowContentIterWith(), or allowContentIterWithNext", - }, - { - selector: - "CallExpression[callee.name='TO_PROPERTY_KEY'] > :not(Identifier).arguments:first-child", - message: - "TO_PROPERTY_KEY macro must be called with a simple identifier", - }, - { - selector: "Identifier[name='arguments']", - message: - "'arguments' is disallowed, use ArgumentsLength(), GetArgument(n), or rest-parameters", - }, - { - selector: "VariableDeclaration[kind='let']", - message: "'let' declarations are disallowed to avoid TDZ checks, use 'var' instead", - }, - { - selector: "VariableDeclaration[kind='const']", - message: "'const' declarations are disallowed to avoid TDZ checks, use 'var' instead", - }, - ], - // Method signatures are important in builtins so disable unused argument errors. - "no-unused-vars": [ - "error", - { - args: "none", - vars: "local", - }, - ], - }, - - globals: { - // The bytecode compiler special-cases these identifiers. - ArgumentsLength: "readonly", - allowContentIter: "readonly", - allowContentIterWith: "readonly", - allowContentIterWithNext: "readonly", - callContentFunction: "readonly", - callFunction: "readonly", - constructContentFunction: "readonly", - DefineDataProperty: "readonly", - forceInterpreter: "readonly", - GetArgument: "readonly", - GetBuiltinConstructor: "readonly", - GetBuiltinPrototype: "readonly", - GetBuiltinSymbol: "readonly", - getPropertySuper: "readonly", - hasOwn: "readonly", - IsNullOrUndefined: "readonly", - IteratorClose: "readonly", - resumeGenerator: "readonly", - SetCanonicalName: "readonly", - SetIsInlinableLargeFunction: "readonly", - ToNumeric: "readonly", - ToString: "readonly", - - // We've disabled all built-in environments, which also removed - // `undefined` from the list of globals. Put it back because it's - // actually allowed in self-hosted code. - undefined: "readonly", - - // Disable globals from stage 2/3 proposals for which we have work in - // progress patches. Eventually these will be part of a future ES - // release, in which case we can remove these extra entries. - AsyncIterator: "off", - Iterator: "off", - Record: "off", - Temporal: "off", - Tuple: "off", - }, - }, - ], -}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/.eslintrc.mjs b/src/third_party/mozjs/extract/js/src/builtin/.eslintrc.mjs new file mode 100644 index 00000000000..262c659ef8c --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/.eslintrc.mjs @@ -0,0 +1,178 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import spidermonkeyJS from "eslint-plugin-spidermonkey-js"; +import mozilla from "eslint-plugin-mozilla"; +import globals from "globals"; + +export default [ + { + plugins: { "spidermonkey-js": spidermonkeyJS }, + files: ["**/*.js"], + processor: "spidermonkey-js/processor", + + rules: { + // We should fix those at some point, but we use this to detect NaNs. + "no-self-compare": "off", + "no-lonely-if": "off", + // Disabled until we can use let/const to fix those erorrs, and undefined + // names cause an exception and abort during runtime initialization. + "no-redeclare": "off", + // Disallow use of |void 0|. Instead use |undefined|. + "no-void": ["error", { allowAsStatement: true }], + // Disallow loose equality because of objects with the [[IsHTMLDDA]] + // internal slot, aka |document.all|, aka "objects emulating undefined". + eqeqeq: "error", + // All self-hosted code is implicitly strict mode, so there's no need to + // add a strict-mode directive. + strict: ["error", "never"], + // Disallow syntax not supported in self-hosted code. + "no-restricted-syntax": [ + "error", + { + selector: "ClassDeclaration", + message: "Class declarations are not allowed", + }, + { + selector: "ClassExpression", + message: "Class expressions are not allowed", + }, + { + selector: "Literal[regex]", + message: "Regular expression literals are not allowed", + }, + { + selector: "CallExpression > MemberExpression.callee", + message: + "Direct method calls are not allowed, use callFunction() or callContentFunction()", + }, + { + selector: "NewExpression > MemberExpression.callee", + message: + "Direct method calls are not allowed, use constructContentFunction()", + }, + { + selector: "YieldExpression[delegate=true]", + message: + "yield* is not allowed because it can run user-modifiable iteration code", + }, + { + selector: "ForOfStatement > :not(CallExpression).right", + message: + "for-of loops must use allowContentIter(), allowContentIterWith(), or allowContentIterWithNext()", + }, + { + selector: + "ForOfStatement > CallExpression.right > :not(Identifier[name='allowContentIter'], Identifier[name='allowContentIterWith'], Identifier[name='allowContentIterWithNext']).callee", + message: + "for-of loops must use allowContentIter(), allowContentIterWith(), or allowContentIterWithNext", + }, + { + selector: + "CallExpression[callee.name='TO_PROPERTY_KEY'] > :not(Identifier).arguments:first-child", + message: + "TO_PROPERTY_KEY macro must be called with a simple identifier", + }, + { + selector: "Identifier[name='arguments']", + message: + "'arguments' is disallowed, use ArgumentsLength(), GetArgument(n), or rest-parameters", + }, + { + selector: "VariableDeclaration[kind='let']", + message: + "'let' declarations are disallowed to avoid TDZ checks, use 'var' instead", + }, + { + selector: "VariableDeclaration[kind='const']", + message: + "'const' declarations are disallowed to avoid TDZ checks, use 'var' instead", + }, + ], + // Method signatures are important in builtins so disable unused argument errors. + "no-unused-vars": [ + "error", + { + args: "none", + vars: "local", + }, + ], + }, + + languageOptions: { + parserOptions: { + ecmaVersion: "latest", + + // Self-hosted code defaults to strict mode. + ecmaFeatures: { + impliedStrict: true, + }, + + // Strict mode has to be enabled separately for the Babel parser. + babelOptions: { + parserOpts: { + strictMode: true, + }, + }, + }, + + sourceType: "script", + globals: { + // Disable all built-in environments. + ...mozilla.turnOff(globals.node), + ...mozilla.turnOff(globals.browser), + ...mozilla.turnOff(globals.builtin), + + // We need to explicitly disable the default environments added from + // "tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js". + ...mozilla.turnOff(globals.es2021), + ...mozilla.turnOff(mozilla.environments.privileged.globals), + ...mozilla.turnOff(mozilla.environments.specific.globals), + + // Enable SpiderMonkey's self-hosted environment. + ...spidermonkeyJS.environments.environment.globals, + + // The bytecode compiler special-cases these identifiers. + ArgumentsLength: "readonly", + allowContentIter: "readonly", + allowContentIterWith: "readonly", + allowContentIterWithNext: "readonly", + callContentFunction: "readonly", + callFunction: "readonly", + constructContentFunction: "readonly", + DefineDataProperty: "readonly", + forceInterpreter: "readonly", + GetArgument: "readonly", + GetBuiltinConstructor: "readonly", + GetBuiltinPrototype: "readonly", + GetBuiltinSymbol: "readonly", + getPropertySuper: "readonly", + hasOwn: "readonly", + IsNullOrUndefined: "readonly", + IteratorClose: "readonly", + resumeGenerator: "readonly", + SetCanonicalName: "readonly", + SetIsInlinableLargeFunction: "readonly", + ToNumeric: "readonly", + ToString: "readonly", + DisposeResourcesAsync: "readonly", + DisposeResourcesSync: "readonly", + + // We've disabled all built-in environments, which also removed + // `undefined` from the list of globals. Put it back because it's + // actually allowed in self-hosted code. + undefined: "readonly", + + // Disable globals from stage 2/3 proposals for which we have work in + // progress patches. Eventually these will be part of a future ES + // release, in which case we can remove these extra entries. + AsyncIterator: "off", + Iterator: "off", + Record: "off", + Temporal: "off", + Tuple: "off", + }, + }, + }, +]; diff --git a/src/third_party/mozjs/extract/js/src/builtin/Array.cpp b/src/third_party/mozjs/extract/js/src/builtin/Array.cpp index 3bc06151dfd..871d4d1abda 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Array.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Array.cpp @@ -32,7 +32,7 @@ #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/PropertySpec.h" #include "util/Poison.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "util/Text.h" #include "vm/ArgumentsObject.h" #include "vm/EqualityOperations.h" @@ -42,16 +42,13 @@ #include "vm/JSFunction.h" #include "vm/JSObject.h" #include "vm/PlainObject.h" // js::PlainObject +#include "vm/Probes.h" #include "vm/SelfHosting.h" #include "vm/Shape.h" #include "vm/StringType.h" #include "vm/ToSource.h" // js::ValueToSource #include "vm/TypedArrayObject.h" #include "vm/WrapperObject.h" -#ifdef ENABLE_RECORD_TUPLE -# include "vm/TupleType.h" -#endif - #include "builtin/Sorting-inl.h" #include "vm/ArgumentsObject-inl.h" #include "vm/ArrayObject-inl.h" @@ -66,7 +63,6 @@ using mozilla::Abs; using mozilla::CeilingLog2; using mozilla::CheckedInt; using mozilla::DebugOnly; -using mozilla::IsAsciiDigit; using mozilla::Maybe; using mozilla::SIMD; @@ -239,7 +235,7 @@ static MOZ_ALWAYS_INLINE bool GetLengthPropertyInlined(JSContext* cx, * "08" or "4.0" as array indices, which they are not. * */ -JS_PUBLIC_API bool js::StringIsArrayIndex(JSLinearString* str, +JS_PUBLIC_API bool js::StringIsArrayIndex(const JSLinearString* str, uint32_t* indexp) { if (!str->isIndex(indexp)) { return false; @@ -650,6 +646,88 @@ struct ReverseIndexComparator { } }; +// Fast path to remove all elements with index >= newLen when setting the +// .length property of an array to a smaller value. +static bool TryFastDeleteElementsForNewLength(JSContext* cx, + Handle arr, + uint32_t newLen, bool* success) { + MOZ_ASSERT(newLen < arr->length()); + + // If there might be an active for-in iterator for this array we have to use + // the generic code path because it supports suppressing deleted properties. + // Keys deleted before being reached during the iteration must not be visited. + if (arr->denseElementsMaybeInIteration()) { + *success = false; + return true; + } + + // Sealed elements are non-configurable and shouldn't be removed. + if (arr->denseElementsAreSealed()) { + *success = false; + return true; + } + + if (arr->isIndexed()) { + // This fast path doesn't suppress deleted properties from active iterators. + if (arr->compartment()->objectMaybeInIteration(arr)) { + *success = false; + return true; + } + + // First add all sparse indexes we want to remove to a vector and check for + // non-configurable elements. + JS::RootedVector keys(cx); + for (ShapePropertyIter iter(arr->shape()); !iter.done(); iter++) { + uint32_t index; + if (!IdIsIndex(iter->key(), &index)) { + continue; + } + if (index < newLen) { + continue; + } + // Non-configurable elements shouldn't be removed. + if (!iter->configurable()) { + *success = false; + return true; + } + if (!keys.append(iter->key())) { + return false; + } + } + + // Remove the sparse elements. Note that this starts at the most recently + // added property because this is most efficient when removing many + // elements. + // + // The rest of this function must be infallible (other than OOM). + for (size_t i = 0, len = keys.length(); i < len; i++) { + MOZ_ASSERT(arr->containsPure(keys[i]), "must still be a sparse element"); + if (!NativeObject::removeProperty(cx, arr, keys[i])) { + MOZ_ASSERT(cx->isThrowingOutOfMemory()); + return false; + } + } + } + + // Remove dense elements. + uint32_t oldCapacity = arr->getDenseCapacity(); + uint32_t oldInitializedLength = arr->getDenseInitializedLength(); + MOZ_ASSERT(oldCapacity >= oldInitializedLength); + if (oldInitializedLength > newLen) { + arr->setDenseInitializedLengthMaybeNonExtensible(cx, newLen); + } + if (oldCapacity > newLen) { + if (arr->isExtensible()) { + arr->shrinkElements(cx, newLen); + } else { + MOZ_ASSERT(arr->getDenseInitializedLength() == arr->getDenseCapacity()); + } + } + + *success = true; + return true; +} + /* ES6 draft rev 34 (2015 Feb 20) 9.4.2.4 ArraySetLength */ bool js::ArraySetLength(JSContext* cx, Handle arr, HandleId id, Handle desc, @@ -729,41 +807,14 @@ bool js::ArraySetLength(JSContext* cx, Handle arr, HandleId id, break; } - // Attempt to propagate dense-element optimization tricks, if possible, - // and avoid the generic (and accordingly slow) deletion code below. - // We can only do this if there are only densely-indexed elements. - // Once there's a sparse indexed element, there's no good way to know, - // save by enumerating all the properties to find it. But we *have* to - // know in case that sparse indexed element is non-configurable, as - // that element must prevent any deletions below it. Bug 586842 should - // fix this inefficiency by moving indexed storage to be entirely - // separate from non-indexed storage. - // A second reason for this optimization to be invalid is an active - // for..in iteration over the array. Keys deleted before being reached - // during the iteration must not be visited, and suppressing them here - // would be too costly. - // This optimization is also invalid when there are sealed - // (non-configurable) elements. - if (!arr->isIndexed() && !arr->denseElementsMaybeInIteration() && - !arr->denseElementsAreSealed()) { - uint32_t oldCapacity = arr->getDenseCapacity(); - uint32_t oldInitializedLength = arr->getDenseInitializedLength(); - MOZ_ASSERT(oldCapacity >= oldInitializedLength); - if (oldInitializedLength > newLen) { - arr->setDenseInitializedLengthMaybeNonExtensible(cx, newLen); - } - if (oldCapacity > newLen) { - if (arr->isExtensible()) { - arr->shrinkElements(cx, newLen); - } else { - MOZ_ASSERT(arr->getDenseInitializedLength() == - arr->getDenseCapacity()); - } - } + bool success; + if (!TryFastDeleteElementsForNewLength(cx, arr, newLen, &success)) { + return false; + } - // We've done the work of deleting any dense elements needing - // deletion, and there are no sparse elements. Thus we can skip - // straight to defining the length. + if (success) { + // We've done the work of deleting any elements needing deletion. + // Thus we can skip straight to defining the length. break; } @@ -878,7 +929,7 @@ bool js::ArraySetLength(JSContext* cx, Handle arr, HandleId id, // Update array length. Technically we should have been doing this // throughout the loop, in step 19.d.iii. - arr->setLength(newLen); + arr->setLength(cx, newLen); // Step 20. if (desc.hasWritable() && !desc.writable()) { @@ -929,7 +980,7 @@ static bool array_addProperty(JSContext* cx, HandleObject obj, HandleId id, if (index >= length) { MOZ_ASSERT(arr->lengthIsWritable(), "how'd this element get added if length is non-writable?"); - arr->setLength(index + 1); + arr->setLength(cx, index + 1); } return true; } @@ -984,6 +1035,38 @@ bool js::IsCrossRealmArrayConstructor(JSContext* cx, JSObject* obj, return true; } +static MOZ_ALWAYS_INLINE bool HasBuiltinArraySpecies(ArrayObject* arr, + JSContext* cx) { + // Ensure `Array.prototype.constructor` and `Array[@@species]` haven't been + // mutated. + if (!cx->realm()->realmFuses.optimizeArraySpeciesFuse.intact()) { + return false; + } + + // Ensure the array has `Array.prototype` as prototype and doesn't have an own + // `constructor` property. + // + // Most arrays have the default array shape so we have a fast path for this + // case. + GlobalObject* global = cx->global(); + if (arr->shape() == global->maybeArrayShapeWithDefaultProto()) { + return true; + } + + // Ensure the array's prototype is the actual Array.prototype. + NativeObject* arrayProto = global->maybeGetArrayPrototype(); + if (!arrayProto || arr->staticPrototype() != arrayProto) { + return false; + } + + // Fail if the array has an own `constructor` property. + if (arr->containsPure(NameToId(cx->names().constructor))) { + return false; + } + + return true; +} + // Returns true iff we know for -sure- that it is definitely safe to use the // realm's array constructor. // @@ -1009,8 +1092,7 @@ static MOZ_ALWAYS_INLINE bool IsArraySpecies(JSContext* cx, return true; } - if (cx->realm()->arraySpeciesLookup.tryOptimizeArray( - cx, &origArray->as())) { + if (HasBuiltinArraySpecies(&origArray->as(), cx)) { return true; } @@ -1043,6 +1125,30 @@ static MOZ_ALWAYS_INLINE bool IsArraySpecies(JSContext* cx, return IsSelfHostedFunctionWithName(getter, cx->names().dollar_ArraySpecies_); } +bool js::intrinsic_CanOptimizeArraySpecies(JSContext* cx, unsigned argc, + Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 1); + + JSObject* obj = &args[0].toObject(); + + // Return `true` if this is a plain array with the original array shape and + // an intact array-species fuse. This is the case for at least 98% of all + // calls on Speedometer 3 and JetStream 2. This condition is also simple + // enough to inline efficiently in JIT code. + // + // The shape check implies: + // - The object is an array object. + // - The array belongs to the current realm. + // - The array has (the current realm's) `Array.prototype` as prototype. + // - The array does not define an own `constructor` property. + bool optimizable = + obj->shape() == cx->global()->maybeArrayShapeWithDefaultProto() && + cx->realm()->realmFuses.optimizeArraySpeciesFuse.intact(); + args.rval().setBoolean(optimizable); + return true; +} + static bool ArraySpeciesCreate(JSContext* cx, HandleObject origArray, uint64_t length, MutableHandleObject arr) { MOZ_ASSERT(length < DOUBLE_INTEGRAL_PRECISION_LIMIT); @@ -1152,7 +1258,7 @@ static bool array_toSource(JSContext* cx, unsigned argc, Value* vp) { template static bool ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, Handle obj, uint64_t length, - StringBuffer& sb, uint32_t* numProcessed) { + StringBuilder& sb, uint32_t* numProcessed) { // This loop handles all elements up to initializedLength. If // length > initLength we rely on the second loop to add the // other elements. @@ -1176,11 +1282,11 @@ static bool ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, return false; } } else if (elem.isNumber()) { - if (!NumberValueToStringBuffer(elem, sb)) { + if (!NumberValueToStringBuilder(elem, sb)) { return false; } } else if (elem.isBoolean()) { - if (!BooleanToStringBuffer(elem.toBoolean(), sb)) { + if (!BooleanToStringBuilder(elem.toBoolean(), sb)) { return false; } } else if (elem.isObject() || elem.isSymbol()) { @@ -1214,7 +1320,7 @@ static bool ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, template static bool ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, - uint64_t length, StringBuffer& sb) { + uint64_t length, StringBuilder& sb) { // Step 6. uint32_t numProcessed = 0; @@ -1240,7 +1346,7 @@ static bool ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, // Steps 7.c-d. if (!v.isNullOrUndefined()) { - if (!ValueToStringBuffer(cx, v, sb)) { + if (!ValueToStringBuilder(cx, v, sb)) { return false; } } @@ -1346,7 +1452,7 @@ bool js::array_join(JSContext* cx, unsigned argc, Value* vp) { // Various optimized versions of steps 6-7. if (seplen == 0) { - auto sepOp = [](StringBuffer&) { return true; }; + auto sepOp = [](StringBuilder&) { return true; }; if (!ArrayJoinKernel(cx, sepOp, obj, length, sb)) { return false; } @@ -1354,19 +1460,21 @@ bool js::array_join(JSContext* cx, unsigned argc, Value* vp) { char16_t c = sepstr->latin1OrTwoByteChar(0); if (c <= JSString::MAX_LATIN1_CHAR) { Latin1Char l1char = Latin1Char(c); - auto sepOp = [l1char](StringBuffer& sb) { return sb.append(l1char); }; + auto sepOp = [l1char](StringBuilder& sb) { return sb.append(l1char); }; if (!ArrayJoinKernel(cx, sepOp, obj, length, sb)) { return false; } } else { - auto sepOp = [c](StringBuffer& sb) { return sb.append(c); }; + auto sepOp = [c](StringBuilder& sb) { return sb.append(c); }; if (!ArrayJoinKernel(cx, sepOp, obj, length, sb)) { return false; } } } else { Handle sepHandle = sepstr; - auto sepOp = [sepHandle](StringBuffer& sb) { return sb.append(sepHandle); }; + auto sepOp = [sepHandle](StringBuilder& sb) { + return sb.append(sepHandle); + }; if (!ArrayJoinKernel(cx, sepOp, obj, length, sb)) { return false; } @@ -1731,9 +1839,9 @@ struct StringifiedElement { struct SortComparatorStringifiedElements { JSContext* const cx; - const StringBuffer& sb; + const StringBuilder& sb; - SortComparatorStringifiedElements(JSContext* cx, const StringBuffer& sb) + SortComparatorStringifiedElements(JSContext* cx, const StringBuilder& sb) : cx(cx), sb(sb) {} bool operator()(const StringifiedElement& a, const StringifiedElement& b, @@ -1920,7 +2028,7 @@ static bool SortLexicographically(JSContext* cx, size_t len) { MOZ_ASSERT(vec.length() >= len); - StringBuffer sb(cx); + StringBuilder sb(cx); Vector strElements(cx); /* MergeSort uses the upper half as scratch space. */ @@ -1935,7 +2043,7 @@ static bool SortLexicographically(JSContext* cx, return false; } - if (!ValueToStringBuffer(cx, vec[i], sb)) { + if (!ValueToStringBuilder(cx, vec[i], sb)) { return false; } @@ -2015,7 +2123,7 @@ static bool FillWithUndefined(JSContext* cx, HandleObject obj, uint32_t start, if (obj->is() && start + count >= obj->as().length()) { - obj->as().setLength(start + count); + obj->as().setLengthToInitializedLength(); } for (uint32_t i = 0; i < count; i++) { @@ -2412,6 +2520,7 @@ bool js::array_sort(JSContext* cx, unsigned argc, Value* vp) { ArraySortResult js::ArraySortFromJit(JSContext* cx, jit::TrampolineNativeFrameLayout* frame) { + AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "sort"); // Initialize the ArraySortData class stored in the trampoline frame. void* dataUninit = frame->getFrameData(); auto* data = new (dataUninit) ArraySortData(cx); @@ -2458,7 +2567,7 @@ bool js::NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v) { } arr->setDenseInitializedLength(length + 1); - arr->setLength(length + 1); + arr->setLengthToInitializedLength(); arr->initDenseElement(length, v); return true; } @@ -2579,7 +2688,7 @@ void js::ArrayShiftMoveElements(ArrayObject* arr) { } MOZ_ASSERT(arr->getDenseInitializedLength() == initlen - 1); - arr->setLength(initlen - 1); + arr->setLengthToInitializedLength(); } static inline void SetInitializedLength(JSContext* cx, NativeObject* obj, @@ -2908,7 +3017,7 @@ static ArrayObject* CopyDenseArrayElements(JSContext* cx, } MOZ_ASSERT(count >= narr->length()); - narr->setLength(count); + narr->setLength(cx, count); if (newlength > 0) { narr->initDenseElements(obj, begin, newlength); @@ -2973,32 +3082,8 @@ static bool CopyArrayElements(JSContext* cx, HandleObject obj, uint64_t begin, // Helpers for array_splice_impl() and array_to_spliced() // // Initialize variables common to splice() and toSpliced(): -// - GetActualStart() returns the index at which to start deleting elements. // - GetItemCount() returns the number of new elements being added. // - GetActualDeleteCount() returns the number of elements being deleted. -static bool GetActualStart(JSContext* cx, HandleValue start, uint64_t len, - uint64_t* result) { - MOZ_ASSERT(len < DOUBLE_INTEGRAL_PRECISION_LIMIT); - - // Steps from proposal: https://github.com/tc39/proposal-change-array-by-copy - // Array.prototype.toSpliced() - - // Step 3. Let relativeStart be ? ToIntegerOrInfinity(start). - double relativeStart; - if (!ToInteger(cx, start, &relativeStart)) { - return false; - } - - // Steps 4-5. If relativeStart is -∞, let actualStart be 0. - // Else if relativeStart < 0, let actualStart be max(len + relativeStart, 0). - if (relativeStart < 0) { - *result = uint64_t(std::max(double(len) + relativeStart, 0.0)); - } else { - // Step 6. Else, let actualStart be min(relativeStart, len). - *result = uint64_t(std::min(relativeStart, double(len))); - } - return true; -} static uint32_t GetItemCount(const CallArgs& args) { if (args.length() < 2) { @@ -3015,9 +3100,6 @@ static bool GetActualDeleteCount(JSContext* cx, const CallArgs& args, MOZ_ASSERT(actualStart <= len); MOZ_ASSERT(insertCount == GetItemCount(args)); - // Steps from proposal: https://github.com/tc39/proposal-change-array-by-copy - // Array.prototype.toSpliced() - if (args.length() < 1) { // Step 8. If start is not present, then let actualDeleteCount be 0. *actualDeleteCount = 0; @@ -3034,8 +3116,8 @@ static bool GetActualDeleteCount(JSContext* cx, const CallArgs& args, // Step 10.b. Let actualDeleteCount be the result of clamping dc between 0 // and len - actualStart. - *actualDeleteCount = uint64_t( - std::min(std::max(0.0, deleteCount), double(len - actualStart))); + *actualDeleteCount = + uint64_t(std::clamp(deleteCount, 0.0, double(len - actualStart))); MOZ_ASSERT(*actualDeleteCount <= len); // Step 11. Let newLen be len + insertCount - actualDeleteCount. @@ -3072,10 +3154,13 @@ static bool array_splice_impl(JSContext* cx, unsigned argc, Value* vp, /* Steps 3-6. */ /* actualStart is the index after which elements will be deleted and/or new elements will be added */ - uint64_t actualStart; - if (!GetActualStart(cx, args.get(0), len, &actualStart)) { - return false; + uint64_t actualStart = 0; + if (args.hasDefined(0)) { + if (!ToIntegerIndex(cx, args[0], len, &actualStart)) { + return false; + } } + MOZ_ASSERT(actualStart <= len); /* Steps 7-10.*/ /* itemCount is the number of elements being added */ @@ -3389,8 +3474,8 @@ static void CopyDenseElementsFillHoles(ArrayObject* arr, NativeObject* nobj, MOZ_ASSERT(arr->denseElementsArePacked()); } -// https://github.com/tc39/proposal-change-array-by-copy -// Array.prototype.toSpliced() +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items ) static bool array_toSpliced(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "toSpliced"); CallArgs args = CallArgsFromVp(argc, vp); @@ -3410,9 +3495,11 @@ static bool array_toSpliced(JSContext* cx, unsigned argc, Value* vp) { // Steps 3-6. // |actualStart| is the index after which elements will be deleted and/or // new elements will be added - uint64_t actualStart; - if (!GetActualStart(cx, args.get(0), len, &actualStart)) { - return false; + uint64_t actualStart = 0; + if (args.hasDefined(0)) { + if (!ToIntegerIndex(cx, args[0], len, &actualStart)) { + return false; + } } MOZ_ASSERT(actualStart <= len); @@ -3470,7 +3557,6 @@ static bool array_toSpliced(JSContext* cx, unsigned argc, Value* vp) { if (!arr) { return false; } - arr->setLength(newLength); // Below code doesn't handle the case when the storage has to grow, // therefore the capacity must fit for at least |newLength| elements. @@ -3654,8 +3740,8 @@ static bool array_toSpliced(JSContext* cx, unsigned argc, Value* vp) { return true; } -// https://github.com/tc39/proposal-change-array-by-copy -// Array.prototype.with() +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// Array.prototype.with ( index, value ) static bool array_with(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "with"); CallArgs args = CallArgsFromVp(argc, vp); @@ -3675,7 +3761,6 @@ static bool array_with(JSContext* cx, unsigned argc, Value* vp) { // Step 3. Let relativeIndex be ? ToIntegerOrInfinity(index). double relativeIndex; if (!ToInteger(cx, args.get(0), &relativeIndex)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX); return false; } @@ -3712,7 +3797,6 @@ static bool array_with(JSContext* cx, unsigned argc, Value* vp) { if (!arr) { return false; } - arr->setLength(length); CopyDenseElementsFillHoles(arr, nobj, length); @@ -3931,19 +4015,6 @@ static JSObject* SliceArguments(JSContext* cx, Handle argsobj, return result; } -template -static inline ArrayLength NormalizeSliceTerm(T value, ArrayLength length) { - if (value < 0) { - value += length; - if (value < 0) { - return 0; - } - } else if (double(value) > double(length)) { - return length; - } - return ArrayLength(value); -} - static bool ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint64_t begin, uint64_t end, MutableHandleValue rval) { if (begin > end) { @@ -4034,26 +4105,19 @@ static bool array_slice(JSContext* cx, unsigned argc, Value* vp) { return false; } + /* Steps 3-4. */ uint64_t k = 0; - uint64_t final = length; - if (args.length() > 0) { - double d; - /* Step 3. */ - if (!ToInteger(cx, args[0], &d)) { + if (args.hasDefined(0)) { + if (!ToIntegerIndex(cx, args[0], length, &k)) { return false; } + } - /* Step 4. */ - k = NormalizeSliceTerm(d, length); - - if (args.hasDefined(1)) { - /* Step 5. */ - if (!ToInteger(cx, args[1], &d)) { - return false; - } - - /* Step 6. */ - final = NormalizeSliceTerm(d, length); + /* Steps 5-6. */ + uint64_t final = length; + if (args.hasDefined(1)) { + if (!ToIntegerIndex(cx, args[1], length, &final)) { + return false; } } @@ -4111,6 +4175,13 @@ static bool array_slice(JSContext* cx, unsigned argc, Value* vp) { return true; } +static inline uint32_t NormalizeSliceTerm(int32_t value, uint32_t length) { + if (value >= 0) { + return std::min(uint32_t(value), length); + } + return uint32_t(std::max(int32_t(uint32_t(value) + length), 0)); +} + static bool ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr, int32_t beginArg, int32_t endArg, ArrayObject* result) { @@ -4136,7 +4207,7 @@ static bool ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr, } MOZ_ASSERT(count >= result->length()); - result->setLength(count); + result->setLength(cx, count); return true; } @@ -4194,7 +4265,7 @@ JSObject* js::ArgumentsSliceDense(JSContext* cx, HandleObject obj, return nullptr; } resArray->setDenseInitializedLength(count); - resArray->setLength(count); + resArray->setLengthToInitializedLength(); for (uint32_t index = 0; index < count; index++) { const Value& v = argsobj->element(actualBegin + index); @@ -4250,11 +4321,6 @@ static bool array_of(JSContext* cx, unsigned argc, Value* vp) { return ArrayFromCallArgs(cx, args); } - if (!ReportUsageCounter(cx, nullptr, SUBCLASSING_ARRAY, - SUBCLASSING_TYPE_II)) { - return false; - } - // Step 4. RootedObject obj(cx); { @@ -4370,8 +4436,7 @@ static bool SearchElementDense(JSContext* cx, HandleValue val, Iter iterator, return iterator(cx, cmp, rval); } - MOZ_ASSERT(val.isBigInt() || - IF_RECORD_TUPLE(val.isExtendedPrimitive(), false)); + MOZ_ASSERT(val.isBigInt()); // Generic implementation for the remaining types. RootedValue elementRoot(cx); @@ -4393,8 +4458,8 @@ static bool SearchElementDense(JSContext* cx, HandleValue val, Iter iterator, return iterator(cx, cmp, rval); } -// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 -// 22.1.3.14 Array.prototype.indexOf ( searchElement [ , fromIndex ] ) +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 23.1.3.17 Array.prototype.indexOf ( searchElement [ , fromIndex ] ) bool js::array_indexOf(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "indexOf"); CallArgs args = CallArgsFromVp(argc, vp); @@ -4417,36 +4482,25 @@ bool js::array_indexOf(JSContext* cx, unsigned argc, Value* vp) { return true; } - // Steps 4-8. + // Steps 4-9. uint64_t k = 0; - if (args.length() > 1) { - double n; - if (!ToInteger(cx, args[1], &n)) { + if (args.hasDefined(1)) { + if (!ToIntegerIndex(cx, args[1], len, &k)) { return false; } - // Step 6. - if (n >= double(len)) { + // Return early if |k| exceeds the current length. + if (k >= len) { args.rval().setInt32(-1); return true; } - - // Steps 7-8. - if (n >= 0) { - k = uint64_t(n); - } else { - double d = double(len) + n; - if (d >= 0) { - k = uint64_t(d); - } - } } MOZ_ASSERT(k < len); HandleValue searchElement = args.get(0); - // Steps 9 and 10 optimized for dense elements. + // Step 10 optimized for dense elements. if (CanOptimizeForDenseStorage(obj, len)) { MOZ_ASSERT(len <= UINT32_MAX); @@ -4490,7 +4544,7 @@ bool js::array_indexOf(JSContext* cx, unsigned argc, Value* vp) { args.rval()); } - // Step 9. + // Step 10. RootedValue v(cx); for (; k < len; k++) { if (!CheckForInterrupt(cx)) { @@ -4515,7 +4569,7 @@ bool js::array_indexOf(JSContext* cx, unsigned argc, Value* vp) { } } - // Step 10. + // Step 11. args.rval().setInt32(-1); return true; } @@ -4634,8 +4688,8 @@ bool js::array_lastIndexOf(JSContext* cx, unsigned argc, Value* vp) { return true; } -// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 -// 22.1.3.13 Array.prototype.includes ( searchElement [ , fromIndex ] ) +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 23.1.3.16 Array.prototype.includes ( searchElement [ , fromIndex ] ) bool js::array_includes(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "includes"); CallArgs args = CallArgsFromVp(argc, vp); @@ -4658,35 +4712,25 @@ bool js::array_includes(JSContext* cx, unsigned argc, Value* vp) { return true; } - // Steps 4-7. + // Steps 4-9. uint64_t k = 0; - if (args.length() > 1) { - double n; - if (!ToInteger(cx, args[1], &n)) { + if (args.hasDefined(1)) { + if (!ToIntegerIndex(cx, args[1], len, &k)) { return false; } - if (n >= double(len)) { + // Return early if |k| exceeds the current length. + if (k >= len) { args.rval().setBoolean(false); return true; } - - // Steps 6-7. - if (n >= 0) { - k = uint64_t(n); - } else { - double d = double(len) + n; - if (d >= 0) { - k = uint64_t(d); - } - } } MOZ_ASSERT(k < len); HandleValue searchElement = args.get(0); - // Steps 8 and 9 optimized for dense elements. + // Step 10 optimized for dense elements. if (CanOptimizeForDenseStorage(obj, len)) { MOZ_ASSERT(len <= UINT32_MAX); @@ -4735,7 +4779,7 @@ bool js::array_includes(JSContext* cx, unsigned argc, Value* vp) { args.rval()); } - // Step 8. + // Step 10. RootedValue v(cx); for (; k < len; k++) { if (!CheckForInterrupt(cx)) { @@ -4756,7 +4800,7 @@ bool js::array_includes(JSContext* cx, unsigned argc, Value* vp) { } } - // Step 9. + // Step 11. args.rval().setBoolean(false); return true; } @@ -5110,16 +5154,17 @@ static const JSFunctionSpec array_methods[] = { JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1, 0), JS_SELF_HOSTED_FN("flat", "ArrayFlat", 0, 0), - /* Proposal */ JS_SELF_HOSTED_FN("at", "ArrayAt", 1, 0), JS_SELF_HOSTED_FN("findLast", "ArrayFindLast", 1, 0), JS_SELF_HOSTED_FN("findLastIndex", "ArrayFindLastIndex", 1, 0), JS_SELF_HOSTED_FN("toReversed", "ArrayToReversed", 0, 0), JS_SELF_HOSTED_FN("toSorted", "ArrayToSorted", 1, 0), - JS_FN("toSpliced", array_toSpliced, 2, 0), JS_FN("with", array_with, 2, 0), + JS_FN("toSpliced", array_toSpliced, 2, 0), + JS_FN("with", array_with, 2, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec array_static_methods[] = { JS_INLINABLE_FN("isArray", array_isArray, 1, 0, ArrayIsArray), @@ -5127,10 +5172,13 @@ static const JSFunctionSpec array_static_methods[] = { JS_SELF_HOSTED_FN("fromAsync", "ArrayFromAsync", 3, 0), JS_FN("of", array_of, 0, 0), - JS_FS_END}; + JS_FS_END, +}; const JSPropertySpec array_static_props[] = { - JS_SELF_HOSTED_SYM_GET(species, "$ArraySpecies", 0), JS_PS_END}; + JS_SELF_HOSTED_SYM_GET(species, "$ArraySpecies", 0), + JS_PS_END, +}; static inline bool ArrayConstructorImpl(JSContext* cx, CallArgs& args, bool isConstructor) { @@ -5191,7 +5239,8 @@ bool js::array_construct(JSContext* cx, unsigned argc, Value* vp) { ArrayObject* js::ArrayConstructorOneArg(JSContext* cx, Handle templateObject, - int32_t lengthInt) { + int32_t lengthInt, + gc::AllocSite* site) { // JIT code can call this with a template object from a different realm when // calling another realm's Array constructor. Maybe ar; @@ -5207,7 +5256,8 @@ ArrayObject* js::ArrayConstructorOneArg(JSContext* cx, } uint32_t length = uint32_t(lengthInt); - ArrayObject* res = NewDensePartlyAllocatedArray(cx, length); + ArrayObject* res = + NewDensePartlyAllocatedArray(cx, length, GenericObject, site); MOZ_ASSERT_IF(res, res->realm() == templateObject->realm()); return res; } @@ -5242,8 +5292,9 @@ static MOZ_ALWAYS_INLINE ArrayObject* NewArrayWithShape( MOZ_ASSERT(shape->lastProperty().key() == NameToId(cx->names().length)); gc::AllocKind allocKind = GuessArrayGCKind(length); - MOZ_ASSERT(CanChangeToBackgroundAllocKind(allocKind, &ArrayObject::class_)); - allocKind = ForegroundToBackgroundAllocKind(allocKind); + MOZ_ASSERT(gc::GetObjectFinalizeKind(&ArrayObject::class_) == + gc::FinalizeKind::None); + MOZ_ASSERT(!IsFinalizedKind(allocKind)); MOZ_ASSERT(shape->slotSpan() == 0); constexpr uint32_t slotSpan = 0; @@ -5251,7 +5302,7 @@ static MOZ_ALWAYS_INLINE ArrayObject* NewArrayWithShape( AutoSetNewObjectMetadata metadata(cx); ArrayObject* arr = ArrayObject::create( cx, allocKind, GetInitialHeap(newKind, &ArrayObject::class_, site), shape, - length, slotSpan, metadata); + length, slotSpan, metadata, site); if (!arr) { return nullptr; } @@ -5340,6 +5391,20 @@ static MOZ_ALWAYS_INLINE ArrayObject* NewArrayWithProto(JSContext* cx, return NewArrayWithShape(cx, shape, length, newKind, nullptr); } +static JSObject* CreateArrayConstructor(JSContext* cx, JSProtoKey key) { + MOZ_ASSERT(key == JSProto_Array); + Rooted ctor(cx, GlobalObject::createConstructor( + cx, ArrayConstructor, cx->names().Array, 1, + gc::AllocKind::FUNCTION, &jit::JitInfo_Array)); + if (!ctor) { + return nullptr; + } + if (!JSObject::setHasFuseProperty(cx, ctor)) { + return nullptr; + } + return ctor; +} + static JSObject* CreateArrayPrototype(JSContext* cx, JSProtoKey key) { MOZ_ASSERT(key == JSProto_Array); RootedObject proto(cx, &cx->global()->getObjectPrototype()); @@ -5399,19 +5464,17 @@ static const JSClassOps ArrayObjectClassOps = { }; static const ClassSpec ArrayObjectClassSpec = { - GenericCreateConstructor, - CreateArrayPrototype, - array_static_methods, - array_static_props, - array_methods, - nullptr, - array_proto_finish}; + CreateArrayConstructor, CreateArrayPrototype, array_static_methods, + array_static_props, array_methods, nullptr, + array_proto_finish, +}; const JSClass ArrayObject::class_ = { "Array", JSCLASS_HAS_CACHED_PROTO(JSProto_Array) | JSCLASS_DELAY_METADATA_BUILDER, - &ArrayObjectClassOps, &ArrayObjectClassSpec}; + &ArrayObjectClassOps, + &ArrayObjectClassSpec, +}; ArrayObject* js::NewDenseEmptyArray(JSContext* cx) { return NewArray<0>(cx, 0, GenericObject); @@ -5428,9 +5491,10 @@ ArrayObject* js::NewDenseFullyAllocatedArray( } ArrayObject* js::NewDensePartlyAllocatedArray( - JSContext* cx, uint32_t length, - NewObjectKind newKind /* = GenericObject */) { - return NewArray(cx, length, newKind); + JSContext* cx, uint32_t length, NewObjectKind newKind /* = GenericObject */, + gc::AllocSite* site /* = nullptr */) { + return NewArray(cx, length, newKind, + site); } ArrayObject* js::NewDensePartlyAllocatedArrayWithProto(JSContext* cx, @@ -5489,8 +5553,9 @@ ArrayObject* js::NewDenseFullyAllocatedArrayWithShape( JSContext* cx, uint32_t length, Handle shape) { AutoSetNewObjectMetadata metadata(cx); gc::AllocKind allocKind = GuessArrayGCKind(length); - MOZ_ASSERT(CanChangeToBackgroundAllocKind(allocKind, &ArrayObject::class_)); - allocKind = ForegroundToBackgroundAllocKind(allocKind); + MOZ_ASSERT(gc::GetObjectFinalizeKind(&ArrayObject::class_) == + gc::FinalizeKind::None); + MOZ_ASSERT(!IsFinalizedKind(allocKind)); gc::Heap heap = GetInitialHeap(GenericObject, &ArrayObject::class_); ArrayObject* arr = ArrayObject::create(cx, allocKind, heap, shape, length, @@ -5550,160 +5615,6 @@ bool js::ArrayInfo(JSContext* cx, unsigned argc, Value* vp) { } #endif -void js::ArraySpeciesLookup::initialize(JSContext* cx) { - MOZ_ASSERT(state_ == State::Uninitialized); - - // Get the canonical Array.prototype. - NativeObject* arrayProto = cx->global()->maybeGetArrayPrototype(); - - // Leave the cache uninitialized if the Array class itself is not yet - // initialized. - if (!arrayProto) { - return; - } - - // Get the canonical Array constructor. The Array constructor must be - // initialized if Array.prototype is initialized. - JSObject& arrayCtorObject = cx->global()->getConstructor(JSProto_Array); - JSFunction* arrayCtor = &arrayCtorObject.as(); - - // Shortcut returns below means Array[@@species] will never be - // optimizable, set to disabled now, and clear it later when we succeed. - state_ = State::Disabled; - - // Look up Array.prototype.constructor and ensure it's a data property. - Maybe ctorProp = - arrayProto->lookup(cx, NameToId(cx->names().constructor)); - if (ctorProp.isNothing() || !ctorProp->isDataProperty()) { - return; - } - - // Get the referred value, and ensure it holds the canonical Array - // constructor. - JSFunction* ctorFun; - if (!IsFunctionObject(arrayProto->getSlot(ctorProp->slot()), &ctorFun)) { - return; - } - if (ctorFun != arrayCtor) { - return; - } - - // Look up the '@@species' value on Array - Maybe speciesProp = arrayCtor->lookup( - cx, PropertyKey::Symbol(cx->wellKnownSymbols().species)); - if (speciesProp.isNothing() || !arrayCtor->hasGetter(*speciesProp)) { - return; - } - - // Get the referred value, ensure it holds the canonical Array[@@species] - // function. - uint32_t speciesGetterSlot = speciesProp->slot(); - JSObject* speciesGetter = arrayCtor->getGetter(speciesGetterSlot); - if (!speciesGetter || !speciesGetter->is()) { - return; - } - JSFunction* speciesFun = &speciesGetter->as(); - if (!IsSelfHostedFunctionWithName(speciesFun, - cx->names().dollar_ArraySpecies_)) { - return; - } - - // Store raw pointers below. This is okay to do here, because all objects - // are in the tenured heap. - MOZ_ASSERT(!IsInsideNursery(arrayProto)); - MOZ_ASSERT(!IsInsideNursery(arrayCtor)); - MOZ_ASSERT(!IsInsideNursery(arrayCtor->shape())); - MOZ_ASSERT(!IsInsideNursery(speciesFun)); - MOZ_ASSERT(!IsInsideNursery(arrayProto->shape())); - - state_ = State::Initialized; - arrayProto_ = arrayProto; - arrayConstructor_ = arrayCtor; - arrayConstructorShape_ = arrayCtor->shape(); - arraySpeciesGetterSlot_ = speciesGetterSlot; - canonicalSpeciesFunc_ = speciesFun; - arrayProtoShape_ = arrayProto->shape(); - arrayProtoConstructorSlot_ = ctorProp->slot(); -} - -void js::ArraySpeciesLookup::reset() { - AlwaysPoison(this, JS_RESET_VALUE_PATTERN, sizeof(*this), - MemCheckKind::MakeUndefined); - state_ = State::Uninitialized; -} - -bool js::ArraySpeciesLookup::isArrayStateStillSane() { - MOZ_ASSERT(state_ == State::Initialized); - - // Ensure that Array.prototype still has the expected shape. - if (arrayProto_->shape() != arrayProtoShape_) { - return false; - } - - // Ensure that Array.prototype.constructor contains the canonical Array - // constructor function. - if (arrayProto_->getSlot(arrayProtoConstructorSlot_) != - ObjectValue(*arrayConstructor_)) { - return false; - } - - // Ensure that Array still has the expected shape. - if (arrayConstructor_->shape() != arrayConstructorShape_) { - return false; - } - - // Ensure the species getter contains the canonical @@species function. - JSObject* getter = arrayConstructor_->getGetter(arraySpeciesGetterSlot_); - return getter == canonicalSpeciesFunc_; -} - -bool js::ArraySpeciesLookup::tryOptimizeArray(JSContext* cx, - ArrayObject* array) { - if (state_ == State::Uninitialized) { - // If the cache is not initialized, initialize it. - initialize(cx); - } else if (state_ == State::Initialized && !isArrayStateStillSane()) { - // Otherwise, if the array state is no longer sane, reinitialize. - reset(); - initialize(cx); - } - - // If the cache is disabled or still uninitialized, don't bother trying to - // optimize. - if (state_ != State::Initialized) { - return false; - } - - // By the time we get here, we should have a sane array state. - MOZ_ASSERT(isArrayStateStillSane()); - - // Ensure |array|'s prototype is the actual Array.prototype. - if (array->staticPrototype() != arrayProto_) { - return false; - } - - // Ensure the array does not define an own "constructor" property which may - // shadow `Array.prototype.constructor`. - - // Most arrays don't define any additional own properties beside their - // "length" property. If "length" is the last property, it must be the only - // property, because it's non-configurable. - MOZ_ASSERT(array->shape()->propMapLength() > 0); - PropertyKey lengthKey = NameToId(cx->names().length); - if (MOZ_LIKELY(array->getLastProperty().key() == lengthKey)) { - MOZ_ASSERT(array->shape()->propMapLength() == 1, "Expected one property"); - return true; - } - - // Fail if the array has an own "constructor" property. - uint32_t index; - if (array->shape()->lookup(cx, NameToId(cx->names().constructor), &index)) { - return false; - } - - return true; -} - JS_PUBLIC_API JSObject* JS::NewArrayObject(JSContext* cx, const HandleValueArray& contents) { MOZ_ASSERT(!cx->zone()->isAtomsZone()); diff --git a/src/third_party/mozjs/extract/js/src/builtin/Array.h b/src/third_party/mozjs/extract/js/src/builtin/Array.h index 1389154014c..2bc8c3dd4a0 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Array.h +++ b/src/third_party/mozjs/extract/js/src/builtin/Array.h @@ -63,7 +63,8 @@ extern ArrayObject* NewDenseFullyAllocatedArray( // Create a dense array with length == 'length', initialized length set to 0, // and capacity == 'length' clamped to EagerAllocationMaxLength. extern ArrayObject* NewDensePartlyAllocatedArray( - JSContext* cx, uint32_t length, NewObjectKind newKind = GenericObject); + JSContext* cx, uint32_t length, NewObjectKind newKind = GenericObject, + gc::AllocSite* site = nullptr); // Like NewDensePartlyAllocatedArray, but the array will have |proto| as // prototype (or Array.prototype if |proto| is nullptr). @@ -142,7 +143,8 @@ extern bool NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v); extern ArrayObject* ArrayConstructorOneArg(JSContext* cx, Handle templateObject, - int32_t lengthInt); + int32_t lengthInt, + gc::AllocSite* site); #ifdef DEBUG extern bool ArrayInfo(JSContext* cx, unsigned argc, Value* vp); @@ -177,88 +179,10 @@ extern bool ArrayLengthSetter(JSContext* cx, HandleObject obj, HandleId id, extern ArraySortResult ArraySortFromJit( JSContext* cx, jit::TrampolineNativeFrameLayout* frame); -class MOZ_NON_TEMPORARY_CLASS ArraySpeciesLookup final { - /* - * An ArraySpeciesLookup holds the following: - * - * Array.prototype (arrayProto_) - * To ensure that the incoming array has the standard proto. - * - * Array.prototype's shape (arrayProtoShape_) - * To ensure that Array.prototype has not been modified. - * - * Array (arrayConstructor_) - * Array's shape (arrayConstructorShape_) - * To ensure that Array has not been modified. - * - * Array.prototype's slot number for constructor (arrayProtoConstructorSlot_) - * To quickly retrieve and ensure that the Array constructor - * stored in the slot has not changed. - * - * Array's slot number for the @@species getter. (arraySpeciesGetterSlot_) - * Array's canonical value for @@species (canonicalSpeciesFunc_) - * To quickly retrieve and ensure that the @@species getter for Array - * has not changed. - * - * MOZ_INIT_OUTSIDE_CTOR fields below are set in |initialize()|. The - * constructor only initializes a |state_| field, that defines whether the - * other fields are accessible. - */ - - // Pointer to canonical Array.prototype and Array. - MOZ_INIT_OUTSIDE_CTOR NativeObject* arrayProto_; - MOZ_INIT_OUTSIDE_CTOR NativeObject* arrayConstructor_; - - // Shape of matching Array, and slot containing the @@species property, and - // the canonical value. - MOZ_INIT_OUTSIDE_CTOR Shape* arrayConstructorShape_; - MOZ_INIT_OUTSIDE_CTOR uint32_t arraySpeciesGetterSlot_; - MOZ_INIT_OUTSIDE_CTOR JSFunction* canonicalSpeciesFunc_; - - // Shape of matching Array.prototype object, and slot containing the - // constructor for it. - MOZ_INIT_OUTSIDE_CTOR Shape* arrayProtoShape_; - MOZ_INIT_OUTSIDE_CTOR uint32_t arrayProtoConstructorSlot_; - - enum class State : uint8_t { - // Flags marking the lazy initialization of the above fields. - Uninitialized, - Initialized, - - // The disabled flag is set when we don't want to try optimizing - // anymore because core objects were changed. - Disabled - }; - - State state_ = State::Uninitialized; - - // Initialize the internal fields. - void initialize(JSContext* cx); - - // Reset the cache. - void reset(); - - // Check if the global array-related objects have not been messed with - // in a way that would disable this cache. - bool isArrayStateStillSane(); - - public: - /** Construct an |ArraySpeciesLookup| in the uninitialized state. */ - ArraySpeciesLookup() { reset(); } - - // Try to optimize the @@species lookup for an array. - bool tryOptimizeArray(JSContext* cx, ArrayObject* array); - - // Purge the cache and all info associated with it. - void purge() { - if (state_ == State::Initialized) { - reset(); - } - } -}; - bool IsArrayConstructor(const JSObject* obj); +bool intrinsic_CanOptimizeArraySpecies(JSContext* cx, unsigned argc, Value* vp); + } /* namespace js */ #endif /* builtin_Array_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/Array.js b/src/third_party/mozjs/extract/js/src/builtin/Array.js index dfa51fc86b6..86cb58ae1a6 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Array.js +++ b/src/third_party/mozjs/extract/js/src/builtin/Array.js @@ -131,7 +131,7 @@ function ArrayMap(callbackfn /*, thisArg*/) { var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; /* Steps 5. */ - var A = ArraySpeciesCreate(O, len); + var A = CanOptimizeArraySpecies(O) ? std_Array(len) : ArraySpeciesCreate(O, len); /* Steps 6-7. */ /* Steps 7.a (implicit), and 7.d. */ @@ -170,7 +170,7 @@ function ArrayFilter(callbackfn /*, thisArg*/) { var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; /* Step 5. */ - var A = ArraySpeciesCreate(O, 0); + var A = CanOptimizeArraySpecies(O) ? [] : ArraySpeciesCreate(O, 0); /* Steps 6-8. */ /* Steps 8.a (implicit), and 8.d. */ @@ -520,7 +520,7 @@ function CreateArrayIterator(obj, kind) { var iterator = NewArrayIterator(); UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_TARGET, iteratedObject); UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, 0); - UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_ITEM_KIND, kind); + UnsafeSetReservedSlot(iterator, ARRAY_ITERATOR_SLOT_ITEM_KIND, kind); return iterator; } @@ -552,7 +552,7 @@ function ArrayIteratorNext() { var index = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX); // Step 7. - var itemKind = UnsafeGetInt32FromReservedSlot(obj, ITERATOR_SLOT_ITEM_KIND); + var itemKind = UnsafeGetInt32FromReservedSlot(obj, ARRAY_ITERATOR_SLOT_ITEM_KIND); // Step 8-9. var len; @@ -681,9 +681,7 @@ function ArrayFromAsync(asyncItems, mapfn = undefined, thisArg = undefined) { // Step 3.e.i. Let A be ? Construct(C). // Step 3.f. Else, // Step 3.f.i. Let A be ! ArrayCreate(0). - var A = IsConstructor(C) ? - (ReportUsageCounter(C, SUBCLASS_ARRAY_TYPE_II), constructContentFunction(C, C)) : []; - + var A = IsConstructor(C) ? constructContentFunction(C, C) : []; // Step 3.j.i. Let k be 0. var k = 0; @@ -751,7 +749,7 @@ function ArrayFromAsync(asyncItems, mapfn = undefined, thisArg = undefined) { // Step 3.k.iv.1. Let A be ? Construct(C, « 𝔽(len) »). // Step 3.k.v. Else, // Step 3.k.v.1. Let A be ? ArrayCreate(len). - var A = IsConstructor(C) ? (ReportUsageCounter(C, SUBCLASS_ARRAY_TYPE_II), constructContentFunction(C, C, len)) : std_Array(len); + var A = IsConstructor(C) ? constructContentFunction(C, C, len) : std_Array(len); // Step 3.k.vi. Let k be 0. var k = 0; @@ -815,7 +813,7 @@ function ArrayFrom(items, mapfn = undefined, thisArg = undefined) { } // Steps 5.a-b. - var A = IsConstructor(C) ? (ReportUsageCounter(C, SUBCLASS_ARRAY_TYPE_II), constructContentFunction(C, C)) : []; + var A = IsConstructor(C) ? constructContentFunction(C, C) : []; // Step 5.d. var k = 0; @@ -858,7 +856,7 @@ function ArrayFrom(items, mapfn = undefined, thisArg = undefined) { // Steps 12-14. var A = IsConstructor(C) - ? (ReportUsageCounter(C, SUBCLASS_ARRAY_TYPE_II), constructContentFunction(C, C, len)) + ? constructContentFunction(C, C, len) : std_Array(len); // Steps 15-16. @@ -996,7 +994,8 @@ function ArraySpeciesCreate(originalArray, length) { } // Step 5.a. - var C = originalArray.constructor; + var originalConstructor = originalArray.constructor; + var C = originalConstructor; // Step 5.b. if (IsConstructor(C) && IsCrossRealmArrayConstructor(C)) { @@ -1031,7 +1030,6 @@ function ArraySpeciesCreate(originalArray, length) { } // Step 8. - ReportUsageCounter(C, SUBCLASS_ARRAY_TYPE_III); return constructContentFunction(C, C, length); } @@ -1053,7 +1051,7 @@ function ArrayFlatMap(mapperFunction /*, thisArg*/) { var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Step 5. - var A = ArraySpeciesCreate(O, 0); + var A = CanOptimizeArraySpecies(O) ? [] : ArraySpeciesCreate(O, 0); // Step 6. FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T); @@ -1080,7 +1078,7 @@ function ArrayFlat(/* depth */) { } // Step 5. - var A = ArraySpeciesCreate(O, 0); + var A = CanOptimizeArraySpecies(O) ? [] : ArraySpeciesCreate(O, 0); // Step 6. FlattenIntoArray(A, O, sourceLen, 0, depthNum); diff --git a/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStack.js b/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStack.js new file mode 100644 index 00000000000..c23c4c41d59 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStack.js @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Explicit Resource Management +// 27.4.3.3 AsyncDisposableStack.prototype.disposeAsync ( ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.disposeAsync +async function $AsyncDisposableStackDisposeAsync() { + // Step 1. Let asyncDisposableStack be the this value. + var asyncDisposableStack = this; + + if (!IsObject(asyncDisposableStack) || (asyncDisposableStack = GuardToAsyncDisposableStackHelper(asyncDisposableStack)) === null) { + return callFunction( + CallAsyncDisposableStackMethodIfWrapped, + this, + "$AsyncDisposableStackDisposeAsync" + ); + } + + // Step 2. Let promiseCapability be ! NewPromiseCapability(%Promise%). + // (implicit) + // Step 3. If asyncDisposableStack does not have an [[AsyncDisposableState]] internal slot, then + var state = UnsafeGetReservedSlot(asyncDisposableStack, DISPOSABLE_STACK_STATE_SLOT); + if (state === undefined) { + // Step 3.a. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »). + // Step 3.b. Return promiseCapability.[[Promise]]. + // (implicit) + ThrowTypeError(JSMSG_INCOMPATIBLE_METHOD, 'disposeAsync', 'method', 'AsyncDisposableStack'); + } + + // Step 4. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, then + if (state === DISPOSABLE_STACK_STATE_DISPOSED) { + // Step 4.a. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »). + // Step 4.b. Return promiseCapability.[[Promise]]. + return undefined; + } + + // Step 5. Set asyncDisposableStack.[[AsyncDisposableState]] to disposed. + UnsafeSetReservedSlot(asyncDisposableStack, DISPOSABLE_STACK_STATE_SLOT, DISPOSABLE_STACK_STATE_DISPOSED); + + // Step 6. Let result be Completion(DisposeResources(asyncDisposableStack.[[DisposeCapability]], NormalCompletion(undefined))). + // Step 7. IfAbruptRejectPromise(result, promiseCapability). + var disposeCapability = UnsafeGetReservedSlot(asyncDisposableStack, DISPOSABLE_STACK_DISPOSABLE_RESOURCE_STACK_SLOT); + UnsafeSetReservedSlot(asyncDisposableStack, DISPOSABLE_STACK_DISPOSABLE_RESOURCE_STACK_SLOT, undefined); + if (disposeCapability === undefined) { + return undefined; + } + DisposeResourcesAsync(disposeCapability, disposeCapability.length); + + // Step 8. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result »). + // Step 9. Return promiseCapability.[[Promise]]. + return undefined; +} +SetCanonicalName($AsyncDisposableStackDisposeAsync, "disposeAsync"); diff --git a/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.cpp new file mode 100644 index 00000000000..697aeebf13e --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.cpp @@ -0,0 +1,391 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "builtin/AsyncDisposableStackObject.h" + +#include "vm/UsingHint.h" + +#include "vm/JSObject-inl.h" +#include "vm/NativeObject-inl.h" + +using namespace js; + +/* static */ AsyncDisposableStackObject* AsyncDisposableStackObject::create( + JSContext* cx, JS::Handle proto, + JS::Handle + initialDisposeCapability /* = JS::UndefinedHandleValue */) { + AsyncDisposableStackObject* obj = + NewObjectWithClassProto(cx, proto); + if (!obj) { + return nullptr; + } + + MOZ_ASSERT(initialDisposeCapability.isUndefined() || + initialDisposeCapability.isObject()); + MOZ_ASSERT_IF(initialDisposeCapability.isObject(), + initialDisposeCapability.toObject().is()); + + obj->initReservedSlot( + AsyncDisposableStackObject::DISPOSABLE_RESOURCE_STACK_SLOT, + initialDisposeCapability); + obj->initReservedSlot( + AsyncDisposableStackObject::STATE_SLOT, + JS::Int32Value( + int32_t(AsyncDisposableStackObject::DisposableState::Pending))); + + return obj; +} + +/** + * Explicit Resource Management Proposal + * + * 27.4.1.1 AsyncDisposableStack ( ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack + */ +/* static */ bool AsyncDisposableStackObject::construct(JSContext* cx, + unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. If NewTarget is undefined, throw a TypeError exception. + if (!ThrowIfNotConstructing(cx, args, "AsyncDisposableStack")) { + return false; + } + + // Step 2. Let asyncDisposableStack be ? + // OrdinaryCreateFromConstructor(NewTarget, + // "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], + // [[DisposeCapability]] »). + // Step 3. Set asyncDisposableStack.[[AsyncDisposableState]] to pending. + // Step 4. Set asyncDisposableStack.[[DisposeCapability]] to + // NewDisposeCapability(). + JS::Rooted proto(cx); + if (!GetPrototypeFromBuiltinConstructor( + cx, args, JSProto_AsyncDisposableStack, &proto)) { + return false; + } + + AsyncDisposableStackObject* obj = + AsyncDisposableStackObject::create(cx, proto); + if (!obj) { + return false; + } + + // Step 5. Return asyncDisposableStack. + args.rval().setObject(*obj); + return true; +} + +/* static */ bool AsyncDisposableStackObject::is(JS::Handle val) { + return val.isObject() && val.toObject().is(); +} + +/** + * Explicit Resource Management Proposal + * + * 27.4.3.6 AsyncDisposableStack.prototype.use ( value ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.use + */ +/* static */ bool AsyncDisposableStackObject::use_impl( + JSContext* cx, const JS::CallArgs& args) { + // Step 1. Let asyncDisposableStack be the this value. + JS::Rooted asyncDisposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(asyncDisposableStack, + // [[AsyncDisposableState]]). + // (done by caller) + // Step 3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw + // a ReferenceError exception. + if (asyncDisposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. Perform ? + // AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], value, + // async-dispose). + JS::Rooted disposeCapability( + cx, GetOrCreateDisposeCapability(cx, asyncDisposableStack)); + if (!disposeCapability) { + return false; + } + + JS::Rooted val(cx, args.get(0)); + if (!AddDisposableResource(cx, disposeCapability, val, UsingHint::Async)) { + return false; + } + + // Step 5. Return value. + args.rval().set(val); + return true; +} + +/* static */ bool AsyncDisposableStackObject::use(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * + * 27.4.3.4 get AsyncDisposableStack.prototype.disposed + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-get-asyncdisposablestack.prototype.disposed + */ +/* static */ bool AsyncDisposableStackObject::disposed_impl( + JSContext* cx, const JS::CallArgs& args) { + // Step 1. Let disposableStack be the this value. + JS::Rooted disposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(disposableStack, + // [[DisposableState]]). + // (done by caller) + // Step 3. If disposableStack.[[DisposableState]] is disposed, return true. + // Step 4. Otherwise, return false. + args.rval().setBoolean(disposableStack->state() == DisposableState::Disposed); + return true; +} + +/* static */ bool AsyncDisposableStackObject::disposed(JSContext* cx, + unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * + * 27.4.3.5 AsyncDisposableStack.prototype.move ( ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.move + */ +/* static */ bool AsyncDisposableStackObject::move_impl( + JSContext* cx, const JS::CallArgs& args) { + // Step 1. Let asyncDisposableStack be the this value. + JS::Rooted asyncDisposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(asyncDisposableStack, + // [[AsyncDisposableState]]). + // (done by caller) + // Step 3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw + // a ReferenceError exception. + if (asyncDisposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. Let newAsyncDisposableStack be ? + // OrdinaryCreateFromConstructor(%AsyncDisposableStack%, + // "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], + // [[DisposeCapability]] »). + // Step 5. Set newAsyncDisposableStack.[[AsyncDisposableState]] to pending. + // Step 6. Set newAsyncDisposableStack.[[DisposeCapability]] to + // asyncDisposableStack.[[DisposeCapability]]. + JS::Rooted existingDisposeCapability( + cx, asyncDisposableStack->getReservedSlot( + AsyncDisposableStackObject::DISPOSABLE_RESOURCE_STACK_SLOT)); + AsyncDisposableStackObject* newAsyncDisposableStack = + AsyncDisposableStackObject::create(cx, nullptr, + existingDisposeCapability); + if (!newAsyncDisposableStack) { + return false; + } + + // Step 7. Set asyncDisposableStack.[[DisposeCapability]] to + // NewDisposeCapability(). + asyncDisposableStack->clearDisposableResourceStack(); + + // Step 8. Set asyncDisposableStack.[[AsyncDisposableState]] to disposed. + asyncDisposableStack->setState(DisposableState::Disposed); + + // Step 9. Return newAsyncDisposableStack. + args.rval().setObject(*newAsyncDisposableStack); + return true; +} + +/* static */ bool AsyncDisposableStackObject::move(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * + * 27.4.3.2 AsyncDisposableStack.prototype.defer ( onDisposeAsync ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.defer + */ +/* static */ bool AsyncDisposableStackObject::defer_impl( + JSContext* cx, const JS::CallArgs& args) { + // Step 1. Let asyncDisposableStack be the this value. + JS::Rooted asyncDisposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(asyncDisposableStack, + // [[AsyncDisposableState]]). + // (done by caller) + // Step 3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, + // throw a ReferenceError exception. + if (asyncDisposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. If IsCallable(onDisposeAsync) is false, throw a TypeError + // exception. + JS::Handle onDisposeAsync = args.get(0); + if (!ThrowIfOnDisposeNotCallable(cx, onDisposeAsync)) { + return false; + } + + // Step 5. Perform ? + // AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], + // undefined, async-dispose, onDisposeAsync). + JS::Rooted disposeCapability( + cx, GetOrCreateDisposeCapability(cx, asyncDisposableStack)); + if (!disposeCapability) { + return false; + } + + if (!AddDisposableResource(cx, disposeCapability, JS::UndefinedHandleValue, + UsingHint::Async, onDisposeAsync)) { + return false; + } + + // Step 6. Return undefined. + args.rval().setUndefined(); + return true; +} + +/* static */ bool AsyncDisposableStackObject::defer(JSContext* cx, + unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * + * 27.4.3.1 AsyncDisposableStack.prototype.adopt ( value, onDisposeAsync ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.adopt + */ +/* static */ bool AsyncDisposableStackObject::adopt_impl( + JSContext* cx, const JS::CallArgs& args) { + // Step 1. Let asyncDisposableStack be the this value. + JS::Rooted asyncDisposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(asyncDisposableStack, + // [[AsyncDisposableState]]). + // (done by caller) + // Step 3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw + // a ReferenceError exception. + if (asyncDisposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. If IsCallable(onDisposeAsync) is false, throw a TypeError + // exception. + JS::Handle onDisposeAsync = args.get(1); + if (!ThrowIfOnDisposeNotCallable(cx, onDisposeAsync)) { + return false; + } + + // Step 5. Let closure be a new Abstract Closure with no parameters that + // captures value and onDisposeAsync and performs the following steps when + // called: + // Step 5.a. (see AdoptClosure) + // Step 6. Let F be CreateBuiltinFunction(closure, 0, "", « »). + JS::Handle funName = cx->names().empty_; + JS::Rooted F( + cx, NewNativeFunction(cx, AdoptClosure, 0, funName, + gc::AllocKind::FUNCTION_EXTENDED, GenericObject)); + if (!F) { + return false; + } + JS::Handle value = args.get(0); + F->initExtendedSlot(AdoptClosureSlot_ValueSlot, value); + F->initExtendedSlot(AdoptClosureSlot_OnDisposeSlot, onDisposeAsync); + + // Step 7. Perform ? + // AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], + // undefined, async-dispose, F). + JS::Rooted disposeCapability( + cx, GetOrCreateDisposeCapability(cx, asyncDisposableStack)); + if (!disposeCapability) { + return false; + } + + JS::Rooted FVal(cx, ObjectValue(*F)); + if (!AddDisposableResource(cx, disposeCapability, JS::UndefinedHandleValue, + UsingHint::Async, FVal)) { + return false; + } + + // Step 8. Return value. + args.rval().set(value); + return true; +} + +/* static */ bool AsyncDisposableStackObject::adopt(JSContext* cx, + unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +const JSPropertySpec AsyncDisposableStackObject::properties[] = { + JS_STRING_SYM_PS(toStringTag, "AsyncDisposableStack", JSPROP_READONLY), + JS_PSG("disposed", disposed, 0), + JS_PS_END, +}; + +const JSFunctionSpec AsyncDisposableStackObject::methods[] = { + JS_FN("adopt", AsyncDisposableStackObject::adopt, 2, 0), + JS_FN("defer", AsyncDisposableStackObject::defer, 1, 0), + JS_SELF_HOSTED_FN("disposeAsync", "$AsyncDisposableStackDisposeAsync", 0, + 0), + JS_FN("move", AsyncDisposableStackObject::move, 0, 0), + JS_FN("use", AsyncDisposableStackObject::use, 1, 0), + JS_SELF_HOSTED_SYM_FN(asyncDispose, "$AsyncDisposableStackDisposeAsync", 0, + 0), + JS_FS_END, +}; + +const ClassSpec AsyncDisposableStackObject::classSpec_ = { + GenericCreateConstructor, + GenericCreatePrototype, + nullptr, + nullptr, + AsyncDisposableStackObject::methods, + AsyncDisposableStackObject::properties, + nullptr, +}; + +const JSClass AsyncDisposableStackObject::class_ = { + "AsyncDisposableStack", + JSCLASS_HAS_RESERVED_SLOTS(AsyncDisposableStackObject::RESERVED_SLOTS) | + JSCLASS_HAS_CACHED_PROTO(JSProto_AsyncDisposableStack), + JS_NULL_CLASS_OPS, + &AsyncDisposableStackObject::classSpec_, +}; + +const JSClass AsyncDisposableStackObject::protoClass_ = { + "AsyncDisposableStack.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_AsyncDisposableStack), + JS_NULL_CLASS_OPS, + &AsyncDisposableStackObject::classSpec_, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.h b/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.h new file mode 100644 index 00000000000..2f39466c06b --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/AsyncDisposableStackObject.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_AsyncDisposableStackObject_h +#define builtin_AsyncDisposableStackObject_h + +#include "builtin/DisposableStackObjectBase.h" +#include "vm/JSObject.h" + +namespace js { + +class AsyncDisposableStackObject : public DisposableStackObjectBase { + public: + static const JSClass class_; + static const JSClass protoClass_; + + static AsyncDisposableStackObject* create( + JSContext* cx, JS::Handle proto, + JS::Handle initialDisposeCapability = + JS::UndefinedHandleValue); + + private: + static const ClassSpec classSpec_; + static const JSPropertySpec properties[]; + static const JSFunctionSpec methods[]; + + static bool is(JS::Handle val); + + static bool construct(JSContext* cx, unsigned argc, JS::Value* vp); + static bool use_impl(JSContext* cx, const JS::CallArgs& args); + static bool use(JSContext* cx, unsigned argc, JS::Value* vp); + static bool disposed_impl(JSContext* cx, const JS::CallArgs& args); + static bool disposed(JSContext* cx, unsigned argc, JS::Value* vp); + static bool move_impl(JSContext* cx, const JS::CallArgs& args); + static bool move(JSContext* cx, unsigned argc, JS::Value* vp); + static bool defer_impl(JSContext* cx, const JS::CallArgs& args); + static bool defer(JSContext* cx, unsigned argc, JS::Value* vp); + static bool adopt_impl(JSContext* cx, const JS::CallArgs& args); + static bool adopt(JSContext* cx, unsigned argc, JS::Value* vp); +}; + +} /* namespace js */ + +#endif /* builtin_AsyncDisposableStackObject_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.cpp index 232108872c4..7cda0633444 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.cpp @@ -21,6 +21,7 @@ #include "jsnum.h" +#include "builtin/Promise.h" #include "jit/AtomicOperations.h" #include "jit/InlinableNatives.h" #include "js/Class.h" @@ -29,6 +30,8 @@ #include "js/Result.h" #include "js/WaitCallbacks.h" #include "vm/GlobalObject.h" +#include "vm/HelperThreads.h" // AutoLockHelperThreadState +#include "vm/OffThreadPromiseRuntimeState.h" // OffthreadPromiseTask #include "vm/TypedArrayObject.h" #include "vm/Compartment-inl.h" @@ -527,30 +530,190 @@ static bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp) { namespace js { -// Represents one waiting worker. -// -// The type is declared opaque in SharedArrayObject.h. Instances of -// js::FutexWaiter are stack-allocated and linked onto a list across a -// call to FutexThread::wait(). -// -// The 'waiters' field of the SharedArrayRawBuffer points to the highest -// priority waiter in the list, and lower priority nodes are linked through -// the 'lower_pri' field. The 'back' field goes the other direction. -// The list is circular, so the 'lower_pri' field of the lowest priority -// node points to the first node in the list. The list has no dedicated -// header node. +/* + * [SMDOC] Atomics.wait, Atomics.waitAsync, and Atomics.notify + * + * `wait`, `waitAsync`, and `notify` are provided as low-level primitives for + * thread synchronization. The primary use case is to take code that looks like + * this: + * + * const ValueIndex = 0; + * const FlagIndex = 1; + * + * THREAD A: + * // Write a value. + * Atomics.store(sharedBuffer, ValueIndex, value); + * // Update a flag to indicate that the value was written. + * Atomics.store(sharedBuffer, FlagIndex, 1); + * + * THREAD B: + * // Busy-wait for the flag to be updated. + * while (Atomics.load(sharedBuffer, FlagIndex) == 0) {} + * // Load the value. + * let value = Atomics.load(sharedBuffer, ValueIndex); + * + * ...and replace the busy-wait: + * + * THREAD A': + * // Write the value and update the flag. + * Atomics.store(sharedBuffer, ValueIndex, value); + * Atomics.store(sharedBuffer, FlagIndex, 1); + * // Notify that the flag has been written. + * Atomics.notify(sharedBuffer, FlagIndex); + * + * THREAD B': + * // Wait until the flag is notified. + * // If it's already non-zero, no wait occurs. + * Atomics.wait(sharedBuffer, FlagIndex, 0); + * // Load the value. + * let value = Atomics.load(sharedBuffer, ValueIndex); + * + * `wait` puts the calling thread to sleep until it is notified (or an optional + * timeout expires). This can't be used on the main thread. + * + * `waitAsync` instead creates a Promise which will be resolved when the + * position is notified (or an optional timeout expires). + * + * When `wait` or `waitAsync` is called, a waiter is created and registered with + * the SharedArrayBuffer. Waiter instances for a SharedArrayRawBuffer are + * connected in a circular doubly-linked list, containing both sync and async + * waiters. Sync waiters are stack allocated in the stack frame of the waiting + * thread. Async waiters are heap-allocated. The `waiters` field of the + * SharedArrayRawBuffer is a dedicated list head node for the list. Waiters are + * awoken in a first-in-first-out order. The `next` field of the list head node + * points to the highest priority waiter. The `prev` field points to the lowest + * priority waiter. This list is traversed when `notify` is called to find the + * waiters that should be woken up. + * + * Synchronous waits are implemented using a per-context condition variable. See + * FutexThread::wait. + * + * Asynchronous waits are more complicated, particularly with respect to + * timeouts. In addition to the AsyncFutexWaiter that is added to the list of + * waiters, we also create: + * + * 1. A Promise object to return to the caller. The promise will be resolved + * when the waiter is notified or times out. + * 2. A WaitAsyncNotifyTask (derived from OffThreadPromiseTask) wrapping that + * promise. `notify` can be called from any thread, but the promise must be + * resolved on the thread that owns it. To resolve the promise, we dispatch + * the task to enqueue a promise resolution task in the target's event + * loop. The notify task is stored in the AsyncFutexWaiter. + * 3. If there is a non-zero timeout, a WaitAsyncTimeoutTask (derived from + * JS::Dispatchable) containing a pointer to the async waiter. We dispatch + * this task to the embedding's event loop, with a delay. When the timeout + * expires and the task runs, if the promise has not yet been resolved, we + * resolve it with "timed-out". + * + * `waitAsync` Lifetimes + * --------------------- + * ┌─────┐ + * │ SAB │ + * └─────┘ + * ┌────► ◄────┐ bi-directional linked list + * │ │ + * ▼ ▼ + * *waiter *waiter + * ▲ ▲ + * │ │ + * └───► * ◄──┘ + * │ + * ┌───────▼────────┐ + * │AsyncFutexWaiter│ ◄───────────┐ + * └────────────────┘ │ + * │ │ + * │ borrow │ borrow + * ▼ ▼ + * ┌────────────────────┐ ┌───────────────────┐ + * │WaitAsyncTimeoutTask│ │WaitAsyncNotifyTask│ ◄─────┐ + * └────────────────────┘ └───┬───────────────┘ │ + * ▲ │ ▲ │ + * │ │ │ │ (transfered) + * │ own ▼ │ │ own + * ┌───────────────────────────┐ ┌─────────────┐ │ ┌─────────────────────┐ + * │DelayedJSDispatchaleHandler│ │PromiseObject│ │ │JSDispatchableHandler│ + * └───────────────────────────┘ └─────────────┘ │ └─────────────────────┘ + * ▲ ▲ │ + * ┌────────┼────────────────────────┼──────┐ │ + * │ ┌──────┴───────┐ ┌────┴────┐ │ │ own (initialized) + * │ │TimeoutManager│ │JSContext┼─┼──────┘ + * │ └──────────────┘ └─────────┘ │ Cancellable List + * │ │ + * │ Runtime (MainThread or Worker) │ + * └────────────────────────────────────────┘ + * + * + * The data representing an async wait is divided between the JSContext in which + * it was created and the SharedArrayBuffer being waited on. There are three + * potential components: + * + * A) The AsyncFutexWaiter itself (shared by the SharedArrayRawBuffer, + * WaitAsyncNotifyTask, and WaitAsyncTimeoutTask if it exists). It + * will be cleaned up manually. + * B) The corresponding WaitAsyncNotifyTask (owned by the JS::Context). It + * destroys itself on run. + * C) The WaitAsyncTimeoutTask (owned by the embedding's job queue). It + * destroys itself on run. + * + * WaitAsyncNotifyTask and WaitAsyncTimeoutTask (if it exists) delete + * themselves. When either task is run or destroyed, they also trigger the + * destruction and unlinking of the AsyncFutexWaiter. There are + * four scenarios: + * + * 1. A call to `Atomics.notify` notifies the waiter (atomics_notify_impl) + * from another thread. + * A) The async waiter is removed from the list. + * B) The notify task is removed from OffThreadPromiseRuntimeState's + * cancelable list and is dispatched to resolve the promise with "ok". + * The task then destroys itself. + * C) The WaitAsyncTimeoutTask is disabled. It will fire and do nothing. + * See AsyncFutexWaiter::maybeCancelTimeout in atomics_notify_impl. + * D) The async waiter is destroyed. + * + * 2. A call to `Atomics.notify` notifies the waiter (atomics_notify_impl) + * from the same thread. + * A) The async waiter is removed from the list. + * B) The notify task is cancelled. The promise is extracted and resolved + * directly. + * C) The WaitAsyncTimeoutTask is disabled. It will fire and do nothing. + * See AsyncFutexWaiter::maybeCancelTimeout in atomics_notify_impl. + * D) The async waiter is destroyed. + * + * 3. The timeout expires without notification (WaitAsyncTimeoutTask::run) + * A) The async waiter is removed from the list. + * B) The notify task is dispatched to resolve the promise with "timed-out" + * and destroys itself.. + * C) The timeout task is running and will be destroyed when it's done. + * D) The async waiter is destroyed. + * + * 4. The context is destroyed (OffThreadPromiseRuntimeState::shutdown): + * A) The async waiter is removed and destroyed by + * WaitAsyncNotifyTask::prepareForCancel. + * B) The notify task is cancelled and destroyed by + * OffThreadPromiseRuntimeState::shutdown. + * C) The WaitAsyncTimeoutTask is disabled. + * See AsyncFutexWaiter::maybeCancelTimeout in prepareForCancel. + * + * 5. The SharedArrayBuffer is collected by the GC (~FutexWaiterListHead) + * A) Async waiters without timeouts can no longer resolve. They are removed. + * B) If no timeout task exists, the notify task is dispatched and + * destroys itself, without resolving the promise. + * C) If there is an enqueued timeout, the waiter can still be resolved. + * In this case it will not be destroyed until it times out. + * + * The UniquePtr can be thought of as a "runnable handle" that gives exclusive + * access to executing a runnable by a given owner. The runnable will still + * delete itself (via js_delete, see OffThreadPromiseRuntimeState.cpp + * implementation of OffThreadPromiseTask::run). If somehow the UniquePtr is not + * passed to embedding code that will run the code, the task is released from + * the pointer. We then use the list of raw pointers in + * OffThreadPromiseRuntimeState's cancellable and dead lists are used to + * identify which were never dispatched, and which failed to dispatch, and clear + * them when the engine has an opportunity to do so (i.e. shutdown). + */ -class FutexWaiter { - public: - FutexWaiter(size_t offset, JSContext* cx) - : offset(offset), cx(cx), lower_pri(nullptr), back(nullptr) {} - - size_t offset; // int32 element index within the SharedArrayBuffer - JSContext* cx; // The waiting thread - FutexWaiter* lower_pri; // Lower priority nodes in circular doubly-linked - // list of waiters - FutexWaiter* back; // Other direction -}; +class WaitAsyncNotifyTask; +class WaitAsyncTimeoutTask; class AutoLockFutexAPI { // We have to wrap this in a Maybe because of the way loading @@ -568,10 +731,438 @@ class AutoLockFutexAPI { js::UniqueLock& unique() { return *unique_; } }; +// Represents one waiter. This is the abstract base class for SyncFutexWaiter +// and AsyncFutexWaiter. +class FutexWaiter : public FutexWaiterListNode { + protected: + FutexWaiter(JSContext* cx, size_t offset, FutexWaiterKind kind) + : FutexWaiterListNode(kind), offset_(offset), cx_(cx) {} + + size_t offset_; // Element index within the SharedArrayBuffer + JSContext* cx_; // The thread that called `wait` or `waitAsync`. + + public: + bool isSync() const { return kind_ == FutexWaiterKind::Sync; } + SyncFutexWaiter* asSync() { + MOZ_ASSERT(isSync()); + return reinterpret_cast(this); + } + + bool isAsync() const { return kind_ == FutexWaiterKind::Async; } + AsyncFutexWaiter* asAsync() { + MOZ_ASSERT(isAsync()); + return reinterpret_cast(this); + } + size_t offset() const { return offset_; } + JSContext* cx() { return cx_; } +}; + +// Represents a worker blocked while calling |Atomics.wait|. +// Instances of js::SyncFutexWaiter are stack-allocated and linked +// onto the waiter list across a call to FutexThread::wait(). +// When this waiter is notified, the worker will resume execution. +class MOZ_STACK_CLASS SyncFutexWaiter : public FutexWaiter { + public: + SyncFutexWaiter(JSContext* cx, size_t offset) + : FutexWaiter(cx, offset, FutexWaiterKind::Sync) {} +}; + +// Represents a waiter asynchronously waiting after calling |Atomics.waitAsync|. +// Instances of js::AsyncFutexWaiter are heap-allocated. +// When this waiter is notified, the promise it holds will be resolved. +class AsyncFutexWaiter : public FutexWaiter { + public: + AsyncFutexWaiter(JSContext* cx, size_t offset) + : FutexWaiter(cx, offset, FutexWaiterKind::Async) {} + + WaitAsyncNotifyTask* notifyTask() { return notifyTask_; } + + void setNotifyTask(WaitAsyncNotifyTask* task) { + MOZ_ASSERT(!notifyTask_); + notifyTask_ = task; + } + + void setTimeoutTask(WaitAsyncTimeoutTask* task) { + MOZ_ASSERT(!timeoutTask_); + timeoutTask_ = task; + } + + bool hasTimeout() const { return !!timeoutTask_; } + WaitAsyncTimeoutTask* timeoutTask() const { return timeoutTask_; } + + void maybeClearTimeout(AutoLockFutexAPI& lock); + + private: + // Both of these pointers are borrowed pointers. The notifyTask is owned by + // the runtime's cancellable list, while the timeout task (if it exists) is + // owned by the embedding's timeout manager. + WaitAsyncNotifyTask* notifyTask_ = nullptr; + WaitAsyncTimeoutTask* timeoutTask_ = nullptr; +}; + +// When an async waiter from a different context is notified, this +// task is queued to resolve the promise on the thread to which it +// belongs. +// +// WaitAsyncNotifyTask (derived from OffThreadPromiseTask) is wrapping that +// promise. `Atomics.notify` can be called from any thread, but the promise must +// be resolved on the thread that owns it. To resolve the promise, we dispatch +// the task to enqueue a promise resolution task in the target's event +// loop. +// +// See [SMDOC] Atomics.wait for more details. +class WaitAsyncNotifyTask : public OffThreadPromiseTask { + public: + enum class Result { Ok, TimedOut, Dead }; + + private: + Result result_ = Result::Ok; + + // A back-edge to the waiter so that it can be cleaned up when the + // Notify Task is dispatched and destroyed. + AsyncFutexWaiter* waiter_ = nullptr; + + public: + WaitAsyncNotifyTask(JSContext* cx, Handle promise) + : OffThreadPromiseTask(cx, promise) {} + + void setWaiter(AsyncFutexWaiter* waiter) { + MOZ_ASSERT(!waiter_); + waiter_ = waiter; + } + + void setResult(Result result, AutoLockFutexAPI& lock) { result_ = result; } + + bool resolve(JSContext* cx, Handle promise) override { + RootedValue resultMsg(cx); + switch (result_) { + case Result::Ok: + resultMsg = StringValue(cx->names().ok); + break; + case Result::TimedOut: + resultMsg = StringValue(cx->names().timed_out_); + break; + case Result::Dead: + // The underlying SharedArrayBuffer is no longer reachable, and no + // timeout is associated with this waiter. The promise will never + // resolve. There's nothing to do here. + return true; + } + return PromiseObject::resolve(cx, promise, resultMsg); + } + + void prepareForCancel() override; +}; + +// WaitAsyncNotifyTask (derived from OffThreadPromiseTask) is wrapping that +// promise. `notify` can be called from any thread, but the promise must be +// resolved on the thread that owns it. To resolve the promise, we dispatch +// the task to enqueue a promise resolution task in the target's event +// loop. +// +// See [SMDOC] Atomics.wait for more details. +class WaitAsyncTimeoutTask : public JS::Dispatchable { + AsyncFutexWaiter* waiter_; + + public: + explicit WaitAsyncTimeoutTask(AsyncFutexWaiter* waiter) : waiter_(waiter) { + MOZ_ASSERT(waiter_); + } + + void clear(AutoLockFutexAPI&) { waiter_ = nullptr; } + bool cleared(AutoLockFutexAPI&) { return !waiter_; } + + void run(JSContext*, MaybeShuttingDown maybeshuttingdown) final; + void transferToRuntime() final; +}; + } // namespace js -// ES2021 draft rev bd868f20b8c574ad6689fba014b62a1dba819e56 -// 24.4.11 Atomics.wait ( typedArray, index, value, timeout ), steps 8-9, 14-25. +// https://tc39.es/ecma262/#sec-addwaiter +static void AddWaiter(SharedArrayRawBuffer* sarb, FutexWaiter* node, + AutoLockFutexAPI&) { + FutexWaiterListNode* listHead = sarb->waiters(); + + // Step 3: Append waiterRecord to WL.[[Waiters]]. + node->setNext(listHead); + node->setPrev(listHead->prev()); + listHead->prev()->setNext(node); + listHead->setPrev(node); +} + +// https://tc39.es/ecma262/#sec-removewaiter +static void RemoveWaiterImpl(FutexWaiterListNode* node, AutoLockFutexAPI&) { + if (!node->prev()) { + MOZ_ASSERT(!node->next()); + return; + } + + node->prev()->setNext(node->next()); + node->next()->setPrev(node->prev()); + + node->setNext(nullptr); + node->setPrev(nullptr); +} + +// Sync waiters are stack allocated and can simply be removed from the list. +static void RemoveSyncWaiter(SyncFutexWaiter* waiter, AutoLockFutexAPI& lock) { + RemoveWaiterImpl(waiter, lock); +} + +// Async waiters are heap allocated. After removing the waiter, the caller +// is responsible for freeing it. Return the waiter to help enforce this. +[[nodiscard]] AsyncFutexWaiter* RemoveAsyncWaiter(AsyncFutexWaiter* waiter, + AutoLockFutexAPI& lock) { + RemoveWaiterImpl(waiter, lock); + return waiter; +} + +FutexWaiterListHead::~FutexWaiterListHead() { + // Cleanup steps from 5. in SMDOC for Atomics.waitAsync + // When a SharedArrayRawBuffer is no longer reachable, the contents of its + // waiters list can no longer be notified. However, they can still resolve if + // they have an associated timeout. When the list head goes away, we walk + // through the remaining waiters and clean up the ones that don't have + // timeouts. We leave the remaining waiters in a free-floating linked list; + // they will remove themselves as the timeouts fire or the associated runtime + // shuts down. + AutoLockHelperThreadState helperLock; + AutoLockFutexAPI lock; + + FutexWaiterListNode* iter = next(); + while (iter != this) { + // All remaining FutexWaiters must be async. A sync waiter can only exist if + // a thread is waiting, and that thread must have a reference to the shared + // array buffer it's waiting on, so that buffer can't be freed. + + AsyncFutexWaiter* removedWaiter = + RemoveAsyncWaiter(iter->toWaiter()->asAsync(), lock); + iter = iter->next(); + + if (removedWaiter->hasTimeout()) { + // If a timeout task exists, assert that the timeout task can still access + // it. This will allow it to clean it up when it runs. See the comment in + // WaitAsyncTimeoutTask::run() or the the SMDOC in this file. + MOZ_ASSERT(removedWaiter->timeoutTask()->cleared(lock)); + continue; + } + // In the case that a timeout task does not exist, the two live raw + // pointers at this point are WaitAsyncNotifyTask and the + // AsyncFutexWaiter. We can clean them up here as there is no way to + // notify them without the SAB or without waiting for the shutdown of the + // JS::Context. In order to do this, we store the removed waiter in a + // unique ptr, so that it is cleared after this function, and dispatch and + // destroy the notify task. + UniquePtr ownedWaiter(removedWaiter); + WaitAsyncNotifyTask* task = ownedWaiter->notifyTask(); + task->setResult(WaitAsyncNotifyTask::Result::Dead, lock); + task->removeFromCancellableListAndDispatch(helperLock); + } + + RemoveWaiterImpl(this, lock); +} + +// Creates an object to use as the return value of Atomics.waitAsync. +static PlainObject* CreateAsyncResultObject(JSContext* cx, bool async, + HandleValue promiseOrString) { + Rooted resultObject(cx, NewPlainObject(cx)); + if (!resultObject) { + return nullptr; + } + + RootedValue isAsync(cx, BooleanValue(async)); + if (!NativeDefineDataProperty(cx, resultObject, cx->names().async, isAsync, + JSPROP_ENUMERATE)) { + return nullptr; + } + + MOZ_ASSERT_IF(!async, promiseOrString.isString()); + MOZ_ASSERT_IF(async, promiseOrString.isObject() && + promiseOrString.toObject().is()); + if (!NativeDefineDataProperty(cx, resultObject, cx->names().value, + promiseOrString, JSPROP_ENUMERATE)) { + return nullptr; + } + + return resultObject; +} + +void WaitAsyncNotifyTask::prepareForCancel() { + AutoLockFutexAPI lock; + UniquePtr waiter(RemoveAsyncWaiter(waiter_, lock)); + waiter->maybeClearTimeout(lock); +} + +void WaitAsyncTimeoutTask::run(JSContext* cx, + MaybeShuttingDown maybeShuttingDown) { + AutoLockHelperThreadState helperLock; + AutoLockFutexAPI lock; + + // If the waiter was notified while this task was enqueued, do nothing. + if (cleared(lock)) { + js_delete(this); + return; + } + + // Cleanup steps from 3. and 5. lifecycle in SMDOC for Atomics.waitAsync + // Take ownership of the async waiter, so that it will be freed + // when we return. + UniquePtr asyncWaiter(RemoveAsyncWaiter(waiter_, lock)); + + // Dispatch a task to resolve the promise with value "timed-out". + WaitAsyncNotifyTask* task = asyncWaiter->notifyTask(); + task->setResult(WaitAsyncNotifyTask::Result::TimedOut, lock); + task->removeFromCancellableListAndDispatch(helperLock); + js_delete(this); +} + +void WaitAsyncTimeoutTask::transferToRuntime() { + // Clear and delete. Clearing this task will result in the cancellable + // notify task being cleaned up on shutdown, as it can no longer be triggered. + // In as sense, the task "transfered" for cleanup is the notify task. + { + AutoLockFutexAPI lock; + clear(lock); + } + // As we are not managing any state, the runtime is not tracking this task, + // and we have nothing to run, we can delete. + js_delete(this); +} + +void AsyncFutexWaiter::maybeClearTimeout(AutoLockFutexAPI& lock) { + if (timeoutTask_) { + timeoutTask_->clear(lock); + } +} + +// DoWait Steps 17-31 +// https://tc39.es/ecma262/#sec-dowait +template +static FutexThread::WaitResult AtomicsWaitAsyncCriticalSection( + JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, T value, + const mozilla::Maybe& timeout, + Handle promise) { + // Step 17: Enter critical section. + // We need to initialize an OffThreadPromiseTask inside this critical section. + // To avoid deadlock, we claim the helper thread lock first. + AutoLockHelperThreadState helperThreadLock; + AutoLockFutexAPI futexLock; + + // Steps 18-20: + SharedMem addr = + sarb->dataPointerShared().cast() + (byteOffset / sizeof(T)); + if (jit::AtomicOperations::loadSafeWhenRacy(addr) != value) { + return FutexThread::WaitResult::NotEqual; + } + + // Step 21 + bool hasTimeout = timeout.isSome(); + if (hasTimeout && timeout.value().IsZero()) { + return FutexThread::WaitResult::TimedOut; + } + + // Steps 22-30 + // To handle potential failures, we split this up into two phases: + // First, we allocate everything: the notify task, the waiter, and + // (if necessary) the timeout task. The allocations are managed + // using unique pointers, which will free them on failure. This + // phase has no external side-effects. + + // Second, we transfer ownership of the allocations to the right places: + // the waiter owns the notify task, the shared array buffer owns the waiter, + // and the event loop owns the timeout task. This phase is infallible. + auto notifyTask = js::MakeUnique(cx, promise); + if (!notifyTask) { + JS_ReportOutOfMemory(cx); + return FutexThread::WaitResult::Error; + } + auto waiter = js::MakeUnique(cx, byteOffset); + if (!waiter) { + JS_ReportOutOfMemory(cx); + return FutexThread::WaitResult::Error; + } + + notifyTask->setWaiter(waiter.get()); + waiter->setNotifyTask(notifyTask.get()); + + UniquePtr timeoutTask; + if (hasTimeout) { + timeoutTask = js::MakeUnique(waiter.get()); + if (!timeoutTask) { + JS_ReportOutOfMemory(cx); + return FutexThread::WaitResult::Error; + } + waiter->setTimeoutTask(timeoutTask.get()); + } + + // This is the last fallible operation. If it fails, all allocations + // will be freed. init has no side-effects if it fails. + if (!js::OffThreadPromiseTask::InitCancellable(cx, helperThreadLock, + std::move(notifyTask))) { + return FutexThread::WaitResult::Error; + } + + // Below this point, everything is infallible. + AddWaiter(sarb, waiter.release(), futexLock); + + if (hasTimeout) { + MOZ_ASSERT(!!timeoutTask); + OffThreadPromiseRuntimeState& state = + cx->runtime()->offThreadPromiseState.ref(); + // We are not tracking the dispatch of the timeout task using the + // OffThreadPromiseRuntimeState, so we ignore the return value. If this + // fails, the embeddings should call transferToRuntime on timeoutTask + // which will clear itself, and set the notify task to be cleaned on + // shutdown. + (void)state.delayedDispatchToEventLoop(std::move(timeoutTask), + timeout.value().ToMilliseconds()); + } + + // Step 31: Leave critical section. + return FutexThread::WaitResult::OK; +} + +// DoWait steps 12-35 +// https://tc39.es/ecma262/#sec-dowait +// This implements the mode=ASYNC case. +template +static PlainObject* AtomicsWaitAsync( + JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, T value, + const mozilla::Maybe& timeout) { + // Step 16a. + Rooted promiseObject( + cx, CreatePromiseObjectWithoutResolutionFunctions(cx)); + if (!promiseObject) { + return nullptr; + } + + // Steps 17-31 + switch (AtomicsWaitAsyncCriticalSection(cx, sarb, byteOffset, value, timeout, + promiseObject)) { + case FutexThread::WaitResult::NotEqual: { + // Steps 16b, 20c-e + RootedValue msg(cx, StringValue(cx->names().not_equal_)); + return CreateAsyncResultObject(cx, false, msg); + } + case FutexThread::WaitResult::TimedOut: { + // Steps 16b, 21c-e + RootedValue msg(cx, StringValue(cx->names().timed_out_)); + return CreateAsyncResultObject(cx, false, msg); + } + case FutexThread::WaitResult::Error: + return nullptr; + case FutexThread::WaitResult::OK: + break; + } + + // Steps 15b, 33-35 + RootedValue objectValue(cx, ObjectValue(*promiseObject)); + return CreateAsyncResultObject(cx, true, objectValue); +} + +// DoWait steps 12-32 +// https://tc39.es/ecma262/#sec-dowait +// This implements the mode=SYNC case. template static FutexThread::WaitResult AtomicsWait( JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, T value, @@ -579,51 +1170,28 @@ static FutexThread::WaitResult AtomicsWait( // Validation and other guards should ensure that this does not happen. MOZ_ASSERT(sarb, "wait is only applicable to shared memory"); - // Steps 8-9. - if (!cx->fx.canWait()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_ATOMICS_WAIT_NOT_ALLOWED); - return FutexThread::WaitResult::Error; - } - SharedMem addr = sarb->dataPointerShared().cast() + (byteOffset / sizeof(T)); - // Steps 15 (reordered), 17.a and 23 (through destructor). + // Steps 17 and 31 (through destructor). // This lock also protects the "waiters" field on SharedArrayRawBuffer, // and it provides the necessary memory fence. AutoLockFutexAPI lock; - // Steps 16-17. + // Steps 18-20. if (jit::AtomicOperations::loadSafeWhenRacy(addr) != value) { return FutexThread::WaitResult::NotEqual; } - // Steps 14, 18-22. - FutexWaiter w(byteOffset, cx); - if (FutexWaiter* waiters = sarb->waiters()) { - w.lower_pri = waiters; - w.back = waiters->back; - waiters->back->lower_pri = &w; - waiters->back = &w; - } else { - w.lower_pri = w.back = &w; - sarb->setWaiters(&w); - } + // Steps 14, 22-27 + SyncFutexWaiter w(cx, byteOffset); + // Steps 28-29 + AddWaiter(sarb, &w, lock); FutexThread::WaitResult retval = cx->fx.wait(cx, lock.unique(), timeout); + RemoveSyncWaiter(&w, lock); - if (w.lower_pri == &w) { - sarb->setWaiters(nullptr); - } else { - w.lower_pri->back = w.back; - w.back->lower_pri = w.lower_pri; - if (sarb->waiters() == &w) { - sarb->setWaiters(w.lower_pri); - } - } - - // Steps 24-25. + // Step 32 return retval; } @@ -639,22 +1207,34 @@ FutexThread::WaitResult js::atomics_wait_impl( return AtomicsWait(cx, sarb, byteOffset, value, timeout); } -// ES2021 draft rev bd868f20b8c574ad6689fba014b62a1dba819e56 -// 24.4.11 Atomics.wait ( typedArray, index, value, timeout ), steps 6-25. +PlainObject* js::atomics_wait_async_impl( + JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int32_t value, + const mozilla::Maybe& timeout) { + return AtomicsWaitAsync(cx, sarb, byteOffset, value, timeout); +} + +PlainObject* js::atomics_wait_async_impl( + JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int64_t value, + const mozilla::Maybe& timeout) { + return AtomicsWaitAsync(cx, sarb, byteOffset, value, timeout); +} + +// https://tc39.es/ecma262/#sec-dowait +// DoWait ( mode, typedArray, index, value, timeout ), steps 8-35. template -static bool DoAtomicsWait(JSContext* cx, +static bool DoAtomicsWait(JSContext* cx, bool isAsync, Handle unwrappedTypedArray, size_t index, T value, HandleValue timeoutv, MutableHandleValue r) { mozilla::Maybe timeout; if (!timeoutv.isUndefined()) { - // Step 6. + // Step 8. double timeout_ms; if (!ToNumber(cx, timeoutv, &timeout_ms)) { return false; } - // Step 7. + // Step 9. if (!std::isnan(timeout_ms)) { if (timeout_ms < 0) { timeout = mozilla::Some(mozilla::TimeDuration::FromSeconds(0.0)); @@ -666,23 +1246,40 @@ static bool DoAtomicsWait(JSContext* cx, } // Step 10. + if (!isAsync && !cx->fx.canWait()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_ATOMICS_WAIT_NOT_ALLOWED); + return false; + } + + // Step 11. Rooted unwrappedSab( cx, unwrappedTypedArray->bufferShared()); - // Step 11. + // Step 12 mozilla::Maybe offset = unwrappedTypedArray->byteOffset(); MOZ_ASSERT( offset, "offset can't become invalid because shared buffers can only grow"); - // Steps 12-13. + // Step 13. // The computation will not overflow because range checks have been // performed. - size_t indexedPosition = index * sizeof(T) + *offset; + size_t byteIndexInBuffer = index * sizeof(T) + *offset; + + // Steps 14-35. + if (isAsync) { + PlainObject* resultObject = atomics_wait_async_impl( + cx, unwrappedSab->rawBufferObject(), byteIndexInBuffer, value, timeout); + if (!resultObject) { + return false; + } + r.setObject(*resultObject); + return true; + } - // Steps 8-9, 14-25. switch (atomics_wait_impl(cx, unwrappedSab->rawBufferObject(), - indexedPosition, value, timeout)) { + byteIndexInBuffer, value, timeout)) { case FutexThread::WaitResult::NotEqual: r.setString(cx->names().not_equal_); return true; @@ -699,8 +1296,58 @@ static bool DoAtomicsWait(JSContext* cx, } } -// ES2021 draft rev bd868f20b8c574ad6689fba014b62a1dba819e56 +// https://tc39.es/ecma262/#sec-dowait +// DoWait ( mode, typedArray, index, value, timeout ) +static bool DoWait(JSContext* cx, bool isAsync, HandleValue objv, + HandleValue index, HandleValue valv, HandleValue timeoutv, + MutableHandleValue r) { + // Steps 1-2. + Rooted unwrappedTypedArray(cx); + if (!ValidateIntegerTypedArray(cx, objv, true, &unwrappedTypedArray)) { + return false; + } + MOZ_ASSERT(unwrappedTypedArray->type() == Scalar::Int32 || + unwrappedTypedArray->type() == Scalar::BigInt64); + + // Step 3 + if (!unwrappedTypedArray->isSharedMemory()) { + return ReportBadArrayType(cx); + } + + // Step 4. + size_t intIndex; + if (!ValidateAtomicAccess(cx, unwrappedTypedArray, index, &intIndex)) { + return false; + } + + // Step 5 + if (unwrappedTypedArray->type() == Scalar::Int32) { + // Step 7. + int32_t value; + if (!ToInt32(cx, valv, &value)) { + return false; + } + + // Steps 8-35. + return DoAtomicsWait(cx, isAsync, unwrappedTypedArray, intIndex, value, + timeoutv, r); + } + + MOZ_ASSERT(unwrappedTypedArray->type() == Scalar::BigInt64); + + // Step 6. + RootedBigInt value(cx, ToBigInt(cx, valv)); + if (!value) { + return false; + } + + // Steps 8-35. + return DoAtomicsWait(cx, isAsync, unwrappedTypedArray, intIndex, + BigInt::toInt64(value), timeoutv, r); +} + // 24.4.11 Atomics.wait ( typedArray, index, value, timeout ) +// https://tc39.es/ecma262/#sec-atomics.wait static bool atomics_wait(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); HandleValue objv = args.get(0); @@ -709,88 +1356,109 @@ static bool atomics_wait(JSContext* cx, unsigned argc, Value* vp) { HandleValue timeoutv = args.get(3); MutableHandleValue r = args.rval(); - // Step 1. - Rooted unwrappedTypedArray(cx); - if (!ValidateIntegerTypedArray(cx, objv, true, &unwrappedTypedArray)) { - return false; - } - MOZ_ASSERT(unwrappedTypedArray->type() == Scalar::Int32 || - unwrappedTypedArray->type() == Scalar::BigInt64); - - // https://github.com/tc39/ecma262/pull/1908 - if (!unwrappedTypedArray->isSharedMemory()) { - return ReportBadArrayType(cx); - } - - // Step 2. - size_t intIndex; - if (!ValidateAtomicAccess(cx, unwrappedTypedArray, index, &intIndex)) { - return false; - } - - if (unwrappedTypedArray->type() == Scalar::Int32) { - // Step 5. - int32_t value; - if (!ToInt32(cx, valv, &value)) { - return false; - } - - // Steps 6-25. - return DoAtomicsWait(cx, unwrappedTypedArray, intIndex, value, timeoutv, r); - } - - MOZ_ASSERT(unwrappedTypedArray->type() == Scalar::BigInt64); - - // Step 4. - RootedBigInt value(cx, ToBigInt(cx, valv)); - if (!value) { - return false; - } - - // Steps 6-25. - return DoAtomicsWait(cx, unwrappedTypedArray, intIndex, - BigInt::toInt64(value), timeoutv, r); + return DoWait(cx, /*isAsync = */ false, objv, index, valv, timeoutv, r); } -// ES2021 draft rev bd868f20b8c574ad6689fba014b62a1dba819e56 -// 24.4.12 Atomics.notify ( typedArray, index, count ), steps 10-16. -int64_t js::atomics_notify_impl(SharedArrayRawBuffer* sarb, size_t byteOffset, - int64_t count) { +// Atomics.waitAsync ( typedArray, index, value, timeout ) +// https://tc39.es/ecma262/#sec-atomics.waitasync +static bool atomics_wait_async(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + HandleValue objv = args.get(0); + HandleValue index = args.get(1); + HandleValue valv = args.get(2); + HandleValue timeoutv = args.get(3); + MutableHandleValue r = args.rval(); + + return DoWait(cx, /*isAsync = */ true, objv, index, valv, timeoutv, r); +} + +// Atomics.notify ( typedArray, index, count ), steps 8-13. +// https://tc39.es/ecma262/#sec-atomics.notify +bool js::atomics_notify_impl(JSContext* cx, SharedArrayRawBuffer* sarb, + size_t byteOffset, int64_t count, int64_t* woken) { + MOZ_ASSERT(woken); + // Validation should ensure this does not happen. MOZ_ASSERT(sarb, "notify is only applicable to shared memory"); - // Steps 12 (reordered), 15 (through destructor). - AutoLockFutexAPI lock; + // Step 8 + *woken = 0; - // Step 11 (reordered). - int64_t woken = 0; - - // Steps 10, 13-14. - FutexWaiter* waiters = sarb->waiters(); - if (waiters && count) { - FutexWaiter* iter = waiters; - do { - FutexWaiter* c = iter; - iter = iter->lower_pri; - if (c->offset != byteOffset || !c->cx->fx.isWaiting()) { + Rooted> promisesToResolve( + cx, GCVector(cx)); + { + // Steps 9, 12 (through destructor). + AutoLockHelperThreadState helperLock; + AutoLockFutexAPI lock; + // Steps 10-11 + FutexWaiterListNode* waiterListHead = sarb->waiters(); + FutexWaiterListNode* iter = waiterListHead->next(); + while (count && iter != waiterListHead) { + FutexWaiter* waiter = iter->toWaiter(); + iter = iter->next(); + if (byteOffset != waiter->offset()) { continue; } - c->cx->fx.notify(FutexThread::NotifyExplicit); + if (waiter->isSync()) { + // For sync waits, the context to notify is currently sleeping. + // We notify that context (unless it's already been notified by + // another thread). + if (!waiter->cx()->fx.isWaiting()) { + continue; + } + waiter->cx()->fx.notify(FutexThread::NotifyExplicit); + } else { + // For async waits, we resolve a promise. + + // Steps to clean up case 1. and 2. in SMDOC for Atomics.waitAsync + // Take ownership of the async waiter, so that it will be + // freed at the end of this block. + UniquePtr asyncWaiter( + RemoveAsyncWaiter(waiter->asAsync(), lock)); + asyncWaiter->maybeClearTimeout(lock); + // If we are notifying a waiter that was created by the current + // context, we resolve the promise directly instead of dispatching + // a task to the event loop. + OffThreadPromiseTask* task = asyncWaiter->notifyTask(); + if (waiter->cx() == cx) { + // Add the promise to a list to resolve as soon as we've left the + // critical section. + PromiseObject* promise = + OffThreadPromiseTask::ExtractAndForget(task, helperLock); + if (!promisesToResolve.append(promise)) { + return false; + } + } else { + // Dispatch a task to resolve the promise with value "ok". + task->removeFromCancellableListAndDispatch(helperLock); + } + } // Overflow will be a problem only in two cases: // (1) 128-bit systems with substantially more than 2^64 bytes of // memory per process, and a very lightweight // Atomics.waitAsync(). Obviously a future problem. // (2) Bugs. - MOZ_RELEASE_ASSERT(woken < INT64_MAX); - ++woken; + MOZ_RELEASE_ASSERT(*woken < INT64_MAX); + (*woken)++; if (count > 0) { --count; } - } while (count && iter != waiters); + } } - // Step 16. - return woken; + // Step 10 (reordered) + // We resolve same-thread promises after we've left the critical section to + // avoid mutex ordering problems. + RootedValue resultMsg(cx, StringValue(cx->names().ok)); + for (uint32_t i = 0; i < promisesToResolve.length(); i++) { + if (!PromiseObject::resolve(cx, promisesToResolve[i], resultMsg)) { + MOZ_ASSERT(cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed()); + return false; + } + } + + // Step 13. + return true; } // ES2021 draft rev bd868f20b8c574ad6689fba014b62a1dba819e56 @@ -854,9 +1522,42 @@ static bool atomics_notify(JSContext* cx, unsigned argc, Value* vp) { size_t indexedPosition = intIndex * elementSize + *offset; // Steps 10-16. - r.setNumber(double(atomics_notify_impl(unwrappedSab->rawBufferObject(), - indexedPosition, count))); + int64_t woken = 0; + if (!atomics_notify_impl(cx, unwrappedSab->rawBufferObject(), indexedPosition, + count, &woken)) { + return false; + } + + r.setNumber(double(woken)); + + return true; +} + +/** + * Atomics.pause ( [ N ] ) + * + * https://tc39.es/proposal-atomics-microwait/ + */ +static bool atomics_pause(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. + if (args.hasDefined(0)) { + if (!args[0].isNumber() || !IsInteger(args[0].toNumber())) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_ATOMICS_PAUSE_BAD_COUNT); + return false; + } + } + + // Step 2. + // + // We ignore the iteration count when not inlining this operation. + jit::AtomicOperations::pause(); + + // Step 3. + args.rval().setUndefined(); return true; } @@ -1086,21 +1787,33 @@ const JSFunctionSpec AtomicsMethods[] = { JS_INLINABLE_FN("xor", atomics_xor, 3, 0, AtomicsXor), JS_INLINABLE_FN("isLockFree", atomics_isLockFree, 1, 0, AtomicsIsLockFree), JS_FN("wait", atomics_wait, 4, 0), + JS_FN("waitAsync", atomics_wait_async, 4, 0), JS_FN("notify", atomics_notify, 3, 0), JS_FN("wake", atomics_notify, 3, 0), // Legacy name - JS_FS_END}; + JS_INLINABLE_FN("pause", atomics_pause, 0, 0, AtomicsPause), + JS_FS_END, +}; static const JSPropertySpec AtomicsProperties[] = { - JS_STRING_SYM_PS(toStringTag, "Atomics", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "Atomics", JSPROP_READONLY), + JS_PS_END, +}; static JSObject* CreateAtomicsObject(JSContext* cx, JSProtoKey key) { RootedObject proto(cx, &cx->global()->getObjectPrototype()); return NewTenuredObjectWithGivenProto(cx, &AtomicsObject::class_, proto); } -static const ClassSpec AtomicsClassSpec = {CreateAtomicsObject, nullptr, - AtomicsMethods, AtomicsProperties}; +static const ClassSpec AtomicsClassSpec = { + CreateAtomicsObject, + nullptr, + AtomicsMethods, + AtomicsProperties, +}; const JSClass AtomicsObject::class_ = { - "Atomics", JSCLASS_HAS_CACHED_PROTO(JSProto_Atomics), JS_NULL_CLASS_OPS, - &AtomicsClassSpec}; + "Atomics", + JSCLASS_HAS_CACHED_PROTO(JSProto_Atomics), + JS_NULL_CLASS_OPS, + &AtomicsClassSpec, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.h b/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.h index 0f2e6c4af9f..419efeb09bc 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/AtomicsObject.h @@ -13,6 +13,7 @@ #include "threading/ConditionVariable.h" #include "threading/ProtectedData.h" // js::ThreadData #include "vm/NativeObject.h" +#include "vm/PlainObject.h" namespace js { @@ -23,6 +24,44 @@ class AtomicsObject : public NativeObject { static const JSClass class_; }; +enum class FutexWaiterKind { Sync, Async, ListHead }; + +class FutexWaiter; +class SyncFutexWaiter; +class AsyncFutexWaiter; + +class FutexWaiterListNode { + private: + FutexWaiterListNode* next_ = nullptr; // Lower priority node in waiter list + FutexWaiterListNode* prev_ = nullptr; // Higher priority node in waiter list + + protected: + explicit FutexWaiterListNode(FutexWaiterKind kind) : kind_(kind) {} + FutexWaiterKind kind_; + + public: + FutexWaiter* toWaiter() { + MOZ_ASSERT(kind_ != FutexWaiterKind::ListHead); + return reinterpret_cast(this); + } + + FutexWaiterKind kind() const { return kind_; } + + FutexWaiterListNode* next() { return next_; } + void setNext(FutexWaiterListNode* next) { next_ = next; } + FutexWaiterListNode* prev() { return prev_; } + void setPrev(FutexWaiterListNode* prev) { prev_ = prev; } +}; + +class FutexWaiterListHead : public FutexWaiterListNode { + public: + FutexWaiterListHead() : FutexWaiterListNode(FutexWaiterKind::ListHead) { + setNext(this); + setPrev(this); + } + ~FutexWaiterListHead(); +}; + class FutexThread { friend class AutoLockFutexAPI; @@ -129,12 +168,29 @@ class FutexThread { JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int64_t value, const mozilla::Maybe& timeout); +// If the int32_t value at the given address equals `value`, return a result +// object containing a promise that will be resolved when that address is +// notified. +[[nodiscard]] PlainObject* atomics_wait_async_impl( + JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int32_t value, + const mozilla::Maybe& timeout); + +// If the int64_t value at the given address equals `value`, return a result +// object containing a promise that will be resolved when that address is +// notified. +[[nodiscard]] PlainObject* atomics_wait_async_impl( + JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int64_t value, + const mozilla::Maybe& timeout); + // Notify some waiters on the given address. If `count` is negative then notify // all. The return value is nonnegative and is the number of waiters woken. If // the number of waiters woken exceeds INT64_MAX then this never returns. If -// `count` is nonnegative then the return value is never greater than `count`. -[[nodiscard]] int64_t atomics_notify_impl(SharedArrayRawBuffer* sarb, - size_t byteOffset, int64_t count); +// `count` is nonnegative then the woken out parameter is never greater than +// `count`. +[[nodiscard]] bool atomics_notify_impl(JSContext* cx, + SharedArrayRawBuffer* sarb, + size_t byteOffset, int64_t count, + int64_t* woken); } /* namespace js */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/BigInt.cpp b/src/third_party/mozjs/extract/js/src/builtin/BigInt.cpp index 378c383295c..f3026b8cd37 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/BigInt.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/BigInt.cpp @@ -39,8 +39,14 @@ static bool BigIntConstructor(JSContext* cx, unsigned argc, Value* vp) { } // Steps 3-4. - BigInt* bi = - v.isNumber() ? NumberToBigInt(cx, v.toNumber()) : ToBigInt(cx, v); + BigInt* bi; + if (!v.isNumber()) { + bi = ToBigInt(cx, v); + } else if (v.isInt32()) { + bi = BigInt::createFromInt64(cx, int64_t(v.toInt32())); + } else { + bi = NumberToBigInt(cx, v.toDouble()); + } if (!bi) { return false; } @@ -199,36 +205,49 @@ bool BigIntObject::asIntN(JSContext* cx, unsigned argc, Value* vp) { } const ClassSpec BigIntObject::classSpec_ = { - GenericCreateConstructor, + GenericCreateConstructor, GenericCreatePrototype, BigIntObject::staticMethods, nullptr, BigIntObject::methods, - BigIntObject::properties}; + BigIntObject::properties, +}; const JSClass BigIntObject::class_ = { "BigInt", JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt) | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), - JS_NULL_CLASS_OPS, &BigIntObject::classSpec_}; + JS_NULL_CLASS_OPS, + &BigIntObject::classSpec_, +}; const JSClass BigIntObject::protoClass_ = { - "BigInt.prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt), - JS_NULL_CLASS_OPS, &BigIntObject::classSpec_}; + "BigInt.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt), + JS_NULL_CLASS_OPS, + &BigIntObject::classSpec_, +}; const JSPropertySpec BigIntObject::properties[] = { // BigInt proposal section 5.3.5 - JS_STRING_SYM_PS(toStringTag, "BigInt", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "BigInt", JSPROP_READONLY), + JS_PS_END, +}; const JSFunctionSpec BigIntObject::methods[] = { - JS_FN("valueOf", valueOf, 0, 0), JS_FN("toString", toString, 0, 0), + JS_FN("valueOf", valueOf, 0, 0), + JS_FN("toString", toString, 0, 0), #ifdef JS_HAS_INTL_API JS_SELF_HOSTED_FN("toLocaleString", "BigInt_toLocaleString", 0, 0), #else JS_FN("toLocaleString", toLocaleString, 0, 0), #endif - JS_FS_END}; + JS_FS_END, +}; const JSFunctionSpec BigIntObject::staticMethods[] = { JS_INLINABLE_FN("asUintN", asUintN, 2, 0, BigIntAsUintN), - JS_INLINABLE_FN("asIntN", asIntN, 2, 0, BigIntAsIntN), JS_FS_END}; + JS_INLINABLE_FN("asIntN", asIntN, 2, 0, BigIntAsIntN), + JS_FS_END, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/Boolean.cpp b/src/third_party/mozjs/extract/js/src/builtin/Boolean.cpp index 7806362d134..1297a2ee49e 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Boolean.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Boolean.cpp @@ -14,7 +14,7 @@ #include "jit/InlinableNatives.h" #include "js/PropertySpec.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/BigIntType.h" #include "vm/GlobalObject.h" #include "vm/JSContext.h" @@ -27,7 +27,9 @@ using namespace js; const JSClass BooleanObject::class_ = { "Boolean", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), - JS_NULL_CLASS_OPS, &BooleanObject::classSpec_}; + JS_NULL_CLASS_OPS, + &BooleanObject::classSpec_, +}; MOZ_ALWAYS_INLINE bool IsBoolean(HandleValue v) { return v.isBoolean() || (v.isObject() && v.toObject().is()); @@ -52,7 +54,7 @@ MOZ_ALWAYS_INLINE bool bool_toSource_impl(JSContext* cx, const CallArgs& args) { bool b = ThisBooleanValue(args.thisv()); JSStringBuilder sb(cx); - if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) || + if (!sb.append("(new Boolean(") || !BooleanToStringBuilder(b, sb) || !sb.append("))")) { return false; } @@ -102,7 +104,9 @@ static bool bool_valueOf(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec boolean_methods[] = { JS_FN("toSource", bool_toSource, 0, 0), JS_FN("toString", bool_toString, 0, 0), - JS_FN("valueOf", bool_valueOf, 0, 0), JS_FS_END}; + JS_FN("valueOf", bool_valueOf, 0, 0), + JS_FS_END, +}; // ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce // 19.3.1.1 Boolean ( value ) @@ -152,7 +156,8 @@ const ClassSpec BooleanObject::classSpec_ = { nullptr, nullptr, boolean_methods, - nullptr}; + nullptr, +}; PropertyName* js::BooleanToString(JSContext* cx, bool b) { return b ? cx->names().true_ : cx->names().false_; @@ -165,12 +170,6 @@ JS_PUBLIC_API bool js::ToBooleanSlow(HandleValue v) { if (v.isBigInt()) { return !v.toBigInt()->isZero(); } -#ifdef ENABLE_RECORD_TUPLE - // proposal-record-tuple Section 3.1.1 - if (v.isExtendedPrimitive()) { - return true; - } -#endif MOZ_ASSERT(v.isObject()); return !EmulatesUndefined(&v.toObject()); diff --git a/src/third_party/mozjs/extract/js/src/builtin/DataViewObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/DataViewObject.cpp index 9c3e8edcc6a..f1fc0fced03 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/DataViewObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/DataViewObject.cpp @@ -43,7 +43,6 @@ using namespace js; using JS::CanonicalizeNaN; using JS::ToInt32; -using mozilla::AssertedCast; using mozilla::WrapToSigned; static bool IsDataView(HandleValue v) { @@ -405,7 +404,7 @@ NativeType DataViewObject::read(uint64_t offset, size_t length, getDataPointer(offset, length, &isSharedMemory); MOZ_ASSERT(data); - NativeType val = 0; + NativeType val{}; if (isSharedMemory) { DataViewIO>::fromBuffer(&val, data, isLittleEndian); @@ -417,16 +416,6 @@ NativeType DataViewObject::read(uint64_t offset, size_t length, return val; } -#ifdef NIGHTLY_BUILD -template <> -float16 DataViewObject::read(uint64_t offset, size_t length, - bool isLittleEndian) { - float16 val{}; - val.val = read(offset, length, isLittleEndian); - return val; -} -#endif - template uint32_t DataViewObject::read(uint64_t offset, size_t length, bool isLittleEndian); @@ -510,7 +499,6 @@ inline bool WebIDLCast(JSContext* cx, HandleValue value, return true; } -#ifdef NIGHTLY_BUILD template <> inline bool WebIDLCast(JSContext* cx, HandleValue value, float16* out) { @@ -521,7 +509,6 @@ inline bool WebIDLCast(JSContext* cx, HandleValue value, *out = float16(temp); return true; } -#endif template <> inline bool WebIDLCast(JSContext* cx, HandleValue value, float* out) { @@ -560,11 +547,9 @@ bool DataViewObject::write(JSContext* cx, Handle obj, } // See the comment in ElementSpecific::doubleToNative. - if (js::SupportDifferentialTesting() && TypeIsFloatingPoint()) { - if constexpr (std::is_same_v) { - value = JS::CanonicalizeNaN(value.toDouble()); - } else { - value = JS::CanonicalizeNaN(value); + if constexpr (!std::numeric_limits::is_integer) { + if (js::SupportDifferentialTesting()) { + value = JS::CanonicalizeNaN(static_cast(value)); } } @@ -767,7 +752,6 @@ bool DataViewObject::fun_getBigUint64(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -#ifdef NIGHTLY_BUILD bool DataViewObject::getFloat16Impl(JSContext* cx, const CallArgs& args) { MOZ_ASSERT(IsDataView(args.thisv())); @@ -779,7 +763,7 @@ bool DataViewObject::getFloat16Impl(JSContext* cx, const CallArgs& args) { return false; } - args.rval().setDouble(CanonicalizeNaN(val.toDouble())); + args.rval().setDouble(CanonicalizeNaN(static_cast(val))); return true; } @@ -787,7 +771,6 @@ bool DataViewObject::fun_getFloat16(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return CallNonGenericMethod(cx, args); } -#endif bool DataViewObject::getFloat32Impl(JSContext* cx, const CallArgs& args) { MOZ_ASSERT(IsDataView(args.thisv())); @@ -977,7 +960,6 @@ bool DataViewObject::fun_setBigUint64(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -#ifdef NIGHTLY_BUILD bool DataViewObject::setFloat16Impl(JSContext* cx, const CallArgs& args) { MOZ_ASSERT(IsDataView(args.thisv())); @@ -995,7 +977,6 @@ bool DataViewObject::fun_setFloat16(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return CallNonGenericMethod(cx, args); } -#endif bool DataViewObject::setFloat32Impl(JSContext* cx, const CallArgs& args) { MOZ_ASSERT(IsDataView(args.thisv())); @@ -1153,10 +1134,8 @@ const JSFunctionSpec DataViewObject::methods[] = { DataViewGetInt32), JS_INLINABLE_FN("getUint32", DataViewObject::fun_getUint32, 1, 0, DataViewGetUint32), -#ifdef NIGHTLY_BUILD - // TODO: See Bug 1835034 for JIT support for Float16Array - JS_FN("getFloat16", DataViewObject::fun_getFloat16, 1, 0), -#endif + JS_INLINABLE_FN("getFloat16", DataViewObject::fun_getFloat16, 1, 0, + DataViewGetFloat16), JS_INLINABLE_FN("getFloat32", DataViewObject::fun_getFloat32, 1, 0, DataViewGetFloat32), JS_INLINABLE_FN("getFloat64", DataViewObject::fun_getFloat64, 1, 0, @@ -1177,10 +1156,8 @@ const JSFunctionSpec DataViewObject::methods[] = { DataViewSetInt32), JS_INLINABLE_FN("setUint32", DataViewObject::fun_setUint32, 2, 0, DataViewSetUint32), -#ifdef NIGHTLY_BUILD - // TODO: See Bug 1835034 for JIT support for Float16Array - JS_FN("setFloat16", DataViewObject::fun_setFloat16, 2, 0), -#endif + JS_INLINABLE_FN("setFloat16", DataViewObject::fun_setFloat16, 2, 0, + DataViewSetFloat16), JS_INLINABLE_FN("setFloat32", DataViewObject::fun_setFloat32, 2, 0, DataViewSetFloat32), JS_INLINABLE_FN("setFloat64", DataViewObject::fun_setFloat64, 2, 0, @@ -1189,13 +1166,16 @@ const JSFunctionSpec DataViewObject::methods[] = { DataViewSetBigInt64), JS_INLINABLE_FN("setBigUint64", DataViewObject::fun_setBigUint64, 2, 0, DataViewSetBigUint64), - JS_FS_END}; + JS_FS_END, +}; const JSPropertySpec DataViewObject::properties[] = { JS_PSG("buffer", DataViewObject::bufferGetter, 0), JS_PSG("byteLength", DataViewObject::byteLengthGetter, 0), JS_PSG("byteOffset", DataViewObject::byteOffsetGetter, 0), - JS_STRING_SYM_PS(toStringTag, "DataView", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "DataView", JSPROP_READONLY), + JS_PS_END, +}; JS_PUBLIC_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer, size_t byteOffset, size_t byteLength) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/DisposableStack.js b/src/third_party/mozjs/extract/js/src/builtin/DisposableStack.js new file mode 100644 index 00000000000..3c60d3a8b45 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/DisposableStack.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Explicit Resource Management Proposal +// 27.3.3.3 DisposableStack.prototype.dispose ( ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.dispose +function $DisposableStackDispose() { + // Step 1. Let disposableStack be the this value. + var disposableStack = this; + + if (!IsObject(disposableStack) || (disposableStack = GuardToDisposableStackHelper(disposableStack)) === null) { + return callFunction( + CallDisposableStackMethodIfWrapped, + this, + "$DisposableStackDispose" + ); + } + + // Step 2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]). + var state = UnsafeGetReservedSlot(disposableStack, DISPOSABLE_STACK_STATE_SLOT); + + // Step 3. If disposableStack.[[DisposableState]] is disposed, return undefined. + if (state === DISPOSABLE_STACK_STATE_DISPOSED) { + return undefined; + } + + // Step 4. Set disposableStack.[[DisposableState]] to disposed. + UnsafeSetReservedSlot(disposableStack, DISPOSABLE_STACK_STATE_SLOT, DISPOSABLE_STACK_STATE_DISPOSED); + + // Step 5. Return ? DisposeResources(disposableStack.[[DisposeCapability]], NormalCompletion(undefined)). + var disposeCapability = UnsafeGetReservedSlot(disposableStack, DISPOSABLE_STACK_DISPOSABLE_RESOURCE_STACK_SLOT); + UnsafeSetReservedSlot(disposableStack, DISPOSABLE_STACK_DISPOSABLE_RESOURCE_STACK_SLOT, undefined); + // disposeCapability being undefined indicates that its an empty stack, thus + // all the following operations are no-ops, hence we can return early. + if (disposeCapability === undefined) { + return undefined; + } + DisposeResourcesSync(disposeCapability, disposeCapability.length); + + return undefined; +} +SetCanonicalName($DisposableStackDispose, "dispose"); diff --git a/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.cpp new file mode 100644 index 00000000000..7f104585d3c --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.cpp @@ -0,0 +1,373 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "builtin/DisposableStackObject.h" + +#include "builtin/Array.h" +#include "builtin/DisposableStackObjectBase.h" +#include "js/friend/ErrorMessages.h" +#include "js/PropertyAndElement.h" +#include "js/PropertySpec.h" +#include "vm/GlobalObject.h" +#include "vm/JSContext.h" +#include "vm/JSObject.h" +#include "vm/UsingHint.h" + +#include "vm/NativeObject-inl.h" + +using namespace js; + +/* static */ DisposableStackObject* DisposableStackObject::create( + JSContext* cx, JS::Handle proto, + JS::Handle + initialDisposeCapability /* = JS::UndefinedHandleValue */) { + DisposableStackObject* obj = + NewObjectWithClassProto(cx, proto); + if (!obj) { + return nullptr; + } + + MOZ_ASSERT(initialDisposeCapability.isUndefined() || + initialDisposeCapability.isObject()); + MOZ_ASSERT_IF(initialDisposeCapability.isObject(), + initialDisposeCapability.toObject().is()); + + obj->initReservedSlot(DisposableStackObject::DISPOSABLE_RESOURCE_STACK_SLOT, + initialDisposeCapability); + obj->initReservedSlot( + DisposableStackObject::STATE_SLOT, + JS::Int32Value(int32_t(DisposableStackObject::DisposableState::Pending))); + + return obj; +} + +/** + * Explicit Resource Management Proposal + * 27.3.1.1 DisposableStack ( ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack + */ +/* static */ bool DisposableStackObject::construct(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. If NewTarget is undefined, throw a TypeError exception. + if (!ThrowIfNotConstructing(cx, args, "DisposableStack")) { + return false; + } + + // Step 2. Let disposableStack be ? OrdinaryCreateFromConstructor(NewTarget, + // "%DisposableStack.prototype%", « [[DisposableState]], [[DisposeCapability]] + // »). + // Step 3. Set disposableStack.[[DisposableState]] to pending. + // Step 4. Set disposableStack.[[DisposeCapability]] to + // NewDisposeCapability(). + JS::Rooted proto(cx); + if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_DisposableStack, + &proto)) { + return false; + } + + DisposableStackObject* obj = DisposableStackObject::create(cx, proto); + if (!obj) { + return false; + } + + // Step 5. Return disposableStack. + args.rval().setObject(*obj); + return true; +} + +/* static */ bool DisposableStackObject::is(JS::Handle val) { + return val.isObject() && val.toObject().is(); +} + +/** + * Explicit Resource Management Proposal + * 27.3.3.6 DisposableStack.prototype.use ( value ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.use + */ +/* static */ bool DisposableStackObject::use_impl(JSContext* cx, + const JS::CallArgs& args) { + // Step 1. Let disposableStack be the this value. + JS::Rooted disposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(disposableStack, + // [[DisposableState]]). + // Step 3. If disposableStack.[[DisposableState]] is disposed, throw a + // ReferenceError exception. + if (disposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. Perform ? + // AddDisposableResource(disposableStack.[[DisposeCapability]], value, + // sync-dispose). + JS::Rooted disposeCapability( + cx, GetOrCreateDisposeCapability(cx, disposableStack)); + if (!disposeCapability) { + return false; + } + + JS::Rooted val(cx, args.get(0)); + if (!AddDisposableResource(cx, disposeCapability, val, UsingHint::Sync)) { + return false; + } + + // Step 5. Return value. + args.rval().set(val); + return true; +} + +/* static */ bool DisposableStackObject::use(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * 27.3.3.2 DisposableStack.prototype.defer ( onDispose ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.defer + */ +/* static */ bool DisposableStackObject::defer_impl(JSContext* cx, + const JS::CallArgs& args) { + // Step 1. Let disposableStack be the this value. + JS::Rooted disposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(disposableStack, + // [[DisposableState]]). + // Step 3. If disposableStack.[[DisposableState]] is disposed, throw a + // ReferenceError exception. + if (disposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. If IsCallable(onDispose) is false, throw a TypeError exception. + JS::Handle onDispose = args.get(0); + if (!ThrowIfOnDisposeNotCallable(cx, onDispose)) { + return false; + } + + // Step 5. Perform ? + // AddDisposableResource(disposableStack.[[DisposeCapability]], undefined, + // sync-dispose, onDispose). + JS::Rooted disposeCapability( + cx, GetOrCreateDisposeCapability(cx, disposableStack)); + if (!disposeCapability) { + return false; + } + + if (!AddDisposableResource(cx, disposeCapability, JS::UndefinedHandleValue, + UsingHint::Sync, onDispose)) { + return false; + } + + // Step 6. Return undefined. + args.rval().setUndefined(); + return true; +} + +/* static */ bool DisposableStackObject::defer(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * 27.3.3.5 DisposableStack.prototype.move ( ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.move + */ +/* static */ bool DisposableStackObject::move_impl(JSContext* cx, + const JS::CallArgs& args) { + // Step 1. Let disposableStack be the this value. + JS::Rooted disposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(disposableStack, + // [[DisposableState]]). + // Step 3. If disposableStack.[[DisposableState]] is disposed, throw a + // ReferenceError exception. + if (disposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. Let newDisposableStack be ? + // OrdinaryCreateFromConstructor(%DisposableStack%, + // "%DisposableStack.prototype%", « [[DisposableState]], [[DisposeCapability]] + // »). + // Step 5. Set newDisposableStack.[[DisposableState]] to pending. + // Step 6. Set newDisposableStack.[[DisposeCapability]] to + // disposableStack.[[DisposeCapability]]. + JS::Rooted existingDisposeCapability( + cx, disposableStack->getReservedSlot( + DisposableStackObject::DISPOSABLE_RESOURCE_STACK_SLOT)); + DisposableStackObject* newDisposableStack = + DisposableStackObject::create(cx, nullptr, existingDisposeCapability); + if (!newDisposableStack) { + return false; + } + + // Step 7. Set disposableStack.[[DisposeCapability]] to + // NewDisposeCapability(). + disposableStack->clearDisposableResourceStack(); + + // Step 8. Set disposableStack.[[DisposableState]] to disposed. + disposableStack->setState(DisposableState::Disposed); + + // Step 9. Return newDisposableStack. + args.rval().setObject(*newDisposableStack); + return true; +} + +/* static */ bool DisposableStackObject::move(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * 27.3.3.1 DisposableStack.prototype.adopt ( value, onDispose ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.adopt + */ +/* static */ bool DisposableStackObject::adopt_impl(JSContext* cx, + const JS::CallArgs& args) { + // Step 1. Let disposableStack be the this value. + JS::Rooted disposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(disposableStack, + // [[DisposableState]]). + // Step 3. If disposableStack.[[DisposableState]] is disposed, throw a + // ReferenceError exception. + if (disposableStack->state() == DisposableState::Disposed) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSABLE_STACK_DISPOSED); + return false; + } + + // Step 4. If IsCallable(onDispose) is false, throw a TypeError exception. + JS::Handle onDispose = args.get(1); + if (!ThrowIfOnDisposeNotCallable(cx, onDispose)) { + return false; + } + + // Step 5. Let closure be a new Abstract Closure with no parameters that + // captures value and onDispose and performs the following steps when called: + // Step 5.a. (see AdoptClosure) + // Step 6. Let F be CreateBuiltinFunction(closure, 0, "", « »). + JS::Handle funName = cx->names().empty_; + JS::Rooted F( + cx, NewNativeFunction(cx, AdoptClosure, 0, funName, + gc::AllocKind::FUNCTION_EXTENDED, GenericObject)); + if (!F) { + return false; + } + JS::Handle value = args.get(0); + F->initExtendedSlot(AdoptClosureSlot_ValueSlot, value); + F->initExtendedSlot(AdoptClosureSlot_OnDisposeSlot, onDispose); + + // Step 7. Perform ? + // AddDisposableResource(disposableStack.[[DisposeCapability]], undefined, + // sync-dispose, F). + JS::Rooted disposeCapability( + cx, GetOrCreateDisposeCapability(cx, disposableStack)); + if (!disposeCapability) { + return false; + } + + JS::Rooted FVal(cx, ObjectValue(*F)); + if (!AddDisposableResource(cx, disposeCapability, JS::UndefinedHandleValue, + UsingHint::Sync, FVal)) { + return false; + } + + // Step 8. Return value. + args.rval().set(value); + return true; +} + +/* static */ bool DisposableStackObject::adopt(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +/** + * Explicit Resource Management Proposal + * 27.3.3.4 get DisposableStack.prototype.disposed + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-get-disposablestack.prototype.disposed + */ +/* static */ bool DisposableStackObject::disposed_impl( + JSContext* cx, const JS::CallArgs& args) { + // Step 1. Let disposableStack be the this value. + JS::Rooted disposableStack( + cx, &args.thisv().toObject().as()); + + // Step 2. Perform ? RequireInternalSlot(disposableStack, + // [[DisposableState]]). + // Step 3. If disposableStack.[[DisposableState]] is disposed, return true. + // Step 4. Otherwise, return false. + args.rval().setBoolean(disposableStack->state() == DisposableState::Disposed); + return true; +} + +/* static */ bool DisposableStackObject::disposed(JSContext* cx, unsigned argc, + JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + return JS::CallNonGenericMethod(cx, args); +} + +const JSPropertySpec DisposableStackObject::properties[] = { + JS_STRING_SYM_PS(toStringTag, "DisposableStack", JSPROP_READONLY), + JS_PSG("disposed", disposed, 0), + JS_PS_END, +}; + +const JSFunctionSpec DisposableStackObject::methods[] = { + JS_FN("use", DisposableStackObject::use, 1, 0), + JS_SELF_HOSTED_FN("dispose", "$DisposableStackDispose", 0, 0), + JS_FN("defer", DisposableStackObject::defer, 1, 0), + JS_FN("move", DisposableStackObject::move, 0, 0), + JS_FN("adopt", DisposableStackObject::adopt, 2, 0), + JS_SELF_HOSTED_SYM_FN(dispose, "$DisposableStackDispose", 0, 0), + JS_FS_END, +}; + +const ClassSpec DisposableStackObject::classSpec_ = { + GenericCreateConstructor, + GenericCreatePrototype, + nullptr, + nullptr, + DisposableStackObject::methods, + DisposableStackObject::properties, + nullptr, +}; + +const JSClass DisposableStackObject::class_ = { + "DisposableStack", + JSCLASS_HAS_RESERVED_SLOTS(DisposableStackObject::RESERVED_SLOTS) | + JSCLASS_HAS_CACHED_PROTO(JSProto_DisposableStack), + JS_NULL_CLASS_OPS, + &DisposableStackObject::classSpec_, +}; + +const JSClass DisposableStackObject::protoClass_ = { + "DisposableStack.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_DisposableStack), + JS_NULL_CLASS_OPS, + &DisposableStackObject::classSpec_, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.h b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.h new file mode 100644 index 00000000000..03963ac561e --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObject.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_DisposableStackObject_h +#define builtin_DisposableStackObject_h + +#include "builtin/DisposableStackObjectBase.h" +#include "vm/JSObject.h" + +namespace js { + +class DisposableStackObject : public DisposableStackObjectBase { + public: + static const JSClass class_; + static const JSClass protoClass_; + + static DisposableStackObject* create( + JSContext* cx, JS::Handle proto, + JS::Handle initialDisposeCapability = + JS::UndefinedHandleValue); + + private: + static const ClassSpec classSpec_; + static const JSPropertySpec properties[]; + static const JSFunctionSpec methods[]; + + static bool is(JS::Handle val); + static bool finishInit(JSContext* cx, JS::Handle ctor, + JS::Handle proto); + + static bool construct(JSContext* cx, unsigned argc, JS::Value* vp); + static bool use_impl(JSContext* cx, const JS::CallArgs& args); + static bool use(JSContext* cx, unsigned argc, JS::Value* vp); + static bool adopt_impl(JSContext* cx, const JS::CallArgs& args); + static bool adopt(JSContext* cx, unsigned argc, JS::Value* vp); + static bool defer_impl(JSContext* cx, const JS::CallArgs& args); + static bool defer(JSContext* cx, unsigned argc, JS::Value* vp); + static bool move_impl(JSContext* cx, const JS::CallArgs& args); + static bool move(JSContext* cx, unsigned argc, JS::Value* vp); + static bool disposed_impl(JSContext* cx, const JS::CallArgs& args); + static bool disposed(JSContext* cx, unsigned argc, JS::Value* vp); +}; + +} /* namespace js */ + +#endif /* builtin_DisposableStackObject_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.cpp b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.cpp new file mode 100644 index 00000000000..ff44daa2bc7 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.cpp @@ -0,0 +1,319 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "builtin/DisposableStackObjectBase.h" + +#include "builtin/Array.h" +#include "vm/ArrayObject.h" +#include "vm/Interpreter.h" + +#include "vm/DisposableRecord-inl.h" +#include "vm/JSObject-inl.h" + +using namespace js; + +/** + * Explicit Resource Management Proposal + * + * 27.4.3.1 AsyncDisposableStack.prototype.adopt ( value, onDisposeAsync ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.adopt + * Step 5.a + * 27.3.3.1 DisposableStack.prototype.adopt ( value, onDispose ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.adopt + * Step 5.a + */ +bool js::AdoptClosure(JSContext* cx, unsigned argc, JS::Value* vp) { + JS::CallArgs args = CallArgsFromVp(argc, vp); + + JS::Rooted callee(cx, &args.callee().as()); + JS::Rooted value( + cx, callee->getExtendedSlot(AdoptClosureSlot_ValueSlot)); + JS::Rooted onDispose( + cx, callee->getExtendedSlot(AdoptClosureSlot_OnDisposeSlot)); + + // Step 5.a. Return ? Call(onDispose, undefined, « value »). + return Call(cx, onDispose, JS::UndefinedHandleValue, value, args.rval()); +} + +bool js::ThrowIfOnDisposeNotCallable(JSContext* cx, + JS::Handle onDispose) { + if (IsCallable(onDispose)) { + return true; + } + + JS::UniqueChars bytes = + DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, onDispose, nullptr); + if (!bytes) { + return false; + } + + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION, + bytes.get()); + + return false; +} + +// Explicit Resource Management Proposal +// CreateDisposableResource ( V, hint [ , method ] ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource +// Steps 1, 3. +bool js::CreateDisposableResource(JSContext* cx, JS::Handle objVal, + UsingHint hint, + JS::MutableHandle result) { + // Step 1. If method is not present, then + // (implicit) + JS::Rooted method(cx); + JS::Rooted object(cx); + // Step 1.a. If V is either null or undefined, then + if (objVal.isNullOrUndefined()) { + // Step 1.a.i. Set V to undefined. + // Step 1.a.ii. Set method to undefined. + object.setUndefined(); + method.setUndefined(); + } else { + // Step 1.b. Else, + // Step 1.b.i. If V is not an Object, throw a TypeError exception. + if (!objVal.isObject()) { + return ThrowCheckIsObject(cx, CheckIsObjectKind::Disposable); + } + + // Step 1.b.ii. Set method to ? GetDisposeMethod(V, hint). + // Step 1.b.iii. If method is undefined, throw a TypeError exception. + object.set(objVal); + if (!GetDisposeMethod(cx, object, hint, &method)) { + return false; + } + } + + // Step 3. Return the + // DisposableResource Record { [[ResourceValue]]: V, [[Hint]]: hint, + // [[DisposeMethod]]: method }. + DisposableRecordObject* disposableRecord = + DisposableRecordObject::create(cx, object, method, hint); + if (!disposableRecord) { + return false; + } + result.set(ObjectValue(*disposableRecord)); + + return true; +} + +// Explicit Resource Management Proposal +// CreateDisposableResource ( V, hint [ , method ] ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource +// Steps 2, 3. +bool js::CreateDisposableResource(JSContext* cx, JS::Handle obj, + UsingHint hint, + JS::Handle methodVal, + JS::MutableHandle result) { + JS::Rooted method(cx); + JS::Rooted object(cx); + + // Step 2. Else, + // Step 2.a. If IsCallable(method) is false, throw a TypeError exception. + if (!IsCallable(methodVal)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSE_NOT_CALLABLE); + return false; + } + object.set(obj); + method.set(methodVal); + + // Step 3. Return the + // DisposableResource Record { [[ResourceValue]]: V, [[Hint]]: hint, + // [[DisposeMethod]]: method }. + DisposableRecordObject* disposableRecord = + DisposableRecordObject::create(cx, object, method, hint); + if (!disposableRecord) { + return false; + } + result.set(ObjectValue(*disposableRecord)); + + return true; +} + +// Explicit Resource Management Proposal +// 7.5.4 AddDisposableResource ( disposeCapability, V, hint [ , method ] ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-adddisposableresource +// Steps 1, 3. +bool js::AddDisposableResource(JSContext* cx, + JS::Handle disposeCapability, + JS::Handle val, UsingHint hint) { + JS::Rooted resource(cx); + + // Step 1. If method is not present, then + // (implicit) + // Step 1.a. If V is either null or undefined and hint is sync-dispose, + // return unused. + if (val.isNullOrUndefined() && hint == UsingHint::Sync) { + return true; + } + + // Step 1.c. Let resource be ? CreateDisposableResource(V, hint). + if (!CreateDisposableResource(cx, val, hint, &resource)) { + return false; + } + + // Step 3. Append resource to disposeCapability.[[DisposableResourceStack]]. + return NewbornArrayPush(cx, disposeCapability, resource); +} + +// Explicit Resource Management Proposal +// 7.5.4 AddDisposableResource ( disposeCapability, V, hint [ , method ] ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-adddisposableresource +bool js::AddDisposableResource(JSContext* cx, + JS::Handle disposeCapability, + JS::Handle val, UsingHint hint, + JS::Handle methodVal) { + JS::Rooted resource(cx); + // Step 2. Else, + // Step 2.a. Assert: V is undefined. + MOZ_ASSERT(val.isUndefined()); + + // Step 2.b. Let resource be ? CreateDisposableResource(undefined, hint, + // method). + if (!CreateDisposableResource(cx, val, hint, methodVal, &resource)) { + return false; + } + // Step 3. Append resource to disposeCapability.[[DisposableResourceStack]]. + return NewbornArrayPush(cx, disposeCapability, resource); +} + +// Explicit Resource Management Proposal +// GetDisposeMethod ( V, hint ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-getdisposemethod +bool js::GetDisposeMethod(JSContext* cx, JS::Handle objVal, + UsingHint hint, + JS::MutableHandle disposeMethod) { + switch (hint) { + case UsingHint::Async: { + // Step 1. If hint is async-dispose, then + // Step 1.a. Let method be ? GetMethod(V, @@asyncDispose). + // GetMethod throws TypeError if method is not callable + // this is handled below at the end of the function. + JS::Rooted idAsync( + cx, PropertyKey::Symbol(cx->wellKnownSymbols().asyncDispose)); + JS::Rooted obj(cx, &objVal.toObject()); + + if (!GetProperty(cx, obj, obj, idAsync, disposeMethod)) { + return false; + } + + // Step 1.b. If method is undefined, then + // GetMethod returns undefined if the function is null but + // since we do not do the conversion here we check for + // null or undefined here. + if (disposeMethod.isNullOrUndefined()) { + // Step 1.b.i. Set method to ? GetMethod(V, @@dispose). + JS::Rooted idSync( + cx, PropertyKey::Symbol(cx->wellKnownSymbols().dispose)); + JS::Rooted syncDisposeMethod(cx); + if (!GetProperty(cx, obj, obj, idSync, &syncDisposeMethod)) { + return false; + } + + if (!syncDisposeMethod.isNullOrUndefined()) { + // Step 1.b.ii. If method is not undefined, then + if (!IsCallable(syncDisposeMethod)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSE_NOT_CALLABLE); + return false; + } + + // Step 1.b.ii.1. Let closure be a new Abstract Closure with no + // parameters that captures method and performs the following steps + // when called: + // Steps 1.b.ii.1.a-f: See SyncDisposalClosure + // Step 1.b.ii.3. Return CreateBuiltinFunction(closure, 0, "", « »). + JS::Handle funName = cx->names().empty_; + JSFunction* asyncWrapper = NewNativeFunction( + cx, SyncDisposalClosure, 0, funName, + gc::AllocKind::FUNCTION_EXTENDED, GenericObject); + if (!asyncWrapper) { + return false; + } + asyncWrapper->initExtendedSlot( + uint8_t(SyncDisposalClosureSlots::Method), syncDisposeMethod); + disposeMethod.set(JS::ObjectValue(*asyncWrapper)); + } + } + + break; + } + + case UsingHint::Sync: { + // Step 2. Else, + // Step 2.a. Let method be ? GetMethod(V, @@dispose). + JS::Rooted id( + cx, PropertyKey::Symbol(cx->wellKnownSymbols().dispose)); + JS::Rooted obj(cx, &objVal.toObject()); + + if (!GetProperty(cx, obj, obj, id, disposeMethod)) { + return false; + } + + break; + } + default: + MOZ_CRASH("Invalid UsingHint"); + } + + // CreateDisposableResource ( V, hint [ , method ] ) + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource + // + // Step 1.b.iii. If method is undefined, throw a TypeError exception. + if (disposeMethod.isNullOrUndefined() || !IsCallable(disposeMethod)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DISPOSE_NOT_CALLABLE); + return false; + } + + return true; +} + +/* static */ ArrayObject* +DisposableStackObjectBase::GetOrCreateDisposeCapability( + JSContext* cx, JS::Handle obj) { + ArrayObject* disposablesList = nullptr; + + if (obj->isDisposableResourceStackEmpty()) { + disposablesList = NewDenseEmptyArray(cx); + if (!disposablesList) { + return nullptr; + } + obj->setReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT, + ObjectValue(*disposablesList)); + } else { + disposablesList = obj->nonEmptyDisposableResourceStack(); + } + + return disposablesList; +} + +bool DisposableStackObjectBase::isDisposableResourceStackEmpty() const { + return getReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT).isUndefined(); +} + +void DisposableStackObjectBase::clearDisposableResourceStack() { + setReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT, JS::UndefinedValue()); +} + +ArrayObject* DisposableStackObjectBase::nonEmptyDisposableResourceStack() + const { + MOZ_ASSERT(!isDisposableResourceStackEmpty()); + return &getReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT) + .toObject() + .as(); +} + +DisposableStackObjectBase::DisposableState DisposableStackObjectBase::state() + const { + return DisposableState(uint8_t(getReservedSlot(STATE_SLOT).toInt32())); +} + +void DisposableStackObjectBase::setState(DisposableState state) { + setReservedSlot(STATE_SLOT, JS::Int32Value(int32_t(state))); +} diff --git a/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.h b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.h new file mode 100644 index 00000000000..af325ac9bc4 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/DisposableStackObjectBase.h @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_DisposableStackObjectBase_h +#define builtin_DisposableStackObjectBase_h + +#include "vm/JSObject.h" +#include "vm/NativeObject.h" +#include "vm/UsingHint.h" + +namespace js { + +enum AdoptClosureSlots { + AdoptClosureSlot_ValueSlot = 0, + AdoptClosureSlot_OnDisposeSlot, +}; + +bool ThrowIfOnDisposeNotCallable(JSContext* cx, + JS::Handle onDispose); + +bool AdoptClosure(JSContext* cx, unsigned argc, JS::Value* vp); + +bool AddDisposableResource(JSContext* cx, + JS::Handle disposeCapability, + JS::Handle val, UsingHint hint); + +bool AddDisposableResource(JSContext* cx, + JS::Handle disposeCapability, + JS::Handle val, UsingHint hint, + JS::Handle methodVal); + +bool CreateDisposableResource(JSContext* cx, JS::Handle objVal, + UsingHint hint, + JS::MutableHandle result); + +bool CreateDisposableResource(JSContext* cx, JS::Handle objVal, + UsingHint hint, JS::Handle methodVal, + JS::MutableHandle result); + +bool GetDisposeMethod(JSContext* cx, JS::Handle obj, UsingHint hint, + JS::MutableHandle disposeMethod); + +// This is a shared base class for common functionality between +// DisposableStackObject and AsyncDisposableStackObject. +class DisposableStackObjectBase : public NativeObject { + public: + enum DisposableState : uint8_t { Pending, Disposed }; + + static constexpr uint32_t DISPOSABLE_RESOURCE_STACK_SLOT = 0; + static constexpr uint32_t STATE_SLOT = 1; + static constexpr uint32_t RESERVED_SLOTS = 2; + + protected: + static ArrayObject* GetOrCreateDisposeCapability( + JSContext* cx, JS::Handle obj); + + bool isDisposableResourceStackEmpty() const; + void clearDisposableResourceStack(); + ArrayObject* nonEmptyDisposableResourceStack() const; + DisposableState state() const; + void setState(DisposableState state); +}; + +} /* namespace js */ + +#endif /* builtin_DisposableStackObjectBase_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/Eval.cpp b/src/third_party/mozjs/extract/js/src/builtin/Eval.cpp index 5fffed2140b..c5257cc3579 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Eval.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Eval.cpp @@ -12,6 +12,7 @@ #include "frontend/BytecodeCompiler.h" // frontend::CompileEvalScript #include "gc/HashUtil.h" #include "js/CompilationAndEvaluation.h" +#include "js/EnvironmentChain.h" // JS::EnvironmentChain #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/friend/JSMEnvironment.h" // JS::NewJSMEnvironment, JS::ExecuteInJSMEnvironment, JS::GetJSMEnvironmentOfScriptedCaller, JS::IsJSMEnvironment #include "js/friend/WindowProxy.h" // js::IsWindowProxy @@ -32,13 +33,10 @@ using namespace js; using mozilla::AddToHash; -using mozilla::HashString; -using mozilla::RangedPtr; using JS::AutoCheckCannotGC; using JS::AutoStableStringChars; using JS::CompileOptions; -using JS::SourceOwnership; using JS::SourceText; // We should be able to assert this for *any* fp->environmentChain(). @@ -237,24 +235,45 @@ static bool EvalKernel(JSContext* cx, HandleValue v, EvalType evalType, jsbytecode* pc, MutableHandleValue vp) { MOZ_ASSERT((evalType == INDIRECT_EVAL) == !caller); MOZ_ASSERT((evalType == INDIRECT_EVAL) == !pc); - MOZ_ASSERT_IF(evalType == INDIRECT_EVAL, IsGlobalLexicalEnvironment(env)); + MOZ_ASSERT_IF(evalType == INDIRECT_EVAL, + env->is()); AssertInnerizedEnvironmentChain(cx, *env); - // Step 2. - if (!v.isString()) { + // "Dynamic Code Brand Checks" adds support for Object values. + // https://tc39.es/proposal-dynamic-code-brand-checks/#sec-performeval + // Steps 2-4. + RootedString str(cx); + if (v.isString()) { + str = v.toString(); + } else if (v.isObject()) { + RootedObject obj(cx, &v.toObject()); + if (!cx->getCodeForEval(obj, &str)) { + return false; + } + } + if (!str) { vp.set(v); return true; } - // Steps 3-4. - RootedString str(cx, v.toString()); - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, str)) { + // Steps 6-8. + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled( + JS::RuntimeCode::JS, str, + evalType == DIRECT_EVAL ? JS::CompilationType::DirectEval + : JS::CompilationType::IndirectEval, + parameterStrings, str, parameterArgs, v, &canCompileStrings)) { + return false; + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL); return false; } - // Step 5 ff. + // Step 9 ff. // Per ES5, indirect eval runs in the global scope. (eval is specified this // way so that the compiler can make assumptions about what bindings may or @@ -406,18 +425,20 @@ static bool ExecuteInExtensibleLexicalEnvironment( JS_PUBLIC_API bool js::ExecuteInFrameScriptEnvironment( JSContext* cx, HandleObject objArg, HandleScript scriptArg, MutableHandleObject envArg) { - RootedObject varEnv(cx, NonSyntacticVariablesObject::create(cx)); + Rooted varEnv( + cx, NonSyntacticVariablesObject::create(cx)); if (!varEnv) { return false; } - RootedObjectVector envChain(cx); + JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No); if (!envChain.append(objArg)) { return false; } - RootedObject env(cx); - if (!js::CreateObjectsForEnvironmentChain(cx, envChain, varEnv, &env)) { + Rooted env( + cx, js::CreateObjectsForEnvironmentChain(cx, envChain, varEnv)); + if (!env) { return false; } @@ -428,8 +449,7 @@ JS_PUBLIC_API bool js::ExecuteInFrameScriptEnvironment( // to |this|, and will fail if it is not bound to a message manager. ObjectRealm& realm = ObjectRealm::get(varEnv); Rooted lexicalEnv( - cx, - realm.getOrCreateNonSyntacticLexicalEnvironment(cx, env, varEnv, objArg)); + cx, realm.getOrCreateNonSyntacticLexicalEnvironment(cx, env, varEnv)); if (!lexicalEnv) { return false; } @@ -443,7 +463,8 @@ JS_PUBLIC_API bool js::ExecuteInFrameScriptEnvironment( } JS_PUBLIC_API JSObject* JS::NewJSMEnvironment(JSContext* cx) { - RootedObject varEnv(cx, NonSyntacticVariablesObject::create(cx)); + Rooted varEnv( + cx, NonSyntacticVariablesObject::create(cx)); if (!varEnv) { return nullptr; } @@ -461,14 +482,13 @@ JS_PUBLIC_API JSObject* JS::NewJSMEnvironment(JSContext* cx) { JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx, HandleScript scriptArg, HandleObject varEnv) { - RootedObjectVector emptyChain(cx); + JS::EnvironmentChain emptyChain(cx, JS::SupportUnscopables::No); return ExecuteInJSMEnvironment(cx, scriptArg, varEnv, emptyChain); } -JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx, - HandleScript scriptArg, - HandleObject varEnv, - HandleObjectVector targetObj) { +JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment( + JSContext* cx, HandleScript scriptArg, HandleObject varEnv, + const EnvironmentChain& targetObj) { cx->check(varEnv); MOZ_ASSERT( ObjectRealm::get(varEnv).getNonSyntacticLexicalEnvironment(varEnv)); @@ -481,7 +501,7 @@ JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx, // them to the environment. These are added after the NSVO environment. if (!targetObj.empty()) { // The environment chain will be as follows: - // GlobalObject / BackstagePass + // GlobalObject / SystemGlobal // GlobalLexicalEnvironmentObject[this=global] // NonSyntacticVariablesObject (the JSMEnvironment) // NonSyntacticLexicalEnvironmentObject[this=nsvo] @@ -491,8 +511,9 @@ JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx, // (*) This environment intercepts JSOp::GlobalThis. // Wrap the target objects in WithEnvironments. - RootedObject envChain(cx); - if (!js::CreateObjectsForEnvironmentChain(cx, targetObj, env, &envChain)) { + Rooted envChain( + cx, js::CreateObjectsForEnvironmentChain(cx, targetObj, env)); + if (!envChain) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.cpp index 194b858ea9b..0d8481e5caf 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.cpp @@ -26,7 +26,9 @@ using namespace js; // FinalizationRecordObject const JSClass FinalizationRecordObject::class_ = { - "FinalizationRecord", JSCLASS_HAS_RESERVED_SLOTS(SlotCount)}; + "FinalizationRecord", + JSCLASS_HAS_RESERVED_SLOTS(SlotCount), +}; /* static */ FinalizationRecordObject* FinalizationRecordObject::create( @@ -86,7 +88,9 @@ void FinalizationRecordObject::clear() { const JSClass FinalizationRegistrationsObject::class_ = { "FinalizationRegistrations", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_BACKGROUND_FINALIZE, - &classOps_, JS_NULL_CLASS_SPEC}; + &classOps_, + JS_NULL_CLASS_SPEC, +}; const JSClassOps FinalizationRegistrationsObject::classOps_ = { nullptr, // addProperty @@ -193,12 +197,16 @@ const JSClass FinalizationRegistryObject::class_ = { "FinalizationRegistry", JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationRegistry) | JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_FOREGROUND_FINALIZE, - &classOps_, &classSpec_}; + &classOps_, + &classSpec_, +}; const JSClass FinalizationRegistryObject::protoClass_ = { "FinalizationRegistry.prototype", - JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationRegistry), JS_NULL_CLASS_OPS, - &classSpec_}; + JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationRegistry), + JS_NULL_CLASS_OPS, + &classSpec_, +}; const JSClassOps FinalizationRegistryObject::classOps_ = { nullptr, // addProperty @@ -219,15 +227,20 @@ const ClassSpec FinalizationRegistryObject::classSpec_ = { nullptr, nullptr, methods_, - properties_}; + properties_, +}; const JSFunctionSpec FinalizationRegistryObject::methods_[] = { - JS_FN("register", register_, 2, 0), JS_FN("unregister", unregister, 1, 0), - JS_FN("cleanupSome", cleanupSome, 0, 0), JS_FS_END}; + JS_FN("register", register_, 2, 0), + JS_FN("unregister", unregister, 1, 0), + JS_FN("cleanupSome", cleanupSome, 0, 0), + JS_FS_END, +}; const JSPropertySpec FinalizationRegistryObject::properties_[] = { JS_STRING_SYM_PS(toStringTag, "FinalizationRegistry", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; /* static */ bool FinalizationRegistryObject::construct(JSContext* cx, unsigned argc, @@ -299,10 +312,9 @@ void FinalizationRegistryObject::traceWeak(JSTracer* trc) { // are weakly held. MOZ_ASSERT(registrations()); - for (ObjectValueWeakMap::Enum e(registrations()->valueMap()); !e.empty(); - e.popFront()) { + for (ObjectWeakMap::Enum e(*registrations()); !e.empty(); e.popFront()) { auto* registrations = - &e.front().value().toObject().as(); + &e.front().value()->as(); if (!registrations->traceWeak(trc)) { e.removeFront(); } @@ -475,12 +487,13 @@ bool FinalizationRegistryObject::addRegistration( auto& map = *registry->registrations(); Rooted recordsObject(cx); - JSObject* obj = map.lookup(unregisterToken); + JSObject* obj = map.get(unregisterToken); if (obj) { recordsObject = &obj->as(); } else { recordsObject = FinalizationRegistrationsObject::create(cx); - if (!recordsObject || !map.add(cx, unregisterToken, recordsObject)) { + if (!recordsObject || !map.put(unregisterToken, recordsObject)) { + ReportOutOfMemory(cx); return false; } } @@ -505,7 +518,7 @@ bool FinalizationRegistryObject::addRegistration( JS::AutoAssertNoGC nogc; auto& map = *registry->registrations(); - JSObject* obj = map.lookup(unregisterToken); + JSObject* obj = map.get(unregisterToken); MOZ_ASSERT(obj); auto records = &obj->as(); records->remove(record); @@ -557,7 +570,7 @@ bool FinalizationRegistryObject::unregister(JSContext* cx, unsigned argc, // i. Remove cell from finalizationRegistry.[[Cells]]. // ii. Set removed to true. - RootedObject obj(cx, registry->registrations()->lookup(unregisterToken)); + RootedObject obj(cx, registry->registrations()->get(unregisterToken)); if (obj) { auto* records = obj->as().records(); MOZ_ASSERT(records); @@ -636,7 +649,8 @@ bool FinalizationRegistryObject::cleanupSome(JSContext* cx, unsigned argc, const JSClass FinalizationQueueObject::class_ = { "FinalizationQueue", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_FOREGROUND_FINALIZE, - &classOps_}; + &classOps_, +}; const JSClassOps FinalizationQueueObject::classOps_ = { nullptr, // addProperty @@ -674,8 +688,8 @@ FinalizationQueueObject* FinalizationQueueObject::create( // you don't know how far to unwrap it to get the original object // back. Instead store a CCW to a plain object in the same compartment as the // global (this uses Object.prototype). - RootedObject incumbentObject(cx); - if (!GetObjectFromIncumbentGlobal(cx, &incumbentObject) || !incumbentObject) { + Rooted hostDefinedData(cx); + if (!GetObjectFromHostDefinedData(cx, &hostDefinedData)) { return nullptr; } @@ -686,7 +700,8 @@ FinalizationQueueObject* FinalizationQueueObject::create( } queue->initReservedSlot(CleanupCallbackSlot, ObjectValue(*cleanupCallback)); - queue->initReservedSlot(IncumbentObjectSlot, ObjectValue(*incumbentObject)); + queue->initReservedSlot(HostDefinedDataSlot, + JS::ObjectOrNullValue(hostDefinedData)); InitReservedSlot(queue, RecordsToBeCleanedUpSlot, recordsToBeCleanedUp.release(), MemoryUse::FinalizationRegistryRecordVector); @@ -740,12 +755,12 @@ inline JSObject* FinalizationQueueObject::cleanupCallback() const { return &value.toObject(); } -JSObject* FinalizationQueueObject::incumbentObject() const { - Value value = getReservedSlot(IncumbentObjectSlot); +JSObject* FinalizationQueueObject::getHostDefinedData() const { + Value value = getReservedSlot(HostDefinedDataSlot); if (value.isUndefined()) { return nullptr; } - return &value.toObject(); + return value.toObjectOrNull(); } FinalizationRecordVector* FinalizationQueueObject::recordsToBeCleanedUp() diff --git a/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.h b/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.h index 288ebea424c..cd1bdb75c69 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/FinalizationRegistryObject.h @@ -87,6 +87,7 @@ #define builtin_FinalizationRegistryObject_h #include "gc/Barrier.h" +#include "gc/WeakMap.h" #include "js/GCVector.h" #include "vm/NativeObject.h" @@ -95,7 +96,6 @@ namespace js { class FinalizationRegistryObject; class FinalizationRecordObject; class FinalizationQueueObject; -class ObjectWeakMap; using HandleFinalizationRegistryObject = Handle; using HandleFinalizationRecordObject = Handle; @@ -226,7 +226,7 @@ class FinalizationRegistryObject : public NativeObject { class FinalizationQueueObject : public NativeObject { enum { CleanupCallbackSlot = 0, - IncumbentObjectSlot, + HostDefinedDataSlot, RecordsToBeCleanedUpSlot, IsQueuedForCleanupSlot, DoCleanupFunctionSlot, @@ -242,7 +242,7 @@ class FinalizationQueueObject : public NativeObject { static const JSClass class_; JSObject* cleanupCallback() const; - JSObject* incumbentObject() const; + JSObject* getHostDefinedData() const; FinalizationRecordVector* recordsToBeCleanedUp() const; bool isQueuedForCleanup() const; JSFunction* doCleanupFunction() const; diff --git a/src/third_party/mozjs/extract/js/src/builtin/Iterator.js b/src/third_party/mozjs/extract/js/src/builtin/Iterator.js index 0cc6cebf18b..9fb506e92c8 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Iterator.js +++ b/src/third_party/mozjs/extract/js/src/builtin/Iterator.js @@ -13,10 +13,10 @@ function IteratorNext(iteratorRecord, value) { ArgumentsLength() < 2 ? callContentFunction(iteratorRecord.nextMethod, iteratorRecord.iterator) : callContentFunction( - iteratorRecord.nextMethod, - iteratorRecord.iterator, - value - ); + iteratorRecord.nextMethod, + iteratorRecord.iterator, + value + ); // Step 3. if (!IsObject(result)) { ThrowTypeError(JSMSG_OBJECT_REQUIRED, result); @@ -216,6 +216,29 @@ function WrapForValidIteratorReturn() { return callContentFunction(returnMethod, iterator); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +/** + * Explicit Resource Management Proposal + * 27.1.2.1 %IteratorPrototype% [ @@dispose ] ( ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25iteratorprototype%25-%40%40dispose + */ +function IteratorDispose() { + // Step 1. Let O be the this value. + var O = this; + + // Step 2. Let return be ? GetMethod(O, "return"). + var returnMethod = GetMethod(O, "return"); + + // Step 3. If return is not undefined, then + if (returnMethod !== undefined) { + // Step 3.a. Perform ? Call(return, O, « »). + callContentFunction(returnMethod, O); + } + + // Step 4. Return NormalCompletion(empty). (implicit) +} +#endif + /** * %IteratorHelperPrototype%.next ( ) * @@ -939,3 +962,351 @@ function IteratorFind(predicate) { } } } + +#ifdef NIGHTLY_BUILD +/** + * Iterator.concat ( ...items ) + * + * https://tc39.es/proposal-iterator-sequencing/ + */ +function IteratorConcat() { + // Step 1. + // + // Stored in reversed order to simplify removing processed items. + var index = ArgumentsLength() * 2; + var iterables = std_Array(index); + + // Step 2. + for (var i = 0; i < ArgumentsLength(); i++) { + var item = GetArgument(i); + + // Step 2.a. + if (!IsObject(item)) { + ThrowTypeError(JSMSG_OBJECT_REQUIRED, typeof item); + } + + // Step 2.b. (Inlined GetMethod) + var method = item[GetBuiltinSymbol("iterator")]; + + // Step 2.c. + if (!IsCallable(method)) { + ThrowTypeError(JSMSG_NOT_ITERABLE, ToSource(item)); + } + + // Step 2.d. + DefineDataProperty(iterables, --index, item); + DefineDataProperty(iterables, --index, method); + } + assert(index === 0, "all items stored"); + + // Steps 3-5. + var result = NewIteratorHelper(); + var generator = IteratorConcatGenerator(iterables); + UnsafeSetReservedSlot( + result, + ITERATOR_HELPER_GENERATOR_SLOT, + generator + ); + + // Step 6. + return result; +} + +/** + * Iterator.concat ( ...items ) + * + * https://tc39.es/proposal-iterator-sequencing/ + */ +function* IteratorConcatGenerator(iterables) { + assert(IsArray(iterables), "iterables is an array"); + assert(iterables.length % 2 === 0, "iterables contains pairs (item, method)"); + + // Step 3.a. + for (var i = iterables.length; i > 0;) { + var item = iterables[--i]; + var method = iterables[--i]; + + // Remove processed items to avoid keeping them alive. + iterables.length -= 2; + + // Steps 3.a.i-v. + for (var innerValue of allowContentIterWith(item, method)) { + // Steps 3.a.v.1-3. (Implicit through for-of loop) + + yield innerValue; + } + } +} + +/** + * Iterator.zip (iterables [, options]) + * + * https://tc39.es/proposal-joint-iteration/#sec-iterator.zip + */ +function IteratorZip(predicate) { + return false; +} + +/** + * Iterator.zipKeyed ( iterables [, options] ) + * + * https://tc39.es/proposal-joint-iteration/#sec-iterator.zipkeyed + */ +function IteratorZipKeyed(predicate) { + return false; +} + + +/** + * CreateNumericRangeIterator (start, end, optionOrStep, type) + * Step 18 + * + * https://tc39.es/proposal-iterator.range/#sec-create-numeric-range-iterator + */ +function IteratorRangeNext() { + var obj = this; + // Step 18. Let closure be a new Abstract Closure with no parameters + // that captures start, end, step, inclusiveEnd, zero, one and performs the following steps when called: + + if (!IsObject(obj) || (obj = GuardToIteratorRange(obj)) === null) { + return callFunction( + CallIteratorRangeMethodIfWrapped, + this, + "IteratorRangeNext" + ); + } + + // Retrieve values from reserved slots + var start = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_START); + var end = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_END); + var step = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_STEP); + var inclusiveEnd = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_INCLUSIVE_END); + var zero = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_ZERO); + var one = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_ONE); + var currentCount = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_CURRENT_COUNT); + + // Step 18.a: If end > start, let ifIncrease be true + // Step 18.b: Else let ifIncrease be false + var ifIncrease = end > start; + + // Step 18.c: If step > zero, let ifStepIncrease be true + // Step 18.d: Else let ifStepIncrease be false + var ifStepIncrease = step > zero; + + // Step 18.e: If ifIncrease is not ifStepIncrease, return undefined. + if (ifIncrease !== ifStepIncrease) { + return { value: undefined, done: true }; + } + + // Step 18.f: Let hitsEnd be false + var hitsEnd = false; + + // Step 18.g: Let currentCount be zero (already handled via slots) + + // Step 18.i.i: Let currentYieldingValue be start + (step × currentCount) + var currentYieldingValue = start + (step * currentCount); + + // Step 18.i.ii: If currentYieldingValue is equal to end, set hitsEnd to true + hitsEnd = currentYieldingValue === end && !inclusiveEnd; + + + // Step 18.i.iii: Set currentCount to currentCount + one + currentCount = currentCount + one; + + // Step 18.i.iv: If ifIncrease is true, then + if (ifIncrease) { + // Step 18.i.iv.1: If inclusiveEnd is true, then + if (inclusiveEnd) { + // Step 18.i.iv.1.a: If currentYieldingValue > end, return undefined. + if (currentYieldingValue > end) { + return { value: undefined, done: true }; + } + } else { + // Step 18.i.iv.2: If currentYieldingValue >= end, return undefined + if (currentYieldingValue >= end) { + return { value: undefined, done: true }; + } + } + } else { + // Step 18.i.v: Else + // Step 18.i.v.1: If inclusiveEnd is true, then + if (inclusiveEnd) { + //Step 18.i.v.1.a.a. If end > currentYieldingValue, return undefined. + if (end > currentYieldingValue) { + return { value: undefined, done: true }; + } + } else { + // Step 18.i.v.2: Else + if (end >= currentYieldingValue) { + // Step 18i.v.2.a: If end >= currentYieldingValue, return undefined + return { value: undefined, done: true }; + } + } + } + + // Step 18.i.vi: Yield currentYieldingValue + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_CURRENT_COUNT, currentCount); + + // Step 18.j: Return undefined if the loop completes + if (hitsEnd) { + return { value: undefined, done: true }; + } + + // Return the current value + return { value: currentYieldingValue, done: false }; +} + + + +/** + * CreateNumericRangeIterator (start, end, optionOrStep, type) + * + * https://tc39.es/proposal-iterator.range/#sec-create-numeric-range-iterator + */ +function CreateNumericRangeIterator(start, end, optionOrStep, isNumberRange) { + + // Step 1: If start is NaN, throw a RangeError exception. + if (isNumberRange && Number_isNaN(start)) { + ThrowRangeError(JSMSG_ITERATOR_RANGE_INVALID_START_RANGEERR); + } + + // Step 2: If end is NaN, throw a RangeError exception. + if (isNumberRange && Number_isNaN(end)) { + ThrowRangeError(JSMSG_ITERATOR_RANGE_INVALID_END_RANGEERR); + } + + // Step 3: If type is NUMBER-RANGE, then + if (isNumberRange) { + // Step 3.a. Assert: start is a Number. + assert(typeof start === 'number', "The 'start' argument must be a number"); + + // Step 3.b. If end is not a Number, throw a TypeError exception. + if (typeof end !== 'number') { + ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_END); + } + + // Step 3.c. Let zero be 0ℤ. + var zero = 0; + + // Step 3.d. Let one be 1ℤ. + var one = 1; + // 4: Else, + } else { + // 4.a. Assert: start is a BigInt. + assert(typeof start === 'bigint', "The 'start' argument must be a bigint"); + + // 4.b. If end is not +∞𝔽 or -∞𝔽 and end is not a BigInt, throw a TypeError exception. + if (typeof end !== 'bigint' && !(Number_isFinite(end))) { + ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_END); + } + + // 4.c. Let zero be 0𝔽. + var zero = 0n; + + // 4.d. Let one be 1𝔽. + var one = 1n; + } + // Step 5: If start is +∞ or -∞, throw a RangeError exception. + if (typeof start === 'number' && !Number_isFinite(start)) { + ThrowRangeError(JSMSG_ITERATOR_RANGE_START_INFINITY); + } + // Step 6: Let inclusiveEnd be false. + var inclusiveEnd = false; + + // Step 7: If optionOrStep is undefined or null, then + // Step 7.a. Let step be undefined. + var step; + + // Step 8: Else if optionOrStep is an Object, then + if (optionOrStep !== null && typeof optionOrStep === 'object') { + // Step 8.a. Let step be ? Get(optionOrStep, "step"). + step = optionOrStep.step; + + // Step 8.b. Set inclusiveEnd to ToBoolean(? Get(optionOrStep, "inclusive")). + inclusiveEnd = ToBoolean(optionOrStep.inclusiveEnd); + } + // Step 9: Else if type is NUMBER-RANGE and optionOrStep is a Number, then + else if (isNumberRange && typeof optionOrStep === 'number') { + // Step 9.a. Let step be optionOrStep. + step = optionOrStep; + } + + // Step 10: Else if type is BIGINT-RANGE and optionOrStep is a BigInt, then + // Step 10.a. Let step be optionOrStep. + else if (!isNumberRange && typeof optionOrStep === 'bigint') { + step = optionOrStep; + } + // Step 11: Else, throw a TypeError exception. + else if (optionOrStep !== undefined && optionOrStep !== null) { + ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_STEP); + } + + // Step 12: If step is undefined or null, then + if (step === undefined || step === null) { + // Step 12.a. If end > start, let step be one. + // Step 12.b. Else let step be -one. + step = end > start ? one : -one; + } + + // Step 13: If step is NaN, throw a RangeError exception. + if (typeof step === "number" && Number_isNaN(step)) { + ThrowRangeError(JSMSG_ITERATOR_RANGE_STEP_NAN); + } + + // Step 14: If type is NUMBER-RANGE and step is not a Number, throw a TypeError exception. + if (isNumberRange && typeof step !== 'number') { + ThrowTypeError(JSMSG_ITERATOR_RANGE_STEP_NOT_NUMBER); + } + + // Step 15: Else if type is BIGINT-RANGE and step is not a BigInt, throw a TypeError exception + else if (!isNumberRange && typeof step !== 'bigint') { + ThrowTypeError(JSMSG_ITERATOR_RANGE_STEP_NOT_BIGINT); + } + + // Step 16: If step is +∞ or -∞, throw a RangeError exception. + if (typeof step === 'number' && !Number_isFinite(step)) { + ThrowRangeError(JSMSG_ITERATOR_RANGE_STEP_NOT_FINITE); + } + + // Step 17: If step is zero and start is not end, throw a RangeError exception. + if (step === zero && start !== end) { + ThrowRangeError(JSMSG_ITERATOR_RANGE_STEP_ZERO); + } + // Step 19: Return CreateIteratorFromClosure(closure, "%NumericRangeIteratorPrototype%", %NumericRangeIteratorPrototype%). + + var obj = NewIteratorRange(); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_START, start); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_END, end); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_STEP, step); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_INCLUSIVE_END, inclusiveEnd); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_ZERO, zero); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_ONE, one); + UnsafeSetReservedSlot(obj, ITERATOR_RANGE_SLOT_CURRENT_COUNT, zero); + + return obj; +} + + + +/** + * Iterator.range ( start, end, optionOrStep ) + * + * https://tc39.es/proposal-iterator.range/#sec-iterator.range + */ +function IteratorRange(start, end, optionOrStep) { + + // Step 1. If start is a Number, return ? CreateNumericRangeIterator(start, end, optionOrStep, NUMBER-RANGE) + if (typeof start === 'number') { + return CreateNumericRangeIterator(start, end, optionOrStep, true); + } + + // Step 2. If start is a BigInt, return ? CreateNumericRangeIterator(start, end, optionOrStep, BIGINT-RANGE) + if (typeof start === 'bigint') { + return CreateNumericRangeIterator(start, end, optionOrStep, false); + } + + // Step 3. Throw a TypeError exception. + ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_START); + +} +#endif diff --git a/src/third_party/mozjs/extract/js/src/builtin/JSON.cpp b/src/third_party/mozjs/extract/js/src/builtin/JSON.cpp index 14235959373..e92e43af24e 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/JSON.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/JSON.cpp @@ -25,11 +25,12 @@ #include "js/friend/StackLimits.h" // js::AutoCheckRecursionLimit #include "js/Object.h" // JS::GetBuiltinClass #include "js/Prefs.h" // JS::Prefs +#include "js/ProfilingCategory.h" #include "js/PropertySpec.h" #include "js/StableStringChars.h" #include "js/TypeDecls.h" #include "js/Value.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/BooleanObject.h" // js::BooleanObject #include "vm/EqualityOperations.h" // js::SameValue #include "vm/Interpreter.h" @@ -42,12 +43,6 @@ #include "vm/NumberObject.h" // js::NumberObject #include "vm/PlainObject.h" // js::PlainObject #include "vm/StringObject.h" // js::StringObject -#ifdef ENABLE_RECORD_TUPLE -# include "builtin/RecordObject.h" -# include "builtin/TupleObject.h" -# include "vm/RecordType.h" -#endif - #include "builtin/Array-inl.h" #include "vm/GeckoProfiler-inl.h" #include "vm/JSAtomUtils-inl.h" // AtomToId, PrimitiveValueToId, IndexToId, IdToString, @@ -159,7 +154,7 @@ static MOZ_ALWAYS_INLINE RangedPtr InfallibleQuoteJSONString( template static size_t QuoteJSONStringHelper(const JSLinearString& linear, - StringBuffer& sb, size_t sbOffset) { + StringBuilder& sb, size_t sbOffset) { size_t len = linear.length(); JS::AutoCheckCannotGC nogc; @@ -172,7 +167,7 @@ static size_t QuoteJSONStringHelper(const JSLinearString& linear, return dstEnd - dstBegin; } -static bool QuoteJSONString(JSContext* cx, StringBuffer& sb, JSString* str) { +static bool QuoteJSONString(JSContext* cx, StringBuilder& sb, JSString* str) { JSLinearString* linear = str->ensureLinear(cx); if (!linear) { return false; @@ -223,7 +218,7 @@ using ObjectVector = GCVector; class StringifyContext { public: - StringifyContext(JSContext* cx, StringBuffer& sb, const StringBuffer& gap, + StringifyContext(JSContext* cx, StringBuilder& sb, const StringBuilder& gap, HandleObject replacer, const RootedIdVector& propertyList, bool maybeSafely) : sb(sb), @@ -237,8 +232,8 @@ class StringifyContext { MOZ_ASSERT_IF(maybeSafely, gap.empty()); } - StringBuffer& sb; - const StringBuffer& gap; + StringBuilder& sb; + const StringBuilder& gap; RootedObject replacer; Rooted stack; const RootedIdVector& propertyList; @@ -383,9 +378,7 @@ static bool PreprocessValue(JSContext* cx, HandleObject holder, KeyType key, return false; } vp.setString(str); - } else if (cls == ESClass::Boolean || cls == ESClass::BigInt || - IF_RECORD_TUPLE( - obj->is() || obj->is(), false)) { + } else if (cls == ESClass::Boolean || cls == ESClass::BigInt) { if (!Unbox(cx, obj, vp)) { return false; } @@ -440,19 +433,17 @@ class CycleDetector { }; static inline JSString* MaybeGetRawJSON(JSContext* cx, JSObject* obj) { - if (!obj->is()) { + auto* unwrappedObj = obj->maybeUnwrapIf(); + if (!unwrappedObj) { return nullptr; } + JSAutoRealm ar(cx, unwrappedObj); - JSString* rawJSON = obj->as().rawJSON(cx); + JSString* rawJSON = unwrappedObj->rawJSON(cx); MOZ_ASSERT(rawJSON); return rawJSON; } -#ifdef ENABLE_RECORD_TUPLE -enum class JOType { Record, Object }; -template -#endif /* https://262.ecma-international.org/14.0/#sec-serializejsonobject */ static bool SerializeJSONObject(JSContext* cx, HandleObject obj, StringifyContext* scx) { @@ -466,16 +457,6 @@ static bool SerializeJSONObject(JSContext* cx, HandleObject obj, * this algorithm (and in SerializeJSONArray as well). */ -#ifdef ENABLE_RECORD_TUPLE - RecordType* rec; - - if constexpr (type == JOType::Record) { - MOZ_ASSERT(obj->is()); - rec = &obj->as(); - } else { - MOZ_ASSERT(!IsExtendedPrimitive(*obj)); - } -#endif MOZ_ASSERT_IF(scx->maybeSafely, obj->is()); /* Steps 1-2, 11. */ @@ -538,18 +519,13 @@ static bool SerializeJSONObject(JSContext* cx, HandleObject obj, prop.propertyInfo().isDataDescriptor()); } #endif // DEBUG - -#ifdef ENABLE_RECORD_TUPLE - if constexpr (type == JOType::Record) { - MOZ_ALWAYS_TRUE(rec->getOwnProperty(cx, id, &outputValue)); - } else -#endif { RootedValue objValue(cx, ObjectValue(*obj)); if (!GetProperty(cx, obj, objValue, id, &outputValue)) { return false; } } + if (!PreprocessValue(cx, obj, HandleId(id), &outputValue, scx)) { return false; } @@ -596,12 +572,6 @@ static MOZ_ALWAYS_INLINE bool GetLengthPropertyForArrayLike(JSContext* cx, *lengthp = obj->as().length(); return true; } -#ifdef ENABLE_RECORD_TUPLE - if (obj->is()) { - *lengthp = obj->as().length(); - return true; - } -#endif MOZ_ASSERT(obj->is()); @@ -777,7 +747,7 @@ static bool SerializeJSONProperty(JSContext* cx, const Value& v, } } - return NumberValueToStringBuffer(v, scx->sb); + return NumberValueToStringBuilder(v, scx->sb); } /* Step 10. */ @@ -793,8 +763,8 @@ static bool SerializeJSONProperty(JSContext* cx, const Value& v, } /* Step 11. */ - MOZ_ASSERT(v.hasObjectPayload()); - RootedObject obj(cx, &v.getObjectPayload()); + MOZ_ASSERT(v.isObject()); + RootedObject obj(cx, &v.toObject()); /* https://tc39.es/proposal-json-parse-with-source/#sec-serializejsonproperty * Step 4a.*/ @@ -810,18 +780,6 @@ static bool SerializeJSONProperty(JSContext* cx, const Value& v, scx->depth++; auto dec = mozilla::MakeScopeExit([&] { scx->depth--; }); -#ifdef ENABLE_RECORD_TUPLE - if (v.isExtendedPrimitive()) { - if (obj->is()) { - return SerializeJSONObject(cx, obj, scx); - } - if (obj->is()) { - return SerializeJSONArray(cx, obj, scx); - } - MOZ_CRASH("Unexpected extended primitive - boxes cannot be stringified."); - } -#endif - bool isArray; if (!IsArray(cx, obj, &isArray)) { return false; @@ -855,12 +813,6 @@ static bool CanFastStringifyObject(NativeObject* obj) { // JSON.stringify. MOZ_ASSERT(!obj->getOpsLookupProperty()); -#ifdef ENABLE_RECORD_TUPLE - if (ObjectValue(*obj).isExtendedPrimitive()) { - return false; - } -#endif - return true; } @@ -1087,7 +1039,7 @@ class OwnNonIndexKeysIterForJSON { }; // Steps from https://262.ecma-international.org/14.0/#sec-serializejsonproperty -static bool EmitSimpleValue(JSContext* cx, StringBuffer& sb, const Value& v) { +static bool EmitSimpleValue(JSContext* cx, StringBuilder& sb, const Value& v) { /* Step 8. */ if (v.isString()) { return QuoteJSONString(cx, sb, v.toString()); @@ -1111,7 +1063,7 @@ static bool EmitSimpleValue(JSContext* cx, StringBuffer& sb, const Value& v) { } } - return NumberValueToStringBuffer(v, sb); + return NumberValueToStringBuilder(v, sb); } // Unrepresentable values. @@ -1126,7 +1078,7 @@ static bool EmitSimpleValue(JSContext* cx, StringBuffer& sb, const Value& v) { // https://262.ecma-international.org/14.0/#sec-serializejsonproperty step 8b // where K is an integer index. -static bool EmitQuotedIndexColon(StringBuffer& sb, uint32_t index) { +static bool EmitQuotedIndexColon(StringBuilder& sb, uint32_t index) { Int32ToCStringBuf cbuf; size_t cstrlen; const char* cstr = ::Int32ToCString(&cbuf, index, &cstrlen); @@ -1184,9 +1136,7 @@ static bool PreprocessFastValue(JSContext* cx, Value* vp, StringifyContext* scx, // Step 4: convert primitive wrapper objects to primitives. Disallowed for // fast path. if (obj->is() || obj->is() || - obj->is() || obj->is() || - IF_RECORD_TUPLE(obj->is() || obj->is(), - false)) { + obj->is() || obj->is()) { // Primitive wrapper objects can invoke arbitrary code when being coerced to // their primitive values (eg via @@toStringTag). *whySlow = BailReason::INELIGIBLE_OBJECT; @@ -1507,7 +1457,7 @@ static bool FastSerializeJSONProperty(JSContext* cx, Handle v, /* https://262.ecma-international.org/14.0/#sec-json.stringify */ bool js::Stringify(JSContext* cx, MutableHandleValue vp, JSObject* replacer_, - const Value& space_, StringBuffer& sb, + const Value& space_, StringBuilder& sb, StringifyBehavior stringifyBehavior) { RootedObject replacer(cx, replacer_); RootedValue space(cx, space_); @@ -1633,7 +1583,7 @@ bool js::Stringify(JSContext* cx, MutableHandleValue vp, JSObject* replacer_, } } - StringBuffer gap(cx); + StringBuilder gap(cx); if (space.isNumber()) { /* Step 7. */ @@ -1742,7 +1692,7 @@ bool js::Stringify(JSContext* cx, MutableHandleValue vp, JSObject* replacer_, if (fastJSON != slowJSON) { MOZ_CRASH("JSON.stringify mismatch between fast and slow paths"); } - // Put the JSON back into the StringBuffer for returning. + // Put the JSON back into the StringBuilder for returning. if (!sb.append(slowJSON)) { return false; } @@ -1752,9 +1702,10 @@ bool js::Stringify(JSContext* cx, MutableHandleValue vp, JSObject* replacer_, } /* https://262.ecma-international.org/14.0/#sec-internalizejsonproperty */ -static bool InternalizeJSONProperty( - JSContext* cx, HandleObject holder, HandleId name, HandleValue reviver, - MutableHandle parseRecord, MutableHandleValue vp) { +static bool InternalizeJSONProperty(JSContext* cx, HandleObject holder, + HandleId name, HandleValue reviver, + Handle parseRecord, + MutableHandleValue vp) { AutoCheckRecursionLimit recursion(cx); if (!recursion.check(cx)) { return false; @@ -1766,31 +1717,32 @@ static bool InternalizeJSONProperty( return false; } -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE RootedObject context(cx); - Rooted> entries(cx); + Rooted entries(cx); if (JS::Prefs::experimental_json_parse_with_source()) { // https://tc39.es/proposal-json-parse-with-source/#sec-internalizejsonproperty - bool sameVal = false; - Rooted parsedValue(cx, parseRecord.get().value); - if (!SameValue(cx, parsedValue, val, &sameVal)) { - return false; - } - if (!parseRecord.get().isEmpty() && sameVal) { - if (parseRecord.get().parseNode) { - MOZ_ASSERT(!val.isObject()); - Rooted props(cx, cx); - if (!props.emplaceBack( - IdValuePair(NameToId(cx->names().source), - StringValue(parseRecord.get().parseNode)))) { - return false; - } - context = NewPlainObjectWithUniqueNames(cx, props); - if (!context) { - return false; - } + if (parseRecord) { + bool sameVal = false; + Rooted parsedValue(cx, parseRecord->getValue()); + if (!SameValue(cx, parsedValue, val, &sameVal)) { + return false; + } + if (parseRecord->hasValue() && sameVal) { + if (parseRecord->getParseNode()) { + MOZ_ASSERT(!val.isObject()); + Rooted props(cx, cx); + if (!props.emplaceBack( + IdValuePair(NameToId(cx->names().source), + StringValue(parseRecord->getParseNode())))) { + return false; + } + context = NewPlainObjectWithUniqueNames(cx, props); + if (!context) { + return false; + } + } + parseRecord->getEntries(cx, &entries); } - entries = std::move(parseRecord.get().entries); } if (!context) { context = NewPlainObject(cx); @@ -1799,7 +1751,6 @@ static bool InternalizeJSONProperty( } } } -#endif /* Step 2. */ if (val.isObject()) { @@ -1830,15 +1781,17 @@ static bool InternalizeJSONProperty( } /* Step 2a(iii)(1). */ - Rooted elementRecord(cx); -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE + Rooted elementRecord(cx); if (entries) { - if (auto entry = entries->lookup(id)) { - elementRecord = std::move(entry->value()); + Rooted value(cx); + if (!JS_GetPropertyById(cx, entries, id, &value)) { + return false; + } + if (!value.isNullOrUndefined()) { + elementRecord = &value.toObject().as(); } } -#endif - if (!InternalizeJSONProperty(cx, obj, id, reviver, &elementRecord, + if (!InternalizeJSONProperty(cx, obj, id, reviver, elementRecord, &newElement)) { return false; } @@ -1878,15 +1831,17 @@ static bool InternalizeJSONProperty( /* Step 2c(ii)(1). */ id = keys[i]; - Rooted entryRecord(cx); -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE + Rooted entryRecord(cx); if (entries) { - if (auto entry = entries->lookup(id)) { - entryRecord = std::move(entry->value()); + Rooted value(cx); + if (!JS_GetPropertyById(cx, entries, id, &value)) { + return false; + } + if (!value.isNullOrUndefined()) { + entryRecord = &value.toObject().as(); } } -#endif - if (!InternalizeJSONProperty(cx, obj, id, reviver, &entryRecord, + if (!InternalizeJSONProperty(cx, obj, id, reviver, entryRecord, &newElement)) { return false; } @@ -1919,18 +1874,15 @@ static bool InternalizeJSONProperty( } RootedValue keyVal(cx, StringValue(key)); -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE if (JS::Prefs::experimental_json_parse_with_source()) { RootedValue contextVal(cx, ObjectValue(*context)); return js::Call(cx, reviver, holder, keyVal, val, contextVal, vp); } -#endif return js::Call(cx, reviver, holder, keyVal, val, vp); } static bool Revive(JSContext* cx, HandleValue reviver, - MutableHandle pro, - MutableHandleValue vp) { + Handle pro, MutableHandleValue vp) { Rooted obj(cx, NewPlainObject(cx)); if (!obj) { return false; @@ -1940,10 +1892,8 @@ static bool Revive(JSContext* cx, HandleValue reviver, return false; } -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE MOZ_ASSERT_IF(JS::Prefs::experimental_json_parse_with_source(), - pro.get().value == vp.get()); -#endif + pro->getValue() == vp.get()); Rooted id(cx, NameToId(cx->names().empty_)); return InternalizeJSONProperty(cx, obj, id, reviver, pro, vp); } @@ -1960,23 +1910,22 @@ template bool js::ParseJSONWithReviver(JSContext* cx, const mozilla::Range chars, HandleValue reviver, MutableHandleValue vp) { + js::AutoGeckoProfilerEntry pseudoFrame(cx, "parse JSON", + JS::ProfilingCategoryPair::JS_Parsing); /* https://262.ecma-international.org/14.0/#sec-json.parse steps 2-10. */ - Rooted pro(cx); -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE + Rooted pro(cx); if (JS::Prefs::experimental_json_parse_with_source() && IsCallable(reviver)) { Rooted> parser(cx, cx, chars); if (!parser.get().parse(vp, &pro)) { return false; } - } else -#endif - if (!ParseJSON(cx, chars, vp)) { + } else if (!ParseJSON(cx, chars, vp)) { return false; } /* Steps 11-12. */ if (IsCallable(reviver)) { - return Revive(cx, reviver, &pro, vp); + return Revive(cx, reviver, pro, vp); } return true; } @@ -2027,164 +1976,6 @@ static bool json_parse(JSContext* cx, unsigned argc, Value* vp) { args.rval()); } -#ifdef ENABLE_RECORD_TUPLE -bool BuildImmutableProperty(JSContext* cx, HandleValue value, HandleId name, - HandleValue reviver, - MutableHandleValue immutableRes) { - MOZ_ASSERT(!name.isSymbol()); - - // Step 1 - if (value.isObject()) { - RootedValue childValue(cx), newElement(cx); - RootedId childName(cx); - - // Step 1.a-1.b - if (value.toObject().is()) { - Rooted arr(cx, &value.toObject().as()); - - // Step 1.b.iii - uint32_t len = arr->length(); - - TupleType* tup = TupleType::createUninitialized(cx, len); - if (!tup) { - return false; - } - immutableRes.setExtendedPrimitive(*tup); - - // Step 1.b.iv - for (uint32_t i = 0; i < len; i++) { - // Step 1.b.iv.1 - childName.set(PropertyKey::Int(i)); - - // Step 1.b.iv.2 - if (!GetProperty(cx, arr, value, childName, &childValue)) { - return false; - } - - // Step 1.b.iv.3 - if (!BuildImmutableProperty(cx, childValue, childName, reviver, - &newElement)) { - return false; - } - MOZ_ASSERT(newElement.isPrimitive()); - - // Step 1.b.iv.5 - if (!tup->initializeNextElement(cx, newElement)) { - return false; - } - } - - // Step 1.b.v - tup->finishInitialization(cx); - } else { - RootedObject obj(cx, &value.toObject()); - - // Step 1.c.i - We only get the property keys rather than the - // entries, but the difference is not observable from user code - // because `obj` is a plan object not exposed externally - RootedIdVector props(cx); - if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &props)) { - return false; - } - - RecordType* rec = RecordType::createUninitialized(cx, props.length()); - if (!rec) { - return false; - } - immutableRes.setExtendedPrimitive(*rec); - - for (uint32_t i = 0; i < props.length(); i++) { - // Step 1.c.iii.1 - childName.set(props[i]); - - // Step 1.c.iii.2 - if (!GetProperty(cx, obj, value, childName, &childValue)) { - return false; - } - - // Step 1.c.iii.3 - if (!BuildImmutableProperty(cx, childValue, childName, reviver, - &newElement)) { - return false; - } - MOZ_ASSERT(newElement.isPrimitive()); - - // Step 1.c.iii.5 - if (!newElement.isUndefined()) { - // Step 1.c.iii.5.a-b - rec->initializeNextProperty(cx, childName, newElement); - } - } - - // Step 1.c.iv - rec->finishInitialization(cx); - } - } else { - // Step 2.a - immutableRes.set(value); - } - - // Step 3 - if (IsCallable(reviver)) { - RootedValue keyVal(cx, StringValue(IdToString(cx, name))); - - // Step 3.a - if (!Call(cx, reviver, UndefinedHandleValue, keyVal, immutableRes, - immutableRes)) { - return false; - } - - // Step 3.b - if (!immutableRes.isPrimitive()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_RECORD_TUPLE_NO_OBJECT); - return false; - } - } - - return true; -} - -static bool json_parseImmutable(JSContext* cx, unsigned argc, Value* vp) { - AutoJSMethodProfilerEntry pseudoFrame(cx, "JSON", "parseImmutable"); - CallArgs args = CallArgsFromVp(argc, vp); - - /* Step 1. */ - JSString* str = (args.length() >= 1) ? ToString(cx, args[0]) - : cx->names().undefined; - if (!str) { - return false; - } - - JSLinearString* linear = str->ensureLinear(cx); - if (!linear) { - return false; - } - - AutoStableStringChars linearChars(cx); - if (!linearChars.init(cx, linear)) { - return false; - } - - HandleValue reviver = args.get(1); - RootedValue unfiltered(cx); - - if (linearChars.isLatin1()) { - if (!ParseJSON(cx, linearChars.latin1Range(), &unfiltered)) { - return false; - } - } else { - if (!ParseJSON(cx, linearChars.twoByteRange(), &unfiltered)) { - return false; - } - } - - RootedId id(cx, NameToId(cx->names().empty_)); - return BuildImmutableProperty(cx, unfiltered, id, reviver, args.rval()); -} -#endif - -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE /* https://tc39.es/proposal-json-parse-with-source/#sec-json.israwjson */ static bool json_isRawJSON(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "JSON", "isRawJSON"); @@ -2193,15 +1984,16 @@ static bool json_isRawJSON(JSContext* cx, unsigned argc, Value* vp) { /* Step 1. */ if (args.get(0).isObject()) { Rooted obj(cx, &args[0].toObject()); -# ifdef DEBUG +#ifdef DEBUG if (obj->is()) { bool objIsFrozen = false; MOZ_ASSERT(js::TestIntegrityLevel(cx, obj, IntegrityLevel::Frozen, &objIsFrozen)); MOZ_ASSERT(objIsFrozen); } -# endif // DEBUG - args.rval().setBoolean(obj->is()); +#endif // DEBUG + args.rval().setBoolean(obj->is() || + obj->canUnwrapAs()); return true; } @@ -2280,7 +2072,6 @@ static bool json_rawJSON(JSContext* cx, unsigned argc, Value* vp) { args.rval().setObject(*obj); return true; } -#endif // ENABLE_JSON_PARSE_WITH_SOURCE /* https://262.ecma-international.org/14.0/#sec-json.stringify */ bool json_stringify(JSContext* cx, unsigned argc, Value* vp) { @@ -2323,17 +2114,15 @@ static const JSFunctionSpec json_static_methods[] = { JS_FN("toSource", json_toSource, 0, 0), JS_FN("parse", json_parse, 2, 0), JS_FN("stringify", json_stringify, 3, 0), -#ifdef ENABLE_RECORD_TUPLE - JS_FN("parseImmutable", json_parseImmutable, 2, 0), -#endif -#ifdef ENABLE_JSON_PARSE_WITH_SOURCE JS_FN("isRawJSON", json_isRawJSON, 1, 0), JS_FN("rawJSON", json_rawJSON, 1, 0), -#endif - JS_FS_END}; + JS_FS_END, +}; static const JSPropertySpec json_static_properties[] = { - JS_STRING_SYM_PS(toStringTag, "JSON", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "JSON", JSPROP_READONLY), + JS_PS_END, +}; static JSObject* CreateJSONObject(JSContext* cx, JSProtoKey key) { RootedObject proto(cx, &cx->global()->getObjectPrototype()); @@ -2341,7 +2130,15 @@ static JSObject* CreateJSONObject(JSContext* cx, JSProtoKey key) { } static const ClassSpec JSONClassSpec = { - CreateJSONObject, nullptr, json_static_methods, json_static_properties}; + CreateJSONObject, + nullptr, + json_static_methods, + json_static_properties, +}; -const JSClass js::JSONClass = {"JSON", JSCLASS_HAS_CACHED_PROTO(JSProto_JSON), - JS_NULL_CLASS_OPS, &JSONClassSpec}; +const JSClass js::JSONClass = { + "JSON", + JSCLASS_HAS_CACHED_PROTO(JSProto_JSON), + JS_NULL_CLASS_OPS, + &JSONClassSpec, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/JSON.h b/src/third_party/mozjs/extract/js/src/builtin/JSON.h index fd2d65e4f72..fc5c52e0905 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/JSON.h +++ b/src/third_party/mozjs/extract/js/src/builtin/JSON.h @@ -15,7 +15,7 @@ namespace js { -class StringBuffer; +class StringBuilder; extern const JSClass JSONClass; @@ -50,7 +50,7 @@ enum class StringifyBehavior { * not try to invoke .toJSON on things as it goes. */ extern bool Stringify(JSContext* cx, js::MutableHandleValue vp, - JSObject* replacer, const Value& space, StringBuffer& sb, + JSObject* replacer, const Value& space, StringBuilder& sb, StringifyBehavior stringifyBehavior); template diff --git a/src/third_party/mozjs/extract/js/src/builtin/Map.js b/src/third_party/mozjs/extract/js/src/builtin/Map.js index 983183ef7ff..a7095ed143f 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Map.js +++ b/src/third_party/mozjs/extract/js/src/builtin/Map.js @@ -98,7 +98,7 @@ function MapIteratorNext() { // Steps 10.b-c (omitted). // Step 6. - var itemKind = UnsafeGetInt32FromReservedSlot(O, ITERATOR_SLOT_ITEM_KIND); + var itemKind = UnsafeGetInt32FromReservedSlot(O, MAP_SET_ITERATOR_SLOT_ITEM_KIND); var result; if (itemKind === ITEM_KIND_KEY) { @@ -196,3 +196,54 @@ function MapGroupBy(items, callbackfn) { // Step 4. return map; } + +#ifdef NIGHTLY_BUILD +/** + * Upsert proposal + * + * Map.prototype.getOrInsertComputed ( key, callbackfn ) + * + * https://tc39.es/proposal-upsert/ + */ +function MapGetOrInsertComputed(key, callbackfn) { + // Step 1. Let M be the this value. + var M = this; + + // Step 2. Perform ? RequireInternalSlot(M, [[MapData]]). + if (!IsObject(M) || (M = GuardToMapObject(M)) === null) { + return callFunction( + CallMapMethodIfWrapped, + this, + key, + callbackfn, + "MapGetOrInsertComputed" + ); + } + + // Step 3. If IsCallable(callbackfn) is false, throw a TypeError exception. + if (!IsCallable(callbackfn)) { + ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); + } + + // Step 4. Set key to CanonicalizeKeyedCollectionKey(key). + // Step 5. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do + // Step 5.a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, return p.[[Value]]. + if (callFunction(std_Map_has, M, key)) { + return callFunction(std_Map_get, M, key); + } + + // Step 6. Let value be ? Call(callbackfn, undefined, « key »). + var value = callContentFunction(callbackfn, undefined, key); + + // Step 7. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do + // Step 7.a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, then + // Step 7.a.i. Set p.[[Value]] to value. + // Step 8. Let p be the Record { [[Key]]: key, [[Value]]: value }. + // Step 9. Append p to M.[[MapData]]. + callFunction(std_Map_set, M, key, value); + + // Step 7.a.ii, 10. Return value. + return value; +} +#endif // #ifdef NIGHTLY_BUILD + diff --git a/src/third_party/mozjs/extract/js/src/builtin/MapObject-inl.h b/src/third_party/mozjs/extract/js/src/builtin/MapObject-inl.h new file mode 100644 index 00000000000..14912b41b5c --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/MapObject-inl.h @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_MapObject_inl_h +#define builtin_MapObject_inl_h + +#include "builtin/MapObject.h" + +#include "vm/JSObject.h" +#include "vm/NativeObject.h" + +#include "vm/JSObject-inl.h" +#include "vm/NativeObject-inl.h" + +namespace js { + +enum class MapOrSet { Map, Set }; + +template +[[nodiscard]] static bool IsOptimizableArrayForMapOrSetCtor(JSObject* iterable, + JSContext* cx) { + if (!IsArrayWithDefaultIterator(iterable, cx)) { + return false; + } + + // For the Map and WeakMap constructors, ensure the elements are also packed + // arrays with at least two elements (key and value). + // + // Limit this to relatively short arrays to avoid adding overhead for large + // arrays in the worst case, when this check fails for one of the last + // elements. + if constexpr (IsMapOrSet == MapOrSet::Map) { + ArrayObject* array = &iterable->as(); + size_t len = array->length(); + static constexpr size_t MaxLength = 100; + if (len > MaxLength) { + return false; + } + for (size_t i = 0; i < len; i++) { + Value elem = array->getDenseElement(i); + if (!elem.isObject()) { + return false; + } + JSObject* obj = &elem.toObject(); + if (!IsPackedArray(obj) || obj->as().length() < 2) { + return false; + } + } + } + + return true; +} + +template +[[nodiscard]] static bool CanOptimizeMapOrSetCtorWithIterable( + JSNative addOrSetNative, NativeObject* mapOrSetObject, JSContext* cx) { + constexpr bool isMap = ProtoKey == JSProto_Map || ProtoKey == JSProto_WeakMap; + constexpr bool isSet = ProtoKey == JSProto_Set || ProtoKey == JSProto_WeakSet; + static_assert(isMap != isSet, "must be either a Map or a Set"); + + // Ensures mapOrSetObject's prototype is the canonical prototype. + JSObject* proto = mapOrSetObject->staticPrototype(); + MOZ_ASSERT(proto); + if (proto != cx->global()->maybeGetPrototype(ProtoKey)) { + return false; + } + + // Ensure the 'add' or 'set' method on the prototype is unchanged. Use a fast + // path based on fuses. + switch (ProtoKey) { + case JSProto_Map: + if (cx->realm()->realmFuses.optimizeMapPrototypeSetFuse.intact()) { + return true; + } + break; + case JSProto_Set: + if (cx->realm()->realmFuses.optimizeSetPrototypeAddFuse.intact()) { + return true; + } + break; + case JSProto_WeakMap: + if (cx->realm()->realmFuses.optimizeWeakMapPrototypeSetFuse.intact()) { + return true; + } + break; + case JSProto_WeakSet: + if (cx->realm()->realmFuses.optimizeWeakSetPrototypeAddFuse.intact()) { + return true; + } + break; + default: + MOZ_CRASH("Unexpected ProtoKey"); + } + + // Look up the 'add' or 'set' property on the prototype object. + auto* nproto = &proto->as(); + PropertyName* propName = isSet ? cx->names().add : cx->names().set; + mozilla::Maybe prop = nproto->lookup(cx, propName); + if (prop.isNothing() || !prop->isDataProperty()) { + return false; + } + + // Get the property value and ensure it's the canonical 'add' or 'set' + // function. + Value propVal = nproto->getSlot(prop->slot()); + return IsNativeFunction(propVal, addOrSetNative); +} + +} // namespace js + +#endif /* builtin_MapObject_inl_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/MapObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/MapObject.cpp index 52f60721ea6..59f68732677 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/MapObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/MapObject.cpp @@ -4,11 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "builtin/MapObject.h" +#include "builtin/MapObject-inl.h" #include "jsapi.h" -#include "ds/OrderedHashTable.h" +#include "builtin/OrderedHashTableObject.h" #include "gc/GCContext.h" #include "jit/InlinableNatives.h" #include "js/MapAndSet.h" @@ -24,13 +24,10 @@ #include "vm/SelfHosting.h" #include "vm/SymbolType.h" -#ifdef ENABLE_RECORD_TUPLE -# include "vm/RecordType.h" -# include "vm/TupleType.h" -#endif - +#include "builtin/OrderedHashTableObject-inl.h" #include "gc/GCContext-inl.h" #include "gc/Marking-inl.h" +#include "gc/ObjectKind-inl.h" #include "vm/GeckoProfiler-inl.h" #include "vm/NativeObject-inl.h" @@ -53,7 +50,7 @@ static PreBarriered NormalizeDoubleValue(double d) { return JS::CanonicalizedDoubleValue(d); } -bool HashableValue::setValue(JSContext* cx, HandleValue v) { +bool HashableValue::setValue(JSContext* cx, const Value& v) { if (v.isString()) { // Atomize so that hash() and operator==() are fast and infallible. JSString* str = AtomizeString(cx, v.toString()); @@ -63,29 +60,13 @@ bool HashableValue::setValue(JSContext* cx, HandleValue v) { value = StringValue(str); } else if (v.isDouble()) { value = NormalizeDoubleValue(v.toDouble()); -#ifdef ENABLE_RECORD_TUPLE - } else if (v.isExtendedPrimitive()) { - JSObject& obj = v.toExtendedPrimitive(); - if (obj.is()) { - if (!obj.as().ensureAtomized(cx)) { - return false; - } - } else { - MOZ_ASSERT(obj.is()); - if (!obj.as().ensureAtomized(cx)) { - return false; - } - } - value = v; -#endif } else { value = v; } MOZ_ASSERT(value.isUndefined() || value.isNull() || value.isBoolean() || value.isNumber() || value.isString() || value.isSymbol() || - value.isObject() || value.isBigInt() || - IF_RECORD_TUPLE(value.isExtendedPrimitive(), false)); + value.isObject() || value.isBigInt()); return true; } @@ -109,21 +90,6 @@ static HashNumber HashValue(const Value& v, if (v.isBigInt()) { return MaybeForwarded(v.toBigInt())->hash(); } -#ifdef ENABLE_RECORD_TUPLE - if (v.isExtendedPrimitive()) { - JSObject* obj = MaybeForwarded(&v.toExtendedPrimitive()); - auto hasher = [&hcs](const Value& v) { - return HashValue( - v.isDouble() ? NormalizeDoubleValue(v.toDouble()).get() : v, hcs); - }; - - if (obj->is()) { - return obj->as().hash(hasher); - } - MOZ_ASSERT(obj->is()); - return obj->as().hash(hasher); - } -#endif if (v.isObject()) { return hcs.scramble(v.asRawBits()); } @@ -136,14 +102,6 @@ HashNumber HashableValue::hash(const mozilla::HashCodeScrambler& hcs) const { return HashValue(value, hcs); } -#ifdef ENABLE_RECORD_TUPLE -inline bool SameExtendedPrimitiveType(const PreBarriered& a, - const PreBarriered& b) { - return a.toExtendedPrimitive().getClass() == - b.toExtendedPrimitive().getClass(); -} -#endif - bool HashableValue::equals(const HashableValue& other) const { // Two HashableValues are equal if they have equal bits. bool b = (value.asRawBits() == other.value.asRawBits()); @@ -154,12 +112,6 @@ bool HashableValue::equals(const HashableValue& other) const { // mathematical value. b = BigInt::equal(value.toBigInt(), other.value.toBigInt()); } -#ifdef ENABLE_RECORD_TUPLE - else if (value.isExtendedPrimitive() && - SameExtendedPrimitiveType(value, other.value)) { - b = js::SameValueZeroLinear(value, other.value); - } -#endif } #ifdef DEBUG @@ -198,24 +150,15 @@ const JSClass MapIteratorObject::class_ = { "Map Iterator", JSCLASS_HAS_RESERVED_SLOTS(MapIteratorObject::SlotCount) | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE, - &MapIteratorObjectClassOps, JS_NULL_CLASS_SPEC, - &MapIteratorObjectClassExtension}; + &MapIteratorObjectClassOps, + JS_NULL_CLASS_SPEC, + &MapIteratorObjectClassExtension, +}; const JSFunctionSpec MapIteratorObject::methods[] = { - JS_SELF_HOSTED_FN("next", "MapIteratorNext", 0, 0), JS_FS_END}; - -static inline ValueMap::Range* MapIteratorObjectRange(NativeObject* obj) { - MOZ_ASSERT(obj->is()); - return obj->maybePtrFromReservedSlot( - MapIteratorObject::RangeSlot); -} - -inline MapObject::IteratorKind MapIteratorObject::kind() const { - int32_t i = getReservedSlot(KindSlot).toInt32(); - MOZ_ASSERT(i == MapObject::Keys || i == MapObject::Values || - i == MapObject::Entries); - return MapObject::IteratorKind(i); -} + JS_SELF_HOSTED_FN("next", "MapIteratorNext", 0, 0), + JS_FS_END, +}; /* static */ bool GlobalObject::initMapIteratorProto(JSContext* cx, @@ -234,24 +177,28 @@ bool GlobalObject::initMapIteratorProto(JSContext* cx, !DefineToStringTag(cx, proto, cx->names().Map_Iterator_)) { return false; } + if (!JSObject::setHasFuseProperty(cx, proto)) { + return false; + } global->initBuiltinProto(ProtoKind::MapIteratorProto, proto); return true; } template -static inline bool HasNurseryMemory(TableObject* t) { - return t->getReservedSlot(TableObject::HasNurseryMemorySlot).toBoolean(); +static inline bool HasRegisteredNurseryIterators(TableObject* t) { + Value v = t->getReservedSlot(TableObject::RegisteredNurseryIteratorsSlot); + return v.toBoolean(); } template -static inline void SetHasNurseryMemory(TableObject* t, bool b) { - t->setReservedSlot(TableObject::HasNurseryMemorySlot, JS::BooleanValue(b)); +static inline void SetRegisteredNurseryIterators(TableObject* t, bool b) { + t->setReservedSlot(TableObject::RegisteredNurseryIteratorsSlot, + JS::BooleanValue(b)); } -MapIteratorObject* MapIteratorObject::create(JSContext* cx, HandleObject obj, - const ValueMap* data, - MapObject::IteratorKind kind) { - Handle mapobj(obj.as()); +MapIteratorObject* MapIteratorObject::create(JSContext* cx, + Handle mapobj, + Kind kind) { Rooted global(cx, &mapobj->global()); Rooted proto( cx, GlobalObject::getOrCreateMapIteratorPrototype(cx, global)); @@ -265,44 +212,16 @@ MapIteratorObject* MapIteratorObject::create(JSContext* cx, HandleObject obj, return nullptr; } - iterobj->init(mapobj, kind); - - constexpr size_t BufferSize = - RoundUp(sizeof(ValueMap::Range), gc::CellAlignBytes); - - Nursery& nursery = cx->nursery(); - void* buffer = - nursery.allocateBufferSameLocation(iterobj, BufferSize, js::MallocArena); - if (!buffer) { - // Retry with |iterobj| and |buffer| forcibly tenured. - iterobj = NewTenuredObjectWithGivenProto(cx, proto); - if (!iterobj) { - return nullptr; - } - - iterobj->init(mapobj, kind); - - buffer = nursery.allocateBufferSameLocation(iterobj, BufferSize, - js::MallocArena); - if (!buffer) { + if (IsInsideNursery(iterobj) && + !HasRegisteredNurseryIterators(mapobj.get())) { + if (!cx->nursery().addMapWithNurseryIterators(mapobj)) { ReportOutOfMemory(cx); return nullptr; } + SetRegisteredNurseryIterators(mapobj.get(), true); } - bool insideNursery = IsInsideNursery(iterobj); - MOZ_ASSERT(insideNursery == nursery.isInside(buffer)); - - if (insideNursery && !HasNurseryMemory(mapobj.get())) { - if (!cx->nursery().addMapWithNurseryMemory(mapobj)) { - ReportOutOfMemory(cx); - return nullptr; - } - SetHasNurseryMemory(mapobj.get(), true); - } - - auto range = data->createRange(buffer, insideNursery); - iterobj->setReservedSlot(RangeSlot, PrivateValue(range)); + MapObject::Table(mapobj).initIterator(iterobj, kind); return iterobj; } @@ -310,71 +229,31 @@ MapIteratorObject* MapIteratorObject::create(JSContext* cx, HandleObject obj, void MapIteratorObject::finalize(JS::GCContext* gcx, JSObject* obj) { MOZ_ASSERT(gcx->onMainThread()); MOZ_ASSERT(!IsInsideNursery(obj)); - - auto range = MapIteratorObjectRange(&obj->as()); - MOZ_ASSERT(!gcx->runtime()->gc.nursery().isInside(range)); - - // Bug 1560019: Malloc memory associated with MapIteratorObjects is not - // currently tracked. - gcx->deleteUntracked(range); + if (obj->as().isActive()) { + obj->as().unlink(); + } } size_t MapIteratorObject::objectMoved(JSObject* obj, JSObject* old) { - if (!IsInsideNursery(old)) { - return 0; - } - MapIteratorObject* iter = &obj->as(); - ValueMap::Range* range = MapIteratorObjectRange(iter); - if (!range) { + if (!iter->isActive()) { return 0; } - - Nursery& nursery = iter->runtimeFromMainThread()->gc.nursery(); - if (!nursery.isInside(range)) { - nursery.removeMallocedBufferDuringMinorGC(range); + if (IsInsideNursery(old)) { + MapObject* mapObj = iter->target(); + MapObject::Table(mapObj).relinkNurseryIterator(iter); + } else { + iter->updateListAfterMove(&old->as()); } - - size_t size = RoundUp(sizeof(ValueMap::Range), gc::CellAlignBytes); - AutoEnterOOMUnsafeRegion oomUnsafe; - void* buffer = nursery.allocateBufferSameLocation(obj, size, js::MallocArena); - if (!buffer) { - oomUnsafe.crash("MapIteratorObject::objectMoved"); - } - - bool iteratorIsInNursery = IsInsideNursery(obj); - MOZ_ASSERT(iteratorIsInNursery == nursery.isInside(buffer)); - auto* newRange = new (buffer) ValueMap::Range(*range, iteratorIsInNursery); - range->~Range(); - iter->setReservedSlot(MapIteratorObject::RangeSlot, PrivateValue(newRange)); - - if (iteratorIsInNursery && iter->target()) { - SetHasNurseryMemory(iter->target(), true); - } - - return size; + return 0; } MapObject* MapIteratorObject::target() const { + MOZ_ASSERT(isActive(), "only active iterators have a target object"); Value value = getFixedSlot(TargetSlot); - if (value.isUndefined()) { - return nullptr; - } - return &MaybeForwarded(&value.toObject())->as(); } -template -static void DestroyRange(JSObject* iterator, Range* range) { - MOZ_ASSERT(IsInsideNursery(iterator) == - iterator->runtimeFromMainThread()->gc.nursery().isInside(range)); - - range->~Range(); - if (!IsInsideNursery(iterator)) { - js_free(range); - } -} - bool MapIteratorObject::next(MapIteratorObject* mapIterator, ArrayObject* resultPairObj) { // IC code calls this directly. @@ -390,34 +269,30 @@ bool MapIteratorObject::next(MapIteratorObject* mapIterator, MOZ_ASSERT(resultPairObj->getDenseInitializedLength() == 2); MOZ_ASSERT(resultPairObj->getDenseCapacity() >= 2); - ValueMap::Range* range = MapIteratorObjectRange(mapIterator); - if (!range) { + if (!mapIterator->isActive()) { + // Already done. return true; } - if (range->empty()) { - DestroyRange(mapIterator, range); - mapIterator->setReservedSlot(RangeSlot, PrivateValue(nullptr)); - return true; - } + auto storeResult = [resultPairObj](Kind kind, const auto& element) { + switch (kind) { + case Kind::Keys: + resultPairObj->setDenseElement(0, element.key.get()); + break; - switch (mapIterator->kind()) { - case MapObject::Keys: - resultPairObj->setDenseElement(0, range->front().key.get()); - break; + case Kind::Values: + resultPairObj->setDenseElement(1, element.value); + break; - case MapObject::Values: - resultPairObj->setDenseElement(1, range->front().value); - break; - - case MapObject::Entries: { - resultPairObj->setDenseElement(0, range->front().key.get()); - resultPairObj->setDenseElement(1, range->front().value); - break; + case Kind::Entries: { + resultPairObj->setDenseElement(0, element.key.get()); + resultPairObj->setDenseElement(1, element.value); + break; + } } - } - range->popFront(); - return false; + }; + MapObject* mapObj = mapIterator->target(); + return MapObject::Table(mapObj).iteratorNext(mapIterator, storeResult); } /* static */ @@ -448,13 +323,11 @@ struct js::UnbarrieredHashPolicy { static void makeEmpty(Value* vp) { vp->setMagic(JS_HASH_KEY_EMPTY); } }; -// ValueMap, MapObject::UnbarrieredTable and MapObject::PreBarrieredTable must -// all have the same memory layout. -static_assert(sizeof(ValueMap) == sizeof(MapObject::UnbarrieredTable)); -static_assert(sizeof(ValueMap::Entry) == +// MapObject::Table, ::UnbarrieredTable and ::PreBarrieredTable must all have +// the same memory layout. +static_assert(sizeof(MapObject::Table::Entry) == sizeof(MapObject::UnbarrieredTable::Entry)); -static_assert(sizeof(ValueMap) == sizeof(MapObject::PreBarrieredTable)); -static_assert(sizeof(ValueMap::Entry) == +static_assert(sizeof(MapObject::Table::Entry) == sizeof(MapObject::PreBarrieredTable::Entry)); const JSClassOps MapObject::classOps_ = { @@ -471,7 +344,8 @@ const JSClassOps MapObject::classOps_ = { }; const ClassSpec MapObject::classSpec_ = { - GenericCreateConstructor, + GenericCreateConstructor, GenericCreatePrototype, MapObject::staticMethods, MapObject::staticProperties, @@ -480,15 +354,17 @@ const ClassSpec MapObject::classSpec_ = { MapObject::finishInit, }; +const ClassExtension MapObject::classExtension_ = { + MapObject::objectMoved, // objectMovedOp +}; + const JSClass MapObject::class_ = { "Map", JSCLASS_DELAY_METADATA_BUILDER | JSCLASS_HAS_RESERVED_SLOTS(MapObject::SlotCount) | - JSCLASS_HAS_CACHED_PROTO(JSProto_Map) | JSCLASS_FOREGROUND_FINALIZE | + JSCLASS_HAS_CACHED_PROTO(JSProto_Map) | JSCLASS_BACKGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE, - &MapObject::classOps_, - &MapObject::classSpec_, -}; + &MapObject::classOps_, &MapObject::classSpec_, &MapObject::classExtension_}; const JSClass MapObject::protoClass_ = { "Map.prototype", @@ -506,12 +382,16 @@ const JSPropertySpec MapObject::properties[] = { const JSFunctionSpec MapObject::methods[] = { JS_INLINABLE_FN("get", get, 1, 0, MapGet), JS_INLINABLE_FN("has", has, 1, 0, MapHas), - JS_FN("set", set, 2, 0), - JS_FN("delete", delete_, 1, 0), + JS_INLINABLE_FN("set", set, 2, 0, MapSet), + JS_INLINABLE_FN("delete", delete_, 1, 0, MapDelete), JS_FN("keys", keys, 0, 0), JS_FN("values", values, 0, 0), JS_FN("clear", clear, 0, 0), JS_SELF_HOSTED_FN("forEach", "MapForEach", 2, 0), +#ifdef NIGHTLY_BUILD + JS_FN("getOrInsert", getOrInsert, 2, 0), + JS_SELF_HOSTED_FN("getOrInsertComputed", "MapGetOrInsertComputed", 2, 0), +#endif JS_FN("entries", entries, 0, 0), // @@iterator is re-defined in finishInit so that it has the // same identity as |entries|. @@ -543,16 +423,19 @@ const JSFunctionSpec MapObject::staticMethods[] = { // The initial value of the @@iterator property is the same function object // as the initial value of the "entries" property. RootedId iteratorId(cx, PropertyKey::Symbol(cx->wellKnownSymbols().iterator)); - return NativeDefineDataProperty(cx, nativeProto, iteratorId, entriesFn, 0); + if (!NativeDefineDataProperty(cx, nativeProto, iteratorId, entriesFn, 0)) { + return false; + } + + return JSObject::setHasFuseProperty(cx, nativeProto); } void MapObject::trace(JSTracer* trc, JSObject* obj) { - if (ValueMap* map = obj->as().getTableUnchecked()) { - map->trace(trc); - } + MapObject* mapObj = &obj->as(); + Table(mapObj).trace(trc); } -using NurseryKeysVector = GCVector; +using NurseryKeysVector = GCVector; template static NurseryKeysVector* GetNurseryKeys(TableObject* t) { @@ -591,20 +474,17 @@ class js::OrderedHashTableRef : public gc::BufferableRef { void trace(JSTracer* trc) override { MOZ_ASSERT(!IsInsideNursery(object)); - auto realTable = object->getTableUnchecked(); - auto unbarrieredTable = - reinterpret_cast(realTable); NurseryKeysVector* keys = GetNurseryKeys(object); MOZ_ASSERT(keys); keys->mutableEraseIf([&](Value& key) { - MOZ_ASSERT( - unbarrieredTable->hash(key) == - realTable->hash(*reinterpret_cast(&key))); + MOZ_ASSERT(typename ObjectT::UnbarrieredTable(object).hash(key) == + typename ObjectT::Table(object).hash( + *reinterpret_cast(&key))); MOZ_ASSERT(IsInsideNursery(key.toGCThing())); - auto result = - unbarrieredTable->rekeyOneEntry(key, [trc](const Value& prior) { + auto result = typename ObjectT::UnbarrieredTable(object).rekeyOneEntry( + key, [trc](const Value& prior) { Value key = prior; TraceManuallyBarrieredEdge(trc, &key, "ordered hash table key"); return key; @@ -629,9 +509,11 @@ class js::OrderedHashTableRef : public gc::BufferableRef { }; template -[[nodiscard]] inline static bool PostWriteBarrierImpl(ObjectT* obj, - const Value& keyValue) { - if (MOZ_LIKELY(!keyValue.hasObjectPayload() && !keyValue.isBigInt())) { +[[nodiscard]] inline static bool PostWriteBarrier(ObjectT* obj, + const Value& keyValue) { + MOZ_ASSERT(!IsInsideNursery(obj)); + + if (MOZ_LIKELY(!keyValue.isObject() && !keyValue.isBigInt())) { MOZ_ASSERT_IF(keyValue.isGCThing(), !IsInsideNursery(keyValue.toGCThing())); return true; } @@ -654,70 +536,37 @@ template return keys->append(keyValue); } -[[nodiscard]] inline static bool PostWriteBarrier(MapObject* map, - const Value& key) { - MOZ_ASSERT(!IsInsideNursery(map)); - return PostWriteBarrierImpl(map, key); -} - -[[nodiscard]] inline static bool PostWriteBarrier(SetObject* set, - const Value& key) { - if (IsInsideNursery(set)) { - return true; - } - - return PostWriteBarrierImpl(set, key); -} - bool MapObject::getKeysAndValuesInterleaved( - HandleObject obj, JS::MutableHandle> entries) { - const ValueMap* map = obj->as().getData(); - if (!map) { + JS::MutableHandle> entries) { + auto appendEntry = [&entries](auto& entry) { + return entries.append(entry.key.get()) && entries.append(entry.value); + }; + return Table(this).forEachEntry(appendEntry); +} + +bool MapObject::set(JSContext* cx, const Value& key, const Value& val) { + HashableValue k; + if (!k.setValue(cx, key)) { return false; } + return setWithHashableKey(cx, k, val); +} - for (ValueMap::Range r = map->all(); !r.empty(); r.popFront()) { - if (!entries.append(r.front().key.get()) || - !entries.append(r.front().value)) { +bool MapObject::setWithHashableKey(JSContext* cx, const HashableValue& key, + const Value& value) { + bool needsPostBarriers = isTenured(); + if (needsPostBarriers) { + // Use the Table representation which has post barriers. + if (!PostWriteBarrier(this, key)) { + ReportOutOfMemory(cx); return false; } - } - - return true; -} - -bool MapObject::set(JSContext* cx, HandleObject obj, HandleValue k, - HandleValue v) { - MapObject* mapObject = &obj->as(); - Rooted key(cx); - if (!key.setValue(cx, k)) { - return false; - } - - return setWithHashableKey(cx, mapObject, key, v); -} - -/* static */ -inline bool MapObject::setWithHashableKey(JSContext* cx, MapObject* obj, - Handle key, - Handle value) { - ValueMap* table = obj->getTableUnchecked(); - if (!table) { - return false; - } - - bool needsPostBarriers = obj->isTenured(); - if (needsPostBarriers) { - // Use the ValueMap representation which has post barriers. - if (!PostWriteBarrier(obj, key.get()) || !table->put(key.get(), value)) { - ReportOutOfMemory(cx); + if (!Table(this).put(cx, key, value)) { return false; } } else { // Use the PreBarrieredTable representation which does not. - auto* preBarriedTable = reinterpret_cast(table); - if (!preBarriedTable->put(key.get(), value.get())) { - ReportOutOfMemory(cx); + if (!PreBarrieredTable(this).put(cx, key, value)) { return false; } } @@ -725,43 +574,113 @@ inline bool MapObject::setWithHashableKey(JSContext* cx, MapObject* obj, return true; } -MapObject* MapObject::create(JSContext* cx, - HandleObject proto /* = nullptr */) { - auto map = cx->make_unique(cx->zone(), - cx->realm()->randomHashCodeScrambler()); - if (!map) { - return nullptr; +#ifdef NIGHTLY_BUILD +bool MapObject::getOrInsert(JSContext* cx, const Value& key, const Value& val, + MutableHandleValue rval) { + HashableValue k; + if (!k.setValue(cx, key)) { + return false; } - if (!map->init()) { - ReportOutOfMemory(cx); - return nullptr; + bool needsPostBarriers = isTenured(); + if (needsPostBarriers) { + if (!PostWriteBarrier(this, k)) { + ReportOutOfMemory(cx); + return false; + } + // Use the Table representation which has post barriers. + if (const Table::Entry* p = Table(this).getOrAdd(cx, k, val)) { + rval.set(p->value); + } else { + return false; + } + } else { + // Use the PreBarrieredTable representation which does not. + if (const PreBarrieredTable::Entry* p = + PreBarrieredTable(this).getOrAdd(cx, k, val)) { + rval.set(p->value); + } else { + return false; + } } + return true; +} +#endif // #ifdef NIGHTLY_BUILD + +MapObject* MapObject::createWithProto(JSContext* cx, HandleObject proto, + NewObjectKind newKind) { + MOZ_ASSERT(proto); + + gc::AllocKind allocKind = gc::GetGCObjectKind(SlotCount); AutoSetNewObjectMetadata metadata(cx); - MapObject* mapObj = NewObjectWithClassProto(cx, proto); + auto* mapObj = + NewObjectWithGivenProtoAndKinds(cx, proto, allocKind, newKind); if (!mapObj) { return nullptr; } - bool insideNursery = IsInsideNursery(mapObj); - if (insideNursery && !cx->nursery().addMapWithNurseryMemory(mapObj)) { - ReportOutOfMemory(cx); + UnbarrieredTable(mapObj).initSlots(); + mapObj->initReservedSlot(NurseryKeysSlot, PrivateValue(nullptr)); + mapObj->initReservedSlot(RegisteredNurseryIteratorsSlot, BooleanValue(false)); + return mapObj; +} + +MapObject* MapObject::create(JSContext* cx, + HandleObject proto /* = nullptr */) { + if (proto) { + return createWithProto(cx, proto, GenericObject); + } + + // This is the common case so use the template object's shape to optimize the + // allocation. + MapObject* templateObj = GlobalObject::getOrCreateMapTemplateObject(cx); + if (!templateObj) { return nullptr; } - InitReservedSlot(mapObj, DataSlot, map.release(), MemoryUse::MapObjectTable); + gc::AllocKind allocKind = templateObj->asTenured().getAllocKind(); + MOZ_ASSERT(gc::GetGCKindSlots(allocKind) >= SlotCount); + MOZ_ASSERT(gc::IsBackgroundFinalized(allocKind)); + + AutoSetNewObjectMetadata metadata(cx); + Rooted shape(cx, templateObj->sharedShape()); + auto* mapObj = + NativeObject::create(cx, allocKind, gc::Heap::Default, shape); + if (!mapObj) { + return nullptr; + } + + UnbarrieredTable(mapObj).initSlots(); mapObj->initReservedSlot(NurseryKeysSlot, PrivateValue(nullptr)); - mapObj->initReservedSlot(HasNurseryMemorySlot, - JS::BooleanValue(insideNursery)); + mapObj->initReservedSlot(RegisteredNurseryIteratorsSlot, BooleanValue(false)); + return mapObj; +} + +// static +MapObject* GlobalObject::getOrCreateMapTemplateObject(JSContext* cx) { + GlobalObjectData& data = cx->global()->data(); + if (MapObject* obj = data.mapObjectTemplate) { + return obj; + } + + Rooted proto(cx, + GlobalObject::getOrCreatePrototype(cx, JSProto_Map)); + if (!proto) { + return nullptr; + } + auto* mapObj = MapObject::createWithProto(cx, proto, TenuredObject); + if (!mapObj) { + return nullptr; + } + + data.mapObjectTemplate.init(mapObj); return mapObj; } size_t MapObject::sizeOfData(mozilla::MallocSizeOf mallocSizeOf) { size_t size = 0; - if (const ValueMap* map = getData()) { - size += map->sizeOfIncludingThis(mallocSizeOf); - } + size += Table(this).sizeOfExcludingObject(mallocSizeOf); if (NurseryKeysVector* nurseryKeys = GetNurseryKeys(this)) { size += nurseryKeys->sizeOfIncludingThis(mallocSizeOf); } @@ -769,28 +688,43 @@ size_t MapObject::sizeOfData(mozilla::MallocSizeOf mallocSizeOf) { } void MapObject::finalize(JS::GCContext* gcx, JSObject* obj) { - MOZ_ASSERT(gcx->onMainThread()); - ValueMap* table = obj->as().getTableUnchecked(); - if (!table) { - return; - } + MapObject* mapObj = &obj->as(); + MOZ_ASSERT(!IsInsideNursery(mapObj)); + MOZ_ASSERT(!UnbarrieredTable(mapObj).hasNurseryIterators()); - MOZ_ASSERT_IF(obj->isTenured(), !table->hasNurseryRanges()); +#ifdef DEBUG + // If we're finalizing a tenured map then it cannot contain nursery things, + // because we evicted the nursery at the start of collection and writing a + // nursery thing into the table would require it to be live, which means it + // would have been marked. + UnbarrieredTable(mapObj).forEachEntryUpTo(1000, [](auto& entry) { + Value key = entry.key; + MOZ_ASSERT_IF(key.isGCThing(), !IsInsideNursery(key.toGCThing())); + Value value = entry.value; + MOZ_ASSERT_IF(value.isGCThing(), !IsInsideNursery(value.toGCThing())); + }); +#endif - bool needsPostBarriers = obj->isTenured(); - if (needsPostBarriers) { - // Use the ValueMap representation which has post barriers. - gcx->delete_(obj, table, MemoryUse::MapObjectTable); - } else { - // Use the PreBarrieredTable representation which does not. - auto* preBarriedTable = reinterpret_cast(table); - gcx->delete_(obj, preBarriedTable, MemoryUse::MapObjectTable); - } + // Finalized tenured maps do not contain nursery GC things, so do not require + // post barriers. Pre barriers are not required for finalization. + UnbarrieredTable(mapObj).destroy(gcx); } -void MapObject::clearNurseryRangesBeforeMinorGC() { - getTableUnchecked()->destroyNurseryRanges(); - SetHasNurseryMemory(this, false); +size_t MapObject::objectMoved(JSObject* obj, JSObject* old) { + auto* mapObj = &obj->as(); + + Table(mapObj).updateIteratorsAfterMove(&old->as()); + + if (IsInsideNursery(old)) { + Nursery& nursery = mapObj->runtimeFromMainThread()->gc.nursery(); + Table(mapObj).maybeMoveBufferOnPromotion(nursery); + } + + return 0; +} + +void MapObject::clearNurseryIteratorsBeforeMinorGC() { + Table(this).clearNurseryIterators(); } /* static */ @@ -798,26 +732,110 @@ MapObject* MapObject::sweepAfterMinorGC(JS::GCContext* gcx, MapObject* mapobj) { Nursery& nursery = gcx->runtime()->gc.nursery(); bool wasInCollectedRegion = nursery.inCollectedRegion(mapobj); if (wasInCollectedRegion && !IsForwarded(mapobj)) { - finalize(gcx, mapobj); + // This MapObject is dead. return nullptr; } mapobj = MaybeForwarded(mapobj); - bool insideNursery = IsInsideNursery(mapobj); - if (insideNursery) { - SetHasNurseryMemory(mapobj, true); + // Keep |mapobj| registered with the nursery if it still has nursery + // iterators. + bool hasNurseryIterators = Table(mapobj).hasNurseryIterators(); + SetRegisteredNurseryIterators(mapobj, hasNurseryIterators); + return hasNurseryIterators ? mapobj : nullptr; +} + +bool MapObject::tryOptimizeCtorWithIterable(JSContext* cx, + const Value& iterableVal, + bool* optimized) { + MOZ_ASSERT(!iterableVal.isNullOrUndefined()); + MOZ_ASSERT(!*optimized); + + if (!CanOptimizeMapOrSetCtorWithIterable(MapObject::set, this, + cx)) { + return true; } - if (wasInCollectedRegion && mapobj->isTenured()) { - AddCellMemory(mapobj, sizeof(ValueMap), MemoryUse::MapObjectTable); + if (!iterableVal.isObject()) { + return true; + } + JSObject* iterable = &iterableVal.toObject(); + + // Fast path for `new Map(array)`. + if (IsOptimizableArrayForMapOrSetCtor(iterable, cx)) { + ArrayObject* array = &iterable->as(); + uint32_t len = array->getDenseInitializedLength(); + + for (uint32_t index = 0; index < len; index++) { + Value element = array->getDenseElement(index); + MOZ_ASSERT(IsPackedArray(&element.toObject())); + + auto* elementArray = &element.toObject().as(); + Value key = elementArray->getDenseElement(0); + Value value = elementArray->getDenseElement(1); + + MOZ_ASSERT(!key.isMagic(JS_ELEMENTS_HOLE)); + MOZ_ASSERT(!value.isMagic(JS_ELEMENTS_HOLE)); + + if (!set(cx, key, value)) { + return false; + } + } + + *optimized = true; + return true; } - if (!HasNurseryMemory(mapobj)) { - return nullptr; + // Fast path for `new Map(map)`. + if (IsMapObjectWithDefaultIterator(iterable, cx)) { + auto* iterableMap = &iterable->as(); + auto addEntry = [cx, this](auto& entry) { + return setWithHashableKey(cx, entry.key, entry.value); + }; + if (!Table(iterableMap).forEachEntry(addEntry)) { + return false; + } + *optimized = true; + return true; } - return mapobj; + return true; +} + +// static +MapObject* MapObject::createFromIterable(JSContext* cx, Handle proto, + Handle iterable, + Handle allocatedFromJit) { + // A null-or-undefined |iterable| is quite common and we check for this in JIT + // code. + MOZ_ASSERT_IF(allocatedFromJit, !iterable.isNullOrUndefined()); + + Rooted obj(cx, allocatedFromJit); + if (!obj) { + obj = MapObject::create(cx, proto); + if (!obj) { + return nullptr; + } + } + + if (!iterable.isNullOrUndefined()) { + bool optimized = false; + if (!obj->tryOptimizeCtorWithIterable(cx, iterable, &optimized)) { + return nullptr; + } + if (!optimized) { + FixedInvokeArgs<1> args(cx); + args[0].set(iterable); + + RootedValue thisv(cx, ObjectValue(*obj)); + if (!CallSelfHostedFunction(cx, cx->names().MapConstructorInit, thisv, + args, args.rval())) { + return nullptr; + } + } + } + + return obj; } bool MapObject::construct(JSContext* cx, unsigned argc, Value* vp) { @@ -833,61 +851,30 @@ bool MapObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - Rooted obj(cx, MapObject::create(cx, proto)); + MapObject* obj = MapObject::createFromIterable(cx, proto, args.get(0)); if (!obj) { return false; } - if (!args.get(0).isNullOrUndefined()) { - FixedInvokeArgs<1> args2(cx); - args2[0].set(args[0]); - - RootedValue thisv(cx, ObjectValue(*obj)); - if (!CallSelfHostedFunction(cx, cx->names().MapConstructorInit, thisv, - args2, args2.rval())) { - return false; - } - } - args.rval().setObject(*obj); return true; } bool MapObject::is(HandleValue v) { - return v.isObject() && v.toObject().hasClass(&class_) && - !v.toObject().as().getReservedSlot(DataSlot).isUndefined(); + return v.isObject() && v.toObject().hasClass(&class_); } -bool MapObject::is(HandleObject o) { - return o->hasClass(&class_) && - !o->as().getReservedSlot(DataSlot).isUndefined(); -} +bool MapObject::is(HandleObject o) { return o->hasClass(&class_); } -#define ARG0_KEY(cx, args, key) \ - Rooted key(cx); \ - if (args.length() > 0 && !key.setValue(cx, args[0])) return false - -const ValueMap& MapObject::extract(HandleObject o) { - MOZ_ASSERT(o->hasClass(&MapObject::class_)); - return *o->as().getData(); -} - -const ValueMap& MapObject::extract(const CallArgs& args) { - MOZ_ASSERT(args.thisv().isObject()); - MOZ_ASSERT(args.thisv().toObject().hasClass(&MapObject::class_)); - return *args.thisv().toObject().as().getData(); -} - -uint32_t MapObject::size(JSContext* cx, HandleObject obj) { - const ValueMap& map = extract(obj); - static_assert(sizeof(map.count()) <= sizeof(uint32_t), +uint32_t MapObject::size() { + static_assert(sizeof(Table(this).count()) <= sizeof(uint32_t), "map count must be precisely representable as a JS number"); - return map.count(); + return Table(this).count(); } bool MapObject::size_impl(JSContext* cx, const CallArgs& args) { - RootedObject obj(cx, &args.thisv().toObject()); - args.rval().setNumber(size(cx, obj)); + auto* mapObj = &args.thisv().toObject().as(); + args.rval().setNumber(mapObj->size()); return true; } @@ -897,16 +884,13 @@ bool MapObject::size(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -bool MapObject::get(JSContext* cx, HandleObject obj, HandleValue key, - MutableHandleValue rval) { - const ValueMap& map = extract(obj); - Rooted k(cx); - +bool MapObject::get(JSContext* cx, const Value& key, MutableHandleValue rval) { + HashableValue k; if (!k.setValue(cx, key)) { return false; } - if (const ValueMap::Entry* p = map.get(k)) { + if (const Table::Entry* p = Table(this).get(k)) { rval.set(p->value); } else { rval.setUndefined(); @@ -916,8 +900,8 @@ bool MapObject::get(JSContext* cx, HandleObject obj, HandleValue key, } bool MapObject::get_impl(JSContext* cx, const CallArgs& args) { - RootedObject obj(cx, &args.thisv().toObject()); - return get(cx, obj, args.get(0), args.rval()); + auto* mapObj = &args.thisv().toObject().as(); + return mapObj->get(cx, args.get(0), args.rval()); } bool MapObject::get(JSContext* cx, unsigned argc, Value* vp) { @@ -926,27 +910,24 @@ bool MapObject::get(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -bool MapObject::has(JSContext* cx, HandleObject obj, HandleValue key, - bool* rval) { - const ValueMap& map = extract(obj); - Rooted k(cx); - +bool MapObject::has(JSContext* cx, const Value& key, bool* rval) { + HashableValue k; if (!k.setValue(cx, key)) { return false; } - *rval = map.has(k); + *rval = Table(this).has(k); return true; } bool MapObject::has_impl(JSContext* cx, const CallArgs& args) { + auto* mapObj = &args.thisv().toObject().as(); bool found; - RootedObject obj(cx, &args.thisv().toObject()); - if (has(cx, obj, args.get(0), &found)) { - args.rval().setBoolean(found); - return true; + if (!mapObj->has(cx, args.get(0), &found)) { + return false; } - return false; + args.rval().setBoolean(found); + return true; } bool MapObject::has(JSContext* cx, unsigned argc, Value* vp) { @@ -956,14 +937,10 @@ bool MapObject::has(JSContext* cx, unsigned argc, Value* vp) { } bool MapObject::set_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(MapObject::is(args.thisv())); - - MapObject* obj = &args.thisv().toObject().as(); - ARG0_KEY(cx, args, key); - if (!setWithHashableKey(cx, obj, key, args.get(1))) { + auto* mapObj = &args.thisv().toObject().as(); + if (!mapObj->set(cx, args.get(0), args.get(1))) { return false; } - args.rval().set(args.thisv()); return true; } @@ -974,48 +951,50 @@ bool MapObject::set(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -bool MapObject::delete_(JSContext* cx, HandleObject obj, HandleValue key, - bool* rval) { - MapObject* mapObject = &obj->as(); - Rooted k(cx); +#ifdef NIGHTLY_BUILD +bool MapObject::getOrInsert_impl(JSContext* cx, const CallArgs& args) { + auto* mapObj = &args.thisv().toObject().as(); + return mapObj->getOrInsert(cx, args.get(0), args.get(1), args.rval()); +} +bool MapObject::getOrInsert(JSContext* cx, unsigned argc, Value* vp) { + AutoJSMethodProfilerEntry pseudoFrame(cx, "Map.prototype", "getOrInsert"); + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, + args); +} +#endif // #ifdef NIGHTLY_BUILD + +bool MapObject::delete_(JSContext* cx, const Value& key, bool* rval) { + HashableValue k; if (!k.setValue(cx, key)) { return false; } - bool ok; - if (mapObject->isTenured()) { - ok = mapObject->tenuredTable()->remove(k, rval); + if (isTenured()) { + *rval = Table(this).remove(cx, k); } else { - ok = mapObject->nurseryTable()->remove(k, rval); + *rval = PreBarrieredTable(this).remove(cx, k); } - - if (!ok) { - ReportOutOfMemory(cx); - return false; - } - return true; } bool MapObject::delete_impl(JSContext* cx, const CallArgs& args) { // MapObject::trace does not trace deleted entries. Incremental GC therefore // requires that no HeapPtr objects pointing to heap values be left - // alive in the ValueMap. + // alive in the hash table. // - // OrderedHashMap::remove() doesn't destroy the removed entry. It merely - // calls OrderedHashMap::MapOps::makeEmpty. But that is sufficient, because - // makeEmpty clears the value by doing e->value = Value(), and in the case - // of a ValueMap, Value() means HeapPtr(), which is the same as + // OrderedHashMapImpl::remove() doesn't destroy the removed entry. It merely + // calls OrderedHashMapImpl::MapOps::makeEmpty. But that is sufficient, + // because makeEmpty clears the value by doing e->value = Value(), and in the + // case of Table, Value() means HeapPtr(), which is the same as // HeapPtr(UndefinedValue()). - MOZ_ASSERT(MapObject::is(args.thisv())); - RootedObject obj(cx, &args.thisv().toObject()); + auto* mapObj = &args.thisv().toObject().as(); bool found; - if (!delete_(cx, obj, args.get(0), &found)) { + if (!mapObj->delete_(cx, args.get(0), &found)) { return false; } - args.rval().setBoolean(found); return true; } @@ -1026,10 +1005,9 @@ bool MapObject::delete_(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -bool MapObject::iterator(JSContext* cx, IteratorKind kind, HandleObject obj, - MutableHandleValue iter) { - const ValueMap& map = extract(obj); - Rooted iterobj(cx, MapIteratorObject::create(cx, obj, &map, kind)); +bool MapObject::iterator(JSContext* cx, IteratorKind kind, + Handle obj, MutableHandleValue iter) { + JSObject* iterobj = MapIteratorObject::create(cx, obj, kind); if (!iterobj) { return false; } @@ -1039,12 +1017,12 @@ bool MapObject::iterator(JSContext* cx, IteratorKind kind, HandleObject obj, bool MapObject::iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind) { - RootedObject obj(cx, &args.thisv().toObject()); - return iterator(cx, kind, obj, args.rval()); + Rooted mapObj(cx, &args.thisv().toObject().as()); + return iterator(cx, kind, mapObj, args.rval()); } bool MapObject::keys_impl(JSContext* cx, const CallArgs& args) { - return iterator_impl(cx, args, Keys); + return iterator_impl(cx, args, IteratorKind::Keys); } bool MapObject::keys(JSContext* cx, unsigned argc, Value* vp) { @@ -1054,7 +1032,7 @@ bool MapObject::keys(JSContext* cx, unsigned argc, Value* vp) { } bool MapObject::values_impl(JSContext* cx, const CallArgs& args) { - return iterator_impl(cx, args, Values); + return iterator_impl(cx, args, IteratorKind::Values); } bool MapObject::values(JSContext* cx, unsigned argc, Value* vp) { @@ -1064,7 +1042,7 @@ bool MapObject::values(JSContext* cx, unsigned argc, Value* vp) { } bool MapObject::entries_impl(JSContext* cx, const CallArgs& args) { - return iterator_impl(cx, args, Entries); + return iterator_impl(cx, args, IteratorKind::Entries); } bool MapObject::entries(JSContext* cx, unsigned argc, Value* vp) { @@ -1074,9 +1052,10 @@ bool MapObject::entries(JSContext* cx, unsigned argc, Value* vp) { } bool MapObject::clear_impl(JSContext* cx, const CallArgs& args) { - RootedObject obj(cx, &args.thisv().toObject()); + auto* mapObj = &args.thisv().toObject().as(); + mapObj->clear(cx); args.rval().setUndefined(); - return clear(cx, obj); + return true; } bool MapObject::clear(JSContext* cx, unsigned argc, Value* vp) { @@ -1085,22 +1064,12 @@ bool MapObject::clear(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, is, clear_impl, args); } -bool MapObject::clear(JSContext* cx, HandleObject obj) { - MapObject* mapObject = &obj->as(); - - bool ok; - if (mapObject->isTenured()) { - ok = mapObject->tenuredTable()->clear(); +void MapObject::clear(JSContext* cx) { + if (isTenured()) { + Table(this).clear(cx); } else { - ok = mapObject->nurseryTable()->clear(); + PreBarrieredTable(this).clear(cx); } - - if (!ok) { - ReportOutOfMemory(cx); - return false; - } - - return true; } /*** SetIterator ************************************************************/ @@ -1126,23 +1095,15 @@ const JSClass SetIteratorObject::class_ = { "Set Iterator", JSCLASS_HAS_RESERVED_SLOTS(SetIteratorObject::SlotCount) | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE, - &SetIteratorObjectClassOps, JS_NULL_CLASS_SPEC, - &SetIteratorObjectClassExtension}; + &SetIteratorObjectClassOps, + JS_NULL_CLASS_SPEC, + &SetIteratorObjectClassExtension, +}; const JSFunctionSpec SetIteratorObject::methods[] = { - JS_SELF_HOSTED_FN("next", "SetIteratorNext", 0, 0), JS_FS_END}; - -static inline ValueSet::Range* SetIteratorObjectRange(NativeObject* obj) { - MOZ_ASSERT(obj->is()); - return obj->maybePtrFromReservedSlot( - SetIteratorObject::RangeSlot); -} - -inline SetObject::IteratorKind SetIteratorObject::kind() const { - int32_t i = getReservedSlot(KindSlot).toInt32(); - MOZ_ASSERT(i == SetObject::Values || i == SetObject::Entries); - return SetObject::IteratorKind(i); -} + JS_SELF_HOSTED_FN("next", "SetIteratorNext", 0, 0), + JS_FS_END, +}; /* static */ bool GlobalObject::initSetIteratorProto(JSContext* cx, @@ -1161,16 +1122,18 @@ bool GlobalObject::initSetIteratorProto(JSContext* cx, !DefineToStringTag(cx, proto, cx->names().Set_Iterator_)) { return false; } + if (!JSObject::setHasFuseProperty(cx, proto)) { + return false; + } global->initBuiltinProto(ProtoKind::SetIteratorProto, proto); return true; } -SetIteratorObject* SetIteratorObject::create(JSContext* cx, HandleObject obj, - ValueSet* data, - SetObject::IteratorKind kind) { - MOZ_ASSERT(kind != SetObject::Keys); +SetIteratorObject* SetIteratorObject::create(JSContext* cx, + Handle setobj, + Kind kind) { + MOZ_ASSERT(kind != Kind::Keys); - Handle setobj(obj.as()); Rooted global(cx, &setobj->global()); Rooted proto( cx, GlobalObject::getOrCreateSetIteratorPrototype(cx, global)); @@ -1184,44 +1147,16 @@ SetIteratorObject* SetIteratorObject::create(JSContext* cx, HandleObject obj, return nullptr; } - iterobj->init(setobj, kind); - - constexpr size_t BufferSize = - RoundUp(sizeof(ValueSet::Range), gc::CellAlignBytes); - - Nursery& nursery = cx->nursery(); - void* buffer = - nursery.allocateBufferSameLocation(iterobj, BufferSize, js::MallocArena); - if (!buffer) { - // Retry with |iterobj| and |buffer| forcibly tenured. - iterobj = NewTenuredObjectWithGivenProto(cx, proto); - if (!iterobj) { - return nullptr; - } - - iterobj->init(setobj, kind); - - buffer = nursery.allocateBufferSameLocation(iterobj, BufferSize, - js::MallocArena); - if (!buffer) { + if (IsInsideNursery(iterobj) && + !HasRegisteredNurseryIterators(setobj.get())) { + if (!cx->nursery().addSetWithNurseryIterators(setobj)) { ReportOutOfMemory(cx); return nullptr; } + SetRegisteredNurseryIterators(setobj.get(), true); } - bool insideNursery = IsInsideNursery(iterobj); - MOZ_ASSERT(insideNursery == nursery.isInside(buffer)); - - if (insideNursery && !HasNurseryMemory(setobj.get())) { - if (!cx->nursery().addSetWithNurseryMemory(setobj)) { - ReportOutOfMemory(cx); - return nullptr; - } - SetHasNurseryMemory(setobj.get(), true); - } - - auto range = data->createRange(buffer, insideNursery); - iterobj->setReservedSlot(RangeSlot, PrivateValue(range)); + SetObject::Table(setobj).initIterator(iterobj, kind); return iterobj; } @@ -1229,58 +1164,28 @@ SetIteratorObject* SetIteratorObject::create(JSContext* cx, HandleObject obj, void SetIteratorObject::finalize(JS::GCContext* gcx, JSObject* obj) { MOZ_ASSERT(gcx->onMainThread()); MOZ_ASSERT(!IsInsideNursery(obj)); - - auto range = SetIteratorObjectRange(&obj->as()); - MOZ_ASSERT(!gcx->runtime()->gc.nursery().isInside(range)); - - // Bug 1560019: Malloc memory associated with SetIteratorObjects is not - // currently tracked. - gcx->deleteUntracked(range); + if (obj->as().isActive()) { + obj->as().unlink(); + } } size_t SetIteratorObject::objectMoved(JSObject* obj, JSObject* old) { - if (!IsInsideNursery(old)) { - return 0; - } - SetIteratorObject* iter = &obj->as(); - ValueSet::Range* range = SetIteratorObjectRange(iter); - if (!range) { + if (!iter->isActive()) { return 0; } - - Nursery& nursery = iter->runtimeFromMainThread()->gc.nursery(); - if (!nursery.isInside(range)) { - nursery.removeMallocedBufferDuringMinorGC(range); + if (IsInsideNursery(old)) { + SetObject* setObj = iter->target(); + SetObject::Table(setObj).relinkNurseryIterator(iter); + } else { + iter->updateListAfterMove(&old->as()); } - - size_t size = RoundUp(sizeof(ValueSet::Range), gc::CellAlignBytes); - ; - AutoEnterOOMUnsafeRegion oomUnsafe; - void* buffer = nursery.allocateBufferSameLocation(obj, size, js::MallocArena); - if (!buffer) { - oomUnsafe.crash("SetIteratorObject::objectMoved"); - } - - bool iteratorIsInNursery = IsInsideNursery(obj); - MOZ_ASSERT(iteratorIsInNursery == nursery.isInside(buffer)); - auto* newRange = new (buffer) ValueSet::Range(*range, iteratorIsInNursery); - range->~Range(); - iter->setReservedSlot(SetIteratorObject::RangeSlot, PrivateValue(newRange)); - - if (iteratorIsInNursery && iter->target()) { - SetHasNurseryMemory(iter->target(), true); - } - - return size; + return 0; } SetObject* SetIteratorObject::target() const { + MOZ_ASSERT(isActive(), "only active iterators have a target object"); Value value = getFixedSlot(TargetSlot); - if (value.isUndefined()) { - return nullptr; - } - return &MaybeForwarded(&value.toObject())->as(); } @@ -1299,20 +1204,16 @@ bool SetIteratorObject::next(SetIteratorObject* setIterator, MOZ_ASSERT(resultObj->getDenseInitializedLength() == 1); MOZ_ASSERT(resultObj->getDenseCapacity() >= 1); - ValueSet::Range* range = SetIteratorObjectRange(setIterator); - if (!range) { + if (!setIterator->isActive()) { + // Already done. return true; } - if (range->empty()) { - DestroyRange(setIterator, range); - setIterator->setReservedSlot(RangeSlot, PrivateValue(nullptr)); - return true; - } - - resultObj->setDenseElement(0, range->front().get()); - range->popFront(); - return false; + auto storeResult = [resultObj](Kind kind, const auto& element) { + resultObj->setDenseElement(0, element.get()); + }; + SetObject* setObj = setIterator->target(); + return SetObject::Table(setObj).iteratorNext(setIterator, storeResult); } /* static */ @@ -1345,7 +1246,8 @@ const JSClassOps SetObject::classOps_ = { }; const ClassSpec SetObject::classSpec_ = { - GenericCreateConstructor, + GenericCreateConstructor, GenericCreatePrototype, nullptr, SetObject::staticProperties, @@ -1354,15 +1256,17 @@ const ClassSpec SetObject::classSpec_ = { SetObject::finishInit, }; +const ClassExtension SetObject::classExtension_ = { + SetObject::objectMoved, // objectMovedOp +}; + const JSClass SetObject::class_ = { "Set", JSCLASS_DELAY_METADATA_BUILDER | JSCLASS_HAS_RESERVED_SLOTS(SetObject::SlotCount) | - JSCLASS_HAS_CACHED_PROTO(JSProto_Set) | JSCLASS_FOREGROUND_FINALIZE | + JSCLASS_HAS_CACHED_PROTO(JSProto_Set) | JSCLASS_BACKGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE, - &SetObject::classOps_, - &SetObject::classSpec_, -}; + &SetObject::classOps_, &SetObject::classSpec_, &SetObject::classExtension_}; const JSClass SetObject::protoClass_ = { "Set.prototype", @@ -1379,8 +1283,8 @@ const JSPropertySpec SetObject::properties[] = { const JSFunctionSpec SetObject::methods[] = { JS_INLINABLE_FN("has", has, 1, 0, SetHas), - JS_FN("add", add, 1, 0), - JS_FN("delete", delete_, 1, 0), + JS_INLINABLE_FN("add", add, 1, 0, SetAdd), + JS_INLINABLE_FN("delete", delete_, 1, 0, SetDelete), JS_FN("entries", entries, 0, 0), JS_FN("clear", clear, 0, 0), JS_SELF_HOSTED_FN("forEach", "SetForEach", 2, 0), @@ -1426,87 +1330,114 @@ const JSPropertySpec SetObject::staticProperties[] = { // 23.2.3.11 Set.prototype[@@iterator]() // See above. RootedId iteratorId(cx, PropertyKey::Symbol(cx->wellKnownSymbols().iterator)); - return NativeDefineDataProperty(cx, nativeProto, iteratorId, valuesFn, 0); + if (!NativeDefineDataProperty(cx, nativeProto, iteratorId, valuesFn, 0)) { + return false; + } + + return JSObject::setHasFuseProperty(cx, nativeProto); } -bool SetObject::keys(JSContext* cx, HandleObject obj, - JS::MutableHandle> keys) { - ValueSet* set = obj->as().getData(); - if (!set) { - return false; - } - - for (ValueSet::Range r = set->all(); !r.empty(); r.popFront()) { - if (!keys.append(r.front().get())) { - return false; - } - } - - return true; +bool SetObject::keys(JS::MutableHandle> keys) { + auto appendEntry = [&keys](auto& entry) { return keys.append(entry.get()); }; + return Table(this).forEachEntry(appendEntry); } -bool SetObject::add(JSContext* cx, HandleObject obj, HandleValue k) { - ValueSet* set = obj->as().getData(); - if (!set) { +bool SetObject::add(JSContext* cx, const Value& key) { + HashableValue k; + if (!k.setValue(cx, key)) { return false; } + return addHashableValue(cx, k); +} - Rooted key(cx); - if (!key.setValue(cx, k)) { - return false; - } - - if (!PostWriteBarrier(&obj->as(), key.get()) || - !set->put(key.get())) { +bool SetObject::addHashableValue(JSContext* cx, const HashableValue& value) { + bool needsPostBarriers = isTenured(); + if (needsPostBarriers && !PostWriteBarrier(this, value)) { ReportOutOfMemory(cx); return false; } - return true; + return Table(this).put(cx, value); +} + +SetObject* SetObject::createWithProto(JSContext* cx, HandleObject proto, + NewObjectKind newKind) { + MOZ_ASSERT(proto); + + gc::AllocKind allocKind = gc::GetGCObjectKind(SlotCount); + + AutoSetNewObjectMetadata metadata(cx); + auto* setObj = + NewObjectWithGivenProtoAndKinds(cx, proto, allocKind, newKind); + if (!setObj) { + return nullptr; + } + + UnbarrieredTable(setObj).initSlots(); + setObj->initReservedSlot(NurseryKeysSlot, PrivateValue(nullptr)); + setObj->initReservedSlot(RegisteredNurseryIteratorsSlot, BooleanValue(false)); + return setObj; } SetObject* SetObject::create(JSContext* cx, HandleObject proto /* = nullptr */) { - auto set = cx->make_unique(cx->zone(), - cx->realm()->randomHashCodeScrambler()); - if (!set) { + if (proto) { + return createWithProto(cx, proto, GenericObject); + } + + // This is the common case so use the template object's shape to optimize the + // allocation. + SetObject* templateObj = GlobalObject::getOrCreateSetTemplateObject(cx); + if (!templateObj) { return nullptr; } - if (!set->init()) { - ReportOutOfMemory(cx); - return nullptr; - } + gc::AllocKind allocKind = templateObj->asTenured().getAllocKind(); + MOZ_ASSERT(gc::GetGCKindSlots(allocKind) >= SlotCount); + MOZ_ASSERT(gc::IsBackgroundFinalized(allocKind)); AutoSetNewObjectMetadata metadata(cx); - SetObject* obj = NewObjectWithClassProto(cx, proto); - if (!obj) { + Rooted shape(cx, templateObj->sharedShape()); + auto* setObj = + NativeObject::create(cx, allocKind, gc::Heap::Default, shape); + if (!setObj) { return nullptr; } - bool insideNursery = IsInsideNursery(obj); - if (insideNursery && !cx->nursery().addSetWithNurseryMemory(obj)) { - ReportOutOfMemory(cx); + UnbarrieredTable(setObj).initSlots(); + setObj->initReservedSlot(NurseryKeysSlot, PrivateValue(nullptr)); + setObj->initReservedSlot(RegisteredNurseryIteratorsSlot, BooleanValue(false)); + return setObj; +} + +// static +SetObject* GlobalObject::getOrCreateSetTemplateObject(JSContext* cx) { + GlobalObjectData& data = cx->global()->data(); + if (SetObject* obj = data.setObjectTemplate) { + return obj; + } + + Rooted proto(cx, + GlobalObject::getOrCreatePrototype(cx, JSProto_Set)); + if (!proto) { + return nullptr; + } + auto* setObj = SetObject::createWithProto(cx, proto, TenuredObject); + if (!setObj) { return nullptr; } - InitReservedSlot(obj, DataSlot, set.release(), MemoryUse::MapObjectTable); - obj->initReservedSlot(NurseryKeysSlot, PrivateValue(nullptr)); - obj->initReservedSlot(HasNurseryMemorySlot, JS::BooleanValue(insideNursery)); - return obj; + data.setObjectTemplate.init(setObj); + return setObj; } void SetObject::trace(JSTracer* trc, JSObject* obj) { SetObject* setobj = static_cast(obj); - if (ValueSet* set = setobj->getData()) { - set->trace(trc); - } + Table(setobj).trace(trc); } size_t SetObject::sizeOfData(mozilla::MallocSizeOf mallocSizeOf) { size_t size = 0; - if (ValueSet* set = getData()) { - size += set->sizeOfIncludingThis(mallocSizeOf); - } + size += Table(this).sizeOfExcludingObject(mallocSizeOf); if (NurseryKeysVector* nurseryKeys = GetNurseryKeys(this)) { size += nurseryKeys->sizeOfIncludingThis(mallocSizeOf); } @@ -1514,17 +1445,41 @@ size_t SetObject::sizeOfData(mozilla::MallocSizeOf mallocSizeOf) { } void SetObject::finalize(JS::GCContext* gcx, JSObject* obj) { - MOZ_ASSERT(gcx->onMainThread()); - SetObject* setobj = static_cast(obj); - if (ValueSet* set = setobj->getData()) { - MOZ_ASSERT_IF(obj->isTenured(), !set->hasNurseryRanges()); - gcx->delete_(obj, set, MemoryUse::MapObjectTable); - } + SetObject* setObj = &obj->as(); + MOZ_ASSERT(!IsInsideNursery(setObj)); + MOZ_ASSERT(!UnbarrieredTable(setObj).hasNurseryIterators()); + +#ifdef DEBUG + // If we're finalizing a tenured set then it cannot contain nursery things, + // because we evicted the nursery at the start of collection and writing a + // nursery thing into the set would require it to be live, which means it + // would have been marked. + UnbarrieredTable(setObj).forEachEntryUpTo(1000, [](auto& entry) { + Value key = entry; + MOZ_ASSERT_IF(key.isGCThing(), !IsInsideNursery(key.toGCThing())); + }); +#endif + + // Finalized tenured sets do not contain nursery GC things, so do not require + // post barriers. Pre barriers are not required for finalization. + UnbarrieredTable(setObj).destroy(gcx); } -void SetObject::clearNurseryRangesBeforeMinorGC() { - getTableUnchecked()->destroyNurseryRanges(); - SetHasNurseryMemory(this, false); +size_t SetObject::objectMoved(JSObject* obj, JSObject* old) { + auto* setObj = &obj->as(); + + Table(setObj).updateIteratorsAfterMove(&old->as()); + + if (IsInsideNursery(old)) { + Nursery& nursery = setObj->runtimeFromMainThread()->gc.nursery(); + Table(setObj).maybeMoveBufferOnPromotion(nursery); + } + + return 0; +} + +void SetObject::clearNurseryIteratorsBeforeMinorGC() { + Table(this).clearNurseryIterators(); } /* static */ @@ -1532,30 +1487,105 @@ SetObject* SetObject::sweepAfterMinorGC(JS::GCContext* gcx, SetObject* setobj) { Nursery& nursery = gcx->runtime()->gc.nursery(); bool wasInCollectedRegion = nursery.inCollectedRegion(setobj); if (wasInCollectedRegion && !IsForwarded(setobj)) { - finalize(gcx, setobj); + // This SetObject is dead. return nullptr; } setobj = MaybeForwarded(setobj); - bool insideNursery = IsInsideNursery(setobj); - if (insideNursery) { - SetHasNurseryMemory(setobj, true); - } - - if (wasInCollectedRegion && setobj->isTenured()) { - AddCellMemory(setobj, sizeof(ValueSet), MemoryUse::MapObjectTable); - } - - if (!HasNurseryMemory(setobj)) { - return nullptr; - } - - return setobj; + // Keep |setobj| registered with the nursery if it still has nursery + // iterators. + bool hasNurseryIterators = Table(setobj).hasNurseryIterators(); + SetRegisteredNurseryIterators(setobj, hasNurseryIterators); + return hasNurseryIterators ? setobj : nullptr; } -bool SetObject::isBuiltinAdd(HandleValue add) { - return IsNativeFunction(add, SetObject::add); +bool SetObject::tryOptimizeCtorWithIterable(JSContext* cx, + const Value& iterableVal, + bool* optimized) { + MOZ_ASSERT(!iterableVal.isNullOrUndefined()); + MOZ_ASSERT(!*optimized); + + if (!CanOptimizeMapOrSetCtorWithIterable(SetObject::add, this, + cx)) { + return true; + } + + if (!iterableVal.isObject()) { + return true; + } + JSObject* iterable = &iterableVal.toObject(); + + // Fast path for `new Set(array)`. + if (IsOptimizableArrayForMapOrSetCtor(iterable, cx)) { + ArrayObject* array = &iterable->as(); + uint32_t len = array->getDenseInitializedLength(); + + for (uint32_t index = 0; index < len; index++) { + Value keyVal = array->getDenseElement(index); + MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE)); + if (!add(cx, keyVal)) { + return false; + } + } + + *optimized = true; + return true; + } + + // Fast path for `new Set(set)`. + if (IsSetObjectWithDefaultIterator(iterable, cx)) { + auto* iterableSet = &iterable->as(); + if (!IsSetObjectWithDefaultIterator(iterableSet, cx)) { + return true; + } + auto addEntry = [cx, this](auto& entry) { + return addHashableValue(cx, entry); + }; + if (!Table(iterableSet).forEachEntry(addEntry)) { + return false; + } + *optimized = true; + return true; + } + + return true; +} + +// static +SetObject* SetObject::createFromIterable(JSContext* cx, Handle proto, + Handle iterable, + Handle allocatedFromJit) { + // A null-or-undefined |iterable| is quite common and we check for this in JIT + // code. + MOZ_ASSERT_IF(allocatedFromJit, !iterable.isNullOrUndefined()); + + Rooted obj(cx, allocatedFromJit); + if (!obj) { + obj = SetObject::create(cx, proto); + if (!obj) { + return nullptr; + } + } + + if (!iterable.isNullOrUndefined()) { + bool optimized = false; + if (!obj->tryOptimizeCtorWithIterable(cx, iterable, &optimized)) { + return nullptr; + } + if (!optimized) { + FixedInvokeArgs<1> args(cx); + args[0].set(iterable); + + RootedValue thisv(cx, ObjectValue(*obj)); + if (!CallSelfHostedFunction(cx, cx->names().SetConstructorInit, thisv, + args, args.rval())) { + return nullptr; + } + } + } + + return obj; } bool SetObject::construct(JSContext* cx, unsigned argc, Value* vp) { @@ -1571,89 +1601,30 @@ bool SetObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - Rooted obj(cx, SetObject::create(cx, proto)); + SetObject* obj = SetObject::createFromIterable(cx, proto, args.get(0)); if (!obj) { return false; } - if (!args.get(0).isNullOrUndefined()) { - RootedValue iterable(cx, args[0]); - bool optimized = false; - if (!IsOptimizableInitForSet(cx, obj, iterable, &optimized)) { - return false; - } - - if (optimized) { - RootedValue keyVal(cx); - Rooted key(cx); - ValueSet* set = obj->getData(); - Rooted array(cx, &iterable.toObject().as()); - for (uint32_t index = 0; index < array->getDenseInitializedLength(); - ++index) { - keyVal.set(array->getDenseElement(index)); - MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE)); - - if (!key.setValue(cx, keyVal)) { - return false; - } - if (!PostWriteBarrier(obj, key.get()) || !set->put(key.get())) { - ReportOutOfMemory(cx); - return false; - } - } - } else { - FixedInvokeArgs<1> args2(cx); - args2[0].set(args[0]); - - RootedValue thisv(cx, ObjectValue(*obj)); - if (!CallSelfHostedFunction(cx, cx->names().SetConstructorInit, thisv, - args2, args2.rval())) { - return false; - } - } - } - args.rval().setObject(*obj); return true; } bool SetObject::is(HandleValue v) { - return v.isObject() && v.toObject().hasClass(&class_) && - !v.toObject().as().getReservedSlot(DataSlot).isUndefined(); + return v.isObject() && v.toObject().hasClass(&class_); } -bool SetObject::is(HandleObject o) { - return o->hasClass(&class_) && - !o->as().getReservedSlot(DataSlot).isUndefined(); -} +bool SetObject::is(HandleObject o) { return o->hasClass(&class_); } -ValueSet& SetObject::extract(HandleObject o) { - MOZ_ASSERT(o->hasClass(&SetObject::class_)); - return *o->as().getData(); -} - -ValueSet& SetObject::extract(const CallArgs& args) { - MOZ_ASSERT(args.thisv().isObject()); - MOZ_ASSERT(args.thisv().toObject().hasClass(&SetObject::class_)); - return *static_cast(args.thisv().toObject()).getData(); -} - -uint32_t SetObject::size(JSContext* cx, HandleObject obj) { - MOZ_ASSERT(SetObject::is(obj)); - ValueSet& set = extract(obj); - static_assert(sizeof(set.count()) <= sizeof(uint32_t), +uint32_t SetObject::size() { + static_assert(sizeof(Table(this).count()) <= sizeof(uint32_t), "set count must be precisely representable as a JS number"); - return set.count(); + return Table(this).count(); } bool SetObject::size_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(is(args.thisv())); - - ValueSet& set = extract(args); - static_assert(sizeof(set.count()) <= sizeof(uint32_t), - "set count must be precisely representable as a JS number"); - args.rval().setNumber(set.count()); + auto* setObj = &args.thisv().toObject().as(); + args.rval().setNumber(setObj->size()); return true; } @@ -1664,26 +1635,22 @@ bool SetObject::size(JSContext* cx, unsigned argc, Value* vp) { } bool SetObject::has_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(is(args.thisv())); - - ValueSet& set = extract(args); - ARG0_KEY(cx, args, key); - args.rval().setBoolean(set.has(key)); + auto* setObj = &args.thisv().toObject().as(); + bool found; + if (!setObj->has(cx, args.get(0), &found)) { + return false; + } + args.rval().setBoolean(found); return true; } -bool SetObject::has(JSContext* cx, HandleObject obj, HandleValue key, - bool* rval) { - MOZ_ASSERT(SetObject::is(obj)); - - ValueSet& set = extract(obj); - Rooted k(cx); - +bool SetObject::has(JSContext* cx, const Value& key, bool* rval) { + HashableValue k; if (!k.setValue(cx, key)) { return false; } - *rval = set.has(k); + *rval = Table(this).has(k); return true; } @@ -1694,13 +1661,8 @@ bool SetObject::has(JSContext* cx, unsigned argc, Value* vp) { } bool SetObject::add_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(is(args.thisv())); - - ValueSet& set = extract(args); - ARG0_KEY(cx, args, key); - if (!PostWriteBarrier(&args.thisv().toObject().as(), key.get()) || - !set.put(key.get())) { - ReportOutOfMemory(cx); + auto* setObj = &args.thisv().toObject().as(); + if (!setObj->add(cx, args.get(0))) { return false; } args.rval().set(args.thisv()); @@ -1713,32 +1675,20 @@ bool SetObject::add(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -bool SetObject::delete_(JSContext* cx, HandleObject obj, HandleValue key, - bool* rval) { - MOZ_ASSERT(SetObject::is(obj)); - - ValueSet& set = extract(obj); - Rooted k(cx); - +bool SetObject::delete_(JSContext* cx, const Value& key, bool* rval) { + HashableValue k; if (!k.setValue(cx, key)) { return false; } - if (!set.remove(k, rval)) { - ReportOutOfMemory(cx); - return false; - } + *rval = Table(this).remove(cx, k); return true; } bool SetObject::delete_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(is(args.thisv())); - - ValueSet& set = extract(args); - ARG0_KEY(cx, args, key); + auto* setObj = &args.thisv().toObject().as(); bool found; - if (!set.remove(key, &found)) { - ReportOutOfMemory(cx); + if (!setObj->delete_(cx, args.get(0), &found)) { return false; } args.rval().setBoolean(found); @@ -1751,11 +1701,9 @@ bool SetObject::delete_(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -bool SetObject::iterator(JSContext* cx, IteratorKind kind, HandleObject obj, - MutableHandleValue iter) { - MOZ_ASSERT(SetObject::is(obj)); - ValueSet& set = extract(obj); - Rooted iterobj(cx, SetIteratorObject::create(cx, obj, &set, kind)); +bool SetObject::iterator(JSContext* cx, IteratorKind kind, + Handle obj, MutableHandleValue iter) { + JSObject* iterobj = SetIteratorObject::create(cx, obj, kind); if (!iterobj) { return false; } @@ -1765,19 +1713,12 @@ bool SetObject::iterator(JSContext* cx, IteratorKind kind, HandleObject obj, bool SetObject::iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind) { - Rooted setobj(cx, &args.thisv().toObject().as()); - ValueSet& set = *setobj->getData(); - Rooted iterobj(cx, - SetIteratorObject::create(cx, setobj, &set, kind)); - if (!iterobj) { - return false; - } - args.rval().setObject(*iterobj); - return true; + Rooted setObj(cx, &args.thisv().toObject().as()); + return iterator(cx, kind, setObj, args.rval()); } bool SetObject::values_impl(JSContext* cx, const CallArgs& args) { - return iterator_impl(cx, args, Values); + return iterator_impl(cx, args, IteratorKind::Values); } bool SetObject::values(JSContext* cx, unsigned argc, Value* vp) { @@ -1787,7 +1728,7 @@ bool SetObject::values(JSContext* cx, unsigned argc, Value* vp) { } bool SetObject::entries_impl(JSContext* cx, const CallArgs& args) { - return iterator_impl(cx, args, Entries); + return iterator_impl(cx, args, IteratorKind::Entries); } bool SetObject::entries(JSContext* cx, unsigned argc, Value* vp) { @@ -1796,22 +1737,11 @@ bool SetObject::entries(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, is, entries_impl, args); } -bool SetObject::clear(JSContext* cx, HandleObject obj) { - MOZ_ASSERT(SetObject::is(obj)); - ValueSet& set = extract(obj); - if (!set.clear()) { - ReportOutOfMemory(cx); - return false; - } - return true; -} +void SetObject::clear(JSContext* cx) { Table(this).clear(cx); } bool SetObject::clear_impl(JSContext* cx, const CallArgs& args) { - Rooted setobj(cx, &args.thisv().toObject().as()); - if (!setobj->getData()->clear()) { - ReportOutOfMemory(cx); - return false; - } + auto* setObj = &args.thisv().toObject().as(); + setObj->clear(cx); args.rval().setUndefined(); return true; } @@ -1832,17 +1762,13 @@ bool SetObject::copy(JSContext* cx, unsigned argc, Value* vp) { return false; } - ValueSet* set = result->getData(); - MOZ_ASSERT(set); - auto* from = &args[0].toObject().as(); - for (auto range = from->getData()->all(); !range.empty(); range.popFront()) { - HashableValue value = range.front().get(); - if (!PostWriteBarrier(result, value) || !set->put(value)) { - ReportOutOfMemory(cx); - return false; - } + auto addToResult = [cx, result](auto& entry) { + return result->addHashableValue(cx, entry); + }; + if (!Table(from).forEachEntry(addToResult)) { + return false; } args.rval().setObject(*result); @@ -1866,76 +1792,23 @@ static bool forEach(const char* funcName, JSContext* cx, HandleObject obj, return Call(cx, fval, obj, callbackFn, thisArg, &fval); } -// Handles Clear/Size for public jsapi map/set access -template -RetT CallObjFunc(RetT (*ObjFunc)(JSContext*, HandleObject), JSContext* cx, - HandleObject obj) { - CHECK_THREAD(cx); - cx->check(obj); +// RAII class that unwraps a wrapped Map or Set object and then enters its +// realm. +template +class MOZ_RAII AutoEnterTableRealm { + mozilla::Maybe ar_; + Rooted unwrapped_; - // Always unwrap, in case this is an xray or cross-compartment wrapper. - RootedObject unwrappedObj(cx); - unwrappedObj = UncheckedUnwrap(obj); - - // Enter the realm of the backing object before calling functions on - // it. - JSAutoRealm ar(cx, unwrappedObj); - return ObjFunc(cx, unwrappedObj); -} - -// Handles Has/Delete for public jsapi map/set access -bool CallObjFunc(bool (*ObjFunc)(JSContext* cx, HandleObject obj, - HandleValue key, bool* rval), - JSContext* cx, HandleObject obj, HandleValue key, bool* rval) { - CHECK_THREAD(cx); - cx->check(obj, key); - - // Always unwrap, in case this is an xray or cross-compartment wrapper. - RootedObject unwrappedObj(cx); - unwrappedObj = UncheckedUnwrap(obj); - JSAutoRealm ar(cx, unwrappedObj); - - // If we're working with a wrapped map/set, rewrap the key into the - // compartment of the unwrapped map/set. - RootedValue wrappedKey(cx, key); - if (obj != unwrappedObj) { - if (!JS_WrapValue(cx, &wrappedKey)) { - return false; - } + public: + AutoEnterTableRealm(JSContext* cx, JSObject* obj) : unwrapped_(cx) { + JSObject* unwrapped = UncheckedUnwrap(obj); + MOZ_ASSERT(unwrapped != obj); + MOZ_RELEASE_ASSERT(unwrapped->is()); + unwrapped_ = &unwrapped->as(); + ar_.emplace(cx, unwrapped_); } - return ObjFunc(cx, unwrappedObj, wrappedKey, rval); -} - -// Handles iterator generation for public jsapi map/set access -template -bool CallObjFunc(bool (*ObjFunc)(JSContext* cx, Iter kind, HandleObject obj, - MutableHandleValue iter), - JSContext* cx, Iter iterType, HandleObject obj, - MutableHandleValue rval) { - CHECK_THREAD(cx); - cx->check(obj); - - // Always unwrap, in case this is an xray or cross-compartment wrapper. - RootedObject unwrappedObj(cx); - unwrappedObj = UncheckedUnwrap(obj); - { - // Retrieve the iterator while in the unwrapped map/set's compartment, - // otherwise we'll crash on a compartment assert. - JSAutoRealm ar(cx, unwrappedObj); - if (!ObjFunc(cx, iterType, unwrappedObj, rval)) { - return false; - } - } - - // If the caller is in a different compartment than the map/set, rewrap the - // iterator object into the caller's compartment. - if (obj != unwrappedObj) { - if (!JS_WrapValue(cx, rval)) { - return false; - } - } - return true; -} + Handle unwrapped() const { return unwrapped_; } +}; /*** JS public APIs *********************************************************/ @@ -1944,7 +1817,15 @@ JS_PUBLIC_API JSObject* JS::NewMapObject(JSContext* cx) { } JS_PUBLIC_API uint32_t JS::MapSize(JSContext* cx, HandleObject obj) { - return CallObjFunc(&MapObject::size, cx, obj); + CHECK_THREAD(cx); + cx->check(obj); + + if (obj->is()) { + return obj.as()->size(); + } + + AutoEnterTableRealm enter(cx, obj); + return enter.unwrapped()->size(); } JS_PUBLIC_API bool JS::MapGet(JSContext* cx, HandleObject obj, HandleValue key, @@ -1952,32 +1833,21 @@ JS_PUBLIC_API bool JS::MapGet(JSContext* cx, HandleObject obj, HandleValue key, CHECK_THREAD(cx); cx->check(obj, key, rval); - // Unwrap the object, and enter its realm. If object isn't wrapped, - // this is essentially a noop. - RootedObject unwrappedObj(cx); - unwrappedObj = UncheckedUnwrap(obj); + if (obj->is()) { + return obj.as()->get(cx, key, rval); + } + { - JSAutoRealm ar(cx, unwrappedObj); - RootedValue wrappedKey(cx, key); - - // If we passed in a wrapper, wrap our key into its compartment now. - if (obj != unwrappedObj) { - if (!JS_WrapValue(cx, &wrappedKey)) { - return false; - } + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + if (!JS_WrapValue(cx, &wrappedKey)) { + return false; } - if (!MapObject::get(cx, unwrappedObj, wrappedKey, rval)) { + if (!enter.unwrapped()->get(cx, wrappedKey, rval)) { return false; } } - - // If we passed in a wrapper, wrap our return value on the way out. - if (obj != unwrappedObj) { - if (!JS_WrapValue(cx, rval)) { - return false; - } - } - return true; + return JS_WrapValue(cx, rval); } JS_PUBLIC_API bool JS::MapSet(JSContext* cx, HandleObject obj, HandleValue key, @@ -1985,53 +1855,128 @@ JS_PUBLIC_API bool JS::MapSet(JSContext* cx, HandleObject obj, HandleValue key, CHECK_THREAD(cx); cx->check(obj, key, val); - // Unwrap the object, and enter its compartment. If object isn't wrapped, - // this is essentially a noop. - RootedObject unwrappedObj(cx); - unwrappedObj = UncheckedUnwrap(obj); - { - JSAutoRealm ar(cx, unwrappedObj); - - // If we passed in a wrapper, wrap both key and value before adding to - // the map - RootedValue wrappedKey(cx, key); - RootedValue wrappedValue(cx, val); - if (obj != unwrappedObj) { - if (!JS_WrapValue(cx, &wrappedKey) || !JS_WrapValue(cx, &wrappedValue)) { - return false; - } - } - return MapObject::set(cx, unwrappedObj, wrappedKey, wrappedValue); + if (obj->is()) { + return obj.as()->set(cx, key, val); } + + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + Rooted wrappedValue(cx, val); + if (!JS_WrapValue(cx, &wrappedKey) || !JS_WrapValue(cx, &wrappedValue)) { + return false; + } + return enter.unwrapped()->set(cx, wrappedKey, wrappedValue); } JS_PUBLIC_API bool JS::MapHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval) { - return CallObjFunc(MapObject::has, cx, obj, key, rval); + CHECK_THREAD(cx); + cx->check(obj, key); + + if (obj->is()) { + return obj.as()->has(cx, key, rval); + } + + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + if (!JS_WrapValue(cx, &wrappedKey)) { + return false; + } + return enter.unwrapped()->has(cx, wrappedKey, rval); } +#ifdef NIGHTLY_BUILD +JS_PUBLIC_API bool JS::MapGetOrInsert(JSContext* cx, HandleObject obj, + HandleValue key, HandleValue val, + MutableHandleValue rval) { + CHECK_THREAD(cx); + cx->check(obj, key, val); + + if (obj->is()) { + return obj.as()->getOrInsert(cx, key, val, rval); + } + { + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + Rooted wrappedValue(cx, val); + if (!JS_WrapValue(cx, &wrappedKey) || !JS_WrapValue(cx, &wrappedValue)) { + return false; + } + if (!enter.unwrapped()->getOrInsert(cx, wrappedKey, wrappedValue, rval)) { + return false; + } + } + return JS_WrapValue(cx, rval); +} +#endif // #ifdef NIGHTLY_BUILD + JS_PUBLIC_API bool JS::MapDelete(JSContext* cx, HandleObject obj, HandleValue key, bool* rval) { - return CallObjFunc(MapObject::delete_, cx, obj, key, rval); + CHECK_THREAD(cx); + cx->check(obj, key); + + if (obj->is()) { + return obj.as()->delete_(cx, key, rval); + } + + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + if (!JS_WrapValue(cx, &wrappedKey)) { + return false; + } + return enter.unwrapped()->delete_(cx, wrappedKey, rval); } JS_PUBLIC_API bool JS::MapClear(JSContext* cx, HandleObject obj) { - return CallObjFunc(&MapObject::clear, cx, obj); + CHECK_THREAD(cx); + cx->check(obj); + + if (obj->is()) { + obj.as()->clear(cx); + return true; + } + + AutoEnterTableRealm enter(cx, obj); + enter.unwrapped()->clear(cx); + return true; +} + +template +[[nodiscard]] static bool CreateIterator( + JSContext* cx, typename TableObject::IteratorKind kind, + Handle obj, MutableHandle rval) { + CHECK_THREAD(cx); + cx->check(obj); + + if (obj->is()) { + return TableObject::iterator(cx, kind, obj.as(), rval); + } + + { + AutoEnterTableRealm enter(cx, obj); + if (!TableObject::iterator(cx, kind, enter.unwrapped(), rval)) { + return false; + } + } + return JS_WrapValue(cx, rval); } JS_PUBLIC_API bool JS::MapKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval) { - return CallObjFunc(&MapObject::iterator, cx, MapObject::Keys, obj, rval); + return CreateIterator(cx, MapObject::IteratorKind::Keys, obj, + rval); } JS_PUBLIC_API bool JS::MapValues(JSContext* cx, HandleObject obj, MutableHandleValue rval) { - return CallObjFunc(&MapObject::iterator, cx, MapObject::Values, obj, rval); + return CreateIterator(cx, MapObject::IteratorKind::Values, obj, + rval); } JS_PUBLIC_API bool JS::MapEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval) { - return CallObjFunc(&MapObject::iterator, cx, MapObject::Entries, obj, rval); + return CreateIterator(cx, MapObject::IteratorKind::Entries, obj, + rval); } JS_PUBLIC_API bool JS::MapForEach(JSContext* cx, HandleObject obj, @@ -2044,7 +1989,15 @@ JS_PUBLIC_API JSObject* JS::NewSetObject(JSContext* cx) { } JS_PUBLIC_API uint32_t JS::SetSize(JSContext* cx, HandleObject obj) { - return CallObjFunc(&SetObject::size, cx, obj); + CHECK_THREAD(cx); + cx->check(obj); + + if (obj->is()) { + return obj.as()->size(); + } + + AutoEnterTableRealm enter(cx, obj); + return enter.unwrapped()->size(); } JS_PUBLIC_API bool JS::SetAdd(JSContext* cx, HandleObject obj, @@ -2052,36 +2005,64 @@ JS_PUBLIC_API bool JS::SetAdd(JSContext* cx, HandleObject obj, CHECK_THREAD(cx); cx->check(obj, key); - // Unwrap the object, and enter its compartment. If object isn't wrapped, - // this is essentially a noop. - RootedObject unwrappedObj(cx); - unwrappedObj = UncheckedUnwrap(obj); - { - JSAutoRealm ar(cx, unwrappedObj); - - // If we passed in a wrapper, wrap key before adding to the set - RootedValue wrappedKey(cx, key); - if (obj != unwrappedObj) { - if (!JS_WrapValue(cx, &wrappedKey)) { - return false; - } - } - return SetObject::add(cx, unwrappedObj, wrappedKey); + if (obj->is()) { + return obj.as()->add(cx, key); } + + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + if (!JS_WrapValue(cx, &wrappedKey)) { + return false; + } + return enter.unwrapped()->add(cx, wrappedKey); } JS_PUBLIC_API bool JS::SetHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval) { - return CallObjFunc(SetObject::has, cx, obj, key, rval); + CHECK_THREAD(cx); + cx->check(obj, key); + + if (obj->is()) { + return obj.as()->has(cx, key, rval); + } + + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + if (!JS_WrapValue(cx, &wrappedKey)) { + return false; + } + return enter.unwrapped()->has(cx, wrappedKey, rval); } JS_PUBLIC_API bool JS::SetDelete(JSContext* cx, HandleObject obj, HandleValue key, bool* rval) { - return CallObjFunc(SetObject::delete_, cx, obj, key, rval); + CHECK_THREAD(cx); + cx->check(obj, key); + + if (obj->is()) { + return obj.as()->delete_(cx, key, rval); + } + + AutoEnterTableRealm enter(cx, obj); + Rooted wrappedKey(cx, key); + if (!JS_WrapValue(cx, &wrappedKey)) { + return false; + } + return enter.unwrapped()->delete_(cx, wrappedKey, rval); } JS_PUBLIC_API bool JS::SetClear(JSContext* cx, HandleObject obj) { - return CallObjFunc(&SetObject::clear, cx, obj); + CHECK_THREAD(cx); + cx->check(obj); + + if (obj->is()) { + obj.as()->clear(cx); + return true; + } + + AutoEnterTableRealm enter(cx, obj); + enter.unwrapped()->clear(cx); + return true; } JS_PUBLIC_API bool JS::SetKeys(JSContext* cx, HandleObject obj, @@ -2091,12 +2072,14 @@ JS_PUBLIC_API bool JS::SetKeys(JSContext* cx, HandleObject obj, JS_PUBLIC_API bool JS::SetValues(JSContext* cx, HandleObject obj, MutableHandleValue rval) { - return CallObjFunc(&SetObject::iterator, cx, SetObject::Values, obj, rval); + return CreateIterator(cx, SetObject::IteratorKind::Values, obj, + rval); } JS_PUBLIC_API bool JS::SetEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval) { - return CallObjFunc(&SetObject::iterator, cx, SetObject::Entries, obj, rval); + return CreateIterator(cx, SetObject::IteratorKind::Entries, obj, + rval); } JS_PUBLIC_API bool JS::SetForEach(JSContext* cx, HandleObject obj, diff --git a/src/third_party/mozjs/extract/js/src/builtin/MapObject.h b/src/third_party/mozjs/extract/js/src/builtin/MapObject.h index d47797eff74..1b08f04b24c 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/MapObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/MapObject.h @@ -9,10 +9,9 @@ #include "mozilla/MemoryReporting.h" -#include "builtin/SelfHostingDefines.h" +#include "builtin/OrderedHashTableObject.h" #include "vm/JSObject.h" #include "vm/NativeObject.h" -#include "vm/PIC.h" namespace js { @@ -31,7 +30,7 @@ class HashableValue { HashableValue() : value(UndefinedValue()) {} explicit HashableValue(JSWhyMagic whyMagic) : value(MagicValue(whyMagic)) {} - [[nodiscard]] bool setValue(JSContext* cx, HandleValue v); + [[nodiscard]] bool setValue(JSContext* cx, const Value& v); HashNumber hash(const mozilla::HashCodeScrambler& hcs) const; // Value equality. Separate BigInt instances may compare equal. @@ -100,75 +99,76 @@ struct HashableValueHasher { static void makeEmpty(Key* vp) { vp->set(HashableValue(JS_HASH_KEY_EMPTY)); } }; -using ValueMap = OrderedHashMap, HeapPtr, - HashableValueHasher, CellAllocPolicy>; - -using ValueSet = OrderedHashSet, - HashableValueHasher, CellAllocPolicy>; - template class OrderedHashTableRef; struct UnbarrieredHashPolicy; -class MapObject : public NativeObject { +class MapObject : public OrderedHashMapObject { public: - enum IteratorKind { Keys, Values, Entries }; - static_assert( - Keys == ITEM_KIND_KEY, - "IteratorKind Keys must match self-hosting define for item kind key."); - static_assert(Values == ITEM_KIND_VALUE, - "IteratorKind Values must match self-hosting define for item " - "kind value."); - static_assert( - Entries == ITEM_KIND_KEY_AND_VALUE, - "IteratorKind Entries must match self-hosting define for item kind " - "key-and-value."); + using Table = OrderedHashMapImpl, HeapPtr, + HashableValueHasher>; + + // PreBarrieredTable has the same memory layout as Table but doesn't have + // wrappers that perform post barriers on the keys/values. Used when the + // MapObject is in the nursery. + using PreBarrieredTable = + OrderedHashMapImpl, PreBarriered, + HashableValueHasher>; + + // UnbarrieredTable has the same memory layout as Table but doesn't have any + // wrappers that perform barriers on the keys/values. Used to allocate and + // delete the table and when updating the nursery allocated keys map during + // minor GC. + using UnbarrieredTable = + OrderedHashMapImpl; + + friend class OrderedHashTableRef; + + enum { + NurseryKeysSlot = Table::SlotCount, + RegisteredNurseryIteratorsSlot, + SlotCount + }; + + using IteratorKind = TableIteratorObject::Kind; static const JSClass class_; static const JSClass protoClass_; - enum { DataSlot, NurseryKeysSlot, HasNurseryMemorySlot, SlotCount }; - - [[nodiscard]] static bool getKeysAndValuesInterleaved( - HandleObject obj, JS::MutableHandle> entries); + [[nodiscard]] bool getKeysAndValuesInterleaved( + JS::MutableHandle> entries); [[nodiscard]] static bool entries(JSContext* cx, unsigned argc, Value* vp); + + static MapObject* createWithProto(JSContext* cx, HandleObject proto, + NewObjectKind newKind); static MapObject* create(JSContext* cx, HandleObject proto = nullptr); + static MapObject* createFromIterable( + JSContext* cx, Handle proto, Handle iterable, + Handle allocatedFromJit = nullptr); // Publicly exposed Map calls for JSAPI access (webidl maplike/setlike // interfaces, etc.) - static uint32_t size(JSContext* cx, HandleObject obj); - [[nodiscard]] static bool get(JSContext* cx, HandleObject obj, - HandleValue key, MutableHandleValue rval); - [[nodiscard]] static bool has(JSContext* cx, HandleObject obj, - HandleValue key, bool* rval); - [[nodiscard]] static bool delete_(JSContext* cx, HandleObject obj, - HandleValue key, bool* rval); + uint32_t size(); + [[nodiscard]] bool get(JSContext* cx, const Value& key, + MutableHandleValue rval); + [[nodiscard]] bool has(JSContext* cx, const Value& key, bool* rval); +#ifdef NIGHTLY_BUILD + [[nodiscard]] bool getOrInsert(JSContext* cx, const Value& key, + const Value& val, MutableHandleValue rval); +#endif // #ifdef NIGHTLY_BUILD + [[nodiscard]] bool delete_(JSContext* cx, const Value& key, bool* rval); // Set call for public JSAPI exposure. Does not actually return map object // as stated in spec, expects caller to return a value. for instance, with // webidl maplike/setlike, should return interface object. - [[nodiscard]] static bool set(JSContext* cx, HandleObject obj, - HandleValue key, HandleValue val); - [[nodiscard]] static bool clear(JSContext* cx, HandleObject obj); + [[nodiscard]] bool set(JSContext* cx, const Value& key, const Value& val); + void clear(JSContext* cx); [[nodiscard]] static bool iterator(JSContext* cx, IteratorKind kind, - HandleObject obj, MutableHandleValue iter); + Handle obj, + MutableHandleValue iter); - // OrderedHashMap with the same memory layout as ValueMap but without wrappers - // that perform post barriers. Used when the owning JS object is in the - // nursery. - using PreBarrieredTable = - OrderedHashMap, PreBarriered, - HashableValueHasher, CellAllocPolicy>; - - // OrderedHashMap with the same memory layout as ValueMap but without any - // wrappers that perform barriers. Used when updating the nursery allocated - // keys map during minor GC. - using UnbarrieredTable = - OrderedHashMap; - friend class OrderedHashTableRef; - - void clearNurseryRangesBeforeMinorGC(); + void clearNurseryIteratorsBeforeMinorGC(); // Sweeps a map that had nursery memory associated with it after a minor // GC. This may finalize the map if it was in the nursery and has died. @@ -179,14 +179,9 @@ class MapObject : public NativeObject { size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf); - static constexpr size_t getDataSlotOffset() { - return getFixedSlotOffset(DataSlot); - } - - const ValueMap* getData() { return getTableUnchecked(); } - [[nodiscard]] static bool get(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static bool set(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); static bool isOriginalSizeGetter(Native native) { return native == static_cast(MapObject::size); @@ -195,34 +190,26 @@ class MapObject : public NativeObject { private: static const ClassSpec classSpec_; static const JSClassOps classOps_; + static const ClassExtension classExtension_; static const JSPropertySpec properties[]; static const JSFunctionSpec methods[]; static const JSPropertySpec staticProperties[]; static const JSFunctionSpec staticMethods[]; - PreBarrieredTable* nurseryTable() { - MOZ_ASSERT(IsInsideNursery(this)); - return maybePtrFromReservedSlot(DataSlot); - } - ValueMap* tenuredTable() { - MOZ_ASSERT(!IsInsideNursery(this)); - return getTableUnchecked(); - } - ValueMap* getTableUnchecked() { - return maybePtrFromReservedSlot(DataSlot); - } + [[nodiscard]] bool setWithHashableKey(JSContext* cx, const HashableValue& key, + const Value& value); - static inline bool setWithHashableKey(JSContext* cx, MapObject* obj, - Handle key, - Handle value); + [[nodiscard]] bool tryOptimizeCtorWithIterable(JSContext* cx, + const Value& iterableVal, + bool* optimized); static bool finishInit(JSContext* cx, HandleObject ctor, HandleObject proto); - static const ValueMap& extract(HandleObject o); - static const ValueMap& extract(const CallArgs& args); static void trace(JSTracer* trc, JSObject* obj); static void finalize(JS::GCContext* gcx, JSObject* obj); + static size_t objectMoved(JSObject* obj, JSObject* old); + [[nodiscard]] static bool construct(JSContext* cx, unsigned argc, Value* vp); static bool is(HandleValue v); @@ -235,8 +222,13 @@ class MapObject : public NativeObject { [[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static bool get_impl(JSContext* cx, const CallArgs& args); [[nodiscard]] static bool has_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static bool set_impl(JSContext* cx, const CallArgs& args); +#ifdef NIGHTLY_BUILD + [[nodiscard]] static bool getOrInsert(JSContext* cx, unsigned argc, + Value* vp); + [[nodiscard]] static bool getOrInsert_impl(JSContext* cx, + const CallArgs& args); +#endif [[nodiscard]] static bool delete_impl(JSContext* cx, const CallArgs& args); [[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static bool keys_impl(JSContext* cx, const CallArgs& args); @@ -248,93 +240,72 @@ class MapObject : public NativeObject { [[nodiscard]] static bool clear(JSContext* cx, unsigned argc, Value* vp); }; -class MapIteratorObject : public NativeObject { +class MapIteratorObject : public TableIteratorObject { public: static const JSClass class_; - enum { TargetSlot, RangeSlot, KindSlot, SlotCount }; - - static_assert( - TargetSlot == ITERATOR_SLOT_TARGET, - "TargetSlot must match self-hosting define for iterated object slot."); - static_assert( - RangeSlot == ITERATOR_SLOT_RANGE, - "RangeSlot must match self-hosting define for range or index slot."); - static_assert(KindSlot == ITERATOR_SLOT_ITEM_KIND, - "KindSlot must match self-hosting define for item kind slot."); - static const JSFunctionSpec methods[]; - static MapIteratorObject* create(JSContext* cx, HandleObject mapobj, - const ValueMap* data, - MapObject::IteratorKind kind); + static MapIteratorObject* create(JSContext* cx, Handle mapobj, + Kind kind); static void finalize(JS::GCContext* gcx, JSObject* obj); static size_t objectMoved(JSObject* obj, JSObject* old); - void init(MapObject* mapObj, MapObject::IteratorKind kind) { - initFixedSlot(TargetSlot, JS::ObjectValue(*mapObj)); - initFixedSlot(RangeSlot, JS::PrivateValue(nullptr)); - initFixedSlot(KindSlot, JS::Int32Value(int32_t(kind))); - } - [[nodiscard]] static bool next(MapIteratorObject* mapIterator, ArrayObject* resultPairObj); static JSObject* createResultPair(JSContext* cx); private: - inline MapObject::IteratorKind kind() const; MapObject* target() const; }; -class SetObject : public NativeObject { +class SetObject : public OrderedHashSetObject { public: - enum IteratorKind { Keys, Values, Entries }; + using Table = + OrderedHashSetImpl, HashableValueHasher>; + using UnbarrieredTable = OrderedHashSetImpl; - static_assert( - Keys == ITEM_KIND_KEY, - "IteratorKind Keys must match self-hosting define for item kind key."); - static_assert(Values == ITEM_KIND_VALUE, - "IteratorKind Values must match self-hosting define for item " - "kind value."); - static_assert( - Entries == ITEM_KIND_KEY_AND_VALUE, - "IteratorKind Entries must match self-hosting define for item kind " - "key-and-value."); + friend class OrderedHashTableRef; + + enum { + NurseryKeysSlot = Table::SlotCount, + RegisteredNurseryIteratorsSlot, + SlotCount + }; + + using IteratorKind = TableIteratorObject::Kind; static const JSClass class_; static const JSClass protoClass_; - enum { DataSlot, NurseryKeysSlot, HasNurseryMemorySlot, SlotCount }; - - [[nodiscard]] static bool keys(JSContext* cx, HandleObject obj, - JS::MutableHandle> keys); + [[nodiscard]] bool keys(JS::MutableHandle> keys); [[nodiscard]] static bool values(JSContext* cx, unsigned argc, Value* vp); - [[nodiscard]] static bool add(JSContext* cx, HandleObject obj, - HandleValue key); + [[nodiscard]] bool add(JSContext* cx, const Value& key); // Publicly exposed Set calls for JSAPI access (webidl maplike/setlike // interfaces, etc.) + static SetObject* createWithProto(JSContext* cx, HandleObject proto, + NewObjectKind newKind); static SetObject* create(JSContext* cx, HandleObject proto = nullptr); - static uint32_t size(JSContext* cx, HandleObject obj); + static SetObject* createFromIterable( + JSContext* cx, Handle proto, Handle iterable, + Handle allocatedFromJit = nullptr); + + uint32_t size(); [[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static bool add(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); - [[nodiscard]] static bool has(JSContext* cx, HandleObject obj, - HandleValue key, bool* rval); - [[nodiscard]] static bool clear(JSContext* cx, HandleObject obj); + [[nodiscard]] bool has(JSContext* cx, const Value& key, bool* rval); + void clear(JSContext* cx); [[nodiscard]] static bool iterator(JSContext* cx, IteratorKind kind, - HandleObject obj, MutableHandleValue iter); + Handle obj, + MutableHandleValue iter); [[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp); - [[nodiscard]] static bool delete_(JSContext* cx, HandleObject obj, - HandleValue key, bool* rval); + [[nodiscard]] bool delete_(JSContext* cx, const Value& key, bool* rval); [[nodiscard]] static bool copy(JSContext* cx, unsigned argc, Value* vp); - using UnbarrieredTable = - OrderedHashSet; - friend class OrderedHashTableRef; - - void clearNurseryRangesBeforeMinorGC(); + void clearNurseryIteratorsBeforeMinorGC(); // Sweeps a set that had nursery memory associated with it after a minor // GC. This may finalize the set if it was in the nursery and has died. @@ -345,12 +316,6 @@ class SetObject : public NativeObject { size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf); - static constexpr size_t getDataSlotOffset() { - return getFixedSlotOffset(DataSlot); - } - - ValueSet* getData() { return getTableUnchecked(); } - static bool isOriginalSizeGetter(Native native) { return native == static_cast(SetObject::size); } @@ -358,28 +323,30 @@ class SetObject : public NativeObject { private: static const ClassSpec classSpec_; static const JSClassOps classOps_; + static const ClassExtension classExtension_; static const JSPropertySpec properties[]; static const JSFunctionSpec methods[]; static const JSPropertySpec staticProperties[]; - ValueSet* getTableUnchecked() { - return maybePtrFromReservedSlot(DataSlot); - } + [[nodiscard]] bool addHashableValue(JSContext* cx, + const HashableValue& value); + + [[nodiscard]] bool tryOptimizeCtorWithIterable(JSContext* cx, + const Value& iterableVal, + bool* optimized); static bool finishInit(JSContext* cx, HandleObject ctor, HandleObject proto); - static ValueSet& extract(HandleObject o); - static ValueSet& extract(const CallArgs& args); static void trace(JSTracer* trc, JSObject* obj); static void finalize(JS::GCContext* gcx, JSObject* obj); + static size_t objectMoved(JSObject* obj, JSObject* old); + static bool construct(JSContext* cx, unsigned argc, Value* vp); static bool is(HandleValue v); static bool is(HandleObject o); - static bool isBuiltinAdd(HandleValue add); - [[nodiscard]] static bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind); @@ -394,95 +361,25 @@ class SetObject : public NativeObject { [[nodiscard]] static bool clear(JSContext* cx, unsigned argc, Value* vp); }; -class SetIteratorObject : public NativeObject { +class SetIteratorObject : public TableIteratorObject { public: static const JSClass class_; - enum { TargetSlot, RangeSlot, KindSlot, SlotCount }; - - static_assert( - TargetSlot == ITERATOR_SLOT_TARGET, - "TargetSlot must match self-hosting define for iterated object slot."); - static_assert( - RangeSlot == ITERATOR_SLOT_RANGE, - "RangeSlot must match self-hosting define for range or index slot."); - static_assert(KindSlot == ITERATOR_SLOT_ITEM_KIND, - "KindSlot must match self-hosting define for item kind slot."); - static const JSFunctionSpec methods[]; - static SetIteratorObject* create(JSContext* cx, HandleObject setobj, - ValueSet* data, - SetObject::IteratorKind kind); + static SetIteratorObject* create(JSContext* cx, Handle setobj, + Kind kind); static void finalize(JS::GCContext* gcx, JSObject* obj); static size_t objectMoved(JSObject* obj, JSObject* old); - void init(SetObject* setObj, SetObject::IteratorKind kind) { - initFixedSlot(TargetSlot, JS::ObjectValue(*setObj)); - initFixedSlot(RangeSlot, JS::PrivateValue(nullptr)); - initFixedSlot(KindSlot, JS::Int32Value(int32_t(kind))); - } - [[nodiscard]] static bool next(SetIteratorObject* setIterator, ArrayObject* resultObj); static JSObject* createResult(JSContext* cx); private: - inline SetObject::IteratorKind kind() const; SetObject* target() const; }; -using SetInitGetPrototypeOp = NativeObject* (*)(JSContext*, - Handle); -using SetInitIsBuiltinOp = bool (*)(HandleValue); - -template -[[nodiscard]] static bool IsOptimizableInitForSet(JSContext* cx, - HandleObject setObject, - HandleValue iterable, - bool* optimized) { - MOZ_ASSERT(!*optimized); - - if (!iterable.isObject()) { - return true; - } - - RootedObject array(cx, &iterable.toObject()); - if (!IsPackedArray(array)) { - return true; - } - - // Get the canonical prototype object. - Rooted setProto(cx, getPrototypeOp(cx, cx->global())); - if (!setProto) { - return false; - } - - // Ensures setObject's prototype is the canonical prototype. - if (setObject->staticPrototype() != setProto) { - return true; - } - - // Look up the 'add' value on the prototype object. - mozilla::Maybe addProp = setProto->lookup(cx, cx->names().add); - if (addProp.isNothing() || !addProp->isDataProperty()) { - return true; - } - - // Get the referred value, ensure it holds the canonical add function. - RootedValue add(cx, setProto->getSlot(addProp->slot())); - if (!isBuiltinOp(add)) { - return true; - } - - ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx); - if (!stubChain) { - return false; - } - - return stubChain->tryOptimizeArray(cx, array.as(), optimized); -} - } /* namespace js */ #endif /* builtin_MapObject_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.cpp index f9059afc047..52e1bd03690 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.cpp @@ -56,6 +56,17 @@ static Value StringOrNullValue(JSString* maybeString) { return maybeString ? StringValue(maybeString) : NullValue(); } +static Value ModuleTypeToValue(JS::ModuleType moduleType) { + static_assert(size_t(JS::ModuleType::Limit) <= INT32_MAX); + return Int32Value(int32_t(moduleType)); +} + +static JS::ModuleType ValueToModuleType(const Value& value) { + int32_t i = value.toInt32(); + MOZ_ASSERT(i >= 0 && i <= int32_t(JS::ModuleType::Limit)); + return static_cast(i); +} + #define DEFINE_ATOM_ACCESSOR_METHOD(cls, name, slot) \ JSAtom* cls::name() const { \ Value value = getReservedSlot(slot); \ @@ -145,7 +156,8 @@ void RequestedModule::trace(JSTracer* trc) { /* static */ const JSClass ResolvedBindingObject::class_ = { "ResolvedBinding", - JSCLASS_HAS_RESERVED_SLOTS(ResolvedBindingObject::SlotCount)}; + JSCLASS_HAS_RESERVED_SLOTS(ResolvedBindingObject::SlotCount), +}; ModuleObject* ResolvedBindingObject::module() const { Value value = getReservedSlot(ModuleSlot); @@ -191,37 +203,20 @@ void ImportAttribute::trace(JSTracer* trc) { // ModuleRequestObject /* static */ const JSClass ModuleRequestObject::class_ = { "ModuleRequest", - JSCLASS_HAS_RESERVED_SLOTS(ModuleRequestObject::SlotCount)}; + JSCLASS_HAS_RESERVED_SLOTS(ModuleRequestObject::SlotCount), +}; DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ModuleRequestObject, specifier, SpecifierSlot) -Span ModuleRequestObject::attributes() const { - Value value = getReservedSlot(AttributesSlot); - if (value.isNullOrUndefined()) { - return Span(); - } - void* ptr = value.toPrivate(); - MOZ_ASSERT(ptr); - auto* vector = static_cast(ptr); - return *vector; +JS::ModuleType ModuleRequestObject::moduleType() const { + return ValueToModuleType(getReservedSlot(ModuleTypeSlot)); } -bool ModuleRequestObject::hasAttributes() const { - return !getReservedSlot(ModuleRequestObject::AttributesSlot) - .isNullOrUndefined(); -} - -/* static */ -bool ModuleRequestObject::getModuleType( - JSContext* cx, const Handle moduleRequest, - JS::ModuleType& moduleType) { - if (!moduleRequest->hasAttributes()) { - moduleType = JS::ModuleType::JavaScript; - return true; - } - - for (const ImportAttribute& importAttribute : moduleRequest->attributes()) { +static bool GetModuleType(JSContext* cx, + Handle maybeAttributes, + JS::ModuleType& moduleType) { + for (const ImportAttribute& importAttribute : maybeAttributes) { if (importAttribute.key() == cx->names().type) { int32_t isJsonString; if (!js::CompareStrings(cx, cx->names().json, importAttribute.value(), @@ -251,7 +246,19 @@ bool ModuleRequestObject::isInstance(HandleValue value) { /* static */ ModuleRequestObject* ModuleRequestObject::create( JSContext* cx, Handle specifier, - MutableHandle> maybeAttributes) { + Handle maybeAttributes) { + JS::ModuleType moduleType = JS::ModuleType::JavaScript; + if (!GetModuleType(cx, maybeAttributes, moduleType)) { + return nullptr; + } + + return create(cx, specifier, moduleType); +} + +/* static */ +ModuleRequestObject* ModuleRequestObject::create(JSContext* cx, + Handle specifier, + JS::ModuleType moduleType) { ModuleRequestObject* self = NewObjectWithGivenProto(cx, nullptr); if (!self) { @@ -259,15 +266,28 @@ ModuleRequestObject* ModuleRequestObject::create( } self->initReservedSlot(SpecifierSlot, StringOrNullValue(specifier)); - - if (maybeAttributes) { - InitReservedSlot(self, AttributesSlot, maybeAttributes.get().release(), - MemoryUse::ModuleImportAttributes); - } + self->initReservedSlot(ModuleTypeSlot, ModuleTypeToValue(moduleType)); return self; } +void ModuleRequestObject::setFirstUnsupportedAttributeKey(Handle key) { + initReservedSlot(FirstUnsupportedAttributeKeySlot, StringOrNullValue(key)); +} + +bool ModuleRequestObject::hasFirstUnsupportedAttributeKey() const { + return !getReservedSlot(FirstUnsupportedAttributeKeySlot).isNullOrUndefined(); +} + +JSAtom* ModuleRequestObject::getFirstUnsupportedAttributeKey() const { + if (!hasFirstUnsupportedAttributeKey()) { + return nullptr; + } + return &getReservedSlot(FirstUnsupportedAttributeKeySlot) + .toString() + ->asAtom(); +} + /////////////////////////////////////////////////////////////////////////// // IndirectBindingMap @@ -338,7 +358,8 @@ bool IndirectBindingMap::lookup(jsid name, ModuleEnvironmentObject** envOut, // ModuleNamespaceObject /* static */ -const ModuleNamespaceObject::ProxyHandler ModuleNamespaceObject::proxyHandler; +constexpr ModuleNamespaceObject::ProxyHandler + ModuleNamespaceObject::proxyHandler; /* static */ bool ModuleNamespaceObject::isInstance(HandleValue value) { @@ -417,10 +438,7 @@ bool ModuleNamespaceObject::addBinding(JSContext* cx, return bindings().put(cx, exportedNameId, environment, targetNameId); } -const char ModuleNamespaceObject::ProxyHandler::family = 0; - -ModuleNamespaceObject::ProxyHandler::ProxyHandler() - : BaseProxyHandler(&family, false) {} +constexpr char ModuleNamespaceObject::ProxyHandler::family = 0; bool ModuleNamespaceObject::ProxyHandler::getPrototype( JSContext* cx, HandleObject proxy, MutableHandleObject protop) const { @@ -886,7 +904,8 @@ Maybe CyclicModuleFields::maybePendingAsyncDependencies() const { "Module", JSCLASS_HAS_RESERVED_SLOTS(ModuleObject::SlotCount) | JSCLASS_BACKGROUND_FINALIZE, - &ModuleObject::classOps_}; + &ModuleObject::classOps_, +}; /* static */ bool ModuleObject::isInstance(HandleValue value) { @@ -899,6 +918,7 @@ bool ModuleObject::hasCyclicModuleFields() const { } CyclicModuleFields* ModuleObject::cyclicModuleFields() { + MOZ_ASSERT(hasCyclicModuleFields()); void* ptr = getReservedSlot(CyclicModuleFieldsSlot).toPrivate(); MOZ_ASSERT(ptr); return static_cast(ptr); @@ -1297,6 +1317,10 @@ bool ModuleObject::hasTopLevelCapability() const { } bool ModuleObject::hadEvaluationError() const { + if (hasSyntheticModuleFields()) { + return false; + } + ModuleStatus fullStatus = cyclicModuleFields()->status; return fullStatus == ModuleStatus::Evaluated_Error; } @@ -1465,7 +1489,7 @@ bool ModuleObject::createEnvironment(JSContext* cx, /*static*/ bool ModuleObject::createSyntheticEnvironment(JSContext* cx, Handle self, - Handle> values) { + JS::HandleVector values) { Rooted env( cx, ModuleEnvironmentObject::createSynthetic(cx, self)); if (!env) { @@ -1490,7 +1514,7 @@ ModuleBuilder::ModuleBuilder(FrontendContext* fc, const frontend::EitherParser& eitherParser) : fc_(fc), eitherParser_(eitherParser), - requestedModuleSpecifiers_(fc), + requestedModuleIndexes_(fc), importEntries_(fc), exportEntries_(fc), exportNames_(fc) {} @@ -1599,15 +1623,9 @@ ModuleRequestObject* frontend::StencilModuleMetadata::createModuleRequestObject( const StencilModuleRequest& request) const { uint32_t numberOfAttributes = request.attributes.length(); - Rooted> attributes(cx); + Rooted attributes(cx); if (numberOfAttributes > 0) { - attributes = cx->make_unique(); - if (!attributes) { - ReportOutOfMemory(cx); - return nullptr; - } - - if (!attributes->reserve(numberOfAttributes)) { + if (!attributes.reserve(numberOfAttributes)) { ReportOutOfMemory(cx); return nullptr; } @@ -1618,7 +1636,8 @@ ModuleRequestObject* frontend::StencilModuleMetadata::createModuleRequestObject( attributeKey = atomCache.getExistingAtomAt(cx, request.attributes[j].key); attributeValue = atomCache.getExistingAtomAt(cx, request.attributes[j].value); - attributes->infallibleEmplaceBack(attributeKey, attributeValue); + + attributes.infallibleEmplaceBack(attributeKey, attributeValue); } } @@ -1626,7 +1645,21 @@ ModuleRequestObject* frontend::StencilModuleMetadata::createModuleRequestObject( atomCache.getExistingAtomAt(cx, request.specifier)); MOZ_ASSERT(specifier); - return ModuleRequestObject::create(cx, specifier, &attributes); + Rooted moduleRequestObject( + cx, ModuleRequestObject::create(cx, specifier, attributes)); + if (!moduleRequestObject) { + return nullptr; + } + + if (request.firstUnsupportedAttributeKey) { + Rooted unsupportedAttributeKey( + cx, + atomCache.getExistingAtomAt(cx, request.firstUnsupportedAttributeKey)); + moduleRequestObject->setFirstUnsupportedAttributeKey( + unsupportedAttributeKey); + } + + return moduleRequestObject; } bool frontend::StencilModuleMetadata::createImportEntries( @@ -1802,15 +1835,26 @@ bool ModuleBuilder::processAttributes(frontend::StencilModuleRequest& request, MOZ_ASSERT(attribute->isKind(ParseNodeKind::ImportAttribute)); auto key = attribute->left()->as().atom(); - auto value = attribute->right()->as().atom(); - markUsedByStencil(key); - markUsedByStencil(value); - StencilModuleImportAttribute attributeStencil(key, value); - if (!request.attributes.append(attributeStencil)) { - js::ReportOutOfMemory(fc_); - return false; + // Note: This should be driven by a host hook + // (HostGetSupportedImportAttributes), however the infrastructure of said + // host hook is deeply unclear, and so right now embedders will not have + // the ability to alter or extend the set of supported attributes. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1840723. + if (key == TaggedParserAtomIndex::WellKnown::type()) { + auto value = attribute->right()->as().atom(); + markUsedByStencil(value); + + StencilModuleImportAttribute attributeStencil(key, value); + if (!request.attributes.append(attributeStencil)) { + js::ReportOutOfMemory(fc_); + return false; + } + } else { + if (!request.firstUnsupportedAttributeKey) { + request.firstUnsupportedAttributeKey = key; + } } } @@ -2096,13 +2140,13 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) { eitherParser_.computeLineAndColumn(spec->pn_pos.begin, &line, &column); StencilModuleEntry entry; - TaggedParserAtomIndex exportName; if (spec->isKind(ParseNodeKind::ExportSpec)) { auto* importNameNode = &spec->as().left()->as(); auto* exportNameNode = &spec->as().right()->as(); auto importName = importNameNode->atom(); - exportName = exportNameNode->atom(); + auto exportName = exportNameNode->atom(); + MOZ_ASSERT(exportNames_.has(exportName)); markUsedByStencil(importName); markUsedByStencil(exportName); @@ -2112,7 +2156,8 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) { } else if (spec->isKind(ParseNodeKind::ExportNamespaceSpec)) { auto* exportNameNode = &spec->as().kid()->as(); - exportName = exportNameNode->atom(); + auto exportName = exportNameNode->atom(); + MOZ_ASSERT(exportNames_.has(exportName)); markUsedByStencil(exportName); entry = StencilModuleEntry::exportNamespaceFromEntry( @@ -2128,9 +2173,6 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) { if (!exportEntries_.append(entry)) { return false; } - if (exportName && !exportNames_.put(exportName)) { - return false; - } } return true; @@ -2147,15 +2189,24 @@ frontend::StencilModuleEntry* ModuleBuilder::importEntryFor( return &ptr->value(); } -bool ModuleBuilder::hasExportedName( - frontend::TaggedParserAtomIndex name) const { +ModuleBuilder::NoteExportedNameResult ModuleBuilder::noteExportedName( + frontend::TaggedParserAtomIndex name) { MOZ_ASSERT(name); - return exportNames_.has(name); + auto addPtr = exportNames_.lookupForAdd(name); + if (addPtr) { + return NoteExportedNameResult::AlreadyDeclared; + } + if (!exportNames_.add(addPtr, name)) { + return NoteExportedNameResult::OutOfMemory; + } + return NoteExportedNameResult::Success; } bool ModuleBuilder::appendExportEntry( frontend::TaggedParserAtomIndex exportName, frontend::TaggedParserAtomIndex localName, frontend::ParseNode* node) { + MOZ_ASSERT(exportNames_.has(exportName)); + uint32_t line = 0; JS::LimitedColumnNumberOneOrigin column; if (node) { @@ -2166,15 +2217,7 @@ bool ModuleBuilder::appendExportEntry( markUsedByStencil(exportName); auto entry = frontend::StencilModuleEntry::exportAsEntry( localName, exportName, line, JS::ColumnNumberOneOrigin(column)); - if (!exportEntries_.append(entry)) { - return false; - } - - if (!exportNames_.put(exportName)) { - return false; - } - - return true; + return exportEntries_.append(entry); } frontend::MaybeModuleRequestIndex ModuleBuilder::appendModuleRequest( @@ -2187,8 +2230,13 @@ frontend::MaybeModuleRequestIndex ModuleBuilder::appendModuleRequest( return MaybeModuleRequestIndex(); } + if (auto ptr = moduleRequestIndexes_.lookup(request)) { + return MaybeModuleRequestIndex(ptr->value()); + } + uint32_t index = moduleRequests_.length(); - if (!moduleRequests_.append(request)) { + if (!moduleRequests_.append(request) || + !moduleRequestIndexes_.put(request, index)) { js::ReportOutOfMemory(fc_); return MaybeModuleRequestIndex(); } @@ -2198,8 +2246,8 @@ frontend::MaybeModuleRequestIndex ModuleBuilder::appendModuleRequest( bool ModuleBuilder::maybeAppendRequestedModule( MaybeModuleRequestIndex moduleRequest, frontend::ParseNode* node) { - auto specifier = moduleRequests_[moduleRequest.value()].specifier; - if (requestedModuleSpecifiers_.has(specifier)) { + uint32_t index = moduleRequest.value(); + if (requestedModuleIndexes_.has(index)) { return true; } @@ -2215,7 +2263,7 @@ bool ModuleBuilder::maybeAppendRequestedModule( return false; } - return requestedModuleSpecifiers_.put(specifier); + return requestedModuleIndexes_.put(index); } void ModuleBuilder::markUsedByStencil(frontend::TaggedParserAtomIndex name) { @@ -2319,18 +2367,6 @@ static bool EvaluateDynamicImportOptions( return false; } - // Step 11.d. If the host supports the deprecated assert keyword for import - // attributes and attributesObj is undefined, then - if (attributesValue.isUndefined() && - cx->options().importAttributesAssertSyntax()) { - // Step 11.d.i. Set attributesObj to Completion(Get(options, "assert")). - RootedId assertId(cx, NameToId(cx->names().assert_)); - if (!GetProperty(cx, attributesWrapperObject, attributesWrapperObject, - assertId, &attributesValue)) { - return false; - } - } - // Step 11.e. If attributesObj is not undefined, then if (attributesValue.isUndefined()) { return true; @@ -2475,32 +2511,16 @@ JSObject* js::StartDynamicModuleImport(JSContext* cx, HandleScript script, return promise; } - Rooted tempAttributes(cx); - if (!EvaluateDynamicImportOptions(cx, optionsArg, &tempAttributes)) { + Rooted attributes(cx); + if (!EvaluateDynamicImportOptions(cx, optionsArg, &attributes)) { if (!RejectPromiseWithPendingError(cx, promise)) { return nullptr; } return promise; } - Rooted> attributes(cx); - if (!tempAttributes.empty()) { - attributes = cx->make_unique(); - if (!attributes) { - return nullptr; - } - if (!attributes->reserve(tempAttributes.length())) { - ReportOutOfMemory(cx); - return nullptr; - } - if (!attributes->appendAll(tempAttributes)) { - ReportOutOfMemory(cx); - return nullptr; - } - } - RootedObject moduleRequest( - cx, ModuleRequestObject::create(cx, specifierAtom, &attributes)); + cx, ModuleRequestObject::create(cx, specifierAtom, attributes)); if (!moduleRequest) { if (!RejectPromiseWithPendingError(cx, promise)) { return nullptr; @@ -2572,17 +2592,18 @@ bool js::OnModuleEvaluationFailure(JSContext* cx, // reference to the referencing private to keep it alive until it is needed. class DynamicImportContextObject : public NativeObject { public: - enum { ReferencingPrivateSlot = 0, SpecifierSlot, SlotCount }; + enum { ReferencingPrivateSlot = 0, SpecifierSlot, ModuleTypeSlot, SlotCount }; static const JSClass class_; static const JSClassOps classOps_; [[nodiscard]] static DynamicImportContextObject* create( JSContext* cx, Handle referencingPrivate, - Handle specifier); + Handle specifier, JS::ModuleType moduleType); Value referencingPrivate() const; JSString* specifier() const; + JS::ModuleType moduleType() const; static void clearReferencingPrivate(JSRuntime* runtime, DynamicImportContextObject* ic); @@ -2595,7 +2616,8 @@ const JSClass DynamicImportContextObject::class_ = { "DynamicImportContextObject", JSCLASS_HAS_RESERVED_SLOTS(DynamicImportContextObject::SlotCount) | JSCLASS_SLOT0_IS_NSISUPPORTS | JSCLASS_FOREGROUND_FINALIZE, - &DynamicImportContextObject::classOps_}; + &DynamicImportContextObject::classOps_, +}; static_assert(DynamicImportContextObject::ReferencingPrivateSlot == 0); /* static */ @@ -2615,7 +2637,7 @@ const JSClassOps DynamicImportContextObject::classOps_ = { /* static */ DynamicImportContextObject* DynamicImportContextObject::create( JSContext* cx, Handle referencingPrivate, - Handle specifier) { + Handle specifier, JS::ModuleType moduleType) { Rooted self( cx, NewObjectWithGivenProto(cx, nullptr)); if (!self) { @@ -2626,6 +2648,8 @@ DynamicImportContextObject* DynamicImportContextObject::create( self->initReservedSlot(ReferencingPrivateSlot, referencingPrivate); self->initReservedSlot(SpecifierSlot, StringValue(specifier)); + self->initReservedSlot(ModuleTypeSlot, ModuleTypeToValue(moduleType)); + return self; } @@ -2642,6 +2666,10 @@ JSString* DynamicImportContextObject::specifier() const { return value.toString(); } +JS::ModuleType DynamicImportContextObject::moduleType() const { + return ValueToModuleType(getReservedSlot(ModuleTypeSlot)); +} + /* static */ void DynamicImportContextObject::finalize(JS::GCContext* gcx, JSObject* obj) { auto* context = &obj->as(); @@ -2678,9 +2706,8 @@ static bool OnResolvedDynamicModule(JSContext* cx, unsigned argc, Value* vp) { } Rooted promise(cx, TargetFromHandler(args)); - Rooted> attributes(cx); RootedObject moduleRequest( - cx, ModuleRequestObject::create(cx, specifier, &attributes)); + cx, ModuleRequestObject::create(cx, specifier, context->moduleType())); if (!moduleRequest) { return RejectPromiseWithPendingError(cx, promise); } @@ -2748,8 +2775,9 @@ bool js::FinishDynamicModuleImport(JSContext* cx, Rooted specifier( cx, moduleRequest->as().specifier()); Rooted context( - cx, - DynamicImportContextObject::create(cx, referencingPrivate, specifier)); + cx, DynamicImportContextObject::create( + cx, referencingPrivate, specifier, + moduleRequest->as().moduleType())); if (!context) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.h b/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.h index 35332016753..4269c6e1b87 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/ModuleObject.h @@ -67,20 +67,32 @@ using ImportAttributeVector = GCVector; class ModuleRequestObject : public NativeObject { public: - enum { SpecifierSlot = 0, AttributesSlot, SlotCount }; + enum { + SpecifierSlot = 0, + FirstUnsupportedAttributeKeySlot, + ModuleTypeSlot, + SlotCount + }; static const JSClass class_; static bool isInstance(HandleValue value); [[nodiscard]] static ModuleRequestObject* create( JSContext* cx, Handle specifier, - MutableHandle> maybeAttributes); + Handle maybeAttributes); + [[nodiscard]] static ModuleRequestObject* create(JSContext* cx, + Handle specifier, + JS::ModuleType moduleType); JSAtom* specifier() const; - mozilla::Span attributes() const; - bool hasAttributes() const; - static bool getModuleType(JSContext* cx, - const Handle moduleRequest, - JS::ModuleType& moduleType); + JS::ModuleType moduleType() const; + + // We process import attributes earlier in the process, but according to the + // spec, we should error during module evaluation if we encounter an + // unsupported attribute. We want to generate a nice error message, so we need + // to keep track of the first unsupported key we encounter. + void setFirstUnsupportedAttributeKey(Handle key); + bool hasFirstUnsupportedAttributeKey() const; + JSAtom* getFirstUnsupportedAttributeKey() const; }; using ModuleRequestVector = @@ -244,7 +256,7 @@ class ModuleNamespaceObject : public ProxyObject { private: struct ProxyHandler : public BaseProxyHandler { - ProxyHandler(); + constexpr ProxyHandler() : BaseProxyHandler(&family, false) {} bool getOwnPropertyDescriptor( JSContext* cx, HandleObject proxy, HandleId id, @@ -449,7 +461,7 @@ class ModuleObject : public NativeObject { static bool createEnvironment(JSContext* cx, Handle self); static bool createSyntheticEnvironment(JSContext* cx, Handle self, - Handle> values); + JS::HandleVector values); void initAsyncSlots(JSContext* cx, bool hasTopLevelAwait, Handle asyncParentModules); diff --git a/src/third_party/mozjs/extract/js/src/builtin/Object.cpp b/src/third_party/mozjs/extract/js/src/builtin/Object.cpp index 3b875d9daee..2dec9d71d6d 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Object.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Object.cpp @@ -25,7 +25,7 @@ #include "js/PropertySpec.h" #include "js/UniquePtr.h" #include "util/Identifier.h" // js::IsIdentifier -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "util/Text.h" #include "vm/BooleanObject.h" #include "vm/DateObject.h" @@ -40,12 +40,6 @@ #include "vm/StringType.h" #include "vm/ToSource.h" // js::ValueToSource #include "vm/Watchtower.h" - -#ifdef ENABLE_RECORD_TUPLE -# include "builtin/RecordObject.h" -# include "builtin/TupleObject.h" -#endif - #include "vm/GeckoProfiler-inl.h" #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" @@ -312,17 +306,6 @@ JSString* js::ObjectToSource(JSContext* cx, HandleObject obj) { return nullptr; } -#ifdef ENABLE_RECORD_TUPLE - if (IsExtendedPrimitiveWrapper(*obj)) { - if (obj->is()) { - Rooted tup(cx, &obj->as().unbox()); - return TupleToSource(cx, tup); - } - MOZ_ASSERT(obj->is()); - return RecordToSource(cx, obj->as().unbox()); - } -#endif - bool comma = false; auto AddProperty = [cx, &comma, &buf](HandleId id, HandleValue val, @@ -745,7 +728,7 @@ bool js::obj_toString(JSContext* cx, unsigned argc, Value* vp) { } // Step 17. - StringBuffer sb(cx); + StringBuilder sb(cx); if (!sb.append("[object ") || !sb.append(tag.toString()) || !sb.append(']')) { return false; } @@ -842,8 +825,8 @@ static bool CanAddNewPropertyExcludingProtoFast(PlainObject* obj) { return false; } - // Don't fastpath assign if we're watching for property modification. - if (Watchtower::watchesPropertyModification(obj)) { + // Don't fastpath assign if we're watching for property value changes. + if (Watchtower::watchesPropertyValueChange(obj)) { return false; } @@ -1204,9 +1187,10 @@ JS_PUBLIC_API bool JS_AssignObject(JSContext* cx, JS::HandleObject target, static bool obj_assign(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "Object", "assign"); CallArgs args = CallArgsFromVp(argc, vp); + RootedTuple roots(cx); // Step 1. - RootedObject to(cx, ToObject(cx, args.get(0))); + RootedField to(roots, ToObject(cx, args.get(0))); if (!to) { return false; } @@ -1215,7 +1199,6 @@ static bool obj_assign(JSContext* cx, unsigned argc, Value* vp) { // there's 1 argument, the loop below is a no-op. // Step 4. - RootedObject from(cx); for (size_t i = 1; i < args.length(); i++) { // Step 4.a. if (args[i].isNullOrUndefined()) { @@ -1223,7 +1206,7 @@ static bool obj_assign(JSContext* cx, unsigned argc, Value* vp) { } // Step 4.b.i. - from = ToObject(cx, args[i]); + RootedField from(roots, ToObject(cx, args[i])); if (!from) { return false; } @@ -1541,16 +1524,6 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj, return true; } -#ifdef ENABLE_RECORD_TUPLE - if (obj->is()) { - Rooted tup(cx, &obj->as().unbox()); - return TryEnumerableOwnPropertiesNative(cx, tup, rval, optimized); - } else if (obj->is()) { - Rooted tup(cx, obj->as().unbox()); - return TryEnumerableOwnPropertiesNative(cx, tup, rval, optimized); - } -#endif - Handle nobj = obj.as(); // Resolve lazy properties on |nobj|. @@ -1694,74 +1667,18 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj, properties[i].set(value); } } -#ifdef ENABLE_RECORD_TUPLE - else if (obj->is()) { - RecordType* rec = &obj->as(); - Rooted keys(cx, rec->keys()); - RootedId keyId(cx); - RootedString keyStr(cx); - - MOZ_ASSERT(properties.empty(), "records cannot have dense elements"); - if (!properties.resize(keys->length())) { - return false; - } - - for (size_t i = 0; i < keys->length(); i++) { - MOZ_ASSERT(keys->getDenseElement(i).isString()); - if (kind == EnumerableOwnPropertiesKind::Keys || - kind == EnumerableOwnPropertiesKind::Names) { - value.set(keys->getDenseElement(i)); - } else if (kind == EnumerableOwnPropertiesKind::Values) { - keyStr.set(keys->getDenseElement(i).toString()); - - if (!JS_StringToId(cx, keyStr, &keyId)) { - return false; - } - MOZ_ALWAYS_TRUE(rec->getOwnProperty(cx, keyId, &value)); - } else { - MOZ_ASSERT(kind == EnumerableOwnPropertiesKind::KeysAndValues); - - key.set(keys->getDenseElement(i)); - keyStr.set(key.toString()); - - if (!JS_StringToId(cx, keyStr, &keyId)) { - return false; - } - MOZ_ALWAYS_TRUE(rec->getOwnProperty(cx, keyId, &value)); - - if (!NewValuePair(cx, key, value, &value, gcHeap)) { - return false; - } - } - - properties[i].set(value); - } - - // Uh, goto... When using records, we already get the (sorted) properties - // from its sorted keys, so we don't read them again as "own properties". - // We could use an `if` or some refactoring to skip the next logic, but - // goto makes it easer to keep the logic separated in - // "#ifdef ENABLE_RECORD_TUPLE" blocks. - // This should be refactored when the #ifdefs are removed. - goto end; - } -#endif // Up to this point no side-effects through accessor properties are // possible which could have replaced |obj| with a non-native object. MOZ_ASSERT(obj->is()); MOZ_ASSERT(obj.as() == nobj); - { - // This new scope exists to support the goto end used by - // ENABLE_RECORD_TUPLE builds, and can be removed when said goto goes away. - size_t approximatePropertyCount = - nobj->shape()->propMap() - ? nobj->shape()->propMap()->approximateEntryCount() - : 0; - if (!properties.reserve(properties.length() + approximatePropertyCount)) { - return false; - } + size_t approximatePropertyCount = + nobj->shape()->propMap() + ? nobj->shape()->propMap()->approximateEntryCount() + : 0; + if (!properties.reserve(properties.length() + approximatePropertyCount)) { + return false; } if (kind == EnumerableOwnPropertiesKind::Keys || @@ -1880,10 +1797,6 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj, } } -#ifdef ENABLE_RECORD_TUPLE -end: -#endif - JSObject* array = NewDenseCopiedArray(cx, properties.length(), properties.begin()); if (!array) { @@ -1915,13 +1828,6 @@ static bool CountEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj, return true; } -#ifdef ENABLE_RECORD_TUPLE - // Skip the optimized path in case of record and tuples. - if (obj->is() || obj->is()) { - return true; - } -#endif - Handle nobj = obj.as(); // Resolve lazy properties on |nobj|. @@ -2009,8 +1915,7 @@ static bool EnumerableOwnProperties(JSContext* cx, const JS::CallArgs& args) { "Only implemented for Object.keys and Object.entries"); // Step 1. (Step 1 of Object.{keys,values,entries}, really.) - RootedObject obj(cx, IF_RECORD_TUPLE(ToObjectOrGetObjectPayload, ToObject)( - cx, args.get(0))); + RootedObject obj(cx, ToObject(cx, args.get(0))); if (!obj) { return false; } @@ -2122,8 +2027,7 @@ bool js::obj_keys(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - RootedObject obj(cx, IF_RECORD_TUPLE(ToObjectOrGetObjectPayload, ToObject)( - cx, args.get(0))); + RootedObject obj(cx, ToObject(cx, args.get(0))); if (!obj) { return false; } @@ -2447,12 +2351,14 @@ static const JSFunctionSpec object_methods[] = { JS_SELF_HOSTED_FN("__defineSetter__", "ObjectDefineSetter", 2, 0), JS_SELF_HOSTED_FN("__lookupGetter__", "ObjectLookupGetter", 1, 0), JS_SELF_HOSTED_FN("__lookupSetter__", "ObjectLookupSetter", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSPropertySpec object_properties[] = { JS_SELF_HOSTED_GETSET("__proto__", "$ObjectProtoGetter", "$ObjectProtoSetter", 0), - JS_PS_END}; + JS_PS_END, +}; static const JSFunctionSpec object_static_methods[] = { JS_FN("assign", obj_assign, 2, 0), @@ -2480,7 +2386,8 @@ static const JSFunctionSpec object_static_methods[] = { JS_SELF_HOSTED_FN("fromEntries", "ObjectFromEntries", 1, 0), JS_SELF_HOSTED_FN("hasOwn", "ObjectHasOwn", 2, 0), JS_SELF_HOSTED_FN("groupBy", "ObjectGroupBy", 2, 0), - JS_FS_END}; + JS_FS_END, +}; static JSObject* CreateObjectConstructor(JSContext* cx, JSProtoKey key) { Rooted self(cx, cx->global()); @@ -2557,10 +2464,14 @@ static const ClassSpec PlainObjectClassSpec = { CreateObjectConstructor, CreateObjectPrototype, object_static_methods, nullptr, object_methods, object_properties, - FinishObjectClassInit}; + FinishObjectClassInit, +}; -const JSClass PlainObject::class_ = {"Object", - JSCLASS_HAS_CACHED_PROTO(JSProto_Object), - JS_NULL_CLASS_OPS, &PlainObjectClassSpec}; +const JSClass PlainObject::class_ = { + "Object", + JSCLASS_HAS_CACHED_PROTO(JSProto_Object), + JS_NULL_CLASS_OPS, + &PlainObjectClassSpec, +}; const JSClass* const js::ObjectClassPtr = &PlainObject::class_; diff --git a/src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject-inl.h b/src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject-inl.h new file mode 100644 index 00000000000..caf19d328c5 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject-inl.h @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_OrderedHashTableObject_inl_h +#define builtin_OrderedHashTableObject_inl_h + +#include "builtin/OrderedHashTableObject.h" + +#include "gc/Nursery-inl.h" + +inline void* js::detail::OrderedHashTableObject::allocateCellBuffer( + JSContext* cx, size_t numBytes) { + return AllocNurseryOrMallocBuffer(cx, this, numBytes); +} + +#endif /* builtin_OrderedHashTableObject_inl_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject.h b/src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject.h new file mode 100644 index 00000000000..c971b308404 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/OrderedHashTableObject.h @@ -0,0 +1,1543 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_OrderedHashTableObject_h +#define builtin_OrderedHashTableObject_h + +/* + * This file defines js::OrderedHashMapObject (a base class of js::MapObject) + * and js::OrderedHashSetObject (a base class of js::SetObject). + * + * It also defines two templates, js::OrderedHashMapImpl and + * js::OrderedHashSetImpl, that operate on these objects and implement the + * ordered hash table algorithm. These templates are defined separately from + * the JS object types because it lets us switch between different template + * instantiations to enable or disable GC barriers. + * + * The implemented hash table algorithm is also different from HashMap and + * HashSet: + * + * - Iterating over an Ordered hash table visits the entries in the order in + * which they were inserted. This means that unlike a HashMap, the behavior + * of an OrderedHashMapImpl is deterministic (as long as the HashPolicy + * methods are effect-free and consistent); the hashing is a pure + * performance optimization. + * + * - Iterator objects remain valid even when entries are added or removed or + * the table is resized. + * + * Hash policies + * + * See the comment about "Hash policy" in HashTable.h for general features that + * hash policy classes must provide. Hash policies for OrderedHashMapImpl and + * Sets differ in that the hash() method takes an extra argument: + * + * static js::HashNumber hash(Lookup, const HashCodeScrambler&); + * + * They must additionally provide a distinguished "empty" key value and the + * following static member functions: + * + * bool isEmpty(const Key&); + * void makeEmpty(Key*); + */ + +#include "mozilla/CheckedInt.h" +#include "mozilla/HashFunctions.h" +#include "mozilla/Likely.h" +#include "mozilla/Maybe.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/TemplateLib.h" + +#include +#include +#include + +#include "builtin/SelfHostingDefines.h" +#include "gc/Barrier.h" +#include "gc/Zone.h" +#include "js/GCPolicyAPI.h" +#include "js/HashTable.h" +#include "vm/JSContext.h" +#include "vm/Realm.h" + +class JSTracer; + +namespace js { + +class MapIteratorObject; +class SetIteratorObject; + +namespace detail { + +template +class OrderedHashTableImpl; + +// Base class for OrderedHashMapObject and OrderedHashSetObject. +class OrderedHashTableObject : public NativeObject { + // Use a friend class to avoid exposing these slot definitions directly to + // MapObject and SetObject. + template + friend class OrderedHashTableImpl; + + enum Slots { + HashTableSlot, + DataSlot, + DataLengthSlot, + DataCapacitySlot, + LiveCountSlot, + HashShiftSlot, + TenuredIteratorsSlot, + NurseryIteratorsSlot, + HashCodeScramblerSlot, + SlotCount + }; + + inline void* allocateCellBuffer(JSContext* cx, size_t numBytes); + + public: + static constexpr size_t offsetOfDataLength() { + return getFixedSlotOffset(DataLengthSlot); + } + static constexpr size_t offsetOfData() { + return getFixedSlotOffset(DataSlot); + } + static constexpr size_t offsetOfHashTable() { + return getFixedSlotOffset(HashTableSlot); + } + static constexpr size_t offsetOfHashShift() { + return getFixedSlotOffset(HashShiftSlot); + } + static constexpr size_t offsetOfLiveCount() { + return getFixedSlotOffset(LiveCountSlot); + } + static constexpr size_t offsetOfHashCodeScrambler() { + return getFixedSlotOffset(HashCodeScramblerSlot); + } +}; + +} // namespace detail + +// Base class for MapIteratorObject and SetIteratorObject. +// +// Iterators remain valid for the lifetime of the OrderedHashTableObject, even +// if entries are added or removed or if the table is resized. Hash table +// objects have a doubly linked list of all active iterator objects and this +// lets us update the iterators when needed. +// +// An "active" iterator object has a target object and must be part of its +// linked list of iterators. When the iterator is finished, the target slot is +// cleared and the iterator is removed from the linked list. +// +// Note: the iterator list stores pointers to iterators as PrivateValue instead +// of ObjectValue because we want these links to be weak pointers: an iterator +// must not keep all other iterators alive. +class TableIteratorObject : public NativeObject { + template + friend class detail::OrderedHashTableImpl; + + public: + enum Slots { + TargetSlot, + KindSlot, + IndexSlot, + CountSlot, + PrevPtrSlot, + NextSlot, + SlotCount + }; + enum class Kind { Keys, Values, Entries }; + + // Slot numbers and Kind values must match constants used in self-hosted code. + static_assert(TargetSlot == ITERATOR_SLOT_TARGET); + static_assert(KindSlot == MAP_SET_ITERATOR_SLOT_ITEM_KIND); + static_assert(int32_t(Kind::Keys) == ITEM_KIND_KEY); + static_assert(int32_t(Kind::Values) == ITEM_KIND_VALUE); + static_assert(int32_t(Kind::Entries) == ITEM_KIND_KEY_AND_VALUE); + + private: + // The index of the current entry within the table's data array. + uint32_t getIndex() const { + return getReservedSlot(IndexSlot).toPrivateUint32(); + } + void setIndex(uint32_t i) { + MOZ_ASSERT(isActive()); + setReservedSlotPrivateUint32Unbarriered(IndexSlot, i); + } + + // The number of nonempty entries in the data array to the left of |index|. + // This is used when the table is resized or compacted. + uint32_t getCount() const { + return getReservedSlot(CountSlot).toPrivateUint32(); + } + void setCount(uint32_t i) { + MOZ_ASSERT(isActive()); + setReservedSlotPrivateUint32Unbarriered(CountSlot, i); + } + + // Links in the doubly-linked list of active iterator objects on the + // OrderedHashTableObject. + // + // The PrevPtr slot points to either the previous iterator's NextSlot or to + // the table's TenuredIteratorsSlot or NurseryIteratorsSlot if this is the + // first iterator in the list. + // + // The Next slot points to the next iterator object, or is nullptr if this is + // the last iterator in the list. + // + // Invariant: *getPrevPtr() == this. + TableIteratorObject** getPrevPtr() const { + MOZ_ASSERT(isActive()); + Value v = getReservedSlot(PrevPtrSlot); + return static_cast(v.toPrivate()); + } + void setPrevPtr(TableIteratorObject** p) { + MOZ_ASSERT(isActive()); + setReservedSlotPrivateUnbarriered(PrevPtrSlot, p); + } + TableIteratorObject* getNext() const { + MOZ_ASSERT(isActive()); + Value v = getReservedSlot(NextSlot); + return static_cast(v.toPrivate()); + } + TableIteratorObject** addressOfNext() { + MOZ_ASSERT(isActive()); + return addressOfFixedSlotPrivatePtr(NextSlot); + } + void setNext(TableIteratorObject* p) { + MOZ_ASSERT(isActive()); + setReservedSlotPrivateUnbarriered(NextSlot, p); + } + + void link(TableIteratorObject** listp) { + MOZ_ASSERT(isActive()); + TableIteratorObject* next = *listp; + setPrevPtr(listp); + setNext(next); + *listp = this; + if (next) { + next->setPrevPtr(this->addressOfNext()); + } + } + + void init(detail::OrderedHashTableObject* target, Kind kind, + TableIteratorObject** listp) { + initReservedSlot(TargetSlot, ObjectValue(*target)); + setReservedSlotPrivateUint32Unbarriered(KindSlot, uint32_t(kind)); + setReservedSlotPrivateUint32Unbarriered(IndexSlot, 0); + setReservedSlotPrivateUint32Unbarriered(CountSlot, 0); + link(listp); + } + + void assertActiveIteratorFor(JSObject* target) { + MOZ_ASSERT(&getReservedSlot(TargetSlot).toObject() == target); + MOZ_ASSERT(*getPrevPtr() == this); + MOZ_ASSERT(getNext() != this); + } + + protected: + bool isActive() const { return getReservedSlot(TargetSlot).isObject(); } + + void finish() { + MOZ_ASSERT(isActive()); + unlink(); + // Mark iterator inactive. + setReservedSlot(TargetSlot, UndefinedValue()); + } + void unlink() { + MOZ_ASSERT(isActive()); + TableIteratorObject** prevp = getPrevPtr(); + TableIteratorObject* next = getNext(); + *prevp = next; + if (next) { + next->setPrevPtr(prevp); + } + } + + // Update list pointers after a compacting GC moved this iterator in memory. + // Note: this isn't used for nursery iterators because in that case we have to + // rebuild the list with clearNurseryIterators and relinkNurseryIterator. + void updateListAfterMove(TableIteratorObject* old) { + MOZ_ASSERT(!IsInsideNursery(old)); + MOZ_ASSERT(isActive()); + MOZ_ASSERT(old != this); + + TableIteratorObject** prevp = getPrevPtr(); + MOZ_ASSERT(*prevp == old); + *prevp = this; + + if (TableIteratorObject* next = getNext()) { + MOZ_ASSERT(next->getPrevPtr() == old->addressOfNext()); + next->setPrevPtr(this->addressOfNext()); + } + } + + Kind kind() const { + uint32_t i = getReservedSlot(KindSlot).toPrivateUint32(); + MOZ_ASSERT(i == uint32_t(Kind::Keys) || i == uint32_t(Kind::Values) || + i == uint32_t(Kind::Entries)); + return Kind(i); + } + + public: + static constexpr size_t offsetOfTarget() { + return getFixedSlotOffset(TargetSlot); + } + static constexpr size_t offsetOfIndex() { + return getFixedSlotOffset(IndexSlot); + } + static constexpr size_t offsetOfCount() { + return getFixedSlotOffset(CountSlot); + } + static constexpr size_t offsetOfPrevPtr() { + return getFixedSlotOffset(PrevPtrSlot); + } + static constexpr size_t offsetOfNext() { + return getFixedSlotOffset(NextSlot); + } +}; + +namespace detail { + +/* + * detail::OrderedHashTableImpl is the underlying code used to implement both + * OrderedHashMapImpl and OrderedHashSetImpl. Programs should use one of those + * two templates rather than OrderedHashTableImpl. + */ +template +class MOZ_STACK_CLASS OrderedHashTableImpl { + public: + using Key = typename Ops::KeyType; + using MutableKey = std::remove_const_t; + using UnbarrieredKey = typename RemoveBarrier::Type; + using Lookup = typename Ops::Lookup; + using HashCodeScrambler = mozilla::HashCodeScrambler; + static constexpr size_t SlotCount = OrderedHashTableObject::SlotCount; + + struct Data { + T element; + Data* chain; + + Data(const T& e, Data* c) : element(e), chain(c) {} + Data(T&& e, Data* c) : element(std::move(e)), chain(c) {} + }; + + private: + using Slots = OrderedHashTableObject::Slots; + OrderedHashTableObject* const obj; + + // Whether we have allocated a buffer for this object. This buffer is + // allocated when adding the first entry and it contains the data array, the + // hash table buckets and the hash code scrambler. + bool hasAllocatedBuffer() const { + MOZ_ASSERT(hasInitializedSlots()); + return obj->getReservedSlot(Slots::DataSlot).toPrivate() != nullptr; + } + + // Hash table. Has hashBuckets() elements. + // Note: a single malloc buffer is used for the data and hashTable arrays and + // the HashCodeScrambler. The pointer in DataSlot points to the start of this + // buffer. + Data** getHashTable() const { + MOZ_ASSERT(hasAllocatedBuffer()); + Value v = obj->getReservedSlot(Slots::HashTableSlot); + return static_cast(v.toPrivate()); + } + void setHashTable(Data** table) { + obj->setReservedSlotPrivateUnbarriered(Slots::HashTableSlot, table); + } + + // Array of Data objects. Elements data[0:dataLength] are constructed and the + // total capacity is dataCapacity. + // + // maybeData returns nullptr if this object doesn't have a buffer yet. + // getData asserts the object has a buffer. + Data* maybeData() const { + Value v = obj->getReservedSlot(Slots::DataSlot); + return static_cast(v.toPrivate()); + } + Data* getData() const { + MOZ_ASSERT(hasAllocatedBuffer()); + return maybeData(); + } + void setData(Data* data) { + obj->setReservedSlotPrivateUnbarriered(Slots::DataSlot, data); + } + + // Number of constructed elements in the data array. + uint32_t getDataLength() const { + return obj->getReservedSlot(Slots::DataLengthSlot).toPrivateUint32(); + } + void setDataLength(uint32_t length) { + obj->setReservedSlotPrivateUint32Unbarriered(Slots::DataLengthSlot, length); + } + + // Size of data array, in elements. + uint32_t getDataCapacity() const { + return obj->getReservedSlot(Slots::DataCapacitySlot).toPrivateUint32(); + } + void setDataCapacity(uint32_t capacity) { + obj->setReservedSlotPrivateUint32Unbarriered(Slots::DataCapacitySlot, + capacity); + } + + // The number of elements in this table. This is different from dataLength + // because the data array can contain empty/removed elements. + uint32_t getLiveCount() const { + return obj->getReservedSlot(Slots::LiveCountSlot).toPrivateUint32(); + } + void setLiveCount(uint32_t liveCount) { + obj->setReservedSlotPrivateUint32Unbarriered(Slots::LiveCountSlot, + liveCount); + } + + // Multiplicative hash shift. + uint32_t getHashShift() const { + MOZ_ASSERT(hasAllocatedBuffer(), + "hash shift is meaningless if there's no hash table"); + return obj->getReservedSlot(Slots::HashShiftSlot).toPrivateUint32(); + } + void setHashShift(uint32_t hashShift) { + obj->setReservedSlotPrivateUint32Unbarriered(Slots::HashShiftSlot, + hashShift); + } + + // List of all active iterators on this table in the tenured heap. Populated + // when iterators are created. + TableIteratorObject* getTenuredIterators() const { + Value v = obj->getReservedSlot(Slots::TenuredIteratorsSlot); + return static_cast(v.toPrivate()); + } + void setTenuredIterators(TableIteratorObject* iter) { + obj->setReservedSlotPrivateUnbarriered(Slots::TenuredIteratorsSlot, iter); + } + TableIteratorObject** addressOfTenuredIterators() const { + static constexpr size_t slot = Slots::TenuredIteratorsSlot; + return obj->addressOfFixedSlotPrivatePtr(slot); + } + + // List of all active iterators on this table in the GC nursery. + // Populated when iterators are created. This is cleared at the start + // of minor GC and rebuilt when iterators are moved. + TableIteratorObject* getNurseryIterators() const { + Value v = obj->getReservedSlot(Slots::NurseryIteratorsSlot); + return static_cast(v.toPrivate()); + } + void setNurseryIterators(TableIteratorObject* iter) { + obj->setReservedSlotPrivateUnbarriered(Slots::NurseryIteratorsSlot, iter); + } + TableIteratorObject** addressOfNurseryIterators() const { + static constexpr size_t slot = Slots::NurseryIteratorsSlot; + return obj->addressOfFixedSlotPrivatePtr(slot); + } + + // Returns a pointer to the list of tenured or nursery iterators depending on + // where |iter| is allocated. + TableIteratorObject** addressOfIterators(TableIteratorObject* iter) { + return IsInsideNursery(iter) ? addressOfNurseryIterators() + : addressOfTenuredIterators(); + } + + // Scrambler to not reveal pointer hash codes. + const HashCodeScrambler* getHashCodeScrambler() const { + MOZ_ASSERT(hasAllocatedBuffer()); + Value v = obj->getReservedSlot(Slots::HashCodeScramblerSlot); + return static_cast(v.toPrivate()); + } + void setHashCodeScrambler(HashCodeScrambler* hcs) { + obj->setReservedSlotPrivateUnbarriered(Slots::HashCodeScramblerSlot, hcs); + } + + static constexpr uint32_t hashShiftToNumHashBuckets(uint32_t hashShift) { + return 1 << (js::kHashNumberBits - hashShift); + } + static constexpr uint32_t numHashBucketsToDataCapacity( + uint32_t numHashBuckets) { + return uint32_t(numHashBuckets * FillFactor); + } + + // Logarithm base 2 of the number of buckets in the hash table initially. + static constexpr uint32_t InitialBucketsLog2 = 1; + static constexpr uint32_t InitialBuckets = 1 << InitialBucketsLog2; + static constexpr uint32_t InitialHashShift = + js::kHashNumberBits - InitialBucketsLog2; + + // The maximum load factor (mean number of entries per bucket). + // It is an invariant that + // dataCapacity == floor(hashBuckets * FillFactor). + // + // The fill factor should be between 2 and 4, and it should be chosen so that + // the fill factor times sizeof(Data) is close to but <= a power of 2. + // This fixed fill factor was chosen to make the size of the data + // array, in bytes, close to a power of two when sizeof(T) is 16. + static constexpr double FillFactor = 8.0 / 3.0; + + // The minimum permitted value of (liveCount / dataLength). + // If that ratio drops below this value, we shrink the table. + static constexpr double MinDataFill = 0.25; + + // Note: a lower hash shift results in a higher capacity. + static constexpr uint32_t MinHashShift = 8; + static constexpr uint32_t MaxHashBuckets = + hashShiftToNumHashBuckets(MinHashShift); // 16777216 + static constexpr uint32_t MaxDataCapacity = + numHashBucketsToDataCapacity(MaxHashBuckets); // 44739242 + + template + void forEachIterator(F&& f) { + TableIteratorObject* next; + for (TableIteratorObject* iter = getTenuredIterators(); iter; iter = next) { + next = iter->getNext(); + f(iter); + } + for (TableIteratorObject* iter = getNurseryIterators(); iter; iter = next) { + next = iter->getNext(); + f(iter); + } + } + + bool hasInitializedSlots() const { + return !obj->getReservedSlot(Slots::DataSlot).isUndefined(); + } + + static MOZ_ALWAYS_INLINE bool calcAllocSize(uint32_t dataCapacity, + uint32_t buckets, + size_t* numBytes) { + using CheckedSize = mozilla::CheckedInt; + auto res = CheckedSize(dataCapacity) * sizeof(Data) + + CheckedSize(sizeof(HashCodeScrambler)) + + CheckedSize(buckets) * sizeof(Data*); + if (MOZ_UNLIKELY(!res.isValid())) { + return false; + } + *numBytes = res.value(); + return true; + } + + // Allocate a single buffer that stores the data array followed by the hash + // code scrambler and the hash table entries. + using AllocationResult = + std::tuple; + AllocationResult allocateBuffer(JSContext* cx, uint32_t dataCapacity, + uint32_t buckets) { + MOZ_ASSERT(dataCapacity <= MaxDataCapacity); + MOZ_ASSERT(buckets <= MaxHashBuckets); + + size_t numBytes = 0; + if (MOZ_UNLIKELY(!calcAllocSize(dataCapacity, buckets, &numBytes))) { + ReportAllocationOverflow(cx); + return {}; + } + + void* buf = obj->allocateCellBuffer(cx, numBytes); + if (!buf) { + return {}; + } + + return getBufferParts(buf, numBytes, dataCapacity, buckets); + } + + static AllocationResult getBufferParts(void* buf, size_t numBytes, + uint32_t dataCapacity, + uint32_t buckets) { + static_assert(alignof(Data) % alignof(HashCodeScrambler) == 0, + "Hash code scrambler must be aligned properly"); + static_assert(alignof(HashCodeScrambler) % alignof(Data*) == 0, + "Hash table entries must be aligned properly"); + + auto* data = static_cast(buf); + auto* hcs = reinterpret_cast(data + dataCapacity); + auto** table = reinterpret_cast(hcs + 1); + + MOZ_ASSERT(uintptr_t(table + buckets) == uintptr_t(buf) + numBytes); + + return {data, table, hcs, numBytes}; + } + + [[nodiscard]] bool initBuffer(JSContext* cx) { + MOZ_ASSERT(!hasAllocatedBuffer()); + MOZ_ASSERT(getDataLength() == 0); + MOZ_ASSERT(getLiveCount() == 0); + + constexpr uint32_t buckets = InitialBuckets; + constexpr uint32_t capacity = uint32_t(buckets * FillFactor); + + auto [dataAlloc, tableAlloc, hcsAlloc, numBytes] = + allocateBuffer(cx, capacity, buckets); + if (!dataAlloc) { + return false; + } + + AddCellMemory(obj, numBytes, MemoryUse::MapObjectData); + + *hcsAlloc = cx->realm()->randomHashCodeScrambler(); + + std::uninitialized_fill_n(tableAlloc, buckets, nullptr); + + setHashTable(tableAlloc); + setData(dataAlloc); + setDataCapacity(capacity); + setHashShift(InitialHashShift); + setHashCodeScrambler(hcsAlloc); + MOZ_ASSERT(hashBuckets() == buckets); + return true; + } + + void updateHashTableForRekey(Data* entry, HashNumber oldHash, + HashNumber newHash) { + uint32_t hashShift = getHashShift(); + oldHash >>= hashShift; + newHash >>= hashShift; + + if (oldHash == newHash) { + return; + } + + // Remove this entry from its old hash chain. (If this crashes reading + // nullptr, it would mean we did not find this entry on the hash chain where + // we expected it. That probably means the key's hash code changed since it + // was inserted, breaking the hash code invariant.) + Data** hashTable = getHashTable(); + Data** ep = &hashTable[oldHash]; + while (*ep != entry) { + ep = &(*ep)->chain; + } + *ep = entry->chain; + + // Add it to the new hash chain. We could just insert it at the beginning of + // the chain. Instead, we do a bit of work to preserve the invariant that + // hash chains always go in reverse insertion order (descending memory + // order). No code currently depends on this invariant, so it's fine to kill + // it if needed. + ep = &hashTable[newHash]; + while (*ep && *ep > entry) { + ep = &(*ep)->chain; + } + entry->chain = *ep; + *ep = entry; + } + + public: + explicit OrderedHashTableImpl(OrderedHashTableObject* obj) : obj(obj) {} + + void initSlots() { + MOZ_ASSERT(!hasInitializedSlots(), "init must be called at most once"); + setHashTable(nullptr); + setData(nullptr); + setDataLength(0); + setDataCapacity(0); + setLiveCount(0); + setHashShift(0); + setTenuredIterators(nullptr); + setNurseryIterators(nullptr); + setHashCodeScrambler(nullptr); + } + + void destroy(JS::GCContext* gcx) { + if (!hasInitializedSlots()) { + return; + } + if (Data* data = maybeData()) { + freeData(gcx, data, getDataLength(), getDataCapacity(), hashBuckets()); + } + } + + void maybeMoveBufferOnPromotion(Nursery& nursery) { + if (!hasAllocatedBuffer()) { + return; + } + + Data* oldData = getData(); + uint32_t dataCapacity = getDataCapacity(); + uint32_t buckets = hashBuckets(); + + size_t numBytes = 0; + MOZ_ALWAYS_TRUE(calcAllocSize(dataCapacity, buckets, &numBytes)); + + void* buf = oldData; + Nursery::WasBufferMoved result = + nursery.maybeMoveNurseryOrMallocBufferOnPromotion( + &buf, obj, numBytes, MemoryUse::MapObjectData); + if (result == Nursery::BufferNotMoved) { + return; + } + + // The buffer was moved in memory. Update reserved slots and fix up the + // |Data*| pointers for the hash table chains. + // TODO(bug 1931492): consider storing indices instead of pointers to + // simplify this. + + auto [data, table, hcs, numBytesUnused] = + getBufferParts(buf, numBytes, dataCapacity, buckets); + + auto entryIndex = [=](const Data* entry) { + MOZ_ASSERT(entry >= oldData); + MOZ_ASSERT(size_t(entry - oldData) < dataCapacity); + return entry - oldData; + }; + + for (uint32_t i = 0, len = getDataLength(); i < len; i++) { + if (const Data* chain = data[i].chain) { + data[i].chain = data + entryIndex(chain); + } + } + for (uint32_t i = 0; i < buckets; i++) { + if (const Data* chain = table[i]) { + table[i] = data + entryIndex(chain); + } + } + + setData(data); + setHashTable(table); + setHashCodeScrambler(hcs); + } + + size_t sizeOfExcludingObject(mozilla::MallocSizeOf mallocSizeOf) const { + size_t size = 0; + if (hasInitializedSlots() && hasAllocatedBuffer()) { + // Note: this also includes the HashCodeScrambler and the hashTable array. + size += mallocSizeOf(getData()); + } + return size; + } + + /* Return the number of elements in the table. */ + uint32_t count() const { return getLiveCount(); } + + /* True if any element matches l. */ + bool has(const Lookup& l) const { return lookup(l) != nullptr; } + + /* Return a pointer to the element, if any, that matches l, or nullptr. */ + T* get(const Lookup& l) { + Data* e = lookup(l); + return e ? &e->element : nullptr; + } + + /* + * If the table already contains an entry that matches |element|, + * replace that entry with |element|. Otherwise add a new entry. + * + * On success, return true, whether there was already a matching element or + * not. On allocation failure, return false. If this returns false, it + * means the element was not added to the table. + */ + template + [[nodiscard]] bool put(JSContext* cx, ElementInput&& element) { + HashNumber h; + if (hasAllocatedBuffer()) { + h = prepareHash(Ops::getKey(element)); + if (Data* e = lookup(Ops::getKey(element), h)) { + e->element = std::forward(element); + return true; + } + if (getDataLength() == getDataCapacity() && !rehashOnFull(cx)) { + return false; + } + } else { + if (!initBuffer(cx)) { + return false; + } + h = prepareHash(Ops::getKey(element)); + } + auto [entry, chain] = addEntry(h); + new (entry) Data(std::forward(element), chain); + return true; + } + +#ifdef NIGHTLY_BUILD + /* + * If the table already contains an entry that matches |element|, + * return that entry. Otherwise add a new entry. + * + * On success, return a pointer to the element, whether there was already a + * matching element or not. On allocation failure, return a nullptr. If this + * returns a nullptr, it means the element was not added to the table. + */ + template + [[nodiscard]] T* getOrAdd(JSContext* cx, ElementInput&& element) { + HashNumber h; + if (hasAllocatedBuffer()) { + h = prepareHash(Ops::getKey(element)); + if (Data* e = lookup(Ops::getKey(element), h)) { + return &e->element; + } + if (getDataLength() == getDataCapacity() && !rehashOnFull(cx)) { + return nullptr; + } + } else { + if (!initBuffer(cx)) { + return nullptr; + } + h = prepareHash(Ops::getKey(element)); + } + auto [entry, chain] = addEntry(h); + new (entry) Data(std::forward(element), chain); + return &entry->element; + } +#endif // #ifdef NIGHTLY_BUILD + + /* + * If the table contains an element matching l, remove it and return true. + * Otherwise return false. + */ + bool remove(JSContext* cx, const Lookup& l) { + // Note: This could be optimized so that removing the last entry, + // data[dataLength - 1], decrements dataLength. LIFO use cases would + // benefit. + + // If a matching entry exists, empty it. + Data* e = lookup(l); + if (e == nullptr) { + return false; + } + + MOZ_ASSERT(uint32_t(e - getData()) < getDataCapacity()); + + uint32_t liveCount = getLiveCount(); + liveCount--; + setLiveCount(liveCount); + Ops::makeEmpty(&e->element); + + // Update active iterators. + uint32_t pos = e - getData(); + forEachIterator( + [this, pos](auto* iter) { IterOps::onRemove(obj, iter, pos); }); + + // If many entries have been removed, try to shrink the table. Ignore OOM + // because shrinking the table is an optimization and it's okay for it to + // fail. + if (hashBuckets() > InitialBuckets && + liveCount < getDataLength() * MinDataFill) { + if (!rehash(cx, getHashShift() + 1)) { + cx->recoverFromOutOfMemory(); + } + } + + return true; + } + + /* + * Remove all entries. + * + * The effect on active iterators is the same as removing all entries; in + * particular, those iterators are still active and will see any entries + * added after a clear(). + */ + void clear(JSContext* cx) { + if (getDataLength() != 0) { + destroyData(getData(), getDataLength()); + setDataLength(0); + setLiveCount(0); + + size_t buckets = hashBuckets(); + std::fill_n(getHashTable(), buckets, nullptr); + + forEachIterator([](auto* iter) { IterOps::onClear(iter); }); + + // Try to shrink the table. Ignore OOM because shrinking the table is an + // optimization and it's okay for it to fail. + if (buckets > InitialBuckets) { + if (!rehash(cx, InitialHashShift)) { + cx->recoverFromOutOfMemory(); + } + } + } + + MOZ_ASSERT(getDataLength() == 0); + MOZ_ASSERT(getLiveCount() == 0); + } + + class IterOps { + friend class OrderedHashTableImpl; + + static void init(OrderedHashTableObject* table, TableIteratorObject* iter, + TableIteratorObject::Kind kind) { + auto** listp = OrderedHashTableImpl(table).addressOfIterators(iter); + iter->init(table, kind, listp); + seek(table, iter); + } + + static void seek(OrderedHashTableObject* table, TableIteratorObject* iter) { + iter->assertActiveIteratorFor(table); + const Data* data = OrderedHashTableImpl(table).maybeData(); + uint32_t dataLength = OrderedHashTableImpl(table).getDataLength(); + uint32_t i = iter->getIndex(); + while (i < dataLength && Ops::isEmpty(Ops::getKey(data[i].element))) { + i++; + } + iter->setIndex(i); + } + + // The hash table calls this when an entry is removed. + // j is the index of the removed entry. + static void onRemove(OrderedHashTableObject* table, + TableIteratorObject* iter, uint32_t j) { + iter->assertActiveIteratorFor(table); + uint32_t i = iter->getIndex(); + if (j < i) { + iter->setCount(iter->getCount() - 1); + } + if (j == i) { + seek(table, iter); + } + } + + // The hash table calls this when the table is resized or compacted. + // Since |count| is the number of nonempty entries to the left of |index|, + // discarding the empty entries will not affect |count|, and it will make + // |index| and |count| equal. + static void onCompact(TableIteratorObject* iter) { + iter->setIndex(iter->getCount()); + } + + // The hash table calls this when cleared. + static void onClear(TableIteratorObject* iter) { + iter->setIndex(0); + iter->setCount(0); + } + + // If the iterator reached the end of the data array, we're done: mark the + // iterator inactive, remove it from the linked list, and return |true|. + // Else, call |f| for the current entry, advance the iterator to the next + // entry, and return |false|. + template + static bool next(OrderedHashTableObject* obj, TableIteratorObject* iter, + F&& f) { + iter->assertActiveIteratorFor(obj); + + OrderedHashTableImpl table(obj); + uint32_t index = iter->getIndex(); + + if (index >= table.getDataLength()) { + iter->finish(); + return true; + } + + f(iter->kind(), table.getData()[index].element); + + iter->setCount(iter->getCount() + 1); + iter->setIndex(index + 1); + seek(obj, iter); + return false; + } + }; + + // Calls |f| for each entry in the table. This function must not mutate the + // table. + template + [[nodiscard]] bool forEachEntry(F&& f) const { + const Data* data = maybeData(); + uint32_t dataLength = getDataLength(); +#ifdef DEBUG + uint32_t liveCount = getLiveCount(); +#endif + for (uint32_t i = 0; i < dataLength; i++) { + if (!Ops::isEmpty(Ops::getKey(data[i].element))) { + if (!f(data[i].element)) { + return false; + } + } + } + MOZ_ASSERT(maybeData() == data); + MOZ_ASSERT(getDataLength() == dataLength); + MOZ_ASSERT(getLiveCount() == liveCount); + return true; + } +#ifdef DEBUG + // Like forEachEntry, but infallible and the function is called at most + // maxCount times. This is useful for debug assertions. + template + void forEachEntryUpTo(size_t maxCount, F&& f) const { + MOZ_ASSERT(maxCount > 0); + const Data* data = maybeData(); + uint32_t dataLength = getDataLength(); + uint32_t liveCount = getLiveCount(); + size_t count = 0; + for (uint32_t i = 0; i < dataLength; i++) { + if (!Ops::isEmpty(Ops::getKey(data[i].element))) { + f(data[i].element); + count++; + if (count == maxCount) { + break; + } + } + } + MOZ_ASSERT(maybeData() == data); + MOZ_ASSERT(getDataLength() == dataLength); + MOZ_ASSERT(getLiveCount() == liveCount); + } +#endif + + void trace(JSTracer* trc) { + Data* data = maybeData(); + uint32_t dataLength = getDataLength(); + for (uint32_t i = 0; i < dataLength; i++) { + if (!Ops::isEmpty(Ops::getKey(data[i].element))) { + Ops::trace(trc, this, i, data[i].element); + } + } + } + + // For use by the implementation of Ops::trace. + void traceKey(JSTracer* trc, uint32_t index, const Key& key) { + MOZ_ASSERT(index < getDataLength()); + UnbarrieredKey newKey = key; + JS::GCPolicy::trace(trc, &newKey, + "OrderedHashTableObject key"); + if (newKey != key) { + rekey(&getData()[index], newKey); + } + } + template + void traceValue(JSTracer* trc, Value& value) { + JS::GCPolicy::trace(trc, &value, "OrderedHashMapObject value"); + } + + void initIterator(TableIteratorObject* iter, + TableIteratorObject::Kind kind) const { + IterOps::init(obj, iter, kind); + } + template + bool iteratorNext(TableIteratorObject* iter, F&& f) const { + return IterOps::next(obj, iter, f); + } + + void clearNurseryIterators() { + if (TableIteratorObject* iter = getNurseryIterators()) { + iter->setPrevPtr(nullptr); + } + setNurseryIterators(nullptr); + } + void relinkNurseryIterator(TableIteratorObject* iter) { + auto** listp = addressOfIterators(iter); + iter->link(listp); + } + + void updateIteratorsAfterMove(OrderedHashTableObject* old) { + if (TableIteratorObject* iter = getTenuredIterators()) { + MOZ_ASSERT(iter->getPrevPtr() == + OrderedHashTableImpl(old).addressOfTenuredIterators()); + iter->setPrevPtr(addressOfTenuredIterators()); + } + if (TableIteratorObject* iter = getNurseryIterators()) { + MOZ_ASSERT(iter->getPrevPtr() == + OrderedHashTableImpl(old).addressOfNurseryIterators()); + iter->setPrevPtr(addressOfNurseryIterators()); + } + } + + bool hasNurseryIterators() const { return getNurseryIterators(); } + + /* + * Change the value of the given key. + * + * This calls Ops::hash on both the current key and the new key. + * Ops::hash on the current key must return the same hash code as + * when the entry was added to the table. + */ + void rekeyOneEntry(const Key& current, const Key& newKey, const T& element) { + if (current == newKey) { + return; + } + + HashNumber currentHash = prepareHash(current); + HashNumber newHash = prepareHash(newKey); + + Data* entry = lookup(current, currentHash); + MOZ_ASSERT(entry); + entry->element = element; + + updateHashTableForRekey(entry, currentHash, newHash); + } + + static constexpr size_t offsetOfDataElement() { + static_assert(offsetof(Data, element) == 0, + "TableIteratorLoadEntry and TableIteratorAdvance depend on " + "offsetof(Data, element) being 0"); + return offsetof(Data, element); + } + static constexpr size_t offsetOfDataChain() { return offsetof(Data, chain); } + static constexpr size_t sizeofData() { return sizeof(Data); } + +#ifdef DEBUG + mozilla::Maybe hash(const Lookup& l) const { + // We can only compute the hash number if we have an allocated buffer + // because the buffer contains the hash code scrambler. + if (!hasAllocatedBuffer()) { + return {}; + } + return mozilla::Some(prepareHash(l)); + } +#endif + + private: + HashNumber prepareHash(const Lookup& l) const { + MOZ_ASSERT(hasAllocatedBuffer(), + "the hash code scrambler is allocated in the buffer"); + const HashCodeScrambler& hcs = *getHashCodeScrambler(); + return mozilla::ScrambleHashCode(Ops::hash(l, hcs)); + } + + /* The size of the hash table, in elements. Always a power of two. */ + uint32_t hashBuckets() const { + return hashShiftToNumHashBuckets(getHashShift()); + } + + void destroyData(Data* data, uint32_t length) { + Data* end = data + length; + for (Data* p = data; p != end; p++) { + p->~Data(); + } + } + + void freeData(JS::GCContext* gcx, Data* data, uint32_t length, + uint32_t capacity, uint32_t hashBuckets) { + MOZ_ASSERT(data); + MOZ_ASSERT(capacity > 0); + + destroyData(data, length); + + size_t numBytes; + MOZ_ALWAYS_TRUE(calcAllocSize(capacity, hashBuckets, &numBytes)); + + if (IsInsideNursery(obj)) { + if (gcx->runtime()->gc.nursery().isInside(data)) { + return; + } + gcx->runtime()->gc.nursery().removeMallocedBuffer(data, numBytes); + } + + gcx->free_(obj, data, numBytes, MemoryUse::MapObjectData); + } + + Data* lookup(const Lookup& l, HashNumber h) const { + MOZ_ASSERT(hasAllocatedBuffer()); + Data** hashTable = getHashTable(); + uint32_t hashShift = getHashShift(); + for (Data* e = hashTable[h >> hashShift]; e; e = e->chain) { + if (Ops::match(Ops::getKey(e->element), l)) { + return e; + } + } + return nullptr; + } + + Data* lookup(const Lookup& l) const { + // Note: checking |getLiveCount() > 0| is a minor performance optimization + // but this check is also required for correctness because it implies + // |hasAllocatedBuffer()|. + if (getLiveCount() == 0) { + return nullptr; + } + return lookup(l, prepareHash(l)); + } + + std::tuple addEntry(HashNumber hash) { + uint32_t dataLength = getDataLength(); + MOZ_ASSERT(dataLength < getDataCapacity()); + + Data* entry = &getData()[dataLength]; + setDataLength(dataLength + 1); + setLiveCount(getLiveCount() + 1); + + Data** hashTable = getHashTable(); + hash >>= getHashShift(); + Data* chain = hashTable[hash]; + hashTable[hash] = entry; + + return std::make_tuple(entry, chain); + } + + /* This is called after rehashing the table. */ + void compacted() { + // If we had any empty entries, compacting may have moved live entries + // to the left within the data array. Notify all active iterators of + // the change. + forEachIterator([](auto* iter) { IterOps::onCompact(iter); }); + } + + /* Compact the entries in the data array and rehash them. */ + void rehashInPlace() { + Data** hashTable = getHashTable(); + std::fill_n(hashTable, hashBuckets(), nullptr); + + Data* const data = getData(); + uint32_t hashShift = getHashShift(); + Data* wp = data; + Data* end = data + getDataLength(); + for (Data* rp = data; rp != end; rp++) { + if (!Ops::isEmpty(Ops::getKey(rp->element))) { + HashNumber h = prepareHash(Ops::getKey(rp->element)) >> hashShift; + if (rp != wp) { + wp->element = std::move(rp->element); + } + wp->chain = hashTable[h]; + hashTable[h] = wp; + wp++; + } + } + MOZ_ASSERT(wp == data + getLiveCount()); + + while (wp != end) { + wp->~Data(); + wp++; + } + setDataLength(getLiveCount()); + compacted(); + } + + [[nodiscard]] bool rehashOnFull(JSContext* cx) { + MOZ_ASSERT(getDataLength() == getDataCapacity()); + + // If the hashTable is more than 1/4 deleted data, simply rehash in + // place to free up some space. Otherwise, grow the table. + uint32_t newHashShift = getLiveCount() >= getDataCapacity() * 0.75 + ? getHashShift() - 1 + : getHashShift(); + return rehash(cx, newHashShift); + } + + /* + * Grow, shrink, or compact both the hash table and data array. + * + * On success, this returns true, dataLength == liveCount, and there are no + * empty elements in data[0:dataLength]. On allocation failure, this + * leaves everything as it was and returns false. + */ + [[nodiscard]] bool rehash(JSContext* cx, uint32_t newHashShift) { + // If the size of the table is not changing, rehash in place to avoid + // allocating memory. + if (newHashShift == getHashShift()) { + rehashInPlace(); + return true; + } + + if (MOZ_UNLIKELY(newHashShift < MinHashShift)) { + ReportAllocationOverflow(cx); + return false; + } + + uint32_t newHashBuckets = hashShiftToNumHashBuckets(newHashShift); + uint32_t newCapacity = numHashBucketsToDataCapacity(newHashBuckets); + + auto [newData, newHashTable, newHcs, numBytes] = + allocateBuffer(cx, newCapacity, newHashBuckets); + if (!newData) { + return false; + } + + *newHcs = *getHashCodeScrambler(); + + std::uninitialized_fill_n(newHashTable, newHashBuckets, nullptr); + + Data* const oldData = getData(); + const uint32_t oldDataLength = getDataLength(); + + Data* wp = newData; + Data* end = oldData + oldDataLength; + for (Data* p = oldData; p != end; p++) { + if (!Ops::isEmpty(Ops::getKey(p->element))) { + HashNumber h = prepareHash(Ops::getKey(p->element)) >> newHashShift; + new (wp) Data(std::move(p->element), newHashTable[h]); + newHashTable[h] = wp; + wp++; + } + } + MOZ_ASSERT(wp == newData + getLiveCount()); + + freeData(obj->runtimeFromMainThread()->gcContext(), oldData, oldDataLength, + getDataCapacity(), hashBuckets()); + + AddCellMemory(obj, numBytes, MemoryUse::MapObjectData); + + setHashTable(newHashTable); + setData(newData); + setDataLength(getLiveCount()); + setDataCapacity(newCapacity); + setHashShift(newHashShift); + setHashCodeScrambler(newHcs); + MOZ_ASSERT(hashBuckets() == newHashBuckets); + + compacted(); + return true; + } + + // Change the key of the front entry. + // + // This calls Ops::hash on both the current key and the new key. Ops::hash on + // the current key must return the same hash code as when the entry was added + // to the table. + void rekey(Data* entry, const UnbarrieredKey& k) { + HashNumber oldHash = prepareHash(Ops::getKey(entry->element)); + HashNumber newHash = prepareHash(k); + reinterpret_cast(Ops::getKeyRef(entry->element)) = k; + updateHashTableForRekey(entry, oldHash, newHash); + } +}; + +} // namespace detail + +class OrderedHashMapObject : public detail::OrderedHashTableObject {}; + +template +class MOZ_STACK_CLASS OrderedHashMapImpl { + public: + class Entry { + template + friend class detail::OrderedHashTableImpl; + void operator=(const Entry& rhs) { + const_cast(key) = rhs.key; + value = rhs.value; + } + + void operator=(Entry&& rhs) { + MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); + const_cast(key) = std::move(rhs.key); + value = std::move(rhs.value); + } + + public: + Entry() = default; + explicit Entry(const Key& k) : key(k) {} + template + Entry(const Key& k, V&& v) : key(k), value(std::forward(v)) {} + Entry(Entry&& rhs) : key(std::move(rhs.key)), value(std::move(rhs.value)) {} + + const Key key{}; + Value value{}; + + static constexpr size_t offsetOfKey() { return offsetof(Entry, key); } + static constexpr size_t offsetOfValue() { return offsetof(Entry, value); } + }; + + private: + struct MapOps; + using Impl = detail::OrderedHashTableImpl; + + struct MapOps : OrderedHashPolicy { + using KeyType = Key; + static void makeEmpty(Entry* e) { + OrderedHashPolicy::makeEmpty(const_cast(&e->key)); + + // Clear the value. Destroying it is another possibility, but that + // would complicate class Entry considerably. + e->value = Value(); + } + static const Key& getKey(const Entry& e) { return e.key; } + static Key& getKeyRef(Entry& e) { return const_cast(e.key); } + static void trace(JSTracer* trc, Impl* table, uint32_t index, + Entry& entry) { + table->traceKey(trc, index, entry.key); + table->traceValue(trc, entry.value); + } + }; + + Impl impl; + + public: + using Lookup = typename Impl::Lookup; + static constexpr size_t SlotCount = Impl::SlotCount; + + explicit OrderedHashMapImpl(OrderedHashMapObject* obj) : impl(obj) {} + + void initSlots() { impl.initSlots(); } + uint32_t count() const { return impl.count(); } + bool has(const Lookup& key) const { return impl.has(key); } + template + [[nodiscard]] bool forEachEntry(F&& f) const { + return impl.forEachEntry(f); + } +#ifdef DEBUG + template + void forEachEntryUpTo(size_t maxCount, F&& f) const { + impl.forEachEntryUpTo(maxCount, f); + } +#endif + Entry* get(const Lookup& key) { return impl.get(key); } + bool remove(JSContext* cx, const Lookup& key) { return impl.remove(cx, key); } + void clear(JSContext* cx) { impl.clear(cx); } + + void destroy(JS::GCContext* gcx) { impl.destroy(gcx); } + + template + [[nodiscard]] bool put(JSContext* cx, K&& key, V&& value) { + return impl.put(cx, Entry(std::forward(key), std::forward(value))); + } + +#ifdef NIGHTLY_BUILD + template + [[nodiscard]] Entry* getOrAdd(JSContext* cx, K&& key, V&& value) { + return impl.getOrAdd(cx, + Entry(std::forward(key), std::forward(value))); + } +#endif // #ifdef NIGHTLY_BUILD + +#ifdef DEBUG + mozilla::Maybe hash(const Lookup& key) const { + return impl.hash(key); + } +#endif + + template + mozilla::Maybe rekeyOneEntry(Lookup& current, GetNewKey&& getNewKey) { + // TODO: This is inefficient because we also look up the entry in + // impl.rekeyOneEntry below. + const Entry* e = get(current); + if (!e) { + return mozilla::Nothing(); + } + + Key newKey = getNewKey(current); + impl.rekeyOneEntry(current, newKey, Entry(newKey, e->value)); + return mozilla::Some(newKey); + } + + void initIterator(MapIteratorObject* iter, + TableIteratorObject::Kind kind) const { + impl.initIterator(iter, kind); + } + template + bool iteratorNext(MapIteratorObject* iter, F&& f) const { + return impl.iteratorNext(iter, f); + } + + void clearNurseryIterators() { impl.clearNurseryIterators(); } + void relinkNurseryIterator(MapIteratorObject* iter) { + impl.relinkNurseryIterator(iter); + } + void updateIteratorsAfterMove(OrderedHashMapObject* old) { + impl.updateIteratorsAfterMove(old); + } + bool hasNurseryIterators() const { return impl.hasNurseryIterators(); } + + void maybeMoveBufferOnPromotion(Nursery& nursery) { + return impl.maybeMoveBufferOnPromotion(nursery); + } + + void trace(JSTracer* trc) { impl.trace(trc); } + + static constexpr size_t offsetOfEntryKey() { return Entry::offsetOfKey(); } + static constexpr size_t offsetOfImplDataElement() { + return Impl::offsetOfDataElement(); + } + static constexpr size_t offsetOfImplDataChain() { + return Impl::offsetOfDataChain(); + } + static constexpr size_t sizeofImplData() { return Impl::sizeofData(); } + + size_t sizeOfExcludingObject(mozilla::MallocSizeOf mallocSizeOf) const { + return impl.sizeOfExcludingObject(mallocSizeOf); + } +}; + +class OrderedHashSetObject : public detail::OrderedHashTableObject {}; + +template +class MOZ_STACK_CLASS OrderedHashSetImpl { + private: + struct SetOps; + using Impl = detail::OrderedHashTableImpl; + + struct SetOps : OrderedHashPolicy { + using KeyType = const T; + static const T& getKey(const T& v) { return v; } + static T& getKeyRef(T& e) { return e; } + static void trace(JSTracer* trc, Impl* table, uint32_t index, T& entry) { + table->traceKey(trc, index, entry); + } + }; + + Impl impl; + + public: + using Lookup = typename Impl::Lookup; + static constexpr size_t SlotCount = Impl::SlotCount; + + explicit OrderedHashSetImpl(OrderedHashSetObject* obj) : impl(obj) {} + + void initSlots() { impl.initSlots(); } + uint32_t count() const { return impl.count(); } + bool has(const Lookup& value) const { return impl.has(value); } + template + [[nodiscard]] bool forEachEntry(F&& f) const { + return impl.forEachEntry(f); + } +#ifdef DEBUG + template + void forEachEntryUpTo(size_t maxCount, F&& f) const { + impl.forEachEntryUpTo(maxCount, f); + } +#endif + template + [[nodiscard]] bool put(JSContext* cx, Input&& value) { + return impl.put(cx, std::forward(value)); + } + bool remove(JSContext* cx, const Lookup& value) { + return impl.remove(cx, value); + } + void clear(JSContext* cx) { impl.clear(cx); } + + void destroy(JS::GCContext* gcx) { impl.destroy(gcx); } + +#ifdef DEBUG + mozilla::Maybe hash(const Lookup& value) const { + return impl.hash(value); + } +#endif + + template + mozilla::Maybe rekeyOneEntry(Lookup& current, GetNewKey&& getNewKey) { + // TODO: This is inefficient because we also look up the entry in + // impl.rekeyOneEntry below. + if (!has(current)) { + return mozilla::Nothing(); + } + + T newKey = getNewKey(current); + impl.rekeyOneEntry(current, newKey, newKey); + return mozilla::Some(newKey); + } + + void initIterator(SetIteratorObject* iter, + TableIteratorObject::Kind kind) const { + impl.initIterator(iter, kind); + } + template + bool iteratorNext(SetIteratorObject* iter, F&& f) const { + return impl.iteratorNext(iter, f); + } + + void clearNurseryIterators() { impl.clearNurseryIterators(); } + void relinkNurseryIterator(SetIteratorObject* iter) { + impl.relinkNurseryIterator(iter); + } + void updateIteratorsAfterMove(OrderedHashSetObject* old) { + impl.updateIteratorsAfterMove(old); + } + bool hasNurseryIterators() const { return impl.hasNurseryIterators(); } + + void maybeMoveBufferOnPromotion(Nursery& nursery) { + return impl.maybeMoveBufferOnPromotion(nursery); + } + + void trace(JSTracer* trc) { impl.trace(trc); } + + static constexpr size_t offsetOfEntryKey() { return 0; } + static constexpr size_t offsetOfImplDataElement() { + return Impl::offsetOfDataElement(); + } + static constexpr size_t offsetOfImplDataChain() { + return Impl::offsetOfDataChain(); + } + static constexpr size_t sizeofImplData() { return Impl::sizeofData(); } + + size_t sizeOfExcludingObject(mozilla::MallocSizeOf mallocSizeOf) const { + return impl.sizeOfExcludingObject(mallocSizeOf); + } +}; + +} // namespace js + +#endif /* builtin_OrderedHashTableObject_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.cpp index efb05d18453..cbea0245336 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.cpp @@ -6,37 +6,68 @@ #include "builtin/ParseRecordObject.h" +#include "jsapi.h" // JS_ValueToId, JS_IdToValue +#include "builtin/Object.h" +#include "vm/PlainObject.h" + #include "vm/JSObject-inl.h" // NewBuiltinClassInstance using namespace js; // https://tc39.es/proposal-json-parse-with-source/#sec-json-parse-record -ParseRecordObject::ParseRecordObject() - : parseNode(nullptr), key(JS::PropertyKey::Void()) {} +const JSClass ParseRecordObject::class_ = { + "ParseRecordObject", + JSCLASS_HAS_RESERVED_SLOTS(SlotCount), +}; -ParseRecordObject::ParseRecordObject(Handle parseNode, - const Value& val) - : parseNode(parseNode), key(JS::PropertyKey::Void()), value(val) {} +/* static */ +ParseRecordObject* ParseRecordObject::create(JSContext* cx, const Value& val) { + Rooted parseNode(cx); + return ParseRecordObject::create(cx, parseNode, val); +} -bool ParseRecordObject::addEntries(JSContext* cx, EntryMap&& appendEntries) { - if (!entries) { - entries = js::MakeUnique(std::move(appendEntries)); - return !!entries; +/* static */ +ParseRecordObject* ParseRecordObject::create(JSContext* cx, + Handle parseNode, + const Value& val) { + Rooted obj( + cx, NewObjectWithGivenProto(cx, nullptr)); + if (!obj) { + return nullptr; } - for (auto iter = appendEntries.iter(); !iter.done(); iter.next()) { - if (!entries->put(iter.get().key(), std::move(iter.get().value()))) { - return false; - } + + if (parseNode) { + obj->initSlot(ParseNodeSlot, StringValue(parseNode)); } + obj->initSlot(ValueSlot, val); + return obj; +} + +JS::PropertyKey ParseRecordObject::getKey(JSContext* cx) const { + Rooted slot(cx, getSlot(KeySlot)); + Rooted key(cx); + MOZ_ALWAYS_TRUE(JS_ValueToId(cx, slot, &key)); + return key; +}; + +bool ParseRecordObject::setKey(JSContext* cx, const JS::PropertyKey& key) { + Rooted val(cx); + if (!JS_IdToValue(cx, key, &val)) { + return false; + } + setSlot(KeySlot, val); return true; } -void ParseRecordObject::trace(JSTracer* trc) { - JS::TraceRoot(trc, &parseNode, "ParseRecordObject parse node"); - JS::TraceRoot(trc, &key, "ParseRecordObject key"); - JS::TraceRoot(trc, &value, "ParseRecordObject value"); - if (entries) { - entries->trace(trc); +void ParseRecordObject::setEntries(JSContext* cx, Handle entries) { + setSlot(EntriesSlot, ObjectValue(*entries)); +} + +void ParseRecordObject::getEntries(JSContext* cx, + MutableHandle entries) { + const Value& entryVal = getSlot(EntriesSlot); + if (entryVal.isObject()) { + entries.set(&entryVal.toObject()); } } diff --git a/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.h b/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.h index 7e3176a23f8..116c0474316 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/ParseRecordObject.h @@ -15,46 +15,46 @@ namespace js { using JSONParseNode = JSString; -class ParseRecordObject { +class ParseRecordObject : public NativeObject { + enum { ParseNodeSlot, ValueSlot, KeySlot, EntriesSlot, SlotCount }; + public: - using EntryMap = js::GCHashMap; + using EntryMap = JSObject; + + static const JSClass class_; + + static ParseRecordObject* create(JSContext* cx, const Value& val); + static ParseRecordObject* create(JSContext* cx, + Handle parseNode, + const Value& val); // The source text that was parsed for this record. According to the spec, we // don't track this for objects and arrays, so it will be a null pointer. - JSONParseNode* parseNode; - // For object members, the member key. For arrays, the index. For JSON - // primitives, it will be undefined. - JS::PropertyKey key; - // The original value corresponding to this record, used to determine if the - // reviver function has modified it. - Value value; - // For objects and arrays, the records for the members and elements - // (respectively). If there are none, or for JSON primitives, we won't - // allocate an EntryMap. - UniquePtr entries; - - ParseRecordObject(); - ParseRecordObject(Handle parseNode, const Value& val); - ParseRecordObject(ParseRecordObject&& other) - : parseNode(std::move(other.parseNode)), - key(std::move(other.key)), - value(std::move(other.value)), - entries(std::move(other.entries)) {} - - bool isEmpty() const { return value.isUndefined(); } - - bool addEntries(JSContext* cx, EntryMap&& appendEntries); - - // move assignment - ParseRecordObject& operator=(ParseRecordObject&& other) noexcept { - parseNode = other.parseNode; - key = other.key; - value = other.value; - entries = std::move(other.entries); - return *this; + JSONParseNode* getParseNode() const { + const Value& slot = getSlot(ParseNodeSlot); + return slot.isUndefined() ? nullptr : slot.toString(); } - void trace(JSTracer* trc); + // For object members, the member key. For arrays, the index. For JSON + // primitives, it will be undefined. + JS::PropertyKey getKey(JSContext* cx) const; + + bool setKey(JSContext* cx, const JS::PropertyKey& key); + + // The original value corresponding to this record, used to determine if the + // reviver function has modified it. + const Value& getValue() const { return getSlot(ValueSlot); } + + void setValue(JS::Handle value) { setSlot(ValueSlot, value); } + + bool hasValue() const { return !getValue().isUndefined(); } + + // For objects and arrays, the records for the members and elements + // (respectively). If there are none, or for JSON primitives, the entries + // parameter is unmodified. + void getEntries(JSContext* cx, MutableHandle entries); + + void setEntries(JSContext* cx, Handle entries); }; } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/builtin/Profilers.cpp b/src/third_party/mozjs/extract/js/src/builtin/Profilers.cpp index 06a825e1110..5750ea25891 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Profilers.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Profilers.cpp @@ -80,7 +80,7 @@ JS_PUBLIC_API bool JS_StartProfiling(const char* profileName, pid_t pid) { ok = StartOSXProfiling(profileName, pid); #endif #ifdef __linux__ - if (!js_StartPerf()) { + if (!js_StartPerf(profileName)) { ok = false; } #endif @@ -363,7 +363,8 @@ static const JSFunctionSpec profiling_functions[] = { JS_FN("stopCallgrind", StopCallgrind, 0, 0), JS_FN("dumpCallgrind", DumpCallgrind, 1, 0), # endif - JS_FS_END}; + JS_FS_END, +}; #endif @@ -442,9 +443,8 @@ JS_PUBLIC_API bool js_DumpCallgrind(const char* outfile) { * * To pass additional parameters to |perf record|, provide them in the * MOZ_PROFILE_PERF_FLAGS environment variable. If this variable does not - * exist, we default it to "--call-graph". (If you don't want --call-graph but - * don't want to pass any other args, define MOZ_PROFILE_PERF_FLAGS to the empty - * string.) + * exist, we default it to "-g". (If you don't want -g but don't want to + * pass any other args, define MOZ_PROFILE_PERF_FLAGS to the empty string.) * * If you include --pid or --output in MOZ_PROFILE_PERF_FLAGS, you're just * asking for trouble. @@ -461,8 +461,9 @@ JS_PUBLIC_API bool js_DumpCallgrind(const char* outfile) { static bool perfInitialized = false; static pid_t perfPid = 0; -bool js_StartPerf() { - const char* outfile = "mozperf.data"; +bool js_StartPerf(const char* profileName) { + const char* outfile = + (profileName && profileName[0]) ? profileName : "mozperf.data"; if (perfPid != 0) { UnsafeError("js_StartPerf: called while perf was already running!\n"); @@ -505,7 +506,7 @@ bool js_StartPerf() { const char* flags = getenv("MOZ_PROFILE_PERF_FLAGS"); if (!flags) { - flags = "--call-graph"; + flags = "-g"; } UniqueChars flags2 = DuplicateString(flags); diff --git a/src/third_party/mozjs/extract/js/src/builtin/Profilers.h b/src/third_party/mozjs/extract/js/src/builtin/Profilers.h index ab6235e215d..0d821ecf8f9 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Profilers.h +++ b/src/third_party/mozjs/extract/js/src/builtin/Profilers.h @@ -79,7 +79,7 @@ JS_PUBLIC_API const char* JS_UnsafeGetLastProfilingError(); #ifdef __linux__ -[[nodiscard]] extern JS_PUBLIC_API bool js_StartPerf(); +[[nodiscard]] extern JS_PUBLIC_API bool js_StartPerf(const char* outfile); [[nodiscard]] extern JS_PUBLIC_API bool js_StopPerf(); diff --git a/src/third_party/mozjs/extract/js/src/builtin/Promise.cpp b/src/third_party/mozjs/extract/js/src/builtin/Promise.cpp index 6bcb67351bb..eaca016b80c 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Promise.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Promise.cpp @@ -31,7 +31,6 @@ #include "vm/JSObject.h" #include "vm/JSONPrinter.h" // js::JSONPrinter #include "vm/PlainObject.h" // js::PlainObject -#include "vm/PromiseLookup.h" // js::PromiseLookup #include "vm/PromiseObject.h" // js::PromiseObject, js::PromiseSlot_* #include "vm/SelfHosting.h" #include "vm/Warnings.h" // js::WarnNumberASCII @@ -108,35 +107,32 @@ enum ReactionJobSlots { ReactionJobSlot_ReactionRecord = 0, }; +// Extended function slots used to pass arguments through to either +// PromiseResolveThenableJob, or PromiseResolveBuiltinThenableJob when calling +// the built-in `then`. enum ThenableJobSlots { - // The handler to use as the Promise reaction. It is a callable object - // that's guaranteed to be from the same compartment as the - // PromiseReactionJob. - ThenableJobSlot_Handler = 0, - - // JobData - a, potentially CCW-wrapped, dense list containing data - // required for proper execution of the reaction. - ThenableJobSlot_JobData, -}; - -enum ThenableJobDataIndices { // The Promise to resolve using the given thenable. - ThenableJobDataIndex_Promise = 0, + // + // This can be a CCW when used for PromiseResolveThenableJob, otherwise it is + // guaranteed not to be. + ThenableJobSlot_Promise = 0, // The thenable to use as the receiver when calling the `then` function. - ThenableJobDataIndex_Thenable, + // + // This can be a CCW when used for PromiseResolveThenableJob, otherwise it is + // guaranteed not to be. + ThenableJobSlot_Thenable, - ThenableJobDataLength, + // The handler to use as the Promise reaction, when not calling the built-in + // `then`. It is a callable object that's guaranteed to be from the same + // compartment as the PromiseReactionJob. + ThenableJobSlot_Handler, + + ThenableJobSlot_Count }; -enum BuiltinThenableJobSlots { - // The Promise to resolve using the given thenable. - BuiltinThenableJobSlot_Promise = 0, - - // The thenable to use as the receiver when calling the built-in `then` - // function. - BuiltinThenableJobSlot_Thenable, -}; +static_assert(size_t(ThenableJobSlot_Count) <= + size_t(FunctionExtended::SlotCount)); struct PromiseCapability { JSObject* promise = nullptr; @@ -240,7 +236,9 @@ class PromiseCombinatorDataHolder : public NativeObject { }; const JSClass PromiseCombinatorDataHolder::class_ = { - "PromiseCombinatorDataHolder", JSCLASS_HAS_RESERVED_SLOTS(SlotsCount)}; + "PromiseCombinatorDataHolder", + JSCLASS_HAS_RESERVED_SLOTS(SlotsCount), +}; // Smart pointer to the "F.[[Values]]" part of the state of a Promise.all or // Promise.allSettled invocation, or the "F.[[Errors]]" part of the state of a @@ -390,6 +388,32 @@ namespace { mozilla::Atomic gIDGenerator(0); } // namespace +// Returns true if the following properties haven't been mutated: +// - On the original Promise.prototype object: "constructor" and "then" +// - On the original Promise constructor: "resolve" and @@species +static bool HasDefaultPromiseProperties(JSContext* cx) { + return cx->realm()->realmFuses.optimizePromiseLookupFuse.intact(); +} + +static bool IsPromiseWithDefaultProperties(PromiseObject* promise, + JSContext* cx) { + if (!HasDefaultPromiseProperties(cx)) { + return false; + } + + // Ensure the promise's prototype is the original Promise.prototype object. + JSObject* proto = cx->global()->maybeGetPrototype(JSProto_Promise); + if (!proto || promise->staticPrototype() != proto) { + return false; + } + + // Ensure `promise` doesn't define any own properties. This serves as a + // quick check to make sure `promise` doesn't define an own "constructor" + // or "then" property which may shadow Promise.prototype.constructor or + // Promise.prototype.then. + return promise->empty(); +} + class PromiseDebugInfo : public NativeObject { private: enum Slots { @@ -544,7 +568,9 @@ class PromiseDebugInfo : public NativeObject { }; const JSClass PromiseDebugInfo::class_ = { - "PromiseDebugInfo", JSCLASS_HAS_RESERVED_SLOTS(SlotCount)}; + "PromiseDebugInfo", + JSCLASS_HAS_RESERVED_SLOTS(SlotCount), +}; double PromiseObject::allocationTime() { auto debugInfo = PromiseDebugInfo::FromPromise(this); @@ -613,8 +639,8 @@ static bool MaybeGetAndClearExceptionAndStack( * be tedious, so the check in step 1 and the entirety of step 2 aren't * included. */ -static bool AbruptRejectPromise(JSContext* cx, CallArgs& args, - HandleObject promiseObj, HandleObject reject) { +bool js::AbruptRejectPromise(JSContext* cx, CallArgs& args, + HandleObject promiseObj, HandleObject reject) { // Step 1.a. Perform // ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). RootedValue reason(cx); @@ -700,8 +726,9 @@ enum ReactionRecordSlots { ReactionRecordSlot_Resolve, ReactionRecordSlot_Reject, - // The incumbent global for this reaction record. Can be null. - ReactionRecordSlot_IncumbentGlobalObject, + // The host defined data for this reaction record. Can be null. + // See step 5 in https://html.spec.whatwg.org/#hostmakejobcallback + ReactionRecordSlot_HostDefinedData, // Bitmask of the REACTION_FLAG values. ReactionRecordSlot_Flags, @@ -901,10 +928,10 @@ class PromiseReactionRecord : public NativeObject { return getFixedSlot(handlerArgSlot()); } - JSObject* getAndClearIncumbentGlobalObject() { + JSObject* getAndClearHostDefinedData() { JSObject* obj = - getFixedSlot(ReactionRecordSlot_IncumbentGlobalObject).toObjectOrNull(); - setFixedSlot(ReactionRecordSlot_IncumbentGlobalObject, UndefinedValue()); + getFixedSlot(ReactionRecordSlot_HostDefinedData).toObjectOrNull(); + setFixedSlot(ReactionRecordSlot_HostDefinedData, UndefinedValue()); return obj; } @@ -914,7 +941,9 @@ class PromiseReactionRecord : public NativeObject { }; const JSClass PromiseReactionRecord::class_ = { - "PromiseReactionRecord", JSCLASS_HAS_RESERVED_SLOTS(ReactionRecordSlots)}; + "PromiseReactionRecord", + JSCLASS_HAS_RESERVED_SLOTS(ReactionRecordSlots), +}; static void AddPromiseFlags(PromiseObject& promise, int32_t flag) { int32_t flags = promise.flags(); @@ -1212,6 +1241,89 @@ static bool Promise_then_impl(JSContext* cx, HandleValue promiseVal, HandleValue onFulfilled, HandleValue onRejected, MutableHandleValue rval, bool rvalExplicitlyUsed); +// This is used to get the 'then' property off of an object, and report some +// information back for telemetry purposes. When we no longer need this +// telemetry this function can be removed and replaced with GetProperty +bool GetThenValue(JSContext* cx, JS::Handle obj, + JS::Handle reciever, + JS::MutableHandle thenVal, bool* isOnProto, + bool* isOnStandardProto, bool* isOnObjectProto) { + MOZ_ASSERT(isOnProto && *isOnProto == false); + MOZ_ASSERT(isOnStandardProto && *isOnStandardProto == false); + MOZ_ASSERT(isOnObjectProto && *isOnObjectProto == false); + + NativeObject* holder; + PropertyResult prop; + + // LookupProperty would be observable unforunately. If we can do the lookup, + // then we can produce information, but otherwise we're left blind. + // Fortunately, since this is purely for the purposes of telemetry, let's just + // use Pure. + RootedId thenId(cx, NameToId(cx->names().then)); + + // If we're doing the lookup on the original promise prototype we want to only + // report telemetry if the value is not the original Promise.prototype.then + // + // We then need to defer until after the lookup to decide this. + bool maybeOnPromiseProto = false; + do { + if (LookupPropertyPure(cx, obj, thenId, &holder, &prop)) { + if (prop.isNotFound()) { + break; + } + + if (holder != obj) { + *isOnProto = true; + + auto key = JS::IdentifyStandardPrototype(holder); + if (key != JSProto_Null) { + if (key == JSProto_Promise) { + maybeOnPromiseProto = true; + } else { + *isOnStandardProto = true; + if (key == JSProto_Object) { + *isOnObjectProto = true; + } + } + } + } + } + } while (false); + + if (!GetProperty(cx, obj, reciever, cx->names().then, thenVal)) { + return false; + } + + if (maybeOnPromiseProto) { + *isOnStandardProto = !IsNativeFunction(thenVal, Promise_then); + } + + return true; +} + +void ReportThenable(JSContext* cx, bool isOnProto, bool isOnStandardProto, + bool isOnObjectProto) { + cx->runtime()->setUseCounter(cx->global(), JSUseCounter::THENABLE_USE); + + if (isOnProto) { + cx->runtime()->setUseCounter(cx->global(), + JSUseCounter::THENABLE_USE_PROTO); + JS_LOG(thenable, Debug, "Thenable on proto"); + } + + if (isOnStandardProto) { + cx->runtime()->setUseCounter(cx->global(), + JSUseCounter::THENABLE_USE_STANDARD_PROTO); + JS_LOG(thenable, Info, "Thenable on standard proto"); + } + + if (isOnObjectProto) { + cx->runtime()->setUseCounter(cx->global(), + JSUseCounter::THENABLE_USE_OBJECT_PROTO); + JS_LOG(thenable, Info, "Thenable on Object.prototype"); + } +} + /** * ES2022 draft rev d03c1ec6e235a5180fa772b6178727c17974cb14 * @@ -1252,8 +1364,11 @@ static bool Promise_then_impl(JSContext* cx, HandleValue promiseVal, // Step 9. Let then be Get(resolution, "then"). RootedValue thenVal(cx); - bool status = - GetProperty(cx, resolution, resolution, cx->names().then, &thenVal); + bool isOnProto = false; + bool isOnStandardProto = false; + bool isOnObjectProto = false; + bool status = GetThenValue(cx, resolution, resolutionVal, &thenVal, + &isOnProto, &isOnStandardProto, &isOnObjectProto); RootedValue error(cx); Rooted errorStack(cx); @@ -1311,6 +1426,8 @@ static bool Promise_then_impl(JSContext* cx, HandleValue promiseVal, } if (!isBuiltinThen) { + ReportThenable(cx, isOnProto, isOnStandardProto, isOnObjectProto); + RootedValue promiseVal(cx, ObjectValue(*promise)); if (!EnqueuePromiseResolveThenableJob(cx, promiseVal, resolutionVal, thenVal)) { @@ -1543,26 +1660,21 @@ static bool PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp); } } - // Using objectFromIncumbentGlobal, we can derive the incumbent global by - // unwrapping and then getting the global. This is very convoluted, but - // much better than having to store the original global as a private value - // because we couldn't wrap it to store it as a normal JS value. - Rooted global(cx); - if (JSObject* objectFromIncumbentGlobal = - reaction->getAndClearIncumbentGlobalObject()) { - objectFromIncumbentGlobal = CheckedUnwrapStatic(objectFromIncumbentGlobal); - MOZ_ASSERT(objectFromIncumbentGlobal); - global = &objectFromIncumbentGlobal->nonCCWGlobal(); + JS::Rooted hostDefinedData(cx); + if (JSObject* hostDefined = reaction->getAndClearHostDefinedData()) { + hostDefined = CheckedUnwrapStatic(hostDefined); + MOZ_ASSERT(hostDefined); + // If the hostDefined object becomes a dead wrapper here, the target + // global has already gone, and the job queue won't run the promise job + // anyway. + if (JS_IsDeadWrapper(hostDefined)) { + return true; + } + hostDefinedData = hostDefined; } // HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]). - // - // Note: the global we pass here might be from a different compartment - // than job and promise. While it's somewhat unusual to pass objects - // from multiple compartments, in this case we specifically need the - // global to be unwrapped because wrapping and unwrapping aren't - // necessarily symmetric for globals. - return cx->runtime()->enqueuePromiseJob(cx, job, promise, global); + return cx->runtime()->enqueuePromiseJob(cx, job, promise, hostDefinedData); } [[nodiscard]] static bool TriggerPromiseReactions(JSContext* cx, @@ -1707,8 +1819,8 @@ enum GetCapabilitiesExecutorSlots { * Promise ( executor ) * https://tc39.es/ecma262/#sec-promise-executor */ -[[nodiscard]] static PromiseObject* -CreatePromiseObjectWithoutResolutionFunctions(JSContext* cx) { +[[nodiscard]] PromiseObject* js::CreatePromiseObjectWithoutResolutionFunctions( + JSContext* cx) { // Steps 3-7. PromiseObject* promise = CreatePromiseObjectInternal(cx); if (!promise) { @@ -1803,9 +1915,6 @@ CreatePromiseObjectWithoutResolutionFunctions(JSContext* cx) { return true; } - // At this point this is effectively subclassing; - ReportUsageCounter(cx, C, SUBCLASSING_PROMISE, SUBCLASSING_TYPE_II); - // Step 4. Let executorClosure be a new Abstract Closure with parameters // (resolve, reject) that captures promiseCapability and performs the // following steps when called: @@ -2218,7 +2327,18 @@ static bool PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp) { // Step 1.d.ii.2. Let handlerResult be ThrowCompletion(argument). resolutionMode = RejectMode; handlerResult = argument; - } else { + } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + else if (handlerNum == PromiseHandler::AsyncIteratorDisposeAwaitFulfilled) { + // Explicit Resource Management Proposal + // 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose + // + // Step 6.e.i. Return undefined. + handlerResult = JS::UndefinedValue(); + } +#endif + else { // Special case for Async-from-Sync Iterator. MOZ_ASSERT(handlerNum == @@ -2288,17 +2408,11 @@ static bool PromiseResolveThenableJob(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedFunction job(cx, &args.callee().as()); + RootedObject promise( + cx, &job->getExtendedSlot(ThenableJobSlot_Promise).toObject()); + RootedValue thenable(cx, job->getExtendedSlot(ThenableJobSlot_Thenable)); RootedValue then(cx, job->getExtendedSlot(ThenableJobSlot_Handler)); MOZ_ASSERT(then.isObject()); - Rooted jobArgs(cx, - &job->getExtendedSlot(ThenableJobSlot_JobData) - .toObject() - .as()); - - RootedObject promise( - cx, &jobArgs->getDenseElement(ThenableJobDataIndex_Promise).toObject()); - RootedValue thenable(cx, - jobArgs->getDenseElement(ThenableJobDataIndex_Thenable)); // Step 1.a. Let resolvingFunctions be // CreateResolvingFunctions(promiseToResolve). @@ -2358,8 +2472,8 @@ static bool PromiseResolveThenableJob(JSContext* cx, unsigned argc, Value* vp) { * extended JSFunction object, with all information required for the job's * execution stored in the function's extended slots. * - * Usage of the function's extended slots is described in the - * BuiltinThenableJobSlots enum. + * Usage of the function's extended slots is described in the ThenableJobSlots + * enum. */ static bool PromiseResolveBuiltinThenableJob(JSContext* cx, unsigned argc, Value* vp) { @@ -2367,9 +2481,11 @@ static bool PromiseResolveBuiltinThenableJob(JSContext* cx, unsigned argc, RootedFunction job(cx, &args.callee().as()); RootedObject promise( - cx, &job->getExtendedSlot(BuiltinThenableJobSlot_Promise).toObject()); + cx, &job->getExtendedSlot(ThenableJobSlot_Promise).toObject()); RootedObject thenable( - cx, &job->getExtendedSlot(BuiltinThenableJobSlot_Thenable).toObject()); + cx, &job->getExtendedSlot(ThenableJobSlot_Thenable).toObject()); + // The handler slot is not used for builtin `then`. + MOZ_ASSERT(job->getExtendedSlot(ThenableJobSlot_Handler).isUndefined()); cx->check(promise, thenable); MOZ_ASSERT(promise->is()); @@ -2484,35 +2600,23 @@ static bool PromiseResolveBuiltinThenableJob(JSContext* cx, unsigned argc, return false; } - // Store the `then` function on the callback. + // Set the `promiseToResolve`, `thenable` and `then` arguments on the + // callback. + job->setExtendedSlot(ThenableJobSlot_Promise, promiseToResolve); + job->setExtendedSlot(ThenableJobSlot_Thenable, thenable); job->setExtendedSlot(ThenableJobSlot_Handler, ObjectValue(*then)); - // Create a dense array to hold the data needed for the reaction job to - // work. - // The layout is described in the ThenableJobDataIndices enum. - Rooted data( - cx, NewDenseFullyAllocatedArray(cx, ThenableJobDataLength)); - if (!data) { - return false; - } - - // Set the `promiseToResolve` and `thenable` arguments. - data->setDenseInitializedLength(ThenableJobDataLength); - data->initDenseElement(ThenableJobDataIndex_Promise, promiseToResolve); - data->initDenseElement(ThenableJobDataIndex_Thenable, thenable); - - // Store the data array on the reaction job. - job->setExtendedSlot(ThenableJobSlot_JobData, ObjectValue(*data)); - // At this point the promise is guaranteed to be wrapped into the job's // compartment. RootedObject promise(cx, &promiseToResolve.toObject()); - Rooted incumbentGlobal(cx, - cx->runtime()->getIncumbentGlobal(cx)); + Rooted hostDefinedData(cx); + if (!cx->runtime()->getHostDefinedData(cx, &hostDefinedData)) { + return false; + } // Step X. HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]). - return cx->runtime()->enqueuePromiseJob(cx, job, promise, incumbentGlobal); + return cx->runtime()->enqueuePromiseJob(cx, job, promise, hostDefinedData); } /** @@ -2551,16 +2655,17 @@ static bool PromiseResolveBuiltinThenableJob(JSContext* cx, unsigned argc, // thus `thenRealm` is also current realm, and we have nothing to do here. // Store the promise and the thenable on the reaction job. - job->setExtendedSlot(BuiltinThenableJobSlot_Promise, - ObjectValue(*promiseToResolve)); - job->setExtendedSlot(BuiltinThenableJobSlot_Thenable, ObjectValue(*thenable)); + job->setExtendedSlot(ThenableJobSlot_Promise, ObjectValue(*promiseToResolve)); + job->setExtendedSlot(ThenableJobSlot_Thenable, ObjectValue(*thenable)); - Rooted incumbentGlobal(cx, - cx->runtime()->getIncumbentGlobal(cx)); + Rooted hostDefinedData(cx); + if (!cx->runtime()->getHostDefinedData(cx, &hostDefinedData)) { + return false; + } // HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]). return cx->runtime()->enqueuePromiseJob(cx, job, promiseToResolve, - incumbentGlobal); + hostDefinedData); } [[nodiscard]] static bool AddDummyPromiseReactionForDebugger( @@ -3011,8 +3116,7 @@ enum class CombinatorKind { All, AllSettled, Any, Race }; return false; } - PromiseLookup& promiseLookup = cx->realm()->promiseLookup; - if (C != promiseCtor || !promiseLookup.isDefaultPromiseState(cx)) { + if (C != promiseCtor || !HasDefaultPromiseProperties(cx)) { // Step 3. Let promiseResolve be GetPromiseResolve(C). // GetPromiseResolve @@ -3509,13 +3613,11 @@ template // during the iteration. bool iterationMayHaveSideEffects = !iterator.isOptimizedDenseArrayIteration(); - PromiseLookup& promiseLookup = cx->realm()->promiseLookup; - // Try to optimize when the Promise object is in its default state, guarded // by |C == promiseCtor| because we can only perform this optimization // for the builtin Promise constructor. bool isDefaultPromiseState = - C == promiseCtor && promiseLookup.isDefaultPromiseState(cx); + C == promiseCtor && HasDefaultPromiseProperties(cx); bool validatePromiseState = iterationMayHaveSideEffects; RootedValue CVal(cx, ObjectValue(*C)); @@ -3560,7 +3662,7 @@ template bool getThen = true; if (isDefaultPromiseState && validatePromiseState) { - isDefaultPromiseState = promiseLookup.isDefaultPromiseState(cx); + isDefaultPromiseState = HasDefaultPromiseProperties(cx); } RootedValue& nextPromise = nextValueOrNextPromise; @@ -3571,8 +3673,7 @@ template } if (nextValuePromise && - promiseLookup.isDefaultInstanceWhenPromiseStateIsSane( - cx, nextValuePromise)) { + IsPromiseWithDefaultProperties(nextValuePromise, cx)) { // The below steps don't produce any side-effects, so we can // skip the Promise state revalidation in the next iteration // when the iterator itself also doesn't produce any @@ -3669,12 +3770,15 @@ template } bool isBuiltinThen; + bool isOnProto = false; + bool isOnStandardProto = false; + bool isOnObjectProto = false; if (getThen) { // We don't use the Promise lookup cache here, because this code // is only called when we had a lookup cache miss, so it's likely // we'd get another cache miss when trying to use the cache here. - if (!GetProperty(cx, nextPromiseObj, nextPromise, cx->names().then, - &thenVal)) { + if (!GetThenValue(cx, nextPromiseObj, nextPromise, &thenVal, &isOnProto, + &isOnStandardProto, &isOnObjectProto)) { return false; } @@ -3745,7 +3849,8 @@ template return false; } } else { - // Optimization failed, do the normal call. + ReportThenable(cx, isOnProto, isOnStandardProto, isOnObjectProto); + RootedValue& ignored = thenVal; if (!Call(cx, thenVal, nextPromise, resolveFunVal, rejectFunVal, &ignored)) { @@ -4936,6 +5041,83 @@ PromiseObject* PromiseObject::unforgeableResolveWithNonPromise( return promise; } +/** + * https://tc39.es/proposal-promise-try/ + * + * Promise.try ( ) + */ +static bool Promise_static_try(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // 1. Let C be the this value. + RootedValue cVal(cx, args.thisv()); + + // 2. If C is not an Object, throw a TypeError exception. + if (!cVal.isObject()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_OBJECT_REQUIRED, + "Receiver of Promise.try call"); + return false; + } + + // 3. Let promiseCapability be ? NewPromiseCapability(C). + RootedObject c(cx, &cVal.toObject()); + Rooted promiseCapability(cx); + if (!NewPromiseCapability(cx, c, &promiseCapability, false)) { + return false; + } + HandleObject promiseObject = promiseCapability.promise(); + + // 4. Let status be Completion(Call(callbackfn, undefined, args)). + size_t argCount = args.length(); + if (argCount > 0) { + argCount--; + } + + InvokeArgs iargs(cx); + if (!iargs.init(cx, argCount)) { + return false; + } + + for (size_t i = 0; i < argCount; i++) { + iargs[i].set(args[i + 1]); + } + + HandleValue callbackfn = args.get(0); + RootedValue rval(cx); + bool ok = Call(cx, callbackfn, UndefinedHandleValue, iargs, &rval); + + // 5. If status is an abrupt completion, then + if (!ok) { + RootedValue reason(cx); + Rooted stack(cx); + + if (!MaybeGetAndClearExceptionAndStack(cx, &reason, &stack)) { + return false; + } + + // 5.a. Perform ? Call(promiseCapability.[[Reject]], undefined, « + // status.[[Value]] »). + if (!CallPromiseRejectFunction(cx, promiseCapability.reject(), reason, + promiseObject, stack, + UnhandledRejectionBehavior::Report)) { + return false; + } + } else { + // 6. Else, + // 6.a. Perform ? Call(promiseCapability.[[Resolve]], undefined, « + // status.[[Value]] »). + if (!CallPromiseResolveFunction(cx, promiseCapability.resolve(), rval, + promiseObject)) { + return false; + } + } + + // 7. Return promiseCapability.[[Promise]]. + args.rval().setObject(*promiseObject); + return true; +} + /** * https://tc39.es/proposal-promise-with-resolvers/ * @@ -5009,12 +5191,12 @@ bool js::Promise_static_species(JSContext* cx, unsigned argc, Value* vp) { return true; } -enum class IncumbentGlobalObject { - // Do not use the incumbent global, this is a special case used by the +enum class HostDefinedDataObject { + // Do not use the host defined data object, this is a special case used by the // debugger. No, - // Use incumbent global, this is the normal operation. + // Use host defined data object, this is the normal operation. Yes }; @@ -5031,10 +5213,10 @@ enum class IncumbentGlobalObject { static PromiseReactionRecord* NewReactionRecord( JSContext* cx, Handle resultCapability, HandleValue onFulfilled, HandleValue onRejected, - IncumbentGlobalObject incumbentGlobalObjectOption) { + HostDefinedDataObject hostDefinedDataObjectOption) { #ifdef DEBUG if (resultCapability.promise()) { - if (incumbentGlobalObjectOption == IncumbentGlobalObject::Yes) { + if (hostDefinedDataObjectOption == HostDefinedDataObject::Yes) { if (resultCapability.promise()->is()) { // If `resultCapability.promise` is a Promise object, // `resultCapability.{resolve,reject}` may be optimized out, @@ -5072,7 +5254,7 @@ static PromiseReactionRecord* NewReactionRecord( // In any case, other fields are also not used. MOZ_ASSERT(!resultCapability.resolve()); MOZ_ASSERT(!resultCapability.reject()); - MOZ_ASSERT(incumbentGlobalObjectOption == IncumbentGlobalObject::Yes); + MOZ_ASSERT(hostDefinedDataObjectOption == HostDefinedDataObject::Yes); } #endif @@ -5093,9 +5275,9 @@ static PromiseReactionRecord* NewReactionRecord( // Handlers must either both be present or both be absent. MOZ_ASSERT(onFulfilled.isNull() == onRejected.isNull()); - RootedObject incumbentGlobalObject(cx); - if (incumbentGlobalObjectOption == IncumbentGlobalObject::Yes) { - if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobalObject)) { + RootedObject hostDefinedData(cx); + if (hostDefinedDataObjectOption == HostDefinedDataObject::Yes) { + if (!GetObjectFromHostDefinedData(cx, &hostDefinedData)) { return nullptr; } } @@ -5111,7 +5293,7 @@ static PromiseReactionRecord* NewReactionRecord( cx->check(onRejected); cx->check(resultCapability.resolve()); cx->check(resultCapability.reject()); - cx->check(incumbentGlobalObject); + cx->check(hostDefinedData); // Step 7. Let fulfillReaction be the PromiseReaction // { [[Capability]]: resultCapability, [[Type]]: Fulfill, @@ -5133,8 +5315,8 @@ static PromiseReactionRecord* NewReactionRecord( ObjectOrNullValue(resultCapability.resolve())); reaction->setFixedSlot(ReactionRecordSlot_Reject, ObjectOrNullValue(resultCapability.reject())); - reaction->setFixedSlot(ReactionRecordSlot_IncumbentGlobalObject, - ObjectOrNullValue(incumbentGlobalObject)); + reaction->setFixedSlot(ReactionRecordSlot_HostDefinedData, + ObjectOrNullValue(hostDefinedData)); return reaction; } @@ -5303,7 +5485,7 @@ static bool PromiseThenNewPromiseCapability( Rooted reaction( cx, NewReactionRecord(cx, resultCapability, onFulfilled, onRejected, - IncumbentGlobalObject::Yes)); + HostDefinedDataObject::Yes)); if (!reaction) { return false; } @@ -5318,8 +5500,8 @@ static bool PromiseThenNewPromiseCapability( static bool CanCallOriginalPromiseThenBuiltin(JSContext* cx, HandleValue promise) { return promise.isObject() && promise.toObject().is() && - cx->realm()->promiseLookup.isDefaultInstance( - cx, &promise.toObject().as()); + IsPromiseWithDefaultProperties(&promise.toObject().as(), + cx); } static MOZ_ALWAYS_INLINE bool IsPromiseThenOrCatchRetValImplicitlyUsed( @@ -5556,7 +5738,7 @@ template resultCapability.promise().set(resultPromise); Rooted reaction( cx, NewReactionRecord(cx, resultCapability, onFulfilledValue, - onRejectedValue, IncumbentGlobalObject::Yes)); + onRejectedValue, HostDefinedDataObject::Yes)); if (!reaction) { return false; } @@ -5564,6 +5746,25 @@ template return PerformPromiseThenWithReaction(cx, unwrappedPromise, reaction); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +// Explicit Resource Management Proposal +// 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) +// Steps 6.c-g +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose +// The steps mentioned above are almost identical to the steps 3-7 of +// https://tc39.es/ecma262/#await we have a utility function InternalAwait which +// covers these steps thus this following function wraps around the utility +// and implements the steps of %AsyncIteratorPrototype% [ @@asyncDispose ] ( ). +[[nodiscard]] bool js::InternalAsyncIteratorDisposeAwait( + JSContext* cx, JS::Handle value, + JS::Handle resultPromise) { + auto extra = [](JS::Handle reaction) {}; + return InternalAwait(cx, value, resultPromise, + PromiseHandler::AsyncIteratorDisposeAwaitFulfilled, + PromiseHandler::Thrower, extra); +} +#endif + [[nodiscard]] bool js::InternalAsyncGeneratorAwait( JSContext* cx, JS::Handle generator, JS::Handle value, PromiseHandler onFulfilled, @@ -5850,7 +6051,15 @@ static bool Promise_catch_impl(JSContext* cx, unsigned argc, Value* vp, // Step 2. Return ? Invoke(promise, "then", « undefined, onRejected »). RootedValue thenVal(cx); - if (!GetProperty(cx, thisVal, cx->names().then, &thenVal)) { + RootedObject thisObj(cx, ToObject(cx, thisVal)); + bool isOnProto = false; + bool isOnStandardProto = false; + bool isOnObjectProto = false; + if (!thisObj) { + return false; + } + if (!GetThenValue(cx, thisObj, thisVal, &thenVal, &isOnProto, + &isOnStandardProto, &isOnObjectProto)) { return false; } @@ -5860,6 +6069,7 @@ static bool Promise_catch_impl(JSContext* cx, unsigned argc, Value* vp, rvalExplicitlyUsed); } + ReportThenable(cx, isOnProto, isOnStandardProto, isOnObjectProto); return Call(cx, thenVal, thisVal, UndefinedHandleValue, onRejected, args.rval()); } @@ -6027,7 +6237,7 @@ bool js::Promise_then(JSContext* cx, unsigned argc, Value* vp) { // NOTE: We use single object for both reactions. Rooted reaction( cx, NewReactionRecord(cx, resultCapability, onFulfilled, onRejected, - IncumbentGlobalObject::Yes)); + HostDefinedDataObject::Yes)); if (!reaction) { return false; } @@ -6067,7 +6277,7 @@ bool js::Promise_then(JSContext* cx, unsigned argc, Value* vp) { // [[Handler]]: onRejectedJobCallback }. Rooted reaction( cx, NewReactionRecord(cx, resultCapability, onFulfilled, onRejected, - IncumbentGlobalObject::Yes)); + HostDefinedDataObject::Yes)); if (!reaction) { return false; } @@ -6256,7 +6466,7 @@ bool js::Promise_then(JSContext* cx, unsigned argc, Value* vp) { Rooted reaction( cx, NewReactionRecord(cx, capability, NullHandleValue, NullHandleValue, - IncumbentGlobalObject::No)); + HostDefinedDataObject::No)); if (!reaction) { return false; } @@ -6648,9 +6858,8 @@ void PromiseReactionRecord::dumpOwnFields(js::JSONPrinter& json) const { } { - js::GenericPrinter& out = json.beginStringProperty("incumbentGlobal"); - getFixedSlot(ReactionRecordSlot_IncumbentGlobalObject) - .dumpStringContent(out); + js::GenericPrinter& out = json.beginStringProperty("hostDefinedData"); + getFixedSlot(ReactionRecordSlot_HostDefinedData).dumpStringContent(out); json.endStringProperty(); } @@ -6917,8 +7126,7 @@ void PromiseObject::dumpOwnStringContent(js::GenericPrinter& out) const {} return true; } - PromiseLookup& promiseLookup = cx->realm()->promiseLookup; - if (!promiseLookup.isDefaultInstance(cx, promise)) { + if (!IsPromiseWithDefaultProperties(promise, cx)) { *canSkip = false; return true; } @@ -7000,10 +7208,14 @@ const JSJitInfo promise_catch_info = { static const JSFunctionSpec promise_methods[] = { JS_FNINFO("then", js::Promise_then, &promise_then_info, 2, 0), JS_FNINFO("catch", Promise_catch, &promise_catch_info, 1, 0), - JS_SELF_HOSTED_FN("finally", "Promise_finally", 1, 0), JS_FS_END}; + JS_SELF_HOSTED_FN("finally", "Promise_finally", 1, 0), + JS_FS_END, +}; static const JSPropertySpec promise_properties[] = { - JS_STRING_SYM_PS(toStringTag, "Promise", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "Promise", JSPROP_READONLY), + JS_PS_END, +}; static const JSFunctionSpec promise_static_methods[] = { JS_FN("all", Promise_static_all, 1, 0), @@ -7013,10 +7225,14 @@ static const JSFunctionSpec promise_static_methods[] = { JS_FN("reject", Promise_reject, 1, 0), JS_FN("resolve", js::Promise_static_resolve, 1, 0), JS_FN("withResolvers", Promise_static_withResolvers, 0, 0), - JS_FS_END}; + JS_FN("try", Promise_static_try, 1, 0), + JS_FS_END, +}; static const JSPropertySpec promise_static_properties[] = { - JS_SYM_GET(species, js::Promise_static_species, 0), JS_PS_END}; + JS_SYM_GET(species, js::Promise_static_species, 0), + JS_PS_END, +}; static const ClassSpec PromiseObjectClassSpec = { GenericCreateConstructor, @@ -7024,15 +7240,22 @@ static const ClassSpec PromiseObjectClassSpec = { promise_static_methods, promise_static_properties, promise_methods, - promise_properties}; + promise_properties, + GenericFinishInit, +}; const JSClass PromiseObject::class_ = { "Promise", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_Promise) | JSCLASS_HAS_XRAYED_CONSTRUCTOR, - JS_NULL_CLASS_OPS, &PromiseObjectClassSpec}; + JS_NULL_CLASS_OPS, + &PromiseObjectClassSpec, +}; const JSClass PromiseObject::protoClass_ = { - "Promise.prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_Promise), - JS_NULL_CLASS_OPS, &PromiseObjectClassSpec}; + "Promise.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_Promise), + JS_NULL_CLASS_OPS, + &PromiseObjectClassSpec, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/Promise.h b/src/third_party/mozjs/extract/js/src/builtin/Promise.h index 3224a073dd9..6104f3e8e69 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Promise.h +++ b/src/third_party/mozjs/extract/js/src/builtin/Promise.h @@ -73,6 +73,15 @@ enum class PromiseHandler : uint32_t { AsyncFromSyncIteratorValueUnwrapDone, AsyncFromSyncIteratorValueUnwrapNotDone, +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // Explicit Resource Management Proposal + // 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose + // + // Step 6.e. unwrap Abstract Closure + AsyncIteratorDisposeAwaitFulfilled, +#endif + // One past the maximum allowed PromiseHandler value. Limit }; @@ -246,6 +255,10 @@ struct PromiseReactionRecordBuilder { [[nodiscard]] PromiseObject* CreatePromiseObjectForAsyncGenerator( JSContext* cx); +// This implements "Let promiseCapability be ! NewPromiseCapability(%Promise%)". +[[nodiscard]] PromiseObject* CreatePromiseObjectWithoutResolutionFunctions( + JSContext* cx); + [[nodiscard]] bool ResolvePromiseInternal(JSContext* cx, JS::Handle promise, JS::Handle resolutionVal); @@ -264,6 +277,16 @@ void SetAlreadyResolvedPromiseWithDefaultResolvingFunction( PromiseObject* promise); bool IsPromiseConstructor(const JSObject* obj); + +bool AbruptRejectPromise(JSContext* cx, JS::CallArgs& args, + JS::Handle promiseObj, + JS::Handle reject); + +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +[[nodiscard]] bool InternalAsyncIteratorDisposeAwait( + JSContext* cx, JS::Handle value, + JS::Handle resultPromise); +#endif } // namespace js #endif // builtin_Promise_h diff --git a/src/third_party/mozjs/extract/js/src/builtin/RawJSONObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/RawJSONObject.cpp index 08a98835c1d..7659321c9a0 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/RawJSONObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/RawJSONObject.cpp @@ -11,20 +11,25 @@ using namespace js; -const JSClass RawJSONObject::class_ = {"RawJSON", - JSCLASS_HAS_RESERVED_SLOTS(SlotCount)}; +const JSClass RawJSONObject::class_ = { + "RawJSON", + JSCLASS_HAS_RESERVED_SLOTS(SlotCount), +}; /* static */ RawJSONObject* RawJSONObject::create(JSContext* cx, Handle jsonString) { + // https://tc39.es/proposal-json-parse-with-source/#sec-json.rawjson + // Step 5 Rooted obj( cx, NewObjectWithGivenProto(cx, nullptr)); if (!obj) { return nullptr; } + // Step 6 Rooted id(cx, NameToId(cx->names().rawJSON)); Rooted jsonStringVal(cx, StringValue(jsonString)); - if (!NativeDefineDataProperty(cx, obj, id, jsonStringVal, 0)) { + if (!NativeDefineDataProperty(cx, obj, id, jsonStringVal, JSPROP_ENUMERATE)) { return nullptr; } return obj; diff --git a/src/third_party/mozjs/extract/js/src/builtin/RecordObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/RecordObject.cpp deleted file mode 100644 index 9b2f73d08e5..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/RecordObject.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "builtin/RecordObject.h" - -#include "jsapi.h" - -#include "vm/ObjectOperations.h" -#include "vm/RecordType.h" - -#include "vm/JSObject-inl.h" - -using namespace js; - -// Record and Record proposal section 9.2.1 - -RecordObject* RecordObject::create(JSContext* cx, Handle record) { - RecordObject* rec = NewBuiltinClassInstance(cx); - if (!rec) { - return nullptr; - } - rec->setFixedSlot(PrimitiveValueSlot, ExtendedPrimitiveValue(*record)); - return rec; -} - -RecordType* RecordObject::unbox() const { - return &getFixedSlot(PrimitiveValueSlot) - .toExtendedPrimitive() - .as(); -} - -bool RecordObject::maybeUnbox(JSObject* obj, MutableHandle rrec) { - if (obj->is()) { - rrec.set(&obj->as()); - return true; - } - if (obj->is()) { - rrec.set(obj->as().unbox()); - return true; - } - return false; -} - -bool rec_resolve(JSContext* cx, HandleObject obj, HandleId id, - bool* resolvedp) { - RootedValue value(cx); - *resolvedp = obj->as().unbox()->getOwnProperty(cx, id, &value); - - if (*resolvedp) { - static const unsigned RECORD_PROPERTY_ATTRS = - JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; - return DefineDataProperty(cx, obj, id, value, - RECORD_PROPERTY_ATTRS | JSPROP_RESOLVING); - } - - return true; -} - -static const JSClassOps RecordObjectClassOps = { - nullptr, // addProperty - nullptr, // delProperty - nullptr, // enumerate - nullptr, // newEnumerate - rec_resolve, // resolve - nullptr, // mayResolve - nullptr, // finalize - nullptr, // call - nullptr, // construct - nullptr, // trace -}; - -const JSClass RecordObject::class_ = {"RecordObject", - JSCLASS_HAS_RESERVED_SLOTS(SlotCount), - &RecordObjectClassOps}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/RecordObject.h b/src/third_party/mozjs/extract/js/src/builtin/RecordObject.h deleted file mode 100644 index dee4d2738b3..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/RecordObject.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef builtin_RecordObject_h -#define builtin_RecordObject_h - -#include "vm/JSObject.h" -#include "vm/NativeObject.h" -#include "vm/RecordType.h" - -namespace js { - -class RecordObject : public NativeObject { - enum { PrimitiveValueSlot, SlotCount }; - - public: - static const JSClass class_; - - static RecordObject* create(JSContext* cx, Handle record); - - JS::RecordType* unbox() const; - - static bool maybeUnbox(JSObject* obj, MutableHandle rrec); -}; - -} // namespace js - -#endif diff --git a/src/third_party/mozjs/extract/js/src/builtin/Reflect.cpp b/src/third_party/mozjs/extract/js/src/builtin/Reflect.cpp index 4c2e3f17422..c3bd303e71e 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Reflect.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Reflect.cpp @@ -215,10 +215,13 @@ static const JSFunctionSpec reflect_methods[] = { JS_FN("preventExtensions", Reflect_preventExtensions, 1, 0), JS_FN("set", Reflect_set, 3, 0), JS_FN("setPrototypeOf", Reflect_setPrototypeOf, 2, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSPropertySpec reflect_properties[] = { - JS_STRING_SYM_PS(toStringTag, "Reflect", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "Reflect", JSPROP_READONLY), + JS_PS_END, +}; /*** Setup ******************************************************************/ @@ -227,8 +230,16 @@ static JSObject* CreateReflectObject(JSContext* cx, JSProtoKey key) { return NewPlainObjectWithProto(cx, proto, TenuredObject); } -static const ClassSpec ReflectClassSpec = {CreateReflectObject, nullptr, - reflect_methods, reflect_properties}; +static const ClassSpec ReflectClassSpec = { + CreateReflectObject, + nullptr, + reflect_methods, + reflect_properties, +}; -const JSClass js::ReflectClass = {"Reflect", 0, JS_NULL_CLASS_OPS, - &ReflectClassSpec}; +const JSClass js::ReflectClass = { + "Reflect", + 0, + JS_NULL_CLASS_OPS, + &ReflectClassSpec, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/ReflectParse.cpp b/src/third_party/mozjs/extract/js/src/builtin/ReflectParse.cpp index ea2de83c73d..ce6fe4092b6 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/ReflectParse.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/ReflectParse.cpp @@ -646,14 +646,6 @@ class NodeBuilder { [[nodiscard]] bool super(TokenPos* pos, MutableHandleValue dst); -#ifdef ENABLE_RECORD_TUPLE - [[nodiscard]] bool recordExpression(NodeVector& elts, TokenPos* pos, - MutableHandleValue dst); - - [[nodiscard]] bool tupleExpression(NodeVector& elts, TokenPos* pos, - MutableHandleValue dst); -#endif - /* * declarations */ @@ -1133,18 +1125,6 @@ bool NodeBuilder::objectExpression(NodeVector& elts, TokenPos* pos, return listNode(AST_OBJECT_EXPR, "properties", elts, pos, dst); } -#ifdef ENABLE_RECORD_TUPLE -bool NodeBuilder::recordExpression(NodeVector& elts, TokenPos* pos, - MutableHandleValue dst) { - return listNode(AST_RECORD_EXPR, "properties", elts, pos, dst); -} - -bool NodeBuilder::tupleExpression(NodeVector& elts, TokenPos* pos, - MutableHandleValue dst) { - return listNode(AST_TUPLE_EXPR, "elements", elts, pos, dst); -} -#endif - bool NodeBuilder::thisExpression(TokenPos* pos, MutableHandleValue dst) { return newNode(AST_THIS_EXPR, pos, dst); } @@ -3132,48 +3112,6 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) { return builder.objectExpression(elts, &obj->pn_pos, dst); } -#ifdef ENABLE_RECORD_TUPLE - case ParseNodeKind::RecordExpr: { - ListNode* record = &pn->as(); - NodeVector elts(cx); - if (!elts.reserve(record->count())) { - return false; - } - - for (ParseNode* item : record->contents()) { - MOZ_ASSERT(record->pn_pos.encloses(item->pn_pos)); - - RootedValue prop(cx); - if (!property(item, &prop)) { - return false; - } - elts.infallibleAppend(prop); - } - - return builder.recordExpression(elts, &record->pn_pos, dst); - } - - case ParseNodeKind::TupleExpr: { - ListNode* tuple = &pn->as(); - NodeVector elts(cx); - if (!elts.reserve(tuple->count())) { - return false; - } - - for (ParseNode* item : tuple->contents()) { - MOZ_ASSERT(tuple->pn_pos.encloses(item->pn_pos)); - - RootedValue expr(cx); - if (!expression(item, &expr)) { - return false; - } - elts.infallibleAppend(expr); - } - - return builder.tupleExpression(elts, &tuple->pn_pos, dst); - } -#endif - case ParseNodeKind::PrivateName: case ParseNodeKind::Name: return identifier(&pn->as(), dst); @@ -3900,10 +3838,9 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) { return false; } - Parser parser( - &fc, options, chars.begin().get(), chars.length(), - /* foldConstants = */ false, compilationState, - /* syntaxParser = */ nullptr); + Parser parser(&fc, options, chars.begin().get(), + chars.length(), compilationState, + /* syntaxParser = */ nullptr); if (!parser.checkOptions()) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/builtin/RegExp.cpp b/src/third_party/mozjs/extract/js/src/builtin/RegExp.cpp index 2a1d12008c2..8de43749073 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/RegExp.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/RegExp.cpp @@ -18,7 +18,7 @@ #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_NEWREGEXP_FLAGGED #include "js/PropertySpec.h" #include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/Interpreter.h" #include "vm/JSContext.h" #include "vm/RegExpObject.h" @@ -973,7 +973,8 @@ const JSPropertySpec js::regexp_properties[] = { JS_PSG("sticky", regexp_sticky, 0), JS_PSG("unicode", regexp_unicode, 0), JS_PSG("unicodeSets", regexp_unicodeSets, 0), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec js::regexp_methods[] = { JS_SELF_HOSTED_FN("toSource", "$RegExpToString", 0, 0), @@ -986,7 +987,303 @@ const JSFunctionSpec js::regexp_methods[] = { JS_SELF_HOSTED_SYM_FN(replace, "RegExpReplace", 2, 0), JS_SELF_HOSTED_SYM_FN(search, "RegExpSearch", 1, 0), JS_SELF_HOSTED_SYM_FN(split, "RegExpSplit", 2, 0), - JS_FS_END}; + JS_FS_END, +}; + +static constexpr JS::Latin1Char SHOULD_HEX_ESCAPE = JSString::MAX_LATIN1_CHAR; + +/** + * Ascii escape map. + * + * 1. If a character is mapped to zero (0x00), then no escape sequence is used. + * 2. Else, + * a. If a character is mapped to SHOULD_HEX_ESCAPE, then hex-escape. + * b. Else, escape with `\` followed by the mapped value. + */ +static constexpr auto AsciiRegExpEscapeMap() { + std::array result = {}; + + // SyntaxCharacter or U+002F (SOLIDUS) + result['^'] = '^'; + result['$'] = '$'; + result['\\'] = '\\'; + result['.'] = '.'; + result['*'] = '*'; + result['+'] = '+'; + result['?'] = '?'; + result['('] = '('; + result[')'] = ')'; + result['['] = '['; + result[']'] = ']'; + result['{'] = '{'; + result['}'] = '}'; + result['|'] = '|'; + result['/'] = '/'; + + // ControlEscape Code Point Values + result['\t'] = 't'; + result['\n'] = 'n'; + result['\v'] = 'v'; + result['\f'] = 'f'; + result['\r'] = 'r'; + + // Other punctuators ",-=<>#&!%:;@~'`" or 0x0022 (QUOTATION MARK) + result[','] = SHOULD_HEX_ESCAPE; + result['-'] = SHOULD_HEX_ESCAPE; + result['='] = SHOULD_HEX_ESCAPE; + result['<'] = SHOULD_HEX_ESCAPE; + result['>'] = SHOULD_HEX_ESCAPE; + result['#'] = SHOULD_HEX_ESCAPE; + result['&'] = SHOULD_HEX_ESCAPE; + result['!'] = SHOULD_HEX_ESCAPE; + result['%'] = SHOULD_HEX_ESCAPE; + result[':'] = SHOULD_HEX_ESCAPE; + result[';'] = SHOULD_HEX_ESCAPE; + result['@'] = SHOULD_HEX_ESCAPE; + result['~'] = SHOULD_HEX_ESCAPE; + result['\''] = SHOULD_HEX_ESCAPE; + result['`'] = SHOULD_HEX_ESCAPE; + result['"'] = SHOULD_HEX_ESCAPE; + + // WhiteSpace or LineTerminator + result[' '] = SHOULD_HEX_ESCAPE; + + return result; +} + +/** + * EncodeForRegExpEscape ( c ) + * + * https://tc39.es/proposal-regex-escaping/#sec-encodeforregexpescape + */ +template +[[nodiscard]] static bool EncodeForRegExpEscape( + mozilla::Span chars, JSStringBuilder& sb) { + MOZ_ASSERT(sb.empty()); + + const size_t length = chars.size(); + if (length == 0) { + return true; + } + + static constexpr auto asciiEscapeMap = AsciiRegExpEscapeMap(); + + // Number of characters added when escaping. + static constexpr size_t EscapeAddLength = 2 - 1; + static constexpr size_t HexEscapeAddLength = 4 - 1; + static constexpr size_t UnicodeEscapeAddLength = 6 - 1; + + // Initial scan to determine if escape sequences are needed and to compute + // the output length. + size_t outLength = length; + + // Leading Ascii alpha-numeric character is hex-escaped. + size_t scanStart = 0; + if (mozilla::IsAsciiAlphanumeric(chars[0])) { + outLength += HexEscapeAddLength; + scanStart = 1; + } + + for (size_t i = scanStart; i < length; i++) { + CharT ch = chars[i]; + + JS::Latin1Char escape = 0; + if (mozilla::IsAscii(ch)) { + escape = asciiEscapeMap[ch]; + } else { + // Surrogate pair. + if (unicode::IsLeadSurrogate(ch) && i + 1 < length && + unicode::IsTrailSurrogate(chars[i + 1])) { + i += 1; + continue; + } + + // WhiteSpace or LineTerminator or unmatched surrogate. + if (unicode::IsSpace(ch) || unicode::IsSurrogate(ch)) { + escape = SHOULD_HEX_ESCAPE; + } + } + if (!escape) { + continue; + } + + if (mozilla::IsAscii(escape)) { + outLength += EscapeAddLength; + } else if (ch <= JSString::MAX_LATIN1_CHAR) { + outLength += HexEscapeAddLength; + } else { + outLength += UnicodeEscapeAddLength; + } + } + + // Return if no escape sequences are needed. + if (outLength == length) { + return true; + } + MOZ_ASSERT(outLength > length); + + // Inflating is fallible, so we have to convert to two-byte upfront. + if constexpr (std::is_same_v) { + if (!sb.ensureTwoByteChars()) { + return false; + } + } + + // Allocate memory for the output using the final length. + if (!sb.reserve(outLength)) { + return false; + } + + // NB: Lower case hex digits. + static constexpr char HexDigits[] = "0123456789abcdef"; + static_assert(std::char_traits::length(HexDigits) == 16); + + // Append |ch| as an escaped character. + auto appendEscape = [&](JS::Latin1Char ch) { + MOZ_ASSERT(mozilla::IsAscii(ch)); + + sb.infallibleAppend('\\'); + sb.infallibleAppend(ch); + }; + + // Append |ch| as a hex-escape sequence. + auto appendHexEscape = [&](CharT ch) { + MOZ_ASSERT(ch <= JSString::MAX_LATIN1_CHAR); + + sb.infallibleAppend('\\'); + sb.infallibleAppend('x'); + sb.infallibleAppend(HexDigits[(ch >> 4) & 0xf]); + sb.infallibleAppend(HexDigits[ch & 0xf]); + }; + + // Append |ch| as a Unicode-escape sequence. + auto appendUnicodeEscape = [&](char16_t ch) { + MOZ_ASSERT(ch > JSString::MAX_LATIN1_CHAR); + + sb.infallibleAppend('\\'); + sb.infallibleAppend('u'); + sb.infallibleAppend(HexDigits[(ch >> 12) & 0xf]); + sb.infallibleAppend(HexDigits[(ch >> 8) & 0xf]); + sb.infallibleAppend(HexDigits[(ch >> 4) & 0xf]); + sb.infallibleAppend(HexDigits[ch & 0xf]); + }; + + // Index after the last character which produced an escape sequence. + size_t startUnescaped = 0; + + // Append unescaped characters from |startUnescaped| (inclusive) to |end| + // (exclusive). + auto appendUnescaped = [&](size_t end) { + MOZ_ASSERT(startUnescaped <= end && end <= length); + + if (startUnescaped < end) { + auto unescaped = chars.FromTo(startUnescaped, end); + sb.infallibleAppend(unescaped.data(), unescaped.size()); + } + startUnescaped = end + 1; + }; + + // Leading Ascii alpha-numeric character is hex-escaped. + size_t start = 0; + if (mozilla::IsAsciiAlphanumeric(chars[0])) { + appendHexEscape(chars[0]); + + start = 1; + startUnescaped = 1; + } + + for (size_t i = start; i < length; i++) { + CharT ch = chars[i]; + + JS::Latin1Char escape = 0; + if (mozilla::IsAscii(ch)) { + escape = asciiEscapeMap[ch]; + } else { + // Surrogate pair. + if (unicode::IsLeadSurrogate(ch) && i + 1 < length && + unicode::IsTrailSurrogate(chars[i + 1])) { + i += 1; + continue; + } + + // WhiteSpace or LineTerminator or unmatched surrogate. + if (unicode::IsSpace(ch) || unicode::IsSurrogate(ch)) { + escape = SHOULD_HEX_ESCAPE; + } + } + if (!escape) { + continue; + } + + appendUnescaped(i); + + if (mozilla::IsAscii(escape)) { + appendEscape(escape); + } else if (ch <= JSString::MAX_LATIN1_CHAR) { + appendHexEscape(ch); + } else { + appendUnicodeEscape(ch); + } + } + + if (startUnescaped) { + appendUnescaped(length); + } + + MOZ_ASSERT(sb.length() == outLength, "all characters were written"); + return true; +} + +[[nodiscard]] static bool EncodeForRegExpEscape(JSLinearString* string, + JSStringBuilder& sb) { + JS::AutoCheckCannotGC nogc; + if (string->hasLatin1Chars()) { + auto chars = mozilla::Span(string->latin1Range(nogc)); + return EncodeForRegExpEscape(chars, sb); + } + auto chars = mozilla::Span(string->twoByteRange(nogc)); + return EncodeForRegExpEscape(chars, sb); +} + +/** + * RegExp.escape ( S ) + * + * https://tc39.es/proposal-regex-escaping/ + */ +static bool regexp_escape(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. + if (!args.get(0).isString()) { + return ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, + args.get(0), nullptr, "not a string"); + } + + Rooted string(cx, args[0].toString()->ensureLinear(cx)); + if (!string) { + return false; + } + + // Step 2-5. + JSStringBuilder sb(cx); + if (!EncodeForRegExpEscape(string, sb)) { + return false; + } + + // Return the input string if no escape sequences were added. + if (sb.empty()) { + args.rval().setString(string); + return true; + } + + auto* result = sb.finishString(); + if (!result) { + return false; + } + + args.rval().setString(result); + return true; +} #define STATIC_PAREN_GETTER_CODE(parenNum) \ if (!res->createParen(cx, parenNum, args.rval())) return false; \ @@ -1086,7 +1383,13 @@ const JSPropertySpec js::regexp_static_props[] = { JS_PSG("$`", static_leftContext_getter, JSPROP_PERMANENT), JS_PSG("$'", static_rightContext_getter, JSPROP_PERMANENT), JS_SELF_HOSTED_SYM_GET(species, "$RegExpSpecies", 0), - JS_PS_END}; + JS_PS_END, +}; + +const JSFunctionSpec js::regexp_static_methods[] = { + JS_FN("escape", regexp_escape, 1, 0), + JS_FS_END, +}; /* * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2 @@ -1620,7 +1923,7 @@ static void DoReplace(Handle matched, size_t tailPos, Handle captures, Handle namedCaptures, Handle replacement, - size_t firstDollarIndex, StringBuffer& sb) { + size_t firstDollarIndex, StringBuilder& sb) { JS::AutoCheckCannotGC nogc; const CharT* replacementBegin = replacement->chars(nogc); const CharT* currentChar = replacementBegin; @@ -1856,6 +2159,19 @@ bool js::RegExpBuiltinExec(JSContext* cx, Handle regexp, int32_t(lastIndex), nullptr, rval); } +bool js::IsOptimizableRegExpObject(JSObject* obj, JSContext* cx) { + // Check the shape to ensure this is a plain RegExpObject with this realm's + // RegExp.prototype as prototype and without any extra own properties. + // The fuse check ensures RegExp.prototype is optimizable. + bool optimizable = + obj->shape() == cx->global()->maybeRegExpShapeWithDefaultProto() && + cx->realm()->realmFuses.optimizeRegExpPrototypeFuse.intact(); + MOZ_ASSERT_IF(optimizable, + obj->is() && + obj->as().realm() == cx->realm()); + return optimizable; +} + // ES2024 draft rev d4927f9bc3706484c75dfef4bbcf5ba826d2632e // // 22.2.7.1 RegExpExec ( R, S ) @@ -1866,9 +2182,16 @@ bool js::RegExpBuiltinExec(JSContext* cx, Handle regexp, bool js::RegExpExec(JSContext* cx, Handle regexp, Handle string, bool forTest, MutableHandle rval) { + // Fast path for the case where `regexp` is a regular expression object with + // the builtin `RegExp.prototype.exec` function. + if (MOZ_LIKELY(IsOptimizableRegExpObject(regexp, cx))) { + return RegExpBuiltinExec(cx, regexp.as(), string, forTest, + rval); + } + // Step 1. Rooted exec(cx); - Rooted execKey(cx, PropertyKey::NonIntAtom(cx->names().exec)); + Rooted execKey(cx, NameToId(cx->names().exec)); if (!GetProperty(cx, regexp, regexp, execKey, &exec)) { return false; } @@ -1877,8 +2200,7 @@ bool js::RegExpExec(JSContext* cx, Handle regexp, // If exec is the original RegExp.prototype.exec, use the same, faster, // path as for the case where exec isn't callable. PropertyName* execName = cx->names().RegExp_prototype_Exec; - if (MOZ_LIKELY(IsSelfHostedFunctionWithName(exec, execName)) || - !IsCallable(exec)) { + if (IsSelfHostedFunctionWithName(exec, execName) || !IsCallable(exec)) { // Steps 3-4. if (MOZ_LIKELY(regexp->is())) { return RegExpBuiltinExec(cx, regexp.as(), string, forTest, @@ -1907,7 +2229,6 @@ bool js::RegExpExec(JSContext* cx, Handle regexp, return cx->compartment()->wrap(cx, rval); } - ReportUsageCounter(cx, nullptr, SUBCLASSING_REGEXP, SUBCLASSING_TYPE_IV); // Step 2.a. Rooted thisv(cx, ObjectValue(*regexp)); FixedInvokeArgs<1> args(cx); @@ -2097,7 +2418,7 @@ static MOZ_ALWAYS_INLINE int GetFirstDollarIndexImpl(const TextChar* text, return -1; } -int32_t js::GetFirstDollarIndexRawFlat(JSLinearString* text) { +int32_t js::GetFirstDollarIndexRawFlat(const JSLinearString* text) { uint32_t len = text->length(); JS::AutoCheckCannotGC nogc; @@ -2118,192 +2439,27 @@ bool js::GetFirstDollarIndexRaw(JSContext* cx, JSString* str, int32_t* index) { return true; } -bool js::RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp) { +bool js::IsRegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp) { + // This can only be called from self-hosted code. + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 0); + + bool optimizable = + cx->realm()->realmFuses.optimizeRegExpPrototypeFuse.intact(); + args.rval().setBoolean(optimizable); + return true; +} + +bool js::IsOptimizableRegExpObject(JSContext* cx, unsigned argc, Value* vp) { // This can only be called from self-hosted code. CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 1); + MOZ_ASSERT(args[0].isObject()); - args.rval().setBoolean( - RegExpPrototypeOptimizableRaw(cx, &args[0].toObject())); - return true; -} + JSObject* obj = &args[0].toObject(); -bool js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto) { - AutoUnsafeCallWithABI unsafe; - AutoAssertNoPendingException aanpe(cx); - if (!proto->is()) { - return false; - } - - NativeObject* nproto = static_cast(proto); - - RegExpRealm& realm = cx->global()->regExpRealm(); - Shape* shape = realm.getOptimizableRegExpPrototypeShape(); - if (shape == nproto->shape()) { - return true; - } - - JSFunction* flagsGetter; - if (!GetOwnGetterPure(cx, proto, NameToId(cx->names().flags), &flagsGetter)) { - return false; - } - - if (!flagsGetter) { - return false; - } - - if (!IsSelfHostedFunctionWithName(flagsGetter, - cx->names().dollar_RegExpFlagsGetter_)) { - return false; - } - - JSNative globalGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().global), - &globalGetter)) { - return false; - } - - if (globalGetter != regexp_global) { - return false; - } - - JSNative hasIndicesGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().hasIndices), - &hasIndicesGetter)) { - return false; - } - - if (hasIndicesGetter != regexp_hasIndices) { - return false; - } - - JSNative ignoreCaseGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().ignoreCase), - &ignoreCaseGetter)) { - return false; - } - - if (ignoreCaseGetter != regexp_ignoreCase) { - return false; - } - - JSNative multilineGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().multiline), - &multilineGetter)) { - return false; - } - - if (multilineGetter != regexp_multiline) { - return false; - } - - JSNative stickyGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().sticky), - &stickyGetter)) { - return false; - } - - if (stickyGetter != regexp_sticky) { - return false; - } - - JSNative unicodeGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().unicode), - &unicodeGetter)) { - return false; - } - - if (unicodeGetter != regexp_unicode) { - return false; - } - - JSNative unicodeSetsGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().unicodeSets), - &unicodeSetsGetter)) { - return false; - } - - if (unicodeSetsGetter != regexp_unicodeSets) { - return false; - } - - JSNative dotAllGetter; - if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().dotAll), - &dotAllGetter)) { - return false; - } - - if (dotAllGetter != regexp_dotAll) { - return false; - } - - // Check if @@match, @@search, and exec are own data properties, - // those values should be tested in selfhosted JS. - bool has = false; - if (!HasOwnDataPropertyPure( - cx, proto, PropertyKey::Symbol(cx->wellKnownSymbols().match), &has)) { - return false; - } - if (!has) { - return false; - } - - if (!HasOwnDataPropertyPure( - cx, proto, PropertyKey::Symbol(cx->wellKnownSymbols().search), - &has)) { - return false; - } - if (!has) { - return false; - } - - if (!HasOwnDataPropertyPure(cx, proto, NameToId(cx->names().exec), &has)) { - return false; - } - if (!has) { - return false; - } - - realm.setOptimizableRegExpPrototypeShape(nproto->shape()); - return true; -} - -bool js::RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp) { - // This can only be called from self-hosted code. - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 2); - - args.rval().setBoolean(RegExpInstanceOptimizableRaw(cx, &args[0].toObject(), - &args[1].toObject())); - return true; -} - -bool js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, - JSObject* proto) { - AutoUnsafeCallWithABI unsafe; - AutoAssertNoPendingException aanpe(cx); - - RegExpObject* rx = &obj->as(); - - RegExpRealm& realm = cx->global()->regExpRealm(); - Shape* shape = realm.getOptimizableRegExpInstanceShape(); - if (shape == rx->shape()) { - return true; - } - - if (!rx->hasStaticPrototype()) { - return false; - } - - if (rx->staticPrototype() != proto) { - return false; - } - - if (!RegExpObject::isInitialShape(rx)) { - return false; - } - - realm.setOptimizableRegExpInstanceShape(rx->shape()); + bool optimizable = IsOptimizableRegExpObject(obj, cx); + args.rval().setBoolean(optimizable); return true; } diff --git a/src/third_party/mozjs/extract/js/src/builtin/RegExp.h b/src/third_party/mozjs/extract/js/src/builtin/RegExp.h index 925528aa5ff..334bb7b4fea 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/RegExp.h +++ b/src/third_party/mozjs/extract/js/src/builtin/RegExp.h @@ -116,19 +116,16 @@ JSObject* InitRegExpClass(JSContext* cx, HandleObject obj); HandleValue flags, MutableHandleValue rval); -[[nodiscard]] extern bool RegExpPrototypeOptimizable(JSContext* cx, - unsigned argc, Value* vp); +[[nodiscard]] extern bool IsRegExpPrototypeOptimizable(JSContext* cx, + unsigned argc, + Value* vp); -[[nodiscard]] extern bool RegExpPrototypeOptimizableRaw(JSContext* cx, - JSObject* proto); +[[nodiscard]] extern bool IsOptimizableRegExpObject(JSObject* obj, + JSContext* cx); -[[nodiscard]] extern bool RegExpInstanceOptimizable(JSContext* cx, +[[nodiscard]] extern bool IsOptimizableRegExpObject(JSContext* cx, unsigned argc, Value* vp); -[[nodiscard]] extern bool RegExpInstanceOptimizableRaw(JSContext* cx, - JSObject* obj, - JSObject* proto); - [[nodiscard]] extern bool RegExpBuiltinExec(JSContext* cx, Handle regexp, Handle string, @@ -156,12 +153,13 @@ JSObject* InitRegExpClass(JSContext* cx, HandleObject obj); [[nodiscard]] extern bool GetFirstDollarIndexRaw(JSContext* cx, JSString* str, int32_t* index); -extern int32_t GetFirstDollarIndexRawFlat(JSLinearString* text); +extern int32_t GetFirstDollarIndexRawFlat(const JSLinearString* text); // RegExp ClassSpec members used in RegExpObject.cpp. [[nodiscard]] extern bool regexp_construct(JSContext* cx, unsigned argc, Value* vp); extern const JSPropertySpec regexp_static_props[]; +extern const JSFunctionSpec regexp_static_methods[]; extern const JSPropertySpec regexp_properties[]; extern const JSFunctionSpec regexp_methods[]; diff --git a/src/third_party/mozjs/extract/js/src/builtin/RegExp.js b/src/third_party/mozjs/extract/js/src/builtin/RegExp.js index 8ed73ad0ec4..546cf123d1d 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/RegExp.js +++ b/src/third_party/mozjs/extract/js/src/builtin/RegExp.js @@ -120,14 +120,14 @@ function RegExpMatch(string) { var S = ToString(string); // Optimized paths for simple cases. - if (IsRegExpMethodOptimizable(rx)) { + if (IsOptimizableRegExpObject(rx)) { // Step 4. var flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT); var global = !!(flags & REGEXP_GLOBAL_FLAG); if (global) { // Step 6.a. - var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG); + var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG) || !!(flags & REGEXP_UNICODESETS_FLAG); // Steps 6.b-e. return RegExpGlobalMatchOpt(rx, S, fullUnicode); @@ -154,7 +154,7 @@ function RegExpMatchSlowPath(rx, S) { } // Step 6.a. - var fullUnicode = callFunction(std_String_includes, flags, "u"); + var fullUnicode = callFunction(std_String_includes, flags, "u") || callFunction(std_String_includes, flags, "v"); // Step 6.b. rx.lastIndex = 0; @@ -243,34 +243,6 @@ function RegExpGlobalMatchOpt(rx, S, fullUnicode) { } } -// Checks if following properties and getters are not modified, and accessing -// them not observed by content script: -// * flags -// * hasIndices -// * global -// * ignoreCase -// * multiline -// * dotAll -// * sticky -// * unicode -// * unicodeSets -// * exec -// * lastIndex -function IsRegExpMethodOptimizable(rx) { - if (!IsRegExpObject(rx)) { - return false; - } - - var RegExpProto = GetBuiltinPrototype("RegExp"); - // If RegExpPrototypeOptimizable and RegExpInstanceOptimizable succeed, - // `RegExpProto.exec` is guaranteed to be data properties. - return ( - RegExpPrototypeOptimizable(RegExpProto) && - RegExpInstanceOptimizable(rx, RegExpProto) && - RegExpProto.exec === RegExp_prototype_Exec - ); -} - // ES2023 draft rev 2c78e6f6b5bc6bfbf79dd8a12a9593e5b57afcd2 // 22.2.5.11 RegExp.prototype [ @@replace ] ( string, replaceValue ) function RegExpReplace(string, replaceValue) { @@ -306,7 +278,7 @@ function RegExpReplace(string, replaceValue) { } // Optimized paths. - if (IsRegExpMethodOptimizable(rx)) { + if (IsOptimizableRegExpObject(rx)) { // Step 7. var flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT); @@ -394,7 +366,7 @@ function RegExpReplaceSlowPath( var fullUnicode = false; if (global) { // Step 9.a. - fullUnicode = callFunction(std_String_includes, flags, "u"); + fullUnicode = callFunction(std_String_includes, flags, "u") || callFunction(std_String_includes, flags, "v"); // Step 9.b. rx.lastIndex = 0; @@ -751,7 +723,7 @@ function RegExpGetFunctionalReplacement(result, S, position, replaceValue) { // * replaceValue is a string without "$" function RegExpGlobalReplaceOptSimple(rx, S, lengthS, replaceValue, flags) { // Step 9.a. - var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG); + var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG) || !!(flags & REGEXP_UNICODESETS_FLAG); // Step 9.b. var lastIndex = 0; @@ -894,7 +866,7 @@ function RegExpSearch(string) { rx.lastIndex = 0; } - if (IsRegExpMethodOptimizable(rx) && S.length < 0x7fff) { + if (IsOptimizableRegExpObject(rx) && S.length < 0x7fff) { // Step 6. var result = RegExpSearcher(rx, S, 0); @@ -951,26 +923,6 @@ function RegExpSearchSlowPath(rx, S, previousLastIndex) { return result.index; } -function IsRegExpSplitOptimizable(rx, C) { - if (!IsRegExpObject(rx)) { - return false; - } - - var RegExpCtor = GetBuiltinConstructor("RegExp"); - if (C !== RegExpCtor) { - return false; - } - - var RegExpProto = RegExpCtor.prototype; - // If RegExpPrototypeOptimizable succeeds, `RegExpProto.exec` is guaranteed - // to be a data property. - return ( - RegExpPrototypeOptimizable(RegExpProto) && - RegExpInstanceOptimizable(rx, RegExpProto) && - RegExpProto.exec === RegExp_prototype_Exec - ); -} - // ES 2017 draft 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 21.2.5.11. function RegExpSplit(string, limit) { // Step 1. @@ -985,10 +937,12 @@ function RegExpSplit(string, limit) { var S = ToString(string); // Step 4. - var C = SpeciesConstructor(rx, GetBuiltinConstructor("RegExp")); + var builtinCtor = GetBuiltinConstructor("RegExp"); + var C = SpeciesConstructor(rx, builtinCtor); var optimizable = - IsRegExpSplitOptimizable(rx, C) && + IsOptimizableRegExpObject(rx) && + C === builtinCtor && (limit === undefined || typeof limit === "number"); var flags, unicodeMatching, splitter; @@ -1236,23 +1190,6 @@ function $RegExpSpecies() { } SetCanonicalName($RegExpSpecies, "get [Symbol.species]"); -function IsRegExpMatchAllOptimizable(rx, C) { - if (!IsRegExpObject(rx)) { - return false; - } - - var RegExpCtor = GetBuiltinConstructor("RegExp"); - if (C !== RegExpCtor) { - return false; - } - - var RegExpProto = RegExpCtor.prototype; - return ( - RegExpPrototypeOptimizable(RegExpProto) && - RegExpInstanceOptimizable(rx, RegExpProto) - ); -} - // String.prototype.matchAll proposal. // // RegExp.prototype [ @@matchAll ] ( string ) @@ -1269,10 +1206,11 @@ function RegExpMatchAll(string) { var str = ToString(string); // Step 4. - var C = SpeciesConstructor(rx, GetBuiltinConstructor("RegExp")); + var builtinCtor = GetBuiltinConstructor("RegExp"); + var C = SpeciesConstructor(rx, builtinCtor); var source, flags, matcher, lastIndex; - if (IsRegExpMatchAllOptimizable(rx, C)) { + if (IsOptimizableRegExpObject(rx) && C === builtinCtor) { // Step 5, 9-12. source = UnsafeGetStringFromReservedSlot(rx, REGEXP_SOURCE_SLOT); flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT); @@ -1337,16 +1275,6 @@ function CreateRegExpStringIterator(regexp, string, source, flags, lastIndex) { return iterator; } -function IsRegExpStringIteratorNextOptimizable() { - var RegExpProto = GetBuiltinPrototype("RegExp"); - // If RegExpPrototypeOptimizable succeeds, `RegExpProto.exec` is - // guaranteed to be a data property. - return ( - RegExpPrototypeOptimizable(RegExpProto) && - RegExpProto.exec === RegExp_prototype_Exec - ); -} - // String.prototype.matchAll proposal. // // %RegExpStringIteratorPrototype%.next ( ) @@ -1391,7 +1319,7 @@ function RegExpStringIteratorNext() { REGEXP_STRING_ITERATOR_FLAGS_SLOT ); var global = !!(flags & REGEXP_GLOBAL_FLAG); - var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG); + var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG) || !!(flags & REGEXP_UNICODESETS_FLAG); if (lastIndex >= 0) { assert(IsRegExpObject(regexp), "|regexp| is a RegExp object"); @@ -1401,7 +1329,7 @@ function RegExpStringIteratorNext() { REGEXP_STRING_ITERATOR_SOURCE_SLOT ); if ( - IsRegExpStringIteratorNextOptimizable() && + IsRegExpPrototypeOptimizable() && UnsafeGetStringFromReservedSlot(regexp, REGEXP_SOURCE_SLOT) === source && UnsafeGetInt32FromReservedSlot(regexp, REGEXP_FLAGS_SLOT) === flags ) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/SelfHostingDefines.h b/src/third_party/mozjs/extract/js/src/builtin/SelfHostingDefines.h index f270c13a626..bcd336afeca 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/SelfHostingDefines.h +++ b/src/third_party/mozjs/extract/js/src/builtin/SelfHostingDefines.h @@ -67,12 +67,14 @@ // name for self-hosted builtins is stored. #define LAZY_FUNCTION_NAME_SLOT 0 +// The iterated object for Array/String/Map/Set iterators. #define ITERATOR_SLOT_TARGET 0 -// Used for collection iterators. -#define ITERATOR_SLOT_RANGE 1 // Used for list, i.e. Array and String, iterators. #define ITERATOR_SLOT_NEXT_INDEX 1 -#define ITERATOR_SLOT_ITEM_KIND 2 +// Item kind for Array iterators. +#define ARRAY_ITERATOR_SLOT_ITEM_KIND 2 +// Item kind for Map/Set iterators. +#define MAP_SET_ITERATOR_SLOT_ITEM_KIND 1 #define ITEM_KIND_KEY 0 #define ITEM_KIND_VALUE 1 @@ -96,6 +98,15 @@ #define REGEXP_STRING_ITERATOR_FLAGS_SLOT 3 #define REGEXP_STRING_ITERATOR_LASTINDEX_SLOT 4 +// Control values for Iterator.range +#define ITERATOR_RANGE_SLOT_START 0 +#define ITERATOR_RANGE_SLOT_END 1 +#define ITERATOR_RANGE_SLOT_STEP 2 +#define ITERATOR_RANGE_SLOT_INCLUSIVE_END 3 +#define ITERATOR_RANGE_SLOT_ZERO 4 +#define ITERATOR_RANGE_SLOT_ONE 5 +#define ITERATOR_RANGE_SLOT_CURRENT_COUNT 6 + #define REGEXP_STRING_ITERATOR_LASTINDEX_DONE -1 #define REGEXP_STRING_ITERATOR_LASTINDEX_SLOW -2 @@ -108,19 +119,6 @@ #define INTL_SEGMENT_ITERATOR_STRING_SLOT 1 #define INTL_SEGMENT_ITERATOR_INDEX_SLOT 3 -#define TYPEDARRAY_KIND_INT8 0 -#define TYPEDARRAY_KIND_UINT8 1 -#define TYPEDARRAY_KIND_INT16 2 -#define TYPEDARRAY_KIND_UINT16 3 -#define TYPEDARRAY_KIND_INT32 4 -#define TYPEDARRAY_KIND_UINT32 5 -#define TYPEDARRAY_KIND_FLOAT32 6 -#define TYPEDARRAY_KIND_FLOAT64 7 -#define TYPEDARRAY_KIND_UINT8CLAMPED 8 -#define TYPEDARRAY_KIND_BIGINT64 9 -#define TYPEDARRAY_KIND_BIGUINT64 10 -#define TYPEDARRAY_KIND_FLOAT16 11 - #define WRAP_FOR_VALID_ITERATOR_ITERATOR_SLOT 0 #define WRAP_FOR_VALID_ITERATOR_NEXT_METHOD_SLOT 1 @@ -128,40 +126,14 @@ #define ASYNC_ITERATOR_HELPER_GENERATOR_SLOT 0 -// Support for usage counters around subclassing: -#define SUBCLASSING_DETERMINE_THROUGH_CONSTRUCTOR 0 -#define SUBCLASSING_ARRAY 1 -#define SUBCLASSING_PROMISE 2 -#define SUBCLASSING_TYPEDARRAY 3 -#define SUBCLASSING_ARRAYBUFFER 4 -#define SUBCLASSING_SHAREDARRAYBUFFER 5 -#define SUBCLASSING_REGEXP 6 -#define SUBCLASSING_LAST_BUILTIN 7 +// For explicit resource management. +#define USING_HINT_SYNC 0 +#define USING_HINT_ASYNC 1 -#define SUBCLASSING_TYPE_II 2 -#define SUBCLASSING_TYPE_III 3 -#define SUBCLASSING_TYPE_IV 4 +#define DISPOSABLE_STACK_DISPOSABLE_RESOURCE_STACK_SLOT 0 +#define DISPOSABLE_STACK_STATE_SLOT 1 -#define SUBCLASSING_TYPE_MASK 0xf - -#define SUBCLASSING_BUILTIN_SHIFT 16 -#define SUBCLASS_ARRAY_TYPE_II \ - ((SUBCLASSING_ARRAY << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_II) -#define SUBCLASS_PROMISE_TYPE_II \ - ((SUBCLASSING_PROMISE << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_II) -#define SUBCLASS_TYPEDARRAY_TYPE_II \ - ((SUBCLASSING_TYPEDARRAY << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_II) - -#define SUBCLASS_ARRAY_TYPE_III \ - ((SUBCLASSING_ARRAY << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_III) -#define SUBCLASS_TYPEDARRAY_TYPE_III \ - ((SUBCLASSING_TYPEDARRAY << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_III) - -#define SUBCLASSING_DETERMINE_THROUGH_CONSTRUCTOR_TYPE_III SUBCLASSING_TYPE_III - -#define SUBCLASS_REGEXP_TYPE_III \ - ((SUBCLASSING_REGEXP << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_III) -#define SUBCLASS_REGEXP_TYPE_IV \ - ((SUBCLASSING_REGEXP << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_IV) +#define DISPOSABLE_STACK_STATE_PENDING 0 +#define DISPOSABLE_STACK_STATE_DISPOSED 1 #endif diff --git a/src/third_party/mozjs/extract/js/src/builtin/Set.js b/src/third_party/mozjs/extract/js/src/builtin/Set.js index 1dbd13cf93e..f271e7b7de7 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Set.js +++ b/src/third_party/mozjs/extract/js/src/builtin/Set.js @@ -99,7 +99,7 @@ function SetIteratorNext() { // Steps 10.b-c (omitted). // Step 6. - var itemKind = UnsafeGetInt32FromReservedSlot(O, ITERATOR_SLOT_ITEM_KIND); + var itemKind = UnsafeGetInt32FromReservedSlot(O, MAP_SET_ITERATOR_SLOT_ITEM_KIND); var result; if (itemKind === ITEM_KIND_VALUE) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/ShadowRealm.cpp b/src/third_party/mozjs/extract/js/src/builtin/ShadowRealm.cpp index 6c76a2b1b3f..e4009a3f377 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/ShadowRealm.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/ShadowRealm.cpp @@ -41,7 +41,6 @@ using namespace js; using JS::AutoStableStringChars; using JS::CompileOptions; -using JS::SourceOwnership; using JS::SourceText; static JSObject* DefaultNewShadowRealmGlobal(JSContext* cx, @@ -49,7 +48,10 @@ static JSObject* DefaultNewShadowRealmGlobal(JSContext* cx, JSPrincipals* principals, Handle unused) { static const JSClass shadowRealmGlobal = { - "ShadowRealmGlobal", JSCLASS_GLOBAL_FLAGS, &JS::DefaultGlobalClassOps}; + "ShadowRealmGlobal", + JSCLASS_GLOBAL_FLAGS, + &JS::DefaultGlobalClassOps, + }; return JS_NewGlobalObject(cx, &shadowRealmGlobal, principals, JS::FireOnNewGlobalHook, options); @@ -194,7 +196,16 @@ static bool PerformShadowRealmEval(JSContext* cx, Handle sourceText, MOZ_ASSERT(callerRealm != evalRealm); // Step 1. Perform ? HostEnsureCanCompileStrings(callerRealm, evalRealm). - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, sourceText)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, sourceText, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return false; + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_SHADOWREALM); return false; @@ -444,9 +455,9 @@ static JSObject* ShadowRealmImportValue(JSContext* cx, return promise; } - Rooted> attributes(cx); + Rooted attributes(cx); Rooted moduleRequest( - cx, ModuleRequestObject::create(cx, specifierAtom, &attributes)); + cx, ModuleRequestObject::create(cx, specifierAtom, attributes)); if (!moduleRequest) { if (!RejectPromiseWithPendingError(cx, promise)) { return nullptr; diff --git a/src/third_party/mozjs/extract/js/src/builtin/String.cpp b/src/third_party/mozjs/extract/js/src/builtin/String.cpp index 1da2270cfbf..fcdd340d14e 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/String.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/String.cpp @@ -34,6 +34,7 @@ # include "builtin/intl/FormatBuffer.h" #endif #include "builtin/RegExp.h" +#include "gc/GC.h" #include "jit/InlinableNatives.h" #include "js/Conversions.h" #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* @@ -46,7 +47,7 @@ #include "js/PropertySpec.h" #include "js/StableStringChars.h" #include "js/UniquePtr.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "util/Unicode.h" #include "vm/GlobalObject.h" #include "vm/JSContext.h" @@ -57,16 +58,12 @@ #include "vm/ToSource.h" // js::ValueToSource #include "vm/GeckoProfiler-inl.h" -#include "vm/InlineCharBuffer-inl.h" #include "vm/NativeObject-inl.h" #include "vm/StringObject-inl.h" #include "vm/StringType-inl.h" using namespace js; -using JS::Symbol; -using JS::SymbolCode; - using mozilla::AsciiAlphanumericToNumber; using mozilla::CheckedInt; using mozilla::EnsureUtf16ValiditySpan; @@ -112,8 +109,7 @@ static bool str_encodeURI_Component(JSContext* cx, unsigned argc, Value* vp); /* ES5 B.2.1 */ template static bool Escape(JSContext* cx, const CharT* chars, uint32_t length, - InlineCharBuffer& newChars, - uint32_t* newLengthOut) { + StringChars& newChars, uint32_t* newLengthOut) { // clang-format off static const uint8_t shouldPassThrough[128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -164,7 +160,8 @@ static bool Escape(JSContext* cx, const CharT* chars, uint32_t length, static const char digits[] = "0123456789ABCDEF"; - Latin1Char* rawNewChars = newChars.get(); + JS::AutoCheckCannotGC nogc; + Latin1Char* rawNewChars = newChars.data(nogc); size_t i, ni; for (i = 0, ni = 0; i < length; i++) { char16_t ch = chars[i]; @@ -198,7 +195,7 @@ static bool str_escape(JSContext* cx, unsigned argc, Value* vp) { return false; } - InlineCharBuffer newChars; + StringChars newChars(cx); uint32_t newLength = 0; // initialize to silence GCC warning if (str->hasLatin1Chars()) { AutoCheckCannotGC nogc; @@ -220,7 +217,7 @@ static bool str_escape(JSContext* cx, unsigned argc, Value* vp) { return true; } - JSString* res = newChars.toString(cx, newLength); + JSString* res = newChars.toStringDontDeflateNonStatic(cx, newLength); if (!res) { return false; } @@ -261,7 +258,7 @@ static inline bool Unhex2(const RangedPtr chars, } template -static bool Unescape(StringBuffer& sb, +static bool Unescape(StringBuilder& sb, const mozilla::Range chars) { // Step 2. uint32_t length = chars.length(); @@ -386,7 +383,6 @@ static const JSFunctionSpec string_functions[] = { JS_FN("encodeURI", str_encodeURI, 1, JSPROP_RESOLVING), JS_FN("decodeURIComponent", str_decodeURI_Component, 1, JSPROP_RESOLVING), JS_FN("encodeURIComponent", str_encodeURI_Component, 1, JSPROP_RESOLVING), - JS_FS_END, }; @@ -460,7 +456,9 @@ const JSClass StringObject::class_ = { "String", JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_String), - &StringObjectClassOps, &StringObject::classSpec_}; + &StringObjectClassOps, + &StringObject::classSpec_, +}; /* * Perform the initial |RequireObjectCoercible(thisv)| and |ToString(thisv)| @@ -620,70 +618,51 @@ JSString* js::SubstringKernel(JSContext* cx, HandleString str, int32_t beginInt, if (str->isRope()) { JSRope* rope = &str->asRope(); - /* Substring is totally in leftChild of rope. */ + if (rope->length() == len) { + // Substring is the full rope. + MOZ_ASSERT(begin == 0); + return rope; + } + if (begin + len <= rope->leftChild()->length()) { + // Substring is fully contained within the rope's left child. return NewDependentString(cx, rope->leftChild(), begin, len); } - /* Substring is totally in rightChild of rope. */ if (begin >= rope->leftChild()->length()) { + // Substring is fully contained within the rope's right child. begin -= rope->leftChild()->length(); return NewDependentString(cx, rope->rightChild(), begin, len); } - /* - * Requested substring is partly in the left and partly in right child. - * Create a rope of substrings for both childs. - */ + // The substring spans both children. Avoid flattening the rope if the + // children are both linear and the substring fits in an inline string. + // + // Note: we could handle longer substrings by allocating a new rope here, + // but this can result in a lot more rope flattening later on. It's safer to + // flatten the rope in this case. See bug 1922926. + MOZ_ASSERT(begin < rope->leftChild()->length() && begin + len > rope->leftChild()->length()); - size_t lhsLength = rope->leftChild()->length() - begin; - size_t rhsLength = begin + len - rope->leftChild()->length(); + bool fitsInline = rope->hasLatin1Chars() + ? JSInlineString::lengthFits(len) + : JSInlineString::lengthFits(len); + if (fitsInline && rope->leftChild()->isLinear() && + rope->rightChild()->isLinear()) { + Rooted left(cx, &rope->leftChild()->asLinear()); + Rooted right(cx, &rope->rightChild()->asLinear()); - Rooted left(cx, rope->leftChild()->ensureLinear(cx)); - if (!left) { - return nullptr; - } + size_t lhsLength = left->length() - begin; + size_t rhsLength = len - lhsLength; - Rooted right(cx, rope->rightChild()->ensureLinear(cx)); - if (!right) { - return nullptr; - } - - if (rope->hasLatin1Chars()) { - if (JSInlineString::lengthFits(len)) { + if (rope->hasLatin1Chars()) { return SubstringInlineString(cx, left, right, begin, lhsLength, rhsLength); } - } else { - if (JSInlineString::lengthFits(len)) { - return SubstringInlineString(cx, left, right, begin, - lhsLength, rhsLength); - } + return SubstringInlineString(cx, left, right, begin, lhsLength, + rhsLength); } - - left = NewDependentString(cx, left, begin, lhsLength); - if (!left) { - return nullptr; - } - - right = NewDependentString(cx, right, 0, rhsLength); - if (!right) { - return nullptr; - } - - // The dependent string of a two-byte string can be a Latin-1 string, so - // check again if the result fits into an inline string. - if (left->hasLatin1Chars() && right->hasLatin1Chars()) { - if (JSInlineString::lengthFits(len)) { - MOZ_ASSERT(str->hasTwoByteChars(), "Latin-1 ropes are handled above"); - return SubstringInlineString(cx, left, right, 0, lhsLength, - rhsLength); - } - } - - return JSRope::new_(cx, left, right, len); } return NewDependentString(cx, str, begin, len); @@ -842,11 +821,11 @@ static size_t ToLowerCaseLength(const char16_t* chars, size_t startIndex, } template -static JSString* ToLowerCase(JSContext* cx, JSLinearString* str) { +static JSLinearString* ToLowerCase(JSContext* cx, JSLinearString* str) { // Unlike toUpperCase, toLowerCase has the nice invariant that if the // input is a Latin-1 string, the output is also a Latin-1 string. - InlineCharBuffer newChars; + StringChars newChars(cx); const size_t length = str->length(); size_t resultLength; @@ -907,10 +886,10 @@ static JSString* ToLowerCase(JSContext* cx, JSLinearString* str) { return nullptr; } - PodCopy(newChars.get(), chars, i); + PodCopy(newChars.data(nogc), chars, i); size_t readChars = - ToLowerCaseImpl(newChars.get(), chars, i, length, resultLength); + ToLowerCaseImpl(newChars.data(nogc), chars, i, length, resultLength); if constexpr (!std::is_same_v) { if (readChars < length) { resultLength = ToLowerCaseLength(chars, readChars, length); @@ -919,7 +898,7 @@ static JSString* ToLowerCase(JSContext* cx, JSLinearString* str) { return nullptr; } - MOZ_ALWAYS_TRUE(length == ToLowerCaseImpl(newChars.get(), chars, + MOZ_ALWAYS_TRUE(length == ToLowerCaseImpl(newChars.data(nogc), chars, readChars, length, resultLength)); } @@ -929,10 +908,10 @@ static JSString* ToLowerCase(JSContext* cx, JSLinearString* str) { } } - return newChars.toStringDontDeflate(cx, resultLength); + return newChars.template toStringDontDeflate(cx, resultLength); } -JSString* js::StringToLowerCase(JSContext* cx, HandleString string) { +JSLinearString* js::StringToLowerCase(JSContext* cx, JSString* string) { JSLinearString* linear = string->ensureLinear(cx); if (!linear) { return nullptr; @@ -948,8 +927,7 @@ static bool str_toLowerCase(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "toLowerCase"); CallArgs args = CallArgsFromVp(argc, vp); - RootedString str(cx, - ToStringForStringFunction(cx, "toLowerCase", args.thisv())); + JSString* str = ToStringForStringFunction(cx, "toLowerCase", args.thisv()); if (!str) { return false; } @@ -1204,21 +1182,22 @@ static size_t ToUpperCaseLength(const CharT* chars, size_t startIndex, } template -static inline bool ToUpperCase(JSContext* cx, - InlineCharBuffer& newChars, +static inline bool ToUpperCase(JSContext* cx, StringChars& newChars, const SrcChar* chars, size_t startIndex, size_t length, size_t* resultLength) { MOZ_ASSERT(startIndex < length); + AutoCheckCannotGC nogc; + *resultLength = length; if (!newChars.maybeAlloc(cx, length)) { return false; } - CopyChars(newChars.get(), chars, startIndex); + CopyChars(newChars.data(nogc), chars, startIndex); size_t readChars = - ToUpperCaseImpl(newChars.get(), chars, startIndex, length, length); + ToUpperCaseImpl(newChars.data(nogc), chars, startIndex, length, length); if (readChars < length) { size_t actualLength = ToUpperCaseLength(chars, readChars, length); @@ -1227,19 +1206,19 @@ static inline bool ToUpperCase(JSContext* cx, return false; } - MOZ_ALWAYS_TRUE(length == ToUpperCaseImpl(newChars.get(), chars, readChars, - length, actualLength)); + MOZ_ALWAYS_TRUE(length == ToUpperCaseImpl(newChars.data(nogc), chars, + readChars, length, actualLength)); } return true; } template -static JSString* ToUpperCase(JSContext* cx, JSLinearString* str) { - using Latin1Buffer = InlineCharBuffer; - using TwoByteBuffer = InlineCharBuffer; +static JSLinearString* ToUpperCase(JSContext* cx, JSLinearString* str) { + using Latin1StringChars = StringChars; + using TwoByteStringChars = StringChars; - mozilla::MaybeOneOf newChars; + mozilla::MaybeOneOf newChars; const size_t length = str->length(); size_t resultLength; { @@ -1318,24 +1297,24 @@ static JSString* ToUpperCase(JSContext* cx, JSLinearString* str) { }); if (resultIsLatin1) { - newChars.construct(); + newChars.construct(cx); - if (!ToUpperCase(cx, newChars.ref(), chars, i, length, - &resultLength)) { + if (!ToUpperCase(cx, newChars.ref(), chars, i, + length, &resultLength)) { return nullptr; } } else { - newChars.construct(); + newChars.construct(cx); - if (!ToUpperCase(cx, newChars.ref(), chars, i, length, - &resultLength)) { + if (!ToUpperCase(cx, newChars.ref(), chars, i, + length, &resultLength)) { return nullptr; } } } else { - newChars.construct(); + newChars.construct(cx); - if (!ToUpperCase(cx, newChars.ref(), chars, i, length, + if (!ToUpperCase(cx, newChars.ref(), chars, i, length, &resultLength)) { return nullptr; } @@ -1343,13 +1322,13 @@ static JSString* ToUpperCase(JSContext* cx, JSLinearString* str) { } auto toString = [&](auto& chars) { - return chars.toStringDontDeflate(cx, resultLength); + return chars.template toStringDontDeflate(cx, resultLength); }; return newChars.mapNonEmpty(toString); } -JSString* js::StringToUpperCase(JSContext* cx, HandleString string) { +JSLinearString* js::StringToUpperCase(JSContext* cx, JSString* string) { JSLinearString* linear = string->ensureLinear(cx); if (!linear) { return nullptr; @@ -1365,8 +1344,7 @@ static bool str_toUpperCase(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "toUpperCase"); CallArgs args = CallArgsFromVp(argc, vp); - RootedString str(cx, - ToStringForStringFunction(cx, "toUpperCase", args.thisv())); + JSString* str = ToStringForStringFunction(cx, "toUpperCase", args.thisv()); if (!str) { return false; } @@ -1718,8 +1696,8 @@ static bool str_toWellFormed(JSContext* cx, unsigned argc, Value* vp) { MOZ_ASSERT(isWellFormedUpTo < len); // Step 4-6 - InlineCharBuffer buffer; - if (!buffer.maybeAlloc(cx, len)) { + StringChars newChars(cx); + if (!newChars.maybeAlloc(cx, len)) { return false; } @@ -1729,9 +1707,9 @@ static bool str_toWellFormed(JSContext* cx, unsigned argc, Value* vp) { JSLinearString* linear = str->ensureLinear(cx); MOZ_ASSERT(linear, "IsStringWellFormedUnicode linearized the string"); - PodCopy(buffer.get(), linear->twoByteChars(nogc), len); + PodCopy(newChars.data(nogc), linear->twoByteChars(nogc), len); - auto span = mozilla::Span{buffer.get(), len}; + auto span = mozilla::Span{newChars.data(nogc), len}; // Replace the character. span[isWellFormedUpTo] = unicode::REPLACEMENT_CHARACTER; @@ -1743,7 +1721,7 @@ static bool str_toWellFormed(JSContext* cx, unsigned argc, Value* vp) { } } - JSString* result = buffer.toStringDontDeflate(cx, len); + JSString* result = newChars.toStringDontDeflateNonStatic(cx, len); if (!result) { return false; } @@ -1753,12 +1731,28 @@ static bool str_toWellFormed(JSContext* cx, unsigned argc, Value* vp) { return true; } -static const JSFunctionSpec wellFormed_functions[] = { - JS_FN("isWellFormed", str_isWellFormed, 0, 0), - JS_FN("toWellFormed", str_toWellFormed, 0, 0), - JS_FS_END, -}; +// Clamp |value| to a string index between 0 and |length|. +static MOZ_ALWAYS_INLINE bool ToClampedStringIndex(JSContext* cx, + Handle value, + uint32_t length, + uint32_t* result) { + // Handle the common case of int32 indices first. + if (value.isInt32()) { + int32_t i = value.toInt32(); + *result = std::min(uint32_t(std::max(i, 0)), length); + return true; + } + double d; + if (!ToInteger(cx, value, &d)) { + return false; + } + *result = uint32_t(std::clamp(d, 0.0, double(length))); + return true; +} + +// Return |Some(index)| if |value| is a string index between 0 and |length|. +// Otherwise return |Nothing|. static MOZ_ALWAYS_INLINE bool ToStringIndex(JSContext* cx, Handle value, size_t length, mozilla::Maybe* result) { @@ -1781,6 +1775,8 @@ static MOZ_ALWAYS_INLINE bool ToStringIndex(JSContext* cx, Handle value, return true; } +// Return |Some(index)| if |value| is a relative string index between 0 and +// |length|. Otherwise return |Nothing|. static MOZ_ALWAYS_INLINE bool ToRelativeStringIndex( JSContext* cx, Handle value, size_t length, mozilla::Maybe* result) { @@ -2156,8 +2152,8 @@ static MOZ_ALWAYS_INLINE int StringMatch(const TextChar* text, uint32_t textLen, text, textLen, pat, patLen); } -static int32_t StringMatch(JSLinearString* text, JSLinearString* pat, - uint32_t start = 0) { +static int32_t StringMatch(const JSLinearString* text, + const JSLinearString* pat, uint32_t start = 0) { MOZ_ASSERT(start <= text->length()); uint32_t textLen = text->length() - start; uint32_t patLen = pat->length(); @@ -2185,12 +2181,12 @@ static int32_t StringMatch(JSLinearString* text, JSLinearString* pat, static const size_t sRopeMatchThresholdRatioLog2 = 4; -int js::StringFindPattern(JSLinearString* text, JSLinearString* pat, +int js::StringFindPattern(const JSLinearString* text, const JSLinearString* pat, size_t start) { return StringMatch(text, pat, start); } -typedef Vector LinearStringVector; +using LinearStringVector = Vector; template static int RopeMatchImpl(const AutoCheckCannotGC& nogc, @@ -2257,7 +2253,7 @@ static int RopeMatchImpl(const AutoCheckCannotGC& nogc, * RopeMatch returns false on OOM and otherwise returns the match index through * the 'match' outparam (-1 for not found). */ -static bool RopeMatch(JSContext* cx, JSRope* text, JSLinearString* pat, +static bool RopeMatch(JSContext* cx, JSRope* text, const JSLinearString* pat, int* match) { uint32_t patLen = pat->length(); if (patLen == 0) { @@ -2354,8 +2350,8 @@ static MOZ_ALWAYS_INLINE bool ReportErrorIfFirstArgIsRegExp( return true; } -// ES2018 draft rev de77aaeffce115deaf948ed30c7dbe4c60983c0c -// 21.1.3.7 String.prototype.includes ( searchString [ , position ] ) +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 22.1.3.8 String.prototype.includes ( searchString [ , position ] ) bool js::str_includes(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "includes"); CallArgs args = CallArgsFromVp(argc, vp); @@ -2377,28 +2373,15 @@ bool js::str_includes(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 6. - uint32_t pos = 0; + // Steps 6-9. + uint32_t start = 0; if (args.hasDefined(1)) { - if (args[1].isInt32()) { - int i = args[1].toInt32(); - pos = (i < 0) ? 0U : uint32_t(i); - } else { - double d; - if (!ToInteger(cx, args[1], &d)) { - return false; - } - pos = uint32_t(std::min(std::max(d, 0.0), double(UINT32_MAX))); + if (!ToClampedStringIndex(cx, args[1], str->length(), &start)) { + return false; } } - // Step 7. - uint32_t textLen = str->length(); - - // Step 8. - uint32_t start = std::min(pos, textLen); - - // Steps 9-10. + // Steps 10-12. JSLinearString* text = str->ensureLinear(cx); if (!text) { return false; @@ -2424,44 +2407,32 @@ bool js::StringIncludes(JSContext* cx, HandleString string, return true; } -/* ES6 20120927 draft 15.5.4.7. */ +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 22.1.3.9 String.prototype.indexOf ( searchString [ , position ] ) bool js::str_indexOf(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "indexOf"); CallArgs args = CallArgsFromVp(argc, vp); - // Steps 1, 2, and 3 + // Steps 1-2. RootedString str(cx, ToStringForStringFunction(cx, "indexOf", args.thisv())); if (!str) { return false; } - // Steps 4 and 5 + // Step 3. Rooted searchStr(cx, ArgToLinearString(cx, args, 0)); if (!searchStr) { return false; } - // Steps 6 and 7 - uint32_t pos = 0; + // Steps 4-7. + uint32_t start = 0; if (args.hasDefined(1)) { - if (args[1].isInt32()) { - int i = args[1].toInt32(); - pos = (i < 0) ? 0U : uint32_t(i); - } else { - double d; - if (!ToInteger(cx, args[1], &d)) { - return false; - } - pos = uint32_t(std::min(std::max(d, 0.0), double(UINT32_MAX))); + if (!ToClampedStringIndex(cx, args[1], str->length(), &start)) { + return false; } } - // Step 8 - uint32_t textLen = str->length(); - - // Step 9 - uint32_t start = std::min(pos, textLen); - if (str == searchStr) { // AngularJS often invokes "false".indexOf("false"). This check should // be cheap enough to not hurt anything else. @@ -2469,7 +2440,7 @@ bool js::str_indexOf(JSContext* cx, unsigned argc, Value* vp) { return true; } - // Steps 10 and 11 + // Steps 8-10. JSLinearString* text = str->ensureLinear(cx); if (!text) { return false; @@ -2529,8 +2500,8 @@ static int32_t LastIndexOfImpl(const TextChar* text, size_t textLen, return -1; } -static int32_t LastIndexOf(JSLinearString* text, JSLinearString* searchStr, - size_t start) { +static int32_t LastIndexOf(const JSLinearString* text, + const JSLinearString* searchStr, size_t start) { AutoCheckCannotGC nogc; size_t len = text->length(); @@ -2555,8 +2526,8 @@ static int32_t LastIndexOf(JSLinearString* text, JSLinearString* searchStr, searchLen, start); } -// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e -// 21.1.3.9 String.prototype.lastIndexOf ( searchString [ , position ] ) +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 22.1.3.11 String.prototype.lastIndexOf ( searchString [ , position ] ) static bool str_lastIndexOf(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "lastIndexOf"); CallArgs args = CallArgsFromVp(argc, vp); @@ -2574,13 +2545,13 @@ static bool str_lastIndexOf(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 6. + // Step 7. size_t len = str->length(); // Step 8. size_t searchLen = searchStr->length(); - // Steps 4-5, 7. + // Steps 4-6 and 9. int start = len - searchLen; // Start searching here if (args.hasDefined(1)) { if (args[1].isInt32()) { @@ -2627,7 +2598,7 @@ static bool str_lastIndexOf(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 9. + // Step 10-12. args.rval().setInt32(LastIndexOf(text, searchStr, start)); return true; } @@ -2670,8 +2641,8 @@ bool js::StringLastIndexOf(JSContext* cx, HandleString string, return true; } -// ES2018 draft rev de77aaeffce115deaf948ed30c7dbe4c60983c0c -// 21.1.3.20 String.prototype.startsWith ( searchString [ , position ] ) +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 22.1.3.24 String.prototype.startsWith ( searchString [ , position ] ) bool js::str_startsWith(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "startsWith"); CallArgs args = CallArgsFromVp(argc, vp); @@ -2695,36 +2666,26 @@ bool js::str_startsWith(JSContext* cx, unsigned argc, Value* vp) { } // Step 6. - uint32_t pos = 0; - if (args.hasDefined(1)) { - if (args[1].isInt32()) { - int i = args[1].toInt32(); - pos = (i < 0) ? 0U : uint32_t(i); - } else { - double d; - if (!ToInteger(cx, args[1], &d)) { - return false; - } - pos = uint32_t(std::min(std::max(d, 0.0), double(UINT32_MAX))); - } - } - - // Step 7. uint32_t textLen = str->length(); - // Step 8. - uint32_t start = std::min(pos, textLen); + // Steps 7-8. + uint32_t start = 0; + if (args.hasDefined(1)) { + if (!ToClampedStringIndex(cx, args[1], textLen, &start)) { + return false; + } + } // Step 9. uint32_t searchLen = searchStr->length(); - // Step 10. + // Step 12. if (searchLen + start < searchLen || searchLen + start > textLen) { args.rval().setBoolean(false); return true; } - // Steps 11-12. + // Steps 10-11 and 13-15. JSLinearString* text = str->ensureLinear(cx); if (!text) { return false; @@ -2755,8 +2716,8 @@ bool js::StringStartsWith(JSContext* cx, HandleString string, return true; } -// ES2018 draft rev de77aaeffce115deaf948ed30c7dbe4c60983c0c -// 21.1.3.6 String.prototype.endsWith ( searchString [ , endPosition ] ) +// ES2026 draft rev a562082b031d89d00ee667181ce8a6158656bd4b +// 22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] ) bool js::str_endsWith(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "String.prototype", "endsWith"); CallArgs args = CallArgsFromVp(argc, vp); @@ -2781,37 +2742,27 @@ bool js::str_endsWith(JSContext* cx, unsigned argc, Value* vp) { // Step 6. uint32_t textLen = str->length(); - // Step 7. - uint32_t pos = textLen; + // Steps 7-8. + uint32_t end = textLen; if (args.hasDefined(1)) { - if (args[1].isInt32()) { - int i = args[1].toInt32(); - pos = (i < 0) ? 0U : uint32_t(i); - } else { - double d; - if (!ToInteger(cx, args[1], &d)) { - return false; - } - pos = uint32_t(std::min(std::max(d, 0.0), double(UINT32_MAX))); + if (!ToClampedStringIndex(cx, args[1], textLen, &end)) { + return false; } } - // Step 8. - uint32_t end = std::min(pos, textLen); - // Step 9. uint32_t searchLen = searchStr->length(); - // Step 11 (reordered). + // Step 12 (reordered). if (searchLen > end) { args.rval().setBoolean(false); return true; } - // Step 10. + // Step 11. uint32_t start = end - searchLen; - // Steps 12-13. + // Steps 10 and 13-15. JSLinearString* text = str->ensureLinear(cx); if (!text) { return false; @@ -3075,9 +3026,10 @@ static JSString* BuildFlatRopeReplacement(JSContext* cx, HandleString textstr, } template -static bool AppendDollarReplacement(StringBuffer& newReplaceChars, +static bool AppendDollarReplacement(StringBuilder& newReplaceChars, size_t firstDollarIndex, size_t matchStart, - size_t matchLimit, JSLinearString* text, + size_t matchLimit, + const JSLinearString* text, const CharT* repChars, size_t repLength) { MOZ_ASSERT(firstDollarIndex < repLength); MOZ_ASSERT(matchStart <= matchLimit); @@ -3186,9 +3138,9 @@ static JSLinearString* InterpretDollarReplacement( } template -static bool StrFlatReplaceGlobal(JSContext* cx, JSLinearString* str, - JSLinearString* pat, JSLinearString* rep, - StringBuffer& sb) { +static bool StrFlatReplaceGlobal(JSContext* cx, const JSLinearString* str, + const JSLinearString* pat, + const JSLinearString* rep, StringBuilder& sb) { MOZ_ASSERT(str->length() > 0); AutoCheckCannotGC nogc; @@ -3366,9 +3318,9 @@ JSString* js::str_replace_string_raw(JSContext* cx, HandleString string, template static bool ReplaceAllInternal(const AutoCheckCannotGC& nogc, - JSLinearString* string, - JSLinearString* searchString, - JSLinearString* replaceString, + const JSLinearString* string, + const JSLinearString* searchString, + const JSLinearString* replaceString, const int32_t startPosition, JSStringBuilder& result) { // Step 7. @@ -3439,8 +3391,8 @@ static bool ReplaceAllInternal(const AutoCheckCannotGC& nogc, // are fused. GetSubstitution is optimized away when possible. template static JSString* ReplaceAll(JSContext* cx, JSLinearString* string, - JSLinearString* searchString, - JSLinearString* replaceString) { + const JSLinearString* searchString, + const JSLinearString* replaceString) { // Step 7 moved into ReplaceAll_internal. // Step 8 (advanceBy is equal to searchLength when searchLength > 0). @@ -3483,8 +3435,9 @@ static JSString* ReplaceAll(JSContext* cx, JSLinearString* string, template static bool ReplaceAllInterleaveInternal(const AutoCheckCannotGC& nogc, - JSContext* cx, JSLinearString* string, - JSLinearString* replaceString, + JSContext* cx, + const JSLinearString* string, + const JSLinearString* replaceString, JSStringBuilder& result) { // Step 7. const size_t stringLength = string->length(); @@ -3549,8 +3502,9 @@ static bool ReplaceAllInterleaveInternal(const AutoCheckCannotGC& nogc, // The steps are quite different, for performance. Loops in steps 11 and 14 // are fused. GetSubstitution is optimized away when possible. template -static JSString* ReplaceAllInterleave(JSContext* cx, JSLinearString* string, - JSLinearString* replaceString) { +static JSString* ReplaceAllInterleave(JSContext* cx, + const JSLinearString* string, + const JSLinearString* replaceString) { // Step 7 moved into ReplaceAllInterleavedInternal. // Step 8 (advanceBy is 1 when searchString is the empty string). @@ -3674,7 +3628,13 @@ static ArrayObject* SplitHelper(JSContext* cx, Handle str, } // Step 3 (reordered). - RootedValueVector splits(cx); + Rooted substrings(cx, NewDenseEmptyArray(cx)); + if (!substrings) { + return nullptr; + } + + // Switch to allocating in the tenured heap if we fill the nursery. + AutoSelectGCHeap gcHeap(cx); // Step 8 (reordered). size_t lastEndIndex = 0; @@ -3720,16 +3680,17 @@ static ArrayObject* SplitHelper(JSContext* cx, Handle str, // Step 14.c.ii.1. size_t subLength = size_t(endIndex - sepLength - lastEndIndex); - JSString* sub = NewDependentString(cx, str, lastEndIndex, subLength); + JSString* sub = + NewDependentString(cx, str, lastEndIndex, subLength, gcHeap); // Steps 14.c.ii.2-4. - if (!sub || !splits.append(StringValue(sub))) { + if (!sub || !NewbornArrayPush(cx, substrings, StringValue(sub))) { return nullptr; } // Step 14.c.ii.5. - if (splits.length() == limit) { - return NewDenseCopiedArray(cx, splits.length(), splits.begin()); + if (substrings->length() == limit) { + return substrings; } // Step 14.c.ii.6. @@ -3740,16 +3701,16 @@ static ArrayObject* SplitHelper(JSContext* cx, Handle str, } // Step 15. - JSString* sub = - NewDependentString(cx, str, lastEndIndex, strLength - lastEndIndex); + size_t subLength = strLength - lastEndIndex; + JSString* sub = NewDependentString(cx, str, lastEndIndex, subLength, gcHeap); // Steps 16-17. - if (!sub || !splits.append(StringValue(sub))) { + if (!sub || !NewbornArrayPush(cx, substrings, StringValue(sub))) { return nullptr; } // Step 18. - return NewDenseCopiedArray(cx, splits.length(), splits.begin()); + return substrings; } // Fast-path for splitting a string into a character array via split(""). @@ -3960,6 +3921,11 @@ static const JSFunctionSpec string_methods[] = { JS_SELF_HOSTED_FN("fontsize", "String_fontsize", 1, 0), JS_SELF_HOSTED_SYM_FN(iterator, "String_iterator", 0, 0), + + /* well-formed unicode strings */ + JS_FN("isWellFormed", str_isWellFormed, 0, 0), + JS_FN("toWellFormed", str_toWellFormed, 0, 0), + JS_FS_END, }; @@ -4022,6 +3988,20 @@ JSLinearString* js::StringFromCodePoint(JSContext* cx, char32_t codePoint) { return NewInlineString(cx, chars, 2); } +// Inspect arguments to guess the output string type. +static bool GuessFromCharCodeIsLatin1(const CallArgs& args) { + // Arbitrarily chosen number of samples to inspect. + constexpr unsigned SampleSize = 8; + + for (unsigned i = 0; i < std::min(args.length(), SampleSize); i++) { + auto v = args[i]; + if (v.isInt32() && uint16_t(v.toInt32()) > JSString::MAX_LATIN1_CHAR) { + return false; + } + } + return true; +} + /** * 22.1.2.1 String.fromCharCode ( ...codeUnits ) * @@ -4048,27 +4028,72 @@ bool js::str_fromCharCode(JSContext* cx, unsigned argc, Value* vp) { return true; } - // Optimize the case where the result will definitely fit in an inline - // string (thin or fat) and so we don't need to malloc the chars. (We could - // cover some cases where args.length() goes up to - // JSFatInlineString::MAX_LENGTH_LATIN1 if we also checked if the chars are - // all Latin-1, but it doesn't seem worth the effort.) - InlineCharBuffer chars; - if (!chars.maybeAlloc(cx, args.length())) { + // Optimize the case where the result will be a Latin-1 string. + StringChars latin1Chars(cx); + + unsigned i = 0; + uint16_t firstTwoByteChar = 0; + if (GuessFromCharCodeIsLatin1(args)) { + if (!latin1Chars.maybeAlloc(cx, args.length())) { + return false; + } + + for (; i < args.length(); i++) { + uint16_t code; + if (!ToUint16(cx, args[i], &code)) { + return false; + } + + if (code > JSString::MAX_LATIN1_CHAR) { + firstTwoByteChar = code; + break; + } + + AutoCheckCannotGC nogc; + latin1Chars.data(nogc)[i] = code; + } + + if (i == args.length()) { + JSString* str = latin1Chars.toStringDontDeflate(cx, args.length()); + if (!str) { + return false; + } + + args.rval().setString(str); + return true; + } + } + + StringChars twoByteChars(cx); + if (!twoByteChars.maybeAlloc(cx, args.length())) { return false; } - char16_t* rawChars = chars.get(); - for (unsigned i = 0; i < args.length(); i++) { + // Copy the already processed characters. + if (i > 0) { + AutoCheckCannotGC nogc; + std::copy_n(latin1Chars.data(nogc), i, twoByteChars.data(nogc)); + } + + // Copy the first two-byte character, if present. + if (firstTwoByteChar > 0) { + MOZ_ASSERT(firstTwoByteChar > JSString::MAX_LATIN1_CHAR); + + AutoCheckCannotGC nogc; + twoByteChars.data(nogc)[i++] = char16_t(firstTwoByteChar); + } + + for (; i < args.length(); i++) { uint16_t code; if (!ToUint16(cx, args[i], &code)) { return false; } - rawChars[i] = char16_t(code); + AutoCheckCannotGC nogc; + twoByteChars.data(nogc)[i] = code; } - JSString* str = chars.toString(cx, args.length()); + JSString* str = twoByteChars.toStringDontDeflate(cx, args.length()); if (!str) { return false; } @@ -4300,12 +4325,6 @@ static bool StringClassFinish(JSContext* cx, HandleObject ctor, return false; } - // Define isWellFormed/toWellFormed functions. - if (JS::Prefs::well_formed_unicode_strings() && - !JS_DefineFunctions(cx, nativeProto, wellFormed_functions)) { - return false; - } - return true; } @@ -4317,7 +4336,8 @@ const ClassSpec StringObject::classSpec_ = { nullptr, string_methods, nullptr, - StringClassFinish}; + StringClassFinish, +}; #define ____ false @@ -4415,7 +4435,7 @@ enum EncodeResult { Encode_Failure, Encode_BadUri, Encode_Success }; // caller Encode function. Annotate both functions with MOZ_NEVER_INLINE resp. // MOZ_ALWAYS_INLINE to ensure we get the desired inlining behavior. template -static MOZ_NEVER_INLINE EncodeResult Encode(StringBuffer& sb, +static MOZ_NEVER_INLINE EncodeResult Encode(StringBuilder& sb, const CharT* chars, size_t length, const bool* unescapedSet) { Latin1Char hexBuf[3]; @@ -4545,7 +4565,7 @@ static MOZ_ALWAYS_INLINE bool Encode(JSContext* cx, Handle str, enum DecodeResult { Decode_Failure, Decode_BadUri, Decode_Success }; template -static DecodeResult Decode(StringBuffer& sb, const CharT* chars, size_t length, +static DecodeResult Decode(StringBuilder& sb, const CharT* chars, size_t length, const bool* reservedSet) { auto appendRange = [&sb, chars](size_t start, size_t end) { MOZ_ASSERT(start <= end); @@ -4827,34 +4847,12 @@ static bool BuildFlatMatchArray(JSContext* cx, HandleString str, return true; } -#ifdef DEBUG -static bool CallIsStringOptimizable(JSContext* cx, const char* name, - bool* result) { - FixedInvokeArgs<0> args(cx); - - RootedValue rval(cx); - if (!CallSelfHostedFunction(cx, name, UndefinedHandleValue, args, &rval)) { - return false; - } - - *result = rval.toBoolean(); - return true; -} -#endif - bool js::FlatStringMatch(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 2); MOZ_ASSERT(args[0].isString()); MOZ_ASSERT(args[1].isString()); -#ifdef DEBUG - bool isOptimizable = false; - if (!CallIsStringOptimizable(cx, "IsStringMatchOptimizable", - &isOptimizable)) { - return false; - } - MOZ_ASSERT(isOptimizable); -#endif + MOZ_ASSERT(cx->realm()->realmFuses.optimizeRegExpPrototypeFuse.intact()); RootedString str(cx, args[0].toString()); RootedString pattern(cx, args[1].toString()); @@ -4878,14 +4876,7 @@ bool js::FlatStringSearch(JSContext* cx, unsigned argc, Value* vp) { MOZ_ASSERT(args.length() == 2); MOZ_ASSERT(args[0].isString()); MOZ_ASSERT(args[1].isString()); -#ifdef DEBUG - bool isOptimizable = false; - if (!CallIsStringOptimizable(cx, "IsStringSearchOptimizable", - &isOptimizable)) { - return false; - } - MOZ_ASSERT(isOptimizable); -#endif + MOZ_ASSERT(cx->realm()->realmFuses.optimizeRegExpPrototypeFuse.intact()); RootedString str(cx, args[0].toString()); RootedString pattern(cx, args[1].toString()); diff --git a/src/third_party/mozjs/extract/js/src/builtin/String.h b/src/third_party/mozjs/extract/js/src/builtin/String.h index 556bc92488e..622d12dd9ad 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/String.h +++ b/src/third_party/mozjs/extract/js/src/builtin/String.h @@ -90,9 +90,9 @@ extern bool StringStartsWith(JSContext* cx, HandleString string, extern bool StringEndsWith(JSContext* cx, HandleString string, HandleString searchString, bool* result); -extern JSString* StringToLowerCase(JSContext* cx, HandleString string); +extern JSLinearString* StringToLowerCase(JSContext* cx, JSString* string); -extern JSString* StringToUpperCase(JSContext* cx, HandleString string); +extern JSLinearString* StringToUpperCase(JSContext* cx, JSString* string); extern JSString* StringTrim(JSContext* cx, HandleString string); diff --git a/src/third_party/mozjs/extract/js/src/builtin/String.js b/src/third_party/mozjs/extract/js/src/builtin/String.js index 864c6ad588e..563b7d3b677 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/String.js +++ b/src/third_party/mozjs/extract/js/src/builtin/String.js @@ -2,26 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -function StringProtoHasNoMatch() { - var ObjectProto = GetBuiltinPrototype("Object"); - var StringProto = GetBuiltinPrototype("String"); - if (!ObjectHasPrototype(StringProto, ObjectProto)) { - return false; - } - return !(GetBuiltinSymbol("match") in StringProto); -} - -function IsStringMatchOptimizable() { - var RegExpProto = GetBuiltinPrototype("RegExp"); - // If RegExpPrototypeOptimizable succeeds, `exec` and `@@match` are - // guaranteed to be data properties. - return ( - RegExpPrototypeOptimizable(RegExpProto) && - RegExpProto.exec === RegExp_prototype_Exec && - RegExpProto[GetBuiltinSymbol("match")] === RegExpMatch - ); -} - function ThrowIncompatibleMethod(name, thisv) { ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "String", name, ToString(thisv)); } @@ -36,14 +16,23 @@ function String_match(regexp) { // Step 2. var isPatternString = typeof regexp === "string"; if ( - !(isPatternString && StringProtoHasNoMatch()) && + !(isPatternString && CanOptimizeStringProtoSymbolLookup()) && !IsNullOrUndefined(regexp) ) { + // Fast path for regular expressions with the original + // RegExp.prototype[@@match] function. + if (IsObject(regexp) && IsOptimizableRegExpObject(regexp)) { + return callFunction(RegExpMatch, regexp, this); + } + // Step 2.a. var matcher = GetMethod(regexp, GetBuiltinSymbol("match")); // Step 2.b. if (matcher !== undefined) { + if (!IsObject(regexp)) { + RegExpSymbolProtocolOnPrimitiveCounter(); + } return callContentFunction(matcher, regexp, this); } } @@ -51,7 +40,7 @@ function String_match(regexp) { // Step 3. var S = ToString(this); - if (isPatternString && IsStringMatchOptimizable()) { + if (isPatternString && IsRegExpPrototypeOptimizable()) { var flatResult = FlatStringMatch(S, regexp); if (flatResult !== undefined) { return flatResult; @@ -62,7 +51,7 @@ function String_match(regexp) { var rx = RegExpCreate(regexp); // Step 5 (optimized case). - if (IsStringMatchOptimizable()) { + if (IsRegExpPrototypeOptimizable()) { return RegExpMatcher(rx, S, 0); } @@ -97,11 +86,20 @@ function String_matchAll(regexp) { } } + // Fast path for regular expressions with the original + // RegExp.prototype[@@matchAll] function. + if (IsObject(regexp) && IsOptimizableRegExpObject(regexp)) { + return callFunction(RegExpMatchAll, regexp, this); + } + // Step 2.c. var matcher = GetMethod(regexp, GetBuiltinSymbol("matchAll")); // Step 2.d. if (matcher !== undefined) { + if (!IsObject(regexp)) { + RegExpSymbolProtocolOnPrimitiveCounter(); + } return callContentFunction(matcher, regexp, this); } } @@ -186,15 +184,6 @@ function String_pad_end(maxLength, fillString = " ") { return callFunction(String_pad, this, maxLength, fillString, true); } -function StringProtoHasNoReplace() { - var ObjectProto = GetBuiltinPrototype("Object"); - var StringProto = GetBuiltinPrototype("String"); - if (!ObjectHasPrototype(StringProto, ObjectProto)) { - return false; - } - return !(GetBuiltinSymbol("replace") in StringProto); -} - // A thin wrapper to call SubstringKernel with int32-typed arguments. // Caller should check the range of |from| and |length|. function Substring(str, from, length) { @@ -224,14 +213,23 @@ function String_replace(searchValue, replaceValue) { // Step 2. if ( - !(typeof searchValue === "string" && StringProtoHasNoReplace()) && + !(typeof searchValue === "string" && CanOptimizeStringProtoSymbolLookup()) && !IsNullOrUndefined(searchValue) ) { + // Fast path for regular expressions with the original + // RegExp.prototype[@@replace] function. + if (IsObject(searchValue) && IsOptimizableRegExpObject(searchValue)) { + return callFunction(RegExpReplace, searchValue, this, replaceValue); + } + // Step 2.a. var replacer = GetMethod(searchValue, GetBuiltinSymbol("replace")); // Step 2.b. if (replacer !== undefined) { + if (!IsObject(searchValue)) { + RegExpSymbolProtocolOnPrimitiveCounter(); + } return callContentFunction(replacer, searchValue, this, replaceValue); } } @@ -313,11 +311,20 @@ function String_replaceAll(searchValue, replaceValue) { } } + // Fast path for regular expressions with the original + // RegExp.prototype[@@replace] function. + if (IsObject(searchValue) && IsOptimizableRegExpObject(searchValue)) { + return callFunction(RegExpReplace, searchValue, this, replaceValue); + } + // Step 2.c. var replacer = GetMethod(searchValue, GetBuiltinSymbol("replace")); // Step 2.b. if (replacer !== undefined) { + if (!IsObject(searchValue)) { + RegExpSymbolProtocolOnPrimitiveCounter(); + } return callContentFunction(replacer, searchValue, this, replaceValue); } } @@ -409,26 +416,6 @@ function String_replaceAll(searchValue, replaceValue) { return result; } -function StringProtoHasNoSearch() { - var ObjectProto = GetBuiltinPrototype("Object"); - var StringProto = GetBuiltinPrototype("String"); - if (!ObjectHasPrototype(StringProto, ObjectProto)) { - return false; - } - return !(GetBuiltinSymbol("search") in StringProto); -} - -function IsStringSearchOptimizable() { - var RegExpProto = GetBuiltinPrototype("RegExp"); - // If RegExpPrototypeOptimizable succeeds, `exec` and `@@search` are - // guaranteed to be data properties. - return ( - RegExpPrototypeOptimizable(RegExpProto) && - RegExpProto.exec === RegExp_prototype_Exec && - RegExpProto[GetBuiltinSymbol("search")] === RegExpSearch - ); -} - // ES 2016 draft Mar 25, 2016 21.1.3.15. function String_search(regexp) { // Step 1. @@ -439,14 +426,23 @@ function String_search(regexp) { // Step 2. var isPatternString = typeof regexp === "string"; if ( - !(isPatternString && StringProtoHasNoSearch()) && + !(isPatternString && CanOptimizeStringProtoSymbolLookup()) && !IsNullOrUndefined(regexp) ) { + // Fast path for regular expressions with the original + // RegExp.prototype[@@search] function. + if (IsObject(regexp) && IsOptimizableRegExpObject(regexp)) { + return callFunction(RegExpSearch, regexp, this); + } + // Step 2.a. var searcher = GetMethod(regexp, GetBuiltinSymbol("search")); // Step 2.b. if (searcher !== undefined) { + if (!IsObject(regexp)) { + RegExpSymbolProtocolOnPrimitiveCounter(); + } return callContentFunction(searcher, regexp, this); } } @@ -454,7 +450,7 @@ function String_search(regexp) { // Step 3. var string = ToString(this); - if (isPatternString && IsStringSearchOptimizable()) { + if (isPatternString && IsRegExpPrototypeOptimizable()) { var flatResult = FlatStringSearch(string, regexp); if (flatResult !== -2) { return flatResult; @@ -472,15 +468,6 @@ function String_search(regexp) { ); } -function StringProtoHasNoSplit() { - var ObjectProto = GetBuiltinPrototype("Object"); - var StringProto = GetBuiltinPrototype("String"); - if (!ObjectHasPrototype(StringProto, ObjectProto)) { - return false; - } - return !(GetBuiltinSymbol("split") in StringProto); -} - // ES 2016 draft Mar 25, 2016 21.1.3.17. function String_split(separator, limit) { // Step 1. @@ -492,7 +479,7 @@ function String_split(separator, limit) { // are constants. Following sequence of if's cannot be put together in // order that IonMonkey sees the constant if present (bug 1246141). if (typeof this === "string") { - if (StringProtoHasNoSplit()) { + if (CanOptimizeStringProtoSymbolLookup()) { if (typeof separator === "string") { if (limit === undefined) { // inlineConstantStringSplitString needs both arguments to @@ -505,14 +492,23 @@ function String_split(separator, limit) { // Step 2. if ( - !(typeof separator === "string" && StringProtoHasNoSplit()) && + !(typeof separator === "string" && CanOptimizeStringProtoSymbolLookup()) && !IsNullOrUndefined(separator) ) { + // Fast path for regular expressions with the original + // RegExp.prototype[@@split] function. + if (IsObject(separator) && IsOptimizableRegExpObject(separator)) { + return callFunction(RegExpSplit, separator, this, limit); + } + // Step 2.a. var splitter = GetMethod(separator, GetBuiltinSymbol("split")); // Step 2.b. if (splitter !== undefined) { + if (!IsObject(separator)) { + RegExpSymbolProtocolOnPrimitiveCounter(); + } return callContentFunction(splitter, separator, this, limit); } } diff --git a/src/third_party/mozjs/extract/js/src/builtin/Symbol.cpp b/src/third_party/mozjs/extract/js/src/builtin/Symbol.cpp index b1b8df4d78d..20b2977d4df 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Symbol.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/Symbol.cpp @@ -20,7 +20,9 @@ const JSClass SymbolObject::class_ = { "Symbol", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_Symbol), - JS_NULL_CLASS_OPS, &SymbolObject::classSpec_}; + JS_NULL_CLASS_OPS, + &SymbolObject::classSpec_, +}; // This uses PlainObject::class_ because: "The Symbol prototype object is an // ordinary object. It is not a Symbol instance and does not have a @@ -38,14 +40,22 @@ SymbolObject* SymbolObject::create(JSContext* cx, JS::HandleSymbol symbol) { const JSPropertySpec SymbolObject::properties[] = { JS_PSG("description", descriptionGetter, 0), - JS_STRING_SYM_PS(toStringTag, "Symbol", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "Symbol", JSPROP_READONLY), + JS_PS_END, +}; const JSFunctionSpec SymbolObject::methods[] = { - JS_FN("toString", toString, 0, 0), JS_FN("valueOf", valueOf, 0, 0), - JS_SYM_FN(toPrimitive, toPrimitive, 1, JSPROP_READONLY), JS_FS_END}; + JS_FN("toString", toString, 0, 0), + JS_FN("valueOf", valueOf, 0, 0), + JS_SYM_FN(toPrimitive, toPrimitive, 1, JSPROP_READONLY), + JS_FS_END, +}; const JSFunctionSpec SymbolObject::staticMethods[] = { - JS_FN("for", for_, 1, 0), JS_FN("keyFor", keyFor, 1, 0), JS_FS_END}; + JS_FN("for", for_, 1, 0), + JS_FN("keyFor", keyFor, 1, 0), + JS_FS_END, +}; static bool SymbolClassFinish(JSContext* cx, HandleObject ctor, HandleObject proto) { @@ -74,7 +84,8 @@ const ClassSpec SymbolObject::classSpec_ = { nullptr, methods, properties, - SymbolClassFinish}; + SymbolClassFinish, +}; // ES2020 draft rev ecb4178012d6b4d9abc13fcbd45f5c6394b832ce // 19.4.1.1 Symbol ( [ description ] ) diff --git a/src/third_party/mozjs/extract/js/src/builtin/TestingFunctions.cpp b/src/third_party/mozjs/extract/js/src/builtin/TestingFunctions.cpp index 618bca5bfde..9cfd307b72f 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/TestingFunctions.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/TestingFunctions.cpp @@ -16,9 +16,11 @@ # include "mozilla/intl/TimeZone.h" #endif #include "mozilla/Maybe.h" +#include "mozilla/RefPtr.h" #include "mozilla/ScopeExit.h" #include "mozilla/Span.h" #include "mozilla/Sprintf.h" +#include "mozilla/StringBuffer.h" #include "mozilla/TextUtils.h" #include "mozilla/ThreadLocal.h" @@ -54,7 +56,6 @@ #include "builtin/Promise.h" #include "builtin/TestingUtility.h" // js::ParseCompileOptions, js::ParseDebugMetadata #include "ds/IdValuePair.h" // js::IdValuePair -#include "frontend/BytecodeCompiler.h" // frontend::{CompileGlobalScriptToExtensibleStencil,ParseModuleToExtensibleStencil} #include "frontend/CompilationStencil.h" // frontend::CompilationStencil #include "frontend/FrontendContext.h" // AutoReportFrontendContext #include "gc/GC.h" @@ -62,24 +63,27 @@ #include "gc/GCLock.h" #include "gc/Zone.h" #include "jit/BaselineJIT.h" +#include "jit/CacheIRSpewer.h" #include "jit/Disassemble.h" +#include "jit/FlushICache.h" #include "jit/InlinableNatives.h" #include "jit/Invalidation.h" #include "jit/Ion.h" #include "jit/JitOptions.h" #include "jit/JitRuntime.h" +#include "jit/JitScript.h" #include "jit/TrialInlining.h" #include "js/Array.h" // JS::NewArrayObject #include "js/ArrayBuffer.h" // JS::{DetachArrayBuffer,GetArrayBufferLengthAndData,NewArrayBufferWithContents} #include "js/CallAndConstruct.h" // JS::Call, JS::IsCallable, JS::IsConstructor, JS_CallFunction #include "js/CharacterEncoding.h" #include "js/CompilationAndEvaluation.h" -#include "js/CompileOptions.h" +#include "js/CompileOptions.h" // JS::CompileOptions, JS::DecodeOptions, JS::InstantiateOptions #include "js/Conversions.h" #include "js/Date.h" -#include "js/experimental/CodeCoverage.h" // js::GetCodeCoverageSummary -#include "js/experimental/CompileScript.h" // JS::ParseGlobalScript, JS::PrepareForInstantiate -#include "js/experimental/JSStencil.h" // JS::Stencil +#include "js/experimental/CodeCoverage.h" // js::GetCodeCoverageSummary +#include "js/experimental/CompileScript.h" // JS::CompileGlobalScriptToStencil, JS::CompileModuleScriptToStencil, JS::PrepareForInstantiate +#include "js/experimental/JSStencil.h" // JS::Stencil, JS::EncodeStencil, JS::DecodeStencil, JS::InstantiateGlobalStencil #include "js/experimental/PCCountProfiling.h" // JS::{Start,Stop}PCCountProfiling, JS::PurgePCCounts, JS::GetPCCountScript{Count,Summary,Contents} #include "js/experimental/TypedData.h" // JS_GetObjectAsUint8Array #include "js/friend/DumpFunctions.h" // js::Dump{Backtrace,Heap,Object}, JS::FormatStackDump, js::IgnoreNurseryObjects @@ -98,6 +102,7 @@ #include "js/Stack.h" #include "js/String.h" // JS::GetLinearStringLength, JS::StringToLinearString #include "js/StructuredClone.h" +#include "js/Transcoding.h" // JS::TranscodeResult, JS::TranscodeRange, JS::TranscodeBuffer, JS::IsTranscodeFailureResult #include "js/UbiNode.h" #include "js/UbiNodeBreadthFirst.h" #include "js/UbiNodeShortestPaths.h" @@ -106,7 +111,7 @@ #include "js/Wrapper.h" #include "threading/CpuCount.h" #include "util/DifferentialTesting.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "util/Text.h" #include "vm/BooleanObject.h" #include "vm/DateObject.h" @@ -126,13 +131,13 @@ #include "vm/SavedStacks.h" #include "vm/ScopeKind.h" #include "vm/Stack.h" -#include "vm/StencilCache.h" // DelazificationCache #include "vm/StencilObject.h" // StencilObject, StencilXDRBufferObject #include "vm/StringObject.h" #include "vm/StringType.h" #include "wasm/AsmJS.h" #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmBuiltinModule.h" +#include "wasm/WasmDump.h" #include "wasm/WasmFeatures.h" #include "wasm/WasmGcObject.h" #include "wasm/WasmInstance.h" @@ -161,8 +166,9 @@ using mozilla::Span; using JS::AutoStableStringChars; using JS::CompileOptions; -using JS::SourceOwnership; +using JS::SliceBudget; using JS::SourceText; +using JS::WorkBudget; // If fuzzingSafe is set, remove functionality that could cause problems with // fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE. @@ -401,15 +407,6 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) { return false; } -#ifdef JS_CODEGEN_MIPS32 - value = BooleanValue(true); -#else - value = BooleanValue(false); -#endif - if (!JS_SetProperty(cx, info, "mips32", value)) { - return false; - } - #ifdef JS_CODEGEN_MIPS64 value = BooleanValue(true); #else @@ -419,15 +416,6 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) { return false; } -#ifdef JS_SIMULATOR_MIPS32 - value = BooleanValue(true); -#else - value = BooleanValue(false); -#endif - if (!JS_SetProperty(cx, info, "mips32-simulator", value)) { - return false; - } - #ifdef JS_SIMULATOR_MIPS64 value = BooleanValue(true); #else @@ -622,6 +610,17 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) { return false; } +#if (defined(__GNUC__) && defined(__SSE__) && defined(__x86_64__)) || \ + defined(__arm__) || defined(__aarch64__) + // See js.cpp "disable-main-thread-denormals" command line option. + value = BooleanValue(true); +#else + value = BooleanValue(false); +#endif + if (!JS_SetProperty(cx, info, "can-disable-main-thread-denormals", value)) { + return false; + } + value = Int32Value(JSFatInlineString::MAX_LENGTH_LATIN1); if (!JS_SetProperty(cx, info, "inline-latin1-chars", value)) { return false; @@ -844,6 +843,18 @@ static bool GCParameter(JSContext* cx, unsigned argc, Value* vp) { return false; } + if (fuzzingSafe) { + // Some Params are not yet fuzzing safe and so we silently skip + // changing said parameters. + switch (param) { + case JSGC_SEMISPACE_NURSERY_ENABLED: + args.rval().setUndefined(); + return true; + default: + break; + } + } + if (disableOOMFunctions) { switch (param) { case JSGC_MAX_BYTES: @@ -876,6 +887,13 @@ static bool GCParameter(JSContext* cx, unsigned argc, Value* vp) { return true; } +static bool FinishBackgroundFree(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + cx->runtime()->gc.waitBackgroundFreeEnd(); + args.rval().setUndefined(); + return true; +} + static bool RelazifyFunctions(JSContext* cx, unsigned argc, Value* vp) { // Relazifying functions on GC is usually only done for compartments that are // not active. To aid fuzzing, this testing function allows us to relazify @@ -963,7 +981,7 @@ static bool WasmMaxMemoryPages(JSContext* cx, unsigned argc, Value* vp) { return false; } if (!args.get(0).isString()) { - JS_ReportErrorASCII(cx, "index type must be a string"); + JS_ReportErrorASCII(cx, "address type must be a string"); return false; } RootedString s(cx, args.get(0).toString()); @@ -973,21 +991,21 @@ static bool WasmMaxMemoryPages(JSContext* cx, unsigned argc, Value* vp) { } if (StringEqualsLiteral(ls, "i32")) { args.rval().setInt32( - int32_t(wasm::MaxMemoryPages(wasm::IndexType::I32).value())); + int32_t(wasm::MaxMemoryPages(wasm::AddressType::I32).value())); return true; } if (StringEqualsLiteral(ls, "i64")) { #ifdef ENABLE_WASM_MEMORY64 if (wasm::Memory64Available(cx)) { args.rval().setInt32( - int32_t(wasm::MaxMemoryPages(wasm::IndexType::I64).value())); + int32_t(wasm::MaxMemoryPages(wasm::AddressType::I64).value())); return true; } #endif JS_ReportErrorASCII(cx, "memory64 not enabled"); return false; } - JS_ReportErrorASCII(cx, "bad index type"); + JS_ReportErrorASCII(cx, "bad address type"); return false; } @@ -1066,6 +1084,21 @@ static bool WasmCompileMode(JSContext* cx, unsigned argc, Value* vp) { return false; } +static bool WasmLazyTieringEnabled(JSContext* cx, unsigned argc, Value* vp) { + // Note: ensure this function stays in sync with `PlatformCanTier()`. + CallArgs args = CallArgsFromVp(argc, vp); + bool baseline = wasm::BaselineAvailable(cx); + bool ion = wasm::IonAvailable(cx); + + bool enabled = + baseline && ion && JS::Prefs::wasm_lazy_tiering() && + (JS::Prefs::wasm_lazy_tiering_synchronous() || + (CanUseExtraThreads() && jit::CanFlushExecutionContextForAllThreads())); + + args.rval().setBoolean(enabled); + return true; +} + static bool WasmBaselineDisabledByFeatures(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1608,7 +1641,7 @@ static bool WasmLosslessInvoke(JSContext* cx, unsigned argc, Value* vp) { } RootedFunction func(cx, &args[0].toObject().as()); - if (!func || !wasm::IsWasmExportedFunction(func)) { + if (!func || !func->isWasm()) { JS_ReportErrorASCII(cx, "argument is not an exported wasm function"); return false; } @@ -1617,8 +1650,8 @@ static bool WasmLosslessInvoke(JSContext* cx, unsigned argc, Value* vp) { AutoRealm ar(cx, func); // Get the instance and funcIndex for calling the function - wasm::Instance& instance = wasm::ExportedFunctionToInstance(func); - uint32_t funcIndex = wasm::ExportedFunctionToFuncIndex(func); + wasm::Instance& instance = func->wasmInstance(); + uint32_t funcIndex = func->wasmFuncIndex(); // Set up a modified call frame following the standard JS // [callee, this, arguments...] convention. @@ -1667,9 +1700,9 @@ static bool ConvertToTier(JSContext* cx, HandleValue value, } if (stableTier) { - *tier = code.stableTier(); + *tier = code.stableCompleteTier(); } else if (bestTier) { - *tier = code.bestTier(); + *tier = code.bestCompleteTier(); } else if (baselineTier) { *tier = wasm::Tier::Baseline; } else if (ionTier) { @@ -1703,8 +1736,7 @@ static bool WasmExtractCode(JSContext* cx, unsigned argc, Value* vp) { return false; } - wasm::Tier tier = module->module().code().stableTier(); - ; + wasm::Tier tier = module->module().code().stableCompleteTier(); if (args.length() > 1 && !ConvertToTier(cx, args[1], module->module().code(), &tier)) { args.rval().setNull(); @@ -1720,30 +1752,22 @@ static bool WasmExtractCode(JSContext* cx, unsigned argc, Value* vp) { return true; } -struct DisasmBuffer { - JSStringBuilder builder; - bool oom; - explicit DisasmBuffer(JSContext* cx) : builder(cx), oom(false) {} -}; - static bool HasDisassembler(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setBoolean(jit::HasDisassembler()); return true; } -MOZ_THREAD_LOCAL(DisasmBuffer*) disasmBuf; +MOZ_THREAD_LOCAL(JSSprinter*) disasmPrinter; static void captureDisasmText(const char* text) { - DisasmBuffer* buf = disasmBuf.get(); - if (!buf->builder.append(text, strlen(text)) || !buf->builder.append('\n')) { - buf->oom = true; - } + JSSprinter* printer = disasmPrinter.get(); + printer->put(text); + printer->printf("\n"); } static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - args.rval().setUndefined(); if (args.length() < 1) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, @@ -1768,44 +1792,31 @@ static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) { uint8_t* jit_end = nullptr; if (fun->isAsmJSNative() || fun->isWasmWithJitEntry()) { - if (fun->isAsmJSNative()) { + if (IsAsmJSModule(fun)) { + JS_ReportErrorASCII(cx, "Can't disassemble asm.js module function."); return false; } - sprinter.printf("; backend=asmjs\n"); + if (fun->isAsmJSNative()) { + sprinter.printf("; backend=asmjs\n"); + } sprinter.printf("; backend=wasm\n"); js::wasm::Instance& inst = fun->wasmInstance(); - const js::wasm::Code& code = inst.code(); - js::wasm::Tier tier = code.bestTier(); + const uint32_t funcIndex = fun->wasmFuncIndex(); + const js::wasm::CodeBlock& codeBlock = inst.code().funcCodeBlock(funcIndex); + const js::wasm::FuncExport& func = codeBlock.lookupFuncExport(funcIndex); + const js::wasm::CodeRange& codeRange = codeBlock.codeRange(func); - const js::wasm::MetadataTier& meta = inst.metadata(tier); - - const js::wasm::CodeSegment& segment = code.segment(tier); - const uint32_t funcIndex = code.getFuncIndex(&*fun); - const js::wasm::FuncExport& func = meta.lookupFuncExport(funcIndex); - const js::wasm::CodeRange& codeRange = meta.codeRange(func); - - jit_begin = segment.base() + codeRange.begin(); - jit_end = segment.base() + codeRange.end(); - } else if (fun->hasJitScript()) { - JSScript* script = fun->nonLazyScript(); - if (script == nullptr) { - return false; - } - - js::jit::IonScript* ion = - script->hasIonScript() ? script->ionScript() : nullptr; - js::jit::BaselineScript* baseline = - script->hasBaselineScript() ? script->baselineScript() : nullptr; - if (ion && ion->method()) { - sprinter.printf("; backend=ion\n"); - jit_begin = ion->method()->raw(); - jit_end = ion->method()->rawEnd(); - } else if (baseline) { - sprinter.printf("; backend=baseline\n"); - jit_begin = baseline->method()->raw(); - jit_end = baseline->method()->rawEnd(); - } + jit_begin = codeBlock.base() + codeRange.begin(); + jit_end = codeBlock.base() + codeRange.end(); + } else if (fun->hasJitScript() && fun->nonLazyScript()->hasIonScript()) { + sprinter.printf("; backend=ion\n"); + jit_begin = fun->nonLazyScript()->ionScript()->method()->raw(); + jit_end = fun->nonLazyScript()->ionScript()->method()->rawEnd(); + } else if (fun->hasJitScript() && fun->nonLazyScript()->hasBaselineScript()) { + sprinter.printf("; backend=baseline\n"); + jit_begin = fun->nonLazyScript()->baselineScript()->method()->raw(); + jit_end = fun->nonLazyScript()->baselineScript()->method()->rawEnd(); } else { JS_ReportErrorASCII(cx, "The function hasn't been warmed up, hence no JIT code " @@ -1813,9 +1824,8 @@ static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) { return false; } - if (jit_begin == nullptr || jit_end == nullptr) { - return false; - } + MOZ_ASSERT(jit_begin); + MOZ_ASSERT(jit_end); #ifdef JS_CODEGEN_ARM // The ARM32 disassembler is currently not fuzzing-safe because it doesn't @@ -1854,48 +1864,107 @@ static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) { fclose(f); } - DisasmBuffer buf(cx); - disasmBuf.set(&buf); - auto onFinish = mozilla::MakeScopeExit([&] { disasmBuf.set(nullptr); }); + disasmPrinter.set(&sprinter); + auto onFinish = mozilla::MakeScopeExit([&] { disasmPrinter.set(nullptr); }); jit::Disassemble(jit_begin, jit_end - jit_begin, &captureDisasmText); - if (buf.oom) { - ReportOutOfMemory(cx); - return false; - } - JSString* sresult = buf.builder.finishString(); - if (!sresult) { - ReportOutOfMemory(cx); - return false; - } - sprinter.putString(cx, sresult); - JSString* str = sprinter.release(cx); if (!str) { return false; } - args[0].setUndefined(); args.rval().setString(str); + return true; +} +static bool DisassembleBaselineICs(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + args.rval().setUndefined(); + + if (!args.requireAtLeast(cx, "disblic", 1)) { + return false; + } + + if (!args[0].isObject() || !args[0].toObject().is()) { + JS_ReportErrorASCII(cx, "The first argument must be a function."); + return false; + } + + JSSprinter sprinter(cx); + if (!sprinter.init()) { + return false; + } + + disasmPrinter.set(&sprinter); + auto onFinish = mozilla::MakeScopeExit([&] { disasmPrinter.set(nullptr); }); + + RootedFunction fun(cx, &args[0].toObject().as()); + + if (!fun->hasJitScript()) { + args.rval().setUndefined(); + return true; + } + +#ifdef JS_CODEGEN_ARM + // The ARM32 disassembler is currently not fuzzing-safe because it doesn't + // handle constant pools correctly (bug 1875363). + if (fuzzingSafe) { + JS_ReportErrorASCII(cx, "disblic is not fuzzing-safe on ARM32"); + return false; + } +#endif + + RootedScript script(cx, fun->nonLazyScript()); + jit::ICScript* icScript = script->jitScript()->icScript(); + for (uint32_t i = 0; i < icScript->numICEntries(); i++) { + jit::ICEntry& entry = icScript->icEntry(i); + jit::ICStub* stub = entry.firstStub(); + + jit::ICStub* fallbackStub = stub; + while (!fallbackStub->isFallback()) { + fallbackStub = fallbackStub->toCacheIRStub()->next(); + } + uint32_t pcOffset = fallbackStub->toFallbackStub()->pcOffset(); + sprinter.printf("; %s (pcOffset %05u)\n", + CodeName(JSOp(*script->offsetToPC(pcOffset))), pcOffset); + + uint32_t stubNum = 1; + while (!stub->isFallback()) { + sprinter.printf("; Stub #%d (entry count: %d)\n", stubNum, + stub->enteredCount()); + jit::ICCacheIRStub* cacheIRStub = stub->toCacheIRStub(); + uint8_t* jit_begin = stub->jitCode()->raw(); + uint8_t* jit_end = stub->jitCode()->rawEnd(); +#ifdef JS_CACHEIR_SPEW + sprinter.printf("; IR:\n"); + SpewCacheIROps(sprinter, "; ", cacheIRStub->stubInfo()); +#endif + + jit::Disassemble(jit_begin, jit_end - jit_begin, &captureDisasmText); + stub = cacheIRStub->next(); + stubNum++; + } + } + + JSString* str = sprinter.release(cx); + if (!str) { + return false; + } + + args.rval().setString(str); return true; } static bool ComputeTier(JSContext* cx, const wasm::Code& code, HandleValue tierSelection, wasm::Tier* tier) { - *tier = code.stableTier(); + *tier = code.stableCompleteTier(); if (!tierSelection.isUndefined() && !ConvertToTier(cx, tierSelection, code, tier)) { JS_ReportErrorASCII(cx, "invalid tier"); return false; } - if (!code.hasTier(*tier)) { - JS_ReportErrorASCII(cx, "function missing selected tier"); - return false; - } - return true; } @@ -1903,17 +1972,16 @@ template static bool DisassembleIt(JSContext* cx, bool asString, MutableHandleValue rval, DisasmFunction&& disassembleIt) { if (asString) { - DisasmBuffer buf(cx); - disasmBuf.set(&buf); - auto onFinish = mozilla::MakeScopeExit([&] { disasmBuf.set(nullptr); }); - disassembleIt(captureDisasmText); - if (buf.oom) { - ReportOutOfMemory(cx); + JSSprinter sprinter(cx); + if (!sprinter.init()) { return false; } - JSString* sresult = buf.builder.finishString(); + disasmPrinter.set(&sprinter); + auto onFinish = mozilla::MakeScopeExit([&] { disasmPrinter.set(nullptr); }); + disassembleIt(captureDisasmText); + + JSString* sresult = sprinter.release(cx); if (!sresult) { - ReportOutOfMemory(cx); return false; } rval.setString(sresult); @@ -1927,14 +1995,19 @@ static bool DisassembleIt(JSContext* cx, bool asString, MutableHandleValue rval, static bool WasmDisassembleFunction(JSContext* cx, const HandleFunction& func, HandleValue tierSelection, bool asString, MutableHandleValue rval) { - wasm::Instance& instance = wasm::ExportedFunctionToInstance(func); + wasm::Instance& instance = func->wasmInstance(); + uint32_t funcIndex = func->wasmFuncIndex(); wasm::Tier tier; if (!ComputeTier(cx, instance.code(), tierSelection, &tier)) { return false; } - uint32_t funcIndex = wasm::ExportedFunctionToFuncIndex(func); + if (!instance.code().funcHasTier(funcIndex, tier)) { + JS_ReportErrorASCII(cx, "function missing selected tier"); + return false; + } + return DisassembleIt( cx, asString, rval, [&](void (*captureText)(const char*)) { instance.disassembleExport(cx, funcIndex, tier, captureText); @@ -2035,7 +2108,7 @@ static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) { } RootedFunction func(cx, args[0].toObject().maybeUnwrapIf()); - if (func && wasm::IsWasmExportedFunction(func)) { + if (func && func->isWasm()) { return WasmDisassembleFunction(cx, func, tierSelection, asString, args.rval()); } @@ -2054,6 +2127,77 @@ static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) { return false; } +static bool WasmModuleToText(JSContext* cx, unsigned argc, Value* vp) { + if (!wasm::HasSupport(cx)) { + JS_ReportErrorASCII(cx, "wasm support unavailable"); + return false; + } + + CallArgs args = CallArgsFromVp(argc, vp); + + if (!args.get(0).isObject()) { + JS_ReportErrorASCII(cx, "argument is not an object"); + return false; + } + + if (!args[0].toObject().is()) { + JS_ReportErrorASCII(cx, "argument is not a wasm module"); + return false; + } + + const wasm::Module& mod = args[0].toObject().as().module(); + JSSprinter out(cx); + if (!out.init()) { + ReportOutOfMemory(cx); + return false; + } + wasm::DumpModule(mod, out); + + JSString* str = out.release(cx); + if (!str) { + ReportOutOfMemory(cx); + return false; + } + args.rval().set(StringValue(str)); + return true; +} + +static bool WasmFunctionTier(JSContext* cx, unsigned argc, Value* vp) { + if (!wasm::HasSupport(cx)) { + JS_ReportErrorASCII(cx, "wasm support unavailable"); + return false; + } + + CallArgs args = CallArgsFromVp(argc, vp); + + args.rval().set(UndefinedValue()); + + if (!args.get(0).isObject()) { + JS_ReportErrorASCII(cx, "argument is not an object"); + return false; + } + + RootedFunction func(cx, args[0].toObject().maybeUnwrapIf()); + if (func && func->isWasm()) { + uint32_t funcIndex = func->wasmFuncIndex(); + wasm::Instance& instance = func->wasmInstance(); + if (funcIndex < instance.code().funcImports().length()) { + JS_ReportErrorASCII(cx, "argument is an imported function"); + return false; + } + wasm::Tier tier = instance.code().funcTier(funcIndex); + RootedString tierString(cx, JS_NewStringCopyZ(cx, wasm::ToString(tier))); + if (!tierString) { + ReportOutOfMemory(cx); + return false; + } + args.rval().set(StringValue(tierString)); + return true; + } + JS_ReportErrorASCII(cx, "argument is not an exported wasm function"); + return false; +} + static bool ToIonDumpContents(JSContext* cx, HandleValue value, wasm::IonDumpContents* contents) { RootedString option(cx, JS::ToString(cx, value)); @@ -2092,11 +2236,8 @@ static bool WasmDumpIon(JSContext* cx, unsigned argc, Value* vp) { args.rval().set(UndefinedValue()); - SharedMem dataPointer; - size_t byteLength; - if (!args.get(0).isObject() || !IsBufferSource(args.get(0).toObjectOrNull(), - &dataPointer, &byteLength)) { - JS_ReportErrorASCII(cx, "argument is not a buffer source"); + if (!args.get(0).isObject()) { + JS_ReportErrorASCII(cx, "argument is not an object"); return false; } @@ -2112,6 +2253,14 @@ static bool WasmDumpIon(JSContext* cx, unsigned argc, Value* vp) { return false; } + SharedMem dataPointer; + size_t byteLength; + if (!IsBufferSource(cx, args.get(0).toObjectOrNull(), /*allowShared*/ false, + /*allowResizable*/ false, &dataPointer, &byteLength)) { + JS_ReportErrorASCII(cx, "argument is not a buffer source"); + return false; + } + wasm::MutableBytes bytecode = cx->new_(); if (!bytecode) { return false; @@ -2174,7 +2323,7 @@ static bool WasmReturnFlag(JSContext* cx, unsigned argc, Value* vp, Flag flag) { b = module->module().loggingDeserialized(); break; case Flag::ParsedBranchHints: - b = module->module().metadata().parsedBranchHints; + b = !module->module().codeMeta().branchHints.failedParse(); break; } @@ -2270,7 +2419,6 @@ static bool WasmBuiltinI8VecMul(JSContext* cx, unsigned argc, Value* vp) { return true; } -#ifdef ENABLE_WASM_GC static bool WasmGcReadField(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject callee(cx, &args.callee()); @@ -2321,7 +2469,6 @@ static bool WasmGcArrayLength(JSContext* cx, unsigned argc, Value* vp) { args.rval().setInt32(int32_t(arr.numElements_)); return true; } -#endif // ENABLE_WASM_GC static bool LargeArrayBufferSupported(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -2362,7 +2509,8 @@ static bool IsRelazifiableFunction(JSContext* cx, unsigned argc, Value* vp) { return true; } -static bool IsInStencilCache(JSContext* cx, unsigned argc, Value* vp) { +static bool IsCollectingDelazifications(JSContext* cx, unsigned argc, + Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { JS_ReportErrorASCII(cx, "The function takes exactly one argument."); @@ -2383,21 +2531,47 @@ static bool IsInStencilCache(JSContext* cx, unsigned argc, Value* vp) { JSFunction* fun = &args[0].toObject().as(); BaseScript* script = fun->baseScript(); - RefPtr ss = script->scriptSource(); - DelazificationCache& cache = DelazificationCache::getSingleton(); - auto guard = cache.isSourceCached(ss); - if (!guard) { + args.rval().setBoolean( + bool(script->sourceObject()->isCollectingDelazifications())); + return true; +} + +static bool IsDelazificationsPopulated(JSContext* cx, unsigned argc, + Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + if (args.length() != 1) { + JS_ReportErrorASCII(cx, "The function takes exactly one argument."); + return false; + } + + if (!args[0].isObject() || !args[0].toObject().is()) { + JS_ReportErrorASCII(cx, "The first argument should be a function."); + return false; + } + + if (fuzzingSafe) { + // When running code concurrently to fill-up the stencil cache, the content + // is not garanteed to be present. args.rval().setBoolean(false); return true; } - StencilContext key(ss, script->extent()); - frontend::CompilationStencil* stencil = cache.lookup(guard, key); + JSFunction* fun = &args[0].toObject().as(); + BaseScript* script = fun->baseScript(); + RefPtr stencils = + script->sourceObject()->maybeGetStencils(); + if (!stencils) { + args.rval().setBoolean(false); + return true; + } + + const frontend::CompilationStencil* stencil = + stencils->getDelazificationFor(script->extent()); args.rval().setBoolean(bool(stencil)); return true; } -static bool WaitForStencilCache(JSContext* cx, unsigned argc, Value* vp) { +static bool WaitForDelazificationOf(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { JS_ReportErrorASCII(cx, "The function takes exactly one argument."); @@ -2412,9 +2586,13 @@ static bool WaitForStencilCache(JSContext* cx, unsigned argc, Value* vp) { JSFunction* fun = &args[0].toObject().as(); BaseScript* script = fun->baseScript(); - RefPtr ss = script->scriptSource(); - DelazificationCache& cache = DelazificationCache::getSingleton(); - StencilContext key(ss, script->extent()); + + if (!script->sourceObject()->isSharingDelazifications()) { + return true; + } + + RefPtr stencils = + script->sourceObject()->maybeGetStencils(); AutoLockHelperThreadState lock; if (!HelperThreadState().isInitialized(lock)) { @@ -2422,18 +2600,10 @@ static bool WaitForStencilCache(JSContext* cx, unsigned argc, Value* vp) { } while (true) { - { - // This capture a Mutex that we have to release before using the wait - // function. - auto guard = cache.isSourceCached(ss); - if (!guard) { - return true; - } - - frontend::CompilationStencil* stencil = cache.lookup(guard, key); - if (stencil) { - break; - } + const frontend::CompilationStencil* stencil = + stencils->getDelazificationFor(script->extent()); + if (stencil) { + break; } HelperThreadState().wait(lock); @@ -2536,18 +2706,27 @@ static bool GCPreserveCode(JSContext* cx, unsigned argc, Value* vp) { #ifdef JS_GC_ZEAL static bool ParseGCZealMode(JSContext* cx, const CallArgs& args, - uint8_t* zeal) { - uint32_t value; - if (!ToUint32(cx, args.get(0), &value)) { + js::gc::GCRuntime::ZealSettings* zeal) { + JSString* modestr = ToString(cx, args.get(0)); + if (!modestr) { return false; } - if (value > uint32_t(gc::ZealMode::Limit)) { - JS_ReportErrorASCII(cx, "gczeal argument out of range"); + UniqueChars mode = EncodeLatin1(cx, modestr); + if (!mode) { + return false; + } + bool invalid; + if (!cx->runtime()->gc.parseZeal(mode.get(), strlen(mode.get()), zeal, + &invalid)) { + js::ReportOutOfMemory(cx); + return false; + } + if (invalid) { + JS_ReportErrorASCII(cx, "invalid gczeal argument"); return false; } - *zeal = static_cast(value); return true; } @@ -2567,19 +2746,24 @@ static bool GCZeal(JSContext* cx, unsigned argc, Value* vp) { return true; } - uint8_t zeal; + js::gc::GCRuntime::ZealSettings zeal; if (!ParseGCZealMode(cx, args, &zeal)) { return false; } - uint32_t frequency = JS::ShellDefaultGCZealFrequency; + Maybe forceFrequency; if (args.length() >= 2) { + uint32_t frequency; if (!ToUint32(cx, args.get(1), &frequency)) { return false; } + forceFrequency.emplace(frequency); + } + + for (auto [mode, frequency] : zeal) { + JS::SetGCZeal(cx, mode, forceFrequency.valueOr(frequency)); } - JS::SetGCZeal(cx, zeal, frequency); args.rval().setUndefined(); return true; } @@ -2593,12 +2777,15 @@ static bool UnsetGCZeal(JSContext* cx, unsigned argc, Value* vp) { return false; } - uint8_t zeal; + js::gc::GCRuntime::ZealSettings zeal; if (!ParseGCZealMode(cx, args, &zeal)) { return false; } - JS::UnsetGCZeal(cx, zeal); + for (auto [mode, _frequency] : zeal) { + JS::UnsetGCZeal(cx, mode); + } + args.rval().setUndefined(); return true; } @@ -2644,6 +2831,7 @@ static bool SelectForGC(JSContext* cx, unsigned argc, Value* vp) { for (unsigned i = 0; i < args.length(); i++) { if (args[i].isObject()) { if (!cx->runtime()->gc.selectForMarking(&args[i].toObject())) { + ReportOutOfMemory(cx); return false; } } @@ -2668,13 +2856,15 @@ static bool VerifyPreBarriers(JSContext* cx, unsigned argc, Value* vp) { } static bool VerifyPostBarriers(JSContext* cx, unsigned argc, Value* vp) { - // This is a no-op since the post barrier verifier was removed. CallArgs args = CallArgsFromVp(argc, vp); + if (args.length()) { RootedObject callee(cx, &args.callee()); ReportUsageErrorASCII(cx, callee, "Too many arguments"); return false; } + + gc::VerifyBarriers(cx->runtime(), gc::PostBarrierVerifier); args.rval().setUndefined(); return true; } @@ -3441,7 +3631,9 @@ static bool NewObjectWithCallHook(JSContext* cx, unsigned argc, Value* vp) { } static constexpr JSClass ObjectWithManyReservedSlotsClass = { - "ObjectWithManyReservedSlots", JSCLASS_HAS_RESERVED_SLOTS(40)}; + "ObjectWithManyReservedSlots", + JSCLASS_HAS_RESERVED_SLOTS(40), +}; static bool NewObjectWithManyReservedSlots(JSContext* cx, unsigned argc, Value* vp) { @@ -3568,6 +3760,8 @@ static bool NewString(JSContext* cx, unsigned argc, Value* vp) { bool wantTwoByte = false; bool forceExternal = false; bool maybeExternal = false; + bool newStringBuffer = false; + bool shareStringBuffer = false; uint32_t capacity = 0; if (args.get(1).isObject()) { @@ -3582,7 +3776,9 @@ static bool NewString(JSContext* cx, unsigned argc, Value* vp) { {BoolSetting{"tenured", &requestTenured}, BoolSetting{"twoByte", &wantTwoByte}, BoolSetting{"external", &forceExternal}, - BoolSetting{"maybeExternal", &maybeExternal}}) { + BoolSetting{"maybeExternal", &maybeExternal}, + BoolSetting{"newStringBuffer", &newStringBuffer}, + BoolSetting{"shareStringBuffer", &shareStringBuffer}}) { if (!JS_GetProperty(cx, options, name, &v)) { return false; } @@ -3610,11 +3806,14 @@ static bool NewString(JSContext* cx, unsigned argc, Value* vp) { heap = requestTenured ? gc::Heap::Tenured : gc::Heap::Default; if (forceExternal || maybeExternal) { wantTwoByte = true; - if (capacity != 0) { - JS_ReportErrorASCII(cx, - "strings cannot be both external and extensible"); - return false; - } + } + unsigned kinds = forceExternal + maybeExternal + (capacity != 0) + + newStringBuffer + shareStringBuffer; + if (kinds > 1) { + JS_ReportErrorASCII(cx, + "external, capacity, and stringBuffer options can " + "not be used at the same time"); + return false; } } @@ -3643,6 +3842,21 @@ static bool NewString(JSContext* cx, unsigned argc, Value* vp) { if (dest && isExternal) { (void)buf.release(); // Ownership was transferred. } + } else if (shareStringBuffer) { + if (!src->isLinear() || !src->asLinear().hasStringBuffer()) { + JS_ReportErrorASCII(cx, "source string must have a string buffer"); + return false; + } + RefPtr buffer = src->asLinear().stringBuffer(); + if (src->hasLatin1Chars()) { + Rooted> owned(cx, std::move(buffer), + len); + dest = + JSLinearString::newValidLength(cx, &owned, heap); + } else { + Rooted> owned(cx, std::move(buffer), len); + dest = JSLinearString::newValidLength(cx, &owned, heap); + } } else { AutoStableStringChars stable(cx); if (!wantTwoByte && src->hasLatin1Chars()) { @@ -3654,7 +3868,32 @@ static bool NewString(JSContext* cx, unsigned argc, Value* vp) { return false; } } - if (capacity) { + if (newStringBuffer) { + auto allocString = [&](const auto* chars) -> JSLinearString* { + using CharT = + std::remove_const_t>; + + if (JSInlineString::lengthFits(len)) { + JS_ReportErrorASCII(cx, "Cannot create small non-inline strings"); + return nullptr; + } + + RefPtr buffer = + mozilla::StringBuffer::Create(chars, len); + if (!buffer) { + ReportOutOfMemory(cx); + return nullptr; + } + + Rooted> owned(cx, std::move(buffer), len); + return JSLinearString::newValidLength(cx, &owned, heap); + }; + if (stable.isLatin1()) { + dest = allocString(stable.latin1Chars()); + } else { + dest = allocString(stable.twoByteChars()); + } + } else if (capacity) { if (capacity < len) { capacity = len; } @@ -3678,8 +3917,7 @@ static bool NewString(JSContext* cx, unsigned argc, Value* vp) { return nullptr; } mozilla::PodCopy(news.get(), chars, len); - Rooted> owned(cx, std::move(news), len, - true); + Rooted> owned(cx, std::move(news), len); return JSLinearString::newValidLength(cx, &owned, heap); }; @@ -3722,6 +3960,7 @@ static bool NewDependentString(JSContext* cx, unsigned argc, Value* vp) { mozilla::Maybe indexEnd; gc::Heap heap = gc::Heap::Default; mozilla::Maybe requiredHeap; + bool suppressContraction = false; if (!ToIndex(cx, args.get(1), &indexStart)) { return false; @@ -3752,6 +3991,10 @@ static bool NewDependentString(JSContext* cx, unsigned argc, Value* vp) { : gc::Heap::Default); heap = *requiredHeap; } + if (!JS_GetProperty(cx, optObj, "suppress-contraction", &v)) { + return false; + } + suppressContraction = ToBoolean(v); } if (indexEnd.isNothing()) { @@ -3767,8 +4010,11 @@ static bool NewDependentString(JSContext* cx, unsigned argc, Value* vp) { return false; } Rooted result( - cx, js::NewDependentString(cx, src, indexStart, *indexEnd - indexStart, - heap)); + cx, js::NewDependentStringForTesting( + cx, src, indexStart, *indexEnd - indexStart, + suppressContraction ? JS::ContractBaseChain::AllowLong + : JS::ContractBaseChain::Contract, + heap)); if (!result) { return false; } @@ -4544,7 +4790,10 @@ static const JSClassOps FinalizeCounterClassOps = { }; static const JSClass FinalizeCounterClass = { - "FinalizeCounter", JSCLASS_FOREGROUND_FINALIZE, &FinalizeCounterClassOps}; + "FinalizeCounter", + JSCLASS_FOREGROUND_FINALIZE, + &FinalizeCounterClassOps, +}; static bool MakeFinalizeObserver(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -4633,7 +4882,7 @@ static bool Terminate(JSContext* cx, unsigned arg, Value* vp) { fprintf(stderr, "terminate called\n"); } - JS_ClearPendingException(cx); + JS::ReportUncatchableException(cx); return false; } @@ -5298,7 +5547,11 @@ class CloneBufferObject : public NativeObject { static bool getCloneBuffer_impl(JSContext* cx, const CallArgs& args) { Rooted obj( cx, &args.thisv().toObject().as()); - MOZ_ASSERT(args.length() == 0); + if (args.length() != 0) { + RootedObject callee(cx, &args.callee()); + ReportUsageErrorASCII(cx, callee, "Too many arguments"); + return false; + } JSStructuredCloneData* data; if (!getData(cx, obj, &data)) { @@ -5338,7 +5591,11 @@ class CloneBufferObject : public NativeObject { const CallArgs& args) { Rooted obj( cx, &args.thisv().toObject().as()); - MOZ_ASSERT(args.length() == 0); + if (args.length() != 0) { + RootedObject callee(cx, &args.callee()); + ReportUsageErrorASCII(cx, callee, "Too many arguments"); + return false; + } JSStructuredCloneData* data; if (!getData(cx, obj, &data)) { @@ -5400,12 +5657,14 @@ const JSClass CloneBufferObject::class_ = { "CloneBuffer", JSCLASS_HAS_RESERVED_SLOTS(CloneBufferObject::NUM_SLOTS) | JSCLASS_FOREGROUND_FINALIZE, - &CloneBufferObjectClassOps}; + &CloneBufferObjectClassOps, +}; const JSPropertySpec CloneBufferObject::props_[] = { JS_PSGS("clonebuffer", getCloneBuffer, setCloneBuffer, 0), JS_PSGS("arraybuffer", getCloneBufferAsArrayBuffer, setCloneBuffer, 0), - JS_PS_END}; + JS_PS_END, +}; static mozilla::Maybe ParseCloneScope( JSContext* cx, HandleString str) { @@ -5485,8 +5744,10 @@ class CustomSerializableObject : public NativeObject { FailDuringRead = 2 }; - static constexpr JSClass class_ = {"CustomSerializable", - JSCLASS_HAS_RESERVED_SLOTS(NUM_SLOTS)}; + static constexpr JSClass class_ = { + "CustomSerializable", + JSCLASS_HAS_RESERVED_SLOTS(NUM_SLOTS), + }; static bool is(HandleValue v) { return v.isObject() && v.toObject().is(); @@ -6158,7 +6419,8 @@ class ShapeSnapshotObject : public NativeObject { "ShapeSnapshotObject", JSCLASS_HAS_RESERVED_SLOTS(ShapeSnapshotObject::ReservedSlots) | JSCLASS_BACKGROUND_FINALIZE, - &ShapeSnapshotObject::classOps_}; + &ShapeSnapshotObject::classOps_, +}; bool ShapeSnapshot::init(JSObject* obj) { object_ = obj; @@ -7119,7 +7381,7 @@ static bool EvalReturningScope(JSContext* cx, unsigned argc, Value* vp) { JS::AutoFilename filename; uint32_t lineno; - JS::DescribeScriptedCaller(cx, &filename, &lineno); + JS::DescribeScriptedCaller(&filename, cx, &lineno); // CompileOption should be created in the target global's realm. RootedObject global(cx); @@ -7412,26 +7674,29 @@ static bool CompileToStencil(JSContext* cx, uint32_t argc, Value* vp) { } } - AutoReportFrontendContext fc(cx); RefPtr stencil; if (isModule) { - stencil = JS::CompileModuleScriptToStencil(&fc, options, srcBuf); + stencil = JS::CompileModuleScriptToStencil(cx, options, srcBuf); } else { - stencil = JS::CompileGlobalScriptToStencil(&fc, options, srcBuf); + stencil = JS::CompileGlobalScriptToStencil(cx, options, srcBuf); } if (!stencil) { return false; } - if (!SetSourceOptions(cx, &fc, stencil->source, displayURL, sourceMapURL)) { - return false; - } - JS::InstantiationStorage storage; - if (prepareForInstantiate) { - if (!JS::PrepareForInstantiate(&fc, *stencil, storage)) { + { + AutoReportFrontendContext fc(cx); + if (!SetSourceOptions(cx, &fc, stencil->getInitial()->source, displayURL, + sourceMapURL)) { return false; } + + if (prepareForInstantiate) { + if (!JS::PrepareForInstantiate(&fc, *stencil, storage)) { + return false; + } + } } Rooted stencilObj( @@ -7463,7 +7728,7 @@ static bool EvalStencil(JSContext* cx, uint32_t argc, Value* vp) { return false; } - if (stencilObj->stencil()->isModule()) { + if (stencilObj->stencil()->getInitial()->isModule()) { JS_ReportErrorASCII(cx, "evalStencil: Module stencil cannot be evaluated. Use " "instantiateModuleStencil instead"); @@ -7499,7 +7764,7 @@ static bool EvalStencil(JSContext* cx, uint32_t argc, Value* vp) { instantiateOptions.hideScriptFromDebugger = true; } - if (!js::ValidateLazinessOfStencilAndGlobal(cx, *stencilObj->stencil())) { + if (!js::ValidateLazinessOfStencilAndGlobal(cx, stencilObj->stencil())) { return false; } @@ -7575,41 +7840,33 @@ static bool CompileToStencilXDR(JSContext* cx, uint32_t argc, Value* vp) { } } - /* Compile the script text to stencil. */ - AutoReportFrontendContext fc(cx); - frontend::NoScopeBindingCache scopeCache; - Rooted input(cx, - frontend::CompilationInput(options)); - UniquePtr stencil; + RefPtr stencil; if (isModule) { - stencil = frontend::ParseModuleToExtensibleStencil( - cx, &fc, cx->tempLifoAlloc(), input.get(), &scopeCache, srcBuf); + stencil = JS::CompileModuleScriptToStencil(cx, options, srcBuf); } else { - stencil = frontend::CompileGlobalScriptToExtensibleStencil( - cx, &fc, input.get(), &scopeCache, srcBuf, ScopeKind::Global); + stencil = JS::CompileGlobalScriptToStencil(cx, options, srcBuf); } if (!stencil) { return false; } - if (!SetSourceOptions(cx, &fc, stencil->source, displayURL, sourceMapURL)) { - return false; + { + AutoReportFrontendContext fc(cx); + if (!SetSourceOptions(cx, &fc, stencil->getInitial()->source, displayURL, + sourceMapURL)) { + return false; + } } /* Serialize the stencil to XDR. */ JS::TranscodeBuffer xdrBytes; - { - frontend::BorrowingCompilationStencil borrowingStencil(*stencil); - bool succeeded = false; - if (!borrowingStencil.serializeStencils(cx, input.get(), xdrBytes, - &succeeded)) { - return false; - } - if (!succeeded) { - fc.clearAutoReport(); - JS_ReportErrorASCII(cx, "Encoding failure"); - return false; - } + auto result = JS::EncodeStencil(cx, stencil, xdrBytes); + if (result == JS::TranscodeResult::Throw) { + return false; + } + if (JS::IsTranscodeFailureResult(result)) { + JS_ReportErrorASCII(cx, "Encoding failure"); + return false; } Rooted xdrObj( @@ -7665,31 +7922,27 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) { } } - /* Prepare the CompilationStencil for decoding. */ - AutoReportFrontendContext fc(cx); - frontend::CompilationStencil stencil(nullptr); - - /* Deserialize the stencil from XDR. */ JS::TranscodeRange xdrRange(xdrObj->buffer(), xdrObj->bufferLength()); - bool succeeded = false; - if (!stencil.deserializeStencils(&fc, options, xdrRange, &succeeded)) { + JS::DecodeOptions decodeOptions(options); + RefPtr stencil; + auto result = + JS::DecodeStencil(cx, decodeOptions, xdrRange, getter_AddRefs(stencil)); + if (result == JS::TranscodeResult::Throw) { return false; } - if (!succeeded) { - fc.clearAutoReport(); + if (JS::IsTranscodeFailureResult(result)) { JS_ReportErrorASCII(cx, "Decoding failure"); return false; } - if (stencil.isModule()) { - fc.clearAutoReport(); + if (stencil->getInitial()->isModule()) { JS_ReportErrorASCII(cx, "evalStencilXDR: Module stencil cannot be evaluated. " "Use instantiateModuleStencilXDR instead"); return false; } - if (!js::ValidateLazinessOfStencilAndGlobal(cx, stencil)) { + if (!js::ValidateLazinessOfStencilAndGlobal(cx, stencil.get())) { return false; } @@ -7700,7 +7953,7 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) { instantiateOptions.hideScriptFromDebugger = true; } RootedScript script( - cx, JS::InstantiateGlobalStencil(cx, instantiateOptions, &stencil)); + cx, JS::InstantiateGlobalStencil(cx, instantiateOptions, stencil.get())); if (!script) { return false; } @@ -7787,7 +8040,9 @@ class AllocationMarkerObject : public NativeObject { static const JSClass class_; }; -const JSClass AllocationMarkerObject::class_ = {"AllocationMarker"}; +const JSClass AllocationMarkerObject::class_ = { + "AllocationMarker", +}; static bool AllocationMarker(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -7970,6 +8225,15 @@ static bool EnqueueMark(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); gc::GCRuntime* gc = &cx->runtime()->gc; + if (gc->isIncrementalGCInProgress() && + gc->hasZealMode(gc::ZealMode::IncrementalMarkingValidator)) { + JS_ReportErrorASCII( + cx, + "Can't add to test mark queue during incremental GC if marking " + "validation is enabled as this can cause failures"); + return false; + } + if (args.get(0).isString()) { RootedString val(cx, args[0].toString()); if (!val->ensureLinear(cx)) { @@ -8594,6 +8858,21 @@ static bool GetFuseState(JSContext* cx, unsigned argc, Value* vp) { return false; } + fuseObj = JS_NewPlainObject(cx); + if (!fuseObj) { + return false; + } + intactValue.setBoolean( + cx->runtime()->hasSeenArrayExceedsInt32LengthFuse.ref().intact()); + if (!JS_DefineProperty(cx, fuseObj, "intact", intactValue, + JSPROP_ENUMERATE)) { + return false; + } + if (!JS_DefineProperty(cx, returnObj, "hasSeenArrayExceedsInt32LengthFuse", + fuseObj, JSPROP_ENUMERATE)) { + return false; + } + args.rval().setObject(*returnObj); return true; } @@ -9012,6 +9291,10 @@ static bool BaselineCompile(JSContext* cx, unsigned argc, Value* vp) { } AutoRealm ar(cx, script); + if (script->isBaselineCompilingOffThread()) { + CancelOffThreadBaselineCompile(script); + } + if (script->hasBaselineScript()) { if (forceDebug && !script->baselineScript()->hasDebugInstrumentation()) { // There isn't an easy way to do this for a script that might be on @@ -9038,7 +9321,12 @@ static bool BaselineCompile(JSContext* cx, unsigned argc, Value* vp) { return false; } - jit::MethodStatus status = jit::BaselineCompile(cx, script, forceDebug); + jit::BaselineOptions options = { + jit::BaselineOption::ForceMainThreadCompilation}; + if (forceDebug) { + options.setFlag(jit::BaselineOption::ForceDebugInstrumentation); + } + jit::MethodStatus status = jit::BaselineCompile(cx, script, options); switch (status) { case jit::Method_Error: return false; @@ -9180,6 +9468,8 @@ static bool GetAvailableLocalesOf(JSContext* cx, unsigned argc, Value* vp) { kind = SupportedLocaleKind::DateTimeFormat; } else if (StringEqualsLiteral(typeStr, "DisplayNames")) { kind = SupportedLocaleKind::DisplayNames; + } else if (StringEqualsLiteral(typeStr, "DurationFormat")) { + kind = SupportedLocaleKind::DurationFormat; } else if (StringEqualsLiteral(typeStr, "ListFormat")) { kind = SupportedLocaleKind::ListFormat; } else if (StringEqualsLiteral(typeStr, "NumberFormat")) { @@ -9333,6 +9623,19 @@ static bool NukeCCW(JSContext* cx, unsigned argc, Value* vp) { return true; } +static bool IsCCW(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() != 1 || !args[0].isObject()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INVALID_ARGS, + "IsCCW"); + return false; + } + + args.rval().setBoolean(IsCrossCompartmentWrapper(&args[0].toObject())); + return true; +} + static bool FdLibM_Pow(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -9356,6 +9659,41 @@ static bool FdLibM_Pow(JSContext* cx, unsigned argc, Value* vp) { return true; } +static bool HadOutOfMemory(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + args.rval().setBoolean(cx->runtime()->hadOutOfMemory); + return true; +} + +static bool WaitForDone(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + if (args.length() != 1) { + JS_ReportErrorASCII(cx, "The function takes exactly one argument."); + return false; + } + + if (!args[0].isObject()) { + JS_ReportErrorASCII(cx, "The first argument should be an object."); + return false; + } + + RootedObject obj(cx, &args[0].toObject()); + RootedValue val(cx); + if (!JS_GetProperty(cx, obj, "done", &val)) { + return false; + } + + args.rval().setUndefined(); + + while (!val.isBoolean() || !val.toBoolean()) { + js::RunJobs(cx); + if (!JS_GetProperty(cx, obj, "done", &val)) { + return false; + } + } + return true; +} + // clang-format off static const JSFunctionSpecWithHelp TestingFunctions[] = { JS_FN_HELP("gc", ::GC, 0, 0, @@ -9380,6 +9718,10 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { "gcparam(name [, value])", " Wrapper for JS_[GS]etGCParameter. The name is one of:" GC_PARAMETER_ARGS_LIST), + JS_FN_HELP("finishBackgroundFree", FinishBackgroundFree, 0, 0, +"finishBackgroundFree()", +" Wait for the GC's background free task to finish.\n"), + JS_FN_HELP("hasDisassembler", HasDisassembler, 0, 0, "hasDisassembler()", " Return true if a disassembler is present (for disnative and wasmDis)."), @@ -9388,6 +9730,10 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { "disnative(fun,[path])", " Disassemble a function into its native code. Optionally write the native code bytes to a file on disk.\n"), + JS_FN_HELP("disblic", DisassembleBaselineICs, 1, 0, +"disblic(fun)", +" Disassemble the baseline ICs for a function into native code.\n"), + JS_FN_HELP("relazifyFunctions", RelazifyFunctions, 0, 0, "relazifyFunctions(...)", " Perform a GC and allow relazification of functions. Accepts the same\n" @@ -9515,11 +9861,18 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { " input string's characters. Latin1 will be used by default if possible\n" " (again regardless of the input string.)\n" " \n" +" - newStringBuffer: create a new string that uses a refcounted StringBuffer for\n" +" the characters.\n" +" \n" +" - shareStringBuffer: create a new string that shares str's StringBuffer.\n" +" \n" " - external: create an external string. External strings are always twoByte and\n" " tenured.\n" " \n" " - maybeExternal: create an external string, unless the data fits within an\n" -" inline string. Inline strings may be nursery-allocated."), +" inline string. Inline strings may be nursery-allocated.\n" +" \n" +" - capacity: create an extensible string with the given capacity"), JS_FN_HELP("newDependentString", NewDependentString, 2, 0, "newDependentString(str, indexStart[, indexEnd] [, options])", @@ -9528,7 +9881,9 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { " control the heap the string object is allocated into:\n" " \n" " - tenured: if true, allocate in the tenured heap or throw. If false,\n" -" allocate in the nursery or throw."), +" allocate in the nursery or throw.\n" +" - suppress-contraction: prevent the optimization of using a base's base rather\n" +" than creating a chain of dependent string bases."), JS_FN_HELP("ensureLinearString", EnsureLinearString, 1, 0, "ensureLinearString(str)", @@ -9655,8 +10010,8 @@ gc::ZealModeHelpText), JS_FN_HELP("unsetgczeal", UnsetGCZeal, 2, 0, "unsetgczeal(mode)", -" Turn off a single zeal mode set with gczeal() and don't finish any ongoing\n" -" collection that may be happening."), +" Turn off the mode or modes given that were set with gczeal() or JS_GC_ZEAL\n" +" and don't finish any ongoing collection that may be happening."), JS_FN_HELP("schedulegc", ScheduleGC, 1, 0, "schedulegc([num])", @@ -9673,7 +10028,7 @@ gc::ZealModeHelpText), JS_FN_HELP("verifypostbarriers", VerifyPostBarriers, 0, 0, "verifypostbarriers()", -" Does nothing (the post-write barrier verifier has been remove)."), +" Enable or disable the post-write barrier verifier."), JS_FN_HELP("currentgc", CurrentGC, 0, 0, "currentgc()", @@ -9826,12 +10181,12 @@ gc::ZealModeHelpText), " virtual memory reservation in order to elide bounds checks on this platform."), JS_FN_HELP("wasmMaxMemoryPages", WasmMaxMemoryPages, 1, 0, -"wasmMaxMemoryPages(indexType)", +"wasmMaxMemoryPages(addressType)", " Returns an int with the maximum number of pages that can be allocated to a memory." -" This is an implementation artifact that does depend on the index type, the hardware," +" This is an implementation artifact that does depend on the address type, the hardware," " the operating system, the build configuration, and flags. The result is constant for" " a given combination of those; there is no guarantee that that size allocation will" -" always succeed, only that it can succeed in principle. The indexType is a string," +" always succeed, only that it can succeed in principle. The addressType is a string," " 'i32' or 'i64'."), #define WASM_FEATURE(NAME, ...) \ @@ -9900,6 +10255,11 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) " executable and not disabled by switches or runtime conditions. At most one\n" " baseline and one optimizing compiler can be available."), + JS_FN_HELP("wasmLazyTieringEnabled", WasmLazyTieringEnabled, 0, 0, +"wasmLazyTieringEnabled()", +" Returns a boolean indicating whether compilation will be performed\n" +" using lazy tiering."), + JS_FN_HELP("wasmBaselineDisabledByFeatures", WasmBaselineDisabledByFeatures, 0, 0, "wasmBaselineDisabledByFeatures()", " If some feature is enabled at compile-time or run-time that prevents baseline\n" @@ -9912,40 +10272,6 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) " from being used then this returns a truthy string describing the features that\n." " are disabling it. Otherwise it returns false."), - JS_FN_HELP("wasmExtractCode", WasmExtractCode, 1, 0, -"wasmExtractCode(module[, tier])", -" Extracts generated machine code from WebAssembly.Module. The tier is a string,\n" -" 'stable', 'best', 'baseline', or 'ion'; the default is 'stable'. If the request\n" -" cannot be satisfied then null is returned. If the request is 'ion' then block\n" -" until background compilation is complete."), - - JS_FN_HELP("wasmDis", WasmDisassemble, 1, 0, -"wasmDis(wasmObject[, options])\n", -" Disassembles generated machine code from an exported WebAssembly function,\n" -" or from all the functions defined in the module or instance, exported and not.\n" -" The `options` is an object with the following optional keys:\n" -" asString: boolean - if true, return a string rather than printing on stderr,\n" -" the default is false.\n" -" tier: string - one of 'stable', 'best', 'baseline', or 'ion'; the default is\n" -" 'stable'.\n" -" kinds: string - if set, and the wasmObject is a module or instance, a\n" -" comma-separated list of the following keys, the default is `Function`:\n" -" Function - functions defined in the module\n" -" InterpEntry - C++-to-wasm stubs\n" -" JitEntry - jitted-js-to-wasm stubs\n" -" ImportInterpExit - wasm-to-C++ stubs\n" -" ImportJitExit - wasm-to-jitted-JS stubs\n" -" all - all kinds, including obscure ones\n"), - - JS_FN_HELP("wasmDumpIon", WasmDumpIon, 2, 0, -"wasmDumpIon(bytecode, funcIndex, [, contents])\n", -"wasmDumpIon(bytecode, funcIndex, [, contents])" -" Returns a dump of compiling a function in the specified module with Ion." -" The `contents` flag controls what is dumped. one of:" -" `mir` | `unopt-mir`: Unoptimized MIR (the default)" -" `opt-mir`: Optimized MIR" -" `lir`: LIR"), - JS_FN_HELP("wasmHasTier2CompilationCompleted", WasmHasTier2CompilationCompleted, 1, 0, "wasmHasTier2CompilationCompleted(module)", " Returns a boolean indicating whether a given module has finished compiled code for tier2. \n" @@ -9960,7 +10286,6 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) "wasmBuiltinI8VecMul()", " Returns a module that implements an i8 vector pairwise multiplication intrinsic."), -#ifdef ENABLE_WASM_GC JS_FN_HELP("wasmGcReadField", WasmGcReadField, 2, 0, "wasmGcReadField(obj, index)", " Gets a field of a WebAssembly GC struct or array."), @@ -9968,7 +10293,6 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) JS_FN_HELP("wasmGcArrayLength", WasmGcArrayLength, 1, 0, "wasmGcArrayLength(arr)", " Gets the length of a WebAssembly GC array."), -#endif // ENABLE_WASM_GC #ifdef ENABLE_WASM_BRANCH_HINTING JS_FN_HELP("wasmParsedBranchHints", WasmParsedBranchHints, 1, 0, @@ -10152,10 +10476,6 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) " element's edge is the node of the i+1'th array element; the destination of\n" " the last array element is implicitly |target|.\n"), - JS_FN_HELP("wasmMetadataAnalysis", wasmMetadataAnalysis, 1, 0, -"wasmMetadataAnalysis(wasmObject)", -" Prints an analysis of the size of metadata on this wasm object.\n"), - JS_FN_HELP("sharedMemoryEnabled", SharedMemoryEnabled, 0, 0, "sharedMemoryEnabled()", " Return true if SharedArrayBuffer and Atomics are enabled"), @@ -10431,6 +10751,10 @@ JS_FN_HELP("isSmallFunction", IsSmallFunction, 1, 0, " Runs the realm's fuse invariant checks -- these will crash on failure. " " Only available in fuzzing or debug builds, so usage should be guarded. "), + JS_FN_HELP("isCCW", IsCCW, 1, 0, +"isCCW(object)", +" Return true if an object is a CCW."), + JS_FN_HELP("popAllFusesInRealm", PopAllFusesInRealm, 0, 0, "popAllFusesInRealm()", " Pops all the fuses in the current realm"), @@ -10443,17 +10767,22 @@ JS_FN_HELP("isSmallFunction", IsSmallFunction, 1, 0, "getPrefValue(name)", " Return the value of the JS pref with the given name."), + JS_FN_HELP("hadOutOfMemory", HadOutOfMemory, 0, 0, +"hadOutOfMemory()", +" Return the runtime's internal hadOutOfMemory flag that is set when\n" +" out of memory is hit with an exception being propagated. "), + JS_FS_HELP_END }; // clang-format on // clang-format off static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = { - JS_FN_HELP("getErrorNotes", GetErrorNotes, 1, 0, +JS_FN_HELP("getErrorNotes", GetErrorNotes, 1, 0, "getErrorNotes(error)", " Returns an array of error notes."), - JS_FN_HELP("setTimeZone", SetTimeZone, 1, 0, +JS_FN_HELP("setTimeZone", SetTimeZone, 1, 0, "setTimeZone(tzname)", " Set the 'TZ' environment variable to the given time zone and applies the new time zone.\n" " The time zone given is validated according to the current environment.\n" @@ -10465,13 +10794,22 @@ JS_FN_HELP("setDefaultLocale", SetDefaultLocale, 1, 0, " An empty string or undefined resets the runtime locale to its default value.\n" " NOTE: The input string is not fully validated, it must be a valid BCP-47 language tag."), -JS_FN_HELP("isInStencilCache", IsInStencilCache, 1, 0, -"isInStencilCache(fun)", -" True if fun is available in the stencil cache."), +JS_FN_HELP("isCollectingDelazifications", IsCollectingDelazifications, 1, 0, +"isCollectingDelazifications(fun)", +" True if script for the function is collecting delazifications."), -JS_FN_HELP("waitForStencilCache", WaitForStencilCache, 1, 0, -"waitForStencilCache(fun)", -" Block main thread execution until the function is made available in the cache."), +JS_FN_HELP("isDelazificationPopulatedFor", IsDelazificationsPopulated, 1, 0, +"isDelazificationPopulatedFor(fun)", +" True if fun is available in the shared stencils."), + +JS_FN_HELP("waitForDelazificationOf", WaitForDelazificationOf, 1, 0, +"waitForDelazificationOf(fun)", +" Block main thread execution until the function is made available in the\n" +" shared stencils. If this function isn't sharing stencils, return immediately."), + +JS_FN_HELP("waitForDone", WaitForDone, 1, 0, +"waitForDone(obj)", +" Loop calling `RunJobs` until the `done` value of `obj` is true"), JS_FN_HELP("getInnerMostEnvironmentObject", GetInnerMostEnvironmentObject, 0, 0, "getInnerMostEnvironmentObject()", @@ -10485,7 +10823,7 @@ JS_FN_HELP("getEnvironmentObjectType", GetEnvironmentObjectType, 1, 0, "getEnvironmentObjectType(env)", " Return a string represents the type of given environment object."), - JS_FN_HELP("shortestPaths", ShortestPaths, 3, 0, +JS_FN_HELP("shortestPaths", ShortestPaths, 3, 0, "shortestPaths(targets, options)", " Return an array of arrays of shortest retaining paths. There is an array of\n" " shortest retaining paths for each object in |targets|. Each element in a path\n" @@ -10496,10 +10834,10 @@ JS_FN_HELP("getEnvironmentObjectType", GetEnvironmentObjectType, 1, 0, " start: The object to start all paths from. If not given, then\n" " the starting point will be the set of GC roots."), - JS_FN_HELP("getFuseState", GetFuseState, 0, 0, - "getFuseState()", - " Return an object describing the calling realm's fuse state, " - "as well as the state of any runtime fuses."), +JS_FN_HELP("getFuseState", GetFuseState, 0, 0, +"getFuseState()", + " Return an object describing the calling realm's fuse state, " + " as well as the state of any runtime fuses."), #if defined(DEBUG) || defined(JS_JITSPEW) JS_FN_HELP("dumpObject", DumpObject, 1, 0, @@ -10521,9 +10859,54 @@ JS_FN_HELP("getEnvironmentObjectType", GetEnvironmentObjectType, 1, 0, JS_FN_HELP("stringRepresentation", GetStringRepresentation, 1, 0, "stringRepresentation(str)", " Return a human-readable description of how the string |str| is represented.\n"), - #endif + JS_FN_HELP("wasmExtractCode", WasmExtractCode, 1, 0, +"wasmExtractCode(module[, tier])", +" Extracts generated machine code from WebAssembly.Module. The tier is a string,\n" +" 'stable', 'best', 'baseline', or 'ion'; the default is 'stable'. If the request\n" +" cannot be satisfied then null is returned. If the request is 'ion' then block\n" +" until background compilation is complete."), + + JS_FN_HELP("wasmDis", WasmDisassemble, 1, 0, +"wasmDis(wasmObject[, options])\n", +" Disassembles generated machine code from an exported WebAssembly function,\n" +" or from all the functions defined in the module or instance, exported and not.\n" +" The `options` is an object with the following optional keys:\n" +" asString: boolean - if true, return a string rather than printing on stderr,\n" +" the default is false.\n" +" tier: string - one of 'stable', 'best', 'baseline', or 'ion'; the default is\n" +" 'stable'.\n" +" kinds: string - if set, and the wasmObject is a module or instance, a\n" +" comma-separated list of the following keys, the default is `Function`:\n" +" Function - functions defined in the module\n" +" InterpEntry - C++-to-wasm stubs\n" +" JitEntry - jitted-js-to-wasm stubs\n" +" ImportInterpExit - wasm-to-C++ stubs\n" +" ImportJitExit - wasm-to-jitted-JS stubs\n" +" all - all kinds, including obscure ones\n"), + + JS_FN_HELP("wasmModuleToText", WasmModuleToText, 1, 0, +"wasmModuleToText(wasmModule[, options])\n", +" Converts a compiled wasm module to the wasm text format.\n"), + + JS_FN_HELP("wasmDumpIon", WasmDumpIon, 2, 0, +"wasmDumpIon(bytecode, funcIndex, [, contents])\n", +"wasmDumpIon(bytecode, funcIndex, [, contents])" +" Returns a dump of compiling a function in the specified module with Ion." +" The `contents` flag controls what is dumped. one of:" +" `mir` | `unopt-mir`: Unoptimized MIR (the default)" +" `opt-mir`: Optimized MIR" +" `lir`: LIR"), + + JS_FN_HELP("wasmFunctionTier", WasmFunctionTier, 1, 0, +"wasmFunctionTier(wasmFunc)\n", +" Returns the best compiled tier for a function. Either 'baseline' or 'optimized'."), + + JS_FN_HELP("wasmMetadataAnalysis", wasmMetadataAnalysis, 1, 0, +"wasmMetadataAnalysis(wasmObject)", +" Prints an analysis of the size of metadata on this wasm object.\n"), + JS_FS_HELP_END }; // clang-format on @@ -10570,7 +10953,7 @@ static const JSFunctionSpecWithHelp FdLibMTestingFunctions[] = { }; // clang-format on -bool js::InitTestingFunctions() { return disasmBuf.init(); } +bool js::InitTestingFunctions() { return disasmPrinter.init(); } bool js::DefineTestingFunctions(JSContext* cx, HandleObject obj, bool fuzzingSafe_, bool disableOOMFunctions_) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.cpp b/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.cpp index 9d4af5897c1..e3f2cab419b 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.cpp @@ -297,9 +297,9 @@ JS::UniqueChars js::StringToLocale(JSContext* cx, JS::Handle callee, return locale; } -bool js::ValidateLazinessOfStencilAndGlobal( - JSContext* cx, const js::frontend::CompilationStencil& stencil) { - if (cx->realm()->behaviors().discardSource() && stencil.canLazilyParse) { +bool js::ValidateLazinessOfStencilAndGlobal(JSContext* cx, + const JS::Stencil* stencil) { + if (cx->realm()->behaviors().discardSource() && stencil->canLazilyParse()) { JS_ReportErrorASCII(cx, "Stencil compiled with with lazy parse option cannot " "be used in a realm with discardSource"); diff --git a/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.h b/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.h index 82225068a14..f49a56b62f7 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.h +++ b/src/third_party/mozjs/extract/js/src/builtin/TestingUtility.h @@ -7,8 +7,9 @@ #ifndef builtin_TestingUtility_h #define builtin_TestingUtility_h -#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle -#include "js/Utility.h" // JS::UniqueChars +#include "js/experimental/JSStencil.h" // JS::Stencil +#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle +#include "js/Utility.h" // JS::UniqueChars struct JSContext; class JSObject; @@ -69,8 +70,8 @@ JSObject* CreateScriptPrivate(JSContext* cx, // Validate the option for lazy-parsing agrees between the current global and // the stencil. -bool ValidateLazinessOfStencilAndGlobal( - JSContext* cx, const frontend::CompilationStencil& stencil); +bool ValidateLazinessOfStencilAndGlobal(JSContext* cx, + const JS::Stencil* stencil); bool ValidateModuleCompileOptions(JSContext* cx, JS::CompileOptions& options); diff --git a/src/third_party/mozjs/extract/js/src/builtin/Tuple.js b/src/third_party/mozjs/extract/js/src/builtin/Tuple.js deleted file mode 100644 index bade1739d00..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/Tuple.js +++ /dev/null @@ -1,711 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -function TupleToArray(obj) { - var len = TupleLength(obj); - var items = std_Array(len); - - for (var k = 0; k < len; k++) { - DefineDataProperty(items, k, obj[k]); - } - return items; -} - -// proposal-record-tuple -// Tuple.prototype.toSorted() -function TupleToSorted(comparefn) { - /* Step 1. */ - if (comparefn !== undefined && !IsCallable(comparefn)) { - ThrowTypeError(JSMSG_BAD_SORT_ARG); - } - - /* Step 2. */ - var T = ThisTupleValue(this); - - /* Step 3. */ - var items = TupleToArray(T); - var sorted = callFunction(std_Array_sort, items, comparefn); - return std_Tuple_unchecked(sorted); -} - -// proposal-record-tuple -// Tuple.prototype.toSpliced() -function TupleToSpliced(start, deleteCount /*, ...items */) { - /* Steps 1-2. */ - var list = ThisTupleValue(this); - - /* Step 3. */ - var len = TupleLength(list); - - /* Step 4. */ - var relativeStart = ToInteger(start); - - /* Step 5. */ - var actualStart; - if (relativeStart < 0) { - actualStart = std_Math_max(len + relativeStart, 0); - } else { - actualStart = std_Math_min(relativeStart, len); - } - - /* Step 6. */ - var insertCount; - var actualDeleteCount; - if (ArgumentsLength() === 0) { - insertCount = 0; - actualDeleteCount = 0; - } else if (ArgumentsLength() === 1) { - /* Step 7. */ - insertCount = 0; - actualDeleteCount = len - actualStart; - } else { - /* Step 8a. */ - insertCount = ArgumentsLength() - 2; - /* Step 8b. */ - var dc = ToInteger(deleteCount); - /* Step 8c. */ - actualDeleteCount = std_Math_min(std_Math_max(dc, 0), len - actualStart); - } - - /* Step 9. */ - if (len + insertCount - actualDeleteCount > MAX_NUMERIC_INDEX) { - ThrowTypeError(JSMSG_TOO_LONG_ARRAY); - } - - /* Step 10. */ - var k = 0; - /* Step 11. */ - /* Step 12. */ - var itemCount = insertCount; - - /* Step 13. */ - var newList = []; - - /* Step 14. */ - while (k < actualStart) { - /* Step 14a. */ - var E = list[k]; - /* Step 14b. */ - DefineDataProperty(newList, k, E); - /* Step 14c. */ - k++; - } - - /* Step 15. */ - var itemK = 0; - /* Step 16. */ - while (itemK < itemCount) { - /* Step 16a. */ - var E = GetArgument(itemK + 2); - /* Step 16b. */ - if (IsObject(E)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - /* Step 16c. */ - DefineDataProperty(newList, k, E); - /* Step 16d. */ - k++; - itemK++; - } - - /* Step 17. */ - itemK = actualStart + actualDeleteCount; - /* Step 18. */ - while (itemK < len) { - /* Step 18a. */ - var E = list[itemK]; - /* Step 18b. */ - DefineDataProperty(newList, k, E); - /* Step 18c. */ - k++; - itemK++; - } - - /* Step 19. */ - return std_Tuple_unchecked(newList); -} - -// proposal-record-tuple -// Tuple.prototype.toReversed() -function TupleToReversed() { - /* Step 1. */ - var T = ThisTupleValue(this); - - /* Step 2 not necessary */ - - /* Step 3. */ - var len = TupleLength(T); - var newList = []; - - /* Step 4. */ - for (var k = len - 1; k >= 0; k--) { - /* Step 5a. */ - var E = T[k]; - /* Step 5b. */ - DefineDataProperty(newList, len - k - 1, E); - } - - /* Step 5. */ - return std_Tuple_unchecked(newList); -} - -// ES 2017 draft (April 8, 2016) 22.1.3.1.1 -function IsConcatSpreadable(O) { - // Step 1. - if (!IsObject(O) && !IsTuple(O)) { - return false; - } - - // Step 2. - var spreadable = O[GetBuiltinSymbol("isConcatSpreadable")]; - - // Step 3. - if (spreadable !== undefined) { - return ToBoolean(spreadable); - } - - if (IsTuple(O)) { - return true; - } - - // Step 4. - return IsArray(O); -} - -// proposal-record-tuple -// Tuple.prototype.concat() -function TupleConcat() { - /* Step 1 */ - var T = ThisTupleValue(this); - /* Step 2 (changed to include all elements from T). */ - var list = TupleToArray(T); - /* Step 3 */ - var n = list.length; - /* Step 4 not necessary due to changed step 2. */ - /* Step 5 */ - for (var i = 0; i < ArgumentsLength(); i++) { - /* Step 5a. */ - var E = GetArgument(i); - /* Step 5b. */ - var spreadable = IsConcatSpreadable(E); - /* Step 5c. */ - if (spreadable) { - /* Step 5c.i. */ - var k = 0; - /* Step 5c.ii */ - var len = ToLength(E.length); - /* Step 5c.iii */ - if (n + len > MAX_NUMERIC_INDEX) { - ThrowTypeError(JSMSG_TOO_LONG_ARRAY); - } - /* Step 5c.iv */ - while (k < len) { - /* Step 5c.iv.2 */ - var exists = E[k] !== undefined; - /* Step 5c.iv.3 */ - if (exists) { - /* Step 5c.iv.3.a */ - var subElement = E[k]; - /* Step 5c.iv.3.b */ - if (IsObject(subElement)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - /* Step 5c.iv.3.c */ - DefineDataProperty(list, n, subElement); - /* Step 5c.iv.4 */ - n++; - } - /* Step 5c.iv.5 */ - k++; - } - } else { - /* Step 5d. */ - /* Step 5d.ii. */ - if (n >= MAX_NUMERIC_INDEX) { - ThrowTypeError(JSMSG_TOO_LONG_ARRAY); - } - /* Step 5d.iii. */ - if (IsObject(E)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - /* Step 5d.iv. */ - DefineDataProperty(list, n, E); - /* Step 5d.v. */ - n++; - } - } - /* Step 6 */ - return std_Tuple_unchecked(list); -} - -// proposal-record-tuple -// Tuple.prototype.includes() -function TupleIncludes(valueToFind /* , fromIndex */) { - var fromIndex = ArgumentsLength() > 1 ? GetArgument(1) : undefined; - return callFunction( - std_Array_includes, - ThisTupleValue(this), - valueToFind, - fromIndex - ); -} - -// proposal-record-tuple -// Tuple.prototype.indexOf() -function TupleIndexOf(valueToFind /* , fromIndex */) { - var fromIndex = ArgumentsLength() > 1 ? GetArgument(1) : undefined; - return callFunction( - std_Array_indexOf, - ThisTupleValue(this), - valueToFind, - fromIndex - ); -} - -// proposal-record-tuple -// Tuple.prototype.join() -function TupleJoin(separator) { - var T = ThisTupleValue(this); - - // Step 2 - var len = TupleLength(T); - - // Steps 3-4 - var sep = ","; - if (!IsNullOrUndefined(separator)) { - var toString = IsCallable(separator.toString) - ? separator.toString - : std_Object_toString; - sep = callContentFunction(toString, separator); - } - - // Step 5 - var R = ""; - - // Step 6 - var k = 0; - - // Step 7 - while (k < len) { - // Step 7a - if (k > 0) { - R += sep; - } - // Step 7b - var element = T[k]; - // Step 7c - var next = ""; - if (!IsNullOrUndefined(element)) { - var toString = IsCallable(element.toString) - ? element.toString - : std_Object_toString; - next = callContentFunction(toString, element); - } - // Step 7d - R += next; - // Step 7e - k++; - } - // Step 8 - return R; -} - -// proposal-record-tuple -// Tuple.prototype.lastIndexOf() -function TupleLastIndexOf(valueToFind /* , fromIndex */) { - if (ArgumentsLength() < 2) { - return callFunction( - std_Array_lastIndexOf, - ThisTupleValue(this), - valueToFind - ); - } - return callFunction( - std_Array_lastIndexOf, - ThisTupleValue(this), - valueToFind, - GetArgument(1) - ); -} - -// proposal-record-tuple -// Tuple.prototype.toString() -function TupleToString() { - /* Step 1. */ - var T = ThisTupleValue(this); - /* Step 2. */ - var func = T.join; - if (!IsCallable(func)) { - return callFunction(std_Object_toString, T); - } - /* Step 4. */ - return callContentFunction(func, T); -} - -// proposal-record-tuple -// Tuple.prototype.toLocaleString() -function TupleToLocaleString(locales, options) { - var T = ThisTupleValue(this); - return callContentFunction( - ArrayToLocaleString, - TupleToArray(T), - locales, - options - ); -} - -// proposal-record-tuple -// Tuple.prototype.entries() -function TupleEntries() { - return CreateArrayIterator(this, ITEM_KIND_KEY_AND_VALUE); -} - -// proposal-record-tuple -// Tuple.prototype.keys() -function TupleKeys() { - return CreateArrayIterator(this, ITEM_KIND_KEY); -} - -// proposal-record-tuple -// Tuple.prototype.values() -function $TupleValues() { - return CreateArrayIterator(this, ITEM_KIND_VALUE); -} - -SetCanonicalName($TupleValues, "values"); - -// proposal-record-tuple -// Tuple.prototype.every() -function TupleEvery(callbackfn) { - return callContentFunction(ArrayEvery, ThisTupleValue(this), callbackfn); -} - -// proposal-record-tuple -// Tuple.prototype.filter() -function TupleFilter(callbackfn) { - /* Steps 1-2 */ - var list = ThisTupleValue(this); - - /* Step 3. */ - var len = TupleLength(list); - - /* Step 4. */ - if (ArgumentsLength() === 0) { - ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Tuple.prototype.filter"); - } - if (!IsCallable(callbackfn)) { - ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); - } - - /* Step 5. */ - var newList = []; - - /* Step 6. */ - var k = 0; - var newK = 0; - - /* Step 7. */ - var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; - while (k < len) { - /* Step 7a. */ - var kValue = list[k]; - /* Step 7b. */ - var selected = ToBoolean( - callContentFunction(callbackfn, T, kValue, k, list) - ); - /* Step 7c. */ - if (selected) { - /* Step 7c.i. */ - DefineDataProperty(newList, newK++, kValue); - } - /* Step 7d. */ - k++; - } - - /* Step 8. */ - return std_Tuple_unchecked(newList); -} - -// proposal-record-tuple -// Tuple.prototype.find() -function TupleFind(predicate) { - return callContentFunction(ArrayFind, ThisTupleValue(this), predicate); -} - -// proposal-record-tuple -// Tuple.prototype.findIndex() -function TupleFindIndex(predicate) { - return callContentFunction(ArrayFindIndex, ThisTupleValue(this), predicate); -} - -// proposal-record-tuple -// Tuple.prototype.forEach() -function TupleForEach(callbackfn) { - return callContentFunction(ArrayForEach, ThisTupleValue(this), callbackfn); -} - -// proposal-record-tuple -// Tuple.prototype.map() -function TupleMap(callbackfn) { - /* Steps 1-2. */ - var list = ThisTupleValue(this); - - /* Step 3. */ - var len = TupleLength(list); - - /* Step 4. */ - if (!IsCallable(callbackfn)) { - ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); - } - - /* Step 5. */ - var newList = []; - - /* Steps 6-7. */ - var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; - for (var k = 0; k < len; k++) { - /* Step 7a. */ - var kValue = list[k]; - /* Step 7b. */ - var mappedValue = callContentFunction(callbackfn, thisArg, kValue, k, list); - /* Step 7c */ - if (IsObject(mappedValue)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - /* Step 7d. */ - DefineDataProperty(newList, k, mappedValue); - } - - /* Step 8. */ - return std_Tuple_unchecked(newList); -} - -// proposal-record-tuple -// Tuple.prototype.reduce() -function TupleReduce(callbackfn /*, initialVal */) { - if (ArgumentsLength() < 2) { - return callContentFunction(ArrayReduce, ThisTupleValue(this), callbackfn); - } - return callContentFunction( - ArrayReduce, - ThisTupleValue(this), - callbackfn, - GetArgument(1) - ); -} - -// proposal-record-tuple -// Tuple.prototype.reduceRight() -function TupleReduceRight(callbackfn /*, initialVal*/) { - if (ArgumentsLength() < 2) { - return callContentFunction( - ArrayReduceRight, - ThisTupleValue(this), - callbackfn - ); - } - return callContentFunction( - ArrayReduceRight, - ThisTupleValue(this), - callbackfn, - GetArgument(1) - ); -} - -// proposal-record-tuple -// Tuple.prototype.some() -function TupleSome(callbackfn) { - return callContentFunction(ArraySome, ThisTupleValue(this), callbackfn); -} - -function FlattenIntoTuple(target, source, depth) { - /* Step 1. */ - assert(IsArray(target), "FlattenIntoTuple: target is not array"); - - /* Step 2. */ - assert(IsTuple(source), "FlattenIntoTuple: source is not tuple"); - - /* Step 3 not needed. */ - - /* Step 4. */ - var mapperFunction = undefined; - var thisArg = undefined; - var mapperIsPresent = ArgumentsLength() > 3; - if (mapperIsPresent) { - mapperFunction = GetArgument(3); - assert( - IsCallable(mapperFunction) && ArgumentsLength() > 4 && depth === 1, - "FlattenIntoTuple: mapper function must be callable, thisArg present, and depth === 1" - ); - thisArg = GetArgument(4); - } - - /* Step 5. */ - var sourceIndex = 0; - - /* Step 6. */ - for (var k = 0; k < source.length; k++) { - var element = source[k]; - /* Step 6a. */ - if (mapperIsPresent) { - /* Step 6a.i. */ - element = callContentFunction( - mapperFunction, - thisArg, - element, - sourceIndex, - source - ); - /* Step 6a.ii. */ - if (IsObject(element)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - } - /* Step 6b. */ - if (depth > 0 && IsTuple(element)) { - FlattenIntoTuple(target, element, depth - 1); - } else { - /* Step 6c.i. */ - var len = ToLength(target.length); - /* Step 6c.ii. */ - if (len > MAX_NUMERIC_INDEX) { - ThrowTypeError(JSMSG_TOO_LONG_ARRAY); - } - /* Step 6c.iii. */ - DefineDataProperty(target, len, element); - } - /* Step 6d. */ - sourceIndex++; - } -} - -// proposal-record-tuple -// Tuple.prototype.flat() -function TupleFlat() { - /* Steps 1-2. */ - var list = ThisTupleValue(this); - - /* Step 3. */ - var depthNum = 1; - - /* Step 4. */ - if (ArgumentsLength() && GetArgument(0) !== undefined) { - depthNum = ToInteger(GetArgument(0)); - } - - /* Step 5. */ - var flat = []; - - /* Step 6. */ - FlattenIntoTuple(flat, list, depthNum); - - /* Step 7. */ - return std_Tuple_unchecked(flat); -} - -// proposal-record-tuple -// Tuple.prototype.flatMap() -function TupleFlatMap(mapperFunction /*, thisArg*/) { - /* Steps 1-2. */ - var list = ThisTupleValue(this); - - /* Step 3. */ - if (ArgumentsLength() === 0) { - ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Tuple.prototype.flatMap"); - } - if (!IsCallable(mapperFunction)) { - ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapperFunction)); - } - - /* Step 4. */ - var flat = []; - - /* Step 5. */ - var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; - FlattenIntoTuple(flat, list, 1, mapperFunction, thisArg); - - /* Step 6. */ - return std_Tuple_unchecked(flat); -} - -function TupleFrom(items /*, mapFn, thisArg */) { - /* Step 1 */ - var mapping; - var mapfn = ArgumentsLength() < 2 ? undefined : GetArgument(1); - var thisArg = ArgumentsLength() < 3 ? undefined : GetArgument(2); - if (mapfn === undefined) { - mapping = false; - } else { - /* Step 2 */ - if (!IsCallable(mapfn)) { - ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, GetArgument(1))); - } - mapping = true; - } - - /* Step 3 */ - var list = []; - - /* Step 4 */ - var k = 0; - - /* Step 5 */ - var usingIterator = GetMethod(items, GetBuiltinSymbol("iterator")); - - /* Step 6 */ - if (usingIterator !== undefined) { - /* Step 6a. */ - var adder = function(value) { - var mappedValue; - /* Step 6a.i */ - if (mapping) { - /* Step 6a.i.1. */ - mappedValue = callContentFunction(mapfn, thisArg, value, k); - } else { - /* Step 6a.ii. */ - mappedValue = value; - } - /* Step 6a.iii. */ - if (IsObject(mappedValue)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - /* Step 6a.iv. */ - DefineDataProperty(list, k, mappedValue); - /* Step 6a.v. */ - k++; - }; - /* Step 6b. */ - for (var nextValue of allowContentIterWith(items, usingIterator)) { - adder(nextValue); - } - /* Step 6c. */ - return std_Tuple_unchecked(list); - } - /* Step 7 */ - /* We assume items is an array-like object */ - /* Step 8 */ - var arrayLike = ToObject(items); - /* Step 9 */ - var len = ToLength(arrayLike.length); - /* Step 10 */ - while (k < len) { - /* Step 10a not necessary */ - /* Step 10b */ - var kValue = arrayLike[k]; - /* Step 10c-d */ - var mappedValue = mapping - ? callContentFunction(mapfn, thisArg, kValue, k) - : kValue; - /* Step 10e */ - if (IsObject(mappedValue)) { - ThrowTypeError(JSMSG_RECORD_TUPLE_NO_OBJECT); - } - /* Step 10f */ - DefineDataProperty(list, k, mappedValue); - /* Step 10g */ - k++; - } - /* Step 11 */ - return std_Tuple_unchecked(list); -} diff --git a/src/third_party/mozjs/extract/js/src/builtin/TupleObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/TupleObject.cpp deleted file mode 100644 index eb66cb22244..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/TupleObject.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "builtin/TupleObject.h" - -#include "mozilla/Assertions.h" -#include "mozilla/Maybe.h" // mozilla::Maybe - -#include "jsapi.h" - -#include "vm/NativeObject.h" -#include "vm/ObjectOperations.h" -#include "vm/TupleType.h" - -#include "vm/JSObject-inl.h" -#include "vm/NativeObject-inl.h" - -using namespace js; -using mozilla::Maybe; - -// Record and Tuple proposal section 9.2.1 - -TupleObject* TupleObject::create(JSContext* cx, Handle tuple) { - TupleObject* tup = NewBuiltinClassInstance(cx); - if (!tup) { - return nullptr; - } - tup->setFixedSlot(PrimitiveValueSlot, ExtendedPrimitiveValue(*tuple)); - return tup; -} - -// Caller is responsible for rooting the result -TupleType& TupleObject::unbox() const { - return getFixedSlot(PrimitiveValueSlot).toExtendedPrimitive().as(); -} - -// Caller is responsible for rooting the result -mozilla::Maybe TupleObject::maybeUnbox(JSObject* obj) { - Maybe result = mozilla::Nothing(); - if (obj->is()) { - result.emplace(obj->as()); - } else if (obj->is()) { - result.emplace(obj->as().unbox()); - } - return result; -} - -bool js::IsTuple(JSObject& obj) { - return (obj.is() || obj.is()); -} - -// Caller is responsible for rooting the result -mozilla::Maybe js::ThisTupleValue(JSContext* cx, HandleValue val) { - if (!js::IsTuple(val)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_BAD_TUPLE_OBJECT); - return mozilla::Nothing(); - } - Maybe result = mozilla::Nothing(); - result.emplace(TupleType::thisTupleValue(val)); - return (result); -} - -bool tup_mayResolve(const JSAtomState&, jsid id, JSObject*) { - // tup_resolve ignores non-integer ids. - return id.isInt(); -} - -bool tup_resolve(JSContext* cx, HandleObject obj, HandleId id, - bool* resolvedp) { - RootedValue value(cx); - *resolvedp = obj->as().unbox().getOwnProperty(id, &value); - - if (*resolvedp) { - static const unsigned TUPLE_ELEMENT_ATTRS = - JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; - return DefineDataProperty(cx, obj, id, value, - TUPLE_ELEMENT_ATTRS | JSPROP_RESOLVING); - } - - return true; -} - -const JSClassOps TupleObjectClassOps = { - nullptr, // addProperty - nullptr, // delProperty - nullptr, // enumerate - nullptr, // newEnumerate - tup_resolve, // resolve - tup_mayResolve, // mayResolve - nullptr, // finalize - nullptr, // call - nullptr, // construct - nullptr, // trace -}; - -const JSClass TupleObject::class_ = { - "TupleObject", - JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | - JSCLASS_HAS_CACHED_PROTO(JSProto_Tuple), - &TupleObjectClassOps}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/TupleObject.h b/src/third_party/mozjs/extract/js/src/builtin/TupleObject.h deleted file mode 100644 index 54875b8ba99..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/TupleObject.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef builtin_TupleObject_h -#define builtin_TupleObject_h - -#include "vm/NativeObject.h" -#include "vm/TupleType.h" - -namespace js { - -[[nodiscard]] mozilla::Maybe ThisTupleValue(JSContext* cx, - HandleValue val); - -class TupleObject : public NativeObject { - enum { PrimitiveValueSlot, SlotCount }; - - public: - static const JSClass class_; - - static TupleObject* create(JSContext* cx, Handle tuple); - - JS::TupleType& unbox() const; - - static mozilla::Maybe maybeUnbox(JSObject* obj); -}; - -bool IsTuple(JSObject& obj); -} // namespace js - -#endif diff --git a/src/third_party/mozjs/extract/js/src/builtin/TypedArray.js b/src/third_party/mozjs/extract/js/src/builtin/TypedArray.js index 7c3f585280d..aaf72f3797e 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/TypedArray.js +++ b/src/third_party/mozjs/extract/js/src/builtin/TypedArray.js @@ -10,10 +10,10 @@ function ViewedArrayBufferIfReified(tarray) { var buf = UnsafeGetReservedSlot(tarray, JS_TYPEDARRAYLAYOUT_BUFFER_SLOT); assert( buf === false || - buf === true || - (IsObject(buf) && - (GuardToArrayBuffer(buf) !== null || - GuardToSharedArrayBuffer(buf) !== null)), + buf === true || + (IsObject(buf) && + (GuardToArrayBuffer(buf) !== null || + GuardToSharedArrayBuffer(buf) !== null)), "unexpected value in buffer slot" ); return IsObject(buf) ? buf : null; @@ -28,7 +28,7 @@ function IsDetachedBuffer(buffer) { assert( GuardToArrayBuffer(buffer) !== null || - GuardToSharedArrayBuffer(buffer) !== null, + GuardToSharedArrayBuffer(buffer) !== null, "non-ArrayBuffer passed to IsDetachedBuffer" ); @@ -103,7 +103,6 @@ function TypedArraySpeciesConstructor(obj) { // Step 7. if (IsConstructor(s)) { - ReportUsageCounter(s, SUBCLASS_TYPEDARRAY_TYPE_III) return s; } @@ -329,83 +328,6 @@ function TypedArrayEvery(callbackfn /*, thisArg*/) { // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayEvery); -// ES2024 draft rev b643e1d9bdc0e98d238a72f9988c01265306d09f -// Including the changes from . -// -// 23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] ) -function TypedArrayFill(value, start = 0, end = undefined) { - // This function is not generic. - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - value, - start, - end, - "TypedArrayFill" - ); - } - - // Step 1. - var O = this; - - // Step 2. - var buffer = GetAttachedArrayBuffer(this); - - // Step 3. - var len = TypedArrayLength(O); - - // Steps 4-5. - var kind = GetTypedArrayKind(O); - if (kind === TYPEDARRAY_KIND_BIGINT64 || kind === TYPEDARRAY_KIND_BIGUINT64) { - value = ToBigInt(value); - } else { - value = ToNumber(value); - } - - // Step 6. - var relativeStart = ToInteger(start); - - // Steps 7-9. - var k = - relativeStart < 0 - ? std_Math_max(len + relativeStart, 0) - : std_Math_min(relativeStart, len); - - // Step 10. - var relativeEnd = end === undefined ? len : ToInteger(end); - - // Steps 11-13. - var final = - relativeEnd < 0 - ? std_Math_max(len + relativeEnd, 0) - : std_Math_min(relativeEnd, len); - - // Steps 14-16. - if (buffer === null) { - // A typed array previously using inline storage may acquire a - // buffer, so we must check with the source. - buffer = ViewedArrayBufferIfReified(O); - } - - if (IsDetachedBuffer(buffer)) { - ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); - } - - len = TypedArrayLength(O); - - // Step 17. - final = std_Math_min(final, len); - - // Step 18. - for (; k < final; k++) { - O[k] = value; - } - - // Step 19. - return O; -} - // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // %TypedArray%.prototype.filter ( callbackfn [ , thisArg ] ) function TypedArrayFilter(callbackfn /*, thisArg*/) { @@ -588,156 +510,6 @@ function TypedArrayForEach(callbackfn /*, thisArg*/) { // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayForEach); -// ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 -// Plus -// 22.2.3.14 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] ) -function TypedArrayIndexOf(searchElement, fromIndex = 0) { - // Step 2. - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - searchElement, - fromIndex, - "TypedArrayIndexOf" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. - var O = this; - - // Step 3. - var len = TypedArrayLength(O); - - // Step 4. - if (len === 0) { - return -1; - } - - // Step 5. - var n = ToInteger(fromIndex); - - // Step 6. - assert(fromIndex !== undefined || n === 0, "ToInteger(undefined) is zero"); - - // Reload O.[[ArrayLength]] in case ToInteger() detached or resized the ArrayBuffer. - // This lets us avoid executing the HasProperty operation in step 11.a. - len = std_Math_min(len, TypedArrayLengthZeroOnOutOfBounds(O)); - - assert( - len === 0 || !IsDetachedBuffer(ViewedArrayBufferIfReified(O)), - "TypedArrays with detached buffers have a length of zero" - ); - - // Step 7. - if (n >= len) { - return -1; - } - - // Steps 7-10. - // Steps 7-8 are handled implicitly. - var k; - if (n >= 0) { - // Step 9.a. - k = n; - } else { - // Step 10.a. - k = len + n; - - // Step 10.b. - if (k < 0) { - k = 0; - } - } - - // Step 11. - for (; k < len; k++) { - // Step 11.a (not necessary in our implementation). - assert(k in O, "unexpected missing element"); - - // Steps 11.b.i-iii. - if (O[k] === searchElement) { - return k; - } - } - - // Step 12. - return -1; -} - -// ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 -// Plus -// 22.2.3.15 %TypedArray%.prototype.join ( separator ) -function TypedArrayJoin(separator) { - // Step 2. - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - separator, - "TypedArrayJoin" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. - var O = this; - - // Step 3. - var len = TypedArrayLength(O); - - // Steps 4-5. - var sep = separator === undefined ? "," : ToString(separator); - - // Steps 6 and 9. - if (len === 0) { - return ""; - } - - var limit = std_Math_min(len, TypedArrayLengthZeroOnOutOfBounds(O)); - - // ToString() might have detached or resized the underlying ArrayBuffer. To avoid - // checking for this condition when looping in step 8.c, do it once here. - if (limit === 0) { - return callFunction(String_repeat, sep, len - 1); - } - - assert( - !IsDetachedBuffer(ViewedArrayBufferIfReified(O)), - "TypedArrays with detached buffers have a length of zero" - ); - - var element0 = O[0]; - - // Omit the 'if' clause in step 8.c, since typed arrays can't have undefined or null elements. - assert(element0 !== undefined, "unexpected undefined element"); - - // Step 6. - var R = ToString(element0); - - // Steps 7-8. - for (var k = 1; k < limit; k++) { - // Step 8.b. - var element = O[k]; - - // Omit the 'if' clause in step 8.c, since typed arrays can't have undefined or null elements. - assert(element !== undefined, "unexpected undefined element"); - - // Steps 8.a and 8.c-d. - R += sep + ToString(element); - } - - if (limit < len) { - R += callFunction(String_repeat, sep, len - limit); - } - - // Step 9. - return R; -} - // ES6 draft (2016/1/11) 22.2.3.15 %TypedArray%.prototype.keys() function TypedArrayKeys() { // Step 1. @@ -753,72 +525,6 @@ function TypedArrayKeys() { return CreateArrayIterator(O, ITEM_KIND_KEY); } -// ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 -// Plus -// 22.2.3.17 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) -function TypedArrayLastIndexOf(searchElement /*, fromIndex*/) { - // Step 2. - if (!IsObject(this) || !IsTypedArray(this)) { - if (ArgumentsLength() > 1) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - searchElement, - GetArgument(1), - "TypedArrayLastIndexOf" - ); - } - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - searchElement, - "TypedArrayLastIndexOf" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. - var O = this; - - // Step 3. - var len = TypedArrayLength(O); - - // Step 4. - if (len === 0) { - return -1; - } - - // Step 5. - var n = ArgumentsLength() > 1 ? ToInteger(GetArgument(1)) : len - 1; - - // Reload O.[[ArrayLength]] in case ToInteger() detached or resized the ArrayBuffer. - // This lets us avoid executing the HasProperty operation in step 9.a. - len = std_Math_min(len, TypedArrayLengthZeroOnOutOfBounds(O)); - - assert( - len === 0 || !IsDetachedBuffer(ViewedArrayBufferIfReified(O)), - "TypedArrays with detached buffers have a length of zero" - ); - - // Steps 6-8. - var k = n >= 0 ? std_Math_min(n, len - 1) : len + n; - - // Step 9. - for (; k >= 0; k--) { - // Step 9.a (not necessary in our implementation). - assert(k in O, "unexpected missing element"); - - // Steps 9.b.i-iii. - if (O[k] === searchElement) { - return k; - } - } - - // Step 10. - return -1; -} - // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.3.19 %TypedArray%.prototype.map ( callbackfn [ , thisArg ] ) function TypedArrayMap(callbackfn /*, thisArg*/) { @@ -968,50 +674,6 @@ function TypedArrayReduceRight(callbackfn /*, initialValue*/) { return accumulator; } -// ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 -// Plus -// 22.2.3.22 %TypedArray%.prototype.reverse ( ) -function TypedArrayReverse() { - // Step 2. - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - "TypedArrayReverse" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. - var O = this; - - // Step 3. - var len = TypedArrayLength(O); - - // Step 4. - var middle = std_Math_floor(len / 2); - - // Steps 5-6. - for (var lower = 0; lower !== middle; lower++) { - // Step 6.a. - var upper = len - lower - 1; - - // Step 6.d. - var lowerValue = O[lower]; - - // Step 6.e. - var upperValue = O[upper]; - - // Steps 6.f-g. - O[lower] = upperValue; - O[upper] = lowerValue; - } - - // Step 7. - return O; -} - // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.3.24 %TypedArray%.prototype.slice ( start, end ) function TypedArraySlice(start, end) { @@ -1162,7 +824,7 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) { // Steps 6-7. // Omit the 'if' clause in step 6, since non-empty typed arrays can't have // undefined or null elements. -#if JS_HAS_INTL_API + #if JS_HAS_INTL_API var R = ToString( callContentFunction( firstElement.toLocaleString, @@ -1171,11 +833,11 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) { options ) ); -#else + #else var R = ToString( callContentFunction(firstElement.toLocaleString, firstElement) ); -#endif + #endif // Step 3 (reordered). // We don't (yet?) implement locale-dependent separators. @@ -1199,7 +861,7 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) { ); // Steps 9.d-e. -#if JS_HAS_INTL_API + #if JS_HAS_INTL_API R += ToString( callContentFunction( nextElement.toLocaleString, @@ -1208,9 +870,9 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) { options ) ); -#else + #else R += ToString(callContentFunction(nextElement.toLocaleString, nextElement)); -#endif + #endif } // Step 10. @@ -1435,71 +1097,6 @@ function $TypedArrayValues() { } SetCanonicalName($TypedArrayValues, "values"); -// ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 -// Plus -// 22.2.3.13 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] ) -function TypedArrayIncludes(searchElement, fromIndex = 0) { - // Step 2. - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - searchElement, - fromIndex, - "TypedArrayIncludes" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. - var O = this; - - // Step 3. - var len = TypedArrayLength(O); - - // Step 4. - if (len === 0) { - return false; - } - - // Step 5. - var n = ToInteger(fromIndex); - - // Step 6. - assert(fromIndex !== undefined || n === 0, "ToInteger(undefined) is zero"); - - // Steps 7-10. - // Steps 7-8 are handled implicitly. - var k; - if (n >= 0) { - // Step 9.a - k = n; - } else { - // Step 10.a. - k = len + n; - - // Step 10.b. - if (k < 0) { - k = 0; - } - } - - // Step 11. - while (k < len) { - // Steps 11.a-b. - if (SameValueZero(searchElement, O[k])) { - return true; - } - - // Step 11.c. - k++; - } - - // Step 12. - return false; -} - // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ) function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) { @@ -1593,9 +1190,6 @@ function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) { var len = values.length; // Step 7.c. - if (!IsTypedArrayConstructor(C)) { - ReportUsageCounter(C, SUBCLASS_TYPEDARRAY_TYPE_II); - } var targetObj = TypedArrayCreateWithLength(C, len); // Steps 7.d-e. @@ -1631,7 +1225,6 @@ function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) { var len = ToLength(arrayLike.length); // Step 11. - ReportUsageCounter(C, SUBCLASS_TYPEDARRAY_TYPE_II); var targetObj = TypedArrayCreateWithLength(C, len); // Steps 12-13. @@ -1729,123 +1322,6 @@ function IterableToList(items, method) { return values; } -// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 -// 24.1.4.3 ArrayBuffer.prototype.slice ( start, end ) -function ArrayBufferSlice(start, end) { - // Step 1. - var O = this; - - // Steps 2-3, - // This function is not generic. - if (!IsObject(O) || (O = GuardToArrayBuffer(O)) === null) { - return callFunction( - CallArrayBufferMethodIfWrapped, - this, - start, - end, - "ArrayBufferSlice" - ); - } - - // Step 4. - if (IsDetachedBuffer(O)) { - ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); - } - - // Step 5. - var len = ArrayBufferByteLength(O); - - // Step 6. - var relativeStart = ToInteger(start); - - // Step 7. - var first = - relativeStart < 0 - ? std_Math_max(len + relativeStart, 0) - : std_Math_min(relativeStart, len); - - // Step 8. - var relativeEnd = end === undefined ? len : ToInteger(end); - - // Step 9. - var final = - relativeEnd < 0 - ? std_Math_max(len + relativeEnd, 0) - : std_Math_min(relativeEnd, len); - - // Step 10. - var newLen = std_Math_max(final - first, 0); - - // Step 11 - var ctor = SpeciesConstructor(O, GetBuiltinConstructor("ArrayBuffer")); - - // Step 12. - var new_ = constructContentFunction(ctor, ctor, newLen); - - // Steps 13-15. - var isWrapped = false; - var newBuffer; - if ((newBuffer = GuardToArrayBuffer(new_)) !== null) { - // Step 15. - if (IsDetachedBuffer(newBuffer)) { - ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); - } - } else { - newBuffer = new_; - - // Steps 13-14. - if (!IsWrappedArrayBuffer(newBuffer)) { - ThrowTypeError(JSMSG_NON_ARRAY_BUFFER_RETURNED); - } - - isWrapped = true; - - // Step 15. - if ( - callFunction( - CallArrayBufferMethodIfWrapped, - newBuffer, - "IsDetachedBufferThis" - ) - ) { - ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); - } - } - - // Step 16. - if (newBuffer === O) { - ThrowTypeError(JSMSG_SAME_ARRAY_BUFFER_RETURNED); - } - - // Step 17. - var actualLen = PossiblyWrappedArrayBufferByteLength(newBuffer); - if (actualLen < newLen) { - ThrowTypeError(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, newLen, actualLen); - } - - // Steps 18-19. - if (IsDetachedBuffer(O)) { - ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); - } - - // Steps 20-22. - // - // Reacquire the length in case the buffer has been resized. - var currentLen = ArrayBufferByteLength(O); - - if (first < currentLen) { - var count = std_Math_min(newLen, currentLen - first); - ArrayBufferCopyData(newBuffer, 0, O, first, count, isWrapped); - } - - // Step 23. - return newBuffer; -} - -function IsDetachedBufferThis() { - return IsDetachedBuffer(this); -} - // ES 2016 draft Mar 25, 2016 24.1.3.3. function $ArrayBufferSpecies() { // Step 1. @@ -1860,83 +1336,6 @@ function $SharedArrayBufferSpecies() { } SetCanonicalName($SharedArrayBufferSpecies, "get [Symbol.species]"); -// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 -// 24.2.4.3 SharedArrayBuffer.prototype.slice ( start, end ) -function SharedArrayBufferSlice(start, end) { - // Step 1. - var O = this; - - // Steps 2-3. - // This function is not generic. - if (!IsObject(O) || (O = GuardToSharedArrayBuffer(O)) === null) { - return callFunction( - CallSharedArrayBufferMethodIfWrapped, - this, - start, - end, - "SharedArrayBufferSlice" - ); - } - - // Step 4. - var len = SharedArrayBufferByteLength(O); - - // Step 5. - var relativeStart = ToInteger(start); - - // Step 6. - var first = - relativeStart < 0 - ? std_Math_max(len + relativeStart, 0) - : std_Math_min(relativeStart, len); - - // Step 7. - var relativeEnd = end === undefined ? len : ToInteger(end); - - // Step 8. - var final = - relativeEnd < 0 - ? std_Math_max(len + relativeEnd, 0) - : std_Math_min(relativeEnd, len); - - // Step 9. - var newLen = std_Math_max(final - first, 0); - - // Step 10 - var ctor = SpeciesConstructor(O, GetBuiltinConstructor("SharedArrayBuffer")); - - // Step 11. - var new_ = constructContentFunction(ctor, ctor, newLen); - - // Steps 12-13. - var isWrapped = false; - var newObj; - if ((newObj = GuardToSharedArrayBuffer(new_)) === null) { - if (!IsWrappedSharedArrayBuffer(new_)) { - ThrowTypeError(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED); - } - isWrapped = true; - newObj = new_; - } - - // Step 14. - if (newObj === O || SharedArrayBuffersMemorySame(newObj, O)) { - ThrowTypeError(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED); - } - - // Step 15. - var actualLen = PossiblyWrappedSharedArrayBufferByteLength(newObj); - if (actualLen < newLen) { - ThrowTypeError(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, newLen, actualLen); - } - - // Steps 16-18. - SharedArrayBufferCopyData(newObj, 0, O, first, newLen, isWrapped); - - // Step 19. - return newObj; -} - // https://github.com/tc39/proposal-change-array-by-copy function TypedArrayCreateSameType(exemplar, length) { // Step 1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots. @@ -1956,123 +1355,6 @@ function TypedArrayCreateSameType(exemplar, length) { return TypedArrayCreateWithLength(constructor, length); } -// https://github.com/tc39/proposal-change-array-by-copy -// TypedArray.prototype.toReversed() -function TypedArrayToReversed() { - // Step 2. Perform ? ValidateTypedArray(O). - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - "TypedArrayToReversed" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. Let O be the this value. - var O = this; - - // Step 3. Let length be O.[[ArrayLength]]. - var len = TypedArrayLength(O); - - // Step 4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(length) »). - var A = TypedArrayCreateSameType(O, len); - - // Step 5. Let k be 0. - // Step 6. Repeat, while k < length, - for (var k = 0; k < len; k++) { - // Step 5.a. Let from be ! ToString(𝔽(length - k - 1)). - var from = len - k - 1; - // Step 5.b. omitted - Let Pk be ! ToString(𝔽(k)). - // k coerced to String by property access - // Step 5.c. Let fromValue be ! Get(O, from). - var fromValue = O[from]; - // Step 5.d. Perform ! Set(A, k, kValue, true). - A[k] = fromValue; - } - - // Step 7. Return A. - return A; -} - -// https://github.com/tc39/proposal-change-array-by-copy -// TypedArray.prototype.with() -function TypedArrayWith(index, value) { - // Step 2. Perform ? ValidateTypedArray(O). - if (!IsObject(this) || !IsTypedArray(this)) { - return callFunction( - CallTypedArrayMethodIfWrapped, - this, - index, - value, - "TypedArrayWith" - ); - } - - GetAttachedArrayBuffer(this); - - // Step 1. Let O be the this value. - var O = this; - - // Step 3. Let len be O.[[ArrayLength]]. - var len = TypedArrayLength(O); - - // Step 4. Let relativeIndex be ? ToIntegerOrInfinity(index). - var relativeIndex = ToInteger(index); - - var actualIndex; - if (relativeIndex >= 0) { - // Step 5. If relativeIndex ≥ 0, let actualIndex be relativeIndex. - actualIndex = relativeIndex; - } else { - // Step 6. Else, let actualIndex be len + relativeIndex. - actualIndex = len + relativeIndex; - } - - var kind = GetTypedArrayKind(O); - if (kind === TYPEDARRAY_KIND_BIGINT64 || kind === TYPEDARRAY_KIND_BIGUINT64) { - // Step 7. If O.[[ContentType]] is BigInt, set value to ? ToBigInt(value). - value = ToBigInt(value); - } else { - // Step 8. Else, set value to ? ToNumber(value). - value = ToNumber(value); - } - - // Reload the array length in case the underlying buffer has been detached or resized. - var currentLen = TypedArrayLengthZeroOnOutOfBounds(O); - assert( - !IsDetachedBuffer(ViewedArrayBufferIfReified(O)) || currentLen === 0, - "length is set to zero when the buffer has been detached" - ); - - // Step 9. If ! IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception. - // This check is an inlined version of the IsValidIntegerIndex abstract operation. - if (actualIndex < 0 || actualIndex >= currentLen) { - ThrowRangeError(JSMSG_BAD_INDEX); - } - - // Step 10. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). - var A = TypedArrayCreateSameType(O, len); - - // Step 11. Let k be 0. - // Step 12. Repeat, while k < len, - for (var k = 0; k < len; k++) { - // Step 12.a. omitted - Let Pk be ! ToString(𝔽(k)). - // k coerced to String by property access - - // Step 12.b. If k is actualIndex, let fromValue be value. - // Step 12.c. Else, let fromValue be ! Get(O, Pk). - var fromValue = k === actualIndex ? value : O[k]; - - // Step 12.d. Perform ! Set(A, Pk, fromValue, true). - A[k] = fromValue; - } - - // Step 13. - return A; -} - // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted // 23.2.3.33 %TypedArray%.prototype.toSorted ( comparefn ) function TypedArrayToSorted(comparefn) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/Utilities.js b/src/third_party/mozjs/extract/js/src/builtin/Utilities.js index ef1cb0ea929..dad4e26bb92 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/Utilities.js +++ b/src/third_party/mozjs/extract/js/src/builtin/Utilities.js @@ -114,9 +114,6 @@ function SpeciesConstructor(obj, defaultConstructor) { // Step 7. if (IsConstructor(s)) { - if (s !== ctor) { - ReportUsageCounter(defaultConstructor, SUBCLASSING_DETERMINE_THROUGH_CONSTRUCTOR_TYPE_III); - } return s; } diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakMap.js b/src/third_party/mozjs/extract/js/src/builtin/WeakMap.js index 5e91c5eba69..dc132369dde 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakMap.js +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakMap.js @@ -26,3 +26,53 @@ function WeakMapConstructorInit(iterable) { callContentFunction(adder, map, nextItem[0], nextItem[1]); } } + +#ifdef NIGHTLY_BUILD +/** + * Upsert proposal + * + * WeakMap.prototype.getOrInsertComputed ( key, callbackfn ) + * + * https://tc39.es/proposal-upsert/ + */ +function WeakMapGetOrInsertComputed(key, callbackfn) { + // Step 1. Let M be the this value. + var M = this; + + // Step 2. Perform ? RequireInternalSlot(M, [[WeakMapData]]). + if (!IsObject(M) || (M = GuardToWeakMapObject(M)) === null) { + return callFunction( + CallWeakMapMethodIfWrapped, + this, + key, + callbackfn, + "WeakMapGetOrInsertComputed" + ); + } + + // Step 3. If IsCallable(callbackfn) is false, throw a TypeError exception. + if (!IsCallable(callbackfn)) { + ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); + } + + // Step 4. If CanBeHeldWeakly(key) is false, throw a TypeError exception. + // Step 5. For each Record { [[Key]], [[Value]] } p of M.[[WeakMapData]], do + // Step 5.a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, return p.[[Value]]. + if (callFunction(std_WeakMap_has, M, key)) { + return callFunction(std_WeakMap_get, M, key); + } + + // Step 6. Let value be ? Call(callbackfn, undefined, « key »). + var value = callContentFunction(callbackfn, undefined, key); + + // Step 7. For each Record { [[Key]], [[Value]] } p of M.[[WeakMapData]], do + // Step 7.a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, then + // Step 7.a.i. Set p.[[Value]] to value. + // Step 8. Let p be the Record { [[Key]]: key, [[Value]]: value }. + // Step 9. Append p to M.[[WeakMapData]]. + callFunction(std_WeakMap_set, M, key, value); + + // Step 7.a.ii, 10. Return value. + return value; +} +#endif // #ifdef NIGHTLY_BUILD diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject-inl.h b/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject-inl.h index 3c5f2ceb27f..176019b9bb1 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject-inl.h +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject-inl.h @@ -27,20 +27,24 @@ static bool TryPreserveReflector(JSContext* cx, HandleObject obj) { return true; } -static MOZ_ALWAYS_INLINE bool WeakCollectionPutEntryInternal( +static MOZ_ALWAYS_INLINE bool EnsureObjectHasWeakMap( + JSContext* cx, WeakCollectionObject* obj) { + if (obj->getMap()) { + return true; + } + auto newMap = cx->make_unique(cx, obj); + if (!newMap) { + return false; + } + ValueValueWeakMap* map = newMap.release(); + InitReservedSlot(obj, WeakCollectionObject::DataSlot, map, + MemoryUse::WeakMapObject); + return true; +} + +static MOZ_ALWAYS_INLINE bool PreserveReflectorAndAssertValidEntry( JSContext* cx, Handle obj, HandleValue key, HandleValue value) { - ValueValueWeakMap* map = obj->getMap(); - if (!map) { - auto newMap = cx->make_unique(cx, obj.get()); - if (!newMap) { - return false; - } - map = newMap.release(); - InitReservedSlot(obj, WeakCollectionObject::DataSlot, map, - MemoryUse::WeakMapObject); - } - if (key.isObject()) { RootedObject keyObj(cx, &key.toObject()); @@ -62,7 +66,21 @@ static MOZ_ALWAYS_INLINE bool WeakCollectionPutEntryInternal( gc::ToMarkable(value)->zoneFromAnyThread()->isAtomsZone()); MOZ_ASSERT_IF(value.isObject(), value.toObject().compartment() == obj->compartment()); - if (!map->put(key, value)) { + return true; +} + +static MOZ_ALWAYS_INLINE bool WeakCollectionPutEntryInternal( + JSContext* cx, Handle obj, HandleValue key, + HandleValue value) { + if (!EnsureObjectHasWeakMap(cx, obj)) { + return false; + } + + if (!PreserveReflectorAndAssertValidEntry(cx, obj, key, value)) { + return false; + } + + if (!obj->getMap()->put(key, value)) { JS_ReportOutOfMemory(cx); return false; } diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.cpp index a9d7dcdedc3..ac3aa6b3434 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.cpp @@ -16,6 +16,7 @@ #include "vm/JSContext.h" #include "vm/SelfHosting.h" +#include "builtin/MapObject-inl.h" #include "gc/GCContext-inl.h" #include "gc/WeakMap-inl.h" #include "vm/NativeObject-inl.h" @@ -117,21 +118,32 @@ bool WeakMapObject::delete_(JSContext* cx, unsigned argc, Value* vp) { cx, args); } +static bool EnsureValidWeakMapKey(JSContext* cx, Handle keyVal) { + if (MOZ_UNLIKELY(!CanBeHeldWeakly(cx, keyVal))) { + unsigned errorNum = GetErrorNumber(true); + ReportValueError(cx, errorNum, JSDVG_IGNORE_STACK, keyVal, nullptr); + return false; + } + return true; +} + +static bool SetWeakMapEntryImpl(JSContext* cx, Handle mapObj, + Handle keyVal, Handle value) { + if (!EnsureValidWeakMapKey(cx, keyVal)) { + return false; + } + return WeakCollectionPutEntryInternal(cx, mapObj, keyVal, value); +} + /* static */ MOZ_ALWAYS_INLINE bool WeakMapObject::set_impl( JSContext* cx, const CallArgs& args) { MOZ_ASSERT(WeakMapObject::is(args.thisv())); - if (!CanBeHeldWeakly(cx, args.get(0))) { - unsigned errorNum = GetErrorNumber(true); - ReportValueError(cx, errorNum, JSDVG_IGNORE_STACK, args.get(0), nullptr); - return false; - } - Rooted map(cx, &args.thisv().toObject().as()); - - if (!WeakCollectionPutEntryInternal(cx, map, args[0], args.get(1))) { + if (!SetWeakMapEntryImpl(cx, map, args.get(0), args.get(1))) { return false; } + args.rval().set(args.thisv()); return true; } @@ -143,6 +155,49 @@ bool WeakMapObject::set(JSContext* cx, unsigned argc, Value* vp) { args); } +#ifdef NIGHTLY_BUILD +static bool GetOrAddWeakMapEntry(JSContext* cx, Handle mapObj, + Handle key, Handle value, + MutableHandleValue rval) { + if (!EnsureValidWeakMapKey(cx, key)) { + return false; + } + + if (!EnsureObjectHasWeakMap(cx, mapObj)) { + return false; + } + + ValueValueWeakMap* map = mapObj->getMap(); + ValueValueWeakMap::AddPtr addPtr = map->lookupForAdd(key); + if (!addPtr) { + if (!PreserveReflectorAndAssertValidEntry(cx, mapObj, key, value)) { + return false; + } + if (!map->add(addPtr, key, value)) { + JS_ReportOutOfMemory(cx); + return false; + } + } + rval.set(addPtr->value()); + return true; +} + +/* static */ MOZ_ALWAYS_INLINE bool WeakMapObject::getOrInsert_impl( + JSContext* cx, const CallArgs& args) { + MOZ_ASSERT(WeakMapObject::is(args.thisv())); + + Rooted map(cx, &args.thisv().toObject().as()); + return GetOrAddWeakMapEntry(cx, map, args.get(0), args.get(1), args.rval()); +} + +/* static */ +bool WeakMapObject::getOrInsert(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} +#endif // #ifdef NIGHTLY_BUILD + size_t WeakCollectionObject::sizeOfExcludingThis( mozilla::MallocSizeOf aMallocSizeOf) { ValueValueWeakMap* map = getMap(); @@ -158,8 +213,7 @@ bool WeakCollectionObject::nondeterministicGetKeys( if (ValueValueWeakMap* map = obj->getMap()) { // Prevent GC from mutating the weakmap while iterating. gc::AutoSuppressGC suppress(cx); - for (ValueValueWeakMap::Base::Range r = map->all(); !r.empty(); - r.popFront()) { + for (ValueValueWeakMap::Range r = map->all(); !r.empty(); r.popFront()) { const auto& key = r.front().key(); MOZ_ASSERT(key.isObject() || key.isSymbol()); JS::ExposeValueToActiveJS(key); @@ -225,9 +279,6 @@ JS_PUBLIC_API bool JS::GetWeakMapEntry(JSContext* cx, HandleObject mapObj, } if (ValueValueWeakMap::Ptr ptr = map->lookup(key)) { - // Read barrier to prevent an incorrectly gray value from escaping the - // weak map. See the comment before UnmarkGrayChildren in gc/Marking.cpp - ExposeValueToActiveJS(ptr->value().get()); rval.set(ptr->value()); } return true; @@ -237,15 +288,54 @@ JS_PUBLIC_API bool JS::SetWeakMapEntry(JSContext* cx, HandleObject mapObj, HandleValue key, HandleValue val) { CHECK_THREAD(cx); cx->check(key, val); - if (!CanBeHeldWeakly(cx, key)) { - unsigned errorNum = GetErrorNumber(true); - ReportValueError(cx, errorNum, JSDVG_IGNORE_STACK, key, nullptr); - return false; + return SetWeakMapEntryImpl(cx, mapObj.as(), key, val); +} + +// static +bool WeakMapObject::tryOptimizeCtorWithIterable(JSContext* cx, + Handle obj, + Handle iterableVal, + bool* optimized) { + MOZ_ASSERT(!iterableVal.isNullOrUndefined()); + MOZ_ASSERT(!*optimized); + + if (!CanOptimizeMapOrSetCtorWithIterable(WeakMapObject::set, + obj, cx)) { + return true; } - Handle rootedMap = mapObj.as(); + if (!iterableVal.isObject()) { + return true; + } + JSObject* iterable = &iterableVal.toObject(); - return WeakCollectionPutEntryInternal(cx, rootedMap, key, val); + // Fast path for `new WeakMap(array)`. + if (IsOptimizableArrayForMapOrSetCtor(iterable, cx)) { + RootedValue keyVal(cx); + RootedValue value(cx); + Rooted array(cx, &iterable->as()); + uint32_t len = array->getDenseInitializedLength(); + + for (uint32_t index = 0; index < len; index++) { + Value element = array->getDenseElement(index); + MOZ_ASSERT(IsPackedArray(&element.toObject())); + + auto* elementArray = &element.toObject().as(); + keyVal.set(elementArray->getDenseElement(0)); + value.set(elementArray->getDenseElement(1)); + MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE)); + MOZ_ASSERT(!value.isMagic(JS_ELEMENTS_HOLE)); + + if (!SetWeakMapEntryImpl(cx, obj, keyVal, value)) { + return false; + } + } + + *optimized = true; + return true; + } + + return true; } /* static */ @@ -262,21 +352,29 @@ bool WeakMapObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - RootedObject obj(cx, NewObjectWithClassProto(cx, proto)); + Rooted obj(cx, + NewObjectWithClassProto(cx, proto)); if (!obj) { return false; } // Steps 5-6, 11. if (!args.get(0).isNullOrUndefined()) { - FixedInvokeArgs<1> args2(cx); - args2[0].set(args[0]); - - RootedValue thisv(cx, ObjectValue(*obj)); - if (!CallSelfHostedFunction(cx, cx->names().WeakMapConstructorInit, thisv, - args2, args2.rval())) { + Handle iterable = args[0]; + bool optimized = false; + if (!tryOptimizeCtorWithIterable(cx, obj, iterable, &optimized)) { return false; } + if (!optimized) { + FixedInvokeArgs<1> args2(cx); + args2[0].set(iterable); + + RootedValue thisv(cx, ObjectValue(*obj)); + if (!CallSelfHostedFunction(cx, cx->names().WeakMapConstructorInit, thisv, + args2, args2.rval())) { + return false; + } + } } args.rval().setObject(*obj); @@ -304,21 +402,38 @@ const ClassSpec WeakMapObject::classSpec_ = { nullptr, WeakMapObject::methods, WeakMapObject::properties, + GenericFinishInit, }; const JSClass WeakMapObject::class_ = { "WeakMap", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap) | JSCLASS_BACKGROUND_FINALIZE, - &WeakCollectionObject::classOps_, &WeakMapObject::classSpec_}; + &WeakCollectionObject::classOps_, + &WeakMapObject::classSpec_, +}; const JSClass WeakMapObject::protoClass_ = { - "WeakMap.prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap), - JS_NULL_CLASS_OPS, &WeakMapObject::classSpec_}; + "WeakMap.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap), + JS_NULL_CLASS_OPS, + &WeakMapObject::classSpec_, +}; const JSPropertySpec WeakMapObject::properties[] = { - JS_STRING_SYM_PS(toStringTag, "WeakMap", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "WeakMap", JSPROP_READONLY), + JS_PS_END, +}; const JSFunctionSpec WeakMapObject::methods[] = { - JS_FN("has", has, 1, 0), JS_FN("get", get, 1, 0), - JS_FN("delete", delete_, 1, 0), JS_FN("set", set, 2, 0), JS_FS_END}; + JS_FN("has", has, 1, 0), + JS_FN("get", get, 1, 0), + JS_FN("delete", delete_, 1, 0), + JS_FN("set", set, 2, 0), +#ifdef NIGHTLY_BUILD + JS_FN("getOrInsert", getOrInsert, 2, 0), + JS_SELF_HOSTED_FN("getOrInsertComputed", "WeakMapGetOrInsertComputed", 2, + 0), +#endif + JS_FS_END, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.h b/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.h index e487b750cbb..7a10ff226f3 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakMapObject.h @@ -36,6 +36,10 @@ class WeakMapObject : public WeakCollectionObject { static const JSClass class_; static const JSClass protoClass_; + [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool get(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool set(JSContext* cx, unsigned argc, Value* vp); + private: static const ClassSpec classSpec_; @@ -44,20 +48,27 @@ class WeakMapObject : public WeakCollectionObject { [[nodiscard]] static bool construct(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool tryOptimizeCtorWithIterable( + JSContext* cx, Handle obj, Handle iterableVal, + bool* optimized); + [[nodiscard]] static MOZ_ALWAYS_INLINE bool is(HandleValue v); [[nodiscard]] static MOZ_ALWAYS_INLINE bool has_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static MOZ_ALWAYS_INLINE bool get_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool get(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static MOZ_ALWAYS_INLINE bool delete_impl(JSContext* cx, const CallArgs& args); [[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static MOZ_ALWAYS_INLINE bool set_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool set(JSContext* cx, unsigned argc, Value* vp); +#ifdef NIGHTLY_BUILD + [[nodiscard]] static MOZ_ALWAYS_INLINE bool getOrInsert_impl( + JSContext* cx, const CallArgs& args); + [[nodiscard]] static bool getOrInsert(JSContext* cx, unsigned argc, + Value* vp); +#endif // #ifdef NIGHTLY_BUILD }; } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakRefObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/WeakRefObject.cpp index d198b6a3a08..6492c91b53b 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakRefObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakRefObject.cpp @@ -160,19 +160,28 @@ const JSClass WeakRefObject::class_ = { "WeakRef", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_HAS_CACHED_PROTO(JSProto_WeakRef) | JSCLASS_FOREGROUND_FINALIZE, - &classOps_, &classSpec_}; + &classOps_, + &classSpec_, +}; const JSClass WeakRefObject::protoClass_ = { // https://tc39.es/proposal-weakrefs/#sec-weak-ref.prototype // https://tc39.es/proposal-weakrefs/#sec-properties-of-the-weak-ref-prototype-object - "WeakRef.prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_WeakRef), - JS_NULL_CLASS_OPS, &classSpec_}; + "WeakRef.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_WeakRef), + JS_NULL_CLASS_OPS, + &classSpec_, +}; const JSPropertySpec WeakRefObject::properties[] = { - JS_STRING_SYM_PS(toStringTag, "WeakRef", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "WeakRef", JSPROP_READONLY), + JS_PS_END, +}; -const JSFunctionSpec WeakRefObject::methods[] = {JS_FN("deref", deref, 0, 0), - JS_FS_END}; +const JSFunctionSpec WeakRefObject::methods[] = { + JS_FN("deref", deref, 0, 0), + JS_FS_END, +}; /* static */ bool WeakRefObject::deref(JSContext* cx, unsigned argc, Value* vp) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.cpp index 3705e942182..f822e5f13e3 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.cpp @@ -13,6 +13,7 @@ #include "vm/JSContext.h" #include "vm/SelfHosting.h" +#include "builtin/MapObject-inl.h" #include "builtin/WeakMapObject-inl.h" #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" @@ -23,23 +24,27 @@ using namespace js; return v.isObject() && v.toObject().is(); } +static bool AddWeakSetEntryImpl(JSContext* cx, Handle setObj, + Handle keyVal) { + if (MOZ_UNLIKELY(!CanBeHeldWeakly(cx, keyVal))) { + unsigned errorNum = GetErrorNumber(false); + ReportValueError(cx, errorNum, JSDVG_IGNORE_STACK, keyVal, nullptr); + return false; + } + + return WeakCollectionPutEntryInternal(cx, setObj, keyVal, TrueHandleValue); +} + // ES2018 draft rev 7a2d3f053ecc2336fc19f377c55d52d78b11b296 // 23.4.3.1 WeakSet.prototype.add ( value ) /* static */ MOZ_ALWAYS_INLINE bool WeakSetObject::add_impl( JSContext* cx, const CallArgs& args) { MOZ_ASSERT(is(args.thisv())); - // Step 4. - if (!CanBeHeldWeakly(cx, args.get(0))) { - unsigned errorNum = GetErrorNumber(false); - ReportValueError(cx, errorNum, JSDVG_IGNORE_STACK, args.get(0), nullptr); - return false; - } - - // Steps 5-7. - RootedValue value(cx, args[0]); - Rooted map(cx, &args.thisv().toObject().as()); - if (!WeakCollectionPutEntryInternal(cx, map, value, TrueHandleValue)) { + // Steps 4-7. + Rooted setObj(cx, + &args.thisv().toObject().as()); + if (!AddWeakSetEntryImpl(cx, setObj, args.get(0))) { return false; } @@ -135,32 +140,79 @@ const ClassSpec WeakSetObject::classSpec_ = { nullptr, WeakSetObject::methods, WeakSetObject::properties, + GenericFinishInit, }; const JSClass WeakSetObject::class_ = { "WeakSet", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet) | JSCLASS_BACKGROUND_FINALIZE, - &WeakCollectionObject::classOps_, &WeakSetObject::classSpec_}; + &WeakCollectionObject::classOps_, + &WeakSetObject::classSpec_, +}; const JSClass WeakSetObject::protoClass_ = { - "WeakSet.prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet), - JS_NULL_CLASS_OPS, &WeakSetObject::classSpec_}; + "WeakSet.prototype", + JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet), + JS_NULL_CLASS_OPS, + &WeakSetObject::classSpec_, +}; const JSPropertySpec WeakSetObject::properties[] = { - JS_STRING_SYM_PS(toStringTag, "WeakSet", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "WeakSet", JSPROP_READONLY), + JS_PS_END, +}; const JSFunctionSpec WeakSetObject::methods[] = { - JS_FN("add", add, 1, 0), JS_FN("delete", delete_, 1, 0), - JS_FN("has", has, 1, 0), JS_FS_END}; + JS_FN("add", add, 1, 0), + JS_FN("delete", delete_, 1, 0), + JS_FN("has", has, 1, 0), + JS_FS_END, +}; WeakSetObject* WeakSetObject::create(JSContext* cx, HandleObject proto /* = nullptr */) { return NewObjectWithClassProto(cx, proto); } -bool WeakSetObject::isBuiltinAdd(HandleValue add) { - return IsNativeFunction(add, WeakSetObject::add); +// static +bool WeakSetObject::tryOptimizeCtorWithIterable(JSContext* cx, + Handle obj, + Handle iterableVal, + bool* optimized) { + MOZ_ASSERT(!iterableVal.isNullOrUndefined()); + MOZ_ASSERT(!*optimized); + + if (!CanOptimizeMapOrSetCtorWithIterable(WeakSetObject::add, + obj, cx)) { + return true; + } + + if (!iterableVal.isObject()) { + return true; + } + JSObject* iterable = &iterableVal.toObject(); + + // Fast path for `new WeakSet(array)`. + if (IsOptimizableArrayForMapOrSetCtor(iterable, cx)) { + RootedValue keyVal(cx); + Rooted array(cx, &iterable->as()); + uint32_t len = array->getDenseInitializedLength(); + + for (uint32_t index = 0; index < len; index++) { + keyVal.set(array->getDenseElement(index)); + MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE)); + + if (!AddWeakSetEntryImpl(cx, obj, keyVal)) { + return false; + } + } + + *optimized = true; + return true; + } + + return true; } bool WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp) { @@ -182,35 +234,14 @@ bool WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp) { } if (!args.get(0).isNullOrUndefined()) { - RootedValue iterable(cx, args[0]); + Handle iterable = args[0]; bool optimized = false; - if (!IsOptimizableInitForSet(cx, obj, iterable, &optimized)) { + if (!tryOptimizeCtorWithIterable(cx, obj, iterable, &optimized)) { return false; } - - if (optimized) { - RootedValue keyVal(cx); - Rooted array(cx, &iterable.toObject().as()); - for (uint32_t index = 0; index < array->getDenseInitializedLength(); - ++index) { - keyVal.set(array->getDenseElement(index)); - MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE)); - - if (!CanBeHeldWeakly(cx, keyVal)) { - unsigned errorNum = GetErrorNumber(false); - ReportValueError(cx, errorNum, JSDVG_IGNORE_STACK, args.get(0), - nullptr); - return false; - } - - if (!WeakCollectionPutEntryInternal(cx, obj, keyVal, TrueHandleValue)) { - return false; - } - } - } else { + if (!optimized) { FixedInvokeArgs<1> args2(cx); - args2[0].set(args[0]); + args2[0].set(iterable); RootedValue thisv(cx, ObjectValue(*obj)); if (!CallSelfHostedFunction(cx, cx->names().WeakSetConstructorInit, thisv, diff --git a/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.h b/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.h index e374ff688bc..20ab668a45f 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.h +++ b/src/third_party/mozjs/extract/js/src/builtin/WeakSetObject.h @@ -16,6 +16,10 @@ class WeakSetObject : public WeakCollectionObject { static const JSClass class_; static const JSClass protoClass_; + [[nodiscard]] static bool add(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); + private: static const ClassSpec classSpec_; @@ -25,19 +29,18 @@ class WeakSetObject : public WeakCollectionObject { static WeakSetObject* create(JSContext* cx, HandleObject proto = nullptr); [[nodiscard]] static bool construct(JSContext* cx, unsigned argc, Value* vp); + [[nodiscard]] static bool tryOptimizeCtorWithIterable( + JSContext* cx, Handle obj, Handle iterableVal, + bool* optimized); + [[nodiscard]] static MOZ_ALWAYS_INLINE bool is(HandleValue v); [[nodiscard]] static MOZ_ALWAYS_INLINE bool add_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool add(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static MOZ_ALWAYS_INLINE bool delete_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp); [[nodiscard]] static MOZ_ALWAYS_INLINE bool has_impl(JSContext* cx, const CallArgs& args); - [[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp); - - static bool isBuiltinAdd(HandleValue add); }; } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/builtin/WrappedFunctionObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/WrappedFunctionObject.cpp index 7b9e0bd263d..6a0ff2e540c 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/WrappedFunctionObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/WrappedFunctionObject.cpp @@ -17,7 +17,7 @@ #include "js/Exception.h" #include "js/TypeDecls.h" #include "js/Value.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/Compartment.h" #include "vm/Interpreter.h" #include "vm/JSFunction.h" diff --git a/src/third_party/mozjs/extract/js/src/builtin/embedjs.py b/src/third_party/mozjs/extract/js/src/builtin/embedjs.py index 685f511e498..989b6cfbff4 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/embedjs.py +++ b/src/third_party/mozjs/extract/js/src/builtin/embedjs.py @@ -148,7 +148,7 @@ def preprocess(cxx, preprocessorOption, source, args=[]): result = subprocess.Popen(cxx + outputArg + args + [tmpIn]).wait() if result != 0: sys.exit(result) - with open(tmpOut, "r") as output: + with open(tmpOut) as output: processed = output.read() os.remove(tmpIn) os.remove(tmpOut) diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/Collator.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/Collator.cpp index 924cfdbdaa7..6ffa3365ce4 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/Collator.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/Collator.cpp @@ -56,7 +56,9 @@ const JSClass CollatorObject::class_ = { JSCLASS_HAS_RESERVED_SLOTS(CollatorObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_Collator) | JSCLASS_FOREGROUND_FINALIZE, - &CollatorObject::classOps_, &CollatorObject::classSpec_}; + &CollatorObject::classOps_, + &CollatorObject::classSpec_, +}; const JSClass& CollatorObject::protoClass_ = PlainObject::class_; @@ -69,15 +71,20 @@ static bool collator_toSource(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec collator_static_methods[] = { JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_Collator_supportedLocalesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec collator_methods[] = { JS_SELF_HOSTED_FN("resolvedOptions", "Intl_Collator_resolvedOptions", 0, 0), - JS_FN("toSource", collator_toSource, 0, 0), JS_FS_END}; + JS_FN("toSource", collator_toSource, 0, 0), + JS_FS_END, +}; static const JSPropertySpec collator_properties[] = { JS_SELF_HOSTED_GET("compare", "$Intl_Collator_compare_get", 0), - JS_STRING_SYM_PS(toStringTag, "Intl.Collator", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "Intl.Collator", JSPROP_READONLY), + JS_PS_END, +}; static bool Collator(JSContext* cx, unsigned argc, Value* vp); @@ -89,7 +96,8 @@ const ClassSpec CollatorObject::classSpec_ = { collator_methods, collator_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /** * 10.1.2 Intl.Collator([ locales [, options]]) diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.cpp index 5c386c4b7e8..0926bd10490 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.cpp @@ -52,10 +52,11 @@ bool js::intl::InitializeDateTimeFormatObject( JSContext* cx, JS::Handle obj, JS::Handle thisValue, JS::Handle locales, JS::Handle options, JS::Handle required, JS::Handle defaults, + JS::Handle toLocaleStringTimeZone, DateTimeFormatOptions dtfOptions, JS::MutableHandle result) { Handle initializer = cx->names().InitializeDateTimeFormat; - FixedInvokeArgs<7> args(cx); + FixedInvokeArgs<8> args(cx); args[0].setObject(*obj); args[1].set(thisValue); @@ -63,7 +64,8 @@ bool js::intl::InitializeDateTimeFormatObject( args[3].set(options); args[4].setString(required); args[5].setString(defaults); - args[6].setBoolean(dtfOptions == DateTimeFormatOptions::EnableMozExtensions); + args[6].set(toLocaleStringTimeZone); + args[7].setBoolean(dtfOptions == DateTimeFormatOptions::EnableMozExtensions); if (!CallSelfHostedFunction(cx, initializer, NullHandleValue, args, result)) { return false; @@ -167,6 +169,10 @@ void js::intl::AddICUCellMemory(JSObject* obj, size_t nbytes) { AddCellMemory(obj, nbytes, MemoryUse::ICUObject); } +void js::intl::RemoveICUCellMemory(JSObject* obj, size_t nbytes) { + RemoveCellMemory(obj, nbytes, MemoryUse::ICUObject); +} + void js::intl::RemoveICUCellMemory(JS::GCContext* gcx, JSObject* obj, size_t nbytes) { gcx->removeCellMemory(obj, nbytes, MemoryUse::ICUObject); diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.h b/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.h index cf7fd4038da..114b0b95b26 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.h @@ -43,6 +43,7 @@ extern bool InitializeDateTimeFormatObject( JSContext* cx, JS::Handle obj, JS::Handle thisValue, JS::Handle locales, JS::Handle options, JS::Handle required, JS::Handle defaults, + JS::Handle toLocaleStringTimeZone, DateTimeFormatOptions dtfOptions, JS::MutableHandle result); /** @@ -101,7 +102,12 @@ constexpr size_t INITIAL_CHAR_BUFFER_SIZE = 32; void AddICUCellMemory(JSObject* obj, size_t nbytes); +void RemoveICUCellMemory(JSObject* obj, size_t nbytes); + void RemoveICUCellMemory(JS::GCContext* gcx, JSObject* obj, size_t nbytes); + +JSLinearString* CanonicalizeTimeZone(JSContext* cx, + JS::Handle timeZone); } // namespace intl } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.js b/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.js index f45b934fa46..e4402bb2e44 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.js +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/CommonFunctions.js @@ -839,6 +839,7 @@ function initializeIntlObject(obj, type, lazyData) { (type === "Collator" && intl_GuardToCollator(obj) !== null) || (type === "DateTimeFormat" && intl_GuardToDateTimeFormat(obj) !== null) || (type === "DisplayNames" && intl_GuardToDisplayNames(obj) !== null) || + (type === "DurationFormat" && intl_GuardToDurationFormat(obj) !== null) || (type === "ListFormat" && intl_GuardToListFormat(obj) !== null) || (type === "NumberFormat" && intl_GuardToNumberFormat(obj) !== null) || (type === "PluralRules" && intl_GuardToPluralRules(obj) !== null) || @@ -856,6 +857,7 @@ function initializeIntlObject(obj, type, lazyData) { // - Collator // - DateTimeFormat // - DisplayNames + // - DurationFormat // - ListFormat // - NumberFormat // - PluralRules @@ -926,6 +928,7 @@ function getIntlObjectInternals(obj) { intl_GuardToCollator(obj) !== null || intl_GuardToDateTimeFormat(obj) !== null || intl_GuardToDisplayNames(obj) !== null || + intl_GuardToDurationFormat(obj) !== null || intl_GuardToListFormat(obj) !== null || intl_GuardToNumberFormat(obj) !== null || intl_GuardToPluralRules(obj) !== null || @@ -944,6 +947,8 @@ function getIntlObjectInternals(obj) { intl_GuardToDateTimeFormat(obj) !== null) || (internals.type === "DisplayNames" && intl_GuardToDisplayNames(obj) !== null) || + (internals.type === "DurationFormat" && + intl_GuardToDurationFormat(obj) !== null) || (internals.type === "ListFormat" && intl_GuardToListFormat(obj) !== null) || (internals.type === "NumberFormat" && @@ -983,6 +988,8 @@ function getInternals(obj) { internalProps = resolveDateTimeFormatInternals(internals.lazyData); } else if (type === "DisplayNames") { internalProps = resolveDisplayNamesInternals(internals.lazyData); + } else if (type === "DurationFormat") { + internalProps = resolveDurationFormatInternals(internals.lazyData); } else if (type === "ListFormat") { internalProps = resolveListFormatInternals(internals.lazyData); } else if (type === "NumberFormat") { diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/CurrencyDataGenerated.js b/src/third_party/mozjs/extract/js/src/builtin/intl/CurrencyDataGenerated.js index dcde0049566..2475eb52864 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/CurrencyDataGenerated.js +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/CurrencyDataGenerated.js @@ -1,5 +1,5 @@ // Generated by make_intl_data.py. DO NOT EDIT. -// Version: 2023-01-01 +// Version: 2025-02-04 /** * Mapping from currency codes to the number of decimal digits used for them. diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.cpp index 00af67ddfd5..e27b9f08184 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.cpp @@ -18,11 +18,24 @@ #include "mozilla/Range.h" #include "mozilla/Span.h" +#include "jsdate.h" + #include "builtin/Array.h" #include "builtin/intl/CommonFunctions.h" #include "builtin/intl/FormatBuffer.h" #include "builtin/intl/LanguageTag.h" #include "builtin/intl/SharedIntlData.h" +#include "builtin/temporal/Calendar.h" +#include "builtin/temporal/Instant.h" +#include "builtin/temporal/PlainDate.h" +#include "builtin/temporal/PlainDateTime.h" +#include "builtin/temporal/PlainMonthDay.h" +#include "builtin/temporal/PlainTime.h" +#include "builtin/temporal/PlainYearMonth.h" +#include "builtin/temporal/Temporal.h" +#include "builtin/temporal/TemporalParser.h" +#include "builtin/temporal/TimeZone.h" +#include "builtin/temporal/ZonedDateTime.h" #include "gc/GCContext.h" #include "js/Date.h" #include "js/experimental/Intl.h" // JS::AddMozDateTimeFormatConstructor @@ -31,6 +44,7 @@ #include "js/PropertyAndElement.h" // JS_DefineFunctions, JS_DefineProperties #include "js/PropertySpec.h" #include "js/StableStringChars.h" +#include "js/Wrapper.h" #include "vm/DateTime.h" #include "vm/GlobalObject.h" #include "vm/JSContext.h" @@ -42,6 +56,7 @@ #include "vm/NativeObject-inl.h" using namespace js; +using namespace js::temporal; using JS::AutoStableStringChars; using JS::ClippedTime; @@ -70,7 +85,9 @@ const JSClass DateTimeFormatObject::class_ = { JSCLASS_HAS_RESERVED_SLOTS(DateTimeFormatObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_DateTimeFormat) | JSCLASS_FOREGROUND_FINALIZE, - &DateTimeFormatObject::classOps_, &DateTimeFormatObject::classSpec_}; + &DateTimeFormatObject::classOps_, + &DateTimeFormatObject::classSpec_, +}; const JSClass& DateTimeFormatObject::protoClass_ = PlainObject::class_; @@ -83,7 +100,8 @@ static bool dateTimeFormat_toSource(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec dateTimeFormat_static_methods[] = { JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_DateTimeFormat_supportedLocalesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec dateTimeFormat_methods[] = { JS_SELF_HOSTED_FN("resolvedOptions", "Intl_DateTimeFormat_resolvedOptions", @@ -94,12 +112,14 @@ static const JSFunctionSpec dateTimeFormat_methods[] = { JS_SELF_HOSTED_FN("formatRangeToParts", "Intl_DateTimeFormat_formatRangeToParts", 2, 0), JS_FN("toSource", dateTimeFormat_toSource, 0, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSPropertySpec dateTimeFormat_properties[] = { JS_SELF_HOSTED_GET("format", "$Intl_DateTimeFormat_format_get", 0), JS_STRING_SYM_PS(toStringTag, "Intl.DateTimeFormat", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; static bool DateTimeFormat(JSContext* cx, unsigned argc, Value* vp); @@ -111,7 +131,8 @@ const ClassSpec DateTimeFormatObject::classSpec_ = { dateTimeFormat_methods, dateTimeFormat_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /** * 12.2.1 Intl.DateTimeFormat([ locales [, options]]) @@ -148,7 +169,7 @@ static bool DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct, // Step 3. return intl::InitializeDateTimeFormatObject( cx, dateTimeFormat, thisValue, locales, options, required, defaults, - dtfOptions, args.rval()); + UndefinedHandleValue, dtfOptions, args.rval()); } static bool DateTimeFormat(JSContext* cx, unsigned argc, Value* vp) { @@ -359,51 +380,69 @@ bool js::intl_IsValidTimeZoneName(JSContext* cx, unsigned argc, Value* vp) { } else { args.rval().setNull(); } - return true; } +JSLinearString* js::intl::CanonicalizeTimeZone(JSContext* cx, + Handle timeZone) { + SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); + + // Some time zone names are canonicalized differently by ICU -- handle those + // first. + Rooted ianaTimeZone(cx); + if (!sharedIntlData.tryCanonicalizeTimeZoneConsistentWithIANA( + cx, timeZone, &ianaTimeZone)) { + return nullptr; + } + + JSLinearString* resultTimeZone; + if (ianaTimeZone) { + cx->markAtom(ianaTimeZone); + resultTimeZone = ianaTimeZone; + } else { + AutoStableStringChars stableChars(cx); + if (!stableChars.initTwoByte(cx, timeZone)) { + return nullptr; + } + + // Call into ICU to canonicalize the time zone. + FormatBuffer canonicalTimeZone(cx); + auto result = mozilla::intl::TimeZone::GetCanonicalTimeZoneID( + stableChars.twoByteRange(), canonicalTimeZone); + if (result.isErr()) { + ReportInternalError(cx, result.unwrapErr()); + return nullptr; + } + + resultTimeZone = canonicalTimeZone.toString(cx); + if (!resultTimeZone) { + return nullptr; + } + } + + MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "Etc/Unknown"), + "Invalid canonical time zone"); + + // Links to UTC are handled by SharedIntlData. + MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "GMT")); + MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "Etc/UTC")); + MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "Etc/GMT")); + + return resultTimeZone; +} + bool js::intl_canonicalizeTimeZone(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 1); MOZ_ASSERT(args[0].isString()); - SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); - - // Some time zone names are canonicalized differently by ICU -- handle - // those first: RootedString timeZone(cx, args[0].toString()); - Rooted ianaTimeZone(cx); - if (!sharedIntlData.tryCanonicalizeTimeZoneConsistentWithIANA( - cx, timeZone, &ianaTimeZone)) { + auto* result = intl::CanonicalizeTimeZone(cx, timeZone); + if (!result) { return false; } - if (ianaTimeZone) { - cx->markAtom(ianaTimeZone); - args.rval().setString(ianaTimeZone); - return true; - } - - AutoStableStringChars stableChars(cx); - if (!stableChars.initTwoByte(cx, timeZone)) { - return false; - } - - FormatBuffer canonicalTimeZone(cx); - auto result = mozilla::intl::TimeZone::GetCanonicalTimeZoneID( - stableChars.twoByteRange(), canonicalTimeZone); - if (result.isErr()) { - intl::ReportInternalError(cx, result.unwrapErr()); - return false; - } - - JSString* str = canonicalTimeZone.toString(cx); - if (!str) { - return false; - } - - args.rval().setString(str); + args.rval().setString(result); return true; } @@ -794,6 +833,438 @@ static bool AssignDateTimeLength( return true; } +enum class Required { Date, Time, YearMonth, MonthDay, Any }; + +enum class Defaults { Date, Time, YearMonth, MonthDay, ZonedDateTime, All }; + +enum class Inherit { All, Relevant }; + +struct DateTimeFormatArgs { + Required required; + Defaults defaults; + Inherit inherit; +}; + +/** + * Get the "required" argument passed to CreateDateTimeFormat. + */ +static bool GetRequired(JSContext* cx, Handle internals, + Required* result) { + Rooted value(cx); + if (!GetProperty(cx, internals, internals, cx->names().required, &value)) { + return false; + } + MOZ_ASSERT(value.isString()); + + JSLinearString* string = value.toString()->ensureLinear(cx); + if (!string) { + return false; + } + + if (StringEqualsLiteral(string, "date")) { + *result = Required::Date; + } else if (StringEqualsLiteral(string, "time")) { + *result = Required::Time; + } else { + MOZ_ASSERT(StringEqualsLiteral(string, "any")); + *result = Required::Any; + } + return true; +} + +/** + * Get the "defaults" argument passed to CreateDateTimeFormat. + */ +static bool GetDefaults(JSContext* cx, Handle internals, + Defaults* result) { + Rooted value(cx); + if (!GetProperty(cx, internals, internals, cx->names().defaults, &value)) { + return false; + } + MOZ_ASSERT(value.isString()); + + JSLinearString* string = value.toString()->ensureLinear(cx); + if (!string) { + return false; + } + + if (StringEqualsLiteral(string, "date")) { + *result = Defaults::Date; + } else if (StringEqualsLiteral(string, "time")) { + *result = Defaults::Time; + } else { + MOZ_ASSERT(StringEqualsLiteral(string, "all")); + *result = Defaults::All; + } + return true; +} + +/** + * Compute the (required, defaults, inherit) arguments passed to + * GetDateTimeFormat. + */ +static bool GetDateTimeFormatArgs(JSContext* cx, Handle internals, + DateTimeValueKind kind, + DateTimeFormatArgs* result) { + switch (kind) { + case DateTimeValueKind::Number: { + Required required; + if (!GetRequired(cx, internals, &required)) { + return false; + } + Defaults defaults; + if (!GetDefaults(cx, internals, &defaults)) { + return false; + } + *result = {required, defaults, Inherit::All}; + return true; + } + case DateTimeValueKind::TemporalDate: + *result = {Required::Date, Defaults::Date, Inherit::Relevant}; + return true; + case DateTimeValueKind::TemporalTime: + *result = {Required::Time, Defaults::Time, Inherit::Relevant}; + return true; + case DateTimeValueKind::TemporalDateTime: + *result = {Required::Any, Defaults::All, Inherit::Relevant}; + return true; + case DateTimeValueKind::TemporalYearMonth: + *result = {Required::YearMonth, Defaults::YearMonth, Inherit::Relevant}; + return true; + case DateTimeValueKind::TemporalMonthDay: + *result = {Required::MonthDay, Defaults::MonthDay, Inherit::Relevant}; + return true; + case DateTimeValueKind::TemporalZonedDateTime: + *result = {Required::Any, Defaults::ZonedDateTime, Inherit::All}; + return true; + case DateTimeValueKind::TemporalInstant: + *result = {Required::Any, Defaults::All, Inherit::All}; + return true; + } + MOZ_CRASH("invalid date-time value kind"); +} + +enum class DateTimeField { + Weekday, + Era, + Year, + Month, + Day, + DayPeriod, + Hour, + Minute, + Second, + FractionalSecondDigits, +}; + +/** + * GetDateTimeFormat ( formats, matcher, options, required, defaults, inherit ) + * + * https://tc39.es/proposal-temporal/#sec-getdatetimeformat + */ +static mozilla::Maybe +GetDateTimeFormat(const mozilla::intl::DateTimeFormat::ComponentsBag& options, + Required required, Defaults defaults, Inherit inherit) { + // Steps 1-5. + mozilla::EnumSet requiredOptions; + switch (required) { + case Required::Date: + requiredOptions = { + DateTimeField::Weekday, + DateTimeField::Year, + DateTimeField::Month, + DateTimeField::Day, + }; + break; + case Required::Time: + requiredOptions = { + DateTimeField::DayPeriod, + DateTimeField::Hour, + DateTimeField::Minute, + DateTimeField::Second, + DateTimeField::FractionalSecondDigits, + }; + break; + case Required::YearMonth: + requiredOptions = { + DateTimeField::Year, + DateTimeField::Month, + }; + break; + case Required::MonthDay: + requiredOptions = { + DateTimeField::Month, + DateTimeField::Day, + }; + break; + case Required::Any: + requiredOptions = { + DateTimeField::Weekday, + DateTimeField::Year, + DateTimeField::Month, + DateTimeField::Day, + DateTimeField::DayPeriod, + DateTimeField::Hour, + DateTimeField::Minute, + DateTimeField::Second, + DateTimeField::FractionalSecondDigits, + }; + break; + } + MOZ_ASSERT(!requiredOptions.contains(DateTimeField::Era), + "standalone era not supported"); + + // Steps 6-10. + mozilla::EnumSet defaultOptions; + switch (defaults) { + case Defaults::Date: + defaultOptions = { + DateTimeField::Year, + DateTimeField::Month, + DateTimeField::Day, + }; + break; + case Defaults::Time: + defaultOptions = { + DateTimeField::Hour, + DateTimeField::Minute, + DateTimeField::Second, + }; + break; + case Defaults::YearMonth: + defaultOptions = { + DateTimeField::Year, + DateTimeField::Month, + }; + break; + case Defaults::MonthDay: + defaultOptions = { + DateTimeField::Month, + DateTimeField::Day, + }; + break; + case Defaults::ZonedDateTime: + case Defaults::All: + defaultOptions = { + DateTimeField::Year, DateTimeField::Month, DateTimeField::Day, + DateTimeField::Hour, DateTimeField::Minute, DateTimeField::Second, + }; + break; + } + MOZ_ASSERT(!defaultOptions.contains(DateTimeField::Weekday)); + MOZ_ASSERT(!defaultOptions.contains(DateTimeField::Era)); + MOZ_ASSERT(!defaultOptions.contains(DateTimeField::DayPeriod)); + MOZ_ASSERT(!defaultOptions.contains(DateTimeField::FractionalSecondDigits)); + + // Steps 11-12. + mozilla::intl::DateTimeFormat::ComponentsBag formatOptions; + if (inherit == Inherit::All) { + // Step 11.a. + formatOptions = options; + } else { + // Step 12.a. (Implicit) + + // Step 12.b. + switch (required) { + case Required::Date: + case Required::YearMonth: + case Required::Any: + formatOptions.era = options.era; + break; + case Required::Time: + case Required::MonthDay: + // |era| option not applicable for these types. + break; + } + + // Step 12.c. + switch (required) { + case Required::Time: + case Required::Any: + formatOptions.hourCycle = options.hourCycle; + formatOptions.hour12 = options.hour12; + break; + case Required::Date: + case Required::YearMonth: + case Required::MonthDay: + // |hourCycle| and |hour12| options not applicable for these types. + break; + } + } + + // Steps 13-14. + // + // Ignore "era" to workaround a spec bug. + // + // FIXME: spec bug - https://github.com/tc39/proposal-temporal/issues/3049 + bool anyPresent = options.weekday || options.year || options.month || + options.day || options.dayPeriod || options.hour || + options.minute || options.second || + options.fractionalSecondDigits; + + // Step 15. + bool needDefaults = true; + + // Step 16. (Loop unrolled) + if (requiredOptions.contains(DateTimeField::Weekday) && options.weekday) { + formatOptions.weekday = options.weekday; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::Year) && options.year) { + formatOptions.year = options.year; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::Month) && options.month) { + formatOptions.month = options.month; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::Day) && options.day) { + formatOptions.day = options.day; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::DayPeriod) && options.dayPeriod) { + formatOptions.dayPeriod = options.dayPeriod; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::Hour) && options.hour) { + formatOptions.hour = options.hour; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::Minute) && options.minute) { + formatOptions.minute = options.minute; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::Second) && options.second) { + formatOptions.second = options.second; + needDefaults = false; + } + if (requiredOptions.contains(DateTimeField::FractionalSecondDigits) && + options.fractionalSecondDigits) { + formatOptions.fractionalSecondDigits = options.fractionalSecondDigits; + needDefaults = false; + } + + // Step 17. + if (needDefaults) { + // Step 17.a. + if (anyPresent && inherit == Inherit::Relevant) { + return mozilla::Nothing(); + } + + // Step 17.b. (Loop unrolled) + auto numericOption = + mozilla::Some(mozilla::intl::DateTimeFormat::Numeric::Numeric); + if (defaultOptions.contains(DateTimeField::Year)) { + formatOptions.year = numericOption; + } + if (defaultOptions.contains(DateTimeField::Month)) { + formatOptions.month = + mozilla::Some(mozilla::intl::DateTimeFormat::Month::Numeric); + } + if (defaultOptions.contains(DateTimeField::Day)) { + formatOptions.day = numericOption; + } + if (defaultOptions.contains(DateTimeField::Hour)) { + formatOptions.hour = numericOption; + } + if (defaultOptions.contains(DateTimeField::Minute)) { + formatOptions.minute = numericOption; + } + if (defaultOptions.contains(DateTimeField::Second)) { + formatOptions.second = numericOption; + } + + // Step 17.c. + if (defaults == Defaults::ZonedDateTime && !formatOptions.timeZoneName) { + formatOptions.timeZoneName = + mozilla::Some(mozilla::intl::DateTimeFormat::TimeZoneName::Short); + } + } + + // Steps 18-20. (Performed in caller). + + return mozilla::Some(formatOptions); +} + +/** + * AdjustDateTimeStyleFormat ( formats, baseFormat, matcher, allowedOptions ) + * + * https://tc39.es/proposal-temporal/#sec-adjustdatetimestyleformat + */ +static mozilla::Result +AdjustDateTimeStyleFormat(mozilla::intl::DateTimeFormat* baseFormat, + mozilla::EnumSet allowedOptions) { + // Step 1. + mozilla::intl::DateTimeFormat::ComponentsBag formatOptions; + + // Step 2. (Loop unrolled) + auto result = baseFormat->ResolveComponents(); + if (result.isErr()) { + return result.propagateErr(); + } + auto options = result.unwrap(); + + if (allowedOptions.contains(DateTimeField::Era) && options.era) { + formatOptions.era = options.era; + } + if (allowedOptions.contains(DateTimeField::Weekday) && options.weekday) { + formatOptions.weekday = options.weekday; + } + if (allowedOptions.contains(DateTimeField::Year) && options.year) { + formatOptions.year = options.year; + } + if (allowedOptions.contains(DateTimeField::Month) && options.month) { + formatOptions.month = options.month; + } + if (allowedOptions.contains(DateTimeField::Day) && options.day) { + formatOptions.day = options.day; + } + if (allowedOptions.contains(DateTimeField::DayPeriod) && options.dayPeriod) { + formatOptions.dayPeriod = options.dayPeriod; + } + if (allowedOptions.contains(DateTimeField::Hour) && options.hour) { + formatOptions.hour = options.hour; + formatOptions.hourCycle = options.hourCycle; + } + if (allowedOptions.contains(DateTimeField::Minute) && options.minute) { + formatOptions.minute = options.minute; + } + if (allowedOptions.contains(DateTimeField::Second) && options.second) { + formatOptions.second = options.second; + } + if (allowedOptions.contains(DateTimeField::FractionalSecondDigits) && + options.fractionalSecondDigits) { + formatOptions.fractionalSecondDigits = options.fractionalSecondDigits; + } + + // Steps 3-5. (Performed in caller) + + return formatOptions; +} + +static const char* DateTimeValueKindToString(DateTimeValueKind kind) { + switch (kind) { + case DateTimeValueKind::Number: + return "number"; + case DateTimeValueKind::TemporalDate: + return "Temporal.PlainDate"; + case DateTimeValueKind::TemporalTime: + return "Temporal.PlainTime"; + case DateTimeValueKind::TemporalDateTime: + return "Temporal.PlainDateTime"; + case DateTimeValueKind::TemporalYearMonth: + return "Temporal.PlainYearMonth"; + case DateTimeValueKind::TemporalMonthDay: + return "Temporal.PlainMonthDay"; + case DateTimeValueKind::TemporalZonedDateTime: + return "Temporal.ZonedDateTime"; + case DateTimeValueKind::TemporalInstant: + return "Temporal.Instant"; + } + MOZ_CRASH("invalid date-time value kind"); +} + class TimeZoneOffsetString { static constexpr std::u16string_view GMT = u"GMT"; @@ -876,7 +1347,8 @@ class TimeZoneOffsetString { * formatting options of the given DateTimeFormat. */ static mozilla::intl::DateTimeFormat* NewDateTimeFormat( - JSContext* cx, Handle dateTimeFormat) { + JSContext* cx, Handle dateTimeFormat, + DateTimeValueKind kind) { RootedValue value(cx); RootedObject internals(cx, intl::GetInternalsObject(cx, dateTimeFormat)); @@ -970,21 +1442,114 @@ static mozilla::intl::DateTimeFormat* NewDateTimeFormat( return nullptr; } - SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); + switch (kind) { + case DateTimeValueKind::TemporalDate: + case DateTimeValueKind::TemporalYearMonth: + case DateTimeValueKind::TemporalMonthDay: { + if (!style.date) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_INVALID_FORMAT_OPTIONS, + DateTimeValueKindToString(kind)); + return nullptr; + } + break; + } - mozilla::intl::DateTimePatternGenerator* gen = - sharedIntlData.getDateTimePatternGenerator(cx, locale.get()); - if (!gen) { + case DateTimeValueKind::TemporalTime: { + if (!style.time) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_INVALID_FORMAT_OPTIONS, + DateTimeValueKindToString(kind)); + return nullptr; + } + break; + } + + case DateTimeValueKind::Number: + case DateTimeValueKind::TemporalDateTime: + case DateTimeValueKind::TemporalZonedDateTime: + case DateTimeValueKind::TemporalInstant: + break; + } + + SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); + auto* dtpg = sharedIntlData.getDateTimePatternGenerator(cx, locale.get()); + if (!dtpg) { return nullptr; } + auto dfResult = mozilla::intl::DateTimeFormat::TryCreateFromStyle( - mozilla::MakeStringSpan(locale.get()), style, gen, + mozilla::MakeStringSpan(locale.get()), style, dtpg, mozilla::Some(timeZoneChars)); if (dfResult.isErr()) { intl::ReportInternalError(cx, dfResult.unwrapErr()); return nullptr; } df = dfResult.unwrap(); + + mozilla::EnumSet allowedOptions; + switch (kind) { + case DateTimeValueKind::TemporalDate: + allowedOptions = { + DateTimeField::Weekday, DateTimeField::Era, DateTimeField::Year, + DateTimeField::Month, DateTimeField::Day, + }; + break; + case DateTimeValueKind::TemporalTime: + allowedOptions = { + DateTimeField::DayPeriod, + DateTimeField::Hour, + DateTimeField::Minute, + DateTimeField::Second, + DateTimeField::FractionalSecondDigits, + }; + break; + case DateTimeValueKind::TemporalDateTime: + allowedOptions = { + DateTimeField::Weekday, DateTimeField::Era, + DateTimeField::Year, DateTimeField::Month, + DateTimeField::Day, DateTimeField::DayPeriod, + DateTimeField::Hour, DateTimeField::Minute, + DateTimeField::Second, DateTimeField::FractionalSecondDigits, + }; + break; + case DateTimeValueKind::TemporalYearMonth: + allowedOptions = { + DateTimeField::Era, + DateTimeField::Year, + DateTimeField::Month, + }; + break; + case DateTimeValueKind::TemporalMonthDay: + allowedOptions = { + DateTimeField::Month, + DateTimeField::Day, + }; + break; + + case DateTimeValueKind::Number: + case DateTimeValueKind::TemporalZonedDateTime: + case DateTimeValueKind::TemporalInstant: + break; + } + + if (!allowedOptions.isEmpty()) { + auto adjusted = AdjustDateTimeStyleFormat(df.get(), allowedOptions); + if (adjusted.isErr()) { + intl::ReportInternalError(cx, dfResult.unwrapErr()); + return nullptr; + } + auto bag = adjusted.unwrap(); + + auto dfResult = mozilla::intl::DateTimeFormat::TryCreateFromComponents( + mozilla::MakeStringSpan(locale.get()), bag, dtpg, + mozilla::Some(timeZoneChars)); + if (dfResult.isErr()) { + intl::ReportInternalError(cx, dfResult.unwrapErr()); + return nullptr; + } + df = dfResult.unwrap(); + } } else { // This is a DateTimeFormat defined by a components bag. mozilla::intl::DateTimeFormat::ComponentsBag bag; @@ -1042,6 +1607,21 @@ static mozilla::intl::DateTimeFormat* NewDateTimeFormat( MOZ_ASSERT(value.isUndefined()); } + DateTimeFormatArgs dateTimeFormatArgs; + if (!GetDateTimeFormatArgs(cx, internals, kind, &dateTimeFormatArgs)) { + return nullptr; + } + auto [required, defaults, inherit] = dateTimeFormatArgs; + + auto resolvedBag = GetDateTimeFormat(bag, required, defaults, inherit); + if (!resolvedBag) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_INVALID_FORMAT_OPTIONS, + DateTimeValueKindToString(kind)); + return nullptr; + } + bag = *resolvedBag; + SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); auto* dtpg = sharedIntlData.getDateTimePatternGenerator(cx, locale.get()); if (!dtpg) { @@ -1058,22 +1638,45 @@ static mozilla::intl::DateTimeFormat* NewDateTimeFormat( df = dfResult.unwrap(); } - // ECMAScript requires the Gregorian calendar to be used from the beginning - // of ECMAScript time. - df->SetStartTimeIfGregorian(StartOfTime); - return df.release(); } +void js::DateTimeFormatObject::maybeClearCache(DateTimeValueKind kind) { + if (getDateTimeValueKind() == kind) { + return; + } + setDateTimeValueKind(kind); + + if (auto* df = getDateFormat()) { + intl::RemoveICUCellMemory( + this, DateTimeFormatObject::UDateFormatEstimatedMemoryUse); + delete df; + + setDateFormat(nullptr); + } + + if (auto* dif = getDateIntervalFormat()) { + intl::RemoveICUCellMemory( + this, DateTimeFormatObject::UDateIntervalFormatEstimatedMemoryUse); + delete dif; + + setDateIntervalFormat(nullptr); + } +} + static mozilla::intl::DateTimeFormat* GetOrCreateDateTimeFormat( - JSContext* cx, Handle dateTimeFormat) { + JSContext* cx, Handle dateTimeFormat, + DateTimeValueKind kind) { + // Clear previously created formatters if their type doesn't match. + dateTimeFormat->maybeClearCache(kind); + // Obtain a cached mozilla::intl::DateTimeFormat object. mozilla::intl::DateTimeFormat* df = dateTimeFormat->getDateFormat(); if (df) { return df; } - df = NewDateTimeFormat(cx, dateTimeFormat); + df = NewDateTimeFormat(cx, dateTimeFormat, kind); if (!df) { return nullptr; } @@ -1116,7 +1719,7 @@ bool js::intl_resolveDateTimeFormatComponents(JSContext* cx, unsigned argc, bool includeDateTimeFields = args[2].toBoolean(); mozilla::intl::DateTimeFormat* df = - GetOrCreateDateTimeFormat(cx, dateTimeFormat); + GetOrCreateDateTimeFormat(cx, dateTimeFormat, DateTimeValueKind::Number); if (!df) { return false; } @@ -1201,6 +1804,461 @@ bool js::intl_resolveDateTimeFormatComponents(JSContext* cx, unsigned argc, return true; } +/** + * ToDateTimeFormattable ( value ) + * + * https://tc39.es/proposal-temporal/#sec-todatetimeformattable + */ +static auto ToDateTimeFormattable(const Value& value) { + // Step 1. (Inlined IsTemporalObject) + if (value.isObject()) { + auto* obj = CheckedUnwrapStatic(&value.toObject()); + if (obj) { + if (obj->is()) { + return DateTimeValueKind::TemporalDate; + } + if (obj->is()) { + return DateTimeValueKind::TemporalDateTime; + } + if (obj->is()) { + return DateTimeValueKind::TemporalTime; + } + if (obj->is()) { + return DateTimeValueKind::TemporalYearMonth; + } + if (obj->is()) { + return DateTimeValueKind::TemporalMonthDay; + } + if (obj->is()) { + return DateTimeValueKind::TemporalZonedDateTime; + } + if (obj->is()) { + return DateTimeValueKind::TemporalInstant; + } + return DateTimeValueKind::Number; + } + } + + // Step 2. (ToNumber performed in caller) + return DateTimeValueKind::Number; +} + +static bool ResolveCalendarAndTimeZone( + JSContext* cx, Handle dateTimeFormat) { + Rooted internals(cx, intl::GetInternalsObject(cx, dateTimeFormat)); + if (!internals) { + return false; + } + + Rooted calendarValue(cx); + if (!GetProperty(cx, internals, internals, cx->names().calendar, + &calendarValue)) { + return false; + } + Rooted calendarString(cx, calendarValue.toString()); + + Rooted calendar(cx); + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } + + Rooted timeZoneValue(cx); + if (!GetProperty(cx, internals, internals, cx->names().timeZone, + &timeZoneValue)) { + return false; + } + Rooted timeZoneString(cx, timeZoneValue.toString()); + + Rooted parsedTimeZone(cx); + Rooted timeZone(cx); + if (!ParseTemporalTimeZoneString(cx, timeZoneString, &parsedTimeZone) || + !ToTemporalTimeZone(cx, parsedTimeZone, &timeZone)) { + return false; + } + + dateTimeFormat->setCalendar(calendar); + dateTimeFormat->setTimeZone(timeZone); + return true; +} + +/** + * HandleDateTimeTemporalDate ( dateTimeFormat, temporalDate ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporaldate + */ +static bool HandleDateTimeTemporalDate( + JSContext* cx, Handle dateTimeFormat, + Handle unwrappedTemporalDate, ClippedTime* result) { + auto isoDate = unwrappedTemporalDate->date(); + auto calendarId = unwrappedTemporalDate->calendar().identifier(); + + Rooted calendar(cx, dateTimeFormat->getCalendar()); + Rooted timeZone(cx, dateTimeFormat->getTimeZone()); + if (!calendar || !timeZone) { + if (!ResolveCalendarAndTimeZone(cx, dateTimeFormat)) { + return false; + } + calendar.set(dateTimeFormat->getCalendar()); + timeZone.set(dateTimeFormat->getTimeZone()); + } + MOZ_ASSERT(calendar && timeZone); + + // Step 1. + if (calendarId != CalendarId::ISO8601 && + calendarId != calendar.identifier()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(calendarId).data(), + CalendarIdentifier(calendar).data()); + return false; + } + + // Step 2. + auto isoDateTime = ISODateTime{isoDate, {12, 0, 0}}; + + // Step 3. + EpochNanoseconds epochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } + + // Steps 4-5. (Performed in NewDateTimeFormat) + + // Step 6. + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * HandleDateTimeTemporalYearMonth ( dateTimeFormat, temporalYearMonth ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporalyearmonth + */ +static bool HandleDateTimeTemporalYearMonth( + JSContext* cx, Handle dateTimeFormat, + Handle unwrappedTemporalYearMonth, + ClippedTime* result) { + auto isoDate = unwrappedTemporalYearMonth->date(); + auto calendarId = unwrappedTemporalYearMonth->calendar().identifier(); + + Rooted calendar(cx, dateTimeFormat->getCalendar()); + Rooted timeZone(cx, dateTimeFormat->getTimeZone()); + if (!calendar || !timeZone) { + if (!ResolveCalendarAndTimeZone(cx, dateTimeFormat)) { + return false; + } + calendar.set(dateTimeFormat->getCalendar()); + timeZone.set(dateTimeFormat->getTimeZone()); + } + MOZ_ASSERT(calendar && timeZone); + + // Step 1. + if (calendarId != calendar.identifier()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(calendarId).data(), + CalendarIdentifier(calendar).data()); + return false; + } + + // Step 2. + auto isoDateTime = ISODateTime{isoDate, {12, 0, 0}}; + + // Step 3. + EpochNanoseconds epochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } + + // Steps 4-5. (Performed in NewDateTimeFormat) + + // Step 6. + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * HandleDateTimeTemporalMonthDay ( dateTimeFormat, temporalMonthDay ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporalmonthday + */ +static bool HandleDateTimeTemporalMonthDay( + JSContext* cx, Handle dateTimeFormat, + Handle unwrappedTemporalMonthDay, + ClippedTime* result) { + auto isoDate = unwrappedTemporalMonthDay->date(); + auto calendarId = unwrappedTemporalMonthDay->calendar().identifier(); + + Rooted calendar(cx, dateTimeFormat->getCalendar()); + Rooted timeZone(cx, dateTimeFormat->getTimeZone()); + if (!calendar || !timeZone) { + if (!ResolveCalendarAndTimeZone(cx, dateTimeFormat)) { + return false; + } + calendar.set(dateTimeFormat->getCalendar()); + timeZone.set(dateTimeFormat->getTimeZone()); + } + MOZ_ASSERT(calendar && timeZone); + + // Step 1. + if (calendarId != calendar.identifier()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(calendarId).data(), + CalendarIdentifier(calendar).data()); + return false; + } + + // Step 2. + auto isoDateTime = ISODateTime{isoDate, {12, 0, 0}}; + + // Step 3. + EpochNanoseconds epochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } + + // Steps 4-5. (Performed in NewDateTimeFormat) + + // Step 6. + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * HandleDateTimeTemporalTime ( dateTimeFormat, temporalTime ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporaltime + */ +static bool HandleDateTimeTemporalTime( + JSContext* cx, Handle dateTimeFormat, + Handle unwrappedTemporalTime, ClippedTime* result) { + auto time = unwrappedTemporalTime->time(); + + Rooted timeZone(cx, dateTimeFormat->getTimeZone()); + if (!timeZone) { + if (!ResolveCalendarAndTimeZone(cx, dateTimeFormat)) { + return false; + } + timeZone.set(dateTimeFormat->getTimeZone()); + } + MOZ_ASSERT(timeZone); + + // Steps 1-2. + auto isoDateTime = ISODateTime{{1970, 1, 1}, time}; + + // Step 3. + EpochNanoseconds epochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } + + // Steps 4-5. (Performed in NewDateTimeFormat) + + // Step 6. + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * HandleDateTimeTemporalDateTime ( dateTimeFormat, dateTime ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporaldatetime + */ +static bool HandleDateTimeTemporalDateTime( + JSContext* cx, Handle dateTimeFormat, + Handle unwrappedDateTime, ClippedTime* result) { + auto isoDateTime = unwrappedDateTime->dateTime(); + auto calendarId = unwrappedDateTime->calendar().identifier(); + + Rooted calendar(cx, dateTimeFormat->getCalendar()); + Rooted timeZone(cx, dateTimeFormat->getTimeZone()); + if (!calendar || !timeZone) { + if (!ResolveCalendarAndTimeZone(cx, dateTimeFormat)) { + return false; + } + calendar.set(dateTimeFormat->getCalendar()); + timeZone.set(dateTimeFormat->getTimeZone()); + } + MOZ_ASSERT(calendar && timeZone); + + // Step 1. + if (calendarId != CalendarId::ISO8601 && + calendarId != calendar.identifier()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(calendarId).data(), + CalendarIdentifier(calendar).data()); + return false; + } + + // Step 2. + EpochNanoseconds epochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } + + // Step 3. (Performed in NewDateTimeFormat) + + // Step 4. + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * HandleDateTimeTemporalInstant ( dateTimeFormat, instant ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporalinstant + */ +static bool HandleDateTimeTemporalInstant(InstantObject* unwrappedInstant, + ClippedTime* result) { + // Step 1. (Performed in NewDateTimeFormat) + + // Step 2. + auto epochNs = unwrappedInstant->epochNanoseconds(); + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * Temporal.ZonedDateTime.prototype.toLocaleString ( [ locales [ , options ] ] ) + */ +static bool HandleDateTimeTemporalZonedDateTime( + JSContext* cx, Handle dateTimeFormat, + Handle unwrappedZonedDateTime, ClippedTime* result) { + auto epochNs = unwrappedZonedDateTime->epochNanoseconds(); + auto calendarId = unwrappedZonedDateTime->calendar().identifier(); + + Rooted calendar(cx, dateTimeFormat->getCalendar()); + Rooted timeZone(cx, dateTimeFormat->getTimeZone()); + if (!calendar || !timeZone) { + if (!ResolveCalendarAndTimeZone(cx, dateTimeFormat)) { + return false; + } + calendar.set(dateTimeFormat->getCalendar()); + timeZone.set(dateTimeFormat->getTimeZone()); + } + MOZ_ASSERT(calendar && timeZone); + + // Step 4. + if (calendarId != CalendarId::ISO8601 && + calendarId != calendar.identifier()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(calendarId).data(), + CalendarIdentifier(calendar).data()); + return false; + } + + // Step 5. + int64_t milliseconds = epochNs.floorToMilliseconds(); + *result = JS::TimeClip(double(milliseconds)); + return true; +} + +/** + * HandleDateTimeOthers ( dateTimeFormat, x ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimeothers + */ +static bool HandleDateTimeOthers(JSContext* cx, const char* method, double x, + ClippedTime* result) { + // Step 1. + auto clipped = JS::TimeClip(x); + + // Step 2. + if (!clipped.isValid()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DATE_NOT_FINITE, "DateTimeFormat", method); + return false; + } + + // Step 4. (Performed in NewDateTimeFormat) + + // Steps 3 and 5. + *result = clipped; + return true; +} + +/** + * HandleDateTimeValue ( dateTimeFormat, x ) + * + * https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevalue + */ +static bool HandleDateTimeValue(JSContext* cx, const char* method, + Handle dateTimeFormat, + Handle x, ClippedTime* result) { + MOZ_ASSERT(x.isObject() || x.isNumber()); + + // Step 1. + if (x.isObject()) { + Rooted unwrapped(cx, CheckedUnwrapStatic(&x.toObject())); + if (!unwrapped) { + ReportAccessDenied(cx); + return false; + } + + // Step 1.a. + if (unwrapped->is()) { + return HandleDateTimeTemporalDate( + cx, dateTimeFormat, unwrapped.as(), result); + } + + // Step 1.b. + if (unwrapped->is()) { + return HandleDateTimeTemporalYearMonth( + cx, dateTimeFormat, unwrapped.as(), result); + } + + // Step 1.c. + if (unwrapped->is()) { + return HandleDateTimeTemporalMonthDay( + cx, dateTimeFormat, unwrapped.as(), result); + } + + // Step 1.d. + if (unwrapped->is()) { + return HandleDateTimeTemporalTime( + cx, dateTimeFormat, unwrapped.as(), result); + } + + // Step 1.e. + if (unwrapped->is()) { + return HandleDateTimeTemporalDateTime( + cx, dateTimeFormat, unwrapped.as(), result); + } + + // Step 1.f. + if (unwrapped->is()) { + return HandleDateTimeTemporalInstant(&unwrapped->as(), + result); + } + + // Step 1.g. + MOZ_ASSERT(unwrapped->is()); + + // Step 1.h. + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_UNEXPECTED_TYPE, "object", + unwrapped->getClass()->name); + return false; + } + + // Step 2. + return HandleDateTimeOthers(cx, method, x.toNumber(), result); +} + static bool intl_FormatDateTime(JSContext* cx, const mozilla::intl::DateTimeFormat* df, ClippedTime x, MutableHandleValue result) { @@ -1371,24 +2429,36 @@ bool js::intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 3); MOZ_ASSERT(args[0].isObject()); - MOZ_ASSERT(args[1].isNumber()); MOZ_ASSERT(args[2].isBoolean()); Rooted dateTimeFormat(cx); dateTimeFormat = &args[0].toObject().as(); bool formatToParts = args[2].toBoolean(); + const char* method = formatToParts ? "formatToParts" : "format"; - ClippedTime x = TimeClip(args[1].toNumber()); - if (!x.isValid()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_DATE_NOT_FINITE, "DateTimeFormat", - formatToParts ? "formatToParts" : "format"); - return false; + auto kind = ToDateTimeFormattable(args[1]); + + JS::ClippedTime x; + if (!args[1].isUndefined()) { + Rooted value(cx, args[1]); + if (kind == DateTimeValueKind::Number) { + if (!ToNumber(cx, &value)) { + return false; + } + } + MOZ_ASSERT(value.isNumber() || value.isObject()); + + if (!HandleDateTimeValue(cx, method, dateTimeFormat, value, &x)) { + return false; + } + } else { + x = DateNow(cx); } + MOZ_ASSERT(x.isValid()); mozilla::intl::DateTimeFormat* df = - GetOrCreateDateTimeFormat(cx, dateTimeFormat); + GetOrCreateDateTimeFormat(cx, dateTimeFormat, kind); if (!df) { return false; } @@ -1471,7 +2541,9 @@ static mozilla::intl::DateIntervalFormat* NewDateIntervalFormat( static mozilla::intl::DateIntervalFormat* GetOrCreateDateIntervalFormat( JSContext* cx, Handle dateTimeFormat, - mozilla::intl::DateTimeFormat& mozDtf) { + mozilla::intl::DateTimeFormat& mozDtf, DateTimeValueKind kind) { + dateTimeFormat->maybeClearCache(kind); + // Obtain a cached DateIntervalFormat object. mozilla::intl::DateIntervalFormat* dif = dateTimeFormat->getDateIntervalFormat(); @@ -1502,51 +2574,12 @@ static bool PartitionDateTimeRangePattern( MOZ_ASSERT(x.isValid()); MOZ_ASSERT(y.isValid()); - // We can't access the calendar used by UDateIntervalFormat to change it to a - // proleptic Gregorian calendar. Instead we need to call a different formatter - // function which accepts UCalendar instead of UDate. - // But creating new UCalendar objects for each call is slow, so when we can - // ensure that the input dates are later than the Gregorian change date, - // directly call the formatter functions taking UDate. - - // The Gregorian change date "1582-10-15T00:00:00.000Z". - constexpr double GregorianChangeDate = -12219292800000.0; - - // Add a full day to account for time zone offsets. - constexpr double GregorianChangeDatePlusOneDay = - GregorianChangeDate + msPerDay; - - mozilla::intl::ICUResult result = Ok(); - if (x.toDouble() < GregorianChangeDatePlusOneDay || - y.toDouble() < GregorianChangeDatePlusOneDay) { - // Create calendar objects for the start and end date by cloning the date - // formatter calendar. The date formatter calendar already has the correct - // time zone set and was changed to use a proleptic Gregorian calendar. - auto startCal = df->CloneCalendar(x.toDouble()); - if (startCal.isErr()) { - intl::ReportInternalError(cx, startCal.unwrapErr()); - return false; - } - - auto endCal = df->CloneCalendar(y.toDouble()); - if (endCal.isErr()) { - intl::ReportInternalError(cx, endCal.unwrapErr()); - return false; - } - - result = dif->TryFormatCalendar(*startCal.unwrap(), *endCal.unwrap(), - formatted, equal); - } else { - // The common fast path which doesn't require creating calendar objects. - result = - dif->TryFormatDateTime(x.toDouble(), y.toDouble(), formatted, equal); - } - + auto result = + dif->TryFormatDateTime(x.toDouble(), y.toDouble(), df, formatted, equal); if (result.isErr()) { intl::ReportInternalError(cx, result.unwrapErr()); return false; } - return true; } @@ -1632,41 +2665,64 @@ bool js::intl_FormatDateTimeRange(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 4); MOZ_ASSERT(args[0].isObject()); - MOZ_ASSERT(args[1].isNumber()); - MOZ_ASSERT(args[2].isNumber()); + MOZ_ASSERT(!args[1].isUndefined()); + MOZ_ASSERT(!args[2].isUndefined()); MOZ_ASSERT(args[3].isBoolean()); Rooted dateTimeFormat(cx); dateTimeFormat = &args[0].toObject().as(); bool formatToParts = args[3].toBoolean(); + const char* method = formatToParts ? "formatRangeToParts" : "formatRange"; + + Rooted start(cx, args[1]); + auto startKind = ToDateTimeFormattable(start); + if (startKind == DateTimeValueKind::Number) { + if (!ToNumber(cx, &start)) { + return false; + } + } + MOZ_ASSERT(start.isNumber() || start.isObject()); + + Rooted end(cx, args[2]); + auto endKind = ToDateTimeFormattable(end); + if (endKind == DateTimeValueKind::Number) { + if (!ToNumber(cx, &end)) { + return false; + } + } + MOZ_ASSERT(end.isNumber() || end.isObject()); + + if (startKind != endKind) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_NOT_EXPECTED_TYPE, method, + DateTimeValueKindToString(startKind), + DateTimeValueKindToString(endKind)); + return false; + } // PartitionDateTimeRangePattern, steps 1-2. - ClippedTime x = TimeClip(args[1].toNumber()); - if (!x.isValid()) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE, "DateTimeFormat", - formatToParts ? "formatRangeToParts" : "formatRange"); + JS::ClippedTime x; + if (!HandleDateTimeValue(cx, method, dateTimeFormat, start, &x)) { return false; } + MOZ_ASSERT(x.isValid()); // PartitionDateTimeRangePattern, steps 3-4. - ClippedTime y = TimeClip(args[2].toNumber()); - if (!y.isValid()) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE, "DateTimeFormat", - formatToParts ? "formatRangeToParts" : "formatRange"); + JS::ClippedTime y; + if (!HandleDateTimeValue(cx, method, dateTimeFormat, end, &y)) { return false; } + MOZ_ASSERT(y.isValid()); mozilla::intl::DateTimeFormat* df = - GetOrCreateDateTimeFormat(cx, dateTimeFormat); + GetOrCreateDateTimeFormat(cx, dateTimeFormat, startKind); if (!df) { return false; } mozilla::intl::DateIntervalFormat* dif = - GetOrCreateDateIntervalFormat(cx, dateTimeFormat, *df); + GetOrCreateDateIntervalFormat(cx, dateTimeFormat, *df, startKind); if (!dif) { return false; } @@ -1676,3 +2732,56 @@ bool js::intl_FormatDateTimeRange(JSContext* cx, unsigned argc, Value* vp) { ? FormatDateTimeRangeToParts(cx, df, dif, x, y, args.rval()) : FormatDateTimeRange(cx, df, dif, x, y, args.rval()); } + +bool js::TemporalObjectToLocaleString(JSContext* cx, const CallArgs& args, + Handle required, + Handle defaults, + Handle toLocaleStringTimeZone) { + MOZ_ASSERT(args.thisv().isObject()); + + auto kind = ToDateTimeFormattable(args.thisv()); + MOZ_ASSERT(kind != DateTimeValueKind::Number); + MOZ_ASSERT_IF(kind != DateTimeValueKind::TemporalZonedDateTime, + toLocaleStringTimeZone.isUndefined()); + MOZ_ASSERT_IF(kind == DateTimeValueKind::TemporalZonedDateTime, + toLocaleStringTimeZone.isString()); + + Rooted dateTimeFormat( + cx, NewBuiltinClassInstance(cx)); + if (!dateTimeFormat) { + return false; + } + + Rooted thisValue(cx, ObjectValue(*dateTimeFormat)); + Rooted ignored(cx); + if (!intl::InitializeDateTimeFormatObject( + cx, dateTimeFormat, thisValue, args.get(0), args.get(1), required, + defaults, toLocaleStringTimeZone, DateTimeFormatOptions::Standard, + &ignored)) { + return false; + } + MOZ_ASSERT(&ignored.toObject() == dateTimeFormat); + + JS::ClippedTime x; + if (kind == DateTimeValueKind::TemporalZonedDateTime) { + Rooted zonedDateTime( + cx, &args.thisv().toObject().as()); + if (!HandleDateTimeTemporalZonedDateTime(cx, dateTimeFormat, zonedDateTime, + &x)) { + return false; + } + } else { + if (!HandleDateTimeValue(cx, "toLocaleString", dateTimeFormat, args.thisv(), + &x)) { + return false; + } + } + MOZ_ASSERT(x.isValid()); + + auto* df = GetOrCreateDateTimeFormat(cx, dateTimeFormat, kind); + if (!df) { + return false; + } + + return intl_FormatDateTime(cx, df, x, args.rval()); +} diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.h b/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.h index fd8cea73051..4d1317715cd 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.h @@ -8,6 +8,8 @@ #define builtin_intl_DateTimeFormat_h #include "builtin/SelfHostingDefines.h" +#include "builtin/temporal/Calendar.h" +#include "builtin/temporal/TimeZone.h" #include "js/Class.h" #include "vm/NativeObject.h" @@ -18,6 +20,17 @@ class DateIntervalFormat; namespace js { +enum class DateTimeValueKind { + Number, + TemporalDate, + TemporalTime, + TemporalDateTime, + TemporalYearMonth, + TemporalMonthDay, + TemporalZonedDateTime, + TemporalInstant, +}; + class DateTimeFormatObject : public NativeObject { public: static const JSClass class_; @@ -26,7 +39,10 @@ class DateTimeFormatObject : public NativeObject { static constexpr uint32_t INTERNALS_SLOT = 0; static constexpr uint32_t DATE_FORMAT_SLOT = 1; static constexpr uint32_t DATE_INTERVAL_FORMAT_SLOT = 2; - static constexpr uint32_t SLOT_COUNT = 3; + static constexpr uint32_t DATE_TIME_VALUE_KIND_SLOT = 3; + static constexpr uint32_t CALENDAR_SLOT = 4; + static constexpr uint32_t TIMEZONE_SLOT = 5; + static constexpr uint32_t SLOT_COUNT = 6; static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT, "INTERNALS_SLOT must match self-hosting define for internals " @@ -63,6 +79,45 @@ class DateTimeFormatObject : public NativeObject { setFixedSlot(DATE_INTERVAL_FORMAT_SLOT, PrivateValue(dateIntervalFormat)); } + DateTimeValueKind getDateTimeValueKind() const { + const auto& slot = getFixedSlot(DATE_TIME_VALUE_KIND_SLOT); + if (slot.isUndefined()) { + return DateTimeValueKind::Number; + } + return static_cast(slot.toInt32()); + } + + void setDateTimeValueKind(DateTimeValueKind kind) { + setFixedSlot(DATE_TIME_VALUE_KIND_SLOT, + Int32Value(static_cast(kind))); + } + + temporal::CalendarValue getCalendar() const { + const auto& slot = getFixedSlot(CALENDAR_SLOT); + if (slot.isUndefined()) { + return temporal::CalendarValue(); + } + return temporal::CalendarValue(slot); + } + + void setCalendar(const temporal::CalendarValue& calendar) { + setFixedSlot(CALENDAR_SLOT, calendar.toSlotValue()); + } + + temporal::TimeZoneValue getTimeZone() const { + const auto& slot = getFixedSlot(TIMEZONE_SLOT); + if (slot.isUndefined()) { + return temporal::TimeZoneValue(); + } + return temporal::TimeZoneValue(slot); + } + + void setTimeZone(const temporal::TimeZoneValue& timeZone) { + setFixedSlot(TIMEZONE_SLOT, timeZone.toSlotValue()); + } + + void maybeClearCache(DateTimeValueKind kind); + private: static const JSClassOps classOps_; static const ClassSpec classSpec_; @@ -183,6 +238,15 @@ class DateTimeFormatObject : public NativeObject { [[nodiscard]] extern bool intl_resolveDateTimeFormatComponents(JSContext* cx, unsigned argc, JS::Value* vp); + +/** + * Shared `toLocaleString` implementation for Temporal objects. + */ +[[nodiscard]] extern bool TemporalObjectToLocaleString( + JSContext* cx, const JS::CallArgs& args, JS::Handle required, + JS::Handle defaults, + JS::Handle toLocaleStringTimeZone = JS::UndefinedHandleValue); + } // namespace js #endif /* builtin_intl_DateTimeFormat_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.js b/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.js index bb6d202a3ac..4ad6d184026 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.js +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DateTimeFormat.js @@ -5,7 +5,7 @@ /* Portions Copyright Norbert Lindenberg 2011-2012. */ /** - * 11.1.2 CreateDateTimeFormat ( newTarget, locales, options, required, defaults ) + * 11.1.2 CreateDateTimeFormat ( newTarget, locales, options, required, defaults [ , toLocaleStringTimeZone ] ) * * Compute an internal properties object from |lazyDateTimeFormatData|. */ @@ -102,6 +102,8 @@ function resolveDateTimeFormatInternals(lazyDateTimeFormatData) { internalProps.dateStyle = lazyDateTimeFormatData.dateStyle; internalProps.timeStyle = lazyDateTimeFormatData.timeStyle; } else { + internalProps.required = lazyDateTimeFormatData.required; + internalProps.defaults = lazyDateTimeFormatData.defaults; internalProps.hourCycle = formatOptions.hourCycle; internalProps.hour12 = formatOptions.hour12; internalProps.weekday = formatOptions.weekday; @@ -195,10 +197,10 @@ function CanonicalizeTimeZoneName(timeZone) { "Unsupported canonical time zone" ); - // Step 3. - if (ianaTimeZone === "Etc/UTC" || ianaTimeZone === "Etc/GMT") { - ianaTimeZone = "UTC"; - } + // Step 3. (Not applicable.) + assert(ianaTimeZone !== "Etc/UTC", "Invalid link to UTC"); + assert(ianaTimeZone !== "Etc/GMT", "Invalid link to UTC"); + assert(ianaTimeZone !== "GMT", "Invalid link to UTC"); // Step 4. return ianaTimeZone; @@ -275,15 +277,9 @@ function TimeZoneOffsetString(offsetString) { assert(typeof(offsetString) === "string", "offsetString is a string"); // UTCOffset ::: - // TemporalSign Hour - // TemporalSign Hour HourSubcomponents[+Extended] - // TemporalSign Hour HourSubcomponents[~Extended] - // - // TemporalSign ::: - // ASCIISign - // - // - // With = U+2212 + // ASCIISign Hour + // ASCIISign Hour HourSubcomponents[+Extended] + // ASCIISign Hour HourSubcomponents[~Extended] // // ASCIISign ::: one of // + - @@ -316,40 +312,19 @@ function TimeZoneOffsetString(offsetString) { return null; } - // Self-hosted code only supports Latin-1 permanent atoms, so the Unicode - // can't be used in a string literal "\u2212". That means the first character has - // to be checked using the character code instead of performing a normal string - // comparison. Alternatively could be generated at runtime through - // |std_String_fromCharCode(0x2212)|, but that means allocating a string just for - // the comparison. And for consistency also check the remaining characters through - // their character code. - - #define PLUS_SIGN 0x2b - #define HYPHEN_MINUS 0x2d - #define MINUS 0x2212 - #define COLON 0x3a - #define DIGIT_ZERO 0x30 - #define DIGIT_TWO 0x32 - #define DIGIT_THREE 0x33 - #define DIGIT_FIVE 0x35 - #define DIGIT_NINE 0x39 - - /* global PLUS_SIGN, HYPHEN_MINUS, MINUS, COLON */ - /* global DIGIT_ZERO, DIGIT_TWO, DIGIT_THREE, DIGIT_FIVE, DIGIT_NINE */ - - // The first character must match |TemporalSign|. - var sign = callFunction(std_String_charCodeAt, offsetString, 0); - if (sign !== PLUS_SIGN && sign !== HYPHEN_MINUS && sign !== MINUS) { + // The first character must match |ASCIISign|. + var sign = offsetString[0]; + if (sign !== "+" && sign !== "-") { return null; } // Read the next two characters for the |Hour| grammar production. - var hourTens = callFunction(std_String_charCodeAt, offsetString, 1); - var hourOnes = callFunction(std_String_charCodeAt, offsetString, 2); + var hourTens = offsetString[1]; + var hourOnes = offsetString[2]; // Read the remaining characters for the optional |MinuteSecond| grammar production. - var minutesTens = DIGIT_ZERO; - var minutesOnes = DIGIT_ZERO; + var minutesTens = "0"; + var minutesOnes = "0"; if (offsetString.length > 3) { // |TimeSeparator| is optional. var separatorLength = offsetString[3] === ":" ? 1 : 0; @@ -359,70 +334,43 @@ function TimeZoneOffsetString(offsetString) { return null; } - minutesTens = callFunction( - std_String_charCodeAt, - offsetString, - 3 + separatorLength, - ); - minutesOnes = callFunction( - std_String_charCodeAt, - offsetString, - 4 + separatorLength, - ); + minutesTens = offsetString[3 + separatorLength]; + minutesOnes = offsetString[4 + separatorLength]; } // Validate the characters match the |Hour| and |MinuteSecond| productions: // - hours must be in the range 0..23 // - minutes must in the range 0..59 if ( - hourTens < DIGIT_ZERO || - hourOnes < DIGIT_ZERO || - minutesTens < DIGIT_ZERO || - minutesOnes < DIGIT_ZERO || - hourTens > DIGIT_TWO || - hourOnes > DIGIT_NINE || - minutesTens > DIGIT_FIVE || - minutesOnes > DIGIT_NINE || - (hourTens === DIGIT_TWO && hourOnes > DIGIT_THREE) + hourTens < "0" || + hourOnes < "0" || + minutesTens < "0" || + minutesOnes < "0" || + hourTens > "2" || + hourOnes > "9" || + minutesTens > "5" || + minutesOnes > "9" || + (hourTens === "2" && hourOnes > "3") ) { return null; } // FormatOffsetTimeZoneIdentifier, steps 1-5. if ( - hourTens === DIGIT_ZERO && - hourOnes === DIGIT_ZERO && - minutesTens === DIGIT_ZERO && - minutesOnes === DIGIT_ZERO + hourTens === "0" && + hourOnes === "0" && + minutesTens === "0" && + minutesOnes === "0" ) { - sign = PLUS_SIGN; - } else if (sign === MINUS) { - sign = HYPHEN_MINUS; + sign = "+"; } - return std_String_fromCharCode( - sign, - hourTens, - hourOnes, - COLON, - minutesTens, - minutesOnes, - ); - - #undef PLUS_SIGN - #undef HYPHEN_MINUS - #undef MINUS - #undef COLON - #undef DIGIT_ZERO - #undef DIGIT_TWO - #undef DIGIT_THREE - #undef DIGIT_FIVE - #undef DIGIT_NINE + return sign + hourTens + hourOnes + ":" + minutesTens + minutesOnes; } /* eslint-disable complexity */ /** - * 11.1.2 CreateDateTimeFormat ( newTarget, locales, options, required, defaults ) + * 11.1.2 CreateDateTimeFormat ( newTarget, locales, options, required, defaults [ , toLocaleStringTimeZone ] ) * * Initializes an object as a DateTimeFormat. * @@ -439,6 +387,7 @@ function InitializeDateTimeFormat( options, required, defaults, + toLocaleStringTimeZone, mozExtensions ) { assert( @@ -457,6 +406,10 @@ function InitializeDateTimeFormat( defaults === "date" || defaults === "time" || defaults === "all", `InitializeDateTimeFormat called with invalid defaults value: ${defaults}` ); + assert( + toLocaleStringTimeZone === undefined || typeof toLocaleStringTimeZone === "string", + `InitializeDateTimeFormat called with invalid toLocaleStringTimeZone value: ${toLocaleStringTimeZone}` + ); // Lazy DateTimeFormat data has the following structure: // @@ -485,6 +438,10 @@ function InitializeDateTimeFormat( // } // // formatMatcher: "basic" / "best fit", + // + // required: "date" / "time" / "any", // optional + // + // defaults: "date" / "time" / "all", // optional // } // // Note that lazy data is only installed as a final step of initialization, @@ -585,11 +542,22 @@ function InitializeDateTimeFormat( // Steps 30-34. if (timeZone === undefined) { // Step 30.a. - timeZone = DefaultTimeZone(); + if (toLocaleStringTimeZone !== undefined) { + timeZone = toLocaleStringTimeZone; + } else { + timeZone = DefaultTimeZone(); + } // Steps 32-34. (Not applicable in our implementation.) } else { // Step 31.a. + if (toLocaleStringTimeZone !== undefined) { + ThrowTypeError( + JSMSG_INVALID_DATETIME_OPTION, + "timeZone", + "Temporal.ZonedDateTime.toLocaleString" + ); + } timeZone = ToString(timeZone); // Steps 32-34. @@ -793,58 +761,16 @@ function InitializeDateTimeFormat( // Step 43.b. if (required === "date" && timeStyle !== undefined) { - ThrowTypeError( - JSMSG_INVALID_DATETIME_STYLE, - "timeStyle", - "toLocaleDateString" - ); + ThrowTypeError(JSMSG_INVALID_DATETIME_STYLE, "timeStyle", "date"); } // Step 43.c. if (required === "time" && dateStyle !== undefined) { - ThrowTypeError( - JSMSG_INVALID_DATETIME_STYLE, - "dateStyle", - "toLocaleTimeString" - ); + ThrowTypeError(JSMSG_INVALID_DATETIME_STYLE, "dateStyle", "time"); } } else { - // Step 44.a. - var needDefaults = true; - - // Step 44.b. - if (required === "date" || required === "any") { - needDefaults = - formatOptions.weekday === undefined && - formatOptions.year === undefined && - formatOptions.month === undefined && - formatOptions.day === undefined; - } - - // Step 44.c. - if (required === "time" || required === "any") { - needDefaults = - needDefaults && - formatOptions.dayPeriod === undefined && - formatOptions.hour === undefined && - formatOptions.minute === undefined && - formatOptions.second === undefined && - formatOptions.fractionalSecondDigits === undefined; - } - - // Step 44.d. - if (needDefaults && (defaults === "date" || defaults === "all")) { - formatOptions.year = "numeric"; - formatOptions.month = "numeric"; - formatOptions.day = "numeric"; - } - - // Step 44.e. - if (needDefaults && (defaults === "time" || defaults === "all")) { - formatOptions.hour = "numeric"; - formatOptions.minute = "numeric"; - formatOptions.second = "numeric"; - } + lazyDateTimeFormatData.required = required; + lazyDateTimeFormatData.defaults = defaults; // Steps 44.f-h provided by ICU, more or less. } @@ -948,11 +874,8 @@ function createDateTimeFormatFormat(dtf) { "dateTimeFormatFormatToBind called with non-DateTimeFormat" ); - // Steps 3-4. - var x = date === undefined ? std_Date_now() : ToNumber(date); - - // Step 5. - return intl_FormatDateTime(dtf, x, /* formatToParts = */ false); + // Steps 3-5. + return intl_FormatDateTime(dtf, date, /* formatToParts = */ false); }; } @@ -1009,14 +932,11 @@ function Intl_DateTimeFormat_formatToParts(date) { ); } - // Steps 4-5. - var x = date === undefined ? std_Date_now() : ToNumber(date); - // Ensure the DateTimeFormat internals are resolved. getDateTimeFormatInternals(dtf); - // Step 6. - return intl_FormatDateTime(dtf, x, /* formatToParts = */ true); + // Steps 4-6. + return intl_FormatDateTime(dtf, date, /* formatToParts = */ true); } /** @@ -1048,17 +968,11 @@ function Intl_DateTimeFormat_formatRange(startDate, endDate) { ); } - // Step 4. - var x = ToNumber(startDate); - - // Step 5. - var y = ToNumber(endDate); - // Ensure the DateTimeFormat internals are resolved. getDateTimeFormatInternals(dtf); - // Step 6. - return intl_FormatDateTimeRange(dtf, x, y, /* formatToParts = */ false); + // Steps 4-6. + return intl_FormatDateTimeRange(dtf, startDate, endDate, /* formatToParts = */ false); } /** @@ -1090,17 +1004,11 @@ function Intl_DateTimeFormat_formatRangeToParts(startDate, endDate) { ); } - // Step 4. - var x = ToNumber(startDate); - - // Step 5. - var y = ToNumber(endDate); - // Ensure the DateTimeFormat internals are resolved. getDateTimeFormatInternals(dtf); - // Step 6. - return intl_FormatDateTimeRange(dtf, x, y, /* formatToParts = */ true); + // Steps 4-6. + return intl_FormatDateTimeRange(dtf, startDate, endDate, /* formatToParts = */ true); } /** diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DisplayNames.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/DisplayNames.cpp index d375be58f3d..d288b1c5e04 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/DisplayNames.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DisplayNames.cpp @@ -46,20 +46,24 @@ using namespace js; -const JSClassOps DisplayNamesObject::classOps_ = {nullptr, /* addProperty */ - nullptr, /* delProperty */ - nullptr, /* enumerate */ - nullptr, /* newEnumerate */ - nullptr, /* resolve */ - nullptr, /* mayResolve */ - DisplayNamesObject::finalize}; +const JSClassOps DisplayNamesObject::classOps_ = { + nullptr, /* addProperty */ + nullptr, /* delProperty */ + nullptr, /* enumerate */ + nullptr, /* newEnumerate */ + nullptr, /* resolve */ + nullptr, /* mayResolve */ + DisplayNamesObject::finalize, +}; const JSClass DisplayNamesObject::class_ = { "Intl.DisplayNames", JSCLASS_HAS_RESERVED_SLOTS(DisplayNamesObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_DisplayNames) | JSCLASS_FOREGROUND_FINALIZE, - &DisplayNamesObject::classOps_, &DisplayNamesObject::classSpec_}; + &DisplayNamesObject::classOps_, + &DisplayNamesObject::classSpec_, +}; const JSClass& DisplayNamesObject::protoClass_ = PlainObject::class_; @@ -72,17 +76,21 @@ static bool displayNames_toSource(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec displayNames_static_methods[] = { JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_DisplayNames_supportedLocalesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec displayNames_methods[] = { JS_SELF_HOSTED_FN("of", "Intl_DisplayNames_of", 1, 0), JS_SELF_HOSTED_FN("resolvedOptions", "Intl_DisplayNames_resolvedOptions", 0, 0), - JS_FN("toSource", displayNames_toSource, 0, 0), JS_FS_END}; + JS_FN("toSource", displayNames_toSource, 0, 0), + JS_FS_END, +}; static const JSPropertySpec displayNames_properties[] = { JS_STRING_SYM_PS(toStringTag, "Intl.DisplayNames", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; static bool DisplayNames(JSContext* cx, unsigned argc, Value* vp); @@ -94,7 +102,8 @@ const ClassSpec DisplayNamesObject::classSpec_ = { displayNames_methods, displayNames_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; enum class DisplayNamesOptions { Standard, diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.cpp new file mode 100644 index 00000000000..d9d3f0459ab --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.cpp @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Intl.DurationFormat implementation. */ + +#include "builtin/intl/DurationFormat.h" + +#include "mozilla/Assertions.h" +#include "mozilla/intl/DateTimeFormat.h" +#include "mozilla/Span.h" + +#include "jspubtd.h" +#include "NamespaceImports.h" + +#include "builtin/intl/CommonFunctions.h" +#include "builtin/intl/FormatBuffer.h" +#include "builtin/temporal/Duration.h" +#include "gc/AllocKind.h" +#include "gc/GCContext.h" +#include "js/CallArgs.h" +#include "js/PropertyDescriptor.h" +#include "js/PropertySpec.h" +#include "js/RootingAPI.h" +#include "js/TypeDecls.h" +#include "js/Value.h" +#include "vm/GlobalObject.h" +#include "vm/JSContext.h" +#include "vm/PlainObject.h" +#include "vm/SelfHosting.h" +#include "vm/WellKnownAtom.h" + +#include "vm/JSObject-inl.h" +#include "vm/NativeObject-inl.h" + +using namespace js; + +const JSClass DurationFormatObject::class_ = { + "Intl.DurationFormat", + JSCLASS_HAS_RESERVED_SLOTS(DurationFormatObject::SLOT_COUNT) | + JSCLASS_HAS_CACHED_PROTO(JSProto_DurationFormat), + JS_NULL_CLASS_OPS, + &DurationFormatObject::classSpec_, +}; + +const JSClass& DurationFormatObject::protoClass_ = PlainObject::class_; + +static bool durationFormat_toSource(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + args.rval().setString(cx->names().DurationFormat); + return true; +} + +static const JSFunctionSpec durationFormat_static_methods[] = { + JS_SELF_HOSTED_FN("supportedLocalesOf", + "Intl_DurationFormat_supportedLocalesOf", 1, 0), + JS_FS_END, +}; + +static const JSFunctionSpec durationFormat_methods[] = { + JS_SELF_HOSTED_FN("resolvedOptions", "Intl_DurationFormat_resolvedOptions", + 0, 0), + JS_SELF_HOSTED_FN("format", "Intl_DurationFormat_format", 1, 0), + JS_SELF_HOSTED_FN("formatToParts", "Intl_DurationFormat_formatToParts", 1, + 0), + JS_FN("toSource", durationFormat_toSource, 0, 0), + JS_FS_END, +}; + +static const JSPropertySpec durationFormat_properties[] = { + JS_STRING_SYM_PS(toStringTag, "Intl.DurationFormat", JSPROP_READONLY), + JS_PS_END, +}; + +static bool DurationFormat(JSContext* cx, unsigned argc, Value* vp); + +const ClassSpec DurationFormatObject::classSpec_ = { + GenericCreateConstructor, + GenericCreatePrototype, + durationFormat_static_methods, + nullptr, + durationFormat_methods, + durationFormat_properties, + nullptr, + ClassSpec::DontDefineConstructor, +}; + +/** + * Intl.DurationFormat ( [ locales [ , options ] ] ) + */ +static bool DurationFormat(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. + if (!ThrowIfNotConstructing(cx, args, "Intl.DurationFormat")) { + return false; + } + + // Step 2 (Inlined 9.1.14, OrdinaryCreateFromConstructor). + RootedObject proto(cx); + if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_DurationFormat, + &proto)) { + return false; + } + + Rooted durationFormat( + cx, NewObjectWithClassProto(cx, proto)); + if (!durationFormat) { + return false; + } + + HandleValue locales = args.get(0); + HandleValue options = args.get(1); + + // Steps 3-28. + if (!intl::InitializeObject(cx, durationFormat, + cx->names().InitializeDurationFormat, locales, + options)) { + return false; + } + + args.rval().setObject(*durationFormat); + return true; +} + +bool js::intl_GetTimeSeparator(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 2); + MOZ_ASSERT(args[0].isString()); + MOZ_ASSERT(args[1].isString()); + + UniqueChars locale = intl::EncodeLocale(cx, args[0].toString()); + if (!locale) { + return false; + } + + UniqueChars numberingSystem = EncodeAscii(cx, args[1].toString()); + if (!numberingSystem) { + return false; + } + + intl::FormatBuffer separator(cx); + auto result = mozilla::intl::DateTimeFormat::GetTimeSeparator( + mozilla::MakeStringSpan(locale.get()), + mozilla::MakeStringSpan(numberingSystem.get()), separator); + if (result.isErr()) { + intl::ReportInternalError(cx, result.unwrapErr()); + return false; + } + + JSString* str = separator.toString(cx); + if (!str) { + return false; + } + + args.rval().setString(str); + return true; +} + +bool js::TemporalDurationToLocaleString(JSContext* cx, + const JS::CallArgs& args) { + MOZ_ASSERT(args.thisv().isObject()); + MOZ_ASSERT(args.thisv().toObject().is()); + + Rooted durationFormat( + cx, NewBuiltinClassInstance(cx)); + if (!durationFormat) { + return false; + } + + if (!intl::InitializeObject(cx, durationFormat, + cx->names().InitializeDurationFormat, args.get(0), + args.get(1))) { + return false; + } + + Rooted thisv(cx, ObjectValue(*durationFormat)); + + FixedInvokeArgs<1> invokeArgs(cx); + invokeArgs[0].set(args.thisv()); + + return CallSelfHostedFunction(cx, cx->names().Intl_DurationFormat_format, + thisv, invokeArgs, args.rval()); +} diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.h b/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.h new file mode 100644 index 00000000000..51d453628f1 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_intl_DurationFormat_h +#define builtin_intl_DurationFormat_h + +#include + +#include "builtin/SelfHostingDefines.h" +#include "js/Class.h" +#include "vm/NativeObject.h" + +namespace js { + +class DurationFormatObject : public NativeObject { + public: + static const JSClass class_; + static const JSClass& protoClass_; + + static constexpr uint32_t INTERNALS_SLOT = 0; + static constexpr uint32_t SLOT_COUNT = 1; + + static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT, + "INTERNALS_SLOT must match self-hosting define for internals " + "object slot"); + + private: + static const ClassSpec classSpec_; +}; + +/** + * Returns the time separator string for the given locale and numbering system. + * + * Usage: separator = intl_GetTimeSeparator(locale, numberingSystem) + */ +[[nodiscard]] extern bool intl_GetTimeSeparator(JSContext* cx, unsigned argc, + Value* vp); + +/** + * `toLocaleString` implementation for Temporal.Duration objects. + */ +[[nodiscard]] extern bool TemporalDurationToLocaleString( + JSContext* cx, const JS::CallArgs& args); + +} // namespace js + +#endif /* builtin_intl_DurationFormat_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.js b/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.js new file mode 100644 index 00000000000..1e175d4bfd0 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/DurationFormat.js @@ -0,0 +1,1623 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * DurationFormat internal properties. + */ +function durationFormatLocaleData() { + return { + nu: getNumberingSystems, + default: { + nu: intl_numberingSystem, + }, + }; +} +var durationFormatInternalProperties = { + localeData: durationFormatLocaleData, + relevantExtensionKeys: ["nu"], +}; + +/** + * Intl.DurationFormat ( [ locales [ , options ] ] ) + * + * Compute an internal properties object from |lazyDurationFormatData|. + */ +function resolveDurationFormatInternals(lazyDurationFormatData) { + assert(IsObject(lazyDurationFormatData), "lazy data not an object?"); + + var internalProps = std_Object_create(null); + + var DurationFormat = durationFormatInternalProperties; + + // Compute effective locale. + + // Step 9. + var r = ResolveLocale( + "DurationFormat", + lazyDurationFormatData.requestedLocales, + lazyDurationFormatData.opt, + DurationFormat.relevantExtensionKeys, + DurationFormat.localeData + ); + + // Steps 10-11. + internalProps.locale = r.locale; + + // Steps 12-21. (Not applicable in our implementation.) + + // Step 22. + internalProps.numberingSystem = r.nu; + + // Step 24. + internalProps.style = lazyDurationFormatData.style; + + // Step 26. + internalProps.yearsStyle = lazyDurationFormatData.yearsStyle; + internalProps.yearsDisplay = lazyDurationFormatData.yearsDisplay; + + internalProps.weeksStyle = lazyDurationFormatData.weeksStyle; + internalProps.weeksDisplay = lazyDurationFormatData.weeksDisplay; + + internalProps.monthsStyle = lazyDurationFormatData.monthsStyle; + internalProps.monthsDisplay = lazyDurationFormatData.monthsDisplay; + + internalProps.daysStyle = lazyDurationFormatData.daysStyle; + internalProps.daysDisplay = lazyDurationFormatData.daysDisplay; + + internalProps.hoursStyle = lazyDurationFormatData.hoursStyle; + internalProps.hoursDisplay = lazyDurationFormatData.hoursDisplay; + + internalProps.minutesStyle = lazyDurationFormatData.minutesStyle; + internalProps.minutesDisplay = lazyDurationFormatData.minutesDisplay; + + internalProps.secondsStyle = lazyDurationFormatData.secondsStyle; + internalProps.secondsDisplay = lazyDurationFormatData.secondsDisplay; + + internalProps.millisecondsStyle = lazyDurationFormatData.millisecondsStyle; + internalProps.millisecondsDisplay = + lazyDurationFormatData.millisecondsDisplay; + + internalProps.microsecondsStyle = lazyDurationFormatData.microsecondsStyle; + internalProps.microsecondsDisplay = + lazyDurationFormatData.microsecondsDisplay; + + internalProps.nanosecondsStyle = lazyDurationFormatData.nanosecondsStyle; + internalProps.nanosecondsDisplay = lazyDurationFormatData.nanosecondsDisplay; + + // Step 27. + internalProps.fractionalDigits = lazyDurationFormatData.fractionalDigits; + + // The caller is responsible for associating |internalProps| with the right + // object using |setInternalProperties|. + return internalProps; +} + +/** + * Returns an object containing the DurationFormat internal properties of |obj|. + */ +function getDurationFormatInternals(obj) { + assert(IsObject(obj), "getDurationFormatInternals called with non-object"); + assert( + intl_GuardToDurationFormat(obj) !== null, + "getDurationFormatInternals called with non-DurationFormat" + ); + + var internals = getIntlObjectInternals(obj); + assert( + internals.type === "DurationFormat", + "bad type escaped getIntlObjectInternals" + ); + + // If internal properties have already been computed, use them. + var internalProps = maybeInternalProperties(internals); + if (internalProps) { + return internalProps; + } + + // Otherwise it's time to fully create them. + internalProps = resolveDurationFormatInternals(internals.lazyData); + setInternalProperties(internals, internalProps); + return internalProps; +} + +/** + * Intl.DurationFormat ( [ locales [ , options ] ] ) + * + * Initializes an object as a DurationFormat. + * + * This method is complicated a moderate bit by its implementing initialization + * as a *lazy* concept. Everything that must happen now, does -- but we defer + * all the work we can until the object is actually used as a DurationFormat. + * This later work occurs in |resolveDurationFormatInternals|; steps not noted + * here occur there. + */ +function InitializeDurationFormat(durationFormat, locales, options) { + assert( + IsObject(durationFormat), + "InitializeDurationFormat called with non-object" + ); + assert( + intl_GuardToDurationFormat(durationFormat) !== null, + "InitializeDurationFormat called with non-DurationFormat" + ); + + // Lazy DurationFormat data has the following structure: + // + // { + // requestedLocales: List of locales, + // style: "long" / "short" / "narrow" / "digital", + // + // yearsStyle: "long" / "short" / "narrow", + // yearsDisplay: "auto" / "always", + // + // monthsStyle: "long" / "short" / "narrow", + // monthsDisplay: "auto" / "always", + // + // weeksStyle: "long" / "short" / "narrow", + // weeksDisplay: "auto" / "always", + // + // daysStyle: "long" / "short" / "narrow", + // daysDisplay: "auto" / "always", + // + // hoursStyle: "long" / "short" / "narrow" / "numeric" / "2-digit", + // hoursDisplay: "auto" / "always", + // + // minutesStyle: "long" / "short" / "narrow" / "numeric" / "2-digit", + // minutesDisplay: "auto" / "always", + // + // secondsStyle: "long" / "short" / "narrow" / "numeric" / "2-digit", + // secondsDisplay: "auto" / "always", + // + // millisecondsStyle: "long" / "short" / "narrow" / "numeric", + // millisecondsDisplay: "auto" / "always", + // + // microsecondsStyle: "long" / "short" / "narrow" / "numeric", + // microsecondsDisplay: "auto" / "always", + // + // nanosecondsStyle: "long" / "short" / "narrow" / "numeric", + // nanosecondsDisplay: "auto" / "always", + // + // fractionalDigits: integer ∈ [0, 9] / undefined, + // + // opt: // opt object computed in InitializeDurationFormat + // { + // localeMatcher: "lookup" / "best fit", + // + // nu: string matching a Unicode extension type, // optional + // } + // } + // + // Note that lazy data is only installed as a final step of initialization, + // so every DurationFormat lazy data object has *all* these properties, + // never a subset of them. + var lazyDurationFormatData = std_Object_create(null); + + // Step 3. + var requestedLocales = CanonicalizeLocaleList(locales); + lazyDurationFormatData.requestedLocales = requestedLocales; + + // Step 4. + if (options === undefined) { + options = std_Object_create(null); + } else if (!IsObject(options)) { + ThrowTypeError( + JSMSG_OBJECT_REQUIRED, + options === null ? "null" : typeof options + ); + } + + // Step 5. + var matcher = GetOption( + options, + "localeMatcher", + "string", + ["lookup", "best fit"], + "best fit" + ); + + // Step 6. + var numberingSystem = GetOption( + options, + "numberingSystem", + "string", + undefined, + undefined + ); + + // Step 7. + if (numberingSystem !== undefined) { + numberingSystem = intl_ValidateAndCanonicalizeUnicodeExtensionType( + numberingSystem, + "numberingSystem", + "nu" + ); + } + + // Step 8. + var opt = new_Record(); + opt.localeMatcher = matcher; + opt.nu = numberingSystem; + + lazyDurationFormatData.opt = opt; + + // Compute formatting options. + + // Steps 23-24. + var style = GetOption( + options, + "style", + "string", + ["long", "short", "narrow", "digital"], + "short" + ); + lazyDurationFormatData.style = style; + + // Step 25. (Not applicable in our implementation) + + // Step 26, unit = "years". + var yearsOptions = GetDurationUnitOptions( + "years", + options, + style, + ["long", "short", "narrow"], + "short", + /* prevStyle= */ "" + ); + lazyDurationFormatData.yearsStyle = yearsOptions.style; + lazyDurationFormatData.yearsDisplay = yearsOptions.display; + + // Step 26, unit = "months". + var monthsOptions = GetDurationUnitOptions( + "months", + options, + style, + ["long", "short", "narrow"], + "short", + /* prevStyle= */ "" + ); + lazyDurationFormatData.monthsStyle = monthsOptions.style; + lazyDurationFormatData.monthsDisplay = monthsOptions.display; + + // Step 26, unit = "weeks". + var weeksOptions = GetDurationUnitOptions( + "weeks", + options, + style, + ["long", "short", "narrow"], + "short", + /* prevStyle= */ "" + ); + lazyDurationFormatData.weeksStyle = weeksOptions.style; + lazyDurationFormatData.weeksDisplay = weeksOptions.display; + + // Step 26, unit = "days". + var daysOptions = GetDurationUnitOptions( + "days", + options, + style, + ["long", "short", "narrow"], + "short", + /* prevStyle= */ "" + ); + lazyDurationFormatData.daysStyle = daysOptions.style; + lazyDurationFormatData.daysDisplay = daysOptions.display; + + // Step 26, unit = "hours". + var hoursOptions = GetDurationUnitOptions( + "hours", + options, + style, + ["long", "short", "narrow", "numeric", "2-digit"], + "numeric", + /* prevStyle= */ "" + ); + lazyDurationFormatData.hoursStyle = hoursOptions.style; + lazyDurationFormatData.hoursDisplay = hoursOptions.display; + + // Step 26, unit = "minutes". + var minutesOptions = GetDurationUnitOptions( + "minutes", + options, + style, + ["long", "short", "narrow", "numeric", "2-digit"], + "numeric", + hoursOptions.style + ); + lazyDurationFormatData.minutesStyle = minutesOptions.style; + lazyDurationFormatData.minutesDisplay = minutesOptions.display; + + // Step 26, unit = "seconds". + var secondsOptions = GetDurationUnitOptions( + "seconds", + options, + style, + ["long", "short", "narrow", "numeric", "2-digit"], + "numeric", + minutesOptions.style + ); + lazyDurationFormatData.secondsStyle = secondsOptions.style; + lazyDurationFormatData.secondsDisplay = secondsOptions.display; + + // Step 26, unit = "milliseconds". + var millisecondsOptions = GetDurationUnitOptions( + "milliseconds", + options, + style, + ["long", "short", "narrow", "numeric"], + "numeric", + secondsOptions.style + ); + lazyDurationFormatData.millisecondsStyle = millisecondsOptions.style; + lazyDurationFormatData.millisecondsDisplay = millisecondsOptions.display; + + // Step 26, unit = "microseconds". + var microsecondsOptions = GetDurationUnitOptions( + "microseconds", + options, + style, + ["long", "short", "narrow", "numeric"], + "numeric", + millisecondsOptions.style + ); + lazyDurationFormatData.microsecondsStyle = microsecondsOptions.style; + lazyDurationFormatData.microsecondsDisplay = microsecondsOptions.display; + + // Step 26, unit = "milliseconds". + var nanosecondsOptions = GetDurationUnitOptions( + "nanoseconds", + options, + style, + ["long", "short", "narrow", "numeric"], + "numeric", + microsecondsOptions.style + ); + lazyDurationFormatData.nanosecondsStyle = nanosecondsOptions.style; + lazyDurationFormatData.nanosecondsDisplay = nanosecondsOptions.display; + + // Step 27. + lazyDurationFormatData.fractionalDigits = GetNumberOption( + options, + "fractionalDigits", + 0, + 9, + undefined + ); + + // We've done everything that must be done now: mark the lazy data as fully + // computed and install it. + initializeIntlObject( + durationFormat, + "DurationFormat", + lazyDurationFormatData + ); +} + +/** + * GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle, twoDigitHours ) + */ +function GetDurationUnitOptions( + unit, + options, + baseStyle, + stylesList, + digitalBase, + prevStyle +) { + assert(typeof unit === "string", "unit is a string"); + assert(IsObject(options), "options is an object"); + assert(typeof baseStyle === "string", "baseStyle is a string"); + assert(IsArray(stylesList), "stylesList is an array"); + assert(typeof digitalBase === "string", "digitalBase is a string"); + assert(typeof prevStyle === "string", "prevStyle is a string"); + + // Step 1. + var styleOption = GetOption(options, unit, "string", stylesList, undefined); + + var style = styleOption; + + // Step 2. + var displayDefault = "always"; + + // Step 3. + if (style === undefined) { + // Steps 3.a-b. + if (baseStyle === "digital") { + // Step 3.a.i. + if (unit !== "hours" && unit !== "minutes" && unit !== "seconds") { + displayDefault = "auto"; + } + + // Step 3.a.ii. + style = digitalBase; + } else { + // Steps 3.b.i-ii. ("fractional" handled implicitly) + if (prevStyle === "numeric" || prevStyle === "2-digit") { + // Step 3.b.i.1. + if (unit !== "minutes" && unit !== "seconds") { + // Step 3.b.i.1.a. + displayDefault = "auto"; + } + + // Step 3.b.i.2. + style = "numeric"; + } else { + // Step 3.b.ii.1. + displayDefault = "auto"; + + // Step 3.b.ii.2. + style = baseStyle; + } + } + } + + // Step 4. + var isFractional = + style === "numeric" && + (unit === "milliseconds" || + unit === "microseconds" || + unit === "nanoseconds"); + if (isFractional) { + // Step 4.a.i. (Not applicable in our implementation) + + // Step 4.a.ii. + displayDefault = "auto"; + } + + // Step 5. + var displayField = unit + "Display"; + + // Step 6. + var displayOption = GetOption( + options, + displayField, + "string", + ["auto", "always"], + undefined + ); + + var display = displayOption ?? displayDefault; + + // Step 7. + if (display === "always" && isFractional) { + assert( + styleOption !== undefined || displayOption !== undefined, + "no error is thrown when both 'style' and 'display' are absent" + ); + + ThrowRangeError( + // eslint-disable-next-line no-nested-ternary + styleOption !== undefined && displayOption !== undefined + ? JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION + : displayOption !== undefined + ? JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_STYLE + : JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_DISPLAY, + unit + ); + } + + // Steps 8-9. + if (prevStyle === "numeric" || prevStyle === "2-digit") { + // Step 8.a. and 9.a. + if (style !== "numeric" && style !== "2-digit") { + ThrowRangeError( + JSMSG_INTL_DURATION_INVALID_NON_NUMERIC_OPTION, + unit, + `"${style}"` + ); + } + + // Step 9.b. + else if (unit === "minutes" || unit === "seconds") { + style = "2-digit"; + } + } + + // Step 10. (Our implementation doesn't use |twoDigitHours|.) + + // Step 11. + return { style, display }; +} + +/** + * Returns the subset of the given locale list for which this locale list has a + * matching (possibly fallback) locale. Locales appear in the same order in the + * returned list as in the input list. + */ +function Intl_DurationFormat_supportedLocalesOf(locales /*, options*/) { + var options = ArgumentsLength() > 1 ? GetArgument(1) : undefined; + + // Step 1. + var availableLocales = "DurationFormat"; + + // Step 2. + var requestedLocales = CanonicalizeLocaleList(locales); + + // Step 3. + return SupportedLocales(availableLocales, requestedLocales, options); +} + +/** + * ToIntegerIfIntegral ( argument ) + */ +function ToIntegerIfIntegral(argument) { + // Step 1. + var number = ToNumber(argument); + + // Step 2. + if (!Number_isInteger(number)) { + ThrowRangeError(JSMSG_INTL_DURATION_NOT_INTEGER, number); + } + + // Step 3. + // + // Add +0 to normalize -0 to +0. + return number + 0; +} + +/** + * ToDurationRecord ( input ) + */ +function ToDurationRecord(input) { + // Step 1. + if (!IsObject(input)) { + // Step 1.a. + if (typeof input === "string") { + ThrowRangeError(JSMSG_INTL_DURATION_UNEXPECTED_STRING); + } + + // Step 1.b. + ThrowTypeError( + JSMSG_OBJECT_REQUIRED, + input === null ? "null" : typeof input + ); + } + + // Step 2. + var result = { + years: 0, + months: 0, + weeks: 0, + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0, + microseconds: 0, + nanoseconds: 0, + }; + + // Step 3. + var days = input.days; + + // Step 4. + if (days !== undefined) { + result.days = ToIntegerIfIntegral(days); + } + + // Step 5. + var hours = input.hours; + + // Step 6. + if (hours !== undefined) { + result.hours = ToIntegerIfIntegral(hours); + } + + // Step 7. + var microseconds = input.microseconds; + + // Step 8. + if (microseconds !== undefined) { + result.microseconds = ToIntegerIfIntegral(microseconds); + } + + // Step 9. + var milliseconds = input.milliseconds; + + // Step 10. + if (milliseconds !== undefined) { + result.milliseconds = ToIntegerIfIntegral(milliseconds); + } + + // Step 11. + var minutes = input.minutes; + + // Step 12. + if (minutes !== undefined) { + result.minutes = ToIntegerIfIntegral(minutes); + } + + // Step 13. + var months = input.months; + + // Step 14. + if (months !== undefined) { + result.months = ToIntegerIfIntegral(months); + } + + // Step 15. + var nanoseconds = input.nanoseconds; + + // Step 16. + if (nanoseconds !== undefined) { + result.nanoseconds = ToIntegerIfIntegral(nanoseconds); + } + + // Step 17. + var seconds = input.seconds; + + // Step 18. + if (seconds !== undefined) { + result.seconds = ToIntegerIfIntegral(seconds); + } + + // Step 19. + var weeks = input.weeks; + + // Step 20. + if (weeks !== undefined) { + result.weeks = ToIntegerIfIntegral(weeks); + } + + // Step 21. + var years = input.years; + + // Step 22. + if (years !== undefined) { + result.years = ToIntegerIfIntegral(years); + } + + // Step 23. + if ( + years === undefined && + months === undefined && + weeks === undefined && + days === undefined && + hours === undefined && + minutes === undefined && + seconds === undefined && + milliseconds === undefined && + microseconds === undefined && + nanoseconds === undefined + ) { + ThrowTypeError(JSMSG_INTL_DURATION_MISSING_UNIT); + } + + // Step 24. + if (!IsValidDurationSign(result)) { + ThrowRangeError(JSMSG_INTL_DURATION_INVALID_SIGN); + } + if (!IsValidDurationLimit(result)) { + ThrowRangeError(JSMSG_INTL_DURATION_INVALID_LIMIT); + } + + // Step 25. + return result; +} + +/** + * DurationSign ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ) + */ +function DurationSign(record) { + assert(IsObject(record), "record is an object"); + assert(Number_isInteger(record.years), "record.years is an integer"); + assert(Number_isInteger(record.months), "record.months is an integer"); + assert(Number_isInteger(record.weeks), "record.weeks is an integer"); + assert(Number_isInteger(record.days), "record.days is an integer"); + assert(Number_isInteger(record.hours), "record.hours is an integer"); + assert(Number_isInteger(record.minutes), "record.minutes is an integer"); + assert(Number_isInteger(record.seconds), "record.seconds is an integer"); + assert( + Number_isInteger(record.milliseconds), + "record.milliseconds is an integer" + ); + assert( + Number_isInteger(record.microseconds), + "record.microseconds is an integer" + ); + assert( + Number_isInteger(record.nanoseconds), + "record.nanoseconds is an integer" + ); + + // Steps 1-2. (Loop unrolled) + return ( + std_Math_sign(record.years) || + std_Math_sign(record.months) || + std_Math_sign(record.weeks) || + std_Math_sign(record.days) || + std_Math_sign(record.hours) || + std_Math_sign(record.minutes) || + std_Math_sign(record.seconds) || + std_Math_sign(record.milliseconds) || + std_Math_sign(record.microseconds) || + std_Math_sign(record.nanoseconds) + ); +} + +/** + * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ) + */ +function IsValidDurationSign(record) { + // Step 1. + var sign = DurationSign(record); + + // Fast-path for an all-zero duration. + if (sign === 0) { + return true; + } + + // Step 2. (Loop unrolled) + if ( + std_Math_sign(record.years) === -sign || + std_Math_sign(record.months) === -sign || + std_Math_sign(record.weeks) === -sign || + std_Math_sign(record.days) === -sign || + std_Math_sign(record.hours) === -sign || + std_Math_sign(record.minutes) === -sign || + std_Math_sign(record.seconds) === -sign || + std_Math_sign(record.milliseconds) === -sign || + std_Math_sign(record.microseconds) === -sign || + std_Math_sign(record.nanoseconds) === -sign + ) { + return false; + } + + // Steps 3-8. (Performed in caller) + + // Step 9. + return true; +} + +/** + * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ) + */ +function IsValidDurationLimit(record) { + // Steps 1-2. (Performed in caller) + assert(IsValidDurationSign(record), "duration has the correct sign"); + + // Steps 3-5. + if ( + std_Math_abs(record.years) >= 2**32 || + std_Math_abs(record.months) >= 2**32 || + std_Math_abs(record.weeks) >= 2**32 + ) { + return false; + } + + // Steps 6-7. + var normalizedSeconds = ( + record.days * 86_400 + + record.hours * 3600 + + record.minutes * 60 + + record.seconds + ); + + var milliseconds = record.milliseconds; + var microseconds = record.microseconds; + var nanoseconds = record.nanoseconds; + if ( + std_Math_abs(milliseconds) < 2 ** 53 && + std_Math_abs(microseconds) < 2 ** 53 && + std_Math_abs(nanoseconds) < 2 ** 53 + ) { + // Fast case for safe integers. + normalizedSeconds += ( + std_Math_trunc(milliseconds / 1e3) + + std_Math_trunc(microseconds / 1e6) + + std_Math_trunc(nanoseconds / 1e9) + ); + } else { + // Slow case for too large numbers. + normalizedSeconds += BigIntToNumber( + NumberToBigInt(milliseconds) / 1_000n + + NumberToBigInt(microseconds) / 1_000_000n + + NumberToBigInt(nanoseconds) / 1_000_000_000n + ); + } + normalizedSeconds += std_Math_trunc(( + (milliseconds % 1e3) * 1e6 + + (microseconds % 1e6) * 1e3 + + (nanoseconds % 1e9) + ) / 1e9); + + // Step 8. + if (std_Math_abs(normalizedSeconds) >= 2**53) { + return false; + } + + // Step 9. + return true; +} + +#ifdef DEBUG +/** + * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ) + */ +function IsValidDuration(record) { + return IsValidDurationSign(record) && IsValidDurationLimit(record); +} +#endif + +/** + * ComputeFractionalDigits ( durationFormat, duration ) + * + * Return the fractional seconds from |duration| as an exact value. This is + * either an integer Number value when the fractional part is zero, or a + * decimal string when the fractional part is non-zero. + */ +function ComputeFractionalDigits(duration, unit) { + assert( + IsValidDuration(duration), + "DurationToFractional called with non-valid duration" + ); + + var exponent; + if (unit === "seconds") { + exponent = 9; + } else if (unit === "milliseconds") { + exponent = 6; + } else { + assert(unit === "microseconds", "unexpected unit"); + exponent = 3; + } + + // Directly return the duration amount when no sub-seconds are present. + switch (exponent) { + case 9: { + if ( + duration.milliseconds === 0 && + duration.microseconds === 0 && + duration.nanoseconds === 0 + ) { + return duration.seconds; + } + break; + } + + case 6: { + if (duration.microseconds === 0 && duration.nanoseconds === 0) { + return duration.milliseconds; + } + break; + } + + case 3: { + if (duration.nanoseconds === 0) { + return duration.microseconds; + } + break; + } + } + + // Otherwise compute the overall amount of nanoseconds using BigInt to avoid + // loss of precision. + var ns = NumberToBigInt(duration.nanoseconds); + switch (exponent) { + case 9: + ns += NumberToBigInt(duration.seconds) * 1_000_000_000n; + // fallthrough + case 6: + ns += NumberToBigInt(duration.milliseconds) * 1_000_000n; + // fallthrough + case 3: + ns += NumberToBigInt(duration.microseconds) * 1_000n; + } + + var e = NumberToBigInt(10 ** exponent); + + // Split the nanoseconds amount into an integer and its fractional part. + var q = ns / e; + var r = ns % e; + + // Pad fractional part, without any leading negative sign, to |exponent| digits. + if (r < 0) { + r = -r; + } + r = callFunction(String_pad_start, ToString(r), exponent, "0"); + + // Return the result as a decimal string. + return `${q}.${r}`; +} + +/** + * FormatNumericHours ( durationFormat, hoursValue, signDisplayed ) + * FormatNumericMinutes ( durationFormat, minutesValue, hoursDisplayed, signDisplayed ) + * FormatNumericSeconds ( durationFormat, secondsValue, minutesDisplayed, signDisplayed ) + */ +function FormatNumericHoursOrMinutesOrSeconds( + internals, + value, + style, + unit, + signDisplayed, + formatToParts +) { + assert( + unit === "hour" || unit === "minute" || unit === "second", + "unexpected unit: " + unit + ); + + // FormatNumericHours, step 1. (Not applicable in our implementation.) + // FormatNumericMinutes, steps 1-3. (Not applicable in our implementation.) + // FormatNumericSeconds, step 1. (Not applicable in our implementation.) + + // FormatNumericHours, step 2. + // FormatNumericMinutes, step 4. + // FormatNumericSeconds, step 2. + assert(style === "numeric" || style === "2-digit", "invalid style: " + style); + + // FormatNumericHours, step 3. (Not applicable in our implementation.) + // FormatNumericSeconds, steps 3-4. (Not applicable in our implementation.) + + // FormatNumericHours, step 4. + // FormatNumericMinutes, step 5. + // FormatNumericSeconds, step 5. + var nfOpts = std_Object_create(null); + + // FormatNumericHours, step 5-6. + // FormatNumericMinutes, steps 6-7. + // FormatNumericSeconds, steps 6-7. + nfOpts.numberingSystem = internals.numberingSystem; + + // FormatNumericHours, step 7. + // FormatNumericMinutes, step 8. + // FormatNumericSeconds, step 8. + if (style === "2-digit") { + nfOpts.minimumIntegerDigits = 2; + } + + // FormatNumericHours, step 8. + // FormatNumericMinutes, step 9. + // FormatNumericSeconds, step 9. + if (!signDisplayed) { + nfOpts.signDisplay = "never"; + } + + // FormatNumericHours, step 9. + // FormatNumericMinutes, step 10. + // FormatNumericSeconds, step 10. + nfOpts.useGrouping = false; + + if (unit === "second") { + // FormatNumericSeconds, steps 11-14. + var fractionalDigits = internals.fractionalDigits; + nfOpts.maximumFractionDigits = fractionalDigits ?? 9; + nfOpts.minimumFractionDigits = fractionalDigits ?? 0; + + // FormatNumericSeconds, step 15. + nfOpts.roundingMode = "trunc"; + } + + // FormatNumericHours, step 10. + // FormatNumericMinutes, step 11. + // FormatNumericSeconds, step 16. + var nf = intl_NumberFormat(internals.locale, nfOpts); + + // FormatNumericHours, step 11. + // FormatNumericMinutes, step 12. + // FormatNumericSeconds, step 17. + var parts = intl_FormatNumber(nf, value, formatToParts); + + // FormatNumericHours, step 12. + // FormatNumericMinutes, step 13. + // FormatNumericSeconds, step 18. + if (formatToParts) { + assert(IsArray(parts), "parts is an array"); + + // Modify the parts in-place instead of creating new objects. + for (var i = 0; i < parts.length; i++) { + DefineDataProperty(parts[i], "unit", unit); + } + } + + // FormatNumericHours, step 13. + // FormatNumericMinutes, step 14. + // FormatNumericSeconds, step 19. + return parts; +} + +/* eslint-disable complexity */ +/** + * FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed ) + */ +function FormatNumericUnits( + internals, + duration, + firstNumericUnit, + signDisplayed, + formatToParts +) { + // Step 1. + assert( + firstNumericUnit === "hours" || + firstNumericUnit === "minutes" || + firstNumericUnit === "seconds", + "invalid numeric unit: " + firstNumericUnit + ); + + // Step 2. + var numericPartsList; + if (formatToParts) { + numericPartsList = []; + } else { + numericPartsList = ""; + } + + // Step 3. + var hoursValue = duration.hours; + + // Step 4. + var hoursDisplay = internals.hoursDisplay; + + // Step 5. + var minutesValue = duration.minutes; + + // Step 6. + var minutesDisplay = internals.minutesDisplay; + + // Steps 7-8. + var secondsValue = ComputeFractionalDigits(duration, "seconds"); + + // Step 9. + var secondsDisplay = internals.secondsDisplay; + + // Step 10. + var hoursFormatted = false; + + // Step 11. + if (firstNumericUnit === "hours") { + // Step 11.a. + hoursFormatted = hoursValue !== 0 || hoursDisplay === "always"; + } + + // Steps 12-13. + var secondsFormatted = secondsValue !== 0 || secondsDisplay === "always"; + + // Step 14. + var minutesFormatted = false; + + // Step 15. + if (firstNumericUnit === "hours" || firstNumericUnit === "minutes") { + // Steps 15.a-b. + minutesFormatted = ( + (hoursFormatted && secondsFormatted) || + minutesValue !== 0 || + minutesDisplay === "always" + ); + } + + // Return early when no units are displayed. + if (!hoursFormatted && !minutesFormatted && !secondsFormatted) { + return undefined; + } + + var timeSeparator; + if ( + (minutesFormatted && hoursFormatted) || + (secondsFormatted && minutesFormatted) + ) { + timeSeparator = intl_GetTimeSeparator( + internals.locale, + internals.numberingSystem + ); + } + + // Step 16. + if (hoursFormatted) { + // Step 16.a. + if (signDisplayed && hoursValue === 0 && DurationSign(duration) < 0) { + hoursValue = -0; + } + + // Step 16.b. + var hoursParts = FormatNumericHoursOrMinutesOrSeconds( + internals, + hoursValue, + internals.hoursStyle, + "hour", + signDisplayed, + formatToParts + ); + if (formatToParts) { + for (var i = 0; i < hoursParts.length; i++) { + DefineDataProperty(numericPartsList, numericPartsList.length, hoursParts[i]); + } + } else { + numericPartsList += hoursParts; + } + + // Step 16.c. + signDisplayed = false; + } + + // Step 17. + if (minutesFormatted) { + // Step 17.a. + if (signDisplayed && minutesValue === 0 && DurationSign(duration) < 0) { + minutesValue = -0; + } + + // Step 17.b. + if (hoursFormatted) { + if (formatToParts) { + DefineDataProperty(numericPartsList, numericPartsList.length, { + type: "literal", + value: timeSeparator, + }); + } else { + numericPartsList += timeSeparator; + } + } + + var minutesParts = FormatNumericHoursOrMinutesOrSeconds( + internals, + minutesValue, + internals.minutesStyle, + "minute", + signDisplayed, + formatToParts + ); + if (formatToParts) { + for (var i = 0; i < minutesParts.length; i++) { + DefineDataProperty(numericPartsList, numericPartsList.length, minutesParts[i]); + } + } else { + numericPartsList += minutesParts; + } + + // Step 17.c. + signDisplayed = false; + } + + // Step 18. + if (secondsFormatted) { + // Step 18.a. + if (minutesFormatted) { + if (formatToParts) { + DefineDataProperty(numericPartsList, numericPartsList.length, { + type: "literal", + value: timeSeparator, + }); + } else { + numericPartsList += timeSeparator; + } + } + + var secondsParts = FormatNumericHoursOrMinutesOrSeconds( + internals, + secondsValue, + internals.secondsStyle, + "second", + signDisplayed, + formatToParts + ); + if (formatToParts) { + for (var i = 0; i < secondsParts.length; i++) { + DefineDataProperty(numericPartsList, numericPartsList.length, secondsParts[i]); + } + } else { + numericPartsList += secondsParts; + } + } + + // Step 19. + return numericPartsList; +} +/* eslint-enable complexity */ + +/** + * ListFormatParts ( durationFormat, partitionedPartsList ) + */ +function ListFormatParts(internals, partitionedPartsList, formatToParts) { + assert(IsArray(partitionedPartsList), "partitionedPartsList is an array"); + + // Step 1. + var lfOpts = std_Object_create(null); + + // Step 2. + lfOpts.type = "unit"; + + // Step 3. + var listStyle = internals.style; + + // Step 4. + if (listStyle === "digital") { + listStyle = "short"; + } + + // Step 5. + lfOpts.style = listStyle; + + // Step 6. + var ListFormat = GetBuiltinConstructor("ListFormat"); + var lf = new ListFormat(internals.locale, lfOpts); + + // Steps 7-14. + if (!formatToParts) { + return intl_FormatList(lf, partitionedPartsList, /* formatToParts = */ false); + } + + // requires + // that the list patterns are sorted, for example "{1} and {0}" isn't a valid + // pattern, because "{1}" appears before "{0}". This requirement also means + // all entries appear in order in the formatted result. + + // Step 7. + var strings = []; + + // Step 8. + for (var i = 0; i < partitionedPartsList.length; i++) { + var parts = partitionedPartsList[i]; + assert(IsArray(parts), "parts is an array"); + + // Step 8.a. + var string = ""; + + // Step 8.b. + // + // Combine the individual number-formatted parts into a single string. + for (var j = 0; j < parts.length; j++) { + var part = parts[j]; + assert( + hasOwn("type", part) && + hasOwn("value", part) && + typeof part.value === "string", + "part is a number-formatted element" + ); + + string += part.value; + } + + // Step 8.c. + DefineDataProperty(strings, strings.length, string); + } + + // Step 9. + var formattedPartsList = intl_FormatList(lf, strings, /* formatToParts = */ true); + + // Step 10. + var partitionedPartsIndex = 0; + + // Step 11. (Not applicable in our implementation.) + + // Step 12. + var flattenedPartsList = []; + + // Step 13. + for (var i = 0; i < formattedPartsList.length; i++) { + var listPart = formattedPartsList[i]; + assert( + hasOwn("type", listPart) && + hasOwn("value", listPart) && + typeof listPart.type === "string", + "part is a list-formatted element" + ); + + // Steps 13.a-b. + if (listPart.type === "element") { + // Step 13.a.i. + assert( + partitionedPartsIndex < partitionedPartsList.length, + "resultIndex is an index into result" + ); + + // Step 13.a.ii. + var parts = partitionedPartsList[partitionedPartsIndex]; + assert(IsArray(parts), "parts is an array"); + + // Step 13.a.iii. + // + // Replace "element" parts with the number-formatted result. + for (var j = 0; j < parts.length; j++) { + DefineDataProperty(flattenedPartsList, flattenedPartsList.length, parts[j]); + } + + // Step 13.a.iv. + partitionedPartsIndex += 1; + } else { + // Step 13.b.i. + assert(listPart.type === "literal", "literal part"); + + // Step 13.b.ii. + // + // Append "literal" parts as-is. + DefineDataProperty(flattenedPartsList, flattenedPartsList.length, listPart); + } + } + assert( + partitionedPartsIndex === partitionedPartsList.length, + "all number-formatted parts handled" + ); + + // Step 14. + return flattenedPartsList; +} + +/** + * PartitionDurationFormatPattern ( durationFormat, duration ) + */ +function PartitionDurationFormatPattern( + durationFormat, + duration, + formatToParts +) { + assert( + IsObject(durationFormat), + "PartitionDurationFormatPattern called with non-object" + ); + assert( + intl_GuardToDurationFormat(durationFormat) !== null, + "PartitionDurationFormatPattern called with non-DurationFormat" + ); + assert( + IsValidDuration(duration), + "PartitionDurationFormatPattern called with non-valid duration" + ); + assert( + typeof formatToParts === "boolean", + "PartitionDurationFormatPattern called with non-boolean formatToParts" + ); + + var units = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + ]; + + var internals = getDurationFormatInternals(durationFormat); + + // Step 1. + var result = []; + + // Step 2. + var signDisplayed = true; + + // Step 3. + var numericUnitFound = false; + + // Step 4. + for (var i = 0; !numericUnitFound && i < units.length; i++) { + // Step 4.d. (Reordered) + var unit = units[i]; + + // Step 4.a. + var value = duration[unit]; + + // Step 4.b. + var style = internals[unit + "Style"]; + + // Step 4.c. + var display = internals[unit + "Display"]; + + // Step 4.d. (Moved above) + + // Steps 4.e-f. + if (style === "numeric" || style === "2-digit") { + // Step 4.e.1. + var numericPartsList = FormatNumericUnits( + internals, + duration, + unit, + signDisplayed, + formatToParts + ); + if (numericPartsList !== undefined) { + DefineDataProperty(result, result.length, numericPartsList); + } + + // Step 4.e.2. + numericUnitFound = true; + } else { + // Step 4.f.i. + var nfOpts = std_Object_create(null); + + // Step 4.f.ii. + if ( + unit === "seconds" || + unit === "milliseconds" || + unit === "microseconds" + ) { + // Step 4.f.ii.1. + if (internals[units[i + 1] + "Style"] === "numeric") { + // Step 4.f.ii.1.a. + value = ComputeFractionalDigits(duration, unit); + + // Steps 4.f.ii.1.b-e. + var fractionalDigits = internals.fractionalDigits; + nfOpts.maximumFractionDigits = fractionalDigits ?? 9; + nfOpts.minimumFractionDigits = fractionalDigits ?? 0; + + // Step 4.f.ii.1.f. + nfOpts.roundingMode = "trunc"; + + // Step 4.f.ii.1.g. + numericUnitFound = true; + } + } + + // Step 4.f.iii. (Condition inverted to reduce indentation.) + if (value === 0 && display === "auto") { + continue; + } + + // Steps 4.f.iii.1-2. + nfOpts.numberingSystem = internals.numberingSystem; + + // Steps 4.f.iii.3-4. + if (signDisplayed) { + // Step 4.f.iii.3.a. + signDisplayed = false; + + // Step 4.f.iii.3.b. + if (value === 0 && DurationSign(duration) < 0) { + value = -0; + } + } else { + // Step 4.f.iii.4.b. + nfOpts.signDisplay = "never"; + } + + // Step 4.f.iii.5. + // + // Remove the trailing 's' from the unit name. + var numberFormatUnit = Substring(unit, 0, unit.length - 1); + + // Step 4.f.iii.6. + nfOpts.style = "unit"; + + // Step 4.f.iii.7. + nfOpts.unit = numberFormatUnit; + + // Step 4.f.iii.8. + nfOpts.unitDisplay = style; + + // Step 4.f.iii.9. + var nf = intl_NumberFormat(internals.locale, nfOpts); + + // Step 4.f.iii.10. + var parts = intl_FormatNumber(nf, value, formatToParts); + + // Steps 4.f.iii.11-12. + if (formatToParts) { + assert(IsArray(parts), "parts is an array"); + + // Modify the parts in-place instead of creating new objects. + for (var j = 0; j < parts.length; j++) { + DefineDataProperty(parts[j], "unit", numberFormatUnit); + } + } + + // Step 4.f.iii.13. + DefineDataProperty(result, result.length, parts); + } + } + + // Step 5. + return ListFormatParts(internals, result, formatToParts); +} + +/** + * Intl.DurationFormat.prototype.format ( durationLike ) + */ +function Intl_DurationFormat_format(durationLike) { + // Step 1. + var df = this; + + // Step 2. + if (!IsObject(df) || (df = intl_GuardToDurationFormat(df)) === null) { + return callFunction( + intl_CallDurationFormatMethodIfWrapped, + this, + durationLike, + "Intl_DurationFormat_format" + ); + } + + // Step 3. + var duration = ToTemporalDuration(durationLike); + + // Fallback if Temporal is disabled. + if (duration === null) { + duration = ToDurationRecord(durationLike); + } + + // Steps 4-7. + return PartitionDurationFormatPattern( + df, + duration, + /* formatToParts = */ false + ); +} + +/** + * Intl.DurationFormat.prototype.formatToParts ( durationLike ) + */ +function Intl_DurationFormat_formatToParts(durationLike) { + // Step 1. + var df = this; + + // Step 2. + if (!IsObject(df) || (df = intl_GuardToDurationFormat(df)) === null) { + return callFunction( + intl_CallDurationFormatMethodIfWrapped, + this, + durationLike, + "Intl_DurationFormat_formatToParts" + ); + } + + // Step 3. + var duration = ToTemporalDuration(durationLike); + + // Fallback if Temporal is disabled. + if (duration === null) { + duration = ToDurationRecord(durationLike); + } + + // Steps 4-8. + return PartitionDurationFormatPattern(df, duration, /* formatToParts = */ true); +} + +/** + * Returns the resolved options for a DurationFormat object. + */ +function Intl_DurationFormat_resolvedOptions() { + // Step 1. + var durationFormat = this; + + // Step 2. + if ( + !IsObject(durationFormat) || + (durationFormat = intl_GuardToDurationFormat(durationFormat)) === null + ) { + return callFunction( + intl_CallDurationFormatMethodIfWrapped, + this, + "Intl_DurationFormat_resolvedOptions" + ); + } + + var internals = getDurationFormatInternals(durationFormat); + + // Steps 3-4. + var result = { + locale: internals.locale, + numberingSystem: internals.numberingSystem, + style: internals.style, + years: internals.yearsStyle, + yearsDisplay: internals.yearsDisplay, + months: internals.monthsStyle, + monthsDisplay: internals.monthsDisplay, + weeks: internals.weeksStyle, + weeksDisplay: internals.weeksDisplay, + days: internals.daysStyle, + daysDisplay: internals.daysDisplay, + hours: internals.hoursStyle, + hoursDisplay: internals.hoursDisplay, + minutes: internals.minutesStyle, + minutesDisplay: internals.minutesDisplay, + seconds: internals.secondsStyle, + secondsDisplay: internals.secondsDisplay, + milliseconds: internals.millisecondsStyle, + millisecondsDisplay: internals.millisecondsDisplay, + microseconds: internals.microsecondsStyle, + microsecondsDisplay: internals.microsecondsDisplay, + nanoseconds: internals.nanosecondsStyle, + nanosecondsDisplay: internals.nanosecondsDisplay, + }; + + if (internals.fractionalDigits !== undefined) { + DefineDataProperty(result, "fractionalDigits", internals.fractionalDigits); + } + + // Step 5. + return result; +} diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/FormatBuffer.h b/src/third_party/mozjs/extract/js/src/builtin/intl/FormatBuffer.h index 42118e77d88..613bfb3d71b 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/FormatBuffer.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/FormatBuffer.h @@ -15,7 +15,6 @@ #include #include "js/AllocPolicy.h" -#include "js/CharacterEncoding.h" #include "js/TypeDecls.h" #include "js/UniquePtr.h" #include "js/Vector.h" @@ -99,23 +98,10 @@ class FormatBuffer { /** * Copies the buffer's data to a JSString. - * - * TODO(#1715842) - This should be more explicit on needing to handle OOM - * errors. In this case it returns a nullptr that must be checked, but it may - * not be obvious. */ JSLinearString* toString(JSContext* cx) const { - if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v) { - // Handle the UTF-8 encoding case. - return NewStringCopyUTF8N( - cx, JS::UTF8Chars(buffer_.begin(), buffer_.length())); - } else { - // Handle the UTF-16 encoding case. - static_assert(std::is_same_v); - return NewStringCopyN(cx, buffer_.begin(), buffer_.length()); - } + static_assert(std::is_same_v); + return NewStringCopyN(cx, buffer_.begin(), buffer_.length()); } /** diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/IntlObject.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/IntlObject.cpp index f504aca2891..f7482fd9794 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/IntlObject.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/IntlObject.cpp @@ -116,8 +116,8 @@ static void ReportBadKey(JSContext* cx, JSString* key) { } } -static bool SameOrParentLocale(JSLinearString* locale, - JSLinearString* otherLocale) { +static bool SameOrParentLocale(const JSLinearString* locale, + const JSLinearString* otherLocale) { // Return true if |locale| is the same locale as |otherLocale|. if (locale->length() == otherLocale->length()) { return EqualStrings(locale, otherLocale); @@ -234,6 +234,8 @@ bool js::intl_BestAvailableLocale(JSContext* cx, unsigned argc, Value* vp) { kind = SupportedLocaleKind::DateTimeFormat; } else if (StringEqualsLiteral(typeStr, "DisplayNames")) { kind = SupportedLocaleKind::DisplayNames; + } else if (StringEqualsLiteral(typeStr, "DurationFormat")) { + kind = SupportedLocaleKind::DurationFormat; } else if (StringEqualsLiteral(typeStr, "ListFormat")) { kind = SupportedLocaleKind::ListFormat; } else if (StringEqualsLiteral(typeStr, "NumberFormat")) { @@ -296,12 +298,7 @@ bool js::intl_BestAvailableLocale(JSContext* cx, unsigned argc, Value* vp) { return false; } - JSLinearString* tagStr = buffer.toString(cx); - if (!tagStr) { - return false; - } - - MOZ_ASSERT(EqualStrings(locale, tagStr), + MOZ_ASSERT(StringEqualsAscii(locale, buffer.data(), buffer.length()), "locale is a canonicalized language tag"); } #endif @@ -419,6 +416,7 @@ bool js::intl_supportedLocaleOrFallback(JSContext* cx, unsigned argc, // the set of supported locales of Intl.DateTimeFormat. for (auto kind : { SupportedLocaleKind::DisplayNames, + SupportedLocaleKind::DurationFormat, SupportedLocaleKind::ListFormat, SupportedLocaleKind::NumberFormat, SupportedLocaleKind::PluralRules, @@ -733,8 +731,7 @@ static ArrayObject* AvailableNumberingSystems(JSContext* cx) { * AvailableTimeZones ( ) */ static ArrayObject* AvailableTimeZones(JSContext* cx) { - // Unsorted list of canonical time zone names, possibly containing - // duplicates. + // Unsorted list of canonical time zone names, possibly containing duplicates. Rooted timeZones(cx, StringList(cx)); intl::SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); @@ -745,54 +742,15 @@ static ArrayObject* AvailableTimeZones(JSContext* cx) { auto iter = iterResult.unwrap(); Rooted validatedTimeZone(cx); - Rooted ianaTimeZone(cx); for (; !iter.done(); iter.next()) { validatedTimeZone = iter.get(); // Canonicalize the time zone before adding it to the result array. - - // Some time zone names are canonicalized differently by ICU -- handle - // those first. - ianaTimeZone.set(nullptr); - if (!sharedIntlData.tryCanonicalizeTimeZoneConsistentWithIANA( - cx, validatedTimeZone, &ianaTimeZone)) { + auto* timeZone = intl::CanonicalizeTimeZone(cx, validatedTimeZone); + if (!timeZone) { return nullptr; } - JSLinearString* timeZone; - if (ianaTimeZone) { - cx->markAtom(ianaTimeZone); - - timeZone = ianaTimeZone; - } else { - // Call into ICU to canonicalize the time zone. - - JS::AutoStableStringChars stableChars(cx); - if (!stableChars.initTwoByte(cx, validatedTimeZone)) { - return nullptr; - } - - intl::FormatBuffer - canonicalTimeZone(cx); - auto result = mozilla::intl::TimeZone::GetCanonicalTimeZoneID( - stableChars.twoByteRange(), canonicalTimeZone); - if (result.isErr()) { - intl::ReportInternalError(cx, result.unwrapErr()); - return nullptr; - } - - timeZone = canonicalTimeZone.toString(cx); - if (!timeZone) { - return nullptr; - } - - // Canonicalize both to "UTC" per CanonicalizeTimeZoneName(). - if (StringEqualsLiteral(timeZone, "Etc/UTC") || - StringEqualsLiteral(timeZone, "Etc/GMT")) { - timeZone = cx->names().UTC; - } - } - if (!timeZones.append(timeZone)) { return nullptr; } @@ -866,10 +824,13 @@ static const JSFunctionSpec intl_static_methods[] = { JS_FN("toSource", intl_toSource, 0, 0), JS_SELF_HOSTED_FN("getCanonicalLocales", "Intl_getCanonicalLocales", 1, 0), JS_SELF_HOSTED_FN("supportedValuesOf", "Intl_supportedValuesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSPropertySpec intl_static_properties[] = { - JS_STRING_SYM_PS(toStringTag, "Intl", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "Intl", JSPROP_READONLY), + JS_PS_END, +}; static JSObject* CreateIntlObject(JSContext* cx, JSProtoKey key) { RootedObject proto(cx, &cx->global()->getObjectPrototype()); @@ -892,6 +853,7 @@ static bool IntlClassFinish(JSContext* cx, HandleObject intl, JSProto_Collator, JSProto_DateTimeFormat, JSProto_DisplayNames, + JSProto_DurationFormat, JSProto_ListFormat, JSProto_Locale, JSProto_NumberFormat, @@ -920,7 +882,12 @@ static bool IntlClassFinish(JSContext* cx, HandleObject intl, static const ClassSpec IntlClassSpec = { CreateIntlObject, nullptr, intl_static_methods, intl_static_properties, - nullptr, nullptr, IntlClassFinish}; + nullptr, nullptr, IntlClassFinish, +}; -const JSClass js::IntlClass = {"Intl", JSCLASS_HAS_CACHED_PROTO(JSProto_Intl), - JS_NULL_CLASS_OPS, &IntlClassSpec}; +const JSClass js::IntlClass = { + "Intl", + JSCLASS_HAS_CACHED_PROTO(JSProto_Intl), + JS_NULL_CLASS_OPS, + &IntlClassSpec, +}; diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/LanguageTag.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/LanguageTag.cpp index 3372f5d99a4..eee32d2259a 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/LanguageTag.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/LanguageTag.cpp @@ -109,7 +109,7 @@ static bool IsAsciiLowercaseAlpha(mozilla::Span span) { return std::all_of(ptr, ptr + length, mozilla::IsAsciiLowercaseAlpha); } -static bool IsAsciiLowercaseAlpha(JSLinearString* str) { +static bool IsAsciiLowercaseAlpha(const JSLinearString* str) { JS::AutoCheckCannotGC nogc; if (str->hasLatin1Chars()) { return IsAsciiLowercaseAlpha(str->latin1Range(nogc)); @@ -127,7 +127,7 @@ static bool IsAsciiAlpha(mozilla::Span span) { return std::all_of(ptr, ptr + length, mozilla::IsAsciiAlpha); } -static bool IsAsciiAlpha(JSLinearString* str) { +static bool IsAsciiAlpha(const JSLinearString* str) { JS::AutoCheckCannotGC nogc; if (str->hasLatin1Chars()) { return IsAsciiAlpha(str->latin1Range(nogc)); diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/ListFormat.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/ListFormat.cpp index decd6fe7b8a..4e90abc9d59 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/ListFormat.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/ListFormat.cpp @@ -44,7 +44,9 @@ const JSClass ListFormatObject::class_ = { JSCLASS_HAS_RESERVED_SLOTS(ListFormatObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_ListFormat) | JSCLASS_FOREGROUND_FINALIZE, - &ListFormatObject::classOps_, &ListFormatObject::classSpec_}; + &ListFormatObject::classOps_, + &ListFormatObject::classSpec_, +}; const JSClass& ListFormatObject::protoClass_ = PlainObject::class_; @@ -57,18 +59,22 @@ static bool listFormat_toSource(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec listFormat_static_methods[] = { JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_ListFormat_supportedLocalesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec listFormat_methods[] = { JS_SELF_HOSTED_FN("resolvedOptions", "Intl_ListFormat_resolvedOptions", 0, 0), JS_SELF_HOSTED_FN("format", "Intl_ListFormat_format", 1, 0), JS_SELF_HOSTED_FN("formatToParts", "Intl_ListFormat_formatToParts", 1, 0), - JS_FN("toSource", listFormat_toSource, 0, 0), JS_FS_END}; + JS_FN("toSource", listFormat_toSource, 0, 0), + JS_FS_END, +}; static const JSPropertySpec listFormat_properties[] = { JS_STRING_SYM_PS(toStringTag, "Intl.ListFormat", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; static bool ListFormat(JSContext* cx, unsigned argc, Value* vp); @@ -80,7 +86,8 @@ const ClassSpec ListFormatObject::classSpec_ = { listFormat_methods, listFormat_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /** * Intl.ListFormat([ locales [, options]]) diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/Locale.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/Locale.cpp index d93f1e62a29..d70e932cd3c 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/Locale.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/Locale.cpp @@ -47,7 +47,9 @@ const JSClass LocaleObject::class_ = { "Intl.Locale", JSCLASS_HAS_RESERVED_SLOTS(LocaleObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_Locale), - JS_NULL_CLASS_OPS, &LocaleObject::classSpec_}; + JS_NULL_CLASS_OPS, + &LocaleObject::classSpec_, +}; const JSClass& LocaleObject::protoClass_ = PlainObject::class_; @@ -74,7 +76,7 @@ struct IndexAndLength { size_t index; size_t length; - IndexAndLength(size_t index, size_t length) : index(index), length(length){}; + IndexAndLength(size_t index, size_t length) : index(index), length(length) {}; template mozilla::Span spanOf(const T* ptr) const { @@ -145,7 +147,7 @@ static LocaleObject* CreateLocaleObject(JSContext* cx, HandleObject prototype, } static inline bool IsValidUnicodeExtensionValue(JSContext* cx, - JSLinearString* linear, + const JSLinearString* linear, bool* isValid) { if (linear->length() == 0) { *isValid = false; @@ -167,7 +169,11 @@ static inline bool IsValidUnicodeExtensionValue(JSContext* cx, return true; } -/** Iterate through (sep keyword) in a valid, lowercased Unicode extension. */ +/** + * Iterate through (sep keyword) in a valid Unicode extension. + * + * The Unicode extension value is not required to be in canonical case. + */ template class SepKeywordIterator { const CharT* iter_; @@ -193,7 +199,8 @@ class SepKeywordIterator { "overall Unicode locale extension or non-leading subtags must " "be at least key-sized"); - MOZ_ASSERT((iter_[0] == 'u' && iter_[1] == '-') || iter_[0] == '-'); + MOZ_ASSERT(((iter_[0] == 'u' || iter_[0] == 'U') && iter_[1] == '-') || + iter_[0] == '-'); while (true) { // Skip past '-' so |std::char_traits::find| makes progress. Skipping @@ -218,9 +225,8 @@ class SepKeywordIterator { } MOZ_ASSERT(iter_[0] == '-'); - MOZ_ASSERT(mozilla::IsAsciiLowercaseAlpha(iter_[1]) || - mozilla::IsAsciiDigit(iter_[1])); - MOZ_ASSERT(mozilla::IsAsciiLowercaseAlpha(iter_[2])); + MOZ_ASSERT(mozilla::IsAsciiAlphanumeric(iter_[1])); + MOZ_ASSERT(mozilla::IsAsciiAlpha(iter_[2])); MOZ_ASSERT_IF(iter_ + SepKeyLength < end_, iter_[SepKeyLength] == '-'); return iter_; } @@ -550,6 +556,12 @@ static bool Locale(JSContext* cx, unsigned argc, Value* vp) { return false; } + if (tag.Language().Length() > 4) { + MOZ_ASSERT(cx->global()); + cx->runtime()->setUseCounter(cx->global(), + JSUseCounter::LEGACY_LANG_SUBTAG); + } + if (auto result = tag.CanonicalizeBaseName(); result.isErr()) { if (result.unwrapErr() == mozilla::intl::Locale::CanonicalizationError::DuplicateVariant) { @@ -797,8 +809,8 @@ static mozilla::Maybe FindUnicodeExtensionType( size_t(endType - beginType)}); } -static inline auto FindUnicodeExtensionType(JSLinearString* unicodeExtension, - UnicodeKey key) { +static inline auto FindUnicodeExtensionType( + const JSLinearString* unicodeExtension, UnicodeKey key) { JS::AutoCheckCannotGC nogc; return unicodeExtension->hasLatin1Chars() ? FindUnicodeExtensionType( @@ -918,7 +930,7 @@ static BaseNamePartsResult BaseNameParts(const CharT* baseName, size_t length) { return {language, script, region}; } -static inline auto BaseNameParts(JSLinearString* baseName) { +static inline auto BaseNameParts(const JSLinearString* baseName) { JS::AutoCheckCannotGC nogc; return baseName->hasLatin1Chars() ? BaseNameParts( @@ -1271,7 +1283,9 @@ static const JSFunctionSpec locale_methods[] = { JS_FN("maximize", Locale_maximize, 0, 0), JS_FN("minimize", Locale_minimize, 0, 0), JS_FN("toString", Locale_toString, 0, 0), - JS_FN("toSource", Locale_toSource, 0, 0), JS_FS_END}; + JS_FN("toSource", Locale_toSource, 0, 0), + JS_FS_END, +}; static const JSPropertySpec locale_properties[] = { JS_PSG("baseName", Locale_baseName, 0), @@ -1285,7 +1299,8 @@ static const JSPropertySpec locale_properties[] = { JS_PSG("script", Locale_script, 0), JS_PSG("region", Locale_region, 0), JS_STRING_SYM_PS(toStringTag, "Intl.Locale", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; const ClassSpec LocaleObject::classSpec_ = { GenericCreateConstructor, @@ -1295,7 +1310,8 @@ const ClassSpec LocaleObject::classSpec_ = { locale_methods, locale_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; bool js::intl_ValidateAndCanonicalizeLanguageTag(JSContext* cx, unsigned argc, Value* vp) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.cpp index 0f849aefff8..20be6cc2c14 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.cpp @@ -74,7 +74,9 @@ const JSClass NumberFormatObject::class_ = { JSCLASS_HAS_RESERVED_SLOTS(NumberFormatObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_NumberFormat) | JSCLASS_FOREGROUND_FINALIZE, - &NumberFormatObject::classOps_, &NumberFormatObject::classSpec_}; + &NumberFormatObject::classOps_, + &NumberFormatObject::classSpec_, +}; const JSClass& NumberFormatObject::protoClass_ = PlainObject::class_; @@ -117,12 +119,13 @@ const ClassSpec NumberFormatObject::classSpec_ = { numberFormat_methods, numberFormat_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /** * 15.1.1 Intl.NumberFormat ( [ locales [ , options ] ] ) * - * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6 + * ES2025 Intl draft rev 5ea95f8a98d660e94c177d6f5e88c6d2962123b1 */ static bool NumberFormat(JSContext* cx, const CallArgs& args, bool construct) { AutoJSConstructorProfilerEntry pseudoFrame(cx, "Intl.NumberFormat"); @@ -147,7 +150,7 @@ static bool NumberFormat(JSContext* cx, const CallArgs& args, bool construct) { HandleValue locales = args.get(0); HandleValue options = args.get(1); - // Step 3. + // Steps 3-33. return intl::InitializeNumberFormatObject(cx, numberFormat, thisValue, locales, options, args.rval()); } @@ -951,7 +954,7 @@ static bool IsNonDecimalNumber(mozilla::Range chars) { return false; } -static bool IsNonDecimalNumber(JSLinearString* str) { +static bool IsNonDecimalNumber(const JSLinearString* str) { JS::AutoCheckCannotGC nogc; return str->hasLatin1Chars() ? IsNonDecimalNumber(str->latin1Range(nogc)) : IsNonDecimalNumber(str->twoByteRange(nogc)); diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.js b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.js index 6dc77fb6397..f11a47f66f5 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.js +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberFormat.js @@ -20,11 +20,11 @@ var numberFormatInternalProperties = { }; /** - * 15.1.2 InitializeNumberFormat ( numberFormat, locales, options ) + * 15.1.1 Intl.NumberFormat ( [ locales [ , options ] ] ) * * Compute an internal properties object from |lazyNumberFormatData|. * - * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6 + * ES2025 Intl draft rev 5ea95f8a98d660e94c177d6f5e88c6d2962123b1 */ function resolveNumberFormatInternals(lazyNumberFormatData) { assert(IsObject(lazyNumberFormatData), "lazy data not an object?"); @@ -35,59 +35,56 @@ function resolveNumberFormatInternals(lazyNumberFormatData) { // Compute effective locale. - // Step 9. - var localeData = NumberFormat.localeData; - - // Step 10. + // Step 11. var r = ResolveLocale( "NumberFormat", lazyNumberFormatData.requestedLocales, lazyNumberFormatData.opt, NumberFormat.relevantExtensionKeys, - localeData + NumberFormat.localeData ); - // Steps 11-13. (Step 12 is not relevant to our implementation.) + // Steps 12-14. (Step 13 is not relevant to our implementation.) internalProps.locale = r.locale; internalProps.numberingSystem = r.nu; // Compute formatting options. - // Step 14. SetNumberFormatUnitOptions, step 4. + // Step 15. SetNumberFormatUnitOptions, step 2. var style = lazyNumberFormatData.style; internalProps.style = style; - // Step 14. SetNumberFormatUnitOptions, step 14. + // Step 15. SetNumberFormatUnitOptions, step 12. if (style === "currency") { internalProps.currency = lazyNumberFormatData.currency; internalProps.currencyDisplay = lazyNumberFormatData.currencyDisplay; internalProps.currencySign = lazyNumberFormatData.currencySign; } - // Step 14. SetNumberFormatUnitOptions, step 15. + // Step 15. SetNumberFormatUnitOptions, step 13. if (style === "unit") { internalProps.unit = lazyNumberFormatData.unit; internalProps.unitDisplay = lazyNumberFormatData.unitDisplay; } - // Step 19. + // Step 18. var notation = lazyNumberFormatData.notation; internalProps.notation = notation; - // Step 20. SetNumberFormatDigitOptions, step 6. + // Step 21. SetNumberFormatDigitOptions, step 6. internalProps.minimumIntegerDigits = lazyNumberFormatData.minimumIntegerDigits; - // Step 20. SetNumberFormatDigitOptions, step 14. + // Step 21. SetNumberFormatDigitOptions, step 14. internalProps.roundingIncrement = lazyNumberFormatData.roundingIncrement; - // Step 20. SetNumberFormatDigitOptions, step 15. + // Step 21. SetNumberFormatDigitOptions, step 15. internalProps.roundingMode = lazyNumberFormatData.roundingMode; - // Step 20. SetNumberFormatDigitOptions, step 16. + // Step 21. SetNumberFormatDigitOptions, step 16. internalProps.trailingZeroDisplay = lazyNumberFormatData.trailingZeroDisplay; - // Step 20. SetNumberFormatDigitOptions, steps 25-26. + // Step 21. SetNumberFormatDigitOptions, steps 25-26. if ("minimumFractionDigits" in lazyNumberFormatData) { // Note: Intl.NumberFormat.prototype.resolvedOptions() exposes the // actual presence (versus undefined-ness) of these properties. @@ -101,7 +98,7 @@ function resolveNumberFormatInternals(lazyNumberFormatData) { lazyNumberFormatData.maximumFractionDigits; } - // Step 20. SetNumberFormatDigitOptions, steps 24 and 26. + // Step 21. SetNumberFormatDigitOptions, steps 24 and 26. if ("minimumSignificantDigits" in lazyNumberFormatData) { // Note: Intl.NumberFormat.prototype.resolvedOptions() exposes the // actual presence (versus undefined-ness) of these properties. @@ -115,18 +112,18 @@ function resolveNumberFormatInternals(lazyNumberFormatData) { lazyNumberFormatData.maximumSignificantDigits; } - // Step 20. SetNumberFormatDigitOptions, steps 26-30. + // Step 21. SetNumberFormatDigitOptions, steps 26-30. internalProps.roundingPriority = lazyNumberFormatData.roundingPriority; - // Step 23. + // Step 24. if (notation === "compact") { internalProps.compactDisplay = lazyNumberFormatData.compactDisplay; } - // Step 28. + // Step 29. internalProps.useGrouping = lazyNumberFormatData.useGrouping; - // Step 30. + // Step 31. internalProps.signDisplay = lazyNumberFormatData.signDisplay; // The caller is responsible for associating |internalProps| with the right @@ -579,7 +576,7 @@ function IsSanctionedSimpleUnitIdentifier(unitIdentifier) { /* eslint-disable complexity */ /** - * 15.1.2 InitializeNumberFormat ( numberFormat, locales, options ) + * 15.1.1 Intl.NumberFormat ( [ locales [ , options ] ] ) * * Initializes an object as a NumberFormat. * @@ -589,7 +586,7 @@ function IsSanctionedSimpleUnitIdentifier(unitIdentifier) { * This later work occurs in |resolveNumberFormatInternals|; steps not noted * here occur there. * - * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6 + * ES2025 Intl draft rev 5ea95f8a98d660e94c177d6f5e88c6d2962123b1 */ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { assert( @@ -660,11 +657,11 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { // subset of them. var lazyNumberFormatData = std_Object_create(null); - // Step 1. + // Step 3. var requestedLocales = CanonicalizeLocaleList(locales); lazyNumberFormatData.requestedLocales = requestedLocales; - // Step 2. (Inlined call to CoerceOptionsToObject.) + // Step 4. (Inlined call to CoerceOptionsToObject.) // // If we ever need more speed here at startup, we should try to detect the // case where |options === undefined| and then directly use the default @@ -677,11 +674,11 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { // Compute options that impact interpretation of locale. - // Step 3. + // Step 5. var opt = new_Record(); lazyNumberFormatData.opt = opt; - // Steps 4-5. + // Steps 6-7. var matcher = GetOption( options, "localeMatcher", @@ -691,7 +688,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { ); opt.localeMatcher = matcher; - // Step 6. + // Step 8. var numberingSystem = GetOption( options, "numberingSystem", @@ -700,7 +697,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { undefined ); - // Step 7. + // Step 9. if (numberingSystem !== undefined) { numberingSystem = intl_ValidateAndCanonicalizeUnicodeExtensionType( numberingSystem, @@ -709,12 +706,12 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { ); } - // Step 8. + // Step 10. opt.nu = numberingSystem; // Compute formatting options. - // Step 14. SetNumberFormatUnitOptions, steps 3-4. + // Step 15. SetNumberFormatUnitOptions, steps 1-2. var style = GetOption( options, "style", @@ -724,10 +721,10 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { ); lazyNumberFormatData.style = style; - // Step 14. SetNumberFormatUnitOptions, step 5. + // Step 15. SetNumberFormatUnitOptions, step 3. var currency = GetOption(options, "currency", "string", undefined, undefined); - // Step 14. SetNumberFormatUnitOptions, steps 6-7. + // Step 15. SetNumberFormatUnitOptions, steps 4-5. if (currency === undefined) { if (style === "currency") { ThrowTypeError(JSMSG_UNDEFINED_CURRENCY); @@ -738,7 +735,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { } } - // Step 14. SetNumberFormatUnitOptions, step 8. + // Step 15. SetNumberFormatUnitOptions, step 6. var currencyDisplay = GetOption( options, "currencyDisplay", @@ -747,7 +744,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { "symbol" ); - // Step 14. SetNumberFormatUnitOptions, step 9. + // Step 15. SetNumberFormatUnitOptions, step 7. var currencySign = GetOption( options, "currencySign", @@ -756,23 +753,23 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { "standard" ); - // Step 14. SetNumberFormatUnitOptions, step 14. (Reordered) + // Step 15. SetNumberFormatUnitOptions, step 12. (Reordered) if (style === "currency") { - // Step 14. SetNumberFormatUnitOptions, step 14.a. + // Step 15. SetNumberFormatUnitOptions, step 12.a. currency = toASCIIUpperCase(currency); lazyNumberFormatData.currency = currency; - // Step 14. SetNumberFormatUnitOptions, step 14.b. + // Step 15. SetNumberFormatUnitOptions, step 12.b. lazyNumberFormatData.currencyDisplay = currencyDisplay; - // Step 14. SetNumberFormatUnitOptions, step 14.c. + // Step 15. SetNumberFormatUnitOptions, step 12.c. lazyNumberFormatData.currencySign = currencySign; } - // Step 14. SetNumberFormatUnitOptions, step 10. + // Step 15. SetNumberFormatUnitOptions, step 8. var unit = GetOption(options, "unit", "string", undefined, undefined); - // Step 14. SetNumberFormatUnitOptions, steps 11-12. + // Step 15. SetNumberFormatUnitOptions, steps 9-10. if (unit === undefined) { if (style === "unit") { ThrowTypeError(JSMSG_UNDEFINED_UNIT); @@ -783,7 +780,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { } } - // Step 14. SetNumberFormatUnitOptions, step 13. + // Step 15. SetNumberFormatUnitOptions, step 11. var unitDisplay = GetOption( options, "unitDisplay", @@ -792,24 +789,15 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { "short" ); - // Step 14. SetNumberFormatUnitOptions, step 15. + // Step 15. SetNumberFormatUnitOptions, step 13. if (style === "unit") { lazyNumberFormatData.unit = unit; lazyNumberFormatData.unitDisplay = unitDisplay; } - // Steps 16-17. - var mnfdDefault, mxfdDefault; - if (style === "currency") { - var cDigits = CurrencyDigits(currency); - mnfdDefault = cDigits; - mxfdDefault = cDigits; - } else { - mnfdDefault = 0; - mxfdDefault = style === "percent" ? 0 : 3; - } + // Step 16. (Not applicable in our implementation.) - // Steps 18-19. + // Steps 17-18. var notation = GetOption( options, "notation", @@ -819,7 +807,18 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { ); lazyNumberFormatData.notation = notation; - // Step 20. + // Steps 19-20. + var mnfdDefault, mxfdDefault; + if (style === "currency" && notation === "standard") { + var cDigits = CurrencyDigits(currency); + mnfdDefault = cDigits; + mxfdDefault = cDigits; + } else { + mnfdDefault = 0; + mxfdDefault = style === "percent" ? 0 : 3; + } + + // Step 21. SetNumberFormatDigitOptions( lazyNumberFormatData, options, @@ -828,7 +827,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { notation ); - // Steps 21 and 23.a. + // Steps 22 and 24.a. var compactDisplay = GetOption( options, "compactDisplay", @@ -840,10 +839,10 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { lazyNumberFormatData.compactDisplay = compactDisplay; } - // Steps 22 and 23.b. + // Steps 23 and 24.b. var defaultUseGrouping = notation !== "compact" ? "auto" : "min2"; - // Steps 24-25. + // Steps 25-26. var useGrouping = GetStringOrBooleanOption( options, "useGrouping", @@ -851,14 +850,14 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { defaultUseGrouping ); - // Steps 26-27. + // Steps 27-28. if (useGrouping === "true" || useGrouping === "false") { useGrouping = defaultUseGrouping; } else if (useGrouping === true) { useGrouping = "always"; } - // Step 28. + // Step 29. assert( useGrouping === "min2" || useGrouping === "auto" || @@ -868,7 +867,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { ); lazyNumberFormatData.useGrouping = useGrouping; - // Steps 29-30. + // Steps 30-31. var signDisplay = GetOption( options, "signDisplay", @@ -878,13 +877,11 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { ); lazyNumberFormatData.signDisplay = signDisplay; - // Step 31. - // // We've done everything that must be done now: mark the lazy data as fully // computed and install it. initializeIntlObject(numberFormat, "NumberFormat", lazyNumberFormatData); - // 15.1.1 Intl.NumberFormat, step 4. (Inlined call to ChainNumberFormat.) + // Step 32. (Inlined call to ChainNumberFormat.) if ( numberFormat !== thisValue && callFunction( @@ -903,7 +900,7 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { return thisValue; } - // 15.1.1 Intl.NumberFormat, step 5. + // Step 33. return numberFormat; } /* eslint-enable complexity */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystems.yaml b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystems.yaml index db287c10ef5..f8fa34b4ce4 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystems.yaml +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystems.yaml @@ -24,9 +24,11 @@ - deva - diak - fullwide +- gara - gong - gonm - gujr +- gukh - guru - hanidec - hmng @@ -36,6 +38,7 @@ - kawi - khmr - knda +- krai - lana - lanatham - laoo @@ -53,14 +56,18 @@ - mroo - mtei - mymr +- mymrepka +- mymrpao - mymrshan - mymrtlng - nagm - newa - nkoo - olck +- onao - orya - osma +- outlined - rohg - saur - segment @@ -69,6 +76,7 @@ - sinh - sora - sund +- sunu - takr - talu - tamldec diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystemsGenerated.h b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystemsGenerated.h index f51d0f9c534..e66e4409ad1 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystemsGenerated.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/NumberingSystemsGenerated.h @@ -22,9 +22,11 @@ "deva", \ "diak", \ "fullwide", \ + "gara", \ "gong", \ "gonm", \ "gujr", \ + "gukh", \ "guru", \ "hanidec", \ "hmng", \ @@ -34,6 +36,7 @@ "kawi", \ "khmr", \ "knda", \ + "krai", \ "lana", \ "lanatham", \ "laoo", \ @@ -51,14 +54,18 @@ "mroo", \ "mtei", \ "mymr", \ + "mymrepka", \ + "mymrpao", \ "mymrshan", \ "mymrtlng", \ "nagm", \ "newa", \ "nkoo", \ "olck", \ + "onao", \ "orya", \ "osma", \ + "outlined", \ "rohg", \ "saur", \ "segment", \ @@ -67,6 +74,7 @@ "sinh", \ "sora", \ "sund", \ + "sunu", \ "takr", \ "talu", \ "tamldec", \ diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/PluralRules.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/PluralRules.cpp index 4d7907f2c81..3d573c310dc 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/PluralRules.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/PluralRules.cpp @@ -46,7 +46,9 @@ const JSClass PluralRulesObject::class_ = { JSCLASS_HAS_RESERVED_SLOTS(PluralRulesObject::SLOT_COUNT) | JSCLASS_HAS_CACHED_PROTO(JSProto_PluralRules) | JSCLASS_FOREGROUND_FINALIZE, - &PluralRulesObject::classOps_, &PluralRulesObject::classSpec_}; + &PluralRulesObject::classOps_, + &PluralRulesObject::classSpec_, +}; const JSClass& PluralRulesObject::protoClass_ = PlainObject::class_; @@ -59,18 +61,22 @@ static bool pluralRules_toSource(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec pluralRules_static_methods[] = { JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_PluralRules_supportedLocalesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec pluralRules_methods[] = { JS_SELF_HOSTED_FN("resolvedOptions", "Intl_PluralRules_resolvedOptions", 0, 0), JS_SELF_HOSTED_FN("select", "Intl_PluralRules_select", 1, 0), JS_SELF_HOSTED_FN("selectRange", "Intl_PluralRules_selectRange", 2, 0), - JS_FN("toSource", pluralRules_toSource, 0, 0), JS_FS_END}; + JS_FN("toSource", pluralRules_toSource, 0, 0), + JS_FS_END, +}; static const JSPropertySpec pluralRules_properties[] = { JS_STRING_SYM_PS(toStringTag, "Intl.PluralRules", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; static bool PluralRules(JSContext* cx, unsigned argc, Value* vp); @@ -82,7 +88,8 @@ const ClassSpec PluralRulesObject::classSpec_ = { pluralRules_methods, pluralRules_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /** * 16.1.1 Intl.PluralRules ( [ locales [ , options ] ] ) @@ -491,11 +498,20 @@ bool js::intl_GetPluralCategories(JSContext* cx, unsigned argc, Value* vp) { res->setDenseInitializedLength(categories.size()); size_t index = 0; - for (PluralRules::Keyword keyword : categories) { - JSString* str = KeywordToString(keyword, cx); - MOZ_ASSERT(str); + for (auto keyword : { + PluralRules::Keyword::Zero, + PluralRules::Keyword::One, + PluralRules::Keyword::Two, + PluralRules::Keyword::Few, + PluralRules::Keyword::Many, + PluralRules::Keyword::Other, + }) { + if (categories.contains(keyword)) { + JSString* str = KeywordToString(keyword, cx); + MOZ_ASSERT(str); - res->initDenseElement(index++, StringValue(str)); + res->initDenseElement(index++, StringValue(str)); + } } MOZ_ASSERT(index == categories.size()); diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/RelativeTimeFormat.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/RelativeTimeFormat.cpp index cb615d34c4d..980ac1a03c1 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/RelativeTimeFormat.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/RelativeTimeFormat.cpp @@ -49,7 +49,8 @@ const JSClass RelativeTimeFormatObject::class_ = { JSCLASS_HAS_CACHED_PROTO(JSProto_RelativeTimeFormat) | JSCLASS_FOREGROUND_FINALIZE, &RelativeTimeFormatObject::classOps_, - &RelativeTimeFormatObject::classSpec_}; + &RelativeTimeFormatObject::classSpec_, +}; const JSClass& RelativeTimeFormatObject::protoClass_ = PlainObject::class_; @@ -63,7 +64,8 @@ static bool relativeTimeFormat_toSource(JSContext* cx, unsigned argc, static const JSFunctionSpec relativeTimeFormat_static_methods[] = { JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_RelativeTimeFormat_supportedLocalesOf", 1, 0), - JS_FS_END}; + JS_FS_END, +}; static const JSFunctionSpec relativeTimeFormat_methods[] = { JS_SELF_HOSTED_FN("resolvedOptions", @@ -71,11 +73,14 @@ static const JSFunctionSpec relativeTimeFormat_methods[] = { JS_SELF_HOSTED_FN("format", "Intl_RelativeTimeFormat_format", 2, 0), JS_SELF_HOSTED_FN("formatToParts", "Intl_RelativeTimeFormat_formatToParts", 2, 0), - JS_FN("toSource", relativeTimeFormat_toSource, 0, 0), JS_FS_END}; + JS_FN("toSource", relativeTimeFormat_toSource, 0, 0), + JS_FS_END, +}; static const JSPropertySpec relativeTimeFormat_properties[] = { JS_STRING_SYM_PS(toStringTag, "Intl.RelativeTimeFormat", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; static bool RelativeTimeFormat(JSContext* cx, unsigned argc, Value* vp); @@ -87,7 +92,8 @@ const ClassSpec RelativeTimeFormatObject::classSpec_ = { relativeTimeFormat_methods, relativeTimeFormat_properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /** * RelativeTimeFormat constructor. diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/Segmenter.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/Segmenter.cpp index 126991c51ad..43037303262 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/Segmenter.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/Segmenter.cpp @@ -10,16 +10,13 @@ #include "mozilla/Assertions.h" #include "mozilla/IntegerTypeTraits.h" +#include "mozilla/intl/ICU4XGeckoDataProvider.h" #include "mozilla/Range.h" #include "mozilla/UniquePtr.h" -#if defined(MOZ_ICU4X) -# include "mozilla/intl/ICU4XGeckoDataProvider.h" -# include "ICU4XGraphemeClusterSegmenter.h" -# include "ICU4XSentenceSegmenter.h" -# include "ICU4XWordSegmenter.h" -#endif - +#include "ICU4XGraphemeClusterSegmenter.h" +#include "ICU4XSentenceSegmenter.h" +#include "ICU4XWordSegmenter.h" #include "jspubtd.h" #include "NamespaceImports.h" @@ -300,7 +297,6 @@ class SegmenterBreakIteratorType { bool isWordLike() const { return Interface::isWordLike(impl_); } }; -#if defined(MOZ_ICU4X) // Each SegmenterBreakIterator interface contains the following definitions: // // - BreakIterator: Type of the ICU4X break iterator. @@ -432,7 +428,6 @@ struct SentenceSegmenter { static constexpr auto& create = capi::ICU4XSentenceSegmenter_create; static constexpr auto& destroy = capi::ICU4XSentenceSegmenter_destroy; }; -#endif /** * Create a new ICU4X segmenter instance. @@ -486,7 +481,6 @@ static bool EnsureInternalsResolved(JSContext* cx, } } -#if defined(MOZ_ICU4X) switch (granularity) { case SegmenterGranularity::Grapheme: { auto* seg = CreateSegmenter(cx); @@ -513,7 +507,6 @@ static bool EnsureInternalsResolved(JSContext* cx, break; } } -#endif segmenter->setLocale(locale); segmenter->setGranularity(granularity); @@ -535,7 +528,6 @@ void SegmenterObject::finalize(JS::GCContext* gcx, JSObject* obj) { auto& segmenter = obj->as(); if (void* seg = segmenter.getSegmenter()) { -#if defined(MOZ_ICU4X) switch (segmenter.getGranularity()) { case SegmenterGranularity::Grapheme: { DestroySegmenter(seg); @@ -550,9 +542,6 @@ void SegmenterObject::finalize(JS::GCContext* gcx, JSObject* obj) { break; } } -#else - MOZ_CRASH("ICU4X disabled"); -#endif } } @@ -570,7 +559,6 @@ static void DestroyBreakIterator(void* brk) { */ template static void DestroyBreakIterator(const T* segments) { -#if defined(MOZ_ICU4X) void* brk = segments->getBreakIterator(); MOZ_ASSERT(brk); @@ -602,9 +590,6 @@ static void DestroyBreakIterator(const T* segments) { break; } } -#else - MOZ_CRASH("ICU4X disabled"); -#endif } void SegmentsObject::finalize(JS::GCContext* gcx, JSObject* obj) { @@ -659,43 +644,31 @@ static Boundaries FindBoundaryFrom(Handle segments, int32_t index) { template static Boundaries GraphemeBoundaries(Handle segments, int32_t index) { -#if defined(MOZ_ICU4X) if (segments->hasLatin1StringChars()) { return FindBoundaryFrom( segments, index); } return FindBoundaryFrom( segments, index); -#else - MOZ_CRASH("ICU4X disabled"); -#endif } template static Boundaries WordBoundaries(Handle segments, int32_t index) { -#if defined(MOZ_ICU4X) if (segments->hasLatin1StringChars()) { return FindBoundaryFrom(segments, index); } return FindBoundaryFrom(segments, index); -#else - MOZ_CRASH("ICU4X disabled"); -#endif } template static Boundaries SentenceBoundaries(Handle segments, int32_t index) { -#if defined(MOZ_ICU4X) if (segments->hasLatin1StringChars()) { return FindBoundaryFrom(segments, index); } return FindBoundaryFrom(segments, index); -#else - MOZ_CRASH("ICU4X disabled"); -#endif } /** @@ -749,13 +722,9 @@ static auto* CreateBreakIterator(Handle segments) { size_t length = segments->getString()->length(); - using Unsigned = typename mozilla::UnsignedStdintTypeForSize::Type; - auto* seg = static_cast(segmenter); auto* ch = chars.template data(); - auto* chUnsigned = reinterpret_cast(ch); - return Interface::create(seg, chUnsigned, length); + return Interface::create(seg, ch, length); } /** @@ -785,7 +754,6 @@ static bool EnsureBreakIterator(JSContext* cx, Handle segments, return false; } -#if defined(MOZ_ICU4X) bool isLatin1 = segments->hasLatin1StringChars(); // Create a new break iterator based on the granularity and character type. @@ -827,9 +795,6 @@ static bool EnsureBreakIterator(JSContext* cx, Handle segments, MOZ_ASSERT(segments->getIndex() == 0, "index is initially zero"); return true; -#else - MOZ_CRASH("ICU4X disabled"); -#endif } /** diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.cpp b/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.cpp index 8b382f22fb0..8aa2dfeef68 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.cpp @@ -63,7 +63,7 @@ static HashNumber HashStringIgnoreCaseASCII(const Char* s, size_t length) { } js::intl::SharedIntlData::TimeZoneHasher::Lookup::Lookup( - JSLinearString* timeZone) + const JSLinearString* timeZone) : js::intl::SharedIntlData::LinearStringLookup(timeZone) { if (isLatin1) { hash = HashStringIgnoreCaseASCII(latin1Chars, length); @@ -285,7 +285,8 @@ js::intl::SharedIntlData::availableTimeZonesIteration(JSContext* cx) { return availableTimeZones.iter(); } -js::intl::SharedIntlData::LocaleHasher::Lookup::Lookup(JSLinearString* locale) +js::intl::SharedIntlData::LocaleHasher::Lookup::Lookup( + const JSLinearString* locale) : js::intl::SharedIntlData::LinearStringLookup(locale) { if (isLatin1) { hash = mozilla::HashString(latin1Chars, length); @@ -530,6 +531,7 @@ bool js::intl::SharedIntlData::isSupportedLocale(JSContext* cx, return true; case SupportedLocaleKind::DateTimeFormat: case SupportedLocaleKind::DisplayNames: + case SupportedLocaleKind::DurationFormat: case SupportedLocaleKind::ListFormat: case SupportedLocaleKind::NumberFormat: case SupportedLocaleKind::PluralRules: @@ -554,6 +556,7 @@ js::ArrayObject* js::intl::SharedIntlData::availableLocalesOf( break; case SupportedLocaleKind::DateTimeFormat: case SupportedLocaleKind::DisplayNames: + case SupportedLocaleKind::DurationFormat: case SupportedLocaleKind::ListFormat: case SupportedLocaleKind::NumberFormat: case SupportedLocaleKind::PluralRules: diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.h b/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.h index 7bf3eb74c9f..ee7dce53d3f 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/SharedIntlData.h @@ -56,7 +56,7 @@ class SharedIntlData { JS::AutoCheckCannotGC nogc; HashNumber hash = 0; - explicit LinearStringLookup(JSLinearString* string) + explicit LinearStringLookup(const JSLinearString* string) : isLatin1(string->hasLatin1Chars()), length(string->length()) { if (isLatin1) { latin1Chars = string->latin1Chars(nogc); @@ -101,7 +101,7 @@ class SharedIntlData { struct TimeZoneHasher { struct Lookup : LinearStringLookup { - explicit Lookup(JSLinearString* timeZone); + explicit Lookup(const JSLinearString* timeZone); }; static js::HashNumber hash(const Lookup& lookup) { return lookup.hash; } @@ -189,7 +189,7 @@ class SharedIntlData { struct LocaleHasher { struct Lookup : LinearStringLookup { - explicit Lookup(JSLinearString* locale); + explicit Lookup(const JSLinearString* locale); Lookup(const char* chars, size_t length); }; @@ -240,6 +240,7 @@ class SharedIntlData { Collator, DateTimeFormat, DisplayNames, + DurationFormat, ListFormat, NumberFormat, PluralRules, diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/StringAsciiChars.h b/src/third_party/mozjs/extract/js/src/builtin/intl/StringAsciiChars.h index 3323544d8c9..7e5930db42a 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/StringAsciiChars.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/StringAsciiChars.h @@ -40,12 +40,12 @@ class MOZ_STACK_CLASS StringAsciiChars final { JS::AutoCheckCannotGC nogc_; - JSLinearString* str_; + const JSLinearString* str_; mozilla::Maybe> ownChars_; public: - explicit StringAsciiChars(JSLinearString* str) : str_(str) { + explicit StringAsciiChars(const JSLinearString* str) : str_(str) { MOZ_ASSERT(StringIsAscii(str)); } diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneDataGenerated.h b/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneDataGenerated.h index 7deea4f891a..3052f86e80f 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneDataGenerated.h +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneDataGenerated.h @@ -1,5 +1,5 @@ // Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2025a +// tzdata version = 2025b #ifndef builtin_intl_TimeZoneDataGenerated_h #define builtin_intl_TimeZoneDataGenerated_h @@ -10,58 +10,26 @@ namespace timezone { // Format: // "ZoneName" // ICU-Name [time zone file] const char* const ianaZonesTreatedAsLinksByICU[] = { - "Africa/Asmara", // Africa/Asmera [backzone] - "Africa/Timbuktu", // Africa/Bamako [backzone] + "Africa/Asmara", // Africa/Asmera [backward] "America/Argentina/Buenos_Aires", // America/Buenos_Aires [southamerica] "America/Argentina/Catamarca", // America/Catamarca [southamerica] - "America/Argentina/ComodRivadavia", // America/Catamarca [backzone] "America/Argentina/Cordoba", // America/Cordoba [southamerica] "America/Argentina/Jujuy", // America/Jujuy [southamerica] "America/Argentina/Mendoza", // America/Mendoza [southamerica] - "America/Atikokan", // America/Coral_Harbour [backzone] - "America/Ensenada", // America/Tijuana [backzone] + "America/Atikokan", // America/Coral_Harbour [backward] "America/Indiana/Indianapolis", // America/Indianapolis [northamerica] "America/Kentucky/Louisville", // America/Louisville [northamerica] - "America/Montreal", // America/Toronto [backzone] - "America/Nipigon", // America/Toronto [backzone] "America/Nuuk", // America/Godthab [europe] - "America/Pangnirtung", // America/Iqaluit [backzone] - "America/Rainy_River", // America/Winnipeg [backzone] - "America/Rosario", // America/Cordoba [backzone] - "America/Thunder_Bay", // America/Toronto [backzone] - "America/Yellowknife", // America/Edmonton [backzone] - "Asia/Chongqing", // Asia/Shanghai [backzone] - "Asia/Harbin", // Asia/Shanghai [backzone] "Asia/Ho_Chi_Minh", // Asia/Saigon [asia] - "Asia/Kashgar", // Asia/Urumqi [backzone] "Asia/Kathmandu", // Asia/Katmandu [asia] "Asia/Kolkata", // Asia/Calcutta [asia] - "Asia/Tel_Aviv", // Asia/Jerusalem [backzone] "Asia/Yangon", // Asia/Rangoon [asia] "Atlantic/Faroe", // Atlantic/Faeroe [europe] - "Atlantic/Jan_Mayen", // Arctic/Longyearbyen [backzone] - "Australia/Currie", // Australia/Hobart [backzone] - "CET", // Europe/Brussels [backzone] - "CST6CDT", // America/Chicago [backzone] - "EET", // Europe/Athens [backzone] - "EST", // America/Panama [backzone] - "EST5EDT", // America/New_York [backzone] - "Europe/Belfast", // Europe/London [backzone] "Europe/Kyiv", // Europe/Kiev [europe] - "Europe/Tiraspol", // Europe/Chisinau [backzone] - "Europe/Uzhgorod", // Europe/Kiev [backzone] - "Europe/Zaporozhye", // Europe/Kiev [backzone] - "Factory", // Etc/Unknown [factory] - "HST", // Pacific/Honolulu [backzone] - "MET", // Europe/Brussels [backzone] - "MST", // America/Phoenix [backzone] - "MST7MDT", // America/Denver [backzone] - "PST8PDT", // America/Los_Angeles [backzone] - "Pacific/Chuuk", // Pacific/Truk [backzone] - "Pacific/Johnston", // Pacific/Honolulu [backzone] + "Pacific/Chuuk", // Pacific/Truk [backward] "Pacific/Kanton", // Pacific/Enderbury [australasia] - "Pacific/Pohnpei", // Pacific/Ponape [backzone] - "WET", // Europe/Lisbon [backzone] + "Pacific/Pohnpei", // Pacific/Ponape [backward] + "UTC", // Etc/UTC [backward] }; // Format: @@ -74,38 +42,48 @@ struct LinkAndTarget const LinkAndTarget ianaLinksCanonicalizedDifferentlyByICU[] = { { "Africa/Asmera", "Africa/Asmara" }, // Africa/Asmera [backward] + { "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca" }, // America/Catamarca [backward] { "America/Buenos_Aires", "America/Argentina/Buenos_Aires" }, // America/Buenos_Aires [backward] { "America/Catamarca", "America/Argentina/Catamarca" }, // America/Catamarca [backward] + { "America/Coral_Harbour", "America/Atikokan" }, // America/Coral_Harbour [backward] { "America/Cordoba", "America/Argentina/Cordoba" }, // America/Cordoba [backward] { "America/Fort_Wayne", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward] { "America/Godthab", "America/Nuuk" }, // America/Godthab [backward] { "America/Indianapolis", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward] { "America/Jujuy", "America/Argentina/Jujuy" }, // America/Jujuy [backward] - { "America/Kralendijk", "America/Curacao" }, // America/Kralendijk [backward] { "America/Louisville", "America/Kentucky/Louisville" }, // America/Louisville [backward] - { "America/Lower_Princes", "America/Curacao" }, // America/Lower_Princes [backward] - { "America/Marigot", "America/Port_of_Spain" }, // America/Marigot [backward] { "America/Mendoza", "America/Argentina/Mendoza" }, // America/Mendoza [backward] - { "America/St_Barthelemy", "America/Port_of_Spain" }, // America/St_Barthelemy [backward] - { "Antarctica/South_Pole", "Antarctica/McMurdo" }, // Pacific/Auckland [backward] - { "Arctic/Longyearbyen", "Europe/Oslo" }, // Arctic/Longyearbyen [backward] + { "America/Rosario", "America/Argentina/Cordoba" }, // America/Cordoba [backward] { "Asia/Calcutta", "Asia/Kolkata" }, // Asia/Calcutta [backward] - { "Asia/Chungking", "Asia/Chongqing" }, // Asia/Shanghai [backward] { "Asia/Katmandu", "Asia/Kathmandu" }, // Asia/Katmandu [backward] { "Asia/Rangoon", "Asia/Yangon" }, // Asia/Rangoon [backward] { "Asia/Saigon", "Asia/Ho_Chi_Minh" }, // Asia/Saigon [backward] { "Atlantic/Faeroe", "Atlantic/Faroe" }, // Atlantic/Faeroe [backward] - { "Europe/Bratislava", "Europe/Prague" }, // Europe/Bratislava [backward] - { "Europe/Busingen", "Europe/Zurich" }, // Europe/Busingen [backward] + { "Etc/GMT", "UTC" }, // Etc/GMT [etcetera] + { "Etc/GMT+0", "UTC" }, // Etc/GMT [backward] + { "Etc/GMT-0", "UTC" }, // Etc/GMT [backward] + { "Etc/GMT0", "UTC" }, // Etc/GMT [backward] + { "Etc/Greenwich", "UTC" }, // Etc/GMT [backward] + { "Etc/UCT", "UTC" }, // Etc/UTC [backward] + { "Etc/UTC", "UTC" }, // Etc/UTC [etcetera] + { "Etc/Universal", "UTC" }, // Etc/UTC [backward] + { "Etc/Zulu", "UTC" }, // Etc/UTC [backward] { "Europe/Kiev", "Europe/Kyiv" }, // Europe/Kiev [backward] - { "Europe/Mariehamn", "Europe/Helsinki" }, // Europe/Mariehamn [backward] - { "Europe/Podgorica", "Europe/Belgrade" }, // Europe/Podgorica [backward] - { "Europe/San_Marino", "Europe/Rome" }, // Europe/San_Marino [backward] - { "Europe/Vatican", "Europe/Rome" }, // Europe/Vatican [backward] + { "Europe/Uzhgorod", "Europe/Kyiv" }, // Europe/Kiev [backward] + { "Europe/Zaporozhye", "Europe/Kyiv" }, // Europe/Kiev [backward] + { "GMT", "UTC" }, // Etc/GMT [etcetera] + { "GMT+0", "UTC" }, // Etc/GMT [backward] + { "GMT-0", "UTC" }, // Etc/GMT [backward] + { "GMT0", "UTC" }, // Etc/GMT [backward] + { "Greenwich", "UTC" }, // Etc/GMT [backward] + { "Pacific/Enderbury", "Pacific/Kanton" }, // Pacific/Enderbury [backward] { "Pacific/Ponape", "Pacific/Pohnpei" }, // Pacific/Ponape [backward] { "Pacific/Truk", "Pacific/Chuuk" }, // Pacific/Truk [backward] { "Pacific/Yap", "Pacific/Chuuk" }, // Pacific/Truk [backward] + { "UCT", "UTC" }, // Etc/UTC [backward] { "US/East-Indiana", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward] + { "Universal", "UTC" }, // Etc/UTC [backward] + { "Zulu", "UTC" }, // Etc/UTC [backward] }; // Legacy ICU time zones, these are not valid IANA time zone names. We also @@ -139,6 +117,7 @@ const char* const legacyICUTimeZones[] = { "SST", "US/Pacific-New", "VST", + "Factory", "SystemV/AST4", "SystemV/AST4ADT", "SystemV/CST6", diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneMapping.yaml b/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneMapping.yaml new file mode 100644 index 00000000000..1ddccccb5b1 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/TimeZoneMapping.yaml @@ -0,0 +1,157 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Provide mapping from time zone identifiers to region codes for time zones +# which aren't listed in tzdata's zone.tab file. + +Africa/Timbuktu: ML +Africa/Asmera: ER + +America/Argentina/ComodRivadavia: AR +America/Atka: US +America/Buenos_Aires: AR +America/Catamarca: AR +America/Coral_Harbour: CA +America/Cordoba: AR +America/Ensenada: MX +America/Fort_Wayne: US +America/Godthab: GL +America/Indianapolis: US +America/Jujuy: AR +America/Knox_IN: US +America/Louisville: US +America/Mendoza: AR +America/Montreal: CA +America/Nipigon: CA +America/Pangnirtung: CA +America/Porto_Acre: BR +America/Rainy_River: CA +America/Rosario: AR +America/Santa_Isabel: MX +America/Shiprock: US +America/Thunder_Bay: CA +America/Virgin: VI +America/Yellowknife: CA + +Antarctica/South_Pole: AQ + +Asia/Choibalsan: MN +Asia/Chongqing: CN +Asia/Harbin: CN +Asia/Kashgar: CN +Asia/Tel_Aviv: IL +Asia/Ashkhabad: TM +Asia/Calcutta: IN +Asia/Chungking: CN +Asia/Dacca: BD +Asia/Istanbul: TR +Asia/Katmandu: NP +Asia/Macao: MO +Asia/Rangoon: MM +Asia/Saigon: VN +Asia/Thimbu: BT +Asia/Ujung_Pandang: ID +Asia/Ulan_Bator: MN + +Atlantic/Jan_Mayen: SJ +Atlantic/Faeroe: FO + +Australia/ACT: AU +Australia/LHI: AU +Australia/NSW: AU +Australia/Canberra: AU +Australia/Currie: AU +Australia/North: AU +Australia/Queensland: AU +Australia/South: AU +Australia/Tasmania: AU +Australia/Victoria: AU +Australia/West: AU +Australia/Yancowinna: AU + +Europe/Belfast: GB +Europe/Tiraspol: MD +Europe/Uzhgorod: UA +Europe/Zaporozhye: UA +Europe/Kiev: UA +Europe/Nicosia: CY + +Pacific/Samoa: AS +Pacific/Enderbury: KI +Pacific/Johnston: US +Pacific/Yap: FM +Pacific/Ponape: FM +Pacific/Truk: FM + +Brazil/Acre: BR +Brazil/DeNoronha: BR +Brazil/East: BR +Brazil/West: BR + +Canada/Atlantic: CA +Canada/Central: CA +Canada/Eastern: CA +Canada/Mountain: CA +Canada/Newfoundland: CA +Canada/Pacific: CA +Canada/Saskatchewan: CA +Canada/Yukon: CA + +Chile/Continental: CL +Chile/EasterIsland: CL + +Mexico/BajaNorte: MX +Mexico/BajaSur: MX +Mexico/General: MX + +US/Alaska: US +US/Aleutian: US +US/Arizona: US +US/Central: US +US/East-Indiana: US +US/Eastern: US +US/Hawaii: US +US/Indiana-Starke: US +US/Michigan: US +US/Mountain: US +US/Pacific: US +US/Samoa: AS + +CET: BE +EET: GR +MET: BE +WET: PT + +CST6CDT: US +EST5EDT: US +EST: PA +HST: US +MST7MDT: US +MST: US +PST8PDT: US + +Cuba: CU +Egypt: EG +Eire: IE +GB: GB +GB-Eire: GB +Hongkong: HK +Iceland: IS +Iran: IR +Israel: IL +Jamaica: JM +Japan: JP +Kwajalein: MH +Libya: LY +NZ: NZ +NZ-CHAT: NZ +Navajo: US +PRC: CN +Poland: PL +Portugal: PT +ROC: TW +ROK: KR +Singapore: SG +Turkey: TR +W-SU: RU diff --git a/src/third_party/mozjs/extract/js/src/builtin/intl/make_intl_data.py b/src/third_party/mozjs/extract/js/src/builtin/intl/make_intl_data.py index a8357445c4f..df11b2b4d6d 100755 --- a/src/third_party/mozjs/extract/js/src/builtin/intl/make_intl_data.py +++ b/src/third_party/mozjs/extract/js/src/builtin/intl/make_intl_data.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -45,32 +44,19 @@ import io import json import os import re -import sys import tarfile import tempfile from contextlib import closing from functools import partial, total_ordering -from itertools import chain, groupby, tee +from itertools import chain, filterfalse, groupby, tee, zip_longest from operator import attrgetter, itemgetter +from urllib.parse import urlsplit +from urllib.request import Request as UrlRequest +from urllib.request import urlopen from zipfile import ZipFile import yaml -if sys.version_info.major == 2: - from itertools import ifilter as filter - from itertools import ifilterfalse as filterfalse - from itertools import imap as map - from itertools import izip_longest as zip_longest - - from urllib2 import Request as UrlRequest - from urllib2 import urlopen - from urlparse import urlsplit -else: - from itertools import filterfalse, zip_longest - from urllib.parse import urlsplit - from urllib.request import Request as UrlRequest - from urllib.request import urlopen - # From https://docs.python.org/3/library/itertools.html def grouper(iterable, n, fillvalue=None): @@ -84,9 +70,9 @@ def writeMappingHeader(println, description, source, url): if type(description) is not list: description = [description] for desc in description: - println("// {0}".format(desc)) - println("// Derived from {0}.".format(source)) - println("// {0}".format(url)) + println(f"// {desc}") + println(f"// Derived from {source}.") + println(f"// {url}") def writeMappingsVar(println, mapping, name, description, source, url): @@ -98,9 +84,9 @@ def writeMappingsVar(println, mapping, name, description, source, url): """ println("") writeMappingHeader(println, description, source, url) - println("var {0} = {{".format(name)) + println(f"var {name} = {{") for key, value in sorted(mapping.items(), key=itemgetter(0)): - println(' "{0}": "{1}",'.format(key, value)) + println(f' "{key}": "{value}",') println("};") @@ -125,13 +111,11 @@ def writeMappingsBinarySearch( println("") writeMappingHeader(println, description, source, url) println( - """ -bool mozilla::intl::Locale::{0}({1} {2}) {{ - MOZ_ASSERT({3}({2}.Span())); - MOZ_ASSERT({4}({2}.Span())); -""".format( - fn_name, type_name, name, validate_fn, validate_case_fn - ).strip() + f""" +bool mozilla::intl::Locale::{fn_name}({type_name} {name}) {{ + MOZ_ASSERT({validate_fn}({name}.Span())); + MOZ_ASSERT({validate_case_fn}({name}.Span())); +""".strip() ) writeMappingsBinarySearchBody(println, name, name, mappings, tag_maxlength) @@ -148,20 +132,14 @@ def writeMappingsBinarySearchBody( ): def write_array(subtags, name, length, fixed): if fixed: - println( - " static const char {}[{}][{}] = {{".format( - name, len(subtags), length + 1 - ) - ) + println(f" static const char {name}[{len(subtags)}][{length + 1}] = {{") else: - println(" static const char* {}[{}] = {{".format(name, len(subtags))) + println(f" static const char* {name}[{len(subtags)}] = {{") # Group in pairs of ten to not exceed the 80 line column limit. for entries in grouper(subtags, 10): entries = ( - '"{}"'.format(tag).rjust(length + 2) - for tag in entries - if tag is not None + f'"{tag}"'.rjust(length + 2) for tag in entries if tag is not None ) println(" {},".format(", ".join(entries))) @@ -172,16 +150,14 @@ def writeMappingsBinarySearchBody( # Sort the subtags by length. That enables using an optimized comparator # for the binary search, which only performs a single |memcmp| for multiple # of two subtag lengths. - mappings_keys = mappings.keys() if type(mappings) == dict else mappings + mappings_keys = mappings.keys() if type(mappings) is dict else mappings for length, subtags in groupby(sorted(mappings_keys, key=len), len): # Omit the length check if the current length is the maximum length. if length != tag_maxlength: println( - """ - if ({}.Length() == {}) {{ -""".format( - source_name, length - ).rstrip( + f""" + if ({source_name}.Length() == {length}) {{ +""".rstrip( "\n" ) ) @@ -199,46 +175,40 @@ def writeMappingsBinarySearchBody( subtags = sorted(subtags) def equals(subtag): - return """{}.EqualTo("{}")""".format(source_name, subtag) + return f"""{source_name}.EqualTo("{subtag}")""" # Don't emit a binary search for short lists. if len(subtags) == 1: - if type(mappings) == dict: + if type(mappings) is dict: println( - """ - if ({}) {{ - {}.Set(mozilla::MakeStringSpan("{}")); + f""" + if ({equals(subtags[0])}) {{ + {target_name}.Set(mozilla::MakeStringSpan("{mappings[subtags[0]]}")); return true; }} return false; -""".format( - equals(subtags[0]), target_name, mappings[subtags[0]] - ).strip( +""".strip( "\n" ) ) else: println( - """ - return {}; -""".format( - equals(subtags[0]) - ).strip( + f""" + return {equals(subtags[0])}; +""".strip( "\n" ) ) elif len(subtags) <= 4: - if type(mappings) == dict: + if type(mappings) is dict: for subtag in subtags: println( - """ - if ({}) {{ - {}.Set("{}"); + f""" + if ({equals(subtag)}) {{ + {target_name}.Set("{mappings[subtag]}"); return true; }} -""".format( - equals(subtag), target_name, mappings[subtag] - ).strip( +""".strip( "\n" ) ) @@ -254,38 +224,32 @@ def writeMappingsBinarySearchBody( cond = (equals(subtag) for subtag in subtags) cond = (" ||\n" + " " * (4 + len("return "))).join(cond) println( - """ - return {}; -""".format( - cond - ).strip( + f""" + return {cond}; +""".strip( "\n" ) ) else: write_array(subtags, source_name + "s", length, True) - if type(mappings) == dict: + if type(mappings) is dict: write_array([mappings[k] for k in subtags], "aliases", length, False) println( - """ - if (const char* replacement = SearchReplacement({0}s, aliases, {0})) {{ - {1}.Set(mozilla::MakeStringSpan(replacement)); + f""" + if (const char* replacement = SearchReplacement({source_name}s, aliases, {source_name})) {{ + {target_name}.Set(mozilla::MakeStringSpan(replacement)); return true; }} return false; -""".format( - source_name, target_name - ).rstrip() +""".rstrip() ) else: println( - """ - return HasReplacement({0}s, {0}); -""".format( - source_name - ).rstrip() + f""" + return HasReplacement({source_name}s, {source_name}); +""".rstrip() ) println( @@ -339,48 +303,40 @@ void mozilla::intl::Locale::PerformComplexLanguageMappings() { first_language = False cond = ( - 'Language().EqualTo("{}")'.format(lang) + f'Language().EqualTo("{lang}")' for lang in [deprecated_language] + language_aliases[key] ) cond = (" ||\n" + " " * (2 + len(if_kind) + 2)).join(cond) println( - """ - {} ({}) {{""".format( - if_kind, cond - ).strip( + f""" + {if_kind} ({cond}) {{""".strip( "\n" ) ) println( - """ - SetLanguage("{}");""".format( - language - ).strip( + f""" + SetLanguage("{language}");""".strip( "\n" ) ) if script is not None: println( - """ + f""" if (Script().Missing()) {{ - SetScript("{}"); - }}""".format( - script - ).strip( + SetScript("{script}"); + }}""".strip( "\n" ) ) if region is not None: println( - """ + f""" if (Region().Missing()) {{ - SetRegion("{}"); - }}""".format( - region - ).strip( + SetRegion("{region}"); + }}""".strip( "\n" ) ) @@ -443,16 +399,14 @@ void mozilla::intl::Locale::PerformComplexRegionMappings() { first_region = False cond = ( - 'Region().EqualTo("{}")'.format(region) + f'Region().EqualTo("{region}")' for region in [deprecated_region] + region_aliases[key] ) cond = (" ||\n" + " " * (2 + len(if_kind) + 2)).join(cond) println( - """ - {} ({}) {{""".format( - if_kind, cond - ).strip( + f""" + {if_kind} ({cond}) {{""".strip( "\n" ) ) @@ -474,10 +428,8 @@ void mozilla::intl::Locale::PerformComplexRegionMappings() { def compare_tags(language, script): if script is None: - return 'Language().EqualTo("{}")'.format(language) - return '(Language().EqualTo("{}") && Script().EqualTo("{}"))'.format( - language, script - ) + return f'Language().EqualTo("{language}")' + return f'(Language().EqualTo("{language}") && Script().EqualTo("{script}"))' cond = ( compare_tags(language, script) @@ -486,26 +438,22 @@ void mozilla::intl::Locale::PerformComplexRegionMappings() { cond = (" ||\n" + " " * (4 + len(if_kind) + 2)).join(cond) println( - """ - {} ({}) {{ - SetRegion("{}"); - }}""".format( - if_kind, cond, replacement_region + f""" + {if_kind} ({cond}) {{ + SetRegion("{replacement_region}"); + }}""".rstrip().strip( + "\n" ) - .rstrip() - .strip("\n") ) println( - """ + f""" else {{ - SetRegion("{}"); + SetRegion("{default}"); }} - }}""".format( - default + }}""".rstrip().strip( + "\n" ) - .rstrip() - .strip("\n") ) println( @@ -1499,7 +1447,7 @@ def readUnicodeExtensions(core_file): extension = keyword.get("extension", "u") assert ( extension == "u" or extension == "t" - ), "unknown extension type: {}".format(extension) + ), f"unknown extension type: {extension}" extension_name = keyword.get("name") @@ -1531,7 +1479,7 @@ def readUnicodeExtensions(core_file): # All other names should match the 'type' production. assert ( typeRE.match(name) is not None - ), "{} matches the 'type' production".format(name) + ), f"{name} matches the 'type' production" # : # @@ -1607,7 +1555,7 @@ def readUnicodeExtensions(core_file): type = alias.get("type") assert ( typeRE.match(type) is not None - ), "{} matches the 'type' production".format(type) + ), f"{type} matches the 'type' production" # Take the first replacement when multiple ones are present. replacement = alias.get("replacement").split(" ")[0].lower() @@ -1619,7 +1567,7 @@ def readUnicodeExtensions(core_file): # Assert the replacement is syntactically correct. assert ( typeRE.match(replacement) is not None - ), "replacement {} matches the 'type' production".format(replacement) + ), f"replacement {replacement} matches the 'type' production" # 'subdivisionAlias' applies to 'rg' and 'sd' keys. mapping["u"].setdefault("rg", {})[type] = replacement @@ -1644,7 +1592,7 @@ def writeCLDRLanguageTagData(println, data, url): println(generatedFileWarning) println("// Version: CLDR-{}".format(data["version"])) - println("// URL: {}".format(url)) + println(f"// URL: {url}") println( """ @@ -1911,7 +1859,7 @@ def writeCLDRLanguageTagLikelySubtagsTest(println, data, url): # Assume no complex region mappings are needed for now. assert ( region not in complex_region_mappings - ), "unexpected region with complex mappings: {}".format(region) + ), f"unexpected region with complex mappings: {region}" return (language, script, region) @@ -1928,10 +1876,9 @@ def writeCLDRLanguageTagLikelySubtagsTest(println, data, url): # Step 2: Lookup. searches = ( (language, script, region), - (language, None, region), (language, script, None), + (language, None, region), (language, None, None), - ("und", script, None), ) search = next(search for search in searches if search in likely_subtags) @@ -2035,7 +1982,7 @@ if (typeof reportCompare === "function") def readCLDRVersionFromICU(): icuDir = os.path.join(topsrcdir, "intl/icu/source") if not os.path.isdir(icuDir): - raise RuntimeError("not a directory: {}".format(icuDir)) + raise RuntimeError(f"not a directory: {icuDir}") reVersion = re.compile(r'\s*cldrVersion\{"(\d+(?:\.\d+)?)"\}') @@ -2093,7 +2040,7 @@ def updateCLDRLangTags(args): readFiles(cldr_data) print("Writing Intl data...") - with io.open(out, mode="w", encoding="utf-8", newline="") as f: + with open(out, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) writeCLDRLanguageTagData(println, data, url) @@ -2104,7 +2051,7 @@ def updateCLDRLangTags(args): js_src_builtin_intl_dir, "../../tests/non262/Intl/Locale/likely-subtags-generated.js", ) - with io.open(test_file, mode="w", encoding="utf-8", newline="") as f: + with open(test_file, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println("// |reftest| skip-if(!this.hasOwnProperty('Intl'))") @@ -2113,13 +2060,13 @@ def updateCLDRLangTags(args): def flines(filepath, encoding="utf-8"): """Open filepath and iterate over its content.""" - with io.open(filepath, mode="r", encoding=encoding) as f: + with open(filepath, encoding=encoding) as f: for line in f: yield line @total_ordering -class Zone(object): +class Zone: """Time zone with optional file name.""" def __init__(self, name, filename=""): @@ -2142,7 +2089,7 @@ class Zone(object): return self.name -class TzDataDir(object): +class TzDataDir: """tzdata source from a directory.""" def __init__(self, obj): @@ -2154,7 +2101,7 @@ class TzDataDir(object): self.readlines = flines -class TzDataFile(object): +class TzDataFile: """tzdata source from a file (tar or gzipped).""" def __init__(self, obj): @@ -2216,7 +2163,8 @@ def readIANAFiles(tzdataDir, files): nameSyntax = r"[\w/+\-]+" pZone = re.compile(r"Zone\s+(?P%s)\s+.*" % nameSyntax) pLink = re.compile( - r"Link\s+(?P%s)\s+(?P%s)(?:\s+#.*)?" % (nameSyntax, nameSyntax) + r"(#PACKRATLIST\s+zone.tab\s+)?Link\s+(?P%s)\s+(?P%s)(?:\s+#.*)?" + % (nameSyntax, nameSyntax) ) def createZone(line, fname): @@ -2231,6 +2179,7 @@ def readIANAFiles(tzdataDir, files): zones = set() links = dict() + packrat_links = dict() for filename in files: filepath = tzdataDir.resolve(filename) for line in tzdataDir.readlines(filepath): @@ -2239,31 +2188,26 @@ def readIANAFiles(tzdataDir, files): if line.startswith("Link"): (link, target) = createLink(line, filename) links[link] = target + if line.startswith("#PACKRATLIST zone.tab Link"): + (link, target) = createLink(line, filename) + packrat_links[link] = target - return (zones, links) + return (zones, links, packrat_links) -def readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory): +def readIANATimeZones(tzdataDir, ignoreFactory): """Read the IANA time zone information from `tzdataDir`.""" - backzoneFiles = {"backzone"} - (bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__) + files_to_ignore = ["backzone"] + + # Ignore the placeholder time zone "Factory". + if ignoreFactory: + files_to_ignore.append("factory") + + tzfiles = (file for file in listIANAFiles(tzdataDir) if file not in files_to_ignore) # Read zone and link infos. - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - (backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles) - - # Remove the placeholder time zone "Factory". - if ignoreFactory: - zones.remove(Zone("Factory")) - - # Merge with backzone data. - if not ignoreBackzone: - zones |= backzones - links = { - name: target for name, target in links.items() if name not in backzones - } - links.update(backlinks) + (zones, links, _) = readIANAFiles(tzdataDir, tzfiles) validateTimeZones(zones, links) @@ -2432,7 +2376,13 @@ def readICUTimeZones(icuDir, icuTzDir, ignoreFactory): # Remove the placeholder time zone "Factory". # See also . if ignoreFactory: + assert Zone("Factory") in zoneinfoZones + assert Zone("Factory") not in zoneinfoLinks + assert Zone("Factory") not in typesZones + assert Zone("Factory") in typesLinks + zoneinfoZones.remove(Zone("Factory")) + del typesLinks[Zone("Factory")] # Remove the ICU placeholder time zone "Etc/Unknown". # See also . @@ -2498,7 +2448,7 @@ def readICULegacyZones(icuDir): # non-IANA time zones and links. # Most legacy, non-IANA time zones and links are in the icuzones file. - (zones, links) = readIANAFiles(tzdir, ["icuzones"]) + (zones, links, _) = readIANAFiles(tzdir, ["icuzones"]) # Remove the ICU placeholder time zone "Etc/Unknown". # See also . @@ -2562,7 +2512,7 @@ def icuTzDataVersion(icuTzDir): return version -def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzone): +def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks): """Find incorrect ICU zone entries.""" def isIANATimeZone(zone): @@ -2576,11 +2526,7 @@ def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzo # All IANA zones should be present in ICU. missingTimeZones = [zone for zone in ianaZones if not isICUTimeZone(zone)] - # Normally zones in backzone are also present as links in one of the other - # time zone files. The only exception to this rule is the Asia/Hanoi time - # zone, this zone is only present in the backzone file. - expectedMissing = [] if ignoreBackzone else [Zone("Asia/Hanoi")] - if missingTimeZones != expectedMissing: + if missingTimeZones: raise RuntimeError( "Not all zones are present in ICU, did you forget " "to run intl/update-tzdata.sh? %s" % missingTimeZones @@ -2661,28 +2607,156 @@ def findIncorrectICULinks(ianaZones, ianaLinks, icuZones, icuLinks): return sorted(result, key=itemgetter(0)) +def readZoneTab(tzdataDir): + zone_country = dict() + + zonetab_path = tzdataDir.resolve("zone.tab") + for line in tzdataDir.readlines(zonetab_path): + if line.startswith("#"): + continue + (country, coords, zone, *comments) = line.strip().split("\t") + assert zone not in zone_country + zone_country[zone] = country + + return zone_country + + +# 6.5.1 AvailableNamedTimeZoneIdentifiers ( ) +# +# https://tc39.es/ecma402/#sup-availablenamedtimezoneidentifiers +def availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory): + js_src_builtin_intl_dir = os.path.dirname(os.path.abspath(__file__)) + + with open( + os.path.join(js_src_builtin_intl_dir, "TimeZoneMapping.yaml"), + encoding="utf-8", + ) as f: + time_zone_mapping = yaml.safe_load(f) + + zone_country = readZoneTab(tzdataDir) + + def country_code_for(name): + if name in zone_country: + return zone_country[name] + return time_zone_mapping[name] + + (ianaZones, ianaLinks) = readIANATimeZones(tzdataDir, ignoreFactory) + + (backzones, backlinks, packratlinks) = readIANAFiles(tzdataDir, ["backzone"]) + all_backzone_links = {**backlinks, **packratlinks} + + # Steps 1-3. (Not applicable) + + # Step 4. + zones = set() + links = dict() + + # Step 5. (Partial, only zones) + for zone in ianaZones: + # Step 5.a. + primary = zone + + # Step 5.b. (Not applicable for zones) + + # Step 5.c. + if primary.name in ["Etc/UTC", "Etc/GMT", "GMT"]: + primary = Zone("UTC", primary.filename) + + # Step 5.d. (Not applicable) + + # Steps 5.e-f. + if primary == zone: + assert zone not in zones + zones.add(primary) + else: + assert zone not in links + links[zone] = primary.name + + # Step 5. (Partial, only links) + for zone, target in ianaLinks.items(): + identifier = zone.name + + # Step 5.a. + primary = identifier + + # Step 5.b. + if identifier not in zone_country: + # Step 5.b.i. (Not applicable) + + # Steps 5.b.ii-iii. + if target.startswith("Etc/"): + primary = target + else: + # Step 5.b.iii.1. + identifier_code_code = country_code_for(identifier) + + # Step 5.b.iii.2. + target_code_code = country_code_for(target) + + # Steps 5.b.iii.3-4 + if identifier_code_code == target_code_code: + primary = target + else: + # Step 5.b.iii.4.a. + country_code_line_count = [ + zone + for (zone, code) in zone_country.items() + if code == identifier_code_code + ] + + # Steps 5.b.iii.4.b-c. + if len(country_code_line_count) == 1: + primary = country_code_line_count[0] + else: + assert Zone(identifier) in all_backzone_links + primary = all_backzone_links[Zone(identifier)] + assert identifier_code_code == country_code_for(primary) + + # Step 5.c. + if primary in ["Etc/UTC", "Etc/GMT", "GMT"]: + primary = "UTC" + + # Step 5.d. (Not applicable) + + # Steps 5.e-f. + if primary == identifier: + assert zone not in zones + zones.add(zone) + else: + assert zone not in links + links[zone] = primary + + # Ensure all zones and links are valid. + validateTimeZones(zones, links) + + # Step 6. + assert Zone("UTC") in zones + + # Step 7. + return (zones, links) + + generatedFileWarning = "// Generated by make_intl_data.py. DO NOT EDIT." tzdataVersionComment = "// tzdata version = {0}" -def processTimeZones( - tzdataDir, icuDir, icuTzDir, version, ignoreBackzone, ignoreFactory, out -): +def processTimeZones(tzdataDir, icuDir, icuTzDir, version, ignoreFactory, out): """Read the time zone info and create a new time zone cpp file.""" print("Processing tzdata mapping...") - (ianaZones, ianaLinks) = readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory) + (ianaZones, ianaLinks) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) (icuZones, icuLinks) = readICUTimeZones(icuDir, icuTzDir, ignoreFactory) (legacyZones, legacyLinks) = readICULegacyZones(icuDir) + if ignoreFactory: + legacyZones.add(Zone("Factory")) + # Remove all legacy ICU time zones. icuZones = {zone for zone in icuZones if zone not in legacyZones} icuLinks = { zone: target for (zone, target) in icuLinks.items() if zone not in legacyLinks } - incorrectZones = findIncorrectICUZones( - ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzone - ) + incorrectZones = findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks) if not incorrectZones: print("<<< No incorrect ICU time zones found, please update Intl.js! >>>") print("<<< Maybe https://ssl.icu-project.org/trac/ticket/12044 was fixed? >>>") @@ -2693,7 +2767,7 @@ def processTimeZones( print("<<< Maybe https://ssl.icu-project.org/trac/ticket/12044 was fixed? >>>") print("Writing Intl tzdata file...") - with io.open(out, mode="w", encoding="utf-8", newline="") as f: + with open(out, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println(generatedFileWarning) @@ -2752,29 +2826,13 @@ def processTimeZones( println("#endif /* builtin_intl_TimeZoneDataGenerated_h */") -def updateBackzoneLinks(tzdataDir, links): - def withZone(fn): - return lambda zone_target: fn(zone_target[0]) +def generateTzDataTestLinks(tzdataDir, version, ignoreFactory, testDir): + fileName = "timeZone_links.js" - (backzoneZones, backzoneLinks) = readIANAFiles(tzdataDir, ["backzone"]) - (stableZones, updatedLinks, updatedZones) = partition( - links.items(), - # Link not changed in backzone. - withZone(lambda zone: zone not in backzoneLinks and zone not in backzoneZones), - # Link has a new target. - withZone(lambda zone: zone in backzoneLinks), - ) - # Keep stable zones and links with updated target. - return dict( - chain( - stableZones, - map(withZone(lambda zone: (zone, backzoneLinks[zone])), updatedLinks), - ) - ) + # Read zone and link infos. + (_, links) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) - -def generateTzDataLinkTestContent(testDir, version, fileName, description, links): - with io.open( + with open( os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline="" ) as f: println = partial(print, file=f) @@ -2793,9 +2851,9 @@ const tzMapper = [ """ ) - println(description) + println("// Link names derived from IANA Time Zone Database.") println("const links = {") - for zone, target in sorted(links, key=itemgetter(0)): + for zone, target in sorted(links.items(), key=itemgetter(0)): println(' "%s": "%s",' % (zone, target)) println("};") @@ -2821,116 +2879,10 @@ if (typeof reportCompare === "function") ) -def generateTzDataTestBackwardLinks(tzdataDir, version, ignoreBackzone, testDir): - (zones, links) = readIANAFiles(tzdataDir, ["backward"]) - assert len(zones) == 0 - - if not ignoreBackzone: - links = updateBackzoneLinks(tzdataDir, links) - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_backward_links.js", - "// Link names derived from IANA Time Zone Database, backward file.", - links.items(), - ) - - -def generateTzDataTestNotBackwardLinks(tzdataDir, version, ignoreBackzone, testDir): - tzfiles = filterfalse( - {"backward", "backzone"}.__contains__, listIANAFiles(tzdataDir) - ) - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - - if not ignoreBackzone: - links = updateBackzoneLinks(tzdataDir, links) - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_notbackward_links.js", - "// Link names derived from IANA Time Zone Database, excluding backward file.", - links.items(), - ) - - -def generateTzDataTestBackzone(tzdataDir, version, ignoreBackzone, testDir): - backzoneFiles = {"backzone"} - (bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__) - - # Read zone and link infos. - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - (backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles) - - if not ignoreBackzone: - comment = """\ -// This file was generated with historical, pre-1970 backzone information -// respected. Therefore, every zone key listed below is its own Zone, not -// a Link to a modern-day target as IANA ignoring backzones would say. - -""" - else: - comment = """\ -// This file was generated while ignoring historical, pre-1970 backzone -// information. Therefore, every zone key listed below is part of a Link -// whose target is the corresponding value. - -""" - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_backzone.js", - comment + "// Backzone zones derived from IANA Time Zone Database.", - ( - (zone, zone if not ignoreBackzone else links[zone]) - for zone in backzones - if zone in links - ), - ) - - -def generateTzDataTestBackzoneLinks(tzdataDir, version, ignoreBackzone, testDir): - backzoneFiles = {"backzone"} - (bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__) - - # Read zone and link infos. - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - (backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles) - - if not ignoreBackzone: - comment = """\ -// This file was generated with historical, pre-1970 backzone information -// respected. Therefore, every zone key listed below points to a target -// in the backzone file and not to its modern-day target as IANA ignoring -// backzones would say. - -""" - else: - comment = """\ -// This file was generated while ignoring historical, pre-1970 backzone -// information. Therefore, every zone key listed below is part of a Link -// whose target is the corresponding value ignoring any backzone entries. - -""" - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_backzone_links.js", - comment + "// Backzone links derived from IANA Time Zone Database.", - ( - (zone, target if not ignoreBackzone else links[zone]) - for (zone, target) in backlinks.items() - ), - ) - - def generateTzDataTestVersion(tzdataDir, version, testDir): fileName = "timeZone_version.js" - with io.open( + with open( os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline="" ) as f: println = partial(print, file=f) @@ -2939,7 +2891,7 @@ def generateTzDataTestVersion(tzdataDir, version, testDir): println("") println(generatedFileWarning) println(tzdataVersionComment.format(version)) - println("""const tzdata = "{0}";""".format(version)) + println(f"""const tzdata = "{version}";""") println( """ @@ -2957,34 +2909,13 @@ if (typeof reportCompare === "function") ) -def generateTzDataTestCanonicalZones( - tzdataDir, version, ignoreBackzone, ignoreFactory, testDir -): +def generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir): fileName = "supportedValuesOf-timeZones-canonical.js" # Read zone and link infos. - (ianaZones, _) = readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory) + (zones, _) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) - # Replace Etc/GMT and Etc/UTC with UTC. - ianaZones.remove(Zone("Etc/GMT")) - ianaZones.remove(Zone("Etc/UTC")) - ianaZones.add(Zone("UTC")) - - # See findIncorrectICUZones() for why Asia/Hanoi has to be special-cased. - ianaZones.remove(Zone("Asia/Hanoi")) - - if not ignoreBackzone: - comment = """\ -// This file was generated with historical, pre-1970 backzone information -// respected. -""" - else: - comment = """\ -// This file was generated while ignoring historical, pre-1970 backzone -// information. -""" - - with io.open( + with open( os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline="" ) as f: println = partial(print, file=f) @@ -2993,11 +2924,9 @@ def generateTzDataTestCanonicalZones( println("") println(generatedFileWarning) println(tzdataVersionComment.format(version)) - println("") - println(comment) println("const zones = [") - for zone in sorted(ianaZones): + for zone in sorted(zones): println(f' "{zone}",') println("];") @@ -3013,19 +2942,112 @@ if (typeof reportCompare === "function") ) -def generateTzDataTests(tzdataDir, version, ignoreBackzone, ignoreFactory, testDir): +def generateTzDataTestZones(tzdataDir, version, ignoreFactory, testDir): + fileName = "zones-and-links.js" + + # Read zone and link infos. + (zones, links) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) + + with open( + os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline="" + ) as f: + println = partial(print, file=f) + + println( + '// |reftest| shell-option(--enable-temporal) skip-if(!this.hasOwnProperty("Temporal"))' + ) + println("") + println(generatedFileWarning) + println(tzdataVersionComment.format(version)) + + println("const zones = [") + for zone in sorted(zones): + println(f' "{zone}",') + println("];") + + println("const links = {") + for link, target in sorted(links.items(), key=itemgetter(0)): + println(f' "{link}": "{target}",') + println("};") + + println( + """ +let epochNanoseconds = [ + new Temporal.PlainDate(1900, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(1950, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(1960, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(1970, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(1980, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(1990, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(2000, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(2010, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(2020, 1, 1).toZonedDateTime("UTC").epochNanoseconds, + new Temporal.PlainDate(2030, 1, 1).toZonedDateTime("UTC").epochNanoseconds, +]; + +function timeZoneId(zdt) { + let str = zdt.toString(); + let m = str.match(/(?<=\\[)[\\w\\/_+-]+(?=\\])/); + assertEq(m !== null, true, str); + return m[0]; +} + +for (let zone of zones) { + let zdt = new Temporal.ZonedDateTime(0n, zone); + + assertEq(zdt.timeZoneId, zone); + assertEq(timeZoneId(zdt), zone); +} + +for (let [link, zone] of Object.entries(links)) { + assertEq(link === zone, false, `link=${link}, zone=${zone}`); + assertEq(zones.includes(zone), true, `zone=${zone}`); + + let zdtLink = new Temporal.ZonedDateTime(0n, link); + let zdtZone = new Temporal.ZonedDateTime(0n, zone); + + assertEq(zdtLink.timeZoneId, link); + assertEq(timeZoneId(zdtLink), link); + + assertEq(zdtZone.timeZoneId, zone); + assertEq(timeZoneId(zdtZone), zone); + + assertEq(zdtLink.equals(zdtZone), true, `link=${link}, zone=${zone}`); + + assertEq( + zdtLink.offsetNanoseconds, + zdtZone.offsetNanoseconds, + `link=${link}, zone=${zone}` + ); + + for (let epochNs of epochNanoseconds) { + assertEq( + new Temporal.ZonedDateTime(epochNs, link).offsetNanoseconds, + new Temporal.ZonedDateTime(epochNs, zone).offsetNanoseconds, + `link=${link}, zone=${zone}, epochNs=${epochNs}` + ); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); +""" + ) + + +def generateTzDataTests(tzdataDir, version, ignoreFactory, testDir): dtfTestDir = os.path.join(testDir, "DateTimeFormat") if not os.path.isdir(dtfTestDir): raise RuntimeError("not a directory: %s" % dtfTestDir) - generateTzDataTestBackwardLinks(tzdataDir, version, ignoreBackzone, dtfTestDir) - generateTzDataTestNotBackwardLinks(tzdataDir, version, ignoreBackzone, dtfTestDir) - generateTzDataTestBackzone(tzdataDir, version, ignoreBackzone, dtfTestDir) - generateTzDataTestBackzoneLinks(tzdataDir, version, ignoreBackzone, dtfTestDir) + zdtTestDir = os.path.join(testDir, "../Temporal/ZonedDateTime") + if not os.path.isdir(zdtTestDir): + raise RuntimeError("not a directory: %s" % zdtTestDir) + + generateTzDataTestLinks(tzdataDir, version, ignoreFactory, dtfTestDir) generateTzDataTestVersion(tzdataDir, version, dtfTestDir) - generateTzDataTestCanonicalZones( - tzdataDir, version, ignoreBackzone, ignoreFactory, testDir - ) + generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir) + generateTzDataTestZones(tzdataDir, version, ignoreFactory, zdtTestDir) def updateTzdata(topsrcdir, args): @@ -3046,11 +3068,11 @@ def updateTzdata(topsrcdir, args): tzDir = args.tz if tzDir is not None and not (os.path.isdir(tzDir) or os.path.isfile(tzDir)): raise RuntimeError("not a directory or file: %s" % tzDir) - ignoreBackzone = args.ignore_backzone - # TODO: Accept or ignore the placeholder time zone "Factory"? - ignoreFactory = False out = args.out + # Ignore the placeholder time zone "Factory". + ignoreFactory = True + version = icuTzDataVersion(icuTzDir) url = ( "https://www.iana.org/time-zones/repository/releases/tzdata%s.tar.gz" % version @@ -3062,7 +3084,6 @@ def updateTzdata(topsrcdir, args): print("\ttzdata directory|file: %s" % tzDir) print("\tICU directory: %s" % icuDir) print("\tICU timezone directory: %s" % icuTzDir) - print("\tIgnore backzone file: %s" % ignoreBackzone) print("\tOutput file: %s" % out) print("") @@ -3074,12 +3095,11 @@ def updateTzdata(topsrcdir, args): icuDir, icuTzDir, version, - ignoreBackzone, ignoreFactory, out, ) generateTzDataTests( - TzDataFile(tar), version, ignoreBackzone, ignoreFactory, intlTestDir + TzDataFile(tar), version, ignoreFactory, intlTestDir ) elif os.path.isdir(f): processTimeZones( @@ -3087,13 +3107,10 @@ def updateTzdata(topsrcdir, args): icuDir, icuTzDir, version, - ignoreBackzone, ignoreFactory, out, ) - generateTzDataTests( - TzDataDir(f), version, ignoreBackzone, ignoreFactory, intlTestDir - ) + generateTzDataTests(TzDataDir(f), version, ignoreFactory, intlTestDir) else: raise RuntimeError("unknown format") @@ -3132,11 +3149,11 @@ def readCurrencyFile(tree): def writeCurrencyFile(published, currencies, out): - with io.open(out, mode="w", encoding="utf-8", newline="") as f: + with open(out, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println(generatedFileWarning) - println("// Version: {}".format(published)) + println(f"// Version: {published}") println( """ @@ -3153,8 +3170,8 @@ def writeCurrencyFile(published, currencies, out): sorted(currencies, key=itemgetter(0)), itemgetter(0) ): for _, minorUnits, currencyName, countryName in entries: - println(" // {} ({})".format(currencyName, countryName)) - println(" {}: {},".format(currency, minorUnits)) + println(f" // {currencyName} ({countryName})") + println(f" {currency}: {minorUnits},") println("};") @@ -3205,24 +3222,22 @@ def updateCurrency(topsrcdir, args): def writeUnicodeExtensionsMappings(println, mapping, extension): println( - """ + f""" template -static inline bool Is{0}Key(mozilla::Span key, const char (&str)[Length]) {{ - static_assert(Length == {0}KeyLength + 1, - "{0} extension key is two characters long"); +static inline bool Is{extension}Key(mozilla::Span key, const char (&str)[Length]) {{ + static_assert(Length == {extension}KeyLength + 1, + "{extension} extension key is two characters long"); return memcmp(key.data(), str, Length - 1) == 0; }} template -static inline bool Is{0}Type(mozilla::Span type, const char (&str)[Length]) {{ - static_assert(Length > {0}KeyLength + 1, - "{0} extension type contains more than two characters"); +static inline bool Is{extension}Type(mozilla::Span type, const char (&str)[Length]) {{ + static_assert(Length > {extension}KeyLength + 1, + "{extension} extension type contains more than two characters"); return type.size() == (Length - 1) && memcmp(type.data(), str, Length - 1) == 0; }} -""".format( - extension - ).rstrip( +""".rstrip( "\n" ) ) @@ -3236,8 +3251,8 @@ static inline bool Is{0}Type(mozilla::Span type, const char (&str)[L if needs_binary_search: println( - """ -static int32_t Compare{0}Type(const char* a, mozilla::Span b) {{ + f""" +static int32_t Compare{extension}Type(const char* a, mozilla::Span b) {{ MOZ_ASSERT(!std::char_traits::find(b.data(), b.size(), '\\0'), "unexpected null-character in string"); @@ -3257,45 +3272,41 @@ static int32_t Compare{0}Type(const char* a, mozilla::Span b) {{ }} template -static inline const char* Search{0}Replacement( +static inline const char* Search{extension}Replacement( const char* (&types)[Length], const char* (&aliases)[Length], mozilla::Span type) {{ auto p = std::lower_bound(std::begin(types), std::end(types), type, [](const auto& a, const auto& b) {{ - return Compare{0}Type(a, b) < 0; + return Compare{extension}Type(a, b) < 0; }}); - if (p != std::end(types) && Compare{0}Type(*p, type) == 0) {{ + if (p != std::end(types) && Compare{extension}Type(*p, type) == 0) {{ return aliases[std::distance(std::begin(types), p)]; }} return nullptr; }} -""".format( - extension - ).rstrip( +""".rstrip( "\n" ) ) println( - """ + f""" /** - * Mapping from deprecated BCP 47 {0} extension types to their preferred + * Mapping from deprecated BCP 47 {extension} extension types to their preferred * values. * * Spec: https://www.unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files * Spec: https://www.unicode.org/reports/tr35/#t_Extension */ -const char* mozilla::intl::Locale::Replace{0}ExtensionType( +const char* mozilla::intl::Locale::Replace{extension}ExtensionType( mozilla::Span key, mozilla::Span type) {{ - MOZ_ASSERT(key.size() == {0}KeyLength); - MOZ_ASSERT(IsCanonicallyCased{0}Key(key)); + MOZ_ASSERT(key.size() == {extension}KeyLength); + MOZ_ASSERT(IsCanonicallyCased{extension}Key(key)); - MOZ_ASSERT(type.size() > {0}KeyLength); - MOZ_ASSERT(IsCanonicallyCased{0}Type(type)); -""".format( - extension - ) + MOZ_ASSERT(type.size() > {extension}KeyLength); + MOZ_ASSERT(IsCanonicallyCased{extension}Type(type)); +""" ) def to_hash_key(replacements): @@ -3304,13 +3315,11 @@ const char* mozilla::intl::Locale::Replace{0}ExtensionType( def write_array(subtags, name, length): max_entries = (80 - len(" ")) // (length + len('"", ')) - println(" static const char* {}[{}] = {{".format(name, len(subtags))) + println(f" static const char* {name}[{len(subtags)}] = {{") for entries in grouper(subtags, max_entries): entries = ( - '"{}"'.format(tag).center(length + 2) - for tag in entries - if tag is not None + f'"{tag}"'.center(length + 2) for tag in entries if tag is not None ) println(" {},".format(", ".join(entries))) @@ -3331,18 +3340,13 @@ const char* mozilla::intl::Locale::Replace{0}ExtensionType( if key in key_aliases[hash_key]: continue - cond = ( - 'Is{}Key(key, "{}")'.format(extension, k) - for k in [key] + key_aliases[hash_key] - ) + cond = (f'Is{extension}Key(key, "{k}")' for k in [key] + key_aliases[hash_key]) if_kind = "if" if first_key else "else if" cond = (" ||\n" + " " * (2 + len(if_kind) + 2)).join(cond) println( - """ - {} ({}) {{""".format( - if_kind, cond - ).strip( + f""" + {if_kind} ({cond}) {{""".strip( "\n" ) ) @@ -3358,23 +3362,19 @@ const char* mozilla::intl::Locale::Replace{0}ExtensionType( write_array(types, "types", max_len) write_array(preferred, "aliases", max_len) println( - """ - return Search{}Replacement(types, aliases, type); -""".format( - extension - ).strip( + f""" + return Search{extension}Replacement(types, aliases, type); +""".strip( "\n" ) ) else: for type, replacement in replacements: println( - """ - if (Is{}Type(type, "{}")) {{ - return "{}"; - }}""".format( - extension, type, replacement - ).strip( + f""" + if (Is{extension}Type(type, "{type}")) {{ + return "{replacement}"; + }}""".strip( "\n" ) ) @@ -3484,7 +3484,7 @@ def readICUUnitResourceFile(filepath): table[entry_key] = entry_value continue - raise Exception("unexpected line: '{}' in {}".format(line, filepath)) + raise Exception(f"unexpected line: '{line}' in {filepath}") assert len(parents) == 0, "Not all tables closed" assert len(table) == 1, "More than one root table" @@ -3523,7 +3523,7 @@ def computeSupportedUnits(all_units, sanctioned_units): def compound_unit_identifiers(): for numerator in sanctioned_units: for denominator in sanctioned_units: - yield "{}-per-{}".format(numerator, denominator) + yield f"{numerator}-per-{denominator}" supported_simple_units = {find_match(unit) for unit in sanctioned_units} assert None not in supported_simple_units @@ -3538,7 +3538,7 @@ def computeSupportedUnits(all_units, sanctioned_units): def readICUDataFilterForUnits(data_filter_file): - with io.open(data_filter_file, mode="r", encoding="utf-8") as f: + with open(data_filter_file, encoding="utf-8") as f: data_filter = json.load(f) # Find the rule set for the "unit_tree". @@ -3573,7 +3573,7 @@ def writeSanctionedSimpleUnitIdentifiersFiles(all_units, sanctioned_units): sanctioned_js_file = os.path.join( js_src_builtin_intl_dir, "SanctionedSimpleUnitIdentifiersGenerated.js" ) - with io.open(sanctioned_js_file, mode="w", encoding="utf-8", newline="") as f: + with open(sanctioned_js_file, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) sanctioned_units_object = json.dumps( @@ -3595,12 +3595,10 @@ def writeSanctionedSimpleUnitIdentifiersFiles(all_units, sanctioned_units): ) println("// prettier-ignore") - println( - "var sanctionedSimpleUnitIdentifiers = {};".format(sanctioned_units_object) - ) + println(f"var sanctionedSimpleUnitIdentifiers = {sanctioned_units_object};") sanctioned_h_file = os.path.join(intl_components_src_dir, "MeasureUnitGenerated.h") - with io.open(sanctioned_h_file, mode="w", encoding="utf-8", newline="") as f: + with open(sanctioned_h_file, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println(generatedFileWarning) @@ -3627,7 +3625,7 @@ inline constexpr SimpleMeasureUnit simpleMeasureUnits[] = { ) for unit_name in sorted(sanctioned_units): - println(' {{"{}", "{}"}},'.format(find_unit_type(unit_name), unit_name)) + println(f' {{"{find_unit_type(unit_name)}", "{unit_name}"}},') println( """ @@ -3655,7 +3653,7 @@ def writeUnitTestFiles(all_units, sanctioned_units): def write_test(file_name, test_content, indent=4): file_path = os.path.join(test_dir, file_name) - with io.open(file_path, mode="w", encoding="utf-8", newline="") as f: + with open(file_path, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println('// |reftest| skip-if(!this.hasOwnProperty("Intl"))') @@ -3670,9 +3668,7 @@ def writeUnitTestFiles(all_units, sanctioned_units): ) println( - "const sanctionedSimpleUnitIdentifiers = {};".format( - sanctioned_units_array - ) + f"const sanctionedSimpleUnitIdentifiers = {sanctioned_units_array};" ) println(test_content) @@ -3706,11 +3702,9 @@ for (const numerator of sanctionedSimpleUnitIdentifiers) { write_test( "unit-well-formed.js", - """ -const allUnits = {}; -""".format( - all_units_array - ) + f""" +const allUnits = {all_units_array}; +""" + r""" // Test only sanctioned unit identifiers are allowed. @@ -3783,9 +3777,8 @@ def updateUnits(topsrcdir, args): icu_path = os.path.join(topsrcdir, "intl", "icu") icu_unit_path = os.path.join(icu_path, "source", "data", "unit") - with io.open( + with open( os.path.join(js_src_builtin_intl_dir, "SanctionedSimpleUnitIdentifiers.yaml"), - mode="r", encoding="utf-8", ) as f: sanctioned_units = yaml.safe_load(f) @@ -3809,13 +3802,13 @@ def updateUnits(topsrcdir, args): missing = supported_units - filtered_units if missing: - raise RuntimeError("Missing units: {}".format(units_to_string(missing))) + raise RuntimeError(f"Missing units: {units_to_string(missing)}") # Not exactly an error, but we currently don't have a use case where we need to support # more units than required by ECMA-402. extra = filtered_units - supported_units if extra: - raise RuntimeError("Unnecessary units: {}".format(units_to_string(extra))) + raise RuntimeError(f"Unnecessary units: {units_to_string(extra)}") writeSanctionedSimpleUnitIdentifiersFiles(all_units, sanctioned_units) @@ -3901,7 +3894,7 @@ def readICUNumberingSystemsResourceFile(filepath): table[entry_key] = entry_value continue - raise Exception("unexpected line: '{}' in {}".format(line, filepath)) + raise Exception(f"unexpected line: '{line}' in {filepath}") assert len(parents) == 0, "Not all tables closed" assert len(table) == 1, "More than one root table" @@ -3915,9 +3908,11 @@ def readICUNumberingSystemsResourceFile(filepath): # Return the numbering systems. return { - key: {"digits": value["desc"], "algorithmic": False} - if not bool(value["algorithmic"]) - else {"algorithmic": True} + key: ( + {"digits": value["desc"], "algorithmic": False} + if not bool(value["algorithmic"]) + else {"algorithmic": True} + ) for (key, value) in numbering_systems.items() } @@ -3928,9 +3923,7 @@ def writeNumberingSystemFiles(numbering_systems): numbering_systems_js_file = os.path.join( js_src_builtin_intl_dir, "NumberingSystemsGenerated.h" ) - with io.open( - numbering_systems_js_file, mode="w", encoding="utf-8", newline="" - ) as f: + with open(numbering_systems_js_file, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println(generatedFileWarning) @@ -3956,9 +3949,7 @@ def writeNumberingSystemFiles(numbering_systems): println("#define NUMBERING_SYSTEMS_WITH_SIMPLE_DIGIT_MAPPINGS \\") println( "{}".format( - ", \\\n".join( - ' "{}"'.format(name) for name in simple_numbering_systems - ) + ", \\\n".join(f' "{name}"' for name in simple_numbering_systems) ) ) println("// clang-format on") @@ -3971,19 +3962,17 @@ def writeNumberingSystemFiles(numbering_systems): intl_shell_js_file = os.path.join(test_dir, "shell.js") - with io.open(intl_shell_js_file, mode="w", encoding="utf-8", newline="") as f: + with open(intl_shell_js_file, mode="w", encoding="utf-8", newline="") as f: println = partial(print, file=f) println(generatedFileWarning) println( - """ -// source: CLDR file common/bcp47/number.xml; version CLDR {}. + f""" +// source: CLDR file common/bcp47/number.xml; version CLDR {readCLDRVersionFromICU()}. // https://github.com/unicode-org/cldr/blob/master/common/bcp47/number.xml // https://github.com/unicode-org/cldr/blob/master/common/supplemental/numberingSystems.xml -""".format( - readCLDRVersionFromICU() - ).rstrip() +""".rstrip() ) numbering_systems_object = json.dumps( @@ -3993,7 +3982,7 @@ def writeNumberingSystemFiles(numbering_systems): sort_keys=True, ensure_ascii=False, ) - println("const numberingSystems = {};".format(numbering_systems_object)) + println(f"const numberingSystems = {numbering_systems_object};") def updateNumberingSystems(topsrcdir, args): @@ -4001,9 +3990,8 @@ def updateNumberingSystems(topsrcdir, args): icu_path = os.path.join(topsrcdir, "intl", "icu") icu_misc_path = os.path.join(icu_path, "source", "data", "misc") - with io.open( + with open( os.path.join(js_src_builtin_intl_dir, "NumberingSystems.yaml"), - mode="r", encoding="utf-8", ) as f: numbering_systems = yaml.safe_load(f) @@ -4022,14 +4010,14 @@ def updateNumberingSystems(topsrcdir, args): # something is broken in ICU. assert all_numbering_systems_simple_digits.issuperset( numbering_systems - ), "{}".format(numbering_systems.difference(all_numbering_systems_simple_digits)) + ), f"{numbering_systems.difference(all_numbering_systems_simple_digits)}" # Assert the spec requires support for all numbering systems with simple digit mappings. If # this assertion fails, file a PR at to include any new # numbering systems. - assert all_numbering_systems_simple_digits.issubset(numbering_systems), "{}".format( - all_numbering_systems_simple_digits.difference(numbering_systems) - ) + assert all_numbering_systems_simple_digits.issubset( + numbering_systems + ), f"{all_numbering_systems_simple_digits.difference(numbering_systems)}" writeNumberingSystemFiles(all_numbering_systems) @@ -4061,7 +4049,7 @@ if __name__ == "__main__": parser_cldr_tags.add_argument( "--url", metavar="URL", - default="https://unicode.org/Public/cldr//cldr-common-.0.zip", + default="https://unicode.org/Public/cldr//cldr-common-.zip", type=EnsureHttps, help="Download url CLDR data (default: %(default)s)", ) @@ -4083,17 +4071,6 @@ if __name__ == "__main__": help="Local tzdata directory or file, if omitted downloads tzdata " "distribution from https://www.iana.org/time-zones/", ) - # ICU doesn't include the backzone file by default, but we still like to - # use the backzone time zone names to avoid user confusion. This does lead - # to formatting "historic" dates (pre-1970 era) with the wrong time zone, - # but that's probably acceptable for now. - parser_tz.add_argument( - "--ignore-backzone", - action="store_true", - help="Ignore tzdata's 'backzone' file. Can be enabled to generate more " - "accurate time zone canonicalization reflecting the actual time " - "zones as used by ICU.", - ) parser_tz.add_argument( "--out", default=os.path.join(thisDir, "TimeZoneDataGenerated.h"), diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.cpp index 45c59686417..fb75a20fa39 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.cpp @@ -8,171 +8,94 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/Casting.h" +#include "mozilla/CheckedInt.h" #include "mozilla/EnumSet.h" #include "mozilla/FloatingPoint.h" -#include "mozilla/Likely.h" +#include "mozilla/intl/ICU4XGeckoDataProvider.h" +#include "mozilla/intl/Locale.h" +#include "mozilla/MathAlgorithms.h" #include "mozilla/Maybe.h" -#include "mozilla/Range.h" +#include "mozilla/Result.h" +#include "mozilla/ResultVariant.h" +#include "mozilla/Span.h" #include "mozilla/TextUtils.h" +#include "mozilla/UniquePtr.h" #include #include #include -#include +#include #include #include #include #include -#include "jsfriendapi.h" +#include "diplomat_runtime.h" +#include "ICU4XAnyCalendarKind.h" +#include "ICU4XCalendar.h" +#include "ICU4XDate.h" +#include "ICU4XError.h" +#include "ICU4XIsoDate.h" +#include "ICU4XIsoWeekday.h" +#include "ICU4XWeekCalculator.h" +#include "ICU4XWeekRelativeUnit.h" + #include "jsnum.h" -#include "jspubtd.h" #include "jstypes.h" #include "NamespaceImports.h" -#include "builtin/Array.h" -#include "builtin/String.h" +#include "builtin/temporal/CalendarFields.h" +#include "builtin/temporal/Crash.h" #include "builtin/temporal/Duration.h" +#include "builtin/temporal/Era.h" +#include "builtin/temporal/MonthCode.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/PlainMonthDay.h" #include "builtin/temporal/PlainTime.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" +#include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" -#include "builtin/temporal/Wrapped.h" #include "builtin/temporal/ZonedDateTime.h" -#include "gc/AllocKind.h" #include "gc/Barrier.h" #include "gc/GCEnum.h" -#include "gc/Tracer.h" #include "js/AllocPolicy.h" -#include "js/CallArgs.h" -#include "js/CallNonGenericMethod.h" -#include "js/Class.h" -#include "js/Conversions.h" #include "js/ErrorReport.h" -#include "js/ForOfIterator.h" #include "js/friend/ErrorMessages.h" -#include "js/GCAPI.h" -#include "js/GCHashTable.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/Printer.h" -#include "js/PropertyDescriptor.h" -#include "js/PropertySpec.h" #include "js/RootingAPI.h" #include "js/TracingAPI.h" #include "js/Value.h" +#include "js/Vector.h" #include "util/Text.h" -#include "vm/ArrayObject.h" #include "vm/BytecodeUtil.h" #include "vm/Compartment.h" -#include "vm/GlobalObject.h" -#include "vm/Interpreter.h" #include "vm/JSAtomState.h" #include "vm/JSContext.h" -#include "vm/JSObject.h" -#include "vm/PlainObject.h" -#include "vm/PropertyInfo.h" -#include "vm/PropertyKey.h" -#include "vm/Realm.h" -#include "vm/Shape.h" -#include "vm/Stack.h" #include "vm/StringType.h" #include "vm/Compartment-inl.h" -#include "vm/JSAtomUtils-inl.h" +#include "vm/JSContext-inl.h" #include "vm/JSObject-inl.h" -#include "vm/NativeObject-inl.h" #include "vm/ObjectOperations-inl.h" using namespace js; using namespace js::temporal; -static inline bool IsCalendar(Handle v) { - return v.isObject() && v.toObject().is(); -} - void js::temporal::CalendarValue::trace(JSTracer* trc) { TraceRoot(trc, &value_, "CalendarValue::value"); } -void js::temporal::CalendarRecord::trace(JSTracer* trc) { - receiver_.trace(trc); - TraceNullableRoot(trc, &dateAdd_, "CalendarRecord::dateAdd"); - TraceNullableRoot(trc, &dateFromFields_, "CalendarRecord::dateFromFields"); - TraceNullableRoot(trc, &dateUntil_, "CalendarRecord::dateUntil"); - TraceNullableRoot(trc, &day_, "CalendarRecord::day"); - TraceNullableRoot(trc, &fields_, "CalendarRecord::fields"); - TraceNullableRoot(trc, &mergeFields_, "CalendarRecord::mergeFields"); - TraceNullableRoot(trc, &monthDayFromFields_, - "CalendarRecord::monthDayFromFields"); - TraceNullableRoot(trc, &yearMonthFromFields_, - "CalendarRecord::yearMonthFromFields"); -} - bool js::temporal::WrapCalendarValue(JSContext* cx, MutableHandle calendar) { - MOZ_ASSERT(calendar.isInt32() || calendar.isObject()); + MOZ_ASSERT(calendar.isInt32()); return cx->compartment()->wrap(cx, calendar); } -/** - * IteratorToListOfType ( iteratorRecord, elementTypes ) - * - * With `elementTypes = « String »`. - * - * This implementation accepts an iterable instead of an iterator record. - */ -static bool IterableToListOfStrings(JSContext* cx, Handle items, - MutableHandle list) { - JS::ForOfIterator iterator(cx); - if (!iterator.init(items)) { - return false; - } - - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Rooted nextValue(cx); - Rooted value(cx); - while (true) { - // Step 2.a. - bool done; - if (!iterator.next(&nextValue, &done)) { - return false; - } - - // Step 2.b. - if (done) { - return true; - } - - // Step 2.d. (Reordered) - if (nextValue.isString()) { - if (!PrimitiveValueToId(cx, nextValue, &value)) { - return false; - } - if (!list.append(value)) { - return false; - } - continue; - } - - // Step 2.c.1. - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, nextValue, - nullptr, "not a string"); - - // Step 2.c.2. - iterator.closeThrow(); - return false; - } -} - /** * IsISOLeapYear ( year ) */ @@ -181,22 +104,10 @@ static constexpr bool IsISOLeapYear(int32_t year) { return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); } -/** - * IsISOLeapYear ( year ) - */ -static bool IsISOLeapYear(double year) { - // Step 1. - MOZ_ASSERT(IsInteger(year)); - - // Steps 2-5. - return std::fmod(year, 4) == 0 && - (std::fmod(year, 100) != 0 || std::fmod(year, 400) == 0); -} - /** * ISODaysInYear ( year ) */ -int32_t js::temporal::ISODaysInYear(int32_t year) { +static int32_t ISODaysInYear(int32_t year) { // Steps 1-3. return IsISOLeapYear(year) ? 366 : 365; } @@ -222,20 +133,6 @@ int32_t js::temporal::ISODaysInMonth(int32_t year, int32_t month) { return ::ISODaysInMonth(year, month); } -/** - * ISODaysInMonth ( year, month ) - */ -int32_t js::temporal::ISODaysInMonth(double year, int32_t month) { - MOZ_ASSERT(1 <= month && month <= 12); - - static constexpr uint8_t daysInMonth[2][13] = { - {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; - - // Steps 1-4. - return daysInMonth[IsISOLeapYear(year)][month]; -} - /** * 21.4.1.6 Week Day * @@ -259,23 +156,19 @@ static int32_t WeekDay(int32_t day) { } /** - * ToISODayOfWeek ( year, month, day ) + * ISODayOfWeek ( isoDate ) */ -static int32_t ToISODayOfWeek(const PlainDate& date) { - MOZ_ASSERT(ISODateTimeWithinLimits(date)); +static int32_t ISODayOfWeek(const ISODate& isoDate) { + MOZ_ASSERT(ISODateWithinLimits(isoDate)); - // Steps 1-3. (Not applicable in our implementation.) + // Step 1. + int32_t day = MakeDay(isoDate); - // TODO: Check if ES MakeDate + WeekDay is efficient enough. - // - // https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Methods_in_computer_code + // Step 2. + int32_t dayOfWeek = WeekDay(day); - // Step 4. - int32_t day = MakeDay(date); - - // Step 5. - int32_t weekday = WeekDay(day); - return weekday != 0 ? weekday : 7; + // Steps 3-4. + return dayOfWeek != 0 ? dayOfWeek : 7; } static constexpr auto FirstDayOfMonth(int32_t year) { @@ -289,18 +182,18 @@ static constexpr auto FirstDayOfMonth(int32_t year) { } /** - * ToISODayOfYear ( year, month, day ) + * ISODayOfYear ( isoDate ) */ -static int32_t ToISODayOfYear(int32_t year, int32_t month, int32_t day) { - MOZ_ASSERT(1 <= month && month <= 12); +static int32_t ISODayOfYear(const ISODate& isoDate) { + MOZ_ASSERT(ISODateWithinLimits(isoDate)); + + const auto& [year, month, day] = isoDate; // First day of month arrays for non-leap and leap years. constexpr decltype(FirstDayOfMonth(0)) firstDayOfMonth[2] = { FirstDayOfMonth(1), FirstDayOfMonth(0)}; - // Steps 1-3. (Not applicable in our implementation.) - - // Steps 4-5. + // Steps 1-2. // // Instead of first computing the date and then using DayWithinYear to map the // date to the day within the year, directly lookup the first day of the month @@ -308,17 +201,6 @@ static int32_t ToISODayOfYear(int32_t year, int32_t month, int32_t day) { return firstDayOfMonth[IsISOLeapYear(year)][month - 1] + day; } -/** - * ToISODayOfYear ( year, month, day ) - */ -int32_t js::temporal::ToISODayOfYear(const PlainDate& date) { - MOZ_ASSERT(ISODateTimeWithinLimits(date)); - - // Steps 1-5. - const auto& [year, month, day] = date; - return ::ToISODayOfYear(year, month, day); -} - static int32_t FloorDiv(int32_t dividend, int32_t divisor) { MOZ_ASSERT(divisor > 0); @@ -341,7 +223,7 @@ static int32_t DayFromYear(int32_t year) { /** * 21.4.1.11 MakeTime ( hour, min, sec, ms ) */ -static int64_t MakeTime(const PlainTime& time) { +static int64_t MakeTime(const Time& time) { MOZ_ASSERT(IsValidTime(time)); // Step 1 (Not applicable). @@ -367,16 +249,16 @@ static int64_t MakeTime(const PlainTime& time) { /** * 21.4.1.12 MakeDay ( year, month, date ) */ -int32_t js::temporal::MakeDay(const PlainDate& date) { - MOZ_ASSERT(ISODateTimeWithinLimits(date)); +int32_t js::temporal::MakeDay(const ISODate& date) { + MOZ_ASSERT(ISODateWithinLimits(date)); - return DayFromYear(date.year) + ToISODayOfYear(date) - 1; + return DayFromYear(date.year) + ISODayOfYear(date) - 1; } /** * 21.4.1.13 MakeDate ( day, time ) */ -int64_t js::temporal::MakeDate(const PlainDateTime& dateTime) { +int64_t js::temporal::MakeDate(const ISODateTime& dateTime) { MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); // Step 1 (Not applicable). @@ -389,304 +271,179 @@ int64_t js::temporal::MakeDate(const PlainDateTime& dateTime) { return tv; } -/** - * 21.4.1.12 MakeDay ( year, month, date ) - */ -static int32_t MakeDay(int32_t year, int32_t month, int32_t day) { - MOZ_ASSERT(1 <= month && month <= 12); - - // FIXME: spec issue - what should happen for invalid years/days? - return DayFromYear(year) + ::ToISODayOfYear(year, month, day) - 1; -} - -/** - * 21.4.1.13 MakeDate ( day, time ) - */ -int64_t js::temporal::MakeDate(int32_t year, int32_t month, int32_t day) { - // NOTE: This version accepts values outside the valid date-time limits. - MOZ_ASSERT(1 <= month && month <= 12); - - // Step 1 (Not applicable). - - // Steps 2-3. - int64_t tv = ::MakeDay(year, month, day) * ToMilliseconds(TemporalUnit::Day); - - // Step 4. - return tv; -} - struct YearWeek final { int32_t year = 0; int32_t week = 0; }; /** - * ToISOWeekOfYear ( year, month, day ) + * ISOWeekOfYear ( isoDate ) */ -static YearWeek ToISOWeekOfYear(const PlainDate& date) { - MOZ_ASSERT(ISODateTimeWithinLimits(date)); +static YearWeek ISOWeekOfYear(const ISODate& isoDate) { + MOZ_ASSERT(ISODateWithinLimits(isoDate)); - const auto& [year, month, day] = date; + // Step 1. + int32_t year = isoDate.year; - // TODO: https://en.wikipedia.org/wiki/Week#The_ISO_week_date_system - // TODO: https://en.wikipedia.org/wiki/ISO_week_date#Algorithms + // Step 2-7. (Not applicable in our implementation.) - // Steps 1-3. (Not applicable in our implementation.) + // Steps 8-9. + int32_t dayOfYear = ISODayOfYear(isoDate); + int32_t dayOfWeek = ISODayOfWeek(isoDate); - // Steps 4-5. - int32_t doy = ToISODayOfYear(date); - int32_t dow = ToISODayOfWeek(date); - - int32_t woy = (10 + doy - dow) / 7; - MOZ_ASSERT(0 <= woy && woy <= 53); + // Step 10. + int32_t week = (10 + dayOfYear - dayOfWeek) / 7; + MOZ_ASSERT(0 <= week && week <= 53); // An ISO year has 53 weeks if the year starts on a Thursday or if it's a // leap year which starts on a Wednesday. auto isLongYear = [](int32_t year) { - int32_t startOfYear = ToISODayOfWeek({year, 1, 1}); + int32_t startOfYear = ISODayOfWeek({year, 1, 1}); return startOfYear == 4 || (startOfYear == 3 && IsISOLeapYear(year)); }; + // Step 11. + // // Part of last year's last week, which is either week 52 or week 53. - if (woy == 0) { + if (week == 0) { return {year - 1, 52 + int32_t(isLongYear(year - 1))}; } + // Step 12. + // // Part of next year's first week if the current year isn't a long year. - if (woy == 53 && !isLongYear(year)) { + if (week == 53 && !isLongYear(year)) { return {year + 1, 1}; } - return {year, woy}; + // Step 13. + return {year, week}; } /** - * ISOMonthCode ( month ) + * ToTemporalCalendarIdentifier ( calendarSlotValue ) */ -static JSString* ISOMonthCode(JSContext* cx, int32_t month) { - MOZ_ASSERT(1 <= month && month <= 12); - - // Steps 1-2. - char monthCode[3] = {'M', char('0' + (month / 10)), char('0' + (month % 10))}; - return NewStringCopyN(cx, monthCode, std::size(monthCode)); -} - -template -static bool ToPlainDate(JSObject* temporalDateLike, PlainDate* result) { - if (auto* obj = temporalDateLike->maybeUnwrapIf()) { - *result = ToPlainDate(obj); - return true; - } - if constexpr (sizeof...(Ts) > 0) { - return ToPlainDate(temporalDateLike, result); - } - return false; -} - -template -static bool ToPlainDate(JSContext* cx, Handle temporalDateLike, - PlainDate* result) { - if (temporalDateLike.isObject()) { - if (ToPlainDate(&temporalDateLike.toObject(), result)) { - return true; - } - } - - return ToTemporalDate(cx, temporalDateLike, result); -} - -#ifdef DEBUG -template -static bool StringIsAsciiLowerCase(mozilla::Range str) { - return std::all_of(str.begin().get(), str.end().get(), [](CharT ch) { - return mozilla::IsAscii(ch) && !mozilla::IsAsciiUppercaseAlpha(ch); - }); -} - -static bool StringIsAsciiLowerCase(const JSLinearString* str) { - JS::AutoCheckCannotGC nogc; - return str->hasLatin1Chars() - ? StringIsAsciiLowerCase(str->latin1Range(nogc)) - : StringIsAsciiLowerCase(str->twoByteRange(nogc)); -} -#endif - -/** - * Return the BCP-47 string for the given calendar id. - */ -static const char* CalendarIdToBcp47(CalendarId id) { - switch (id) { +std::string_view js::temporal::CalendarIdentifier(CalendarId calendarId) { + switch (calendarId) { case CalendarId::ISO8601: return "iso8601"; + case CalendarId::Buddhist: + return "buddhist"; + case CalendarId::Chinese: + return "chinese"; + case CalendarId::Coptic: + return "coptic"; + case CalendarId::Dangi: + return "dangi"; + case CalendarId::Ethiopian: + return "ethiopic"; + case CalendarId::EthiopianAmeteAlem: + return "ethioaa"; + case CalendarId::Gregorian: + return "gregory"; + case CalendarId::Hebrew: + return "hebrew"; + case CalendarId::Indian: + return "indian"; + case CalendarId::Islamic: + return "islamic"; + case CalendarId::IslamicCivil: + return "islamic-civil"; + case CalendarId::IslamicRGSA: + return "islamic-rgsa"; + case CalendarId::IslamicTabular: + return "islamic-tbla"; + case CalendarId::IslamicUmmAlQura: + return "islamic-umalqura"; + case CalendarId::Japanese: + return "japanese"; + case CalendarId::Persian: + return "persian"; + case CalendarId::ROC: + return "roc"; } MOZ_CRASH("invalid calendar id"); } -/** - * AvailableCalendars ( ) - */ -static constexpr auto AvailableCalendars() { - return std::array{ - CalendarId::ISO8601, - }; -} +class MOZ_STACK_CLASS AsciiLowerCaseChars final { + static constexpr size_t InlineCapacity = 24; + + Vector chars_; + + public: + explicit AsciiLowerCaseChars(JSContext* cx) : chars_(cx) {} + + operator mozilla::Span() const { + return mozilla::Span{chars_}; + } + + [[nodiscard]] bool init(JSLinearString* str) { + MOZ_ASSERT(StringIsAscii(str)); + + if (!chars_.resize(str->length())) { + return false; + } + + CopyChars(reinterpret_cast(chars_.begin()), *str); + + mozilla::intl::AsciiToLowerCase(chars_.begin(), chars_.length(), + chars_.begin()); + + return true; + } +}; /** - * IsBuiltinCalendar ( id ) + * CanonicalizeCalendar ( id ) */ -static mozilla::Maybe IsBuiltinCalendar(JSLinearString* id) { - // Callers must convert to lower case. - MOZ_ASSERT(StringIsAsciiLowerCase(id)); - - // Step 1. - static constexpr auto calendars = AvailableCalendars(); - - // Step 2. - for (auto identifier : calendars) { - if (StringEqualsAscii(id, CalendarIdToBcp47(identifier))) { - return mozilla::Some(identifier); - } - } - - // Step 3. - return mozilla::Nothing(); -} - -static bool ToBuiltinCalendar(JSContext* cx, Handle id, - CalendarId* result) { - if (!StringIsAscii(id)) { - if (auto chars = QuoteString(cx, id)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_ID, chars.get()); - } - return false; - } - - JSString* lower = StringToLowerCase(cx, id); - if (!lower) { - return false; - } - - JSLinearString* linear = lower->ensureLinear(cx); - if (!linear) { - return false; - } - - auto builtin = IsBuiltinCalendar(linear); - if (!builtin) { - if (auto chars = QuoteString(cx, id)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_ID, chars.get()); - } - return false; - } - - *result = *builtin; - return true; -} - -bool js::temporal::ToBuiltinCalendar(JSContext* cx, Handle id, - MutableHandle result) { +bool js::temporal::CanonicalizeCalendar(JSContext* cx, Handle id, + MutableHandle result) { Rooted linear(cx, id->ensureLinear(cx)); if (!linear) { return false; } - CalendarId identifier; - if (!::ToBuiltinCalendar(cx, linear, &identifier)) { - return false; - } + // Steps 1-3. + do { + if (!StringIsAscii(linear) || linear->empty()) { + break; + } - result.set(CalendarValue(identifier)); - return true; -} - -/** - * CreateTemporalCalendar ( identifier [ , newTarget ] ) - */ -static CalendarObject* CreateTemporalCalendar(JSContext* cx, - const CallArgs& args, - CalendarId identifier) { - // Step 1. (Not applicable in our implementation.) - - // Steps 2-3. - Rooted proto(cx); - if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Calendar, &proto)) { - return nullptr; - } - - auto* obj = NewObjectWithClassProto(cx, proto); - if (!obj) { - return nullptr; - } - - // Step 4. - obj->setFixedSlot(CalendarObject::IDENTIFIER_SLOT, - Int32Value(static_cast(identifier))); - - // Step 5. - return obj; -} - -/** - * CreateTemporalCalendar ( identifier [ , newTarget ] ) - */ -static CalendarObject* CreateTemporalCalendar(JSContext* cx, - CalendarId identifier) { - // Step 1. (Not applicable in our implementation.) - - // Steps 2-3. - auto* obj = NewBuiltinClassInstance(cx); - if (!obj) { - return nullptr; - } - - // Step 4. - obj->setFixedSlot(CalendarObject::IDENTIFIER_SLOT, - Int32Value(static_cast(identifier))); - - // Step 5. - return obj; -} - -/** - * ObjectImplementsTemporalCalendarProtocol ( object ) - */ -static bool ObjectImplementsTemporalCalendarProtocol(JSContext* cx, - Handle object, - bool* result) { - // Step 1. (Not applicable in our implementation.) - MOZ_ASSERT(!object->canUnwrapAs(), - "Calendar objects handled in the caller"); - - // Step 2. - for (auto key : { - &JSAtomState::dateAdd, &JSAtomState::dateFromFields, - &JSAtomState::dateUntil, &JSAtomState::day, - &JSAtomState::dayOfWeek, &JSAtomState::dayOfYear, - &JSAtomState::daysInMonth, &JSAtomState::daysInWeek, - &JSAtomState::daysInYear, &JSAtomState::fields, - &JSAtomState::id, &JSAtomState::inLeapYear, - &JSAtomState::mergeFields, &JSAtomState::month, - &JSAtomState::monthCode, &JSAtomState::monthDayFromFields, - &JSAtomState::monthsInYear, &JSAtomState::weekOfYear, - &JSAtomState::year, &JSAtomState::yearMonthFromFields, - &JSAtomState::yearOfWeek, - }) { - // Step 2.a. - bool has; - if (!HasProperty(cx, object, cx->names().*key, &has)) { + AsciiLowerCaseChars lowerCaseChars(cx); + if (!lowerCaseChars.init(linear)) { return false; } - if (!has) { - *result = false; - return true; - } - } + mozilla::Span id = lowerCaseChars; - // Step 3. - *result = true; - return true; + // Reject invalid types before trying to resolve aliases. + if (mozilla::intl::LocaleParser::CanParseUnicodeExtensionType(id).isErr()) { + break; + } + + // Resolve calendar aliases. + static constexpr auto key = mozilla::MakeStringSpan("ca"); + if (const char* replacement = + mozilla::intl::Locale::ReplaceUnicodeExtensionType(key, id)) { + id = mozilla::MakeStringSpan(replacement); + } + + // Step 1. + static constexpr auto& calendars = AvailableCalendars(); + + // Steps 2-3. + for (auto identifier : calendars) { + if (id == mozilla::Span{CalendarIdentifier(identifier)}) { + result.set(CalendarValue(identifier)); + return true; + } + } + } while (false); + + if (auto chars = QuoteString(cx, linear)) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INVALID_ID, chars.get()); + } + return false; } template @@ -706,25 +463,16 @@ static bool ToTemporalCalendar(JSContext* cx, Handle object, } /** - * ToTemporalCalendarSlotValue ( temporalCalendarLike [ , default ] ) + * ToTemporalCalendarSlotValue ( temporalCalendarLike ) */ bool js::temporal::ToTemporalCalendar(JSContext* cx, Handle temporalCalendarLike, MutableHandle result) { - // Step 1. (Not applicable) + // Step 1. + if (temporalCalendarLike.isObject()) { + Rooted obj(cx, &temporalCalendarLike.toObject()); - // Step 2. - Rooted calendarLike(cx, temporalCalendarLike); - if (calendarLike.isObject()) { - Rooted obj(cx, &calendarLike.toObject()); - - // Step 2.b. (Partial) - if (obj->canUnwrapAs()) { - result.set(CalendarValue(obj)); - return true; - } - - // Step 2.a. + // Step 1.a. Rooted calendar(cx); if (!::ToTemporalCalendargetClass()->name); - return false; - } - - // Step 2.c. - result.set(CalendarValue(obj)); - return true; } - // Step 3. - if (!calendarLike.isString()) { + // Step 2. + if (!temporalCalendarLike.isString()) { ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, - calendarLike, nullptr, "not a string"); + temporalCalendarLike, nullptr, "not a string"); return false; } - Rooted str(cx, calendarLike.toString()); + Rooted str(cx, temporalCalendarLike.toString()); - // Step 4. + // Step 3. Rooted id(cx, ParseTemporalCalendarString(cx, str)); if (!id) { return false; } - // Step 5. - CalendarId identifier; - if (!::ToBuiltinCalendar(cx, id, &identifier)) { - return false; - } - - // Step 6. - result.set(CalendarValue(identifier)); - return true; -} - -/** - * ToTemporalCalendarSlotValue ( temporalCalendarLike [ , default ] ) - * - * When called with `default = "iso8601"`. - */ -bool js::temporal::ToTemporalCalendarWithISODefault( - JSContext* cx, Handle temporalCalendarLike, - MutableHandle result) { - // Step 1. - if (temporalCalendarLike.isUndefined()) { - result.set(CalendarValue(CalendarId::ISO8601)); - return true; - } - - // Steps 2-6. - return ToTemporalCalendar(cx, temporalCalendarLike, result); + // Step 4. + return CanonicalizeCalendar(cx, id, result); } /** @@ -822,2003 +528,1604 @@ bool js::temporal::GetTemporalCalendarWithISODefault( } // Step 3. - return ToTemporalCalendarWithISODefault(cx, calendarValue, result); -} - -/** - * ToTemporalCalendarIdentifier ( calendarSlotValue ) - */ -static JSLinearString* ToTemporalCalendarIdentifier(JSContext* cx, - CalendarId id) { - // TODO: Avoid string allocations? - return NewStringCopyZ(cx, CalendarIdToBcp47(id)); -} - -/** - * ToTemporalCalendarIdentifier ( calendarSlotValue ) - */ -JSLinearString* js::temporal::ToTemporalCalendarIdentifier( - JSContext* cx, Handle calendar) { - // Step 1. - if (calendar.isString()) { - return ToTemporalCalendarIdentifier(cx, calendar.toString()); - } - - // Step 2. - Rooted calendarObj(cx, calendar.toObject()); - Rooted identifier(cx); - if (!GetProperty(cx, calendarObj, calendarObj, cx->names().id, &identifier)) { - return nullptr; - } - - // Step 3. - if (!identifier.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, identifier, - nullptr, "not a string"); - return nullptr; + if (calendarValue.isUndefined()) { + result.set(CalendarValue(CalendarId::ISO8601)); + return true; } // Step 4. - return identifier.toString()->ensureLinear(cx); + return ToTemporalCalendar(cx, calendarValue, result); } -/** - * ToTemporalCalendarObject ( calendarSlotValue ) - */ -JSObject* js::temporal::ToTemporalCalendarObject( - JSContext* cx, Handle calendar) { - // Step 1. - if (calendar.isObject()) { - return calendar.toObject(); - } - - // Step 2. - return CreateTemporalCalendar(cx, calendar.toString()); -} - -bool js::temporal::ToTemporalCalendar(JSContext* cx, - const CalendarValue& calendar, - MutableHandle result) { - if (calendar.isObject()) { - result.setObject(*calendar.toObject()); - return true; - } - - auto* str = ToTemporalCalendarIdentifier(cx, calendar.toString()); - if (!str) { - return false; - } - - result.setString(str); - return true; -} - -static bool Calendar_dateAdd(JSContext* cx, unsigned argc, Value* vp); -static bool Calendar_dateFromFields(JSContext* cx, unsigned argc, Value* vp); -static bool Calendar_dateUntil(JSContext* cx, unsigned argc, Value* vp); -static bool Calendar_day(JSContext* cx, unsigned argc, Value* vp); -static bool Calendar_fields(JSContext* cx, unsigned argc, Value* vp); -static bool Calendar_mergeFields(JSContext* cx, unsigned argc, Value* vp); -static bool Calendar_monthDayFromFields(JSContext* cx, unsigned argc, - Value* vp); -static bool Calendar_yearMonthFromFields(JSContext* cx, unsigned argc, - Value* vp); - -/** - * CalendarMethodsRecordLookup ( calendarRec, methodName ) - */ -static bool CalendarMethodsRecordLookup(JSContext* cx, - MutableHandle calendar, - CalendarMethod methodName) { - // Step 1. (Not applicable in our implementation.) - - // Steps 2-10. - Rooted object(cx, calendar.receiver().toObject()); - - auto lookup = [&](Handle name, JSNative native, - MutableHandle result) { - auto* method = GetMethod(cx, object, name); - if (!method) { - return false; - } - - // As an optimization we only store the method if the receiver is either - // a custom calendar object or if the method isn't the default, built-in - // calender method. - if (!object->is() || !IsNativeFunction(method, native)) { - result.set(method); - } - return true; +static inline bool DayOfMonthCanBeZero(CalendarId calendarId) { + // Workaround when day-of-month returns zero. + // + // See . + static constexpr mozilla::EnumSet calendars{ + CalendarId::Islamic, + CalendarId::IslamicRGSA, + CalendarId::IslamicUmmAlQura, }; - - switch (methodName) { - // Steps 2 and 10. - case CalendarMethod::DateAdd: - return lookup(cx->names().dateAdd, Calendar_dateAdd, calendar.dateAdd()); - - // Steps 3 and 10. - case CalendarMethod::DateFromFields: - return lookup(cx->names().dateFromFields, Calendar_dateFromFields, - calendar.dateFromFields()); - - // Steps 4 and 10. - case CalendarMethod::DateUntil: - return lookup(cx->names().dateUntil, Calendar_dateUntil, - calendar.dateUntil()); - - // Steps 5 and 10. - case CalendarMethod::Day: - return lookup(cx->names().day, Calendar_day, calendar.day()); - - // Steps 6 and 10. - case CalendarMethod::Fields: - return lookup(cx->names().fields, Calendar_fields, calendar.fields()); - - // Steps 7 and 10. - case CalendarMethod::MergeFields: - return lookup(cx->names().mergeFields, Calendar_mergeFields, - calendar.mergeFields()); - - // Steps 8 and 10. - case CalendarMethod::MonthDayFromFields: - return lookup(cx->names().monthDayFromFields, Calendar_monthDayFromFields, - calendar.monthDayFromFields()); - - // Steps 9 and 10. - case CalendarMethod::YearMonthFromFields: - return lookup(cx->names().yearMonthFromFields, - Calendar_yearMonthFromFields, - calendar.yearMonthFromFields()); - } - - MOZ_CRASH("invalid calendar method"); + return calendars.contains(calendarId); } -/** - * CreateCalendarMethodsRecord ( calendar, methods ) - */ -bool js::temporal::CreateCalendarMethodsRecord( - JSContext* cx, Handle calendar, - mozilla::EnumSet methods, - MutableHandle result) { - MOZ_ASSERT(!methods.isEmpty()); +static inline int32_t OrdinalMonth(CalendarId calendarId, + const capi::ICU4XDate* date) { + int32_t month = capi::ICU4XDate_ordinal_month(date); + MOZ_ASSERT(month > 0); - // Step 1. - result.set(CalendarRecord{calendar}); - -#ifdef DEBUG - // Remember the set of looked-up methods for assertions. - result.get().lookedUp() += methods; -#endif - - // Built-in calendars don't perform observable lookups. - if (calendar.isString()) { - return true; - } - - // Step 2. - for (auto method : methods) { - if (!CalendarMethodsRecordLookup(cx, result, method)) { - return false; + if (DayOfMonthCanBeZero(calendarId)) { + // If |dayOfMonth| is zero, interpret as last day of previous month. + int32_t dayOfMonth = capi::ICU4XDate_day_of_month(date); + if (dayOfMonth == 0) { + MOZ_ASSERT(month > 1); + month -= 1; } } - // Step 3. - return true; + return month; } -static CalendarId BuiltinCalendarId(const CalendarValue& calendar) { - if (calendar.isString()) { - return calendar.toString(); +static inline int32_t DayOfMonth(CalendarId calendarId, + const capi::ICU4XDate* date) { + int32_t dayOfMonth = capi::ICU4XDate_day_of_month(date); + + if (DayOfMonthCanBeZero(calendarId)) { + // If |dayOfMonth| is zero, interpret as last day of previous month. + if (dayOfMonth == 0) { + MOZ_ASSERT(CalendarDaysInMonth(calendarId).second == 30); + dayOfMonth = 30; + } } - return calendar.toObject()->as().identifier(); + + MOZ_ASSERT(dayOfMonth > 0); + return dayOfMonth; } -static bool ToCalendarField(JSContext* cx, JSLinearString* linear, - CalendarField* result) { - if (StringEqualsLiteral(linear, "year")) { - *result = CalendarField::Year; - return true; - } - if (StringEqualsLiteral(linear, "month")) { - *result = CalendarField::Month; - return true; - } - if (StringEqualsLiteral(linear, "monthCode")) { - *result = CalendarField::MonthCode; - return true; - } - if (StringEqualsLiteral(linear, "day")) { - *result = CalendarField::Day; - return true; - } - if (auto chars = QuoteString(cx, linear, '"')) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_FIELD, - chars.get()); - } - return false; +static inline int32_t DayOfYear(const capi::ICU4XDate* date) { + int32_t dayOfYear = capi::ICU4XDate_day_of_year(date); + MOZ_ASSERT(dayOfYear > 0); + return dayOfYear; } -static constexpr auto sortedCalendarFields = std::array{ - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, +static inline int32_t DaysInMonth(const capi::ICU4XDate* date) { + int32_t daysInMonth = capi::ICU4XDate_days_in_month(date); + MOZ_ASSERT(daysInMonth > 0); + return daysInMonth; +} + +static inline int32_t DaysInYear(const capi::ICU4XDate* date) { + int32_t daysInYear = capi::ICU4XDate_days_in_year(date); + MOZ_ASSERT(daysInYear > 0); + return daysInYear; +} + +static inline int32_t MonthsInYear(const capi::ICU4XDate* date) { + int32_t monthsInYear = capi::ICU4XDate_months_in_year(date); + MOZ_ASSERT(monthsInYear > 0); + return monthsInYear; +} + +static auto ToAnyCalendarKind(CalendarId id) { + switch (id) { + case CalendarId::ISO8601: + return capi::ICU4XAnyCalendarKind_Iso; + case CalendarId::Buddhist: + return capi::ICU4XAnyCalendarKind_Buddhist; + case CalendarId::Chinese: + return capi::ICU4XAnyCalendarKind_Chinese; + case CalendarId::Coptic: + return capi::ICU4XAnyCalendarKind_Coptic; + case CalendarId::Dangi: + return capi::ICU4XAnyCalendarKind_Dangi; + case CalendarId::Ethiopian: + return capi::ICU4XAnyCalendarKind_Ethiopian; + case CalendarId::EthiopianAmeteAlem: + return capi::ICU4XAnyCalendarKind_EthiopianAmeteAlem; + case CalendarId::Gregorian: + return capi::ICU4XAnyCalendarKind_Gregorian; + case CalendarId::Hebrew: + return capi::ICU4XAnyCalendarKind_Hebrew; + case CalendarId::Indian: + return capi::ICU4XAnyCalendarKind_Indian; + case CalendarId::IslamicCivil: + return capi::ICU4XAnyCalendarKind_IslamicCivil; + case CalendarId::Islamic: + return capi::ICU4XAnyCalendarKind_IslamicObservational; + case CalendarId::IslamicRGSA: + // ICU4X doesn't support a separate islamic-rgsa calendar, so we use the + // observational calendar instead. This also matches ICU4C. + return capi::ICU4XAnyCalendarKind_IslamicObservational; + case CalendarId::IslamicTabular: + return capi::ICU4XAnyCalendarKind_IslamicTabular; + case CalendarId::IslamicUmmAlQura: + return capi::ICU4XAnyCalendarKind_IslamicUmmAlQura; + case CalendarId::Japanese: + return capi::ICU4XAnyCalendarKind_Japanese; + case CalendarId::Persian: + return capi::ICU4XAnyCalendarKind_Persian; + case CalendarId::ROC: + return capi::ICU4XAnyCalendarKind_Roc; + } + MOZ_CRASH("invalid calendar id"); +} + +class ICU4XCalendarDeleter { + public: + void operator()(capi::ICU4XCalendar* ptr) { + capi::ICU4XCalendar_destroy(ptr); + } }; -// TODO: Consider reordering CalendarField so we don't need this. Probably best -// to decide after has -// landed. -using SortedCalendarFields = SortedEnumSet; +using UniqueICU4XCalendar = + mozilla::UniquePtr; -static TemporalField ToTemporalField(CalendarField field) { - switch (field) { - case CalendarField::Year: - return TemporalField::Year; - case CalendarField::Month: - return TemporalField::Month; - case CalendarField::MonthCode: - return TemporalField::MonthCode; - case CalendarField::Day: - return TemporalField::Day; +static UniqueICU4XCalendar CreateICU4XCalendar(JSContext* cx, CalendarId id) { + auto result = capi::ICU4XCalendar_create_for_kind( + mozilla::intl::GetDataProvider(), ToAnyCalendarKind(id)); + if (!result.is_ok) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return nullptr; } - MOZ_CRASH("invalid calendar field name"); + return UniqueICU4XCalendar{result.ok}; } -/** - * Temporal.Calendar.prototype.fields ( fields ) - */ -static bool BuiltinCalendarFields(JSContext* cx, CalendarId calendarId, - mozilla::EnumSet fieldNames, - CalendarFieldNames& result) { - MOZ_ASSERT(result.empty()); - - // Steps 1-4. (Not applicable.) - - // Steps 5-6. - mozilla::EnumSet temporalFields{}; - for (auto fieldName : fieldNames) { - // Steps 6.a and 6.b.i-iii. (Not applicable) - - // Step 6.b.iv. - temporalFields += ToTemporalField(fieldName); - } - - // Reserve space for the append operation. - if (!result.reserve(temporalFields.size())) { - return false; - } - - // Append all fields, sorted. - for (auto field : SortedTemporalFields{temporalFields}) { - auto* name = ToPropertyName(cx, field); - result.infallibleAppend(NameToId(name)); - } - - return true; -} - -/** - * Temporal.Calendar.prototype.fields ( fields ) - */ -static bool BuiltinCalendarFields(JSContext* cx, CalendarId calendarId, - Handle fields, - MutableHandle result) { - // Step 3. - JS::ForOfIterator iterator(cx); - if (!iterator.init(fields)) { - return false; - } - - // Step 4. - JS::RootedVector fieldNames(cx); - mozilla::EnumSet seen; - - // Steps 5-6. - Rooted nextValue(cx); - Rooted linear(cx); - while (true) { - // Step 6.a. - bool done; - if (!iterator.next(&nextValue, &done)) { - return false; +static uint32_t MaximumISOYear(CalendarId calendarId) { + switch (calendarId) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Gregorian: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::IslamicCivil: + case CalendarId::IslamicTabular: + case CalendarId::Japanese: + case CalendarId::Persian: + case CalendarId::ROC: { + // Passing values near INT32_{MIN,MAX} triggers ICU4X assertions, so we + // have to handle large input years early. + return 300'000; } - if (done) { + + case CalendarId::Chinese: + case CalendarId::Dangi: { + // Lower limit for these calendars to avoid running into ICU4X assertions. + // + // https://github.com/unicode-org/icu4x/issues/4917 + return 10'000; + } + + case CalendarId::Islamic: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicUmmAlQura: { + // Lower limit for these calendars to avoid running into ICU4X assertions. + // + // https://github.com/unicode-org/icu4x/issues/4917 + return 5'000; + } + } + MOZ_CRASH("invalid calendar"); +} + +static uint32_t MaximumCalendarYear(CalendarId calendarId) { + switch (calendarId) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Gregorian: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::IslamicCivil: + case CalendarId::IslamicTabular: + case CalendarId::Japanese: + case CalendarId::Persian: + case CalendarId::ROC: { + // Passing values near INT32_{MIN,MAX} triggers ICU4X assertions, so we + // have to handle large input years early. + return 300'000; + } + + case CalendarId::Chinese: + case CalendarId::Dangi: { + // Lower limit for these calendars to avoid running into ICU4X assertions. + // + // https://github.com/unicode-org/icu4x/issues/4917 + return 10'000; + } + + case CalendarId::Islamic: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicUmmAlQura: { + // Lower limit for these calendars to avoid running into ICU4X assertions. + // + // https://github.com/unicode-org/icu4x/issues/4917 + return 5'000; + } + } + MOZ_CRASH("invalid calendar"); +} + +static void ReportCalendarFieldOverflow(JSContext* cx, const char* name, + double num) { + ToCStringBuf numCbuf; + const char* numStr = NumberToCString(&numCbuf, num); + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_OVERFLOW_FIELD, name, + numStr); +} + +class ICU4XDateDeleter { + public: + void operator()(capi::ICU4XDate* ptr) { capi::ICU4XDate_destroy(ptr); } +}; + +using UniqueICU4XDate = mozilla::UniquePtr; + +static UniqueICU4XDate CreateICU4XDate(JSContext* cx, const ISODate& date, + CalendarId calendarId, + const capi::ICU4XCalendar* calendar) { + if (mozilla::Abs(date.year) > MaximumISOYear(calendarId)) { + ReportCalendarFieldOverflow(cx, "year", date.year); + return nullptr; + } + + auto result = capi::ICU4XDate_create_from_iso_in_calendar( + date.year, date.month, date.day, calendar); + if (!result.is_ok) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return nullptr; + } + return UniqueICU4XDate{result.ok}; +} + +class ICU4XIsoDateDeleter { + public: + void operator()(capi::ICU4XIsoDate* ptr) { capi::ICU4XIsoDate_destroy(ptr); } +}; + +using UniqueICU4XIsoDate = + mozilla::UniquePtr; + +class ICU4XWeekCalculatorDeleter { + public: + void operator()(capi::ICU4XWeekCalculator* ptr) { + capi::ICU4XWeekCalculator_destroy(ptr); + } +}; + +using UniqueICU4XWeekCalculator = + mozilla::UniquePtr; + +static UniqueICU4XWeekCalculator CreateICU4WeekCalculator(JSContext* cx, + CalendarId calendar) { + MOZ_ASSERT(calendar == CalendarId::Gregorian); + + auto firstWeekday = capi::ICU4XIsoWeekday_Monday; + uint8_t minWeekDays = 1; + + auto* result = + capi::ICU4XWeekCalculator_create_from_first_day_of_week_and_min_week_days( + firstWeekday, minWeekDays); + return UniqueICU4XWeekCalculator{result}; +} + +// Define IMPLEMENTS_DR2126 if DR2126 is implemented. +// +// https://cplusplus.github.io/CWG/issues/2126.html +#if defined(__clang__) +# if (__clang_major__ >= 12) +# define IMPLEMENTS_DR2126 +# endif +#else +# define IMPLEMENTS_DR2126 +#endif + +#ifdef IMPLEMENTS_DR2126 +static constexpr size_t EraNameMaxLength() { + size_t length = 0; + for (auto calendar : AvailableCalendars()) { + for (auto era : CalendarEras(calendar)) { + for (auto name : CalendarEraNames(calendar, era)) { + length = std::max(length, name.length()); + } + } + } + return length; +} +#endif + +static mozilla::Maybe EraForString(CalendarId calendar, + JSLinearString* string) { + MOZ_ASSERT(CalendarEraRelevant(calendar)); + + // Note: Assigning MaxLength to EraNameMaxLength() breaks the CDT indexer. + constexpr size_t MaxLength = 24; +#ifdef IMPLEMENTS_DR2126 + static_assert(MaxLength >= EraNameMaxLength(), + "Storage size is at least as large as the largest known era"); +#endif + + if (string->length() > MaxLength || !StringIsAscii(string)) { + return mozilla::Nothing(); + } + + char chars[MaxLength] = {}; + CopyChars(reinterpret_cast(chars), *string); + + auto stringView = std::string_view{chars, string->length()}; + + for (auto era : CalendarEras(calendar)) { + for (auto name : CalendarEraNames(calendar, era)) { + if (name == stringView) { + return mozilla::Some(era); + } + } + } + return mozilla::Nothing(); +} + +static constexpr std::string_view IcuEraName(CalendarId calendar, EraCode era) { + switch (calendar) { + // https://docs.rs/icu/latest/icu/calendar/iso/struct.Iso.html#era-codes + case CalendarId::ISO8601: { + MOZ_ASSERT(era == EraCode::Standard); + return "default"; + } + + // https://docs.rs/icu/latest/icu/calendar/buddhist/struct.Buddhist.html#era-codes + case CalendarId::Buddhist: { + MOZ_ASSERT(era == EraCode::Standard); + return "be"; + } + + // https://docs.rs/icu/latest/icu/calendar/chinese/struct.Chinese.html#year-and-era-codes + case CalendarId::Chinese: { + MOZ_ASSERT(era == EraCode::Standard); + return "chinese"; + } + + // https://docs.rs/icu/latest/icu/calendar/coptic/struct.Coptic.html#era-codes + case CalendarId::Coptic: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? "ad" : "bd"; + } + + // https://docs.rs/icu/latest/icu/calendar/dangi/struct.Dangi.html#era-codes + case CalendarId::Dangi: { + MOZ_ASSERT(era == EraCode::Standard); + return "dangi"; + } + + // https://docs.rs/icu/latest/icu/calendar/ethiopian/struct.Ethiopian.html#era-codes + case CalendarId::Ethiopian: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? "incar" : "pre-incar"; + } + + // https://docs.rs/icu/latest/icu/calendar/ethiopian/struct.Ethiopian.html#era-codes + case CalendarId::EthiopianAmeteAlem: { + MOZ_ASSERT(era == EraCode::Standard); + return "mundi"; + } + + // https://docs.rs/icu/latest/icu/calendar/gregorian/struct.Gregorian.html#era-codes + case CalendarId::Gregorian: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? "ce" : "bce"; + } + + // https://docs.rs/icu/latest/icu/calendar/hebrew/struct.Hebrew.html + case CalendarId::Hebrew: { + MOZ_ASSERT(era == EraCode::Standard); + return "am"; + } + + // https://docs.rs/icu/latest/icu/calendar/indian/struct.Indian.html#era-codes + case CalendarId::Indian: { + MOZ_ASSERT(era == EraCode::Standard); + return "saka"; + } + + // https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicCivil.html#era-codes + // https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicObservational.html#era-codes + // https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicTabular.html#era-codes + // https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicUmmAlQura.html#era-codes + // https://docs.rs/icu/latest/icu/calendar/persian/struct.Persian.html#era-codes + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: { + MOZ_ASSERT(era == EraCode::Standard); + return "ah"; + } + + // https://docs.rs/icu/latest/icu/calendar/japanese/struct.Japanese.html#era-codes + case CalendarId::Japanese: { + switch (era) { + case EraCode::Standard: + return "ce"; + case EraCode::Inverse: + return "bce"; + case EraCode::Meiji: + return "meiji"; + case EraCode::Taisho: + return "taisho"; + case EraCode::Showa: + return "showa"; + case EraCode::Heisei: + return "heisei"; + case EraCode::Reiwa: + return "reiwa"; + } break; } - // Step 6.b.i. - if (!nextValue.isString()) { - // Step 6.b.i.1. - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, nextValue, - nullptr, "not a string"); - - // Step 6.b.i.2. - iterator.closeThrow(); - return false; + // https://docs.rs/icu/latest/icu/calendar/roc/struct.Roc.html#era-codes + case CalendarId::ROC: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? "roc" : "roc-inverse"; } + } + JS_CONSTEXPR_CRASH("invalid era"); +} - linear = nextValue.toString()->ensureLinear(cx); - if (!linear) { - return false; - } +enum class CalendarError { + // Catch-all kind for all other error types. + Generic, - // Step 6.b.iii. (Reordered) - CalendarField field; - if (!ToCalendarField(cx, linear, &field)) { - iterator.closeThrow(); - return false; - } + // https://docs.rs/icu/latest/icu/calendar/enum.Error.html#variant.Overflow + Overflow, - // Step 6.b.ii. - if (seen.contains(field)) { - // Step 6.b.ii.1. - if (auto chars = QuoteString(cx, linear, '"')) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_DUPLICATE_FIELD, - chars.get()); - } + // https://docs.rs/icu/latest/icu/calendar/enum.Error.html#variant.Underflow + Underflow, - // Step 6.b.ii.2. - iterator.closeThrow(); - return false; - } + // https://docs.rs/icu/latest/icu/calendar/enum.Error.html#variant.OutOfRange + OutOfRange, - // Step 6.b.iv. - if (!fieldNames.append(nextValue)) { - return false; - } - seen += field; + // https://docs.rs/icu/latest/icu/calendar/enum.Error.html#variant.UnknownEra + UnknownEra, + + // https://docs.rs/icu/latest/icu/calendar/enum.Error.html#variant.UnknownMonthCode + UnknownMonthCode, +}; + +#ifdef DEBUG +static auto CalendarErasAsEnumSet(CalendarId calendarId) { + // `mozilla::EnumSet(CalendarEras(calendarId))` doesn't work in old + // GCC versions, so add all era codes manually to the enum set. + mozilla::EnumSet eras{}; + for (auto era : CalendarEras(calendarId)) { + eras += era; + } + return eras; +} +#endif + +static mozilla::Result CreateDateFromCodes( + CalendarId calendarId, const capi::ICU4XCalendar* calendar, EraYear eraYear, + MonthCode monthCode, int32_t day) { + MOZ_ASSERT(calendarId != CalendarId::ISO8601); + MOZ_ASSERT(capi::ICU4XCalendar_kind(calendar) == + ToAnyCalendarKind(calendarId)); + MOZ_ASSERT(CalendarErasAsEnumSet(calendarId).contains(eraYear.era)); + MOZ_ASSERT_IF(CalendarEraRelevant(calendarId), eraYear.year > 0); + MOZ_ASSERT(mozilla::Abs(eraYear.year) <= MaximumCalendarYear(calendarId)); + MOZ_ASSERT(CalendarMonthCodes(calendarId).contains(monthCode)); + MOZ_ASSERT(day > 0); + MOZ_ASSERT(day <= CalendarDaysInMonth(calendarId).second); + + auto era = IcuEraName(calendarId, eraYear.era); + auto monthCodeView = std::string_view{monthCode}; + auto date = capi::ICU4XDate_create_from_codes_in_calendar( + era.data(), era.length(), eraYear.year, monthCodeView.data(), + monthCodeView.length(), day, calendar); + if (date.is_ok) { + return UniqueICU4XDate{date.ok}; } - // Steps 7-9. - auto* array = - NewDenseCopiedArray(cx, fieldNames.length(), fieldNames.begin()); - if (!array) { + // Map possible calendar errors. + // + // Calendar error codes which can't happen for `create_from_codes_in_calendar` + // are mapped to `CalendarError::Generic`. + switch (date.err) { + case capi::ICU4XError_CalendarOverflowError: + return mozilla::Err(CalendarError::Overflow); + case capi::ICU4XError_CalendarUnderflowError: + return mozilla::Err(CalendarError::Underflow); + case capi::ICU4XError_CalendarOutOfRangeError: + return mozilla::Err(CalendarError::OutOfRange); + case capi::ICU4XError_CalendarUnknownEraError: + return mozilla::Err(CalendarError::UnknownEra); + case capi::ICU4XError_CalendarUnknownMonthCodeError: + return mozilla::Err(CalendarError::UnknownMonthCode); + default: + return mozilla::Err(CalendarError::Generic); + } +} + +/** + * Return the first year (gannen) of a Japanese era. + */ +static bool FirstYearOfJapaneseEra(JSContext* cx, CalendarId calendarId, + const capi::ICU4XCalendar* calendar, + EraCode era, int32_t* result) { + MOZ_ASSERT(calendarId == CalendarId::Japanese); + MOZ_ASSERT(!CalendarEraStartsAtYearBoundary(calendarId, era)); + + // All supported Japanese eras last at least one year, so December 31 is + // guaranteed to be in the first year of the era. + auto dateResult = + CreateDateFromCodes(calendarId, calendar, {era, 1}, MonthCode{12}, 31); + if (dateResult.isErr()) { + MOZ_ASSERT(dateResult.inspectErr() == CalendarError::Generic, + "unexpected non-generic calendar error"); + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); return false; } - result.setObject(*array); + auto date = dateResult.unwrap(); + UniqueICU4XIsoDate isoDate{capi::ICU4XDate_to_iso(date.get())}; + + int32_t isoYear = capi::ICU4XIsoDate_year(isoDate.get()); + MOZ_ASSERT(isoYear > 0, "unexpected era start before 1 CE"); + + *result = isoYear; return true; } /** - * CalendarFields ( calendarRec, fieldNames ) + * Return the equivalent common era year for a Japanese era year. */ -bool js::temporal::CalendarFields(JSContext* cx, - Handle calendar, - mozilla::EnumSet fieldNames, - MutableHandle result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::Fields)); - - // Step 1. (Not applicable in our implementation.) - - // Step 2. - auto fields = calendar.fields(); - if (!fields) { - bool arrayIterationSane; - if (calendar.receiver().isString()) { - // "String" calendars don't perform observable array iteration. - arrayIterationSane = true; - } else { - // "Object" calendars need to ensure array iteration is still sane. - if (!IsArrayIterationSane(cx, &arrayIterationSane)) { - return false; - } - } - - if (arrayIterationSane) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - - // Steps 2.a-b. - return BuiltinCalendarFields(cx, calendarId, fieldNames, result.get()); - - // Steps 2.c-e. (Not applicable in our implementation.) - } - } - - // Step 3. (Inlined call to CalendarMethodsRecordCall.) - - auto* array = NewDenseFullyAllocatedArray(cx, fieldNames.size()); - if (!array) { +static bool JapaneseEraYearToCommonEraYear(JSContext* cx, CalendarId calendarId, + const capi::ICU4XCalendar* calendar, + EraYear eraYear, EraYear* result) { + int32_t firstYearOfEra; + if (!FirstYearOfJapaneseEra(cx, calendarId, calendar, eraYear.era, + &firstYearOfEra)) { return false; } - array->setDenseInitializedLength(fieldNames.size()); - size_t index = 0; - for (auto calendarField : SortedCalendarFields{fieldNames}) { - auto* name = ToPropertyName(cx, ::ToTemporalField(calendarField)); - array->initDenseElement(index++, StringValue(name)); + // Map non-positive era years to years before the first era year: + // + // 1 Reiwa = 2019 CE + // 0 Reiwa -> 2018 CE + // -1 Reiwa -> 2017 CE + // etc. + // + // Map too large era years to the next era: + // + // Heisei 31 = 2019 CE + // Heisei 32 -> 2020 CE + // ... + + int32_t year = (firstYearOfEra - 1) + eraYear.year; + if (year > 0) { + *result = {EraCode::Standard, year}; + return true; } - MOZ_ASSERT(index == fieldNames.size()); + *result = {EraCode::Inverse, int32_t(mozilla::Abs(year) + 1)}; + return true; +} - Rooted fieldsArray(cx, ObjectValue(*array)); - Rooted calendarFieldNames(cx); - if (fields) { - Rooted fieldsFn(cx, ObjectValue(*fields)); - auto thisv = calendar.receiver().toObjectValue(); - if (!Call(cx, fieldsFn, thisv, fieldsArray, &calendarFieldNames)) { - return false; - } +static UniqueICU4XDate CreateDateFromCodes(JSContext* cx, CalendarId calendarId, + const capi::ICU4XCalendar* calendar, + EraYear eraYear, MonthCode monthCode, + int32_t day, + TemporalOverflow overflow) { + MOZ_ASSERT(CalendarMonthCodes(calendarId).contains(monthCode)); + MOZ_ASSERT(day > 0); + MOZ_ASSERT(day <= CalendarDaysInMonth(calendarId).second); + + // Constrain day to the maximum possible day for the input month. + // + // Special cases like February 29 in leap years of the Gregorian calendar are + // handled below. + int32_t daysInMonth = CalendarDaysInMonth(calendarId, monthCode).second; + if (overflow == TemporalOverflow::Constrain) { + day = std::min(day, daysInMonth); } else { - auto calendarId = BuiltinCalendarId(calendar.receiver()); + MOZ_ASSERT(overflow == TemporalOverflow::Reject); - if (!BuiltinCalendarFields(cx, calendarId, fieldsArray, - &calendarFieldNames)) { - return false; - } - } - - // Steps 4-5. - if (!IterableToListOfStrings(cx, calendarFieldNames, result)) { - return false; - } - - // The spec sorts the field names in PrepareTemporalFields. Sorting is only - // needed for user-defined calendars, so our implementation performs this step - // here instead of in PrepareTemporalFields. - return SortTemporalFieldNames(cx, result.get()); -} - -static bool RequireIntegralNumber(JSContext* cx, Handle value, - Handle name, - MutableHandle result) { - if (MOZ_LIKELY(value.isInt32())) { - result.set(value); - return true; - } - - if (value.isDouble()) { - double d = value.toDouble(); - if (js::IsInteger(d)) { - result.setNumber(d); - return true; - } - - if (auto str = QuoteString(cx, name)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_INTEGER, str.get()); - } - return false; - } - - if (auto str = QuoteString(cx, name)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_UNEXPECTED_TYPE, str.get(), "not a number"); - } - return false; -} - -static bool RequireIntegralPositiveNumber(JSContext* cx, Handle value, - Handle name, - MutableHandle result) { - if (!RequireIntegralNumber(cx, value, name, result)) { - return false; - } - - if (result.toNumber() <= 0) { - if (auto str = QuoteString(cx, name)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_NUMBER, str.get()); - } - return false; - } - return true; -} - -static bool RequireIntegralNumberOrUndefined(JSContext* cx, Handle value, - Handle name, - MutableHandle result) { - if (value.isUndefined()) { - result.setUndefined(); - return true; - } - return RequireIntegralNumber(cx, value, name, result); -} - -static bool RequireIntegralPositiveNumberOrUndefined( - JSContext* cx, Handle value, Handle name, - MutableHandle result) { - if (value.isUndefined()) { - result.setUndefined(); - return true; - } - return RequireIntegralPositiveNumber(cx, value, name, result); -} - -static bool RequireString(JSContext* cx, Handle value, - Handle name, - MutableHandle result) { - if (MOZ_LIKELY(value.isString())) { - result.set(value); - return true; - } - - if (auto str = QuoteString(cx, name)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_UNEXPECTED_TYPE, str.get(), "not a string"); - } - return false; -} - -static bool RequireStringOrUndefined(JSContext* cx, Handle value, - Handle name, - MutableHandle result) { - if (value.isUndefined()) { - result.setUndefined(); - return true; - } - return RequireString(cx, value, name, result); -} - -static bool RequireBoolean(JSContext* cx, Handle value, - Handle name, - MutableHandle result) { - if (MOZ_LIKELY(value.isBoolean())) { - result.set(value); - return true; - } - - if (auto str = QuoteString(cx, name)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_UNEXPECTED_TYPE, str.get(), - "not a boolean"); - } - return false; -} - -using BuiltinCalendarMethod = bool (*)(JSContext* cx, CalendarId, - const PlainDate&, MutableHandle); - -using CalendarConversion = bool (*)(JSContext*, Handle, - Handle, - MutableHandle); - -template -static bool CallCalendarMethod(JSContext* cx, Handle name, - JSNative native, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Step 1. - if (calendar.isString()) { - auto calendarId = BuiltinCalendarId(calendar); - return builtin(cx, calendarId, date, result); - } - - // Step 2. - Rooted calendarObj(cx, calendar.toObject()); - JSObject* fn = GetMethod(cx, calendarObj, name); - if (!fn) { - return false; - } - - // Fast-path for the default implementation. - if (calendarObj->is() && IsNativeFunction(fn, native)) { - auto calendarId = BuiltinCalendarId(calendar); - return builtin(cx, calendarId, date, result); - } - - Rooted fnVal(cx, ObjectValue(*fn)); - Rooted dateLikeValue(cx, ObjectValue(*dateLike)); - if (!Call(cx, fnVal, calendarObj, dateLikeValue, result)) { - return false; - } - - // Steps 3-5. - return conversion(cx, result, name, result); -} - -/** - * Temporal.Calendar.prototype.era ( temporalDateLike ) - */ -static bool BuiltinCalendarEra(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-5. - result.setUndefined(); - return true; -} - -static bool Calendar_era(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarEra ( calendar, dateLike ) - */ -static bool CalendarEra(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-5. - return CallCalendarMethod( - cx, cx->names().era, Calendar_era, calendar, dateLike, date, result); -} - -/** - * CalendarEra ( calendar, dateLike ) - */ -bool js::temporal::CalendarEra(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarEra(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarEra ( calendar, dateLike ) - */ -bool js::temporal::CalendarEra(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarEra(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarEra ( calendar, dateLike ) - */ -bool js::temporal::CalendarEra(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarEra(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarEra ( calendar, dateLike ) - */ -bool js::temporal::CalendarEra(JSContext* cx, Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarEra(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.eraYear ( temporalDateLike ) - */ -static bool BuiltinCalendarEraYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-7. - result.setUndefined(); - return true; -} - -static bool Calendar_eraYear(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -static bool CalendarEraYear(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-6. - return CallCalendarMethod( - cx, cx->names().eraYear, Calendar_eraYear, calendar, dateLike, date, - result); -} - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarEraYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarEraYear(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarEraYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarEraYear(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarEraYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarEraYear(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarEraYear(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarEraYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.year ( temporalDateLike ) - */ -static bool BuiltinCalendarYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(date.year); - return true; -} - -static bool Calendar_year(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarYear ( calendar, dateLike ) - */ -static bool CalendarYear(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-5. - return CallCalendarMethod( - cx, cx->names().year, Calendar_year, calendar, dateLike, date, result); -} - -/** - * CalendarYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarYear(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarYear(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarYear(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarYear(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarYear(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarYear(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarYear(JSContext* cx, Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.month ( temporalDateLike ) - */ -static bool BuiltinCalendarMonth(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-4. (Not applicable.) - - // Steps 5-7. - result.setInt32(date.month); - return true; -} - -static bool Calendar_month(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarMonth ( calendar, dateLike ) - */ -static bool CalendarMonth(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-6. - return CallCalendarMethod( - cx, cx->names().month, Calendar_month, calendar, dateLike, date, result); -} - -/** - * CalendarMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonth(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonth(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonth(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonth(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonth(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonth(cx, calendar, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonth(JSContext* cx, Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarMonth(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.monthCode ( temporalDateLike ) - */ -static bool BuiltinCalendarMonthCode(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - JSString* str = ISOMonthCode(cx, date.month); - if (!str) { - return false; - } - - result.setString(str); - return true; -} - -static bool Calendar_monthCode(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -static bool CalendarMonthCode(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-4. - return CallCalendarMethod( - cx, cx->names().monthCode, Calendar_monthCode, calendar, dateLike, date, - result); -} - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthCode(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonthCode(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthCode(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonthCode(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthCode(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonthCode(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthCode(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarMonthCode(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthCode(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarMonthCode(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.day ( temporalDateLike ) - */ -static bool BuiltinCalendarDay(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(date.day); - return true; -} - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -static bool CalendarDay(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - MOZ_ASSERT(CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::Day)); - - // Step 2. (Reordered) - auto day = calendar.day(); - if (!day) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarDay(cx, calendarId, date, result); - } - - // Step 1. (Inlined call to CalendarMethodsRecordCall.) - Rooted fn(cx, ObjectValue(*day)); - auto thisv = calendar.receiver().toObjectValue(); - Rooted dateLikeValue(cx, ObjectValue(*dateLike)); - if (!Call(cx, fn, thisv, dateLikeValue, result)) { - return false; - } - - // Steps 3-6. - return RequireIntegralPositiveNumber(cx, result, cx->names().day, result); -} - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool js::temporal::CalendarDay(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::Day, - }, - &calendarRec)) { - return false; - } - - return CalendarDay(cx, calendarRec, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool js::temporal::CalendarDay(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::Day, - }, - &calendarRec)) { - return false; - } - - return CalendarDay(cx, calendarRec, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool js::temporal::CalendarDay(JSContext* cx, Handle calendar, - Handle dateLike, - MutableHandle result) { - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::Day, - }, - &calendarRec)) { - return false; - } - - return CalendarDay(cx, calendarRec, dateLike, ToPlainDate(dateLike), result); -} - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool js::temporal::CalendarDay(JSContext* cx, Handle calendar, - const PlainDate& date, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDate(cx, date, calendar.receiver())); - if (!dateLike) { - return false; - } - - return ::CalendarDay(cx, calendar, dateLike, date, result); -} - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool js::temporal::CalendarDay(JSContext* cx, Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar.receiver())); - if (!dateLike) { - return false; - } - - return ::CalendarDay(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.dayOfWeek ( temporalDateLike ) - */ -static bool BuiltinCalendarDayOfWeek(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(ToISODayOfWeek(date)); - return true; -} - -static bool Calendar_dayOfWeek(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarDayOfWeek ( calendar, dateLike ) - */ -static bool CalendarDayOfWeek(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-6. - return CallCalendarMethod( - cx, cx->names().dayOfWeek, Calendar_dayOfWeek, calendar, dateLike, date, - result); -} - -/** - * CalendarDayOfWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarDayOfWeek(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDayOfWeek(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDayOfWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarDayOfWeek(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDayOfWeek(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDayOfWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarDayOfWeek(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarDayOfWeek(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.dayOfYear ( temporalDateLike ) - */ -static bool BuiltinCalendarDayOfYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(ToISODayOfYear(date)); - return true; -} - -static bool Calendar_dayOfYear(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarDayOfYear ( calendar, dateLike ) - */ -static bool CalendarDayOfYear(JSContext* cx, Handle calendar, - Handle dateLike, const PlainDate& date, - MutableHandle result) { - // Steps 1-6. - return CallCalendarMethod( - cx, cx->names().dayOfYear, Calendar_dayOfYear, calendar, dateLike, date, - result); -} - -/** - * CalendarDayOfYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDayOfYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDayOfYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDayOfYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDayOfYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDayOfYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDayOfYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDayOfYear(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarDayOfYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.weekOfYear ( temporalDateLike ) - */ -static bool BuiltinCalendarWeekOfYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(ToISOWeekOfYear(date).week); - return true; -} - -static bool Calendar_weekOfYear(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarWeekOfYear ( calendar, dateLike ) - */ -static bool CalendarWeekOfYear(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Steps 1-6. - return CallCalendarMethod( - cx, cx->names().weekOfYear, Calendar_weekOfYear, calendar, dateLike, date, - result); -} - -/** - * CalendarWeekOfYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarWeekOfYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarWeekOfYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarWeekOfYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarWeekOfYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarWeekOfYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarWeekOfYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarWeekOfYear(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarWeekOfYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike ) - */ -static bool BuiltinCalendarYearOfWeek(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(ToISOWeekOfYear(date).year); - return true; -} - -static bool Calendar_yearOfWeek(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarYearOfWeek ( calendar, dateLike ) - */ -static bool CalendarYearOfWeek(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Steps 1-5. - return CallCalendarMethod( - cx, cx->names().yearOfWeek, Calendar_yearOfWeek, calendar, dateLike, date, - result); -} - -/** - * CalendarYearOfWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarYearOfWeek(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarYearOfWeek(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarYearOfWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarYearOfWeek(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarYearOfWeek(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarYearOfWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarYearOfWeek(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarYearOfWeek(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.daysInWeek ( temporalDateLike ) - */ -static bool BuiltinCalendarDaysInWeek(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(7); - return true; -} - -static bool Calendar_daysInWeek(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarDaysInWeek ( calendar, dateLike ) - */ -static bool CalendarDaysInWeek(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Steps 1-6. - return CallCalendarMethod( - cx, cx->names().daysInWeek, Calendar_daysInWeek, calendar, dateLike, date, - result); -} - -/** - * CalendarDaysInWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInWeek(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInWeek(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInWeek(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInWeek(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInWeek ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInWeek(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarDaysInWeek(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.daysInMonth ( temporalDateLike ) - */ -static bool BuiltinCalendarDaysInMonth(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(::ISODaysInMonth(date.year, date.month)); - return true; -} - -static bool Calendar_daysInMonth(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -static bool CalendarDaysInMonth(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Step 1-6. - return CallCalendarMethod( - cx, cx->names().daysInMonth, Calendar_daysInMonth, calendar, dateLike, - date, result); -} - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInMonth(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInMonth(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInMonth(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInMonth(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInMonth(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInMonth(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInMonth(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarDaysInMonth(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.daysInYear ( temporalDateLike ) - */ -static bool BuiltinCalendarDaysInYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(ISODaysInYear(date.year)); - return true; -} - -static bool Calendar_daysInYear(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -static bool CalendarDaysInYear(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Step 1-6. - return CallCalendarMethod( - cx, cx->names().daysInYear, Calendar_daysInYear, calendar, dateLike, date, - result); -} - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return CalendarDaysInYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarDaysInYear(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarDaysInYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.monthsInYear ( temporalDateLike ) - */ -static bool BuiltinCalendarMonthsInYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setInt32(12); - return true; -} - -static bool Calendar_monthsInYear(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -static bool CalendarMonthsInYear(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Step 1-6. - return CallCalendarMethod( - cx, cx->names().monthsInYear, Calendar_monthsInYear, calendar, dateLike, - date, result); -} - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthsInYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return ::CalendarMonthsInYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthsInYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return ::CalendarMonthsInYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthsInYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return ::CalendarMonthsInYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarMonthsInYear(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarMonthsInYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * Temporal.Calendar.prototype.inLeapYear ( temporalDateLike ) - */ -static bool BuiltinCalendarInLeapYear(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - MutableHandle result) { - // Steps 1-3. (Not applicable.) - - // Steps 4-6. - result.setBoolean(IsISOLeapYear(date.year)); - return true; -} - -static bool Calendar_inLeapYear(JSContext* cx, unsigned argc, Value* vp); - -/** - * CalendarInLeapYear ( calendar, dateLike ) - */ -static bool CalendarInLeapYear(JSContext* cx, Handle calendar, - Handle dateLike, - const PlainDate& date, - MutableHandle result) { - // Step 1-4. - return CallCalendarMethod( - cx, cx->names().inLeapYear, Calendar_inLeapYear, calendar, dateLike, date, - result); -} - -/** - * CalendarInLeapYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarInLeapYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return ::CalendarInLeapYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarInLeapYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarInLeapYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return ::CalendarInLeapYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarInLeapYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarInLeapYear(JSContext* cx, - Handle calendar, - Handle dateLike, - MutableHandle result) { - return ::CalendarInLeapYear(cx, calendar, dateLike, ToPlainDate(dateLike), - result); -} - -/** - * CalendarInLeapYear ( calendar, dateLike ) - */ -bool js::temporal::CalendarInLeapYear(JSContext* cx, - Handle calendar, - const PlainDateTime& dateTime, - MutableHandle result) { - Rooted dateLike( - cx, CreateTemporalDateTime(cx, dateTime, calendar)); - if (!dateLike) { - return false; - } - - return ::CalendarInLeapYear(cx, calendar, dateLike, dateTime.date, result); -} - -/** - * ISOResolveMonth ( fields ) - */ -static bool ISOResolveMonth(JSContext* cx, - MutableHandle fields) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - double month = fields.month(); - - // Step 3. - MOZ_ASSERT((IsInteger(month) && month > 0) || std::isnan(month)); - - // Step 4. - Handle monthCode = fields.monthCode(); - - // Step 5. - if (!monthCode) { - // Step 5.a. - if (std::isnan(month)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_MISSING_FIELD, - "monthCode"); - return false; - } - - // Step 5.b. - return true; - } - - // Steps 6-7. (Not applicable in our implementation.) - - // Step 8. - if (monthCode->length() != 3) { - if (auto code = QuoteString(cx, monthCode)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, - code.get()); - } - return false; - } - - JSLinearString* linear = monthCode->ensureLinear(cx); - if (!linear) { - return false; - } - - char16_t chars[3] = { - linear->latin1OrTwoByteChar(0), - linear->latin1OrTwoByteChar(1), - linear->latin1OrTwoByteChar(2), - }; - - // Steps 9-11. (Partial) - if (chars[0] != 'M' || !mozilla::IsAsciiDigit(chars[1]) || - !mozilla::IsAsciiDigit(chars[2])) { - if (auto code = QuoteString(cx, linear)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, - code.get()); - } - return false; - } - - // Step 12. - int32_t monthCodeInteger = - AsciiDigitToNumber(chars[1]) * 10 + AsciiDigitToNumber(chars[2]); - - // Step 11. (Partial) - if (monthCodeInteger < 1 || monthCodeInteger > 12) { - if (auto code = QuoteString(cx, linear)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, - code.get()); - } - return false; - } - - // Step 13. (Not applicable in our implementation.) - - // Step 14. - if (!std::isnan(month) && month != monthCodeInteger) { - if (auto code = QuoteString(cx, linear)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, - code.get()); - } - return false; - } - - // Step 15. - fields.month() = monthCodeInteger; - - // Step 16. - return true; -} - -/** - * ISODateFromFields ( fields, overflow ) - */ -static bool ISODateFromFields(JSContext* cx, Handle fields, - TemporalOverflow overflow, PlainDate* result) { - // Steps 1-2. (Not applicable in our implementation.) - - // Step 3. - double year = fields.year(); - - // Step 4. - double month = fields.month(); - - // Step 5. - double day = fields.day(); - - // Step 6. - MOZ_ASSERT(!std::isnan(year) && !std::isnan(month) && !std::isnan(day)); - - // Step 7. - RegulatedISODate regulated; - if (!RegulateISODate(cx, year, month, day, overflow, ®ulated)) { - return false; - } - - // The result is used to create a new PlainDateObject, so it's okay to - // directly throw an error for invalid years. That way we don't have to worry - // about representing doubles in PlainDate structs. - int32_t intYear; - if (!mozilla::NumberEqualsInt32(regulated.year, &intYear)) { - // CreateTemporalDate, steps 1-2. - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_DATE_INVALID); - return false; - } - - *result = {intYear, regulated.month, regulated.day}; - return true; -} - -/** - * Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] ) - */ -static PlainDateObject* BuiltinCalendarDateFromFields( - JSContext* cx, CalendarId calendarId, Handle fields, - Handle maybeOptions) { - // Steps 1-4. (Not applicable) - - // Step 5. - auto relevantFieldNames = {TemporalField::Day, TemporalField::Month, - TemporalField::MonthCode, TemporalField::Year}; - - // Steps 6-7. - Rooted dateFields(cx); - if (!PrepareTemporalFields(cx, fields, relevantFieldNames, - {TemporalField::Day, TemporalField::Year}, - &dateFields)) { - return nullptr; - } - - // Step 8. - auto overflow = TemporalOverflow::Constrain; - if (maybeOptions) { - if (!GetTemporalOverflowOption(cx, maybeOptions, &overflow)) { + if (day > daysInMonth) { + ReportCalendarFieldOverflow(cx, "day", day); return nullptr; } } - // Step 9.a. - if (!ISOResolveMonth(cx, &dateFields)) { + // ICU4X doesn't support large dates, so we have to handle this case early. + if (mozilla::Abs(eraYear.year) > MaximumCalendarYear(calendarId)) { + ReportCalendarFieldOverflow(cx, "year", eraYear.year); return nullptr; } - // Step 9.b. - PlainDate result; - if (!ISODateFromFields(cx, dateFields, overflow, &result)) { - return nullptr; + auto result = + CreateDateFromCodes(calendarId, calendar, eraYear, monthCode, day); + if (result.isOk()) { + return result.unwrap(); } - // Step 11. - Rooted calendar(cx, CalendarValue(calendarId)); - return CreateTemporalDate(cx, result, calendar); + switch (result.inspectErr()) { + case CalendarError::UnknownMonthCode: { + // We've asserted above that |monthCode| is valid for this calendar, so + // any unknown month code must be for a leap month which doesn't happen in + // the current year. + MOZ_ASSERT(CalendarHasLeapMonths(calendarId)); + MOZ_ASSERT(monthCode.isLeapMonth()); + + if (overflow == TemporalOverflow::Reject) { + // Ensure the month code is null-terminated. + char code[5] = {}; + auto monthCodeView = std::string_view{monthCode}; + monthCodeView.copy(code, monthCodeView.length()); + + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, + code); + return nullptr; + } + + // Retry as non-leap month when we're allowed to constrain. + // + // CalendarDateToISO ( calendar, fields, overflow ) + // + // If the month is a leap month that doesn't exist in the year, pick + // another date according to the cultural conventions of that calendar's + // users. Usually this will result in the same day in the month before or + // after where that month would normally fall in a leap year. + // + // Hebrew calendar: + // Replace Adar I (M05L) with Adar (M06). + // + // Chinese/Dangi calendar: + // Pick the next month, for example M03L -> M04, except for M12L, because + // we don't want to switch over to the next year. + + // TODO: Temporal spec polyfill replaces M03L with M03 for Chinese/Dangi. + // No idea what are the "cultural conventions" for these two calendars... + // + // https://github.com/tc39/proposal-intl-era-monthcode/issues/32 + + int32_t nonLeapMonth = std::min(monthCode.ordinal() + 1, 12); + auto nonLeapMonthCode = MonthCode{nonLeapMonth}; + return CreateDateFromCodes(cx, calendarId, calendar, eraYear, + nonLeapMonthCode, day, overflow); + } + + case CalendarError::Overflow: { + // ICU4X throws an overflow error when: + // 1. month > monthsInYear(year), or + // 2. days > daysInMonthOf(year, month). + // + // Case 1 can't happen for month-codes, so it doesn't apply here. + // Case 2 can only happen when |day| is larger than the minimum number + // of days in the month. + MOZ_ASSERT(day > CalendarDaysInMonth(calendarId, monthCode).first); + + if (overflow == TemporalOverflow::Reject) { + ReportCalendarFieldOverflow(cx, "day", day); + return nullptr; + } + + auto firstDayOfMonth = CreateDateFromCodes( + cx, calendarId, calendar, eraYear, monthCode, 1, overflow); + if (!firstDayOfMonth) { + return nullptr; + } + + int32_t daysInMonth = DaysInMonth(firstDayOfMonth.get()); + MOZ_ASSERT(day > daysInMonth); + return CreateDateFromCodes(cx, calendarId, calendar, eraYear, monthCode, + daysInMonth, overflow); + } + + case CalendarError::OutOfRange: { + // ICU4X throws an out-of-range error if: + // 1. Non-positive era years are given. + // 2. Dates are before/after the requested named Japanese era. + // + // Case 1 doesn't happen for us, because we always pass strictly positive + // era years, so this error must be for case 2. + MOZ_ASSERT(calendarId == CalendarId::Japanese); + MOZ_ASSERT(!CalendarEraStartsAtYearBoundary(calendarId, eraYear.era)); + + EraYear commonEraYear; + if (!JapaneseEraYearToCommonEraYear(cx, calendarId, calendar, eraYear, + &commonEraYear)) { + return nullptr; + } + return CreateDateFromCodes(cx, calendarId, calendar, commonEraYear, + monthCode, day, overflow); + } + + case CalendarError::Underflow: + case CalendarError::UnknownEra: + MOZ_ASSERT(false, "unexpected calendar error"); + break; + + case CalendarError::Generic: + break; + } + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return nullptr; +} + +static UniqueICU4XDate CreateDateFrom(JSContext* cx, CalendarId calendarId, + const capi::ICU4XCalendar* calendar, + EraYear eraYear, int32_t month, + int32_t day, TemporalOverflow overflow) { + MOZ_ASSERT(calendarId != CalendarId::ISO8601); + MOZ_ASSERT(month > 0); + MOZ_ASSERT(day > 0); + MOZ_ASSERT(month <= CalendarMonthsPerYear(calendarId)); + MOZ_ASSERT(day <= CalendarDaysInMonth(calendarId).second); + + switch (calendarId) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Gregorian: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Japanese: + case CalendarId::Persian: + case CalendarId::ROC: { + MOZ_ASSERT(!CalendarHasLeapMonths(calendarId)); + + // Use the month-code corresponding to the ordinal month number for + // calendar systems without leap months. + auto date = CreateDateFromCodes(cx, calendarId, calendar, eraYear, + MonthCode{month}, day, overflow); + if (!date) { + return nullptr; + } + MOZ_ASSERT_IF(CalendarEraStartsAtYearBoundary(calendarId), + OrdinalMonth(calendarId, date.get()) == month); + return date; + } + + case CalendarId::Dangi: + case CalendarId::Chinese: { + static_assert(CalendarHasLeapMonths(CalendarId::Chinese)); + static_assert(CalendarMonthsPerYear(CalendarId::Chinese) == 13); + static_assert(CalendarHasLeapMonths(CalendarId::Dangi)); + static_assert(CalendarMonthsPerYear(CalendarId::Dangi) == 13); + + MOZ_ASSERT(1 <= month && month <= 13); + + // Create date with month number replaced by month-code. + auto monthCode = MonthCode{std::min(month, 12)}; + auto date = CreateDateFromCodes(cx, calendarId, calendar, eraYear, + monthCode, day, overflow); + if (!date) { + return nullptr; + } + + // If the ordinal month of |date| matches the input month, no additional + // changes are necessary and we can directly return |date|. + int32_t ordinal = OrdinalMonth(calendarId, date.get()); + if (ordinal == month) { + return date; + } + + // Otherwise we need to handle three cases: + // 1. The input year contains a leap month and we need to adjust the + // month-code. + // 2. The thirteenth month of a year without leap months was requested. + // 3. The thirteenth month of a year with leap months was requested. + if (ordinal > month) { + MOZ_ASSERT(1 < month && month <= 12); + + // This case can only happen in leap years. + MOZ_ASSERT(MonthsInYear(date.get()) == 13); + + // Leap months can occur after any month in the Chinese calendar. + // + // Example when the fourth month is a leap month between M03 and M04. + // + // Month code: M01 M02 M03 M03L M04 M05 M06 ... + // Ordinal month: 1 2 3 4 5 6 7 + + // The month can be off by exactly one. + MOZ_ASSERT((ordinal - month) == 1); + + // First try the case when the previous month isn't a leap month. This + // case can only occur when |month > 2|, because otherwise we know that + // "M01L" is the correct answer. + if (month > 2) { + auto previousMonthCode = MonthCode{month - 1}; + date = CreateDateFromCodes(cx, calendarId, calendar, eraYear, + previousMonthCode, day, overflow); + if (!date) { + return nullptr; + } + + int32_t ordinal = OrdinalMonth(calendarId, date.get()); + if (ordinal == month) { + return date; + } + } + + // Fall-through when the previous month is a leap month. + } else { + MOZ_ASSERT(month == 13); + MOZ_ASSERT(ordinal == 12); + + // Years with leap months contain thirteen months. + if (MonthsInYear(date.get()) != 13) { + if (overflow == TemporalOverflow::Reject) { + ReportCalendarFieldOverflow(cx, "month", month); + return nullptr; + } + return date; + } + + // Fall-through to return leap month "M12L" at the end of the year. + } + + // Finally handle the case when the previous month is a leap month. + auto leapMonthCode = MonthCode{month - 1, /* isLeapMonth= */ true}; + date = CreateDateFromCodes(cx, calendarId, calendar, eraYear, + leapMonthCode, day, overflow); + if (!date) { + return nullptr; + } + MOZ_ASSERT(OrdinalMonth(calendarId, date.get()) == month, + "unexpected ordinal month"); + return date; + } + + case CalendarId::Hebrew: { + static_assert(CalendarHasLeapMonths(CalendarId::Hebrew)); + static_assert(CalendarMonthsPerYear(CalendarId::Hebrew) == 13); + + MOZ_ASSERT(1 <= month && month <= 13); + + // Create date with month number replaced by month-code. + auto monthCode = MonthCode{std::min(month, 12)}; + auto date = CreateDateFromCodes(cx, calendarId, calendar, eraYear, + monthCode, day, overflow); + if (!date) { + return nullptr; + } + + // If the ordinal month of |date| matches the input month, no additional + // changes are necessary and we can directly return |date|. + int32_t ordinal = OrdinalMonth(calendarId, date.get()); + if (ordinal == month) { + return date; + } + + // Otherwise we need to handle two cases: + // 1. The input year contains a leap month and we need to adjust the + // month-code. + // 2. The thirteenth month of a year without leap months was requested. + if (ordinal > month) { + MOZ_ASSERT(1 < month && month <= 12); + + // This case can only happen in leap years. + MOZ_ASSERT(MonthsInYear(date.get()) == 13); + + // Leap months can occur between M05 and M06 in the Hebrew calendar. + // + // Month code: M01 M02 M03 M04 M05 M05L M06 ... + // Ordinal month: 1 2 3 4 5 6 7 + + // The month can be off by exactly one. + MOZ_ASSERT((ordinal - month) == 1); + } else { + MOZ_ASSERT(month == 13); + MOZ_ASSERT(ordinal == 12); + + if (overflow == TemporalOverflow::Reject) { + ReportCalendarFieldOverflow(cx, "month", month); + return nullptr; + } + return date; + } + + // The previous month is the leap month Adar I iff |month| is six. + bool isLeapMonth = month == 6; + auto previousMonthCode = MonthCode{month - 1, isLeapMonth}; + date = CreateDateFromCodes(cx, calendarId, calendar, eraYear, + previousMonthCode, day, overflow); + if (!date) { + return nullptr; + } + MOZ_ASSERT(OrdinalMonth(calendarId, date.get()) == month, + "unexpected ordinal month"); + return date; + } + } + MOZ_CRASH("invalid calendar id"); +} + +#ifdef IMPLEMENTS_DR2126 +static constexpr size_t ICUEraNameMaxLength() { + size_t length = 0; + for (auto calendar : AvailableCalendars()) { + for (auto era : CalendarEras(calendar)) { + auto name = IcuEraName(calendar, era); + length = std::max(length, name.length()); + } + } + return length; +} +#endif + +/** + * Retrieve the era code from |date| and then map the returned ICU4X era code to + * the corresponding |EraCode| member. + */ +static bool CalendarDateEra(JSContext* cx, CalendarId calendar, + const capi::ICU4XDate* date, EraCode* result) { + MOZ_ASSERT(calendar != CalendarId::ISO8601); + + // Note: Assigning MaxLength to ICUEraNameMaxLength() breaks the CDT indexer. + constexpr size_t MaxLength = 15; +#ifdef IMPLEMENTS_DR2126 + +// Disable tautological-value-range-compare to avoid a bogus Clang warning. +// See bug 1956918 and bug 1936626. +# ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wtautological-value-range-compare" +# endif + + static_assert(MaxLength >= ICUEraNameMaxLength(), + "Storage size is at least as large as the largest known era"); + +# ifdef __clang__ +# pragma clang diagnostic pop +# endif + +#endif + + // Storage for the largest known era string and the terminating NUL-character. + char buf[MaxLength + 1] = {}; + auto writable = capi::diplomat_simple_writeable(buf, std::size(buf)); + + if (!capi::ICU4XDate_era(date, &writable).is_ok) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return false; + } + MOZ_ASSERT(writable.buf == buf, "unexpected buffer relocation"); + + auto dateEra = std::string_view{writable.buf, writable.len}; + + // Map to era name to era code. + for (auto era : CalendarEras(calendar)) { + if (IcuEraName(calendar, era) == dateEra) { + *result = era; + return true; + } + } + + // Invalid/Unknown era name. + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return false; } /** - * CalendarDateFromFields ( calendarRec, fields [ , options ] ) + * Return the extended (non-era) year from |date|. */ -static Wrapped CalendarDateFromFields( - JSContext* cx, Handle calendar, Handle fields, - Handle maybeOptions) { - MOZ_ASSERT(CalendarMethodsRecordHasLookedUp(calendar, - CalendarMethod::DateFromFields)); +static bool CalendarDateYear(JSContext* cx, CalendarId calendar, + const capi::ICU4XDate* date, int32_t* result) { + MOZ_ASSERT(calendar != CalendarId::ISO8601); - // Step 1. (Not applicable in our implemetation.) + // FIXME: ICU4X doesn't yet support CalendarDateYear, so we need to manually + // adjust the era year to determine the non-era year. + // + // https://github.com/unicode-org/icu4x/issues/3962 - // Step 3. (Reordered) - auto dateFromFields = calendar.dateFromFields(); - if (!dateFromFields) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarDateFromFields(cx, calendarId, fields, maybeOptions); + if (!CalendarEraRelevant(calendar)) { + int32_t year = capi::ICU4XDate_year_in_era(date); + *result = year; + return true; } - // Step 2. (Inlined call to CalendarMethodsRecordCall.) + if (calendar != CalendarId::Japanese) { + MOZ_ASSERT(CalendarEras(calendar).size() == 2); - Rooted dateFromFieldsFn(cx, ObjectValue(*dateFromFields)); - auto thisv = calendar.receiver().toObjectValue(); - Rooted rval(cx); + int32_t year = capi::ICU4XDate_year_in_era(date); + MOZ_ASSERT(year > 0, "era years are strictly positive in ICU4X"); - FixedInvokeArgs<2> args(cx); - args[0].setObject(*fields); - if (maybeOptions) { - args[1].setObject(*maybeOptions); - } else { - args[1].setUndefined(); + EraCode era; + if (!CalendarDateEra(cx, calendar, date, &era)) { + return false; + } + + // Map from era year to extended year. + // + // For example in the Gregorian calendar: + // + // ---------------------------- + // | Era Year | Extended Year | + // | 2 CE | 2 | + // | 1 CE | 1 | + // | 1 BCE | 0 | + // | 2 BCE | -1 | + // ---------------------------- + if (era == EraCode::Inverse) { + year = -(year - 1); + } else { + MOZ_ASSERT(era == EraCode::Standard); + } + + *result = year; + return true; } - if (!Call(cx, dateFromFieldsFn, thisv, args, &rval)) { - return nullptr; - } + // Japanese uses a proleptic Gregorian calendar, so we can use the ISO year. + UniqueICU4XIsoDate isoDate{capi::ICU4XDate_to_iso(date)}; + int32_t isoYear = capi::ICU4XIsoDate_year(isoDate.get()); - // Step 4. - if (!rval.isObject() || !rval.toObject().canUnwrapAs()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, rval, - nullptr, "not a PlainDate object"); - return nullptr; - } - - // Step 5. - return &rval.toObject(); + *result = isoYear; + return true; } /** - * CalendarDateFromFields ( calendarRec, fields [ , options ] ) + * Retrieve the month code from |date| and then map the returned ICU4X month + * code to the corresponding |MonthCode| member. */ -Wrapped js::temporal::CalendarDateFromFields( - JSContext* cx, Handle calendar, - Handle fields) { - // Steps 1-6. - return ::CalendarDateFromFields(cx, calendar, fields, nullptr); +static bool CalendarDateMonthCode(JSContext* cx, CalendarId calendar, + const capi::ICU4XDate* date, + MonthCode* result) { + MOZ_ASSERT(calendar != CalendarId::ISO8601); + + // Valid month codes are "M01".."M13" and "M01L".."M12L". + constexpr size_t MaxLength = + std::string_view{MonthCode::maxLeapMonth()}.length(); + static_assert( + MaxLength > std::string_view{MonthCode::maxNonLeapMonth()}.length(), + "string representation of max-leap month is larger"); + + // Storage for the largest valid month code and the terminating NUL-character. + char buf[MaxLength + 1] = {}; + auto writable = capi::diplomat_simple_writeable(buf, std::size(buf)); + + if (!capi::ICU4XDate_month_code(date, &writable).is_ok) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return false; + } + MOZ_ASSERT(writable.buf == buf, "unexpected buffer relocation"); + + auto view = std::string_view{writable.buf, writable.len}; + + MOZ_ASSERT(view.length() >= 3); + MOZ_ASSERT(view[0] == 'M'); + MOZ_ASSERT(mozilla::IsAsciiDigit(view[1])); + MOZ_ASSERT(mozilla::IsAsciiDigit(view[2])); + MOZ_ASSERT_IF(view.length() > 3, view[3] == 'L'); + + int32_t ordinal = + AsciiDigitToNumber(view[1]) * 10 + AsciiDigitToNumber(view[2]); + bool isLeapMonth = view.length() > 3; + auto monthCode = MonthCode{ordinal, isLeapMonth}; + + static constexpr auto IrregularAdarII = + MonthCode{6, /* isLeapMonth = */ true}; + static constexpr auto RegularAdarII = MonthCode{6}; + + // Handle the irregular month code "M06L" for Adar II in leap years. + // + // https://docs.rs/icu/latest/icu/calendar/hebrew/struct.Hebrew.html#month-codes + if (calendar == CalendarId::Hebrew && monthCode == IrregularAdarII) { + monthCode = RegularAdarII; + } + + if (DayOfMonthCanBeZero(calendar)) { + // If |dayOfMonth| is zero, interpret as last day of previous month. + int32_t dayOfMonth = capi::ICU4XDate_day_of_month(date); + if (dayOfMonth == 0) { + MOZ_ASSERT(ordinal > 1 && !isLeapMonth); + monthCode = MonthCode{ordinal - 1}; + } + } + + // The month code must be valid for this calendar. + MOZ_ASSERT(CalendarMonthCodes(calendar).contains(monthCode)); + + *result = monthCode; + return true; } -/** - * CalendarDateFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarDateFromFields( - JSContext* cx, Handle calendar, Handle fields, - Handle options) { - // Steps 1-6. - return ::CalendarDateFromFields(cx, calendar, fields, options); -} +class MonthCodeString { + // Zero-terminated month code string. + char str_[4 + 1]; -struct RegulatedISOYearMonth final { - double year = 0; - int32_t month = 0; + public: + explicit MonthCodeString(MonthCodeField field) { + str_[0] = 'M'; + str_[1] = char('0' + (field.ordinal() / 10)); + str_[2] = char('0' + (field.ordinal() % 10)); + str_[3] = field.isLeapMonth() ? 'L' : '\0'; + str_[4] = '\0'; + } + + const char* toCString() const { return str_; } }; /** - * RegulateISOYearMonth ( year, month, overflow ) + * CalendarResolveFields ( calendar, fields, type ) */ -static bool RegulateISOYearMonth(JSContext* cx, double year, double month, - TemporalOverflow overflow, - RegulatedISOYearMonth* result) { +static bool ISOCalendarResolveMonth(JSContext* cx, + Handle fields, + double* result) { + double month = fields.month(); + MOZ_ASSERT_IF(fields.has(CalendarField::Month), + IsInteger(month) && month > 0); + + // CalendarResolveFields, steps 1.e. + if (!fields.has(CalendarField::MonthCode)) { + MOZ_ASSERT(fields.has(CalendarField::Month)); + + *result = month; + return true; + } + + auto monthCode = fields.monthCode(); + + // CalendarResolveFields, steps 1.f-k. + int32_t ordinal = monthCode.ordinal(); + if (ordinal < 1 || ordinal > 12 || monthCode.isLeapMonth()) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, + MonthCodeString{monthCode}.toCString()); + return false; + } + + // CalendarResolveFields, steps 1.l-m. + if (fields.has(CalendarField::Month) && month != ordinal) { + ToCStringBuf cbuf; + const char* monthStr = NumberToCString(&cbuf, month); + + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_MONTHCODE, + MonthCodeString{monthCode}.toCString(), monthStr); + return false; + } + + // CalendarResolveFields, steps 1.n. + *result = ordinal; + return true; +} + +struct EraYears { + // Year starting from the calendar epoch. + mozilla::Maybe fromEpoch; + + // Year starting from a specific calendar era. + mozilla::Maybe fromEra; +}; + +static bool CalendarEraYear(JSContext* cx, CalendarId calendarId, + EraYear eraYear, EraYear* result) { + MOZ_ASSERT(CalendarEraRelevant(calendarId)); + MOZ_ASSERT(mozilla::Abs(eraYear.year) <= MaximumCalendarYear(calendarId)); + + if (eraYear.year > 0) { + *result = eraYear; + return true; + } + + switch (eraYear.era) { + case EraCode::Standard: { + // Map non-positive era years as follows: + // + // 0 CE -> 1 BCE + // -1 CE -> 2 BCE + // etc. + *result = {EraCode::Inverse, int32_t(mozilla::Abs(eraYear.year) + 1)}; + return true; + } + + case EraCode::Inverse: { + // Map non-positive era years as follows: + // + // 0 BCE -> 1 CE + // -1 BCE -> 2 CE + // etc. + *result = {EraCode::Standard, int32_t(mozilla::Abs(eraYear.year) + 1)}; + return true; + } + + case EraCode::Meiji: + case EraCode::Taisho: + case EraCode::Showa: + case EraCode::Heisei: + case EraCode::Reiwa: { + MOZ_ASSERT(calendarId == CalendarId::Japanese); + + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + return JapaneseEraYearToCommonEraYear(cx, calendarId, cal.get(), eraYear, + result); + } + } + MOZ_CRASH("invalid era id"); +} + +/** + * CalendarResolveFields ( calendar, fields, type ) + * CalendarDateToISO ( calendar, fields, overflow ) + * CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow ) + * + * Extract `year` and `eraYear` from |fields| and perform some initial + * validation to ensure the values are valid for the requested calendar. + */ +static bool CalendarFieldYear(JSContext* cx, CalendarId calendar, + Handle fields, EraYears* result) { + MOZ_ASSERT(fields.has(CalendarField::Year) || + fields.has(CalendarField::EraYear)); + + // |eraYear| is to be ignored when not relevant for |calendar| per + // CalendarResolveFields. + bool hasRelevantEra = + fields.has(CalendarField::Era) && CalendarEraRelevant(calendar); + MOZ_ASSERT_IF(fields.has(CalendarField::Era), CalendarEraRelevant(calendar)); + + // Case 1: |year| field is present. + mozilla::Maybe fromEpoch; + if (fields.has(CalendarField::Year)) { + double year = fields.year(); + MOZ_ASSERT(IsInteger(year)); + + int32_t intYear; + if (!mozilla::NumberEqualsInt32(year, &intYear) || + mozilla::Abs(intYear) > MaximumCalendarYear(calendar)) { + ReportCalendarFieldOverflow(cx, "year", year); + return false; + } + + fromEpoch = mozilla::Some(CalendarEraYear(calendar, intYear)); + } else { + MOZ_ASSERT(hasRelevantEra); + } + + // Case 2: |era| and |eraYear| fields are present and relevant for |calendar|. + mozilla::Maybe fromEra; + if (hasRelevantEra) { + MOZ_ASSERT(fields.has(CalendarField::Era)); + MOZ_ASSERT(fields.has(CalendarField::EraYear)); + + auto era = fields.era(); + MOZ_ASSERT(era); + + double eraYear = fields.eraYear(); + MOZ_ASSERT(IsInteger(eraYear)); + + auto* linearEra = era->ensureLinear(cx); + if (!linearEra) { + return false; + } + + // Ensure the requested era is valid for |calendar|. + auto eraCode = EraForString(calendar, linearEra); + if (!eraCode) { + if (auto code = QuoteString(cx, era)) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INVALID_ERA, + code.get()); + } + return false; + } + + int32_t intEraYear; + if (!mozilla::NumberEqualsInt32(eraYear, &intEraYear) || + mozilla::Abs(intEraYear) > MaximumCalendarYear(calendar)) { + ReportCalendarFieldOverflow(cx, "eraYear", eraYear); + return false; + } + + EraYear eraAndYear; + if (!CalendarEraYear(cx, calendar, {*eraCode, intEraYear}, &eraAndYear)) { + return false; + } + fromEra = mozilla::Some(eraAndYear); + } + + *result = {fromEpoch, fromEra}; + return true; +} + +struct Month { + // Month code. + MonthCode code; + + // Ordinal month number. + int32_t ordinal = 0; +}; + +/** + * CalendarResolveFields ( calendar, fields, type ) + * CalendarDateToISO ( calendar, fields, overflow ) + * CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow ) + * + * Extract `month` and `monthCode` from |fields| and perform some initial + * validation to ensure the values are valid for the requested calendar. + */ +static bool CalendarFieldMonth(JSContext* cx, CalendarId calendar, + Handle fields, + TemporalOverflow overflow, Month* result) { + MOZ_ASSERT(fields.has(CalendarField::Month) || + fields.has(CalendarField::MonthCode)); + + // Case 1: |month| field is present. + int32_t intMonth = 0; + if (fields.has(CalendarField::Month)) { + double month = fields.month(); + MOZ_ASSERT(IsInteger(month) && month > 0); + + if (!mozilla::NumberEqualsInt32(month, &intMonth)) { + intMonth = 0; + } + + const int32_t monthsPerYear = CalendarMonthsPerYear(calendar); + if (intMonth < 1 || intMonth > monthsPerYear) { + if (overflow == TemporalOverflow::Reject) { + ReportCalendarFieldOverflow(cx, "month", month); + return false; + } + MOZ_ASSERT(overflow == TemporalOverflow::Constrain); + + intMonth = monthsPerYear; + } + + MOZ_ASSERT(intMonth > 0); + } + + // Case 2: |monthCode| field is present. + MonthCode fromMonthCode; + if (fields.has(CalendarField::MonthCode)) { + auto monthCode = fields.monthCode(); + int32_t ordinal = monthCode.ordinal(); + bool isLeapMonth = monthCode.isLeapMonth(); + + constexpr int32_t minMonth = MonthCode{1}.ordinal(); + constexpr int32_t maxNonLeapMonth = MonthCode::maxNonLeapMonth().ordinal(); + constexpr int32_t maxLeapMonth = MonthCode::maxLeapMonth().ordinal(); + + // Minimum month number is 1. Maximum month is 12 (or 13 when the calendar + // uses epagomenal months). + const int32_t maxMonth = isLeapMonth ? maxLeapMonth : maxNonLeapMonth; + if (minMonth <= ordinal && ordinal <= maxMonth) { + fromMonthCode = MonthCode{ordinal, isLeapMonth}; + } + + // Ensure the month code is valid for this calendar. + const auto& monthCodes = CalendarMonthCodes(calendar); + if (!monthCodes.contains(fromMonthCode)) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, + MonthCodeString{monthCode}.toCString()); + return false; + } + } + + *result = {fromMonthCode, intMonth}; + return true; +} + +/** + * CalendarResolveFields ( calendar, fields, type ) + * CalendarDateToISO ( calendar, fields, overflow ) + * CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow ) + * + * Extract `day` from |fields| and perform some initial validation to ensure the + * value is valid for the requested calendar. + */ +static bool CalendarFieldDay(JSContext* cx, CalendarId calendar, + Handle fields, + TemporalOverflow overflow, int32_t* result) { + MOZ_ASSERT(fields.has(CalendarField::Day)); + + double day = fields.day(); + MOZ_ASSERT(IsInteger(day) && day > 0); + + int32_t intDay; + if (!mozilla::NumberEqualsInt32(day, &intDay)) { + intDay = 0; + } + + // Constrain to a valid day value in this calendar. + int32_t daysPerMonth = CalendarDaysInMonth(calendar).second; + if (intDay < 1 || intDay > daysPerMonth) { + if (overflow == TemporalOverflow::Reject) { + ReportCalendarFieldOverflow(cx, "day", day); + return false; + } + MOZ_ASSERT(overflow == TemporalOverflow::Constrain); + + intDay = daysPerMonth; + } + + *result = intDay; + return true; +} + +/** + * CalendarResolveFields ( calendar, fields, type ) + * + * > The operation throws a TypeError exception if the properties of fields are + * > internally inconsistent within the calendar [...]. For example: + * > + * > [...] The values for "era" and "eraYear" do not together identify the same + * > year as the value for "year". + */ +static bool CalendarFieldEraYearMatchesYear(JSContext* cx, CalendarId calendar, + Handle fields, + const capi::ICU4XDate* date) { + MOZ_ASSERT(fields.has(CalendarField::EraYear)); + MOZ_ASSERT(fields.has(CalendarField::Year)); + + double year = fields.year(); MOZ_ASSERT(IsInteger(year)); + + int32_t intYear; + MOZ_ALWAYS_TRUE(mozilla::NumberEqualsInt32(year, &intYear)); + + int32_t yearFromEraYear; + if (!CalendarDateYear(cx, calendar, date, &yearFromEraYear)) { + return false; + } + + // The user requested year must match the actual (extended/epoch) year. + if (intYear != yearFromEraYear) { + ToCStringBuf yearCbuf; + const char* yearStr = NumberToCString(&yearCbuf, intYear); + + ToCStringBuf fromEraCbuf; + const char* fromEraStr = NumberToCString(&fromEraCbuf, yearFromEraYear); + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_YEAR, + yearStr, fromEraStr); + return false; + } + return true; +} + +/** + * CalendarResolveFields ( calendar, fields, type ) + * + * > The operation throws a TypeError exception if the properties of fields are + * > internally inconsistent within the calendar [...]. For example: + * > + * > If "month" and "monthCode" in the calendar [...] do not identify the same + * > month. + */ +static bool CalendarFieldMonthCodeMatchesMonth(JSContext* cx, + CalendarId calendarId, + Handle fields, + const capi::ICU4XDate* date, + int32_t month) { + int32_t ordinal = OrdinalMonth(calendarId, date); + + // The user requested month must match the actual ordinal month. + if (month != ordinal) { + ToCStringBuf cbuf; + const char* monthStr = NumberToCString(&cbuf, fields.month()); + + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_MONTHCODE, + MonthCodeString{fields.monthCode()}.toCString(), + monthStr); + return false; + } + return true; +} + +static ISODate ToISODate(const capi::ICU4XDate* date) { + UniqueICU4XIsoDate isoDate{capi::ICU4XDate_to_iso(date)}; + + int32_t isoYear = capi::ICU4XIsoDate_year(isoDate.get()); + + int32_t isoMonth = capi::ICU4XIsoDate_month(isoDate.get()); + MOZ_ASSERT(1 <= isoMonth && isoMonth <= 12); + + int32_t isoDay = capi::ICU4XIsoDate_day_of_month(isoDate.get()); + + // TODO: Workaround for . + if (isoDay == 0) { + MOZ_ASSERT(capi::ICU4XCalendar_kind(capi::ICU4XDate_calendar(date)) == + capi::ICU4XAnyCalendarKind_Indian); + isoDay = 31; + isoMonth = 12; + isoYear -= 1; + } + + MOZ_ASSERT(1 <= isoDay && isoDay <= ::ISODaysInMonth(isoYear, isoMonth)); + + return {isoYear, isoMonth, isoDay}; +} + +static UniqueICU4XDate CreateDateFrom(JSContext* cx, CalendarId calendar, + const capi::ICU4XCalendar* cal, + const EraYears& eraYears, + const Month& month, int32_t day, + Handle fields, + TemporalOverflow overflow) { + // Use |eraYear| if present, so we can more easily check for consistent + // |year| and |eraYear| fields. + auto eraYear = eraYears.fromEra ? *eraYears.fromEra : *eraYears.fromEpoch; + + UniqueICU4XDate date; + if (month.code != MonthCode{}) { + date = CreateDateFromCodes(cx, calendar, cal, eraYear, month.code, day, + overflow); + } else { + date = CreateDateFrom(cx, calendar, cal, eraYear, month.ordinal, day, + overflow); + } + if (!date) { + return nullptr; + } + + // |year| and |eraYear| must be consistent. + if (eraYears.fromEpoch && eraYears.fromEra) { + if (!CalendarFieldEraYearMatchesYear(cx, calendar, fields, date.get())) { + return nullptr; + } + } + + // |month| and |monthCode| must be consistent. + if (month.code != MonthCode{} && month.ordinal > 0) { + if (!CalendarFieldMonthCodeMatchesMonth(cx, calendar, fields, date.get(), + month.ordinal)) { + return nullptr; + } + } + + return date; +} + +/** + * RegulateISODate ( year, month, day, overflow ) + */ +static bool RegulateISODate(JSContext* cx, int32_t year, double month, + double day, TemporalOverflow overflow, + ISODate* result) { MOZ_ASSERT(IsInteger(month)); + MOZ_ASSERT(IsInteger(day)); // Step 1. if (overflow == TemporalOverflow::Constrain) { // Step 1.a. - month = std::clamp(month, 1.0, 12.0); + int32_t m = int32_t(std::clamp(month, 1.0, 12.0)); // Step 1.b. - *result = {year, int32_t(month)}; + double daysInMonth = double(::ISODaysInMonth(year, m)); + + // Step 1.c. + int32_t d = int32_t(std::clamp(day, 1.0, daysInMonth)); + + // Step 3. (Inlined call to CreateISODateRecord.) + *result = {year, m, d}; return true; } @@ -2826,2318 +2133,2104 @@ static bool RegulateISOYearMonth(JSContext* cx, double year, double month, MOZ_ASSERT(overflow == TemporalOverflow::Reject); // Step 2.b. - if (month < 1 || month > 12) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID); + if (!ThrowIfInvalidISODate(cx, year, month, day)) { return false; } - // Step 2.c. - *result = {year, int32_t(month)}; + // Step 3. (Inlined call to CreateISODateRecord.) + *result = {year, int32_t(month), int32_t(day)}; return true; } /** - * ISOYearMonthFromFields ( fields, overflow ) + * CalendarDateToISO ( calendar, fields, overflow ) */ -static bool ISOYearMonthFromFields(JSContext* cx, Handle fields, - TemporalOverflow overflow, - PlainDate* result) { +static bool CalendarDateToISO(JSContext* cx, CalendarId calendar, + Handle fields, + TemporalOverflow overflow, ISODate* result) { // Step 1. - double year = fields.year(); + if (calendar == CalendarId::ISO8601) { + // Step 1.a. + MOZ_ASSERT(fields.has(CalendarField::Year)); + MOZ_ASSERT(fields.has(CalendarField::Month) || + fields.has(CalendarField::MonthCode)); + MOZ_ASSERT(fields.has(CalendarField::Day)); - // Step 2. - double month = fields.month(); - - // Step 3. - MOZ_ASSERT(!std::isnan(year) && !std::isnan(month)); - - // Step 4. - RegulatedISOYearMonth regulated; - if (!RegulateISOYearMonth(cx, year, month, overflow, ®ulated)) { - return false; - } - - // Step 5. - - // The result is used to create a new PlainYearMonthObject, so it's okay to - // directly throw an error for invalid years. That way we don't have to worry - // about representing doubles in PlainDate structs. - int32_t intYear; - if (!mozilla::NumberEqualsInt32(regulated.year, &intYear)) { - // CreateTemporalYearMonth, steps 1-2. - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID); - return false; - } - - *result = {intYear, regulated.month, 1}; - return true; -} - -/** - * Temporal.Calendar.prototype.yearMonthFromFields ( fields [ , options ] ) - */ -static PlainYearMonthObject* BuiltinCalendarYearMonthFromFields( - JSContext* cx, CalendarId calendarId, Handle fields, - Handle maybeOptions) { - // Steps 1-4. (Not applicable) - - // Step 5. - auto relevantFieldNames = {TemporalField::Month, TemporalField::MonthCode, - TemporalField::Year}; - - // Steps 6-7. - Rooted dateFields(cx); - if (!PrepareTemporalFields(cx, fields, relevantFieldNames, - {TemporalField::Year}, &dateFields)) { - return nullptr; - } - - // Step 8. - auto overflow = TemporalOverflow::Constrain; - if (maybeOptions) { - if (!GetTemporalOverflowOption(cx, maybeOptions, &overflow)) { - return nullptr; - } - } - - // Step 9.a. - if (!ISOResolveMonth(cx, &dateFields)) { - return nullptr; - } - - // Step 9.b. - PlainDate result; - if (!ISOYearMonthFromFields(cx, dateFields, overflow, &result)) { - return nullptr; - } - - // Step 11. - Rooted calendar(cx, CalendarValue(calendarId)); - return CreateTemporalYearMonth(cx, result, calendar); -} - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -static Wrapped CalendarYearMonthFromFields( - JSContext* cx, Handle calendar, Handle fields, - Handle maybeOptions) { - MOZ_ASSERT(CalendarMethodsRecordHasLookedUp( - calendar, CalendarMethod::YearMonthFromFields)); - - // Step 1. (Not applicable in our implementation.) - - // Step 3. (Reordered) - auto yearMonthFromFields = calendar.yearMonthFromFields(); - if (!yearMonthFromFields) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarYearMonthFromFields(cx, calendarId, fields, - maybeOptions); - } - - // Step 2. (Inlined call to CalendarMethodsRecordCall.) - - Rooted yearMonthFromFieldsFn(cx, ObjectValue(*yearMonthFromFields)); - auto thisv = calendar.receiver().toObjectValue(); - Rooted rval(cx); - - FixedInvokeArgs<2> args(cx); - args[0].setObject(*fields); - if (maybeOptions) { - args[1].setObject(*maybeOptions); - } else { - args[1].setUndefined(); - } - - if (!Call(cx, yearMonthFromFieldsFn, thisv, args, &rval)) { - return nullptr; - } - - // Step 4. - if (!rval.isObject() || - !rval.toObject().canUnwrapAs()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, rval, - nullptr, "not a PlainYearMonth object"); - return nullptr; - } - - // Step 5. - return &rval.toObject(); -} - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarYearMonthFromFields( - JSContext* cx, Handle calendar, - Handle fields) { - // Steps 1-4. - return ::CalendarYearMonthFromFields(cx, calendar, fields, nullptr); -} - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarYearMonthFromFields( - JSContext* cx, Handle calendar, - Handle fields) { - // Steps 1-4. - return ::CalendarYearMonthFromFields(cx, calendar, fields, nullptr); -} - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarYearMonthFromFields( - JSContext* cx, Handle calendar, Handle fields, - Handle options) { - // Steps 1-4. - return ::CalendarYearMonthFromFields(cx, calendar, fields, options); -} - -/** - * ISOMonthDayFromFields ( fields, overflow ) - */ -static bool ISOMonthDayFromFields(JSContext* cx, Handle fields, - TemporalOverflow overflow, - PlainDate* result) { - // Step 1. - double month = fields.month(); - - // Step 2. - double day = fields.day(); - - // Step 3. - MOZ_ASSERT(!std::isnan(month)); - MOZ_ASSERT(!std::isnan(day)); - - // Step 4. - double year = fields.year(); - - // Step 5. - int32_t referenceISOYear = 1972; - - // Steps 6-7. - double y = std::isnan(year) ? referenceISOYear : year; - RegulatedISODate regulated; - if (!RegulateISODate(cx, y, month, day, overflow, ®ulated)) { - return false; - } - - // Step 8. - *result = {referenceISOYear, regulated.month, regulated.day}; - return true; -} - -/** - * Temporal.Calendar.prototype.monthDayFromFields ( fields [ , options ] ) - */ -static PlainMonthDayObject* BuiltinCalendarMonthDayFromFields( - JSContext* cx, CalendarId calendarId, Handle fields, - Handle maybeOptions) { - // Steps 1-4. (Not applicable) - - // Step 5. - auto relevantFieldNames = {TemporalField::Day, TemporalField::Month, - TemporalField::MonthCode, TemporalField::Year}; - - // Steps 6-7. - Rooted dateFields(cx); - if (!PrepareTemporalFields(cx, fields, relevantFieldNames, - {TemporalField::Day}, &dateFields)) { - return nullptr; - } - - // Step 8. - auto overflow = TemporalOverflow::Constrain; - if (maybeOptions) { - if (!GetTemporalOverflowOption(cx, maybeOptions, &overflow)) { - return nullptr; - } - } - - // Step 9.a. - if (!ISOResolveMonth(cx, &dateFields)) { - return nullptr; - } - - // Step 9.b. - PlainDate result; - if (!ISOMonthDayFromFields(cx, dateFields, overflow, &result)) { - return nullptr; - } - - // Step 11. - Rooted calendar(cx, CalendarValue(calendarId)); - return CreateTemporalMonthDay(cx, result, calendar); -} - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -static Wrapped CalendarMonthDayFromFields( - JSContext* cx, Handle calendar, Handle fields, - Handle maybeOptions) { - MOZ_ASSERT(CalendarMethodsRecordHasLookedUp( - calendar, CalendarMethod::MonthDayFromFields)); - - // Step 1. (Not applicable in our implementation.) - - // Step 3. (Reordered) - auto monthDayFromFields = calendar.monthDayFromFields(); - if (!monthDayFromFields) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarMonthDayFromFields(cx, calendarId, fields, - maybeOptions); - } - - // Step 2. (Inlined call to CalendarMethodsRecordCall.) - - Rooted monthDayFromFieldsFn(cx, ObjectValue(*monthDayFromFields)); - auto thisv = calendar.receiver().toObjectValue(); - Rooted rval(cx); - - FixedInvokeArgs<2> args(cx); - args[0].setObject(*fields); - if (maybeOptions) { - args[1].setObject(*maybeOptions); - } else { - args[1].setUndefined(); - } - - if (!Call(cx, monthDayFromFieldsFn, thisv, args, &rval)) { - return nullptr; - } - - // Step 4. - if (!rval.isObject() || !rval.toObject().canUnwrapAs()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, rval, - nullptr, "not a PlainMonthDay object"); - return nullptr; - } - - // Step 5. - return &rval.toObject(); -} - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarMonthDayFromFields( - JSContext* cx, Handle calendar, - Handle fields) { - // Steps 1-4. - return ::CalendarMonthDayFromFields(cx, calendar, fields, nullptr); -} - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarMonthDayFromFields( - JSContext* cx, Handle calendar, - Handle fields) { - // Steps 1-4. - return ::CalendarMonthDayFromFields(cx, calendar, fields, nullptr); -} - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped js::temporal::CalendarMonthDayFromFields( - JSContext* cx, Handle calendar, Handle fields, - Handle options) { - // Steps 1-4. - return ::CalendarMonthDayFromFields(cx, calendar, fields, options); -} - -using PropertyHashSet = JS::GCHashSet; -using PropertyVector = JS::StackGCVector; - -static bool SetFromList(JSContext* cx, const PropertyVector& keys, - PropertyHashSet& keysSet) { - MOZ_ASSERT(keysSet.empty(), "expected an empty output hashset"); - - if (!keysSet.reserve(keys.length())) { - return false; - } - - for (const auto& key : keys) { - if (!keysSet.putNew(key)) { + // Remaining steps from CalendarResolveFields to resolve the month. + double month; + if (!ISOCalendarResolveMonth(cx, fields, &month)) { return false; } - } - return true; -} -/** - * ISOFieldKeysToIgnore ( keys ) - */ -static auto ISOFieldKeysToIgnore(mozilla::EnumSet keys) { - // Steps 1 and 2.a. - auto ignoredKeys = keys; + int32_t intYear; + if (!mozilla::NumberEqualsInt32(fields.year(), &intYear)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; + } - // Step 2.b. - if (keys.contains(TemporalField::Month)) { - ignoredKeys += TemporalField::MonthCode; + // Step 1.b. + return RegulateISODate(cx, intYear, month, fields.day(), overflow, result); } - // Step 2.c. - else if (keys.contains(TemporalField::MonthCode)) { - ignoredKeys += TemporalField::Month; - } + // Step 2. - // Steps 3-4. - return ignoredKeys; -} - -#ifdef DEBUG -static bool IsPlainDataObject(PlainObject* obj) { - // [[Prototype]] is null. - if (obj->staticPrototype() != nullptr) { + EraYears eraYears; + if (!CalendarFieldYear(cx, calendar, fields, &eraYears)) { return false; } - // All properties are simple data properties. - for (ShapePropertyIter iter(obj->shape()); !iter.done(); iter++) { - if (iter->flags() != PropertyFlags::defaultDataPropFlags) { - return false; - } + Month month; + if (!CalendarFieldMonth(cx, calendar, fields, overflow, &month)) { + return false; } + + int32_t day; + if (!CalendarFieldDay(cx, calendar, fields, overflow, &day)) { + return false; + } + + auto cal = CreateICU4XCalendar(cx, calendar); + if (!cal) { + return false; + } + + auto date = CreateDateFrom(cx, calendar, cal.get(), eraYears, month, day, + fields, overflow); + if (!date) { + return false; + } + + *result = ToISODate(date.get()); return true; } -#endif /** - * Temporal.Calendar.prototype.mergeFields ( fields, additionalFields ) + * CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow ) */ -static PlainObject* BuiltinCalendarMergeFields( - JSContext* cx, CalendarId calendarId, Handle fields, - Handle additionalFields) { - MOZ_ASSERT(IsPlainDataObject(fields)); - MOZ_ASSERT(IsPlainDataObject(additionalFields)); +static bool CalendarMonthDayToISOReferenceDate(JSContext* cx, + CalendarId calendar, + Handle fields, + TemporalOverflow overflow, + ISODate* result) { + // Step 1. + if (calendar == CalendarId::ISO8601) { + // Step 1.a. + MOZ_ASSERT(fields.has(CalendarField::Month) || + fields.has(CalendarField::MonthCode)); + MOZ_ASSERT(fields.has(CalendarField::Day)); - // Steps 1-4. (Not applicable in our implementation.) - - // Steps 5-6. - // - // |additionalFields| contains no non-enumerable properties, so we don't need - // to pass JSITER_HIDDEN. - JS::RootedVector additionalKeys(cx); - if (!GetPropertyKeys(cx, additionalFields, JSITER_OWNONLY | JSITER_SYMBOLS, - &additionalKeys)) { - return nullptr; - } - - // Steps 7-8. - mozilla::EnumSet additionalFieldKeys; - for (const auto& additionalKey : additionalKeys) { - auto field = ToTemporalField(cx, additionalKey); - if (field) { - additionalFieldKeys += *field; + // Remaining steps from CalendarResolveFields to resolve the month. + double month; + if (!ISOCalendarResolveMonth(cx, fields, &month)) { + return false; } - } - auto toIgnore = ISOFieldKeysToIgnore(additionalFieldKeys); - MOZ_ASSERT(toIgnore.contains(additionalFieldKeys)); + // Step 1.b. + int32_t referenceISOYear = 1972; - Rooted overriddenKeys(cx, PropertyHashSet(cx)); - if (!SetFromList(cx, additionalKeys.get(), overriddenKeys.get())) { - return nullptr; - } + // Step 1.c. + double year = + !fields.has(CalendarField::Year) ? referenceISOYear : fields.year(); - auto additionalFieldsToIgnore = toIgnore - additionalFieldKeys; - for (auto field : additionalFieldsToIgnore) { - auto* fieldName = ToPropertyName(cx, field); - if (!overriddenKeys.put(NameToId(fieldName))) { - return nullptr; + int32_t intYear; + if (!mozilla::NumberEqualsInt32(year, &intYear)) { + // Calendar cycles repeat every 400 years in the Gregorian calendar. + intYear = int32_t(std::fmod(year, 400)); } + + // Step 1.d. + ISODate regulated; + if (!RegulateISODate(cx, intYear, month, fields.day(), overflow, + ®ulated)) { + return false; + } + + // Step 1.e. + *result = {referenceISOYear, regulated.month, regulated.day}; + return true; } - // Step 9. - Rooted merged(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!merged) { - return nullptr; + // Step 2. + + EraYears eraYears; + if (fields.has(CalendarField::Year) || fields.has(CalendarField::EraYear)) { + if (!CalendarFieldYear(cx, calendar, fields, &eraYears)) { + return false; + } + } else { + MOZ_ASSERT(fields.has(CalendarField::MonthCode)); } - // Steps 10-11. - // - // See above why JSITER_HIDDEN isn't needed. - JS::RootedVector fieldsKeys(cx); - if (!GetPropertyKeys(cx, fields, JSITER_OWNONLY | JSITER_SYMBOLS, - &fieldsKeys)) { - return nullptr; + Month month; + if (!CalendarFieldMonth(cx, calendar, fields, overflow, &month)) { + return false; } - // Step 12. - Rooted propValue(cx); - for (size_t i = 0; i < fieldsKeys.length(); i++) { - Handle key = fieldsKeys[i]; + int32_t day; + if (!CalendarFieldDay(cx, calendar, fields, overflow, &day)) { + return false; + } - // Steps 12.a-b. - if (overriddenKeys.has(key)) { - if (!GetProperty(cx, additionalFields, additionalFields, key, - &propValue)) { - return nullptr; + auto cal = CreateICU4XCalendar(cx, calendar); + if (!cal) { + return false; + } + + // We first have to compute the month-code if it wasn't provided to us. + auto monthCode = month.code; + if (fields.has(CalendarField::Year) || fields.has(CalendarField::EraYear)) { + auto date = CreateDateFrom(cx, calendar, cal.get(), eraYears, month, day, + fields, overflow); + if (!date) { + return false; + } + + // This operation throws a RangeError if the ISO 8601 year corresponding to + // `fields.[[Year]]` is outside the valid limits. + auto isoDate = ToISODate(date.get()); + if (!ISODateWithinLimits(isoDate)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; + } + + if (!fields.has(CalendarField::MonthCode)) { + if (!CalendarDateMonthCode(cx, calendar, date.get(), &monthCode)) { + return false; + } + } + MOZ_ASSERT(monthCode != MonthCode{}); + + if (overflow == TemporalOverflow::Constrain) { + // Call into ICU4X if `day` exceeds the minimum number of days. + int32_t minDaysInMonth = CalendarDaysInMonth(calendar, monthCode).first; + if (day > minDaysInMonth) { + day = DayOfMonth(calendar, date.get()); } } else { - if (!GetProperty(cx, fields, fields, key, &propValue)) { - return nullptr; - } + MOZ_ASSERT(overflow == TemporalOverflow::Reject); + MOZ_ASSERT(day == DayOfMonth(calendar, date.get())); } + } else { + MOZ_ASSERT(monthCode != MonthCode{}); - // Step 12.c. - if (!propValue.isUndefined()) { - if (!DefineDataProperty(cx, merged, key, propValue)) { - return nullptr; + // Constrain `day` to maximum possible day of the input month. + int32_t maxDaysInMonth = CalendarDaysInMonth(calendar, monthCode).second; + if (overflow == TemporalOverflow::Constrain) { + day = std::min(day, maxDaysInMonth); + } else { + MOZ_ASSERT(overflow == TemporalOverflow::Reject); + + if (day > maxDaysInMonth) { + ReportCalendarFieldOverflow(cx, "day", day); + return false; } } } - // Step 13. - if (!CopyDataProperties(cx, merged, additionalFields)) { - return nullptr; + // Try years starting from 31 December, 1972. + constexpr auto isoReferenceDate = ISODate{1972, 12, 31}; + + auto fromIsoDate = CreateICU4XDate(cx, isoReferenceDate, calendar, cal.get()); + if (!fromIsoDate) { + return false; } - // Step 14. - return merged; + // Find the calendar year for the ISO reference date. + int32_t calendarYear; + if (!CalendarDateYear(cx, calendar, fromIsoDate.get(), &calendarYear)) { + return false; + } + + // 10'000 is sufficient to find all possible month-days, even for rare cases + // like `{calendar: "chinese", monthCode: "M09L", day: 30}`. + constexpr size_t maxIterations = 10'000; + + UniqueICU4XDate date; + for (size_t i = 0; i < maxIterations; i++) { + // This loop can run for a long time. + if (!CheckForInterrupt(cx)) { + return false; + } + + auto candidateYear = CalendarEraYear(calendar, calendarYear); + + auto result = + CreateDateFromCodes(calendar, cal.get(), candidateYear, monthCode, day); + if (result.isOk()) { + // Make sure the resolved date is before December 31, 1972. + auto isoDate = ToISODate(result.inspect().get()); + if (isoDate.year > isoReferenceDate.year) { + calendarYear -= 1; + continue; + } + + date = result.unwrap(); + break; + } + + switch (result.inspectErr()) { + case CalendarError::UnknownMonthCode: { + MOZ_ASSERT(CalendarHasLeapMonths(calendar)); + MOZ_ASSERT(monthCode.isLeapMonth()); + + // Try the next candidate year if the requested leap month doesn't + // occur in the current year. + calendarYear -= 1; + continue; + } + + case CalendarError::Overflow: { + // ICU4X throws an overflow error when: + // 1. month > monthsInYear(year), or + // 2. days > daysInMonthOf(year, month). + // + // Case 1 can't happen for month-codes, so it doesn't apply here. + // Case 2 can only happen when |day| is larger than the minimum number + // of days in the month. + MOZ_ASSERT(day > CalendarDaysInMonth(calendar, monthCode).first); + + // Try next candidate year to find an earlier year which can fulfill + // the input request. + calendarYear -= 1; + continue; + } + + case CalendarError::OutOfRange: + case CalendarError::Underflow: + case CalendarError::UnknownEra: + MOZ_ASSERT(false, "unexpected calendar error"); + break; + + case CalendarError::Generic: + break; + } + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return false; + } + + // We shouldn't end up here with |maxIterations == 10'000|, but just in case + // still handle this case and report an error. + if (!date) { + ReportCalendarFieldOverflow(cx, "day", day); + return false; + } + + // |month| and |monthCode| must be consistent. + if (month.code != MonthCode{} && month.ordinal > 0) { + if (!CalendarFieldMonthCodeMatchesMonth(cx, calendar, fields, date.get(), + month.ordinal)) { + return false; + } + } + + *result = ToISODate(date.get()); + return true; +} + +enum class FieldType { Date, YearMonth, MonthDay }; + +/** + * CalendarResolveFields ( calendar, fields, type ) + */ +static bool CalendarResolveFields(JSContext* cx, CalendarId calendar, + Handle fields, + FieldType type) { + // Step 1. + if (calendar == CalendarId::ISO8601) { + // Steps 1.a-e. + const char* missingField = nullptr; + if ((type == FieldType::Date || type == FieldType::YearMonth) && + !fields.has(CalendarField::Year)) { + missingField = "year"; + } else if ((type == FieldType::Date || type == FieldType::MonthDay) && + !fields.has(CalendarField::Day)) { + missingField = "day"; + } else if (!fields.has(CalendarField::MonthCode) && + !fields.has(CalendarField::Month)) { + missingField = "month"; + } + + if (missingField) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_MISSING_FIELD, + missingField); + return false; + } + + // Steps 1.f-n. (Handled in ISOCalendarResolveMonth.) + + return true; + } + + // Step 2. + + // Date and Month-Day require |day| to be present. + bool requireDay = type == FieldType::Date || type == FieldType::MonthDay; + + // Date and Year-Month require |year| (or |eraYear|) to be present. + // Month-Day requires |year| (or |eraYear|) if |monthCode| is absent. + bool requireYear = type == FieldType::Date || type == FieldType::YearMonth || + !fields.has(CalendarField::MonthCode); + + // Determine if any calendar fields are missing. + const char* missingField = nullptr; + if (!fields.has(CalendarField::MonthCode) && + !fields.has(CalendarField::Month)) { + // |monthCode| or |month| must be present. + missingField = "monthCode"; + } else if (requireDay && !fields.has(CalendarField::Day)) { + missingField = "day"; + } else if (!CalendarEraRelevant(calendar)) { + if (requireYear && !fields.has(CalendarField::Year)) { + missingField = "year"; + } + } else { + if (fields.has(CalendarField::Era) != fields.has(CalendarField::EraYear)) { + // |era| and |eraYear| must either both be present or both absent. + missingField = fields.has(CalendarField::Era) ? "eraYear" : "era"; + } else if (requireYear && !fields.has(CalendarField::EraYear) && + !fields.has(CalendarField::Year)) { + missingField = "eraYear"; + } + } + + if (missingField) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_MISSING_FIELD, + missingField); + return false; + } + + return true; } /** - * CalendarMergeFields ( calendarRec, fields, additionalFields ) + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[Era]] field. */ -JSObject* js::temporal::CalendarMergeFields( - JSContext* cx, Handle calendar, Handle fields, - Handle additionalFields) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::MergeFields)); +bool js::temporal::CalendarEra(JSContext* cx, Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); - // Step 2. (Reordered) - auto mergeFields = calendar.mergeFields(); - if (!mergeFields) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarMergeFields(cx, calendarId, fields, additionalFields); + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setUndefined(); + return true; } - // Step 1. (Inlined call to CalendarMethodsRecordCall.) + // Step 2. + if (!CalendarEraRelevant(calendarId)) { + result.setUndefined(); + return true; + } - Rooted mergeFieldsFn(cx, ObjectValue(*mergeFields)); - auto thisv = calendar.receiver().toObjectValue(); - Rooted result(cx); + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } - FixedInvokeArgs<2> args(cx); - args[0].setObject(*fields); - args[1].setObject(*additionalFields); + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } - if (!Call(cx, mergeFieldsFn, thisv, args, &result)) { - return nullptr; + EraCode era; + if (!CalendarDateEra(cx, calendarId, dt.get(), &era)) { + return false; + } + + auto* str = NewStringCopy(cx, CalendarEraName(calendarId, era)); + if (!str) { + return false; + } + + result.setString(str); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[EraYear]] field. + */ +bool js::temporal::CalendarEraYear(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setUndefined(); + return true; + } + + // Step 2. + if (!CalendarEraRelevant(calendarId)) { + result.setUndefined(); + return true; + } + + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t year = capi::ICU4XDate_year_in_era(dt.get()); + result.setInt32(year); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[Year]] field. + */ +bool js::temporal::CalendarYear(JSContext* cx, Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(date.year); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t year; + if (!CalendarDateYear(cx, calendarId, dt.get(), &year)) { + return false; + } + + result.setInt32(year); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[Month]] field. + */ +bool js::temporal::CalendarMonth(JSContext* cx, Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(date.month); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t month = OrdinalMonth(calendarId, dt.get()); + result.setInt32(month); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[MonthCode]] field. + */ +bool js::temporal::CalendarMonthCode(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + // Steps 1.a-b. + auto monthCode = MonthCode{date.month}; + JSString* str = NewStringCopy(cx, std::string_view{monthCode}); + if (!str) { + return false; + } + + result.setString(str); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + MonthCode monthCode; + if (!CalendarDateMonthCode(cx, calendarId, dt.get(), &monthCode)) { + return false; + } + + auto* str = NewStringCopy(cx, std::string_view{monthCode}); + if (!str) { + return false; + } + + result.setString(str); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[Day]] field. + */ +bool js::temporal::CalendarDay(JSContext* cx, Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(date.day); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t day = DayOfMonth(calendarId, dt.get()); + result.setInt32(day); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[DayOfWeek]] field. + */ +bool js::temporal::CalendarDayOfWeek(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(ISODayOfWeek(date)); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + // Week day codes are correctly ordered. + static_assert(capi::ICU4XIsoWeekday_Monday == 1); + static_assert(capi::ICU4XIsoWeekday_Tuesday == 2); + static_assert(capi::ICU4XIsoWeekday_Wednesday == 3); + static_assert(capi::ICU4XIsoWeekday_Thursday == 4); + static_assert(capi::ICU4XIsoWeekday_Friday == 5); + static_assert(capi::ICU4XIsoWeekday_Saturday == 6); + static_assert(capi::ICU4XIsoWeekday_Sunday == 7); + + capi::ICU4XIsoWeekday day = capi::ICU4XDate_day_of_week(dt.get()); + result.setInt32(static_cast(day)); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[DayOfYear]] field. + */ +bool js::temporal::CalendarDayOfYear(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(ISODayOfYear(date)); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + // Workaround for https://github.com/unicode-org/icu4x/issues/5655 + if (calendarId == CalendarId::Japanese) { + // Use the extended year instead of the era year to correctly handle the + // case when the era changes in the current year. This can happen in the + // Japanese calendar. + int32_t year; + if (!CalendarDateYear(cx, calendarId, dt.get(), &year)) { + return false; + } + auto eraYear = CalendarEraYear(calendarId, year); + + int32_t dayOfYear = DayOfMonth(calendarId, dt.get()); + int32_t month = OrdinalMonth(calendarId, dt.get()); + + // Add the number of days of all preceding months to compute the overall day + // of the year. + while (month > 1) { + auto previousMonth = CreateDateFrom(cx, calendarId, cal.get(), eraYear, + --month, 1, TemporalOverflow::Reject); + if (!previousMonth) { + return false; + } + + dayOfYear += DaysInMonth(previousMonth.get()); + } + + MOZ_ASSERT(dayOfYear <= DaysInYear(dt.get())); + + result.setInt32(dayOfYear); + return true; + } + + int32_t day = DayOfYear(dt.get()); + result.setInt32(day); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[WeekOfYear]].[[Week]] field. + */ +bool js::temporal::CalendarWeekOfYear(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(ISOWeekOfYear(date).week); + return true; + } + + // Step 2. + + // Non-Gregorian calendars don't get week-of-year support for now. + // + // https://github.com/tc39/proposal-intl-era-monthcode/issues/15 + if (calendarId != CalendarId::Gregorian) { + result.setUndefined(); + return true; + } + + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + auto weekCal = CreateICU4WeekCalculator(cx, calendarId); + if (!weekCal) { + return false; + } + + auto week = capi::ICU4XDate_week_of_year(dt.get(), weekCal.get()); + if (!week.is_ok) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return false; + } + + result.setInt32(week.ok.week); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[WeekOfYear]].[[Year]] field. + */ +bool js::temporal::CalendarYearOfWeek(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(ISOWeekOfYear(date).year); + return true; + } + + // Step 2. + + // Non-Gregorian calendars don't get week-of-year support for now. + // + // https://github.com/tc39/proposal-intl-era-monthcode/issues/15 + if (calendarId != CalendarId::Gregorian) { + result.setUndefined(); + return true; + } + + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + auto weekCal = CreateICU4WeekCalculator(cx, calendarId); + if (!weekCal) { + return false; + } + + auto week = capi::ICU4XDate_week_of_year(dt.get(), weekCal.get()); + if (!week.is_ok) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR); + return false; + } + + int32_t relative = 0; + switch (week.ok.unit) { + case capi::ICU4XWeekRelativeUnit_Previous: + relative = -1; + break; + case capi::ICU4XWeekRelativeUnit_Current: + relative = 0; + break; + case capi::ICU4XWeekRelativeUnit_Next: + relative = 1; + break; + } + + int32_t calendarYear; + if (!CalendarDateYear(cx, calendarId, dt.get(), &calendarYear)) { + return false; + } + + result.setInt32(calendarYear + relative); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[DaysInWeek]] field. + */ +bool js::temporal::CalendarDaysInWeek(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + // All supported ICU4X calendars use a 7-day week and so does the ISO 8601 + // calendar. + // + // This function isn't supported through the ICU4X FFI, so we have to + // hardcode the result. + + // Step 1-2. + result.setInt32(7); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[DaysInMonth]] field. + */ +bool js::temporal::CalendarDaysInMonth(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(::ISODaysInMonth(date.year, date.month)); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t days = DaysInMonth(dt.get()); + result.setInt32(days); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[DaysInYear]] field. + */ +bool js::temporal::CalendarDaysInYear(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(ISODaysInYear(date.year)); + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t days = DaysInYear(dt.get()); + result.setInt32(days); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[MonthsInYear]] field. + */ +bool js::temporal::CalendarMonthsInYear(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setInt32(12); + return true; + } + + // Step 2 + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + int32_t months = MonthsInYear(dt.get()); + result.setInt32(months); + return true; +} + +/** + * CalendarISOToDate ( calendar, isoDate ) + * + * Return the Calendar Date Record's [[InLeapYear]] field. + */ +bool js::temporal::CalendarInLeapYear(JSContext* cx, + Handle calendar, + const ISODate& date, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (calendarId == CalendarId::ISO8601) { + result.setBoolean(IsISOLeapYear(date.year)); + return true; + } + + // Step 2. + + // FIXME: Not supported in ICU4X. + // + // https://github.com/unicode-org/icu4x/issues/5654 + + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + bool inLeapYear = false; + switch (calendarId) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Gregorian: + case CalendarId::Japanese: + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Indian: + case CalendarId::Persian: + case CalendarId::ROC: { + MOZ_ASSERT(!CalendarHasLeapMonths(calendarId)); + + // Solar calendars have either 365 or 366 days per year. + int32_t days = DaysInYear(dt.get()); + MOZ_ASSERT(days == 365 || days == 366); + + // Leap years have 366 days. + inLeapYear = days == 366; + break; + } + + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: { + MOZ_ASSERT(!CalendarHasLeapMonths(calendarId)); + + // Lunar Islamic calendars have either 354 or 355 days per year. + // + // Allow 353 days to workaround + // . + int32_t days = DaysInYear(dt.get()); + MOZ_ASSERT(days == 353 || days == 354 || days == 355); + + // Leap years have 355 days. + inLeapYear = days == 355; + break; + } + + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::Hebrew: { + MOZ_ASSERT(CalendarHasLeapMonths(calendarId)); + + // Calendars with separate leap months have either 12 or 13 months per + // year. + int32_t months = MonthsInYear(dt.get()); + MOZ_ASSERT(months == 12 || months == 13); + + // Leap years have 13 months. + inLeapYear = months == 13; + break; + } + } + + result.setBoolean(inLeapYear); + return true; +} + +enum class DateFieldType { Date, YearMonth, MonthDay }; + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +static bool ISODateToFields(JSContext* cx, Handle calendar, + const ISODate& date, DateFieldType type, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + result.set(CalendarFields{}); + + // Steps 2-6. (Optimization for the ISO 8601 calendar.) + if (calendarId == CalendarId::ISO8601) { + // Step 2. (Not applicable in our implementation.) + + // Step 3. + result.setMonthCode(MonthCode{date.month}); + + // Step 4. + if (type == DateFieldType::MonthDay || type == DateFieldType::Date) { + result.setDay(date.day); + } + + // Step 5. + if (type == DateFieldType::YearMonth || type == DateFieldType::Date) { + result.setYear(date.year); + } + + // Step 6. + return true; + } + + // Step 2. + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; + } + + auto dt = CreateICU4XDate(cx, date, calendarId, cal.get()); + if (!dt) { + return false; + } + + // Step 3. + MonthCode monthCode; + if (!CalendarDateMonthCode(cx, calendarId, dt.get(), &monthCode)) { + return false; + } + result.setMonthCode(monthCode); + + // Step 4. + if (type == DateFieldType::MonthDay || type == DateFieldType::Date) { + int32_t day = DayOfMonth(calendarId, dt.get()); + result.setDay(day); + } + + // Step 5. + if (type == DateFieldType::YearMonth || type == DateFieldType::Date) { + int32_t year; + if (!CalendarDateYear(cx, calendarId, dt.get(), &year)) { + return false; + } + result.setYear(year); + } + + // Step 6. + return true; +} + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool js::temporal::ISODateToFields(JSContext* cx, Handle date, + MutableHandle result) { + return ISODateToFields(cx, date.calendar(), date, DateFieldType::Date, + result); +} + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool js::temporal::ISODateToFields(JSContext* cx, + Handle dateTime, + MutableHandle result) { + return ISODateToFields(cx, dateTime.calendar(), dateTime.date(), + DateFieldType::Date, result); +} + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool js::temporal::ISODateToFields(JSContext* cx, + Handle monthDay, + MutableHandle result) { + return ISODateToFields(cx, monthDay.calendar(), monthDay.date(), + DateFieldType::MonthDay, result); +} + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool js::temporal::ISODateToFields(JSContext* cx, + Handle yearMonth, + MutableHandle result) { + return ISODateToFields(cx, yearMonth.calendar(), yearMonth.date(), + DateFieldType::YearMonth, result); +} + +/** + * CalendarDateFromFields ( calendar, fields, overflow ) + */ +bool js::temporal::CalendarDateFromFields(JSContext* cx, + Handle calendar, + Handle fields, + TemporalOverflow overflow, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (!CalendarResolveFields(cx, calendarId, fields, FieldType::Date)) { + return false; + } + + // Step 2. + ISODate date; + if (!CalendarDateToISO(cx, calendarId, fields, overflow, &date)) { + return false; } // Steps 3-4. - return RequireObject(cx, result); + return CreateTemporalDate(cx, date, calendar, result); } /** - * Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) + * CalendarYearMonthFromFields ( calendar, fields, overflow ) */ -static bool BuiltinCalendarAdd(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - const NormalizedDuration& duration, - Handle options, PlainDate* result) { - MOZ_ASSERT(IsValidISODate(date)); +bool js::temporal::CalendarYearMonthFromFields( + JSContext* cx, Handle calendar, + Handle fields, TemporalOverflow overflow, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (!CalendarResolveFields(cx, calendarId, fields, FieldType::YearMonth)) { + return false; + } + + // Step 2. + int32_t firstDayIndex = 1; + + // Step 3. + Rooted resolvedFields(cx, CalendarFields{fields}); + resolvedFields.setDay(firstDayIndex); + + // Step 4. + ISODate date; + if (!CalendarDateToISO(cx, calendarId, resolvedFields, overflow, &date)) { + return false; + } + + // Steps 5-6. + return CreateTemporalYearMonth(cx, date, calendar, result); +} + +/** + * CalendarMonthDayFromFields ( calendar, fields, overflow ) + */ +bool js::temporal::CalendarMonthDayFromFields( + JSContext* cx, Handle calendar, + Handle fields, TemporalOverflow overflow, + MutableHandle result) { + auto calendarId = calendar.identifier(); + + // Step 1. + if (!CalendarResolveFields(cx, calendarId, fields, FieldType::MonthDay)) { + return false; + } + + // Step 2. + ISODate date; + if (!CalendarMonthDayToISOReferenceDate(cx, calendarId, fields, overflow, + &date)) { + return false; + } + + // Step 3-4. + return CreateTemporalMonthDay(cx, date, calendar, result); +} + +/** + * Mathematical Operations, "modulo" notation. + */ +static int32_t NonNegativeModulo(int64_t x, int32_t y) { + MOZ_ASSERT(y > 0); + + int32_t result = mozilla::AssertedCast(x % y); + return (result < 0) ? (result + y) : result; +} + +/** + * RegulateISODate ( year, month, day, overflow ) + * + * With |overflow = "constrain"|. + */ +static ISODate ConstrainISODate(const ISODate& date) { + const auto& [year, month, day] = date; + + // Step 1.a. + int32_t m = std::clamp(month, 1, 12); + + // Step 1.b. + int32_t daysInMonth = ::ISODaysInMonth(year, m); + + // Step 1.c. + int32_t d = std::clamp(day, 1, daysInMonth); + + // Step 3. + return {year, m, d}; +} + +/** + * RegulateISODate ( year, month, day, overflow ) + */ +static bool RegulateISODate(JSContext* cx, const ISODate& date, + TemporalOverflow overflow, ISODate* result) { + // Step 1. + if (overflow == TemporalOverflow::Constrain) { + // Steps 1.a-c and 3. + *result = ConstrainISODate(date); + return true; + } + + // Step 2.a. + MOZ_ASSERT(overflow == TemporalOverflow::Reject); + + // Step 2.b. + if (!ThrowIfInvalidISODate(cx, date)) { + return false; + } + + // Step 3. (Inlined call to CreateISODateRecord.) + *result = date; + return true; +} + +struct BalancedYearMonth final { + int64_t year = 0; + int32_t month = 0; +}; + +/** + * BalanceISOYearMonth ( year, month ) + */ +static BalancedYearMonth BalanceISOYearMonth(int64_t year, int64_t month) { + MOZ_ASSERT(std::abs(year) < (int64_t(1) << 33), + "year is the addition of plain-date year with duration years"); + MOZ_ASSERT(std::abs(month) < (int64_t(1) << 33), + "month is the addition of plain-date month with duration months"); + + // Step 1. (Not applicable in our implementation.) + + // Step 2. + int64_t balancedYear = year + temporal::FloorDiv(month - 1, 12); + + // Step 3. + int32_t balancedMonth = NonNegativeModulo(month - 1, 12) + 1; + MOZ_ASSERT(1 <= balancedMonth && balancedMonth <= 12); + + // Step 4. + return {balancedYear, balancedMonth}; +} + +static BalancedYearMonth BalanceYearMonth(int64_t year, int64_t month, + int32_t monthsPerYear) { + MOZ_ASSERT(std::abs(year) < (int64_t(1) << 33), + "year is the addition of plain-date year with duration years"); + MOZ_ASSERT(std::abs(month) < (int64_t(1) << 33), + "month is the addition of plain-date month with duration months"); + + int64_t balancedYear = year + temporal::FloorDiv(month - 1, monthsPerYear); + + int32_t balancedMonth = NonNegativeModulo(month - 1, monthsPerYear) + 1; + MOZ_ASSERT(1 <= balancedMonth && balancedMonth <= monthsPerYear); + + return {balancedYear, balancedMonth}; +} + +/** + * CalendarDateAdd ( calendar, isoDate, duration, overflow ) + */ +static bool AddISODate(JSContext* cx, const ISODate& isoDate, + const DateDuration& duration, TemporalOverflow overflow, + ISODate* result) { + MOZ_ASSERT(ISODateWithinLimits(isoDate)); MOZ_ASSERT(IsValidDuration(duration)); - // Steps 1-5. (Not applicable) + // Step 1.a. + auto yearMonth = BalanceISOYearMonth(isoDate.year + duration.years, + isoDate.month + duration.months); + MOZ_ASSERT(1 <= yearMonth.month && yearMonth.month <= 12); - // Step 6. - auto overflow = TemporalOverflow::Constrain; - if (options) { - if (!GetTemporalOverflowOption(cx, options, &overflow)) { + auto balancedYear = mozilla::CheckedInt(yearMonth.year); + if (!balancedYear.isValid()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; + } + + // Step 1.b. + ISODate regulated; + if (!RegulateISODate(cx, {balancedYear.value(), yearMonth.month, isoDate.day}, + overflow, ®ulated)) { + return false; + } + if (!ISODateWithinLimits(regulated)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; + } + + // Step 1.c. + int64_t days = duration.days + duration.weeks * 7; + + // Step 1.d. + ISODate balanced; + if (!BalanceISODate(cx, regulated, days, &balanced)) { + return false; + } + MOZ_ASSERT(IsValidISODate(balanced)); + + *result = balanced; + return true; +} + +struct CalendarDate { + int32_t year = 0; + MonthCode monthCode = {}; + int32_t day = 0; +}; + +/** + * CompareISODate adjusted for calendar dates. + */ +static int32_t CompareCalendarDate(const CalendarDate& one, + const CalendarDate& two) { + if (one.year != two.year) { + return one.year < two.year ? -1 : 1; + } + if (one.monthCode != two.monthCode) { + return one.monthCode < two.monthCode ? -1 : 1; + } + if (one.day != two.day) { + return one.day < two.day ? -1 : 1; + } + return 0; +} + +static bool ToCalendarDate(JSContext* cx, CalendarId calendarId, + const capi::ICU4XDate* dt, CalendarDate* result) { + int32_t year; + if (!CalendarDateYear(cx, calendarId, dt, &year)) { + return false; + } + + MonthCode monthCode; + if (!CalendarDateMonthCode(cx, calendarId, dt, &monthCode)) { + return false; + } + + int32_t day = DayOfMonth(calendarId, dt); + + *result = {year, monthCode, day}; + return true; +} + +/** + * Store a calendar date in a |ISODate| struct when leap months don't matter. + */ +static bool ToCalendarDate(JSContext* cx, CalendarId calendarId, + const capi::ICU4XDate* dt, ISODate* result) { + MOZ_ASSERT(!CalendarHasLeapMonths(calendarId)); + + int32_t year; + if (!CalendarDateYear(cx, calendarId, dt, &year)) { + return false; + } + + int32_t month = OrdinalMonth(calendarId, dt); + int32_t day = DayOfMonth(calendarId, dt); + + *result = {year, month, day}; + return true; +} + +static bool AddYearMonthDuration(JSContext* cx, CalendarId calendarId, + const ISODate& calendarDate, + const DateDuration& duration, + CalendarDate* result) { + MOZ_ASSERT(!CalendarHasLeapMonths(calendarId)); + MOZ_ASSERT(IsValidDuration(duration)); + + auto [year, month, day] = calendarDate; + + // Months per year are fixed, so we can directly compute the final number of + // years. + auto yearMonth = + BalanceYearMonth(year + duration.years, month + duration.months, + CalendarMonthsPerYear(calendarId)); + + auto balancedYear = mozilla::CheckedInt(yearMonth.year); + if (!balancedYear.isValid()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; + } + + *result = {balancedYear.value(), MonthCode{yearMonth.month}, day}; + return true; +} + +static bool AddYearMonthDuration(JSContext* cx, CalendarId calendarId, + const capi::ICU4XCalendar* calendar, + const CalendarDate& calendarDate, + const DateDuration& duration, + CalendarDate* result) { + MOZ_ASSERT(CalendarHasLeapMonths(calendarId)); + MOZ_ASSERT(IsValidDuration(duration)); + + auto [year, monthCode, day] = calendarDate; + + // Add all duration years. + auto durationYear = mozilla::CheckedInt(year) + duration.years; + if (!durationYear.isValid()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; + } + year = durationYear.value(); + + // Months per year are variable, so we have construct a new date for each + // year to balance the years and months. + int64_t months = duration.months; + if (months != 0) { + auto eraYear = CalendarEraYear(calendarId, year); + auto firstDayOfMonth = + CreateDateFromCodes(cx, calendarId, calendar, eraYear, monthCode, 1, + TemporalOverflow::Constrain); + if (!firstDayOfMonth) { + return false; + } + + if (months > 0) { + while (true) { + // Check if adding |months| is still in the current year. + int32_t month = OrdinalMonth(calendarId, firstDayOfMonth.get()); + int32_t monthsInYear = MonthsInYear(firstDayOfMonth.get()); + if (month + months <= monthsInYear) { + break; + } + + // We've crossed a year boundary. Increase |year| and adjust |months|. + year += 1; + months -= (monthsInYear - month + 1); + + // Restart the loop with the first month of the next year. + eraYear = CalendarEraYear(calendarId, year); + firstDayOfMonth = CreateDateFrom(cx, calendarId, calendar, eraYear, 1, + 1, TemporalOverflow::Constrain); + if (!firstDayOfMonth) { + return false; + } + } + } else { + int32_t monthsPerYear = CalendarMonthsPerYear(calendarId); + + while (true) { + // Check if subtracting |months| is still in the current year. + int32_t month = OrdinalMonth(calendarId, firstDayOfMonth.get()); + if (month + months >= 1) { + break; + } + + // We've crossed a year boundary. Decrease |year| and adjust |months|. + year -= 1; + months += month; + + // Restart the loop with the last month of the previous year. + eraYear = CalendarEraYear(calendarId, year); + firstDayOfMonth = + CreateDateFrom(cx, calendarId, calendar, eraYear, monthsPerYear, 1, + TemporalOverflow::Constrain); + if (!firstDayOfMonth) { + return false; + } + } + } + + // Compute the actual month to find the correct month code. + int32_t month = OrdinalMonth(calendarId, firstDayOfMonth.get()) + months; + firstDayOfMonth = CreateDateFrom(cx, calendarId, calendar, eraYear, month, + 1, TemporalOverflow::Constrain); + if (!firstDayOfMonth) { + return false; + } + + if (!CalendarDateMonthCode(cx, calendarId, firstDayOfMonth.get(), + &monthCode)) { return false; } } - // Step 7. - const auto& timeDuration = duration.time; - - // Step 8. - auto balanceResult = BalanceTimeDuration(timeDuration, TemporalUnit::Day); - - auto addDuration = DateDuration{ - duration.date.years, - duration.date.months, - duration.date.weeks, - duration.date.days + balanceResult.days, - }; - return AddISODate(cx, date, addDuration, overflow, result); + *result = {year, monthCode, day}; + return true; } -/** - * Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) - */ -static bool BuiltinCalendarAdd(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - const DateDuration& duration, - Handle options, PlainDate* result) { - // Steps 1-5. (Not applicable) +static bool AddNonISODate(JSContext* cx, CalendarId calendarId, + const ISODate& isoDate, const DateDuration& duration, + TemporalOverflow overflow, ISODate* result) { + MOZ_ASSERT(ISODateWithinLimits(isoDate)); + MOZ_ASSERT(IsValidDuration(duration)); - // Step 7. (Reordered) - auto normalized = CreateNormalizedDurationRecord(duration, {}); - - // Steps 6 and 8-10. - return BuiltinCalendarAdd(cx, calendarId, date, normalized, options, result); -} - -/** - * Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) - */ -static PlainDateObject* BuiltinCalendarAdd(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - const DateDuration& duration, - Handle options) { - // Steps 1-10. - PlainDate result; - if (!BuiltinCalendarAdd(cx, calendarId, date, duration, options, &result)) { - return nullptr; + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { + return false; } - // Step 11. - Rooted calendar(cx, CalendarValue(calendarId)); - return CreateTemporalDate(cx, result, calendar); -} - -/** - * Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) - */ -static PlainDateObject* BuiltinCalendarAdd(JSContext* cx, CalendarId calendarId, - const PlainDate& date, - const Duration& duration, - Handle options) { - // Steps 1-5. (Not applicable) - - // Step 7. (Reordered) - auto normalized = CreateNormalizedDurationRecord(duration); - - // Steps 6 and 8-10. - PlainDate result; - if (!BuiltinCalendarAdd(cx, calendarId, date, normalized, options, &result)) { - return nullptr; + auto dt = CreateICU4XDate(cx, isoDate, calendarId, cal.get()); + if (!dt) { + return false; } - // Step 11. - Rooted calendar(cx, CalendarValue(calendarId)); - return CreateTemporalDate(cx, result, calendar); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -static Wrapped CalendarDateAddSlow( - JSContext* cx, Handle calendar, - Handle> date, - Handle> duration, Handle options) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - MOZ_ASSERT(calendar.receiver().isObject()); - MOZ_ASSERT(calendar.dateAdd()); - - // Step 1. (Not applicable). - - // Step 2. (Inlined call to CalendarMethodsRecordCall.) - Rooted dateAdd(cx, ObjectValue(*calendar.dateAdd())); - auto thisv = calendar.receiver().toObjectValue(); - Rooted rval(cx); - - FixedInvokeArgs<3> args(cx); - args[0].setObject(*date); - args[1].setObject(*duration); - if (options) { - args[2].setObject(*options); + CalendarDate calendarDate; + if (!CalendarHasLeapMonths(calendarId)) { + ISODate date; + if (!ToCalendarDate(cx, calendarId, dt.get(), &date)) { + return false; + } + if (!AddYearMonthDuration(cx, calendarId, date, duration, &calendarDate)) { + return false; + } } else { - args[2].setUndefined(); + CalendarDate date; + if (!ToCalendarDate(cx, calendarId, dt.get(), &date)) { + return false; + } + if (!AddYearMonthDuration(cx, calendarId, cal.get(), date, duration, + &calendarDate)) { + return false; + } } - if (!Call(cx, dateAdd, thisv, args, &rval)) { - return nullptr; + // Regulate according to |overflow|. + auto eraYear = CalendarEraYear(calendarId, calendarDate.year); + auto regulated = + CreateDateFromCodes(cx, calendarId, cal.get(), eraYear, + calendarDate.monthCode, calendarDate.day, overflow); + if (!regulated) { + return false; } - // Step 3. (Not applicable) - MOZ_ASSERT(!CalendarMethodsRecordIsBuiltin(calendar)); - - // Step 4. - if (!rval.isObject() || !rval.toObject().canUnwrapAs()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, rval, - nullptr, "not a PlainDate object"); - return nullptr; + // Compute the corresponding ISO date. + auto regulatedIso = ToISODate(regulated.get()); + if (!ISODateWithinLimits(regulatedIso)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); + return false; } - // Step 5. - return &rval.toObject(); + // Add duration days and weeks. + int64_t days = duration.days + duration.weeks * 7; + + // Adding days isn't calendar-specific, so we can use BalanceISODate. + ISODate balancedIso; + if (!BalanceISODate(cx, regulatedIso, days, &balancedIso)) { + return false; + } + MOZ_ASSERT(IsValidISODate(balancedIso)); + + *result = balancedIso; + return true; } -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -static Wrapped CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, const Duration& duration, - Handle options) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 1. (Not applicable). - - // Step 3. (Reordered) - if (!calendar.dateAdd()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - - auto* unwrappedDate = date.unwrap(cx); - if (!unwrappedDate) { - return nullptr; - } - auto date = ToPlainDate(unwrappedDate); - - return BuiltinCalendarAdd(cx, calendarId, date, duration, options); - } - - // Steps 2 and 4-5. - Rooted durationObj(cx, CreateTemporalDuration(cx, duration)); - if (!durationObj) { - return nullptr; - } - return CalendarDateAddSlow(cx, calendar, date, durationObj, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -static Wrapped CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, const DateDuration& duration, - Handle options) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 1. (Not applicable). - - // Step 3. (Reordered) - if (!calendar.dateAdd()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - - auto* unwrappedDate = date.unwrap(cx); - if (!unwrappedDate) { - return nullptr; - } - auto date = ToPlainDate(unwrappedDate); - - return BuiltinCalendarAdd(cx, calendarId, date, duration, options); - } - - // Steps 2 and 4-5. - Rooted durationObj( - cx, CreateTemporalDuration(cx, duration.toDuration())); - if (!durationObj) { - return nullptr; - } - return CalendarDateAddSlow(cx, calendar, date, durationObj, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -static Wrapped CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, - Handle> duration, Handle options) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 1. (Not applicable). - - // Step 3. (Reordered) - if (!calendar.dateAdd()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - - auto* unwrappedDate = date.unwrap(cx); - if (!unwrappedDate) { - return nullptr; - } - auto date = ToPlainDate(unwrappedDate); - - auto* unwrappedDuration = duration.unwrap(cx); - if (!unwrappedDuration) { - return nullptr; - } - auto duration = ToDuration(unwrappedDuration); - - return BuiltinCalendarAdd(cx, calendarId, date, duration, options); - } - - // Steps 2 and 4-5. - return CalendarDateAddSlow(cx, calendar, date, duration, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -static bool CalendarDateAdd(JSContext* cx, Handle calendar, - Handle> date, +static bool AddCalendarDate(JSContext* cx, CalendarId calendarId, + const ISODate& isoDate, const DateDuration& duration, - Handle options, PlainDate* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); + TemporalOverflow overflow, ISODate* result) { + // ICU4X doesn't yet provide a public API for CalendarDateAdd. + // + // https://github.com/unicode-org/icu4x/issues/3964 - // Step 1. (Not applicable). + // If neither |years| nor |months| are present, just delegate to the ISO 8601 + // calendar version. This works because all supported calendars use a 7-days + // week. + if (duration.years == 0 && duration.months == 0) { + return AddISODate(cx, isoDate, duration, overflow, result); + } - // Step 3. (Reordered) - if (!calendar.dateAdd()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); + switch (calendarId) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Gregorian: + case CalendarId::Japanese: + case CalendarId::ROC: + // Use the ISO 8601 calendar if the calendar system starts its year at the + // same time as the ISO 8601 calendar and all months exactly match the + // ISO 8601 calendar months. + return AddISODate(cx, isoDate, duration, overflow, result); - auto* unwrappedDate = date.unwrap(cx); - if (!unwrappedDate) { + case CalendarId::Chinese: + case CalendarId::Coptic: + case CalendarId::Dangi: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: + return AddNonISODate(cx, calendarId, isoDate, duration, overflow, result); + } + MOZ_CRASH("invalid calendar id"); +} + +/** + * CalendarDateAdd ( calendar, isoDate, duration, overflow ) + */ +bool js::temporal::CalendarDateAdd(JSContext* cx, + Handle calendar, + const ISODate& isoDate, + const DateDuration& duration, + TemporalOverflow overflow, ISODate* result) { + MOZ_ASSERT(ISODateWithinLimits(isoDate)); + MOZ_ASSERT(IsValidDuration(duration)); + + auto calendarId = calendar.identifier(); + + // Steps 1-2. + if (calendarId == CalendarId::ISO8601) { + if (!AddISODate(cx, isoDate, duration, overflow, result)) { + return false; + } + } else { + if (!AddCalendarDate(cx, calendarId, isoDate, duration, overflow, result)) { return false; } - auto date = ToPlainDate(unwrappedDate); - - return BuiltinCalendarAdd(cx, calendarId, date, duration, options, result); } - // Steps 2 and 4-5. - - Rooted durationObj( - cx, CreateTemporalDuration(cx, duration.toDuration())); - if (!durationObj) { + // Step 3. + if (!ISODateWithinLimits(*result)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return false; } - auto obj = CalendarDateAddSlow(cx, calendar, date, durationObj, options); - if (!obj) { - return false; - } - - *result = ToPlainDate(&obj.unwrap()); + // Step 4. return true; } /** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) + * CalendarDateUntil ( calendar, one, two, largestUnit ) */ -static bool CalendarDateAdd(JSContext* cx, Handle calendar, - const PlainDate& date, const DateDuration& duration, - Handle options, PlainDate* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); +static DateDuration DifferenceISODate(const ISODate& one, const ISODate& two, + TemporalUnit largestUnit) { + MOZ_ASSERT(IsValidISODate(one)); + MOZ_ASSERT(IsValidISODate(two)); - // Step 1. (Not applicable). + // Both inputs are also within the date limits. + MOZ_ASSERT(ISODateWithinLimits(one)); + MOZ_ASSERT(ISODateWithinLimits(two)); - // Step 3. (Reordered) - if (!calendar.dateAdd()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarAdd(cx, calendarId, date, duration, options, result); + MOZ_ASSERT(TemporalUnit::Year <= largestUnit && + largestUnit <= TemporalUnit::Day); + + // Step 1.a. + int32_t sign = -CompareISODate(one, two); + + // Step 1.b. + if (sign == 0) { + return {}; } - // Steps 2 and 4-5. + // Step 1.c. + int32_t years = 0; - Rooted dateObj( - cx, CreateTemporalDate(cx, date, calendar.receiver())); - if (!dateObj) { + // Step 1.e. (Reordered) + int32_t months = 0; + + // Steps 1.d and 1.f. + if (largestUnit == TemporalUnit::Year || largestUnit == TemporalUnit::Month) { + years = two.year - one.year; + months = two.month - one.month; + + auto intermediate = ISODate{one.year + years, one.month, one.day}; + if (CompareISODate(intermediate, two) * sign > 0) { + years -= sign; + months += 12 * sign; + } + + intermediate = ISODate{one.year + years, one.month + months, one.day}; + if (intermediate.month > 12) { + intermediate.month -= 12; + intermediate.year += 1; + } else if (intermediate.month < 1) { + intermediate.month += 12; + intermediate.year -= 1; + } + if (CompareISODate(intermediate, two) * sign > 0) { + months -= sign; + } + + if (largestUnit == TemporalUnit::Month) { + months += years * 12; + years = 0; + } + } + + // Step 1.g. + auto intermediate = BalanceISOYearMonth(one.year + years, one.month + months); + + // Step 1.h. + auto constrained = ConstrainISODate( + ISODate{int32_t(intermediate.year), intermediate.month, one.day}); + + // Step 1.i. + int64_t weeks = 0; + + // Steps 1.k-n. + int64_t days = MakeDay(two) - MakeDay(constrained); + + // Step 1.j. (Reordered) + if (largestUnit == TemporalUnit::Week) { + weeks = days / 7; + days %= 7; + } + + // Step 1.o. + auto result = DateDuration{ + int64_t(years), + int64_t(months), + int64_t(weeks), + int64_t(days), + }; + MOZ_ASSERT(IsValidDuration(result)); + return result; +} + +static bool DifferenceNonISODate(JSContext* cx, CalendarId calendarId, + const ISODate& one, const ISODate& two, + TemporalUnit largestUnit, + DateDuration* result) { + // Both inputs are also within the date limits. + MOZ_ASSERT(ISODateWithinLimits(one)); + MOZ_ASSERT(ISODateWithinLimits(two)); + + MOZ_ASSERT(TemporalUnit::Year <= largestUnit && + largestUnit <= TemporalUnit::Month); + + if (one == two) { + *result = {}; + return true; + } + + auto cal = CreateICU4XCalendar(cx, calendarId); + if (!cal) { return false; } - Rooted durationObj( - cx, CreateTemporalDuration(cx, duration.toDuration())); - if (!durationObj) { + auto dtOne = CreateICU4XDate(cx, one, calendarId, cal.get()); + if (!dtOne) { return false; } - auto obj = CalendarDateAddSlow(cx, calendar, dateObj, durationObj, options); - if (!obj) { + auto dtTwo = CreateICU4XDate(cx, two, calendarId, cal.get()); + if (!dtTwo) { return false; } - *result = ToPlainDate(&obj.unwrap()); + int32_t years = 0; + int32_t months = 0; + + ISODate constrainedIso; + if (!CalendarHasLeapMonths(calendarId)) { + // If the months per year are fixed, we can use a modified DifferenceISODate + // implementation to compute the date duration. + int32_t monthsPerYear = CalendarMonthsPerYear(calendarId); + + ISODate oneDate; + if (!ToCalendarDate(cx, calendarId, dtOne.get(), &oneDate)) { + return false; + } + + ISODate twoDate; + if (!ToCalendarDate(cx, calendarId, dtTwo.get(), &twoDate)) { + return false; + } + + int32_t sign = -CompareISODate(oneDate, twoDate); + MOZ_ASSERT(sign != 0); + + years = twoDate.year - oneDate.year; + months = twoDate.month - oneDate.month; + + // If |oneDate + years| surpasses |twoDate|, reduce |years| by one and add + // |monthsPerYear| to |months|. The next step will balance the intermediate + // result. + auto intermediate = + ISODate{oneDate.year + years, oneDate.month, oneDate.day}; + if (CompareISODate(intermediate, twoDate) * sign > 0) { + years -= sign; + months += monthsPerYear * sign; + } + + // Add both |years| and |months| and then balance the intermediate result to + // ensure its month is within the valid bounds. + intermediate = + ISODate{oneDate.year + years, oneDate.month + months, oneDate.day}; + if (intermediate.month > monthsPerYear) { + intermediate.month -= monthsPerYear; + intermediate.year += 1; + } else if (intermediate.month < 1) { + intermediate.month += monthsPerYear; + intermediate.year -= 1; + } + + // If |intermediate| surpasses |twoDate|, reduce |month| by one. + if (CompareISODate(intermediate, twoDate) * sign > 0) { + months -= sign; + } + + // Convert years to months if necessary. + if (largestUnit == TemporalUnit::Month) { + months += years * monthsPerYear; + years = 0; + } + + // Constrain to a proper date. + auto balanced = BalanceYearMonth(oneDate.year + years, + oneDate.month + months, monthsPerYear); + + auto eraYear = CalendarEraYear(calendarId, balanced.year); + auto constrained = + CreateDateFrom(cx, calendarId, cal.get(), eraYear, balanced.month, + oneDate.day, TemporalOverflow::Constrain); + if (!constrained) { + return false; + } + constrainedIso = ToISODate(constrained.get()); + + MOZ_ASSERT(CompareISODate(constrainedIso, two) * sign <= 0, + "constrained doesn't surpass two"); + } else { + CalendarDate oneDate; + if (!ToCalendarDate(cx, calendarId, dtOne.get(), &oneDate)) { + return false; + } + + CalendarDate twoDate; + if (!ToCalendarDate(cx, calendarId, dtTwo.get(), &twoDate)) { + return false; + } + + int32_t sign = -CompareCalendarDate(oneDate, twoDate); + MOZ_ASSERT(sign != 0); + + years = twoDate.year - oneDate.year; + + // If |oneDate + years| surpasses |twoDate|, reduce |years| by one and add + // |monthsPerYear| to |months|. The next step will balance the intermediate + // result. + auto eraYear = CalendarEraYear(calendarId, oneDate.year + years); + auto constrained = CreateDateFromCodes(cx, calendarId, cal.get(), eraYear, + oneDate.monthCode, oneDate.day, + TemporalOverflow::Constrain); + if (!constrained) { + return false; + } + + CalendarDate constrainedDate; + if (!ToCalendarDate(cx, calendarId, constrained.get(), &constrainedDate)) { + return false; + } + + if (CompareCalendarDate(constrainedDate, twoDate) * sign > 0) { + years -= sign; + } + + // Add as many months as possible without surpassing |twoDate|. + while (true) { + CalendarDate intermediateDate; + if (!AddYearMonthDuration(cx, calendarId, cal.get(), oneDate, + {years, months + sign}, &intermediateDate)) { + return false; + } + if (CompareCalendarDate(intermediateDate, twoDate) * sign > 0) { + break; + } + months += sign; + constrainedDate = intermediateDate; + } + MOZ_ASSERT(std::abs(months) < CalendarMonthsPerYear(calendarId)); + + // Convert years to months if necessary. + if (largestUnit == TemporalUnit::Month && years != 0) { + auto monthsUntilEndOfYear = [calendarId](const capi::ICU4XDate* date) { + int32_t month = OrdinalMonth(calendarId, date); + int32_t monthsInYear = MonthsInYear(date); + MOZ_ASSERT(1 <= month && month <= monthsInYear); + + return monthsInYear - month + 1; + }; + + auto monthsSinceStartOfYear = [calendarId](const capi::ICU4XDate* date) { + return OrdinalMonth(calendarId, date) - 1; + }; + + // Add months until end of year resp. since start of year. + if (sign > 0) { + months += monthsUntilEndOfYear(dtOne.get()); + } else { + months -= monthsSinceStartOfYear(dtOne.get()); + } + + // Months in full year. + for (int32_t y = sign; y != years; y += sign) { + auto eraYear = CalendarEraYear(calendarId, oneDate.year + y); + auto dt = + CreateDateFromCodes(cx, calendarId, cal.get(), eraYear, + MonthCode{1}, 1, TemporalOverflow::Constrain); + if (!dt) { + return false; + } + months += MonthsInYear(dt.get()) * sign; + } + + // Add months since start of year resp. until end of year. + auto eraYear = CalendarEraYear(calendarId, oneDate.year + years); + auto dt = CreateDateFromCodes(cx, calendarId, cal.get(), eraYear, + oneDate.monthCode, 1, + TemporalOverflow::Constrain); + if (!dt) { + return false; + } + if (sign > 0) { + months += monthsSinceStartOfYear(dt.get()); + } else { + months -= monthsUntilEndOfYear(dt.get()); + } + + years = 0; + } + + eraYear = CalendarEraYear(calendarId, constrainedDate.year); + constrained = CreateDateFromCodes( + cx, calendarId, cal.get(), eraYear, constrainedDate.monthCode, + constrainedDate.day, TemporalOverflow::Constrain); + if (!constrained) { + return false; + } + constrainedIso = ToISODate(constrained.get()); + + MOZ_ASSERT(CompareISODate(constrainedIso, two) * sign <= 0, + "constrained doesn't surpass two"); + } + + int64_t days = MakeDay(two) - MakeDay(constrainedIso); + + *result = DateDuration{ + int64_t(years), + int64_t(months), + 0, + int64_t(days), + }; + MOZ_ASSERT(IsValidDuration(*result)); return true; } -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped js::temporal::CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, const Duration& duration, - Handle options) { - // Step 1. (Not applicable). +static bool DifferenceCalendarDate(JSContext* cx, CalendarId calendarId, + const ISODate& one, const ISODate& two, + TemporalUnit largestUnit, + DateDuration* result) { + // ICU4X doesn't yet provide a public API for CalendarDateUntil. + // + // https://github.com/unicode-org/icu4x/issues/3964 - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped js::temporal::CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, const DateDuration& duration) { - // Step 1. - Handle options = nullptr; - - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped js::temporal::CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, - Handle> duration) { - // Step 1. - Handle options = nullptr; - - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped js::temporal::CalendarDateAdd( - JSContext* cx, Handle calendar, - Handle> date, - Handle> duration, Handle options) { - // Step 1. (Not applicable). - - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -bool js::temporal::CalendarDateAdd(JSContext* cx, - Handle calendar, - const PlainDate& date, - const DateDuration& duration, - PlainDate* result) { - // Step 1. - Handle options = nullptr; - - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options, result); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -bool js::temporal::CalendarDateAdd(JSContext* cx, - Handle calendar, - const PlainDate& date, - const DateDuration& duration, - Handle options, - PlainDate* result) { - // Step 1. (Not applicable) - - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options, result); -} - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -bool js::temporal::CalendarDateAdd(JSContext* cx, - Handle calendar, - Handle> date, - const DateDuration& duration, - PlainDate* result) { - // Step 1. - Handle options = nullptr; - - // Steps 2-5. - return ::CalendarDateAdd(cx, calendar, date, duration, options, result); -} - -/** - * Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] ) - */ -static bool BuiltinCalendarDateUntil(JSContext* cx, CalendarId calendarId, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, - DateDuration* result) { - // Steps 1-7. (Not applicable) - - // Step 8. - *result = DifferenceISODate(one, two, largestUnit); - return true; -} - -/** - * Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] ) - */ -static bool BuiltinCalendarDateUntil(JSContext* cx, CalendarId calendarId, - Handle> one, - Handle> two, - TemporalUnit largestUnit, - DateDuration* result) { - MOZ_ASSERT(largestUnit <= TemporalUnit::Day); - - auto* unwrappedOne = one.unwrap(cx); - if (!unwrappedOne) { - return false; + // Delegate to the ISO 8601 calendar for "weeks" and "days". This works + // because all supported calendars use a 7-days week. + if (largestUnit >= TemporalUnit::Week) { + *result = DifferenceISODate(one, two, largestUnit); + return true; } - auto dateOne = ToPlainDate(unwrappedOne); - auto* unwrappedTwo = two.unwrap(cx); - if (!unwrappedTwo) { - return false; - } - auto dateTwo = ToPlainDate(unwrappedTwo); + switch (calendarId) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Gregorian: + case CalendarId::Japanese: + case CalendarId::ROC: + // Use the ISO 8601 calendar if the calendar system starts its year at the + // same time as the ISO 8601 calendar and all months exactly match the + // ISO 8601 calendar months. + *result = DifferenceISODate(one, two, largestUnit); + return true; - // Steps 1-9. - return BuiltinCalendarDateUntil(cx, calendarId, dateOne, dateTwo, largestUnit, + case CalendarId::Chinese: + case CalendarId::Coptic: + case CalendarId::Dangi: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: + return DifferenceNonISODate(cx, calendarId, one, two, largestUnit, result); -} - -static bool CalendarDateUntilSlow(JSContext* cx, - Handle calendar, - Handle> one, - Handle> two, - TemporalUnit largestUnit, - Handle maybeOptions, - DateDuration* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - MOZ_ASSERT(calendar.receiver().isObject()); - MOZ_ASSERT(calendar.dateUntil()); - - Rooted options(cx, maybeOptions); - if (!options) { - options = NewPlainObjectWithProto(cx, nullptr); - if (!options) { - return false; - } } - - Rooted value(cx, StringValue(TemporalUnitToString(cx, largestUnit))); - if (!DefineDataProperty(cx, options, cx->names().largestUnit, value)) { - return false; - } - - // Step 1. (Inlined call to CalendarMethodsRecordCall.) - Rooted dateUntil(cx, ObjectValue(*calendar.dateUntil())); - auto thisv = calendar.receiver().toObjectValue(); - Rooted rval(cx); - - FixedInvokeArgs<3> args(cx); - args[0].setObject(*one); - args[1].setObject(*two); - args[2].setObject(*options); - - if (!Call(cx, dateUntil, thisv, args, &rval)) { - return false; - } - - // Step 2. (Not applicable) - MOZ_ASSERT(!CalendarMethodsRecordIsBuiltin(calendar)); - - // Step 3. - if (!rval.isObject() || !rval.toObject().canUnwrapAs()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, rval, - nullptr, "not a Duration object"); - return false; - } - - // Step 4. - auto duration = ToDuration(&rval.toObject().unwrapAs()); - *result = duration.toDateDuration(); - return true; -} - -static bool CalendarDateUntilSlow(JSContext* cx, - Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, - Handle maybeOptions, - DateDuration* result) { - Rooted date1( - cx, CreateTemporalDate(cx, one, calendar.receiver())); - if (!date1) { - return false; - } - - Rooted date2( - cx, CreateTemporalDate(cx, two, calendar.receiver())); - if (!date2) { - return false; - } - - return CalendarDateUntilSlow(cx, calendar, date1, date2, largestUnit, - maybeOptions, result); + MOZ_CRASH("invalid calendar id"); } /** - * CalendarDateUntil ( calendarRec, one, two, options ) + * CalendarDateUntil ( calendar, one, two, largestUnit ) */ bool js::temporal::CalendarDateUntil(JSContext* cx, - Handle calendar, - const PlainDate& one, const PlainDate& two, + Handle calendar, + const ISODate& one, const ISODate& two, TemporalUnit largestUnit, DateDuration* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); MOZ_ASSERT(largestUnit <= TemporalUnit::Day); - // Step 2. (Reordered) - if (!calendar.dateUntil()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarDateUntil(cx, calendarId, one, two, largestUnit, - result); - } + auto calendarId = calendar.identifier(); - // Steps 1 and 3-4. - return CalendarDateUntilSlow(cx, calendar, one, two, largestUnit, nullptr, - result); -} - -/** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool js::temporal::CalendarDateUntil(JSContext* cx, - Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, - Handle options, - DateDuration* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - - // As an optimization, our implementation only adds |largestUnit| to the - // options object when taking the slow-path. -#ifdef DEBUG - // The object must be extensible, otherwise we'd need to throw an error when - // attempting to add the "largestUnit" property to a non-extensible object. - MOZ_ASSERT(options->isExtensible()); - - // Similarily, if there's an existing "largestUnit" property, this property - // must be configurable. - auto largestUnitProp = options->lookupPure(cx->names().largestUnit); - MOZ_ASSERT_IF(largestUnitProp, largestUnitProp->configurable()); -#endif - - // Step 2. (Reordered) - if (!calendar.dateUntil()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarDateUntil(cx, calendarId, one, two, largestUnit, - result); - } - - // Steps 1 and 3-4. - return CalendarDateUntilSlow(cx, calendar, one, two, largestUnit, options, - result); -} - -/** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool js::temporal::CalendarDateUntil(JSContext* cx, - Handle calendar, - Handle> one, - Handle> two, - TemporalUnit largestUnit, - DateDuration* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - MOZ_ASSERT(largestUnit <= TemporalUnit::Day); - - // Step 2. (Reordered) - if (!calendar.dateUntil()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarDateUntil(cx, calendarId, one, two, largestUnit, - result); - } - - // Steps 1 and 3-4. - return CalendarDateUntilSlow(cx, calendar, one, two, largestUnit, nullptr, - result); -} - -/** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool js::temporal::CalendarDateUntil(JSContext* cx, - Handle calendar, - Handle> one, - Handle> two, - TemporalUnit largestUnit, - Handle options, - DateDuration* result) { - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - - // As an optimization, our implementation only adds |largestUnit| to the - // options object when taking the slow-path. -#ifdef DEBUG - // The object must be extensible, otherwise we'd need to throw an error when - // attempting to add the "largestUnit" property to a non-extensible object. - MOZ_ASSERT(options->isExtensible()); - - // Similarily, if there's an existing "largestUnit" property, this property - // must be configurable. - auto largestUnitProp = options->lookupPure(cx->names().largestUnit); - MOZ_ASSERT_IF(largestUnitProp, largestUnitProp->configurable()); -#endif - - // Step 2. (Reordered) - if (!calendar.dateUntil()) { - auto calendarId = BuiltinCalendarId(calendar.receiver()); - return BuiltinCalendarDateUntil(cx, calendarId, one, two, largestUnit, - result); - } - - // Steps 1 and 3-4. - return CalendarDateUntilSlow(cx, calendar, one, two, largestUnit, options, - result); -} - -/** - * CalendarEquals ( one, two ) - */ -bool js::temporal::CalendarEquals(JSContext* cx, Handle one, - Handle two, bool* equals) { // Step 1. - if (one.isObject() && two.isObject() && one.toObject() == two.toObject()) { - *equals = true; + if (calendarId == CalendarId::ISO8601) { + *result = DifferenceISODate(one, two, largestUnit); return true; } // Step 2. - Rooted calendarOne(cx, - ToTemporalCalendarIdentifier(cx, one)); - if (!calendarOne) { - return false; - } - - // Step 3. - JSLinearString* calendarTwo = ToTemporalCalendarIdentifier(cx, two); - if (!calendarTwo) { - return false; - } - - // Steps 4-5. - *equals = EqualStrings(calendarOne, calendarTwo); - return true; -} - -/** - * CalendarEquals ( one, two ) - */ -bool js::temporal::CalendarEqualsOrThrow(JSContext* cx, - Handle one, - Handle two) { - // Step 1. - if (one.isObject() && two.isObject() && one.toObject() == two.toObject()) { - return true; - } - - // Step 2. - Rooted calendarOne(cx, - ToTemporalCalendarIdentifier(cx, one)); - if (!calendarOne) { - return false; - } - - // Step 3. - JSLinearString* calendarTwo = ToTemporalCalendarIdentifier(cx, two); - if (!calendarTwo) { - return false; - } - - // Steps 4-5. - if (EqualStrings(calendarOne, calendarTwo)) { - return true; - } - - // Throw an error when the calendar identifiers don't match. Used when unequal - // calendars throw a RangeError. - if (auto charsOne = QuoteString(cx, calendarOne)) { - if (auto charsTwo = QuoteString(cx, calendarTwo)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, - charsOne.get(), charsTwo.get()); - } - } - return false; -} - -/** - * ConsolidateCalendars ( one, two ) - */ -bool js::temporal::ConsolidateCalendars(JSContext* cx, - Handle one, - Handle two, - MutableHandle result) { - // Step 1. - if (one.isObject() && two.isObject() && one.toObject() == two.toObject()) { - result.set(two); - return true; - } - - // Step 2. - Rooted calendarOne(cx, - ToTemporalCalendarIdentifier(cx, one)); - if (!calendarOne) { - return false; - } - - // Step 3. - Rooted calendarTwo(cx, - ToTemporalCalendarIdentifier(cx, two)); - if (!calendarTwo) { - return false; - } - - // Step 4. - if (EqualStrings(calendarOne, calendarTwo)) { - result.set(two); - return true; - } - - // Step 5. - if (StringEqualsLiteral(calendarOne, "iso8601")) { - result.set(two); - return true; - } - - // Step 6. - if (StringEqualsLiteral(calendarTwo, "iso8601")) { - result.set(one); - return true; - } - - // Step 7. - if (auto charsOne = QuoteString(cx, calendarOne)) { - if (auto charsTwo = QuoteString(cx, calendarTwo)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, - charsOne.get(), charsTwo.get()); - } - } - return false; -} - -/** - * Temporal.Calendar ( id ) - */ -static bool CalendarConstructor(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. - if (!ThrowIfNotConstructing(cx, args, "Temporal.Calendar")) { - return false; - } - - // Step 2. - if (!args.requireAtLeast(cx, "Temporal.Calendar", 1)) { - return false; - } - - if (!args[0].isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, args[0], - nullptr, "not a string"); - return false; - } - - Rooted id(cx, args[0].toString()->ensureLinear(cx)); - if (!id) { - return false; - } - - // Step 3. - CalendarId identifier; - if (!::ToBuiltinCalendar(cx, id, &identifier)) { - return false; - } - - // Step 4. - auto* calendar = CreateTemporalCalendar(cx, args, identifier); - if (!calendar) { - return false; - } - - args.rval().setObject(*calendar); - return true; -} - -/** - * Temporal.Calendar.from ( item ) - */ -static bool Calendar_from(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. - Rooted calendar(cx); - if (!ToTemporalCalendar(cx, args.get(0), &calendar)) { - return false; - } - - // Step 2. - auto* obj = ToTemporalCalendarObject(cx, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * get Temporal.Calendar.prototype.id - */ -static bool Calendar_id(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - - // Step 3. - auto* str = ToTemporalCalendarIdentifier(cx, calendar->identifier()); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; -} - -/** - * get Temporal.Calendar.prototype.id - */ -static bool Calendar_id(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] ) - */ -static bool Calendar_dateFromFields(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - Rooted fields( - cx, RequireObjectArg(cx, "fields", "dateFromFields", args.get(0))); - if (!fields) { - return false; - } - - // Step 4. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "dateFromFields", args[1]); - if (!options) { - return false; - } - } - - // Steps 5-11. - auto* obj = BuiltinCalendarDateFromFields(cx, calendarId, fields, options); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] ) - */ -static bool Calendar_dateFromFields(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.yearMonthFromFields ( fields [ , options ] ) - */ -static bool Calendar_yearMonthFromFields(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - Rooted fields( - cx, RequireObjectArg(cx, "fields", "yearMonthFromFields", args.get(0))); - if (!fields) { - return false; - } - - // Step 4. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "yearMonthFromFields", args[1]); - if (!options) { - return false; - } - } - - // Steps 5-11. - auto* obj = - BuiltinCalendarYearMonthFromFields(cx, calendarId, fields, options); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.Calendar.prototype.yearMonthFromFields ( fields [ , options ] ) - */ -static bool Calendar_yearMonthFromFields(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - -/** - * Temporal.Calendar.prototype.monthDayFromFields ( fields [ , options ] ) - */ -static bool Calendar_monthDayFromFields(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - Rooted fields( - cx, RequireObjectArg(cx, "fields", "monthDayFromFields", args.get(0))); - if (!fields) { - return false; - } - - // Step 4. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "monthDayFromFields", args[1]); - if (!options) { - return false; - } - } - - // Steps 5-11. - auto* obj = - BuiltinCalendarMonthDayFromFields(cx, calendarId, fields, options); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.Calendar.prototype.monthDayFromFields ( fields [ , options ] ) - */ -static bool Calendar_monthDayFromFields(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - -/** - * Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) - */ -static bool Calendar_dateAdd(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToTemporalDate(cx, args.get(0), &date)) { - return false; - } - - // Step 4. - Duration duration; - if (!ToTemporalDuration(cx, args.get(1), &duration)) { - return false; - } - - // Step 5. - Rooted options(cx); - if (args.hasDefined(2)) { - options = RequireObjectArg(cx, "options", "dateAdd", args[2]); - if (!options) { - return false; - } - } - - // Steps 6-11. - auto* obj = BuiltinCalendarAdd(cx, calendarId, date, duration, options); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) - */ -static bool Calendar_dateAdd(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] ) - */ -static bool Calendar_dateUntil(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate one; - if (!ToTemporalDate(cx, args.get(0), &one)) { - return false; - } - - // Step 4. - PlainDate two; - if (!ToTemporalDate(cx, args.get(1), &two)) { - return false; - } - - // Steps 5-7. - auto largestUnit = TemporalUnit::Day; - if (args.hasDefined(2)) { - // Step 5. - Rooted options( - cx, RequireObjectArg(cx, "options", "dateUntil", args[2])); - if (!options) { - return false; - } - - // Steps 6-7. - if (!GetTemporalUnitValuedOption(cx, options, TemporalUnitKey::LargestUnit, - TemporalUnitGroup::Date, &largestUnit)) { - return false; - } - } - - // Steps 8-9. - DateDuration duration; - if (!BuiltinCalendarDateUntil(cx, calendarId, one, two, largestUnit, - &duration)) { - return false; - } - - // Step 10. - auto* obj = CreateTemporalDuration(cx, duration.toDuration()); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] ) - */ -static bool Calendar_dateUntil(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.era ( temporalDateLike ) - */ -static bool Calendar_era(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-5. - return BuiltinCalendarEra(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.era ( temporalDateLike ) - */ -static bool Calendar_era(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.eraYear ( temporalDateLike ) - */ -static bool Calendar_eraYear(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-7. - return BuiltinCalendarEraYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.eraYear ( temporalDateLike ) - */ -static bool Calendar_eraYear(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.year ( temporalDateLike ) - */ -static bool Calendar_year(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.year ( temporalDateLike ) - */ -static bool Calendar_year(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.month ( temporalDateLike ) - */ -static bool Calendar_month(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - Handle temporalDateLike = args.get(0); - if (temporalDateLike.isObject() && - temporalDateLike.toObject().canUnwrapAs()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, - temporalDateLike, nullptr, "a PlainMonthDay object"); - return false; - } - - // Step 4. - PlainDate date; - if (!ToPlainDate( - cx, temporalDateLike, &date)) { - return false; - } - - // Steps 5-7. - return BuiltinCalendarMonth(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.month ( temporalDateLike ) - */ -static bool Calendar_month(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.monthCode ( temporalDateLike ) - */ -static bool Calendar_monthCode(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate(cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarMonthCode(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.monthCode ( temporalDateLike ) - */ -static bool Calendar_monthCode(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.day ( temporalDateLike ) - */ -static bool Calendar_day(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarDay(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.day ( temporalDateLike ) - */ -static bool Calendar_day(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.dayOfWeek ( temporalDateLike ) - */ -static bool Calendar_dayOfWeek(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToTemporalDate(cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarDayOfWeek(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.dayOfWeek ( temporalDateLike ) - */ -static bool Calendar_dayOfWeek(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.dayOfYear ( temporalDateLike ) - */ -static bool Calendar_dayOfYear(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToTemporalDate(cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarDayOfYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.dayOfYear ( temporalDateLike ) - */ -static bool Calendar_dayOfYear(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.weekOfYear ( temporalDateLike ) - */ -static bool Calendar_weekOfYear(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToTemporalDate(cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarWeekOfYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.weekOfYear ( temporalDateLike ) - */ -static bool Calendar_weekOfYear(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike ) - */ -static bool Calendar_yearOfWeek(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToTemporalDate(cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarYearOfWeek(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike ) - */ -static bool Calendar_yearOfWeek(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.daysInWeek ( temporalDateLike ) - */ -static bool Calendar_daysInWeek(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToTemporalDate(cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarDaysInWeek(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.daysInWeek ( temporalDateLike ) - */ -static bool Calendar_daysInWeek(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.daysInMonth ( temporalDateLike ) - */ -static bool Calendar_daysInMonth(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarDaysInMonth(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.daysInMonth ( temporalDateLike ) - */ -static bool Calendar_daysInMonth(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.daysInYear ( temporalDateLike ) - */ -static bool Calendar_daysInYear(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarDaysInYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.daysInYear ( temporalDateLike ) - */ -static bool Calendar_daysInYear(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.monthsInYear ( temporalDateLike ) - */ -static bool Calendar_monthsInYear(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarMonthsInYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.monthsInYear ( temporalDateLike ) - */ -static bool Calendar_monthsInYear(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.inLeapYear ( temporalDateLike ) - */ -static bool Calendar_inLeapYear(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - PlainDate date; - if (!ToPlainDate( - cx, args.get(0), &date)) { - return false; - } - - // Steps 4-6. - return BuiltinCalendarInLeapYear(cx, calendarId, date, args.rval()); -} - -/** - * Temporal.Calendar.prototype.inLeapYear ( temporalDateLike ) - */ -static bool Calendar_inLeapYear(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.fields ( fields ) - */ -static bool Calendar_fields(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Steps 3-9. - return BuiltinCalendarFields(cx, calendarId, args.get(0), args.rval()); -} - -/** - * Temporal.Calendar.prototype.fields ( fields ) - */ -static bool Calendar_fields(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.mergeFields ( fields, additionalFields ) - */ -static bool Calendar_mergeFields(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - auto calendarId = calendar->identifier(); - - // Step 3. - Rooted fields(cx, JS::ToObject(cx, args.get(0))); - if (!fields) { - return false; - } - - Rooted fieldsCopy( - cx, SnapshotOwnPropertiesIgnoreUndefined(cx, fields)); - if (!fieldsCopy) { - return false; - } - - // Step 4. - Rooted additionalFields(cx, JS::ToObject(cx, args.get(1))); - if (!additionalFields) { - return false; - } - - Rooted additionalFieldsCopy( - cx, SnapshotOwnPropertiesIgnoreUndefined(cx, additionalFields)); - if (!additionalFieldsCopy) { - return false; - } - - // Steps 5-13. - auto* merged = BuiltinCalendarMergeFields(cx, calendarId, fieldsCopy, - additionalFieldsCopy); - if (!merged) { - return false; - } - - // Step 14. - args.rval().setObject(*merged); - return true; -} - -/** - * Temporal.Calendar.prototype.mergeFields ( fields, additionalFields ) - */ -static bool Calendar_mergeFields(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.toString ( ) - */ -static bool Calendar_toString(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - - // Step 3. - auto* str = ToTemporalCalendarIdentifier(cx, calendar->identifier()); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; -} - -/** - * Temporal.Calendar.prototype.toString ( ) - */ -static bool Calendar_toString(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.Calendar.prototype.toJSON ( ) - */ -static bool Calendar_toJSON(JSContext* cx, const CallArgs& args) { - auto* calendar = &args.thisv().toObject().as(); - - // Step 3. - auto* str = ToTemporalCalendarIdentifier(cx, calendar->identifier()); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; -} - -/** - * Temporal.Calendar.prototype.toJSON ( ) - */ -static bool Calendar_toJSON(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -const JSClass CalendarObject::class_ = { - "Temporal.Calendar", - JSCLASS_HAS_RESERVED_SLOTS(CalendarObject::SLOT_COUNT) | - JSCLASS_HAS_CACHED_PROTO(JSProto_Calendar), - JS_NULL_CLASS_OPS, - &CalendarObject::classSpec_, -}; - -const JSClass& CalendarObject::protoClass_ = PlainObject::class_; - -static const JSFunctionSpec Calendar_methods[] = { - JS_FN("from", Calendar_from, 1, 0), - JS_FS_END, -}; - -static const JSFunctionSpec Calendar_prototype_methods[] = { - JS_FN("dateFromFields", Calendar_dateFromFields, 1, 0), - JS_FN("yearMonthFromFields", Calendar_yearMonthFromFields, 1, 0), - JS_FN("monthDayFromFields", Calendar_monthDayFromFields, 1, 0), - JS_FN("dateAdd", Calendar_dateAdd, 2, 0), - JS_FN("dateUntil", Calendar_dateUntil, 2, 0), - JS_FN("era", Calendar_era, 1, 0), - JS_FN("eraYear", Calendar_eraYear, 1, 0), - JS_FN("year", Calendar_year, 1, 0), - JS_FN("month", Calendar_month, 1, 0), - JS_FN("monthCode", Calendar_monthCode, 1, 0), - JS_FN("day", Calendar_day, 1, 0), - JS_FN("dayOfWeek", Calendar_dayOfWeek, 1, 0), - JS_FN("dayOfYear", Calendar_dayOfYear, 1, 0), - JS_FN("weekOfYear", Calendar_weekOfYear, 1, 0), - JS_FN("yearOfWeek", Calendar_yearOfWeek, 1, 0), - JS_FN("daysInWeek", Calendar_daysInWeek, 1, 0), - JS_FN("daysInMonth", Calendar_daysInMonth, 1, 0), - JS_FN("daysInYear", Calendar_daysInYear, 1, 0), - JS_FN("monthsInYear", Calendar_monthsInYear, 1, 0), - JS_FN("inLeapYear", Calendar_inLeapYear, 1, 0), - JS_FN("fields", Calendar_fields, 1, 0), - JS_FN("mergeFields", Calendar_mergeFields, 2, 0), - JS_FN("toString", Calendar_toString, 0, 0), - JS_FN("toJSON", Calendar_toJSON, 0, 0), - JS_FS_END, -}; - -static const JSPropertySpec Calendar_prototype_properties[] = { - JS_PSG("id", Calendar_id, 0), - JS_STRING_SYM_PS(toStringTag, "Temporal.Calendar", JSPROP_READONLY), - JS_PS_END, -}; - -const ClassSpec CalendarObject::classSpec_ = { - GenericCreateConstructor, - GenericCreatePrototype, - Calendar_methods, - nullptr, - Calendar_prototype_methods, - Calendar_prototype_properties, - nullptr, - ClassSpec::DontDefineConstructor, -}; - -struct MOZ_STACK_CLASS CalendarNameAndNative final { - PropertyName* name; - JSNative native; -}; - -static CalendarNameAndNative GetCalendarNameAndNative(JSContext* cx, - CalendarField fieldName) { - switch (fieldName) { - case CalendarField::Year: - return {cx->names().year, Calendar_year}; - case CalendarField::Month: - return {cx->names().month, Calendar_month}; - case CalendarField::MonthCode: - return {cx->names().monthCode, Calendar_monthCode}; - case CalendarField::Day: - return {cx->names().day, Calendar_day}; - } - MOZ_CRASH("invalid temporal field name"); -} - -bool js::temporal::IsBuiltinAccess( - JSContext* cx, Handle calendar, - std::initializer_list fieldNames) { - // Don't optimize when the object has any own properties which may shadow the - // built-in methods. - if (!calendar->empty()) { - return false; - } - - JSObject* proto = cx->global()->maybeGetPrototype(JSProto_Calendar); - - // Don't attempt to optimize when the class isn't yet initialized. - if (!proto) { - return false; - } - - // Don't optimize when the prototype isn't the built-in prototype. - if (calendar->staticPrototype() != proto) { - return false; - } - - auto* nproto = &proto->as(); - for (auto fieldName : fieldNames) { - auto [name, native] = GetCalendarNameAndNative(cx, fieldName); - auto prop = nproto->lookupPure(name); - - // Return if the property isn't a data property. - if (!prop || !prop->isDataProperty()) { - return false; - } - - // Return if the property isn't the initial method. - if (!IsNativeFunction(nproto->getSlot(prop->slot()), native)) { - return false; - } - } - - // TODO: Pass accessor list from caller to avoid excessive checks. - - // Additionally check the various calendar fields operations. - for (const auto& [name, native] : (CalendarNameAndNative[]){ - {cx->names().fields, Calendar_fields}, - {cx->names().mergeFields, Calendar_mergeFields}, - {cx->names().dateFromFields, Calendar_dateFromFields}, - {cx->names().monthDayFromFields, Calendar_monthDayFromFields}, - {cx->names().yearMonthFromFields, Calendar_yearMonthFromFields}, - }) { - auto prop = nproto->lookupPure(name); - - // Return if the property isn't a data property. - if (!prop || !prop->isDataProperty()) { - return false; - } - - // Return if the property isn't the initial method. - if (!IsNativeFunction(nproto->getSlot(prop->slot()), native)) { - return false; - } - } - - // CalendarFields observably uses array iteration. - bool arrayIterationSane; - if (!IsArrayIterationSane(cx, &arrayIterationSane)) { - cx->recoverFromOutOfMemory(); - return false; - } - if (!arrayIterationSane) { - return false; - } - - // Success! The access can be optimized. - return true; + return DifferenceCalendarDate(cx, calendarId, one, two, largestUnit, result); } diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.h index 4bd088fde1f..0c7ae3f01e0 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Calendar.h @@ -9,31 +9,108 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" -#include "mozilla/EnumSet.h" -#include #include +#include -#include "builtin/temporal/Wrapped.h" #include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" #include "vm/NativeObject.h" -#include "vm/StringType.h" class JS_PUBLIC_API JSTracer; namespace js { struct ClassSpec; -class PlainObject; } // namespace js namespace js::temporal { enum class CalendarId : int32_t { ISO8601, + + // Thai Buddhist solar calendar. + Buddhist, + + // Chinese lunisolar calendar. + Chinese, + + // Coptic calendar. + Coptic, + + // Korean lunisolar calendar. + Dangi, + + // Ethiopian Amete Mihret calendar. + Ethiopian, + + // Ethiopian Amete Alem calendar. + EthiopianAmeteAlem, + + // Gregorian calendar. + Gregorian, + + // Hebrew lunisolar calendar. + Hebrew, + + // Indian national calendar. + Indian, + + // Islamic lunar calendars. + Islamic, + IslamicCivil, + IslamicRGSA, + IslamicTabular, + IslamicUmmAlQura, + + // Japanese calendar. + Japanese, + + // Persian solar Hijri calendar. + Persian, + + // Republic of China (ROC) calendar. + ROC, }; +inline constexpr auto availableCalendars = { + CalendarId::ISO8601, + CalendarId::Buddhist, + CalendarId::Chinese, + CalendarId::Coptic, + CalendarId::Dangi, + CalendarId::Ethiopian, + CalendarId::EthiopianAmeteAlem, + CalendarId::Gregorian, + CalendarId::Hebrew, + CalendarId::Indian, +// See Bug 1950425, this calendar is only available on Nightly due to +// inconsistencies between ICU4X and ICU4C. +#ifdef NIGHTLY_BUILD + CalendarId::Islamic, +#endif + CalendarId::IslamicCivil, +// See Bug 1950425, this calendar is only available on Nightly due to +// inconsistencies between ICU4X and ICU4C. +#ifdef NIGHTLY_BUILD + CalendarId::IslamicRGSA, +#endif + CalendarId::IslamicTabular, +// See Bug 1950425, this calendar is only available on Nightly due to +// inconsistencies between ICU4X and ICU4C. +#ifdef NIGHTLY_BUILD + CalendarId::IslamicUmmAlQura, +#endif + CalendarId::Japanese, + CalendarId::Persian, + CalendarId::ROC, +}; + +/** + * AvailableCalendars ( ) + */ +constexpr auto& AvailableCalendars() { return availableCalendars; } + class CalendarObject : public NativeObject { public: static const JSClass class_; @@ -51,8 +128,7 @@ class CalendarObject : public NativeObject { }; /** - * Calendar value, which is either a string containing a canonical calendar - * identifier or an object. + * Calendar value, which is a string containing a canonical calendar identifier. */ class MOZ_STACK_CLASS CalendarValue final { JS::Value value_{}; @@ -67,7 +143,7 @@ class MOZ_STACK_CLASS CalendarValue final { * Default initialize this CalendarValue. */ explicit CalendarValue(const JS::Value& value) : value_(value) { - MOZ_ASSERT(value.isInt32() || value.isObject()); + MOZ_ASSERT(value.isInt32()); } /** @@ -76,12 +152,6 @@ class MOZ_STACK_CLASS CalendarValue final { explicit CalendarValue(CalendarId calendarId) : value_(JS::Int32Value(static_cast(calendarId))) {} - /** - * Initialize this CalendarValue with a calendar object. - */ - explicit CalendarValue(JSObject* calendar) - : value_(JS::ObjectValue(*calendar)) {} - /** * Return true iff this CalendarValue is initialized with either a canonical * calendar identifier or a calendar object. @@ -93,178 +163,74 @@ class MOZ_STACK_CLASS CalendarValue final { */ JS::Value toSlotValue() const { return value_; } - /** - * Return true if this CalendarValue is a string. - */ - bool isString() const { return value_.isInt32(); } - - /** - * Return true if this CalendarValue is an object. - */ - bool isObject() const { return value_.isObject(); } - /** * Return the calendar identifier. */ - CalendarId toString() const { + CalendarId identifier() const { return static_cast(value_.toInt32()); } - /** - * Return the calendar object. - */ - JSObject* toObject() const { return &value_.toObject(); } - void trace(JSTracer* trc); JS::Value* valueDoNotUse() { return &value_; } JS::Value const* valueDoNotUse() const { return &value_; } }; -enum class CalendarMethod { - DateAdd, - DateFromFields, - DateUntil, - Day, - Fields, - MergeFields, - MonthDayFromFields, - YearMonthFromFields, -}; - -class MOZ_STACK_CLASS CalendarRecord final { - CalendarValue receiver_; - - // Null unless non-builtin calendar methods are used. - JSObject* dateAdd_ = nullptr; - JSObject* dateFromFields_ = nullptr; - JSObject* dateUntil_ = nullptr; - JSObject* day_ = nullptr; - JSObject* fields_ = nullptr; - JSObject* mergeFields_ = nullptr; - JSObject* monthDayFromFields_ = nullptr; - JSObject* yearMonthFromFields_ = nullptr; - -#ifdef DEBUG - mozilla::EnumSet lookedUp_{}; -#endif - - public: - /** - * Default initialize this CalendarRecord. - */ - CalendarRecord() = default; - - explicit CalendarRecord(const CalendarValue& receiver) - : receiver_(receiver) {} - - const auto& receiver() const { return receiver_; } - auto* dateAdd() const { return dateAdd_; } - auto* dateFromFields() const { return dateFromFields_; } - auto* dateUntil() const { return dateUntil_; } - auto* day() const { return day_; } - auto* fields() const { return fields_; } - auto* mergeFields() const { return mergeFields_; } - auto* monthDayFromFields() const { return monthDayFromFields_; } - auto* yearMonthFromFields() const { return yearMonthFromFields_; } - -#ifdef DEBUG - auto& lookedUp() const { return lookedUp_; } - auto& lookedUp() { return lookedUp_; } -#endif - - // Helper methods for (Mutable)WrappedPtrOperations. - auto* receiverDoNotUse() const { return &receiver_; } - auto* dateAddDoNotUse() const { return &dateAdd_; } - auto* dateAddDoNotUse() { return &dateAdd_; } - auto* dateFromFieldsDoNotUse() const { return &dateFromFields_; } - auto* dateFromFieldsDoNotUse() { return &dateFromFields_; } - auto* dateUntilDoNotUse() const { return &dateUntil_; } - auto* dateUntilDoNotUse() { return &dateUntil_; } - auto* dayDoNotUse() const { return &day_; } - auto* dayDoNotUse() { return &day_; } - auto* fieldsDoNotUse() const { return &fields_; } - auto* fieldsDoNotUse() { return &fields_; } - auto* mergeFieldsDoNotUse() const { return &mergeFields_; } - auto* mergeFieldsDoNotUse() { return &mergeFields_; } - auto* monthDayFromFieldsDoNotUse() const { return &monthDayFromFields_; } - auto* monthDayFromFieldsDoNotUse() { return &monthDayFromFields_; } - auto* yearMonthFromFieldsDoNotUse() const { return &yearMonthFromFields_; } - auto* yearMonthFromFieldsDoNotUse() { return &yearMonthFromFields_; } - - // Trace implementation. - void trace(JSTracer* trc); -}; - struct DateDuration; -struct Duration; -struct PlainDate; -struct PlainDateTime; -class DurationObject; -class PlainDateObject; -class PlainDateTimeObject; +struct ISODate; +struct ISODateTime; +class PlainDate; class PlainMonthDayObject; +class PlainMonthDay; class PlainYearMonthObject; -enum class ShowCalendar; +class PlainYearMonth; +class CalendarFields; enum class TemporalOverflow; enum class TemporalUnit; -/** - * ISODaysInYear ( year ) - */ -int32_t ISODaysInYear(int32_t year); - /** * ISODaysInMonth ( year, month ) */ int32_t ISODaysInMonth(int32_t year, int32_t month); -/** - * ISODaysInMonth ( year, month ) - */ -int32_t ISODaysInMonth(double year, int32_t month); - -/** - * ToISODayOfYear ( year, month, day ) - */ -int32_t ToISODayOfYear(const PlainDate& date); - /** * 21.4.1.12 MakeDay ( year, month, date ) */ -int32_t MakeDay(const PlainDate& date); +int32_t MakeDay(const ISODate& date); /** * 21.4.1.13 MakeDate ( day, time ) */ -int64_t MakeDate(const PlainDateTime& dateTime); +int64_t MakeDate(const ISODateTime& dateTime); /** - * 21.4.1.13 MakeDate ( day, time ) + * Return the BCP 47 identifier of the calendar. */ -int64_t MakeDate(int32_t year, int32_t month, int32_t day); +std::string_view CalendarIdentifier(CalendarId calendarId); /** + * Return the BCP 47 identifier of the calendar. + */ +inline std::string_view CalendarIdentifier(const CalendarValue& calendar) { + return CalendarIdentifier(calendar.identifier()); +} + +/** + * CanonicalizeCalendar ( id ) + * * Return the case-normalized calendar identifier if |id| is a built-in calendar * identifier. Otherwise throws a RangeError. */ -bool ToBuiltinCalendar(JSContext* cx, JS::Handle id, - JS::MutableHandle result); +bool CanonicalizeCalendar(JSContext* cx, JS::Handle id, + JS::MutableHandle result); /** - * ToTemporalCalendarSlotValue ( temporalCalendarLike [ , default ] ) + * ToTemporalCalendarSlotValue ( temporalCalendarLike ) */ bool ToTemporalCalendar(JSContext* cx, JS::Handle temporalCalendarLike, JS::MutableHandle result); -/** - * ToTemporalCalendarSlotValue ( temporalCalendarLike [ , default ] ) - */ -bool ToTemporalCalendarWithISODefault( - JSContext* cx, JS::Handle temporalCalendarLike, - JS::MutableHandle result); - /** * GetTemporalCalendarWithISODefault ( item ) */ @@ -273,636 +239,184 @@ bool GetTemporalCalendarWithISODefault(JSContext* cx, JS::MutableHandle result); /** - * ToTemporalCalendarIdentifier ( calendarSlotValue ) + * CalendarDateAdd ( calendar, isoDate, duration, overflow ) */ -JSLinearString* ToTemporalCalendarIdentifier( - JSContext* cx, JS::Handle calendar); +bool CalendarDateAdd(JSContext* cx, JS::Handle calendar, + const ISODate& isoDate, const DateDuration& duration, + TemporalOverflow overflow, ISODate* result); /** - * ToTemporalCalendarObject ( calendarSlotValue ) + * CalendarDateUntil ( calendar, one, two, largestUnit ) */ -JSObject* ToTemporalCalendarObject(JSContext* cx, - JS::Handle calendar); - -bool ToTemporalCalendar(JSContext* cx, const CalendarValue& calendar, - JS::MutableHandle result); - -enum class CalendarField { - Year, - Month, - MonthCode, - Day, -}; - -using CalendarFieldNames = JS::StackGCVector; - -/** - * CalendarFields ( calendarRec, fieldNames ) - */ -bool CalendarFields(JSContext* cx, JS::Handle calendar, - mozilla::EnumSet fieldNames, - JS::MutableHandle result); - -/** - * CalendarMergeFields ( calendarRec, fields, additionalFields ) - */ -JSObject* CalendarMergeFields(JSContext* cx, - JS::Handle calendar, - JS::Handle fields, - JS::Handle additionalFields); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped CalendarDateAdd( - JSContext* cx, JS::Handle calendar, - JS::Handle> date, const DateDuration& duration); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped CalendarDateAdd( - JSContext* cx, JS::Handle calendar, - JS::Handle> date, const Duration& duration, - JS::Handle options); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped CalendarDateAdd( - JSContext* cx, JS::Handle calendar, - JS::Handle> date, - JS::Handle> duration); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -Wrapped CalendarDateAdd( - JSContext* cx, JS::Handle calendar, - JS::Handle> date, - JS::Handle> duration, - JS::Handle options); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -bool CalendarDateAdd(JSContext* cx, JS::Handle calendar, - const PlainDate& date, const DateDuration& duration, - PlainDate* result); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -bool CalendarDateAdd(JSContext* cx, JS::Handle calendar, - const PlainDate& date, const DateDuration& duration, - JS::Handle options, PlainDate* result); - -/** - * CalendarDateAdd ( calendarRec, date, duration [ , options ] ) - */ -bool CalendarDateAdd(JSContext* cx, JS::Handle calendar, - JS::Handle> date, - const DateDuration& duration, PlainDate* result); - -/** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool CalendarDateUntil(JSContext* cx, JS::Handle calendar, - const PlainDate& one, const PlainDate& two, +bool CalendarDateUntil(JSContext* cx, JS::Handle calendar, + const ISODate& one, const ISODate& two, TemporalUnit largestUnit, DateDuration* result); /** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool CalendarDateUntil(JSContext* cx, JS::Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, - JS::Handle options, DateDuration* result); - -/** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool CalendarDateUntil(JSContext* cx, JS::Handle calendar, - JS::Handle> one, - JS::Handle> two, - TemporalUnit largestUnit, DateDuration* result); - -/** - * CalendarDateUntil ( calendarRec, one, two, options ) - */ -bool CalendarDateUntil(JSContext* cx, JS::Handle calendar, - JS::Handle> one, - JS::Handle> two, - TemporalUnit largestUnit, - JS::Handle options, DateDuration* result); - -/** - * CalendarEra ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[Era]] of the returned Calendar Date Record. */ bool CalendarEra(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); + const ISODate& date, JS::MutableHandle result); /** - * CalendarEra ( calendar, dateLike ) - */ -bool CalendarEra(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarEra ( calendar, dateLike ) - */ -bool CalendarEra(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarEra ( calendar, dateLike ) - */ -bool CalendarEra(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarEraYear ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[EraYear]] of the returned Calendar Date Record. */ bool CalendarEraYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - + const ISODate& date, JS::MutableHandle result); /** - * CalendarEraYear ( calendar, dateLike ) - */ -bool CalendarEraYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -bool CalendarEraYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarEraYear ( calendar, dateLike ) - */ -bool CalendarEraYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarYear ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[Year]] of the returned Calendar Date Record. */ bool CalendarYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); + const ISODate& date, JS::MutableHandle result); /** - * CalendarYear ( calendar, dateLike ) - */ -bool CalendarYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarYear ( calendar, dateLike ) - */ -bool CalendarYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarYear ( calendar, dateLike ) - */ -bool CalendarYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarMonth ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[Month]] of the returned Calendar Date Record. */ bool CalendarMonth(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); + const ISODate& date, JS::MutableHandle result); /** - * CalendarMonth ( calendar, dateLike ) - */ -bool CalendarMonth(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonth ( calendar, dateLike ) - */ -bool CalendarMonth(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonth ( calendar, dateLike ) - */ -bool CalendarMonth(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarMonthCode ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[MonthCode]] of the returned Calendar Date Record. */ bool CalendarMonthCode(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool CalendarMonthCode(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool CalendarMonthCode(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool CalendarMonthCode(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonthCode ( calendar, dateLike ) - */ -bool CalendarMonthCode(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDay ( calendarRec, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[Day]] of the returned Calendar Date Record. */ bool CalendarDay(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); + const ISODate& date, JS::MutableHandle result); /** - * CalendarDay ( calendarRec, dateLike ) - */ -bool CalendarDay(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool CalendarDay(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool CalendarDay(JSContext* cx, JS::Handle calendar, - const PlainDate& date, JS::MutableHandle result); - -/** - * CalendarDay ( calendarRec, dateLike ) - */ -bool CalendarDay(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDayOfWeek ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[DayOfWeek]] of the returned Calendar Date Record. */ bool CalendarDayOfWeek(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarDayOfWeek ( calendar, dateLike ) - */ -bool CalendarDayOfWeek(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDayOfWeek ( calendar, dateLike ) - */ -bool CalendarDayOfWeek(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDayOfYear ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[DayOfYear]] of the returned Calendar Date Record. */ bool CalendarDayOfYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarDayOfYear ( calendar, dateLike ) - */ -bool CalendarDayOfYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDayOfYear ( calendar, dateLike ) - */ -bool CalendarDayOfYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarWeekOfYear ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[Week]] field of the [[WeekOfYear]] of the returned + * Calendar Date Record. */ bool CalendarWeekOfYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarWeekOfYear ( calendar, dateLike ) - */ -bool CalendarWeekOfYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarWeekOfYear ( calendar, dateLike ) - */ -bool CalendarWeekOfYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarYearOfWeek ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[Year]] field of the [[WeekOfYear]] of the returned + * Calendar Date Record. */ bool CalendarYearOfWeek(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarYearOfWeek ( calendar, dateLike ) - */ -bool CalendarYearOfWeek(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarYearOfWeek ( calendar, dateLike ) - */ -bool CalendarYearOfWeek(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDaysInWeek ( calendar, dateLike ) + * * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[DaysInWeek]] of the returned Calendar Date Record. */ bool CalendarDaysInWeek(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarDaysInWeek ( calendar, dateLike ) - */ -bool CalendarDaysInWeek(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDaysInWeek ( calendar, dateLike ) - */ -bool CalendarDaysInWeek(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDaysInMonth ( calendar, dateLike ) + * * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[DaysInMonth]] of the returned Calendar Date Record. */ bool CalendarDaysInMonth(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool CalendarDaysInMonth(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool CalendarDaysInMonth(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDaysInMonth ( calendar, dateLike ) - */ -bool CalendarDaysInMonth(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDaysInYear ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[DaysInYear]] of the returned Calendar Date Record. */ bool CalendarDaysInYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool CalendarDaysInYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool CalendarDaysInYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarDaysInYear ( calendar, dateLike ) - */ -bool CalendarDaysInYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarMonthsInYear ( calendar, dateLike ) + * * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[MonthsInYear]] of the returned Calendar Date Record. */ bool CalendarMonthsInYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool CalendarMonthsInYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool CalendarMonthsInYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarMonthsInYear ( calendar, dateLike ) - */ -bool CalendarMonthsInYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarInLeapYear ( calendar, dateLike ) + * CalendarISOToDate ( calendar, isoDate ) + * + * When accessing the [[InLeapYear]] of the returned Calendar Date Record. */ bool CalendarInLeapYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, + const ISODate& date, JS::MutableHandle result); /** - * CalendarInLeapYear ( calendar, dateLike ) + * CalendarDateFromFields ( calendar, fields, overflow ) */ -bool CalendarInLeapYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); +bool CalendarDateFromFields(JSContext* cx, JS::Handle calendar, + JS::Handle fields, + TemporalOverflow overflow, + MutableHandle result); /** - * CalendarInLeapYear ( calendar, dateLike ) + * CalendarYearMonthFromFields ( calendar, fields, overflow ) */ -bool CalendarInLeapYear(JSContext* cx, JS::Handle calendar, - JS::Handle dateLike, - JS::MutableHandle result); - -/** - * CalendarInLeapYear ( calendar, dateLike ) - */ -bool CalendarInLeapYear(JSContext* cx, JS::Handle calendar, - const PlainDateTime& dateTime, - JS::MutableHandle result); - -/** - * CalendarDateFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarDateFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields); - -/** - * CalendarDateFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarDateFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields, JS::Handle options); - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarYearMonthFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields); - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarYearMonthFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields); - -/** - * CalendarYearMonthFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarYearMonthFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields, JS::Handle options); - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarMonthDayFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields); - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarMonthDayFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields); - -/** - * CalendarMonthDayFromFields ( calendarRec, fields [ , options ] ) - */ -Wrapped CalendarMonthDayFromFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields, JS::Handle options); - -/** - * CalendarEquals ( one, two ) - */ -bool CalendarEquals(JSContext* cx, JS::Handle one, - JS::Handle two, bool* equals); - -/** - * CalendarEquals ( one, two ) - */ -bool CalendarEqualsOrThrow(JSContext* cx, JS::Handle one, - JS::Handle two); - -/** - * ConsolidateCalendars ( one, two ) - */ -bool ConsolidateCalendars(JSContext* cx, JS::Handle one, - JS::Handle two, - JS::MutableHandle result); - -/** - * CreateCalendarMethodsRecord ( calendar, methods ) - */ -bool CreateCalendarMethodsRecord(JSContext* cx, +bool CalendarYearMonthFromFields(JSContext* cx, JS::Handle calendar, - mozilla::EnumSet methods, - JS::MutableHandle result); - -#ifdef DEBUG -/** - * CalendarMethodsRecordHasLookedUp ( calendarRec, methodName ) - */ -inline bool CalendarMethodsRecordHasLookedUp(const CalendarRecord& calendar, - CalendarMethod methodName) { - // Steps 1-10. - return calendar.lookedUp().contains(methodName); -} -#endif + JS::Handle fields, + TemporalOverflow overflow, + JS::MutableHandle result); /** - * CalendarMethodsRecordIsBuiltin ( calendarRec ) + * CalendarMonthDayFromFields ( calendar, fields, overflow ) */ -inline bool CalendarMethodsRecordIsBuiltin(const CalendarRecord& calendar) { +bool CalendarMonthDayFromFields(JSContext* cx, + JS::Handle calendar, + JS::Handle fields, + TemporalOverflow overflow, + JS::MutableHandle result); + +/** + * CalendarEquals ( one, two ) + */ +inline bool CalendarEquals(const CalendarValue& one, const CalendarValue& two) { // Steps 1-2. - return calendar.receiver().isString(); + return one.identifier() == two.identifier(); } -/** - * Return true when accessing the calendar fields |fieldNames| can be optimized. - * Otherwise returns false. - */ -bool IsBuiltinAccess(JSContext* cx, JS::Handle calendar, - std::initializer_list fieldNames); - // Helper for MutableWrappedPtrOperations. bool WrapCalendarValue(JSContext* cx, JS::MutableHandle calendar); @@ -924,19 +438,7 @@ class WrappedPtrOperations { container().valueDoNotUse()); } - JS::Handle toObjectValue() const { - MOZ_ASSERT(isObject()); - return JS::Handle::fromMarkedLocation( - container().valueDoNotUse()); - } - - bool isString() const { return container().isString(); } - - bool isObject() const { return container().isObject(); } - - temporal::CalendarId toString() const { return container().toString(); } - - JSObject* toObject() const { return container().toObject(); } + temporal::CalendarId identifier() const { return container().identifier(); } }; template @@ -955,91 +457,6 @@ class MutableWrappedPtrOperations } }; -template -class WrappedPtrOperations { - const auto& container() const { - return static_cast(this)->get(); - } - - public: - JS::Handle receiver() const { - return JS::Handle::fromMarkedLocation( - container().receiverDoNotUse()); - } - - JS::Handle dateAdd() const { - return JS::Handle::fromMarkedLocation( - container().dateAddDoNotUse()); - } - JS::Handle dateFromFields() const { - return JS::Handle::fromMarkedLocation( - container().dateFromFieldsDoNotUse()); - } - JS::Handle dateUntil() const { - return JS::Handle::fromMarkedLocation( - container().dateUntilDoNotUse()); - } - JS::Handle day() const { - return JS::Handle::fromMarkedLocation(container().dayDoNotUse()); - } - JS::Handle fields() const { - return JS::Handle::fromMarkedLocation( - container().fieldsDoNotUse()); - } - JS::Handle mergeFields() const { - return JS::Handle::fromMarkedLocation( - container().mergeFieldsDoNotUse()); - } - JS::Handle monthDayFromFields() const { - return JS::Handle::fromMarkedLocation( - container().monthDayFromFieldsDoNotUse()); - } - JS::Handle yearMonthFromFields() const { - return JS::Handle::fromMarkedLocation( - container().yearMonthFromFieldsDoNotUse()); - } -}; - -template -class MutableWrappedPtrOperations - : public WrappedPtrOperations { - auto& container() { return static_cast(this)->get(); } - - public: - JS::MutableHandle dateAdd() { - return JS::MutableHandle::fromMarkedLocation( - container().dateAddDoNotUse()); - } - JS::MutableHandle dateFromFields() { - return JS::MutableHandle::fromMarkedLocation( - container().dateFromFieldsDoNotUse()); - } - JS::MutableHandle dateUntil() { - return JS::MutableHandle::fromMarkedLocation( - container().dateUntilDoNotUse()); - } - JS::MutableHandle day() { - return JS::MutableHandle::fromMarkedLocation( - container().dayDoNotUse()); - } - JS::MutableHandle fields() { - return JS::MutableHandle::fromMarkedLocation( - container().fieldsDoNotUse()); - } - JS::MutableHandle mergeFields() { - return JS::MutableHandle::fromMarkedLocation( - container().mergeFieldsDoNotUse()); - } - JS::MutableHandle monthDayFromFields() { - return JS::MutableHandle::fromMarkedLocation( - container().monthDayFromFieldsDoNotUse()); - } - JS::MutableHandle yearMonthFromFields() { - return JS::MutableHandle::fromMarkedLocation( - container().yearMonthFromFieldsDoNotUse()); - } -}; - } /* namespace js */ #endif /* builtin_temporal_Calendar_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.cpp new file mode 100644 index 00000000000..3c135ed2d35 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.cpp @@ -0,0 +1,654 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "builtin/temporal/CalendarFields.h" + +#include "mozilla/Assertions.h" +#include "mozilla/EnumTypeTraits.h" +#include "mozilla/Maybe.h" +#include "mozilla/Range.h" +#include "mozilla/TextUtils.h" + +#include +#include + +#include "jspubtd.h" +#include "NamespaceImports.h" + +#include "builtin/temporal/Calendar.h" +#include "builtin/temporal/Crash.h" +#include "builtin/temporal/Era.h" +#include "builtin/temporal/Temporal.h" +#include "builtin/temporal/TemporalParser.h" +#include "builtin/temporal/TimeZone.h" +#include "gc/Barrier.h" +#include "gc/Tracer.h" +#include "js/Conversions.h" +#include "js/ErrorReport.h" +#include "js/friend/ErrorMessages.h" +#include "js/GCAPI.h" +#include "js/Printer.h" +#include "js/RootingAPI.h" +#include "js/Value.h" +#include "util/Text.h" +#include "vm/BytecodeUtil.h" +#include "vm/JSAtomState.h" +#include "vm/JSContext.h" +#include "vm/JSObject.h" +#include "vm/StringType.h" + +#include "vm/JSObject-inl.h" +#include "vm/ObjectOperations-inl.h" + +using namespace js; +using namespace js::temporal; + +void CalendarFields::trace(JSTracer* trc) { + TraceNullableRoot(trc, &era_, "CalendarFields::era"); + timeZone_.trace(trc); +} + +void CalendarFields::setFrom(CalendarField field, + const CalendarFields& source) { + MOZ_ASSERT(source.has(field)); + + switch (field) { + case CalendarField::Era: + setEra(source.era()); + return; + case CalendarField::EraYear: + setEraYear(source.eraYear()); + return; + case CalendarField::Year: + setYear(source.year()); + return; + case CalendarField::Month: + setMonth(source.month()); + return; + case CalendarField::MonthCode: + setMonthCode(source.monthCode()); + return; + case CalendarField::Day: + setDay(source.day()); + return; + case CalendarField::Hour: + setHour(source.hour()); + return; + case CalendarField::Minute: + setMinute(source.minute()); + return; + case CalendarField::Second: + setSecond(source.second()); + return; + case CalendarField::Millisecond: + setMillisecond(source.millisecond()); + return; + case CalendarField::Microsecond: + setMicrosecond(source.microsecond()); + return; + case CalendarField::Nanosecond: + setNanosecond(source.nanosecond()); + return; + case CalendarField::Offset: + setOffset(source.offset()); + return; + case CalendarField::TimeZone: + setTimeZone(source.timeZone()); + return; + } + MOZ_CRASH("invalid temporal field"); +} + +static PropertyName* ToPropertyName(JSContext* cx, CalendarField field) { + switch (field) { + case CalendarField::Era: + return cx->names().era; + case CalendarField::EraYear: + return cx->names().eraYear; + case CalendarField::Year: + return cx->names().year; + case CalendarField::Month: + return cx->names().month; + case CalendarField::MonthCode: + return cx->names().monthCode; + case CalendarField::Day: + return cx->names().day; + case CalendarField::Hour: + return cx->names().hour; + case CalendarField::Minute: + return cx->names().minute; + case CalendarField::Second: + return cx->names().second; + case CalendarField::Millisecond: + return cx->names().millisecond; + case CalendarField::Microsecond: + return cx->names().microsecond; + case CalendarField::Nanosecond: + return cx->names().nanosecond; + case CalendarField::Offset: + return cx->names().offset; + case CalendarField::TimeZone: + return cx->names().timeZone; + } + MOZ_CRASH("invalid temporal field name"); +} + +static constexpr const char* ToCString(CalendarField field) { + switch (field) { + case CalendarField::Era: + return "era"; + case CalendarField::EraYear: + return "eraYear"; + case CalendarField::Year: + return "year"; + case CalendarField::Month: + return "month"; + case CalendarField::MonthCode: + return "monthCode"; + case CalendarField::Day: + return "day"; + case CalendarField::Hour: + return "hour"; + case CalendarField::Minute: + return "minute"; + case CalendarField::Second: + return "second"; + case CalendarField::Millisecond: + return "millisecond"; + case CalendarField::Microsecond: + return "microsecond"; + case CalendarField::Nanosecond: + return "nanosecond"; + case CalendarField::Offset: + return "offset"; + case CalendarField::TimeZone: + return "timeZone"; + } + JS_CONSTEXPR_CRASH("invalid temporal field name"); +} + +static constexpr bool CalendarFieldsAreSorted() { + constexpr auto min = mozilla::ContiguousEnumValues::min; + constexpr auto max = mozilla::ContiguousEnumValues::max; + + auto field = min; + while (field != max) { + auto next = static_cast(mozilla::UnderlyingValue(field) + 1); + + auto a = std::string_view{ToCString(field)}; + auto b = std::string_view{ToCString(next)}; + if (a.compare(b) >= 0) { + return false; + } + field = next; + } + return true; +} + +/** + * CalendarExtraFields ( calendar, fields ) + */ +static mozilla::EnumSet CalendarExtraFields( + CalendarId calendar, mozilla::EnumSet fields) { + // Step 1. + if (calendar == CalendarId::ISO8601) { + return {}; + } + + // Step 2. + + // "era" and "eraYear" are relevant for calendars with multiple eras when + // "year" is present. + if (fields.contains(CalendarField::Year) && CalendarEraRelevant(calendar)) { + return {CalendarField::Era, CalendarField::EraYear}; + } + return {}; +} + +/** + * ToMonthCode ( argument ) + */ +template +static mozilla::Maybe ToMonthCode( + mozilla::Range chars) { + // Steps 1-2. (Not applicable) + + // Step 3. + // + // Caller is responsible to ensure the string has the correct length. + MOZ_ASSERT(chars.length() >= 3 && chars.length() <= 4); + + // Steps 4 and 7. + // + // Starts with capital letter 'M'. Leap months end with capital letter 'L'. + bool isLeapMonth = chars.length() == 4; + if (chars[0] != 'M' || (isLeapMonth && chars[3] != 'L')) { + return mozilla::Nothing(); + } + + // Steps 5-6. + // + // Month numbers are ASCII digits. + if (!mozilla::IsAsciiDigit(chars[1]) || !mozilla::IsAsciiDigit(chars[2])) { + return mozilla::Nothing(); + } + + // Steps 8-9. + int32_t ordinal = + AsciiDigitToNumber(chars[1]) * 10 + AsciiDigitToNumber(chars[2]); + + // Step 10. + if (ordinal == 0 && !isLeapMonth) { + return mozilla::Nothing(); + } + + // Step 11. + return mozilla::Some(MonthCodeField{ordinal, isLeapMonth}); +} + +/** + * ToMonthCode ( argument ) + */ +static auto ToMonthCode(const JSLinearString* linear) { + JS::AutoCheckCannotGC nogc; + + if (linear->hasLatin1Chars()) { + return ToMonthCode(linear->latin1Range(nogc)); + } + return ToMonthCode(linear->twoByteRange(nogc)); +} + +/** + * ToMonthCode ( argument ) + */ +static bool ToMonthCode(JSContext* cx, Handle value, + MonthCodeField* result) { + auto reportInvalidMonthCode = [&](JSLinearString* monthCode) { + if (auto code = QuoteString(cx, monthCode)) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, + code.get()); + } + return false; + }; + + // Step 1. + Rooted monthCode(cx, value); + if (!ToPrimitive(cx, JSTYPE_STRING, &monthCode)) { + return false; + } + + // Step 2. + if (!monthCode.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, monthCode, + nullptr, "not a string"); + return false; + } + + JSLinearString* monthCodeStr = monthCode.toString()->ensureLinear(cx); + if (!monthCodeStr) { + return false; + } + + // Step 3. + if (monthCodeStr->length() < 3 || monthCodeStr->length() > 4) { + return reportInvalidMonthCode(monthCodeStr); + } + + // Steps 4-11. + auto parsed = ToMonthCode(monthCodeStr); + if (!parsed) { + return reportInvalidMonthCode(monthCodeStr); + } + + *result = *parsed; + return true; +} + +/** + * ToOffsetString ( argument ) + */ +static bool ToOffsetString(JSContext* cx, Handle value, + int64_t* result) { + // Step 1. + Rooted offset(cx, value); + if (!ToPrimitive(cx, JSTYPE_STRING, &offset)) { + return false; + } + + // Step 2. + if (!offset.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, offset, + nullptr, "not a string"); + return false; + } + Rooted offsetStr(cx, offset.toString()); + + // Steps 3-4. + return ParseDateTimeUTCOffset(cx, offsetStr, result); +} + +enum class Partial : bool { No, Yes }; + +/** + * PrepareCalendarFields ( calendar, fields, calendarFieldNames, + * nonCalendarFieldNames, requiredFieldNames ) + */ +static bool PrepareCalendarFields( + JSContext* cx, Handle calendar, Handle fields, + mozilla::EnumSet fieldNames, + mozilla::EnumSet requiredFields, Partial partial, + MutableHandle result) { + MOZ_ASSERT_IF(partial == Partial::Yes, requiredFields.isEmpty()); + + // Steps 1-2. (Not applicable in our implementation.) + + // Step 3. + auto extraFieldNames = CalendarExtraFields(calendar.identifier(), fieldNames); + + // Step 4. + fieldNames += extraFieldNames; + + // Step 5. (Not applicable in our implementation.) + + // Step 6. + // + // Default initialize the result. + result.set(CalendarFields{}); + + // Step 7. (Not applicable in our implementation.) + + // Step 8. + static_assert(CalendarFieldsAreSorted(), + "EnumSet iteration is sorted"); + + // Step 9. + Rooted value(cx); + for (auto fieldName : fieldNames) { + auto* propertyName = ToPropertyName(cx, fieldName); + const auto* cstr = ToCString(fieldName); + + // Step 9.a. (Not applicable in our implementation.) + + // Step 9.b. + if (!GetProperty(cx, fields, fields, propertyName, &value)) { + return false; + } + + // Steps 9.c-d. + if (!value.isUndefined()) { + // Steps 9.c.i-ii. (Not applicable in our implementation.) + + // Steps 9.c.iii-ix. + switch (fieldName) { + case CalendarField::Era: { + JSString* era = ToString(cx, value); + if (!era) { + return false; + } + result.setEra(era); + break; + } + case CalendarField::EraYear: { + double eraYear; + if (!ToIntegerWithTruncation(cx, value, cstr, &eraYear)) { + return false; + } + result.setEraYear(eraYear); + break; + } + case CalendarField::Year: { + double year; + if (!ToIntegerWithTruncation(cx, value, cstr, &year)) { + return false; + } + result.setYear(year); + break; + } + case CalendarField::Month: { + double month; + if (!ToPositiveIntegerWithTruncation(cx, value, cstr, &month)) { + return false; + } + result.setMonth(month); + break; + } + case CalendarField::MonthCode: { + MonthCodeField monthCode; + if (!ToMonthCode(cx, value, &monthCode)) { + return false; + } + result.setMonthCode(monthCode); + break; + } + case CalendarField::Day: { + double day; + if (!ToPositiveIntegerWithTruncation(cx, value, cstr, &day)) { + return false; + } + result.setDay(day); + break; + } + case CalendarField::Hour: { + double hour; + if (!ToIntegerWithTruncation(cx, value, cstr, &hour)) { + return false; + } + result.setHour(hour); + break; + } + case CalendarField::Minute: { + double minute; + if (!ToIntegerWithTruncation(cx, value, cstr, &minute)) { + return false; + } + result.setMinute(minute); + break; + } + case CalendarField::Second: { + double second; + if (!ToIntegerWithTruncation(cx, value, cstr, &second)) { + return false; + } + result.setSecond(second); + break; + } + case CalendarField::Millisecond: { + double millisecond; + if (!ToIntegerWithTruncation(cx, value, cstr, &millisecond)) { + return false; + } + result.setMillisecond(millisecond); + break; + } + case CalendarField::Microsecond: { + double microsecond; + if (!ToIntegerWithTruncation(cx, value, cstr, µsecond)) { + return false; + } + result.setMicrosecond(microsecond); + break; + } + case CalendarField::Nanosecond: { + double nanosecond; + if (!ToIntegerWithTruncation(cx, value, cstr, &nanosecond)) { + return false; + } + result.setNanosecond(nanosecond); + break; + } + case CalendarField::Offset: { + int64_t offset; + if (!ToOffsetString(cx, value, &offset)) { + return false; + } + result.setOffset(OffsetField{offset}); + break; + } + case CalendarField::TimeZone: + Rooted timeZone(cx); + if (!ToTemporalTimeZone(cx, value, &timeZone)) { + return false; + } + result.setTimeZone(timeZone); + break; + } + } else if (partial == Partial::No) { + // Step 9.d.i. + if (requiredFields.contains(fieldName)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_MISSING_PROPERTY, cstr); + return false; + } + + // Step 9.d.ii. + result.setDefault(fieldName); + } + } + + // Step 10. + if (partial == Partial::Yes && result.keys().isEmpty()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_MISSING_TEMPORAL_FIELDS); + return false; + } + + // Step 11. + return true; +} + +/** + * PrepareCalendarFields ( calendar, fields, calendarFieldNames, + * nonCalendarFieldNames, requiredFieldNames ) + */ +bool js::temporal::PrepareCalendarFields( + JSContext* cx, Handle calendar, Handle fields, + mozilla::EnumSet fieldNames, + mozilla::EnumSet requiredFields, + MutableHandle result) { + return PrepareCalendarFields(cx, calendar, fields, fieldNames, requiredFields, + Partial::No, result); +} + +/** + * PrepareCalendarFields ( calendar, fields, calendarFieldNames, + * nonCalendarFieldNames, requiredFieldNames ) + */ +bool js::temporal::PreparePartialCalendarFields( + JSContext* cx, Handle calendar, Handle fields, + mozilla::EnumSet fieldNames, + JS::MutableHandle result) { + return PrepareCalendarFields(cx, calendar, fields, fieldNames, {}, + Partial::Yes, result); +} + +/** + * CalendarFieldKeysToIgnore ( calendar, keys ) + */ +static auto CalendarFieldKeysToIgnore(CalendarId calendar, + mozilla::EnumSet keys) { + // Step 1. + if (calendar == CalendarId::ISO8601) { + // Steps 1.a and 1.b.i. + auto ignoredKeys = keys; + + // Step 1.b.ii. + if (keys.contains(CalendarField::Month)) { + ignoredKeys += CalendarField::MonthCode; + } + + // Step 1.b.iii. + else if (keys.contains(CalendarField::MonthCode)) { + ignoredKeys += CalendarField::Month; + } + + // Steps 1.c-d. + return ignoredKeys; + } + + // Step 2. + + static constexpr auto eraOrEraYear = mozilla::EnumSet{ + CalendarField::Era, + CalendarField::EraYear, + }; + + static constexpr auto eraOrAnyYear = mozilla::EnumSet{ + CalendarField::Era, + CalendarField::EraYear, + CalendarField::Year, + }; + + static constexpr auto monthOrMonthCode = mozilla::EnumSet{ + CalendarField::Month, + CalendarField::MonthCode, + }; + + static constexpr auto dayOrAnyMonth = mozilla::EnumSet{ + CalendarField::Day, + CalendarField::Month, + CalendarField::MonthCode, + }; + + // A field always invalidates at least itself, so start with ignoring all + // input fields. + auto result = keys; + + // "month" and "monthCode" are mutually exclusive. + if (!(keys & monthOrMonthCode).isEmpty()) { + result += monthOrMonthCode; + } + + // "era", "eraYear", and "year" are mutually exclusive in non-single era + // calendar systems. + if (CalendarEraRelevant(calendar) && !(keys & eraOrAnyYear).isEmpty()) { + result += eraOrAnyYear; + } + + // If eras don't start at year boundaries, we have to ignore "era" and + // "eraYear" if any of "day", "month", or "monthCode" is present. + if (!CalendarEraStartsAtYearBoundary(calendar) && + !(keys & dayOrAnyMonth).isEmpty()) { + result += eraOrEraYear; + } + + return result; +} + +/** + * CalendarMergeFields ( calendar, fields, additionalFields ) + */ +CalendarFields js::temporal::CalendarMergeFields( + const CalendarValue& calendar, const CalendarFields& fields, + const CalendarFields& additionalFields) { + auto calendarId = calendar.identifier(); + + // Steps 1. + auto additionalKeys = additionalFields.keys(); + + // Step 2. + auto overriddenKeys = CalendarFieldKeysToIgnore(calendarId, additionalKeys); + MOZ_ASSERT(overriddenKeys.contains(additionalKeys)); + + // Step 3. + auto merged = CalendarFields{}; + + // Step 4. + auto fieldsKeys = fields.keys(); + + // Step 5.b. + for (auto key : (fieldsKeys - overriddenKeys)) { + merged.setFrom(key, fields); + } + + // Step 5.c. + for (auto key : additionalKeys) { + merged.setFrom(key, additionalFields); + } + + // Step 6. + return merged; +} diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.h new file mode 100644 index 00000000000..f81060473c8 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/CalendarFields.h @@ -0,0 +1,387 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_temporal_CalendarFields_h +#define builtin_temporal_CalendarFields_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/EnumSet.h" +#include "mozilla/EnumTypeTraits.h" +#include "mozilla/FloatingPoint.h" + +#include +#include + +#include "jstypes.h" + +#include "builtin/temporal/MonthCode.h" +#include "builtin/temporal/TemporalUnit.h" +#include "builtin/temporal/TimeZone.h" +#include "js/RootingAPI.h" +#include "js/TypeDecls.h" + +class JS_PUBLIC_API JSTracer; + +namespace js::temporal { + +// NB: The fields must be sorted alphabetically! +enum class CalendarField { + Day, + Era, + EraYear, + Hour, + Microsecond, + Millisecond, + Minute, + Month, + MonthCode, + Nanosecond, + Offset, + Second, + TimeZone, + Year, +}; + +class MonthCodeField final { + // Packed representation for ordinal month (31 bits) and leap month (1 bit). + uint32_t code_ = 0; + + public: + MonthCodeField() = default; + + MonthCodeField(int32_t ordinal, bool isLeapMonth) + : code_((ordinal << 1) | isLeapMonth) { + MOZ_ASSERT(ordinal >= 0); + MOZ_ASSERT_IF(ordinal == 0, isLeapMonth); + } + + MOZ_IMPLICIT MonthCodeField(MonthCode monthCode) + : MonthCodeField(monthCode.ordinal(), monthCode.isLeapMonth()) {} + + int32_t ordinal() const { return (code_ >> 1); } + + bool isLeapMonth() const { return bool(code_ & 1); } +}; + +class OffsetField final { + int64_t offset_ = INT64_MIN; + + public: + OffsetField() = default; + + explicit OffsetField(int64_t offset) : offset_(offset) { + MOZ_ASSERT(std::abs(offset) < ToNanoseconds(TemporalUnit::Day)); + } + + explicit operator int64_t() const { + MOZ_ASSERT(offset_ != INT64_MIN); + return offset_; + } +}; + +// Default values are specified in [1]. `UNSET` is replaced with an appropriate +// value based on the type, for example `double` fields use NaN whereas pointer +// fields use nullptr. +// +// [1] +// +class MOZ_STACK_CLASS CalendarFields final { + mozilla::EnumSet fields_ = {}; + + JSString* era_ = nullptr; + double eraYear_ = mozilla::UnspecifiedNaN(); + double year_ = mozilla::UnspecifiedNaN(); + double month_ = mozilla::UnspecifiedNaN(); + MonthCodeField monthCode_ = {}; + double day_ = mozilla::UnspecifiedNaN(); + double hour_ = 0; + double minute_ = 0; + double second_ = 0; + double millisecond_ = 0; + double microsecond_ = 0; + double nanosecond_ = 0; + OffsetField offset_ = {}; + TimeZoneValue timeZone_ = {}; + + public: + CalendarFields() = default; + CalendarFields(const CalendarFields&) = default; + + auto* era() const { return era_; } + auto eraYear() const { return eraYear_; } + auto year() const { return year_; } + auto month() const { return month_; } + auto monthCode() const { return monthCode_; } + auto day() const { return day_; } + auto hour() const { return hour_; } + auto minute() const { return minute_; } + auto second() const { return second_; } + auto millisecond() const { return millisecond_; } + auto microsecond() const { return microsecond_; } + auto nanosecond() const { return nanosecond_; } + auto offset() const { return offset_; } + auto& timeZone() const { return timeZone_; } + + void setEra(JSString* era) { + fields_ += CalendarField::Era; + era_ = era; + } + void setEraYear(double eraYear) { + fields_ += CalendarField::EraYear; + eraYear_ = eraYear; + } + void setYear(double year) { + fields_ += CalendarField::Year; + year_ = year; + } + void setMonth(double month) { + fields_ += CalendarField::Month; + month_ = month; + } + void setMonthCode(MonthCodeField monthCode) { + fields_ += CalendarField::MonthCode; + monthCode_ = monthCode; + } + void setDay(double day) { + fields_ += CalendarField::Day; + day_ = day; + } + void setHour(double hour) { + fields_ += CalendarField::Hour; + hour_ = hour; + } + void setMinute(double minute) { + fields_ += CalendarField::Minute; + minute_ = minute; + } + void setSecond(double second) { + fields_ += CalendarField::Second; + second_ = second; + } + void setMillisecond(double millisecond) { + fields_ += CalendarField::Millisecond; + millisecond_ = millisecond; + } + void setMicrosecond(double microsecond) { + fields_ += CalendarField::Microsecond; + microsecond_ = microsecond; + } + void setNanosecond(double nanosecond) { + fields_ += CalendarField::Nanosecond; + nanosecond_ = nanosecond; + } + void setOffset(OffsetField offset) { + fields_ += CalendarField::Offset; + offset_ = offset; + } + void setTimeZone(const TimeZoneValue& timeZone) { + fields_ += CalendarField::TimeZone; + timeZone_ = timeZone; + } + + /** + * Return `true` if the field is present. + */ + bool has(CalendarField field) const { return fields_.contains(field); } + + /** + * Return the set of all present fields. + */ + mozilla::EnumSet keys() const { return fields_; } + + /** + * Mark that `field` is present, but uses its default value. The field must + * not already be present in `this`. + */ + void setDefault(CalendarField field) { + MOZ_ASSERT(!fields_.contains(field)); + + // Field whose default value is not UNSET. + static constexpr mozilla::EnumSet notUnsetDefault = { + CalendarField::Hour, CalendarField::Minute, + CalendarField::Second, CalendarField::Millisecond, + CalendarField::Microsecond, CalendarField::Nanosecond, + }; + + // Fields whose default value is UNSET are ignored. + if (notUnsetDefault.contains(field)) { + fields_ += field; + } + } + + /** + * Set `field` from `source`. The field must be present in `source`. + */ + void setFrom(CalendarField field, const CalendarFields& source); + + // Helper methods for WrappedPtrOperations. + auto eraDoNotUse() const { return &era_; } + auto timeZoneDoNotUse() const { return &timeZone_; } + + // Trace implementation. + void trace(JSTracer* trc); +}; +} // namespace js::temporal + +namespace js { + +template +class WrappedPtrOperations { + const temporal::CalendarFields& container() const { + return static_cast(this)->get(); + } + + public: + JS::Handle era() const { + return JS::Handle::fromMarkedLocation(container().eraDoNotUse()); + } + double eraYear() const { return container().eraYear(); } + double year() const { return container().year(); } + double month() const { return container().month(); } + temporal::MonthCodeField monthCode() const { return container().monthCode(); } + double day() const { return container().day(); } + double hour() const { return container().hour(); } + double minute() const { return container().minute(); } + double second() const { return container().second(); } + double millisecond() const { return container().millisecond(); } + double microsecond() const { return container().microsecond(); } + double nanosecond() const { return container().nanosecond(); } + temporal::OffsetField offset() const { return container().offset(); } + JS::Handle timeZone() const { + return JS::Handle::fromMarkedLocation( + container().timeZoneDoNotUse()); + } + + bool has(temporal::CalendarField field) const { + return container().has(field); + } + auto keys() const { return container().keys(); } +}; + +template +class MutableWrappedPtrOperations + : public WrappedPtrOperations { + temporal::CalendarFields& container() { + return static_cast(this)->get(); + } + + public: + void setEra(JSString* era) { container().setEra(era); } + void setEraYear(double eraYear) { container().setEraYear(eraYear); } + void setYear(double year) { container().setYear(year); } + void setMonth(double month) { container().setMonth(month); } + void setMonthCode(temporal::MonthCodeField monthCode) { + container().setMonthCode(monthCode); + } + void setDay(double day) { container().setDay(day); } + void setHour(double hour) { container().setHour(hour); } + void setMinute(double minute) { container().setMinute(minute); } + void setSecond(double second) { container().setSecond(second); } + void setMillisecond(double millisecond) { + container().setMillisecond(millisecond); + } + void setMicrosecond(double microsecond) { + container().setMicrosecond(microsecond); + } + void setNanosecond(double nanosecond) { + container().setNanosecond(nanosecond); + } + void setOffset(temporal::OffsetField offset) { + container().setOffset(offset); + } + void setTimeZone(const temporal::TimeZoneValue& timeZone) { + container().setTimeZone(timeZone); + } + + void setDefault(temporal::CalendarField field) { + container().setDefault(field); + } +}; + +} // namespace js + +namespace js::temporal { + +class CalendarValue; +class PlainDate; +class PlainDateTime; +class PlainMonthDay; +class PlainYearMonth; + +/** + * PrepareCalendarFields ( calendar, fields, calendarFieldNames, + * nonCalendarFieldNames, requiredFieldNames ) + */ +bool PrepareCalendarFields(JSContext* cx, JS::Handle calendar, + JS::Handle fields, + mozilla::EnumSet fieldNames, + mozilla::EnumSet requiredFields, + JS::MutableHandle result); + +/** + * PrepareCalendarFields ( calendar, fields, calendarFieldNames, + * nonCalendarFieldNames, requiredFieldNames ) + */ +inline bool PrepareCalendarFields(JSContext* cx, + JS::Handle calendar, + JS::Handle fields, + mozilla::EnumSet fieldNames, + JS::MutableHandle result) { + return PrepareCalendarFields(cx, calendar, fields, fieldNames, {}, result); +} + +/** + * PrepareCalendarFields ( calendar, fields, calendarFieldNames, + * nonCalendarFieldNames, requiredFieldNames ) + */ +bool PreparePartialCalendarFields(JSContext* cx, + JS::Handle calendar, + JS::Handle fields, + mozilla::EnumSet fieldNames, + JS::MutableHandle result); + +/** + * CalendarMergeFields ( calendar, fields, additionalFields ) + */ +CalendarFields CalendarMergeFields(const CalendarValue& calendar, + const CalendarFields& fields, + const CalendarFields& additionalFields); + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool ISODateToFields(JSContext* cx, Handle date, + MutableHandle result); + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool ISODateToFields(JSContext* cx, Handle dateTime, + MutableHandle result); + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool ISODateToFields(JSContext* cx, Handle monthDay, + MutableHandle result); + +/** + * ISODateToFields ( calendar, isoDate, type ) + */ +bool ISODateToFields(JSContext* cx, Handle yearMonth, + MutableHandle result); + +} /* namespace js::temporal */ + +namespace mozilla { +template <> +struct MaxContiguousEnumValue { + static constexpr auto value = js::temporal::CalendarField::Year; +}; +} // namespace mozilla + +#endif /* builtin_temporal_CalendarFields_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.cpp index 57622180dc7..e4c28ff6a1f 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.cpp @@ -9,7 +9,6 @@ #include "mozilla/Assertions.h" #include "mozilla/Casting.h" #include "mozilla/CheckedInt.h" -#include "mozilla/EnumSet.h" #include "mozilla/FloatingPoint.h" #include "mozilla/Maybe.h" @@ -25,20 +24,21 @@ #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DurationFormat.h" #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/CalendarFields.h" #include "builtin/temporal/Instant.h" #include "builtin/temporal/Int128.h" #include "builtin/temporal/Int96.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainDateTime.h" +#include "builtin/temporal/PlainTime.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/TimeZone.h" -#include "builtin/temporal/Wrapped.h" #include "builtin/temporal/ZonedDateTime.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" @@ -49,20 +49,17 @@ #include "js/Conversions.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/Printer.h" #include "js/PropertyDescriptor.h" #include "js/PropertySpec.h" #include "js/RootingAPI.h" #include "js/Value.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/BytecodeUtil.h" #include "vm/GlobalObject.h" #include "vm/JSAtomState.h" #include "vm/JSContext.h" #include "vm/JSObject.h" -#include "vm/ObjectOperations.h" #include "vm/PlainObject.h" #include "vm/StringType.h" @@ -106,15 +103,8 @@ static bool IsIntegerDuration(const Duration& duration) { } #endif -static constexpr bool IsSafeInteger(int64_t x) { - constexpr int64_t MaxSafeInteger = int64_t(1) << 53; - constexpr int64_t MinSafeInteger = -MaxSafeInteger; - return MinSafeInteger < x && x < MaxSafeInteger; -} - /** - * DurationSign ( years, months, weeks, days, hours, minutes, seconds, - * milliseconds, microseconds, nanoseconds ) + * DurationSign ( duration ) */ int32_t js::temporal::DurationSign(const Duration& duration) { MOZ_ASSERT(IsIntegerOrInfinityDuration(duration)); @@ -141,10 +131,9 @@ int32_t js::temporal::DurationSign(const Duration& duration) { } /** - * DurationSign ( years, months, weeks, days, hours, minutes, seconds, - * milliseconds, microseconds, nanoseconds ) + * DateDurationSign ( dateDuration ) */ -int32_t js::temporal::DurationSign(const DateDuration& duration) { +int32_t js::temporal::DateDurationSign(const DateDuration& duration) { const auto& [years, months, weeks, days] = duration; // Step 1. @@ -165,89 +154,101 @@ int32_t js::temporal::DurationSign(const DateDuration& duration) { } /** - * Normalize a nanoseconds amount into a time duration. + * InternalDurationSign ( internalDuration ) */ -static NormalizedTimeDuration NormalizeNanoseconds(const Int96& nanoseconds) { - // Split into seconds and nanoseconds. - auto [seconds, nanos] = nanoseconds / ToNanoseconds(TemporalUnit::Second); +static int32_t InternalDurationSign(const InternalDuration& duration) { + MOZ_ASSERT(IsValidDuration(duration)); - return {seconds, nanos}; + if (int32_t sign = DateDurationSign(duration.date)) { + return sign; + } + return TimeDurationSign(duration.time); } /** - * Normalize a nanoseconds amount into a time duration. Return Nothing if the - * value is too large. + * Create a time duration from a nanoseconds amount. */ -static mozilla::Maybe NormalizeNanoseconds( +static TimeDuration TimeDurationFromNanoseconds(const Int96& nanoseconds) { + // Split into seconds and nanoseconds. + auto [seconds, nanos] = nanoseconds / ToNanoseconds(TemporalUnit::Second); + + return {{seconds, nanos}}; +} + +/** + * Create a time duration from a nanoseconds amount. Return Nothing if the value + * is too large. + */ +static mozilla::Maybe TimeDurationFromNanoseconds( double nanoseconds) { MOZ_ASSERT(IsInteger(nanoseconds)); if (auto int96 = Int96::fromInteger(nanoseconds)) { - // The number of normalized seconds must not exceed `2**53 - 1`. + // The number of time duration seconds must not exceed `2**53 - 1`. constexpr auto limit = Int96{uint64_t(1) << 53} * ToNanoseconds(TemporalUnit::Second); if (int96->abs() < limit) { - return mozilla::Some(NormalizeNanoseconds(*int96)); + return mozilla::Some(TimeDurationFromNanoseconds(*int96)); } } return mozilla::Nothing(); } /** - * Normalize a microseconds amount into a time duration. + * Create a time duration from a microseconds amount. */ -static NormalizedTimeDuration NormalizeMicroseconds(const Int96& microseconds) { +static TimeDuration TimeDurationFromMicroseconds(const Int96& microseconds) { // Split into seconds and microseconds. auto [seconds, micros] = microseconds / ToMicroseconds(TemporalUnit::Second); // Scale microseconds to nanoseconds. int32_t nanos = micros * int32_t(ToNanoseconds(TemporalUnit::Microsecond)); - return {seconds, nanos}; + return {{seconds, nanos}}; } /** - * Normalize a microseconds amount into a time duration. Return Nothing if the + * Create a time duration from a microseconds amount. Return Nothing if the * value is too large. */ -static mozilla::Maybe NormalizeMicroseconds( +static mozilla::Maybe TimeDurationFromMicroseconds( double microseconds) { MOZ_ASSERT(IsInteger(microseconds)); if (auto int96 = Int96::fromInteger(microseconds)) { - // The number of normalized seconds must not exceed `2**53 - 1`. + // The number of time duration seconds must not exceed `2**53 - 1`. constexpr auto limit = Int96{uint64_t(1) << 53} * ToMicroseconds(TemporalUnit::Second); if (int96->abs() < limit) { - return mozilla::Some(NormalizeMicroseconds(*int96)); + return mozilla::Some(TimeDurationFromMicroseconds(*int96)); } } return mozilla::Nothing(); } /** - * Normalize a duration into a time duration. Return Nothing if any duration + * Create a time duration from a duration. Return Nothing if any duration * value is too large. */ -static mozilla::Maybe NormalizeSeconds( +static mozilla::Maybe TimeDurationFromDuration( const Duration& duration) { do { - auto nanoseconds = NormalizeNanoseconds(duration.nanoseconds); + auto nanoseconds = TimeDurationFromNanoseconds(duration.nanoseconds); if (!nanoseconds) { break; } - MOZ_ASSERT(IsValidNormalizedTimeDuration(*nanoseconds)); + MOZ_ASSERT(IsValidTimeDuration(*nanoseconds)); - auto microseconds = NormalizeMicroseconds(duration.microseconds); + auto microseconds = TimeDurationFromMicroseconds(duration.microseconds); if (!microseconds) { break; } - MOZ_ASSERT(IsValidNormalizedTimeDuration(*microseconds)); + MOZ_ASSERT(IsValidTimeDuration(*microseconds)); // Overflows for millis/seconds/minutes/hours/days always result in an - // invalid normalized time duration. + // invalid time duration. int64_t milliseconds; if (!mozilla::NumberEqualsInt64(duration.milliseconds, &milliseconds)) { @@ -288,14 +289,14 @@ static mozilla::Maybe NormalizeSeconds( break; } - auto milli = NormalizedTimeDuration::fromMilliseconds(millis.value()); - if (!IsValidNormalizedTimeDuration(milli)) { + auto milli = TimeDuration::fromMilliseconds(millis.value()); + if (!IsValidTimeDuration(milli)) { break; } // Compute the overall time duration. auto result = milli + *microseconds + *nanoseconds; - if (!IsValidNormalizedTimeDuration(result)) { + if (!IsValidTimeDuration(result)) { break; } @@ -306,36 +307,14 @@ static mozilla::Maybe NormalizeSeconds( } /** - * Normalize a days amount into a time duration. Return Nothing if the value is - * too large. + * TimeDurationFromComponents ( hours, minutes, seconds, milliseconds, + * microseconds, nanoseconds ) */ -static mozilla::Maybe NormalizeDays(int64_t days) { - do { - // Compute the overall amount of milliseconds. - auto millis = - mozilla::CheckedInt64(days) * ToMilliseconds(TemporalUnit::Day); - if (!millis.isValid()) { - break; - } - - auto result = NormalizedTimeDuration::fromMilliseconds(millis.value()); - if (!IsValidNormalizedTimeDuration(result)) { - break; - } - - return mozilla::Some(result); - } while (false); - - return mozilla::Nothing(); -} - -/** - * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds, - * nanoseconds ) - */ -static NormalizedTimeDuration NormalizeTimeDuration( - double hours, double minutes, double seconds, double milliseconds, - double microseconds, double nanoseconds) { +static TimeDuration TimeDurationFromComponents(double hours, double minutes, + double seconds, + double milliseconds, + double microseconds, + double nanoseconds) { MOZ_ASSERT(IsInteger(hours)); MOZ_ASSERT(IsInteger(minutes)); MOZ_ASSERT(IsInteger(seconds)); @@ -353,87 +332,64 @@ static NormalizedTimeDuration NormalizeTimeDuration( millis += int64_t(milliseconds); MOZ_ASSERT(millis.isValid()); - auto normalized = NormalizedTimeDuration::fromMilliseconds(millis.value()); + auto timeDuration = TimeDuration::fromMilliseconds(millis.value()); // Step 4. auto micros = Int96::fromInteger(microseconds); MOZ_ASSERT(micros); - normalized += NormalizeMicroseconds(*micros); + timeDuration += TimeDurationFromMicroseconds(*micros); // Step 5. auto nanos = Int96::fromInteger(nanoseconds); MOZ_ASSERT(nanos); - normalized += NormalizeNanoseconds(*nanos); + timeDuration += TimeDurationFromNanoseconds(*nanos); // Step 6. - MOZ_ASSERT(IsValidNormalizedTimeDuration(normalized)); + MOZ_ASSERT(IsValidTimeDuration(timeDuration)); // Step 7. - return normalized; + return timeDuration; } /** - * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds, - * nanoseconds ) + * TimeDurationFromComponents ( hours, minutes, seconds, milliseconds, + * microseconds, nanoseconds ) */ -NormalizedTimeDuration js::temporal::NormalizeTimeDuration( - int32_t hours, int32_t minutes, int32_t seconds, int32_t milliseconds, - int32_t microseconds, int32_t nanoseconds) { - // Steps 1-3. - mozilla::CheckedInt64 millis = int64_t(hours); - millis *= 60; - millis += int64_t(minutes); - millis *= 60; - millis += int64_t(seconds); - millis *= 1000; - millis += int64_t(milliseconds); - MOZ_ASSERT(millis.isValid()); - - auto normalized = NormalizedTimeDuration::fromMilliseconds(millis.value()); - - // Step 4. - normalized += NormalizeMicroseconds(Int96{microseconds}); - - // Step 5. - normalized += NormalizeNanoseconds(Int96{nanoseconds}); - - // Step 6. - MOZ_ASSERT(IsValidNormalizedTimeDuration(normalized)); - - // Step 7. - return normalized; -} - -/** - * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds, - * nanoseconds ) - */ -NormalizedTimeDuration js::temporal::NormalizeTimeDuration( +TimeDuration js::temporal::TimeDurationFromComponents( const Duration& duration) { MOZ_ASSERT(IsValidDuration(duration)); - return ::NormalizeTimeDuration(duration.hours, duration.minutes, - duration.seconds, duration.milliseconds, - duration.microseconds, duration.nanoseconds); + return ::TimeDurationFromComponents( + duration.hours, duration.minutes, duration.seconds, duration.milliseconds, + duration.microseconds, duration.nanoseconds); } /** - * AddNormalizedTimeDuration ( one, two ) + * Add24HourDaysToTimeDuration ( d, days ) */ -static bool AddNormalizedTimeDuration(JSContext* cx, - const NormalizedTimeDuration& one, - const NormalizedTimeDuration& two, - NormalizedTimeDuration* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(one)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(two)); +static bool Add24HourDaysToTimeDuration(JSContext* cx, const TimeDuration& d, + int64_t days, TimeDuration* result) { + MOZ_ASSERT(IsValidTimeDuration(d)); // Step 1. - auto sum = one + two; + if (days > TimeDuration::max().toDays()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + + auto timeDurationDays = TimeDuration::fromDays(days); + if (!IsValidTimeDuration(timeDurationDays)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } // Step 2. - if (!IsValidNormalizedTimeDuration(sum)) { + auto sum = d + timeDurationDays; + if (!IsValidTimeDuration(sum)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); return false; @@ -445,105 +401,439 @@ static bool AddNormalizedTimeDuration(JSContext* cx, } /** - * SubtractNormalizedTimeDuration ( one, two ) + * ToInternalDurationRecordWith24HourDays ( duration ) */ -static bool SubtractNormalizedTimeDuration(JSContext* cx, - const NormalizedTimeDuration& one, - const NormalizedTimeDuration& two, - NormalizedTimeDuration* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(one)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(two)); +InternalDuration js::temporal::ToInternalDurationRecordWith24HourDays( + const Duration& duration) { + MOZ_ASSERT(IsValidDuration(duration)); // Step 1. - auto sum = one - two; + auto timeDuration = TimeDurationFromComponents(duration); - // Step 2. - if (!IsValidNormalizedTimeDuration(sum)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } + // Step 2. (Inlined Add24HourDaysToTimeDuration) + timeDuration += TimeDuration::fromDays(int64_t(duration.days)); // Step 3. - *result = sum; - return true; + auto dateDuration = DateDuration{ + int64_t(duration.years), + int64_t(duration.months), + int64_t(duration.weeks), + 0, + }; + + // Step 4. (Inlined CombineDateAndTimeDuration) + return InternalDuration{dateDuration, timeDuration}; } /** - * Add24HourDaysToNormalizedTimeDuration ( d, days ) + * ToDateDurationRecordWithoutTime ( duration ) */ -bool js::temporal::Add24HourDaysToNormalizedTimeDuration( - JSContext* cx, const NormalizedTimeDuration& d, int64_t days, - NormalizedTimeDuration* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(d)); - +DateDuration js::temporal::ToDateDurationRecordWithoutTime( + const Duration& duration) { // Step 1. - auto normalizedDays = NormalizeDays(days); - if (!normalizedDays) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } + auto internalDuration = ToInternalDurationRecordWith24HourDays(duration); // Step 2. - auto sum = d + *normalizedDays; - if (!IsValidNormalizedTimeDuration(sum)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } + int64_t days = internalDuration.time.toDays(); // Step 3. - *result = sum; - return true; + auto result = DateDuration{ + internalDuration.date.years, + internalDuration.date.months, + internalDuration.date.weeks, + days, + }; + MOZ_ASSERT(IsValidDuration(result)); + + return result; } /** - * CombineDateAndNormalizedTimeDuration ( dateDurationRecord, norm ) + * TemporalDurationFromInternal ( internalDuration, largestUnit ) */ -bool js::temporal::CombineDateAndNormalizedTimeDuration( - JSContext* cx, const DateDuration& date, const NormalizedTimeDuration& time, - NormalizedDuration* result) { - MOZ_ASSERT(IsValidDuration(date)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(time)); +static Duration TemporalDurationFromInternal(const TimeDuration& timeDuration, + TemporalUnit largestUnit) { + MOZ_ASSERT(IsValidTimeDuration(timeDuration)); + MOZ_ASSERT(largestUnit <= TemporalUnit::Second, + "fallible fractional seconds units"); + + auto [seconds, nanoseconds] = timeDuration.denormalize(); // Step 1. - int32_t dateSign = DurationSign(date); + int64_t days = 0; + int64_t hours = 0; + int64_t minutes = 0; + int64_t milliseconds = 0; + int64_t microseconds = 0; - // Step 2. - int32_t timeSign = NormalizedTimeDurationSign(time); + // Steps 2-3. (Not applicable in our implementation.) + // + // We don't need to convert to positive numbers, because integer division + // truncates and the %-operator has modulo semantics. - // Step 3 - if ((dateSign * timeSign) < 0) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_COMBINE_INVALID_SIGN); - return false; + // Steps 4-11. + switch (largestUnit) { + // Step 4. + case TemporalUnit::Year: + case TemporalUnit::Month: + case TemporalUnit::Week: + case TemporalUnit::Day: { + // Step 4.a. + microseconds = nanoseconds / 1000; + + // Step 4.b. + nanoseconds = nanoseconds % 1000; + + // Step 4.c. + milliseconds = microseconds / 1000; + + // Step 4.d. + microseconds = microseconds % 1000; + + // Steps 4.e-f. (Not applicable) + MOZ_ASSERT(std::abs(milliseconds) <= 999); + + // Step 4.g. + minutes = seconds / 60; + + // Step 4.h. + seconds = seconds % 60; + + // Step 4.i. + hours = minutes / 60; + + // Step 4.j. + minutes = minutes % 60; + + // Step 4.k. + days = hours / 24; + + // Step 4.l. + hours = hours % 24; + + break; + } + + // Step 5. + case TemporalUnit::Hour: { + // Step 5.a. + microseconds = nanoseconds / 1000; + + // Step 5.b. + nanoseconds = nanoseconds % 1000; + + // Step 5.c. + milliseconds = microseconds / 1000; + + // Step 5.d. + microseconds = microseconds % 1000; + + // Steps 5.e-f. (Not applicable) + MOZ_ASSERT(std::abs(milliseconds) <= 999); + + // Step 5.g. + minutes = seconds / 60; + + // Step 5.h. + seconds = seconds % 60; + + // Step 5.i. + hours = minutes / 60; + + // Step 5.j. + minutes = minutes % 60; + + break; + } + + case TemporalUnit::Minute: { + // Step 6.a. + microseconds = nanoseconds / 1000; + + // Step 6.b. + nanoseconds = nanoseconds % 1000; + + // Step 6.c. + milliseconds = microseconds / 1000; + + // Step 6.d. + microseconds = microseconds % 1000; + + // Steps 6.e-f. (Not applicable) + MOZ_ASSERT(std::abs(milliseconds) <= 999); + + // Step 6.g. + minutes = seconds / 60; + + // Step 6.h. + seconds = seconds % 60; + + break; + } + + // Step 7. + case TemporalUnit::Second: { + // Step 7.a. + microseconds = nanoseconds / 1000; + + // Step 7.b. + nanoseconds = nanoseconds % 1000; + + // Step 7.c. + milliseconds = microseconds / 1000; + + // Step 7.d. + microseconds = microseconds % 1000; + + // Steps 7.e-f. (Not applicable) + MOZ_ASSERT(std::abs(milliseconds) <= 999); + + break; + } + + // Steps 8-11. (Not applicable in our implementation) + case TemporalUnit::Millisecond: + case TemporalUnit::Microsecond: + case TemporalUnit::Nanosecond: + case TemporalUnit::Auto: + MOZ_CRASH("Unexpected temporal unit"); } - // Step 4. - *result = {date, time}; - return true; + // Step 12. + auto result = Duration{ + 0, + 0, + 0, + double(days), + double(hours), + double(minutes), + double(seconds), + double(milliseconds), + double(microseconds), + double(nanoseconds), + }; + MOZ_ASSERT(IsValidDuration(result)); + return result; } /** - * NormalizedTimeDurationFromEpochNanosecondsDifference ( one, two ) + * TemporalDurationFromInternal ( internalDuration, largestUnit ) */ -NormalizedTimeDuration -js::temporal::NormalizedTimeDurationFromEpochNanosecondsDifference( - const Instant& one, const Instant& two) { - MOZ_ASSERT(IsValidEpochInstant(one)); - MOZ_ASSERT(IsValidEpochInstant(two)); +bool js::temporal::TemporalDurationFromInternal( + JSContext* cx, const TimeDuration& timeDuration, TemporalUnit largestUnit, + Duration* result) { + MOZ_ASSERT(IsValidTimeDuration(timeDuration)); + + auto [seconds, nanoseconds] = timeDuration.denormalize(); + + // Steps 1-3. (Not applicable in our implementation.) + // + // We don't need to convert to positive numbers, because integer division + // truncates and the %-operator has modulo semantics. + + // Steps 4-10. + switch (largestUnit) { + // Steps 4-7. + case TemporalUnit::Year: + case TemporalUnit::Month: + case TemporalUnit::Week: + case TemporalUnit::Day: + case TemporalUnit::Hour: + case TemporalUnit::Minute: + case TemporalUnit::Second: + *result = ::TemporalDurationFromInternal(timeDuration, largestUnit); + return true; + + // Step 8. + case TemporalUnit::Millisecond: { + // Valid time durations must be below |limit|. + constexpr auto limit = TimeDuration::max().toMilliseconds() + 1; + + // The largest possible milliseconds value whose double representation + // doesn't exceed the time duration limit. + constexpr auto max = int64_t(0x7cff'ffff'ffff'fdff); + + // Assert |max| is the maximum allowed milliseconds value. + static_assert(double(max) < double(limit)); + static_assert(double(max + 1) >= double(limit)); + + static_assert((TimeDuration::max().seconds + 1) * + ToMilliseconds(TemporalUnit::Second) <= + INT64_MAX, + "total number duration milliseconds fits into int64"); + + // Step 8.a. + int64_t microseconds = nanoseconds / 1000; + + // Step 8.b. + nanoseconds = nanoseconds % 1000; + + // Step 8.c. + int64_t milliseconds = microseconds / 1000; + MOZ_ASSERT(std::abs(milliseconds) <= 999); + + // Step 8.d. + microseconds = microseconds % 1000; + + auto millis = + (seconds * ToMilliseconds(TemporalUnit::Second)) + milliseconds; + if (std::abs(millis) > max) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + + // Step 11. + *result = {0, + 0, + 0, + 0, + 0, + 0, + 0, + double(millis), + double(microseconds), + double(nanoseconds)}; + MOZ_ASSERT(IsValidDuration(*result)); + return true; + } + + // Step 9. + case TemporalUnit::Microsecond: { + // Valid time durations must be below |limit|. + constexpr auto limit = + Uint128{TimeDuration::max().toMicroseconds()} + Uint128{1}; + + // The largest possible microseconds value whose double representation + // doesn't exceed the time duration limit. + constexpr auto max = + (Uint128{0x1e8} << 64) + Uint128{0x47ff'ffff'fff7'ffff}; + static_assert(max < limit); + + // Assert |max| is the maximum allowed microseconds value. + MOZ_ASSERT(double(max) < double(limit)); + MOZ_ASSERT(double(max + Uint128{1}) >= double(limit)); + + // Step 9.a. + int64_t microseconds = nanoseconds / 1000; + MOZ_ASSERT(std::abs(microseconds) <= 999'999); + + // Step 9.b. + nanoseconds = nanoseconds % 1000; + + auto micros = + (Int128{seconds} * Int128{ToMicroseconds(TemporalUnit::Second)}) + + Int128{microseconds}; + if (micros.abs() > max) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + + // Step 11. + *result = {0, 0, 0, 0, 0, 0, 0, 0, double(micros), double(nanoseconds)}; + MOZ_ASSERT(IsValidDuration(*result)); + return true; + } + + // Step 10. + case TemporalUnit::Nanosecond: { + // Valid time durations must be below |limit|. + constexpr auto limit = + Uint128{TimeDuration::max().toNanoseconds()} + Uint128{1}; + + // The largest possible nanoseconds value whose double representation + // doesn't exceed the time duration limit. + constexpr auto max = + (Uint128{0x77359} << 64) + Uint128{0x3fff'ffff'dfff'ffff}; + static_assert(max < limit); + + // Assert |max| is the maximum allowed nanoseconds value. + MOZ_ASSERT(double(max) < double(limit)); + MOZ_ASSERT(double(max + Uint128{1}) >= double(limit)); + + MOZ_ASSERT(std::abs(nanoseconds) <= 999'999'999); + + auto nanos = + (Int128{seconds} * Int128{ToNanoseconds(TemporalUnit::Second)}) + + Int128{nanoseconds}; + if (nanos.abs() > max) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + + // Step 11. + *result = {0, 0, 0, 0, 0, 0, 0, 0, 0, double(nanos)}; + MOZ_ASSERT(IsValidDuration(*result)); + return true; + } + + case TemporalUnit::Auto: + break; + } + MOZ_CRASH("Unexpected temporal unit"); +} + +/** + * TemporalDurationFromInternal ( internalDuration, largestUnit ) + */ +bool js::temporal::TemporalDurationFromInternal( + JSContext* cx, const InternalDuration& internalDuration, + TemporalUnit largestUnit, Duration* result) { + MOZ_ASSERT(IsValidDuration(internalDuration.date)); + MOZ_ASSERT(IsValidTimeDuration(internalDuration.time)); + + // Steps 1-11. + Duration duration; + if (!TemporalDurationFromInternal(cx, internalDuration.time, largestUnit, + &duration)) { + return false; + } + MOZ_ASSERT(IsValidDuration(duration)); + + // Step 12. + auto days = mozilla::CheckedInt64(internalDuration.date.days) + + mozilla::AssertedCast(duration.days); + MOZ_ASSERT(days.isValid(), "valid duration days can't overflow"); + + *result = { + double(internalDuration.date.years), + double(internalDuration.date.months), + double(internalDuration.date.weeks), + double(days.value()), + duration.hours, + duration.minutes, + duration.seconds, + duration.milliseconds, + duration.microseconds, + duration.nanoseconds, + }; + return ThrowIfInvalidDuration(cx, *result); +} + +/** + * TimeDurationFromEpochNanosecondsDifference ( one, two ) + */ +TimeDuration js::temporal::TimeDurationFromEpochNanosecondsDifference( + const EpochNanoseconds& one, const EpochNanoseconds& two) { + MOZ_ASSERT(IsValidEpochNanoseconds(one)); + MOZ_ASSERT(IsValidEpochNanoseconds(two)); // Step 1. auto result = one - two; // Step 2. - MOZ_ASSERT(IsValidInstantSpan(result)); + MOZ_ASSERT(IsValidEpochDuration(result)); // Step 3. - return result.to(); + return result.to(); } +#ifdef DEBUG /** * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) @@ -555,7 +845,7 @@ bool js::temporal::IsValidDuration(const Duration& duration) { milliseconds, microseconds, nanoseconds] = duration; // Step 1. - int32_t sign = DurationSign(duration); + int32_t sign = 0; // Step 2. for (auto v : {years, months, weeks, days, hours, minutes, seconds, @@ -566,13 +856,25 @@ bool js::temporal::IsValidDuration(const Duration& duration) { } // Step 2.b. - if (v < 0 && sign > 0) { - return false; + if (v < 0) { + // Step 2.b.i. + if (sign > 0) { + return false; + } + + // Step 2.b.ii. + sign = -1; } // Step 2.c. - if (v > 0 && sign < 0) { - return false; + else if (v > 0) { + // Step 2.c.i. + if (sign < 0) { + return false; + } + + // Step 2.c.ii. + sign = 1; } } @@ -592,7 +894,7 @@ bool js::temporal::IsValidDuration(const Duration& duration) { } // Steps 6-8. - if (!NormalizeSeconds(duration)) { + if (!TimeDurationFromDuration(duration)) { return false; } @@ -600,7 +902,6 @@ bool js::temporal::IsValidDuration(const Duration& duration) { return true; } -#ifdef DEBUG /** * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) @@ -613,12 +914,17 @@ bool js::temporal::IsValidDuration(const DateDuration& duration) { * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) */ -bool js::temporal::IsValidDuration(const NormalizedDuration& duration) { - return IsValidDuration(duration.date) && - IsValidNormalizedTimeDuration(duration.time) && - (DurationSign(duration.date) * - NormalizedTimeDurationSign(duration.time) >= - 0); +bool js::temporal::IsValidDuration(const InternalDuration& duration) { + if (!IsValidTimeDuration(duration.time)) { + return false; + } + + auto d = duration.date.toDuration(); + auto [seconds, nanoseconds] = duration.time.denormalize(); + d.seconds = double(seconds); + d.nanoseconds = double(nanoseconds); + + return IsValidDuration(d); } #endif @@ -718,7 +1024,7 @@ bool js::temporal::ThrowIfInvalidDuration(JSContext* cx, } // Steps 6-8. - if (!NormalizeSeconds(duration)) { + if (!TimeDurationFromDuration(duration)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); return false; @@ -731,81 +1037,7 @@ bool js::temporal::ThrowIfInvalidDuration(JSContext* cx, } /** - * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, - * milliseconds, microseconds, nanoseconds ) - */ -bool js::temporal::ThrowIfInvalidDuration(JSContext* cx, - const DateDuration& duration) { - const auto& [years, months, weeks, days] = duration; - - // Step 1. - int32_t sign = DurationSign(duration); - - auto throwIfInvalid = [&](int64_t v, const char* name) { - // Step 2.a. (Not applicable) - - // Steps 2.b-c. - if ((v < 0 && sign > 0) || (v > 0 && sign < 0)) { - return ThrowInvalidDurationPart(cx, double(v), name, - JSMSG_TEMPORAL_DURATION_INVALID_SIGN); - } - - return true; - }; - - auto throwIfTooLarge = [&](int64_t v, const char* name) { - if (std::abs(v) >= (int64_t(1) << 32)) { - return ThrowInvalidDurationPart( - cx, double(v), name, JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE); - } - return true; - }; - - // Step 2. - if (!throwIfInvalid(years, "years")) { - return false; - } - if (!throwIfInvalid(months, "months")) { - return false; - } - if (!throwIfInvalid(weeks, "weeks")) { - return false; - } - if (!throwIfInvalid(days, "days")) { - return false; - } - - // Step 3. - if (!throwIfTooLarge(years, "years")) { - return false; - } - - // Step 4. - if (!throwIfTooLarge(months, "months")) { - return false; - } - - // Step 5. - if (!throwIfTooLarge(weeks, "weeks")) { - return false; - } - - // Steps 6-8. - if (std::abs(days) > ((int64_t(1) << 53) / 86400)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } - - MOZ_ASSERT(IsValidDuration(duration)); - - // Step 9. - return true; -} - -/** - * DefaultTemporalLargestUnit ( years, months, weeks, days, hours, minutes, - * seconds, milliseconds, microseconds ) + * DefaultTemporalLargestUnit ( duration ) */ static TemporalUnit DefaultTemporalLargestUnit(const Duration& duration) { MOZ_ASSERT(IsIntegerDuration(duration)); @@ -1087,910 +1319,70 @@ static bool ToTemporalPartialDurationRecord( return true; } -/** - * ToTemporalDurationRecord ( temporalDurationLike ) - */ -bool js::temporal::ToTemporalDurationRecord(JSContext* cx, - Handle temporalDurationLike, - Duration* result) { - // Step 1. - if (!temporalDurationLike.isObject()) { - // Step 1.a. - if (!temporalDurationLike.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, - temporalDurationLike, nullptr, "not a string"); - return false; - } - Rooted string(cx, temporalDurationLike.toString()); - - // Step 1.b. - return ParseTemporalDurationString(cx, string, result); - } - - Rooted durationLike(cx, &temporalDurationLike.toObject()); - - // Step 2. - if (auto* duration = durationLike->maybeUnwrapIf()) { - *result = ToDuration(duration); - return true; - } - - // Step 3. - Duration duration = {}; - - // Steps 4-14. - if (!ToTemporalPartialDurationRecord(cx, durationLike, &duration)) { - return false; - } - - // Step 15. - if (!ThrowIfInvalidDuration(cx, duration)) { - return false; - } - - // Step 16. - *result = duration; - return true; -} - -/** - * ToTemporalDuration ( item ) - */ -Wrapped js::temporal::ToTemporalDuration(JSContext* cx, - Handle item) { - // Step 1. - if (item.isObject()) { - JSObject* itemObj = &item.toObject(); - if (itemObj->canUnwrapAs()) { - return itemObj; - } - } - - // Step 2. - Duration result; - if (!ToTemporalDurationRecord(cx, item, &result)) { - return nullptr; - } - - // Step 3. - return CreateTemporalDuration(cx, result); -} - /** * ToTemporalDuration ( item ) */ bool js::temporal::ToTemporalDuration(JSContext* cx, Handle item, Duration* result) { - auto obj = ToTemporalDuration(cx, item); - if (!obj) { - return false; - } + // Steps 1 and 3-15. + if (item.isObject()) { + Rooted itemObj(cx, &item.toObject()); - *result = ToDuration(&obj.unwrap()); - return true; -} - -/** - * DaysUntil ( earlier, later ) - */ -int32_t js::temporal::DaysUntil(const PlainDate& earlier, - const PlainDate& later) { - MOZ_ASSERT(ISODateTimeWithinLimits(earlier)); - MOZ_ASSERT(ISODateTimeWithinLimits(later)); - - // Steps 1-2. - int32_t epochDaysEarlier = MakeDay(earlier); - MOZ_ASSERT(MinEpochDay <= epochDaysEarlier && - epochDaysEarlier <= MaxEpochDay); - - // Steps 3-4. - int32_t epochDaysLater = MakeDay(later); - MOZ_ASSERT(MinEpochDay <= epochDaysLater && epochDaysLater <= MaxEpochDay); - - // Step 5. - return epochDaysLater - epochDaysEarlier; -} - -/** - * MoveRelativeDate ( calendarRec, relativeTo, duration ) - */ -static bool MoveRelativeDate( - JSContext* cx, Handle calendar, - Handle> relativeTo, const DateDuration& duration, - MutableHandle> relativeToResult, - int32_t* daysResult) { - auto* unwrappedRelativeTo = relativeTo.unwrap(cx); - if (!unwrappedRelativeTo) { - return false; - } - auto relativeToDate = ToPlainDate(unwrappedRelativeTo); - - // Step 1. - auto newDate = AddDate(cx, calendar, relativeTo, duration); - if (!newDate) { - return false; - } - auto later = ToPlainDate(&newDate.unwrap()); - relativeToResult.set(newDate); - - // Step 2. - *daysResult = DaysUntil(relativeToDate, later); - MOZ_ASSERT(std::abs(*daysResult) <= MaxEpochDaysDuration); - - // Step 3. - return true; -} - -/** - * MoveRelativeZonedDateTime ( zonedDateTime, calendarRec, timeZoneRec, years, - * months, weeks, days, precalculatedPlainDateTime ) - */ -static bool MoveRelativeZonedDateTime( - JSContext* cx, Handle zonedDateTime, - Handle calendar, Handle timeZone, - const DateDuration& duration, - mozilla::Maybe precalculatedPlainDateTime, - MutableHandle result) { - // Step 1. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Step 2. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); - - // Step 3. - Instant intermediateNs; - if (precalculatedPlainDateTime) { - if (!AddZonedDateTime(cx, zonedDateTime.instant(), timeZone, calendar, - duration, *precalculatedPlainDateTime, - &intermediateNs)) { - return false; - } - } else { - if (!AddZonedDateTime(cx, zonedDateTime.instant(), timeZone, calendar, - duration, &intermediateNs)) { - return false; - } - } - MOZ_ASSERT(IsValidEpochInstant(intermediateNs)); - - // Step 4. - result.set(ZonedDateTime{intermediateNs, zonedDateTime.timeZone(), - zonedDateTime.calendar()}); - return true; -} - -/** - * Split duration into full days and remainding nanoseconds. - */ -static NormalizedTimeAndDays NormalizedTimeDurationToDays( - const NormalizedTimeDuration& duration) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); - - auto [seconds, nanoseconds] = duration; - if (seconds < 0 && nanoseconds > 0) { - seconds += 1; - nanoseconds -= 1'000'000'000; - } - - int64_t days = seconds / ToSeconds(TemporalUnit::Day); - seconds = seconds % ToSeconds(TemporalUnit::Day); - - int64_t time = seconds * ToNanoseconds(TemporalUnit::Second) + nanoseconds; - - constexpr int64_t dayLength = ToNanoseconds(TemporalUnit::Day); - MOZ_ASSERT(std::abs(time) < dayLength); - - return {days, time, dayLength}; -} - -/** - * CreateTimeDurationRecord ( days, hours, minutes, seconds, milliseconds, - * microseconds, nanoseconds ) - */ -static TimeDuration CreateTimeDurationRecord(int64_t days, int64_t hours, - int64_t minutes, int64_t seconds, - int64_t milliseconds, - int64_t microseconds, - int64_t nanoseconds) { - // Step 1. - MOZ_ASSERT(IsValidDuration( - {0, 0, 0, double(days), double(hours), double(minutes), double(seconds), - double(milliseconds), double(microseconds), double(nanoseconds)})); - - // All values are safe integers, so we don't need to convert to `double` and - // back for the `ℝ(𝔽(x))` conversion. - MOZ_ASSERT(IsSafeInteger(days)); - MOZ_ASSERT(IsSafeInteger(hours)); - MOZ_ASSERT(IsSafeInteger(minutes)); - MOZ_ASSERT(IsSafeInteger(seconds)); - MOZ_ASSERT(IsSafeInteger(milliseconds)); - MOZ_ASSERT(IsSafeInteger(microseconds)); - MOZ_ASSERT(IsSafeInteger(nanoseconds)); - - // Step 2. - return { - days, - hours, - minutes, - seconds, - milliseconds, - double(microseconds), - double(nanoseconds), - }; -} - -/** - * CreateTimeDurationRecord ( days, hours, minutes, seconds, milliseconds, - * microseconds, nanoseconds ) - */ -static TimeDuration CreateTimeDurationRecord(int64_t milliseconds, - const Int128& microseconds, - const Int128& nanoseconds) { - // Step 1. - MOZ_ASSERT(IsValidDuration({0, 0, 0, 0, 0, 0, 0, double(milliseconds), - double(microseconds), double(nanoseconds)})); - - // Step 2. - return { - 0, 0, 0, 0, milliseconds, double(microseconds), double(nanoseconds), - }; -} - -/** - * BalanceTimeDuration ( norm, largestUnit ) - */ -TimeDuration js::temporal::BalanceTimeDuration( - const NormalizedTimeDuration& duration, TemporalUnit largestUnit) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); - MOZ_ASSERT(largestUnit <= TemporalUnit::Second, - "fallible fractional seconds units"); - - auto [seconds, nanoseconds] = duration; - - // Negative nanoseconds are represented as the difference to 1'000'000'000. - // Convert these back to their absolute value and adjust the seconds part - // accordingly. - // - // For example the nanoseconds duration |-1n| is represented as the - // duration {seconds: -1, nanoseconds: 999'999'999}. - if (seconds < 0 && nanoseconds > 0) { - seconds += 1; - nanoseconds -= ToNanoseconds(TemporalUnit::Second); - } - - // Step 1. - int64_t days = 0; - int64_t hours = 0; - int64_t minutes = 0; - int64_t milliseconds = 0; - int64_t microseconds = 0; - - // Steps 2-3. (Not applicable in our implementation.) - // - // We don't need to convert to positive numbers, because integer division - // truncates and the %-operator has modulo semantics. - - // Steps 4-10. - switch (largestUnit) { - // Step 4. - case TemporalUnit::Year: - case TemporalUnit::Month: - case TemporalUnit::Week: - case TemporalUnit::Day: { - // Step 4.a. - microseconds = nanoseconds / 1000; - - // Step 4.b. - nanoseconds = nanoseconds % 1000; - - // Step 4.c. - milliseconds = microseconds / 1000; - - // Step 4.d. - microseconds = microseconds % 1000; - - // Steps 4.e-f. (Not applicable) - MOZ_ASSERT(std::abs(milliseconds) <= 999); - - // Step 4.g. - minutes = seconds / 60; - - // Step 4.h. - seconds = seconds % 60; - - // Step 4.i. - hours = minutes / 60; - - // Step 4.j. - minutes = minutes % 60; - - // Step 4.k. - days = hours / 24; - - // Step 4.l. - hours = hours % 24; - - break; - } - - // Step 5. - case TemporalUnit::Hour: { - // Step 5.a. - microseconds = nanoseconds / 1000; - - // Step 5.b. - nanoseconds = nanoseconds % 1000; - - // Step 5.c. - milliseconds = microseconds / 1000; - - // Step 5.d. - microseconds = microseconds % 1000; - - // Steps 5.e-f. (Not applicable) - MOZ_ASSERT(std::abs(milliseconds) <= 999); - - // Step 5.g. - minutes = seconds / 60; - - // Step 5.h. - seconds = seconds % 60; - - // Step 5.i. - hours = minutes / 60; - - // Step 5.j. - minutes = minutes % 60; - - break; - } - - case TemporalUnit::Minute: { - // Step 6.a. - microseconds = nanoseconds / 1000; - - // Step 6.b. - nanoseconds = nanoseconds % 1000; - - // Step 6.c. - milliseconds = microseconds / 1000; - - // Step 6.d. - microseconds = microseconds % 1000; - - // Steps 6.e-f. (Not applicable) - MOZ_ASSERT(std::abs(milliseconds) <= 999); - - // Step 6.g. - minutes = seconds / 60; - - // Step 6.h. - seconds = seconds % 60; - - break; - } - - // Step 7. - case TemporalUnit::Second: { - // Step 7.a. - microseconds = nanoseconds / 1000; - - // Step 7.b. - nanoseconds = nanoseconds % 1000; - - // Step 7.c. - milliseconds = microseconds / 1000; - - // Step 7.d. - microseconds = microseconds % 1000; - - // Steps 7.e-f. (Not applicable) - MOZ_ASSERT(std::abs(milliseconds) <= 999); - - break; - } - - case TemporalUnit::Millisecond: - case TemporalUnit::Microsecond: - case TemporalUnit::Nanosecond: - case TemporalUnit::Auto: - MOZ_CRASH("Unexpected temporal unit"); - } - - // Step 11. - return CreateTimeDurationRecord(days, hours, minutes, seconds, milliseconds, - microseconds, nanoseconds); -} - -/** - * BalanceTimeDuration ( norm, largestUnit ) - */ -bool js::temporal::BalanceTimeDuration(JSContext* cx, - const NormalizedTimeDuration& duration, - TemporalUnit largestUnit, - TimeDuration* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); - - auto [seconds, nanoseconds] = duration; - - // Negative nanoseconds are represented as the difference to 1'000'000'000. - // Convert these back to their absolute value and adjust the seconds part - // accordingly. - // - // For example the nanoseconds duration |-1n| is represented as the - // duration {seconds: -1, nanoseconds: 999'999'999}. - if (seconds < 0 && nanoseconds > 0) { - seconds += 1; - nanoseconds -= ToNanoseconds(TemporalUnit::Second); - } - - // Steps 1-3. (Not applicable in our implementation.) - // - // We don't need to convert to positive numbers, because integer division - // truncates and the %-operator has modulo semantics. - - // Steps 4-10. - switch (largestUnit) { - // Steps 4-7. - case TemporalUnit::Year: - case TemporalUnit::Month: - case TemporalUnit::Week: - case TemporalUnit::Day: - case TemporalUnit::Hour: - case TemporalUnit::Minute: - case TemporalUnit::Second: - *result = BalanceTimeDuration(duration, largestUnit); - return true; - - // Step 8. - case TemporalUnit::Millisecond: { - // The number of normalized seconds must not exceed `2**53 - 1`. - constexpr auto limit = - (int64_t(1) << 53) * ToMilliseconds(TemporalUnit::Second); - - // The largest possible milliseconds value whose double representation - // doesn't exceed the normalized seconds limit. - constexpr auto max = int64_t(0x7cff'ffff'ffff'fdff); - - // Assert |max| is the maximum allowed milliseconds value. - static_assert(double(max) < double(limit)); - static_assert(double(max + 1) >= double(limit)); - - static_assert((NormalizedTimeDuration::max().seconds + 1) * - ToMilliseconds(TemporalUnit::Second) <= - INT64_MAX, - "total number duration milliseconds fits into int64"); - - // Step 8.a. - int64_t microseconds = nanoseconds / 1000; - - // Step 8.b. - nanoseconds = nanoseconds % 1000; - - // Step 8.c. - int64_t milliseconds = microseconds / 1000; - MOZ_ASSERT(std::abs(milliseconds) <= 999); - - // Step 8.d. - microseconds = microseconds % 1000; - - auto millis = - (seconds * ToMilliseconds(TemporalUnit::Second)) + milliseconds; - if (std::abs(millis) > max) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } - - // Step 11. - *result = CreateTimeDurationRecord(millis, Int128{microseconds}, - Int128{nanoseconds}); + // Step 1. + if (auto* duration = itemObj->maybeUnwrapIf()) { + *result = ToDuration(duration); return true; } - // Step 9. - case TemporalUnit::Microsecond: { - // The number of normalized seconds must not exceed `2**53 - 1`. - constexpr auto limit = Uint128{int64_t(1) << 53} * - Uint128{ToMicroseconds(TemporalUnit::Second)}; + // Step 3. (Reordered) + Duration duration = {}; - // The largest possible microseconds value whose double representation - // doesn't exceed the normalized seconds limit. - constexpr auto max = - (Uint128{0x1e8} << 64) + Uint128{0x47ff'ffff'fff7'ffff}; - static_assert(max < limit); - - // Assert |max| is the maximum allowed microseconds value. - MOZ_ASSERT(double(max) < double(limit)); - MOZ_ASSERT(double(max + Uint128{1}) >= double(limit)); - - // Step 9.a. - int64_t microseconds = nanoseconds / 1000; - MOZ_ASSERT(std::abs(microseconds) <= 999'999); - - // Step 9.b. - nanoseconds = nanoseconds % 1000; - - auto micros = - (Int128{seconds} * Int128{ToMicroseconds(TemporalUnit::Second)}) + - Int128{microseconds}; - if (micros.abs() > max) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } - - // Step 11. - *result = CreateTimeDurationRecord(0, micros, Int128{nanoseconds}); - return true; - } - - // Step 10. - case TemporalUnit::Nanosecond: { - // The number of normalized seconds must not exceed `2**53 - 1`. - constexpr auto limit = Uint128{int64_t(1) << 53} * - Uint128{ToNanoseconds(TemporalUnit::Second)}; - - // The largest possible nanoseconds value whose double representation - // doesn't exceed the normalized seconds limit. - constexpr auto max = - (Uint128{0x77359} << 64) + Uint128{0x3fff'ffff'dfff'ffff}; - static_assert(max < limit); - - // Assert |max| is the maximum allowed nanoseconds value. - MOZ_ASSERT(double(max) < double(limit)); - MOZ_ASSERT(double(max + Uint128{1}) >= double(limit)); - - MOZ_ASSERT(std::abs(nanoseconds) <= 999'999'999); - - auto nanos = - (Int128{seconds} * Int128{ToNanoseconds(TemporalUnit::Second)}) + - Int128{nanoseconds}; - if (nanos.abs() > max) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } - - // Step 11. - *result = CreateTimeDurationRecord(0, Int128{}, nanos); - return true; - } - - case TemporalUnit::Auto: - break; - } - MOZ_CRASH("Unexpected temporal unit"); -} - -/** - * BalanceTimeDurationRelative ( days, norm, largestUnit, zonedRelativeTo, - * timeZoneRec, precalculatedPlainDateTime ) - */ -static bool BalanceTimeDurationRelative( - JSContext* cx, const NormalizedDuration& duration, TemporalUnit largestUnit, - Handle relativeTo, Handle timeZone, - mozilla::Maybe precalculatedPlainDateTime, - TimeDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - - // Step 1. - const auto& startNs = relativeTo.instant(); - - // Step 2. - const auto& startInstant = startNs; - - // Step 3. - auto intermediateNs = startNs; - - // Step 4. - PlainDateTime startDateTime; - if (duration.date.days != 0) { - // Step 4.a. - if (!precalculatedPlainDateTime) { - if (!GetPlainDateTimeFor(cx, timeZone, startInstant, &startDateTime)) { - return false; - } - precalculatedPlainDateTime = - mozilla::SomeRef(startDateTime); - } - - // Steps 4.b-c. - Rooted isoCalendar(cx, CalendarValue(CalendarId::ISO8601)); - if (!AddDaysToZonedDateTime(cx, startInstant, *precalculatedPlainDateTime, - timeZone, isoCalendar, duration.date.days, - &intermediateNs)) { - return false; - } - } - - // Step 5. - Instant endNs; - if (!AddInstant(cx, intermediateNs, duration.time, &endNs)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(endNs)); - - // Step 6. - auto normalized = - NormalizedTimeDurationFromEpochNanosecondsDifference(endNs, startInstant); - - // Step 7. - if (normalized == NormalizedTimeDuration{}) { - *result = {}; - return true; - } - - // Steps 8-9. - int64_t days = 0; - if (TemporalUnit::Year <= largestUnit && largestUnit <= TemporalUnit::Day) { - // Step 8.a. - if (!precalculatedPlainDateTime) { - if (!GetPlainDateTimeFor(cx, timeZone, startInstant, &startDateTime)) { - return false; - } - precalculatedPlainDateTime = - mozilla::SomeRef(startDateTime); - } - - // Step 8.b. - NormalizedTimeAndDays timeAndDays; - if (!NormalizedTimeDurationToDays(cx, normalized, relativeTo, timeZone, - *precalculatedPlainDateTime, - &timeAndDays)) { + // Steps 4-14. + if (!ToTemporalPartialDurationRecord(cx, itemObj, &duration)) { return false; } - // Step 8.c. - days = timeAndDays.days; + // Step 15. + if (!ThrowIfInvalidDuration(cx, duration)) { + return false; + } - // Step 8.d. - normalized = NormalizedTimeDuration::fromNanoseconds(timeAndDays.time); - MOZ_ASSERT_IF(days > 0, normalized >= NormalizedTimeDuration{}); - MOZ_ASSERT_IF(days < 0, normalized <= NormalizedTimeDuration{}); - - // Step 8.e. - largestUnit = TemporalUnit::Hour; - } - - // Step 10. - TimeDuration balanceResult; - if (!BalanceTimeDuration(cx, normalized, largestUnit, &balanceResult)) { - return false; - } - - // Step 11. - *result = { - days, - balanceResult.hours, - balanceResult.minutes, - balanceResult.seconds, - balanceResult.milliseconds, - balanceResult.microseconds, - balanceResult.nanoseconds, - }; - MOZ_ASSERT(IsValidDuration(result->toDuration())); - return true; -} - -/** - * CreateDateDurationRecord ( years, months, weeks, days ) - */ -static DateDuration CreateDateDurationRecord(int64_t years, int64_t months, - int64_t weeks, int64_t days) { - MOZ_ASSERT(IsValidDuration(Duration{ - double(years), - double(months), - double(weeks), - double(days), - })); - return {years, months, weeks, days}; -} - -/** - * CreateDateDurationRecord ( years, months, weeks, days ) - */ -static bool CreateDateDurationRecord(JSContext* cx, int64_t years, - int64_t months, int64_t weeks, - int64_t days, DateDuration* result) { - auto duration = DateDuration{years, months, weeks, days}; - if (!ThrowIfInvalidDuration(cx, duration)) { - return false; - } - - *result = duration; - return true; -} - -static bool UnbalanceDateDurationRelativeHasEffect(const DateDuration& duration, - TemporalUnit largestUnit) { - MOZ_ASSERT(largestUnit != TemporalUnit::Auto); - - // Steps 2-4. - return (largestUnit > TemporalUnit::Year && duration.years != 0) || - (largestUnit > TemporalUnit::Month && duration.months != 0) || - (largestUnit > TemporalUnit::Week && duration.weeks != 0); -} - -/** - * UnbalanceDateDurationRelative ( years, months, weeks, days, largestUnit, - * plainRelativeTo, calendarRec ) - */ -static bool UnbalanceDateDurationRelative( - JSContext* cx, const DateDuration& duration, TemporalUnit largestUnit, - Handle> plainRelativeTo, - Handle calendar, DateDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - - auto [years, months, weeks, days] = duration; - - // Step 1. (Not applicable in our implementation.) - - // Steps 2-4. - if (!UnbalanceDateDurationRelativeHasEffect(duration, largestUnit)) { *result = duration; return true; } - // Step 5. - MOZ_ASSERT(largestUnit != TemporalUnit::Year); - - // Step 6. (Not applicable in our implementation.) - - // Step 7. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 8. - if (largestUnit == TemporalUnit::Month) { - // Step 8.a. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - - // Step 8.b. - auto yearsDuration = DateDuration{years}; - - // Step 8.c. - Rooted> later( - cx, CalendarDateAdd(cx, calendar, plainRelativeTo, yearsDuration)); - if (!later) { - return false; - } - - // Steps 8.d-f. - DateDuration untilResult; - if (!CalendarDateUntil(cx, calendar, plainRelativeTo, later, - TemporalUnit::Month, &untilResult)) { - return false; - } - - // Step 8.g. - int64_t yearsInMonths = untilResult.months; - - // Step 8.h. - return CreateDateDurationRecord(cx, 0, months + yearsInMonths, weeks, days, - result); + // Step 2.a. + if (!item.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, + nullptr, "not a string"); + return false; } + Rooted string(cx, item.toString()); - // Step 9. - if (largestUnit == TemporalUnit::Week) { - // Step 9.a. - auto yearsMonthsDuration = DateDuration{years, months}; + // Step 2.b. + return ParseTemporalDurationString(cx, string, result); +} - // Step 9.b. - auto later = - CalendarDateAdd(cx, calendar, plainRelativeTo, yearsMonthsDuration); - if (!later) { - return false; - } - auto laterDate = ToPlainDate(&later.unwrap()); +/** + * DateDurationDays ( dateDuration, plainRelativeTo ) + */ +static bool DateDurationDays(JSContext* cx, const DateDuration& duration, + Handle plainRelativeTo, + int64_t* result) { + MOZ_ASSERT(IsValidDuration(duration)); - auto* unwrappedRelativeTo = plainRelativeTo.unwrap(cx); - if (!unwrappedRelativeTo) { - return false; - } - auto relativeToDate = ToPlainDate(unwrappedRelativeTo); + auto [years, months, weeks, days] = duration; - // Step 9.c. - int32_t yearsMonthsInDays = DaysUntil(relativeToDate, laterDate); - - // Step 9.d. - return CreateDateDurationRecord(cx, 0, 0, weeks, days + yearsMonthsInDays, - result); - } - - // Step 10. (Not applicable in our implementation.) - - // Step 11. + // Step 1. auto yearsMonthsWeeksDuration = DateDuration{years, months, weeks}; - // Step 12. - auto later = - CalendarDateAdd(cx, calendar, plainRelativeTo, yearsMonthsWeeksDuration); - if (!later) { - return false; - } - auto laterDate = ToPlainDate(&later.unwrap()); - - auto* unwrappedRelativeTo = plainRelativeTo.unwrap(cx); - if (!unwrappedRelativeTo) { - return false; - } - auto relativeToDate = ToPlainDate(unwrappedRelativeTo); - - // Step 13. - int32_t yearsMonthsWeeksInDay = DaysUntil(relativeToDate, laterDate); - - // Step 14. - return CreateDateDurationRecord(cx, 0, 0, 0, days + yearsMonthsWeeksInDay, - result); -} - -/** - * UnbalanceDateDurationRelative ( years, months, weeks, days, largestUnit, - * plainRelativeTo, calendarRec ) - */ -static bool UnbalanceDateDurationRelative(JSContext* cx, - const DateDuration& duration, - TemporalUnit largestUnit, - DateDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - - // Step 1. (Not applicable.) - - // Step 2-4. - if (!UnbalanceDateDurationRelativeHasEffect(duration, largestUnit)) { - *result = duration; + // Step 2. + if (yearsMonthsWeeksDuration == DateDuration{}) { + *result = days; return true; } - // Step 5. - MOZ_ASSERT(largestUnit != TemporalUnit::Year); - - // Steps 6. - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, "calendar"); - return false; -} - -/** - * BalanceDateDurationRelative ( years, months, weeks, days, largestUnit, - * smallestUnit, plainRelativeTo, calendarRec ) - */ -static bool BalanceDateDurationRelative( - JSContext* cx, const DateDuration& duration, TemporalUnit largestUnit, - TemporalUnit smallestUnit, - Handle> plainRelativeTo, - Handle calendar, DateDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - MOZ_ASSERT(largestUnit <= smallestUnit); - - auto [years, months, weeks, days] = duration; - - // FIXME: spec issue - effectful code paths should be more fine-grained - // similar to UnbalanceDateDurationRelative. For example: - // 1. If largestUnit = "year" and days = 0 and months = 0, then no-op. - // 2. Else if largestUnit = "month" and days = 0, then no-op. - // 3. Else if days = 0, then no-op. - // - // Also note that |weeks| is never balanced, even when non-zero. - - // Step 1. (Not applicable in our implementation.) - - // Steps 2-4. - if (largestUnit > TemporalUnit::Week || - (years == 0 && months == 0 && weeks == 0 && days == 0)) { - // Step 4.a. - *result = duration; - return true; - } - - // Step 5. + // Moved from caller. if (!plainRelativeTo) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, @@ -1998,539 +1390,30 @@ static bool BalanceDateDurationRelative( return false; } - // Step 6. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 7. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - - // Steps 8-9. (Not applicable in our implementation.) - - auto untilAddedDate = [&](const DateDuration& duration, - DateDuration* untilResult) { - Rooted> later( - cx, AddDate(cx, calendar, plainRelativeTo, duration)); - if (!later) { - return false; - } - - return CalendarDateUntil(cx, calendar, plainRelativeTo, later, largestUnit, - untilResult); - }; - - // Step 10. - if (largestUnit == TemporalUnit::Year) { - // Step 10.a. - if (smallestUnit == TemporalUnit::Week) { - // Step 10.a.i. - MOZ_ASSERT(days == 0); - - // Step 10.a.ii. - auto yearsMonthsDuration = DateDuration{years, months}; - - // Steps 10.a.iii-iv. - DateDuration untilResult; - if (!untilAddedDate(yearsMonthsDuration, &untilResult)) { - return false; - } - - // Step 10.a.v. - *result = CreateDateDurationRecord(untilResult.years, untilResult.months, - weeks, 0); - return true; - } - - // Step 10.b. - const auto& yearsMonthsWeeksDaysDuration = duration; - - // Steps 10.c-d. - DateDuration untilResult; - if (!untilAddedDate(yearsMonthsWeeksDaysDuration, &untilResult)) { - return false; - } - - // Step 10.e. - *result = CreateDateDurationRecord(untilResult.years, untilResult.months, - untilResult.weeks, untilResult.days); - return true; - } - - // Step 11. - if (largestUnit == TemporalUnit::Month) { - // Step 11.a. - MOZ_ASSERT(years == 0); - - // Step 11.b. - if (smallestUnit == TemporalUnit::Week) { - // Step 10.b.i. - MOZ_ASSERT(days == 0); - - // Step 10.b.ii. - *result = CreateDateDurationRecord(0, months, weeks, 0); - return true; - } - - // Step 11.c. - const auto& monthsWeeksDaysDuration = duration; - - // Steps 11.d-e. - DateDuration untilResult; - if (!untilAddedDate(monthsWeeksDaysDuration, &untilResult)) { - return false; - } - - // Step 11.f. - *result = CreateDateDurationRecord(0, untilResult.months, untilResult.weeks, - untilResult.days); - return true; - } - - // Step 12. - MOZ_ASSERT(largestUnit == TemporalUnit::Week); - - // Step 13. - MOZ_ASSERT(years == 0); - - // Step 14. - MOZ_ASSERT(months == 0); - - // Step 15. - const auto& weeksDaysDuration = duration; - - // Steps 16-17. - DateDuration untilResult; - if (!untilAddedDate(weeksDaysDuration, &untilResult)) { + // Step 3. + ISODate later; + if (!CalendarDateAdd(cx, plainRelativeTo.calendar(), plainRelativeTo, + yearsMonthsWeeksDuration, TemporalOverflow::Constrain, + &later)) { return false; } - // Step 18. - *result = CreateDateDurationRecord(0, 0, untilResult.weeks, untilResult.days); - return true; -} - -/** - * BalanceDateDurationRelative ( years, months, weeks, days, largestUnit, - * smallestUnit, plainRelativeTo, calendarRec ) - */ -bool js::temporal::BalanceDateDurationRelative( - JSContext* cx, const DateDuration& duration, TemporalUnit largestUnit, - TemporalUnit smallestUnit, - Handle> plainRelativeTo, - Handle calendar, DateDuration* result) { - MOZ_ASSERT(plainRelativeTo); - MOZ_ASSERT(calendar.receiver()); - - return ::BalanceDateDurationRelative(cx, duration, largestUnit, smallestUnit, - plainRelativeTo, calendar, result); -} - -/** - * AddDuration ( y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, w2, - * d2, h2, min2, s2, ms2, mus2, ns2, plainRelativeTo, calendarRec, - * zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - */ -static bool AddDuration(JSContext* cx, const Duration& one, const Duration& two, - Duration* result) { - MOZ_ASSERT(IsValidDuration(one)); - MOZ_ASSERT(IsValidDuration(two)); - - // Steps 1-2. (Not applicable) - - // Step 3. - auto largestUnit1 = DefaultTemporalLargestUnit(one); - // Step 4. - auto largestUnit2 = DefaultTemporalLargestUnit(two); + int32_t epochDays1 = MakeDay(plainRelativeTo); + MOZ_ASSERT(MinEpochDay <= epochDays1 && epochDays1 <= MaxEpochDay); // Step 5. - auto largestUnit = std::min(largestUnit1, largestUnit2); - - // Step 6. - auto normalized1 = NormalizeTimeDuration(one); - - // Step 7. - auto normalized2 = NormalizeTimeDuration(two); - - // Step 8.a. - if (largestUnit <= TemporalUnit::Week) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, - "relativeTo"); - return false; - } - - // Step 8.b. - NormalizedTimeDuration normalized; - if (!AddNormalizedTimeDuration(cx, normalized1, normalized2, &normalized)) { - return false; - } - - // Step 8.c. - int64_t days1 = mozilla::AssertedCast(one.days); - int64_t days2 = mozilla::AssertedCast(two.days); - auto totalDays = mozilla::CheckedInt64(days1) + days2; - MOZ_ASSERT(totalDays.isValid(), "adding two duration days can't overflow"); - - if (!Add24HourDaysToNormalizedTimeDuration(cx, normalized, totalDays.value(), - &normalized)) { - return false; - } - - // Step 8.d. - TimeDuration balanced; - if (!temporal::BalanceTimeDuration(cx, normalized, largestUnit, &balanced)) { - return false; - } - - // Steps 8.e. - *result = balanced.toDuration(); - return true; -} - -/** - * AddDuration ( y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, w2, - * d2, h2, min2, s2, ms2, mus2, ns2, plainRelativeTo, calendarRec, - * zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - */ -static bool AddDuration(JSContext* cx, const Duration& one, const Duration& two, - Handle> plainRelativeTo, - Handle calendar, Duration* result) { - MOZ_ASSERT(IsValidDuration(one)); - MOZ_ASSERT(IsValidDuration(two)); - - // Steps 1-2. (Not applicable) - - // Step 3. - auto largestUnit1 = DefaultTemporalLargestUnit(one); + int32_t epochDays2 = MakeDay(later); + MOZ_ASSERT(MinEpochDay <= epochDays2 && epochDays2 <= MaxEpochDay); // Step 4. - auto largestUnit2 = DefaultTemporalLargestUnit(two); + int32_t yearsMonthsWeeksInDay = epochDays2 - epochDays1; // Step 5. - auto largestUnit = std::min(largestUnit1, largestUnit2); - - // Step 6. - auto normalized1 = NormalizeTimeDuration(one); - - // Step 7. - auto normalized2 = NormalizeTimeDuration(two); - - // Step 8. (Not applicable) - - // Step 9.a. (Not applicable in our implementation.) - - // Step 9.b. - auto dateDuration1 = one.toDateDuration(); - - // Step 9.c. - auto dateDuration2 = two.toDateDuration(); - - // Step 9.d. - Rooted> intermediate( - cx, AddDate(cx, calendar, plainRelativeTo, dateDuration1)); - if (!intermediate) { - return false; - } - - // Step 9.e. - Rooted> end( - cx, AddDate(cx, calendar, intermediate, dateDuration2)); - if (!end) { - return false; - } - - // Step 9.f. - auto dateLargestUnit = std::min(TemporalUnit::Day, largestUnit); - - // Steps 9.g-i. - DateDuration dateDifference; - if (!DifferenceDate(cx, calendar, plainRelativeTo, end, dateLargestUnit, - &dateDifference)) { - return false; - } - - // Step 9.j. - NormalizedTimeDuration normalized1WithDays; - if (!Add24HourDaysToNormalizedTimeDuration( - cx, normalized1, dateDifference.days, &normalized1WithDays)) { - return false; - } - - // Step 9.k. - NormalizedTimeDuration normalized; - if (!AddNormalizedTimeDuration(cx, normalized1WithDays, normalized2, - &normalized)) { - return false; - } - - // Step 9.l. - TimeDuration balanced; - if (!temporal::BalanceTimeDuration(cx, normalized, largestUnit, &balanced)) { - return false; - } - - // Steps 9.m. - *result = { - double(dateDifference.years), double(dateDifference.months), - double(dateDifference.weeks), double(balanced.days), - double(balanced.hours), double(balanced.minutes), - double(balanced.seconds), double(balanced.milliseconds), - balanced.microseconds, balanced.nanoseconds, - }; - MOZ_ASSERT(IsValidDuration(*result)); + *result = days + yearsMonthsWeeksInDay; return true; } -/** - * AddDuration ( y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, w2, - * d2, h2, min2, s2, ms2, mus2, ns2, plainRelativeTo, calendarRec, - * zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - */ -static bool AddDuration( - JSContext* cx, const Duration& one, const Duration& two, - Handle zonedRelativeTo, Handle calendar, - Handle timeZone, - mozilla::Maybe precalculatedPlainDateTime, - Duration* result) { - // Steps 1-2. (Not applicable) - - // Step 3. - auto largestUnit1 = DefaultTemporalLargestUnit(one); - - // Step 4. - auto largestUnit2 = DefaultTemporalLargestUnit(two); - - // Step 5. - auto largestUnit = std::min(largestUnit1, largestUnit2); - - // Step 6. - auto normalized1 = NormalizeTimeDuration(one); - - // Step 7. - auto normalized2 = NormalizeTimeDuration(two); - - // Steps 8-9. (Not applicable) - - // Steps 10-11. (Not applicable in our implementation.) - - // Step 12. - bool startDateTimeNeeded = largestUnit <= TemporalUnit::Day; - - // Steps 13-17. - if (!startDateTimeNeeded) { - // Steps 13-14. (Not applicable) - - // Step 15. (Inlined AddZonedDateTime, step 6.) - Instant intermediateNs; - if (!AddInstant(cx, zonedRelativeTo.instant(), normalized1, - &intermediateNs)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(intermediateNs)); - - // Step 16. (Inlined AddZonedDateTime, step 6.) - Instant endNs; - if (!AddInstant(cx, intermediateNs, normalized2, &endNs)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(endNs)); - - // Step 17.a. - auto normalized = NormalizedTimeDurationFromEpochNanosecondsDifference( - endNs, zonedRelativeTo.instant()); - - // Step 17.b. - TimeDuration balanced; - if (!BalanceTimeDuration(cx, normalized, largestUnit, &balanced)) { - return false; - } - - // Step 17.c. - *result = balanced.toDuration(); - return true; - } - - // Steps 13-14. - PlainDateTime startDateTime; - if (!precalculatedPlainDateTime) { - if (!GetPlainDateTimeFor(cx, timeZone, zonedRelativeTo.instant(), - &startDateTime)) { - return false; - } - } else { - startDateTime = *precalculatedPlainDateTime; - } - - // Step 15. - auto norm1 = - CreateNormalizedDurationRecord(one.toDateDuration(), normalized1); - Instant intermediateNs; - if (!AddZonedDateTime(cx, zonedRelativeTo.instant(), timeZone, calendar, - norm1, startDateTime, &intermediateNs)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(intermediateNs)); - - // Step 16. - auto norm2 = - CreateNormalizedDurationRecord(two.toDateDuration(), normalized2); - Instant endNs; - if (!AddZonedDateTime(cx, intermediateNs, timeZone, calendar, norm2, - &endNs)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(endNs)); - - // Step 17. (Not applicable) - - // Step 18. - NormalizedDuration difference; - if (!DifferenceZonedDateTime(cx, zonedRelativeTo.instant(), endNs, timeZone, - calendar, largestUnit, startDateTime, - &difference)) { - return false; - } - - // Step 19. - auto balanced = BalanceTimeDuration(difference.time, TemporalUnit::Hour); - - // Step 20. - *result = { - double(difference.date.years), double(difference.date.months), - double(difference.date.weeks), double(difference.date.days), - double(balanced.hours), double(balanced.minutes), - double(balanced.seconds), double(balanced.milliseconds), - balanced.microseconds, balanced.nanoseconds, - }; - MOZ_ASSERT(IsValidDuration(*result)); - return true; -} - -/** - * AddDuration ( y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, w2, - * d2, h2, min2, s2, ms2, mus2, ns2, plainRelativeTo, calendarRec, - * zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - */ -static bool AddDuration(JSContext* cx, const Duration& one, const Duration& two, - Handle zonedRelativeTo, - Handle calendar, - Handle timeZone, Duration* result) { - return AddDuration(cx, one, two, zonedRelativeTo, calendar, timeZone, - mozilla::Nothing(), result); -} - -/** - * AdjustRoundedDurationDays ( years, months, weeks, days, norm, increment, - * unit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec, - * precalculatedPlainDateTime ) - */ -static bool AdjustRoundedDurationDays( - JSContext* cx, const NormalizedDuration& duration, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode, - Handle zonedRelativeTo, Handle calendar, - Handle timeZone, - mozilla::Maybe precalculatedPlainDateTime, - NormalizedDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - - // Step 1. - if ((TemporalUnit::Year <= unit && unit <= TemporalUnit::Day) || - (unit == TemporalUnit::Nanosecond && increment == Increment{1})) { - *result = duration; - return true; - } - - // The increment is limited for all smaller temporal units. - MOZ_ASSERT(increment < MaximumTemporalDurationRoundingIncrement(unit)); - - // Step 2. - MOZ_ASSERT(precalculatedPlainDateTime); - - // Step 3. - int32_t direction = NormalizedTimeDurationSign(duration.time); - - // Steps 4-5. - Instant dayStart; - if (!AddZonedDateTime(cx, zonedRelativeTo.instant(), timeZone, calendar, - duration.date, *precalculatedPlainDateTime, - &dayStart)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(dayStart)); - - // Step 6. - PlainDateTime dayStartDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, dayStart, &dayStartDateTime)) { - return false; - } - - // Step 7. - Instant dayEnd; - if (!AddDaysToZonedDateTime(cx, dayStart, dayStartDateTime, timeZone, - zonedRelativeTo.calendar(), direction, &dayEnd)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(dayEnd)); - - // Step 8. - auto dayLengthNs = - NormalizedTimeDurationFromEpochNanosecondsDifference(dayEnd, dayStart); - MOZ_ASSERT(IsValidInstantSpan(dayLengthNs.to())); - - // Step 9. - NormalizedTimeDuration oneDayLess; - if (!SubtractNormalizedTimeDuration(cx, duration.time, dayLengthNs, - &oneDayLess)) { - return false; - } - - // Step 10. - int32_t oneDayLessSign = NormalizedTimeDurationSign(oneDayLess); - if ((direction > 0 && oneDayLessSign < 0) || - (direction < 0 && oneDayLessSign > 0)) { - *result = duration; - return true; - } - - // Step 11. - Duration adjustedDateDuration; - if (!AddDuration(cx, duration.date.toDuration(), {0, 0, 0, double(direction)}, - zonedRelativeTo, calendar, timeZone, - precalculatedPlainDateTime, &adjustedDateDuration)) { - return false; - } - - // Step 12. - NormalizedTimeDuration roundedTime; - if (!RoundDuration(cx, oneDayLess, increment, unit, roundingMode, - &roundedTime)) { - return false; - } - - // Step 13. - return CombineDateAndNormalizedTimeDuration( - cx, adjustedDateDuration.toDateDuration(), roundedTime, result); -} - -/** - * AdjustRoundedDurationDays ( years, months, weeks, days, norm, increment, - * unit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec, - * precalculatedPlainDateTime ) - */ -bool js::temporal::AdjustRoundedDurationDays( - JSContext* cx, const NormalizedDuration& duration, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode, - Handle zonedRelativeTo, Handle calendar, - Handle timeZone, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result) { - return ::AdjustRoundedDurationDays( - cx, duration, increment, unit, roundingMode, zonedRelativeTo, calendar, - timeZone, mozilla::SomeRef(precalculatedPlainDateTime), result); -} - static bool NumberToStringBuilder(JSContext* cx, double num, JSStringBuilder& sb) { MOZ_ASSERT(IsInteger(num)); @@ -2611,8 +1494,7 @@ static Duration AbsoluteDuration(const Duration& duration) { } /** - * TemporalDurationToString ( years, months, weeks, days, hours, minutes, - * normSeconds, precision ) + * TemporalDurationToString ( duration, precision ) */ static JSString* TemporalDurationToString(JSContext* cx, const Duration& duration, @@ -2641,23 +1523,20 @@ static JSString* TemporalDurationToString(JSContext* cx, MOZ_ASSERT(minutes < DOUBLE_INTEGRAL_PRECISION_LIMIT); MOZ_ASSERT(seconds < DOUBLE_INTEGRAL_PRECISION_LIMIT); - auto secondsDuration = NormalizeTimeDuration(0.0, 0.0, seconds, milliseconds, - microseconds, nanoseconds); - // Step 1. int32_t sign = DurationSign(duration); // Steps 2 and 7. JSStringBuilder result(cx); - // Step 13. (Reordered) + // Step 14. (Reordered) if (sign < 0) { if (!result.append('-')) { return nullptr; } } - // Step 14. (Reordered) + // Step 15. (Reordered) if (!result.append('P')) { return nullptr; } @@ -2708,11 +1587,15 @@ static JSString* TemporalDurationToString(JSContext* cx, bool zeroMinutesAndHigher = years == 0 && months == 0 && weeks == 0 && days == 0 && hours == 0 && minutes == 0; - // Steps 8-9, 12, and 15. - bool hasSecondsPart = (secondsDuration != NormalizedTimeDuration{}) || + // Step 12. + auto secondsDuration = TimeDurationFromComponents( + 0.0, 0.0, seconds, milliseconds, microseconds, nanoseconds); + + // Steps 8-9, 13, and 16. + bool hasSecondsPart = (secondsDuration != TimeDuration{}) || zeroMinutesAndHigher || precision != Precision::Auto(); if (hours != 0 || minutes != 0 || hasSecondsPart) { - // Step 15. (Reordered) + // Step 16. (Reordered) if (!result.append('T')) { return nullptr; } @@ -2737,29 +1620,29 @@ static JSString* TemporalDurationToString(JSContext* cx, } } - // Step 12. + // Step 13. if (hasSecondsPart) { - // Step 12.a. + // Step 13.a. if (!NumberToStringBuilder(cx, double(secondsDuration.seconds), result)) { return nullptr; } - // Step 12.b. + // Step 13.b. if (!FormatFractionalSeconds(result, secondsDuration.nanoseconds, precision)) { return nullptr; } - // Step 12.c. + // Step 13.c. if (!result.append('S')) { return nullptr; } } } - // Steps 13-15. (Moved above) + // Steps 14-16. (Moved above) - // Step 16. + // Step 17. return result.finishString(); } @@ -2768,9 +1651,12 @@ static JSString* TemporalDurationToString(JSContext* cx, */ static bool GetTemporalRelativeToOption( JSContext* cx, Handle options, - MutableHandle> plainRelativeTo, - MutableHandle zonedRelativeTo, - MutableHandle timeZoneRecord) { + MutableHandle plainRelativeTo, + MutableHandle zonedRelativeTo) { + // Default initialize both return values. + plainRelativeTo.set(PlainDate{}); + zonedRelativeTo.set(ZonedDateTime{}); + // Step 1. Rooted value(cx); if (!GetProperty(cx, options, options, cx->names().relativeTo, &value)) { @@ -2779,9 +1665,6 @@ static bool GetTemporalRelativeToOption( // Step 2. if (value.isUndefined()) { - plainRelativeTo.set(nullptr); - zonedRelativeTo.set(ZonedDateTime{}); - timeZoneRecord.set(TimeZoneRecord{}); return true; } @@ -2792,16 +1675,15 @@ static bool GetTemporalRelativeToOption( auto matchBehaviour = MatchBehaviour::MatchExactly; // Steps 5-6. - PlainDateTime dateTime; - Rooted calendar(cx); + EpochNanoseconds epochNanoseconds; Rooted timeZone(cx); - int64_t offsetNs; + Rooted calendar(cx); if (value.isObject()) { Rooted obj(cx, &value.toObject()); // Step 5.a. if (auto* zonedDateTime = obj->maybeUnwrapIf()) { - auto instant = ToInstant(zonedDateTime); + auto epochNs = zonedDateTime->epochNanoseconds(); Rooted timeZone(cx, zonedDateTime->timeZone()); Rooted calendar(cx, zonedDateTime->calendar()); @@ -2813,51 +1695,35 @@ static bool GetTemporalRelativeToOption( } // Step 5.a.i. - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord( - cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZoneRec)) { - return false; - } - - // Step 5.a.ii. - plainRelativeTo.set(nullptr); - zonedRelativeTo.set(ZonedDateTime{instant, timeZone, calendar}); - timeZoneRecord.set(timeZoneRec); + zonedRelativeTo.set(ZonedDateTime{epochNs, timeZone, calendar}); return true; } // Step 5.b. - if (obj->canUnwrapAs()) { - plainRelativeTo.set(obj); - zonedRelativeTo.set(ZonedDateTime{}); - timeZoneRecord.set(TimeZoneRecord{}); + if (auto* plainDate = obj->maybeUnwrapIf()) { + auto date = plainDate->date(); + + Rooted calendar(cx, plainDate->calendar()); + if (!calendar.wrap(cx)) { + return false; + } + + // Step 5.b.i. + plainRelativeTo.set(PlainDate{date, calendar}); return true; } // Step 5.c. if (auto* dateTime = obj->maybeUnwrapIf()) { - auto plainDateTime = ToPlainDate(dateTime); + auto date = dateTime->date(); Rooted calendar(cx, dateTime->calendar()); if (!calendar.wrap(cx)) { return false; } - // Step 5.c.i. - auto* plainDate = CreateTemporalDate(cx, plainDateTime, calendar); - if (!plainDate) { - return false; - } - - // Step 5.c.ii. - plainRelativeTo.set(plainDate); - zonedRelativeTo.set(ZonedDateTime{}); - timeZoneRecord.set(TimeZoneRecord{}); + // Steps 5.c.i-ii. + plainRelativeTo.set(PlainDate{date, calendar}); return true; } @@ -2867,102 +1733,63 @@ static bool GetTemporalRelativeToOption( } // Step 5.e. - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - }, - &calendarRec)) { + Rooted fields(cx); + if (!PrepareCalendarFields(cx, calendar, obj, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + CalendarField::Hour, + CalendarField::Minute, + CalendarField::Second, + CalendarField::Millisecond, + CalendarField::Microsecond, + CalendarField::Nanosecond, + CalendarField::Offset, + CalendarField::TimeZone, + }, + &fields)) { return false; } // Step 5.f. - Rooted fields( - cx, PrepareCalendarFields(cx, calendarRec, obj, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - { - TemporalField::Hour, - TemporalField::Microsecond, - TemporalField::Millisecond, - TemporalField::Minute, - TemporalField::Nanosecond, - TemporalField::Offset, - TemporalField::Second, - TemporalField::TimeZone, - })); - if (!fields) { + ISODateTime dateTime; + if (!InterpretTemporalDateTimeFields( + cx, calendar, fields, TemporalOverflow::Constrain, &dateTime)) { return false; } // Step 5.g. - Rooted dateOptions(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!dateOptions) { - return false; - } + timeZone = fields.timeZone(); // Step 5.h. - Rooted overflow(cx, StringValue(cx->names().constrain)); - if (!DefineDataProperty(cx, dateOptions, cx->names().overflow, overflow)) { - return false; - } - - // Step 5.i. - if (!InterpretTemporalDateTimeFields(cx, calendarRec, fields, dateOptions, - &dateTime)) { - return false; - } + auto offset = fields.offset(); // Step 5.j. - Rooted offset(cx); - if (!GetProperty(cx, fields, fields, cx->names().offset, &offset)) { - return false; - } - - // Step 5.k. - Rooted timeZoneValue(cx); - if (!GetProperty(cx, fields, fields, cx->names().timeZone, - &timeZoneValue)) { - return false; - } - - // Step 5.l. - if (!timeZoneValue.isUndefined()) { - if (!ToTemporalTimeZone(cx, timeZoneValue, &timeZone)) { - return false; - } - } - - // Step 5.m. - if (offset.isUndefined()) { + if (!fields.has(CalendarField::Offset)) { offsetBehaviour = OffsetBehaviour::Wall; } + // Step 7. + if (!timeZone) { + // Steps 7.a-b. + return CreateTemporalDate(cx, dateTime.date, calendar, plainRelativeTo); + } + // Steps 8-9. - if (timeZone) { - if (offsetBehaviour == OffsetBehaviour::Option) { - MOZ_ASSERT(!offset.isUndefined()); - MOZ_ASSERT(offset.isString()); + int64_t offsetNs = 0; + if (offsetBehaviour == OffsetBehaviour::Option) { + // Step 8.a. + offsetNs = int64_t(offset); + } - // Step 8.a. - Rooted offsetString(cx, offset.toString()); - if (!offsetString) { - return false; - } - - // Step 8.b. - if (!ParseDateTimeUTCOffset(cx, offsetString, &offsetNs)) { - return false; - } - } else { - // Step 9. - offsetNs = 0; - } + // Step 10. + if (!InterpretISODateTimeOffset( + cx, dateTime, offsetBehaviour, offsetNs, timeZone, + TemporalDisambiguation::Compatible, TemporalOffset::Reject, + matchBehaviour, &epochNanoseconds)) { + return false; } } else { // Step 6.a. @@ -2974,30 +1801,24 @@ static bool GetTemporalRelativeToOption( Rooted string(cx, value.toString()); // Step 6.b. - bool isUTC; - bool hasOffset; - int64_t timeZoneOffset; - Rooted timeZoneAnnotation(cx); - Rooted calendarString(cx); - if (!ParseTemporalRelativeToString(cx, string, &dateTime, &isUTC, - &hasOffset, &timeZoneOffset, - &timeZoneAnnotation, &calendarString)) { + Rooted parsed(cx); + if (!ParseTemporalRelativeToString(cx, string, &parsed)) { return false; } - // Step 6.c. (Not applicable in our implementation.) + // Steps 6.c-e. (Not applicable in our implementation.) - // Steps 6.e-f. - if (timeZoneAnnotation) { + // Step 6.f. + if (parsed.timeZoneAnnotation()) { // Step 6.f.i. - if (!ToTemporalTimeZone(cx, timeZoneAnnotation, &timeZone)) { + if (!ToTemporalTimeZone(cx, parsed.timeZoneAnnotation(), &timeZone)) { return false; } // Steps 6.f.ii-iii. - if (isUTC) { + if (parsed.isUTC()) { offsetBehaviour = OffsetBehaviour::Exact; - } else if (!hasOffset) { + } else if (!parsed.hasOffset()) { offsetBehaviour = OffsetBehaviour::Wall; } @@ -3007,164 +1828,87 @@ static bool GetTemporalRelativeToOption( MOZ_ASSERT(!timeZone); } - // Steps 6.g-j. - if (calendarString) { - if (!ToBuiltinCalendar(cx, calendarString, &calendar)) { + // Steps 6.g-i. + if (parsed.calendar()) { + if (!CanonicalizeCalendar(cx, parsed.calendar(), &calendar)) { return false; } } else { calendar.set(CalendarValue(CalendarId::ISO8601)); } - // Steps 8-9. - if (timeZone) { - if (offsetBehaviour == OffsetBehaviour::Option) { - MOZ_ASSERT(hasOffset); + // Step 7. + if (!timeZone) { + // Steps 7.a-b. + return CreateTemporalDate(cx, parsed.dateTime().date, calendar, + plainRelativeTo); + } - // Step 8.a. - offsetNs = timeZoneOffset; - } else { - // Step 9. - offsetNs = 0; + // Steps 8-9. + int64_t offsetNs; + if (offsetBehaviour == OffsetBehaviour::Option) { + MOZ_ASSERT(parsed.hasOffset()); + + // Step 8.a. + offsetNs = parsed.timeZoneOffset(); + } else { + // Step 9. + offsetNs = 0; + } + + // Step 10. + if (parsed.isStartOfDay()) { + if (!InterpretISODateTimeOffset( + cx, parsed.dateTime().date, offsetBehaviour, offsetNs, timeZone, + TemporalDisambiguation::Compatible, TemporalOffset::Reject, + matchBehaviour, &epochNanoseconds)) { + return false; + } + } else { + if (!InterpretISODateTimeOffset( + cx, parsed.dateTime(), offsetBehaviour, offsetNs, timeZone, + TemporalDisambiguation::Compatible, TemporalOffset::Reject, + matchBehaviour, &epochNanoseconds)) { + return false; } } } + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); - // Step 7. - if (!timeZone) { - // Step 7.a. - auto* plainDate = CreateTemporalDate(cx, dateTime.date, calendar); - if (!plainDate) { - return false; - } - - plainRelativeTo.set(plainDate); - zonedRelativeTo.set(ZonedDateTime{}); - timeZoneRecord.set(TimeZoneRecord{}); - return true; - } - - // Steps 8-9. (Moved above) - - // Step 10. - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZoneRec)) { - return false; - } - - // Step 11. - Instant epochNanoseconds; - if (!InterpretISODateTimeOffset( - cx, dateTime, offsetBehaviour, offsetNs, timeZoneRec, - TemporalDisambiguation::Compatible, TemporalOffset::Reject, - matchBehaviour, &epochNanoseconds)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(epochNanoseconds)); - - // Step 12. - plainRelativeTo.set(nullptr); + // Steps 11-12. zonedRelativeTo.set(ZonedDateTime{epochNanoseconds, timeZone, calendar}); - timeZoneRecord.set(timeZoneRec); return true; } /** - * CreateCalendarMethodsRecordFromRelativeTo ( plainRelativeTo, zonedRelativeTo, - * methods ) + * RoundTimeDurationToIncrement ( d, increment, roundingMode ) */ -static bool CreateCalendarMethodsRecordFromRelativeTo( - JSContext* cx, Handle> plainRelativeTo, - Handle zonedRelativeTo, - mozilla::EnumSet methods, - MutableHandle result) { - // Step 1. - if (zonedRelativeTo) { - return CreateCalendarMethodsRecord(cx, zonedRelativeTo.calendar(), methods, - result); - } +static TimeDuration RoundTimeDurationToIncrement( + const TimeDuration& duration, const TemporalUnit unit, Increment increment, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidTimeDuration(duration)); + MOZ_ASSERT(unit >= TemporalUnit::Day); + MOZ_ASSERT_IF(unit >= TemporalUnit::Hour, + increment <= MaximumTemporalDurationRoundingIncrement(unit)); - // Step 2. - if (plainRelativeTo) { - auto* unwrapped = plainRelativeTo.unwrap(cx); - if (!unwrapped) { - return false; - } - - Rooted calendar(cx, unwrapped->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - return CreateCalendarMethodsRecord(cx, calendar, methods, result); - } - - // Step 3. - return true; -} - -struct RoundedDuration final { - NormalizedDuration duration; - double total = 0; -}; - -enum class ComputeRemainder : bool { No, Yes }; - -/** - * RoundNormalizedTimeDurationToIncrement ( d, increment, roundingMode ) - */ -static NormalizedTimeDuration RoundNormalizedTimeDurationToIncrement( - const NormalizedTimeDuration& duration, const TemporalUnit unit, - Increment increment, TemporalRoundingMode roundingMode) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); - MOZ_ASSERT(unit > TemporalUnit::Day); - MOZ_ASSERT(increment <= MaximumTemporalDurationRoundingIncrement(unit)); - - int64_t divisor = ToNanoseconds(unit) * increment.value(); - MOZ_ASSERT(divisor > 0); - MOZ_ASSERT(divisor <= ToNanoseconds(TemporalUnit::Day)); + auto divisor = Int128{ToNanoseconds(unit)} * Int128{increment.value()}; + MOZ_ASSERT(divisor > Int128{0}); + MOZ_ASSERT_IF(unit >= TemporalUnit::Hour, + divisor <= Int128{ToNanoseconds(TemporalUnit::Day)}); auto totalNanoseconds = duration.toNanoseconds(); auto rounded = - RoundNumberToIncrement(totalNanoseconds, Int128{divisor}, roundingMode); - return NormalizedTimeDuration::fromNanoseconds(rounded); + RoundNumberToIncrement(totalNanoseconds, divisor, roundingMode); + return TimeDuration::fromNanoseconds(rounded); } /** - * RoundNormalizedTimeDurationToIncrement ( d, increment, roundingMode ) + * TotalTimeDuration ( timeDuration, unit ) */ -static bool RoundNormalizedTimeDurationToIncrement( - JSContext* cx, const NormalizedTimeDuration& duration, - const TemporalUnit unit, Increment increment, - TemporalRoundingMode roundingMode, NormalizedTimeDuration* result) { - // Step 1. - auto rounded = RoundNormalizedTimeDurationToIncrement( - duration, unit, increment, roundingMode); - - // Step 2. - if (!IsValidNormalizedTimeDuration(rounded)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); - return false; - } - - // Step 3. - *result = rounded; - return true; -} - -/** - * DivideNormalizedTimeDuration ( d, divisor ) - */ -static double TotalNormalizedTimeDuration( - const NormalizedTimeDuration& duration, const TemporalUnit unit) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); - MOZ_ASSERT(unit > TemporalUnit::Day); +double js::temporal::TotalTimeDuration(const TimeDuration& duration, + TemporalUnit unit) { + MOZ_ASSERT(IsValidTimeDuration(duration)); + MOZ_ASSERT(unit >= TemporalUnit::Day); auto numerator = duration.toNanoseconds(); auto denominator = Int128{ToNanoseconds(unit)}; @@ -3172,1097 +1916,902 @@ static double TotalNormalizedTimeDuration( } /** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) + * RoundTimeDuration ( duration, increment, unit, roundingMode ) */ -NormalizedTimeDuration js::temporal::RoundDuration( - const NormalizedTimeDuration& duration, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); +static bool RoundTimeDuration(JSContext* cx, const TimeDuration& duration, + Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode, + TimeDuration* result) { + MOZ_ASSERT(IsValidTimeDuration(duration)); + MOZ_ASSERT(increment <= Increment::max()); MOZ_ASSERT(unit > TemporalUnit::Day); - // Steps 1-12. (Not applicable) - - // Step 13. - auto rounded = RoundNormalizedTimeDurationToIncrement( - duration, unit, increment, roundingMode); - MOZ_ASSERT(IsValidNormalizedTimeDuration(rounded)); - - // Step 14. - return rounded; + // Step 1-2. + auto rounded = + RoundTimeDurationToIncrement(duration, unit, increment, roundingMode); + if (!IsValidTimeDuration(rounded)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + *result = rounded; + return true; } /** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) + * RoundTimeDuration ( duration, increment, unit, roundingMode ) */ -bool js::temporal::RoundDuration(JSContext* cx, - const NormalizedTimeDuration& duration, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode, - NormalizedTimeDuration* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); +TimeDuration js::temporal::RoundTimeDuration( + const TimeDuration& duration, Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidTimeDuration(duration)); + MOZ_ASSERT(increment <= Increment::max()); MOZ_ASSERT(unit > TemporalUnit::Day); - // Steps 1-12. (Not applicable) + auto result = + RoundTimeDurationToIncrement(duration, unit, increment, roundingMode); + MOZ_ASSERT(IsValidTimeDuration(result)); - // Steps 13-14. - return RoundNormalizedTimeDurationToIncrement(cx, duration, unit, increment, - roundingMode, result); + return result; } #ifdef DEBUG -// Valid duration days are smaller than ⌈(2**53) / (24 * 60 * 60)⌉. -static constexpr int64_t MaxDurationDays = (int64_t(1) << 53) / (24 * 60 * 60); +/** + * Return true if the input is within the valid epoch nanoseconds limits with a + * time zone offset applied, i.e. it's smaller than ±(8.64 × 10^21 + nsPerDay). + */ +static bool IsValidLocalNanoseconds(const EpochNanoseconds& epochNanoseconds) { + MOZ_ASSERT(0 <= epochNanoseconds.nanoseconds && + epochNanoseconds.nanoseconds <= 999'999'999); -// Maximum number of days in |FractionalDays|. -static constexpr int64_t MaxFractionalDays = - 2 * MaxDurationDays + 2 * MaxEpochDaysDuration; + // Time zone offsets can't exceed 24 hours. + constexpr auto oneDay = EpochDuration::fromDays(1); + + // Exclusive limits. + constexpr auto min = EpochNanoseconds::min() - oneDay; + constexpr auto max = EpochNanoseconds::max() + oneDay; + + return min < epochNanoseconds && epochNanoseconds < max; +} #endif -struct FractionalDays final { - int64_t days = 0; - int64_t time = 0; - int64_t dayLength = 0; - - FractionalDays() = default; - - explicit FractionalDays(int64_t durationDays, - const NormalizedTimeAndDays& timeAndDays) - : days(durationDays + timeAndDays.days), - time(timeAndDays.time), - dayLength(timeAndDays.dayLength) { - MOZ_ASSERT(std::abs(durationDays) <= MaxDurationDays); - MOZ_ASSERT(std::abs(timeAndDays.days) <= MaxDurationDays); - MOZ_ASSERT(std::abs(days) <= MaxFractionalDays); - - // NormalizedTimeDurationToDays guarantees that |dayLength| is strictly - // positive and less than 2**53. - MOZ_ASSERT(dayLength > 0); - MOZ_ASSERT(dayLength < int64_t(1) << 53); - - // NormalizedTimeDurationToDays guarantees that |abs(timeAndDays.time)| is - // less than |timeAndDays.dayLength|. - MOZ_ASSERT(std::abs(time) < dayLength); - } - - FractionalDays operator+=(int32_t epochDays) { - MOZ_ASSERT(std::abs(epochDays) <= MaxEpochDaysDuration); - days += epochDays; - MOZ_ASSERT(std::abs(days) <= MaxFractionalDays); - return *this; - } - - FractionalDays operator-=(int32_t epochDays) { - MOZ_ASSERT(std::abs(epochDays) <= MaxEpochDaysDuration); - days -= epochDays; - MOZ_ASSERT(std::abs(days) <= MaxFractionalDays); - return *this; - } - - int64_t truncate() const { - int64_t truncatedDays = days; - if (time > 0) { - // Round toward positive infinity when the integer days are negative and - // the fractional part is positive. - if (truncatedDays < 0) { - truncatedDays += 1; - } - } else if (time < 0) { - // Round toward negative infinity when the integer days are positive and - // the fractional part is negative. - if (truncatedDays > 0) { - truncatedDays -= 1; - } - } - MOZ_ASSERT(std::abs(truncatedDays) <= MaxFractionalDays + 1); - return truncatedDays; - } - - int32_t sign() const { - if (days != 0) { - return days < 0 ? -1 : 1; - } - return time < 0 ? -1 : time > 0 ? 1 : 0; - } +enum class UnsignedRoundingMode { + Zero, + Infinity, + HalfZero, + HalfInfinity, + HalfEven }; -struct Fraction final { - int64_t numerator = 0; - int32_t denominator = 0; - - constexpr Fraction() = default; - - constexpr Fraction(int64_t numerator, int32_t denominator) - : numerator(numerator), denominator(denominator) { - MOZ_ASSERT(denominator > 0); +/** + * GetUnsignedRoundingMode ( roundingMode, sign ) + */ +static UnsignedRoundingMode GetUnsignedRoundingMode( + TemporalRoundingMode roundingMode, bool isNegative) { + switch (roundingMode) { + case TemporalRoundingMode::Ceil: + return isNegative ? UnsignedRoundingMode::Zero + : UnsignedRoundingMode::Infinity; + case TemporalRoundingMode::Floor: + return isNegative ? UnsignedRoundingMode::Infinity + : UnsignedRoundingMode::Zero; + case TemporalRoundingMode::Expand: + return UnsignedRoundingMode::Infinity; + case TemporalRoundingMode::Trunc: + return UnsignedRoundingMode::Zero; + case TemporalRoundingMode::HalfCeil: + return isNegative ? UnsignedRoundingMode::HalfZero + : UnsignedRoundingMode::HalfInfinity; + case TemporalRoundingMode::HalfFloor: + return isNegative ? UnsignedRoundingMode::HalfInfinity + : UnsignedRoundingMode::HalfZero; + case TemporalRoundingMode::HalfExpand: + return UnsignedRoundingMode::HalfInfinity; + case TemporalRoundingMode::HalfTrunc: + return UnsignedRoundingMode::HalfZero; + case TemporalRoundingMode::HalfEven: + return UnsignedRoundingMode::HalfEven; } -}; + MOZ_CRASH("invalid rounding mode"); +} -struct RoundedNumber final { - Int128 rounded; +struct DurationNudge { + InternalDuration duration; + EpochNanoseconds epochNs; double total = 0; + bool didExpandCalendarUnit = false; }; -static RoundedNumber RoundNumberToIncrement( - const Fraction& fraction, const FractionalDays& fractionalDays, - Increment increment, TemporalRoundingMode roundingMode, - ComputeRemainder computeRemainder) { - MOZ_ASSERT(std::abs(fraction.numerator) < (int64_t(1) << 32) * 2); - MOZ_ASSERT(fraction.denominator > 0); - MOZ_ASSERT(fraction.denominator <= MaxEpochDaysDuration); - MOZ_ASSERT(std::abs(fractionalDays.days) <= MaxFractionalDays); - MOZ_ASSERT(fractionalDays.dayLength > 0); - MOZ_ASSERT(fractionalDays.dayLength < (int64_t(1) << 53)); - MOZ_ASSERT(std::abs(fractionalDays.time) < fractionalDays.dayLength); - MOZ_ASSERT(increment <= Increment::max()); +/** + * NudgeToCalendarUnit ( sign, duration, destEpochNs, isoDateTime, timeZone, + * calendar, increment, unit, roundingMode ) + */ +static bool NudgeToCalendarUnit(JSContext* cx, const InternalDuration& duration, + const EpochNanoseconds& destEpochNs, + const ISODateTime& isoDateTime, + Handle timeZone, + Handle calendar, + Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode, + DurationNudge* result) { + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(destEpochNs)); + MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(destEpochNs)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); + MOZ_ASSERT(unit <= TemporalUnit::Day); + int32_t sign = InternalDurationSign(duration) < 0 ? -1 : 1; + + // Steps 1-4. + int64_t r1; + int64_t r2; + DateDuration startDuration; + DateDuration endDuration; + if (unit == TemporalUnit::Year) { + // Step 1.a. + int64_t years = RoundNumberToIncrement(duration.date.years, increment, + TemporalRoundingMode::Trunc); + + // Step 1.b. + r1 = years; + + // Step 1.c. + r2 = years + int64_t(increment.value()) * sign; + + // Step 1.d. + startDuration = {r1}; + + // Step 1.e. + endDuration = {r2}; + } else if (unit == TemporalUnit::Month) { + // Step 2.a. + int64_t months = RoundNumberToIncrement(duration.date.months, increment, + TemporalRoundingMode::Trunc); + + // Step 2.b. + r1 = months; + + // Step 2.c. + r2 = months + int64_t(increment.value()) * sign; + + // Step 2.d. + startDuration = {duration.date.years, r1}; + + // Step 2.e. + endDuration = {duration.date.years, r2}; + } else if (unit == TemporalUnit::Week) { + // Step 3.a. + auto yearsMonths = DateDuration{duration.date.years, duration.date.months}; + + // Step 3.b. + ISODate weeksStart; + if (!CalendarDateAdd(cx, calendar, isoDateTime.date, yearsMonths, + TemporalOverflow::Constrain, &weeksStart)) { + return false; + } + MOZ_ASSERT(ISODateWithinLimits(weeksStart)); + + // Step 3.c. + ISODate weeksEnd; + if (!BalanceISODate(cx, weeksStart, duration.date.days, &weeksEnd)) { + return false; + } + MOZ_ASSERT(ISODateWithinLimits(weeksEnd)); + + // Step 3.d. + DateDuration untilResult; + if (!CalendarDateUntil(cx, calendar, weeksStart, weeksEnd, + TemporalUnit::Week, &untilResult)) { + return false; + } + + // Step 3.e. + int64_t weeks = + RoundNumberToIncrement(duration.date.weeks + untilResult.weeks, + increment, TemporalRoundingMode::Trunc); + + // Step 3.f. + r1 = weeks; + + // Step 3.g. + r2 = weeks + int64_t(increment.value()) * sign; + + // Step 3.h. + startDuration = {duration.date.years, duration.date.months, r1}; + + // Step 3.i. + endDuration = {duration.date.years, duration.date.months, r2}; + } else { + // Step 4.a. + MOZ_ASSERT(unit == TemporalUnit::Day); + + // Step 4.b. + int64_t days = RoundNumberToIncrement(duration.date.days, increment, + TemporalRoundingMode::Trunc); + + // Step 4.c. + r1 = days; + + // Step 4.d. + r2 = days + int64_t(increment.value()) * sign; + + // Step 4.e. + startDuration = {duration.date.years, duration.date.months, + duration.date.weeks, r1}; + + // Step 4.f. + endDuration = {duration.date.years, duration.date.months, + duration.date.weeks, r2}; + } + MOZ_ASSERT(IsValidDuration(startDuration)); + MOZ_ASSERT(IsValidDuration(endDuration)); + + // Step 5. + MOZ_ASSERT_IF(sign > 0, r1 >= 0 && r1 < r2); + + // Step 6. + MOZ_ASSERT_IF(sign < 0, r1 <= 0 && r1 > r2); + + // Step 7. + ISODate start; + if (!CalendarDateAdd(cx, calendar, isoDateTime.date, startDuration, + TemporalOverflow::Constrain, &start)) { + return false; + } + + // Step 8. + ISODate end; + if (!CalendarDateAdd(cx, calendar, isoDateTime.date, endDuration, + TemporalOverflow::Constrain, &end)) { + return false; + } + + // Step 9. + auto startDateTime = ISODateTime{start, isoDateTime.time}; + MOZ_ASSERT(ISODateTimeWithinLimits(startDateTime)); + + // Step 10. + auto endDateTime = ISODateTime{end, isoDateTime.time}; + MOZ_ASSERT(ISODateTimeWithinLimits(endDateTime)); + + // Steps 11-12. + EpochNanoseconds startEpochNs; + EpochNanoseconds endEpochNs; + if (!timeZone) { + // Step 11.a. + startEpochNs = GetUTCEpochNanoseconds(startDateTime); + + // Step 11.b. + endEpochNs = GetUTCEpochNanoseconds(endDateTime); + } else { + // Step 12.a. + if (!GetEpochNanosecondsFor(cx, timeZone, startDateTime, + TemporalDisambiguation::Compatible, + &startEpochNs)) { + return false; + } + + // Step 12.b. + if (!GetEpochNanosecondsFor(cx, timeZone, endDateTime, + TemporalDisambiguation::Compatible, + &endEpochNs)) { + return false; + } + } + + // Steps 13-14. + MOZ_ASSERT_IF(sign > 0, + startEpochNs <= destEpochNs && destEpochNs <= endEpochNs); + MOZ_ASSERT_IF(sign < 0, + endEpochNs <= destEpochNs && destEpochNs <= startEpochNs); + + // Step 15. + MOZ_ASSERT(startEpochNs != endEpochNs); + + // Step 16. + auto numerator = (destEpochNs - startEpochNs).toNanoseconds(); + auto denominator = (endEpochNs - startEpochNs).toNanoseconds(); + MOZ_ASSERT(denominator != Int128{0}); + MOZ_ASSERT(numerator.abs() <= denominator.abs()); + MOZ_ASSERT_IF(denominator > Int128{0}, numerator >= Int128{0}); + MOZ_ASSERT_IF(denominator < Int128{0}, numerator <= Int128{0}); + + // Ensure |numerator| and |denominator| are both non-negative to simplify the + // following computations. + if (denominator < Int128{0}) { + numerator = -numerator; + denominator = -denominator; + } + + // Steps 17-19. + // + // |total| must only be computed when called from Duration.prototype.total, + // which always passes "trunc" rounding mode with an increment of one. + double total = mozilla::UnspecifiedNaN(); + if (roundingMode == TemporalRoundingMode::Trunc && + increment == Increment{1}) { + // total = r1 + progress × increment × sign + // = r1 + (numerator / denominator) × increment × sign + // = r1 + (numerator × increment × sign) / denominator + // = (r1 × denominator + numerator × increment × sign) / denominator + // + // Computing `n` can't overflow, because: + // - For years, months, and weeks, `abs(r1) ≤ 2^32`. + // - For days, `abs(r1) < ⌈(2^53) / (24 * 60 * 60)⌉`. + // - `denominator` and `numerator` are below-or-equal `2 × 8.64 × 10^21`. + // - And finally `increment ≤ 10^9`. + auto n = Int128{r1} * denominator + numerator * Int128{sign}; + total = FractionToDouble(n, denominator); + } + + // Steps 20-21. + auto unsignedRoundingMode = GetUnsignedRoundingMode(roundingMode, sign < 0); + + // Steps 22-23. (Inlined ApplyUnsignedRoundingMode) + // // clang-format off // - // Change the representation of |fractionalWeeks| from a real number to a - // rational number, because we don't support arbitrary precision real - // numbers. + // ApplyUnsignedRoundingMode, steps 1-16. // - // |fractionalWeeks| is defined as: + // `total = r1` iff `progress = 0`. And `progress = 0` iff `numerator = 0`. // - // fractionalWeeks - // = weeks + days' / abs(oneWeekDays) + // d1 = total - r1 + // = (r1 × denominator + numerator × increment × sign) / denominator - r1 + // = (numerator × increment × sign) / denominator // - // where days' = days + nanoseconds / dayLength. + // d2 = r2 - total + // = r1 + increment - (r1 × denominator + numerator × increment × sign) / denominator + // = (increment × denominator - numerator × increment × sign) / denominator // - // The fractional part |nanoseconds / dayLength| is from step 7. + // d1 < d2 + // ⇔ (numerator × increment × sign) / denominator < (increment × denominator - numerator × increment × sign) / denominator + // ⇔ (numerator × increment × sign) < (increment × denominator - numerator × increment × sign) + // ⇔ (numerator × sign) < (denominator - numerator × sign) + // ⇔ (2 × numerator × sign) < denominator // - // The denominator for |fractionalWeeks| is |dayLength * abs(oneWeekDays)|. - // - // fractionalWeeks - // = weeks + (days + nanoseconds / dayLength) / abs(oneWeekDays) - // = weeks + days / abs(oneWeekDays) + nanoseconds / (dayLength * abs(oneWeekDays)) - // = (weeks * dayLength * abs(oneWeekDays) + days * dayLength + nanoseconds) / (dayLength * abs(oneWeekDays)) - // - // Because |abs(nanoseconds / dayLength) < 0|, this operation can be rewritten - // to omit the multiplication by |dayLength| when the rounding conditions are - // appropriately modified to account for the |nanoseconds / dayLength| part. - // This allows to implement rounding using only int64 values. - // - // This optimization is currently only implemented when |nanoseconds| is zero. - // - // Example how to expand this optimization for non-zero |nanoseconds|: - // - // |Round(fraction / increment) * increment| with: - // fraction = numerator / denominator - // numerator = weeks * dayLength * abs(oneWeekDays) + days * dayLength + nanoseconds - // denominator = dayLength * abs(oneWeekDays) - // - // When ignoring the |nanoseconds / dayLength| part, this can be simplified to: - // - // |Round(fraction / increment) * increment| with: - // fraction = numerator / denominator - // numerator = weeks * abs(oneWeekDays) + days - // denominator = abs(oneWeekDays) - // - // Where: - // fraction / increment - // = (numerator / denominator) / increment - // = numerator / (denominator * increment) - // - // And |numerator| and |denominator * increment| both fit into int64. - // - // The "ceiling" operation has to be modified from: - // - // CeilDiv(dividend, divisor) - // quot, rem = dividend / divisor - // return quot + (rem > 0) - // - // To: - // - // CeilDiv(dividend, divisor, fractional) - // quot, rem = dividend / divisor - // return quot + ((rem > 0) || (fractional > 0)) - // - // To properly account for the fractional |nanoseconds| part. Alternatively - // |dividend| can be modified before calling `CeilDiv`. + // cardinality = (r1 / (r2 – r1)) modulo 2 + // = (r1 / (r1 + increment - r1)) modulo 2 + // = (r1 / increment) modulo 2 // // clang-format on - - if (fractionalDays.time == 0) { - auto [numerator, denominator] = fraction; - int64_t totalDays = fractionalDays.days + denominator * numerator; - - if (computeRemainder == ComputeRemainder::Yes) { - constexpr auto rounded = Int128{0}; - double total = FractionToDouble(totalDays, denominator); - return {rounded, total}; - } - - auto rounded = - RoundNumberToIncrement(totalDays, denominator, increment, roundingMode); - constexpr double total = 0; - return {rounded, total}; + bool didExpandCalendarUnit; + if (numerator == denominator) { + didExpandCalendarUnit = true; + } else if (numerator == Int128{0}) { + didExpandCalendarUnit = false; + } else if (unsignedRoundingMode == UnsignedRoundingMode::Zero) { + didExpandCalendarUnit = false; + } else if (unsignedRoundingMode == UnsignedRoundingMode::Infinity) { + didExpandCalendarUnit = true; + } else if (numerator + numerator < denominator) { + didExpandCalendarUnit = false; + } else if (numerator + numerator > denominator) { + didExpandCalendarUnit = true; + } else if (unsignedRoundingMode == UnsignedRoundingMode::HalfZero) { + didExpandCalendarUnit = false; + } else if (unsignedRoundingMode == UnsignedRoundingMode::HalfInfinity) { + didExpandCalendarUnit = true; + } else if ((r1 / increment.value()) % 2 == 0) { + didExpandCalendarUnit = false; + } else { + didExpandCalendarUnit = true; } - do { - auto dayLength = mozilla::CheckedInt64(fractionalDays.dayLength); - - auto denominator = dayLength * fraction.denominator; - if (!denominator.isValid()) { - break; - } - - auto amountNanos = denominator * fraction.numerator; - if (!amountNanos.isValid()) { - break; - } - - auto totalNanoseconds = dayLength * fractionalDays.days; - totalNanoseconds += fractionalDays.time; - totalNanoseconds += amountNanos; - if (!totalNanoseconds.isValid()) { - break; - } - - if (computeRemainder == ComputeRemainder::Yes) { - constexpr auto rounded = Int128{0}; - double total = - FractionToDouble(totalNanoseconds.value(), denominator.value()); - return {rounded, total}; - } - - auto rounded = RoundNumberToIncrement( - totalNanoseconds.value(), denominator.value(), increment, roundingMode); - constexpr double total = 0; - return {rounded, total}; - } while (false); - - // Use int128 when values are too large for int64. Additionally assert all - // values fit into int128. - - // `dayLength` < 2**53 - auto dayLength = Int128{fractionalDays.dayLength}; - MOZ_ASSERT(dayLength < Int128{1} << 53); - - // `fraction.denominator` < MaxEpochDaysDuration - // log2(MaxEpochDaysDuration) = ~27.57. - auto denominator = dayLength * Int128{fraction.denominator}; - MOZ_ASSERT(denominator < Int128{1} << (53 + 28)); - - // log2(24*60*60) = ~16.4 and log2(2 * MaxEpochDaysDuration) = ~28.57. - // - // `abs(MaxFractionalDays)` - // = `abs(2 * MaxDurationDays + 2 * MaxEpochDaysDuration)` - // = `abs(2 * 2**(53 - 16) + 2 * MaxEpochDaysDuration)` - // ≤ 2 * 2**37 + 2**29 - // ≤ 2**39 - auto totalDays = Int128{fractionalDays.days}; - MOZ_ASSERT(totalDays.abs() <= Uint128{1} << 39); - - // `abs(fraction.numerator)` ≤ (2**33) - auto totalAmount = Int128{fraction.numerator}; - MOZ_ASSERT(totalAmount.abs() <= Uint128{1} << 33); - - // `denominator` < 2**(53 + 28) - // `abs(totalAmount)` <= 2**33 - // - // `denominator * totalAmount` - // ≤ 2**(53 + 28) * 2**33 - // = 2**(53 + 28 + 33) - // = 2**114 - auto amountNanos = denominator * totalAmount; - MOZ_ASSERT(amountNanos.abs() <= Uint128{1} << 114); - - // `dayLength` < 2**53 - // `totalDays` ≤ 2**39 - // `fractionalDays.time` < `dayLength` < 2**53 - // `amountNanos` ≤ 2**114 - // - // `dayLength * totalDays` - // ≤ 2**(53 + 39) = 2**92 - // - // `dayLength * totalDays + fractionalDays.time` - // ≤ 2**93 - // - // `dayLength * totalDays + fractionalDays.time + amountNanos` - // ≤ 2**115 - auto totalNanoseconds = dayLength * totalDays; - totalNanoseconds += Int128{fractionalDays.time}; - totalNanoseconds += amountNanos; - MOZ_ASSERT(totalNanoseconds.abs() <= Uint128{1} << 115); - - if (computeRemainder == ComputeRemainder::Yes) { - constexpr auto rounded = Int128{0}; - double total = FractionToDouble(totalNanoseconds, denominator); - return {rounded, total}; - } - - auto rounded = RoundNumberToIncrement(totalNanoseconds, denominator, - increment, roundingMode); - constexpr double total = 0; - return {rounded, total}; -} - -static bool RoundDurationYear(JSContext* cx, const NormalizedDuration& duration, - FractionalDays fractionalDays, - Increment increment, - TemporalRoundingMode roundingMode, - Handle> dateRelativeTo, - Handle calendar, - ComputeRemainder computeRemainder, - RoundedDuration* result) { - auto [years, months, weeks, days] = duration.date; - - // Step 9.a. - auto yearsDuration = DateDuration{years}; - - // Step 9.b. - auto yearsLater = AddDate(cx, calendar, dateRelativeTo, yearsDuration); - if (!yearsLater) { - return false; - } - auto yearsLaterDate = ToPlainDate(&yearsLater.unwrap()); - - // Step 9.f. (Reordered) - Rooted> newRelativeTo(cx, yearsLater); - - // Step 9.c. - auto yearsMonthsWeeks = DateDuration{years, months, weeks}; - - // Step 9.d. - PlainDate yearsMonthsWeeksLater; - if (!AddDate(cx, calendar, dateRelativeTo, yearsMonthsWeeks, - &yearsMonthsWeeksLater)) { - return false; - } - - // Step 9.e. - int32_t monthsWeeksInDays = DaysUntil(yearsLaterDate, yearsMonthsWeeksLater); - MOZ_ASSERT(std::abs(monthsWeeksInDays) <= MaxEpochDaysDuration); - - // Step 9.f. (Moved up) - - // Step 9.g. - fractionalDays += monthsWeeksInDays; - - // FIXME: spec issue - truncation doesn't match the spec polyfill. - // https://github.com/tc39/proposal-temporal/issues/2540 - - // Step 9.h. - PlainDate isoResult; - if (!BalanceISODate(cx, yearsLaterDate, fractionalDays.truncate(), - &isoResult)) { - return false; - } - - // Step 9.i. - Rooted wholeDaysLater( - cx, CreateTemporalDate(cx, isoResult, calendar.receiver())); - if (!wholeDaysLater) { - return false; - } - - // Steps 9.j-l. - DateDuration timePassed; - if (!DifferenceDate(cx, calendar, newRelativeTo, wholeDaysLater, - TemporalUnit::Year, &timePassed)) { - return false; - } - - // Step 9.m. - int64_t yearsPassed = timePassed.years; - - // Step 9.n. - years += yearsPassed; - - // Step 9.o. - auto yearsPassedDuration = DateDuration{yearsPassed}; - - // Steps 9.p-r. - int32_t daysPassed; - if (!MoveRelativeDate(cx, calendar, newRelativeTo, yearsPassedDuration, - &newRelativeTo, &daysPassed)) { - return false; - } - MOZ_ASSERT(std::abs(daysPassed) <= MaxEpochDaysDuration); - - // Step 9.s. - fractionalDays -= daysPassed; - - // Steps 9.t. - int32_t sign = fractionalDays.sign() < 0 ? -1 : 1; - - // Step 9.u. - auto oneYear = DateDuration{sign}; - - // Steps 9.v-w. - Rooted> moveResultIgnored(cx); - int32_t oneYearDays; - if (!MoveRelativeDate(cx, calendar, newRelativeTo, oneYear, - &moveResultIgnored, &oneYearDays)) { - return false; - } - - // Step 9.x. - if (oneYearDays == 0) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_NUMBER, "days"); - return false; - } - - // Steps 9.y. - auto fractionalYears = Fraction{years, std::abs(oneYearDays)}; - - // Steps 9.z-aa. - auto [numYears, total] = - RoundNumberToIncrement(fractionalYears, fractionalDays, increment, - roundingMode, computeRemainder); - - // Step 9.ab. - int64_t numMonths = 0; - int64_t numWeeks = 0; - - // Step 9.ac. - constexpr auto time = NormalizedTimeDuration{}; - - // Step 14. - if (numYears.abs() >= (Uint128{1} << 32)) { - return ThrowInvalidDurationPart(cx, double(numYears), "years", - JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE); - } - - auto resultDuration = DateDuration{int64_t(numYears), numMonths, numWeeks}; - if (!ThrowIfInvalidDuration(cx, resultDuration)) { - return false; - } - - *result = {{resultDuration, time}, total}; + // Steps 24-28. + auto resultDuration = didExpandCalendarUnit ? endDuration : startDuration; + auto resultEpochNs = didExpandCalendarUnit ? endEpochNs : startEpochNs; + *result = {{resultDuration, {}}, resultEpochNs, total, didExpandCalendarUnit}; return true; } -static bool RoundDurationMonth(JSContext* cx, - const NormalizedDuration& duration, - FractionalDays fractionalDays, - Increment increment, - TemporalRoundingMode roundingMode, - Handle> dateRelativeTo, - Handle calendar, - ComputeRemainder computeRemainder, - RoundedDuration* result) { - auto [years, months, weeks, days] = duration.date; +#ifdef DEBUG +static bool IsValidTimeFromDateTimeDuration(const TimeDuration& timeDuration) { + // Time zone adjustment can't exceed 24 hours. + constexpr auto oneDay = EpochDuration::fromDays(1); - // Step 10.a. - auto yearsMonths = DateDuration{years, months}; + // Time zone adjusted nsMinInstant and nsMaxInstant. + constexpr auto min = EpochNanoseconds::min() - oneDay; + constexpr auto max = EpochNanoseconds::max() + oneDay; - // Step 10.b. - auto yearsMonthsLater = AddDate(cx, calendar, dateRelativeTo, yearsMonths); - if (!yearsMonthsLater) { - return false; - } - auto yearsMonthsLaterDate = ToPlainDate(&yearsMonthsLater.unwrap()); + // Maximum duration between two date-time points. + constexpr auto maxDuration = (max - min).to(); + static_assert(maxDuration == TimeDuration::fromDays(200'000'002)); - // Step 10.f. (Reordered) - Rooted> newRelativeTo(cx, yearsMonthsLater); - - // Step 10.c. - auto yearsMonthsWeeks = DateDuration{years, months, weeks}; - - // Step 10.d. - PlainDate yearsMonthsWeeksLater; - if (!AddDate(cx, calendar, dateRelativeTo, yearsMonthsWeeks, - &yearsMonthsWeeksLater)) { - return false; - } - - // Step 10.e. - int32_t weeksInDays = DaysUntil(yearsMonthsLaterDate, yearsMonthsWeeksLater); - MOZ_ASSERT(std::abs(weeksInDays) <= MaxEpochDaysDuration); - - // Step 10.f. (Moved up) - - // Step 10.g. - fractionalDays += weeksInDays; - - // FIXME: spec issue - truncation doesn't match the spec polyfill. - // https://github.com/tc39/proposal-temporal/issues/2540 - - // Step 10.h. - PlainDate isoResult; - if (!BalanceISODate(cx, yearsMonthsLaterDate, fractionalDays.truncate(), - &isoResult)) { - return false; - } - - // Step 10.i. - Rooted wholeDaysLater( - cx, CreateTemporalDate(cx, isoResult, calendar.receiver())); - if (!wholeDaysLater) { - return false; - } - - // Steps 10.j-l. - DateDuration timePassed; - if (!DifferenceDate(cx, calendar, newRelativeTo, wholeDaysLater, - TemporalUnit::Month, &timePassed)) { - return false; - } - - // Step 10.m. - int64_t monthsPassed = timePassed.months; - - // Step 10.n. - months += monthsPassed; - - // Step 10.o. - auto monthsPassedDuration = DateDuration{0, monthsPassed}; - - // Steps 10.p-r. - int32_t daysPassed; - if (!MoveRelativeDate(cx, calendar, newRelativeTo, monthsPassedDuration, - &newRelativeTo, &daysPassed)) { - return false; - } - MOZ_ASSERT(std::abs(daysPassed) <= MaxEpochDaysDuration); - - // Step 10.s. - fractionalDays -= daysPassed; - - // Steps 10.t. - int32_t sign = fractionalDays.sign() < 0 ? -1 : 1; - - // Step 10.u. - auto oneMonth = DateDuration{0, sign}; - - // Steps 10.v-w. - Rooted> moveResultIgnored(cx); - int32_t oneMonthDays; - if (!MoveRelativeDate(cx, calendar, newRelativeTo, oneMonth, - &moveResultIgnored, &oneMonthDays)) { - return false; - } - - // Step 10.x. - if (oneMonthDays == 0) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_NUMBER, "days"); - return false; - } - - // Step 10.y. - auto fractionalMonths = Fraction{months, std::abs(oneMonthDays)}; - - // Steps 10.z-aa. - auto [numMonths, total] = - RoundNumberToIncrement(fractionalMonths, fractionalDays, increment, - roundingMode, computeRemainder); - - // Step 10.ab. - int64_t numWeeks = 0; - - // Step 10.ac. - constexpr auto time = NormalizedTimeDuration{}; - - // Step 14. - if (numMonths.abs() >= (Uint128{1} << 32)) { - return ThrowInvalidDurationPart(cx, double(numMonths), "months", - JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE); - } - - auto resultDuration = DateDuration{years, int64_t(numMonths), numWeeks}; - if (!ThrowIfInvalidDuration(cx, resultDuration)) { - return false; - } - - *result = {{resultDuration, time}, total}; - return true; + // If |timeDuration| is a duration between two date-times within the valid + // limits, the duration can't exceed the duration between time zone adjusted + // nsMinInstant and nsMaxInstant. + return timeDuration.abs() < maxDuration; } +#endif -static bool RoundDurationWeek(JSContext* cx, const NormalizedDuration& duration, - FractionalDays fractionalDays, - Increment increment, - TemporalRoundingMode roundingMode, - Handle> dateRelativeTo, - Handle calendar, - ComputeRemainder computeRemainder, - RoundedDuration* result) { - auto [years, months, weeks, days] = duration.date; - - auto* unwrappedRelativeTo = dateRelativeTo.unwrap(cx); - if (!unwrappedRelativeTo) { - return false; - } - auto relativeToDate = ToPlainDate(unwrappedRelativeTo); - - // Step 11.a - PlainDate isoResult; - if (!BalanceISODate(cx, relativeToDate, fractionalDays.truncate(), - &isoResult)) { - return false; - } - - // Step 11.b. - Rooted wholeDaysLater( - cx, CreateTemporalDate(cx, isoResult, calendar.receiver())); - if (!wholeDaysLater) { - return false; - } - - // Steps 11.c-e. - DateDuration timePassed; - if (!DifferenceDate(cx, calendar, dateRelativeTo, wholeDaysLater, - TemporalUnit::Week, &timePassed)) { - return false; - } - - // Step 11.f. - int64_t weeksPassed = timePassed.weeks; - - // Step 11.g. - weeks += weeksPassed; - - // Step 11.h. - auto weeksPassedDuration = DateDuration{0, 0, weeksPassed}; - - // Steps 11.i-k. - Rooted> newRelativeTo(cx); - int32_t daysPassed; - if (!MoveRelativeDate(cx, calendar, dateRelativeTo, weeksPassedDuration, - &newRelativeTo, &daysPassed)) { - return false; - } - MOZ_ASSERT(std::abs(daysPassed) <= MaxEpochDaysDuration); - - // Step 11.l. - fractionalDays -= daysPassed; - - // Steps 11.m. - int32_t sign = fractionalDays.sign() < 0 ? -1 : 1; - - // Step 11.n. - auto oneWeek = DateDuration{0, 0, sign}; - - // Steps 11.o-p. - Rooted> moveResultIgnored(cx); - int32_t oneWeekDays; - if (!MoveRelativeDate(cx, calendar, newRelativeTo, oneWeek, - &moveResultIgnored, &oneWeekDays)) { - return false; - } - - // Step 11.q. - if (oneWeekDays == 0) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_NUMBER, "days"); - return false; - } - - // Step 11.r. - auto fractionalWeeks = Fraction{weeks, std::abs(oneWeekDays)}; - - // Steps 11.s-t. - auto [numWeeks, total] = - RoundNumberToIncrement(fractionalWeeks, fractionalDays, increment, - roundingMode, computeRemainder); - - // Step 11.u. - constexpr auto time = NormalizedTimeDuration{}; - - // Step 14. - if (numWeeks.abs() >= (Uint128{1} << 32)) { - return ThrowInvalidDurationPart(cx, double(numWeeks), "weeks", - JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE); - } - - auto resultDuration = DateDuration{years, months, int64_t(numWeeks)}; - if (!ThrowIfInvalidDuration(cx, resultDuration)) { - return false; - } - - *result = {{resultDuration, time}, total}; - return true; -} - -static bool RoundDurationDay(JSContext* cx, const NormalizedDuration& duration, - const FractionalDays& fractionalDays, - Increment increment, +/** + * NudgeToZonedTime ( sign, duration, isoDateTime, timeZone, calendar, + * increment, unit, roundingMode ) + */ +static bool NudgeToZonedTime(JSContext* cx, const InternalDuration& duration, + const ISODateTime& isoDateTime, + Handle timeZone, + Handle calendar, + Increment increment, TemporalUnit unit, TemporalRoundingMode roundingMode, - ComputeRemainder computeRemainder, - RoundedDuration* result) { - auto [years, months, weeks, days] = duration.date; + DurationNudge* result) { + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT(IsValidTimeFromDateTimeDuration(duration.time)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); + MOZ_ASSERT(unit >= TemporalUnit::Hour); - // Pass zero fraction. - constexpr auto zero = Fraction{0, 1}; + int32_t sign = InternalDurationSign(duration) < 0 ? -1 : 1; - // Steps 12.a-b. - auto [numDays, total] = RoundNumberToIncrement( - zero, fractionalDays, increment, roundingMode, computeRemainder); - - MOZ_ASSERT(Int128{INT64_MIN} <= numDays && numDays <= Int128{INT64_MAX}, - "rounded days fits in int64"); - - // Step 12.c. - constexpr auto time = NormalizedTimeDuration{}; - - // Step 14. - auto resultDuration = DateDuration{years, months, weeks, int64_t(numDays)}; - if (!ThrowIfInvalidDuration(cx, resultDuration)) { + // Step 1. + ISODate start; + if (!CalendarDateAdd(cx, calendar, isoDateTime.date, duration.date, + TemporalOverflow::Constrain, &start)) { return false; } - *result = {{resultDuration, time}, total}; + // Step 2. + auto startDateTime = ISODateTime{start, isoDateTime.time}; + MOZ_ASSERT(ISODateTimeWithinLimits(startDateTime)); + + // Step 3. + auto end = BalanceISODate(start, sign); + + // Step 4. + auto endDateTime = ISODateTime{end, isoDateTime.time}; + if (!ISODateTimeWithinLimits(endDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } + + // Step 5. + EpochNanoseconds startEpochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, startDateTime, + TemporalDisambiguation::Compatible, + &startEpochNs)) { + return false; + } + + // Step 6. + EpochNanoseconds endEpochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, endDateTime, + TemporalDisambiguation::Compatible, + &endEpochNs)) { + return false; + } + + // Step 7. + auto daySpan = + TimeDurationFromEpochNanosecondsDifference(endEpochNs, startEpochNs); + MOZ_ASSERT(daySpan.abs() <= TimeDuration::fromDays(2), + "maximum day length for repeated days"); + + // Step 8. + MOZ_ASSERT(TimeDurationSign(daySpan) == sign); + + // Steps 9-10. + // + // RoundTimeDurationToIncrement is infallible |duration.time| is a valid + // date-time duration. + auto roundedTime = RoundTimeDurationToIncrement(duration.time, unit, + increment, roundingMode); + MOZ_ASSERT(IsValidTimeDuration(roundedTime)); + + // Step 11. (Inlined AddTimeDuration) + auto beyondDaySpan = roundedTime - daySpan; + MOZ_ASSERT(IsValidTimeDuration(beyondDaySpan)); + + // Steps 12-13. + bool didRoundBeyondDay; + int32_t dayDelta; + EpochNanoseconds nudgedEpochNs; + if (TimeDurationSign(beyondDaySpan) != -sign) { + // Step 12.a. + didRoundBeyondDay = true; + + // Step 12.b. + dayDelta = sign; + + // Step 12.c. + // + // This call to RoundTimeDurationToIncrement is also infallible. + roundedTime = RoundTimeDurationToIncrement(beyondDaySpan, unit, increment, + roundingMode); + MOZ_ASSERT(IsValidTimeDuration(roundedTime)); + + // Step 12.d. (Inlined AddTimeDurationToEpochNanoseconds) + nudgedEpochNs = endEpochNs + roundedTime.to(); + } else { + // Step 13.a. + didRoundBeyondDay = false; + + // Step 13.b. + dayDelta = 0; + + // Step 13.c. (Inlined AddTimeDurationToEpochNanoseconds) + nudgedEpochNs = startEpochNs + roundedTime.to(); + } + + // Step 14. + auto dateDuration = DateDuration{ + duration.date.years, + duration.date.months, + duration.date.weeks, + duration.date.days + dayDelta, + }; + MOZ_ASSERT(IsValidDuration(dateDuration)); + + // Step 15. + MOZ_ASSERT(DateDurationSign(dateDuration) * TimeDurationSign(roundedTime) >= + 0); + auto resultDuration = InternalDuration{dateDuration, roundedTime}; + + // Step 16. + *result = { + resultDuration, + nudgedEpochNs, + mozilla::UnspecifiedNaN(), + didRoundBeyondDay, + }; return true; } /** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) + * NudgeToDayOrTime ( duration, destEpochNs, largestUnit, increment, + * smallestUnit, roundingMode ) */ -static bool RoundDuration(JSContext* cx, const NormalizedDuration& duration, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode, - ComputeRemainder computeRemainder, - RoundedDuration* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration.time)); - MOZ_ASSERT_IF(unit > TemporalUnit::Day, IsValidDuration(duration.date)); +static DurationNudge NudgeToDayOrTime(const InternalDuration& duration, + const EpochNanoseconds& destEpochNs, + TemporalUnit largestUnit, + Increment increment, + TemporalUnit smallestUnit, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT(IsValidLocalNanoseconds(destEpochNs)); + MOZ_ASSERT(smallestUnit >= TemporalUnit::Day); - // The remainder is only needed when called from |Duration_total|. And `total` - // always passes |increment=1| and |roundingMode=trunc|. - MOZ_ASSERT_IF(computeRemainder == ComputeRemainder::Yes, - increment == Increment{1}); - MOZ_ASSERT_IF(computeRemainder == ComputeRemainder::Yes, - roundingMode == TemporalRoundingMode::Trunc); + // Step 1. (Inlined Add24HourDaysToTimeDuration) + auto timeDuration = + duration.time + TimeDuration::fromDays(duration.date.days); + MOZ_ASSERT(IsValidTimeDuration(timeDuration)); + MOZ_ASSERT(IsValidTimeFromDateTimeDuration(timeDuration)); - // Steps 1-5. (Not applicable.) + // Steps 2-3. + // + // RoundTimeDurationToIncrement is infallible |timeDuration| is a valid + // date-time duration. + auto roundedTime = RoundTimeDurationToIncrement(timeDuration, smallestUnit, + increment, roundingMode); + MOZ_ASSERT(IsValidTimeDuration(roundedTime)); + + // Step 4. (Inlined AddTimeDuration) + auto diffTime = roundedTime - timeDuration; + MOZ_ASSERT(IsValidTimeDuration(diffTime)); + + // Step 5. + int64_t wholeDays = timeDuration.toDays(); // Step 6. - if (unit <= TemporalUnit::Week) { + int64_t roundedWholeDays = roundedTime.toDays(); + + // Step 7. + int64_t dayDelta = roundedWholeDays - wholeDays; + + // Step 8. + int32_t dayDeltaSign = dayDelta < 0 ? -1 : dayDelta > 0 ? 1 : 0; + + // Step 9. + bool didExpandDays = dayDeltaSign == TimeDurationSign(timeDuration); + + // Step 10. (Inlined AddTimeDurationToEpochNanoseconds) + auto nudgedEpochNs = destEpochNs + diffTime.to(); + + // Step 11. + int64_t days = 0; + + // Step 12. + auto remainder = roundedTime; + + // Step 13. + if (largestUnit <= TemporalUnit::Day) { + // Step 13.a. + days = roundedWholeDays; + + // Step 13.b. + remainder = roundedTime - TimeDuration::fromDays(roundedWholeDays); + MOZ_ASSERT(IsValidTimeDuration(remainder)); + } + + // Step 14. + auto dateDuration = DateDuration{ + duration.date.years, + duration.date.months, + duration.date.weeks, + days, + }; + MOZ_ASSERT(IsValidDuration(dateDuration)); + + // Step 15. + MOZ_ASSERT(DateDurationSign(dateDuration) * TimeDurationSign(remainder) >= 0); + auto resultDuration = InternalDuration{dateDuration, remainder}; + + // Step 16. + return {resultDuration, nudgedEpochNs, mozilla::UnspecifiedNaN(), + didExpandDays}; +} + +/** + * BubbleRelativeDuration ( sign, duration, nudgedEpochNs, isoDateTime, + * timeZone, calendar, largestUnit, smallestUnit ) + */ +static bool BubbleRelativeDuration( + JSContext* cx, const InternalDuration& duration, const DurationNudge& nudge, + const ISODateTime& isoDateTime, Handle timeZone, + Handle calendar, TemporalUnit largestUnit, + TemporalUnit smallestUnit, InternalDuration* result) { + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT(IsValidDuration(nudge.duration)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); + MOZ_ASSERT(largestUnit <= TemporalUnit::Day); + MOZ_ASSERT(smallestUnit <= TemporalUnit::Day); + MOZ_ASSERT(largestUnit <= smallestUnit); + + int32_t sign = InternalDurationSign(duration) < 0 ? -1 : 1; + + // Step 1. + if (smallestUnit == largestUnit) { + *result = nudge.duration; + return true; + } + MOZ_ASSERT(smallestUnit != TemporalUnit::Year); + + // Steps 2-6. + auto dateDuration = nudge.duration.date; + auto timeDuration = nudge.duration.time; + auto unit = smallestUnit; + while (unit > largestUnit) { + using TemporalUnitType = std::underlying_type_t; + + static_assert(static_cast(TemporalUnit::Auto) == 0, + "TemporalUnit::Auto has value zero"); + MOZ_ASSERT(unit > TemporalUnit::Auto, "can subtract unit by one"); + + // Steps 4, 6.a, and 6.c. + unit = static_cast(static_cast(unit) - 1); + MOZ_ASSERT(TemporalUnit::Year <= unit && unit <= TemporalUnit::Week); + + // Step 6.b. + if (unit != TemporalUnit::Week || largestUnit == TemporalUnit::Week) { + // Steps 6.b.i-iii. + DateDuration endDuration; + if (unit == TemporalUnit::Year) { + // Step 6.b.i.1. + int64_t years = dateDuration.years + sign; + + // Step 6.b.i.2. + endDuration = {years}; + } else if (unit == TemporalUnit::Month) { + // Step 6.b.ii.1. + int64_t months = dateDuration.months + sign; + + // Step 6.b.ii.2. + endDuration = {dateDuration.years, months}; + } else { + // Step 6.b.iii.1. + MOZ_ASSERT(unit == TemporalUnit::Week); + + // Step 6.b.iii.2. + int64_t weeks = dateDuration.weeks + sign; + + // Step 6.b.iii.3. + endDuration = {dateDuration.years, dateDuration.months, weeks}; + } + MOZ_ASSERT(IsValidDuration(endDuration)); + + // Steps 6.b.iv. + ISODate end; + if (!CalendarDateAdd(cx, calendar, isoDateTime.date, endDuration, + TemporalOverflow::Constrain, &end)) { + return false; + } + + // Steps 6.b.v. + auto endDateTime = ISODateTime{end, isoDateTime.time}; + MOZ_ASSERT(ISODateTimeWithinLimits(endDateTime)); + + // Steps 6.b.vi-vii. + EpochNanoseconds endEpochNs; + if (!timeZone) { + endEpochNs = GetUTCEpochNanoseconds(endDateTime); + } else { + if (!GetEpochNanosecondsFor(cx, timeZone, endDateTime, + TemporalDisambiguation::Compatible, + &endEpochNs)) { + return false; + } + } + + // Step 6.b.viii. + // + // NB: |nudge.epochNs| can be outside the valid epoch nanoseconds limits. + auto beyondEnd = nudge.epochNs - endEpochNs; + + // Step 6.b.ix. + int32_t beyondEndSign = beyondEnd < EpochDuration{} ? -1 + : beyondEnd > EpochDuration{} ? 1 + : 0; + + // Steps 6.b.x-xi. + if (beyondEndSign != -sign) { + dateDuration = endDuration; + timeDuration = {}; + } else { + break; + } + } + + // Step 6.c. (Moved above) + } + + // Step 7. + *result = {dateDuration, timeDuration}; + return true; +} + +/** + * RoundRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, + * calendar, largestUnit, increment, smallestUnit, roundingMode ) + */ +bool js::temporal::RoundRelativeDuration( + JSContext* cx, const InternalDuration& duration, + const EpochNanoseconds& destEpochNs, const ISODateTime& isoDateTime, + Handle timeZone, Handle calendar, + TemporalUnit largestUnit, Increment increment, TemporalUnit smallestUnit, + TemporalRoundingMode roundingMode, InternalDuration* result) { + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(destEpochNs)); + MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(destEpochNs)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); + MOZ_ASSERT(largestUnit <= smallestUnit); + + // Steps 1-3. + bool irregularLengthUnit = (smallestUnit < TemporalUnit::Day) || + (timeZone && smallestUnit == TemporalUnit::Day); + + // Step 4. (Not applicable in our implementation.) + + // Steps 5-7. + DurationNudge nudge; + if (irregularLengthUnit) { + // Step 5.a. + if (!NudgeToCalendarUnit(cx, duration, destEpochNs, isoDateTime, timeZone, + calendar, increment, smallestUnit, roundingMode, + &nudge)) { + return false; + } + } else if (timeZone) { + // Step 6.a. + if (!NudgeToZonedTime(cx, duration, isoDateTime, timeZone, calendar, + increment, smallestUnit, roundingMode, &nudge)) { + return false; + } + } else { + // Step 7.a. + nudge = NudgeToDayOrTime(duration, destEpochNs, largestUnit, increment, + smallestUnit, roundingMode); + } + + // Step 8. + auto nudgedDuration = nudge.duration; + + // Step 9. + if (nudge.didExpandCalendarUnit && smallestUnit != TemporalUnit::Week) { + // Step 9.a. (Inlined LargerOfTwoTemporalUnits) + auto startUnit = std::min(smallestUnit, TemporalUnit::Day); + + // Step 9.b. + if (!BubbleRelativeDuration(cx, duration, nudge, isoDateTime, timeZone, + calendar, largestUnit, startUnit, + &nudgedDuration)) { + return false; + } + } + + // Step 10. + *result = nudgedDuration; + return true; +} + +/** + * TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, + * calendar, unit ) + */ +bool js::temporal::TotalRelativeDuration(JSContext* cx, + const InternalDuration& duration, + const EpochNanoseconds& destEpochNs, + const ISODateTime& isoDateTime, + JS::Handle timeZone, + JS::Handle calendar, + TemporalUnit unit, double* result) { + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT_IF(timeZone, IsValidEpochNanoseconds(destEpochNs)); + MOZ_ASSERT_IF(!timeZone, IsValidLocalNanoseconds(destEpochNs)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); + MOZ_ASSERT(unit <= TemporalUnit::Day); + MOZ_ASSERT_IF(unit == TemporalUnit::Day, timeZone); + + // Steps 1.a-b. + DurationNudge nudge; + if (!NudgeToCalendarUnit(cx, duration, destEpochNs, isoDateTime, timeZone, + calendar, Increment{1}, unit, + TemporalRoundingMode::Trunc, &nudge)) { + return false; + } + + // Step 1.c. + *result = nudge.total; + return true; +} + +/** + * AddDurations ( operation, duration, other ) + */ +static bool AddDurations(JSContext* cx, TemporalAddDuration operation, + const CallArgs& args) { + auto* durationObj = &args.thisv().toObject().as(); + auto duration = ToDuration(durationObj); + + // Step 1. + Duration other; + if (!ToTemporalDuration(cx, args.get(0), &other)) { + return false; + } + + // Step 2. + if (operation == TemporalAddDuration::Subtract) { + other = other.negate(); + } + + // Step 3. + auto largestUnit1 = DefaultTemporalLargestUnit(duration); + + // Step 4. + auto largestUnit2 = DefaultTemporalLargestUnit(other); + + // Step 5. + auto largestUnit = std::min(largestUnit1, largestUnit2); + + // Step 6. + if (largestUnit <= TemporalUnit::Week) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, "relativeTo"); return false; } - // TODO: We could directly return here if unit=nanoseconds and increment=1, - // because in that case this operation is a no-op. This case happens for - // example when calling Temporal.PlainTime.prototype.{since,until} without an - // options object. - // - // But maybe this can be even more efficiently handled in the callers. For - // example when Temporal.PlainTime.prototype.{since,until} is called without - // an options object, we can not only skip the RoundDuration call, but also - // the following BalanceTimeDuration call. - - // Step 7. (Moved below.) - - // Step 8. (Not applicable.) - - // Steps 9-11. (Not applicable.) - - // Step 12. - if (unit == TemporalUnit::Day) { - // Step 7. - auto timeAndDays = NormalizedTimeDurationToDays(duration.time); - auto fractionalDays = FractionalDays{duration.date.days, timeAndDays}; - - return RoundDurationDay(cx, duration, fractionalDays, increment, - roundingMode, computeRemainder, result); - } - - MOZ_ASSERT(TemporalUnit::Hour <= unit && unit <= TemporalUnit::Nanosecond); - - // Step 13. - auto time = duration.time; - double total = 0; - if (computeRemainder == ComputeRemainder::No) { - if (!RoundNormalizedTimeDurationToIncrement(cx, time, unit, increment, - roundingMode, &time)) { - return false; - } - } else { - MOZ_ASSERT(increment == Increment{1}); - MOZ_ASSERT(roundingMode == TemporalRoundingMode::Trunc); - - total = TotalNormalizedTimeDuration(duration.time, unit); - } - MOZ_ASSERT(IsValidNormalizedTimeDuration(time)); - - // Step 14. - MOZ_ASSERT(IsValidDuration(duration.date)); - *result = {{duration.date, time}, total}; - return true; -} - -/** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) - */ -static bool RoundDuration( - JSContext* cx, const NormalizedDuration& duration, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode, - Handle> plainRelativeTo, - Handle calendar, Handle zonedRelativeTo, - Handle timeZone, - mozilla::Maybe precalculatedPlainDateTime, - ComputeRemainder computeRemainder, RoundedDuration* result) { - // Note: |duration.days| can have a different sign than the other date - // components. The date and time components can have different signs, too. - MOZ_ASSERT(IsValidDuration(Duration{double(duration.date.years), - double(duration.date.months), - double(duration.date.weeks)})); - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration.time)); - MOZ_ASSERT_IF(unit > TemporalUnit::Day, IsValidDuration(duration.date)); - - MOZ_ASSERT(plainRelativeTo || zonedRelativeTo, - "Use RoundDuration without relativeTo when plainRelativeTo and " - "zonedRelativeTo are both undefined"); - - // The remainder is only needed when called from |Duration_total|. And `total` - // always passes |increment=1| and |roundingMode=trunc|. - MOZ_ASSERT_IF(computeRemainder == ComputeRemainder::Yes, - increment == Increment{1}); - MOZ_ASSERT_IF(computeRemainder == ComputeRemainder::Yes, - roundingMode == TemporalRoundingMode::Trunc); - - // Steps 1-5. (Not applicable in our implementation.) - - // Step 6.a. (Not applicable in our implementation.) - MOZ_ASSERT_IF(unit <= TemporalUnit::Week, plainRelativeTo); - - // Step 6.b. - MOZ_ASSERT_IF( - unit <= TemporalUnit::Week, - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 6.c. - MOZ_ASSERT_IF( - unit <= TemporalUnit::Week, - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); - - switch (unit) { - case TemporalUnit::Year: - case TemporalUnit::Month: - case TemporalUnit::Week: - break; - case TemporalUnit::Day: - // We can't take the faster code path when |zonedRelativeTo| is present. - if (zonedRelativeTo) { - break; - } - [[fallthrough]]; - case TemporalUnit::Hour: - case TemporalUnit::Minute: - case TemporalUnit::Second: - case TemporalUnit::Millisecond: - case TemporalUnit::Microsecond: - case TemporalUnit::Nanosecond: - // Steps 7-9 and 13-14. - return ::RoundDuration(cx, duration, increment, unit, roundingMode, - computeRemainder, result); - case TemporalUnit::Auto: - MOZ_CRASH("Unexpected temporal unit"); - } - // Step 7. - MOZ_ASSERT(TemporalUnit::Year <= unit && unit <= TemporalUnit::Day); - - // Steps 7.a-c. - FractionalDays fractionalDays; - if (zonedRelativeTo) { - // Step 7.a.i. - Rooted intermediate(cx); - if (!MoveRelativeZonedDateTime(cx, zonedRelativeTo, calendar, timeZone, - duration.date, precalculatedPlainDateTime, - &intermediate)) { - return false; - } - - // Steps 7.a.ii. - NormalizedTimeAndDays timeAndDays; - if (!NormalizedTimeDurationToDays(cx, duration.time, intermediate, timeZone, - &timeAndDays)) { - return false; - } - - // Step 7.a.iii. - fractionalDays = FractionalDays{duration.date.days, timeAndDays}; - } else { - // Step 7.b. - auto timeAndDays = NormalizedTimeDurationToDays(duration.time); - fractionalDays = FractionalDays{duration.date.days, timeAndDays}; - } - - // Step 7.c. (Moved below) - - // Step 8. (Not applicable) - - // Steps 9-14. - switch (unit) { - // Steps 9 and 14. - case TemporalUnit::Year: - return RoundDurationYear(cx, duration, fractionalDays, increment, - roundingMode, plainRelativeTo, calendar, - computeRemainder, result); - - // Steps 10 and 14. - case TemporalUnit::Month: - return RoundDurationMonth(cx, duration, fractionalDays, increment, - roundingMode, plainRelativeTo, calendar, - computeRemainder, result); - - // Steps 11 and 14. - case TemporalUnit::Week: - return RoundDurationWeek(cx, duration, fractionalDays, increment, - roundingMode, plainRelativeTo, calendar, - computeRemainder, result); - - // Steps 12 and 14. - case TemporalUnit::Day: - return RoundDurationDay(cx, duration, fractionalDays, increment, - roundingMode, computeRemainder, result); - - // Steps 13-14. (Handled elsewhere) - case TemporalUnit::Auto: - case TemporalUnit::Hour: - case TemporalUnit::Minute: - case TemporalUnit::Second: - case TemporalUnit::Millisecond: - case TemporalUnit::Microsecond: - case TemporalUnit::Nanosecond: - break; - } - - MOZ_CRASH("Unexpected temporal unit"); -} - -/** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) - */ -bool js::temporal::RoundDuration( - JSContext* cx, const NormalizedDuration& duration, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode, - Handle> plainRelativeTo, - Handle calendar, NormalizedDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - - Rooted zonedRelativeTo(cx, ZonedDateTime{}); - Rooted timeZone(cx, TimeZoneRecord{}); - mozilla::Maybe precalculatedPlainDateTime{}; - RoundedDuration rounded; - if (!::RoundDuration(cx, duration, increment, unit, roundingMode, - plainRelativeTo, calendar, zonedRelativeTo, timeZone, - precalculatedPlainDateTime, ComputeRemainder::No, - &rounded)) { - return false; - } - - *result = rounded.duration; - return true; -} - -/** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) - */ -bool js::temporal::RoundDuration( - JSContext* cx, const NormalizedDuration& duration, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode, - Handle plainRelativeTo, Handle calendar, - Handle zonedRelativeTo, Handle timeZone, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result) { - MOZ_ASSERT(IsValidDuration(duration)); - - RoundedDuration rounded; - if (!::RoundDuration(cx, duration, increment, unit, roundingMode, - plainRelativeTo, calendar, zonedRelativeTo, timeZone, - mozilla::SomeRef(precalculatedPlainDateTime), - ComputeRemainder::No, &rounded)) { - return false; - } - - *result = rounded.duration; - return true; -} - -enum class DurationOperation { Add, Subtract }; - -/** - * AddDurationToOrSubtractDurationFromDuration ( operation, duration, other, - * options ) - */ -static bool AddDurationToOrSubtractDurationFromDuration( - JSContext* cx, DurationOperation operation, const CallArgs& args) { - auto* durationObj = &args.thisv().toObject().as(); - auto duration = ToDuration(durationObj); - - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Duration other; - if (!ToTemporalDurationRecord(cx, args.get(0), &other)) { - return false; - } - - Rooted> plainRelativeTo(cx); - Rooted zonedRelativeTo(cx); - Rooted timeZone(cx); - if (args.hasDefined(1)) { - const char* name = operation == DurationOperation::Add ? "add" : "subtract"; - - // Step 3. - Rooted options(cx, - RequireObjectArg(cx, "options", name, args[1])); - if (!options) { - return false; - } - - // Steps 4-7. - if (!GetTemporalRelativeToOption(cx, options, &plainRelativeTo, - &zonedRelativeTo, &timeZone)) { - return false; - } - MOZ_ASSERT(!plainRelativeTo || !zonedRelativeTo); - MOZ_ASSERT_IF(zonedRelativeTo, timeZone.receiver()); - } + auto d1 = ToInternalDurationRecordWith24HourDays(duration).time; // Step 8. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo, - zonedRelativeTo, - { - CalendarMethod::DateAdd, - CalendarMethod::DateUntil, - }, - &calendar)) { + auto d2 = ToInternalDurationRecordWith24HourDays(other).time; + + // Step 9. (Inline AddTimeDuration) + auto timeResult = d1 + d2; + if (!IsValidTimeDuration(timeResult)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); return false; } - // Step 9. - if (operation == DurationOperation::Subtract) { - other = other.negate(); + // Steps 10-11. + Duration resultDuration; + if (!TemporalDurationFromInternal(cx, timeResult, largestUnit, + &resultDuration)) { + return false; } + MOZ_ASSERT(IsValidDuration(resultDuration)); - Duration result; - if (plainRelativeTo) { - if (!AddDuration(cx, duration, other, plainRelativeTo, calendar, &result)) { - return false; - } - } else if (zonedRelativeTo) { - if (!AddDuration(cx, duration, other, zonedRelativeTo, calendar, timeZone, - &result)) { - return false; - } - } else { - if (!AddDuration(cx, duration, other, &result)) { - return false; - } - } - - // Step 10. - auto* obj = CreateTemporalDuration(cx, result); + auto* obj = CreateTemporalDuration(cx, resultDuration); if (!obj) { return false; } @@ -4372,28 +2921,18 @@ static bool DurationConstructor(JSContext* cx, unsigned argc, Value* vp) { static bool Duration_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - Handle item = args.get(0); - // Step 1. - if (item.isObject()) { - if (auto* duration = item.toObject().maybeUnwrapIf()) { - auto* result = CreateTemporalDuration(cx, ToDuration(duration)); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; - } - } - - // Step 2. - auto result = ToTemporalDuration(cx, item); - if (!result) { + Duration result; + if (!ToTemporalDuration(cx, args.get(0), &result)) { return false; } - args.rval().setObject(*result); + auto* obj = CreateTemporalDuration(cx, result); + if (!obj) { + return false; + } + + args.rval().setObject(*obj); return true; } @@ -4415,158 +2954,87 @@ static bool Duration_compare(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 3. - Rooted options(cx); + // Steps 3-4. + Rooted plainRelativeTo(cx); + Rooted zonedRelativeTo(cx); if (args.hasDefined(2)) { - options = RequireObjectArg(cx, "options", "compare", args[2]); + // Step 3. + Rooted options( + cx, RequireObjectArg(cx, "options", "compare", args[2])); if (!options) { return false; } + + // Step 4. + if (!GetTemporalRelativeToOption(cx, options, &plainRelativeTo, + &zonedRelativeTo)) { + return false; + } + MOZ_ASSERT(!plainRelativeTo || !zonedRelativeTo); } - // Step 4. + // Step 5. if (one == two) { args.rval().setInt32(0); return true; } - // Steps 5-8. - Rooted> plainRelativeTo(cx); - Rooted zonedRelativeTo(cx); - Rooted timeZone(cx); - if (options) { - if (!GetTemporalRelativeToOption(cx, options, &plainRelativeTo, - &zonedRelativeTo, &timeZone)) { - return false; - } - MOZ_ASSERT(!plainRelativeTo || !zonedRelativeTo); - MOZ_ASSERT_IF(zonedRelativeTo, timeZone.receiver()); - } + // Steps 6-9. (Not applicable in our implementation.) - // Steps 9-10. - auto hasCalendarUnit = [](const auto& d) { - return d.years != 0 || d.months != 0 || d.weeks != 0; - }; - bool calendarUnitsPresent = hasCalendarUnit(one) || hasCalendarUnit(two); + // Step 10. + auto duration1 = ToInternalDurationRecord(one); // Step 11. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo, - zonedRelativeTo, - { - CalendarMethod::DateAdd, - }, - &calendar)) { - return false; - } + auto duration2 = ToInternalDurationRecord(two); // Step 12. if (zonedRelativeTo && - (calendarUnitsPresent || one.days != 0 || two.days != 0)) { - // Step 12.a. - const auto& instant = zonedRelativeTo.instant(); - - // Step 12.b. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, timeZone, instant, &dateTime)) { - return false; - } + (duration1.date != DateDuration{} || duration2.date != DateDuration{})) { + // Steps 12.a-b. (Not applicable in our implementation.) // Step 12.c. - auto normalized1 = CreateNormalizedDurationRecord(one); + EpochNanoseconds after1; + if (!AddZonedDateTime(cx, zonedRelativeTo, duration1, &after1)) { + return false; + } // Step 12.d. - auto normalized2 = CreateNormalizedDurationRecord(two); - - // Step 12.e. - Instant after1; - if (!AddZonedDateTime(cx, instant, timeZone, calendar, normalized1, - dateTime, &after1)) { + EpochNanoseconds after2; + if (!AddZonedDateTime(cx, zonedRelativeTo, duration2, &after2)) { return false; } - // Step 12.f. - Instant after2; - if (!AddZonedDateTime(cx, instant, timeZone, calendar, normalized2, - dateTime, &after2)) { - return false; - } - - // Steps 12.g-i. + // Steps 12.e-g. args.rval().setInt32(after1 < after2 ? -1 : after1 > after2 ? 1 : 0); return true; } - // Steps 13-14. - int64_t days1, days2; - if (calendarUnitsPresent) { - // FIXME: spec issue - directly throw an error if plainRelativeTo is undef. + // Steps 13.a-b and 14.a. + int64_t days1; + if (!DateDurationDays(cx, duration1.date, plainRelativeTo, &days1)) { + return false; + } - // Step 13.a. - DateDuration unbalanceResult1; - if (plainRelativeTo) { - if (!UnbalanceDateDurationRelative(cx, one.toDateDuration(), - TemporalUnit::Day, plainRelativeTo, - calendar, &unbalanceResult1)) { - return false; - } - } else { - if (!UnbalanceDateDurationRelative( - cx, one.toDateDuration(), TemporalUnit::Day, &unbalanceResult1)) { - return false; - } - MOZ_ASSERT(one.toDateDuration() == unbalanceResult1); - } - - // Step 13.b. - DateDuration unbalanceResult2; - if (plainRelativeTo) { - if (!UnbalanceDateDurationRelative(cx, two.toDateDuration(), - TemporalUnit::Day, plainRelativeTo, - calendar, &unbalanceResult2)) { - return false; - } - } else { - if (!UnbalanceDateDurationRelative( - cx, two.toDateDuration(), TemporalUnit::Day, &unbalanceResult2)) { - return false; - } - MOZ_ASSERT(two.toDateDuration() == unbalanceResult2); - } - - // Step 13.c. - days1 = unbalanceResult1.days; - - // Step 13.d. - days2 = unbalanceResult2.days; - } else { - // Step 14.a. - days1 = mozilla::AssertedCast(one.days); - - // Step 14.b. - days2 = mozilla::AssertedCast(two.days); + // Steps 13.a, 13.c, and 14.b. + int64_t days2; + if (!DateDurationDays(cx, duration2.date, plainRelativeTo, &days2)) { + return false; } // Step 15. - auto normalized1 = NormalizeTimeDuration(one); + auto timeDuration1 = duration1.time; + if (!Add24HourDaysToTimeDuration(cx, duration1.time, days1, &timeDuration1)) { + return false; + } // Step 16. - if (!Add24HourDaysToNormalizedTimeDuration(cx, normalized1, days1, - &normalized1)) { + auto timeDuration2 = duration2.time; + if (!Add24HourDaysToTimeDuration(cx, duration2.time, days2, &timeDuration2)) { return false; } // Step 17. - auto normalized2 = NormalizeTimeDuration(two); - - // Step 18. - if (!Add24HourDaysToNormalizedTimeDuration(cx, normalized2, days2, - &normalized2)) { - return false; - } - - // Step 19. - args.rval().setInt32(CompareNormalizedTimeDuration(normalized1, normalized2)); + args.rval().setInt32(CompareTimeDuration(timeDuration1, timeDuration2)); return true; } @@ -4786,7 +3254,7 @@ static bool Duration_sign(JSContext* cx, unsigned argc, Value* vp) { static bool Duration_blank(JSContext* cx, const CallArgs& args) { auto duration = ToDuration(&args.thisv().toObject().as()); - // Steps 3-5. + // Steps 3-4. args.rval().setBoolean(duration == Duration{}); return true; } @@ -4802,8 +3270,6 @@ static bool Duration_blank(JSContext* cx, unsigned argc, Value* vp) { /** * Temporal.Duration.prototype.with ( temporalDurationLike ) - * - * ToPartialDuration ( temporalDurationLike ) */ static bool Duration_with(JSContext* cx, const CallArgs& args) { // Absent values default to the corresponding values of |this| object. @@ -4889,15 +3355,15 @@ static bool Duration_abs(JSContext* cx, unsigned argc, Value* vp) { } /** - * Temporal.Duration.prototype.add ( other [ , options ] ) + * Temporal.Duration.prototype.add ( other ) */ static bool Duration_add(JSContext* cx, const CallArgs& args) { - return AddDurationToOrSubtractDurationFromDuration(cx, DurationOperation::Add, - args); + // Step 3. + return AddDurations(cx, TemporalAddDuration::Add, args); } /** - * Temporal.Duration.prototype.add ( other [ , options ] ) + * Temporal.Duration.prototype.add ( other ) */ static bool Duration_add(JSContext* cx, unsigned argc, Value* vp) { // Steps 1-2. @@ -4906,15 +3372,15 @@ static bool Duration_add(JSContext* cx, unsigned argc, Value* vp) { } /** - * Temporal.Duration.prototype.subtract ( other [ , options ] ) + * Temporal.Duration.prototype.subtract ( other ) */ static bool Duration_subtract(JSContext* cx, const CallArgs& args) { - return AddDurationToOrSubtractDurationFromDuration( - cx, DurationOperation::Subtract, args); + // Step 3. + return AddDurations(cx, TemporalAddDuration::Subtract, args); } /** - * Temporal.Duration.prototype.subtract ( other [ , options ] ) + * Temporal.Duration.prototype.subtract ( other ) */ static bool Duration_subtract(JSContext* cx, unsigned argc, Value* vp) { // Steps 1-2. @@ -4928,7 +3394,7 @@ static bool Duration_subtract(JSContext* cx, unsigned argc, Value* vp) { static bool Duration_round(JSContext* cx, const CallArgs& args) { auto duration = ToDuration(&args.thisv().toObject().as()); - // Step 18. (Reordered) + // Step 17. (Reordered) auto existingLargestUnit = DefaultTemporalLargestUnit(duration); // Steps 3-25. @@ -4936,16 +3402,14 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) { TemporalUnit largestUnit; auto roundingMode = TemporalRoundingMode::HalfExpand; auto roundingIncrement = Increment{1}; - Rooted relativeTo(cx); - Rooted> plainRelativeTo(cx); + Rooted plainRelativeTo(cx); Rooted zonedRelativeTo(cx); - Rooted timeZone(cx); if (args.get(0).isString()) { // Step 4. (Not applicable in our implementation.) - // Steps 6-15. (Not applicable) + // Steps 6-14. (Not applicable) - // Step 16. + // Step 15. Rooted paramString(cx, args[0].toString()); if (!GetTemporalUnitValuedOption( cx, paramString, TemporalUnitKey::SmallestUnit, @@ -4953,21 +3417,21 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) { return false; } - // Step 17. (Not applicable) + // Step 16. (Not applicable) - // Step 18. (Moved above) + // Step 17. (Moved above) - // Step 19. + // Step 18. auto defaultLargestUnit = std::min(existingLargestUnit, smallestUnit); - // Step 20. (Not applicable) + // Step 19. (Not applicable) - // Step 20.a. (Not applicable) + // Step 19.a. (Not applicable) - // Step 20.b. + // Step 19.b. largestUnit = defaultLargestUnit; - // Steps 21-25. (Not applicable) + // Steps 20-25. (Not applicable) } else { // Steps 3 and 5. Rooted options( @@ -5006,114 +3470,133 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) { } } - // Steps 10-13. + // Steps 10-12. if (!GetTemporalRelativeToOption(cx, options, &plainRelativeTo, - &zonedRelativeTo, &timeZone)) { + &zonedRelativeTo)) { return false; } MOZ_ASSERT(!plainRelativeTo || !zonedRelativeTo); - MOZ_ASSERT_IF(zonedRelativeTo, timeZone.receiver()); - // Step 14. + // Step 13. if (!GetRoundingIncrementOption(cx, options, &roundingIncrement)) { return false; } - // Step 15. + // Step 14. if (!GetRoundingModeOption(cx, options, &roundingMode)) { return false; } - // Step 16. + // Step 15. if (!GetTemporalUnitValuedOption(cx, options, TemporalUnitKey::SmallestUnit, TemporalUnitGroup::DateTime, &smallestUnit)) { return false; } - // Step 17. + // Step 16. if (smallestUnit == TemporalUnit::Auto) { - // Step 17.a. + // Step 16.a. smallestUnitPresent = false; - // Step 17.b. + // Step 16.b. smallestUnit = TemporalUnit::Nanosecond; } - // Step 18. (Moved above) + // Step 17. (Moved above) - // Step 19. + // Step 18. auto defaultLargestUnit = std::min(existingLargestUnit, smallestUnit); - // Steps 20-21. + // Steps 19-20. if (largestUnitValue.isUndefined()) { - // Step 20.a. + // Step 19.a. largestUnitPresent = false; - // Step 20.b. + // Step 19.b. largestUnit = defaultLargestUnit; } else if (largestUnit == TemporalUnit::Auto) { - // Step 21.a + // Step 20.a largestUnit = defaultLargestUnit; } - // Step 22. + // Step 21. if (!smallestUnitPresent && !largestUnitPresent) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_DURATION_MISSING_UNIT_SPECIFIER); return false; } - // Step 23. + // Step 22. if (largestUnit > smallestUnit) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_INVALID_UNIT_RANGE); return false; } - // Steps 24-25. + // Steps 23-24. if (smallestUnit > TemporalUnit::Day) { - // Step 24. + // Step 23. auto maximum = MaximumTemporalDurationRoundingIncrement(smallestUnit); - // Step 25. + // Step 24. if (!ValidateTemporalRoundingIncrement(cx, roundingIncrement, maximum, false)) { return false; } } + + // Step 25. + if (roundingIncrement > Increment{1} && largestUnit != smallestUnit && + smallestUnit <= TemporalUnit::Day) { + Int32ToCStringBuf cbuf; + const char* numStr = + Int32ToCString(&cbuf, int32_t(roundingIncrement.value())); + + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_INVALID_OPTION_VALUE, "roundingIncrement", + numStr); + return false; + } } // Step 26. - bool hoursToDaysConversionMayOccur = false; + if (zonedRelativeTo) { + // Step 26.a. + auto internalDuration = ToInternalDurationRecord(duration); - // Step 27. - if (duration.days != 0 && zonedRelativeTo) { - hoursToDaysConversionMayOccur = true; - } + // Steps 26.b-d. (Not applicable in our implementation.) - // Step 28. - else if (std::abs(duration.hours) >= 24) { - hoursToDaysConversionMayOccur = true; - } + // Step 26.e. + EpochNanoseconds targetEpochNs; + if (!AddZonedDateTime(cx, zonedRelativeTo, internalDuration, + &targetEpochNs)) { + return false; + } - // Step 29. - bool roundingGranularityIsNoop = smallestUnit == TemporalUnit::Nanosecond && - roundingIncrement == Increment{1}; + // Step 26.f. + if (!DifferenceZonedDateTimeWithRounding(cx, zonedRelativeTo, targetEpochNs, + { + smallestUnit, + largestUnit, + roundingMode, + roundingIncrement, + }, + &internalDuration)) { + return false; + } - // Step 30. - bool calendarUnitsPresent = - duration.years != 0 || duration.months != 0 || duration.weeks != 0; + // Step 26.g. + largestUnit = std::max(largestUnit, TemporalUnit::Hour); - // Step 31. - if (roundingGranularityIsNoop && largestUnit == existingLargestUnit && - !calendarUnitsPresent && !hoursToDaysConversionMayOccur && - std::abs(duration.minutes) < 60 && std::abs(duration.seconds) < 60 && - std::abs(duration.milliseconds) < 1000 && - std::abs(duration.microseconds) < 1000 && - std::abs(duration.nanoseconds) < 1000) { - // Steps 31.a-b. - auto* obj = CreateTemporalDuration(cx, duration); + // Step 26.h + Duration result; + if (!TemporalDurationFromInternal(cx, internalDuration, largestUnit, + &result)) { + return false; + } + + auto* obj = CreateTemporalDuration(cx, result); if (!obj) { return false; } @@ -5122,143 +3605,133 @@ static bool Duration_round(JSContext* cx, const CallArgs& args) { return true; } - // Step 32. - mozilla::Maybe precalculatedPlainDateTime{}; - - // Step 33. - bool plainDateTimeOrRelativeToWillBeUsed = - !roundingGranularityIsNoop || largestUnit <= TemporalUnit::Day || - calendarUnitsPresent || duration.days != 0; - - // Step 34. - PlainDateTime relativeToDateTime; - if (zonedRelativeTo && plainDateTimeOrRelativeToWillBeUsed) { - // Steps 34.a-b. - const auto& instant = zonedRelativeTo.instant(); - - // Step 34.c. - if (!GetPlainDateTimeFor(cx, timeZone, instant, &relativeToDateTime)) { - return false; - } - precalculatedPlainDateTime = - mozilla::SomeRef(relativeToDateTime); - - // Step 34.d. - plainRelativeTo = CreateTemporalDate(cx, relativeToDateTime.date, - zonedRelativeTo.calendar()); - if (!plainRelativeTo) { - return false; - } - } - - // Step 35. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo, - zonedRelativeTo, - { - CalendarMethod::DateAdd, - CalendarMethod::DateUntil, - }, - &calendar)) { - return false; - } - - // Step 36. - DateDuration unbalanceResult; + // Step 27. if (plainRelativeTo) { - if (!UnbalanceDateDurationRelative(cx, duration.toDateDuration(), - largestUnit, plainRelativeTo, calendar, - &unbalanceResult)) { - return false; - } - } else { - if (!UnbalanceDateDurationRelative(cx, duration.toDateDuration(), - largestUnit, &unbalanceResult)) { - return false; - } - MOZ_ASSERT(duration.toDateDuration() == unbalanceResult); - } - MOZ_ASSERT(IsValidDuration(unbalanceResult)); + // Step 27.a. + auto internalDuration = ToInternalDurationRecordWith24HourDays(duration); - // Steps 37-38. - auto roundInput = - NormalizedDuration{unbalanceResult, NormalizeTimeDuration(duration)}; - RoundedDuration rounded; - if (plainRelativeTo || zonedRelativeTo) { - if (!::RoundDuration(cx, roundInput, roundingIncrement, smallestUnit, - roundingMode, plainRelativeTo, calendar, - zonedRelativeTo, timeZone, precalculatedPlainDateTime, - ComputeRemainder::No, &rounded)) { - return false; - } - } else { - MOZ_ASSERT(IsValidDuration(roundInput)); + // Step 27.b. + auto targetTime = AddTime(Time{}, internalDuration.time); - if (!::RoundDuration(cx, roundInput, roundingIncrement, smallestUnit, - roundingMode, ComputeRemainder::No, &rounded)) { + // Step 27.c. + auto calendar = plainRelativeTo.calendar(); + + // Step 27.d. + auto dateDuration = DateDuration{ + internalDuration.date.years, + internalDuration.date.months, + internalDuration.date.weeks, + targetTime.days, + }; + MOZ_ASSERT(IsValidDuration(dateDuration)); + + // 27.e. + ISODate targetDate; + if (!CalendarDateAdd(cx, calendar, plainRelativeTo, dateDuration, + TemporalOverflow::Constrain, &targetDate)) { return false; } + + // Step 27.f. + auto isoDateTime = ISODateTime{plainRelativeTo, {}}; + + // Step 27.g. + auto targetDateTime = ISODateTime{targetDate, targetTime.time}; + + // DifferencePlainDateTimeWithRounding, step 2. + if (!ISODateTimeWithinLimits(isoDateTime) || + !ISODateTimeWithinLimits(targetDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } + + // Step 27.h. + if (!DifferencePlainDateTimeWithRounding(cx, isoDateTime, targetDateTime, + calendar, + { + smallestUnit, + largestUnit, + roundingMode, + roundingIncrement, + }, + &internalDuration)) { + return false; + } + + // Step 27.i + Duration result; + if (!TemporalDurationFromInternal(cx, internalDuration, largestUnit, + &result)) { + return false; + } + + auto* obj = CreateTemporalDuration(cx, result); + if (!obj) { + return false; + } + + args.rval().setObject(*obj); + return true; } - // Step 39. - auto roundResult = rounded.duration; - - // Steps 40-41. - TimeDuration balanceResult; - if (zonedRelativeTo) { - // Step 40.a. - NormalizedDuration adjustResult; - if (!AdjustRoundedDurationDays(cx, roundResult, roundingIncrement, - smallestUnit, roundingMode, zonedRelativeTo, - calendar, timeZone, - precalculatedPlainDateTime, &adjustResult)) { - return false; - } - roundResult = adjustResult; - - // Step 40.b. - if (!BalanceTimeDurationRelative( - cx, roundResult, largestUnit, zonedRelativeTo, timeZone, - precalculatedPlainDateTime, &balanceResult)) { - return false; - } - } else { - // Step 41.a. - NormalizedTimeDuration withDays; - if (!Add24HourDaysToNormalizedTimeDuration( - cx, roundResult.time, roundResult.date.days, &withDays)) { - return false; - } - - // Step 41.b. - if (!temporal::BalanceTimeDuration(cx, withDays, largestUnit, - &balanceResult)) { - return false; - } - } - - // Step 42. - auto balanceInput = DateDuration{ - roundResult.date.years, - roundResult.date.months, - roundResult.date.weeks, - balanceResult.days, - }; - DateDuration dateResult; - if (!::BalanceDateDurationRelative(cx, balanceInput, largestUnit, - smallestUnit, plainRelativeTo, calendar, - &dateResult)) { + // Step 28. + if (existingLargestUnit < TemporalUnit::Day || + largestUnit < TemporalUnit::Day) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, + "relativeTo"); return false; } - // Step 43. - auto result = Duration{ - double(dateResult.years), double(dateResult.months), - double(dateResult.weeks), double(dateResult.days), - double(balanceResult.hours), double(balanceResult.minutes), - double(balanceResult.seconds), double(balanceResult.milliseconds), - balanceResult.microseconds, balanceResult.nanoseconds, - }; + // Step 29. + MOZ_ASSERT(smallestUnit >= TemporalUnit::Day); + + // Step 30. + auto internalDuration = ToInternalDurationRecordWith24HourDays(duration); + MOZ_ASSERT(internalDuration.date == DateDuration{}); + + // Steps 31-32. + if (smallestUnit == TemporalUnit::Day) { + // Steps 31.a-b. + constexpr auto nsPerDay = ToNanoseconds(TemporalUnit::Day); + auto rounded = + RoundNumberToIncrement(internalDuration.time.toNanoseconds(), nsPerDay, + roundingIncrement, roundingMode); + MOZ_ASSERT(Int128{INT64_MIN} <= rounded && rounded <= Int128{INT64_MAX}, + "rounded days fits in int64"); + auto days = static_cast(rounded); + + // Step 31.c. (Inlined CreateDateDurationRecord) + if (std::abs(days) > TimeDuration::max().toDays()) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + auto dateDuration = DateDuration{0, 0, 0, days}; + MOZ_ASSERT(IsValidDuration(dateDuration)); + + // Step 31.d. + internalDuration = {dateDuration, {}}; + } else { + // Step 32.a. + TimeDuration timeDuration; + if (!RoundTimeDuration(cx, internalDuration.time, roundingIncrement, + smallestUnit, roundingMode, &timeDuration)) { + return false; + } + + // Step 32.b. + internalDuration = {{}, timeDuration}; + } + + // Step 32. + Duration result; + if (!TemporalDurationFromInternal(cx, internalDuration, largestUnit, + &result)) { + return false; + } auto* obj = CreateTemporalDuration(cx, result); if (!obj) { @@ -5285,19 +3758,17 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) { auto* durationObj = &args.thisv().toObject().as(); auto duration = ToDuration(durationObj); - // Steps 3-11. - Rooted relativeTo(cx); - Rooted> plainRelativeTo(cx); + // Steps 3-10. + Rooted plainRelativeTo(cx); Rooted zonedRelativeTo(cx); - Rooted timeZone(cx); auto unit = TemporalUnit::Auto; if (args.get(0).isString()) { // Step 4. (Not applicable in our implementation.) - // Steps 6-10. (Implicit) + // Steps 6-9. (Implicit) MOZ_ASSERT(!plainRelativeTo && !zonedRelativeTo); - // Step 11. + // Step 10. Rooted paramString(cx, args[0].toString()); if (!GetTemporalUnitValuedOption(cx, paramString, TemporalUnitKey::Unit, TemporalUnitGroup::DateTime, &unit)) { @@ -5311,15 +3782,14 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) { return false; } - // Steps 6-10. + // Steps 6-9. if (!GetTemporalRelativeToOption(cx, totalOf, &plainRelativeTo, - &zonedRelativeTo, &timeZone)) { + &zonedRelativeTo)) { return false; } MOZ_ASSERT(!plainRelativeTo || !zonedRelativeTo); - MOZ_ASSERT_IF(zonedRelativeTo, timeZone.receiver()); - // Step 11. + // Step 10. if (!GetTemporalUnitValuedOption(cx, totalOf, TemporalUnitKey::Unit, TemporalUnitGroup::DateTime, &unit)) { return false; @@ -5332,204 +3802,90 @@ static bool Duration_total(JSContext* cx, const CallArgs& args) { } } - // Step 12. - mozilla::Maybe precalculatedPlainDateTime{}; + // Steps 11-13. + double total; + if (zonedRelativeTo) { + // Step 11.a. + auto internalDuration = ToInternalDurationRecord(duration); - // Step 13. - bool plainDateTimeOrRelativeToWillBeUsed = - unit <= TemporalUnit::Day || duration.toDateDuration() != DateDuration{}; + // Steps 11.b-d. (Not applicable in our implementation.) + + // Step 11.e. + EpochNanoseconds targetEpochNs; + if (!AddZonedDateTime(cx, zonedRelativeTo, internalDuration, + &targetEpochNs)) { + return false; + } + + // Step 11.f. + if (!DifferenceZonedDateTimeWithTotal(cx, zonedRelativeTo, targetEpochNs, + unit, &total)) { + return false; + } + } else if (plainRelativeTo) { + // Step 12.a. + auto internalDuration = ToInternalDurationRecordWith24HourDays(duration); + + // Step 12.b. + auto targetTime = AddTime(Time{}, internalDuration.time); + + // Step 12.c. + auto calendar = plainRelativeTo.calendar(); + + // Step 12.d. + auto dateDuration = DateDuration{ + internalDuration.date.years, + internalDuration.date.months, + internalDuration.date.weeks, + targetTime.days, + }; + MOZ_ASSERT(IsValidDuration(dateDuration)); + + // Step 12.e. + ISODate targetDate; + if (!CalendarDateAdd(cx, calendar, plainRelativeTo, dateDuration, + TemporalOverflow::Constrain, &targetDate)) { + return false; + } + + // Step 12.f. + auto isoDateTime = ISODateTime{plainRelativeTo, {}}; + + // Step 12.g. + auto targetDateTime = ISODateTime{targetDate, targetTime.time}; + + // DifferencePlainDateTimeWithTotal, step 2. + if (!ISODateTimeWithinLimits(isoDateTime) || + !ISODateTimeWithinLimits(targetDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } + + // Step 12.h. + if (!DifferencePlainDateTimeWithTotal(cx, isoDateTime, targetDateTime, + calendar, unit, &total)) { + return false; + } + } else { + // Steps 13.a-b. + if (duration.years != 0 || duration.months != 0 || duration.weeks != 0 || + unit < TemporalUnit::Day) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, + "relativeTo"); + return false; + } + + // Step 13.c. + auto internalDuration = ToInternalDurationRecordWith24HourDays(duration); + + // Step 13.d. + total = TotalTimeDuration(internalDuration.time, unit); + } // Step 14. - PlainDateTime relativeToDateTime; - if (zonedRelativeTo && plainDateTimeOrRelativeToWillBeUsed) { - // Steps 14.a-b. - const auto& instant = zonedRelativeTo.instant(); - - // Step 14.c. - if (!GetPlainDateTimeFor(cx, timeZone, instant, &relativeToDateTime)) { - return false; - } - precalculatedPlainDateTime = - mozilla::SomeRef(relativeToDateTime); - - // Step 14.d - plainRelativeTo = CreateTemporalDate(cx, relativeToDateTime.date, - zonedRelativeTo.calendar()); - if (!plainRelativeTo) { - return false; - } - } - - // Step 15. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecordFromRelativeTo(cx, plainRelativeTo, - zonedRelativeTo, - { - CalendarMethod::DateAdd, - CalendarMethod::DateUntil, - }, - &calendar)) { - return false; - } - - // Step 16. - DateDuration unbalanceResult; - if (plainRelativeTo) { - if (!UnbalanceDateDurationRelative(cx, duration.toDateDuration(), unit, - plainRelativeTo, calendar, - &unbalanceResult)) { - return false; - } - } else { - if (!UnbalanceDateDurationRelative(cx, duration.toDateDuration(), unit, - &unbalanceResult)) { - return false; - } - MOZ_ASSERT(duration.toDateDuration() == unbalanceResult); - } - - // Step 17. - int64_t unbalancedDays = unbalanceResult.days; - - // Steps 18-19. - int64_t days; - NormalizedTimeDuration normTime; - if (zonedRelativeTo) { - // Step 18.a - Rooted intermediate(cx); - if (!MoveRelativeZonedDateTime( - cx, zonedRelativeTo, calendar, timeZone, - {unbalanceResult.years, unbalanceResult.months, - unbalanceResult.weeks, 0}, - precalculatedPlainDateTime, &intermediate)) { - return false; - } - - // Step 18.b. - auto timeDuration = NormalizeTimeDuration(duration); - - // Step 18.c - const auto& startNs = intermediate.instant(); - - // Step 18.d. - const auto& startInstant = startNs; - - // Step 18.e. - mozilla::Maybe startDateTime{}; - - // Steps 18.f-g. - Instant intermediateNs; - if (unbalancedDays != 0) { - // Step 18.f.i. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, timeZone, startInstant, &dateTime)) { - return false; - } - startDateTime = mozilla::Some(dateTime); - - // Step 18.f.ii. - Rooted isoCalendar(cx, CalendarValue(CalendarId::ISO8601)); - Instant addResult; - if (!AddDaysToZonedDateTime(cx, startInstant, dateTime, timeZone, - isoCalendar, unbalancedDays, &addResult)) { - return false; - } - - // Step 18.f.iii. - intermediateNs = addResult; - } else { - // Step 18.g. - intermediateNs = startNs; - } - - // Step 18.h. - Instant endNs; - if (!AddInstant(cx, intermediateNs, timeDuration, &endNs)) { - return false; - } - - // Step 18.i. - auto difference = - NormalizedTimeDurationFromEpochNanosecondsDifference(endNs, startNs); - - // Steps 18.j-k. - // - // Avoid calling NormalizedTimeDurationToDays for a zero time difference. - if (TemporalUnit::Year <= unit && unit <= TemporalUnit::Day && - difference != NormalizedTimeDuration{}) { - // Step 18.j.i. - if (!startDateTime) { - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, timeZone, startInstant, &dateTime)) { - return false; - } - startDateTime = mozilla::Some(dateTime); - } - - // Step 18.j.ii. - NormalizedTimeAndDays timeAndDays; - if (!NormalizedTimeDurationToDays(cx, difference, intermediate, timeZone, - *startDateTime, &timeAndDays)) { - return false; - } - - // Step 18.j.iii. - normTime = NormalizedTimeDuration::fromNanoseconds(timeAndDays.time); - - // Step 18.j.iv. - days = timeAndDays.days; - } else { - // Step 18.k.i. - normTime = difference; - days = 0; - } - } else { - // Step 19.a. - auto timeDuration = NormalizeTimeDuration(duration); - - // Step 19.b. - if (!Add24HourDaysToNormalizedTimeDuration(cx, timeDuration, unbalancedDays, - &normTime)) { - return false; - } - - // Step 19.c. - days = 0; - } - MOZ_ASSERT(IsValidNormalizedTimeDuration(normTime)); - - // Step 20. - auto roundInput = NormalizedDuration{ - { - unbalanceResult.years, - unbalanceResult.months, - unbalanceResult.weeks, - days, - }, - normTime, - }; - MOZ_ASSERT_IF(unit > TemporalUnit::Day, IsValidDuration(roundInput.date)); - - RoundedDuration rounded; - if (plainRelativeTo || zonedRelativeTo) { - if (!::RoundDuration(cx, roundInput, Increment{1}, unit, - TemporalRoundingMode::Trunc, plainRelativeTo, calendar, - zonedRelativeTo, timeZone, precalculatedPlainDateTime, - ComputeRemainder::Yes, &rounded)) { - return false; - } - } else { - MOZ_ASSERT(IsValidDuration(roundInput)); - - if (!::RoundDuration(cx, roundInput, Increment{1}, unit, - TemporalRoundingMode::Trunc, ComputeRemainder::Yes, - &rounded)) { - return false; - } - } - - // Step 21. - args.rval().setNumber(rounded.total); + args.rval().setNumber(total); return true; } @@ -5592,44 +3948,42 @@ static bool Duration_toString(JSContext* cx, const CallArgs& args) { // Step 9. precision = ToSecondsStringPrecision(smallestUnit, digits); } + MOZ_ASSERT(precision.unit >= TemporalUnit::Minute); - // Steps 10-11. - Duration result; + // Steps 10-16. + auto roundedDuration = duration; if (precision.unit != TemporalUnit::Nanosecond || precision.increment != Increment{1}) { - // Step 10.a. - auto timeDuration = NormalizeTimeDuration(duration); - - // Step 10.b. + // Step 11. auto largestUnit = DefaultTemporalLargestUnit(duration); - // Steps 10.c-d. - NormalizedTimeDuration rounded; - if (!RoundDuration(cx, timeDuration, precision.increment, precision.unit, - roundingMode, &rounded)) { + // Step 12. + auto internalDuration = ToInternalDurationRecord(duration); + + // Step 13. + TimeDuration timeDuration; + if (!RoundTimeDuration(cx, internalDuration.time, precision.increment, + precision.unit, roundingMode, &timeDuration)) { return false; } - // Step 10.e. - auto balanced = BalanceTimeDuration( - rounded, std::min(largestUnit, TemporalUnit::Second)); + // Step 14. + internalDuration = {internalDuration.date, timeDuration}; - // Step 10.f. - result = { - duration.years, duration.months, - duration.weeks, duration.days + double(balanced.days), - double(balanced.hours), double(balanced.minutes), - double(balanced.seconds), double(balanced.milliseconds), - balanced.microseconds, balanced.nanoseconds, - }; - MOZ_ASSERT(IsValidDuration(duration)); - } else { - // Step 11. - result = duration; + // Step 15. + auto roundedLargestUnit = std::min(largestUnit, TemporalUnit::Second); + + // Step 16. + if (!TemporalDurationFromInternal(cx, internalDuration, roundedLargestUnit, + &roundedDuration)) { + return false; + } + MOZ_ASSERT(IsValidDuration(roundedDuration)); } - // Steps 12-13. - JSString* str = TemporalDurationToString(cx, result, precision.precision); + // Steps 10.a. and 17. + JSString* str = + TemporalDurationToString(cx, roundedDuration, precision.precision); if (!str) { return false; } @@ -5653,7 +4007,7 @@ static bool Duration_toString(JSContext* cx, unsigned argc, Value* vp) { static bool Duration_toJSON(JSContext* cx, const CallArgs& args) { auto duration = ToDuration(&args.thisv().toObject().as()); - // Steps 3-4. + // Step 3. JSString* str = TemporalDurationToString(cx, duration, Precision::Auto()); if (!str) { return false; @@ -5676,16 +4030,8 @@ static bool Duration_toJSON(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Duration.prototype.toLocaleString ( [ locales [ , options ] ] ) */ static bool Duration_toLocaleString(JSContext* cx, const CallArgs& args) { - auto duration = ToDuration(&args.thisv().toObject().as()); - - // Steps 3-4. - JSString* str = TemporalDurationToString(cx, duration, Precision::Auto()); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-7. + return TemporalDurationToLocaleString(cx, args); } /** diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.h index e1aea4d1d42..c1fde1ea3cf 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Duration.h @@ -7,10 +7,11 @@ #ifndef builtin_temporal_Duration_h #define builtin_temporal_Duration_h +#include "mozilla/Assertions.h" + #include #include "builtin/temporal/TemporalTypes.h" -#include "builtin/temporal/Wrapped.h" #include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" @@ -74,33 +75,28 @@ inline Duration ToDuration(const DurationObject* duration) { } class Increment; -class CalendarRecord; -class PlainDateObject; -class TimeZoneRecord; -class ZonedDateTime; -class ZonedDateTimeObject; +class CalendarValue; +class TimeZoneValue; enum class TemporalRoundingMode; enum class TemporalUnit; /** - * DurationSign ( years, months, weeks, days, hours, minutes, seconds, - * milliseconds, microseconds, nanoseconds ) + * DurationSign ( duration ) */ int32_t DurationSign(const Duration& duration); /** - * DurationSign ( years, months, weeks, days, hours, minutes, seconds, - * milliseconds, microseconds, nanoseconds ) + * DateDurationSign ( dateDuration ) */ -int32_t DurationSign(const DateDuration& duration); +int32_t DateDurationSign(const DateDuration& duration); +#ifdef DEBUG /** * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) */ bool IsValidDuration(const Duration& duration); -#ifdef DEBUG /** * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) @@ -111,7 +107,7 @@ bool IsValidDuration(const DateDuration& duration); * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) */ -bool IsValidDuration(const NormalizedDuration& duration); +bool IsValidDuration(const InternalDuration& duration); #endif /** @@ -124,48 +120,39 @@ bool ThrowIfInvalidDuration(JSContext* cx, const Duration& duration); * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, * milliseconds, microseconds, nanoseconds ) */ -bool ThrowIfInvalidDuration(JSContext* cx, const DateDuration& duration); - -/** - * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, - * milliseconds, microseconds, nanoseconds ) - */ -inline bool IsValidNormalizedTimeDuration( - const NormalizedTimeDuration& duration) { +inline bool IsValidTimeDuration(const TimeDuration& duration) { MOZ_ASSERT(0 <= duration.nanoseconds && duration.nanoseconds <= 999'999'999); - // Step 4. - // - // The absolute value of the seconds part of normalized time duration must be + // The absolute value of the seconds part of a time duration must be // less-or-equal to `2**53 - 1` and the nanoseconds part must be less or equal // to `999'999'999`. - return NormalizedTimeDuration::min() <= duration && - duration <= NormalizedTimeDuration::max(); + // + // Add ±1 nanosecond to make the nanoseconds part zero, which enables faster + // codegen. + + constexpr auto max = TimeDuration::max() + TimeDuration::fromNanoseconds(1); + static_assert(max.nanoseconds == 0); + + constexpr auto min = TimeDuration::min() - TimeDuration::fromNanoseconds(1); + static_assert(min.nanoseconds == 0); + + // Step 4. + return min < duration && duration < max; } /** - * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds, - * nanoseconds ) + * TimeDurationFromComponents ( hours, minutes, seconds, milliseconds, + * microseconds, nanoseconds ) */ -NormalizedTimeDuration NormalizeTimeDuration(int32_t hours, int32_t minutes, - int32_t seconds, - int32_t milliseconds, - int32_t microseconds, - int32_t nanoseconds); +TimeDuration TimeDurationFromComponents(const Duration& duration); /** - * NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds, - * nanoseconds ) + * CompareTimeDuration ( one, two ) */ -NormalizedTimeDuration NormalizeTimeDuration(const Duration& duration); - -/** - * CompareNormalizedTimeDuration ( one, two ) - */ -inline int32_t CompareNormalizedTimeDuration( - const NormalizedTimeDuration& one, const NormalizedTimeDuration& two) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(one)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(two)); +inline int32_t CompareTimeDuration(const TimeDuration& one, + const TimeDuration& two) { + MOZ_ASSERT(IsValidTimeDuration(one)); + MOZ_ASSERT(IsValidTimeDuration(two)); // Step 1. if (one > two) { @@ -182,72 +169,55 @@ inline int32_t CompareNormalizedTimeDuration( } /** - * NormalizedTimeDurationSign ( d ) + * TimeDurationSign ( d ) */ -inline int32_t NormalizedTimeDurationSign(const NormalizedTimeDuration& d) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(d)); +inline int32_t TimeDurationSign(const TimeDuration& d) { + MOZ_ASSERT(IsValidTimeDuration(d)); // Steps 1-3. - return CompareNormalizedTimeDuration(d, NormalizedTimeDuration{}); + return CompareTimeDuration(d, TimeDuration{}); } /** - * Add24HourDaysToNormalizedTimeDuration ( d, days ) + * ToInternalDurationRecord ( duration ) */ -bool Add24HourDaysToNormalizedTimeDuration(JSContext* cx, - const NormalizedTimeDuration& d, - int64_t days, - NormalizedTimeDuration* result); +inline InternalDuration ToInternalDurationRecord(const Duration& duration) { + MOZ_ASSERT(IsValidDuration(duration)); -/** - * CreateNormalizedDurationRecord ( years, months, weeks, days, norm ) - */ -inline NormalizedDuration CreateNormalizedDurationRecord( - const DateDuration& date, const NormalizedTimeDuration& time) { - MOZ_ASSERT(IsValidDuration(date)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(time)); -#ifdef DEBUG - int64_t dateValues = date.years | date.months | date.weeks | date.days; - int32_t dateSign = dateValues ? dateValues < 0 ? -1 : 1 : 0; - int32_t timeSign = NormalizedTimeDurationSign(time); - MOZ_ASSERT((dateSign * timeSign) >= 0); -#endif - - return {date, time}; + // Steps 1-3. + return {duration.toDateDuration(), TimeDurationFromComponents(duration)}; } /** - * CreateNormalizedDurationRecord ( years, months, weeks, days, norm ) + * ToInternalDurationRecordWith24HourDays ( duration ) */ -inline NormalizedDuration CreateNormalizedDurationRecord( - const Duration& duration) { - return CreateNormalizedDurationRecord(duration.toDateDuration(), - NormalizeTimeDuration(duration)); -} +InternalDuration ToInternalDurationRecordWith24HourDays( + const Duration& duration); /** - * CombineDateAndNormalizedTimeDuration ( dateDurationRecord, norm ) + * ToDateDurationRecordWithoutTime ( duration ) */ -bool CombineDateAndNormalizedTimeDuration(JSContext* cx, - const DateDuration& date, - const NormalizedTimeDuration& time, - NormalizedDuration* result); +DateDuration ToDateDurationRecordWithoutTime(const Duration& duration); /** - * CreateNormalizedDurationRecord ( years, months, weeks, days, norm ) + * TemporalDurationFromInternal ( internalDuration, largestUnit ) */ -inline bool CreateNormalizedDurationRecord(JSContext* cx, - const DateDuration& date, - const NormalizedTimeDuration& time, - NormalizedDuration* result) { - return CombineDateAndNormalizedTimeDuration(cx, date, time, result); -} +bool TemporalDurationFromInternal(JSContext* cx, + const TimeDuration& timeDuration, + TemporalUnit largestUnit, Duration* result); /** - * NormalizedTimeDurationFromEpochNanosecondsDifference ( one, two ) + * TemporalDurationFromInternal ( internalDuration, largestUnit ) */ -NormalizedTimeDuration NormalizedTimeDurationFromEpochNanosecondsDifference( - const Instant& one, const Instant& two); +bool TemporalDurationFromInternal(JSContext* cx, + const InternalDuration& internalDuration, + TemporalUnit largestUnit, Duration* result); + +/** + * TimeDurationFromEpochNanosecondsDifference ( one, two ) + */ +TimeDuration TimeDurationFromEpochNanosecondsDifference( + const EpochNanoseconds& one, const EpochNanoseconds& two); /** * CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds, @@ -255,12 +225,6 @@ NormalizedTimeDuration NormalizedTimeDurationFromEpochNanosecondsDifference( */ DurationObject* CreateTemporalDuration(JSContext* cx, const Duration& duration); -/** - * ToTemporalDuration ( item ) - */ -Wrapped ToTemporalDuration(JSContext* cx, - JS::Handle item); - /** * ToTemporalDuration ( item ) */ @@ -268,99 +232,38 @@ bool ToTemporalDuration(JSContext* cx, JS::Handle item, Duration* result); /** - * ToTemporalDurationRecord ( temporalDurationLike ) + * RoundTimeDuration ( duration, increment, unit, roundingMode ) */ -bool ToTemporalDurationRecord(JSContext* cx, - JS::Handle temporalDurationLike, - Duration* result); - -/** - * BalanceTimeDuration ( norm, largestUnit ) - */ -TimeDuration BalanceTimeDuration(const NormalizedTimeDuration& duration, - TemporalUnit largestUnit); - -/** - * BalanceTimeDuration ( norm, largestUnit ) - */ -bool BalanceTimeDuration(JSContext* cx, const NormalizedTimeDuration& duration, - TemporalUnit largestUnit, TimeDuration* result); - -/** - * BalanceDateDurationRelative ( years, months, weeks, days, largestUnit, - * smallestUnit, plainRelativeTo, calendarRec ) - */ -bool BalanceDateDurationRelative( - JSContext* cx, const DateDuration& duration, TemporalUnit largestUnit, - TemporalUnit smallestUnit, - JS::Handle> plainRelativeTo, - JS::Handle calendar, DateDuration* result); - -/** - * AdjustRoundedDurationDays ( years, months, weeks, days, norm, increment, - * unit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec, - * precalculatedPlainDateTime ) - */ -bool AdjustRoundedDurationDays(JSContext* cx, - const NormalizedDuration& duration, +TimeDuration RoundTimeDuration(const TimeDuration& duration, Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode, - JS::Handle relativeTo, - JS::Handle calendar, - JS::Handle timeZone, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result); + TemporalRoundingMode roundingMode); /** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) + * RoundRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, + * calendar, largestUnit, increment, smallestUnit, roundingMode ) */ -NormalizedTimeDuration RoundDuration(const NormalizedTimeDuration& duration, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode); +bool RoundRelativeDuration( + JSContext* cx, const InternalDuration& duration, + const EpochNanoseconds& destEpochNs, const ISODateTime& isoDateTime, + JS::Handle timeZone, JS::Handle calendar, + TemporalUnit largestUnit, Increment increment, TemporalUnit smallestUnit, + TemporalRoundingMode roundingMode, InternalDuration* result); /** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) + * TotalRelativeDuration ( duration, destEpochNs, isoDateTime, timeZone, + * calendar, unit ) */ -bool RoundDuration(JSContext* cx, const NormalizedTimeDuration& duration, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode, - NormalizedTimeDuration* result); +bool TotalRelativeDuration(JSContext* cx, const InternalDuration& duration, + const EpochNanoseconds& destEpochNs, + const ISODateTime& isoDateTime, + JS::Handle timeZone, + JS::Handle calendar, + TemporalUnit unit, double* result); /** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) + * TotalTimeDuration ( timeDuration, unit ) */ -bool RoundDuration(JSContext* cx, const NormalizedDuration& duration, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode, - JS::Handle> plainRelativeTo, - JS::Handle calendar, - NormalizedDuration* result); - -/** - * RoundDuration ( years, months, weeks, days, norm, increment, unit, - * roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , - * timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ) - */ -bool RoundDuration(JSContext* cx, const NormalizedDuration& duration, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode, - JS::Handle plainRelativeTo, - JS::Handle calendar, - JS::Handle zonedRelativeTo, - JS::Handle timeZone, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result); - -/** - * DaysUntil ( earlier, later ) - */ -int32_t DaysUntil(const PlainDate& earlier, const PlainDate& later); +double TotalTimeDuration(const TimeDuration& duration, TemporalUnit unit); } /* namespace js::temporal */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Era.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/Era.h new file mode 100644 index 00000000000..370054f0cf3 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Era.h @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_temporal_Era_h +#define builtin_temporal_Era_h + +#include "mozilla/Assertions.h" +#include "mozilla/MathAlgorithms.h" + +#include +#include +#include +#include + +#include "jstypes.h" + +#include "builtin/temporal/Calendar.h" +#include "builtin/temporal/Crash.h" + +namespace js::temporal { + +enum class EraCode { + // The standard era of a calendar. + Standard, + + // The era before the standard era of a calendar. + Inverse, + + // Named Japanese eras. + Meiji, + Taisho, + Showa, + Heisei, + Reiwa, +}; + +// static variables in constexpr functions requires C++23 support, so we can't +// declare the eras directly in CalendarEras. +namespace eras { +inline constexpr auto Standard = {EraCode::Standard}; + +inline constexpr auto StandardInverse = {EraCode::Standard, EraCode::Inverse}; + +inline constexpr auto Japanese = { + EraCode::Standard, EraCode::Inverse, + + EraCode::Meiji, EraCode::Taisho, EraCode::Showa, + EraCode::Heisei, EraCode::Reiwa, +}; + +// https://tc39.es/proposal-intl-era-monthcode/#table-eras +// +// Calendars which don't use eras were omitted. +namespace names { +using namespace std::literals; + +// Empty placeholder. +inline constexpr auto Empty = { + ""sv, +}; + +inline constexpr auto Coptic = { + "coptic"sv, +}; + +inline constexpr auto CopticInverse = { + "coptic-inverse"sv, +}; + +inline constexpr auto Ethiopian = { + "ethiopic"sv, + "incar"sv, +}; + +inline constexpr auto EthiopianInverse = { + "ethioaa"sv, + "ethiopic-amete-alem"sv, + "mundi"sv, +}; + +inline constexpr auto Gregorian = { + "gregory"sv, + "ce"sv, + "ad"sv, +}; + +inline constexpr auto GregorianInverse = { + "gregory-inverse"sv, + "bc"sv, + "bce"sv, +}; + +inline constexpr auto Japanese = { + "japanese"sv, + "gregory"sv, + "ad"sv, + "ce"sv, +}; + +inline constexpr auto JapaneseInverse = { + "japanese-inverse"sv, + "gregory-inverse"sv, + "bc"sv, + "bce"sv, +}; + +inline constexpr auto JapaneseMeiji = { + "meiji"sv, +}; + +inline constexpr auto JapaneseTaisho = { + "taisho"sv, +}; + +inline constexpr auto JapaneseShowa = { + "showa"sv, +}; + +inline constexpr auto JapaneseHeisei = { + "heisei"sv, +}; + +inline constexpr auto JapaneseReiwa = { + "reiwa"sv, +}; + +inline constexpr auto ROC = { + "roc"sv, + "minguo"sv, +}; + +inline constexpr auto ROCInverse = { + "roc-inverse"sv, + "before-roc"sv, +}; +} // namespace names +} // namespace eras + +constexpr auto& CalendarEras(CalendarId id) { + switch (id) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: + return eras::Standard; + + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::Gregorian: + case CalendarId::ROC: + return eras::StandardInverse; + + case CalendarId::Japanese: + return eras::Japanese; + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +constexpr bool CalendarEraRelevant(CalendarId calendar) { + return CalendarEras(calendar).size() > 1; +} + +constexpr auto& CalendarEraNames(CalendarId calendar, EraCode era) { + switch (calendar) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: + return eras::names::Empty; + + case CalendarId::Coptic: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? eras::names::Coptic + : eras::names::CopticInverse; + } + + case CalendarId::Ethiopian: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? eras::names::Ethiopian + : eras::names::EthiopianInverse; + } + + case CalendarId::Gregorian: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? eras::names::Gregorian + : eras::names::GregorianInverse; + } + + case CalendarId::Japanese: { + switch (era) { + case EraCode::Standard: + return eras::names::Japanese; + case EraCode::Inverse: + return eras::names::JapaneseInverse; + case EraCode::Meiji: + return eras::names::JapaneseMeiji; + case EraCode::Taisho: + return eras::names::JapaneseTaisho; + case EraCode::Showa: + return eras::names::JapaneseShowa; + case EraCode::Heisei: + return eras::names::JapaneseHeisei; + case EraCode::Reiwa: + return eras::names::JapaneseReiwa; + } + break; + } + + case CalendarId::ROC: { + MOZ_ASSERT(era == EraCode::Standard || era == EraCode::Inverse); + return era == EraCode::Standard ? eras::names::ROC + : eras::names::ROCInverse; + } + } + JS_CONSTEXPR_CRASH("invalid era"); +} + +constexpr auto CalendarEraName(CalendarId calendar, EraCode era) { + auto& names = CalendarEraNames(calendar, era); + MOZ_ASSERT(names.size() > 0); + return *names.begin(); +} + +constexpr bool CalendarEraStartsAtYearBoundary(CalendarId id) { + switch (id) { + // Calendar system which use a single era. + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: + return true; + + // Calendar system which use multiple eras, but each era starts at a year + // boundary. + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::Gregorian: + case CalendarId::ROC: + return true; + + // Calendar system which use multiple eras and eras can start within a year. + case CalendarId::Japanese: + return false; + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +constexpr bool CalendarEraStartsAtYearBoundary(CalendarId id, EraCode era) { + MOZ_ASSERT_IF(id != CalendarId::Japanese, + CalendarEraStartsAtYearBoundary(id)); + return era == EraCode::Standard || era == EraCode::Inverse; +} + +struct EraYear { + EraCode era = EraCode::Standard; + int32_t year = 0; +}; + +constexpr EraYear CalendarEraYear(CalendarId id, int32_t year) { + if (year > 0 || !CalendarEraRelevant(id)) { + return EraYear{EraCode::Standard, year}; + } + return EraYear{EraCode::Inverse, int32_t(mozilla::Abs(year) + 1)}; +} + +} // namespace js::temporal + +#endif /* builtin_temporal_Era_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.cpp index 6f6bad43c9a..ae4064d1bfb 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.cpp @@ -8,9 +8,6 @@ #include "mozilla/Assertions.h" #include "mozilla/Casting.h" -#include "mozilla/CheckedInt.h" -#include "mozilla/FloatingPoint.h" -#include "mozilla/Maybe.h" #include "mozilla/Span.h" #include @@ -25,8 +22,10 @@ #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Calendar.h" #include "builtin/temporal/Duration.h" +#include "builtin/temporal/Int128.h" #include "builtin/temporal/Int96.h" #include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/Temporal.h" @@ -36,7 +35,6 @@ #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ToString.h" -#include "builtin/temporal/Wrapped.h" #include "builtin/temporal/ZonedDateTime.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" @@ -58,7 +56,6 @@ #include "vm/JSContext.h" #include "vm/JSObject.h" #include "vm/PlainObject.h" -#include "vm/StringType.h" #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" @@ -129,54 +126,41 @@ static constexpr auto EpochLimitBigIntDigits = NanosecondsMaxInstant(); * IsValidEpochNanoseconds ( epochNanoseconds ) */ bool js::temporal::IsValidEpochNanoseconds(const BigInt* epochNanoseconds) { - // Steps 1-3. + // Steps 1-2. return AbsoluteValueIsLessOrEqual(epochNanoseconds); } -static bool IsValidEpochMicroseconds(const BigInt* epochMicroseconds) { - int64_t i; - if (!BigInt::isInt64(epochMicroseconds, &i)) { - return false; - } - - constexpr int64_t MicrosecondsMaxInstant = Instant::max().toMicroseconds(); - return -MicrosecondsMaxInstant <= i && i <= MicrosecondsMaxInstant; -} - static bool IsValidEpochMilliseconds(double epochMilliseconds) { MOZ_ASSERT(IsInteger(epochMilliseconds)); - constexpr int64_t MillisecondsMaxInstant = Instant::max().toMilliseconds(); + constexpr int64_t MillisecondsMaxInstant = + EpochNanoseconds::max().toMilliseconds(); return std::abs(epochMilliseconds) <= double(MillisecondsMaxInstant); } -static bool IsValidEpochSeconds(double epochSeconds) { - MOZ_ASSERT(IsInteger(epochSeconds)); - - constexpr int64_t SecondsMaxInstant = Instant::max().toSeconds(); - return std::abs(epochSeconds) <= double(SecondsMaxInstant); -} - /** * IsValidEpochNanoseconds ( epochNanoseconds ) */ -bool js::temporal::IsValidEpochInstant(const Instant& instant) { - MOZ_ASSERT(0 <= instant.nanoseconds && instant.nanoseconds <= 999'999'999); +bool js::temporal::IsValidEpochNanoseconds( + const EpochNanoseconds& epochNanoseconds) { + MOZ_ASSERT(0 <= epochNanoseconds.nanoseconds && + epochNanoseconds.nanoseconds <= 999'999'999); - // Steps 1-3. - return Instant::min() <= instant && instant <= Instant::max(); + // Steps 1-2. + return EpochNanoseconds::min() <= epochNanoseconds && + epochNanoseconds <= EpochNanoseconds::max(); } #ifdef DEBUG /** * Validates a nanoseconds amount is at most as large as the difference - * between two valid nanoseconds from the epoch instants. + * between two valid epoch nanoseconds. */ -bool js::temporal::IsValidInstantSpan(const InstantSpan& span) { - MOZ_ASSERT(0 <= span.nanoseconds && span.nanoseconds <= 999'999'999); +bool js::temporal::IsValidEpochDuration(const EpochDuration& duration) { + MOZ_ASSERT(0 <= duration.nanoseconds && duration.nanoseconds <= 999'999'999); - // Steps 1-3. - return InstantSpan::min() <= span && span <= InstantSpan::max(); + // Steps 1-2. + return EpochDuration::min() <= duration && duration <= EpochDuration::max(); } #endif @@ -228,12 +212,13 @@ static Int96 ToInt96(const BigInt* ns) { } } -Instant js::temporal::ToInstant(const BigInt* epochNanoseconds) { +EpochNanoseconds js::temporal::ToEpochNanoseconds( + const BigInt* epochNanoseconds) { MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); auto [seconds, nanos] = ToInt96(epochNanoseconds) / ToNanoseconds(TemporalUnit::Second); - return {seconds, nanos}; + return {{seconds, nanos}}; } static BigInt* CreateBigInt(JSContext* cx, @@ -319,78 +304,44 @@ static auto ToBigIntDigits(uint64_t seconds, uint32_t nanoseconds) { return accumulator; } -template -static BigInt* ToBigInt(JSContext* cx, - const SecondsAndNanoseconds& secondsAndNanoseconds) { - uint64_t seconds = std::abs(secondsAndNanoseconds.seconds); - uint32_t nanoseconds = secondsAndNanoseconds.nanoseconds; +BigInt* js::temporal::ToBigInt(JSContext* cx, + const EpochNanoseconds& epochNanoseconds) { + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); - // Negative nanoseconds are represented as the difference to 1'000'000'000. - // Convert these back to their absolute value and adjust the seconds part - // accordingly. - // - // For example the nanoseconds from the epoch value |-1n| is represented as - // the instant {seconds: -1, nanoseconds: 999'999'999}. - if (secondsAndNanoseconds.seconds < 0 && nanoseconds != 0) { - nanoseconds = ToNanoseconds(TemporalUnit::Second) - nanoseconds; - seconds -= 1; - } - - auto digits = ToBigIntDigits(seconds, nanoseconds); - return CreateBigInt(cx, digits, secondsAndNanoseconds.seconds < 0); -} - -BigInt* js::temporal::ToEpochNanoseconds(JSContext* cx, - const Instant& instant) { - MOZ_ASSERT(IsValidEpochInstant(instant)); - return ::ToBigInt(cx, instant); + auto [seconds, nanoseconds] = epochNanoseconds.abs(); + auto digits = ToBigIntDigits(uint64_t(seconds), uint32_t(nanoseconds)); + return CreateBigInt(cx, digits, epochNanoseconds.seconds < 0); } /** - * GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond [ , offsetNanoseconds ] ) + * GetUTCEpochNanoseconds ( isoDateTime ) */ -Instant js::temporal::GetUTCEpochNanoseconds(const PlainDateTime& dateTime) { - const auto& [date, time] = dateTime; +EpochNanoseconds js::temporal::GetUTCEpochNanoseconds( + const ISODateTime& isoDateTime) { + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); - // Step 1. - MOZ_ASSERT(IsValidISODateTime(dateTime)); + const auto& [date, time] = isoDateTime; - // Additionally ensure the date-time value can be represented as an Instant. - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); - - // Steps 2-5. - int64_t ms = MakeDate(dateTime); + // Steps 1-4. + int64_t ms = MakeDate(isoDateTime); // Propagate the input range to the compiler. int32_t nanos = std::clamp(time.microsecond * 1'000 + time.nanosecond, 0, 999'999); - // Steps 6-8. - return Instant::fromMilliseconds(ms) + InstantSpan{0, nanos}; -} - -/** - * GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond [ , offsetNanoseconds ] ) - */ -Instant js::temporal::GetUTCEpochNanoseconds( - const PlainDateTime& dateTime, const InstantSpan& offsetNanoseconds) { - MOZ_ASSERT(offsetNanoseconds.abs() < - InstantSpan::fromNanoseconds(ToNanoseconds(TemporalUnit::Day))); - - // Steps 1-6. - auto epochNanoseconds = GetUTCEpochNanoseconds(dateTime); - - // Steps 7-9. - return epochNanoseconds - offsetNanoseconds; + // Step 5. + // + // The returned epoch nanoseconds value can exceed ±8.64 × 10^21, because it + // includes the local time zone offset. + return EpochNanoseconds::fromMilliseconds(ms) + EpochDuration{{0, nanos}}; } /** * CompareEpochNanoseconds ( epochNanosecondsOne, epochNanosecondsTwo ) */ -static int32_t CompareEpochNanoseconds(const Instant& epochNanosecondsOne, - const Instant& epochNanosecondsTwo) { +static int32_t CompareEpochNanoseconds( + const EpochNanoseconds& epochNanosecondsOne, + const EpochNanoseconds& epochNanosecondsTwo) { // Step 1. if (epochNanosecondsOne > epochNanosecondsTwo) { return 1; @@ -408,10 +359,10 @@ static int32_t CompareEpochNanoseconds(const Instant& epochNanosecondsOne, /** * CreateTemporalInstant ( epochNanoseconds [ , newTarget ] ) */ -InstantObject* js::temporal::CreateTemporalInstant(JSContext* cx, - const Instant& instant) { +InstantObject* js::temporal::CreateTemporalInstant( + JSContext* cx, const EpochNanoseconds& epochNanoseconds) { // Step 1. - MOZ_ASSERT(IsValidEpochInstant(instant)); + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); // Steps 2-3. auto* object = NewBuiltinClassInstance(cx); @@ -421,9 +372,9 @@ InstantObject* js::temporal::CreateTemporalInstant(JSContext* cx, // Step 4. object->setFixedSlot(InstantObject::SECONDS_SLOT, - NumberValue(instant.seconds)); + NumberValue(epochNanoseconds.seconds)); object->setFixedSlot(InstantObject::NANOSECONDS_SLOT, - Int32Value(instant.nanoseconds)); + Int32Value(epochNanoseconds.nanoseconds)); // Step 5. return object; @@ -449,11 +400,11 @@ static InstantObject* CreateTemporalInstant(JSContext* cx, const CallArgs& args, } // Step 4. - auto instant = ToInstant(epochNanoseconds); + auto epochNs = ToEpochNanoseconds(epochNanoseconds); object->setFixedSlot(InstantObject::SECONDS_SLOT, - NumberValue(instant.seconds)); + NumberValue(epochNs.seconds)); object->setFixedSlot(InstantObject::NANOSECONDS_SLOT, - Int32Value(instant.nanoseconds)); + Int32Value(epochNs.nanoseconds)); // Step 5. return object; @@ -462,33 +413,8 @@ static InstantObject* CreateTemporalInstant(JSContext* cx, const CallArgs& args, /** * ToTemporalInstant ( item ) */ -Wrapped js::temporal::ToTemporalInstant(JSContext* cx, - Handle item) { - // Step 1. - if (item.isObject()) { - JSObject* itemObj = &item.toObject(); - - // Step 1.a. - if (itemObj->canUnwrapAs()) { - return itemObj; - } - } - - // Steps 1.b-d and 3-7 - Instant epochNanoseconds; - if (!ToTemporalInstant(cx, item, &epochNanoseconds)) { - return nullptr; - } - - // Step 8. - return CreateTemporalInstant(cx, epochNanoseconds); -} - -/** - * ToTemporalInstant ( item ) - */ -bool js::temporal::ToTemporalInstant(JSContext* cx, Handle item, - Instant* result) { +static bool ToTemporalInstant(JSContext* cx, Handle item, + EpochNanoseconds* result) { // Step 1. Rooted primitiveValue(cx, item); if (item.isObject()) { @@ -496,17 +422,15 @@ bool js::temporal::ToTemporalInstant(JSContext* cx, Handle item, // Step 1.a. if (auto* instant = itemObj->maybeUnwrapIf()) { - *result = ToInstant(instant); + *result = instant->epochNanoseconds(); return true; } - - // Step 1.b. if (auto* zonedDateTime = itemObj->maybeUnwrapIf()) { - *result = ToInstant(zonedDateTime); + *result = zonedDateTime->epochNanoseconds(); return true; } - // Steps 1.c-d. + // Steps 1.b-c. if (!ToPrimitive(cx, JSTYPE_STRING, &primitiveValue)) { return false; } @@ -522,33 +446,35 @@ bool js::temporal::ToTemporalInstant(JSContext* cx, Handle item, } Rooted string(cx, primitiveValue.toString()); - // Steps 3-4. - PlainDateTime dateTime; + // Steps 3-7. + ISODateTime dateTime; int64_t offset; if (!ParseTemporalInstantString(cx, string, &dateTime, &offset)) { return false; } MOZ_ASSERT(std::abs(offset) < ToNanoseconds(TemporalUnit::Day)); - // Steps 5-6. (Reordered) + // Steps 8-9. + // + // Modified to call ISODateTimeWithinLimits instead of BalanceISODateTime. if (!ISODateTimeWithinLimits(dateTime)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_INSTANT_INVALID); return false; } - // Step 4. + // Step 10. auto epochNanoseconds = - GetUTCEpochNanoseconds(dateTime, InstantSpan::fromNanoseconds(offset)); + GetUTCEpochNanoseconds(dateTime) - EpochDuration::fromNanoseconds(offset); - // Step 7. - if (!IsValidEpochInstant(epochNanoseconds)) { + // Step 11. + if (!IsValidEpochNanoseconds(epochNanoseconds)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_INSTANT_INVALID); return false; } - // Step 8. + // Step 12. *result = epochNanoseconds; return true; } @@ -557,17 +483,18 @@ bool js::temporal::ToTemporalInstant(JSContext* cx, Handle item, * AddInstant ( epochNanoseconds, hours, minutes, seconds, milliseconds, * microseconds, nanoseconds ) */ -bool js::temporal::AddInstant(JSContext* cx, const Instant& instant, - const NormalizedTimeDuration& duration, - Instant* result) { - MOZ_ASSERT(IsValidEpochInstant(instant)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); +bool js::temporal::AddInstant(JSContext* cx, + const EpochNanoseconds& epochNanoseconds, + const TimeDuration& duration, + EpochNanoseconds* result) { + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); + MOZ_ASSERT(IsValidTimeDuration(duration)); - // Step 1. (Inlined AddNormalizedTimeDurationToEpochNanoseconds) - auto r = instant + duration.to(); + // Step 1. (Inlined AddTimeDurationToEpochNanoseconds) + auto r = epochNanoseconds + duration.to(); // Step 2. - if (!IsValidEpochInstant(r)) { + if (!IsValidEpochNanoseconds(r)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_INSTANT_INVALID); return false; @@ -581,35 +508,31 @@ bool js::temporal::AddInstant(JSContext* cx, const Instant& instant, /** * DifferenceInstant ( ns1, ns2, roundingIncrement, smallestUnit, roundingMode ) */ -NormalizedTimeDuration js::temporal::DifferenceInstant( - const Instant& ns1, const Instant& ns2, Increment roundingIncrement, - TemporalUnit smallestUnit, TemporalRoundingMode roundingMode) { - MOZ_ASSERT(IsValidEpochInstant(ns1)); - MOZ_ASSERT(IsValidEpochInstant(ns2)); +TimeDuration js::temporal::DifferenceInstant( + const EpochNanoseconds& ns1, const EpochNanoseconds& ns2, + Increment roundingIncrement, TemporalUnit smallestUnit, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidEpochNanoseconds(ns1)); + MOZ_ASSERT(IsValidEpochNanoseconds(ns2)); MOZ_ASSERT(smallestUnit > TemporalUnit::Day); MOZ_ASSERT(roundingIncrement <= MaximumTemporalDurationRoundingIncrement(smallestUnit)); // Step 1. - auto diff = NormalizedTimeDurationFromEpochNanosecondsDifference(ns2, ns1); - MOZ_ASSERT(IsValidInstantSpan(diff.to())); + auto diff = TimeDurationFromEpochNanosecondsDifference(ns2, ns1); + MOZ_ASSERT(IsValidEpochDuration(diff.to())); - // Step 2. - if (smallestUnit == TemporalUnit::Nanosecond && - roundingIncrement == Increment{1}) { - return diff; - } - - // Steps 3-4. - return RoundDuration(diff, roundingIncrement, smallestUnit, roundingMode); + // Steps 2-3. + return RoundTimeDuration(diff, roundingIncrement, smallestUnit, roundingMode); } /** * RoundNumberToIncrementAsIfPositive ( x, increment, roundingMode ) */ -static Instant RoundNumberToIncrementAsIfPositive( - const Instant& x, int64_t increment, TemporalRoundingMode roundingMode) { - MOZ_ASSERT(IsValidEpochInstant(x)); +static EpochNanoseconds RoundNumberToIncrementAsIfPositive( + const EpochNanoseconds& x, int64_t increment, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidEpochNanoseconds(x)); MOZ_ASSERT(increment > 0); MOZ_ASSERT(increment <= ToNanoseconds(TemporalUnit::Day)); @@ -617,32 +540,29 @@ static Instant RoundNumberToIncrementAsIfPositive( // |ToPositiveRoundingMode| and then calling |RoundNumberToIncrement|. auto rounded = RoundNumberToIncrement(x.toNanoseconds(), Int128{increment}, ToPositiveRoundingMode(roundingMode)); - return Instant::fromNanoseconds(rounded); + return EpochNanoseconds::fromNanoseconds(rounded); } /** * RoundTemporalInstant ( ns, increment, unit, roundingMode ) */ -Instant js::temporal::RoundTemporalInstant(const Instant& ns, - Increment increment, - TemporalUnit unit, - TemporalRoundingMode roundingMode) { - MOZ_ASSERT(IsValidEpochInstant(ns)); +EpochNanoseconds js::temporal::RoundTemporalInstant( + const EpochNanoseconds& ns, Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidEpochNanoseconds(ns)); MOZ_ASSERT(increment >= Increment::min()); MOZ_ASSERT(uint64_t(increment.value()) <= ToNanoseconds(TemporalUnit::Day)); - - // Step 1. MOZ_ASSERT(unit > TemporalUnit::Day); - // Step 2. + // Step 1. int64_t unitLength = ToNanoseconds(unit); - // Step 3. + // Step 2. int64_t incrementNs = increment.value() * unitLength; MOZ_ASSERT(incrementNs <= ToNanoseconds(TemporalUnit::Day), - "incrementNs doesn't overflow instant resolution"); + "incrementNs doesn't overflow epoch nanoseconds resolution"); - // Step 4. + // Step 3. return RoundNumberToIncrementAsIfPositive(ns, incrementNs, roundingMode); } @@ -652,19 +572,18 @@ Instant js::temporal::RoundTemporalInstant(const Instant& ns, static bool DifferenceTemporalInstant(JSContext* cx, TemporalDifference operation, const CallArgs& args) { - auto instant = ToInstant(&args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Instant other; + // Step 1. + EpochNanoseconds other; if (!ToTemporalInstant(cx, args.get(0), &other)) { return false; } - // Steps 3-4. + // Steps 2-3. DifferenceSettings settings; if (args.hasDefined(1)) { + // Step 2. Rooted options( cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); if (!options) { @@ -672,20 +591,13 @@ static bool DifferenceTemporalInstant(JSContext* cx, } // Step 3. - Rooted resolvedOptions(cx, - SnapshotOwnProperties(cx, options)); - if (!resolvedOptions) { - return false; - } - - // Step 4. - if (!GetDifferenceSettings( - cx, operation, resolvedOptions, TemporalUnitGroup::Time, - TemporalUnit::Nanosecond, TemporalUnit::Second, &settings)) { + if (!GetDifferenceSettings(cx, operation, options, TemporalUnitGroup::Time, + TemporalUnit::Nanosecond, TemporalUnit::Second, + &settings)) { return false; } } else { - // Steps 3-4. + // Steps 2-3. settings = { TemporalUnit::Nanosecond, TemporalUnit::Second, @@ -694,23 +606,24 @@ static bool DifferenceTemporalInstant(JSContext* cx, }; } - // Step 5. - auto difference = - DifferenceInstant(instant, other, settings.roundingIncrement, + // Steps 4. + auto timeDuration = + DifferenceInstant(epochNs, other, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode); - // Step 6. - TimeDuration balanced; - if (!BalanceTimeDuration(cx, difference, settings.largestUnit, &balanced)) { + // Step 5. + Duration duration; + if (!TemporalDurationFromInternal(cx, timeDuration, settings.largestUnit, + &duration)) { return false; } - // Step 7. - auto duration = balanced.toDuration(); + // Step 6. if (operation == TemporalDifference::Since) { duration = duration.negate(); } + // Step 7. auto* obj = CreateTemporalDuration(cx, duration); if (!obj) { return false; @@ -720,26 +633,26 @@ static bool DifferenceTemporalInstant(JSContext* cx, return true; } -enum class InstantDuration { Add, Subtract }; - /** - * AddDurationToOrSubtractDurationFromInstant ( operation, instant, - * temporalDurationLike ) + * AddDurationToInstant ( operation, instant, temporalDurationLike ) */ -static bool AddDurationToOrSubtractDurationFromInstant( - JSContext* cx, InstantDuration operation, const CallArgs& args) { +static bool AddDurationToInstant(JSContext* cx, TemporalAddDuration operation, + const CallArgs& args) { auto* instant = &args.thisv().toObject().as(); - auto epochNanoseconds = ToInstant(instant); + auto epochNanoseconds = instant->epochNanoseconds(); - // Step 1. (Not applicable in our implementation.) - - // Step 2. + // Step 1. Duration duration; - if (!ToTemporalDurationRecord(cx, args.get(0), &duration)) { + if (!ToTemporalDuration(cx, args.get(0), &duration)) { return false; } - // Steps 3-6. + // Step 2. + if (operation == TemporalAddDuration::Subtract) { + duration = duration.negate(); + } + + // Steps 3-4. (Inlined DefaultTemporalLargestUnit and TemporalUnitCategory.) if (duration.years != 0 || duration.months != 0 || duration.weeks != 0 || duration.days != 0) { const char* part = duration.years != 0 ? "years" @@ -751,19 +664,16 @@ static bool AddDurationToOrSubtractDurationFromInstant( return false; } - // Step 7. - if (operation == InstantDuration::Subtract) { - duration = duration.negate(); - } - auto timeDuration = NormalizeTimeDuration(duration); + // Step 5. (Inlined ToInternalDurationRecordWith24HourDays.) + auto timeDuration = TimeDurationFromComponents(duration); - // Step 8. - Instant ns; + // Step 6. + EpochNanoseconds ns; if (!AddInstant(cx, epochNanoseconds, timeDuration, &ns)) { return false; } - // Step 9. + // Step 7. auto* result = CreateTemporalInstant(cx, ns); if (!result) { return false; @@ -813,56 +723,13 @@ static bool InstantConstructor(JSContext* cx, unsigned argc, Value* vp) { static bool Instant_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Steps 1-2. - Instant epochInstant; - if (!ToTemporalInstant(cx, args.get(0), &epochInstant)) { - return false; - } - - auto* result = CreateTemporalInstant(cx, epochInstant); - if (!result) { - return false; - } - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.Instant.fromEpochSeconds ( epochSeconds ) - */ -static bool Instant_fromEpochSeconds(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - // Step 1. - double epochSeconds; - if (!JS::ToNumber(cx, args.get(0), &epochSeconds)) { + EpochNanoseconds epochNs; + if (!ToTemporalInstant(cx, args.get(0), &epochNs)) { return false; } - // Step 2. - // - // NumberToBigInt throws a RangeError for non-integral numbers. - if (!IsInteger(epochSeconds)) { - ToCStringBuf cbuf; - const char* str = NumberToCString(&cbuf, epochSeconds); - - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INSTANT_NONINTEGER, str); - return false; - } - - // Step 3. (Not applicable) - - // Step 4. - if (!IsValidEpochSeconds(epochSeconds)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INSTANT_INVALID); - return false; - } - - // Step 5. - int64_t seconds = mozilla::AssertedCast(epochSeconds); - auto* result = CreateTemporalInstant(cx, Instant::fromSeconds(seconds)); + auto* result = CreateTemporalInstant(cx, epochNs); if (!result) { return false; } @@ -906,42 +773,8 @@ static bool Instant_fromEpochMilliseconds(JSContext* cx, unsigned argc, // Step 5. int64_t milliseconds = mozilla::AssertedCast(epochMilliseconds); - auto* result = - CreateTemporalInstant(cx, Instant::fromMilliseconds(milliseconds)); - if (!result) { - return false; - } - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.Instant.fromEpochMicroseconds ( epochMicroseconds ) - */ -static bool Instant_fromEpochMicroseconds(JSContext* cx, unsigned argc, - Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. - Rooted epochMicroseconds(cx, js::ToBigInt(cx, args.get(0))); - if (!epochMicroseconds) { - return false; - } - - // Step 2. (Not applicable) - - // Step 3. - if (!IsValidEpochMicroseconds(epochMicroseconds)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INSTANT_INVALID); - return false; - } - - int64_t i; - MOZ_ALWAYS_TRUE(BigInt::isInt64(epochMicroseconds, &i)); - - // Step 4. - auto* result = CreateTemporalInstant(cx, Instant::fromMicroseconds(i)); + auto* result = CreateTemporalInstant( + cx, EpochNanoseconds::fromMilliseconds(milliseconds)); if (!result) { return false; } @@ -970,7 +803,8 @@ static bool Instant_fromEpochNanoseconds(JSContext* cx, unsigned argc, } // Step 3. - auto* result = CreateTemporalInstant(cx, ToInstant(epochNanoseconds)); + auto* result = + CreateTemporalInstant(cx, ToEpochNanoseconds(epochNanoseconds)); if (!result) { return false; } @@ -985,13 +819,13 @@ static bool Instant_compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - Instant one; + EpochNanoseconds one; if (!ToTemporalInstant(cx, args.get(0), &one)) { return false; } // Step 2. - Instant two; + EpochNanoseconds two; if (!ToTemporalInstant(cx, args.get(1), &two)) { return false; } @@ -1001,36 +835,15 @@ static bool Instant_compare(JSContext* cx, unsigned argc, Value* vp) { return true; } -/** - * get Temporal.Instant.prototype.epochSeconds - */ -static bool Instant_epochSeconds(JSContext* cx, const CallArgs& args) { - // Step 3. - auto instant = ToInstant(&args.thisv().toObject().as()); - - // Steps 4-5. - args.rval().setNumber(instant.seconds); - return true; -} - -/** - * get Temporal.Instant.prototype.epochSeconds - */ -static bool Instant_epochSeconds(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - /** * get Temporal.Instant.prototype.epochMilliseconds */ static bool Instant_epochMilliseconds(JSContext* cx, const CallArgs& args) { // Step 3. - auto instant = ToInstant(&args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); // Step 4-5. - args.rval().setNumber(instant.floorToMilliseconds()); + args.rval().setNumber(epochNs.floorToMilliseconds()); return true; } @@ -1043,46 +856,17 @@ static bool Instant_epochMilliseconds(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -/** - * get Temporal.Instant.prototype.epochMicroseconds - */ -static bool Instant_epochMicroseconds(JSContext* cx, const CallArgs& args) { - // Step 3. - auto instant = ToInstant(&args.thisv().toObject().as()); - - // Step 4. - auto* microseconds = - BigInt::createFromInt64(cx, instant.floorToMicroseconds()); - if (!microseconds) { - return false; - } - - // Step 5. - args.rval().setBigInt(microseconds); - return true; -} - -/** - * get Temporal.Instant.prototype.epochMicroseconds - */ -static bool Instant_epochMicroseconds(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - /** * get Temporal.Instant.prototype.epochNanoseconds */ static bool Instant_epochNanoseconds(JSContext* cx, const CallArgs& args) { // Step 3. - auto instant = ToInstant(&args.thisv().toObject().as()); - auto* nanoseconds = ToEpochNanoseconds(cx, instant); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); + auto* nanoseconds = ToBigInt(cx, epochNs); if (!nanoseconds) { return false; } - // Step 4. args.rval().setBigInt(nanoseconds); return true; } @@ -1100,8 +884,8 @@ static bool Instant_epochNanoseconds(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.add ( temporalDurationLike ) */ static bool Instant_add(JSContext* cx, const CallArgs& args) { - return AddDurationToOrSubtractDurationFromInstant(cx, InstantDuration::Add, - args); + // Step 3. + return AddDurationToInstant(cx, TemporalAddDuration::Add, args); } /** @@ -1117,8 +901,8 @@ static bool Instant_add(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.subtract ( temporalDurationLike ) */ static bool Instant_subtract(JSContext* cx, const CallArgs& args) { - return AddDurationToOrSubtractDurationFromInstant( - cx, InstantDuration::Subtract, args); + // Step 3. + return AddDurationToInstant(cx, TemporalAddDuration::Subtract, args); } /** @@ -1134,6 +918,7 @@ static bool Instant_subtract(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.until ( other [ , options ] ) */ static bool Instant_until(JSContext* cx, const CallArgs& args) { + // Step 3. return DifferenceTemporalInstant(cx, TemporalDifference::Until, args); } @@ -1150,6 +935,7 @@ static bool Instant_until(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.since ( other [ , options ] ) */ static bool Instant_since(JSContext* cx, const CallArgs& args) { + // Step 3. return DifferenceTemporalInstant(cx, TemporalDifference::Since, args); } @@ -1166,7 +952,7 @@ static bool Instant_since(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.round ( roundTo ) */ static bool Instant_round(JSContext* cx, const CallArgs& args) { - auto instant = ToInstant(&args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); // Steps 3-16. auto smallestUnit = TemporalUnit::Auto; @@ -1224,7 +1010,7 @@ static bool Instant_round(JSContext* cx, const CallArgs& args) { } // Step 17. - auto roundedNs = RoundTemporalInstant(instant, roundingIncrement, + auto roundedNs = RoundTemporalInstant(epochNs, roundingIncrement, smallestUnit, roundingMode); // Step 18. @@ -1249,16 +1035,16 @@ static bool Instant_round(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.equals ( other ) */ static bool Instant_equals(JSContext* cx, const CallArgs& args) { - auto instant = ToInstant(&args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); // Step 3. - Instant other; + EpochNanoseconds other; if (!ToTemporalInstant(cx, args.get(0), &other)) { return false; } // Steps 4-5. - args.rval().setBoolean(instant == other); + args.rval().setBoolean(epochNs == other); return true; } @@ -1275,7 +1061,7 @@ static bool Instant_equals(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.toString ( [ options ] ) */ static bool Instant_toString(JSContext* cx, const CallArgs& args) { - auto instant = ToInstant(&args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); Rooted timeZone(cx); auto roundingMode = TemporalRoundingMode::Trunc; @@ -1332,19 +1118,13 @@ static bool Instant_toString(JSContext* cx, const CallArgs& args) { precision = ToSecondsStringPrecision(smallestUnit, digits); } - // Step 12. - auto ns = RoundTemporalInstant(instant, precision.increment, precision.unit, - roundingMode); - - // Step 13. - Rooted roundedInstant(cx, CreateTemporalInstant(cx, ns)); - if (!roundedInstant) { - return false; - } + // Steps 12-13. + auto roundedNs = RoundTemporalInstant(epochNs, precision.increment, + precision.unit, roundingMode); // Step 14. - JSString* str = TemporalInstantToString(cx, roundedInstant, timeZone, - precision.precision); + JSString* str = + TemporalInstantToString(cx, roundedNs, timeZone, precision.precision); if (!str) { return false; } @@ -1366,19 +1146,10 @@ static bool Instant_toString(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.toLocaleString ( [ locales [ , options ] ] ) */ static bool Instant_toLocaleString(JSContext* cx, const CallArgs& args) { - Rooted instant(cx, - &args.thisv().toObject().as()); - - // Step 3. - Rooted timeZone(cx); - JSString* str = - TemporalInstantToString(cx, instant, timeZone, Precision::Auto()); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-4. + Handle required = cx->names().any; + Handle defaults = cx->names().all; + return TemporalObjectToLocaleString(cx, args, required, defaults); } /** @@ -1394,13 +1165,12 @@ static bool Instant_toLocaleString(JSContext* cx, unsigned argc, Value* vp) { * Temporal.Instant.prototype.toJSON ( ) */ static bool Instant_toJSON(JSContext* cx, const CallArgs& args) { - Rooted instant(cx, - &args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); // Step 3. Rooted timeZone(cx); JSString* str = - TemporalInstantToString(cx, instant, timeZone, Precision::Auto()); + TemporalInstantToString(cx, epochNs, timeZone, Precision::Auto()); if (!str) { return false; } @@ -1427,81 +1197,11 @@ static bool Instant_valueOf(JSContext* cx, unsigned argc, Value* vp) { return false; } -/** - * Temporal.Instant.prototype.toZonedDateTime ( item ) - */ -static bool Instant_toZonedDateTime(JSContext* cx, const CallArgs& args) { - auto instant = ToInstant(&args.thisv().toObject().as()); - - // Step 3. - Rooted item( - cx, RequireObjectArg(cx, "item", "toZonedDateTime", args.get(0))); - if (!item) { - return false; - } - - // Step 4. - Rooted calendarLike(cx); - if (!GetProperty(cx, item, item, cx->names().calendar, &calendarLike)) { - return false; - } - - // Step 5. - if (calendarLike.isUndefined()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_PROPERTY, "calendar"); - return false; - } - - // Step 6. - Rooted calendar(cx); - if (!ToTemporalCalendar(cx, calendarLike, &calendar)) { - return false; - } - - // Step 7. - Rooted timeZoneLike(cx); - if (!GetProperty(cx, item, item, cx->names().timeZone, &timeZoneLike)) { - return false; - } - - // Step 8. - if (timeZoneLike.isUndefined()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_PROPERTY, "timeZone"); - return false; - } - - // Step 9. - Rooted timeZone(cx); - if (!ToTemporalTimeZone(cx, timeZoneLike, &timeZone)) { - return false; - } - - // Step 10. - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.Instant.prototype.toZonedDateTime ( item ) - */ -static bool Instant_toZonedDateTime(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - /** * Temporal.Instant.prototype.toZonedDateTimeISO ( item ) */ static bool Instant_toZonedDateTimeISO(JSContext* cx, const CallArgs& args) { - auto instant = ToInstant(&args.thisv().toObject().as()); + auto epochNs = args.thisv().toObject().as().epochNanoseconds(); // Step 3. Rooted timeZone(cx); @@ -1511,7 +1211,7 @@ static bool Instant_toZonedDateTimeISO(JSContext* cx, const CallArgs& args) { // Step 4. Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); + auto* result = CreateTemporalZonedDateTime(cx, epochNs, timeZone, calendar); if (!result) { return false; } @@ -1542,9 +1242,7 @@ const JSClass& InstantObject::protoClass_ = PlainObject::class_; static const JSFunctionSpec Instant_methods[] = { JS_FN("from", Instant_from, 1, 0), - JS_FN("fromEpochSeconds", Instant_fromEpochSeconds, 1, 0), JS_FN("fromEpochMilliseconds", Instant_fromEpochMilliseconds, 1, 0), - JS_FN("fromEpochMicroseconds", Instant_fromEpochMicroseconds, 1, 0), JS_FN("fromEpochNanoseconds", Instant_fromEpochNanoseconds, 1, 0), JS_FN("compare", Instant_compare, 2, 0), JS_FS_END, @@ -1561,15 +1259,12 @@ static const JSFunctionSpec Instant_prototype_methods[] = { JS_FN("toLocaleString", Instant_toLocaleString, 0, 0), JS_FN("toJSON", Instant_toJSON, 0, 0), JS_FN("valueOf", Instant_valueOf, 0, 0), - JS_FN("toZonedDateTime", Instant_toZonedDateTime, 1, 0), JS_FN("toZonedDateTimeISO", Instant_toZonedDateTimeISO, 1, 0), JS_FS_END, }; static const JSPropertySpec Instant_prototype_properties[] = { - JS_PSG("epochSeconds", Instant_epochSeconds, 0), JS_PSG("epochMilliseconds", Instant_epochMilliseconds, 0), - JS_PSG("epochMicroseconds", Instant_epochMicroseconds, 0), JS_PSG("epochNanoseconds", Instant_epochNanoseconds, 0), JS_STRING_SYM_PS(toStringTag, "Temporal.Instant", JSPROP_READONLY), JS_PS_END, diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.h index 9ad7f159db0..be0b01a4ff2 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Instant.h @@ -12,7 +12,6 @@ #include #include "builtin/temporal/TemporalTypes.h" -#include "builtin/temporal/Wrapped.h" #include "js/TypeDecls.h" #include "js/Value.h" #include "vm/NativeObject.h" @@ -32,29 +31,23 @@ class InstantObject : public NativeObject { static constexpr uint32_t NANOSECONDS_SLOT = 1; static constexpr uint32_t SLOT_COUNT = 2; - int64_t seconds() const { + /** + * Extract the epoch nanoseconds fields from this ZonedDateTime object. + */ + EpochNanoseconds epochNanoseconds() const { double seconds = getFixedSlot(SECONDS_SLOT).toNumber(); MOZ_ASSERT(-8'640'000'000'000 <= seconds && seconds <= 8'640'000'000'000); - return int64_t(seconds); - } - int32_t nanoseconds() const { int32_t nanoseconds = getFixedSlot(NANOSECONDS_SLOT).toInt32(); MOZ_ASSERT(0 <= nanoseconds && nanoseconds <= 999'999'999); - return nanoseconds; + + return {{int64_t(seconds), nanoseconds}}; } private: static const ClassSpec classSpec_; }; -/** - * Extract the instant fields from the Instant object. - */ -inline Instant ToInstant(const InstantObject* instant) { - return {instant->seconds(), instant->nanoseconds()}; -} - class Increment; enum class TemporalUnit; enum class TemporalRoundingMode; @@ -67,76 +60,59 @@ bool IsValidEpochNanoseconds(const JS::BigInt* epochNanoseconds); /** * IsValidEpochNanoseconds ( epochNanoseconds ) */ -bool IsValidEpochInstant(const Instant& instant); +bool IsValidEpochNanoseconds(const EpochNanoseconds& epochNanoseconds); #ifdef DEBUG /** - * Return true if the input is within the valid instant span limits. + * Return true if the input is within the valid epoch duration limits. */ -bool IsValidInstantSpan(const InstantSpan& span); +bool IsValidEpochDuration(const EpochDuration& duration); #endif /** - * Convert a BigInt to an instant. The input must be a valid epoch nanoseconds - * value. + * Convert a BigInt to epoch nanoseconds. The input must be a valid epoch + * nanoseconds value. */ -Instant ToInstant(const JS::BigInt* epochNanoseconds); +EpochNanoseconds ToEpochNanoseconds(const JS::BigInt* epochNanoseconds); /** - * Convert an instant to a BigInt. The input must be a valid epoch instant. + * Convert epoch nanoseconds to a BigInt. The input must be valid epoch + * nanoseconds. */ -JS::BigInt* ToEpochNanoseconds(JSContext* cx, const Instant& instant); - -/** - * ToTemporalInstant ( item ) - */ -Wrapped ToTemporalInstant(JSContext* cx, - JS::Handle item); - -/** - * ToTemporalInstant ( item ) - */ -bool ToTemporalInstant(JSContext* cx, JS::Handle item, - Instant* result); +JS::BigInt* ToBigInt(JSContext* cx, const EpochNanoseconds& epochNanoseconds); /** * CreateTemporalInstant ( epochNanoseconds [ , newTarget ] ) */ -InstantObject* CreateTemporalInstant(JSContext* cx, const Instant& instant); +InstantObject* CreateTemporalInstant(JSContext* cx, + const EpochNanoseconds& epochNanoseconds); /** - * GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond [ , offsetNanoseconds ] ) + * GetUTCEpochNanoseconds ( isoDateTime ) */ -Instant GetUTCEpochNanoseconds(const PlainDateTime& dateTime); - -/** - * GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond [ , offsetNanoseconds ] ) - */ -Instant GetUTCEpochNanoseconds(const PlainDateTime& dateTime, - const InstantSpan& offsetNanoseconds); +EpochNanoseconds GetUTCEpochNanoseconds(const ISODateTime& isoDateTime); /** * RoundTemporalInstant ( ns, increment, unit, roundingMode ) */ -Instant RoundTemporalInstant(const Instant& ns, Increment increment, - TemporalUnit unit, - TemporalRoundingMode roundingMode); +EpochNanoseconds RoundTemporalInstant(const EpochNanoseconds& ns, + Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode); /** * AddInstant ( epochNanoseconds, norm ) */ -bool AddInstant(JSContext* cx, const Instant& instant, - const NormalizedTimeDuration& duration, Instant* result); +bool AddInstant(JSContext* cx, const EpochNanoseconds& epochNanoseconds, + const TimeDuration& duration, EpochNanoseconds* result); /** * DifferenceInstant ( ns1, ns2, roundingIncrement, smallestUnit, roundingMode ) */ -NormalizedTimeDuration DifferenceInstant(const Instant& ns1, const Instant& ns2, - Increment roundingIncrement, - TemporalUnit smallestUnit, - TemporalRoundingMode roundingMode); +TimeDuration DifferenceInstant(const EpochNanoseconds& ns1, + const EpochNanoseconds& ns2, + Increment roundingIncrement, + TemporalUnit smallestUnit, + TemporalRoundingMode roundingMode); } /* namespace js::temporal */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/MonthCode.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/MonthCode.h new file mode 100644 index 00000000000..97067fb5e7c --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/MonthCode.h @@ -0,0 +1,496 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef builtin_temporal_MonthCode_h +#define builtin_temporal_MonthCode_h + +#include "mozilla/Assertions.h" +#include "mozilla/EnumSet.h" + +#include +#include +#include +#include +#include + +#include "jstypes.h" + +#include "builtin/temporal/Calendar.h" +#include "builtin/temporal/Crash.h" + +namespace js::temporal { + +class MonthCode final { + public: + enum class Code { + Invalid = 0, + + // Months 01 - M12. + M01 = 1, + M02, + M03, + M04, + M05, + M06, + M07, + M08, + M09, + M10, + M11, + M12, + + // Epagomenal month M13. + M13, + + // Leap months M01 - M12. + M01L, + M02L, + M03L, + M04L, + M05L, + M06L, + M07L, + M08L, + M09L, + M10L, + M11L, + M12L, + }; + + private: + static constexpr int32_t toLeapMonth = + static_cast(Code::M01L) - static_cast(Code::M01); + + Code code_ = Code::Invalid; + + public: + constexpr MonthCode() = default; + + constexpr explicit MonthCode(Code code) : code_(code) {} + + constexpr explicit MonthCode(int32_t month, bool isLeapMonth = false) { + MOZ_ASSERT(1 <= month && month <= 13); + MOZ_ASSERT_IF(isLeapMonth, 1 <= month && month <= 12); + + code_ = static_cast(month + (isLeapMonth ? toLeapMonth : 0)); + } + + constexpr auto code() const { return code_; } + + constexpr int32_t ordinal() const { + int32_t ordinal = static_cast(code_); + if (isLeapMonth()) { + ordinal -= toLeapMonth; + } + return ordinal; + } + + constexpr bool isLeapMonth() const { return code_ >= Code::M01L; } + + constexpr bool operator==(const MonthCode& other) const { + return other.code_ == code_; + } + + constexpr bool operator!=(const MonthCode& other) const { + return !(*this == other); + } + + constexpr bool operator<(const MonthCode& other) const { + if (ordinal() != other.ordinal()) { + return ordinal() < other.ordinal(); + } + return code_ < other.code_; + } + + constexpr bool operator>(const MonthCode& other) const { + return other < *this; + } + + constexpr bool operator<=(const MonthCode& other) const { + return !(other < *this); + } + + constexpr bool operator>=(const MonthCode& other) const { + return !(*this < other); + } + + constexpr explicit operator std::string_view() const { + constexpr const char* name = + "M01L" + "M02L" + "M03L" + "M04L" + "M05L" + "M06L" + "M07L" + "M08L" + "M09L" + "M10L" + "M11L" + "M12L" + "M13"; + size_t index = (ordinal() - 1) * 4; + size_t length = 3 + isLeapMonth(); + return {name + index, length}; + } + + /** + * Returns the maximum non-leap month. This is the epagomenal month "M13". + */ + constexpr static auto maxNonLeapMonth() { return MonthCode{Code::M13}; } + + /** + * Returns the maximum leap month. + */ + constexpr static auto maxLeapMonth() { return MonthCode{Code::M12L}; } +}; + +class MonthCodes final { + mozilla::EnumSet monthCodes_{ + MonthCode::Code::M01, MonthCode::Code::M02, MonthCode::Code::M03, + MonthCode::Code::M04, MonthCode::Code::M05, MonthCode::Code::M06, + MonthCode::Code::M07, MonthCode::Code::M08, MonthCode::Code::M09, + MonthCode::Code::M10, MonthCode::Code::M11, MonthCode::Code::M12, + }; + + public: + constexpr MOZ_IMPLICIT MonthCodes(std::initializer_list list) { + for (auto value : list) { + monthCodes_ += value.code(); + } + } + + bool contains(MonthCode monthCode) const { + return monthCodes_.contains(monthCode.code()); + } + + bool contains(const MonthCodes& monthCodes) const { + return monthCodes_.contains(monthCodes.monthCodes_); + } +}; + +// static variables in constexpr functions requires C++23 support, so we can't +// declare the month codes directly in CalendarMonthCodes. +// +// https://tc39.es/proposal-intl-era-monthcode/#table-additional-month-codes +// +// https://docs.rs/icu/latest/icu/calendar/buddhist/struct.Buddhist.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/indian/struct.Indian.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicCivil.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicObservational.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicTabular.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/islamic/struct.IslamicUmmAlQura.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/japanese/struct.Japanese.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/persian/struct.Persian.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/roc/struct.Roc.html#month-codes +// +// https://docs.rs/icu/latest/icu/calendar/chinese/struct.Chinese.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/dangi/struct.Dangi.html#month-codes +// +// https://docs.rs/icu/latest/icu/calendar/coptic/struct.Coptic.html#month-codes +// +// https://docs.rs/icu/latest/icu/calendar/ethiopian/struct.Ethiopian.html#month-codes +// https://docs.rs/icu/latest/icu/calendar/hebrew/struct.Hebrew.html#month-codes +namespace monthcodes { +inline constexpr MonthCodes ISO8601 = {}; + +inline constexpr MonthCodes ChineseOrDangi = { + // Leap months. + MonthCode{1, /* isLeapMonth = */ true}, + MonthCode{2, /* isLeapMonth = */ true}, + MonthCode{3, /* isLeapMonth = */ true}, + MonthCode{4, /* isLeapMonth = */ true}, + MonthCode{5, /* isLeapMonth = */ true}, + MonthCode{6, /* isLeapMonth = */ true}, + MonthCode{7, /* isLeapMonth = */ true}, + MonthCode{8, /* isLeapMonth = */ true}, + MonthCode{9, /* isLeapMonth = */ true}, + MonthCode{10, /* isLeapMonth = */ true}, + MonthCode{11, /* isLeapMonth = */ true}, + MonthCode{12, /* isLeapMonth = */ true}, +}; + +inline constexpr MonthCodes CopticOrEthiopian = { + // Short epagomenal month. + MonthCode{13}, +}; + +inline constexpr MonthCodes Hebrew = { + // Leap month Adar I. + MonthCode{5, /* isLeapMonth = */ true}, +}; +} // namespace monthcodes + +constexpr auto& CalendarMonthCodes(CalendarId id) { + switch (id) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Gregorian: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Persian: + case CalendarId::Japanese: + case CalendarId::ROC: + return monthcodes::ISO8601; + + case CalendarId::Chinese: + case CalendarId::Dangi: + return monthcodes::ChineseOrDangi; + + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + return monthcodes::CopticOrEthiopian; + + case CalendarId::Hebrew: + return monthcodes::Hebrew; + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +constexpr bool CalendarHasLeapMonths(CalendarId id) { + switch (id) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + case CalendarId::Gregorian: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Japanese: + case CalendarId::Persian: + case CalendarId::ROC: + return false; + + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::Hebrew: + return true; + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +constexpr bool CalendarHasEpagomenalMonths(CalendarId id) { + switch (id) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::Gregorian: + case CalendarId::Hebrew: + case CalendarId::Indian: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + case CalendarId::Japanese: + case CalendarId::Persian: + case CalendarId::ROC: + return false; + + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + return true; + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +constexpr int32_t CalendarMonthsPerYear(CalendarId id) { + if (CalendarHasLeapMonths(id) || CalendarHasEpagomenalMonths(id)) { + return 13; + } + return 12; +} + +constexpr std::pair CalendarDaysInMonth(CalendarId id) { + switch (id) { + // ISO8601 calendar. + // M02: 28-29 days + // M04, M06, M09, M11: 30 days + // M01, M03, M05, M07, M08, M10, M12: 31 days + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Gregorian: + case CalendarId::Japanese: + case CalendarId::ROC: + return {28, 31}; + + // Chinese/Dangi calendars have 29-30 days per month. + // + // Hebrew: + // M01, M05, M07, M09, M11: 30 days. + // M02, M03: 29-30 days. + // M04, M06, M08, M10, M12: 29 days. + // M05L: 30 days + // + // Islamic calendars have 29-30 days. + // + // IslamicCivil, IslamicTabular: + // M01, M03, M05, M07, M09, M11: 30 days + // M02, M04, M06, M08, M10: 29 days + // M12: 29-30 days. + case CalendarId::Chinese: + case CalendarId::Dangi: + case CalendarId::Hebrew: + case CalendarId::Islamic: + case CalendarId::IslamicCivil: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicTabular: + case CalendarId::IslamicUmmAlQura: + return {29, 30}; + + // Coptic, Ethiopian, EthiopianAmeteAlem: + // M01..M12: 30 days. + // M13: 5-6 days. + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: + return {5, 30}; + + // Indian: + // M1: 30-31 days. + // M02..M06: 31 days + // M07..M12: 30 days + case CalendarId::Indian: + return {30, 31}; + + // Persian: + // M01..M06: 31 days + // M07..M11: 30 days + // M12: 29-30 days + case CalendarId::Persian: + return {29, 31}; + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +// ISO8601 calendar. +// M02: 28-29 days +// M04, M06, M09, M11: 30 days +// M01, M03, M05, M07, M08, M10, M12: 31 days +constexpr std::pair ISODaysInMonth(MonthCode monthCode) { + int32_t ordinal = monthCode.ordinal(); + if (ordinal == 2) { + return {28, 29}; + } + if (ordinal == 4 || ordinal == 6 || ordinal == 9 || ordinal == 11) { + return {30, 30}; + } + return {31, 31}; +} + +constexpr std::pair CalendarDaysInMonth(CalendarId id, + MonthCode monthCode) { + switch (id) { + case CalendarId::ISO8601: + case CalendarId::Buddhist: + case CalendarId::Gregorian: + case CalendarId::Japanese: + case CalendarId::ROC: + return ISODaysInMonth(monthCode); + + // Chinese/Dangi calendars have 29-30 days per month. + case CalendarId::Chinese: + case CalendarId::Dangi: + return {29, 30}; + + // Coptic, Ethiopian, EthiopianAmeteAlem: + // M01..M12: 30 days. + // M13: 5-6 days. + case CalendarId::Coptic: + case CalendarId::Ethiopian: + case CalendarId::EthiopianAmeteAlem: { + if (monthCode.ordinal() <= 12) { + return {30, 30}; + } + return {5, 6}; + } + + // Hebrew: + // M01, M05, M07, M09, M11: 30 days. + // M02, M03: 29-30 days. + // M04, M06, M08, M10, M12: 29 days. + // M05L: 30 days + case CalendarId::Hebrew: { + int32_t ordinal = monthCode.ordinal(); + if (ordinal == 2 || ordinal == 3) { + return {29, 30}; + } + if ((ordinal & 1) == 1 || monthCode.isLeapMonth()) { + return {30, 30}; + } + return {29, 29}; + } + + // Indian: + // M1: 30-31 days. + // M02..M06: 31 days + // M07..M12: 30 days + case CalendarId::Indian: { + int32_t ordinal = monthCode.ordinal(); + if (ordinal == 1) { + return {30, 31}; + } + if (ordinal <= 6) { + return {31, 31}; + } + return {30, 30}; + } + + // Islamic calendars have 29-30 days per month. + case CalendarId::Islamic: + case CalendarId::IslamicRGSA: + case CalendarId::IslamicUmmAlQura: + return {29, 30}; + + // IslamicCivil, IslamicTabular: + // M01, M03, M05, M07, M09, M11: 30 days + // M02, M04, M06, M08, M10: 29 days + // M12: 29-30 days. + case CalendarId::IslamicCivil: + case CalendarId::IslamicTabular: { + int32_t ordinal = monthCode.ordinal(); + if ((ordinal & 1) == 1) { + return {30, 30}; + } + if (ordinal < 12) { + return {29, 29}; + } + return {29, 30}; + } + + // Persian: + // M01..M06: 31 days + // M07..M11: 30 days + // M12: 29-30 days + case CalendarId::Persian: { + int32_t ordinal = monthCode.ordinal(); + if (ordinal <= 6) { + return {31, 31}; + } + if (ordinal <= 11) { + return {30, 30}; + } + return {29, 30}; + } + } + JS_CONSTEXPR_CRASH("invalid calendar id"); +} + +} // namespace js::temporal + +#endif /* builtin_temporal_MonthCode_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.cpp index 1b907573045..587b190481d 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.cpp @@ -7,51 +7,45 @@ #include "builtin/temporal/PlainDate.h" #include "mozilla/Assertions.h" -#include "mozilla/Casting.h" -#include "mozilla/FloatingPoint.h" -#include "mozilla/Maybe.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/EnumSet.h" -#include #include #include -#include #include -#include #include +#include "jsdate.h" #include "jsnum.h" #include "jspubtd.h" #include "jstypes.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/CalendarFields.h" #include "builtin/temporal/Duration.h" +#include "builtin/temporal/Instant.h" #include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/PlainMonthDay.h" #include "builtin/temporal/PlainTime.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ToString.h" -#include "builtin/temporal/Wrapped.h" #include "builtin/temporal/ZonedDateTime.h" -#include "ds/IdValuePair.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" -#include "js/AllocPolicy.h" +#include "gc/GCEnum.h" #include "js/CallArgs.h" #include "js/CallNonGenericMethod.h" #include "js/Class.h" -#include "js/Date.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/PropertyDescriptor.h" #include "js/PropertySpec.h" #include "js/RootingAPI.h" @@ -63,9 +57,6 @@ #include "vm/JSContext.h" #include "vm/JSObject.h" #include "vm/PlainObject.h" -#include "vm/PropertyInfo.h" -#include "vm/Realm.h" -#include "vm/Shape.h" #include "vm/StringType.h" #include "vm/JSObject-inl.h" @@ -83,43 +74,45 @@ static inline bool IsPlainDate(Handle v) { /** * IsValidISODate ( year, month, day ) */ -template -static bool IsValidISODate(T year, T month, T day) { - static_assert(std::is_same_v || std::is_same_v); +bool js::temporal::IsValidISODate(const ISODate& date) { + const auto& [year, month, day] = date; // Step 1. - MOZ_ASSERT(IsInteger(year)); - MOZ_ASSERT(IsInteger(month)); - MOZ_ASSERT(IsInteger(day)); - - // Step 2. if (month < 1 || month > 12) { return false; } - // Step 3. - int32_t daysInMonth = js::temporal::ISODaysInMonth(year, int32_t(month)); + // Step 2. + int32_t daysInMonth = js::temporal::ISODaysInMonth(year, month); - // Steps 4-5. + // Steps 3-4. return 1 <= day && day <= daysInMonth; } - -/** - * IsValidISODate ( year, month, day ) - */ -bool js::temporal::IsValidISODate(const PlainDate& date) { - const auto& [year, month, day] = date; - return ::IsValidISODate(year, month, day); -} - -/** - * IsValidISODate ( year, month, day ) - */ -bool js::temporal::IsValidISODate(double year, double month, double day) { - return ::IsValidISODate(year, month, day); -} #endif +/** + * ISODateWithinLimits ( isoDate ) + */ +bool js::temporal::ISODateWithinLimits(const ISODate& isoDate) { + MOZ_ASSERT(IsValidISODate(isoDate)); + + constexpr auto min = ISODate::min(); + constexpr auto max = ISODate::max(); + + const auto& year = isoDate.year; + + // Fast-path when the input is definitely in range. + if (min.year < year && year < max.year) { + return true; + } + + // Check |isoDate| is within the valid limits. + if (year < 0) { + return isoDate >= min; + } + return isoDate <= max; +} + static void ReportInvalidDateValue(JSContext* cx, const char* name, int32_t min, int32_t max, double num) { Int32ToCStringBuf minCbuf; @@ -158,13 +151,20 @@ static bool ThrowIfInvalidISODate(JSContext* cx, T year, T month, T day) { MOZ_ASSERT(IsInteger(month)); MOZ_ASSERT(IsInteger(day)); + if constexpr (std::is_same_v) { + if (!ThrowIfInvalidDateValue(cx, "year", INT32_MIN, INT32_MAX, year)) { + return false; + } + } + // Step 2. if (!ThrowIfInvalidDateValue(cx, "month", 1, 12, month)) { return false; } // Step 3. - int32_t daysInMonth = js::temporal::ISODaysInMonth(year, int32_t(month)); + int32_t daysInMonth = + js::temporal::ISODaysInMonth(int32_t(year), int32_t(month)); // Steps 4-5. return ThrowIfInvalidDateValue(cx, "day", 1, daysInMonth, day); @@ -173,7 +173,7 @@ static bool ThrowIfInvalidISODate(JSContext* cx, T year, T month, T day) { /** * IsValidISODate ( year, month, day ) */ -bool js::temporal::ThrowIfInvalidISODate(JSContext* cx, const PlainDate& date) { +bool js::temporal::ThrowIfInvalidISODate(JSContext* cx, const ISODate& date) { const auto& [year, month, day] = date; return ::ThrowIfInvalidISODate(cx, year, month, day); } @@ -187,114 +187,21 @@ bool js::temporal::ThrowIfInvalidISODate(JSContext* cx, double year, } /** - * RegulateISODate ( year, month, day, overflow ) - * - * With |overflow = "constrain"|. - */ -static PlainDate ConstrainISODate(const PlainDate& date) { - const auto& [year, month, day] = date; - - // Step 1.a. - int32_t m = std::clamp(month, 1, 12); - - // Step 1.b. - int32_t daysInMonth = temporal::ISODaysInMonth(year, m); - - // Step 1.c. - int32_t d = std::clamp(day, 1, daysInMonth); - - // Step 1.d. - return {year, m, d}; -} - -/** - * RegulateISODate ( year, month, day, overflow ) - */ -bool js::temporal::RegulateISODate(JSContext* cx, const PlainDate& date, - TemporalOverflow overflow, - PlainDate* result) { - // Step 1. - if (overflow == TemporalOverflow::Constrain) { - *result = ::ConstrainISODate(date); - return true; - } - - // Step 2.a. - MOZ_ASSERT(overflow == TemporalOverflow::Reject); - - // Step 2.b. - if (!ThrowIfInvalidISODate(cx, date)) { - return false; - } - - // Step 2.b. (Inlined call to CreateISODateRecord.) - *result = date; - return true; -} - -/** - * RegulateISODate ( year, month, day, overflow ) - */ -bool js::temporal::RegulateISODate(JSContext* cx, double year, double month, - double day, TemporalOverflow overflow, - RegulatedISODate* result) { - MOZ_ASSERT(IsInteger(year)); - MOZ_ASSERT(IsInteger(month)); - MOZ_ASSERT(IsInteger(day)); - - // Step 1. - if (overflow == TemporalOverflow::Constrain) { - // Step 1.a. - int32_t m = int32_t(std::clamp(month, 1.0, 12.0)); - - // Step 1.b. - double daysInMonth = double(ISODaysInMonth(year, m)); - - // Step 1.c. - int32_t d = int32_t(std::clamp(day, 1.0, daysInMonth)); - - // Step 1.d. - *result = {year, m, d}; - return true; - } - - // Step 2.a. - MOZ_ASSERT(overflow == TemporalOverflow::Reject); - - // Step 2.b. - if (!ThrowIfInvalidISODate(cx, year, month, day)) { - return false; - } - - // Step 2.b. (Inlined call to CreateISODateRecord.) - *result = {year, int32_t(month), int32_t(day)}; - return true; -} - -/** - * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ) + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) */ static PlainDateObject* CreateTemporalDate(JSContext* cx, const CallArgs& args, - double isoYear, double isoMonth, - double isoDay, + const ISODate& isoDate, Handle calendar) { - MOZ_ASSERT(IsInteger(isoYear)); - MOZ_ASSERT(IsInteger(isoMonth)); - MOZ_ASSERT(IsInteger(isoDay)); + MOZ_ASSERT(IsValidISODate(isoDate)); // Step 1. - if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { - return nullptr; - } - - // Step 2. - if (!ISODateTimeWithinLimits(isoYear, isoMonth, isoDay)) { + if (!ISODateWithinLimits(isoDate)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return nullptr; } - // Steps 3-4. + // Steps 2-3. Rooted proto(cx); if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PlainDate, &proto)) { @@ -306,1015 +213,341 @@ static PlainDateObject* CreateTemporalDate(JSContext* cx, const CallArgs& args, return nullptr; } + // Step 4. + auto packedDate = PackedDate::pack(isoDate); + object->setFixedSlot(PlainDateObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); + // Step 5. - object->setFixedSlot(PlainDateObject::ISO_YEAR_SLOT, - Int32Value(int32_t(isoYear))); - - // Step 6. - object->setFixedSlot(PlainDateObject::ISO_MONTH_SLOT, - Int32Value(int32_t(isoMonth))); - - // Step 7. - object->setFixedSlot(PlainDateObject::ISO_DAY_SLOT, - Int32Value(int32_t(isoDay))); - - // Step 8. object->setFixedSlot(PlainDateObject::CALENDAR_SLOT, calendar.toSlotValue()); - // Step 9. + // Step 6. return object; } /** - * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ) + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) */ PlainDateObject* js::temporal::CreateTemporalDate( - JSContext* cx, const PlainDate& date, Handle calendar) { - const auto& [isoYear, isoMonth, isoDay] = date; + JSContext* cx, const ISODate& isoDate, Handle calendar) { + MOZ_ASSERT(IsValidISODate(isoDate)); // Step 1. - if (!ThrowIfInvalidISODate(cx, date)) { - return nullptr; - } - - // Step 2. - if (!ISODateTimeWithinLimits(date)) { + if (!ISODateWithinLimits(isoDate)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return nullptr; } - // Steps 3-4. + // Steps 2-3. auto* object = NewBuiltinClassInstance(cx); if (!object) { return nullptr; } + // Step 4. + auto packedDate = PackedDate::pack(isoDate); + object->setFixedSlot(PlainDateObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); + // Step 5. - object->setFixedSlot(PlainDateObject::ISO_YEAR_SLOT, Int32Value(isoYear)); - - // Step 6. - object->setFixedSlot(PlainDateObject::ISO_MONTH_SLOT, Int32Value(isoMonth)); - - // Step 7. - object->setFixedSlot(PlainDateObject::ISO_DAY_SLOT, Int32Value(isoDay)); - - // Step 8. object->setFixedSlot(PlainDateObject::CALENDAR_SLOT, calendar.toSlotValue()); - // Step 9. + // Step 6. return object; } /** - * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ) + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) */ -bool js::temporal::CreateTemporalDate( - JSContext* cx, const PlainDate& date, Handle calendar, - MutableHandle result) { - // Step 1. - if (!ThrowIfInvalidISODate(cx, date)) { - return false; - } +PlainDateObject* js::temporal::CreateTemporalDate(JSContext* cx, + Handle date) { + MOZ_ASSERT(ISODateWithinLimits(date)); + return CreateTemporalDate(cx, date, date.calendar()); +} - // Step 2. - if (!ISODateTimeWithinLimits(date)) { +/** + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) + */ +bool js::temporal::CreateTemporalDate(JSContext* cx, const ISODate& isoDate, + Handle calendar, + MutableHandle result) { + MOZ_ASSERT(IsValidISODate(isoDate)); + + // Step 1. + if (!ISODateWithinLimits(isoDate)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return false; } - // Steps 3-9. - result.set(PlainDateWithCalendar{date, calendar}); + // Steps 2-6. + result.set(PlainDate{isoDate, calendar}); + return true; +} + +struct DateOptions { + TemporalOverflow overflow = TemporalOverflow::Constrain; +}; + +/** + * ToTemporalDate ( item [ , options ] ) + */ +static bool ToTemporalDateOptions(JSContext* cx, Handle options, + DateOptions* result) { + if (options.isUndefined()) { + *result = {}; + return true; + } + + // NOTE: |options| are only passed from `Temporal.PlainDate.from`. + + Rooted resolvedOptions( + cx, RequireObjectArg(cx, "options", "from", options)); + if (!resolvedOptions) { + return false; + } + + auto overflow = TemporalOverflow::Constrain; + if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) { + return false; + } + + *result = {overflow}; return true; } /** * ToTemporalDate ( item [ , options ] ) */ -static Wrapped ToTemporalDate( - JSContext* cx, Handle item, Handle maybeOptions) { - // Step 1-2. (Not applicable in our implementation.) +static bool ToTemporalDate(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { + // Step 1. (Not applicable in our implementation.) - // Step 3.a. - if (item->canUnwrapAs()) { - return item; + // Step 2.a. + if (auto* plainDate = item->maybeUnwrapIf()) { + auto date = plainDate->date(); + Rooted calendar(cx, plainDate->calendar()); + if (!calendar.wrap(cx)) { + return false; + } + + // Steps 2.a.i-ii. + DateOptions ignoredOptions; + if (!ToTemporalDateOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.a.iii. + result.set(PlainDate{date, calendar}); + return true; } - // Step 3.b. + // Step 2.b. if (auto* zonedDateTime = item->maybeUnwrapIf()) { - auto epochInstant = ToInstant(zonedDateTime); + auto epochNs = zonedDateTime->epochNanoseconds(); Rooted timeZone(cx, zonedDateTime->timeZone()); Rooted calendar(cx, zonedDateTime->calendar()); if (!timeZone.wrap(cx)) { - return nullptr; + return false; } if (!calendar.wrap(cx)) { - return nullptr; + return false; } - // Step 3.b.i. - if (maybeOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeOptions, &ignored)) { - return nullptr; - } + // Steps 2.b.ii. + ISODateTime isoDateTime; + if (!GetISODateTimeFor(cx, timeZone, epochNs, &isoDateTime)) { + return false; } - // Steps 3.b.ii-iv. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, timeZone, epochInstant, &dateTime)) { - return nullptr; + // Steps 2.b.ii-iii. + DateOptions ignoredOptions; + if (!ToTemporalDateOptions(cx, options, &ignoredOptions)) { + return false; } - // Step 3.b.v. - return CreateTemporalDate(cx, dateTime.date, calendar); + // Step 2.b.iv. + result.set(PlainDate{isoDateTime.date, calendar}); + return true; } - // Step 3.c. + // Step 2.c. if (auto* dateTime = item->maybeUnwrapIf()) { - auto date = ToPlainDate(dateTime); + auto date = dateTime->date(); Rooted calendar(cx, dateTime->calendar()); if (!calendar.wrap(cx)) { - return nullptr; + return false; } - // Step 3.c.i. - if (maybeOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeOptions, &ignored)) { - return nullptr; - } + // Steps 2.c.i-ii. + DateOptions ignoredOptions; + if (!ToTemporalDateOptions(cx, options, &ignoredOptions)) { + return false; } - // Step 3.c.ii. - return CreateTemporalDate(cx, date, calendar); + // Step 2.c.iii. + result.set(PlainDate{date, calendar}); + return true; } - // Step 3.d. - Rooted calendarValue(cx); - if (!GetTemporalCalendarWithISODefault(cx, item, &calendarValue)) { - return nullptr; + // Step 2.d. + Rooted calendar(cx); + if (!GetTemporalCalendarWithISODefault(cx, item, &calendar)) { + return false; } - // Step 3.e. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - }, - &calendar)) { - return nullptr; + // Step 2.e. + Rooted fields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + }, + &fields)) { + return false; } - // Step 3.f. - Rooted fields( - cx, PrepareCalendarFields(cx, calendar, item, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - })); - if (!fields) { - return nullptr; + // Steps 2.f-g. + DateOptions resolvedOptions; + if (!ToTemporalDateOptions(cx, options, &resolvedOptions)) { + return false; } + auto [overflow] = resolvedOptions; - // Step 3.g. - if (maybeOptions) { - return temporal::CalendarDateFromFields(cx, calendar, fields, maybeOptions); - } - return temporal::CalendarDateFromFields(cx, calendar, fields); + // Steps 2.h-i. + return CalendarDateFromFields(cx, calendar, fields, overflow, result); } /** * ToTemporalDate ( item [ , options ] ) */ -static Wrapped ToTemporalDate( - JSContext* cx, Handle item, Handle maybeOptions) { +static bool ToTemporalDate(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { // Step 1. (Not applicable in our implementation.) // Step 2. - Rooted maybeResolvedOptions(cx); - if (maybeOptions) { - maybeResolvedOptions = SnapshotOwnProperties(cx, maybeOptions); - if (!maybeResolvedOptions) { - return nullptr; - } + if (item.isObject()) { + Rooted itemObj(cx, &item.toObject()); + return ToTemporalDate(cx, itemObj, options, result); } // Step 3. - if (item.isObject()) { - Rooted itemObj(cx, &item.toObject()); - return ::ToTemporalDate(cx, itemObj, maybeResolvedOptions); - } - - // Step 4. if (!item.isString()) { ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, nullptr, "not a string"); - return nullptr; + return false; } Rooted string(cx, item.toString()); - // Step 5. - PlainDate result; + // Step 4. + ISODateTime dateTime; Rooted calendarString(cx); - if (!ParseTemporalDateString(cx, string, &result, &calendarString)) { - return nullptr; + if (!ParseTemporalDateTimeString(cx, string, &dateTime, &calendarString)) { + return false; } + MOZ_ASSERT(IsValidISODate(dateTime.date)); - // Step 6. - MOZ_ASSERT(IsValidISODate(result)); - - // Steps 7-10. + // Steps 5-7. Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); if (calendarString) { - if (!ToBuiltinCalendar(cx, calendarString, &calendar)) { - return nullptr; + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; } } - // Step 11. - if (maybeResolvedOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return nullptr; - } + // Steps 8-9. + DateOptions ignoredOptions; + if (!ToTemporalDateOptions(cx, options, &ignoredOptions)) { + return false; } - // Step 12. - return CreateTemporalDate(cx, result, calendar); + // Steps 10-11. + return CreateTemporalDate(cx, dateTime.date, calendar, result); } /** * ToTemporalDate ( item [ , options ] ) */ -static Wrapped ToTemporalDate(JSContext* cx, - Handle item) { - return ::ToTemporalDate(cx, item, nullptr); +static bool ToTemporalDate(JSContext* cx, Handle item, + MutableHandle result) { + return ToTemporalDate(cx, item, UndefinedHandleValue, result); +} + +static bool IsValidISODateEpochMilliseconds(int64_t epochMilliseconds) { + // Epoch nanoseconds limits, adjusted to the range supported by ISODate. + constexpr auto oneDay = EpochDuration::fromDays(1); + constexpr auto min = EpochNanoseconds::min() - oneDay; + constexpr auto max = EpochNanoseconds::max() + oneDay; + + // NB: Minimum limit is inclusive, whereas maximim limit is exclusive. + auto epochNs = EpochNanoseconds::fromMilliseconds(epochMilliseconds); + return min <= epochNs && epochNs < max; } /** - * ToTemporalDate ( item [ , options ] ) + * BalanceISODate ( year, month, day ) */ -bool js::temporal::ToTemporalDate(JSContext* cx, Handle item, - PlainDate* result) { - auto obj = ::ToTemporalDate(cx, item, nullptr); - if (!obj) { - return false; - } +bool js::temporal::BalanceISODate(JSContext* cx, const ISODate& date, + int64_t days, ISODate* result) { + MOZ_ASSERT(IsValidISODate(date)); + MOZ_ASSERT(ISODateWithinLimits(date)); - *result = ToPlainDate(&obj.unwrap()); - return true; -} - -/** - * ToTemporalDate ( item [ , options ] ) - */ -bool js::temporal::ToTemporalDate(JSContext* cx, Handle item, - MutableHandle result) { - auto* obj = ::ToTemporalDate(cx, item, nullptr).unwrapOrNull(); - if (!obj) { - return false; - } - - auto date = ToPlainDate(obj); - Rooted calendar(cx, obj->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - result.set(PlainDateWithCalendar{date, calendar}); - return true; -} - -/** - * Mathematical Operations, "modulo" notation. - */ -static int32_t NonNegativeModulo(int64_t x, int32_t y) { - MOZ_ASSERT(y > 0); - - int32_t result = mozilla::AssertedCast(x % y); - return (result < 0) ? (result + y) : result; -} - -struct BalancedYearMonth final { - int64_t year = 0; - int32_t month = 0; -}; - -/** - * BalanceISOYearMonth ( year, month ) - */ -static BalancedYearMonth BalanceISOYearMonth(int64_t year, int64_t month) { - MOZ_ASSERT(std::abs(year) < (int64_t(1) << 33), - "year is the addition of plain-date year with duration years"); - MOZ_ASSERT(std::abs(month) < (int64_t(1) << 33), - "month is the addition of plain-date month with duration months"); - - // Step 1. (Not applicable in our implementation.) - - // Note: If either abs(year) or abs(month) is greater than 2^53 (the double - // integral precision limit), the additions resp. subtractions below are - // imprecise. This doesn't matter for us, because the single caller to this - // function (AddISODate) will throw an error for large values anyway. + // Step 1. + auto epochDays = MakeDay(date) + mozilla::CheckedInt64{days}; // Step 2. - int64_t balancedYear = year + temporal::FloorDiv(month - 1, 12); - - // Step 3. - int32_t balancedMonth = NonNegativeModulo(month - 1, 12) + 1; - MOZ_ASSERT(1 <= balancedMonth && balancedMonth <= 12); - - // Step 4. - return {balancedYear, balancedMonth}; -} - -static bool CanBalanceISOYear(int64_t year) { - // TODO: Export these values somewhere. - constexpr int32_t minYear = -271821; - constexpr int32_t maxYear = 275760; - - // If the year is below resp. above the min-/max-year, no value of |day| will - // make the resulting date valid. - return minYear <= year && year <= maxYear; -} - -static bool CanBalanceISODay(int64_t day) { - // The maximum number of seconds from the epoch is 8.64 * 10^12. - constexpr int64_t maxInstantSeconds = 8'640'000'000'000; - - // In days that makes 10^8. - constexpr int64_t maxInstantDays = maxInstantSeconds / 60 / 60 / 24; - - // Multiply by two to take both directions into account and add twenty to - // account for the day number of the minimum date "-271821-02-20". - constexpr int64_t maximumDayDifference = 2 * maxInstantDays + 20; - - // When |day| is below |maximumDayDifference|, it can be represented as int32. - static_assert(maximumDayDifference <= INT32_MAX); - - // When the day difference exceeds the maximum valid day difference, the - // overall result won't be a valid date. Detect this early so we don't have to - // struggle with floating point precision issues in BalanceISODate. - // - // This also means BalanceISODate, step 1 doesn't apply to our implementation. - return std::abs(day) <= maximumDayDifference; -} - -/** - * BalanceISODate ( year, month, day ) - */ -PlainDate js::temporal::BalanceISODateNew(int32_t year, int32_t month, - int32_t day) { - MOZ_ASSERT(1 <= month && month <= 12); - - // Steps 1-3. - double ms = double(MakeDate(year, month, day)); - - // TODO: Add ISODateToEpochDays & friends which handle larger inputs. - - // TODO: This approach isn't efficient, because MonthFromTime and DayFromTime - // both recompute YearFromTime. - - // Step 4. - return {int32_t(JS::YearFromTime(ms)), int32_t(JS::MonthFromTime(ms) + 1), - int32_t(JS::DayFromTime(ms))}; -} - -/** - * BalanceISODate ( year, month, day ) - */ -bool js::temporal::BalanceISODate(JSContext* cx, const PlainDate& date, - int64_t days, PlainDate* result) { - MOZ_ASSERT(IsValidISODate(date)); - MOZ_ASSERT(ISODateTimeWithinLimits(date)); - - int64_t day = int64_t(date.day) + days; - if (!CanBalanceISODay(day)) { + auto epochMilliseconds = epochDays * ToMilliseconds(TemporalUnit::Day); + if (!epochMilliseconds.isValid() || + !IsValidISODateEpochMilliseconds(epochMilliseconds.value())) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return false; } - *result = BalanceISODate(date.year, date.month, int32_t(day)); + // Step 3. + auto [year, month, day] = ToYearMonthDay(epochMilliseconds.value()); + + *result = ISODate{year, month + 1, day}; + MOZ_ASSERT(IsValidISODate(*result)); + MOZ_ASSERT(ISODateWithinLimits(*result)); + return true; } /** * BalanceISODate ( year, month, day ) */ -PlainDate js::temporal::BalanceISODate(int32_t year, int32_t month, - int32_t day) { - // Check no inputs can lead to floating point precision issues below. This - // also ensures all loops can finish in reasonable time, so we don't need to - // worry about interrupts here. And it ensures there won't be overflows when - // using int32_t values. - MOZ_ASSERT(CanBalanceISOYear(year)); - MOZ_ASSERT(1 <= month && month <= 12); - MOZ_ASSERT(CanBalanceISODay(day)); - - // TODO: BalanceISODate now works using ISODateToEpochDays & friends. - // TODO: Can't use JS::MakeDate, because it expects valid month/day values. - - // Step 1. (Not applicable in our implementation.) - - // Steps 3-4. (Not applicable in our implementation.) - - constexpr int32_t daysInNonLeapYear = 365; - - // Skip steps 5-11 for the common case when abs(day) doesn't exceed 365. - if (std::abs(day) > daysInNonLeapYear) { - // Step 5. (Note) - - // Steps 6-7. - int32_t testYear = month > 2 ? year : year - 1; - - // Step 8. - while (day < -ISODaysInYear(testYear)) { - // Step 8.a. - day += ISODaysInYear(testYear); - - // Step 8.b. - year -= 1; - - // Step 8.c. - testYear -= 1; - } - - // Step 9. (Note) - - // Step 10. - testYear += 1; - - // Step 11. - while (day > ISODaysInYear(testYear)) { - // Step 11.a. - day -= ISODaysInYear(testYear); - - // Step 11.b. - year += 1; - - // Step 11.c. - testYear += 1; - } - } - - // Step 12. (Note) - - // Step 13. - while (day < 1) { - // Steps 13.a-b. (Inlined call to BalanceISOYearMonth.) - if (--month == 0) { - month = 12; - year -= 1; - } - - // Step 13.d - day += ISODaysInMonth(year, month); - } - - // Step 14. (Note) - - // Step 15. - while (day > ISODaysInMonth(year, month)) { - // Step 15.a. - day -= ISODaysInMonth(year, month); - - // Steps 15.b-d. (Inlined call to BalanceISOYearMonth.) - if (++month == 13) { - month = 1; - year += 1; - } - } - - MOZ_ASSERT(1 <= month && month <= 12); - MOZ_ASSERT(1 <= day && day <= 31); - - // Step 16. - return {year, month, day}; -} - -/** - * AddISODate ( year, month, day, years, months, weeks, days, overflow ) - */ -bool js::temporal::AddISODate(JSContext* cx, const PlainDate& date, - const DateDuration& duration, - TemporalOverflow overflow, PlainDate* result) { +ISODate js::temporal::BalanceISODate(const ISODate& date, int32_t days) { MOZ_ASSERT(IsValidISODate(date)); - MOZ_ASSERT(ISODateTimeWithinLimits(date)); - - // TODO: Not quite sure if this holds for all callers. But if it does hold, - // then we can directly reject any numbers which can't be represented with - // int32_t. That in turn avoids the precision loss issue noted in - // BalanceISODate. - MOZ_ASSERT(IsValidDuration(duration)); - - // Steps 1-2. (Not applicable in our implementation.) - - // Step 3. - auto yearMonth = BalanceISOYearMonth(date.year + duration.years, - date.month + duration.months); - MOZ_ASSERT(1 <= yearMonth.month && yearMonth.month <= 12); - - // FIXME: spec issue? - // new Temporal.PlainDate(2021, 5, 31).subtract({months:1, days:1}).toString() - // returns "2021-04-29", but "2021-04-30" seems more likely expected. - // Note: "2021-04-29" agrees with java.time, though. - // - // Example where this creates inconsistent results: - // - // clang-format off - // - // js> Temporal.PlainDate.from("2021-05-31").since("2021-04-30", {largestUnit:"months"}).toString() - // "P1M1D" - // js> Temporal.PlainDate.from("2021-05-31").subtract("P1M1D").toString() - // "2021-04-29" - // - // clang-format on - // - // Later: This now returns "P1M" instead "P1M1D", so the results are at least - // consistent. Let's add a test case for this behaviour. - // - // Revisit when has - // been addressed. - - // |yearMonth.year| can only exceed the valid years range when called from - // `Temporal.Calendar.prototype.dateAdd`. And because `dateAdd` uses the - // result of AddISODate to create a new Temporal.PlainDate, we can directly - // throw an error if the result isn't within the valid date-time limits. This - // in turn allows to work on integer values and we don't have to worry about - // imprecise double value computations. - if (!CanBalanceISOYear(yearMonth.year)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_DATE_INVALID); - return false; - } - - // Step 4. - PlainDate regulated; - if (!RegulateISODate(cx, {int32_t(yearMonth.year), yearMonth.month, date.day}, - overflow, ®ulated)) { - return false; - } - - // NB: BalanceISODate will reject too large days, so we don't have to worry - // about imprecise number arithmetic here. - - // Steps 5-6. - int64_t d = regulated.day + (duration.days + duration.weeks * 7); - - // Just as with |yearMonth.year|, also directly throw an error if the |days| - // value is too large. - if (!CanBalanceISODay(d)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_DATE_INVALID); - return false; - } - - // Step 7. - auto balanced = BalanceISODate(regulated.year, regulated.month, int32_t(d)); - MOZ_ASSERT(IsValidISODate(balanced)); - - *result = balanced; - return true; -} - -struct YearMonthDuration { - int32_t years = 0; - int32_t months = 0; -}; - -/** - * AddISODate ( year, month, day, years, months, weeks, days, overflow ) - * - * With |overflow = "constrain"|. - */ -static PlainDate AddISODate(const PlainDate& date, - const YearMonthDuration& duration) { - MOZ_ASSERT(IsValidISODate(date)); - MOZ_ASSERT(ISODateTimeWithinLimits(date)); - - MOZ_ASSERT_IF(duration.years < 0, duration.months <= 0); - MOZ_ASSERT_IF(duration.years > 0, duration.months >= 0); - - // TODO: Export these values somewhere. - [[maybe_unused]] constexpr int32_t minYear = -271821; - [[maybe_unused]] constexpr int32_t maxYear = 275760; - - MOZ_ASSERT(std::abs(duration.years) <= (maxYear - minYear), - "years doesn't exceed the maximum duration between valid years"); - MOZ_ASSERT(std::abs(duration.months) <= 12, - "months duration is at most one year"); - - // Steps 1-2. (Not applicable) - - // Step 3. (Inlined BalanceISOYearMonth) - int32_t year = date.year + duration.years; - int32_t month = date.month + duration.months; - MOZ_ASSERT(-11 <= month && month <= 24); - - if (month > 12) { - month -= 12; - year += 1; - } else if (month <= 0) { - month += 12; - year -= 1; - } - - MOZ_ASSERT(1 <= month && month <= 12); - MOZ_ASSERT(CanBalanceISOYear(year)); - - // Steps 4-7. - return ::ConstrainISODate({year, month, date.day}); -} - -static bool HasYearsMonthsOrWeeks(const Duration& duration) { - return duration.years != 0 || duration.months != 0 || duration.weeks != 0; -} - -static bool HasYearsMonthsOrWeeks(const DateDuration& duration) { - return duration.years != 0 || duration.months != 0 || duration.weeks != 0; -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -static bool AddDate(JSContext* cx, const PlainDate& date, - const NormalizedDuration& duration, - TemporalOverflow overflow, PlainDate* result) { - MOZ_ASSERT(!HasYearsMonthsOrWeeks(duration.date)); - MOZ_ASSERT(IsValidDuration(duration)); - - // Steps 1-4. (Not applicable) - - // Step 5. (Not applicable) - const auto& timeDuration = duration.time; - - // Step 6. - int64_t balancedDays = - BalanceTimeDuration(timeDuration, TemporalUnit::Day).days; - int64_t days = duration.date.days + balancedDays; - - // Step 7. - return AddISODate(cx, date, {0, 0, 0, days}, overflow, result); -} - -static bool AddDate(JSContext* cx, Handle> date, - const NormalizedDuration& duration, - TemporalOverflow overflow, PlainDate* result) { - auto* unwrappedDate = date.unwrap(cx); - if (!unwrappedDate) { - return false; - } - return ::AddDate(cx, ToPlainDate(unwrappedDate), duration, overflow, result); -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -static Wrapped AddDate(JSContext* cx, - Handle calendar, - Handle> date, - const Duration& duration, - Handle options) { - // Step 1. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 2. (Not applicable in our implementation.) - - // Step 3. - if (HasYearsMonthsOrWeeks(duration)) { - return temporal::CalendarDateAdd(cx, calendar, date, duration, options); - } - - // Step 4. - auto overflow = TemporalOverflow::Constrain; - if (!GetTemporalOverflowOption(cx, options, &overflow)) { - return nullptr; - } - - // Step 5. - auto normalized = CreateNormalizedDurationRecord(duration); - - // Steps 6-7. - PlainDate resultDate; - if (!::AddDate(cx, date, normalized, overflow, &resultDate)) { - return nullptr; - } - - // Step 8. - return CreateTemporalDate(cx, resultDate, calendar.receiver()); -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -Wrapped js::temporal::AddDate( - JSContext* cx, Handle calendar, - Handle> date, const DateDuration& duration) { - // Step 1. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 2. (Not applicable in our implementation.) - - // Step 3. - if (HasYearsMonthsOrWeeks(duration)) { - return CalendarDateAdd(cx, calendar, date, duration); - } - - // Step 4. - auto overflow = TemporalOverflow::Constrain; - - // Step 5. - auto normalized = NormalizedDuration{duration}; - - // Steps 6-7. - PlainDate resultDate; - if (!::AddDate(cx, date, normalized, overflow, &resultDate)) { - return nullptr; - } - - // Step 8. - return CreateTemporalDate(cx, resultDate, calendar.receiver()); -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -Wrapped js::temporal::AddDate( - JSContext* cx, Handle calendar, - Handle> date, const DateDuration& duration, - Handle options) { - return ::AddDate(cx, calendar, date, duration.toDuration(), options); -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -static Wrapped AddDate( - JSContext* cx, Handle calendar, - Handle> date, - Handle> durationObj, Handle options) { - auto* unwrappedDuration = durationObj.unwrap(cx); - if (!unwrappedDuration) { - return nullptr; - } - auto duration = ToDuration(unwrappedDuration); + MOZ_ASSERT(ISODateWithinLimits(date)); + MOZ_ASSERT(std::abs(days) <= 400'000'000, "days limit for ToYearMonthDay"); // Step 1. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); + int32_t epochDays = MakeDay(date) + days; - // Step 2. (Not applicable in our implementation.) + // Step 2. + int64_t epochMilliseconds = epochDays * ToMilliseconds(TemporalUnit::Day); // Step 3. - if (HasYearsMonthsOrWeeks(duration)) { - return temporal::CalendarDateAdd(cx, calendar, date, durationObj, options); - } + auto [year, month, day] = ToYearMonthDay(epochMilliseconds); - // Step 4. - auto overflow = TemporalOverflow::Constrain; - if (!GetTemporalOverflowOption(cx, options, &overflow)) { - return nullptr; - } + // NB: The returned date is possibly outside the valid limits! + auto result = ISODate{year, month + 1, day}; + MOZ_ASSERT(IsValidISODate(result)); - // Step 5. - auto normalized = CreateNormalizedDurationRecord(duration); - - // Steps 6-7. - PlainDate resultDate; - if (!::AddDate(cx, date, normalized, overflow, &resultDate)) { - return nullptr; - } - - // Step 8. - return CreateTemporalDate(cx, resultDate, calendar.receiver()); -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -bool js::temporal::AddDate(JSContext* cx, Handle calendar, - const PlainDate& date, const DateDuration& duration, - Handle options, PlainDate* result) { - // Step 1. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 2. (Not applicable in our implementation.) - - // Step 3. - if (HasYearsMonthsOrWeeks(duration)) { - return temporal::CalendarDateAdd(cx, calendar, date, duration, options, - result); - } - - // Step 4. - auto overflow = TemporalOverflow::Constrain; - if (!GetTemporalOverflowOption(cx, options, &overflow)) { - return false; - } - - // Step 5. - auto normalized = NormalizedDuration{duration}; - - // Steps 5-8. - return ::AddDate(cx, date, normalized, overflow, result); -} - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -bool js::temporal::AddDate(JSContext* cx, Handle calendar, - Handle> date, - const DateDuration& duration, PlainDate* result) { - // Step 1. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 2. (Not applicable in our implementation.) - - // Step 3. - if (HasYearsMonthsOrWeeks(duration)) { - return CalendarDateAdd(cx, calendar, date, duration, result); - } - - // Step 4. - auto overflow = TemporalOverflow::Constrain; - - // Step 5. - auto normalized = NormalizedDuration{duration}; - - // Steps 6-8. - return ::AddDate(cx, date, normalized, overflow, result); -} - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool js::temporal::DifferenceDate(JSContext* cx, - Handle calendar, - Handle> one, - Handle> two, - TemporalUnit largestUnit, - Handle options, - DateDuration* result) { - auto* unwrappedOne = one.unwrap(cx); - if (!unwrappedOne) { - return false; - } - auto oneDate = ToPlainDate(unwrappedOne); - - auto* unwrappedTwo = two.unwrap(cx); - if (!unwrappedTwo) { - return false; - } - auto twoDate = ToPlainDate(unwrappedTwo); - - // Steps 1-2. (Not applicable in our implementation.) - - // Step 3. - MOZ_ASSERT(options->staticPrototype() == nullptr); - - // Step 4. (Not applicable in our implementation.) - - // Step 5. - if (oneDate == twoDate) { - *result = {}; - return true; - } - - // Step 6. - if (largestUnit == TemporalUnit::Day) { - // Step 6.a. - int32_t days = DaysUntil(oneDate, twoDate); - - // Step 6.b. - *result = {0, 0, 0, days}; - return true; - } - - // Step 7. - return CalendarDateUntil(cx, calendar, one, two, largestUnit, options, - result); -} - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool js::temporal::DifferenceDate(JSContext* cx, - Handle calendar, - Handle> one, - Handle> two, - TemporalUnit largestUnit, - DateDuration* result) { - auto* unwrappedOne = one.unwrap(cx); - if (!unwrappedOne) { - return false; - } - auto oneDate = ToPlainDate(unwrappedOne); - - auto* unwrappedTwo = two.unwrap(cx); - if (!unwrappedTwo) { - return false; - } - auto twoDate = ToPlainDate(unwrappedTwo); - - // Steps 1-4. (Not applicable in our implementation.) - - // Step 5. - if (oneDate == twoDate) { - *result = {}; - return true; - } - - // Step 6. - if (largestUnit == TemporalUnit::Day) { - // Step 6.a. - int32_t days = DaysUntil(oneDate, twoDate); - - // Step 6.b. - *result = {0, 0, 0, days}; - return true; - } - - // Step 7. - return CalendarDateUntil(cx, calendar, one, two, largestUnit, result); -} - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool js::temporal::DifferenceDate(JSContext* cx, - Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, - Handle options, - DateDuration* result) { - // Steps 1-4. (Not applicable in our implementation.) - - // Step 5. - if (one == two) { - *result = {}; - return true; - } - - // Step 6. - if (largestUnit == TemporalUnit::Day) { - // Step 6.a. - int32_t days = DaysUntil(one, two); - - // Step 6.b. - *result = {0, 0, 0, days}; - return true; - } - - // Step 7. - return CalendarDateUntil(cx, calendar, one, two, largestUnit, options, - result); -} - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool js::temporal::DifferenceDate(JSContext* cx, - Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, - DateDuration* result) { - // Steps 1-4. (Not applicable in our implementation.) - - // Step 5. - if (one == two) { - *result = {}; - return true; - } - - // Step 6. - if (largestUnit == TemporalUnit::Day) { - // Step 6.a. - int32_t days = DaysUntil(one, two); - - // Step 6.b. - *result = {0, 0, 0, days}; - return true; - } - - // Step 7. - return CalendarDateUntil(cx, calendar, one, two, largestUnit, result); + return result; } /** * CompareISODate ( y1, m1, d1, y2, m2, d2 ) */ -int32_t js::temporal::CompareISODate(const PlainDate& one, - const PlainDate& two) { +int32_t js::temporal::CompareISODate(const ISODate& one, const ISODate& two) { // Steps 1-2. if (one.year != two.year) { return one.year < two.year ? -1 : 1; @@ -1334,258 +567,34 @@ int32_t js::temporal::CompareISODate(const PlainDate& one, return 0; } -/** - * CreateDateDurationRecord ( years, months, weeks, days ) - */ -static DateDuration CreateDateDurationRecord(int32_t years, int32_t months, - int32_t weeks, int32_t days) { - MOZ_ASSERT(IsValidDuration( - Duration{double(years), double(months), double(weeks), double(days)})); - return {years, months, weeks, days}; -} - -/** - * DifferenceISODate ( y1, m1, d1, y2, m2, d2, largestUnit ) - */ -DateDuration js::temporal::DifferenceISODate(const PlainDate& start, - const PlainDate& end, - TemporalUnit largestUnit) { - // Steps 1-2. - MOZ_ASSERT(IsValidISODate(start)); - MOZ_ASSERT(IsValidISODate(end)); - - // Both inputs are also within the date-time limits. - MOZ_ASSERT(ISODateTimeWithinLimits(start)); - MOZ_ASSERT(ISODateTimeWithinLimits(end)); - - // Because both inputs are valid dates, we don't need to worry about integer - // overflow in any of the computations below. - - MOZ_ASSERT(TemporalUnit::Year <= largestUnit && - largestUnit <= TemporalUnit::Day); - - // Step 3. - if (largestUnit == TemporalUnit::Year || largestUnit == TemporalUnit::Month) { - // Step 3.a. - int32_t sign = -CompareISODate(start, end); - - // Step 3.b. - if (sign == 0) { - return CreateDateDurationRecord(0, 0, 0, 0); - } - - // FIXME: spec issue - results can be ambiguous, is this intentional? - // https://github.com/tc39/proposal-temporal/issues/2535 - // - // clang-format off - // js> var end = new Temporal.PlainDate(1970, 2, 28) - // js> var start = new Temporal.PlainDate(1970, 1, 28) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P1M" - // js> var start = new Temporal.PlainDate(1970, 1, 29) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P1M" - // js> var start = new Temporal.PlainDate(1970, 1, 30) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P1M" - // js> var start = new Temporal.PlainDate(1970, 1, 31) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P1M" - // - // Compare to java.time.temporal - // - // jshell> import java.time.LocalDate - // jshell> var end = LocalDate.of(1970, 2, 28) - // end ==> 1970-02-28 - // jshell> var start = LocalDate.of(1970, 1, 28) - // start ==> 1970-01-28 - // jshell> start.until(end) - // $27 ==> P1M - // jshell> var start = LocalDate.of(1970, 1, 29) - // start ==> 1970-01-29 - // jshell> start.until(end) - // $29 ==> P30D - // jshell> var start = LocalDate.of(1970, 1, 30) - // start ==> 1970-01-30 - // jshell> start.until(end) - // $31 ==> P29D - // jshell> var start = LocalDate.of(1970, 1, 31) - // start ==> 1970-01-31 - // jshell> start.until(end) - // $33 ==> P28D - // - // Also compare to: - // - // js> var end = new Temporal.PlainDate(1970, 2, 27) - // js> var start = new Temporal.PlainDate(1970, 1, 27) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P1M" - // js> var start = new Temporal.PlainDate(1970, 1, 28) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P30D" - // js> var start = new Temporal.PlainDate(1970, 1, 29) - // js> start.calendar.dateUntil(start, end, {largestUnit:"months"}).toString() - // "P29D" - // - // clang-format on - - // Steps 3.c-d. (Not applicable in our implementation.) - - // FIXME: spec issue - consistently use either |end.[[Year]]| or |y2|. - - // Step 3.e. - int32_t years = end.year - start.year; - - // TODO: We could inline this, because the AddISODate call is just a more - // complicated way to perform: - // mid = ConstrainISODate(end.year, start.month, start.day) - // - // The remaining computations can probably simplified similarily. - - // Step 3.f. - auto mid = ::AddISODate(start, {years, 0}); - - // Step 3.g. - int32_t midSign = -CompareISODate(mid, end); - - // Step 3.h. - if (midSign == 0) { - // Step 3.h.i. - if (largestUnit == TemporalUnit::Year) { - return CreateDateDurationRecord(years, 0, 0, 0); - } - - // Step 3.h.ii. - return CreateDateDurationRecord(0, years * 12, 0, 0); - } - - // Step 3.i. - int32_t months = end.month - start.month; - - // Step 3.j. - if (midSign != sign) { - // Step 3.j.i. - years -= sign; - - // Step 3.j.ii. - months += sign * 12; - } - - // Step 3.k. - mid = ::AddISODate(start, {years, months}); - - // Step 3.l. - midSign = -CompareISODate(mid, end); - - // Step 3.m. - if (midSign == 0) { - // Step 3.m.i. - if (largestUnit == TemporalUnit::Year) { - return CreateDateDurationRecord(years, months, 0, 0); - } - - // Step 3.m.ii. - return CreateDateDurationRecord(0, months + years * 12, 0, 0); - } - - // Step 3.n. - if (midSign != sign) { - // Step 3.n.i. - months -= sign; - - // Step 3.n.ii. - mid = ::AddISODate(start, {years, months}); - } - - // Steps 3.o-q. - int32_t days; - if (mid.month == end.month) { - MOZ_ASSERT(mid.year == end.year); - - days = end.day - mid.day; - } else if (sign < 0) { - days = -mid.day - (ISODaysInMonth(end.year, end.month) - end.day); - } else { - days = end.day + (ISODaysInMonth(mid.year, mid.month) - mid.day); - } - - // Step 3.r. - if (largestUnit == TemporalUnit::Month) { - // Step 3.r.i. - months += years * 12; - - // Step 3.r.ii. - years = 0; - } - - // Step 3.s. - return CreateDateDurationRecord(years, months, 0, days); - } - - // Step 4.a. - MOZ_ASSERT(largestUnit == TemporalUnit::Week || - largestUnit == TemporalUnit::Day); - - // Step 4.b. - int32_t epochDaysStart = MakeDay(start); - - // Step 4.c. - int32_t epochDaysEnd = MakeDay(end); - - // Step 4.d. - int32_t days = epochDaysEnd - epochDaysStart; - - // Step 4.e. - int32_t weeks = 0; - - // Step 4.f. - if (largestUnit == TemporalUnit::Week) { - // Step 4.f.i - weeks = days / 7; - - // Step 4.f.ii. - days = days % 7; - } - - // Step 4.g. - return CreateDateDurationRecord(0, 0, weeks, days); -} - /** * DifferenceTemporalPlainDate ( operation, temporalDate, other, options ) */ static bool DifferenceTemporalPlainDate(JSContext* cx, TemporalDifference operation, const CallArgs& args) { - Rooted temporalDate( + Rooted temporalDate( cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, temporalDate->calendar()); - // Step 1. (Not applicable in our implementation) + // Step 1. + Rooted other(cx); + if (!ToTemporalDate(cx, args.get(0), &other)) { + return false; + } // Step 2. - auto wrappedOther = ::ToTemporalDate(cx, args.get(0)); - if (!wrappedOther) { - return false; - } - auto* unwrappedOther = &wrappedOther.unwrap(); - auto otherDate = ToPlainDate(unwrappedOther); - - Rooted> other(cx, wrappedOther); - Rooted otherCalendar(cx, unwrappedOther->calendar()); - if (!otherCalendar.wrap(cx)) { + if (!CalendarEquals(temporalDate.calendar(), other.calendar())) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(temporalDate.calendar()).data(), + CalendarIdentifier(other.calendar()).data()); return false; } - // Step 3. - if (!CalendarEqualsOrThrow(cx, calendarValue, otherCalendar)) { - return false; - } - - // Steps 4-5. + // Steps 3-4. DifferenceSettings settings; - Rooted resolvedOptions(cx); if (args.hasDefined(1)) { + // Step 3. Rooted options( cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); if (!options) { @@ -1593,19 +602,13 @@ static bool DifferenceTemporalPlainDate(JSContext* cx, } // Step 4. - resolvedOptions = SnapshotOwnProperties(cx, options); - if (!resolvedOptions) { - return false; - } - - // Step 5. - if (!GetDifferenceSettings(cx, operation, resolvedOptions, - TemporalUnitGroup::Date, TemporalUnit::Day, - TemporalUnit::Day, &settings)) { + if (!GetDifferenceSettings(cx, operation, options, TemporalUnitGroup::Date, + TemporalUnit::Day, TemporalUnit::Day, + &settings)) { return false; } } else { - // Steps 4-5. + // Steps 3-4. settings = { TemporalUnit::Day, TemporalUnit::Day, @@ -1614,8 +617,8 @@ static bool DifferenceTemporalPlainDate(JSContext* cx, }; } - // Step 6. - if (ToPlainDate(temporalDate) == otherDate) { + // Step 5. + if (temporalDate.date() == other.date()) { auto* obj = CreateTemporalDuration(cx, {}); if (!obj) { return false; @@ -1625,66 +628,52 @@ static bool DifferenceTemporalPlainDate(JSContext* cx, return true; } - // Step 7. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateAdd, - CalendarMethod::DateUntil, - }, - &calendar)) { + // Step 6. + DateDuration dateDifference; + if (!CalendarDateUntil(cx, temporalDate.calendar(), temporalDate.date(), + other.date(), settings.largestUnit, &dateDifference)) { return false; } - // Steps 8-9. - DateDuration difference; - if (resolvedOptions) { - // Steps 8-9. - if (!DifferenceDate(cx, calendar, temporalDate, other, settings.largestUnit, - resolvedOptions, &difference)) { + // Step 7. + auto duration = InternalDuration{dateDifference, {}}; + + // Step 8. + if (settings.smallestUnit != TemporalUnit::Day || + settings.roundingIncrement != Increment{1}) { + // Step 8.a. + auto isoDateTime = ISODateTime{temporalDate.date(), {}}; + + // Step 8.b. + auto isoDateTimeOther = ISODateTime{other.date(), {}}; + + // Step 8.c. + auto destEpochNs = GetUTCEpochNanoseconds(isoDateTimeOther); + + // Step 8.d. + Rooted timeZone(cx, TimeZoneValue{}); + if (!RoundRelativeDuration(cx, duration, destEpochNs, isoDateTime, timeZone, + temporalDate.calendar(), settings.largestUnit, + settings.roundingIncrement, + settings.smallestUnit, settings.roundingMode, + &duration)) { return false; } - } else { - // Steps 8-9. - if (!DifferenceDate(cx, calendar, temporalDate, other, settings.largestUnit, - &difference)) { - return false; - } - } - - // Step 10. - bool roundingGranularityIsNoop = settings.smallestUnit == TemporalUnit::Day && - settings.roundingIncrement == Increment{1}; - - // Step 11. - if (!roundingGranularityIsNoop) { - // Steps 11.a-b. - NormalizedDuration roundResult; - if (!temporal::RoundDuration(cx, {difference, {}}, - settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode, - temporalDate, calendar, &roundResult)) { - return false; - } - - // Step 11.c. - DateDuration balanceResult; - if (!temporal::BalanceDateDurationRelative( - cx, roundResult.date, settings.largestUnit, settings.smallestUnit, - temporalDate, calendar, &balanceResult)) { - return false; - } - difference = balanceResult; - } - - // Step 12. - auto duration = difference.toDuration(); - if (operation == TemporalDifference::Since) { - duration = duration.negate(); } MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT(duration.time == TimeDuration{}); - auto* obj = CreateTemporalDuration(cx, duration); + // Step 9. (Inlined TemporalDurationFromInternal) + auto result = duration.date.toDuration(); + + // Step 10. + if (operation == TemporalDifference::Since) { + result = result.negate(); + } + MOZ_ASSERT(IsValidDuration(result)); + + // Step 11. + auto* obj = CreateTemporalDuration(cx, result); if (!obj) { return false; } @@ -1694,7 +683,65 @@ static bool DifferenceTemporalPlainDate(JSContext* cx, } /** - * Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ) + * AddDurationToDate ( operation, temporalDate, temporalDurationLike, options ) + */ +static bool AddDurationToDate(JSContext* cx, TemporalAddDuration operation, + const CallArgs& args) { + Rooted temporalDate( + cx, &args.thisv().toObject().as()); + + // Step 1. + auto calendar = temporalDate.calendar(); + + // Step 2. + Duration duration; + if (!ToTemporalDuration(cx, args.get(0), &duration)) { + return false; + } + + // Step 3. + if (operation == TemporalAddDuration::Subtract) { + duration = duration.negate(); + } + + // Step 4. + auto dateDuration = ToDateDurationRecordWithoutTime(duration); + + // Steps 6-7. + auto overflow = TemporalOverflow::Constrain; + if (args.hasDefined(1)) { + // Step 6. + Rooted options( + cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); + if (!options) { + return false; + } + + // Step 7. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } + } + + // Step 8. + ISODate result; + if (!CalendarDateAdd(cx, calendar, temporalDate.date(), dateDuration, + overflow, &result)) { + return false; + } + + // Step 9. + auto* obj = CreateTemporalDate(cx, result, calendar); + if (!obj) { + return false; + } + + args.rval().setObject(*obj); + return true; +} + +/** + * Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendar ] ) */ static bool PlainDateConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1722,15 +769,33 @@ static bool PlainDateConstructor(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 5. - Rooted calendar(cx); - if (!ToTemporalCalendarWithISODefault(cx, args.get(3), &calendar)) { + // Steps 5-7. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (args.hasDefined(3)) { + // Step 6. + if (!args[3].isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args[3], + nullptr, "not a string"); + return false; + } + + // Step 7. + Rooted calendarString(cx, args[3].toString()); + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } + } + + // Step 8. + if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { return false; } - // Step 6. - auto* temporalDate = - CreateTemporalDate(cx, args, isoYear, isoMonth, isoDay, calendar); + // Step 9. + auto isoDate = ISODate{int32_t(isoYear), int32_t(isoMonth), int32_t(isoDay)}; + + // Step 10. + auto* temporalDate = CreateTemporalDate(cx, args, isoDate, calendar); if (!temporalDate) { return false; } @@ -1746,46 +811,12 @@ static bool PlainDate_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "from", args[1]); - if (!options) { - return false; - } + Rooted date(cx); + if (!ToTemporalDate(cx, args.get(0), args.get(1), &date)) { + return false; } - // Step 2. - if (args.get(0).isObject()) { - JSObject* item = &args[0].toObject(); - if (auto* temporalDate = item->maybeUnwrapIf()) { - auto date = ToPlainDate(temporalDate); - - Rooted calendar(cx, temporalDate->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - if (options) { - // Step 2.a. - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, options, &ignored)) { - return false; - } - } - - // Step 2.b. - auto* result = CreateTemporalDate(cx, date, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; - } - } - - // Step 3. - auto result = ToTemporalDate(cx, args.get(0), options); + auto* result = CreateTemporalDate(cx, date); if (!result) { return false; } @@ -1801,13 +832,13 @@ static bool PlainDate_compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - PlainDate one; + Rooted one(cx); if (!ToTemporalDate(cx, args.get(0), &one)) { return false; } // Step 2. - PlainDate two; + Rooted two(cx); if (!ToTemporalDate(cx, args.get(1), &two)) { return false; } @@ -1822,15 +853,15 @@ static bool PlainDate_compare(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDate_calendarId(JSContext* cx, const CallArgs& args) { auto* temporalDate = &args.thisv().toObject().as(); - Rooted calendar(cx, temporalDate->calendar()); // Step 3. - auto* calendarId = ToTemporalCalendarIdentifier(cx, calendar); - if (!calendarId) { + auto* str = + NewStringCopy(cx, CalendarIdentifier(temporalDate->calendar())); + if (!str) { return false; } - args.rval().setString(calendarId); + args.rval().setString(str); return true; } @@ -1847,13 +878,11 @@ static bool PlainDate_calendarId(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.era */ static bool PlainDate_era(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarEra(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarEra(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -1869,13 +898,11 @@ static bool PlainDate_era(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.eraYear */ static bool PlainDate_eraYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Steps 4-6. - return CalendarEraYear(cx, calendar, temporalDate, args.rval()); + // Steps 3-5. + return CalendarEraYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -1891,13 +918,11 @@ static bool PlainDate_eraYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.year */ static bool PlainDate_year(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarYear(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -1913,13 +938,11 @@ static bool PlainDate_year(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.month */ static bool PlainDate_month(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarMonth(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarMonth(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -1935,13 +958,11 @@ static bool PlainDate_month(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.monthCode */ static bool PlainDate_monthCode(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarMonthCode(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarMonthCode(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -1957,13 +978,11 @@ static bool PlainDate_monthCode(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.day */ static bool PlainDate_day(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarDay(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarDay(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -1979,13 +998,11 @@ static bool PlainDate_day(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.dayOfWeek */ static bool PlainDate_dayOfWeek(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarDayOfWeek(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarDayOfWeek(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2001,13 +1018,11 @@ static bool PlainDate_dayOfWeek(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.dayOfYear */ static bool PlainDate_dayOfYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarDayOfYear(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarDayOfYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2023,13 +1038,11 @@ static bool PlainDate_dayOfYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.weekOfYear */ static bool PlainDate_weekOfYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Steps 4-6. - return CalendarWeekOfYear(cx, calendar, temporalDate, args.rval()); + // Steps 3-5. + return CalendarWeekOfYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2045,13 +1058,11 @@ static bool PlainDate_weekOfYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.yearOfWeek */ static bool PlainDate_yearOfWeek(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Steps 4-6. - return CalendarYearOfWeek(cx, calendar, temporalDate, args.rval()); + // Steps 3-5. + return CalendarYearOfWeek(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2067,13 +1078,11 @@ static bool PlainDate_yearOfWeek(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.daysInWeek */ static bool PlainDate_daysInWeek(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarDaysInWeek(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarDaysInWeek(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2089,13 +1098,11 @@ static bool PlainDate_daysInWeek(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.daysInMonth */ static bool PlainDate_daysInMonth(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarDaysInMonth(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarDaysInMonth(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2111,13 +1118,11 @@ static bool PlainDate_daysInMonth(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.daysInYear */ static bool PlainDate_daysInYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarDaysInYear(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarDaysInYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2133,13 +1138,11 @@ static bool PlainDate_daysInYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.monthsInYear */ static bool PlainDate_monthsInYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarMonthsInYear(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarMonthsInYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2155,13 +1158,11 @@ static bool PlainDate_monthsInYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDate.prototype.inLeapYear */ static bool PlainDate_inLeapYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted temporalDate( - cx, &args.thisv().toObject().as()); + auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); - // Step 4. - return CalendarInLeapYear(cx, calendar, temporalDate, args.rval()); + // Step 3. + return CalendarInLeapYear(cx, calendar, temporalDate->date(), args.rval()); } /** @@ -2177,32 +1178,27 @@ static bool PlainDate_inLeapYear(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainDate.prototype.toPlainYearMonth ( ) */ static bool PlainDate_toPlainYearMonth(JSContext* cx, const CallArgs& args) { - Rooted temporalDate( + Rooted temporalDate( cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, temporalDate->calendar()); // Step 3. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return false; - } + auto calendar = temporalDate.calendar(); // Step 4. - Rooted fields( - cx, - PrepareCalendarFields(cx, calendar, temporalDate, - {CalendarField::MonthCode, CalendarField::Year})); - if (!fields) { + Rooted fields(cx); + if (!ISODateToFields(cx, temporalDate, &fields)) { return false; } - // Steps 5-6. - auto obj = CalendarYearMonthFromFields(cx, calendar, fields); + // Step 5. + Rooted result(cx); + if (!CalendarYearMonthFromFields(cx, calendar, fields, + TemporalOverflow::Constrain, &result)) { + return false; + } + + // Steps 6-7. + auto* obj = CreateTemporalYearMonth(cx, result); if (!obj) { return false; } @@ -2226,70 +1222,27 @@ static bool PlainDate_toPlainYearMonth(JSContext* cx, unsigned argc, * Temporal.PlainDate.prototype.toPlainMonthDay ( ) */ static bool PlainDate_toPlainMonthDay(JSContext* cx, const CallArgs& args) { - Rooted temporalDate( + Rooted temporalDate( cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, temporalDate->calendar()); - - // Example for the optimisation described in TemporalFields.cpp - - // Optimization for built-in objects. - do { - // Step 4. - static constexpr std::initializer_list fieldNames = { - CalendarField::Day, CalendarField::MonthCode}; - - // Step 5. - if (calendarValue.isObject()) { - Rooted calendarObj(cx, calendarValue.toObject()); - if (!calendarObj->is()) { - break; - } - auto builtinCalendar = calendarObj.as(); - - // Step 5. - if (!IsBuiltinAccess(cx, builtinCalendar, fieldNames)) { - break; - } - } - if (!IsBuiltinAccess(cx, temporalDate, fieldNames)) { - break; - } - - // Step 6. - auto date = ToPlainDate(temporalDate); - auto result = PlainDate{1972 /* referenceISOYear */, date.month, date.day}; - - auto* obj = CreateTemporalMonthDay(cx, result, calendarValue); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; - } while (false); // Step 3. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::MonthDayFromFields, - }, - &calendar)) { - return false; - } + auto calendar = temporalDate.calendar(); // Step 4. - Rooted fields( - cx, - PrepareCalendarFields(cx, calendar, temporalDate, - {CalendarField::Day, CalendarField::MonthCode})); - if (!fields) { + Rooted fields(cx); + if (!ISODateToFields(cx, temporalDate, &fields)) { return false; } - // Steps 5-6. - auto obj = CalendarMonthDayFromFields(cx, calendar, fields); + // Step 5. + Rooted result(cx); + if (!CalendarMonthDayFromFields(cx, calendar, fields, + TemporalOverflow::Constrain, &result)) { + return false; + } + + // Steps 6-7. + auto* obj = CreateTemporalMonthDay(cx, result); if (!obj) { return false; } @@ -2314,18 +1267,22 @@ static bool PlainDate_toPlainDateTime(JSContext* cx, const CallArgs& args) { auto* temporalDate = &args.thisv().toObject().as(); Rooted calendar(cx, temporalDate->calendar()); + // Step 4. (Reordered) + // // Default initialize the time component to all zero. - PlainDateTime dateTime = {ToPlainDate(temporalDate), {}}; + auto isoDateTime = ISODateTime{temporalDate->date(), {}}; // Step 3. (Inlined ToTemporalTimeOrMidnight) if (args.hasDefined(0)) { - if (!ToTemporalTime(cx, args[0], &dateTime.time)) { + if (!ToTemporalTime(cx, args[0], &isoDateTime.time)) { return false; } } - // Step 4. - auto* obj = CreateTemporalDateTime(cx, dateTime, calendar); + // Step 4. (Moved above) + + // Step 5. + auto* obj = CreateTemporalDateTime(cx, isoDateTime, calendar); if (!obj) { return false; } @@ -2343,132 +1300,12 @@ static bool PlainDate_toPlainDateTime(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -/** - * Temporal.PlainDate.prototype.getISOFields ( ) - */ -static bool PlainDate_getISOFields(JSContext* cx, const CallArgs& args) { - auto* temporalDate = &args.thisv().toObject().as(); - auto date = ToPlainDate(temporalDate); - auto calendar = temporalDate->calendar(); - - // Step 3. - Rooted fields(cx, IdValueVector(cx)); - - // Step 4. - Rooted cal(cx); - if (!ToTemporalCalendar(cx, calendar, &cal)) { - return false; - } - if (!fields.emplaceBack(NameToId(cx->names().calendar), cal)) { - return false; - } - - // Step 5. - if (!fields.emplaceBack(NameToId(cx->names().isoDay), Int32Value(date.day))) { - return false; - } - - // Step 6. - if (!fields.emplaceBack(NameToId(cx->names().isoMonth), - Int32Value(date.month))) { - return false; - } - - // Step 7. - if (!fields.emplaceBack(NameToId(cx->names().isoYear), - Int32Value(date.year))) { - return false; - } - - // Step 8. - auto* obj = NewPlainObjectWithUniqueNames(cx, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDate.prototype.getISOFields ( ) - */ -static bool PlainDate_getISOFields(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.PlainDate.prototype.getCalendar ( ) - */ -static bool PlainDate_getCalendar(JSContext* cx, const CallArgs& args) { - auto* temporalDate = &args.thisv().toObject().as(); - Rooted calendar(cx, temporalDate->calendar()); - - // Step 3. - auto* obj = ToTemporalCalendarObject(cx, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDate.prototype.getCalendar ( ) - */ -static bool PlainDate_getCalendar(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - /** * Temporal.PlainDate.prototype.add ( temporalDurationLike [ , options ] ) */ static bool PlainDate_add(JSContext* cx, const CallArgs& args) { - Rooted temporalDate( - cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, temporalDate->calendar()); - // Step 3. - Rooted> duration( - cx, ToTemporalDuration(cx, args.get(0))); - if (!duration) { - return false; - } - - // Step 4. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "add", args[1]); - } else { - options = NewPlainObjectWithProto(cx, nullptr); - } - if (!options) { - return false; - } - - // Step 5. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateAdd, - }, - &calendar)) { - return false; - } - - // Step 6. - auto result = AddDate(cx, calendar, temporalDate, duration, options); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; + return AddDurationToDate(cx, TemporalAddDuration::Add, args); } /** @@ -2484,48 +1321,8 @@ static bool PlainDate_add(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainDate.prototype.subtract ( temporalDurationLike [ , options ] ) */ static bool PlainDate_subtract(JSContext* cx, const CallArgs& args) { - Rooted temporalDate( - cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, temporalDate->calendar()); - // Step 3. - Duration duration; - if (!ToTemporalDuration(cx, args.get(0), &duration)) { - return false; - } - - // Step 4. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "subtract", args[1]); - } else { - options = NewPlainObjectWithProto(cx, nullptr); - } - if (!options) { - return false; - } - - // Step 5. - auto negatedDuration = duration.negate(); - - // Step 6. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateAdd, - }, - &calendar)) { - return false; - } - - // Step 7. - auto result = ::AddDate(cx, calendar, temporalDate, negatedDuration, options); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; + return AddDurationToDate(cx, TemporalAddDuration::Subtract, args); } /** @@ -2541,7 +1338,7 @@ static bool PlainDate_subtract(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainDate.prototype.with ( temporalDateLike [ , options ] ) */ static bool PlainDate_with(JSContext* cx, const CallArgs& args) { - Rooted temporalDate( + Rooted temporalDate( cx, &args.thisv().toObject().as()); // Step 3. @@ -2555,71 +1352,55 @@ static bool PlainDate_with(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted resolvedOptions(cx); + auto calendar = temporalDate.calendar(); + + // Step 5. + Rooted fields(cx); + if (!ISODateToFields(cx, temporalDate, &fields)) { + return false; + } + + // Step 6. + Rooted partialDate(cx); + if (!PreparePartialCalendarFields(cx, calendar, temporalDateLike, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + }, + &partialDate)) { + return false; + } + MOZ_ASSERT(!partialDate.keys().isEmpty()); + + // Step 7. + fields = CalendarMergeFields(calendar, fields, partialDate); + + // Steps 8-9. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { + // Step 8. Rooted options(cx, RequireObjectArg(cx, "options", "with", args[1])); if (!options) { return false; } - resolvedOptions = SnapshotOwnProperties(cx, options); - } else { - resolvedOptions = NewPlainObjectWithProto(cx, nullptr); - } - if (!resolvedOptions) { - return false; - } - // Step 5. - Rooted calendarValue(cx, temporalDate->calendar()); - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - CalendarMethod::MergeFields, - }, - &calendar)) { - return false; - } - - // Step 6. - Rooted fields(cx); - JS::RootedVector fieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, temporalDate, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - &fields, &fieldNames)) { - return false; - } - - // Step 7. - Rooted partialDate( - cx, PreparePartialTemporalFields(cx, temporalDateLike, fieldNames)); - if (!partialDate) { - return false; - } - - // Step 8. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, fields, partialDate)); - if (!mergedFields) { - return false; - } - - // Step 9. - fields = PrepareTemporalFields(cx, mergedFields, fieldNames); - if (!fields) { - return false; + // Step 9. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } } // Step 10. - auto result = - temporal::CalendarDateFromFields(cx, calendar, fields, resolvedOptions); + Rooted date(cx); + if (!CalendarDateFromFields(cx, calendar, fields, overflow, &date)) { + return false; + } + + // Step 11. + auto* result = CreateTemporalDate(cx, date); if (!result) { return false; } @@ -2642,7 +1423,7 @@ static bool PlainDate_with(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDate_withCalendar(JSContext* cx, const CallArgs& args) { auto* temporalDate = &args.thisv().toObject().as(); - auto date = ToPlainDate(temporalDate); + auto date = temporalDate->date(); // Step 3. Rooted calendar(cx); @@ -2708,20 +1489,18 @@ static bool PlainDate_since(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDate_equals(JSContext* cx, const CallArgs& args) { auto* temporalDate = &args.thisv().toObject().as(); - auto date = ToPlainDate(temporalDate); + auto date = temporalDate->date(); Rooted calendar(cx, temporalDate->calendar()); // Step 3. - Rooted other(cx); + Rooted other(cx); if (!ToTemporalDate(cx, args.get(0), &other)) { return false; } - // Steps 4-7. - bool equals = date == other.date(); - if (equals && !CalendarEquals(cx, calendar, other.calendar(), &equals)) { - return false; - } + // Steps 4-5. + bool equals = + date == other.date() && CalendarEquals(calendar, other.calendar()); args.rval().setBoolean(equals); return true; @@ -2741,67 +1520,44 @@ static bool PlainDate_equals(JSContext* cx, unsigned argc, Value* vp) { * * The |item| argument represents either a time zone or an options object. The * following cases are supported: - * - |item| is a `Temporal.TimeZone` object. - * - |item| is a user-defined time zone object. * - |item| is an options object with `timeZone` and `plainTime` properties. * - |item| is a time zone identifier string. - * - * User-defined time zone objects are distinguished from options objects by the - * `timeZone` property, i.e. if a `timeZone` property is present, the object is - * treated as an options object, otherwise an object is treated as a - * user-defined time zone. */ static bool PlainDate_toZonedDateTime(JSContext* cx, const CallArgs& args) { auto* temporalDate = &args.thisv().toObject().as(); - auto date = ToPlainDate(temporalDate); + auto date = temporalDate->date(); Rooted calendar(cx, temporalDate->calendar()); // Steps 3-4 Rooted timeZone(cx); - PlainTime time = {}; + Rooted temporalTime(cx); if (args.get(0).isObject()) { Rooted item(cx, &args[0].toObject()); - // Steps 3.a-b. - if (item->canUnwrapAs()) { - // Step 3.a.i. - timeZone.set(TimeZoneValue(item)); + // Step 3.a. + Rooted timeZoneLike(cx); + if (!GetProperty(cx, item, item, cx->names().timeZone, &timeZoneLike)) { + return false; + } - // Step 3.a.ii. (Not applicable in our implementation.) - } else { + // Steps 3.b-c. + if (timeZoneLike.isUndefined()) { // Step 3.b.i. - Rooted timeZoneLike(cx); - if (!GetProperty(cx, item, item, cx->names().timeZone, &timeZoneLike)) { + if (!ToTemporalTimeZone(cx, args[0], &timeZone)) { return false; } - // Steps 3.b.ii-iii. - if (timeZoneLike.isUndefined()) { - // Step 3.b.ii.1. - if (!ToTemporalTimeZone(cx, args[0], &timeZone)) { - return false; - } + // Step 3.b.ii. + MOZ_ASSERT(temporalTime.isUndefined()); + } else { + // Step 3.c.i. + if (!ToTemporalTimeZone(cx, timeZoneLike, &timeZone)) { + return false; + } - // Step 3.b.ii.2. (Not applicable in our implementation.) - } else { - // Step 3.b.iii.1. - if (!ToTemporalTimeZone(cx, timeZoneLike, &timeZone)) { - return false; - } - - // Step 3.b.iii.2. - Rooted temporalTime(cx); - if (!GetProperty(cx, item, item, cx->names().plainTime, - &temporalTime)) { - return false; - } - - // Step 5. (Inlined ToTemporalTimeOrMidnight) - if (!temporalTime.isUndefined()) { - if (!ToTemporalTime(cx, temporalTime, &time)) { - return false; - } - } + // Step 3.c.ii. + if (!GetProperty(cx, item, item, cx->names().plainTime, &temporalTime)) { + return false; } } } else { @@ -2810,26 +1566,43 @@ static bool PlainDate_toZonedDateTime(JSContext* cx, const CallArgs& args) { return false; } - // Step 4.b. (Not applicable in our implementation.) + // Step 4.b. + MOZ_ASSERT(temporalTime.isUndefined()); } - // Step 5. (Moved next to step 3.b.iii.2.) + // Steps 5-6. + EpochNanoseconds epochNs; + if (temporalTime.isUndefined()) { + // Step 5.a. + if (!GetStartOfDay(cx, timeZone, date, &epochNs)) { + return false; + } + } else { + // Step 6.a. + Time time; + if (!ToTemporalTime(cx, temporalTime, &time)) { + return false; + } - // Step 6. - Rooted temporalDateTime(cx); - if (!CreateTemporalDateTime(cx, {date, time}, calendar, &temporalDateTime)) { - return false; + // Step 6.b. + auto isoDateTime = ISODateTime{date, time}; + + // Step 6.c. + if (!ISODateTimeWithinLimits(isoDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } + + // Step 6.d. + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } } - // Steps 7-8. - Instant instant; - if (!GetInstantFor(cx, timeZone, temporalDateTime, - TemporalDisambiguation::Compatible, &instant)) { - return false; - } - - // Step 9. - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); + // Step 7. + auto* result = CreateTemporalZonedDateTime(cx, epochNs, timeZone, calendar); if (!result) { return false; } @@ -2892,17 +1665,10 @@ static bool PlainDate_toString(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainDate.prototype.toLocaleString ( [ locales [ , options ] ] ) */ static bool PlainDate_toLocaleString(JSContext* cx, const CallArgs& args) { - Rooted temporalDate( - cx, &args.thisv().toObject().as()); - - // Step 3. - JSString* str = TemporalDateToString(cx, temporalDate, ShowCalendar::Auto); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-4. + Handle required = cx->names().date; + Handle defaults = cx->names().date; + return TemporalObjectToLocaleString(cx, args, required, defaults); } /** @@ -2969,8 +1735,6 @@ static const JSFunctionSpec PlainDate_prototype_methods[] = { JS_FN("toPlainMonthDay", PlainDate_toPlainMonthDay, 0, 0), JS_FN("toPlainYearMonth", PlainDate_toPlainYearMonth, 0, 0), JS_FN("toPlainDateTime", PlainDate_toPlainDateTime, 0, 0), - JS_FN("getISOFields", PlainDate_getISOFields, 0, 0), - JS_FN("getCalendar", PlainDate_getCalendar, 0, 0), JS_FN("add", PlainDate_add, 1, 0), JS_FN("subtract", PlainDate_subtract, 1, 0), JS_FN("with", PlainDate_with, 1, 0), @@ -3017,64 +1781,3 @@ const ClassSpec PlainDateObject::classSpec_ = { nullptr, ClassSpec::DontDefineConstructor, }; - -struct PlainDateNameAndNative final { - PropertyName* name; - JSNative native; -}; - -static PlainDateNameAndNative GetPlainDateNameAndNative( - JSContext* cx, CalendarField fieldName) { - switch (fieldName) { - case CalendarField::Year: - return {cx->names().year, PlainDate_year}; - case CalendarField::Month: - return {cx->names().month, PlainDate_month}; - case CalendarField::MonthCode: - return {cx->names().monthCode, PlainDate_monthCode}; - case CalendarField::Day: - return {cx->names().day, PlainDate_day}; - } - MOZ_CRASH("invalid temporal field name"); -} - -bool js::temporal::IsBuiltinAccess( - JSContext* cx, Handle date, - std::initializer_list fieldNames) { - // Don't optimize when the object has any own properties which may shadow the - // built-in methods. - if (date->shape()->propMapLength() > 0) { - return false; - } - - JSObject* proto = cx->global()->maybeGetPrototype(JSProto_PlainDate); - - // Don't attempt to optimize when the class isn't yet initialized. - if (!proto) { - return false; - } - - // Don't optimize when the prototype isn't the built-in prototype. - if (date->staticPrototype() != proto) { - return false; - } - - auto* nproto = &proto->as(); - for (auto fieldName : fieldNames) { - auto [name, native] = GetPlainDateNameAndNative(cx, fieldName); - auto prop = nproto->lookupPure(name); - - // Return if the property isn't a data property. - if (!prop || !prop->isDataProperty()) { - return false; - } - - // Return if the property isn't the initial method. - if (!IsNativeFunction(nproto->getSlot(prop->slot()), native)) { - return false; - } - } - - // Success! The access can be optimized. - return true; -} diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.h index f8217eb5e02..4f4b3e14975 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDate.h @@ -10,13 +10,10 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" -#include #include #include "builtin/temporal/Calendar.h" -#include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/TemporalTypes.h" -#include "builtin/temporal/Wrapped.h" #include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" @@ -26,7 +23,6 @@ class JS_PUBLIC_API JSTracer; namespace js { struct ClassSpec; -class PlainObject; } // namespace js namespace js::temporal { @@ -36,22 +32,17 @@ class PlainDateObject : public NativeObject { static const JSClass class_; static const JSClass& protoClass_; - // TODO: Consider compacting fields to reduce object size. - // - // ceil(log2(271821)) + ceil(log2(12)) + ceil(log2(31)) = 28 bits are - // needed to store a date value in a single int32. + static constexpr uint32_t PACKED_DATE_SLOT = 0; + static constexpr uint32_t CALENDAR_SLOT = 1; + static constexpr uint32_t SLOT_COUNT = 2; - static constexpr uint32_t ISO_YEAR_SLOT = 0; - static constexpr uint32_t ISO_MONTH_SLOT = 1; - static constexpr uint32_t ISO_DAY_SLOT = 2; - static constexpr uint32_t CALENDAR_SLOT = 3; - static constexpr uint32_t SLOT_COUNT = 4; - - int32_t isoYear() const { return getFixedSlot(ISO_YEAR_SLOT).toInt32(); } - - int32_t isoMonth() const { return getFixedSlot(ISO_MONTH_SLOT).toInt32(); } - - int32_t isoDay() const { return getFixedSlot(ISO_DAY_SLOT).toInt32(); } + /** + * Extract the date fields from this PlainDate object. + */ + ISODate date() const { + auto packed = PackedDate{getFixedSlot(PACKED_DATE_SLOT).toPrivateUint32()}; + return PackedDate::unpack(packed); + } CalendarValue calendar() const { return CalendarValue(getFixedSlot(CALENDAR_SLOT)); @@ -61,57 +52,17 @@ class PlainDateObject : public NativeObject { static const ClassSpec classSpec_; }; -class MOZ_STACK_CLASS PlainDateWithCalendar final { - PlainDate date_; - CalendarValue calendar_; - - public: - PlainDateWithCalendar() = default; - - PlainDateWithCalendar(const PlainDate& date, const CalendarValue& calendar) - : date_(date), calendar_(calendar) { - MOZ_ASSERT(ISODateTimeWithinLimits(date)); - } - - const auto& date() const { return date_; } - const auto& calendar() const { return calendar_; } - - // Allow implicit conversion to a calendar-less PlainDate. - operator const PlainDate&() const { return date(); } - - void trace(JSTracer* trc) { calendar_.trace(trc); } - - const auto* calendarDoNotUse() const { return &calendar_; } -}; - -/** - * Extract the date fields from the PlainDate object. - */ -inline PlainDate ToPlainDate(const PlainDateObject* date) { - return {date->isoYear(), date->isoMonth(), date->isoDay()}; -} - -enum class TemporalOverflow; -enum class TemporalUnit; -class DurationObject; -class ZonedDateTimeObject; - #ifdef DEBUG /** * IsValidISODate ( year, month, day ) */ -bool IsValidISODate(const PlainDate& date); - -/** - * IsValidISODate ( year, month, day ) - */ -bool IsValidISODate(double year, double month, double day); +bool IsValidISODate(const ISODate& date); #endif /** * IsValidISODate ( year, month, day ) */ -bool ThrowIfInvalidISODate(JSContext* cx, const PlainDate& date); +bool ThrowIfInvalidISODate(JSContext* cx, const ISODate& date); /** * IsValidISODate ( year, month, day ) @@ -120,163 +71,85 @@ bool ThrowIfInvalidISODate(JSContext* cx, double year, double month, double day); /** - * ToTemporalDate ( item [ , options ] ) + * ISODateWithinLimits ( isoDate ) */ -bool ToTemporalDate(JSContext* cx, JS::Handle item, - PlainDate* result); +bool ISODateWithinLimits(const ISODate& isoDate); -/** - * ToTemporalDate ( item [ , options ] ) - */ -bool ToTemporalDate(JSContext* cx, JS::Handle item, - JS::MutableHandle result); +class MOZ_STACK_CLASS PlainDate final { + ISODate date_; + CalendarValue calendar_; -/** - * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ) - */ -PlainDateObject* CreateTemporalDate(JSContext* cx, const PlainDate& date, - JS::Handle calendar); + public: + PlainDate() = default; -/** - * CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ) - */ -bool CreateTemporalDate(JSContext* cx, const PlainDate& date, - JS::Handle calendar, - JS::MutableHandle result); + PlainDate(const ISODate& date, const CalendarValue& calendar) + : date_(date), calendar_(calendar) { + MOZ_ASSERT(ISODateWithinLimits(date)); + } -/** - * RegulateISODate ( year, month, day, overflow ) - */ -bool RegulateISODate(JSContext* cx, const PlainDate& date, - TemporalOverflow overflow, PlainDate* result); + explicit PlainDate(const PlainDateObject* date) + : PlainDate(date->date(), date->calendar()) {} -struct RegulatedISODate final { - double year = 0; - int32_t month = 0; - int32_t day = 0; + const auto& date() const { return date_; } + const auto& calendar() const { return calendar_; } + + // Allow implicit conversion to an ISODate. + operator const ISODate&() const { return date(); } + + explicit operator bool() const { return !!calendar_; } + + void trace(JSTracer* trc) { calendar_.trace(trc); } + + const auto* calendarDoNotUse() const { return &calendar_; } }; /** - * RegulateISODate ( year, month, day, overflow ) + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) */ -bool RegulateISODate(JSContext* cx, double year, double month, double day, - TemporalOverflow overflow, RegulatedISODate* result); +PlainDateObject* CreateTemporalDate(JSContext* cx, const ISODate& isoDate, + JS::Handle calendar); /** - * AddISODate ( year, month, day, years, months, weeks, days, overflow ) + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) */ -bool AddISODate(JSContext* cx, const PlainDate& date, - const DateDuration& duration, TemporalOverflow overflow, - PlainDate* result); +PlainDateObject* CreateTemporalDate(JSContext* cx, JS::Handle date); /** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) + * CreateTemporalDate ( isoDate, calendar [ , newTarget ] ) */ -Wrapped AddDate(JSContext* cx, - JS::Handle calendar, - JS::Handle> date, - const DateDuration& duration); - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -Wrapped AddDate(JSContext* cx, - JS::Handle calendar, - JS::Handle> date, - const DateDuration& duration, - JS::Handle options); - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -bool AddDate(JSContext* cx, JS::Handle calendar, - const PlainDate& date, const DateDuration& duration, - JS::Handle options, PlainDate* result); - -/** - * AddDate ( calendarRec, plainDate, duration [ , options ] ) - */ -bool AddDate(JSContext* cx, JS::Handle calendar, - JS::Handle> date, - const DateDuration& duration, PlainDate* result); - -/** - * DifferenceISODate ( y1, m1, d1, y2, m2, d2, largestUnit ) - */ -DateDuration DifferenceISODate(const PlainDate& start, const PlainDate& end, - TemporalUnit largestUnit); - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool DifferenceDate(JSContext* cx, JS::Handle calendar, - JS::Handle> one, - JS::Handle> two, - TemporalUnit largestUnit, JS::Handle options, - DateDuration* result); - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool DifferenceDate(JSContext* cx, JS::Handle calendar, - JS::Handle> one, - JS::Handle> two, - TemporalUnit largestUnit, DateDuration* result); - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool DifferenceDate(JSContext* cx, JS::Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, JS::Handle options, - DateDuration* result); - -/** - * DifferenceDate ( calendarRec, one, two, options ) - */ -bool DifferenceDate(JSContext* cx, JS::Handle calendar, - const PlainDate& one, const PlainDate& two, - TemporalUnit largestUnit, DateDuration* result); +bool CreateTemporalDate(JSContext* cx, const ISODate& isoDate, + JS::Handle calendar, + JS::MutableHandle result); /** * CompareISODate ( y1, m1, d1, y2, m2, d2 ) */ -int32_t CompareISODate(const PlainDate& one, const PlainDate& two); +int32_t CompareISODate(const ISODate& one, const ISODate& two); /** * BalanceISODate ( year, month, day ) */ -bool BalanceISODate(JSContext* cx, const PlainDate& date, int64_t days, - PlainDate* result); +bool BalanceISODate(JSContext* cx, const ISODate& date, int64_t days, + ISODate* result); /** * BalanceISODate ( year, month, day ) */ -PlainDate BalanceISODate(int32_t year, int32_t month, int32_t day); - -/** - * BalanceISODate ( year, month, day ) - */ -PlainDate BalanceISODateNew(int32_t year, int32_t month, int32_t day); - -/** - * Return true when accessing the calendar fields |fieldNames| can be optimized. - * Otherwise returns false. - */ -bool IsBuiltinAccess(JSContext* cx, JS::Handle date, - std::initializer_list fieldNames); +ISODate BalanceISODate(const ISODate& date, int32_t days); } /* namespace js::temporal */ namespace js { template -class WrappedPtrOperations { +class WrappedPtrOperations { const auto& container() const { return static_cast(this)->get(); } public: + explicit operator bool() const { return bool(container()); } + const auto& date() const { return container().date(); } JS::Handle calendar() const { @@ -284,8 +157,8 @@ class WrappedPtrOperations { container().calendarDoNotUse()); } - // Allow implicit conversion to a calendar-less PlainDate. - operator const temporal::PlainDate&() const { return date(); } + // Allow implicit conversion to an ISODate. + operator const temporal::ISODate&() const { return date(); } }; } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.cpp index 61a41c5bd65..413ca394d1b 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.cpp @@ -7,42 +7,40 @@ #include "builtin/temporal/PlainDateTime.h" #include "mozilla/Assertions.h" +#include "mozilla/Casting.h" +#include "mozilla/EnumSet.h" #include -#include #include -#include "jsnum.h" #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/CalendarFields.h" #include "builtin/temporal/Duration.h" +#include "builtin/temporal/Instant.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainMonthDay.h" #include "builtin/temporal/PlainTime.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ToString.h" -#include "builtin/temporal/Wrapped.h" #include "builtin/temporal/ZonedDateTime.h" -#include "ds/IdValuePair.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" -#include "js/AllocPolicy.h" +#include "gc/GCEnum.h" #include "js/CallArgs.h" #include "js/CallNonGenericMethod.h" #include "js/Class.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/PropertyDescriptor.h" #include "js/PropertySpec.h" #include "js/RootingAPI.h" @@ -53,7 +51,6 @@ #include "vm/JSAtomState.h" #include "vm/JSContext.h" #include "vm/JSObject.h" -#include "vm/ObjectOperations.h" #include "vm/PlainObject.h" #include "vm/StringType.h" @@ -69,814 +66,608 @@ static inline bool IsPlainDateTime(Handle v) { #ifdef DEBUG /** - * IsValidISODateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond ) + * IsValidISODate ( year, month, day ) + * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -bool js::temporal::IsValidISODateTime(const PlainDateTime& dateTime) { - return IsValidISODate(dateTime.date) && IsValidTime(dateTime.time); +bool js::temporal::IsValidISODateTime(const ISODateTime& isoDateTime) { + return IsValidISODate(isoDateTime.date) && IsValidTime(isoDateTime.time); } #endif /** - * IsValidISODateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond ) + * ISODateTimeWithinLimits ( isoDateTime ) */ -static bool ThrowIfInvalidISODateTime(JSContext* cx, - const PlainDateTime& dateTime) { - return ThrowIfInvalidISODate(cx, dateTime.date) && - ThrowIfInvalidTime(cx, dateTime.time); -} +bool js::temporal::ISODateTimeWithinLimits(const ISODateTime& isoDateTime) { + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); -/** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -template -static bool ISODateTimeWithinLimits(T year, T month, T day, T hour, T minute, - T second, T millisecond, T microsecond, - T nanosecond) { - static_assert(std::is_same_v || std::is_same_v); + constexpr auto min = ISODate::min(); + constexpr auto max = ISODate::max(); - // Step 1. - MOZ_ASSERT(IsInteger(year)); - MOZ_ASSERT(IsInteger(month)); - MOZ_ASSERT(IsInteger(day)); - MOZ_ASSERT(IsInteger(hour)); - MOZ_ASSERT(IsInteger(minute)); - MOZ_ASSERT(IsInteger(second)); - MOZ_ASSERT(IsInteger(millisecond)); - MOZ_ASSERT(IsInteger(microsecond)); - MOZ_ASSERT(IsInteger(nanosecond)); + const auto& year = isoDateTime.date.year; - MOZ_ASSERT(IsValidISODate(year, month, day)); - MOZ_ASSERT( - IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond)); - - // js> new Date(-8_64000_00000_00000).toISOString() - // "-271821-04-20T00:00:00.000Z" - // - // js> new Date(+8_64000_00000_00000).toISOString() - // "+275760-09-13T00:00:00.000Z" - - constexpr int32_t minYear = -271821; - constexpr int32_t maxYear = 275760; - - // Definitely in range. - if (minYear < year && year < maxYear) { + // Fast-path when the input is definitely in range. + if (min.year < year && year < max.year) { return true; } - // -271821 April, 20 + // Check |isoDateTime| is within the valid limits. if (year < 0) { - if (year != minYear) { - return false; + if (isoDateTime.date != min) { + return isoDateTime.date > min; } - if (month != 4) { - return month > 4; - } - if (day != (20 - 1)) { - return day > (20 - 1); - } - // Needs to be past midnight on April, 19. - return !(hour == 0 && minute == 0 && second == 0 && millisecond == 0 && - microsecond == 0 && nanosecond == 0); - } - // 275760 September, 13 - if (year != maxYear) { - return false; + // Needs to be past midnight. + return isoDateTime.time != Time{}; } - if (month != 9) { - return month < 9; - } - if (day > 13) { - return false; - } - return true; + return isoDateTime.date <= max; } /** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -template -static bool ISODateTimeWithinLimits(T year, T month, T day) { - static_assert(std::is_same_v || std::is_same_v); - - MOZ_ASSERT(IsValidISODate(year, month, day)); - - // js> new Date(-8_64000_00000_00000).toISOString() - // "-271821-04-20T00:00:00.000Z" - // - // js> new Date(+8_64000_00000_00000).toISOString() - // "+275760-09-13T00:00:00.000Z" - - constexpr int32_t minYear = -271821; - constexpr int32_t maxYear = 275760; - - // ISODateTimeWithinLimits is called with hour=12 and the remaining time - // components set to zero. That means the maximum value is exclusive, whereas - // the minimum value is inclusive. - - // Definitely in range. - if (minYear < year && year < maxYear) { - return true; - } - - // -271821 April, 20 - if (year < 0) { - if (year != minYear) { - return false; - } - if (month != 4) { - return month > 4; - } - if (day < (20 - 1)) { - return false; - } - return true; - } - - // 275760 September, 13 - if (year != maxYear) { - return false; - } - if (month != 9) { - return month < 9; - } - if (day > 13) { - return false; - } - return true; -} - -/** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -bool js::temporal::ISODateTimeWithinLimits(double year, double month, - double day) { - return ::ISODateTimeWithinLimits(year, month, day); -} - -/** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -bool js::temporal::ISODateTimeWithinLimits(const PlainDateTime& dateTime) { - const auto& [date, time] = dateTime; - return ::ISODateTimeWithinLimits(date.year, date.month, date.day, time.hour, - time.minute, time.second, time.millisecond, - time.microsecond, time.nanosecond); -} - -/** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -bool js::temporal::ISODateTimeWithinLimits(const PlainDate& date) { - return ::ISODateTimeWithinLimits(date.year, date.month, date.day); -} - -/** - * CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar [ , newTarget ] ) + * CreateTemporalDateTime ( isoDateTime, calendar [ , newTarget ] ) */ static PlainDateTimeObject* CreateTemporalDateTime( - JSContext* cx, const CallArgs& args, double isoYear, double isoMonth, - double isoDay, double hour, double minute, double second, - double millisecond, double microsecond, double nanosecond, + JSContext* cx, const CallArgs& args, const ISODateTime& isoDateTime, Handle calendar) { - MOZ_ASSERT(IsInteger(isoYear)); - MOZ_ASSERT(IsInteger(isoMonth)); - MOZ_ASSERT(IsInteger(isoDay)); - MOZ_ASSERT(IsInteger(hour)); - MOZ_ASSERT(IsInteger(minute)); - MOZ_ASSERT(IsInteger(second)); - MOZ_ASSERT(IsInteger(millisecond)); - MOZ_ASSERT(IsInteger(microsecond)); - MOZ_ASSERT(IsInteger(nanosecond)); + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); // Step 1. - if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { - return nullptr; - } - - // Step 2. - if (!ThrowIfInvalidTime(cx, hour, minute, second, millisecond, microsecond, - nanosecond)) { - return nullptr; - } - - // Step 3. - if (!ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, hour, minute, second, - millisecond, microsecond, nanosecond)) { + if (!ISODateTimeWithinLimits(isoDateTime)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); return nullptr; } - // Steps 4-5. + // Steps 2-3. Rooted proto(cx); if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PlainDateTime, &proto)) { return nullptr; } - auto* dateTime = NewObjectWithClassProto(cx, proto); - if (!dateTime) { + auto* object = NewObjectWithClassProto(cx, proto); + if (!object) { return nullptr; } + // Step 4. + auto packedDate = PackedDate::pack(isoDateTime.date); + auto packedTime = PackedTime::pack(isoDateTime.time); + object->setFixedSlot(PlainDateTimeObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); + object->setFixedSlot( + PlainDateTimeObject::PACKED_TIME_SLOT, + DoubleValue(mozilla::BitwiseCast(packedTime.value))); + + // Step 5. + object->setFixedSlot(PlainDateTimeObject::CALENDAR_SLOT, + calendar.toSlotValue()); + // Step 6. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_YEAR_SLOT, - Int32Value(int32_t(isoYear))); - - // Step 7. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_MONTH_SLOT, - Int32Value(int32_t(isoMonth))); - - // Step 8. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_DAY_SLOT, - Int32Value(int32_t(isoDay))); - - // Step 9. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_HOUR_SLOT, - Int32Value(int32_t(hour))); - - // Step 10. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_MINUTE_SLOT, - Int32Value(int32_t(minute))); - - // Step 11. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_SECOND_SLOT, - Int32Value(int32_t(second))); - - // Step 12. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_MILLISECOND_SLOT, - Int32Value(int32_t(millisecond))); - - // Step 13. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_MICROSECOND_SLOT, - Int32Value(int32_t(microsecond))); - - // Step 14. - dateTime->setFixedSlot(PlainDateTimeObject::ISO_NANOSECOND_SLOT, - Int32Value(int32_t(nanosecond))); - - // Step 15. - dateTime->setFixedSlot(PlainDateTimeObject::CALENDAR_SLOT, - calendar.toSlotValue()); - - // Step 16. - return dateTime; + return object; } /** - * CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar [ , newTarget ] ) + * CreateTemporalDateTime ( isoDateTime, calendar [ , newTarget ] ) */ PlainDateTimeObject* js::temporal::CreateTemporalDateTime( - JSContext* cx, const PlainDateTime& dateTime, + JSContext* cx, const ISODateTime& isoDateTime, Handle calendar) { - const auto& [date, time] = dateTime; - const auto& [isoYear, isoMonth, isoDay] = date; - const auto& [hour, minute, second, millisecond, microsecond, nanosecond] = - time; + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); - // Steps 1-2. - if (!ThrowIfInvalidISODateTime(cx, dateTime)) { - return nullptr; - } - - // Step 3. - if (!ISODateTimeWithinLimits(dateTime)) { + // Step 1. + if (!ISODateTimeWithinLimits(isoDateTime)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); return nullptr; } - // Steps 4-5. + // Steps 2-3. auto* object = NewBuiltinClassInstance(cx); if (!object) { return nullptr; } - // Step 6. - object->setFixedSlot(PlainDateTimeObject::ISO_YEAR_SLOT, Int32Value(isoYear)); + // Step 4. + auto packedDate = PackedDate::pack(isoDateTime.date); + auto packedTime = PackedTime::pack(isoDateTime.time); + object->setFixedSlot(PlainDateTimeObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); + object->setFixedSlot( + PlainDateTimeObject::PACKED_TIME_SLOT, + DoubleValue(mozilla::BitwiseCast(packedTime.value))); - // Step 7. - object->setFixedSlot(PlainDateTimeObject::ISO_MONTH_SLOT, - Int32Value(isoMonth)); - - // Step 8. - object->setFixedSlot(PlainDateTimeObject::ISO_DAY_SLOT, Int32Value(isoDay)); - - // Step 9. - object->setFixedSlot(PlainDateTimeObject::ISO_HOUR_SLOT, Int32Value(hour)); - - // Step 10. - object->setFixedSlot(PlainDateTimeObject::ISO_MINUTE_SLOT, - Int32Value(minute)); - - // Step 11. - object->setFixedSlot(PlainDateTimeObject::ISO_SECOND_SLOT, - Int32Value(second)); - - // Step 12. - object->setFixedSlot(PlainDateTimeObject::ISO_MILLISECOND_SLOT, - Int32Value(millisecond)); - - // Step 13. - object->setFixedSlot(PlainDateTimeObject::ISO_MICROSECOND_SLOT, - Int32Value(microsecond)); - - // Step 14. - object->setFixedSlot(PlainDateTimeObject::ISO_NANOSECOND_SLOT, - Int32Value(nanosecond)); - - // Step 15. + // Step 5. object->setFixedSlot(PlainDateTimeObject::CALENDAR_SLOT, calendar.toSlotValue()); - // Step 16. + // Step 6. return object; } /** - * CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar [ , newTarget ] ) + * CreateTemporalDateTime ( isoDateTime, calendar [ , newTarget ] ) */ -bool js::temporal::CreateTemporalDateTime( - JSContext* cx, const PlainDateTime& dateTime, - Handle calendar, - MutableHandle result) { - // Steps 1-2. - if (!ThrowIfInvalidISODateTime(cx, dateTime)) { - return false; - } +static PlainDateTimeObject* CreateTemporalDateTime( + JSContext* cx, Handle dateTime) { + MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); + return CreateTemporalDateTime(cx, dateTime, dateTime.calendar()); +} - // Step 3. +/** + * CreateTemporalDateTime ( isoDateTime, calendar [ , newTarget ] ) + */ +static bool CreateTemporalDateTime(JSContext* cx, const ISODateTime& dateTime, + Handle calendar, + MutableHandle result) { + MOZ_ASSERT(IsValidISODateTime(dateTime)); + + // Step 1. if (!ISODateTimeWithinLimits(dateTime)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); return false; } - result.set(PlainDateTimeWithCalendar{dateTime, calendar}); + // Step 2-6. + result.set(PlainDateTime{dateTime, calendar}); return true; } /** - * InterpretTemporalDateTimeFields ( calendarRec, fields, options ) + * InterpretTemporalDateTimeFields ( calendar, fields, overflow ) */ bool js::temporal::InterpretTemporalDateTimeFields( - JSContext* cx, Handle calendar, Handle fields, - Handle options, PlainDateTime* result) { - // Step 1. (Not applicable in our implementation.) + JSContext* cx, Handle calendar, + Handle fields, TemporalOverflow overflow, + ISODateTime* result) { + // Step 1. + Rooted temporalDate(cx); + if (!CalendarDateFromFields(cx, calendar, fields, overflow, &temporalDate)) { + return false; + } // Step 2. - MOZ_ASSERT(CalendarMethodsRecordHasLookedUp(calendar, - CalendarMethod::DateFromFields)); + auto timeLike = TemporalTimeLike{ + fields.hour(), fields.minute(), fields.second(), + fields.millisecond(), fields.microsecond(), fields.nanosecond(), + }; + Time time; + if (!RegulateTime(cx, timeLike, overflow, &time)) { + return false; + } // Step 3. - TemporalTimeLike timeResult; - if (!ToTemporalTimeRecord(cx, fields, &timeResult)) { - return false; - } - - // Step 4. - auto overflow = TemporalOverflow::Constrain; - if (!GetTemporalOverflowOption(cx, options, &overflow)) { - return false; - } - - // Steps 5-6. - Rooted overflowValue(cx); - if (overflow == TemporalOverflow::Constrain) { - overflowValue.setString(cx->names().constrain); - } else { - MOZ_ASSERT(overflow == TemporalOverflow::Reject); - overflowValue.setString(cx->names().reject); - } - if (!DefineDataProperty(cx, options, cx->names().overflow, overflowValue)) { - return false; - } - - // Step 7. - auto temporalDate = - js::temporal::CalendarDateFromFields(cx, calendar, fields, options); - if (!temporalDate) { - return false; - } - auto date = ToPlainDate(&temporalDate.unwrap()); - - // Step 8. - PlainTime time; - if (!RegulateTime(cx, timeResult, overflow, &time)) { - return false; - } - - // Step 9. - *result = {date, time}; + *result = {temporalDate.date(), time}; return true; } +struct DateTimeOptions { + TemporalOverflow overflow = TemporalOverflow::Constrain; +}; + /** - * InterpretTemporalDateTimeFields ( calendarRec, fields, options ) + * ToTemporalDateTime ( item [ , options ] ) */ -bool js::temporal::InterpretTemporalDateTimeFields( - JSContext* cx, Handle calendar, Handle fields, - PlainDateTime* result) { - // TODO: Avoid creating the options object when CalendarDateFromFields calls - // the built-in Calendar.prototype.dateFromFields method. - Rooted options(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!options) { +static bool ToTemporalDateTimeOptions(JSContext* cx, Handle options, + DateTimeOptions* result) { + if (options.isUndefined()) { + *result = {}; + return true; + } + + // NOTE: |options| are only passed from `Temporal.PlainDateTime.from`. + + Rooted resolvedOptions( + cx, RequireObjectArg(cx, "options", "from", options)); + if (!resolvedOptions) { return false; } - return InterpretTemporalDateTimeFields(cx, calendar, fields, options, result); + auto overflow = TemporalOverflow::Constrain; + if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) { + return false; + } + + *result = {overflow}; + return true; } /** * ToTemporalDateTime ( item [ , options ] ) */ -static Wrapped ToTemporalDateTime( - JSContext* cx, Handle item, Handle maybeOptions) { +static bool ToTemporalDateTime(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { + // Step 1. (Not applicable in our implementation.) + + // Step 2.a. + if (auto* plainDateTime = item->maybeUnwrapIf()) { + auto dateTime = plainDateTime->dateTime(); + Rooted calendar(cx, plainDateTime->calendar()); + if (!calendar.wrap(cx)) { + return false; + } + + // Steps 2.a.i-ii. + DateTimeOptions ignoredOptions; + if (!ToTemporalDateTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.a.iii. + result.set(PlainDateTime{dateTime, calendar}); + return true; + } + + // Step 2.b. + if (auto* zonedDateTime = item->maybeUnwrapIf()) { + auto epochNs = zonedDateTime->epochNanoseconds(); + Rooted timeZone(cx, zonedDateTime->timeZone()); + Rooted calendar(cx, zonedDateTime->calendar()); + + if (!timeZone.wrap(cx)) { + return false; + } + if (!calendar.wrap(cx)) { + return false; + } + + // Step 2.b.i. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, timeZone, epochNs, &dateTime)) { + return false; + } + + // Steps 2.b.ii-iii. + DateTimeOptions ignoredOptions; + if (!ToTemporalDateTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.b.iv. + result.set(PlainDateTime{dateTime, calendar}); + return true; + } + + // Step 2.c. + if (auto* plainDate = item->maybeUnwrapIf()) { + auto date = plainDate->date(); + Rooted calendar(cx, plainDate->calendar()); + if (!calendar.wrap(cx)) { + return false; + } + + // Steps 2.c.i-ii. + DateTimeOptions ignoredOptions; + if (!ToTemporalDateTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Steps 2.c.iii-iv. + return CreateTemporalDateTime(cx, ISODateTime{date}, calendar, result); + } + + // Step 2.d. + Rooted calendar(cx); + if (!GetTemporalCalendarWithISODefault(cx, item, &calendar)) { + return false; + } + + // Step 2.e. + Rooted fields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + CalendarField::Hour, + CalendarField::Minute, + CalendarField::Second, + CalendarField::Millisecond, + CalendarField::Microsecond, + CalendarField::Nanosecond, + }, + &fields)) { + return false; + } + + // Steps 2.f-g. + DateTimeOptions resolvedOptions; + if (!ToTemporalDateTimeOptions(cx, options, &resolvedOptions)) { + return false; + } + auto [overflow] = resolvedOptions; + + // Step 2.h. + ISODateTime dateTime; + if (!InterpretTemporalDateTimeFields(cx, calendar, fields, overflow, + &dateTime)) { + return false; + } + + // Step 2.i. + return CreateTemporalDateTime(cx, dateTime, calendar, result); +} + +/** + * ToTemporalDateTime ( item [ , options ] ) + */ +static bool ToTemporalDateTime(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { // Step 1. (Not applicable) // Step 2. - Rooted maybeResolvedOptions(cx); - if (maybeOptions) { - maybeResolvedOptions = SnapshotOwnProperties(cx, maybeOptions); - if (!maybeResolvedOptions) { - return nullptr; - } - } - - // Steps 3-4. - Rooted calendar(cx); - PlainDateTime result; if (item.isObject()) { Rooted itemObj(cx, &item.toObject()); + return ToTemporalDateTime(cx, itemObj, options, result); + } - // Step 3.a. - if (itemObj->canUnwrapAs()) { - return itemObj; - } + // Step 3. + if (!item.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, + nullptr, "not a string"); + return false; + } + Rooted string(cx, item.toString()); - // Step 3.b. - if (auto* zonedDateTime = itemObj->maybeUnwrapIf()) { - auto epochInstant = ToInstant(zonedDateTime); - Rooted timeZone(cx, zonedDateTime->timeZone()); - Rooted calendar(cx, zonedDateTime->calendar()); + // Steps 4-5. + ISODateTime dateTime; + Rooted calendarString(cx); + if (!ParseTemporalDateTimeString(cx, string, &dateTime, &calendarString)) { + return false; + } + MOZ_ASSERT(IsValidISODateTime(dateTime)); - if (!timeZone.wrap(cx)) { - return nullptr; - } - if (!calendar.wrap(cx)) { - return nullptr; - } - - // Step 3.b.i. - if (maybeResolvedOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return nullptr; - } - } - - // Steps 3.b.ii-iv. - return GetPlainDateTimeFor(cx, timeZone, epochInstant, calendar); - } - - // Step 3.c. - if (auto* date = itemObj->maybeUnwrapIf()) { - PlainDateTime dateTime = {ToPlainDate(date), {}}; - Rooted calendar(cx, date->calendar()); - if (!calendar.wrap(cx)) { - return nullptr; - } - - // Step 3.c.i. - if (maybeResolvedOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return nullptr; - } - } - - // Step 3.c.ii. - return CreateTemporalDateTime(cx, dateTime, calendar); - } - - // Step 3.d. - if (!GetTemporalCalendarWithISODefault(cx, itemObj, &calendar)) { - return nullptr; - } - - // Step 3.e. - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - }, - &calendarRec)) { - return nullptr; - } - - // Step 3.f. - Rooted fields( - cx, PrepareCalendarFields(cx, calendarRec, itemObj, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - { - TemporalField::Hour, - TemporalField::Microsecond, - TemporalField::Millisecond, - TemporalField::Minute, - TemporalField::Nanosecond, - TemporalField::Second, - })); - if (!fields) { - return nullptr; - } - - // Step 3.g. - if (maybeResolvedOptions) { - if (!InterpretTemporalDateTimeFields(cx, calendarRec, fields, - maybeResolvedOptions, &result)) { - return nullptr; - } - } else { - if (!InterpretTemporalDateTimeFields(cx, calendarRec, fields, &result)) { - return nullptr; - } - } - } else { - // Step 4.a. - if (!item.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, - nullptr, "not a string"); - return nullptr; - } - Rooted string(cx, item.toString()); - - // Step 4.b. - Rooted calendarString(cx); - if (!ParseTemporalDateTimeString(cx, string, &result, &calendarString)) { - return nullptr; - } - - // Step 4.c. - MOZ_ASSERT(IsValidISODate(result.date)); - - // Step 4.d. - MOZ_ASSERT(IsValidTime(result.time)); - - // Steps 4.e-h. - if (calendarString) { - if (!ToBuiltinCalendar(cx, calendarString, &calendar)) { - return nullptr; - } - } else { - calendar.set(CalendarValue(CalendarId::ISO8601)); - } - - // Step 4.i. - if (maybeResolvedOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return nullptr; - } + // Steps 6-8. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (calendarString) { + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; } } - // Step 5. - return CreateTemporalDateTime(cx, result, calendar); + // Steps 9-10. + DateTimeOptions ignoredOptions; + if (!ToTemporalDateTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Steps 11-13. + return CreateTemporalDateTime(cx, dateTime, calendar, result); } /** * ToTemporalDateTime ( item [ , options ] ) */ -Wrapped js::temporal::ToTemporalDateTime( - JSContext* cx, Handle item) { - return ::ToTemporalDateTime(cx, item, nullptr); +static bool ToTemporalDateTime(JSContext* cx, Handle item, + MutableHandle result) { + return ToTemporalDateTime(cx, item, UndefinedHandleValue, result); } /** - * ToTemporalDateTime ( item [ , options ] ) + * CompareISODateTime ( isoDateTime1, isoDateTime2 ) */ -bool js::temporal::ToTemporalDateTime(JSContext* cx, Handle item, - PlainDateTime* result) { - auto obj = ::ToTemporalDateTime(cx, item, nullptr); - if (!obj) { - return false; - } - - *result = ToPlainDateTime(&obj.unwrap()); - return true; -} - -/** - * ToTemporalDateTime ( item [ , options ] ) - */ -static bool ToTemporalDateTime( - JSContext* cx, Handle item, - MutableHandle result) { - Handle options = nullptr; - - auto* obj = ::ToTemporalDateTime(cx, item, options).unwrapOrNull(); - if (!obj) { - return false; - } - - auto dateTime = ToPlainDateTime(obj); - Rooted calendar(cx, obj->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - result.set(PlainDateTimeWithCalendar{dateTime, calendar}); - return true; -} - -/** - * CompareISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, - * d2, h2, min2, s2, ms2, mus2, ns2 ) - */ -static int32_t CompareISODateTime(const PlainDateTime& one, - const PlainDateTime& two) { - // Step 1. (Not applicable in our implementation.) - - // Steps 2-3. - if (int32_t dateResult = CompareISODate(one.date, two.date)) { +static int32_t CompareISODateTime(const ISODateTime& isoDateTime1, + const ISODateTime& isoDateTime2) { + // Steps 1-2. + if (int32_t dateResult = + CompareISODate(isoDateTime1.date, isoDateTime2.date)) { return dateResult; } - // Steps 4. - return CompareTemporalTime(one.time, two.time); + // Steps 3. + return CompareTimeRecord(isoDateTime1.time, isoDateTime2.time); } /** - * AddDateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond, calendarRec, years, months, weeks, days, norm, - * options ) + * Add24HourDaysToTimeDuration ( d, days ) */ -static bool AddDateTime(JSContext* cx, const PlainDateTime& dateTime, - Handle calendar, - const NormalizedDuration& duration, - Handle options, PlainDateTime* result) { - MOZ_ASSERT(IsValidDuration(duration)); - +static TimeDuration Add24HourDaysToTimeDuration(const TimeDuration& d, + int32_t days) { // Step 1. - MOZ_ASSERT(IsValidISODateTime(dateTime)); + auto result = d + TimeDuration::fromDays(days); // Step 2. - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); + MOZ_ASSERT(result.abs() <= TimeDuration::max()); // Step 3. - auto timeResult = AddTime(dateTime.time, duration.time); + return result; +} + +/** + * DifferenceISODateTime ( isoDateTime1, isoDateTime2, calendar, largestUnit ) + */ +static bool DifferenceISODateTime(JSContext* cx, + const ISODateTime& isoDateTime1, + const ISODateTime& isoDateTime2, + Handle calendar, + TemporalUnit largestUnit, + InternalDuration* result) { + MOZ_ASSERT(isoDateTime1 != isoDateTime2, + "fast-path for same date-time case handled in caller"); + + // Steps 1-2. + MOZ_ASSERT(IsValidISODateTime(isoDateTime1)); + MOZ_ASSERT(IsValidISODateTime(isoDateTime2)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime1)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime2)); + + // Step 3. + auto timeDuration = DifferenceTime(isoDateTime1.time, isoDateTime2.time); // Step 4. - const auto& datePart = dateTime.date; + int32_t timeSign = TimeDurationSign(timeDuration); // Step 5. - auto dateDuration = DateDuration{ - duration.date.years, - duration.date.months, - duration.date.weeks, - duration.date.days + timeResult.days, - }; - if (!ThrowIfInvalidDuration(cx, dateDuration)) { - return false; - } + int32_t dateSign = CompareISODate(isoDateTime1.date, isoDateTime2.date); // Step 6. - PlainDate addedDate; - if (!AddDate(cx, calendar, datePart, dateDuration, options, &addedDate)) { + auto adjustedDate = isoDateTime2.date; + + // Step 7. + if (timeSign == dateSign) { + // Step 7.a. + adjustedDate = BalanceISODate(adjustedDate, timeSign); + + // Step 7.b. + timeDuration = Add24HourDaysToTimeDuration(timeDuration, -timeSign); + } + + MOZ_ASSERT(IsValidISODate(adjustedDate)); + MOZ_ASSERT(ISODateWithinLimits(adjustedDate)); + + // Step 8. + auto dateLargestUnit = std::min(TemporalUnit::Day, largestUnit); + + // Step 9. + DateDuration dateDifference; + if (!CalendarDateUntil(cx, calendar, isoDateTime1.date, adjustedDate, + dateLargestUnit, &dateDifference)) { return false; } - // Step 7. - *result = {addedDate, timeResult.time}; + // Steps 10. + if (largestUnit > TemporalUnit::Day) { + // Step 10.a. + auto days = mozilla::AssertedCast(dateDifference.days); + timeDuration = Add24HourDaysToTimeDuration(timeDuration, days); + + // Step 10.b. + dateDifference.days = 0; + } + + // Step 11. + MOZ_ASSERT( + DateDurationSign(dateDifference) * TimeDurationSign(timeDuration) >= 0); + *result = {dateDifference, timeDuration}; return true; } /** - * DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, - * d2, h2, min2, s2, ms2, mus2, ns2, calendarRec, largestUnit, options ) + * RoundISODateTime ( isoDateTime, increment, unit, roundingMode ) */ -static bool DifferenceISODateTime(JSContext* cx, const PlainDateTime& one, - const PlainDateTime& two, - Handle calendar, - TemporalUnit largestUnit, - Handle maybeOptions, - NormalizedDuration* result) { - // Steps 1-2. - MOZ_ASSERT(IsValidISODateTime(one)); - MOZ_ASSERT(IsValidISODateTime(two)); - MOZ_ASSERT(ISODateTimeWithinLimits(one)); - MOZ_ASSERT(ISODateTimeWithinLimits(two)); +ISODateTime js::temporal::RoundISODateTime(const ISODateTime& isoDateTime, + Increment increment, + TemporalUnit unit, + TemporalRoundingMode roundingMode) { + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); + + // Step 1. + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); + + // Step 2. + auto roundedTime = RoundTime(isoDateTime.time, increment, unit, roundingMode); + MOZ_ASSERT(0 <= roundedTime.days && roundedTime.days <= 1); // Step 3. - MOZ_ASSERT_IF( - one.date != two.date && largestUnit < TemporalUnit::Day, - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateUntil)); + auto balanceResult = BalanceISODate(isoDateTime.date, roundedTime.days); // Step 4. - auto timeDuration = DifferenceTime(one.time, two.time); - - // Step 5. - int32_t timeSign = NormalizedTimeDurationSign(timeDuration); - - // Step 6. - int32_t dateSign = CompareISODate(two.date, one.date); - - // Step 7. - auto adjustedDate = one.date; - - // Step 8. - if (timeSign == -dateSign) { - // Step 8.a. - adjustedDate = BalanceISODate(adjustedDate.year, adjustedDate.month, - adjustedDate.day - timeSign); - - // Step 8.b. - if (!Add24HourDaysToNormalizedTimeDuration(cx, timeDuration, -timeSign, - &timeDuration)) { - return false; - } - } - - MOZ_ASSERT(IsValidISODate(adjustedDate)); - MOZ_ASSERT(ISODateTimeWithinLimits(adjustedDate)); - - // Step 9. - const auto& date1 = adjustedDate; - - // Step 10. - const auto& date2 = two.date; - - // Step 11. - auto dateLargestUnit = std::min(TemporalUnit::Day, largestUnit); - - DateDuration dateDifference; - if (maybeOptions) { - // Step 12. - // - // The spec performs an unnecessary copy operation. As an optimization, we - // omit this copy. - auto untilOptions = maybeOptions; - - // Steps 13-14. - if (!DifferenceDate(cx, calendar, date1, date2, dateLargestUnit, - untilOptions, &dateDifference)) { - return false; - } - } else { - // Steps 12-14. - if (!DifferenceDate(cx, calendar, date1, date2, dateLargestUnit, - &dateDifference)) { - return false; - } - } - - // Step 15. - return CreateNormalizedDurationRecord(cx, dateDifference, timeDuration, - result); + return {balanceResult, roundedTime.time}; } /** - * RoundISODateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond, increment, unit, roundingMode ) + * DifferencePlainDateTimeWithRounding ( isoDateTime1, isoDateTime2, calendar, + * largestUnit, roundingIncrement, smallestUnit, roundingMode ) */ -PlainDateTime js::temporal::RoundISODateTime( - const PlainDateTime& dateTime, Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode) { - const auto& [date, time] = dateTime; +bool js::temporal::DifferencePlainDateTimeWithRounding( + JSContext* cx, const ISODateTime& isoDateTime1, + const ISODateTime& isoDateTime2, Handle calendar, + const DifferenceSettings& settings, InternalDuration* result) { + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime1)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime2)); // Step 1. - MOZ_ASSERT(IsValidISODateTime(dateTime)); + if (isoDateTime1 == isoDateTime2) { + // Step 1.a. + *result = {}; + return true; + } - // Step 2. - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); + // Step 2. (Not applicable in our implementation.) // Step 3. - auto roundedTime = RoundTime(time, increment, unit, roundingMode); - MOZ_ASSERT(0 <= roundedTime.days && roundedTime.days <= 1); + InternalDuration diff; + if (!DifferenceISODateTime(cx, isoDateTime1, isoDateTime2, calendar, + settings.largestUnit, &diff)) { + return false; + } // Step 4. - auto balanceResult = BalanceISODate(date.year, date.month, - date.day + int32_t(roundedTime.days)); + if (settings.smallestUnit == TemporalUnit::Nanosecond && + settings.roundingIncrement == Increment{1}) { + *result = diff; + return true; + } // Step 5. - return {balanceResult, roundedTime.time}; + auto destEpochNs = GetUTCEpochNanoseconds(isoDateTime2); + + // Step 6. + Rooted timeZone(cx, TimeZoneValue{}); + return RoundRelativeDuration( + cx, diff, destEpochNs, isoDateTime1, timeZone, calendar, + settings.largestUnit, settings.roundingIncrement, settings.smallestUnit, + settings.roundingMode, result); +} + +/** + * DifferencePlainDateTimeWithTotal ( isoDateTime1, isoDateTime2, calendar, unit + * ) + */ +bool js::temporal::DifferencePlainDateTimeWithTotal( + JSContext* cx, const ISODateTime& isoDateTime1, + const ISODateTime& isoDateTime2, Handle calendar, + TemporalUnit unit, double* result) { + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime1)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime2)); + + // Step 1. + if (isoDateTime1 == isoDateTime2) { + // Step 1.a. + *result = 0; + return true; + } + + // Step 2. (Not applicable in our implementation.) + + // Step 3. + InternalDuration diff; + if (!DifferenceISODateTime(cx, isoDateTime1, isoDateTime2, calendar, unit, + &diff)) { + return false; + } + + // Step 4. (Optimized to avoid GetUTCEpochNanoseconds for non-calendar units.) + if (unit > TemporalUnit::Day) { + MOZ_ASSERT(diff.date == DateDuration{}); + + // TotalRelativeDuration, steps 1-2. (Not applicable) + + // TotalRelativeDuration, step 3. + *result = TotalTimeDuration(diff.time, unit); + return true; + } else if (unit == TemporalUnit::Day) { + // TotalRelativeDuration, step 1. (Not applicable) + + // TotalRelativeDuration, step 2. + auto days = mozilla::AssertedCast(diff.date.days); + auto timeDuration = Add24HourDaysToTimeDuration(diff.time, days); + + // TotalRelativeDuration, step 3. + *result = TotalTimeDuration(timeDuration, unit); + return true; + } + + // Step 5. + auto destEpochNs = GetUTCEpochNanoseconds(isoDateTime2); + + // Step 6. + Rooted timeZone(cx, TimeZoneValue{}); + return TotalRelativeDuration(cx, diff, destEpochNs, isoDateTime1, timeZone, + calendar, unit, result); } /** @@ -885,26 +676,28 @@ PlainDateTime js::temporal::RoundISODateTime( static bool DifferenceTemporalPlainDateTime(JSContext* cx, TemporalDifference operation, const CallArgs& args) { - Rooted dateTime( + Rooted dateTime( cx, &args.thisv().toObject().as()); - // Step 1. (Not applicable in our implementation.) + // Step 1. + Rooted other(cx); + if (!ToTemporalDateTime(cx, args.get(0), &other)) { + return false; + } // Step 2. - Rooted other(cx); - if (!::ToTemporalDateTime(cx, args.get(0), &other)) { + if (!CalendarEquals(dateTime.calendar(), other.calendar())) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(dateTime.calendar()).data(), + CalendarIdentifier(other.calendar()).data()); return false; } - // Step 3. - if (!CalendarEqualsOrThrow(cx, dateTime.calendar(), other.calendar())) { - return false; - } - - // Steps 4-5. + // Steps 3-4. DifferenceSettings settings; - Rooted resolvedOptions(cx); if (args.hasDefined(1)) { + // Step 3. Rooted options( cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); if (!options) { @@ -912,19 +705,13 @@ static bool DifferenceTemporalPlainDateTime(JSContext* cx, } // Step 4. - resolvedOptions = SnapshotOwnProperties(cx, options); - if (!resolvedOptions) { - return false; - } - - // Step 5. if (!GetDifferenceSettings( - cx, operation, resolvedOptions, TemporalUnitGroup::DateTime, + cx, operation, options, TemporalUnitGroup::DateTime, TemporalUnit::Nanosecond, TemporalUnit::Day, &settings)) { return false; } } else { - // Steps 4-5. + // Steps 3-4. settings = { TemporalUnit::Nanosecond, TemporalUnit::Day, @@ -933,11 +720,8 @@ static bool DifferenceTemporalPlainDateTime(JSContext* cx, }; } - // Steps 6-7. - bool datePartsIdentical = dateTime.date() == other.date(); - - // Step 8. - if (datePartsIdentical && dateTime.time() == other.time()) { + // Step 5. + if (dateTime.dateTime() == other.dateTime()) { auto* obj = CreateTemporalDuration(cx, {}); if (!obj) { return false; @@ -947,110 +731,30 @@ static bool DifferenceTemporalPlainDateTime(JSContext* cx, return true; } - // Step 9. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, dateTime.calendar(), - { - CalendarMethod::DateAdd, - CalendarMethod::DateUntil, - }, - &calendar)) { + // Step 6. + InternalDuration internalDuration; + if (!DifferencePlainDateTimeWithRounding(cx, dateTime, other, + dateTime.calendar(), settings, + &internalDuration)) { return false; } + MOZ_ASSERT(IsValidDuration(internalDuration)); - // Step 10. - NormalizedDuration diff; - if (!::DifferenceISODateTime(cx, dateTime, other, calendar, - settings.largestUnit, resolvedOptions, &diff)) { + // Step 7. + Duration result; + if (!TemporalDurationFromInternal(cx, internalDuration, settings.largestUnit, + &result)) { return false; } + MOZ_ASSERT(IsValidDuration(result)); - // Step 11. - bool roundingGranularityIsNoop = - settings.smallestUnit == TemporalUnit::Nanosecond && - settings.roundingIncrement == Increment{1}; - - // Steps 12-13. - DateDuration balancedDate; - TimeDuration balancedTime; - if (!roundingGranularityIsNoop) { - // Step 12.a. - Rooted relativeTo( - cx, CreateTemporalDate(cx, dateTime.date(), dateTime.calendar())); - if (!relativeTo) { - return false; - } - - // Steps 12.b-c. - NormalizedDuration roundResult; - if (!temporal::RoundDuration(cx, diff, settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode, - relativeTo, calendar, &roundResult)) { - return false; - } - - // Step 12.d. - NormalizedTimeDuration withDays; - if (!Add24HourDaysToNormalizedTimeDuration( - cx, roundResult.time, roundResult.date.days, &withDays)) { - return false; - } - - // Step 12.e. - if (!BalanceTimeDuration(cx, withDays, settings.largestUnit, - &balancedTime)) { - return false; - } - - // Step 12.f. - auto toBalance = DateDuration{ - roundResult.date.years, - roundResult.date.months, - roundResult.date.weeks, - balancedTime.days, - }; - if (!temporal::BalanceDateDurationRelative( - cx, toBalance, settings.largestUnit, settings.smallestUnit, - relativeTo, calendar, &balancedDate)) { - return false; - } - } else { - // Step 13.a. - NormalizedTimeDuration withDays; - if (!Add24HourDaysToNormalizedTimeDuration(cx, diff.time, diff.date.days, - &withDays)) { - return false; - } - - // Step 13.b. - if (!BalanceTimeDuration(cx, withDays, settings.largestUnit, - &balancedTime)) { - return false; - } - - // Step 13.c. - balancedDate = { - diff.date.years, - diff.date.months, - diff.date.weeks, - balancedTime.days, - }; - } - MOZ_ASSERT(IsValidDuration(balancedDate)); - - // Step 14. - Duration duration = { - double(balancedDate.years), double(balancedDate.months), - double(balancedDate.weeks), double(balancedDate.days), - double(balancedTime.hours), double(balancedTime.minutes), - double(balancedTime.seconds), double(balancedTime.milliseconds), - balancedTime.microseconds, balancedTime.nanoseconds, - }; + // Step 8. if (operation == TemporalDifference::Since) { - duration = duration.negate(); + result = result.negate(); } - auto* obj = CreateTemporalDuration(cx, duration); + // Step 9. + auto* obj = CreateTemporalDuration(cx, result); if (!obj) { return false; } @@ -1059,64 +763,74 @@ static bool DifferenceTemporalPlainDateTime(JSContext* cx, return true; } -enum class PlainDateTimeDuration { Add, Subtract }; - /** - * AddDurationToOrSubtractDurationFromPlainDateTime ( operation, dateTime, - * temporalDurationLike, options ) + * AddDurationToDateTime ( operation, dateTime, temporalDurationLike, options ) */ -static bool AddDurationToOrSubtractDurationFromPlainDateTime( - JSContext* cx, PlainDateTimeDuration operation, const CallArgs& args) { - Rooted dateTime( +static bool AddDurationToDateTime(JSContext* cx, TemporalAddDuration operation, + const CallArgs& args) { + Rooted dateTime( cx, &args.thisv().toObject().as()); - // Step 1. (Not applicable in our implementation.) + // Step 1. + Duration duration; + if (!ToTemporalDuration(cx, args.get(0), &duration)) { + return false; + } // Step 2. - Duration duration; - if (!ToTemporalDurationRecord(cx, args.get(0), &duration)) { - return false; + if (operation == TemporalAddDuration::Subtract) { + duration = duration.negate(); } - // Step 3. - Rooted options(cx); + // Steps 3-4. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { - const char* name = - operation == PlainDateTimeDuration::Add ? "add" : "subtract"; - options = RequireObjectArg(cx, "options", name, args[1]); - } else { - options = NewPlainObjectWithProto(cx, nullptr); - } - if (!options) { - return false; - } + // Step 3. + Rooted options( + cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); + if (!options) { + return false; + } - // Step 4. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, dateTime.calendar(), - { - CalendarMethod::DateAdd, - }, - &calendar)) { - return false; + // Step 4. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } } // Step 5. - if (operation == PlainDateTimeDuration::Subtract) { - duration = duration.negate(); - } - auto normalized = CreateNormalizedDurationRecord(duration); + auto internalDuration = ToInternalDurationRecordWith24HourDays(duration); + MOZ_ASSERT(IsValidDuration(internalDuration)); - // Step 6 - PlainDateTime result; - if (!AddDateTime(cx, dateTime, calendar, normalized, options, &result)) { + // Step 6. + auto timeResult = AddTime(dateTime.time(), internalDuration.time); + + // Step 7. (Inlined AdjustDateDurationRecord) + if (std::abs(timeResult.days) > TimeDuration::max().toDays()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME); + return false; + } + auto dateDuration = DateDuration{ + internalDuration.date.years, + internalDuration.date.months, + internalDuration.date.weeks, + timeResult.days, + }; + MOZ_ASSERT(IsValidDuration(dateDuration)); + + // Step 8. + ISODate addedDate; + if (!CalendarDateAdd(cx, dateTime.calendar(), dateTime.date(), dateDuration, + overflow, &addedDate)) { return false; } - // Steps 7-8. + // Step 9. + auto result = ISODateTime{addedDate, timeResult.time}; MOZ_ASSERT(IsValidISODateTime(result)); - // Step 9. + // Step 10. auto* obj = CreateTemporalDateTime(cx, result, dateTime.calendar()); if (!obj) { return false; @@ -1128,8 +842,8 @@ static bool AddDurationToOrSubtractDurationFromPlainDateTime( /** * Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , - * second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] - * ] ] ] ] ) + * second [ , millisecond [ , microsecond [ , nanosecond [ , calendar ] ] ] ] ] + * ] ] ) */ static bool PlainDateTimeConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1205,16 +919,48 @@ static bool PlainDateTimeConstructor(JSContext* cx, unsigned argc, Value* vp) { } } - // Step 11. - Rooted calendar(cx); - if (!ToTemporalCalendarWithISODefault(cx, args.get(9), &calendar)) { + // Steps 11-13. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (args.hasDefined(9)) { + // Step 12. + if (!args[9].isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args[9], + nullptr, "not a string"); + return false; + } + + // Step 13. + Rooted calendarString(cx, args[9].toString()); + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } + } + + // Step 14. + if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { return false; } - // Step 12. - auto* temporalDateTime = CreateTemporalDateTime( - cx, args, isoYear, isoMonth, isoDay, hour, minute, second, millisecond, - microsecond, nanosecond, calendar); + // Step 15. + auto isoDate = ISODate{int32_t(isoYear), int32_t(isoMonth), int32_t(isoDay)}; + + // Step 16. + if (!ThrowIfInvalidTime(cx, hour, minute, second, millisecond, microsecond, + nanosecond)) { + return false; + } + + // Step 17. + auto time = + Time{int32_t(hour), int32_t(minute), int32_t(second), + int32_t(millisecond), int32_t(microsecond), int32_t(nanosecond)}; + + // Step 18. + auto isoDateTime = ISODateTime{isoDate, time}; + + // Step 19. + auto* temporalDateTime = + CreateTemporalDateTime(cx, args, isoDateTime, calendar); if (!temporalDateTime) { return false; } @@ -1230,46 +976,12 @@ static bool PlainDateTime_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "from", args[1]); - if (!options) { - return false; - } + Rooted dateTime(cx); + if (!ToTemporalDateTime(cx, args.get(0), args.get(1), &dateTime)) { + return false; } - // Step 2. - if (args.get(0).isObject()) { - JSObject* item = &args[0].toObject(); - if (auto* temporalDateTime = item->maybeUnwrapIf()) { - auto dateTime = ToPlainDateTime(temporalDateTime); - - Rooted calendar(cx, temporalDateTime->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - if (options) { - // Step 2.a. - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, options, &ignored)) { - return false; - } - } - - // Step 2.b. - auto* result = CreateTemporalDateTime(cx, dateTime, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; - } - } - - // Step 3. - auto result = ToTemporalDateTime(cx, args.get(0), options); + auto* result = CreateTemporalDateTime(cx, dateTime); if (!result) { return false; } @@ -1285,13 +997,13 @@ static bool PlainDateTime_compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - PlainDateTime one; + Rooted one(cx); if (!ToTemporalDateTime(cx, args.get(0), &one)) { return false; } // Step 2. - PlainDateTime two; + Rooted two(cx); if (!ToTemporalDateTime(cx, args.get(1), &two)) { return false; } @@ -1308,13 +1020,13 @@ static bool PlainDateTime_calendarId(JSContext* cx, const CallArgs& args) { auto* dateTime = &args.thisv().toObject().as(); // Step 3. - Rooted calendar(cx, dateTime->calendar()); - auto* calendarId = ToTemporalCalendarIdentifier(cx, calendar); - if (!calendarId) { + auto* str = + NewStringCopy(cx, CalendarIdentifier(dateTime->calendar())); + if (!str) { return false; } - args.rval().setString(calendarId); + args.rval().setString(str); return true; } @@ -1332,13 +1044,11 @@ static bool PlainDateTime_calendarId(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.era */ static bool PlainDateTime_era(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarEra(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarEra(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1354,13 +1064,11 @@ static bool PlainDateTime_era(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.eraYear */ static bool PlainDateTime_eraYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Steps 4-6. - return CalendarEraYear(cx, calendar, dateTime, args.rval()); + // Steps 3-5. + return CalendarEraYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1376,13 +1084,11 @@ static bool PlainDateTime_eraYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.year */ static bool PlainDateTime_year(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarYear(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1398,13 +1104,11 @@ static bool PlainDateTime_year(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.month */ static bool PlainDateTime_month(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarMonth(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarMonth(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1420,13 +1124,11 @@ static bool PlainDateTime_month(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.monthCode */ static bool PlainDateTime_monthCode(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarMonthCode(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarMonthCode(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1443,13 +1145,11 @@ static bool PlainDateTime_monthCode(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.day */ static bool PlainDateTime_day(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarDay(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarDay(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1467,7 +1167,7 @@ static bool PlainDateTime_day(JSContext* cx, unsigned argc, Value* vp) { static bool PlainDateTime_hour(JSContext* cx, const CallArgs& args) { // Step 3. auto* dateTime = &args.thisv().toObject().as(); - args.rval().setInt32(dateTime->isoHour()); + args.rval().setInt32(dateTime->time().hour); return true; } @@ -1486,7 +1186,7 @@ static bool PlainDateTime_hour(JSContext* cx, unsigned argc, Value* vp) { static bool PlainDateTime_minute(JSContext* cx, const CallArgs& args) { // Step 3. auto* dateTime = &args.thisv().toObject().as(); - args.rval().setInt32(dateTime->isoMinute()); + args.rval().setInt32(dateTime->time().minute); return true; } @@ -1505,7 +1205,7 @@ static bool PlainDateTime_minute(JSContext* cx, unsigned argc, Value* vp) { static bool PlainDateTime_second(JSContext* cx, const CallArgs& args) { // Step 3. auto* dateTime = &args.thisv().toObject().as(); - args.rval().setInt32(dateTime->isoSecond()); + args.rval().setInt32(dateTime->time().second); return true; } @@ -1524,7 +1224,7 @@ static bool PlainDateTime_second(JSContext* cx, unsigned argc, Value* vp) { static bool PlainDateTime_millisecond(JSContext* cx, const CallArgs& args) { // Step 3. auto* dateTime = &args.thisv().toObject().as(); - args.rval().setInt32(dateTime->isoMillisecond()); + args.rval().setInt32(dateTime->time().millisecond); return true; } @@ -1544,7 +1244,7 @@ static bool PlainDateTime_millisecond(JSContext* cx, unsigned argc, Value* vp) { static bool PlainDateTime_microsecond(JSContext* cx, const CallArgs& args) { // Step 3. auto* dateTime = &args.thisv().toObject().as(); - args.rval().setInt32(dateTime->isoMicrosecond()); + args.rval().setInt32(dateTime->time().microsecond); return true; } @@ -1564,7 +1264,7 @@ static bool PlainDateTime_microsecond(JSContext* cx, unsigned argc, Value* vp) { static bool PlainDateTime_nanosecond(JSContext* cx, const CallArgs& args) { // Step 3. auto* dateTime = &args.thisv().toObject().as(); - args.rval().setInt32(dateTime->isoNanosecond()); + args.rval().setInt32(dateTime->time().nanosecond); return true; } @@ -1582,13 +1282,11 @@ static bool PlainDateTime_nanosecond(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.dayOfWeek */ static bool PlainDateTime_dayOfWeek(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarDayOfWeek(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarDayOfWeek(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1605,13 +1303,11 @@ static bool PlainDateTime_dayOfWeek(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.dayOfYear */ static bool PlainDateTime_dayOfYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarDayOfYear(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarDayOfYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1628,13 +1324,11 @@ static bool PlainDateTime_dayOfYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.weekOfYear */ static bool PlainDateTime_weekOfYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Steps 4-6. - return CalendarWeekOfYear(cx, calendar, dateTime, args.rval()); + // Steps 3-5. + return CalendarWeekOfYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1651,13 +1345,11 @@ static bool PlainDateTime_weekOfYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.yearOfWeek */ static bool PlainDateTime_yearOfWeek(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Steps 4-6. - return CalendarYearOfWeek(cx, calendar, dateTime, args.rval()); + // Steps 3-5. + return CalendarYearOfWeek(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1674,13 +1366,11 @@ static bool PlainDateTime_yearOfWeek(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.daysInWeek */ static bool PlainDateTime_daysInWeek(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarDaysInWeek(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarDaysInWeek(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1697,13 +1387,11 @@ static bool PlainDateTime_daysInWeek(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.daysInMonth */ static bool PlainDateTime_daysInMonth(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarDaysInMonth(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarDaysInMonth(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1720,13 +1408,11 @@ static bool PlainDateTime_daysInMonth(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.daysInYear */ static bool PlainDateTime_daysInYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarDaysInYear(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarDaysInYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1743,13 +1429,11 @@ static bool PlainDateTime_daysInYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainDateTime.prototype.monthsInYear */ static bool PlainDateTime_monthsInYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarMonthsInYear(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarMonthsInYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1767,13 +1451,11 @@ static bool PlainDateTime_monthsInYear(JSContext* cx, unsigned argc, * get Temporal.PlainDateTime.prototype.inLeapYear */ static bool PlainDateTime_inLeapYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted dateTime( - cx, &args.thisv().toObject().as()); + auto* dateTime = &args.thisv().toObject().as(); Rooted calendar(cx, dateTime->calendar()); - // Step 4. - return CalendarInLeapYear(cx, calendar, dateTime, args.rval()); + // Step 3. + return CalendarInLeapYear(cx, calendar, dateTime->date(), args.rval()); } /** @@ -1790,7 +1472,7 @@ static bool PlainDateTime_inLeapYear(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainDateTime.prototype.with ( temporalDateTimeLike [ , options ] ) */ static bool PlainDateTime_with(JSContext* cx, const CallArgs& args) { - Rooted dateTime( + Rooted dateTime( cx, &args.thisv().toObject().as()); // Step 3. @@ -1804,118 +1486,71 @@ static bool PlainDateTime_with(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted resolvedOptions(cx); + auto calendar = dateTime.calendar(); + + // Step 5. + Rooted fields(cx); + if (!ISODateToFields(cx, dateTime, &fields)) { + return false; + } + + // Steps 6-11. + fields.setHour(dateTime.time().hour); + fields.setMinute(dateTime.time().minute); + fields.setSecond(dateTime.time().second); + fields.setMillisecond(dateTime.time().millisecond); + fields.setMicrosecond(dateTime.time().microsecond); + fields.setNanosecond(dateTime.time().nanosecond); + + // Step 12. + Rooted partialDateTime(cx); + if (!PreparePartialCalendarFields(cx, calendar, temporalDateTimeLike, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + CalendarField::Hour, + CalendarField::Minute, + CalendarField::Second, + CalendarField::Millisecond, + CalendarField::Microsecond, + CalendarField::Nanosecond, + }, + &partialDateTime)) { + return false; + } + MOZ_ASSERT(!partialDateTime.keys().isEmpty()); + + // Step 13. + fields = CalendarMergeFields(calendar, fields, partialDateTime); + + // Steps 14-15. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { + // Step 14. Rooted options(cx, RequireObjectArg(cx, "options", "with", args[1])); if (!options) { return false; } - resolvedOptions = SnapshotOwnProperties(cx, options); - } else { - resolvedOptions = NewPlainObjectWithProto(cx, nullptr); - } - if (!resolvedOptions) { - return false; - } - // Step 5. - Rooted calendarValue(cx, dateTime->calendar()); - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - CalendarMethod::MergeFields, - }, - &calendar)) { - return false; - } - - // Step 6. - Rooted fields(cx); - JS::RootedVector fieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, dateTime, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - &fields, &fieldNames)) { - return false; - } - - // Steps 7-12. - struct TimeField { - using FieldName = ImmutableTenuredPtr JSAtomState::*; - - FieldName name; - int32_t value; - } timeFields[] = { - {&JSAtomState::hour, dateTime->isoHour()}, - {&JSAtomState::minute, dateTime->isoMinute()}, - {&JSAtomState::second, dateTime->isoSecond()}, - {&JSAtomState::millisecond, dateTime->isoMillisecond()}, - {&JSAtomState::microsecond, dateTime->isoMicrosecond()}, - {&JSAtomState::nanosecond, dateTime->isoNanosecond()}, - }; - - Rooted timeFieldValue(cx); - for (const auto& timeField : timeFields) { - Handle name = cx->names().*(timeField.name); - timeFieldValue.setInt32(timeField.value); - - if (!DefineDataProperty(cx, fields, name, timeFieldValue)) { + // Step 15. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { return false; } } - // Step 13. - if (!AppendSorted(cx, fieldNames.get(), - { - TemporalField::Hour, - TemporalField::Microsecond, - TemporalField::Millisecond, - TemporalField::Minute, - TemporalField::Nanosecond, - TemporalField::Second, - })) { - return false; - } - - // Step 14. - Rooted partialDateTime( - cx, PreparePartialTemporalFields(cx, temporalDateTimeLike, fieldNames)); - if (!partialDateTime) { - return false; - } - - // Step 15. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, fields, partialDateTime)); - if (!mergedFields) { - return false; - } - // Step 16. - fields = PrepareTemporalFields(cx, mergedFields, fieldNames); - if (!fields) { - return false; - } - - // Step 17. - PlainDateTime result; - if (!InterpretTemporalDateTimeFields(cx, calendar, fields, resolvedOptions, + ISODateTime result; + if (!InterpretTemporalDateTimeFields(cx, calendar, fields, overflow, &result)) { return false; } - - // Steps 18-19. MOZ_ASSERT(IsValidISODateTime(result)); - // Step 20. - auto* obj = CreateTemporalDateTime(cx, result, calendar.receiver()); + // Step 21. + auto* obj = CreateTemporalDateTime(cx, result, calendar); if (!obj) { return false; } @@ -1938,11 +1573,11 @@ static bool PlainDateTime_with(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDateTime_withPlainTime(JSContext* cx, const CallArgs& args) { auto* temporalDateTime = &args.thisv().toObject().as(); - auto date = ToPlainDate(temporalDateTime); + auto date = temporalDateTime->date(); Rooted calendar(cx, temporalDateTime->calendar()); // Step 3. (Inlined ToTemporalTimeOrMidnight) - PlainTime time = {}; + Time time = {}; if (args.hasDefined(0)) { if (!ToTemporalTime(cx, args[0], &time)) { return false; @@ -1950,7 +1585,10 @@ static bool PlainDateTime_withPlainTime(JSContext* cx, const CallArgs& args) { } // Step 4. - auto* obj = CreateTemporalDateTime(cx, {date, time}, calendar); + auto isoDateTime = ISODateTime{date, time}; + + // Step 5. + auto* obj = CreateTemporalDateTime(cx, isoDateTime, calendar); if (!obj) { return false; } @@ -1970,53 +1608,12 @@ static bool PlainDateTime_withPlainTime(JSContext* cx, unsigned argc, cx, args); } -/** - * Temporal.PlainDateTime.prototype.withPlainDate ( plainDateLike ) - */ -static bool PlainDateTime_withPlainDate(JSContext* cx, const CallArgs& args) { - auto* temporalDateTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalDateTime); - Rooted calendar(cx, temporalDateTime->calendar()); - - // Step 3. - Rooted plainDate(cx); - if (!ToTemporalDate(cx, args.get(0), &plainDate)) { - return false; - } - auto date = plainDate.date(); - - // Step 4. - if (!ConsolidateCalendars(cx, calendar, plainDate.calendar(), &calendar)) { - return false; - } - - // Step 5. - auto* obj = CreateTemporalDateTime(cx, {date, time}, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDateTime.prototype.withPlainDate ( plainDateLike ) - */ -static bool PlainDateTime_withPlainDate(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - /** * Temporal.PlainDateTime.prototype.withCalendar ( calendar ) */ static bool PlainDateTime_withCalendar(JSContext* cx, const CallArgs& args) { auto* temporalDateTime = &args.thisv().toObject().as(); - auto dateTime = ToPlainDateTime(temporalDateTime); + auto dateTime = temporalDateTime->dateTime(); // Step 3. Rooted calendar(cx); @@ -2050,8 +1647,7 @@ static bool PlainDateTime_withCalendar(JSContext* cx, unsigned argc, */ static bool PlainDateTime_add(JSContext* cx, const CallArgs& args) { // Step 3. - return AddDurationToOrSubtractDurationFromPlainDateTime( - cx, PlainDateTimeDuration::Add, args); + return AddDurationToDateTime(cx, TemporalAddDuration::Add, args); } /** @@ -2069,8 +1665,7 @@ static bool PlainDateTime_add(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDateTime_subtract(JSContext* cx, const CallArgs& args) { // Step 3. - return AddDurationToOrSubtractDurationFromPlainDateTime( - cx, PlainDateTimeDuration::Subtract, args); + return AddDurationToDateTime(cx, TemporalAddDuration::Subtract, args); } /** @@ -2123,7 +1718,7 @@ static bool PlainDateTime_since(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDateTime_round(JSContext* cx, const CallArgs& args) { auto* temporalDateTime = &args.thisv().toObject().as(); - auto dateTime = ToPlainDateTime(temporalDateTime); + auto dateTime = temporalDateTime->dateTime(); Rooted calendar(cx, temporalDateTime->calendar()); // Steps 3-12. @@ -2234,20 +1829,18 @@ static bool PlainDateTime_round(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDateTime_equals(JSContext* cx, const CallArgs& args) { auto* temporalDateTime = &args.thisv().toObject().as(); - auto dateTime = ToPlainDateTime(temporalDateTime); + auto dateTime = temporalDateTime->dateTime(); Rooted calendar(cx, temporalDateTime->calendar()); // Step 3. - Rooted other(cx); - if (!::ToTemporalDateTime(cx, args.get(0), &other)) { + Rooted other(cx); + if (!ToTemporalDateTime(cx, args.get(0), &other)) { return false; } - // Steps 4-13. - bool equals = dateTime == other.dateTime(); - if (equals && !CalendarEquals(cx, calendar, other.calendar(), &equals)) { - return false; - } + // Steps 4-5. + bool equals = dateTime == other.dateTime() && + CalendarEquals(calendar, other.calendar()); args.rval().setBoolean(equals); return true; @@ -2267,7 +1860,7 @@ static bool PlainDateTime_equals(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainDateTime_toString(JSContext* cx, const CallArgs& args) { auto* dateTime = &args.thisv().toObject().as(); - auto dt = ToPlainDateTime(dateTime); + auto dt = dateTime->dateTime(); Rooted calendar(cx, dateTime->calendar()); SecondsStringPrecision precision = {Precision::Auto(), @@ -2322,8 +1915,15 @@ static bool PlainDateTime_toString(JSContext* cx, const CallArgs& args) { RoundISODateTime(dt, precision.increment, precision.unit, roundingMode); // Step 12. - JSString* str = ::TemporalDateTimeToString(cx, result, calendar, - precision.precision, showCalendar); + if (!ISODateTimeWithinLimits(result)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } + + // Step 13. + JSString* str = ISODateTimeToString(cx, result, calendar, precision.precision, + showCalendar); if (!str) { return false; } @@ -2346,19 +1946,10 @@ static bool PlainDateTime_toString(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainDateTime.prototype.toLocaleString ( [ locales [ , options ] ] ) */ static bool PlainDateTime_toLocaleString(JSContext* cx, const CallArgs& args) { - auto* dateTime = &args.thisv().toObject().as(); - auto dt = ToPlainDateTime(dateTime); - Rooted calendar(cx, dateTime->calendar()); - - // Step 3. - JSString* str = ::TemporalDateTimeToString( - cx, dt, calendar, Precision::Auto(), ShowCalendar::Auto); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-4. + Handle required = cx->names().any; + Handle defaults = cx->names().all; + return TemporalObjectToLocaleString(cx, args, required, defaults); } /** @@ -2377,12 +1968,12 @@ static bool PlainDateTime_toLocaleString(JSContext* cx, unsigned argc, */ static bool PlainDateTime_toJSON(JSContext* cx, const CallArgs& args) { auto* dateTime = &args.thisv().toObject().as(); - auto dt = ToPlainDateTime(dateTime); + auto dt = dateTime->dateTime(); Rooted calendar(cx, dateTime->calendar()); // Step 3. - JSString* str = ::TemporalDateTimeToString( - cx, dt, calendar, Precision::Auto(), ShowCalendar::Auto); + JSString* str = ISODateTimeToString(cx, dt, calendar, Precision::Auto(), + ShowCalendar::Auto); if (!str) { return false; } @@ -2409,136 +2000,14 @@ static bool PlainDateTime_valueOf(JSContext* cx, unsigned argc, Value* vp) { return false; } -/** - * Temporal.PlainDateTime.prototype.getISOFields ( ) - */ -static bool PlainDateTime_getISOFields(JSContext* cx, const CallArgs& args) { - auto* temporalDateTime = &args.thisv().toObject().as(); - auto dateTime = ToPlainDateTime(temporalDateTime); - auto calendar = temporalDateTime->calendar(); - - // Step 3. - Rooted fields(cx, IdValueVector(cx)); - - // Step 4. - Rooted cal(cx); - if (!ToTemporalCalendar(cx, calendar, &cal)) { - return false; - } - if (!fields.emplaceBack(NameToId(cx->names().calendar), cal)) { - return false; - } - - // Step 5. - if (!fields.emplaceBack(NameToId(cx->names().isoDay), - Int32Value(dateTime.date.day))) { - return false; - } - - // Step 6. - if (!fields.emplaceBack(NameToId(cx->names().isoHour), - Int32Value(dateTime.time.hour))) { - return false; - } - - // Step 7. - if (!fields.emplaceBack(NameToId(cx->names().isoMicrosecond), - Int32Value(dateTime.time.microsecond))) { - return false; - } - - // Step 8. - if (!fields.emplaceBack(NameToId(cx->names().isoMillisecond), - Int32Value(dateTime.time.millisecond))) { - return false; - } - - // Step 9. - if (!fields.emplaceBack(NameToId(cx->names().isoMinute), - Int32Value(dateTime.time.minute))) { - return false; - } - - // Step 10. - if (!fields.emplaceBack(NameToId(cx->names().isoMonth), - Int32Value(dateTime.date.month))) { - return false; - } - - // Step 11. - if (!fields.emplaceBack(NameToId(cx->names().isoNanosecond), - Int32Value(dateTime.time.nanosecond))) { - return false; - } - - // Step 12. - if (!fields.emplaceBack(NameToId(cx->names().isoSecond), - Int32Value(dateTime.time.second))) { - return false; - } - - // Step 13. - if (!fields.emplaceBack(NameToId(cx->names().isoYear), - Int32Value(dateTime.date.year))) { - return false; - } - - // Step 14. - auto* obj = NewPlainObjectWithUniqueNames(cx, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDateTime.prototype.getISOFields ( ) - */ -static bool PlainDateTime_getISOFields(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.PlainDateTime.prototype.getCalendar ( ) - */ -static bool PlainDateTime_getCalendar(JSContext* cx, const CallArgs& args) { - auto* temporalDateTime = &args.thisv().toObject().as(); - Rooted calendar(cx, temporalDateTime->calendar()); - - // Step 3. - auto* obj = ToTemporalCalendarObject(cx, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDateTime.prototype.getCalendar ( ) - */ -static bool PlainDateTime_getCalendar(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - /** * Temporal.PlainDateTime.prototype.toZonedDateTime ( temporalTimeZoneLike [ , * options ] ) */ static bool PlainDateTime_toZonedDateTime(JSContext* cx, const CallArgs& args) { - Rooted dateTime( - cx, &args.thisv().toObject().as()); - Rooted calendar(cx, dateTime->calendar()); + auto* temporalDateTime = &args.thisv().toObject().as(); + auto isoDateTime = temporalDateTime->dateTime(); + Rooted calendar(cx, temporalDateTime->calendar()); // Step 3. Rooted timeZone(cx); @@ -2561,14 +2030,15 @@ static bool PlainDateTime_toZonedDateTime(JSContext* cx, const CallArgs& args) { } } - // Steps 6-7. - Instant instant; - if (!GetInstantFor(cx, timeZone, dateTime, disambiguation, &instant)) { + // Step 6. + EpochNanoseconds epochNs; + if (!GetEpochNanosecondsFor(cx, timeZone, isoDateTime, disambiguation, + &epochNs)) { return false; } - // Step 8. - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); + // Step 7. + auto* result = CreateTemporalZonedDateTime(cx, epochNs, timeZone, calendar); if (!result) { return false; } @@ -2597,7 +2067,7 @@ static bool PlainDateTime_toPlainDate(JSContext* cx, const CallArgs& args) { Rooted calendar(cx, dateTime->calendar()); // Step 3. - auto* obj = CreateTemporalDate(cx, ToPlainDate(dateTime), calendar); + auto* obj = CreateTemporalDate(cx, dateTime->date(), calendar); if (!obj) { return false; } @@ -2616,105 +2086,6 @@ static bool PlainDateTime_toPlainDate(JSContext* cx, unsigned argc, Value* vp) { args); } -/** - * Temporal.PlainDateTime.prototype.toPlainYearMonth ( ) - */ -static bool PlainDateTime_toPlainYearMonth(JSContext* cx, - const CallArgs& args) { - Rooted dateTime( - cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, dateTime->calendar()); - - // Step 3. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return false; - } - - // Step 4. - Rooted fields( - cx, - PrepareCalendarFields(cx, calendar, dateTime, - {CalendarField::MonthCode, CalendarField::Year})); - if (!fields) { - return false; - } - - // Steps 5-6. - auto obj = CalendarYearMonthFromFields(cx, calendar, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDateTime.prototype.toPlainYearMonth ( ) - */ -static bool PlainDateTime_toPlainYearMonth(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.PlainDateTime.prototype.toPlainMonthDay ( ) - */ -static bool PlainDateTime_toPlainMonthDay(JSContext* cx, const CallArgs& args) { - Rooted dateTime( - cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, dateTime->calendar()); - - // Step 3. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::MonthDayFromFields, - }, - &calendar)) { - return false; - } - - // Step 4. - Rooted fields( - cx, - PrepareCalendarFields(cx, calendar, dateTime, - {CalendarField::Day, CalendarField::MonthCode})); - if (!fields) { - return false; - } - - // Steps 5-6. - auto obj = CalendarMonthDayFromFields(cx, calendar, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainDateTime.prototype.toPlainMonthDay ( ) - */ -static bool PlainDateTime_toPlainMonthDay(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - /** * Temporal.PlainDateTime.prototype.toPlainTime ( ) */ @@ -2722,7 +2093,7 @@ static bool PlainDateTime_toPlainTime(JSContext* cx, const CallArgs& args) { auto* dateTime = &args.thisv().toObject().as(); // Step 3. - auto* obj = CreateTemporalTime(cx, ToPlainTime(dateTime)); + auto* obj = CreateTemporalTime(cx, dateTime->time()); if (!obj) { return false; } @@ -2760,7 +2131,6 @@ static const JSFunctionSpec PlainDateTime_methods[] = { static const JSFunctionSpec PlainDateTime_prototype_methods[] = { JS_FN("with", PlainDateTime_with, 1, 0), JS_FN("withPlainTime", PlainDateTime_withPlainTime, 0, 0), - JS_FN("withPlainDate", PlainDateTime_withPlainDate, 1, 0), JS_FN("withCalendar", PlainDateTime_withCalendar, 1, 0), JS_FN("add", PlainDateTime_add, 1, 0), JS_FN("subtract", PlainDateTime_subtract, 1, 0), @@ -2774,11 +2144,7 @@ static const JSFunctionSpec PlainDateTime_prototype_methods[] = { JS_FN("valueOf", PlainDateTime_valueOf, 0, 0), JS_FN("toZonedDateTime", PlainDateTime_toZonedDateTime, 1, 0), JS_FN("toPlainDate", PlainDateTime_toPlainDate, 0, 0), - JS_FN("toPlainYearMonth", PlainDateTime_toPlainYearMonth, 0, 0), - JS_FN("toPlainMonthDay", PlainDateTime_toPlainMonthDay, 0, 0), JS_FN("toPlainTime", PlainDateTime_toPlainTime, 0, 0), - JS_FN("getISOFields", PlainDateTime_getISOFields, 0, 0), - JS_FN("getCalendar", PlainDateTime_getCalendar, 0, 0), JS_FS_END, }; diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.h index 1ae80a45089..69f9fe974ea 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainDateTime.h @@ -9,12 +9,12 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/Casting.h" #include #include "builtin/temporal/Calendar.h" #include "builtin/temporal/TemporalTypes.h" -#include "builtin/temporal/Wrapped.h" #include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" @@ -24,7 +24,6 @@ class JS_PUBLIC_API JSTracer; namespace js { struct ClassSpec; -class PlainObject; } // namespace js namespace js::temporal { @@ -34,45 +33,32 @@ class PlainDateTimeObject : public NativeObject { static const JSClass class_; static const JSClass& protoClass_; - // TODO: Consider compacting fields to reduce object size. - // - // See also PlainDateObject and PlainTimeObject. + static constexpr uint32_t PACKED_DATE_SLOT = 0; + static constexpr uint32_t PACKED_TIME_SLOT = 1; + static constexpr uint32_t CALENDAR_SLOT = 2; + static constexpr uint32_t SLOT_COUNT = 3; - static constexpr uint32_t ISO_YEAR_SLOT = 0; - static constexpr uint32_t ISO_MONTH_SLOT = 1; - static constexpr uint32_t ISO_DAY_SLOT = 2; - static constexpr uint32_t ISO_HOUR_SLOT = 3; - static constexpr uint32_t ISO_MINUTE_SLOT = 4; - static constexpr uint32_t ISO_SECOND_SLOT = 5; - static constexpr uint32_t ISO_MILLISECOND_SLOT = 6; - static constexpr uint32_t ISO_MICROSECOND_SLOT = 7; - static constexpr uint32_t ISO_NANOSECOND_SLOT = 8; - static constexpr uint32_t CALENDAR_SLOT = 9; - static constexpr uint32_t SLOT_COUNT = 10; - - int32_t isoYear() const { return getFixedSlot(ISO_YEAR_SLOT).toInt32(); } - - int32_t isoMonth() const { return getFixedSlot(ISO_MONTH_SLOT).toInt32(); } - - int32_t isoDay() const { return getFixedSlot(ISO_DAY_SLOT).toInt32(); } - - int32_t isoHour() const { return getFixedSlot(ISO_HOUR_SLOT).toInt32(); } - - int32_t isoMinute() const { return getFixedSlot(ISO_MINUTE_SLOT).toInt32(); } - - int32_t isoSecond() const { return getFixedSlot(ISO_SECOND_SLOT).toInt32(); } - - int32_t isoMillisecond() const { - return getFixedSlot(ISO_MILLISECOND_SLOT).toInt32(); + /** + * Extract the date fields from this PlainDateTime object. + */ + ISODate date() const { + auto packed = PackedDate{getFixedSlot(PACKED_DATE_SLOT).toPrivateUint32()}; + return PackedDate::unpack(packed); } - int32_t isoMicrosecond() const { - return getFixedSlot(ISO_MICROSECOND_SLOT).toInt32(); + /** + * Extract the time fields from this PlainDateTime object. + */ + Time time() const { + auto packed = PackedTime{mozilla::BitwiseCast( + getFixedSlot(PACKED_TIME_SLOT).toDouble())}; + return PackedTime::unpack(packed); } - int32_t isoNanosecond() const { - return getFixedSlot(ISO_NANOSECOND_SLOT).toInt32(); - } + /** + * Extract the date-time fields from this PlainDateTime object. + */ + ISODateTime dateTime() const { return {date(), time()}; } CalendarValue calendar() const { return CalendarValue(getFixedSlot(CALENDAR_SLOT)); @@ -82,128 +68,48 @@ class PlainDateTimeObject : public NativeObject { static const ClassSpec classSpec_; }; -/** - * Extract the date fields from the PlainDateTime object. - */ -inline PlainDate ToPlainDate(const PlainDateTimeObject* dateTime) { - return {dateTime->isoYear(), dateTime->isoMonth(), dateTime->isoDay()}; -} - -/** - * Extract the time fields from the PlainDateTime object. - */ -inline PlainTime ToPlainTime(const PlainDateTimeObject* dateTime) { - return {dateTime->isoHour(), dateTime->isoMinute(), - dateTime->isoSecond(), dateTime->isoMillisecond(), - dateTime->isoMicrosecond(), dateTime->isoNanosecond()}; -} - -/** - * Extract the date-time fields from the PlainDateTime object. - */ -inline PlainDateTime ToPlainDateTime(const PlainDateTimeObject* dateTime) { - return {ToPlainDate(dateTime), ToPlainTime(dateTime)}; -} - +struct DifferenceSettings; class Increment; +class CalendarFields; +enum class TemporalOverflow; enum class TemporalRoundingMode; enum class TemporalUnit; #ifdef DEBUG /** - * IsValidISODateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond ) + * IsValidISODate ( year, month, day ) + * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -bool IsValidISODateTime(const PlainDateTime& dateTime); +bool IsValidISODateTime(const ISODateTime& isoDateTime); #endif /** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) + * ISODateTimeWithinLimits ( isoDateTime ) */ -bool ISODateTimeWithinLimits(const PlainDateTime& dateTime); +bool ISODateTimeWithinLimits(const ISODateTime& isoDateTime); -/** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -bool ISODateTimeWithinLimits(const PlainDate& date); - -/** - * ISODateTimeWithinLimits ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond ) - */ -bool ISODateTimeWithinLimits(double year, double month, double day); - -/** - * CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar [ , newTarget ] ) - */ -PlainDateTimeObject* CreateTemporalDateTime(JSContext* cx, - const PlainDateTime& dateTime, - JS::Handle calendar); - -/** - * ToTemporalDateTime ( item [ , options ] ) - */ -Wrapped ToTemporalDateTime(JSContext* cx, - JS::Handle item); - -/** - * ToTemporalDateTime ( item [ , options ] ) - */ -bool ToTemporalDateTime(JSContext* cx, JS::Handle item, - PlainDateTime* result); - -/** - * InterpretTemporalDateTimeFields ( calendarRec, fields, options ) - */ -bool InterpretTemporalDateTimeFields(JSContext* cx, - JS::Handle calendar, - JS::Handle fields, - JS::Handle options, - PlainDateTime* result); - -/** - * InterpretTemporalDateTimeFields ( calendarRec, fields, options ) - */ -bool InterpretTemporalDateTimeFields(JSContext* cx, - JS::Handle calendar, - JS::Handle fields, - PlainDateTime* result); - -/** - * RoundISODateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond, increment, unit, roundingMode ) - */ -PlainDateTime RoundISODateTime(const PlainDateTime& dateTime, - Increment increment, TemporalUnit unit, - TemporalRoundingMode roundingMode); - -class MOZ_STACK_CLASS PlainDateTimeWithCalendar final { - PlainDateTime dateTime_; +class MOZ_STACK_CLASS PlainDateTime final { + ISODateTime dateTime_; CalendarValue calendar_; public: - PlainDateTimeWithCalendar() = default; + PlainDateTime() = default; - PlainDateTimeWithCalendar(const PlainDateTime& dateTime, - const CalendarValue& calendar) + PlainDateTime(const ISODateTime& dateTime, const CalendarValue& calendar) : dateTime_(dateTime), calendar_(calendar) { MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); } - explicit PlainDateTimeWithCalendar(const PlainDateTimeObject* dateTime) - : PlainDateTimeWithCalendar(ToPlainDateTime(dateTime), - dateTime->calendar()) {} + explicit PlainDateTime(const PlainDateTimeObject* dateTime) + : PlainDateTime(dateTime->dateTime(), dateTime->calendar()) {} const auto& dateTime() const { return dateTime_; } const auto& date() const { return dateTime_.date; } const auto& time() const { return dateTime_.time; } const auto& calendar() const { return calendar_; } - // Allow implicit conversion to a calendar-less PlainDateTime. - operator const PlainDateTime&() const { return dateTime(); } + // Allow implicit conversion to an ISODateTime. + operator const ISODateTime&() const { return dateTime(); } void trace(JSTracer* trc) { calendar_.trace(trc); } @@ -211,27 +117,54 @@ class MOZ_STACK_CLASS PlainDateTimeWithCalendar final { }; /** - * Extract the date-time fields from the PlainDateTimeWithCalendar object. + * CreateTemporalDateTime ( isoDateTime, calendar [ , newTarget ] ) */ -inline const auto& ToPlainDateTime(const PlainDateTimeWithCalendar& dateTime) { - return dateTime.dateTime(); -} +PlainDateTimeObject* CreateTemporalDateTime(JSContext* cx, + const ISODateTime& dateTime, + JS::Handle calendar); /** - * CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar [ , newTarget ] ) + * InterpretTemporalDateTimeFields ( calendar, fields, overflow ) */ -bool CreateTemporalDateTime( - JSContext* cx, const PlainDateTime& dateTime, - JS::Handle calendar, - JS::MutableHandle result); +bool InterpretTemporalDateTimeFields(JSContext* cx, + JS::Handle calendar, + JS::Handle fields, + TemporalOverflow overflow, + ISODateTime* result); + +/** + * RoundISODateTime ( isoDateTime, increment, unit, roundingMode ) + */ +ISODateTime RoundISODateTime(const ISODateTime& isoDateTime, + Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode); + +/** + * DifferencePlainDateTimeWithRounding ( isoDateTime1, isoDateTime2, calendar, + * largestUnit, roundingIncrement, smallestUnit, roundingMode ) + */ +bool DifferencePlainDateTimeWithRounding(JSContext* cx, + const ISODateTime& isoDateTime1, + const ISODateTime& isoDateTime2, + JS::Handle calendar, + const DifferenceSettings& settings, + InternalDuration* result); +/** + * DifferencePlainDateTimeWithTotal ( isoDateTime1, isoDateTime2, calendar, unit + * ) + */ +bool DifferencePlainDateTimeWithTotal(JSContext* cx, + const ISODateTime& isoDateTime1, + const ISODateTime& isoDateTime2, + JS::Handle calendar, + TemporalUnit unit, double* result); } /* namespace js::temporal */ namespace js { template -class WrappedPtrOperations { +class WrappedPtrOperations { const auto& container() const { return static_cast(this)->get(); } @@ -246,8 +179,8 @@ class WrappedPtrOperations { container().calendarDoNotUse()); } - // Allow implicit conversion to a calendar-less PlainDateTime. - operator const temporal::PlainDateTime&() const { return dateTime(); } + // Allow implicit conversion to an ISODateTime. + operator const temporal::ISODateTime&() const { return dateTime(); } }; } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.cpp index 2aedd7d864b..fdea114d4fd 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.cpp @@ -7,35 +7,31 @@ #include "builtin/temporal/PlainMonthDay.h" #include "mozilla/Assertions.h" +#include "mozilla/EnumSet.h" #include -#include "jsnum.h" #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/CalendarFields.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/ToString.h" -#include "builtin/temporal/Wrapped.h" -#include "builtin/temporal/ZonedDateTime.h" -#include "ds/IdValuePair.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" -#include "js/AllocPolicy.h" +#include "gc/GCEnum.h" #include "js/CallArgs.h" #include "js/CallNonGenericMethod.h" #include "js/Class.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/PropertyDescriptor.h" #include "js/PropertySpec.h" #include "js/RootingAPI.h" @@ -51,7 +47,6 @@ #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" -#include "vm/ObjectOperations-inl.h" using namespace js; using namespace js::temporal; @@ -61,285 +56,263 @@ static inline bool IsPlainMonthDay(Handle v) { } /** - * CreateTemporalMonthDay ( isoMonth, isoDay, calendar, referenceISOYear [ , - * newTarget ] ) + * CreateTemporalMonthDay ( isoDate, calendar [ , newTarget ] ) */ static PlainMonthDayObject* CreateTemporalMonthDay( - JSContext* cx, const CallArgs& args, double isoYear, double isoMonth, - double isoDay, Handle calendar) { - MOZ_ASSERT(IsInteger(isoYear)); - MOZ_ASSERT(IsInteger(isoMonth)); - MOZ_ASSERT(IsInteger(isoDay)); - + JSContext* cx, const CallArgs& args, const ISODate& isoDate, + Handle calendar) { // Step 1. - if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { - return nullptr; - } - - // Step 2. - if (!ISODateTimeWithinLimits(isoYear, isoMonth, isoDay)) { + if (!ISODateWithinLimits(isoDate)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID); return nullptr; } - // Steps 3-4. + // Steps 2-3. Rooted proto(cx); if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PlainMonthDay, &proto)) { return nullptr; } - auto* obj = NewObjectWithClassProto(cx, proto); - if (!obj) { + auto* object = NewObjectWithClassProto(cx, proto); + if (!object) { return nullptr; } + // Step 4. + auto packedDate = PackedDate::pack(isoDate); + object->setFixedSlot(PlainMonthDayObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); + // Step 5. - obj->setFixedSlot(PlainMonthDayObject::ISO_MONTH_SLOT, - Int32Value(int32_t(isoMonth))); + object->setFixedSlot(PlainMonthDayObject::CALENDAR_SLOT, + calendar.toSlotValue()); // Step 6. - obj->setFixedSlot(PlainMonthDayObject::ISO_DAY_SLOT, - Int32Value(int32_t(isoDay))); - - // Step 7. - obj->setFixedSlot(PlainMonthDayObject::CALENDAR_SLOT, calendar.toSlotValue()); - - // Step 8. - obj->setFixedSlot(PlainMonthDayObject::ISO_YEAR_SLOT, - Int32Value(int32_t(isoYear))); - - // Step 9. - return obj; + return object; } /** - * CreateTemporalMonthDay ( isoMonth, isoDay, calendar, referenceISOYear [ , - * newTarget ] ) + * CreateTemporalMonthDay ( isoDate, calendar [ , newTarget ] ) */ PlainMonthDayObject* js::temporal::CreateTemporalMonthDay( - JSContext* cx, const PlainDate& date, Handle calendar) { - const auto& [isoYear, isoMonth, isoDay] = date; + JSContext* cx, Handle monthDay) { + MOZ_ASSERT(IsValidISODate(monthDay)); // Step 1. - if (!ThrowIfInvalidISODate(cx, date)) { + MOZ_ASSERT(ISODateWithinLimits(monthDay)); + + // Steps 2-3. + auto* object = NewBuiltinClassInstance(cx); + if (!object) { return nullptr; } - // Step 2. - if (!ISODateTimeWithinLimits(date)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID); - return nullptr; - } - - // Steps 3-4. - auto* obj = NewBuiltinClassInstance(cx); - if (!obj) { - return nullptr; - } + // Step 4. + auto packedDate = PackedDate::pack(monthDay); + object->setFixedSlot(PlainMonthDayObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); // Step 5. - obj->setFixedSlot(PlainMonthDayObject::ISO_MONTH_SLOT, Int32Value(isoMonth)); + object->setFixedSlot(PlainMonthDayObject::CALENDAR_SLOT, + monthDay.calendar().toSlotValue()); // Step 6. - obj->setFixedSlot(PlainMonthDayObject::ISO_DAY_SLOT, Int32Value(isoDay)); - - // Step 7. - obj->setFixedSlot(PlainMonthDayObject::CALENDAR_SLOT, calendar.toSlotValue()); - - // Step 8. - obj->setFixedSlot(PlainMonthDayObject::ISO_YEAR_SLOT, Int32Value(isoYear)); - - // Step 9. - return obj; + return object; } -template -static bool ToTemporalCalendarForMonthDay(JSContext* cx, - Handle object, - MutableHandle result) { - if (auto* unwrapped = object->maybeUnwrapIf()) { - result.set(unwrapped->calendar()); - return result.wrap(cx); +/** + * CreateTemporalMonthDay ( isoDate, calendar [ , newTarget ] ) + */ +bool js::temporal::CreateTemporalMonthDay(JSContext* cx, const ISODate& isoDate, + Handle calendar, + MutableHandle result) { + MOZ_ASSERT(IsValidISODate(isoDate)); + + // Step 1. + if (!ISODateWithinLimits(isoDate)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID); + return false; } - if constexpr (sizeof...(Ts) > 0) { - return ToTemporalCalendarForMonthDay(cx, object, result); + // Steps 2-6. + result.set(PlainMonthDay{isoDate, calendar}); + return true; +} + +struct MonthDayOptions { + TemporalOverflow overflow = TemporalOverflow::Constrain; +}; + +/** + * ToTemporalMonthDay ( item [ , options ] ) + */ +static bool ToTemporalMonthDayOptions(JSContext* cx, Handle options, + MonthDayOptions* result) { + if (options.isUndefined()) { + *result = {}; + return true; } - result.set(CalendarValue()); + // NOTE: |options| are only passed from `Temporal.PlainMonthDay.from`. + + Rooted resolvedOptions( + cx, RequireObjectArg(cx, "options", "from", options)); + if (!resolvedOptions) { + return false; + } + + auto overflow = TemporalOverflow::Constrain; + if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) { + return false; + } + + *result = {overflow}; return true; } /** * ToTemporalMonthDay ( item [ , options ] ) */ -static Wrapped ToTemporalMonthDay( - JSContext* cx, Handle item, - Handle maybeOptions = nullptr) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Rooted maybeResolvedOptions(cx); - if (maybeOptions) { - maybeResolvedOptions = SnapshotOwnProperties(cx, maybeOptions); - if (!maybeResolvedOptions) { - return nullptr; - } - } - - // Step 3. - if (item.isObject()) { - Rooted itemObj(cx, &item.toObject()); - - // Step 3.a. - if (itemObj->canUnwrapAs()) { - return itemObj; +static bool ToTemporalMonthDay(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { + // Step 2.a. + if (auto* plainMonthDay = item->maybeUnwrapIf()) { + auto date = plainMonthDay->date(); + Rooted calendar(cx, plainMonthDay->calendar()); + if (!calendar.wrap(cx)) { + return false; } - // Steps 3.b-c. - Rooted calendarValue(cx); - if (!::ToTemporalCalendarForMonthDay(cx, itemObj, - &calendarValue)) { - return nullptr; - } - if (!calendarValue) { - // Step 3.c.i. - Rooted calendarLike(cx); - if (!GetProperty(cx, itemObj, itemObj, cx->names().calendar, - &calendarLike)) { - return nullptr; - } - - // Step 3.c.ii. - if (!ToTemporalCalendarWithISODefault(cx, calendarLike, &calendarValue)) { - return nullptr; - } + // Steps 2.a.i-ii. + MonthDayOptions ignoredOptions; + if (!ToTemporalMonthDayOptions(cx, options, &ignoredOptions)) { + return false; } - // Step 3.d. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::MonthDayFromFields, - }, - &calendar)) { - return nullptr; - } - - // Step 3.e. - Rooted fields( - cx, PrepareCalendarFields(cx, calendar, itemObj, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - })); - if (!fields) { - return nullptr; - } - - // Step 3.f. - if (maybeResolvedOptions) { - return js::temporal::CalendarMonthDayFromFields(cx, calendar, fields, - maybeResolvedOptions); - } - return js::temporal::CalendarMonthDayFromFields(cx, calendar, fields); + // Step 2.a.iii. + result.set(PlainMonthDay{date, calendar}); + return true; } - // Step 4. - if (!item.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, - nullptr, "not a string"); - return nullptr; - } - Rooted string(cx, item.toString()); - - // Step 5. - PlainDate result; - bool hasYear; - Rooted calendarString(cx); - if (!ParseTemporalMonthDayString(cx, string, &result, &hasYear, - &calendarString)) { - return nullptr; + // Step 2.b. + Rooted calendar(cx); + if (!GetTemporalCalendarWithISODefault(cx, item, &calendar)) { + return false; } - // Steps 6-9. - Rooted calendarValue(cx, CalendarValue(CalendarId::ISO8601)); - if (calendarString) { - if (!ToBuiltinCalendar(cx, calendarString, &calendarValue)) { - return nullptr; - } + // Step 2.c. + Rooted fields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + }, + &fields)) { + return false; } - // Step 10. - if (maybeResolvedOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return nullptr; - } + // Steps 2.d-e. + MonthDayOptions resolvedOptions; + if (!ToTemporalMonthDayOptions(cx, options, &resolvedOptions)) { + return false; } + auto [overflow] = resolvedOptions; - // Step 11. - if (!hasYear) { - // Step 11.a. - MOZ_ASSERT(calendarValue.isString() && - calendarValue.toString() == CalendarId::ISO8601); - - // Step 11.b. - constexpr int32_t referenceISOYear = 1972; - - // Step 11.a. - return CreateTemporalMonthDay( - cx, {referenceISOYear, result.month, result.day}, calendarValue); - } - - // Step 12. - Rooted obj( - cx, CreateTemporalMonthDay(cx, result, calendarValue)); - if (!obj) { - return nullptr; - } - - // Step 13. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::MonthDayFromFields, - }, - &calendar)) { - return nullptr; - } - - // Steps 14-15. - return CalendarMonthDayFromFields(cx, calendar, obj); + // Step 2.f. + return CalendarMonthDayFromFields(cx, calendar, fields, overflow, result); } /** * ToTemporalMonthDay ( item [ , options ] ) */ static bool ToTemporalMonthDay(JSContext* cx, Handle item, - PlainDate* result, - MutableHandle calendar) { - auto* obj = ToTemporalMonthDay(cx, item).unwrapOrNull(); - if (!obj) { + Handle options, + MutableHandle result) { + // Step 1. (Not applicable in our implementation.) + + // Step 2. + if (item.isObject()) { + Rooted itemObj(cx, &item.toObject()); + return ToTemporalMonthDay(cx, itemObj, options, result); + } + + // Step 3. + if (!item.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, + nullptr, "not a string"); + return false; + } + Rooted string(cx, item.toString()); + + // Step 4. + ISODate date; + bool hasYear; + Rooted calendarString(cx); + if (!ParseTemporalMonthDayString(cx, string, &date, &hasYear, + &calendarString)) { return false; } - *result = ToPlainDate(obj); - calendar.set(obj->calendar()); - return calendar.wrap(cx); + // Steps 5-7. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (calendarString) { + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } + } + + // Steps 8-9. + MonthDayOptions ignoredOptions; + if (!ToTemporalMonthDayOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 10. + if (calendar.identifier() == CalendarId::ISO8601) { + // Step 10.a. + constexpr int32_t referenceISOYear = 1972; + + // Step 10.b. + auto isoDate = ISODate{referenceISOYear, date.month, date.day}; + + // Step 10.c. + return CreateTemporalMonthDay(cx, isoDate, calendar, result); + } + + // Steps 11-12. + Rooted monthDay(cx); + if (!CreateTemporalMonthDay(cx, date, calendar, &monthDay)) { + return false; + } + + // Step 13. + Rooted fields(cx); + if (!ISODateToFields(cx, monthDay, &fields)) { + return false; + } + + // Steps 14-15. + return CalendarMonthDayFromFields(cx, calendar, fields, + TemporalOverflow::Constrain, result); } /** - * Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , - * referenceISOYear ] ] ) + * ToTemporalMonthDay ( item [ , options ] ) + */ +static bool ToTemporalMonthDay(JSContext* cx, Handle item, + MutableHandle result) { + return ToTemporalMonthDay(cx, item, UndefinedHandleValue, result); +} + +/** + * Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendar [ , referenceISOYear ] + * ] ) */ static bool PlainMonthDayConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -361,13 +334,24 @@ static bool PlainMonthDayConstructor(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 5. - Rooted calendar(cx); - if (!ToTemporalCalendarWithISODefault(cx, args.get(2), &calendar)) { - return false; + // Steps 5-7. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (args.hasDefined(2)) { + // Step 6. + if (!args[2].isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args[2], + nullptr, "not a string"); + return false; + } + + // Step 7. + Rooted calendarString(cx, args[2].toString()); + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } } - // Steps 2 and 6. + // Steps 2 and 8. double isoYear = 1972; if (args.hasDefined(3)) { if (!ToIntegerWithTruncation(cx, args[3], "year", &isoYear)) { @@ -375,9 +359,16 @@ static bool PlainMonthDayConstructor(JSContext* cx, unsigned argc, Value* vp) { } } - // Step 7. - auto* monthDay = - CreateTemporalMonthDay(cx, args, isoYear, isoMonth, isoDay, calendar); + // Step 9. + if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { + return false; + } + + // Step 10. + auto isoDate = ISODate{int32_t(isoYear), int32_t(isoMonth), int32_t(isoDay)}; + + // Step 9. + auto* monthDay = CreateTemporalMonthDay(cx, args, isoDate, calendar); if (!monthDay) { return false; } @@ -393,52 +384,17 @@ static bool PlainMonthDay_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "from", args[1]); - if (!options) { - return false; - } - } - - // Step 2. - if (args.get(0).isObject()) { - JSObject* item = &args[0].toObject(); - - if (auto* monthDay = item->maybeUnwrapIf()) { - auto date = ToPlainDate(monthDay); - - Rooted calendar(cx, monthDay->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - if (options) { - // Step 2.a. - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, options, &ignored)) { - return false; - } - } - - // Step 2.b. - auto* obj = CreateTemporalMonthDay(cx, date, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; - } - } - - // Step 3. - auto obj = ToTemporalMonthDay(cx, args.get(0), options); - if (!obj) { + Rooted monthDay(cx); + if (!ToTemporalMonthDay(cx, args.get(0), args.get(1), &monthDay)) { return false; } - args.rval().setObject(*obj); + auto* result = CreateTemporalMonthDay(cx, monthDay); + if (!result) { + return false; + } + + args.rval().setObject(*result); return true; } @@ -449,13 +405,13 @@ static bool PlainMonthDay_calendarId(JSContext* cx, const CallArgs& args) { auto* monthDay = &args.thisv().toObject().as(); // Step 3. - Rooted calendar(cx, monthDay->calendar()); - auto* calendarId = ToTemporalCalendarIdentifier(cx, calendar); - if (!calendarId) { + auto* str = + NewStringCopy(cx, CalendarIdentifier(monthDay->calendar())); + if (!str) { return false; } - args.rval().setString(calendarId); + args.rval().setString(str); return true; } @@ -473,13 +429,11 @@ static bool PlainMonthDay_calendarId(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainMonthDay.prototype.monthCode */ static bool PlainMonthDay_monthCode(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted monthDay( - cx, &args.thisv().toObject().as()); + auto* monthDay = &args.thisv().toObject().as(); Rooted calendar(cx, monthDay->calendar()); - // Step 4. - return CalendarMonthCode(cx, calendar, monthDay, args.rval()); + // Step 3. + return CalendarMonthCode(cx, calendar, monthDay->date(), args.rval()); } /** @@ -496,13 +450,11 @@ static bool PlainMonthDay_monthCode(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainMonthDay.prototype.day */ static bool PlainMonthDay_day(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted monthDay( - cx, &args.thisv().toObject().as()); + auto* monthDay = &args.thisv().toObject().as(); Rooted calendar(cx, monthDay->calendar()); - // Step 4. - return CalendarDay(cx, calendar, monthDay, args.rval()); + // Step 3. + return CalendarDay(cx, calendar, monthDay->date(), args.rval()); } /** @@ -518,9 +470,8 @@ static bool PlainMonthDay_day(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainMonthDay.prototype.with ( temporalMonthDayLike [ , options ] ) */ static bool PlainMonthDay_with(JSContext* cx, const CallArgs& args) { - Rooted monthDay( + Rooted monthDay( cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, monthDay->calendar()); // Step 3. Rooted temporalMonthDayLike( @@ -533,70 +484,56 @@ static bool PlainMonthDay_with(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted resolvedOptions(cx); + auto calendar = monthDay.calendar(); + + // Step 5. + Rooted fields(cx); + if (!ISODateToFields(cx, monthDay, &fields)) { + return false; + } + + // Step 6. + Rooted partialMonthDay(cx); + if (!PreparePartialCalendarFields(cx, calendar, temporalMonthDayLike, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + }, + &partialMonthDay)) { + return false; + } + MOZ_ASSERT(!partialMonthDay.keys().isEmpty()); + + // Step 7. + fields = CalendarMergeFields(calendar, fields, partialMonthDay); + + // Steps 8-9. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { + // Step 8. Rooted options(cx, RequireObjectArg(cx, "options", "with", args[1])); if (!options) { return false; } - resolvedOptions = SnapshotOwnProperties(cx, options); - } else { - resolvedOptions = NewPlainObjectWithProto(cx, nullptr); - } - if (!resolvedOptions) { - return false; - } - // Step 5. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::MergeFields, - CalendarMethod::MonthDayFromFields, - }, - &calendar)) { - return false; - } - - // Step 6. - Rooted fields(cx); - JS::RootedVector fieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, monthDay, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - &fields, &fieldNames)) { - return false; - } - - // Step 7. - Rooted partialMonthDay( - cx, PreparePartialTemporalFields(cx, temporalMonthDayLike, fieldNames)); - if (!partialMonthDay) { - return false; - } - - // Step 8. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, fields, partialMonthDay)); - if (!mergedFields) { - return false; - } - - // Step 9. - fields = PrepareTemporalFields(cx, mergedFields, fieldNames); - if (!fields) { - return false; + // Step 9. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } } // Step 10. - auto obj = js::temporal::CalendarMonthDayFromFields(cx, calendar, fields, - resolvedOptions); + Rooted result(cx); + if (!CalendarMonthDayFromFields(cx, calendar, fields, overflow, &result)) { + return false; + } + MOZ_ASSERT(ISODateWithinLimits(result)); + + // Step 11. + auto* obj = CreateTemporalMonthDay(cx, result); if (!obj) { return false; } @@ -619,21 +556,18 @@ static bool PlainMonthDay_with(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainMonthDay_equals(JSContext* cx, const CallArgs& args) { auto* monthDay = &args.thisv().toObject().as(); - auto date = ToPlainDate(monthDay); + auto date = monthDay->date(); Rooted calendar(cx, monthDay->calendar()); // Step 3. - PlainDate other; - Rooted otherCalendar(cx); - if (!ToTemporalMonthDay(cx, args.get(0), &other, &otherCalendar)) { + Rooted other(cx); + if (!ToTemporalMonthDay(cx, args.get(0), &other)) { return false; } // Steps 4-7. - bool equals = date == other; - if (equals && !CalendarEquals(cx, calendar, otherCalendar, &equals)) { - return false; - } + bool equals = + date == other.date() && CalendarEquals(calendar, other.calendar()); args.rval().setBoolean(equals); return true; @@ -694,17 +628,10 @@ static bool PlainMonthDay_toString(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainMonthDay.prototype.toLocaleString ( [ locales [ , options ] ] ) */ static bool PlainMonthDay_toLocaleString(JSContext* cx, const CallArgs& args) { - Rooted monthDay( - cx, &args.thisv().toObject().as()); - - // Step 3. - JSString* str = TemporalMonthDayToString(cx, monthDay, ShowCalendar::Auto); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-4. + Handle required = cx->names().date; + Handle defaults = cx->names().date; + return TemporalObjectToLocaleString(cx, args, required, defaults); } /** @@ -757,7 +684,7 @@ static bool PlainMonthDay_valueOf(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainMonthDay.prototype.toPlainDate ( item ) */ static bool PlainMonthDay_toPlainDate(JSContext* cx, const CallArgs& args) { - Rooted monthDay( + Rooted monthDay( cx, &args.thisv().toObject().as()); // Step 3. @@ -768,65 +695,37 @@ static bool PlainMonthDay_toPlainDate(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted calendarValue(cx, monthDay->calendar()); - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - CalendarMethod::MergeFields, - }, - &calendar)) { - return false; - } + auto calendar = monthDay.calendar(); // Step 5. - Rooted receiverFields(cx); - JS::RootedVector receiverFieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, monthDay, - { - CalendarField::Day, - CalendarField::MonthCode, - }, - &receiverFields, - &receiverFieldNames)) { + Rooted fields(cx); + if (!ISODateToFields(cx, monthDay, &fields)) { return false; } // Step 6. - Rooted inputFields(cx); - JS::RootedVector inputFieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, item, - { - CalendarField::Year, - }, - &inputFields, &inputFieldNames)) { + Rooted inputFields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Year, + }, + &inputFields)) { return false; } // Step 7. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, receiverFields, inputFields)); - if (!mergedFields) { - return false; - } + fields = CalendarMergeFields(calendar, fields, inputFields); // Step 8. - JS::RootedVector concatenatedFieldNames(cx); - if (!ConcatTemporalFieldNames(receiverFieldNames, inputFieldNames, - concatenatedFieldNames.get())) { + Rooted date(cx); + if (!CalendarDateFromFields(cx, calendar, fields, TemporalOverflow::Constrain, + &date)) { return false; } + MOZ_ASSERT(ISODateWithinLimits(date)); // Step 9. - Rooted mergedFromConcatenatedFields( - cx, PrepareTemporalFields(cx, mergedFields, concatenatedFieldNames)); - if (!mergedFromConcatenatedFields) { - return false; - } - - // Step 10. - auto obj = CalendarDateFromFields(cx, calendar, mergedFromConcatenatedFields); + auto* obj = CreateTemporalDate(cx, date); if (!obj) { return false; } @@ -845,92 +744,6 @@ static bool PlainMonthDay_toPlainDate(JSContext* cx, unsigned argc, Value* vp) { args); } -/** - * Temporal.PlainMonthDay.prototype.getISOFields ( ) - */ -static bool PlainMonthDay_getISOFields(JSContext* cx, const CallArgs& args) { - Rooted monthDay( - cx, &args.thisv().toObject().as()); - auto calendar = monthDay->calendar(); - - // Step 3. - Rooted fields(cx, IdValueVector(cx)); - - // Step 4. - Rooted cal(cx); - if (!ToTemporalCalendar(cx, calendar, &cal)) { - return false; - } - if (!fields.emplaceBack(NameToId(cx->names().calendar), cal)) { - return false; - } - - // Step 5. - if (!fields.emplaceBack(NameToId(cx->names().isoDay), - Int32Value(monthDay->isoDay()))) { - return false; - } - - // Step 6. - if (!fields.emplaceBack(NameToId(cx->names().isoMonth), - Int32Value(monthDay->isoMonth()))) { - return false; - } - - // Step 7. - if (!fields.emplaceBack(NameToId(cx->names().isoYear), - Int32Value(monthDay->isoYear()))) { - return false; - } - - // Step 8. - auto* obj = NewPlainObjectWithUniqueNames(cx, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainMonthDay.prototype.getISOFields ( ) - */ -static bool PlainMonthDay_getISOFields(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.PlainMonthDay.prototype.getCalendar ( ) - */ -static bool PlainMonthDay_getCalendar(JSContext* cx, const CallArgs& args) { - auto* monthDay = &args.thisv().toObject().as(); - Rooted calendar(cx, monthDay->calendar()); - - // Step 3. - auto* obj = ToTemporalCalendarObject(cx, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainMonthDay.prototype.getCalendar ( ) - */ -static bool PlainMonthDay_getCalendar(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - const JSClass PlainMonthDayObject::class_ = { "Temporal.PlainMonthDay", JSCLASS_HAS_RESERVED_SLOTS(PlainMonthDayObject::SLOT_COUNT) | @@ -954,8 +767,6 @@ static const JSFunctionSpec PlainMonthDay_prototype_methods[] = { JS_FN("toJSON", PlainMonthDay_toJSON, 0, 0), JS_FN("valueOf", PlainMonthDay_valueOf, 0, 0), JS_FN("toPlainDate", PlainMonthDay_toPlainDate, 1, 0), - JS_FN("getISOFields", PlainMonthDay_getISOFields, 0, 0), - JS_FN("getCalendar", PlainMonthDay_getCalendar, 0, 0), JS_FS_END, }; diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.h index 1a485133874..3ceaffa94cd 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainMonthDay.h @@ -7,14 +7,23 @@ #ifndef builtin_temporal_PlainMonthDay_h #define builtin_temporal_PlainMonthDay_h +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + #include +#include "jstypes.h" + #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/PlainDate.h" #include "builtin/temporal/TemporalTypes.h" +#include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" #include "vm/NativeObject.h" +class JS_PUBLIC_API JSTracer; + namespace js { struct ClassSpec; } @@ -26,17 +35,17 @@ class PlainMonthDayObject : public NativeObject { static const JSClass class_; static const JSClass& protoClass_; - static constexpr uint32_t ISO_YEAR_SLOT = 0; - static constexpr uint32_t ISO_MONTH_SLOT = 1; - static constexpr uint32_t ISO_DAY_SLOT = 2; - static constexpr uint32_t CALENDAR_SLOT = 3; - static constexpr uint32_t SLOT_COUNT = 4; + static constexpr uint32_t PACKED_DATE_SLOT = 0; + static constexpr uint32_t CALENDAR_SLOT = 1; + static constexpr uint32_t SLOT_COUNT = 2; - int32_t isoYear() const { return getFixedSlot(ISO_YEAR_SLOT).toInt32(); } - - int32_t isoMonth() const { return getFixedSlot(ISO_MONTH_SLOT).toInt32(); } - - int32_t isoDay() const { return getFixedSlot(ISO_DAY_SLOT).toInt32(); } + /** + * Extract the date fields from this PlainDate object. + */ + ISODate date() const { + auto packed = PackedDate{getFixedSlot(PACKED_DATE_SLOT).toPrivateUint32()}; + return PackedDate::unpack(packed); + } CalendarValue calendar() const { return CalendarValue(getFixedSlot(CALENDAR_SLOT)); @@ -46,21 +55,67 @@ class PlainMonthDayObject : public NativeObject { static const ClassSpec classSpec_; }; -/** - * Extract the date fields from the PlainMonthDay object. - */ -inline PlainDate ToPlainDate(const PlainMonthDayObject* monthDay) { - return {monthDay->isoYear(), monthDay->isoMonth(), monthDay->isoDay()}; -} +class MOZ_STACK_CLASS PlainMonthDay final { + ISODate date_; + CalendarValue calendar_; + + public: + PlainMonthDay() = default; + + PlainMonthDay(const ISODate& date, const CalendarValue& calendar) + : date_(date), calendar_(calendar) { + MOZ_ASSERT(ISODateWithinLimits(date)); + } + + explicit PlainMonthDay(const PlainMonthDayObject* monthDay) + : PlainMonthDay(monthDay->date(), monthDay->calendar()) {} + + const auto& date() const { return date_; } + const auto& calendar() const { return calendar_; } + + // Allow implicit conversion to an ISODate. + operator const ISODate&() const { return date(); } + + void trace(JSTracer* trc) { calendar_.trace(trc); } + + const auto* calendarDoNotUse() const { return &calendar_; } +}; /** - * CreateTemporalMonthDay ( isoMonth, isoDay, calendar, referenceISOYear [ , - * newTarget ] ) + * CreateTemporalMonthDay ( isoDate, calendar [ , newTarget ] ) */ PlainMonthDayObject* CreateTemporalMonthDay(JSContext* cx, - const PlainDate& date, - JS::Handle calendar); + JS::Handle monthDay); + +/** + * CreateTemporalMonthDay ( isoDate, calendar [ , newTarget ] ) + */ +bool CreateTemporalMonthDay(JSContext* cx, const ISODate& isoDate, + JS::Handle calendar, + JS::MutableHandle result); } /* namespace js::temporal */ +namespace js { + +template +class WrappedPtrOperations { + const auto& container() const { + return static_cast(this)->get(); + } + + public: + const auto& date() const { return container().date(); } + + JS::Handle calendar() const { + return JS::Handle::fromMarkedLocation( + container().calendarDoNotUse()); + } + + // Allow implicit conversion to an ISODate. + operator const temporal::ISODate&() const { return date(); } +}; + +} // namespace js + #endif /* builtin_temporal_PlainMonthDay_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.cpp index 4202945cacf..72e09e2e1f4 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.cpp @@ -7,22 +7,17 @@ #include "builtin/temporal/PlainTime.h" #include "mozilla/Assertions.h" -#include "mozilla/FloatingPoint.h" -#include "mozilla/Maybe.h" #include #include #include -#include -#include #include "jsnum.h" #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Duration.h" -#include "builtin/temporal/Instant.h" -#include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/Temporal.h" #include "builtin/temporal/TemporalParser.h" @@ -32,10 +27,8 @@ #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ToString.h" #include "builtin/temporal/ZonedDateTime.h" -#include "ds/IdValuePair.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" -#include "js/AllocPolicy.h" #include "js/CallArgs.h" #include "js/CallNonGenericMethod.h" #include "js/Class.h" @@ -51,7 +44,6 @@ #include "vm/JSContext.h" #include "vm/JSObject.h" #include "vm/PlainObject.h" -#include "vm/StringType.h" #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" @@ -73,7 +65,6 @@ static bool IsValidTime(T hour, T minute, T second, T millisecond, T microsecond, T nanosecond) { static_assert(std::is_same_v || std::is_same_v); - // Step 1. MOZ_ASSERT(IsInteger(hour)); MOZ_ASSERT(IsInteger(minute)); MOZ_ASSERT(IsInteger(second)); @@ -81,44 +72,44 @@ static bool IsValidTime(T hour, T minute, T second, T millisecond, MOZ_ASSERT(IsInteger(microsecond)); MOZ_ASSERT(IsInteger(nanosecond)); - // Step 2. + // Step 1. if (hour < 0 || hour > 23) { return false; } - // Step 3. + // Step 2. if (minute < 0 || minute > 59) { return false; } - // Step 4. + // Step 3. if (second < 0 || second > 59) { return false; } - // Step 5. + // Step 4. if (millisecond < 0 || millisecond > 999) { return false; } - // Step 6. + // Step 5. if (microsecond < 0 || microsecond > 999) { return false; } - // Step 7. + // Step 6. if (nanosecond < 0 || nanosecond > 999) { return false; } - // Step 8. + // Step 7. return true; } /** * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -bool js::temporal::IsValidTime(const PlainTime& time) { +bool js::temporal::IsValidTime(const Time& time) { const auto& [hour, minute, second, millisecond, microsecond, nanosecond] = time; return ::IsValidTime(hour, minute, second, millisecond, microsecond, @@ -152,9 +143,9 @@ static void ReportInvalidTimeValue(JSContext* cx, const char* name, int32_t min, minStr, maxStr, numStr); } -template static inline bool ThrowIfInvalidTimeValue(JSContext* cx, const char* name, - int32_t min, int32_t max, T num) { + int32_t min, int32_t max, + double num) { if (min <= num && num <= max) { return true; } @@ -165,11 +156,9 @@ static inline bool ThrowIfInvalidTimeValue(JSContext* cx, const char* name, /** * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -template -static bool ThrowIfInvalidTime(JSContext* cx, T hour, T minute, T second, - T millisecond, T microsecond, T nanosecond) { - static_assert(std::is_same_v || std::is_same_v); - +bool js::temporal::ThrowIfInvalidTime(JSContext* cx, double hour, double minute, + double second, double millisecond, + double microsecond, double nanosecond) { // Step 1. MOZ_ASSERT(IsInteger(hour)); MOZ_ASSERT(IsInteger(minute)); @@ -212,61 +201,13 @@ static bool ThrowIfInvalidTime(JSContext* cx, T hour, T minute, T second, return true; } -/** - * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) - */ -bool js::temporal::ThrowIfInvalidTime(JSContext* cx, const PlainTime& time) { - const auto& [hour, minute, second, millisecond, microsecond, nanosecond] = - time; - return ::ThrowIfInvalidTime(cx, hour, minute, second, millisecond, - microsecond, nanosecond); -} - -/** - * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) - */ -bool js::temporal::ThrowIfInvalidTime(JSContext* cx, double hour, double minute, - double second, double millisecond, - double microsecond, double nanosecond) { - return ::ThrowIfInvalidTime(cx, hour, minute, second, millisecond, - microsecond, nanosecond); -} - -/** - * ConstrainTime ( hour, minute, second, millisecond, microsecond, nanosecond ) - */ -static PlainTime ConstrainTime(double hour, double minute, double second, - double millisecond, double microsecond, - double nanosecond) { - // Step 1. - MOZ_ASSERT(IsInteger(hour)); - MOZ_ASSERT(IsInteger(minute)); - MOZ_ASSERT(IsInteger(second)); - MOZ_ASSERT(IsInteger(millisecond)); - MOZ_ASSERT(IsInteger(microsecond)); - MOZ_ASSERT(IsInteger(nanosecond)); - - // Steps 2-8. - return { - int32_t(std::clamp(hour, 0.0, 23.0)), - int32_t(std::clamp(minute, 0.0, 59.0)), - int32_t(std::clamp(second, 0.0, 59.0)), - int32_t(std::clamp(millisecond, 0.0, 999.0)), - int32_t(std::clamp(microsecond, 0.0, 999.0)), - int32_t(std::clamp(nanosecond, 0.0, 999.0)), - }; -} - /** * RegulateTime ( hour, minute, second, millisecond, microsecond, nanosecond, * overflow ) */ bool js::temporal::RegulateTime(JSContext* cx, const TemporalTimeLike& time, - TemporalOverflow overflow, PlainTime* result) { - const auto& [hour, minute, second, millisecond, microsecond, nanosecond] = - time; - - // Step 1. + TemporalOverflow overflow, Time* result) { + auto [hour, minute, second, millisecond, microsecond, nanosecond] = time; MOZ_ASSERT(IsInteger(hour)); MOZ_ASSERT(IsInteger(minute)); MOZ_ASSERT(IsInteger(second)); @@ -274,25 +215,37 @@ bool js::temporal::RegulateTime(JSContext* cx, const TemporalTimeLike& time, MOZ_ASSERT(IsInteger(microsecond)); MOZ_ASSERT(IsInteger(nanosecond)); - // Step 2. (Not applicable in our implementation.) + // Steps 1-2. + if (overflow == TemporalOverflow::Constrain) { + // Step 1.a. + hour = std::clamp(hour, 0.0, 23.0); + + // Step 1.b. + minute = std::clamp(minute, 0.0, 59.0); + + // Step 1.c. + second = std::clamp(second, 0.0, 59.0); + + // Step 1.d. + millisecond = std::clamp(millisecond, 0.0, 999.0); + + // Step 1.e. + microsecond = std::clamp(microsecond, 0.0, 999.0); + + // Step 1.f. + nanosecond = std::clamp(nanosecond, 0.0, 999.0); + } else { + // Step 2.a. + MOZ_ASSERT(overflow == TemporalOverflow::Reject); + + // Step 2.b. + if (!ThrowIfInvalidTime(cx, hour, minute, second, millisecond, microsecond, + nanosecond)) { + return false; + } + } // Step 3. - if (overflow == TemporalOverflow::Constrain) { - *result = ConstrainTime(hour, minute, second, millisecond, microsecond, - nanosecond); - return true; - } - - // Step 4.a. - MOZ_ASSERT(overflow == TemporalOverflow::Reject); - - // Step 4.b. - if (!ThrowIfInvalidTime(cx, hour, minute, second, millisecond, microsecond, - nanosecond)) { - return false; - } - - // Step 4.c. *result = { int32_t(hour), int32_t(minute), int32_t(second), int32_t(millisecond), int32_t(microsecond), int32_t(nanosecond), @@ -301,28 +254,13 @@ bool js::temporal::RegulateTime(JSContext* cx, const TemporalTimeLike& time, } /** - * CreateTemporalTime ( hour, minute, second, millisecond, microsecond, - * nanosecond [ , newTarget ] ) + * CreateTemporalTime ( time [ , newTarget ] ) */ static PlainTimeObject* CreateTemporalTime(JSContext* cx, const CallArgs& args, - double hour, double minute, - double second, double millisecond, - double microsecond, - double nanosecond) { - MOZ_ASSERT(IsInteger(hour)); - MOZ_ASSERT(IsInteger(minute)); - MOZ_ASSERT(IsInteger(second)); - MOZ_ASSERT(IsInteger(millisecond)); - MOZ_ASSERT(IsInteger(microsecond)); - MOZ_ASSERT(IsInteger(nanosecond)); + const Time& time) { + MOZ_ASSERT(IsValidTime(time)); - // Step 1. - if (!ThrowIfInvalidTime(cx, hour, minute, second, millisecond, microsecond, - nanosecond)) { - return nullptr; - } - - // Steps 2-3. + // Steps 1-2. Rooted proto(cx); if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PlainTime, &proto)) { @@ -334,76 +272,36 @@ static PlainTimeObject* CreateTemporalTime(JSContext* cx, const CallArgs& args, return nullptr; } + // Step 3. + auto packedTime = PackedTime::pack(time); + object->setFixedSlot( + PlainTimeObject::PACKED_TIME_SLOT, + DoubleValue(mozilla::BitwiseCast(packedTime.value))); + // Step 4. - object->setFixedSlot(PlainTimeObject::ISO_HOUR_SLOT, - Int32Value(int32_t(hour))); - - // Step 5. - object->setFixedSlot(PlainTimeObject::ISO_MINUTE_SLOT, - Int32Value(int32_t(minute))); - - // Step 6. - object->setFixedSlot(PlainTimeObject::ISO_SECOND_SLOT, - Int32Value(int32_t(second))); - - // Step 7. - object->setFixedSlot(PlainTimeObject::ISO_MILLISECOND_SLOT, - Int32Value(int32_t(millisecond))); - - // Step 8. - object->setFixedSlot(PlainTimeObject::ISO_MICROSECOND_SLOT, - Int32Value(int32_t(microsecond))); - - // Step 9. - object->setFixedSlot(PlainTimeObject::ISO_NANOSECOND_SLOT, - Int32Value(int32_t(nanosecond))); - - // Step 10. return object; } /** - * CreateTemporalTime ( hour, minute, second, millisecond, microsecond, - * nanosecond [ , newTarget ] ) + * CreateTemporalTime ( time [ , newTarget ] ) */ PlainTimeObject* js::temporal::CreateTemporalTime(JSContext* cx, - const PlainTime& time) { - const auto& [hour, minute, second, millisecond, microsecond, nanosecond] = - time; + const Time& time) { + MOZ_ASSERT(IsValidTime(time)); - // Step 1. - if (!ThrowIfInvalidTime(cx, time)) { - return nullptr; - } - - // Steps 2-3. + // Steps 1-2. auto* object = NewBuiltinClassInstance(cx); if (!object) { return nullptr; } + // Step 3. + auto packedTime = PackedTime::pack(time); + object->setFixedSlot( + PlainTimeObject::PACKED_TIME_SLOT, + DoubleValue(mozilla::BitwiseCast(packedTime.value))); + // Step 4. - object->setFixedSlot(PlainTimeObject::ISO_HOUR_SLOT, Int32Value(hour)); - - // Step 5. - object->setFixedSlot(PlainTimeObject::ISO_MINUTE_SLOT, Int32Value(minute)); - - // Step 6. - object->setFixedSlot(PlainTimeObject::ISO_SECOND_SLOT, Int32Value(second)); - - // Step 7. - object->setFixedSlot(PlainTimeObject::ISO_MILLISECOND_SLOT, - Int32Value(millisecond)); - - // Step 8. - object->setFixedSlot(PlainTimeObject::ISO_MICROSECOND_SLOT, - Int32Value(microsecond)); - - // Step 9. - object->setFixedSlot(PlainTimeObject::ISO_NANOSECOND_SLOT, - Int32Value(nanosecond)); - - // Step 10. return object; } @@ -411,9 +309,9 @@ PlainTimeObject* js::temporal::CreateTemporalTime(JSContext* cx, * BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ template -static BalancedTime BalanceTime(IntT hour, IntT minute, IntT second, - IntT millisecond, IntT microsecond, - IntT nanosecond) { +static TimeRecord BalanceTime(IntT hour, IntT minute, IntT second, + IntT millisecond, IntT microsecond, + IntT nanosecond) { // Combined floor'ed division and modulo operation. auto divmod = [](IntT dividend, int32_t divisor, int32_t* remainder) { MOZ_ASSERT(divisor > 0); @@ -431,7 +329,7 @@ static BalancedTime BalanceTime(IntT hour, IntT minute, IntT second, return quotient; }; - PlainTime time = {}; + Time time = {}; // Steps 1-2. microsecond += divmod(nanosecond, 1000, &time.nanosecond); @@ -449,7 +347,7 @@ static BalancedTime BalanceTime(IntT hour, IntT minute, IntT second, hour += divmod(minute, 60, &time.minute); // Steps 11-12. - int32_t days = divmod(hour, 24, &time.hour); + int64_t days = divmod(hour, 24, &time.hour); // Step 13. MOZ_ASSERT(IsValidTime(time)); @@ -459,9 +357,9 @@ static BalancedTime BalanceTime(IntT hour, IntT minute, IntT second, /** * BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -static BalancedTime BalanceTime(int32_t hour, int32_t minute, int32_t second, - int32_t millisecond, int32_t microsecond, - int32_t nanosecond) { +static TimeRecord BalanceTime(int32_t hour, int32_t minute, int32_t second, + int32_t millisecond, int32_t microsecond, + int32_t nanosecond) { MOZ_ASSERT(-24 < hour && hour < 2 * 24); MOZ_ASSERT(-60 < minute && minute < 2 * 60); MOZ_ASSERT(-60 < second && second < 2 * 60); @@ -476,8 +374,7 @@ static BalancedTime BalanceTime(int32_t hour, int32_t minute, int32_t second, /** * BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -BalancedTime js::temporal::BalanceTime(const PlainTime& time, - int64_t nanoseconds) { +TimeRecord js::temporal::BalanceTime(const Time& time, int64_t nanoseconds) { MOZ_ASSERT(IsValidTime(time)); MOZ_ASSERT(std::abs(nanoseconds) <= ToNanoseconds(TemporalUnit::Day)); @@ -487,10 +384,49 @@ BalancedTime js::temporal::BalanceTime(const PlainTime& time, } /** - * DifferenceTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2 ) + * TimeDurationFromComponents ( hours, minutes, seconds, milliseconds, + * microseconds, nanoseconds ) */ -NormalizedTimeDuration js::temporal::DifferenceTime(const PlainTime& time1, - const PlainTime& time2) { +static TimeDuration TimeDurationFromComponents(int32_t hours, int32_t minutes, + int32_t seconds, + int32_t milliseconds, + int32_t microseconds, + int32_t nanoseconds) { + MOZ_ASSERT(std::abs(hours) <= 23); + MOZ_ASSERT(std::abs(minutes) <= 59); + MOZ_ASSERT(std::abs(seconds) <= 59); + MOZ_ASSERT(std::abs(milliseconds) <= 999); + MOZ_ASSERT(std::abs(microseconds) <= 999); + MOZ_ASSERT(std::abs(nanoseconds) <= 999); + + // Steps 1-5. + int64_t nanos = int64_t(hours); + nanos *= 60; + nanos += int64_t(minutes); + nanos *= 60; + nanos += int64_t(seconds); + nanos *= 1000; + nanos += int64_t(milliseconds); + nanos *= 1000; + nanos += int64_t(microseconds); + nanos *= 1000; + nanos += int64_t(nanoseconds); + MOZ_ASSERT(std::abs(nanos) < ToNanoseconds(TemporalUnit::Day)); + + auto timeDuration = TimeDuration::fromNanoseconds(nanos); + + // Step 6. + MOZ_ASSERT(IsValidTimeDuration(timeDuration)); + + // Step 7. + return timeDuration; +} + +/** + * DifferenceTime ( time1, time2 ) + */ +TimeDuration js::temporal::DifferenceTime(const Time& time1, + const Time& time2) { MOZ_ASSERT(IsValidTime(time1)); MOZ_ASSERT(IsValidTime(time2)); @@ -513,123 +449,247 @@ NormalizedTimeDuration js::temporal::DifferenceTime(const PlainTime& time1, int32_t nanoseconds = time2.nanosecond - time1.nanosecond; // Step 7. - auto result = NormalizeTimeDuration(hours, minutes, seconds, milliseconds, - microseconds, nanoseconds); + auto result = ::TimeDurationFromComponents( + hours, minutes, seconds, milliseconds, microseconds, nanoseconds); // Step 8. - MOZ_ASSERT(result.abs().toNanoseconds() < - Int128{ToNanoseconds(TemporalUnit::Day)}); + MOZ_ASSERT(result.abs() < TimeDuration::fromDays(1)); // Step 9. return result; } /** - * ToTemporalTime ( item [ , overflow ] ) + * ToTemporalTimeRecord ( temporalTimeLike [ , completeness ] ) */ -static bool ToTemporalTime(JSContext* cx, Handle item, - TemporalOverflow overflow, PlainTime* result) { - // Steps 1-2. (Not applicable in our implementation.) +static bool ToTemporalTimeRecord(JSContext* cx, + Handle temporalTimeLike, + TemporalTimeLike* result) { + // Steps 1-3. (Not applicable in our implementation.) - // Steps 3-4. - if (item.isObject()) { - // Step 3. - Rooted itemObj(cx, &item.toObject()); + // Step 4. + bool any = false; - // Step 3.a. - if (auto* time = itemObj->maybeUnwrapIf()) { - *result = ToPlainTime(time); - return true; + Rooted value(cx); + auto getTimeProperty = [&](Handle property, const char* name, + double* num) { + if (!GetProperty(cx, temporalTimeLike, temporalTimeLike, property, + &value)) { + return false; } - // Step 3.b. - if (auto* zonedDateTime = itemObj->maybeUnwrapIf()) { - auto epochInstant = ToInstant(zonedDateTime); - Rooted timeZone(cx, zonedDateTime->timeZone()); + if (!value.isUndefined()) { + any = true; - if (!timeZone.wrap(cx)) { + if (!ToIntegerWithTruncation(cx, value, name, num)) { return false; } - - // Steps 3.b.i-iii. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, timeZone, epochInstant, &dateTime)) { - return false; - } - - // Step 3.b.iv. - *result = dateTime.time; - return true; } + return true; + }; - // Step 3.c. - if (auto* dateTime = itemObj->maybeUnwrapIf()) { - *result = ToPlainTime(dateTime); - return true; - } - - // Step 3.d. - TemporalTimeLike timeResult; - if (!ToTemporalTimeRecord(cx, itemObj, &timeResult)) { - return false; - } - - // Step 3.e. - if (!RegulateTime(cx, timeResult, overflow, result)) { - return false; - } - } else { - // Step 4. - - // Step 4.a. - if (!item.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, - nullptr, "not a string"); - return false; - } - Rooted string(cx, item.toString()); - - // Step 4.b. - if (!ParseTemporalTimeString(cx, string, result)) { - return false; - } - - // Step 4.c. - MOZ_ASSERT(IsValidTime(*result)); + // Steps 5-6. + if (!getTimeProperty(cx->names().hour, "hour", &result->hour)) { + return false; } - // Step 5. + // Steps 7-8. + if (!getTimeProperty(cx->names().microsecond, "microsecond", + &result->microsecond)) { + return false; + } + + // Steps 9-10. + if (!getTimeProperty(cx->names().millisecond, "millisecond", + &result->millisecond)) { + return false; + } + + // Steps 11-12. + if (!getTimeProperty(cx->names().minute, "minute", &result->minute)) { + return false; + } + + // Steps 13-14. + if (!getTimeProperty(cx->names().nanosecond, "nanosecond", + &result->nanosecond)) { + return false; + } + + // Steps 15-16. + if (!getTimeProperty(cx->names().second, "second", &result->second)) { + return false; + } + + // Step 17. + if (!any) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_TIME_MISSING_UNIT); + return false; + } + + // Step 18. + return true; +} + +struct TimeOptions { + TemporalOverflow overflow = TemporalOverflow::Constrain; +}; + +/** + * ToTemporalTime ( item [ , options ] ) + */ +static bool ToTemporalTimeOptions(JSContext* cx, Handle options, + TimeOptions* result) { + if (options.isUndefined()) { + *result = {}; + return true; + } + + // NOTE: |options| are only passed from `Temporal.PlainTime.from`. + + Rooted resolvedOptions( + cx, RequireObjectArg(cx, "options", "from", options)); + if (!resolvedOptions) { + return false; + } + + auto overflow = TemporalOverflow::Constrain; + if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) { + return false; + } + + *result = {overflow}; return true; } /** - * ToTemporalTime ( item [ , overflow ] ) + * ToTemporalTime ( item [ , options ] ) */ -static PlainTimeObject* ToTemporalTime(JSContext* cx, Handle item, - TemporalOverflow overflow) { - PlainTime time; - if (!ToTemporalTime(cx, item, overflow, &time)) { - return nullptr; - } - MOZ_ASSERT(IsValidTime(time)); +static bool ToTemporalTime(JSContext* cx, Handle item, + Handle options, Time* result) { + // Step 2.a. + if (auto* plainTime = item->maybeUnwrapIf()) { + auto time = plainTime->time(); - return CreateTemporalTime(cx, time); + // Steps 2.a.i-ii. + TimeOptions ignoredOptions; + if (!ToTemporalTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.a.iii. + *result = time; + return true; + } + + // Step 2.b. + if (auto* dateTime = item->maybeUnwrapIf()) { + auto time = dateTime->time(); + + // Steps 2.b.i-ii. + TimeOptions ignoredOptions; + if (!ToTemporalTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.b.iii. + *result = time; + return true; + } + + // Step 2.c. + if (auto* zonedDateTime = item->maybeUnwrapIf()) { + auto epochNs = zonedDateTime->epochNanoseconds(); + Rooted timeZone(cx, zonedDateTime->timeZone()); + + if (!timeZone.wrap(cx)) { + return false; + } + + // Steps 2.c.i. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, timeZone, epochNs, &dateTime)) { + return false; + } + + // Steps 2.c.ii-iii. + TimeOptions ignoredOptions; + if (!ToTemporalTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.c.iv. + *result = dateTime.time; + return true; + } + + // Step 2.d. + TemporalTimeLike timeResult{}; + if (!ToTemporalTimeRecord(cx, item, &timeResult)) { + return false; + } + + // Steps 2.e-f. + TimeOptions resolvedOptions; + if (!ToTemporalTimeOptions(cx, options, &resolvedOptions)) { + return false; + } + auto [overflow] = resolvedOptions; + + // Step 2.g and 4. + return RegulateTime(cx, timeResult, overflow, result); } /** - * ToTemporalTime ( item [ , overflow ] ) + * ToTemporalTime ( item [ , options ] ) + */ +static bool ToTemporalTime(JSContext* cx, Handle item, + Handle options, Time* result) { + // Step 1. (Not applicable in our implementation.) + + // Step 2. + if (item.isObject()) { + Rooted itemObj(cx, &item.toObject()); + return ToTemporalTime(cx, itemObj, options, result); + } + + // Step 3.a. + if (!item.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, + nullptr, "not a string"); + return false; + } + Rooted string(cx, item.toString()); + + // Steps 3.b-e. + if (!ParseTemporalTimeString(cx, string, result)) { + return false; + } + MOZ_ASSERT(IsValidTime(*result)); + + // Steps 3.f-g. + TimeOptions ignoredOptions; + if (!ToTemporalTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 4. + return true; +} + +/** + * ToTemporalTime ( item [ , options ] ) */ bool js::temporal::ToTemporalTime(JSContext* cx, Handle item, - PlainTime* result) { - return ToTemporalTime(cx, item, TemporalOverflow::Constrain, result); + Time* result) { + return ToTemporalTime(cx, item, UndefinedHandleValue, result); } /** - * CompareTemporalTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, - * ns2 ) + * CompareTimeRecord ( time1, time2 ) */ -int32_t js::temporal::CompareTemporalTime(const PlainTime& one, - const PlainTime& two) { +int32_t js::temporal::CompareTimeRecord(const Time& one, const Time& two) { // Steps 1-2. if (int32_t diff = one.hour - two.hour) { return diff < 0 ? -1 : 1; @@ -664,92 +724,7 @@ int32_t js::temporal::CompareTemporalTime(const PlainTime& one, return 0; } -/** - * ToTemporalTimeRecord ( temporalTimeLike [ , completeness ] ) - */ -static bool ToTemporalTimeRecord(JSContext* cx, - Handle temporalTimeLike, - TemporalTimeLike* result) { - // Steps 1 and 3-4. (Not applicable in our implementation.) - - // Step 2. (Inlined call to PrepareTemporalFields.) - // PrepareTemporalFields, step 1. (Not applicable in our implementation.) - - // PrepareTemporalFields, step 2. - bool any = false; - - // PrepareTemporalFields, steps 3-4. (Loop unrolled) - Rooted value(cx); - auto getTimeProperty = [&](Handle property, const char* name, - double* num) { - // Step 4.a. - if (!GetProperty(cx, temporalTimeLike, temporalTimeLike, property, - &value)) { - return false; - } - - // Step 4.b. - if (!value.isUndefined()) { - // Step 4.b.i. - any = true; - - // Step 4.b.ii.2. - if (!ToIntegerWithTruncation(cx, value, name, num)) { - return false; - } - } - return true; - }; - - if (!getTimeProperty(cx->names().hour, "hour", &result->hour)) { - return false; - } - if (!getTimeProperty(cx->names().microsecond, "microsecond", - &result->microsecond)) { - return false; - } - if (!getTimeProperty(cx->names().millisecond, "millisecond", - &result->millisecond)) { - return false; - } - if (!getTimeProperty(cx->names().minute, "minute", &result->minute)) { - return false; - } - if (!getTimeProperty(cx->names().nanosecond, "nanosecond", - &result->nanosecond)) { - return false; - } - if (!getTimeProperty(cx->names().second, "second", &result->second)) { - return false; - } - - // PrepareTemporalFields, step 5. - if (!any) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_TIME_MISSING_UNIT); - return false; - } - - // Steps 5-16. (Performed implicitly in our implementation.) - - // Step 17. - return true; -} - -/** - * ToTemporalTimeRecord ( temporalTimeLike [ , completeness ] ) - */ -bool js::temporal::ToTemporalTimeRecord(JSContext* cx, - Handle temporalTimeLike, - TemporalTimeLike* result) { - // Step 3.a. (Set all fields to zero.) - *result = {}; - - // Steps 1-2 and 4-17. - return ::ToTemporalTimeRecord(cx, temporalTimeLike, result); -} - -static int64_t TimeToNanos(const PlainTime& time) { +static int64_t TimeToNanos(const Time& time) { // No overflow possible because the input is a valid time. MOZ_ASSERT(IsValidTime(time)); @@ -765,12 +740,11 @@ static int64_t TimeToNanos(const PlainTime& time) { } /** - * RoundTime ( hour, minute, second, millisecond, microsecond, nanosecond, - * increment, unit, roundingMode ) + * RoundTime ( time, increment, unit, roundingMode ) */ -RoundedTime js::temporal::RoundTime(const PlainTime& time, Increment increment, - TemporalUnit unit, - TemporalRoundingMode roundingMode) { +TimeRecord js::temporal::RoundTime(const Time& time, Increment increment, + TemporalUnit unit, + TemporalRoundingMode roundingMode) { MOZ_ASSERT(IsValidTime(time)); MOZ_ASSERT(unit >= TemporalUnit::Day); MOZ_ASSERT_IF(unit > TemporalUnit::Day, @@ -780,11 +754,8 @@ RoundedTime js::temporal::RoundTime(const PlainTime& time, Increment increment, int32_t days = 0; auto [hour, minute, second, millisecond, microsecond, nanosecond] = time; - // Take the same approach as used in RoundDuration() to perform exact - // mathematical operations without possible loss of precision. - // Steps 1-6. - PlainTime quantity; + Time quantity; int32_t* result; switch (unit) { case TemporalUnit::Day: @@ -861,37 +832,25 @@ RoundedTime js::temporal::RoundTime(const PlainTime& time, Increment increment, } // Steps 10-16. - auto balanced = - ::BalanceTime(hour, minute, second, millisecond, microsecond, nanosecond); - return {int64_t(balanced.days), balanced.time}; + return ::BalanceTime(hour, minute, second, millisecond, microsecond, + nanosecond); } /** - * AddTime ( hour, minute, second, millisecond, microsecond, nanosecond, norm ) + * AddTime ( time, timeDuration ) */ -AddedTime js::temporal::AddTime(const PlainTime& time, - const NormalizedTimeDuration& duration) { +TimeRecord js::temporal::AddTime(const Time& time, + const TimeDuration& duration) { MOZ_ASSERT(IsValidTime(time)); - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); + MOZ_ASSERT(IsValidTimeDuration(duration)); - auto [seconds, nanoseconds] = duration; - if (seconds < 0 && nanoseconds > 0) { - seconds += 1; - nanoseconds -= 1'000'000'000; - } + auto [seconds, nanoseconds] = duration.denormalize(); MOZ_ASSERT(std::abs(nanoseconds) <= 999'999'999); - // Step 1. - int64_t second = time.second + seconds; - - // Step 2. - int32_t nanosecond = time.nanosecond + nanoseconds; - - // Step 3. - auto balanced = - ::BalanceTime(time.hour, time.minute, second, time.millisecond, - time.microsecond, nanosecond); - return {balanced.days, balanced.time}; + // Steps 1-2. + return ::BalanceTime(time.hour, time.minute, time.second + seconds, + time.millisecond, time.microsecond, + time.nanosecond + nanoseconds); } /** @@ -900,20 +859,18 @@ AddedTime js::temporal::AddTime(const PlainTime& time, static bool DifferenceTemporalPlainTime(JSContext* cx, TemporalDifference operation, const CallArgs& args) { - auto temporalTime = - ToPlainTime(&args.thisv().toObject().as()); + auto temporalTime = args.thisv().toObject().as().time(); - // Step 1. (Not applicable in our implementation.) - - // Step 2. - PlainTime other; + // Step 1. + Time other; if (!ToTemporalTime(cx, args.get(0), &other)) { return false; } - // Steps 3-4. + // Steps 2-3. DifferenceSettings settings; if (args.hasDefined(1)) { + // Step 2. Rooted options( cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); if (!options) { @@ -921,20 +878,13 @@ static bool DifferenceTemporalPlainTime(JSContext* cx, } // Step 3. - Rooted resolvedOptions(cx, - SnapshotOwnProperties(cx, options)); - if (!resolvedOptions) { - return false; - } - - // Step 4. - if (!GetDifferenceSettings( - cx, operation, resolvedOptions, TemporalUnitGroup::Time, - TemporalUnit::Nanosecond, TemporalUnit::Hour, &settings)) { + if (!GetDifferenceSettings(cx, operation, options, TemporalUnitGroup::Time, + TemporalUnit::Nanosecond, TemporalUnit::Hour, + &settings)) { return false; } } else { - // Steps 3-4. + // Steps 2-3. settings = { TemporalUnit::Nanosecond, TemporalUnit::Hour, @@ -943,29 +893,27 @@ static bool DifferenceTemporalPlainTime(JSContext* cx, }; } + // Step 4. + auto timeDuration = DifferenceTime(temporalTime, other); + // Step 5. - auto diff = DifferenceTime(temporalTime, other); + timeDuration = + RoundTimeDuration(timeDuration, settings.roundingIncrement, + settings.smallestUnit, settings.roundingMode); - // Step 6. - if (settings.smallestUnit != TemporalUnit::Nanosecond || - settings.roundingIncrement != Increment{1}) { - // Steps 6.a-b. - diff = RoundDuration(diff, settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode); - } - - // Step 7. - TimeDuration balancedDuration; - if (!BalanceTimeDuration(cx, diff, settings.largestUnit, &balancedDuration)) { + // Steps 6-7. + Duration duration; + if (!TemporalDurationFromInternal(cx, timeDuration, settings.largestUnit, + &duration)) { return false; } // Step 8. - auto duration = balancedDuration.toDuration(); if (operation == TemporalDifference::Since) { duration = duration.negate(); } + // Step 9. auto* result = CreateTemporalDuration(cx, duration); if (!result) { return false; @@ -975,30 +923,27 @@ static bool DifferenceTemporalPlainTime(JSContext* cx, return true; } -enum class PlainTimeDuration { Add, Subtract }; - /** - * AddDurationToOrSubtractDurationFromPlainTime ( operation, temporalTime, - * temporalDurationLike ) + * AddDurationToTime ( operation, temporalTime, temporalDurationLike ) */ -static bool AddDurationToOrSubtractDurationFromPlainTime( - JSContext* cx, PlainTimeDuration operation, const CallArgs& args) { +static bool AddDurationToTime(JSContext* cx, TemporalAddDuration operation, + const CallArgs& args) { auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); + auto time = temporalTime->time(); - // Step 1. (Not applicable in our implementation.) - - // Step 2. + // Step 1. Duration duration; - if (!ToTemporalDurationRecord(cx, args.get(0), &duration)) { + if (!ToTemporalDuration(cx, args.get(0), &duration)) { return false; } - // Step 3. - if (operation == PlainTimeDuration::Subtract) { + // Step 2. + if (operation == TemporalAddDuration::Subtract) { duration = duration.negate(); } - auto timeDuration = NormalizeTimeDuration(duration); + + // Step 3. (Inlined ToInternalDurationRecord) + auto timeDuration = TimeDurationFromComponents(duration); // Step 4. auto result = AddTime(time, timeDuration); @@ -1074,9 +1019,23 @@ static bool PlainTimeConstructor(JSContext* cx, unsigned argc, Value* vp) { } } - // Step 8. - auto* temporalTime = CreateTemporalTime(cx, args, hour, minute, second, - millisecond, microsecond, nanosecond); + // Steps 8-9. + Time time; + if (!RegulateTime(cx, + { + hour, + minute, + second, + millisecond, + microsecond, + nanosecond, + }, + TemporalOverflow::Reject, &time)) { + return false; + } + + // Step 10. + auto* temporalTime = CreateTemporalTime(cx, args, time); if (!temporalTime) { return false; } @@ -1091,30 +1050,19 @@ static bool PlainTimeConstructor(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Step 1. (Not applicable) - - auto overflow = TemporalOverflow::Constrain; - if (args.hasDefined(1)) { - // Step 2. - Rooted options(cx, - RequireObjectArg(cx, "options", "from", args[1])); - if (!options) { - return false; - } - - // Step 3. - if (!GetTemporalOverflowOption(cx, options, &overflow)) { - return false; - } + // Step 1. + Time result; + if (!ToTemporalTime(cx, args.get(0), args.get(1), &result)) { + return false; } + MOZ_ASSERT(IsValidTime(result)); - // Steps 4-5. - auto* result = ToTemporalTime(cx, args.get(0), overflow); - if (!result) { + auto* obj = temporal::CreateTemporalTime(cx, result); + if (!obj) { return false; } - args.rval().setObject(*result); + args.rval().setObject(*obj); return true; } @@ -1125,19 +1073,19 @@ static bool PlainTime_compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - PlainTime one; + Time one; if (!ToTemporalTime(cx, args.get(0), &one)) { return false; } // Step 2. - PlainTime two; + Time two; if (!ToTemporalTime(cx, args.get(1), &two)) { return false; } // Step 3. - args.rval().setInt32(CompareTemporalTime(one, two)); + args.rval().setInt32(CompareTimeRecord(one, two)); return true; } @@ -1147,7 +1095,7 @@ static bool PlainTime_compare(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_hour(JSContext* cx, const CallArgs& args) { // Step 3. auto* temporalTime = &args.thisv().toObject().as(); - args.rval().setInt32(temporalTime->isoHour()); + args.rval().setInt32(temporalTime->time().hour); return true; } @@ -1166,7 +1114,7 @@ static bool PlainTime_hour(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_minute(JSContext* cx, const CallArgs& args) { // Step 3. auto* temporalTime = &args.thisv().toObject().as(); - args.rval().setInt32(temporalTime->isoMinute()); + args.rval().setInt32(temporalTime->time().minute); return true; } @@ -1185,7 +1133,7 @@ static bool PlainTime_minute(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_second(JSContext* cx, const CallArgs& args) { // Step 3. auto* temporalTime = &args.thisv().toObject().as(); - args.rval().setInt32(temporalTime->isoSecond()); + args.rval().setInt32(temporalTime->time().second); return true; } @@ -1204,7 +1152,7 @@ static bool PlainTime_second(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_millisecond(JSContext* cx, const CallArgs& args) { // Step 3. auto* temporalTime = &args.thisv().toObject().as(); - args.rval().setInt32(temporalTime->isoMillisecond()); + args.rval().setInt32(temporalTime->time().millisecond); return true; } @@ -1223,7 +1171,7 @@ static bool PlainTime_millisecond(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_microsecond(JSContext* cx, const CallArgs& args) { // Step 3. auto* temporalTime = &args.thisv().toObject().as(); - args.rval().setInt32(temporalTime->isoMicrosecond()); + args.rval().setInt32(temporalTime->time().microsecond); return true; } @@ -1242,7 +1190,7 @@ static bool PlainTime_microsecond(JSContext* cx, unsigned argc, Value* vp) { static bool PlainTime_nanosecond(JSContext* cx, const CallArgs& args) { // Step 3. auto* temporalTime = &args.thisv().toObject().as(); - args.rval().setInt32(temporalTime->isoNanosecond()); + args.rval().setInt32(temporalTime->time().nanosecond); return true; } @@ -1260,8 +1208,7 @@ static bool PlainTime_nanosecond(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainTime_add(JSContext* cx, const CallArgs& args) { // Step 3. - return AddDurationToOrSubtractDurationFromPlainTime( - cx, PlainTimeDuration::Add, args); + return AddDurationToTime(cx, TemporalAddDuration::Add, args); } /** @@ -1278,8 +1225,7 @@ static bool PlainTime_add(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainTime_subtract(JSContext* cx, const CallArgs& args) { // Step 3. - return AddDurationToOrSubtractDurationFromPlainTime( - cx, PlainTimeDuration::Subtract, args); + return AddDurationToTime(cx, TemporalAddDuration::Subtract, args); } /** @@ -1296,7 +1242,7 @@ static bool PlainTime_subtract(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainTime_with(JSContext* cx, const CallArgs& args) { auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); + auto time = temporalTime->time(); // Step 3. Rooted temporalTimeLike( @@ -1308,22 +1254,7 @@ static bool PlainTime_with(JSContext* cx, const CallArgs& args) { return false; } - auto overflow = TemporalOverflow::Constrain; - if (args.hasDefined(1)) { - // Step 4. - Rooted options(cx, - RequireObjectArg(cx, "options", "with", args[1])); - if (!options) { - return false; - } - - // Step 5. - if (!GetTemporalOverflowOption(cx, options, &overflow)) { - return false; - } - } - - // Steps 6-18. + // Steps 4-16. TemporalTimeLike partialTime = { double(time.hour), double(time.minute), double(time.second), double(time.millisecond), @@ -1333,8 +1264,24 @@ static bool PlainTime_with(JSContext* cx, const CallArgs& args) { return false; } + // Steps 17-18 + auto overflow = TemporalOverflow::Constrain; + if (args.hasDefined(1)) { + // Step 17. + Rooted options(cx, + RequireObjectArg(cx, "options", "with", args[1])); + if (!options) { + return false; + } + + // Step 18. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } + } + // Step 19. - PlainTime result; + Time result; if (!RegulateTime(cx, partialTime, overflow, &result)) { return false; } @@ -1397,7 +1344,7 @@ static bool PlainTime_since(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainTime_round(JSContext* cx, const CallArgs& args) { auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); + auto time = temporalTime->time(); // Steps 3-12. auto smallestUnit = TemporalUnit::Auto; @@ -1481,16 +1428,15 @@ static bool PlainTime_round(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainTime.prototype.equals ( other ) */ static bool PlainTime_equals(JSContext* cx, const CallArgs& args) { - auto temporalTime = - ToPlainTime(&args.thisv().toObject().as()); + auto temporalTime = args.thisv().toObject().as().time(); // Step 3. - PlainTime other; + Time other; if (!ToTemporalTime(cx, args.get(0), &other)) { return false; } - // Steps 4-10. + // Steps 4-5. args.rval().setBoolean(temporalTime == other); return true; } @@ -1504,202 +1450,12 @@ static bool PlainTime_equals(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } -/** - * Temporal.PlainTime.prototype.toPlainDateTime ( temporalDate ) - */ -static bool PlainTime_toPlainDateTime(JSContext* cx, const CallArgs& args) { - auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); - - // Step 3. - Rooted plainDate(cx); - if (!ToTemporalDate(cx, args.get(0), &plainDate)) { - return false; - } - auto date = plainDate.date(); - auto calendar = plainDate.calendar(); - - // Step 4. - auto* result = CreateTemporalDateTime(cx, {date, time}, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.PlainTime.prototype.toPlainDateTime ( temporalDate ) - */ -static bool PlainTime_toPlainDateTime(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.PlainTime.prototype.toZonedDateTime ( item ) - * - * |item| is an options object with `plainDate` and `timeZone` properties. - */ -static bool PlainTime_toZonedDateTime(JSContext* cx, const CallArgs& args) { - auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); - - // Step 3. - Rooted itemObj( - cx, RequireObjectArg(cx, "item", "toZonedDateTime", args.get(0))); - if (!itemObj) { - return false; - } - - // Step 4. - Rooted temporalDateLike(cx); - if (!GetProperty(cx, itemObj, args[0], cx->names().plainDate, - &temporalDateLike)) { - return false; - } - - // Step 5. - if (temporalDateLike.isUndefined()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_PROPERTY, "plainDate"); - return false; - } - - // Step 6. - Rooted plainDate(cx); - if (!ToTemporalDate(cx, temporalDateLike, &plainDate)) { - return false; - } - auto date = plainDate.date(); - auto calendar = plainDate.calendar(); - - // Step 7. - Rooted temporalTimeZoneLike(cx); - if (!GetProperty(cx, itemObj, itemObj, cx->names().timeZone, - &temporalTimeZoneLike)) { - return false; - } - - // Step 8. - if (temporalTimeZoneLike.isUndefined()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_PROPERTY, "timeZone"); - return false; - } - - // Step 9. - Rooted timeZone(cx); - if (!ToTemporalTimeZone(cx, temporalTimeZoneLike, &timeZone)) { - return false; - } - - // Step 10. - Rooted temporalDateTime(cx); - if (!CreateTemporalDateTime(cx, {date, time}, calendar, &temporalDateTime)) { - return false; - } - - // Steps 11-12. - Instant instant; - if (!GetInstantFor(cx, timeZone, temporalDateTime, - TemporalDisambiguation::Compatible, &instant)) { - return false; - } - - // Step 13. - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.PlainTime.prototype.toZonedDateTime ( item ) - */ -static bool PlainTime_toZonedDateTime(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.PlainTime.prototype.getISOFields ( ) - */ -static bool PlainTime_getISOFields(JSContext* cx, const CallArgs& args) { - Rooted temporalTime( - cx, &args.thisv().toObject().as()); - auto time = ToPlainTime(temporalTime); - - // Step 3. - Rooted fields(cx, IdValueVector(cx)); - - // Step 4. - if (!fields.emplaceBack(NameToId(cx->names().isoHour), - Int32Value(time.hour))) { - return false; - } - - // Step 5. - if (!fields.emplaceBack(NameToId(cx->names().isoMicrosecond), - Int32Value(time.microsecond))) { - return false; - } - - // Step 6. - if (!fields.emplaceBack(NameToId(cx->names().isoMillisecond), - Int32Value(time.millisecond))) { - return false; - } - - // Step 7. - if (!fields.emplaceBack(NameToId(cx->names().isoMinute), - Int32Value(time.minute))) { - return false; - } - - // Step 8. - if (!fields.emplaceBack(NameToId(cx->names().isoNanosecond), - Int32Value(time.nanosecond))) { - return false; - } - - // Step 9. - if (!fields.emplaceBack(NameToId(cx->names().isoSecond), - Int32Value(time.second))) { - return false; - } - - // Step 10. - auto* obj = NewPlainObjectWithUniqueNames(cx, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainTime.prototype.getISOFields ( ) - */ -static bool PlainTime_getISOFields(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - /** * Temporal.PlainTime.prototype.toString ( [ options ] ) */ static bool PlainTime_toString(JSContext* cx, const CallArgs& args) { auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); + auto time = temporalTime->time(); SecondsStringPrecision precision = {Precision::Auto(), TemporalUnit::Nanosecond, Increment{1}}; @@ -1747,8 +1503,7 @@ static bool PlainTime_toString(JSContext* cx, const CallArgs& args) { RoundTime(time, precision.increment, precision.unit, roundingMode); // Step 11. - JSString* str = - TemporalTimeToString(cx, roundedTime.time, precision.precision); + JSString* str = TimeRecordToString(cx, roundedTime.time, precision.precision); if (!str) { return false; } @@ -1770,17 +1525,10 @@ static bool PlainTime_toString(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainTime.prototype.toLocaleString ( [ locales [ , options ] ] ) */ static bool PlainTime_toLocaleString(JSContext* cx, const CallArgs& args) { - auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); - - // Step 3. - JSString* str = TemporalTimeToString(cx, time, Precision::Auto()); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-4. + Handle required = cx->names().time; + Handle defaults = cx->names().time; + return TemporalObjectToLocaleString(cx, args, required, defaults); } /** @@ -1797,10 +1545,10 @@ static bool PlainTime_toLocaleString(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainTime_toJSON(JSContext* cx, const CallArgs& args) { auto* temporalTime = &args.thisv().toObject().as(); - auto time = ToPlainTime(temporalTime); + auto time = temporalTime->time(); // Step 3. - JSString* str = TemporalTimeToString(cx, time, Precision::Auto()); + JSString* str = TimeRecordToString(cx, time, Precision::Auto()); if (!str) { return false; } @@ -1851,9 +1599,6 @@ static const JSFunctionSpec PlainTime_prototype_methods[] = { JS_FN("since", PlainTime_since, 1, 0), JS_FN("round", PlainTime_round, 1, 0), JS_FN("equals", PlainTime_equals, 1, 0), - JS_FN("toPlainDateTime", PlainTime_toPlainDateTime, 1, 0), - JS_FN("toZonedDateTime", PlainTime_toZonedDateTime, 1, 0), - JS_FN("getISOFields", PlainTime_getISOFields, 0, 0), JS_FN("toString", PlainTime_toString, 0, 0), JS_FN("toLocaleString", PlainTime_toLocaleString, 0, 0), JS_FN("toJSON", PlainTime_toJSON, 0, 0), diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.h index 0614430e466..3ab15f33f96 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainTime.h @@ -7,6 +7,8 @@ #ifndef builtin_temporal_PlainTime_h #define builtin_temporal_PlainTime_h +#include "mozilla/Casting.h" + #include #include "builtin/temporal/TemporalTypes.h" @@ -25,51 +27,22 @@ class PlainTimeObject : public NativeObject { static const JSClass class_; static const JSClass& protoClass_; - // TODO: Consider compacting fields to reduce object size. - // - // ceil(log2(24)) + 2 * ceil(log2(60)) + 3 * ceil(log2(1000)) = 47 bits are - // needed to store a time value in a single int64. 47 bits can be stored as - // raw bits in a JS::Value. + static constexpr uint32_t PACKED_TIME_SLOT = 0; + static constexpr uint32_t SLOT_COUNT = 1; - static constexpr uint32_t ISO_HOUR_SLOT = 0; - static constexpr uint32_t ISO_MINUTE_SLOT = 1; - static constexpr uint32_t ISO_SECOND_SLOT = 2; - static constexpr uint32_t ISO_MILLISECOND_SLOT = 3; - static constexpr uint32_t ISO_MICROSECOND_SLOT = 4; - static constexpr uint32_t ISO_NANOSECOND_SLOT = 5; - static constexpr uint32_t SLOT_COUNT = 6; - - int32_t isoHour() const { return getFixedSlot(ISO_HOUR_SLOT).toInt32(); } - - int32_t isoMinute() const { return getFixedSlot(ISO_MINUTE_SLOT).toInt32(); } - - int32_t isoSecond() const { return getFixedSlot(ISO_SECOND_SLOT).toInt32(); } - - int32_t isoMillisecond() const { - return getFixedSlot(ISO_MILLISECOND_SLOT).toInt32(); - } - - int32_t isoMicrosecond() const { - return getFixedSlot(ISO_MICROSECOND_SLOT).toInt32(); - } - - int32_t isoNanosecond() const { - return getFixedSlot(ISO_NANOSECOND_SLOT).toInt32(); + /** + * Extract the time fields from this PlainTime object. + */ + Time time() const { + auto packed = PackedTime{mozilla::BitwiseCast( + getFixedSlot(PACKED_TIME_SLOT).toDouble())}; + return PackedTime::unpack(packed); } private: static const ClassSpec classSpec_; }; -/** - * Extract the time fields from the PlainTime object. - */ -inline PlainTime ToPlainTime(const PlainTimeObject* time) { - return {time->isoHour(), time->isoMinute(), - time->isoSecond(), time->isoMillisecond(), - time->isoMicrosecond(), time->isoNanosecond()}; -} - class Increment; enum class TemporalOverflow; enum class TemporalRoundingMode; @@ -79,7 +52,7 @@ enum class TemporalUnit; /** * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -bool IsValidTime(const PlainTime& time); +bool IsValidTime(const Time& time); /** * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) @@ -88,11 +61,6 @@ bool IsValidTime(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond); #endif -/** - * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) - */ -bool ThrowIfInvalidTime(JSContext* cx, const PlainTime& time); - /** * IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ @@ -101,33 +69,29 @@ bool ThrowIfInvalidTime(JSContext* cx, double hour, double minute, double nanosecond); /** - * CreateTemporalTime ( hour, minute, second, millisecond, microsecond, - * nanosecond [ , newTarget ] ) + * CreateTemporalTime ( time [ , newTarget ] ) */ -PlainTimeObject* CreateTemporalTime(JSContext* cx, const PlainTime& time); +PlainTimeObject* CreateTemporalTime(JSContext* cx, const Time& time); /** * ToTemporalTime ( item [ , overflow ] ) */ -bool ToTemporalTime(JSContext* cx, JS::Handle item, - PlainTime* result); +bool ToTemporalTime(JSContext* cx, JS::Handle item, Time* result); -struct AddedTime { - int32_t days = 0; - PlainTime time; +struct TimeRecord final { + int64_t days = 0; + Time time; }; /** - * AddTime ( hour, minute, second, millisecond, microsecond, nanosecond, norm ) + * AddTime ( time, timeDuration ) */ -AddedTime AddTime(const PlainTime& time, - const NormalizedTimeDuration& duration); +TimeRecord AddTime(const Time& time, const TimeDuration& duration); /** - * DifferenceTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2 ) + * DifferenceTime ( time1, time2 ) */ -NormalizedTimeDuration DifferenceTime(const PlainTime& time1, - const PlainTime& time2); +TimeDuration DifferenceTime(const Time& time1, const Time& time2); struct TemporalTimeLike final { double hour = 0; @@ -138,46 +102,28 @@ struct TemporalTimeLike final { double nanosecond = 0; }; -/** - * ToTemporalTimeRecord ( temporalTimeLike [ , completeness ] ) - */ -bool ToTemporalTimeRecord(JSContext* cx, JS::Handle temporalTimeLike, - TemporalTimeLike* result); - /** * RegulateTime ( hour, minute, second, millisecond, microsecond, nanosecond, * overflow ) */ bool RegulateTime(JSContext* cx, const TemporalTimeLike& time, - TemporalOverflow overflow, PlainTime* result); + TemporalOverflow overflow, Time* result); /** - * CompareTemporalTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, - * ns2 ) + * CompareTimeRecord ( time1, time2 ) */ -int32_t CompareTemporalTime(const PlainTime& one, const PlainTime& two); - -struct BalancedTime final { - int32_t days = 0; - PlainTime time; -}; +int32_t CompareTimeRecord(const Time& one, const Time& two); /** * BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ) */ -BalancedTime BalanceTime(const PlainTime& time, int64_t nanoseconds); - -struct RoundedTime final { - int64_t days = 0; - PlainTime time; -}; +TimeRecord BalanceTime(const Time& time, int64_t nanoseconds); /** - * RoundTime ( hour, minute, second, millisecond, microsecond, nanosecond, - * increment, unit, roundingMode ) + * RoundTime ( time, increment, unit, roundingMode ) */ -RoundedTime RoundTime(const PlainTime& time, Increment increment, - TemporalUnit unit, TemporalRoundingMode roundingMode); +TimeRecord RoundTime(const Time& time, Increment increment, TemporalUnit unit, + TemporalRoundingMode roundingMode); } /* namespace js::temporal */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.cpp index 9aaabe379c3..1d480540017 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.cpp @@ -7,36 +7,36 @@ #include "builtin/temporal/PlainYearMonth.h" #include "mozilla/Assertions.h" +#include "mozilla/EnumSet.h" -#include #include -#include "jsnum.h" #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/CalendarFields.h" #include "builtin/temporal/Duration.h" +#include "builtin/temporal/Instant.h" #include "builtin/temporal/PlainDate.h" +#include "builtin/temporal/PlainDateTime.h" +#include "builtin/temporal/PlainMonthDay.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" +#include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ToString.h" -#include "builtin/temporal/Wrapped.h" -#include "ds/IdValuePair.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" -#include "js/AllocPolicy.h" +#include "gc/GCEnum.h" #include "js/CallArgs.h" #include "js/CallNonGenericMethod.h" #include "js/Class.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/PropertyDescriptor.h" #include "js/PropertySpec.h" #include "js/RootingAPI.h" @@ -47,7 +47,6 @@ #include "vm/JSAtomState.h" #include "vm/JSContext.h" #include "vm/JSObject.h" -#include "vm/ObjectOperations.h" #include "vm/PlainObject.h" #include "vm/StringType.h" @@ -62,285 +61,268 @@ static inline bool IsPlainYearMonth(Handle v) { } /** - * ISOYearMonthWithinLimits ( year, month ) + * ISOYearMonthWithinLimits ( isoDate ) */ -template -static bool ISOYearMonthWithinLimits(T year, int32_t month) { - static_assert(std::is_same_v || std::is_same_v); +bool js::temporal::ISOYearMonthWithinLimits(const ISODate& isoDate) { + MOZ_ASSERT(IsValidISODate(isoDate)); - // Step 1. - MOZ_ASSERT(IsInteger(year)); - MOZ_ASSERT(1 <= month && month <= 12); + constexpr auto min = ISODate::min(); + constexpr auto max = ISODate::max(); - // Step 2. - if (year < -271821 || year > 275760) { - return false; + const auto& year = isoDate.year; + + // Fast-path when the input is definitely in range. + if (min.year < year && year < max.year) { + return true; } - // Step 3. - if (year == -271821 && month < 4) { - return false; + // Check |isoDate| is within the valid limits. + if (year < 0) { + return isoDate >= ISODate{min.year, min.month, 1}; } - - // Step 4. - if (year == 275760 && month > 9) { - return false; - } - - // Step 5. - return true; + return isoDate < ISODate{max.year, max.month + 1, 1}; } /** - * CreateTemporalYearMonth ( isoYear, isoMonth, calendar, referenceISODay [ , - * newTarget ] ) + * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] ) */ static PlainYearMonthObject* CreateTemporalYearMonth( - JSContext* cx, const CallArgs& args, double isoYear, double isoMonth, - double isoDay, Handle calendar) { - MOZ_ASSERT(IsInteger(isoYear)); - MOZ_ASSERT(IsInteger(isoMonth)); - MOZ_ASSERT(IsInteger(isoDay)); - + JSContext* cx, const CallArgs& args, const ISODate& isoDate, + Handle calendar) { // Step 1. - if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { - return nullptr; - } - - // FIXME: spec issue - Consider calling ISODateTimeWithinLimits to include - // testing |referenceISODay|? - - // Step 2. - if (!ISOYearMonthWithinLimits(isoYear, int32_t(isoMonth))) { + if (!ISOYearMonthWithinLimits(isoDate)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID); return nullptr; } - // Steps 3-4. + // Steps 2-3. Rooted proto(cx); if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PlainYearMonth, &proto)) { return nullptr; } - auto* obj = NewObjectWithClassProto(cx, proto); - if (!obj) { + auto* object = NewObjectWithClassProto(cx, proto); + if (!object) { return nullptr; } - // Step 5. - obj->setFixedSlot(PlainYearMonthObject::ISO_YEAR_SLOT, - Int32Value(int32_t(isoYear))); - - // Step 6. - obj->setFixedSlot(PlainYearMonthObject::ISO_MONTH_SLOT, - Int32Value(int32_t(isoMonth))); - - // Step 7. - obj->setFixedSlot(PlainYearMonthObject::CALENDAR_SLOT, - calendar.toSlotValue()); - - // Step 8. - obj->setFixedSlot(PlainYearMonthObject::ISO_DAY_SLOT, - Int32Value(int32_t(isoDay))); - - // Step 9. - return obj; -} - -/** - * CreateTemporalYearMonth ( isoYear, isoMonth, calendar, referenceISODay [ , - * newTarget ] ) - */ -PlainYearMonthObject* js::temporal::CreateTemporalYearMonth( - JSContext* cx, const PlainDate& date, Handle calendar) { - const auto& [isoYear, isoMonth, isoDay] = date; - - // Step 1. - if (!ThrowIfInvalidISODate(cx, date)) { - return nullptr; - } - - // FIXME: spec issue - Consider calling ISODateTimeWithinLimits to include - // testing |referenceISODay|? - - // Step 2. - if (!ISOYearMonthWithinLimits(isoYear, isoMonth)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID); - return nullptr; - } - - // Steps 3-4. - auto* obj = NewBuiltinClassInstance(cx); - if (!obj) { - return nullptr; - } - - // Step 5. - obj->setFixedSlot(PlainYearMonthObject::ISO_YEAR_SLOT, Int32Value(isoYear)); - - // Step 6. - obj->setFixedSlot(PlainYearMonthObject::ISO_MONTH_SLOT, Int32Value(isoMonth)); - - // Step 7. - obj->setFixedSlot(PlainYearMonthObject::CALENDAR_SLOT, - calendar.toSlotValue()); - - // Step 8. - obj->setFixedSlot(PlainYearMonthObject::ISO_DAY_SLOT, Int32Value(isoDay)); - - // Step 9. - return obj; -} - -/** - * ToTemporalYearMonth ( item [ , options ] ) - */ -static Wrapped ToTemporalYearMonth( - JSContext* cx, Handle item, - Handle maybeOptions = nullptr) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Rooted maybeResolvedOptions(cx); - if (maybeOptions) { - maybeResolvedOptions = SnapshotOwnProperties(cx, maybeOptions); - if (!maybeResolvedOptions) { - return nullptr; - } - } - - // Step 3. - if (item.isObject()) { - Rooted itemObj(cx, &item.toObject()); - - // Step 3.a. - if (itemObj->canUnwrapAs()) { - return itemObj; - } - - // Step 3.b. - Rooted calendarValue(cx); - if (!GetTemporalCalendarWithISODefault(cx, itemObj, &calendarValue)) { - return nullptr; - } - - // Step 3.c. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return nullptr; - } - - // Step 3.d. - Rooted fields( - cx, PrepareCalendarFields(cx, calendar, itemObj, - { - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - })); - if (!fields) { - return nullptr; - } - - // Step 3.e. - if (maybeResolvedOptions) { - return temporal::CalendarYearMonthFromFields(cx, calendar, fields, - maybeResolvedOptions); - } - return CalendarYearMonthFromFields(cx, calendar, fields); - } - // Step 4. - if (!item.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, - nullptr, "not a string"); - return nullptr; - } - Rooted string(cx, item.toString()); + auto packedDate = PackedDate::pack(isoDate); + object->setFixedSlot(PlainYearMonthObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); // Step 5. - PlainDate result; - Rooted calendarString(cx); - if (!ParseTemporalYearMonthString(cx, string, &result, &calendarString)) { - return nullptr; - } + object->setFixedSlot(PlainYearMonthObject::CALENDAR_SLOT, + calendar.toSlotValue()); - // Steps 6-9. - Rooted calendarValue(cx, CalendarValue(CalendarId::ISO8601)); - if (calendarString) { - if (!ToBuiltinCalendar(cx, calendarString, &calendarValue)) { - return nullptr; - } - } - - // Step 10. - if (maybeResolvedOptions) { - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return nullptr; - } - } - - // Step 11. - Rooted obj( - cx, CreateTemporalYearMonth(cx, result, calendarValue)); - if (!obj) { - return nullptr; - } - - // Step 12. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return nullptr; - } - - // FIXME: spec issue - reorder note to appear directly before - // CalendarYearMonthFromFields - - // Steps 13-14. - return CalendarYearMonthFromFields(cx, calendar, obj); + // Step 6. + return object; } +/** + * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] ) + */ +PlainYearMonthObject* js::temporal::CreateTemporalYearMonth( + JSContext* cx, Handle yearMonth) { + MOZ_ASSERT(IsValidISODate(yearMonth)); + + // Step 1. + MOZ_ASSERT(ISOYearMonthWithinLimits(yearMonth)); + + // Steps 2-3. + auto* object = NewBuiltinClassInstance(cx); + if (!object) { + return nullptr; + } + + // Step 4. + auto packedDate = PackedDate::pack(yearMonth); + object->setFixedSlot(PlainYearMonthObject::PACKED_DATE_SLOT, + PrivateUint32Value(packedDate.value)); + + // Step 5. + object->setFixedSlot(PlainYearMonthObject::CALENDAR_SLOT, + yearMonth.calendar().toSlotValue()); + + // Step 6. + return object; +} + +/** + * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] ) + */ +bool js::temporal::CreateTemporalYearMonth( + JSContext* cx, const ISODate& isoDate, Handle calendar, + MutableHandle result) { + MOZ_ASSERT(IsValidISODate(isoDate)); + + // Step 1. + if (!ISOYearMonthWithinLimits(isoDate)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID); + return false; + } + + // Steps 2-6. + result.set(PlainYearMonth{isoDate, calendar}); + return true; +} + +struct YearMonthOptions { + TemporalOverflow overflow = TemporalOverflow::Constrain; +}; + /** * ToTemporalYearMonth ( item [ , options ] ) */ -static bool ToTemporalYearMonth(JSContext* cx, Handle item, - PlainDate* result) { - auto obj = ToTemporalYearMonth(cx, item); - if (!obj) { +static bool ToTemporalYearMonthOptions(JSContext* cx, Handle options, + YearMonthOptions* result) { + if (options.isUndefined()) { + *result = {}; + return true; + } + + // NOTE: |options| are only passed from `Temporal.PlainYearMonth.from`. + + Rooted resolvedOptions( + cx, RequireObjectArg(cx, "options", "from", options)); + if (!resolvedOptions) { return false; } - *result = ToPlainDate(&obj.unwrap()); + auto overflow = TemporalOverflow::Constrain; + if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) { + return false; + } + + *result = {overflow}; return true; } /** * ToTemporalYearMonth ( item [ , options ] ) */ -static bool ToTemporalYearMonth(JSContext* cx, Handle item, - PlainDate* result, - MutableHandle calendar) { - auto* obj = ToTemporalYearMonth(cx, item).unwrapOrNull(); - if (!obj) { +static bool ToTemporalYearMonth(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { + // Step 1. (Not applicable in our implementation.) + + // Step 2.a. + if (auto* plainYearMonth = item->maybeUnwrapIf()) { + auto date = plainYearMonth->date(); + Rooted calendar(cx, plainYearMonth->calendar()); + if (!calendar.wrap(cx)) { + return false; + } + + // Steps 2.a.i-ii. + YearMonthOptions ignoredOptions; + if (!ToTemporalYearMonthOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 2.a.iii. + result.set(PlainYearMonth{date, calendar}); + return true; + } + + // Step 2.b. + Rooted calendar(cx); + if (!GetTemporalCalendarWithISODefault(cx, item, &calendar)) { return false; } - *result = ToPlainDate(obj); - calendar.set(obj->calendar()); - return calendar.wrap(cx); + // Step 2.c. + Rooted fields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + }, + &fields)) { + return false; + } + + // Steps 2.d-e. + YearMonthOptions resolvedOptions; + if (!ToTemporalYearMonthOptions(cx, options, &resolvedOptions)) { + return false; + } + auto [overflow] = resolvedOptions; + + // Step 2.f. + return CalendarYearMonthFromFields(cx, calendar, fields, overflow, result); +} + +/** + * ToTemporalYearMonth ( item [ , options ] ) + */ +static bool ToTemporalYearMonth(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { + // Step 1. (Not applicable in our implementation.) + + // Step 2. + if (item.isObject()) { + Rooted itemObj(cx, &item.toObject()); + return ToTemporalYearMonth(cx, itemObj, options, result); + } + + // Step 3. + if (!item.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, + nullptr, "not a string"); + return false; + } + Rooted string(cx, item.toString()); + + // Step 4. + ISODate date; + Rooted calendarString(cx); + if (!ParseTemporalYearMonthString(cx, string, &date, &calendarString)) { + return false; + } + + // Steps 5-7. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (calendarString) { + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } + } + + // Steps 8-9. + YearMonthOptions ignoredOptions; + if (!ToTemporalYearMonthOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 10-11. + Rooted yearMonth(cx); + if (!CreateTemporalYearMonth(cx, date, calendar, &yearMonth)) { + return false; + } + + // Step 12. + Rooted fields(cx); + if (!ISODateToFields(cx, yearMonth, &fields)) { + return false; + } + + // Steps 13-14. + return CalendarYearMonthFromFields(cx, calendar, fields, + TemporalOverflow::Constrain, result); +} + +/** + * ToTemporalYearMonth ( item [ , options ] ) + */ +static bool ToTemporalYearMonth(JSContext* cx, Handle item, + MutableHandle result) { + return ToTemporalYearMonth(cx, item, UndefinedHandleValue, result); } /** @@ -349,37 +331,32 @@ static bool ToTemporalYearMonth(JSContext* cx, Handle item, static bool DifferenceTemporalPlainYearMonth(JSContext* cx, TemporalDifference operation, const CallArgs& args) { - Rooted yearMonth( + Rooted yearMonth( cx, &args.thisv().toObject().as()); - // Step 1. (Not applicable in our implementation.) + // Step 1. + Rooted other(cx); + if (!ToTemporalYearMonth(cx, args.get(0), &other)) { + return false; + } // Step 2. - auto otherYearMonth = ToTemporalYearMonth(cx, args.get(0)); - if (!otherYearMonth) { - return false; - } - auto* unwrappedOtherYearMonth = &otherYearMonth.unwrap(); - auto otherYearMonthDate = ToPlainDate(unwrappedOtherYearMonth); - - Rooted> other(cx, otherYearMonth); - Rooted otherCalendar(cx, unwrappedOtherYearMonth->calendar()); - if (!otherCalendar.wrap(cx)) { - return false; - } + auto calendar = yearMonth.calendar(); // Step 3. - Rooted calendar(cx, yearMonth->calendar()); - - // Step 4. - if (!CalendarEqualsOrThrow(cx, calendar, otherCalendar)) { + if (!CalendarEquals(calendar, other.calendar())) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(calendar).data(), + CalendarIdentifier(other.calendar()).data()); return false; } - // Steps 5-6. + // Steps 4-5. DifferenceSettings settings; Rooted resolvedOptions(cx); if (args.hasDefined(1)) { + // Step 4. Rooted options( cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); if (!options) { @@ -387,20 +364,13 @@ static bool DifferenceTemporalPlainYearMonth(JSContext* cx, } // Step 5. - resolvedOptions = SnapshotOwnProperties(cx, options); - if (!resolvedOptions) { - return false; - } - - // Step 6. - if (!GetDifferenceSettings(cx, operation, resolvedOptions, - TemporalUnitGroup::Date, TemporalUnit::Month, - TemporalUnit::Month, TemporalUnit::Year, - &settings)) { + if (!GetDifferenceSettings(cx, operation, options, TemporalUnitGroup::Date, + TemporalUnit::Month, TemporalUnit::Month, + TemporalUnit::Year, &settings)) { return false; } } else { - // Steps 5-6. + // Steps 4-5. settings = { TemporalUnit::Month, TemporalUnit::Year, @@ -409,8 +379,8 @@ static bool DifferenceTemporalPlainYearMonth(JSContext* cx, }; } - // Step 7. - if (ToPlainDate(yearMonth) == otherYearMonthDate) { + // Step 6. + if (yearMonth.date() == other.date()) { auto* obj = CreateTemporalDuration(cx, {}); if (!obj) { return false; @@ -420,110 +390,88 @@ static bool DifferenceTemporalPlainYearMonth(JSContext* cx, return true; } - // Step 8. - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::DateAdd, - CalendarMethod::DateFromFields, - CalendarMethod::DateUntil, - CalendarMethod::Fields, - }, - &calendarRec)) { + // Step 7. + Rooted thisFields(cx); + if (!ISODateToFields(cx, yearMonth, &thisFields)) { return false; } + // Step 8. + MOZ_ASSERT(!thisFields.has(CalendarField::Day)); + thisFields.setDay(1); + // Step 9. - Rooted thisFields(cx); - JS::RootedVector thisFieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendarRec, yearMonth, - { - CalendarField::MonthCode, - CalendarField::Year, - }, - &thisFields, &thisFieldNames)) { + Rooted thisDate(cx); + if (!CalendarDateFromFields(cx, calendar, thisFields, + TemporalOverflow::Constrain, &thisDate)) { return false; } // Step 10. - Value one = Int32Value(1); - auto handleOne = Handle::fromMarkedLocation(&one); - if (!DefineDataProperty(cx, thisFields, cx->names().day, handleOne)) { + Rooted otherFields(cx); + if (!ISODateToFields(cx, other, &otherFields)) { return false; } // Step 11. - Rooted> thisDate( - cx, CalendarDateFromFields(cx, calendarRec, thisFields)); - if (!thisDate) { - return false; - } + MOZ_ASSERT(!otherFields.has(CalendarField::Day)); + otherFields.setDay(1); // Step 12. - Rooted otherFields( - cx, PrepareTemporalFields(cx, other, thisFieldNames)); - if (!otherFields) { + Rooted otherDate(cx); + if (!CalendarDateFromFields(cx, calendar, otherFields, + TemporalOverflow::Constrain, &otherDate)) { return false; } // Step 13. - if (!DefineDataProperty(cx, otherFields, cx->names().day, handleOne)) { - return false; - } - - // Step 14. - Rooted> otherDate( - cx, CalendarDateFromFields(cx, calendarRec, otherFields)); - if (!otherDate) { - return false; - } - - // Steps 15-16. DateDuration until; - if (resolvedOptions) { - if (!CalendarDateUntil(cx, calendarRec, thisDate, otherDate, - settings.largestUnit, resolvedOptions, &until)) { - return false; - } - } else { - if (!CalendarDateUntil(cx, calendarRec, thisDate, otherDate, - settings.largestUnit, &until)) { - return false; - } + if (!CalendarDateUntil(cx, calendar, thisDate, otherDate, + settings.largestUnit, &until)) { + return false; } + // Step 14. (Inlined AdjustDateDurationRecord) + // // We only care about years and months here, all other fields are set to zero. auto dateDuration = DateDuration{until.years, until.months}; - // Step 17. + // Step 15. + auto duration = InternalDuration{dateDuration, {}}; + + // Step 16. if (settings.smallestUnit != TemporalUnit::Month || settings.roundingIncrement != Increment{1}) { - // Steps 17.a-b. - NormalizedDuration roundResult; - if (!RoundDuration(cx, {dateDuration, {}}, settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode, thisDate, - calendarRec, &roundResult)) { - return false; - } + // Step 16.a. + auto destEpochNs = GetUTCEpochNanoseconds(ISODateTime{otherDate, {}}); - // Step 17.c. - auto toBalance = - DateDuration{roundResult.date.years, roundResult.date.months}; - if (!temporal::BalanceDateDurationRelative( - cx, toBalance, settings.largestUnit, settings.smallestUnit, - thisDate, calendarRec, &dateDuration)) { + // Steps 16.b-c. + auto dateTime = ISODateTime{thisDate, {}}; + + // Step 16.d. + Rooted timeZone(cx, TimeZoneValue{}); + if (!RoundRelativeDuration( + cx, duration, destEpochNs, dateTime, timeZone, calendar, + settings.largestUnit, settings.roundingIncrement, + settings.smallestUnit, settings.roundingMode, &duration)) { return false; } } + MOZ_ASSERT(IsValidDuration(duration)); + MOZ_ASSERT(duration.date.weeks == 0); + MOZ_ASSERT(duration.date.days == 0); + MOZ_ASSERT(duration.time == TimeDuration{}); + + // Step 17. (Inlined TemporalDurationFromInternal) + auto result = duration.date.toDuration(); // Step 18. - auto duration = - Duration{double(dateDuration.years), double(dateDuration.months)}; if (operation == TemporalDifference::Since) { - duration = duration.negate(); + result = result.negate(); } - auto* obj = CreateTemporalDuration(cx, duration); + // Step 19. + auto* obj = CreateTemporalDuration(cx, result); if (!obj) { return false; } @@ -532,108 +480,67 @@ static bool DifferenceTemporalPlainYearMonth(JSContext* cx, return true; } -enum class PlainYearMonthDuration { Add, Subtract }; - /** - * AddDurationToOrSubtractDurationFromPlainYearMonth ( operation, yearMonth, - * temporalDurationLike, options ) + * AddDurationToYearMonth ( operation, yearMonth, temporalDurationLike, options + * ) */ -static bool AddDurationToOrSubtractDurationFromPlainYearMonth( - JSContext* cx, PlainYearMonthDuration operation, const CallArgs& args) { - Rooted yearMonth( +static bool AddDurationToYearMonth(JSContext* cx, TemporalAddDuration operation, + const CallArgs& args) { + Rooted yearMonth( cx, &args.thisv().toObject().as()); // Step 1. Duration duration; - if (!ToTemporalDurationRecord(cx, args.get(0), &duration)) { + if (!ToTemporalDuration(cx, args.get(0), &duration)) { return false; } // Step 2. - if (operation == PlainYearMonthDuration::Subtract) { + if (operation == TemporalAddDuration::Subtract) { duration = duration.negate(); } - // Step 3. - Rooted options(cx); + // Steps 3-4. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { - const char* name = - operation == PlainYearMonthDuration::Add ? "add" : "subtract"; - options = RequireObjectArg(cx, "options", name, args[1]); - } else { - // TODO: Avoid creating an options object if not necessary. - options = NewPlainObjectWithProto(cx, nullptr); - } - if (!options) { - return false; - } + // Step 3. + Rooted options( + cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); + if (!options) { + return false; + } - // Step 4. - auto timeDuration = NormalizeTimeDuration(duration); + // Step 4. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } + } // Step 5. - auto balancedTime = BalanceTimeDuration(timeDuration, TemporalUnit::Day); + int32_t sign = DurationSign(duration); - // Steps 6 and 15. (Reordered) - auto durationToAdd = DateDuration{ - int64_t(duration.years), - int64_t(duration.months), - int64_t(duration.weeks), - int64_t(duration.days) + balancedTime.days, - }; + // Step 6. + auto calendar = yearMonth.calendar(); // Step 7. - int32_t sign = DurationSign(durationToAdd); + Rooted fields(cx); + if (!ISODateToFields(cx, yearMonth, &fields)) { + return false; + } // Step 8. - Rooted calendarValue(cx, yearMonth->calendar()); - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateAdd, - CalendarMethod::DateFromFields, - CalendarMethod::Day, - CalendarMethod::Fields, - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return false; - }; + MOZ_ASSERT(!fields.has(CalendarField::Day)); + fields.setDay(1); // Step 9. - Rooted fields(cx); - JS::RootedVector fieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, yearMonth, - { - CalendarField::MonthCode, - CalendarField::Year, - }, - &fields, &fieldNames)) { + Rooted intermediateDate(cx); + if (!CalendarDateFromFields(cx, calendar, fields, TemporalOverflow::Constrain, + &intermediateDate)) { return false; } - // Step 10. - Rooted fieldsCopy(cx, SnapshotOwnProperties(cx, fields)); - if (!fieldsCopy) { - return false; - } - - // Step 11. - Value one = Int32Value(1); - auto handleOne = Handle::fromMarkedLocation(&one); - if (!DefineDataProperty(cx, fields, cx->names().day, handleOne)) { - return false; - } - - // Step 12. - Rooted> intermediateDate( - cx, CalendarDateFromFields(cx, calendar, fields)); - if (!intermediateDate) { - return false; - } - - // Steps 13-14. - Rooted> date(cx); + // Steps 10-11. + ISODate date; if (sign < 0) { // |intermediateDate| is initialized to the first day of |yearMonth|'s // month. Compute the last day of |yearMonth|'s month by first adding one @@ -649,79 +556,55 @@ static bool AddDurationToOrSubtractDurationFromPlainYearMonth( // some days are skipped, for example consider the Julian-to-Gregorian // calendar transition. - // Step 13.a. + // Step 10.a. auto oneMonthDuration = DateDuration{0, 1}; - // Step 13.b. - Rooted> nextMonth( - cx, CalendarDateAdd(cx, calendar, intermediateDate, oneMonthDuration)); - if (!nextMonth) { + // Step 10.b. + ISODate nextMonth; + if (!CalendarDateAdd(cx, calendar, intermediateDate, oneMonthDuration, + TemporalOverflow::Constrain, &nextMonth)) { return false; } - auto* unwrappedNextMonth = nextMonth.unwrap(cx); - if (!unwrappedNextMonth) { - return false; - } - auto nextMonthDate = ToPlainDate(unwrappedNextMonth); + // Step 10.c. + date = BalanceISODate(nextMonth, -1); - // Step 13.c. - auto endOfMonthISO = BalanceISODate(nextMonthDate.year, nextMonthDate.month, - nextMonthDate.day - 1); - - // Step 13.d. - Rooted endOfMonth(cx); - if (!CreateTemporalDate(cx, endOfMonthISO, calendar.receiver(), - &endOfMonth)) { - return false; - } - - // Step 13.e. - Rooted day(cx); - if (!CalendarDay(cx, calendar, endOfMonth.date(), &day)) { - return false; - } - - // Step 13.f. - if (!DefineDataProperty(cx, fieldsCopy, cx->names().day, day)) { - return false; - } - - // Step 13.g. - date = CalendarDateFromFields(cx, calendar, fieldsCopy); - if (!date) { - return false; - } + // Step 10.d. + MOZ_ASSERT(ISODateWithinLimits(date)); } else { - // Step 14.a. + // Step 11.a. date = intermediateDate; } - // Step 15. (Moved above) + // Steps 12. + auto durationToAdd = ToDateDurationRecordWithoutTime(duration); + + // Step 13. + ISODate addedDate; + if (!CalendarDateAdd(cx, calendar, date, durationToAdd, overflow, + &addedDate)) { + return false; + } + MOZ_ASSERT(ISODateWithinLimits(addedDate)); + + Rooted addedYearMonth(cx, + PlainYearMonth{addedDate, calendar}); + + // Step 14. + Rooted addedDateFields(cx); + if (!ISODateToFields(cx, addedYearMonth, &addedDateFields)) { + return false; + } + + // Step 15. + Rooted result(cx); + if (!CalendarYearMonthFromFields(cx, calendar, addedDateFields, overflow, + &result)) { + return false; + } // Step 16. - Rooted optionsCopy(cx, SnapshotOwnProperties(cx, options)); - if (!optionsCopy) { - return false; - } - - // Step 17. - Rooted> addedDate( - cx, AddDate(cx, calendar, date, durationToAdd, options)); - if (!addedDate) { - return false; - } - - // Step 18. - Rooted addedDateFields( - cx, PrepareTemporalFields(cx, addedDate, fieldNames)); - if (!addedDateFields) { - return false; - } - - // Step 19. - auto obj = temporal::CalendarYearMonthFromFields( - cx, calendar, addedDateFields, optionsCopy); + auto* obj = CreateTemporalYearMonth(cx, result); if (!obj) { return false; } @@ -731,8 +614,8 @@ static bool AddDurationToOrSubtractDurationFromPlainYearMonth( } /** - * Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , - * referenceISODay ] ] ) + * Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendar [ , referenceISODay + * ] ] ) */ static bool PlainYearMonthConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -754,13 +637,24 @@ static bool PlainYearMonthConstructor(JSContext* cx, unsigned argc, Value* vp) { return false; } - // Step 5. - Rooted calendar(cx); - if (!ToTemporalCalendarWithISODefault(cx, args.get(2), &calendar)) { - return false; + // Steps 5-7. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (args.hasDefined(2)) { + // Step 6. + if (!args[2].isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args[2], + nullptr, "not a string"); + return false; + } + + // Step 7. + Rooted calendarString(cx, args[2].toString()); + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } } - // Steps 2 and 6. + // Steps 2 and 8. double isoDay = 1; if (args.hasDefined(3)) { if (!ToIntegerWithTruncation(cx, args[3], "day", &isoDay)) { @@ -768,9 +662,16 @@ static bool PlainYearMonthConstructor(JSContext* cx, unsigned argc, Value* vp) { } } - // Step 7. - auto* yearMonth = - CreateTemporalYearMonth(cx, args, isoYear, isoMonth, isoDay, calendar); + // Step 9. + if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) { + return false; + } + + // Step 10. + auto isoDate = ISODate{int32_t(isoYear), int32_t(isoMonth), int32_t(isoDay)}; + + // Step 11. + auto* yearMonth = CreateTemporalYearMonth(cx, args, isoDate, calendar); if (!yearMonth) { return false; } @@ -786,52 +687,17 @@ static bool PlainYearMonth_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "from", args[1]); - if (!options) { - return false; - } - } - - // Step 2. - if (args.get(0).isObject()) { - JSObject* item = &args[0].toObject(); - - if (auto* yearMonth = item->maybeUnwrapIf()) { - auto date = ToPlainDate(yearMonth); - - Rooted calendar(cx, yearMonth->calendar()); - if (!calendar.wrap(cx)) { - return false; - } - - if (options) { - // Step 2.a. - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, options, &ignored)) { - return false; - } - } - - // Step 2.b. - auto* obj = CreateTemporalYearMonth(cx, date, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; - } - } - - // Step 3. - auto obj = ToTemporalYearMonth(cx, args.get(0), options); - if (!obj) { + Rooted yearMonth(cx); + if (!ToTemporalYearMonth(cx, args.get(0), args.get(1), &yearMonth)) { return false; } - args.rval().setObject(*obj); + auto* result = CreateTemporalYearMonth(cx, yearMonth); + if (!result) { + return false; + } + + args.rval().setObject(*result); return true; } @@ -842,13 +708,13 @@ static bool PlainYearMonth_compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - PlainDate one; + Rooted one(cx); if (!ToTemporalYearMonth(cx, args.get(0), &one)) { return false; } // Step 2. - PlainDate two; + Rooted two(cx); if (!ToTemporalYearMonth(cx, args.get(1), &two)) { return false; } @@ -863,15 +729,15 @@ static bool PlainYearMonth_compare(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainYearMonth_calendarId(JSContext* cx, const CallArgs& args) { auto* yearMonth = &args.thisv().toObject().as(); - Rooted calendar(cx, yearMonth->calendar()); // Step 3. - auto* calendarId = ToTemporalCalendarIdentifier(cx, calendar); - if (!calendarId) { + auto* str = + NewStringCopy(cx, CalendarIdentifier(yearMonth->calendar())); + if (!str) { return false; } - args.rval().setString(calendarId); + args.rval().setString(str); return true; } @@ -889,13 +755,11 @@ static bool PlainYearMonth_calendarId(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.era */ static bool PlainYearMonth_era(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarEra(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarEra(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -911,13 +775,11 @@ static bool PlainYearMonth_era(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.eraYear */ static bool PlainYearMonth_eraYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Steps 4-6. - return CalendarEraYear(cx, calendar, yearMonth, args.rval()); + // Steps 3-5. + return CalendarEraYear(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -934,13 +796,11 @@ static bool PlainYearMonth_eraYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.year */ static bool PlainYearMonth_year(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarYear(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarYear(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -956,13 +816,11 @@ static bool PlainYearMonth_year(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.month */ static bool PlainYearMonth_month(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarMonth(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarMonth(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -978,13 +836,11 @@ static bool PlainYearMonth_month(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.monthCode */ static bool PlainYearMonth_monthCode(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarMonthCode(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarMonthCode(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -1001,13 +857,11 @@ static bool PlainYearMonth_monthCode(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.daysInYear */ static bool PlainYearMonth_daysInYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarDaysInYear(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarDaysInYear(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -1024,13 +878,11 @@ static bool PlainYearMonth_daysInYear(JSContext* cx, unsigned argc, Value* vp) { * get Temporal.PlainYearMonth.prototype.daysInMonth */ static bool PlainYearMonth_daysInMonth(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarDaysInMonth(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarDaysInMonth(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -1048,13 +900,11 @@ static bool PlainYearMonth_daysInMonth(JSContext* cx, unsigned argc, * get Temporal.PlainYearMonth.prototype.monthsInYear */ static bool PlainYearMonth_monthsInYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarMonthsInYear(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarMonthsInYear(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -1072,13 +922,11 @@ static bool PlainYearMonth_monthsInYear(JSContext* cx, unsigned argc, * get Temporal.PlainYearMonth.prototype.inLeapYear */ static bool PlainYearMonth_inLeapYear(JSContext* cx, const CallArgs& args) { - // Step 3. - Rooted yearMonth( - cx, &args.thisv().toObject().as()); + auto* yearMonth = &args.thisv().toObject().as(); Rooted calendar(cx, yearMonth->calendar()); - // Step 4. - return CalendarInLeapYear(cx, calendar, yearMonth, args.rval()); + // Step 3. + return CalendarInLeapYear(cx, calendar, yearMonth->date(), args.rval()); } /** @@ -1096,9 +944,8 @@ static bool PlainYearMonth_inLeapYear(JSContext* cx, unsigned argc, Value* vp) { * ) */ static bool PlainYearMonth_with(JSContext* cx, const CallArgs& args) { - Rooted yearMonth( + Rooted yearMonth( cx, &args.thisv().toObject().as()); - Rooted calendarValue(cx, yearMonth->calendar()); // Step 3. Rooted temporalYearMonthLike( @@ -1111,69 +958,54 @@ static bool PlainYearMonth_with(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted resolvedOptions(cx); + auto calendar = yearMonth.calendar(); + + // Step 5. + Rooted fields(cx); + if (!ISODateToFields(cx, yearMonth, &fields)) { + return false; + } + + // Step 6. + Rooted partialYearMonth(cx); + if (!PreparePartialCalendarFields(cx, calendar, temporalYearMonthLike, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + }, + &partialYearMonth)) { + return false; + } + MOZ_ASSERT(!partialYearMonth.keys().isEmpty()); + + // Step 7. + fields = CalendarMergeFields(calendar, fields, partialYearMonth); + + // Steps 8-9. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { + // Step 8. Rooted options(cx, RequireObjectArg(cx, "options", "with", args[1])); if (!options) { return false; } - resolvedOptions = SnapshotOwnProperties(cx, options); - } else { - resolvedOptions = NewPlainObjectWithProto(cx, nullptr); - } - if (!resolvedOptions) { - return false; - } - // Step 5. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::Fields, - CalendarMethod::MergeFields, - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return false; - } - - // Step 6. - Rooted fields(cx); - JS::RootedVector fieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, yearMonth, - { - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - &fields, &fieldNames)) { - return false; - } - - // Step 7. - Rooted partialYearMonth( - cx, PreparePartialTemporalFields(cx, temporalYearMonthLike, fieldNames)); - if (!partialYearMonth) { - return false; - } - - // Step 8. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, fields, partialYearMonth)); - if (!mergedFields) { - return false; - } - - // Step 9. - fields = PrepareTemporalFields(cx, mergedFields, fieldNames); - if (!fields) { - return false; + // Step 9. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } } // Step 10. - auto obj = temporal::CalendarYearMonthFromFields(cx, calendar, fields, - resolvedOptions); + Rooted result(cx); + if (!CalendarYearMonthFromFields(cx, calendar, fields, overflow, &result)) { + return false; + } + + // Step 11. + auto* obj = CreateTemporalYearMonth(cx, result); if (!obj) { return false; } @@ -1197,8 +1029,7 @@ static bool PlainYearMonth_with(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainYearMonth_add(JSContext* cx, const CallArgs& args) { // Step 3. - return AddDurationToOrSubtractDurationFromPlainYearMonth( - cx, PlainYearMonthDuration::Add, args); + return AddDurationToYearMonth(cx, TemporalAddDuration::Add, args); } /** @@ -1216,8 +1047,7 @@ static bool PlainYearMonth_add(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainYearMonth_subtract(JSContext* cx, const CallArgs& args) { // Step 3. - return AddDurationToOrSubtractDurationFromPlainYearMonth( - cx, PlainYearMonthDuration::Subtract, args); + return AddDurationToYearMonth(cx, TemporalAddDuration::Subtract, args); } /** @@ -1270,21 +1100,18 @@ static bool PlainYearMonth_since(JSContext* cx, unsigned argc, Value* vp) { */ static bool PlainYearMonth_equals(JSContext* cx, const CallArgs& args) { auto* yearMonth = &args.thisv().toObject().as(); - auto date = ToPlainDate(yearMonth); + auto date = yearMonth->date(); Rooted calendar(cx, yearMonth->calendar()); // Step 3. - PlainDate other; - Rooted otherCalendar(cx); - if (!ToTemporalYearMonth(cx, args.get(0), &other, &otherCalendar)) { + Rooted other(cx); + if (!ToTemporalYearMonth(cx, args.get(0), &other)) { return false; } // Steps 4-7. - bool equals = date == other; - if (equals && !CalendarEquals(cx, calendar, otherCalendar, &equals)) { - return false; - } + bool equals = + date == other.date() && CalendarEquals(calendar, other.calendar()); args.rval().setBoolean(equals); return true; @@ -1347,17 +1174,10 @@ static bool PlainYearMonth_toString(JSContext* cx, unsigned argc, Value* vp) { * ) */ static bool PlainYearMonth_toLocaleString(JSContext* cx, const CallArgs& args) { - Rooted yearMonth( - cx, &args.thisv().toObject().as()); - - // Step 3. - JSString* str = TemporalYearMonthToString(cx, yearMonth, ShowCalendar::Auto); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-4. + Handle required = cx->names().date; + Handle defaults = cx->names().date; + return TemporalObjectToLocaleString(cx, args, required, defaults); } /** @@ -1412,7 +1232,7 @@ static bool PlainYearMonth_valueOf(JSContext* cx, unsigned argc, Value* vp) { * Temporal.PlainYearMonth.prototype.toPlainDate ( item ) */ static bool PlainYearMonth_toPlainDate(JSContext* cx, const CallArgs& args) { - Rooted yearMonth( + Rooted yearMonth( cx, &args.thisv().toObject().as()); // Step 3. @@ -1423,65 +1243,36 @@ static bool PlainYearMonth_toPlainDate(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted calendarValue(cx, yearMonth->calendar()); - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, calendarValue, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - CalendarMethod::MergeFields, - }, - &calendar)) { - return false; - } + auto calendar = yearMonth.calendar(); // Step 5. - Rooted receiverFields(cx); - JS::RootedVector receiverFieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, yearMonth, - { - CalendarField::MonthCode, - CalendarField::Year, - }, - &receiverFields, - &receiverFieldNames)) { + Rooted fields(cx); + if (!ISODateToFields(cx, yearMonth, &fields)) { return false; } // Step 6. - Rooted inputFields(cx); - JS::RootedVector inputFieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, item, - { - CalendarField::Day, - }, - &inputFields, &inputFieldNames)) { + Rooted inputFields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Day, + }, + &inputFields)) { return false; } // Step 7. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, receiverFields, inputFields)); - if (!mergedFields) { - return false; - } + fields = CalendarMergeFields(calendar, fields, inputFields); // Step 8. - JS::RootedVector concatenatedFieldNames(cx); - if (!ConcatTemporalFieldNames(receiverFieldNames, inputFieldNames, - concatenatedFieldNames.get())) { + Rooted result(cx); + if (!CalendarDateFromFields(cx, calendar, fields, TemporalOverflow::Constrain, + &result)) { return false; } // Step 9. - Rooted mergedFromConcatenatedFields( - cx, PrepareTemporalFields(cx, mergedFields, concatenatedFieldNames)); - if (!mergedFromConcatenatedFields) { - return false; - } - - // Step 10. - auto obj = CalendarDateFromFields(cx, calendar, mergedFromConcatenatedFields); + auto* obj = CreateTemporalDate(cx, result); if (!obj) { return false; } @@ -1501,93 +1292,6 @@ static bool PlainYearMonth_toPlainDate(JSContext* cx, unsigned argc, cx, args); } -/** - * Temporal.PlainYearMonth.prototype.getISOFields ( ) - */ -static bool PlainYearMonth_getISOFields(JSContext* cx, const CallArgs& args) { - Rooted yearMonth( - cx, &args.thisv().toObject().as()); - auto calendar = yearMonth->calendar(); - - // Step 3. - Rooted fields(cx, IdValueVector(cx)); - - // Step 4. - Rooted cal(cx); - if (!ToTemporalCalendar(cx, calendar, &cal)) { - return false; - } - if (!fields.emplaceBack(NameToId(cx->names().calendar), cal)) { - return false; - } - - // Step 5. - if (!fields.emplaceBack(NameToId(cx->names().isoDay), - Int32Value(yearMonth->isoDay()))) { - return false; - } - - // Step 6. - if (!fields.emplaceBack(NameToId(cx->names().isoMonth), - Int32Value(yearMonth->isoMonth()))) { - return false; - } - - // Step 7. - if (!fields.emplaceBack(NameToId(cx->names().isoYear), - Int32Value(yearMonth->isoYear()))) { - return false; - } - - // Step 8. - auto* obj = NewPlainObjectWithUniqueNames(cx, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainYearMonth.prototype.getISOFields ( ) - */ -static bool PlainYearMonth_getISOFields(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.PlainYearMonth.prototype.getCalendar ( ) - */ -static bool PlainYearMonth_getCalendar(JSContext* cx, const CallArgs& args) { - auto* yearMonth = &args.thisv().toObject().as(); - Rooted calendar(cx, yearMonth->calendar()); - - // Step 3. - auto* obj = ToTemporalCalendarObject(cx, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.PlainYearMonth.prototype.getCalendar ( ) - */ -static bool PlainYearMonth_getCalendar(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - const JSClass PlainYearMonthObject::class_ = { "Temporal.PlainYearMonth", JSCLASS_HAS_RESERVED_SLOTS(PlainYearMonthObject::SLOT_COUNT) | @@ -1616,8 +1320,6 @@ static const JSFunctionSpec PlainYearMonth_prototype_methods[] = { JS_FN("toJSON", PlainYearMonth_toJSON, 0, 0), JS_FN("valueOf", PlainYearMonth_valueOf, 0, 0), JS_FN("toPlainDate", PlainYearMonth_toPlainDate, 1, 0), - JS_FN("getISOFields", PlainYearMonth_getISOFields, 0, 0), - JS_FN("getCalendar", PlainYearMonth_getCalendar, 0, 0), JS_FS_END, }; diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.h index e9adda9b08b..f5046edb6be 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/PlainYearMonth.h @@ -7,10 +7,14 @@ #ifndef builtin_temporal_PlainYearMonth_h #define builtin_temporal_PlainYearMonth_h +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + #include #include "builtin/temporal/Calendar.h" #include "builtin/temporal/TemporalTypes.h" +#include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" #include "vm/NativeObject.h" @@ -26,17 +30,17 @@ class PlainYearMonthObject : public NativeObject { static const JSClass class_; static const JSClass& protoClass_; - static constexpr uint32_t ISO_YEAR_SLOT = 0; - static constexpr uint32_t ISO_MONTH_SLOT = 1; - static constexpr uint32_t ISO_DAY_SLOT = 2; - static constexpr uint32_t CALENDAR_SLOT = 3; - static constexpr uint32_t SLOT_COUNT = 4; + static constexpr uint32_t PACKED_DATE_SLOT = 0; + static constexpr uint32_t CALENDAR_SLOT = 1; + static constexpr uint32_t SLOT_COUNT = 2; - int32_t isoYear() const { return getFixedSlot(ISO_YEAR_SLOT).toInt32(); } - - int32_t isoMonth() const { return getFixedSlot(ISO_MONTH_SLOT).toInt32(); } - - int32_t isoDay() const { return getFixedSlot(ISO_DAY_SLOT).toInt32(); } + /** + * Extract the date fields from this PlainYearMonth object. + */ + ISODate date() const { + auto packed = PackedDate{getFixedSlot(PACKED_DATE_SLOT).toPrivateUint32()}; + return PackedDate::unpack(packed); + } CalendarValue calendar() const { return CalendarValue(getFixedSlot(CALENDAR_SLOT)); @@ -47,19 +51,71 @@ class PlainYearMonthObject : public NativeObject { }; /** - * Extract the date fields from the PlainYearMonth object. + * ISOYearMonthWithinLimits ( isoDate ) */ -inline PlainDate ToPlainDate(const PlainYearMonthObject* yearMonth) { - return {yearMonth->isoYear(), yearMonth->isoMonth(), yearMonth->isoDay()}; -} +bool ISOYearMonthWithinLimits(const ISODate& isoDate); + +class MOZ_STACK_CLASS PlainYearMonth final { + ISODate date_; + CalendarValue calendar_; + + public: + PlainYearMonth() = default; + + PlainYearMonth(const ISODate& date, const CalendarValue& calendar) + : date_(date), calendar_(calendar) { + MOZ_ASSERT(ISOYearMonthWithinLimits(date)); + } + + explicit PlainYearMonth(const PlainYearMonthObject* yearMonth) + : PlainYearMonth(yearMonth->date(), yearMonth->calendar()) {} + + const auto& date() const { return date_; } + const auto& calendar() const { return calendar_; } + + // Allow implicit conversion to an ISODate. + operator const ISODate&() const { return date(); } + + void trace(JSTracer* trc) { calendar_.trace(trc); } + + const auto* calendarDoNotUse() const { return &calendar_; } +}; /** - * CreateTemporalYearMonth ( isoYear, isoMonth, calendar, referenceISODay [ , - * newTarget ] ) + * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] ) */ PlainYearMonthObject* CreateTemporalYearMonth( - JSContext* cx, const PlainDate& date, JS::Handle calendar); + JSContext* cx, JS::Handle yearMonth); + +/** + * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] ) + */ +bool CreateTemporalYearMonth(JSContext* cx, const ISODate& isoDate, + JS::Handle calendar, + JS::MutableHandle result); } /* namespace js::temporal */ +namespace js { + +template +class WrappedPtrOperations { + const auto& container() const { + return static_cast(this)->get(); + } + + public: + const auto& date() const { return container().date(); } + + JS::Handle calendar() const { + return JS::Handle::fromMarkedLocation( + container().calendarDoNotUse()); + } + + // Allow implicit conversion to an ISODate. + operator const temporal::ISODate&() const { return date(); } +}; + +} // namespace js + #endif /* builtin_temporal_PlainYearMonth_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.cpp index 28db2b5b4fd..723638f8152 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.cpp @@ -8,9 +8,9 @@ #include "mozilla/Casting.h" #include "mozilla/CheckedInt.h" +#include "mozilla/FloatingPoint.h" #include "mozilla/Likely.h" #include "mozilla/MathAlgorithms.h" -#include "mozilla/Maybe.h" #include #include @@ -20,15 +20,12 @@ #include #include #include -#include #include -#include "jsfriendapi.h" #include "jsnum.h" #include "jspubtd.h" #include "NamespaceImports.h" -#include "builtin/temporal/Instant.h" #include "builtin/temporal/Int128.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainDateTime.h" @@ -36,7 +33,6 @@ #include "builtin/temporal/PlainTime.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/TemporalRoundingMode.h" -#include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/ZonedDateTime.h" #include "gc/Barrier.h" @@ -44,7 +40,6 @@ #include "js/Conversions.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" #include "js/Id.h" #include "js/Printer.h" #include "js/PropertyDescriptor.h" @@ -59,8 +54,6 @@ #include "vm/JSContext.h" #include "vm/JSObject.h" #include "vm/ObjectOperations.h" -#include "vm/PIC.h" -#include "vm/PlainObject.h" #include "vm/Realm.h" #include "vm/StringType.h" @@ -104,54 +97,33 @@ static bool GetStringOption(JSContext* cx, Handle options, return true; } -/** - * GetOption ( options, property, type, values, default ) - */ -static bool GetNumberOption(JSContext* cx, Handle options, - Handle property, double* number) { - // Step 1. - Rooted value(cx); - if (!GetProperty(cx, options, options, property, &value)) { - return false; - } - - // Step 2. (Caller should fill in the fallback.) - if (value.isUndefined()) { - return true; - } - - // Steps 3 and 5. (Not applicable in our implementation) - - // Step 4.a. - if (!JS::ToNumber(cx, value, number)) { - return false; - } - - // Step 4.b. (Caller must check for NaN values.) - - // Step 7. (Not applicable in our implementation) - - // Step 8. - return true; -} - /** * GetRoundingIncrementOption ( normalizedOptions, dividend, inclusive ) */ bool js::temporal::GetRoundingIncrementOption(JSContext* cx, Handle options, Increment* increment) { - // Steps 1-3. - double number = 1; - if (!GetNumberOption(cx, options, cx->names().roundingIncrement, &number)) { + // Step 1. + Rooted value(cx); + if (!GetProperty(cx, options, options, cx->names().roundingIncrement, + &value)) { return false; } - // Step 5. (Reordered) - number = std::trunc(number); + // Step 2. + if (value.isUndefined()) { + *increment = Increment{1}; + return true; + } - // Steps 4 and 6. - if (!std::isfinite(number) || number < 1 || number > 1'000'000'000) { + // Step 3. + double number; + if (!ToIntegerWithTruncation(cx, value, "roundingIncrement", &number)) { + return false; + } + + // Step 4. + if (number < 1 || number > 1'000'000'000) { ToCStringBuf cbuf; const char* numStr = NumberToCString(&cbuf, number); @@ -161,7 +133,7 @@ bool js::temporal::GetRoundingIncrementOption(JSContext* cx, return false; } - // Step 7. + // Step 5. *increment = Increment{uint32_t(number)}; return true; } @@ -195,35 +167,6 @@ bool js::temporal::ValidateTemporalRoundingIncrement(JSContext* cx, return true; } -PropertyName* js::temporal::TemporalUnitToString(JSContext* cx, - TemporalUnit unit) { - switch (unit) { - case TemporalUnit::Auto: - break; - case TemporalUnit::Year: - return cx->names().year; - case TemporalUnit::Month: - return cx->names().month; - case TemporalUnit::Week: - return cx->names().week; - case TemporalUnit::Day: - return cx->names().day; - case TemporalUnit::Hour: - return cx->names().hour; - case TemporalUnit::Minute: - return cx->names().minute; - case TemporalUnit::Second: - return cx->names().second; - case TemporalUnit::Millisecond: - return cx->names().millisecond; - case TemporalUnit::Microsecond: - return cx->names().microsecond; - case TemporalUnit::Nanosecond: - return cx->names().nanosecond; - } - MOZ_CRASH("invalid temporal unit"); -} - static Handle ToPropertyName(JSContext* cx, TemporalUnitKey key) { switch (key) { @@ -471,58 +414,17 @@ bool IsValidMul(const Int128& x, const Int128& y) { /** * RoundNumberToIncrement ( x, increment, roundingMode ) */ -Int128 js::temporal::RoundNumberToIncrement(int64_t numerator, +Int128 js::temporal::RoundNumberToIncrement(const Int128& numerator, int64_t denominator, Increment increment, TemporalRoundingMode roundingMode) { MOZ_ASSERT(denominator > 0); MOZ_ASSERT(Increment::min() <= increment && increment <= Increment::max()); - // Dividing zero is always zero. - if (numerator == 0) { - return Int128{0}; - } - - // We don't have to adjust the divisor when |increment=1|. - if (increment == Increment{1}) { - // Steps 1-8 and implicit step 9. - return Int128{Divide(numerator, denominator, roundingMode)}; - } - - // Fast-path when we can perform the whole computation with int64 values. - auto divisor = mozilla::CheckedInt64(denominator) * increment.value(); - if (MOZ_LIKELY(divisor.isValid())) { - MOZ_ASSERT(divisor.value() > 0); - - // Steps 1-8. - int64_t rounded = Divide(numerator, divisor.value(), roundingMode); - - // Step 9. - auto result = mozilla::CheckedInt64(rounded) * increment.value(); - if (MOZ_LIKELY(result.isValid())) { - return Int128{result.value()}; - } - } - - // Int128 path on overflow. - return RoundNumberToIncrement(Int128{numerator}, Int128{denominator}, - increment, roundingMode); -} - -/** - * RoundNumberToIncrement ( x, increment, roundingMode ) - */ -Int128 js::temporal::RoundNumberToIncrement(const Int128& numerator, - const Int128& denominator, - Increment increment, - TemporalRoundingMode roundingMode) { - MOZ_ASSERT(denominator > Int128{0}); - MOZ_ASSERT(Increment::min() <= increment && increment <= Increment::max()); - auto inc = Int128{increment.value()}; - MOZ_ASSERT(IsValidMul(denominator, inc), "unsupported overflow"); + MOZ_ASSERT(IsValidMul(Int128{denominator}, inc), "unsupported overflow"); - auto divisor = denominator * inc; + auto divisor = Int128{denominator} * inc; MOZ_ASSERT(divisor > Int128{0}); // Steps 1-8. @@ -1195,6 +1097,52 @@ bool js::temporal::GetTemporalShowOffsetOption(JSContext* cx, return true; } +/** + * GetDirectionOption ( options ) + */ +bool js::temporal::GetDirectionOption(JSContext* cx, + Handle direction, + Direction* result) { + JSLinearString* linear = direction->ensureLinear(cx); + if (!linear) { + return false; + } + + if (StringEqualsLiteral(linear, "next")) { + *result = Direction::Next; + } else if (StringEqualsLiteral(linear, "previous")) { + *result = Direction::Previous; + } else { + if (auto chars = QuoteString(cx, linear, '"')) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_INVALID_OPTION_VALUE, "direction", + chars.get()); + } + return false; + } + return true; +} + +/** + * GetDirectionOption ( options ) + */ +bool js::temporal::GetDirectionOption(JSContext* cx, Handle options, + Direction* result) { + // Step 1. + Rooted direction(cx); + if (!GetStringOption(cx, options, cx->names().direction, &direction)) { + return false; + } + + if (!direction) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_MISSING_OPTION, "direction"); + return false; + } + + return GetDirectionOption(cx, direction, result); +} + template static JSObject* MaybeUnwrapIf(JSObject* object) { if (auto* unwrapped = object->maybeUnwrapIf()) { @@ -1302,199 +1250,12 @@ bool js::temporal::ToIntegerWithTruncation(JSContext* cx, Handle value, return true; } -/** - * GetMethod ( V, P ) - */ -JSObject* js::temporal::GetMethod(JSContext* cx, Handle object, - Handle name) { - // Step 1. - Rooted value(cx); - if (!GetProperty(cx, object, object, name, &value)) { - return nullptr; - } - - // Steps 2-3. - if (!IsCallable(value)) { - if (auto chars = StringToNewUTF8CharsZ(cx, *name)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_PROPERTY_NOT_CALLABLE, chars.get()); - } - return nullptr; - } - - // Step 4. - return &value.toObject(); -} - -/** - * CopyDataProperties ( target, source, excludedKeys [ , excludedValues ] ) - * - * Implementation when |excludedKeys| and |excludedValues| are both empty lists. - */ -bool js::temporal::CopyDataProperties(JSContext* cx, - Handle target, - Handle source) { - // Optimization for the common case when |source| is a native object. - if (source->is()) { - bool optimized = false; - if (!CopyDataPropertiesNative(cx, target, source.as(), - nullptr, &optimized)) { - return false; - } - if (optimized) { - return true; - } - } - - // Step 1-2. (Not applicable) - - // Step 3. - JS::RootedVector keys(cx); - if (!GetPropertyKeys( - cx, source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &keys)) { - return false; - } - - // Step 4. - Rooted> desc(cx); - Rooted propValue(cx); - for (size_t i = 0; i < keys.length(); i++) { - Handle key = keys[i]; - - // Steps 4.a-b. (Not applicable) - - // Step 4.c.i. - if (!GetOwnPropertyDescriptor(cx, source, key, &desc)) { - return false; - } - - // Step 4.c.ii. - if (desc.isNothing() || !desc->enumerable()) { - continue; - } - - // Step 4.c.ii.1. - if (!GetProperty(cx, source, source, key, &propValue)) { - return false; - } - - // Step 4.c.ii.2. (Not applicable) - - // Step 4.c.ii.3. - if (!DefineDataProperty(cx, target, key, propValue)) { - return false; - } - } - - // Step 5. - return true; -} - -/** - * CopyDataProperties ( target, source, excludedKeys [ , excludedValues ] ) - * - * Implementation when |excludedKeys| is an empty list and |excludedValues| is - * the list «undefined». - */ -static bool CopyDataPropertiesIgnoreUndefined(JSContext* cx, - Handle target, - Handle source) { - // Step 1-2. (Not applicable) - - // Step 3. - JS::RootedVector keys(cx); - if (!GetPropertyKeys( - cx, source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &keys)) { - return false; - } - - // Step 4. - Rooted> desc(cx); - Rooted propValue(cx); - for (size_t i = 0; i < keys.length(); i++) { - Handle key = keys[i]; - - // Steps 4.a-b. (Not applicable) - - // Step 4.c.i. - if (!GetOwnPropertyDescriptor(cx, source, key, &desc)) { - return false; - } - - // Step 4.c.ii. - if (desc.isNothing() || !desc->enumerable()) { - continue; - } - - // Step 4.c.ii.1. - if (!GetProperty(cx, source, source, key, &propValue)) { - return false; - } - - // Step 4.c.ii.2. - if (propValue.isUndefined()) { - continue; - } - - // Step 4.c.ii.3. - if (!DefineDataProperty(cx, target, key, propValue)) { - return false; - } - } - - // Step 5. - return true; -} - -/** - * SnapshotOwnProperties ( source, proto [, excludedKeys [, excludedValues ] ] ) - */ -PlainObject* js::temporal::SnapshotOwnProperties(JSContext* cx, - Handle source) { - // Step 1. - Rooted copy(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!copy) { - return nullptr; - } - - // Steps 2-4. - if (!CopyDataProperties(cx, copy, source)) { - return nullptr; - } - - // Step 3. - return copy; -} - -/** - * SnapshotOwnProperties ( source, proto [, excludedKeys [, excludedValues ] ] ) - * - * Implementation when |excludedKeys| is an empty list and |excludedValues| is - * the list «undefined». - */ -PlainObject* js::temporal::SnapshotOwnPropertiesIgnoreUndefined( - JSContext* cx, Handle source) { - // Step 1. - Rooted copy(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!copy) { - return nullptr; - } - - // Steps 2-4. - if (!CopyDataPropertiesIgnoreUndefined(cx, copy, source)) { - return nullptr; - } - - // Step 3. - return copy; -} - /** * GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, * fallbackSmallestUnit, smallestLargestDefaultUnit ) */ bool js::temporal::GetDifferenceSettings( - JSContext* cx, TemporalDifference operation, Handle options, + JSContext* cx, TemporalDifference operation, Handle options, TemporalUnitGroup unitGroup, TemporalUnit smallestAllowedUnit, TemporalUnit fallbackSmallestUnit, TemporalUnit smallestLargestDefaultUnit, DifferenceSettings* result) { @@ -1577,14 +1338,6 @@ bool js::temporal::GetDifferenceSettings( return true; } -bool temporal::IsArrayIterationSane(JSContext* cx, bool* result) { - auto* stubChain = ForOfPIC::getOrCreate(cx); - if (!stubChain) { - return false; - } - return stubChain->tryOptimizeArray(cx, result); -} - static JSObject* CreateTemporalObject(JSContext* cx, JSProtoKey key) { Rooted proto(cx, &cx->global()->getObjectPrototype()); @@ -1613,7 +1366,6 @@ static bool TemporalClassFinish(JSContext* cx, Handle temporal, // Add the constructor properties. for (const auto& protoKey : { - JSProto_Calendar, JSProto_Duration, JSProto_Instant, JSProto_PlainDate, @@ -1621,7 +1373,6 @@ static bool TemporalClassFinish(JSContext* cx, Handle temporal, JSProto_PlainMonthDay, JSProto_PlainTime, JSProto_PlainYearMonth, - JSProto_TimeZone, JSProto_ZonedDateTime, }) { if (!defineProperty(protoKey, ClassName(protoKey, cx))) { diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.h index 2c7e4060e79..81be1fac383 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/Temporal.h @@ -22,8 +22,6 @@ namespace js { struct ClassSpec; -class PlainObject; -class PropertyName; } // namespace js namespace js::temporal { @@ -122,8 +120,6 @@ constexpr Increment MaximumTemporalDurationRoundingIncrement( return Increment{1000}; } -PropertyName* TemporalUnitToString(JSContext* cx, TemporalUnit unit); - enum class TemporalUnitGroup { // Allow date units: "year", "month", "week", "day". Date, @@ -171,23 +167,24 @@ bool GetRoundingModeOption(JSContext* cx, JS::Handle options, /** * RoundNumberToIncrement ( x, increment, roundingMode ) */ -Int128 RoundNumberToIncrement(int64_t numerator, int64_t denominator, +Int128 RoundNumberToIncrement(const Int128& numerator, int64_t denominator, Increment increment, TemporalRoundingMode roundingMode); -/** - * RoundNumberToIncrement ( x, increment, roundingMode ) - */ -Int128 RoundNumberToIncrement(const Int128& numerator, - const Int128& denominator, Increment increment, - TemporalRoundingMode roundingMode); - /** * RoundNumberToIncrement ( x, increment, roundingMode ) */ int64_t RoundNumberToIncrement(int64_t x, int64_t increment, TemporalRoundingMode roundingMode); +/** + * RoundNumberToIncrement ( x, increment, roundingMode ) + */ +inline int64_t RoundNumberToIncrement(int64_t x, Increment increment, + TemporalRoundingMode roundingMode) { + return RoundNumberToIncrement(x, int64_t(increment.value()), roundingMode); +} + /** * RoundNumberToIncrement ( x, increment, roundingMode ) */ @@ -310,6 +307,20 @@ enum class ShowOffset { Auto, Never }; bool GetTemporalShowOffsetOption(JSContext* cx, JS::Handle options, ShowOffset* result); +enum class Direction { Next, Previous }; + +/** + * GetDirectionOption ( options ) + */ +bool GetDirectionOption(JSContext* cx, JS::Handle options, + Direction* result); + +/** + * GetDirectionOption ( options ) + */ +bool GetDirectionOption(JSContext* cx, JS::Handle direction, + Direction* result); + /** * IsPartialTemporalObject ( object ) * @@ -330,37 +341,18 @@ bool ToPositiveIntegerWithTruncation(JSContext* cx, JS::Handle value, bool ToIntegerWithTruncation(JSContext* cx, JS::Handle value, const char* name, double* result); -/** - * GetMethod ( V, P ) - */ -JSObject* GetMethod(JSContext* cx, JS::Handle object, - JS::Handle name); - -/** - * SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ] - * ) - */ -PlainObject* SnapshotOwnProperties(JSContext* cx, JS::Handle source); - -/** - * SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ] - * ) - */ -PlainObject* SnapshotOwnPropertiesIgnoreUndefined(JSContext* cx, - JS::Handle source); - -/** - * CopyDataProperties ( target, source, excludedKeys [ , excludedValues ] ) - */ -bool CopyDataProperties(JSContext* cx, JS::Handle target, - JS::Handle source); - enum class TemporalDifference { Since, Until }; inline const char* ToName(TemporalDifference difference) { return difference == TemporalDifference::Since ? "since" : "until"; } +enum class TemporalAddDuration { Add, Subtract }; + +inline const char* ToName(TemporalAddDuration addDuration) { + return addDuration == TemporalAddDuration::Add ? "add" : "subtract"; +} + struct DifferenceSettings final { TemporalUnit smallestUnit = TemporalUnit::Auto; TemporalUnit largestUnit = TemporalUnit::Auto; @@ -373,7 +365,7 @@ struct DifferenceSettings final { * fallbackSmallestUnit, smallestLargestDefaultUnit ) */ bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation, - JS::Handle options, + JS::Handle options, TemporalUnitGroup unitGroup, TemporalUnit smallestAllowedUnit, TemporalUnit fallbackSmallestUnit, @@ -385,7 +377,7 @@ bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation, * fallbackSmallestUnit, smallestLargestDefaultUnit ) */ inline bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation, - JS::Handle options, + JS::Handle options, TemporalUnitGroup unitGroup, TemporalUnit fallbackSmallestUnit, TemporalUnit smallestLargestDefaultUnit, @@ -395,11 +387,6 @@ inline bool GetDifferenceSettings(JSContext* cx, TemporalDifference operation, smallestLargestDefaultUnit, result); } -/** - * Sets |result| to `true` when array iteration is still in its initial state. - */ -bool IsArrayIterationSane(JSContext* cx, bool* result); - } /* namespace js::temporal */ #endif /* builtin_temporal_Temporal_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.cpp deleted file mode 100644 index 3086f126ca1..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.cpp +++ /dev/null @@ -1,1052 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "builtin/temporal/TemporalFields.h" - -#include "mozilla/Assertions.h" -#include "mozilla/Likely.h" -#include "mozilla/Maybe.h" -#include "mozilla/Range.h" -#include "mozilla/RangedPtr.h" - -#include -#include -#include -#include -#include -#include - -#include "jsnum.h" -#include "jspubtd.h" -#include "NamespaceImports.h" - -#include "builtin/temporal/Crash.h" -#include "builtin/temporal/Temporal.h" -#include "ds/Sort.h" -#include "gc/Barrier.h" -#include "gc/Tracer.h" -#include "js/AllocPolicy.h" -#include "js/ComparisonOperators.h" -#include "js/ErrorReport.h" -#include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" -#include "js/Printer.h" -#include "js/RootingAPI.h" -#include "js/TracingAPI.h" -#include "js/TypeDecls.h" -#include "js/Utility.h" -#include "js/Value.h" -#include "util/Text.h" -#include "vm/BytecodeUtil.h" -#include "vm/JSAtomState.h" -#include "vm/JSContext.h" -#include "vm/JSObject.h" -#include "vm/PlainObject.h" -#include "vm/StringType.h" -#include "vm/SymbolType.h" - -#include "vm/JSAtomUtils-inl.h" -#include "vm/ObjectOperations-inl.h" - -using namespace js; -using namespace js::temporal; - -void TemporalFields::trace(JSTracer* trc) { - TraceNullableRoot(trc, &monthCode, "TemporalFields::monthCode"); - TraceNullableRoot(trc, &offset, "TemporalFields::offset"); - TraceNullableRoot(trc, &era, "TemporalFields::era"); - TraceRoot(trc, &timeZone, "TemporalFields::timeZone"); -} - -PropertyName* js::temporal::ToPropertyName(JSContext* cx, TemporalField field) { - switch (field) { - case TemporalField::Year: - return cx->names().year; - case TemporalField::Month: - return cx->names().month; - case TemporalField::MonthCode: - return cx->names().monthCode; - case TemporalField::Day: - return cx->names().day; - case TemporalField::Hour: - return cx->names().hour; - case TemporalField::Minute: - return cx->names().minute; - case TemporalField::Second: - return cx->names().second; - case TemporalField::Millisecond: - return cx->names().millisecond; - case TemporalField::Microsecond: - return cx->names().microsecond; - case TemporalField::Nanosecond: - return cx->names().nanosecond; - case TemporalField::Offset: - return cx->names().offset; - case TemporalField::Era: - return cx->names().era; - case TemporalField::EraYear: - return cx->names().eraYear; - case TemporalField::TimeZone: - return cx->names().timeZone; - } - MOZ_CRASH("invalid temporal field name"); -} - -static constexpr const char* ToCString(TemporalField field) { - switch (field) { - case TemporalField::Year: - return "year"; - case TemporalField::Month: - return "month"; - case TemporalField::MonthCode: - return "monthCode"; - case TemporalField::Day: - return "day"; - case TemporalField::Hour: - return "hour"; - case TemporalField::Minute: - return "minute"; - case TemporalField::Second: - return "second"; - case TemporalField::Millisecond: - return "millisecond"; - case TemporalField::Microsecond: - return "microsecond"; - case TemporalField::Nanosecond: - return "nanosecond"; - case TemporalField::Offset: - return "offset"; - case TemporalField::Era: - return "era"; - case TemporalField::EraYear: - return "eraYear"; - case TemporalField::TimeZone: - return "timeZone"; - } - JS_CONSTEXPR_CRASH("invalid temporal field name"); -} - -static JS::UniqueChars QuoteString(JSContext* cx, const char* str) { - Sprinter sprinter(cx); - if (!sprinter.init()) { - return nullptr; - } - mozilla::Range range(reinterpret_cast(str), - std::strlen(str)); - QuoteString(&sprinter, range); - return sprinter.release(); -} - -static JS::UniqueChars QuoteString(JSContext* cx, PropertyKey key) { - if (key.isString()) { - return QuoteString(cx, key.toString()); - } - - if (key.isInt()) { - Int32ToCStringBuf buf; - size_t length; - const char* str = Int32ToCString(&buf, key.toInt(), &length); - return DuplicateString(cx, str, length); - } - - MOZ_ASSERT(key.isSymbol()); - return QuoteString(cx, key.toSymbol()->description()); -} - -mozilla::Maybe js::temporal::ToTemporalField( - JSContext* cx, PropertyKey property) { - static constexpr TemporalField fieldNames[] = { - TemporalField::Year, TemporalField::Month, - TemporalField::MonthCode, TemporalField::Day, - TemporalField::Hour, TemporalField::Minute, - TemporalField::Second, TemporalField::Millisecond, - TemporalField::Microsecond, TemporalField::Nanosecond, - TemporalField::Offset, TemporalField::Era, - TemporalField::EraYear, TemporalField::TimeZone, - }; - - for (const auto& fieldName : fieldNames) { - auto* name = ToPropertyName(cx, fieldName); - if (property.isAtom(name)) { - return mozilla::Some(fieldName); - } - } - return mozilla::Nothing(); -} - -static JSString* ToPrimitiveAndRequireString(JSContext* cx, - Handle value) { - Rooted primitive(cx, value); - if (!ToPrimitive(cx, JSTYPE_STRING, &primitive)) { - return nullptr; - } - if (!primitive.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, primitive, - nullptr, "not a string"); - return nullptr; - } - return primitive.toString(); -} - -static Value TemporalFieldDefaultValue(TemporalField field) { - switch (field) { - case TemporalField::Year: - case TemporalField::Month: - case TemporalField::MonthCode: - case TemporalField::Day: - case TemporalField::Offset: - case TemporalField::Era: - case TemporalField::EraYear: - case TemporalField::TimeZone: - return UndefinedValue(); - case TemporalField::Hour: - case TemporalField::Minute: - case TemporalField::Second: - case TemporalField::Millisecond: - case TemporalField::Microsecond: - case TemporalField::Nanosecond: - return Int32Value(0); - } - MOZ_CRASH("invalid temporal field name"); -} - -static bool TemporalFieldConvertValue(JSContext* cx, TemporalField field, - MutableHandle value) { - const auto* name = ToCString(field); - switch (field) { - case TemporalField::Year: - case TemporalField::Hour: - case TemporalField::Minute: - case TemporalField::Second: - case TemporalField::Millisecond: - case TemporalField::Microsecond: - case TemporalField::Nanosecond: - case TemporalField::EraYear: { - double num; - if (!ToIntegerWithTruncation(cx, value, name, &num)) { - return false; - } - value.setNumber(num); - return true; - } - - case TemporalField::Month: - case TemporalField::Day: { - double num; - if (!ToPositiveIntegerWithTruncation(cx, value, name, &num)) { - return false; - } - value.setNumber(num); - return true; - } - - case TemporalField::MonthCode: - case TemporalField::Offset: - case TemporalField::Era: { - JSString* str = ToPrimitiveAndRequireString(cx, value); - if (!str) { - return false; - } - value.setString(str); - return true; - } - - case TemporalField::TimeZone: - // NB: timeZone has no conversion function. - return true; - } - MOZ_CRASH("invalid temporal field name"); -} - -static int32_t ComparePropertyKey(PropertyKey x, PropertyKey y) { - MOZ_ASSERT(x.isAtom() || x.isInt()); - MOZ_ASSERT(y.isAtom() || y.isInt()); - - if (MOZ_LIKELY(x.isAtom() && y.isAtom())) { - return CompareStrings(x.toAtom(), y.toAtom()); - } - - if (x.isInt() && y.isInt()) { - return x.toInt() - y.toInt(); - } - - uint32_t index = uint32_t(x.isInt() ? x.toInt() : y.toInt()); - JSAtom* str = x.isAtom() ? x.toAtom() : y.toAtom(); - - char16_t buf[UINT32_CHAR_BUFFER_LENGTH]; - mozilla::RangedPtr end(std::end(buf), buf, std::end(buf)); - mozilla::RangedPtr start = BackfillIndexInCharBuffer(index, end); - - int32_t result = CompareChars(start.get(), end - start, str); - return x.isInt() ? result : -result; -} - -#ifdef DEBUG -static bool IsSorted(const TemporalFieldNames& fieldNames) { - return std::is_sorted( - fieldNames.begin(), fieldNames.end(), - [](auto x, auto y) { return ComparePropertyKey(x, y) < 0; }); -} -#endif - -template -static constexpr bool IsSorted(const std::array& arr) { - for (size_t i = 1; i < arr.size(); i++) { - auto a = std::string_view{ToCString(arr[i - 1])}; - auto b = std::string_view{ToCString(arr[i])}; - if (a.compare(b) >= 0) { - return false; - } - } - return true; -} - -static_assert(IsSorted(js::temporal::detail::sortedTemporalFields)); - -static void AssignFromFallback(TemporalField fieldName, - MutableHandle result) { - // `const` can be changed to `constexpr` when we switch to C++20. - // - // Hazard analysis complains when |FallbackValues| is directly contained in - // loop body of |PrepareTemporalFields|. As a workaround the code was moved - // into the separate |AssignFromFallback| function. - const TemporalFields FallbackValues{}; - - switch (fieldName) { - case TemporalField::Year: - result.year() = FallbackValues.year; - break; - case TemporalField::Month: - result.month() = FallbackValues.month; - break; - case TemporalField::MonthCode: - result.monthCode().set(FallbackValues.monthCode); - break; - case TemporalField::Day: - result.day() = FallbackValues.day; - break; - case TemporalField::Hour: - result.hour() = FallbackValues.hour; - break; - case TemporalField::Minute: - result.minute() = FallbackValues.minute; - break; - case TemporalField::Second: - result.second() = FallbackValues.second; - break; - case TemporalField::Millisecond: - result.millisecond() = FallbackValues.millisecond; - break; - case TemporalField::Microsecond: - result.microsecond() = FallbackValues.microsecond; - break; - case TemporalField::Nanosecond: - result.nanosecond() = FallbackValues.nanosecond; - break; - case TemporalField::Offset: - result.offset().set(FallbackValues.offset); - break; - case TemporalField::Era: - result.era().set(FallbackValues.era); - break; - case TemporalField::EraYear: - result.eraYear() = FallbackValues.eraYear; - break; - case TemporalField::TimeZone: - result.timeZone().set(FallbackValues.timeZone); - break; - } -} - -// clang-format off -// -// TODO: |fields| is often a built-in Temporal type, so we likely want to -// optimise for this case. -// -// Consider the case when PlainDate.prototype.toPlainMonthDay is called. The -// following steps are applied: -// -// 1. CalendarFields(calendar, «"day", "monthCode"») is called to retrieve the -// relevant calendar fields. For (most?) built-in calendars this will just -// return the input list «"day", "monthCode"». -// 2. PrepareTemporalFields(plainDate, «"day", "monthCode"») is called. This -// will access the properties `plainDate.day` and `plainDate.monthCode`. -// a. `plainDate.day` will call CalendarDay(calendar, plainDate). -// b. For built-in calendars, this will simply access `plainDate.[[IsoDay]]`. -// c. `plainDate.monthCode` will call CalendarMonthCode(calendar, plainDate). -// d. For built-in calendars, ISOMonthCode(plainDate.[[IsoMonth]]) is called. -// 3. CalendarMonthDayFromFields(calendar, {day, monthCode}) is called. -// 4. For built-in calendars, this calls PrepareTemporalFields({day, monthCode}, -// «"day", "month", "monthCode", "year"», «"day"»). -// 5. The previous PrepareTemporalFields call is a no-op and returns {day, monthCode}. -// 6. Then ISOMonthDayFromFields({day, monthCode}, "constrain") gets called. -// 7. ResolveISOMonth(monthCode) is called to parse the just created `monthCode`. -// 8. RegulateISODate(referenceISOYear, month, day, "constrain") is called. -// 9. Finally CreateTemporalMonthDay is called to create the PlainMonthDay instance. -// -// All these steps could be simplified to just: -// 1. CreateTemporalMonthDay(referenceISOYear, plainDate.[[IsoMonth]], plainDate.[[IsoDay]]). -// -// When the following conditions are true: -// 1. The `plainDate` is a Temporal.PlainDate instance and has no overridden methods. -// 2. The `calendar` is a Temporal.Calendar instance and has no overridden methods. -// 3. Temporal.PlainDate.prototype and Temporal.Calendar.prototype are in their initial state. -// 4. Array iteration is still in its initial state. (Required by CalendarFields) -// -// PlainDate_toPlainMonthDay has an example implementation for this optimisation. -// -// clang-format on - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields ) - */ -bool js::temporal::PrepareTemporalFields( - JSContext* cx, Handle fields, - mozilla::EnumSet fieldNames, - mozilla::EnumSet requiredFields, - MutableHandle result) { - // Steps 1-5. (Not applicable in our implementation.) - - // Step 6. - Rooted value(cx); - for (auto fieldName : SortedTemporalFields{fieldNames}) { - auto* property = ToPropertyName(cx, fieldName); - const auto* cstr = ToCString(fieldName); - - // Step 6.a. (Not applicable in our implementation.) - - // Step 6.b.i. - if (!GetProperty(cx, fields, fields, property, &value)) { - return false; - } - - // Steps 6.b.ii-iii. - if (!value.isUndefined()) { - // Step 6.b.ii.1. (Not applicable in our implementation.) - - // Steps 6.b.ii.2-3. - switch (fieldName) { - case TemporalField::Year: - if (!ToIntegerWithTruncation(cx, value, cstr, &result.year())) { - return false; - } - break; - case TemporalField::Month: - if (!ToPositiveIntegerWithTruncation(cx, value, cstr, - &result.month())) { - return false; - } - break; - case TemporalField::MonthCode: { - JSString* str = ToPrimitiveAndRequireString(cx, value); - if (!str) { - return false; - } - result.monthCode().set(str); - break; - } - case TemporalField::Day: - if (!ToPositiveIntegerWithTruncation(cx, value, cstr, - &result.day())) { - return false; - } - break; - case TemporalField::Hour: - if (!ToIntegerWithTruncation(cx, value, cstr, &result.hour())) { - return false; - } - break; - case TemporalField::Minute: - if (!ToIntegerWithTruncation(cx, value, cstr, &result.minute())) { - return false; - } - break; - case TemporalField::Second: - if (!ToIntegerWithTruncation(cx, value, cstr, &result.second())) { - return false; - } - break; - case TemporalField::Millisecond: - if (!ToIntegerWithTruncation(cx, value, cstr, - &result.millisecond())) { - return false; - } - break; - case TemporalField::Microsecond: - if (!ToIntegerWithTruncation(cx, value, cstr, - &result.microsecond())) { - return false; - } - break; - case TemporalField::Nanosecond: - if (!ToIntegerWithTruncation(cx, value, cstr, &result.nanosecond())) { - return false; - } - break; - case TemporalField::Offset: { - JSString* str = ToPrimitiveAndRequireString(cx, value); - if (!str) { - return false; - } - result.offset().set(str); - break; - } - case TemporalField::Era: { - JSString* str = ToPrimitiveAndRequireString(cx, value); - if (!str) { - return false; - } - result.era().set(str); - break; - } - case TemporalField::EraYear: - if (!ToIntegerWithTruncation(cx, value, cstr, &result.eraYear())) { - return false; - } - break; - case TemporalField::TimeZone: - // NB: TemporalField::TimeZone has no conversion function. - result.timeZone().set(value); - break; - } - } else { - // Step 6.b.iii.1. - if (requiredFields.contains(fieldName)) { - if (auto chars = QuoteString(cx, cstr)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_PROPERTY, - chars.get()); - } - return false; - } - - // Steps 6.b.iii.2-3. - AssignFromFallback(fieldName, result); - } - - // Steps 6.c-d. (Not applicable in our implementation.) - } - - // Step 7. (Not applicable in our implementation.) - - // Step 8. - return true; -} - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * duplicateBehaviour ] ) - */ -PlainObject* js::temporal::PrepareTemporalFields( - JSContext* cx, Handle fields, - Handle fieldNames) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Rooted result(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!result) { - return nullptr; - } - - // Step 3. (Not applicable in our implementation.) - - // Step 4. (The list is already sorted in our implementation.) - MOZ_ASSERT(IsSorted(fieldNames)); - - // Step 5. (The list doesn't contain duplicates in our implementation.) - MOZ_ASSERT(std::adjacent_find(fieldNames.begin(), fieldNames.end()) == - fieldNames.end()); - - // Step 6. - Rooted value(cx); - for (size_t i = 0; i < fieldNames.length(); i++) { - Handle property = fieldNames[i]; - - // Step 6.a. - MOZ_ASSERT(property != NameToId(cx->names().constructor)); - MOZ_ASSERT(property != NameToId(cx->names().proto_)); - - // Step 6.b.i. - if (!GetProperty(cx, fields, fields, property, &value)) { - return nullptr; - } - - // Steps 6.b.ii-iii. - if (auto fieldName = ToTemporalField(cx, property)) { - if (!value.isUndefined()) { - // Step 6.b.ii.1. (Not applicable in our implementation.) - - // Step 6.b.ii.2. - if (!TemporalFieldConvertValue(cx, *fieldName, &value)) { - return nullptr; - } - } else { - // Step 6.b.iii.1. (Not applicable in our implementation.) - - // Step 6.b.iii.2. - value = TemporalFieldDefaultValue(*fieldName); - } - } - - // Steps 6.b.ii.3 and 6.b.iii.3. - if (!DefineDataProperty(cx, result, property, value)) { - return nullptr; - } - - // Steps 6.c-d. (Not applicable in our implementation.) - } - - // Step 7. (Not applicable in our implementation.) - - // Step 8. - return result; -} - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * duplicateBehaviour ] ) - */ -PlainObject* js::temporal::PrepareTemporalFields( - JSContext* cx, Handle fields, - Handle fieldNames, - mozilla::EnumSet requiredFields) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Rooted result(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!result) { - return nullptr; - } - - // Step 3. (Not applicable in our implementation.) - - // Step 4. (The list is already sorted in our implementation.) - MOZ_ASSERT(IsSorted(fieldNames)); - - // Step 5. (The list doesn't contain duplicates in our implementation.) - MOZ_ASSERT(std::adjacent_find(fieldNames.begin(), fieldNames.end()) == - fieldNames.end()); - - // Step 6. - Rooted value(cx); - for (size_t i = 0; i < fieldNames.length(); i++) { - Handle property = fieldNames[i]; - - // Step 6.a. - MOZ_ASSERT(property != NameToId(cx->names().constructor)); - MOZ_ASSERT(property != NameToId(cx->names().proto_)); - - // Step 6.b.i. - if (!GetProperty(cx, fields, fields, property, &value)) { - return nullptr; - } - - // Steps 6.b.ii-iii. - if (auto fieldName = ToTemporalField(cx, property)) { - if (!value.isUndefined()) { - // Step 6.b.ii.1. (Not applicable in our implementation.) - - // Step 6.b.ii.2. - if (!TemporalFieldConvertValue(cx, *fieldName, &value)) { - return nullptr; - } - } else { - // Step 6.b.iii.1. - if (requiredFields.contains(*fieldName)) { - if (auto chars = QuoteString(cx, property.toString())) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_PROPERTY, - chars.get()); - } - return nullptr; - } - - // Step 6.b.iii.2. - value = TemporalFieldDefaultValue(*fieldName); - } - } - - // Steps 6.b.ii.3 and 6.b.iii.3. - if (!DefineDataProperty(cx, result, property, value)) { - return nullptr; - } - - // Steps 6.c-d. (Not applicable in our implementation.) - } - - // Step 7. (Not applicable in our implementation.) - - // Step 8. - return result; -} - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * duplicateBehaviour ] ) - */ -PlainObject* js::temporal::PreparePartialTemporalFields( - JSContext* cx, Handle fields, - Handle fieldNames) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - Rooted result(cx, NewPlainObjectWithProto(cx, nullptr)); - if (!result) { - return nullptr; - } - - // Step 3. - bool any = false; - - // Step 4. (The list is already sorted in our implementation.) - MOZ_ASSERT(IsSorted(fieldNames)); - - // Step 5. (The list doesn't contain duplicates in our implementation.) - MOZ_ASSERT(std::adjacent_find(fieldNames.begin(), fieldNames.end()) == - fieldNames.end()); - - // Step 6. - Rooted value(cx); - for (size_t i = 0; i < fieldNames.length(); i++) { - Handle property = fieldNames[i]; - - // Step 6.a. - MOZ_ASSERT(property != NameToId(cx->names().constructor)); - MOZ_ASSERT(property != NameToId(cx->names().proto_)); - - // Step 6.b.i. - if (!GetProperty(cx, fields, fields, property, &value)) { - return nullptr; - } - - // Steps 6.b.ii-iii. - if (!value.isUndefined()) { - // Step 6.b.ii.1. - any = true; - - // Step 6.b.ii.2. - if (auto fieldName = ToTemporalField(cx, property)) { - if (!TemporalFieldConvertValue(cx, *fieldName, &value)) { - return nullptr; - } - } - - // Steps 6.b.ii.3. - if (!DefineDataProperty(cx, result, property, value)) { - return nullptr; - } - } else { - // Step 6.b.iii. (Not applicable in our implementation.) - } - - // Steps 6.c-d. (Not applicable in our implementation.) - } - - // Step 7. - if (!any) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_MISSING_TEMPORAL_FIELDS); - return nullptr; - } - - // Step 8. - return result; -} - -/** - * PrepareCalendarFieldsAndFieldNames ( calendarRec, fields, calendarFieldNames - * [ , nonCalendarFieldNames [ , requiredFieldNames ] ] ) - */ -static bool PrepareCalendarFieldsAndFieldNames( - JSContext* cx, Handle calendar, Handle fields, - mozilla::EnumSet calendarFieldNames, - mozilla::EnumSet nonCalendarFieldNames, - mozilla::EnumSet requiredFieldNames, - MutableHandle resultFields, - MutableHandle resultFieldNames) { - // Steps 1-2. (Not applicable in our implementation.) - - // Steps 3-4. - JS::RootedVector fieldNames(cx); - if (!CalendarFields(cx, calendar, calendarFieldNames, &fieldNames)) { - return false; - } - - // Step 5. - if (nonCalendarFieldNames.size() != 0) { - if (!AppendSorted(cx, fieldNames.get(), nonCalendarFieldNames)) { - return false; - } - } - - // Step 6. - PlainObject* flds; - if (requiredFieldNames.size() == 0) { - flds = PrepareTemporalFields(cx, fields, fieldNames); - } else { - flds = PrepareTemporalFields(cx, fields, fieldNames, requiredFieldNames); - } - if (!flds) { - return false; - } - - // Step 7. - resultFields.set(flds); - resultFieldNames.set(std::move(fieldNames.get())); - return true; -} - -/** - * PrepareCalendarFieldsAndFieldNames ( calendarRec, fields, calendarFieldNames - * [ , nonCalendarFieldNames [ , requiredFieldNames ] ] ) - */ -bool js::temporal::PrepareCalendarFieldsAndFieldNames( - JSContext* cx, Handle calendar, Handle fields, - mozilla::EnumSet calendarFieldNames, - MutableHandle resultFields, - MutableHandle resultFieldNames) { - return ::PrepareCalendarFieldsAndFieldNames(cx, calendar, fields, - calendarFieldNames, {}, {}, - resultFields, resultFieldNames); -} - -#ifdef DEBUG -static auto AsTemporalFieldSet(mozilla::EnumSet values) { - using T = std::underlying_type_t; - static_assert(std::is_same_v>); - - static_assert(static_cast(TemporalField::Year) == - static_cast(CalendarField::Year)); - static_assert(static_cast(TemporalField::Month) == - static_cast(CalendarField::Month)); - static_assert(static_cast(TemporalField::MonthCode) == - static_cast(CalendarField::MonthCode)); - static_assert(static_cast(TemporalField::Day) == - static_cast(CalendarField::Day)); - - auto result = mozilla::EnumSet{}; - result.deserialize(values.serialize()); - return result; -} - -static constexpr mozilla::EnumSet NonCalendarFieldNames = { - TemporalField::Hour, TemporalField::Minute, - TemporalField::Second, TemporalField::Millisecond, - TemporalField::Microsecond, TemporalField::Nanosecond, - TemporalField::Offset, TemporalField::TimeZone, -}; -#endif - -/** - * PrepareCalendarFields ( calendarRec, fields, calendarFieldNames, - * nonCalendarFieldNames, requiredFieldNames ) - */ -PlainObject* js::temporal::PrepareCalendarFields( - JSContext* cx, Handle calendar, Handle fields, - mozilla::EnumSet calendarFieldNames, - mozilla::EnumSet nonCalendarFieldNames, - mozilla::EnumSet requiredFieldNames) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. - // - // Ensure `nonCalendarFieldNames ⊆ NonCalendarFieldNames`. - MOZ_ASSERT(NonCalendarFieldNames.contains(nonCalendarFieldNames)); - - // Step 3. - // - // Ensure `requiredFieldNames ⊆ (calendarFieldNames ∪ nonCalendarFieldNames)`. - MOZ_ASSERT((AsTemporalFieldSet(calendarFieldNames) + nonCalendarFieldNames) - .contains(requiredFieldNames)); - - // Steps 4-5. - Rooted resultFields(cx); - JS::RootedVector resultFieldNames(cx); - if (!::PrepareCalendarFieldsAndFieldNames( - cx, calendar, fields, calendarFieldNames, nonCalendarFieldNames, - requiredFieldNames, &resultFields, &resultFieldNames)) { - return nullptr; - } - return resultFields; -} - -/** - * Performs list-concatenation, removes any duplicates, and sorts the result. - */ -bool js::temporal::ConcatTemporalFieldNames( - const TemporalFieldNames& receiverFieldNames, - const TemporalFieldNames& inputFieldNames, - TemporalFieldNames& concatenatedFieldNames) { - MOZ_ASSERT(IsSorted(receiverFieldNames)); - MOZ_ASSERT(IsSorted(inputFieldNames)); - MOZ_ASSERT(concatenatedFieldNames.empty()); - - auto appendUnique = [&](auto key) { - if (concatenatedFieldNames.empty() || - concatenatedFieldNames.back() != key) { - return concatenatedFieldNames.append(key); - } - return true; - }; - - size_t i = 0; - size_t j = 0; - - // Append the names from |receiverFieldNames| and |inputFieldNames|. - while (i < receiverFieldNames.length() && j < inputFieldNames.length()) { - auto x = receiverFieldNames[i]; - auto y = inputFieldNames[j]; - - PropertyKey z; - if (ComparePropertyKey(x, y) <= 0) { - z = x; - i++; - } else { - z = y; - j++; - } - if (!appendUnique(z)) { - return false; - } - } - - // Append the remaining names from |receiverFieldNames|. - while (i < receiverFieldNames.length()) { - if (!appendUnique(receiverFieldNames[i++])) { - return false; - } - } - - // Append the remaining names from |inputFieldNames|. - while (j < inputFieldNames.length()) { - if (!appendUnique(inputFieldNames[j++])) { - return false; - } - } - - return true; -} - -bool js::temporal::AppendSorted( - JSContext* cx, TemporalFieldNames& fieldNames, - mozilla::EnumSet additionalNames) { - // |fieldNames| is sorted and doesn't include any duplicates - MOZ_ASSERT(IsSorted(fieldNames)); - MOZ_ASSERT(std::adjacent_find(fieldNames.begin(), fieldNames.end()) == - fieldNames.end()); - - // |additionalNames| is non-empty. - MOZ_ASSERT(additionalNames.size() > 0); - - // Allocate space for entries from |additionalNames|. - if (!fieldNames.growBy(additionalNames.size())) { - return false; - } - - auto sortedAdditionalNames = SortedTemporalFields{additionalNames}; - const auto sortedAdditionalNamesBegin = sortedAdditionalNames.begin(); - - const auto* left = std::prev(fieldNames.end(), additionalNames.size()); - auto right = sortedAdditionalNames.end(); - auto* out = fieldNames.end(); - - // Write backwards into the newly allocated space. - while (left != fieldNames.begin() && right != sortedAdditionalNamesBegin) { - MOZ_ASSERT(out != fieldNames.begin()); - auto x = *std::prev(left); - auto y = NameToId(ToPropertyName(cx, *std::prev(right))); - - int32_t r = ComparePropertyKey(x, y); - - // Reject duplicates per PrepareTemporalFields, step 6.c. - if (r == 0) { - if (auto chars = QuoteString(cx, x)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DUPLICATE_PROPERTY, - chars.get()); - } - return false; - } - - // Insert the lexicographically greater key. - PropertyKey z; - if (r > 0) { - z = x; - left--; - } else { - z = y; - right--; - } - *--out = z; - } - - // Avoid unnecessary copying if possible. - if (left == out) { - MOZ_ASSERT(right == sortedAdditionalNamesBegin); - return true; - } - - // Prepend the remaining names from |fieldNames|. - while (left != fieldNames.begin()) { - MOZ_ASSERT(out != fieldNames.begin()); - *--out = *--left; - } - - // Prepend the remaining names from |additionalNames|. - while (right != sortedAdditionalNamesBegin) { - MOZ_ASSERT(out != fieldNames.begin()); - *--out = NameToId(ToPropertyName(cx, *--right)); - } - - // All field names were written into the result list. - MOZ_ASSERT(out == fieldNames.begin()); - - return true; -} - -bool js::temporal::SortTemporalFieldNames(JSContext* cx, - TemporalFieldNames& fieldNames) { - // Create scratch space for MergeSort(). - TemporalFieldNames scratch(cx); - if (!scratch.resize(fieldNames.length())) { - return false; - } - - // Sort all field names in alphabetical order. - auto comparator = [](const auto& x, const auto& y, bool* lessOrEqual) { - *lessOrEqual = ComparePropertyKey(x, y) <= 0; - return true; - }; - MOZ_ALWAYS_TRUE(MergeSort(fieldNames.begin(), fieldNames.length(), - scratch.begin(), comparator)); - - for (size_t i = 0; i < fieldNames.length(); i++) { - auto property = fieldNames[i]; - - // Reject "constructor" and "__proto__" per PrepareTemporalFields, step 6.a. - if (property == NameToId(cx->names().constructor) || - property == NameToId(cx->names().proto_)) { - if (auto chars = QuoteString(cx, property)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_PROPERTY, chars.get()); - } - return false; - } - - // Reject duplicates per PrepareTemporalFields, step 6.c. - if (i > 0 && property == fieldNames[i - 1]) { - if (auto chars = QuoteString(cx, property)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_DUPLICATE_PROPERTY, - chars.get()); - } - return false; - } - } - - return true; -} diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.h deleted file mode 100644 index 66a631f666d..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalFields.h +++ /dev/null @@ -1,353 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef builtin_temporal_TemporalFields_h -#define builtin_temporal_TemporalFields_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" -#include "mozilla/EnumSet.h" -#include "mozilla/FloatingPoint.h" -#include "mozilla/Maybe.h" - -#include -#include -#include - -#include "jstypes.h" - -#include "builtin/temporal/Calendar.h" -#include "js/RootingAPI.h" -#include "js/TypeDecls.h" -#include "js/Value.h" - -class JS_PUBLIC_API JSTracer; - -namespace js { -class PlainObject; -} - -namespace js::temporal { -enum class TemporalField { - Year, - Month, - MonthCode, - Day, - Hour, - Minute, - Second, - Millisecond, - Microsecond, - Nanosecond, - Offset, - Era, - EraYear, - TimeZone, -}; - -struct FieldDescriptors { - mozilla::EnumSet relevant; - mozilla::EnumSet required; - -#ifdef DEBUG - FieldDescriptors(mozilla::EnumSet relevant, - mozilla::EnumSet required) - : relevant(relevant), required(required) { - MOZ_ASSERT(relevant.contains(required), - "required is a subset of the relevant fields"); - } -#endif -}; - -template -class SortedEnumSet { - mozilla::EnumSet fields_; - - public: - explicit SortedEnumSet(mozilla::EnumSet fields) : fields_(fields) {} - - class Iterator { - mozilla::EnumSet fields_; - size_t index_; - - void findNext() { - while (index_ < sorted.size() && !fields_.contains(sorted[index_])) { - index_++; - } - } - - void findPrevious() { - while (index_ > 0 && !fields_.contains(sorted[index_])) { - index_--; - } - } - - public: - // Iterator traits. - using difference_type = ptrdiff_t; - using value_type = TemporalField; - using pointer = TemporalField*; - using reference = TemporalField&; - using iterator_category = std::bidirectional_iterator_tag; - - Iterator(mozilla::EnumSet fields, size_t index) - : fields_(fields), index_(index) { - findNext(); - } - - bool operator==(const Iterator& other) const { - MOZ_ASSERT(fields_ == other.fields_); - return index_ == other.index_; - } - - bool operator!=(const Iterator& other) const { return !(*this == other); } - - auto operator*() const { - MOZ_ASSERT(index_ < sorted.size()); - MOZ_ASSERT(fields_.contains(sorted[index_])); - return sorted[index_]; - } - - auto& operator++() { - MOZ_ASSERT(index_ < sorted.size()); - index_++; - findNext(); - return *this; - } - - auto operator++(int) { - auto result = *this; - ++(*this); - return result; - } - - auto& operator--() { - MOZ_ASSERT(index_ > 0); - index_--; - findPrevious(); - return *this; - } - - auto operator--(int) { - auto result = *this; - --(*this); - return result; - } - }; - - Iterator begin() const { return Iterator{fields_, 0}; }; - - Iterator end() const { return Iterator{fields_, sorted.size()}; } -}; - -namespace detail { -static constexpr auto sortedTemporalFields = std::array{ - TemporalField::Day, TemporalField::Era, - TemporalField::EraYear, TemporalField::Hour, - TemporalField::Microsecond, TemporalField::Millisecond, - TemporalField::Minute, TemporalField::Month, - TemporalField::MonthCode, TemporalField::Nanosecond, - TemporalField::Offset, TemporalField::Second, - TemporalField::TimeZone, TemporalField::Year, -}; -} - -// TODO: Consider reordering TemporalField so we don't need this. Probably best -// to decide after has -// landed. -using SortedTemporalFields = - SortedEnumSet; - -// Default values are specified in Table 15 [1]. `undefined` is replaced with -// an appropriate value based on the type, for example `double` fields use -// NaN whereas pointer fields use nullptr. -// -// [1] -struct MOZ_STACK_CLASS TemporalFields final { - double year = mozilla::UnspecifiedNaN(); - double month = mozilla::UnspecifiedNaN(); - JSString* monthCode = nullptr; - double day = mozilla::UnspecifiedNaN(); - double hour = 0; - double minute = 0; - double second = 0; - double millisecond = 0; - double microsecond = 0; - double nanosecond = 0; - JSString* offset = nullptr; - JSString* era = nullptr; - double eraYear = mozilla::UnspecifiedNaN(); - JS::Value timeZone = JS::UndefinedValue(); - - TemporalFields() = default; - - void trace(JSTracer* trc); -}; -} // namespace js::temporal - -namespace js { - -template -class WrappedPtrOperations { - const temporal::TemporalFields& fields() const { - return static_cast(this)->get(); - } - - public: - double year() const { return fields().year; } - double month() const { return fields().month; } - double day() const { return fields().day; } - double hour() const { return fields().hour; } - double minute() const { return fields().minute; } - double second() const { return fields().second; } - double millisecond() const { return fields().millisecond; } - double microsecond() const { return fields().microsecond; } - double nanosecond() const { return fields().nanosecond; } - double eraYear() const { return fields().eraYear; } - - JS::Handle monthCode() const { - return JS::Handle::fromMarkedLocation(&fields().monthCode); - } - JS::Handle offset() const { - return JS::Handle::fromMarkedLocation(&fields().offset); - } - JS::Handle era() const { - return JS::Handle::fromMarkedLocation(&fields().era); - } - JS::Handle timeZone() const { - return JS::Handle::fromMarkedLocation(&fields().timeZone); - } -}; - -template -class MutableWrappedPtrOperations - : public WrappedPtrOperations { - temporal::TemporalFields& fields() { - return static_cast(this)->get(); - } - - public: - double& year() { return fields().year; } - double& month() { return fields().month; } - double& day() { return fields().day; } - double& hour() { return fields().hour; } - double& minute() { return fields().minute; } - double& second() { return fields().second; } - double& millisecond() { return fields().millisecond; } - double& microsecond() { return fields().microsecond; } - double& nanosecond() { return fields().nanosecond; } - double& eraYear() { return fields().eraYear; } - - JS::MutableHandle monthCode() { - return JS::MutableHandle::fromMarkedLocation( - &fields().monthCode); - } - JS::MutableHandle offset() { - return JS::MutableHandle::fromMarkedLocation(&fields().offset); - } - JS::MutableHandle era() { - return JS::MutableHandle::fromMarkedLocation(&fields().era); - } - JS::MutableHandle timeZone() { - return JS::MutableHandle::fromMarkedLocation(&fields().timeZone); - } -}; - -} // namespace js - -namespace js::temporal { - -PropertyName* ToPropertyName(JSContext* cx, TemporalField field); - -mozilla::Maybe ToTemporalField(JSContext* cx, - PropertyKey property); - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * extraFieldDescriptors [ , duplicateBehaviour ] ] ) - */ -bool PrepareTemporalFields(JSContext* cx, JS::Handle fields, - mozilla::EnumSet fieldNames, - mozilla::EnumSet requiredFields, - JS::MutableHandle result); - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * extraFieldDescriptors [ , duplicateBehaviour ] ] ) - */ -inline bool PrepareTemporalFields( - JSContext* cx, JS::Handle fields, - mozilla::EnumSet fieldNames, - mozilla::EnumSet requiredFields, - const FieldDescriptors& extraFieldDescriptors, - JS::MutableHandle result) { - return PrepareTemporalFields( - cx, fields, fieldNames + extraFieldDescriptors.relevant, - requiredFields + extraFieldDescriptors.required, result); -} - -using TemporalFieldNames = JS::StackGCVector; - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * extraFieldDescriptors [ , duplicateBehaviour ] ] ) - */ -PlainObject* PrepareTemporalFields(JSContext* cx, JS::Handle fields, - JS::Handle fieldNames); - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * extraFieldDescriptors [ , duplicateBehaviour ] ] ) - */ -PlainObject* PrepareTemporalFields( - JSContext* cx, JS::Handle fields, - JS::Handle fieldNames, - mozilla::EnumSet requiredFields); - -/** - * PrepareTemporalFields ( fields, fieldNames, requiredFields [ , - * extraFieldDescriptors [ , duplicateBehaviour ] ] ) - */ -PlainObject* PreparePartialTemporalFields( - JSContext* cx, JS::Handle fields, - JS::Handle fieldNames); - -/** - * PrepareCalendarFieldsAndFieldNames ( calendarRec, fields, calendarFieldNames - * [ , nonCalendarFieldNames [ , requiredFieldNames ] ] ) - */ -bool PrepareCalendarFieldsAndFieldNames( - JSContext* cx, JS::Handle calendar, - JS::Handle fields, - mozilla::EnumSet calendarFieldNames, - JS::MutableHandle resultFields, - JS::MutableHandle resultFieldNames); - -/** - * PrepareCalendarFields ( calendarRec, fields, calendarFieldNames, - * nonCalendarFieldNames, requiredFieldNames ) - */ -PlainObject* PrepareCalendarFields( - JSContext* cx, JS::Handle calendar, - JS::Handle fields, - mozilla::EnumSet calendarFieldNames, - mozilla::EnumSet nonCalendarFieldNames = {}, - mozilla::EnumSet requiredFieldNames = {}); - -[[nodiscard]] bool ConcatTemporalFieldNames( - const TemporalFieldNames& receiverFieldNames, - const TemporalFieldNames& inputFieldNames, - TemporalFieldNames& concatenatedFieldNames); - -[[nodiscard]] bool AppendSorted( - JSContext* cx, TemporalFieldNames& fieldNames, - mozilla::EnumSet additionalNames); - -[[nodiscard]] bool SortTemporalFieldNames(JSContext* cx, - TemporalFieldNames& fieldNames); -} /* namespace js::temporal */ - -#endif /* builtin_temporal_TemporalFields_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalNow.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalNow.cpp index 4684eb87003..86009ed7ac7 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalNow.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalNow.cpp @@ -7,20 +7,14 @@ #include "builtin/temporal/TemporalNow.h" #include "mozilla/Assertions.h" -#include "mozilla/Result.h" -#include #include -#include -#include #include "jsdate.h" #include "jspubtd.h" #include "jstypes.h" #include "NamespaceImports.h" -#include "builtin/intl/CommonFunctions.h" -#include "builtin/intl/FormatBuffer.h" #include "builtin/temporal/Calendar.h" #include "builtin/temporal/Instant.h" #include "builtin/temporal/PlainDate.h" @@ -30,9 +24,6 @@ #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ZonedDateTime.h" -#include "gc/Barrier.h" -#include "gc/GCEnum.h" -#include "js/AllocPolicy.h" #include "js/CallArgs.h" #include "js/Class.h" #include "js/Date.h" @@ -42,7 +33,6 @@ #include "js/TypeDecls.h" #include "vm/DateTime.h" #include "vm/GlobalObject.h" -#include "vm/JSAtomState.h" #include "vm/JSContext.h" #include "vm/Realm.h" #include "vm/StringType.h" @@ -52,176 +42,64 @@ using namespace js; using namespace js::temporal; -static bool SystemTimeZoneOffset(JSContext* cx, int32_t* offset) { - auto rawOffset = - DateTimeInfo::getRawOffsetMs(DateTimeInfo::forceUTC(cx->realm())); - if (rawOffset.isErr()) { - intl::ReportInternalError(cx); - return false; - } - - *offset = rawOffset.unwrap(); - return true; -} - /** - * 6.4.3 DefaultTimeZone () - * - * Returns the IANA time zone name for the host environment's current time zone. - * - * ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3 + * SystemUTCEpochNanoseconds ( ) */ -static JSString* SystemTimeZoneIdentifier(JSContext* cx) { - intl::FormatBuffer formatBuffer(cx); - auto result = DateTimeInfo::timeZoneId(DateTimeInfo::forceUTC(cx->realm()), - formatBuffer); - if (result.isErr()) { - intl::ReportInternalError(cx, result.unwrapErr()); - return nullptr; - } +static int64_t SystemUTCEpochMilliseconds(JSContext* cx) { + // Steps 1-2. + JS::ClippedTime nowMillis = DateNow(cx); + MOZ_ASSERT(nowMillis.isValid()); + MOZ_ASSERT(nowMillis.toDouble() >= js::StartOfTime); + MOZ_ASSERT(nowMillis.toDouble() <= js::EndOfTime); - Rooted timeZone(cx, formatBuffer.toString(cx)); - if (!timeZone) { - return nullptr; - } - - Rooted validTimeZone(cx); - if (!IsValidTimeZoneName(cx, timeZone, &validTimeZone)) { - return nullptr; - } - if (validTimeZone) { - return CanonicalizeTimeZoneName(cx, validTimeZone); - } - - // See DateTimeFormat.js for the JS implementation. - // TODO: Move the JS implementation into C++. - - // Before defaulting to "UTC", try to represent the system time zone using - // the Etc/GMT + offset format. This format only accepts full hour offsets. - int32_t offset; - if (!SystemTimeZoneOffset(cx, &offset)) { - return nullptr; - } - - constexpr int32_t msPerHour = 60 * 60 * 1000; - int32_t offsetHours = std::abs(offset / msPerHour); - int32_t offsetHoursFraction = offset % msPerHour; - if (offsetHoursFraction == 0 && offsetHours < 24) { - // Etc/GMT + offset uses POSIX-style signs, i.e. a positive offset - // means a location west of GMT. - constexpr std::string_view etcGMT = "Etc/GMT"; - - char offsetString[etcGMT.length() + 3]; - - size_t n = etcGMT.copy(offsetString, etcGMT.length()); - offsetString[n++] = offset < 0 ? '+' : '-'; - if (offsetHours >= 10) { - offsetString[n++] = char('0' + (offsetHours / 10)); - } - offsetString[n++] = char('0' + (offsetHours % 10)); - - MOZ_ASSERT(n == etcGMT.length() + 2 || n == etcGMT.length() + 3); - - timeZone = NewStringCopyN(cx, offsetString, n); - if (!timeZone) { - return nullptr; - } - - // Check if the fallback is valid. - if (!IsValidTimeZoneName(cx, timeZone, &validTimeZone)) { - return nullptr; - } - if (validTimeZone) { - return CanonicalizeTimeZoneName(cx, validTimeZone); - } - } - - // Fallback to "UTC" if everything else fails. - return cx->names().UTC; -} - -static BuiltinTimeZoneObject* SystemTimeZoneObject(JSContext* cx) { - Rooted timeZoneIdentifier(cx, SystemTimeZoneIdentifier(cx)); - if (!timeZoneIdentifier) { - return nullptr; - } - - return CreateTemporalTimeZone(cx, timeZoneIdentifier); + // Step 3. + return int64_t(nowMillis.toDouble()); } /** * SystemUTCEpochNanoseconds ( ) */ -static bool SystemUTCEpochNanoseconds(JSContext* cx, Instant* result) { - // Step 1. - JS::ClippedTime nowMillis = DateNow(cx); - MOZ_ASSERT(nowMillis.isValid()); - - // Step 2. - MOZ_ASSERT(nowMillis.toDouble() >= js::StartOfTime); - MOZ_ASSERT(nowMillis.toDouble() <= js::EndOfTime); - - // Step 3. - *result = Instant::fromMilliseconds(int64_t(nowMillis.toDouble())); - return true; +static EpochNanoseconds SystemUTCEpochNanoseconds(JSContext* cx) { + return EpochNanoseconds::fromMilliseconds(SystemUTCEpochMilliseconds(cx)); } /** - * SystemInstant ( ) + * SystemDateTime ( temporalTimeZoneLike ) */ -static bool SystemInstant(JSContext* cx, Instant* result) { - // Steps 1-2. - return SystemUTCEpochNanoseconds(cx, result); -} - -/** - * SystemInstant ( ) - */ -static InstantObject* SystemInstant(JSContext* cx) { - // Step 1. - Instant instant; - if (!SystemUTCEpochNanoseconds(cx, &instant)) { - return nullptr; - } - - // Step 2. - return CreateTemporalInstant(cx, instant); -} - -/** - * SystemDateTime ( temporalTimeZoneLike, calendarLike ) - * SystemZonedDateTime ( temporalTimeZoneLike, calendarLike ) - */ -static bool ToTemporalTimeZoneOrSystemTimeZone( - JSContext* cx, Handle temporalTimeZoneLike, - MutableHandle timeZone) { +static bool SystemDateTime(JSContext* cx, Handle temporalTimeZoneLike, + ISODateTime* dateTime) { // Step 1. + // + // Optimization to directly retrieve the system time zone offset. if (temporalTimeZoneLike.isUndefined()) { - auto* timeZoneObj = SystemTimeZoneObject(cx); - if (!timeZoneObj) { - return false; - } - timeZone.set(TimeZoneValue(timeZoneObj)); + // Step 2. (Not applicable) + + // Step 3. + int64_t epochMillis = SystemUTCEpochMilliseconds(cx); + + // Step 4. + int32_t offsetMillis = DateTimeInfo::getOffsetMilliseconds( + DateTimeInfo::forceUTC(cx->realm()), epochMillis, + DateTimeInfo::TimeZoneOffset::UTC); + MOZ_ASSERT(std::abs(offsetMillis) < ToMilliseconds(TemporalUnit::Day)); + + *dateTime = GetISODateTimeFor( + EpochNanoseconds::fromMilliseconds(epochMillis), + offsetMillis * ToNanoseconds(TemporalUnit::Millisecond)); return true; } // Step 2. - return ToTemporalTimeZone(cx, temporalTimeZoneLike, timeZone); -} - -/** - * SystemDateTime ( temporalTimeZoneLike, calendarLike ) - */ -static bool SystemDateTime(JSContext* cx, Handle timeZone, - PlainDateTime* dateTime) { - // SystemDateTime, step 4. - Instant instant; - if (!SystemInstant(cx, &instant)) { + Rooted timeZone(cx); + if (!ToTemporalTimeZone(cx, temporalTimeZoneLike, &timeZone)) { return false; } - // SystemDateTime, steps 5-6. - return GetPlainDateTimeFor(cx, timeZone, instant, dateTime); + // Step 3. + auto epochNs = SystemUTCEpochNanoseconds(cx); + + // Step 4. + return GetISODateTimeFor(cx, timeZone, epochNs, dateTime); } /** @@ -247,43 +125,10 @@ static bool Temporal_Now_instant(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - auto* result = SystemInstant(cx); - if (!result) { - return false; - } + auto epochNs = SystemUTCEpochNanoseconds(cx); - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.Now.plainDateTime ( calendar [ , temporalTimeZoneLike ] ) - */ -static bool Temporal_Now_plainDateTime(JSContext* cx, unsigned argc, - Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. (Inlined call to SystemDateTime) - - // SystemDateTime, steps 1-2. - Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(1), &timeZone)) { - return false; - } - - // SystemDateTime, step 3. - Rooted calendar(cx); - if (!ToTemporalCalendar(cx, args.get(0), &calendar)) { - return false; - } - - // SystemDateTime, steps 4-5. - PlainDateTime dateTime; - if (!SystemDateTime(cx, timeZone, &dateTime)) { - return false; - } - - auto* result = CreateTemporalDateTime(cx, dateTime, calendar); + // Step 2. + auto* result = CreateTemporalInstant(cx, epochNs); if (!result) { return false; } @@ -299,23 +144,14 @@ static bool Temporal_Now_plainDateTimeISO(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Step 1. (Inlined call to SystemDateTime) - - // SystemDateTime, steps 1-2. - Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(0), &timeZone)) { + // Step 1. + ISODateTime dateTime; + if (!SystemDateTime(cx, args.get(0), &dateTime)) { return false; } - // SystemDateTime, step 3. + // Step 2. Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - - // SystemDateTime, steps 4-5. - PlainDateTime dateTime; - if (!SystemDateTime(cx, timeZone, &dateTime)) { - return false; - } - auto* result = CreateTemporalDateTime(cx, dateTime, calendar); if (!result) { return false; @@ -325,43 +161,6 @@ static bool Temporal_Now_plainDateTimeISO(JSContext* cx, unsigned argc, return true; } -/** - * Temporal.Now.zonedDateTime ( calendar [ , temporalTimeZoneLike ] ) - */ -static bool Temporal_Now_zonedDateTime(JSContext* cx, unsigned argc, - Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. (Inlined call to SystemZonedDateTime) - - // SystemZonedDateTime, steps 1-2. - Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(1), &timeZone)) { - return false; - } - - // SystemZonedDateTime, step 3. - Rooted calendar(cx); - if (!ToTemporalCalendar(cx, args.get(0), &calendar)) { - return false; - } - - // SystemZonedDateTime, step 4. - Instant instant; - if (!SystemUTCEpochNanoseconds(cx, &instant)) { - return false; - } - - // SystemZonedDateTime, step 5. - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - /** * Temporal.Now.zonedDateTimeISO ( [ temporalTimeZoneLike ] ) */ @@ -369,61 +168,24 @@ static bool Temporal_Now_zonedDateTimeISO(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Step 1. (Inlined call to SystemZonedDateTime) - - // SystemZonedDateTime, steps 1-2. + // Steps 1-2. Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(0), &timeZone)) { - return false; + if (!args.hasDefined(0)) { + if (!SystemTimeZone(cx, &timeZone)) { + return false; + } + } else { + if (!ToTemporalTimeZone(cx, args[0], &timeZone)) { + return false; + } } - // SystemZonedDateTime, step 3. + // Step 3. + auto epochNs = SystemUTCEpochNanoseconds(cx); + + // Step 4. Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - - // SystemZonedDateTime, step 4. - Instant instant; - if (!SystemUTCEpochNanoseconds(cx, &instant)) { - return false; - } - - // SystemZonedDateTime, step 5. - auto* result = CreateTemporalZonedDateTime(cx, instant, timeZone, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.Now.plainDate ( calendar [ , temporalTimeZoneLike ] ) - */ -static bool Temporal_Now_plainDate(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. (Inlined call to SystemDateTime) - - // SystemDateTime, steps 1-2. - Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(1), &timeZone)) { - return false; - } - - // SystemDateTime, step 3. - Rooted calendar(cx); - if (!ToTemporalCalendar(cx, args.get(0), &calendar)) { - return false; - } - - // SystemDateTime, steps 4-5. - PlainDateTime dateTime; - if (!SystemDateTime(cx, timeZone, &dateTime)) { - return false; - } - - // Step 2. - auto* result = CreateTemporalDate(cx, dateTime.date, calendar); + auto* result = CreateTemporalZonedDateTime(cx, epochNs, timeZone, calendar); if (!result) { return false; } @@ -438,24 +200,14 @@ static bool Temporal_Now_plainDate(JSContext* cx, unsigned argc, Value* vp) { static bool Temporal_Now_plainDateISO(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Step 1. (Inlined call to SystemDateTime) - - // SystemDateTime, steps 1-2. - Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(0), &timeZone)) { - return false; - } - - // SystemDateTime, step 3. - Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - - // SystemDateTime, steps 4-5. - PlainDateTime dateTime; - if (!SystemDateTime(cx, timeZone, &dateTime)) { + // Step 1. + ISODateTime dateTime; + if (!SystemDateTime(cx, args.get(0), &dateTime)) { return false; } // Step 2. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); auto* result = CreateTemporalDate(cx, dateTime.date, calendar); if (!result) { return false; @@ -471,19 +223,9 @@ static bool Temporal_Now_plainDateISO(JSContext* cx, unsigned argc, Value* vp) { static bool Temporal_Now_plainTimeISO(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - // Step 1. (Inlined call to SystemDateTime) - - // SystemDateTime, steps 1-2. - Rooted timeZone(cx); - if (!ToTemporalTimeZoneOrSystemTimeZone(cx, args.get(0), &timeZone)) { - return false; - } - - // SystemDateTime, step 3. (Not applicable) - - // SystemDateTime, steps 4-5. - PlainDateTime dateTime; - if (!SystemDateTime(cx, timeZone, &dateTime)) { + // Step 1. + ISODateTime dateTime; + if (!SystemDateTime(cx, args.get(0), &dateTime)) { return false; } @@ -507,11 +249,8 @@ const JSClass TemporalNowObject::class_ = { static const JSFunctionSpec TemporalNow_methods[] = { JS_FN("timeZoneId", Temporal_Now_timeZoneId, 0, 0), JS_FN("instant", Temporal_Now_instant, 0, 0), - JS_FN("plainDateTime", Temporal_Now_plainDateTime, 1, 0), JS_FN("plainDateTimeISO", Temporal_Now_plainDateTimeISO, 0, 0), - JS_FN("zonedDateTime", Temporal_Now_zonedDateTime, 1, 0), JS_FN("zonedDateTimeISO", Temporal_Now_zonedDateTimeISO, 0, 0), - JS_FN("plainDate", Temporal_Now_plainDate, 1, 0), JS_FN("plainDateISO", Temporal_Now_plainDateISO, 0, 0), JS_FN("plainTimeISO", Temporal_Now_plainTimeISO, 0, 0), JS_FS_END, diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.cpp index 1dd301f9f3f..b6d74fb2f99 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.cpp @@ -13,11 +13,11 @@ #include "mozilla/Result.h" #include "mozilla/Span.h" #include "mozilla/TextUtils.h" +#include "mozilla/Try.h" #include #include #include -#include #include #include #include @@ -27,6 +27,7 @@ #include "jsnum.h" #include "NamespaceImports.h" +#include "builtin/temporal/Calendar.h" #include "builtin/temporal/Duration.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainTime.h" @@ -47,11 +48,6 @@ using namespace js; using namespace js::temporal; -// TODO: Better error message for empty strings? -// TODO: Add string input to error message? -// TODO: Better error messages, for example display current character? -// https://bugzilla.mozilla.org/show_bug.cgi?id=1839676 - struct StringName final { // Start position and length of this name. size_t start = 0; @@ -101,7 +97,7 @@ struct Annotation final { }; struct TimeSpec final { - PlainTime time; + Time time; }; struct TimeZoneUTCOffset final { @@ -258,10 +254,11 @@ struct TimeZoneString final { * Struct to hold the parsed date, time, time zone, and calendar components. */ struct ZonedDateTimeString final { - PlainDate date; - PlainTime time; + ISODate date; + Time time; TimeZoneString timeZone; CalendarName calendar; + bool startOfDay; }; template @@ -286,48 +283,55 @@ static constexpr int32_t AbsentYear = INT32_MAX; * ParseISODateTime ( isoString ) */ static bool ParseISODateTime(JSContext* cx, const ZonedDateTimeString& parsed, - PlainDateTime* result) { - // Steps 1-6, 8, 10-13 (Not applicable here). + ISODateTime* result) { + // Steps 1-7, 9, 11-16 (Not applicable here). - PlainDateTime dateTime = {parsed.date, parsed.time}; + ISODateTime dateTime = {parsed.date, parsed.time}; // NOTE: ToIntegerOrInfinity("") is 0. if (dateTime.date.year == AbsentYear) { dateTime.date.year = 0; } - // Step 7. + // Step 8. if (dateTime.date.month == 0) { dateTime.date.month = 1; } - // Step 9. + // Step 10. if (dateTime.date.day == 0) { dateTime.date.day = 1; } - // Step 14. + // Step 17.b. if (dateTime.time.second == 60) { dateTime.time.second = 59; } - // ParseISODateTime, steps 15-16 (Not applicable in our implementation). + // ParseISODateTime, steps 18-19 (Not applicable in our implementation). - // Call ThrowIfInvalidISODate to report an error if |days| exceeds the number - // of days in the month. All other values are already in-bounds. + // Perform early error checks now that absent |day| and |month| values were + // handled: + // `IsValidDate(DateSpec)` and `IsValidMonthDay(DateSpecMonthDay)` validate + // that |day| doesn't exceed the number of days in |month|. This check can be + // implemented by calling `ThrowIfInvalidISODate`. + // + // All other values are already in-bounds. MOZ_ASSERT(std::abs(dateTime.date.year) <= 999'999); MOZ_ASSERT(1 <= dateTime.date.month && dateTime.date.month <= 12); MOZ_ASSERT(1 <= dateTime.date.day && dateTime.date.day <= 31); - // ParseISODateTime, step 17. if (!ThrowIfInvalidISODate(cx, dateTime.date)) { return false; } - // ParseISODateTime, step 18. + // Step 20. + MOZ_ASSERT(IsValidISODate(dateTime.date)); + + // Step 21. MOZ_ASSERT(IsValidTime(dateTime.time)); - // Steps 19-25. (Handled in caller.) + // Steps 22-28. (Handled in caller.) *result = dateTime; return true; @@ -395,6 +399,8 @@ class ParserError final { JSErrNum error_ = JSMSG_NOT_AN_ERROR; public: + constexpr ParserError() = default; + constexpr MOZ_IMPLICIT ParserError(JSErrNum error) : error_(error) {} constexpr JSErrNum error() const { return error_; } @@ -434,6 +440,29 @@ struct UnusedZero<::ParserError> { static_assert(mozilla::Result::Strategy != mozilla::detail::PackingStrategy::Variant); +/** + * Track the error and reader index of the last largest successful parse. + */ +class LikelyError final { + size_t index_ = 0; + ParserError error_{}; + + public: + template + void update(const mozilla::Result& result, size_t index) { + MOZ_ASSERT(result.isErr()); + + if (index >= index_) { + index_ = index; + error_ = result.inspectErr(); + } + } + + size_t index() const { return index_; } + + auto propagate() const { return mozilla::Err(error_); } +}; + template class StringReader final { mozilla::Span string_; @@ -544,11 +573,8 @@ class TemporalParser final { return mozilla::Some(num); } - // TimeFractionalPart ::: - // Digit{1, 9} - // - // Fraction ::: - // DecimalSeparator TimeFractionalPart + // TemporalDecimalFraction ::: + // TemporalDecimalSeparator DecimalDigit{1,9} mozilla::Maybe fraction() { if (!reader_.hasMore(2)) { return mozilla::Nothing(); @@ -679,13 +705,9 @@ class TemporalParser final { return true; } - // Sign ::: - // ASCIISign - // U+2212 - // // ASCIISign ::: one of // + - - bool hasSign() const { return hasOneOf({'+', '-', 0x2212}); } + bool hasSign() const { return hasOneOf({'+', '-'}); } /** * Consumes the current character, which must be a sign character, and returns @@ -698,7 +720,19 @@ class TemporalParser final { return plus ? 1 : -1; } - // DecimalSeparator ::: one of + // DateSeparator[Extended] ::: + // [+Extended] - + // [~Extended] [empty] + bool dateSeparator() { return character('-'); } + + // TimeSeparator[Extended] ::: + // [+Extended] : + // [~Extended] [empty] + bool hasTimeSeparator() const { return hasCharacter(':'); } + + bool timeSeparator() { return character(':'); } + + // TemporalDecimalSeparator ::: one of // . , bool hasDecimalSeparator() const { return hasOneOf({'.', ','}); } @@ -822,17 +856,30 @@ class TemporalParser final { return min <= x && x <= max; } - mozilla::Result dateTime(); + static auto err(JSErrNum error) { + // Explicitly create |ParserError| when JSErrNum is auto-convertible to the + // success type. + return mozilla::Err(ParserError{error}); + } - mozilla::Result date(); + mozilla::Result dateYear(); + mozilla::Result dateMonth(); + mozilla::Result dateDay(); + mozilla::Result hour(); + mozilla::Result, ParserError> minute(bool required); + mozilla::Result, ParserError> second(bool required); + mozilla::Result, ParserError> timeSecond( + bool required); - mozilla::Result dateSpecYearMonth(); + mozilla::Result date(); - mozilla::Result dateSpecMonthDay(); + mozilla::Result time(); - mozilla::Result validMonthDay(); + mozilla::Result dateTime(bool allowZ); - mozilla::Result timeSpec(); + mozilla::Result dateSpecYearMonth(); + + mozilla::Result dateSpecMonthDay(); // Return true when |Annotation| can start at the current position. bool hasAnnotationStart() const { return hasCharacter('['); } @@ -858,11 +905,9 @@ class TemporalParser final { } // Return true when |DateTimeUTCOffset| can start at the current position. - bool hasDateTimeUTCOffsetStart() { - return hasOneOf({'Z', 'z', '+', '-', 0x2212}); - } + bool hasDateTimeUTCOffsetStart() { return hasOneOf({'Z', 'z', '+', '-'}); } - mozilla::Result dateTimeUTCOffset(); + mozilla::Result dateTimeUTCOffset(bool allowZ); mozilla::Result utcOffsetSubMinutePrecision(); @@ -890,6 +935,17 @@ class TemporalParser final { mozilla::Result annotatedMonthDay(); + mozilla::Result durationDigits(JSContext* cx); + + template + mozilla::Result parse( + mozilla::Result&& result) const; + + template + mozilla::Result complete(const T& value) const; + + mozilla::Result nonempty() const; + public: explicit TemporalParser(mozilla::Span str) : reader_(str) {} @@ -901,8 +957,6 @@ class TemporalParser final { mozilla::Result parseTimeZoneIdentifier(); - mozilla::Result parseTimeZoneOffsetString(); - mozilla::Result parseDateTimeUTCOffset(); mozilla::Result @@ -924,87 +978,82 @@ class TemporalParser final { mozilla::Result parseTemporalZonedDateTimeString(); + + mozilla::Result + parseTemporalRelativeToString(); }; template -mozilla::Result -TemporalParser::dateTime() { - // DateTime ::: - // Date - // Date DateTimeSeparator TimeSpec DateTimeUTCOffset? - ZonedDateTimeString result = {}; - - auto dt = date(); - if (dt.isErr()) { - return dt.propagateErr(); +template +mozilla::Result TemporalParser::parse( + mozilla::Result&& result) const { + if (result.isOk() && !reader_.atEnd()) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_UNEXPECTED_CHARACTERS_AT_END); } - result.date = dt.unwrap(); + return std::move(result); +} - if (dateTimeSeparator()) { - auto time = timeSpec(); - if (time.isErr()) { - return time.propagateErr(); - } - result.time = time.unwrap(); - - if (hasDateTimeUTCOffsetStart()) { - auto tz = dateTimeUTCOffset(); - if (tz.isErr()) { - return tz.propagateErr(); - } - result.timeZone = tz.unwrap(); - } +template +template +mozilla::Result TemporalParser::complete( + const T& result) const { + if (!reader_.atEnd()) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_UNEXPECTED_CHARACTERS_AT_END); } - return result; } template -mozilla::Result TemporalParser::date() { - // Date ::: - // DateYear - DateMonth - DateDay - // DateYear DateMonth DateDay - PlainDate result = {}; +mozilla::Result TemporalParser::nonempty() + const { + if (reader_.length() == 0) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_EMPTY_STRING); + } + return mozilla::Ok{}; +} +template +mozilla::Result TemporalParser::dateYear() { // DateYear ::: // DecimalDigit{4} - // Sign DecimalDigit{6} + // ASCIISign DecimalDigit{6} + if (auto year = digits(4)) { - result.year = year.value(); - } else if (hasSign()) { + return year.value(); + } + if (hasSign()) { int32_t yearSign = sign(); if (auto year = digits(6)) { - result.year = yearSign * year.value(); - if (yearSign < 0 && result.year == 0) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR); + int32_t result = yearSign * year.value(); + if (yearSign < 0 && result == 0) { + return err(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR); } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR); + return result; } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_YEAR); + return err(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR); } + return err(JSMSG_TEMPORAL_PARSER_MISSING_YEAR); +} - // Optional: - - character('-'); - +template +mozilla::Result TemporalParser::dateMonth() { // DateMonth ::: // 0 NonzeroDigit // 10 // 11 // 12 if (auto month = digits(2)) { - result.month = month.value(); - if (!inBounds(result.month, 1, 12)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MONTH); + int32_t result = month.value(); + if (!inBounds(result, 1, 12)) { + return err(JSMSG_TEMPORAL_PARSER_INVALID_MONTH); } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MONTH); + return result; } + return err(JSMSG_TEMPORAL_PARSER_MISSING_MONTH); +} - // Optional: - - character('-'); - +template +mozilla::Result TemporalParser::dateDay() { // DateDay ::: // 0 NonzeroDigit // 1 DecimalDigit @@ -1012,30 +1061,17 @@ mozilla::Result TemporalParser::date() { // 30 // 31 if (auto day = digits(2)) { - result.day = day.value(); - if (!inBounds(result.day, 1, 31)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_DAY); + int32_t result = day.value(); + if (!inBounds(result, 1, 31)) { + return err(JSMSG_TEMPORAL_PARSER_INVALID_DAY); } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DAY); + return result; } - - return result; + return err(JSMSG_TEMPORAL_PARSER_MISSING_DAY); } template -mozilla::Result TemporalParser::timeSpec() { - // TimeSpec ::: - // TimeHour - // TimeHour : TimeMinute - // TimeHour TimeMinute - // TimeHour : TimeMinute : TimeSecond TimeFraction? - // TimeHour TimeMinute TimeSecond TimeFraction? - PlainTime result = {}; - - // TimeHour ::: - // Hour - // +mozilla::Result TemporalParser::hour() { // Hour ::: // 0 DecimalDigit // 1 DecimalDigit @@ -1044,19 +1080,65 @@ mozilla::Result TemporalParser::timeSpec() { // 22 // 23 if (auto hour = digits(2)) { - result.hour = hour.value(); - if (!inBounds(result.hour, 0, 23)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_HOUR); + int32_t result = hour.value(); + if (!inBounds(result, 0, 23)) { + return err(JSMSG_TEMPORAL_PARSER_INVALID_HOUR); } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_HOUR); + return result; } + return err(JSMSG_TEMPORAL_PARSER_MISSING_HOUR); +} - // Optional: : - bool needsMinutes = character(':'); +template +mozilla::Result, ParserError> +TemporalParser::minute(bool required) { + // MinuteSecond ::: + // 0 DecimalDigit + // 1 DecimalDigit + // 2 DecimalDigit + // 3 DecimalDigit + // 4 DecimalDigit + // 5 DecimalDigit + if (auto minute = digits(2)) { + if (!inBounds(minute.value(), 0, 59)) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE); + } + return minute; + } + if (!required) { + return mozilla::Maybe{mozilla::Nothing{}}; + } + return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE); +} - // TimeMinute ::: +template +mozilla::Result, ParserError> +TemporalParser::second(bool required) { + // MinuteSecond ::: + // 0 DecimalDigit + // 1 DecimalDigit + // 2 DecimalDigit + // 3 DecimalDigit + // 4 DecimalDigit + // 5 DecimalDigit + if (auto minute = digits(2)) { + if (!inBounds(minute.value(), 0, 59)) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_SECOND); + } + return minute; + } + if (!required) { + return mozilla::Maybe{mozilla::Nothing{}}; + } + return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_SECOND); +} + +template +mozilla::Result, ParserError> +TemporalParser::timeSecond(bool required) { + // TimeSecond ::: // MinuteSecond + // 60 // // MinuteSecond ::: // 0 DecimalDigit @@ -1066,36 +1148,127 @@ mozilla::Result TemporalParser::timeSpec() { // 4 DecimalDigit // 5 DecimalDigit if (auto minute = digits(2)) { - result.minute = minute.value(); - if (!inBounds(result.minute, 0, 59)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE); + if (!inBounds(minute.value(), 0, 60)) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND); } + return minute; + } + if (!required) { + return mozilla::Maybe{mozilla::Nothing{}}; + } + return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_SECOND); +} - // Optional: : - bool needsSeconds = needsMinutes && character(':'); +template +mozilla::Result TemporalParser::date() { + // clang-format off + // + // Date ::: + // DateSpec[+Extended] + // DateSpec[~Extended] + // + // DateSpec[Extended] ::: + // DateYear DateSeparator[?Extended] DateMonth DateSeparator[?Extended] DateDay + // + // clang-format on - // TimeSecond ::: - // MinuteSecond - // 60 - if (auto second = digits(2)) { - result.second = second.value(); - if (!inBounds(result.second, 0, 60)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND); + ISODate result{}; + + MOZ_TRY_VAR(result.year, dateYear()); + + // Optional |DateSeparator|. + bool hasMonthSeparator = dateSeparator(); + + MOZ_TRY_VAR(result.month, dateMonth()); + + // Optional |DateSeparator|. + bool hasDaySeparator = dateSeparator(); + + // Date separators must be consistent. + if (hasMonthSeparator != hasDaySeparator) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INCONSISTENT_DATE_SEPARATOR); + } + + MOZ_TRY_VAR(result.day, dateDay()); + + return result; +} + +template +mozilla::Result TemporalParser::time() { + // clang-format off + // + // Time ::: + // TimeSpec[+Extended] + // TimeSpec[~Extended] + // + // TimeSpec[Extended] ::: + // Hour + // Hour TimeSeparator[?Extended] MinuteSecond + // Hour TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] TimeSecond TemporalDecimalFraction? + // + // clang-format on + + Time result{}; + + MOZ_TRY_VAR(result.hour, hour()); + + // Optional |TimeSeparator|. + bool hasMinuteSeparator = timeSeparator(); + + mozilla::Maybe minutes; + MOZ_TRY_VAR(minutes, minute(hasMinuteSeparator)); + if (minutes) { + result.minute = minutes.value(); + + // Optional |TimeSeparator|. + bool hasSecondSeparator = timeSeparator(); + + mozilla::Maybe seconds; + MOZ_TRY_VAR(seconds, timeSecond(hasSecondSeparator)); + if (seconds) { + result.second = seconds.value(); + + // Time separators must be consistent. + if (hasMinuteSeparator != hasSecondSeparator) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR); } - // TimeFraction ::: - // Fraction + // TemporalDecimalFraction ::: + // TemporalDecimalSeparator DecimalDigit{1,9} if (auto f = fraction()) { int32_t fractionalPart = f.value(); result.millisecond = fractionalPart / 1'000'000; result.microsecond = (fractionalPart % 1'000'000) / 1'000; result.nanosecond = fractionalPart % 1'000; } - } else if (needsSeconds) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_SECOND); } - } else if (needsMinutes) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE); + } + + return result; +} + +template +mozilla::Result +TemporalParser::dateTime(bool allowZ) { + // DateTime[Z, TimeRequired] ::: + // [~TimeRequired] Date + // Date DateTimeSeparator Time DateTimeUTCOffset[?Z]? + // + // When called as `DateTime[?Z, ~TimeRequired]`. + + ZonedDateTimeString result{}; + + MOZ_TRY_VAR(result.date, date()); + + if (dateTimeSeparator()) { + MOZ_TRY_VAR(result.time, time()); + + if (hasDateTimeUTCOffsetStart()) { + MOZ_TRY_VAR(result.timeZone, dateTimeUTCOffset(allowZ)); + } + } else { + result.startOfDay = true; } return result; @@ -1103,21 +1276,23 @@ mozilla::Result TemporalParser::timeSpec() { template mozilla::Result -TemporalParser::dateTimeUTCOffset() { - // DateTimeUTCOffset ::: - // UTCDesignator - // UTCOffsetSubMinutePrecision +TemporalParser::dateTimeUTCOffset(bool allowZ) { + // DateTimeUTCOffset[Z] ::: + // [+Z] UTCDesignator + // UTCOffset[+SubMinutePrecision] if (utcDesignator()) { + if (!allowZ) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR); + } return TimeZoneString::UTC(); } if (hasSign()) { - auto offset = utcOffsetSubMinutePrecision(); - if (offset.isErr()) { - return offset.propagateErr(); - } - return TimeZoneString::from(offset.unwrap()); + DateTimeUTCOffset offset; + MOZ_TRY_VAR(offset, utcOffsetSubMinutePrecision()); + + return TimeZoneString::from(offset); } return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE); @@ -1126,60 +1301,39 @@ TemporalParser::dateTimeUTCOffset() { template mozilla::Result TemporalParser::timeZoneUTCOffsetName() { - // TimeZoneUTCOffsetName ::: - // UTCOffsetMinutePrecision + // clang-format off // - // UTCOffsetMinutePrecision ::: - // Sign Hour - // Sign Hour TimeSeparator[+Extended] MinuteSecond - // Sign Hour TimeSeparator[~Extended] MinuteSecond + // UTCOffset[SubMinutePrecision] ::: + // ASCIISign Hour + // ASCIISign Hour TimeSeparator[+Extended] MinuteSecond + // ASCIISign Hour TimeSeparator[~Extended] MinuteSecond + // [+SubMinutePrecision] ASCIISign Hour TimeSeparator[+Extended] MinuteSecond TimeSeparator[+Extended] MinuteSecond TemporalDecimalFraction? + // [+SubMinutePrecision] ASCIISign Hour TimeSeparator[~Extended] MinuteSecond TimeSeparator[~Extended] MinuteSecond TemporalDecimalFraction? + // + // When called as `UTCOffset[~SubMinutePrecision]`. + // + // clang-format on - TimeZoneUTCOffset result = {}; + TimeZoneUTCOffset result{}; if (!hasSign()) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_SIGN); } result.sign = sign(); - // Hour ::: - // 0 DecimalDigit - // 1 DecimalDigit - // 20 - // 21 - // 22 - // 23 - if (auto hour = digits(2)) { - result.hour = hour.value(); - if (!inBounds(result.hour, 0, 23)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_HOUR); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_HOUR); - } + MOZ_TRY_VAR(result.hour, hour()); - // TimeSeparator[Extended] ::: - // [+Extended] : - // [~Extended] [empty] - bool needsMinutes = character(':'); + // Optional |TimeSeparator|. + bool hasMinuteSeparator = timeSeparator(); - // MinuteSecond ::: - // 0 DecimalDigit - // 1 DecimalDigit - // 2 DecimalDigit - // 3 DecimalDigit - // 4 DecimalDigit - // 5 DecimalDigit - if (auto minute = digits(2)) { - result.minute = minute.value(); - if (!inBounds(result.minute, 0, 59)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE); - } + mozilla::Maybe minutes; + MOZ_TRY_VAR(minutes, minute(hasMinuteSeparator)); + if (minutes) { + result.minute = minutes.value(); - if (hasCharacter(':')) { + if (hasTimeSeparator()) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE); } - } else if (needsMinutes) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE); } return result; @@ -1190,78 +1344,45 @@ mozilla::Result TemporalParser::utcOffsetSubMinutePrecision() { // clang-format off // - // UTCOffsetSubMinutePrecision ::: - // UTCOffsetMinutePrecision - // UTCOffsetWithSubMinuteComponents[+Extended] - // UTCOffsetWithSubMinuteComponents[~Extended] + // UTCOffset[SubMinutePrecision] ::: + // ASCIISign Hour + // ASCIISign Hour TimeSeparator[+Extended] MinuteSecond + // ASCIISign Hour TimeSeparator[~Extended] MinuteSecond + // [+SubMinutePrecision] ASCIISign Hour TimeSeparator[+Extended] MinuteSecond TimeSeparator[+Extended] MinuteSecond TemporalDecimalFraction? + // [+SubMinutePrecision] ASCIISign Hour TimeSeparator[~Extended] MinuteSecond TimeSeparator[~Extended] MinuteSecond TemporalDecimalFraction? // - // UTCOffsetMinutePrecision ::: - // Sign Hour - // Sign Hour TimeSeparator[+Extended] MinuteSecond - // Sign Hour TimeSeparator[~Extended] MinuteSecond - // - // UTCOffsetWithSubMinuteComponents[Extended] ::: - // Sign Hour TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond Fraction? + // When called as `UTCOffset[+SubMinutePrecision]`. // // clang-format on - DateTimeUTCOffset result = {}; + DateTimeUTCOffset result{}; if (!hasSign()) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_SIGN); } result.sign = sign(); - // Hour ::: - // 0 DecimalDigit - // 1 DecimalDigit - // 20 - // 21 - // 22 - // 23 - if (auto hour = digits(2)) { - result.hour = hour.value(); - if (!inBounds(result.hour, 0, 23)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_HOUR); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_HOUR); - } + MOZ_TRY_VAR(result.hour, hour()); - // TimeSeparator[Extended] ::: - // [+Extended] : - // [~Extended] [empty] - bool needsMinutes = character(':'); + // Optional |TimeSeparator|. + bool hasMinuteSeparator = timeSeparator(); - // MinuteSecond ::: - // 0 DecimalDigit - // 1 DecimalDigit - // 2 DecimalDigit - // 3 DecimalDigit - // 4 DecimalDigit - // 5 DecimalDigit - if (auto minute = digits(2)) { - result.minute = minute.value(); - if (!inBounds(result.minute, 0, 59)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE); - } + mozilla::Maybe minutes; + MOZ_TRY_VAR(minutes, minute(hasMinuteSeparator)); + if (minutes) { + result.minute = minutes.value(); - // TimeSeparator[Extended] ::: - // [+Extended] : - // [~Extended] [empty] - bool needsSeconds = needsMinutes && character(':'); + // Optional |TimeSeparator|. + bool hasSecondSeparator = timeSeparator(); - // MinuteSecond ::: - // 0 DecimalDigit - // 1 DecimalDigit - // 2 DecimalDigit - // 3 DecimalDigit - // 4 DecimalDigit - // 5 DecimalDigit - if (auto second = digits(2)) { - result.second = second.value(); - if (!inBounds(result.second, 0, 59)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_SECOND); + mozilla::Maybe seconds; + MOZ_TRY_VAR(seconds, second(hasSecondSeparator)); + if (seconds) { + result.second = seconds.value(); + + // Time separators must be consistent. + if (hasMinuteSeparator != hasSecondSeparator) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR); } if (auto fractionalPart = fraction()) { @@ -1269,11 +1390,7 @@ TemporalParser::utcOffsetSubMinutePrecision() { } result.subMinutePrecision = true; - } else if (needsSeconds) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_SECOND); } - } else if (needsMinutes) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE); } return result; @@ -1283,22 +1400,14 @@ template mozilla::Result TemporalParser::timeZoneIdentifier() { // TimeZoneIdentifier ::: - // TimeZoneUTCOffsetName + // UTCOffset[~SubMinutePrecision] // TimeZoneIANAName - TimeZoneAnnotation result = {}; + TimeZoneAnnotation result{}; if (hasSign()) { - auto offset = timeZoneUTCOffsetName(); - if (offset.isErr()) { - return offset.propagateErr(); - } - result.offset = offset.unwrap(); + MOZ_TRY_VAR(result.offset, timeZoneUTCOffsetName()); } else { - auto name = timeZoneIANAName(); - if (name.isErr()) { - return name.propagateErr(); - } - result.name = name.unwrap(); + MOZ_TRY_VAR(result.name, timeZoneIANAName()); } return result; @@ -1377,57 +1486,37 @@ mozilla::Maybe TemporalParser::digits(JSContext* cx) { template mozilla::Result TemporalParser::parseTemporalInstantString() { + MOZ_TRY(nonempty()); + // Initialize all fields to zero. - ZonedDateTimeString result = {}; + ZonedDateTimeString result{}; // clang-format off // // TemporalInstantString ::: - // Date DateTimeSeparator TimeSpec DateTimeUTCOffset TimeZoneAnnotation? Annotations? + // Date DateTimeSeparator Time DateTimeUTCOffset[+Z] TimeZoneAnnotation? Annotations? // // clang-format on - auto dt = date(); - if (dt.isErr()) { - return dt.propagateErr(); - } - result.date = dt.unwrap(); + MOZ_TRY_VAR(result.date, date()); if (!dateTimeSeparator()) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DATE_TIME_SEPARATOR); } - auto time = timeSpec(); - if (time.isErr()) { - return time.propagateErr(); - } - result.time = time.unwrap(); + MOZ_TRY_VAR(result.time, time()); - auto tz = dateTimeUTCOffset(); - if (tz.isErr()) { - return tz.propagateErr(); - } - result.timeZone = tz.unwrap(); + MOZ_TRY_VAR(result.timeZone, dateTimeUTCOffset(/* allowZ = */ true)); if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); } if (hasAnnotationStart()) { - if (auto cal = annotations(); cal.isErr()) { - return cal.propagateErr(); - } + MOZ_TRY(annotations()); } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - - return result; + return complete(result); } /** @@ -1455,7 +1544,7 @@ static auto ParseTemporalInstantString(Handle str) { */ bool js::temporal::ParseTemporalInstantString(JSContext* cx, Handle str, - PlainDateTime* result, + ISODateTime* result, int64_t* offset) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { @@ -1466,7 +1555,7 @@ bool js::temporal::ParseTemporalInstantString(JSContext* cx, auto parseResult = ::ParseTemporalInstantString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "instant"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); @@ -1489,25 +1578,24 @@ bool js::temporal::ParseTemporalInstantString(JSContext* cx, template mozilla::Result TemporalParser::parseTemporalTimeZoneString() { - // TimeZoneIdentifier ::: - // TimeZoneUTCOffsetName - // TimeZoneIANAName + MOZ_TRY(nonempty()); - if (hasSign()) { - if (auto offset = timeZoneUTCOffsetName(); - offset.isOk() && reader_.atEnd()) { - ZonedDateTimeString result = {}; - result.timeZone = TimeZoneString::from(offset.unwrap()); - return result; - } - } else { - if (auto name = timeZoneIANAName(); name.isOk() && reader_.atEnd()) { - ZonedDateTimeString result = {}; - result.timeZone = TimeZoneString::from(name.unwrap()); - return result; + // Handle the common case of a standalone time zone identifier first. + if (auto tz = parse(timeZoneIdentifier()); tz.isOk()) { + auto timeZone = tz.unwrap(); + + ZonedDateTimeString result{}; + if (timeZone.hasOffset()) { + result.timeZone = TimeZoneString::from(timeZone.offset); + } else { + MOZ_ASSERT(timeZone.hasName()); + result.timeZone = TimeZoneString::from(timeZone.name); } + return result; } + LikelyError likelyError{}; + // Try all five parse goals from ParseISODateTime in order. // // TemporalDateTimeString @@ -1519,39 +1607,49 @@ TemporalParser::parseTemporalTimeZoneString() { // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalDateTimeString(); dt.isOk()) { - return dt.unwrap(); + auto dateTime = parseTemporalDateTimeString(); + if (dateTime.isOk()) { + return dateTime; } + likelyError.update(dateTime, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalInstantString(); dt.isOk()) { - return dt.unwrap(); + auto instant = parseTemporalInstantString(); + if (instant.isOk()) { + return instant; } + likelyError.update(instant, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalTimeString(); dt.isOk()) { - return dt.unwrap(); + auto time = parseTemporalTimeString(); + if (time.isOk()) { + return time; } + likelyError.update(time, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalMonthDayString(); dt.isOk()) { - return dt.unwrap(); + auto monthDay = parseTemporalMonthDayString(); + if (monthDay.isOk()) { + return monthDay; } + likelyError.update(monthDay, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalYearMonthString(); dt.isOk()) { - return dt.unwrap(); - } else { - return dt.propagateErr(); + auto yearMonth = parseTemporalYearMonthString(); + if (yearMonth.isOk()) { + return yearMonth; } + likelyError.update(yearMonth, reader_.index()); + + return likelyError.propagate(); } /** @@ -1589,14 +1687,14 @@ bool js::temporal::ParseTemporalTimeZoneString( auto parseResult = ::ParseTemporalTimeZoneString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "time zone"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); const auto& timeZone = parsed.timeZone; // Step 3. - PlainDateTime unused; + ISODateTime unused; if (!ParseISODateTime(cx, parsed, &unused)) { return false; } @@ -1621,7 +1719,7 @@ bool js::temporal::ParseTemporalTimeZoneString( if (timeZone.offset.subMinutePrecision) { JS_ReportErrorNumberASCII( cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE); + JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE, "time zone"); return false; } @@ -1630,7 +1728,8 @@ bool js::temporal::ParseTemporalTimeZoneString( } else { // Step 5. JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE); + JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE, + "time zone"); return false; } @@ -1641,14 +1740,8 @@ bool js::temporal::ParseTemporalTimeZoneString( template mozilla::Result TemporalParser::parseTimeZoneIdentifier() { - auto result = timeZoneIdentifier(); - if (result.isErr()) { - return result.propagateErr(); - } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return result; + MOZ_TRY(nonempty()); + return parse(timeZoneIdentifier()); } /** @@ -1686,7 +1779,7 @@ bool js::temporal::ParseTimeZoneIdentifier( auto parseResult = ::ParseTimeZoneIdentifier(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "time zone identifier"); return false; } auto timeZone = parseResult.unwrap(); @@ -1695,76 +1788,11 @@ bool js::temporal::ParseTimeZoneIdentifier( return ParseTimeZoneAnnotation(cx, timeZone, linear, result); } -template -mozilla::Result -TemporalParser::parseTimeZoneOffsetString() { - auto offset = timeZoneUTCOffsetName(); - if (offset.isErr()) { - return offset.propagateErr(); - } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return offset.unwrap(); -} - -/** - * ParseTimeZoneOffsetString ( isoString ) - */ -template -static auto ParseTimeZoneOffsetString(mozilla::Span str) { - TemporalParser parser(str); - return parser.parseTimeZoneOffsetString(); -} - -/** - * ParseTimeZoneOffsetString ( isoString ) - */ -static auto ParseTimeZoneOffsetString(Handle str) { - JS::AutoCheckCannotGC nogc; - if (str->hasLatin1Chars()) { - return ParseTimeZoneOffsetString(str->latin1Range(nogc)); - } - return ParseTimeZoneOffsetString(str->twoByteRange(nogc)); -} - -/** - * ParseTimeZoneOffsetString ( isoString ) - */ -bool js::temporal::ParseTimeZoneOffsetString(JSContext* cx, - Handle str, - int32_t* result) { - // Step 1. (Not applicable in our implementation.) - - Rooted linear(cx, str->ensureLinear(cx)); - if (!linear) { - return false; - } - - // Step 2. - auto parseResult = ::ParseTimeZoneOffsetString(linear); - if (parseResult.isErr()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); - return false; - } - - // Steps 3-13. - *result = ParseTimeZoneOffset(parseResult.unwrap()); - return true; -} - template mozilla::Result TemporalParser::parseDateTimeUTCOffset() { - auto offset = utcOffsetSubMinutePrecision(); - if (offset.isErr()) { - return offset.propagateErr(); - } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return offset.unwrap(); + MOZ_TRY(nonempty()); + return parse(utcOffsetSubMinutePrecision()); } /** @@ -1801,7 +1829,7 @@ bool js::temporal::ParseDateTimeUTCOffset(JSContext* cx, Handle str, auto parseResult = ::ParseDateTimeUTCOffset(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "UTC offset"); return false; } @@ -1810,18 +1838,30 @@ bool js::temporal::ParseDateTimeUTCOffset(JSContext* cx, Handle str, return true; } +template +mozilla::Result TemporalParser::durationDigits( + JSContext* cx) { + auto d = digits(cx); + if (!d) { + return err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); + } + return *d; +} + template mozilla::Result TemporalParser::parseTemporalDurationString(JSContext* cx) { + MOZ_TRY(nonempty()); + // Initialize all fields to zero. - TemporalDurationString result = {}; + TemporalDurationString result{}; // TemporalDurationString ::: // Duration // // Duration ::: - // Sign? DurationDesignator DurationDate - // Sign? DurationDesignator DurationTime + // ASCIISign? DurationDesignator DurationDate + // ASCIISign? DurationDesignator DurationTime if (hasSign()) { result.sign = sign(); @@ -1838,23 +1878,17 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { // DurationDaysPart DurationTime? do { - double num; if (hasTimeDesignator()) { break; } - if (auto d = digits(cx); !d) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } else { - num = *d; - } + + double num; + MOZ_TRY_VAR(num, durationDigits(cx)); // DurationYearsPart ::: - // DurationYears YearsDesignator DurationMonthsPart - // DurationYears YearsDesignator DurationWeeksPart - // DurationYears YearsDesignator DurationDaysPart? - // - // DurationYears ::: - // DecimalDigits[~Sep] + // DecimalDigits[~Sep] YearsDesignator DurationMonthsPart + // DecimalDigits[~Sep] YearsDesignator DurationWeeksPart + // DecimalDigits[~Sep] YearsDesignator DurationDaysPart? if (yearsDesignator()) { result.years = num; if (reader_.atEnd()) { @@ -1863,19 +1897,12 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { if (hasTimeDesignator()) { break; } - if (auto d = digits(cx); !d) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } else { - num = *d; - } + MOZ_TRY_VAR(num, durationDigits(cx)); } // DurationMonthsPart ::: - // DurationMonths MonthsDesignator DurationWeeksPart - // DurationMonths MonthsDesignator DurationDaysPart? - // - // DurationMonths ::: - // DecimalDigits[~Sep] + // DecimalDigits[~Sep] MonthsDesignator DurationWeeksPart + // DecimalDigits[~Sep] MonthsDesignator DurationDaysPart? if (monthsDesignator()) { result.months = num; if (reader_.atEnd()) { @@ -1884,18 +1911,11 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { if (hasTimeDesignator()) { break; } - if (auto d = digits(cx); !d) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } else { - num = *d; - } + MOZ_TRY_VAR(num, durationDigits(cx)); } // DurationWeeksPart ::: - // DurationWeeks WeeksDesignator DurationDaysPart? - // - // DurationWeeks ::: - // DecimalDigits[~Sep] + // DecimalDigits[~Sep] WeeksDesignator DurationDaysPart? if (weeksDesignator()) { result.weeks = num; if (reader_.atEnd()) { @@ -1904,18 +1924,11 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { if (hasTimeDesignator()) { break; } - if (auto d = digits(cx); !d) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } else { - num = *d; - } + MOZ_TRY_VAR(num, durationDigits(cx)); } // DurationDaysPart ::: - // DurationDays DaysDesignator - // - // DurationDays ::: - // DecimalDigits[~Sep] + // DecimalDigits[~Sep] DaysDesignator if (daysDesignator()) { result.days = num; if (reader_.atEnd()) { @@ -1926,50 +1939,26 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { } } - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); + return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_UNIT_DESIGNATOR); } while (false); // DurationTime ::: - // DurationTimeDesignator DurationHoursPart - // DurationTimeDesignator DurationMinutesPart - // DurationTimeDesignator DurationSecondsPart + // TimeDesignator DurationHoursPart + // TimeDesignator DurationMinutesPart + // TimeDesignator DurationSecondsPart if (!timeDesignator()) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_TIME_DESIGNATOR); } double num; - mozilla::Maybe frac; - auto digitsAndFraction = [&]() { - auto d = digits(cx); - if (!d) { - return false; - } - num = *d; - frac = fraction(); - return true; - }; + MOZ_TRY_VAR(num, durationDigits(cx)); - if (!digitsAndFraction()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } + auto frac = fraction(); - // clang-format off - // // DurationHoursPart ::: - // DurationWholeHours DurationHoursFraction HoursDesignator - // DurationWholeHours HoursDesignator DurationMinutesPart - // DurationWholeHours HoursDesignator DurationSecondsPart? - // - // DurationWholeHours ::: - // DecimalDigits[~Sep] - // - // DurationHoursFraction ::: - // TimeFraction - // - // TimeFraction ::: - // Fraction - // - // clang-format on + // DecimalDigits[~Sep] TemporalDecimalFraction HoursDesignator + // DecimalDigits[~Sep] HoursDesignator DurationMinutesPart + // DecimalDigits[~Sep] HoursDesignator DurationSecondsPart? bool hasHoursFraction = false; if (hoursDesignator()) { hasHoursFraction = bool(frac); @@ -1978,27 +1967,14 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { if (reader_.atEnd()) { return result; } - if (!digitsAndFraction()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } + + MOZ_TRY_VAR(num, durationDigits(cx)); + frac = fraction(); } - // clang-format off - // // DurationMinutesPart ::: - // DurationWholeMinutes DurationMinutesFraction MinutesDesignator - // DurationWholeMinutes MinutesDesignator DurationSecondsPart? - // - // DurationWholeMinutes ::: - // DecimalDigits[~Sep] - // - // DurationMinutesFraction ::: - // TimeFraction - // - // TimeFraction ::: - // Fraction - // - // clang-format on + // DecimalDigits[~Sep] TemporalDecimalFraction MinutesDesignator + // DecimalDigits[~Sep] MinutesDesignator DurationSecondsPart? bool hasMinutesFraction = false; if (minutesDesignator()) { if (hasHoursFraction) { @@ -2010,22 +1986,13 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { if (reader_.atEnd()) { return result; } - if (!digitsAndFraction()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS); - } + + MOZ_TRY_VAR(num, durationDigits(cx)); + frac = fraction(); } // DurationSecondsPart ::: - // DurationWholeSeconds DurationSecondsFraction? SecondsDesignator - // - // DurationWholeSeconds ::: - // DecimalDigits[~Sep] - // - // DurationSecondsFraction ::: - // TimeFraction - // - // TimeFraction ::: - // Fraction + // DecimalDigits[~Sep] TemporalDecimalFraction? SecondsDesignator if (secondsDesignator()) { if (hasHoursFraction || hasMinutesFraction) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_SECONDS); @@ -2037,7 +2004,7 @@ TemporalParser::parseTemporalDurationString(JSContext* cx) { } } - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); + return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_UNIT_DESIGNATOR); } /** @@ -2077,7 +2044,7 @@ bool js::temporal::ParseTemporalDurationString(JSContext* cx, auto parseResult = ::ParseTemporalDurationString(cx, linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "duration"); return false; } TemporalDurationString parsed = parseResult.unwrap(); @@ -2225,27 +2192,23 @@ mozilla::Result TemporalParser::annotation() { return mozilla::Err(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_ANNOTATION); } - bool critical = annotationCriticalFlag(); + Annotation result{}; - auto key = annotationKey(); - if (key.isErr()) { - return key.propagateErr(); - } + result.critical = annotationCriticalFlag(); + + MOZ_TRY_VAR(result.key, annotationKey()); if (!character('=')) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_ASSIGNMENT_IN_ANNOTATION); } - auto value = annotationValue(); - if (value.isErr()) { - return value.propagateErr(); - } + MOZ_TRY_VAR(result.value, annotationValue()); if (!character(']')) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_ANNOTATION); } - return Annotation{key.unwrap(), value.unwrap(), critical}; + return result; } template @@ -2259,11 +2222,10 @@ TemporalParser::annotations() { CalendarName calendar; bool calendarWasCritical = false; while (hasAnnotationStart()) { - auto anno = annotation(); - if (anno.isErr()) { - return anno.propagateErr(); - } - auto [key, value, critical] = anno.unwrap(); + Annotation anno; + MOZ_TRY_VAR(anno, annotation()); + + auto [key, value, critical] = anno; static constexpr std::string_view ca = "u-ca"; @@ -2289,109 +2251,64 @@ TemporalParser::annotatedTime() { // clang-format off // // AnnotatedTime ::: - // TimeDesignator TimeSpec DateTimeUTCOffset? TimeZoneAnnotation? Annotations? - // TimeSpecWithOptionalOffsetNotAmbiguous TimeZoneAnnotation? Annotations? + // TimeDesignator Time DateTimeUTCOffset[~Z]? TimeZoneAnnotation? Annotations? + // Time DateTimeUTCOffset[~Z]? TimeZoneAnnotation? Annotations? // // clang-format on - if (timeDesignator()) { - ZonedDateTimeString result = {}; - - auto time = timeSpec(); - if (time.isErr()) { - return time.propagateErr(); - } - result.time = time.unwrap(); - - if (hasDateTimeUTCOffsetStart()) { - auto tz = dateTimeUTCOffset(); - if (tz.isErr()) { - return tz.propagateErr(); - } - result.timeZone = tz.unwrap(); - } - - if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); - } - - if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); - } - - return result; - } - - // clang-format off - // - // TimeSpecWithOptionalOffsetNotAmbiguous ::: - // TimeSpec DateTimeUTCOffset? but not one of ValidMonthDay or DateSpecYearMonth - // - // clang-format on + ZonedDateTimeString result{}; size_t start = reader_.index(); + bool hasTimeDesignator = timeDesignator(); - ZonedDateTimeString result = {}; - - auto time = timeSpec(); - if (time.isErr()) { - return time.propagateErr(); - } - result.time = time.unwrap(); + MOZ_TRY_VAR(result.time, time()); if (hasDateTimeUTCOffsetStart()) { - auto tz = dateTimeUTCOffset(); - if (tz.isErr()) { - return tz.propagateErr(); - } - result.timeZone = tz.unwrap(); + MOZ_TRY_VAR(result.timeZone, dateTimeUTCOffset(/* allowZ = */ false)); } - size_t end = reader_.index(); + // Early error if `Time DateTimeUTCOffset[~Z]` can be parsed as either + // `DateSpecMonthDay` or `DateSpecYearMonth`. + if (!hasTimeDesignator) { + size_t end = reader_.index(); - // Reset and check if the input can also be parsed as ValidMonthDay. - reader_.reset(start); + auto isValidMonthDay = [](const ISODate& date) { + MOZ_ASSERT(date.year == AbsentYear); + MOZ_ASSERT(1 <= date.month && date.month <= 12); + MOZ_ASSERT(1 <= date.day && date.day <= 31); - if (validMonthDay().isOk()) { - if (reader_.index() == end) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_MONTH_DAY); + constexpr int32_t leapYear = 0; + return date.day <= ISODaysInMonth(leapYear, date.month); + }; + + // Reset and check if the input can also be parsed as DateSpecMonthDay. + reader_.reset(start); + + if (auto monthDay = dateSpecMonthDay(); monthDay.isOk()) { + if (reader_.index() == end && isValidMonthDay(monthDay.unwrap())) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_MONTH_DAY); + } } - } - // Reset and check if the input can also be parsed as DateSpecYearMonth. - reader_.reset(start); + // Reset and check if the input can also be parsed as DateSpecYearMonth. + reader_.reset(start); - if (dateSpecYearMonth().isOk()) { - if (reader_.index() == end) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_YEAR_MONTH); + if (dateSpecYearMonth().isOk()) { + if (reader_.index() == end) { + return mozilla::Err(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_YEAR_MONTH); + } } - } - // Input can neither be parsed as ValidMonthDay nor DateSpecYearMonth. - reader_.reset(end); + // Input can neither be parsed as DateSpecMonthDay nor DateSpecYearMonth. + reader_.reset(end); + } if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); } if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); + MOZ_TRY_VAR(result.calendar, annotations()); } return result; @@ -2400,30 +2317,21 @@ TemporalParser::annotatedTime() { template mozilla::Result TemporalParser::annotatedDateTime() { - // AnnotatedDateTime[Zoned] ::: - // [~Zoned] DateTime TimeZoneAnnotation? Annotations? - // [+Zoned] DateTime TimeZoneAnnotation Annotations? + // AnnotatedDateTime[Zoned, TimeRequired] ::: + // [~Zoned] DateTime[~Z, ?TimeRequired] TimeZoneAnnotation? Annotations? + // [+Zoned] DateTime[+Z, ?TimeRequired] TimeZoneAnnotation Annotations? + // + // When called as `AnnotatedDateTime[~Zoned, ~TimeRequired]`. - auto dt = dateTime(); - if (dt.isErr()) { - return dt.propagateErr(); - } - auto result = dt.unwrap(); + ZonedDateTimeString result; + MOZ_TRY_VAR(result, dateTime(/* allowZ = */ false)); if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); } if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); + MOZ_TRY_VAR(result.calendar, annotations()); } return result; @@ -2432,53 +2340,36 @@ TemporalParser::annotatedDateTime() { template mozilla::Result TemporalParser::annotatedDateTimeTimeRequired() { - // clang-format off + // AnnotatedDateTime[Zoned, TimeRequired] ::: + // [~Zoned] DateTime[~Z, ?TimeRequired] TimeZoneAnnotation? Annotations? + // [+Zoned] DateTime[+Z, ?TimeRequired] TimeZoneAnnotation Annotations? // - // AnnotatedDateTimeTimeRequired ::: - // Date DateTimeSeparator TimeSpec DateTimeUTCOffset? TimeZoneAnnotation? Annotations? + // DateTime[Z, TimeRequired] ::: + // [~TimeRequired] Date + // Date DateTimeSeparator Time DateTimeUTCOffset[?Z]? // - // clang-format on + // When called as `AnnotatedDateTime[~Zoned, +TimeRequired]`. - ZonedDateTimeString result = {}; + ZonedDateTimeString result{}; - auto dt = date(); - if (dt.isErr()) { - return dt.propagateErr(); - } - result.date = dt.unwrap(); + MOZ_TRY_VAR(result.date, date()); if (!dateTimeSeparator()) { return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DATE_TIME_SEPARATOR); } - auto time = timeSpec(); - if (time.isErr()) { - return time.propagateErr(); - } - result.time = time.unwrap(); + MOZ_TRY_VAR(result.time, time()); if (hasDateTimeUTCOffsetStart()) { - auto tz = dateTimeUTCOffset(); - if (tz.isErr()) { - return tz.propagateErr(); - } - result.timeZone = tz.unwrap(); + MOZ_TRY_VAR(result.timeZone, dateTimeUTCOffset(/* allowZ = */ false)); } if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); } if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); + MOZ_TRY_VAR(result.calendar, annotations()); } return result; @@ -2490,28 +2381,16 @@ TemporalParser::annotatedYearMonth() { // AnnotatedYearMonth ::: // DateSpecYearMonth TimeZoneAnnotation? Annotations? - ZonedDateTimeString result = {}; + ZonedDateTimeString result{}; - auto yearMonth = dateSpecYearMonth(); - if (yearMonth.isErr()) { - return yearMonth.propagateErr(); - } - result.date = yearMonth.unwrap(); + MOZ_TRY_VAR(result.date, dateSpecYearMonth()); if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); } if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); + MOZ_TRY_VAR(result.calendar, annotations()); } return result; @@ -2523,186 +2402,60 @@ TemporalParser::annotatedMonthDay() { // AnnotatedMonthDay ::: // DateSpecMonthDay TimeZoneAnnotation? Annotations? - ZonedDateTimeString result = {}; + ZonedDateTimeString result{}; - auto monthDay = dateSpecMonthDay(); - if (monthDay.isErr()) { - return monthDay.propagateErr(); - } - result.date = monthDay.unwrap(); + MOZ_TRY_VAR(result.date, dateSpecMonthDay()); if (hasTimeZoneAnnotationStart()) { - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); } if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); + MOZ_TRY_VAR(result.calendar, annotations()); } return result; } template -mozilla::Result +mozilla::Result TemporalParser::dateSpecYearMonth() { // DateSpecYearMonth ::: - // DateYear -? DateMonth - PlainDate result = {}; + // DateYear DateSeparator[+Extended] DateMonth + // DateYear DateSeparator[~Extended] DateMonth - // DateYear ::: - // DecimalDigit{4} - // Sign DecimalDigit{6} - if (auto year = digits(4)) { - result.year = year.value(); - } else if (hasSign()) { - int32_t yearSign = sign(); - if (auto year = digits(6)) { - result.year = yearSign * year.value(); - if (yearSign < 0 && result.year == 0) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_YEAR); - } + ISODate result{}; - character('-'); + MOZ_TRY_VAR(result.year, dateYear()); - // DateMonth ::: - // 0 NonzeroDigit - // 10 - // 11 - // 12 - if (auto month = digits(2)) { - result.month = month.value(); - if (!inBounds(result.month, 1, 12)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MONTH); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MONTH); - } + // Optional |DateSeparator|. + dateSeparator(); - // Absent days default to 1, cf. ParseISODateTime. - result.day = 1; + MOZ_TRY_VAR(result.month, dateMonth()); return result; } template -mozilla::Result +mozilla::Result TemporalParser::dateSpecMonthDay() { // DateSpecMonthDay ::: - // -- DateMonth -? DateDay - // DateMonth -? DateDay - PlainDate result = {}; + // --? DateMonth DateSeparator[+Extended] DateDay + // --? DateMonth DateSeparator[~Extended] DateDay + + ISODate result{}; // Optional: -- string("--"); result.year = AbsentYear; - // DateMonth ::: - // 0 NonzeroDigit - // 10 - // 11 - // 12 - if (auto month = digits(2)) { - result.month = month.value(); - if (!inBounds(result.month, 1, 12)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MONTH); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MONTH); - } + MOZ_TRY_VAR(result.month, dateMonth()); - // Optional: - - character('-'); + // Optional |DateSeparator|. + dateSeparator(); - // DateDay ::: - // 0 NonzeroDigit - // 1 DecimalDigit - // 2 DecimalDigit - // 30 - // 31 - if (auto day = digits(2)) { - result.day = day.value(); - if (!inBounds(result.day, 1, 31)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_DAY); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DAY); - } - - return result; -} - -template -mozilla::Result TemporalParser::validMonthDay() { - // ValidMonthDay ::: - // DateMonth -? 0 NonZeroDigit - // DateMonth -? 1 DecimalDigit - // DateMonth -? 2 DecimalDigit - // DateMonth -? 30 but not one of 0230 or 02-30 - // DateMonthWithThirtyOneDays -? 31 - // - // DateMonthWithThirtyOneDays ::: one of - // 01 03 05 07 08 10 12 - - PlainDate result = {}; - - // DateMonth ::: - // 0 NonzeroDigit - // 10 - // 11 - // 12 - if (auto month = digits(2)) { - result.month = month.value(); - if (!inBounds(result.month, 1, 12)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_MONTH); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_MONTH); - } - - // Optional: - - character('-'); - - if (auto day = digits(2)) { - result.day = day.value(); - if (!inBounds(result.day, 1, 31)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_DAY); - } - } else { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_MISSING_DAY); - } - - if (result.month == 2 && result.day > 29) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_DAY); - } - - if (result.day > 30) { - MOZ_ASSERT(result.day == 31); - - static constexpr int32_t monthsWithThirtyOneDays[] = { - 1, 3, 5, 7, 8, 10, 12, - }; - - if (std::find(std::begin(monthsWithThirtyOneDays), - std::end(monthsWithThirtyOneDays), - result.month) == std::end(monthsWithThirtyOneDays)) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_INVALID_DAY); - } - } + MOZ_TRY_VAR(result.day, dateDay()); return result; } @@ -2710,6 +2463,8 @@ mozilla::Result TemporalParser::validMonthDay() { template mozilla::Result TemporalParser::parseTemporalCalendarString() { + MOZ_TRY(nonempty()); + // Handle the common case of a standalone calendar name first. // // All valid calendar names start with two alphabetic characters and none of @@ -2717,61 +2472,66 @@ TemporalParser::parseTemporalCalendarString() { // TemporalTimeString can start with 'T', so we can't only check the first // character. if (hasTwoAsciiAlpha()) { - auto cal = annotationValue(); - if (cal.isErr()) { - return cal.propagateErr(); - } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } + ZonedDateTimeString result{}; + + MOZ_TRY_VAR(result.calendar, parse(annotationValue())); - ZonedDateTimeString result = {}; - result.calendar = cal.unwrap(); return result; } + LikelyError likelyError{}; + // Try all five parse goals from ParseISODateTime in order. // // TemporalDateTimeString // TemporalInstantString // TemporalTimeString - // TemporalZonedDateTimeString // TemporalMonthDayString // TemporalYearMonthString - if (auto dt = parseTemporalDateTimeString(); dt.isOk()) { - return dt.unwrap(); + auto dateTime = parseTemporalDateTimeString(); + if (dateTime.isOk()) { + return dateTime; } + likelyError.update(dateTime, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalInstantString(); dt.isOk()) { - return dt.unwrap(); + auto instant = parseTemporalInstantString(); + if (instant.isOk()) { + return instant; } + likelyError.update(instant, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalTimeString(); dt.isOk()) { - return dt.unwrap(); + auto time = parseTemporalTimeString(); + if (time.isOk()) { + return time; } + likelyError.update(time, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalMonthDayString(); dt.isOk()) { - return dt.unwrap(); + auto monthDay = parseTemporalMonthDayString(); + if (monthDay.isOk()) { + return monthDay; } + likelyError.update(monthDay, reader_.index()); // Restart parsing from the start of the string. reader_.reset(); - if (auto dt = parseTemporalYearMonthString(); dt.isOk()) { - return dt.unwrap(); - } else { - return dt.propagateErr(); + auto yearMonth = parseTemporalYearMonthString(); + if (yearMonth.isOk()) { + return yearMonth; } + likelyError.update(yearMonth, reader_.index()); + + return likelyError.propagate(); } /** @@ -2804,16 +2564,16 @@ JSLinearString* js::temporal::ParseTemporalCalendarString( return nullptr; } - // Steps 1-3. + // Steps 1 and 3.a. auto parseResult = ::ParseTemporalCalendarString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "calendar"); return nullptr; } ZonedDateTimeString parsed = parseResult.unwrap(); - PlainDateTime unused; + ISODateTime unused; if (!ParseISODateTime(cx, parsed, &unused)) { return nullptr; } @@ -2830,25 +2590,34 @@ JSLinearString* js::temporal::ParseTemporalCalendarString( template mozilla::Result TemporalParser::parseTemporalTimeString() { + MOZ_TRY(nonempty()); + // TemporalTimeString ::: // AnnotatedTime - // AnnotatedDateTimeTimeRequired + // AnnotatedDateTime[~Zoned, +TimeRequired] - if (auto time = annotatedTime(); time.isOk() && reader_.atEnd()) { - return time.unwrap(); + LikelyError likelyError{}; + + auto time = parse(annotatedTime()); + if (time.isOk()) { + return time; } + likelyError.update(time, reader_.index()); // Reset and try the next option. reader_.reset(); - auto dt = annotatedDateTimeTimeRequired(); - if (dt.isErr()) { - return dt.propagateErr(); + auto dateTime = parse(annotatedDateTimeTimeRequired()); + if (dateTime.isOk()) { + return dateTime; } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return dt.unwrap(); + likelyError.update(time, reader_.index()); + + // Set current index to the likely error index to give better error messages + // when called from parserTemporal{Calendar,TimeZone}String. + reader_.reset(likelyError.index()); + + return likelyError.propagate(); } /** @@ -2875,7 +2644,7 @@ static auto ParseTemporalTimeString(Handle str) { * ParseTemporalTimeString ( isoString ) */ bool js::temporal::ParseTemporalTimeString(JSContext* cx, Handle str, - PlainTime* result) { + Time* result) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { return false; @@ -2885,25 +2654,21 @@ bool js::temporal::ParseTemporalTimeString(JSContext* cx, Handle str, auto parseResult = ::ParseTemporalTimeString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "time"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); // Step 3. - if (parsed.timeZone.isUTC()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR); - return false; - } - - // Step 4. - PlainDateTime dateTime; + ISODateTime dateTime; if (!ParseISODateTime(cx, parsed, &dateTime)) { return false; } *result = dateTime.time; + // Step 4. + MOZ_ASSERT(!parsed.startOfDay); + // Step 5. return true; } @@ -2911,11 +2676,16 @@ bool js::temporal::ParseTemporalTimeString(JSContext* cx, Handle str, template mozilla::Result TemporalParser::parseTemporalMonthDayString() { + MOZ_TRY(nonempty()); + // TemporalMonthDayString ::: // AnnotatedMonthDay - // AnnotatedDateTime[~Zoned] + // AnnotatedDateTime[~Zoned, ~TimeRequired] - if (auto monthDay = annotatedMonthDay(); monthDay.isOk() && reader_.atEnd()) { + LikelyError likelyError{}; + + auto monthDay = parse(annotatedMonthDay()); + if (monthDay.isOk()) { auto result = monthDay.unwrap(); // ParseISODateTime, step 3. @@ -2925,18 +2695,22 @@ TemporalParser::parseTemporalMonthDayString() { } return result; } + likelyError.update(monthDay, reader_.index()); // Reset and try the next option. reader_.reset(); - auto dt = annotatedDateTime(); - if (dt.isErr()) { - return dt.propagateErr(); + auto dateTime = parse(annotatedDateTime()); + if (dateTime.isOk()) { + return dateTime; } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return dt.unwrap(); + likelyError.update(dateTime, reader_.index()); + + // Set current index to the likely error index to give better error messages + // when called from parserTemporal{Calendar,TimeZone}String. + reader_.reset(likelyError.index()); + + return likelyError.propagate(); } /** @@ -2963,37 +2737,30 @@ static auto ParseTemporalMonthDayString(Handle str) { * ParseTemporalMonthDayString ( isoString ) */ bool js::temporal::ParseTemporalMonthDayString( - JSContext* cx, Handle str, PlainDate* result, bool* hasYear, + JSContext* cx, Handle str, ISODate* result, bool* hasYear, MutableHandle calendar) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { return false; } - // Steps 1-2 . + // Steps 1-2. auto parseResult = ::ParseTemporalMonthDayString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "month-day"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); // Step 3. - if (parsed.timeZone.isUTC()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR); - return false; - } - - // Step 4. - PlainDateTime dateTime; + ISODateTime dateTime; if (!ParseISODateTime(cx, parsed, &dateTime)) { return false; } *result = dateTime.date; - // Steps 5-6. + // Steps 4-5. *hasYear = parsed.date.year != AbsentYear; if (parsed.calendar.present()) { @@ -3003,19 +2770,23 @@ bool js::temporal::ParseTemporalMonthDayString( } } - // Step 7. + // Step 6. return true; } template mozilla::Result TemporalParser::parseTemporalYearMonthString() { + MOZ_TRY(nonempty()); + // TemporalYearMonthString ::: // AnnotatedYearMonth - // AnnotatedDateTime[~Zoned] + // AnnotatedDateTime[~Zoned, ~TimeRequired] - if (auto yearMonth = annotatedYearMonth(); - yearMonth.isOk() && reader_.atEnd()) { + LikelyError likelyError{}; + + auto yearMonth = parse(annotatedYearMonth()); + if (yearMonth.isOk()) { auto result = yearMonth.unwrap(); // ParseISODateTime, step 3. @@ -3026,18 +2797,22 @@ TemporalParser::parseTemporalYearMonthString() { } return result; } + likelyError.update(yearMonth, reader_.index()); // Reset and try the next option. reader_.reset(); - auto dt = annotatedDateTime(); - if (dt.isErr()) { - return dt.propagateErr(); + auto dateTime = parse(annotatedDateTime()); + if (dateTime.isOk()) { + return dateTime; } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return dt.unwrap(); + likelyError.update(dateTime, reader_.index()); + + // Set current index to the likely error index to give better error messages + // when called from parserTemporal{Calendar,TimeZone}String. + reader_.reset(likelyError.index()); + + return likelyError.propagate(); } /** @@ -3064,7 +2839,7 @@ static auto ParseTemporalYearMonthString(Handle str) { * ParseTemporalYearMonthString ( isoString ) */ bool js::temporal::ParseTemporalYearMonthString( - JSContext* cx, Handle str, PlainDate* result, + JSContext* cx, Handle str, ISODate* result, MutableHandle calendar) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { @@ -3075,20 +2850,13 @@ bool js::temporal::ParseTemporalYearMonthString( auto parseResult = ::ParseTemporalYearMonthString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "year-month"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); // Step 3. - if (parsed.timeZone.isUTC()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR); - return false; - } - - // Step 4. - PlainDateTime dateTime; + ISODateTime dateTime; if (!ParseISODateTime(cx, parsed, &dateTime)) { return false; } @@ -3101,24 +2869,18 @@ bool js::temporal::ParseTemporalYearMonthString( } } - // Step 5. return true; } template mozilla::Result TemporalParser::parseTemporalDateTimeString() { - // TemporalDateTimeString[Zoned] ::: - // AnnotatedDateTime[?Zoned] + MOZ_TRY(nonempty()); - auto dateTime = annotatedDateTime(); - if (dateTime.isErr()) { - return dateTime.propagateErr(); - } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - return dateTime.unwrap(); + // TemporalDateTimeString[Zoned] ::: + // AnnotatedDateTime[?Zoned, ~TimeRequired] + + return parse(annotatedDateTime()); } /** @@ -3145,7 +2907,7 @@ static auto ParseTemporalDateTimeString(Handle str) { * ParseTemporalDateTimeString ( isoString ) */ bool js::temporal::ParseTemporalDateTimeString( - JSContext* cx, Handle str, PlainDateTime* result, + JSContext* cx, Handle str, ISODateTime* result, MutableHandle calendar) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { @@ -3156,19 +2918,12 @@ bool js::temporal::ParseTemporalDateTimeString( auto parseResult = ::ParseTemporalDateTimeString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "date-time"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); // Step 3. - if (parsed.timeZone.isUTC()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR); - return false; - } - - // Step 4. if (!ParseISODateTime(cx, parsed, result)) { return false; } @@ -3183,60 +2938,31 @@ bool js::temporal::ParseTemporalDateTimeString( return true; } -/** - * ParseTemporalDateString ( isoString ) - */ -bool js::temporal::ParseTemporalDateString(JSContext* cx, Handle str, - PlainDate* result, - MutableHandle calendar) { - // Step 1. - PlainDateTime dateTime; - if (!ParseTemporalDateTimeString(cx, str, &dateTime, calendar)) { - return false; - } - - // Step 2. - *result = dateTime.date; - return true; -} - template mozilla::Result TemporalParser::parseTemporalZonedDateTimeString() { + MOZ_TRY(nonempty()); + // Parse goal: TemporalDateTimeString[+Zoned] // // TemporalDateTimeString[Zoned] ::: - // AnnotatedDateTime[?Zoned] + // AnnotatedDateTime[?Zoned, ~TimeRequired] // - // AnnotatedDateTime[Zoned] ::: - // [~Zoned] DateTime TimeZoneAnnotation? Annotations? - // [+Zoned] DateTime TimeZoneAnnotation Annotations? + // AnnotatedDateTime[Zoned, TimeRequired] ::: + // [~Zoned] DateTime[~Z, ?TimeRequired] TimeZoneAnnotation? Annotations? + // [+Zoned] DateTime[+Z, ?TimeRequired] TimeZoneAnnotation Annotations? - auto dt = dateTime(); - if (dt.isErr()) { - return dt.propagateErr(); - } - auto result = dt.unwrap(); + ZonedDateTimeString result{}; - auto annotation = timeZoneAnnotation(); - if (annotation.isErr()) { - return annotation.propagateErr(); - } - result.timeZone.annotation = annotation.unwrap(); + MOZ_TRY_VAR(result, dateTime(/* allowZ = */ true)); + + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); if (hasAnnotationStart()) { - auto cal = annotations(); - if (cal.isErr()) { - return cal.propagateErr(); - } - result.calendar = cal.unwrap(); + MOZ_TRY_VAR(result.calendar, annotations()); } - if (!reader_.atEnd()) { - return mozilla::Err(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT); - } - - return result; + return complete(result); } /** @@ -3263,10 +2989,8 @@ static auto ParseTemporalZonedDateTimeString(Handle str) { * ParseTemporalZonedDateTimeString ( isoString ) */ bool js::temporal::ParseTemporalZonedDateTimeString( - JSContext* cx, Handle str, PlainDateTime* dateTime, bool* isUTC, - bool* hasOffset, int64_t* timeZoneOffset, - MutableHandle timeZoneAnnotation, - MutableHandle calendar) { + JSContext* cx, Handle str, + JS::MutableHandle result) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { return false; @@ -3276,17 +3000,34 @@ bool js::temporal::ParseTemporalZonedDateTimeString( auto parseResult = ::ParseTemporalZonedDateTimeString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "zoned date-time"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); - // Step 2. (ParseISODateTime, steps 1-18.) - if (!ParseISODateTime(cx, parsed, dateTime)) { + // Step 2. (ParseISODateTime, steps 2-3.) + Rooted calendar(cx); + if (parsed.calendar.present()) { + calendar = ToString(cx, linear, parsed.calendar); + if (!calendar) { + return false; + } + } + + // Step 2. (ParseISODateTime, steps 4-21.) + ISODateTime dateTime; + if (!ParseISODateTime(cx, parsed, &dateTime)) { return false; } - // Step 2. (ParseISODateTime, steps 19-21.) + // Step 2. (ParseISODateTime, steps 22-23.) + bool isStartOfDay = parsed.startOfDay; + + // Step 2. (ParseISODateTime, steps 24-27.) + bool isUTC; + bool hasOffset; + int64_t timeZoneOffset; + Rooted timeZoneAnnotation(cx); { MOZ_ASSERT(parsed.timeZone.hasAnnotation()); @@ -3309,44 +3050,75 @@ bool js::temporal::ParseTemporalZonedDateTimeString( // { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: "Europe/Berlin" } const auto& annotation = parsed.timeZone.annotation; - if (!ParseTimeZoneAnnotation(cx, annotation, linear, timeZoneAnnotation)) { + if (!ParseTimeZoneAnnotation(cx, annotation, linear, &timeZoneAnnotation)) { return false; } if (parsed.timeZone.isUTC()) { - *isUTC = true; - *hasOffset = false; - *timeZoneOffset = 0; + isUTC = true; + hasOffset = false; + timeZoneOffset = 0; } else if (parsed.timeZone.hasOffset()) { - *isUTC = false; - *hasOffset = true; - *timeZoneOffset = ParseDateTimeUTCOffset(parsed.timeZone.offset); + isUTC = false; + hasOffset = true; + timeZoneOffset = ParseDateTimeUTCOffset(parsed.timeZone.offset); } else { - *isUTC = false; - *hasOffset = false; - *timeZoneOffset = 0; + isUTC = false; + hasOffset = false; + timeZoneOffset = 0; } } - // Step 2. (ParseISODateTime, steps 23-24.) - if (parsed.calendar.present()) { - calendar.set(ToString(cx, linear, parsed.calendar)); - if (!calendar) { - return false; - } - } - - // Step 2. (ParseISODateTime, step 25.) + // Step 2. (ParseISODateTime, step 28.) + result.set(ParsedZonedDateTime{ + dateTime, + calendar, + timeZoneAnnotation.get(), + timeZoneOffset, + isUTC, + hasOffset, + isStartOfDay, + }); return true; } +template +mozilla::Result +TemporalParser::parseTemporalRelativeToString() { + MOZ_TRY(nonempty()); + + // Parse goals: + // TemporalDateTimeString[+Zoned] and TemporalDateTimeString[~Zoned] + // + // TemporalDateTimeString[Zoned] ::: + // AnnotatedDateTime[?Zoned, ~TimeRequired] + // + // AnnotatedDateTime[Zoned, TimeRequired] ::: + // [~Zoned] DateTime[~Z, ?TimeRequired] TimeZoneAnnotation? Annotations? + // [+Zoned] DateTime[+Z, ?TimeRequired] TimeZoneAnnotation Annotations? + + ZonedDateTimeString result{}; + + MOZ_TRY_VAR(result, dateTime(/* allowZ = */ true)); + + if (hasTimeZoneAnnotationStart()) { + MOZ_TRY_VAR(result.timeZone.annotation, timeZoneAnnotation()); + } + + if (hasAnnotationStart()) { + MOZ_TRY_VAR(result.calendar, annotations()); + } + + return complete(result); +} + /** * ParseTemporalRelativeToString ( isoString ) */ template static auto ParseTemporalRelativeToString(mozilla::Span str) { TemporalParser parser(str); - return parser.parseTemporalDateTimeString(); + return parser.parseTemporalRelativeToString(); } /** @@ -3364,10 +3136,8 @@ static auto ParseTemporalRelativeToString(Handle str) { * ParseTemporalRelativeToString ( isoString ) */ bool js::temporal::ParseTemporalRelativeToString( - JSContext* cx, Handle str, PlainDateTime* dateTime, bool* isUTC, - bool* hasOffset, int64_t* timeZoneOffset, - MutableHandle timeZoneAnnotation, - MutableHandle calendar) { + JSContext* cx, Handle str, + MutableHandle result) { Rooted linear(cx, str->ensureLinear(cx)); if (!linear) { return false; @@ -3377,7 +3147,7 @@ bool js::temporal::ParseTemporalRelativeToString( auto parseResult = ::ParseTemporalRelativeToString(linear); if (parseResult.isErr()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - parseResult.unwrapErr()); + parseResult.unwrapErr(), "relative date-time"); return false; } ZonedDateTimeString parsed = parseResult.unwrap(); @@ -3386,16 +3156,23 @@ bool js::temporal::ParseTemporalRelativeToString( if (parsed.timeZone.isUTC() && !parsed.timeZone.hasAnnotation()) { JS_ReportErrorNumberASCII( cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME); + JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME, + "relative date-time"); return false; } // Step 4. (ParseISODateTime, steps 1-18.) - if (!ParseISODateTime(cx, parsed, dateTime)) { + ISODateTime dateTime; + if (!ParseISODateTime(cx, parsed, &dateTime)) { return false; } + bool isStartOfDay = parsed.startOfDay; // Step 4. (ParseISODateTime, steps 19-22.) + bool isUTC; + bool hasOffset; + int64_t timeZoneOffset; + Rooted timeZoneAnnotation(cx); if (parsed.timeZone.hasAnnotation()) { // Case 1: 19700101Z[+02:00] // { [[Z]]: true, [[OffsetString]]: undefined, [[Name]]: "+02:00" } @@ -3416,45 +3193,60 @@ bool js::temporal::ParseTemporalRelativeToString( // { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: "Europe/Berlin" } const auto& annotation = parsed.timeZone.annotation; - if (!ParseTimeZoneAnnotation(cx, annotation, linear, timeZoneAnnotation)) { + if (!ParseTimeZoneAnnotation(cx, annotation, linear, &timeZoneAnnotation)) { return false; } if (parsed.timeZone.isUTC()) { - *isUTC = true; - *hasOffset = false; - *timeZoneOffset = 0; + isUTC = true; + hasOffset = false; + timeZoneOffset = 0; } else if (parsed.timeZone.hasOffset()) { - *isUTC = false; - *hasOffset = true; - *timeZoneOffset = ParseDateTimeUTCOffset(parsed.timeZone.offset); + isUTC = false; + hasOffset = true; + timeZoneOffset = ParseDateTimeUTCOffset(parsed.timeZone.offset); } else { - *isUTC = false; - *hasOffset = false; - *timeZoneOffset = 0; + isUTC = false; + hasOffset = false; + timeZoneOffset = 0; } } else { // GetTemporalRelativeToOption ignores any other time zone information when // no bracketed time zone annotation is present. - *isUTC = false; - *hasOffset = false; - *timeZoneOffset = 0; + isUTC = false; + hasOffset = false; + timeZoneOffset = 0; timeZoneAnnotation.set(ParsedTimeZone{}); } // Step 4. (ParseISODateTime, steps 23-24.) + JSLinearString* calendar = nullptr; if (parsed.calendar.present()) { - calendar.set(ToString(cx, linear, parsed.calendar)); + calendar = ToString(cx, linear, parsed.calendar); if (!calendar) { return false; } } // Step 4. (Return) + result.set(ParsedZonedDateTime{ + dateTime, + calendar, + timeZoneAnnotation.get(), + timeZoneOffset, + isUTC, + hasOffset, + isStartOfDay, + }); return true; } void js::temporal::ParsedTimeZone::trace(JSTracer* trc) { TraceNullableRoot(trc, &name, "ParsedTimeZone::name"); } + +void js::temporal::ParsedZonedDateTime::trace(JSTracer* trc) { + TraceNullableRoot(trc, &calendar, "ParsedZonedDateTime::calendar"); + timeZoneAnnotation.trace(trc); +} diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.h index 86ac7bbd82f..35d783f1d3c 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalParser.h @@ -13,6 +13,7 @@ #include #include +#include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "js/RootingAPI.h" #include "js/TypeDecls.h" @@ -22,11 +23,6 @@ class JS_PUBLIC_API JSTracer; namespace js::temporal { -struct Duration; -struct PlainDate; -struct PlainDateTime; -struct PlainTime; - struct MOZ_STACK_CLASS ParsedTimeZone final { JSLinearString* name = nullptr; int32_t offset = INT32_MIN; @@ -48,11 +44,23 @@ struct MOZ_STACK_CLASS ParsedTimeZone final { } }; +struct MOZ_STACK_CLASS ParsedZonedDateTime final { + ISODateTime dateTime = {}; + JSLinearString* calendar = nullptr; + ParsedTimeZone timeZoneAnnotation{}; + int64_t timeZoneOffset = 0; + bool isUTC = false; + bool hasOffset = false; + bool isStartOfDay = false; + + void trace(JSTracer* trc); +}; + /** * ParseTemporalInstantString ( isoString ) */ bool ParseTemporalInstantString(JSContext* cx, JS::Handle str, - PlainDateTime* result, int64_t* offset); + ISODateTime* result, int64_t* offset); /** * ParseTemporalTimeZoneString ( timeZoneString ) @@ -66,12 +74,6 @@ bool ParseTemporalTimeZoneString(JSContext* cx, JS::Handle str, bool ParseTimeZoneIdentifier(JSContext* cx, JS::Handle str, JS::MutableHandle result); -/** - * ParseTimeZoneOffsetString ( isoString ) - */ -bool ParseTimeZoneOffsetString(JSContext* cx, JS::Handle str, - int32_t* result); - /** * ParseDateTimeUTCOffset ( offsetString ) */ @@ -94,53 +96,42 @@ JSLinearString* ParseTemporalCalendarString(JSContext* cx, * ParseTemporalTimeString ( isoString ) */ bool ParseTemporalTimeString(JSContext* cx, JS::Handle str, - PlainTime* result); - -/** - * ParseTemporalDateString ( isoString ) - */ -bool ParseTemporalDateString(JSContext* cx, JS::Handle str, - PlainDate* result, - JS::MutableHandle calendar); + Time* result); /** * ParseTemporalMonthDayString ( isoString ) */ bool ParseTemporalMonthDayString(JSContext* cx, JS::Handle str, - PlainDate* result, bool* hasYear, + ISODate* result, bool* hasYear, JS::MutableHandle calendar); /** * ParseTemporalYearMonthString ( isoString ) */ bool ParseTemporalYearMonthString(JSContext* cx, JS::Handle str, - PlainDate* result, + ISODate* result, JS::MutableHandle calendar); /** * ParseTemporalDateTimeString ( isoString ) */ bool ParseTemporalDateTimeString(JSContext* cx, JS::Handle str, - PlainDateTime* result, + ISODateTime* result, JS::MutableHandle calendar); /** * ParseTemporalZonedDateTimeString ( isoString ) */ bool ParseTemporalZonedDateTimeString( - JSContext* cx, JS::Handle str, PlainDateTime* dateTime, - bool* isUTC, bool* hasOffset, int64_t* timeZoneOffset, - JS::MutableHandle timeZoneAnnotation, - JS::MutableHandle calendar); + JSContext* cx, JS::Handle str, + JS::MutableHandle result); /** * ParseTemporalRelativeToString ( isoString ) */ bool ParseTemporalRelativeToString( - JSContext* cx, JS::Handle str, PlainDateTime* dateTime, - bool* isUTC, bool* hasOffset, int64_t* timeZoneOffset, - JS::MutableHandle timeZoneAnnotation, - JS::MutableHandle calendar); + JSContext* cx, JS::Handle str, + JS::MutableHandle result); } /* namespace js::temporal */ @@ -162,6 +153,33 @@ class WrappedPtrOperations { explicit operator bool() const { return bool(object()); } }; +template +class WrappedPtrOperations { + const auto& object() const { + return static_cast(this)->get(); + } + + public: + const temporal::ISODateTime& dateTime() const { return object().dateTime; } + + JS::Handle calendar() const { + return JS::Handle::fromMarkedLocation(&object().calendar); + } + + JS::Handle timeZoneAnnotation() const { + return JS::Handle::fromMarkedLocation( + &object().timeZoneAnnotation); + } + + int64_t timeZoneOffset() const { return object().timeZoneOffset; } + + bool isUTC() const { return object().isUTC; } + + bool hasOffset() const { return object().hasOffset; } + + bool isStartOfDay() const { return object().isStartOfDay; } +}; + } /* namespace js */ #endif /* builtin_temporal_TemporalParser_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalTypes.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalTypes.h index 84080c93688..0f36a5a2117 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalTypes.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/TemporalTypes.h @@ -10,8 +10,12 @@ #include "mozilla/Assertions.h" #include "mozilla/CheckedInt.h" +#include #include #include +#include + +#include "jstypes.h" #include "builtin/temporal/Int128.h" #include "builtin/temporal/TemporalUnit.h" @@ -54,8 +58,9 @@ struct SecondsAndNanoseconds { } constexpr bool operator<(const SecondsAndNanoseconds& other) const { - // The compiler can optimize expressions like |instant < Instant{}| to a - // single right-shift operation when we propagate the range of nanoseconds. + // The compiler can optimize expressions like |epochNs < EpochNanoseconds{}| + // to a single right-shift operation when we propagate the range of + // nanoseconds. JS_ASSUME(nanoseconds >= 0); JS_ASSUME(other.nanoseconds >= 0); return (seconds < other.seconds) || @@ -96,7 +101,7 @@ struct SecondsAndNanoseconds { } MOZ_ASSERT(0 <= nanos.value() && nanos.value() < 1'000'000'000); - return {secs.value(), nanos.value()}; + return {{secs.value(), nanos.value()}}; } template @@ -118,7 +123,7 @@ struct SecondsAndNanoseconds { } MOZ_ASSERT(0 <= nanos.value() && nanos.value() < 1'000'000'000); - return {secs.value(), nanos.value()}; + return {{secs.value(), nanos.value()}}; } static constexpr Derived negate(const Derived& self) { @@ -127,58 +132,56 @@ struct SecondsAndNanoseconds { public: /** - * Return the absolute value. + * Denormalize the seconds and nanoseconds components. + * + * Negative nanoseconds are represented as the difference to 1'000'000'000. + * Convert these back to their absolute value and adjust the seconds part + * accordingly. + * + * For example the nanoseconds duration `-1n` is represented as the duration + * `{seconds: -1, nanoseconds: 999'999'999}`. */ - constexpr Derived abs() const { + constexpr std::pair denormalize() const { int64_t sec = seconds; int32_t nanos = nanoseconds; - if (sec < 0) { - if (nanos > 0) { - sec += 1; - nanos -= 1'000'000'000; - } - sec = -sec; - nanos = -nanos; + if (sec < 0 && nanos > 0) { + sec += 1; + nanos -= 1'000'000'000; } return {sec, nanos}; } /** - * Return the seconds value, rounded towards zero. + * Return the absolute value. */ - constexpr int64_t toSeconds() const { - int64_t sec = seconds; - int32_t nanos = nanoseconds; - if (sec < 0 && nanos > 0) { - sec += 1; - } - return sec; + constexpr Derived abs() const { + auto [sec, nanos] = denormalize(); + return {{std::abs(sec), std::abs(nanos)}}; + } + + /** + * Return the 24-hour days value, rounded towards zero. + */ + constexpr int64_t toDays() const { + auto [sec, nanos] = denormalize(); + return sec / ToSeconds(TemporalUnit::Day); } /** * Return the milliseconds value, rounded towards zero. */ constexpr int64_t toMilliseconds() const { - int64_t sec = seconds; - int32_t nanos = nanoseconds; - if (sec < 0 && nanos > 0) { - sec += 1; - nanos -= 1'000'000'000; - } + auto [sec, nanos] = denormalize(); return (sec * 1'000) + (nanos / 1'000'000); } /** * Return the microseconds value, rounded towards zero. */ - constexpr int64_t toMicroseconds() const { - int64_t sec = seconds; - int32_t nanos = nanoseconds; - if (sec < 0 && nanos > 0) { - sec += 1; - nanos -= 1'000'000'000; - } - return (sec * 1'000'000) + (nanos / 1'000); + constexpr Int128 toMicroseconds() const { + auto [sec, nanos] = denormalize(); + return Int128{sec} * Int128{ToMicroseconds(TemporalUnit::Second)} + + Int128{nanos / 1'000}; } /** @@ -195,21 +198,23 @@ struct SecondsAndNanoseconds { template constexpr Other to() const { static_assert(std::is_base_of_v, Other>); - return Other{seconds, nanoseconds}; + return Other{{seconds, nanoseconds}}; + } + + /** + * Create from a days value. + */ + static constexpr Derived fromDays(int64_t days) { + return {{days * ToSeconds(TemporalUnit::Day), 0}}; } /** * Create from a minutes value. */ static constexpr Derived fromMinutes(int64_t minutes) { - return {minutes * 60, 0}; + return {{minutes * ToSeconds(TemporalUnit::Minute), 0}}; } - /** - * Create from a seconds value. - */ - static constexpr Derived fromSeconds(int64_t seconds) { return {seconds, 0}; } - /** * Create from a milliseconds value. */ @@ -220,20 +225,7 @@ struct SecondsAndNanoseconds { seconds -= 1; millis += 1'000; } - return {seconds, millis * 1'000'000}; - } - - /** - * Create from a microseconds value. - */ - static constexpr Derived fromMicroseconds(int64_t microseconds) { - int64_t seconds = microseconds / 1'000'000; - int32_t micros = int32_t(microseconds % 1'000'000); - if (micros < 0) { - seconds -= 1; - micros += 1'000'000; - } - return {seconds, micros * 1'000}; + return {{seconds, millis * 1'000'000}}; } /** @@ -246,7 +238,7 @@ struct SecondsAndNanoseconds { seconds -= 1; nanos += 1'000'000'000; } - return {seconds, nanos}; + return {{seconds, nanos}}; } /** @@ -260,129 +252,123 @@ struct SecondsAndNanoseconds { seconds -= 1; nanos += 1'000'000'000; } - return {seconds, nanos}; + return {{seconds, nanos}}; } }; #undef JS_ASSUME /** - * InstantSpan represents a span of time between two Instants, measured in - * nanoseconds. + * EpochDuration represents a duration of time between two epoch nanoseconds, + * measured in nanoseconds. */ -struct InstantSpan final : SecondsAndNanoseconds { - constexpr InstantSpan& operator+=(const InstantSpan& other) { +struct EpochDuration final : SecondsAndNanoseconds { + constexpr EpochDuration& operator+=(const EpochDuration& other) { *this = add(*this, other); return *this; } - constexpr InstantSpan& operator-=(const InstantSpan& other) { + constexpr EpochDuration& operator-=(const EpochDuration& other) { *this = subtract(*this, other); return *this; } - constexpr InstantSpan operator+(const InstantSpan& other) const { + constexpr EpochDuration operator+(const EpochDuration& other) const { return add(*this, other); } - constexpr InstantSpan operator-(const InstantSpan& other) const { + constexpr EpochDuration operator-(const EpochDuration& other) const { return subtract(*this, other); } - constexpr InstantSpan operator-() const { return negate(*this); } + constexpr EpochDuration operator-() const { return negate(*this); } /** - * Returns the maximum instant span value. + * Returns the maximum epoch duration value. */ - static constexpr InstantSpan max() { + static constexpr EpochDuration max() { // The limit is 2×8.64 × 10^21 nanoseconds, which is 2×8.64 × 10^12 seconds. constexpr int64_t seconds = 2 * 8'640'000'000'000; constexpr int64_t nanos = 0; - return {seconds, nanos}; + return {{seconds, nanos}}; } /** - * Returns the minimum instant span value. + * Returns the minimum epoch duration value. */ - static constexpr InstantSpan min() { return -max(); } + static constexpr EpochDuration min() { return -max(); } }; /** - * Instant represents a time since the epoch value, measured in nanoseconds. + * EpochNanoseconds represents a time since the epoch value, measured in + * nanoseconds. * - * Instant supports a range of ±8.64 × 10^21 nanoseconds, covering ±10^8 days - * in either direction relative to midnight at the beginning of 1 January 1970 - * UTC. The range also exactly matches the supported range of JavaScript Date + * EpochNanoseconds supports a range of ±8.64 × 10^21 nanoseconds, covering + * ±10^8 days in either direction relative to midnight at the beginning of + * 1 January 1970 UTC. This matches the range supported by JavaScript Date * objects. * * C++ doesn't provide a built-in type capable of storing an integer in the * range ±8.64 × 10^21, therefore we need to create our own abstraction. This - * struct follows the design of `std::timespec` and splits the instant into a - * signed seconds part and an unsigned nanoseconds part. + * struct follows the design of `std::timespec` and splits the epoch nanoseconds + * into a signed seconds part and an unsigned nanoseconds part. */ -struct Instant final : SecondsAndNanoseconds { - constexpr Instant& operator+=(const InstantSpan& other) { +struct EpochNanoseconds final : SecondsAndNanoseconds { + constexpr EpochNanoseconds& operator+=(const EpochDuration& other) { *this = add(*this, other); return *this; } - constexpr Instant& operator-=(const InstantSpan& other) { + constexpr EpochNanoseconds& operator-=(const EpochDuration& other) { *this = subtract(*this, other); return *this; } - constexpr Instant operator+(const InstantSpan& other) const { + constexpr EpochNanoseconds operator+(const EpochDuration& other) const { return add(*this, other); } - constexpr Instant operator-(const InstantSpan& other) const { + constexpr EpochNanoseconds operator-(const EpochDuration& other) const { return subtract(*this, other); } - constexpr InstantSpan operator-(const Instant& other) const { - return subtract(*this, other); + constexpr EpochDuration operator-(const EpochNanoseconds& other) const { + return subtract(*this, + other); } - constexpr Instant operator-() const { return negate(*this); } + constexpr EpochNanoseconds operator-() const { return negate(*this); } /** - * Return this instant as microseconds from the start of the epoch. (Rounds - * towards negative infinity.) - */ - constexpr int64_t floorToMicroseconds() const { - return (seconds * 1'000'000) + (nanoseconds / 1'000); - } - - /** - * Return this instant as milliseconds from the start of the epoch. (Rounds - * towards negative infinity.) + * Return this epoch nanoseconds as milliseconds from the start of the epoch. + * (Rounds towards negative infinity.) */ constexpr int64_t floorToMilliseconds() const { return (seconds * 1'000) + (nanoseconds / 1'000'000); } /** - * Return this instant as milliseconds from the start of the epoch. (Rounds - * towards positive infinity.) + * Return this epoch nanoseconds as milliseconds from the start of the epoch. + * (Rounds towards positive infinity.) */ constexpr int64_t ceilToMilliseconds() const { return floorToMilliseconds() + int64_t(nanoseconds % 1'000'000 != 0); } /** - * Returns the maximum instant value. + * Returns the maximum epoch nanoseconds value. */ - static constexpr Instant max() { + static constexpr EpochNanoseconds max() { // The limit is 8.64 × 10^21 nanoseconds, which is 8.64 × 10^12 seconds. constexpr int64_t seconds = 8'640'000'000'000; constexpr int64_t nanos = 0; - return {seconds, nanos}; + return {{seconds, nanos}}; } /** - * Returns the minimum instant value. + * Returns the minimum epoch nanoseconds value. */ - static constexpr Instant min() { return -max(); } + static constexpr EpochNanoseconds min() { return -max(); } }; // Minimum and maximum valid epoch day relative to midnight at the beginning of @@ -404,17 +390,18 @@ constexpr inline int32_t MinEpochDay = -100'000'001; constexpr inline int32_t MaxEpochDay = 100'000'000; static_assert(MinEpochDay == - Instant::min().seconds / ToSeconds(TemporalUnit::Day) - 1); + EpochNanoseconds::min().seconds / ToSeconds(TemporalUnit::Day) - + 1); static_assert(MaxEpochDay == - Instant::max().seconds / ToSeconds(TemporalUnit::Day)); + EpochNanoseconds::max().seconds / ToSeconds(TemporalUnit::Day)); // Maximum number of days between two valid epoch days. constexpr inline int32_t MaxEpochDaysDuration = MaxEpochDay - MinEpochDay; /** - * Plain date represents a date in the ISO 8601 calendar. + * ISODate represents a date in the ISO 8601 calendar. */ -struct PlainDate final { +struct ISODate final { // [-271821, 275760] // // Dates are limited to the range of ±100'000'000 days relative to midnight at @@ -428,18 +415,50 @@ struct PlainDate final { // [1, 31] int32_t day = 0; - bool operator==(const PlainDate& other) const { + constexpr bool operator==(const ISODate& other) const { return year == other.year && month == other.month && day == other.day; } - bool operator!=(const PlainDate& other) const { return !(*this == other); } + constexpr bool operator!=(const ISODate& other) const { + return !(*this == other); + } + + constexpr bool operator<(const ISODate& other) const { + if (year != other.year) { + return year < other.year; + } + if (month != other.month) { + return month < other.month; + } + return day < other.day; + } + + constexpr bool operator>(const ISODate& other) const { return other < *this; } + + constexpr bool operator<=(const ISODate& other) const { + return !(other < *this); + } + + constexpr bool operator>=(const ISODate& other) const { + return !(*this < other); + } + + /** + * The minimum ISODate within the valid limits is -271821 April, 19. + */ + static constexpr ISODate min() { return {-271821, 4, 19}; } + + /** + * The maximum ISODate within the valid limits is 275760 September, 13. + */ + static constexpr ISODate max() { return {275760, 9, 13}; } }; /** - * Plain time represents a time value on a 24-hour clock. Leap seconds aren't + * Time represents a time value on a 24-hour clock. Leap seconds aren't * supported. */ -struct PlainTime final { +struct Time final { // [0, 23] int32_t hour = 0; @@ -458,48 +477,180 @@ struct PlainTime final { // [0, 999] int32_t nanosecond = 0; - bool operator==(const PlainTime& other) const { + constexpr bool operator==(const Time& other) const { return hour == other.hour && minute == other.minute && second == other.second && millisecond == other.millisecond && microsecond == other.microsecond && nanosecond == other.nanosecond; } - bool operator!=(const PlainTime& other) const { return !(*this == other); } + constexpr bool operator!=(const Time& other) const { + return !(*this == other); + } + + constexpr bool operator<(const Time& other) const { + if (hour != other.hour) { + return hour < other.hour; + } + if (minute != other.minute) { + return minute < other.minute; + } + if (second != other.second) { + return second < other.second; + } + if (millisecond != other.millisecond) { + return millisecond < other.millisecond; + } + if (microsecond != other.microsecond) { + return microsecond < other.microsecond; + } + return nanosecond < other.nanosecond; + } + + constexpr bool operator>(const Time& other) const { return other < *this; } + + constexpr bool operator<=(const Time& other) const { + return !(other < *this); + } + + constexpr bool operator>=(const Time& other) const { + return !(*this < other); + } }; /** - * Plain date-time represents a date-time value in the ISO 8601 calendar. + * ISODateTime represents a date-time value in the ISO 8601 calendar. */ -struct PlainDateTime final { - PlainDate date; - PlainTime time; +struct ISODateTime final { + ISODate date; + Time time; - bool operator==(const PlainDateTime& other) const { + bool operator==(const ISODateTime& other) const { return date == other.date && time == other.time; } - bool operator!=(const PlainDateTime& other) const { - return !(*this == other); + bool operator!=(const ISODateTime& other) const { return !(*this == other); } + + constexpr bool operator<(const ISODateTime& other) const { + if (date != other.date) { + return date < other.date; + } + return time < other.time; + } + + constexpr bool operator>(const ISODateTime& other) const { + return other < *this; + } + + constexpr bool operator<=(const ISODateTime& other) const { + return !(other < *this); + } + + constexpr bool operator>=(const ISODateTime& other) const { + return !(*this < other); + } +}; + +// 32-bit packed date to store an ISO date within PrivateUint32Value. +struct PackedDate final { + static constexpr uint32_t DayBits = 8; + static constexpr uint32_t MonthBits = 4; + static constexpr uint32_t YearBits = 20; + + static constexpr uint32_t DayShift = 0; + static constexpr uint32_t MonthShift = DayShift + DayBits; + static constexpr uint32_t YearShift = MonthShift + MonthBits; + + uint32_t value = 0; + + static constexpr PackedDate pack(const ISODate& date) { + return {uint32_t((date.year << YearShift) | (date.month << MonthShift) | + (date.day << DayShift))}; + } + + static constexpr ISODate unpack(const PackedDate& date) { + return { + int32_t(date.value) >> YearShift, + int32_t((date.value >> MonthShift) & BitMask(MonthBits)), + int32_t((date.value >> DayShift) & BitMask(DayBits)), + }; + } +}; + +// 47-bit packed time to store a time within DoubleValue. +struct PackedTime final { + static constexpr uint32_t NanosecondBits = 10; + static constexpr uint32_t MicrosecondBits = 10; + static constexpr uint32_t MillisecondBits = 10; + static constexpr uint32_t SecondBits = 6; + static constexpr uint32_t MinuteBits = 6; + static constexpr uint32_t HourBits = 5; + + static constexpr uint32_t NanosecondShift = 0; + static constexpr uint32_t MicrosecondShift = NanosecondShift + NanosecondBits; + static constexpr uint32_t MillisecondShift = + MicrosecondShift + MicrosecondBits; + static constexpr uint32_t SecondShift = MillisecondShift + MillisecondBits; + static constexpr uint32_t MinuteShift = SecondShift + SecondBits; + static constexpr uint32_t HourShift = MinuteShift + MinuteBits; + + uint64_t value = 0; + + static constexpr PackedTime pack(const Time& time) { + return {uint64_t(time.hour) << HourShift | + uint64_t(time.minute) << MinuteShift | + uint64_t(time.second) << SecondShift | + uint64_t(time.millisecond) << MillisecondShift | + uint64_t(time.microsecond) << MicrosecondShift | + uint64_t(time.nanosecond) << NanosecondShift}; + } + + static constexpr Time unpack(const PackedTime& time) { + return { + int32_t((time.value >> HourShift) & BitMask(HourBits)), + int32_t((time.value >> MinuteShift) & BitMask(MinuteBits)), + int32_t((time.value >> SecondShift) & BitMask(SecondBits)), + int32_t((time.value >> MillisecondShift) & BitMask(MillisecondBits)), + int32_t((time.value >> MicrosecondShift) & BitMask(MicrosecondBits)), + int32_t((time.value >> NanosecondShift) & BitMask(NanosecondBits)), + }; } }; struct DateDuration; -struct TimeDuration; /** * Duration represents the difference between dates or times. Each duration * component is an integer and all components must have the same sign. */ struct Duration final { + // abs(years) < 2**32 double years = 0; + + // abs(months) < 2**32 double months = 0; + + // abs(weeks) < 2**32 double weeks = 0; + + // abs(days) < ⌈(2**53) / (24 * 60 * 60)⌉ double days = 0; + + // abs(hours) < ⌈(2**53) / (60 * 60)⌉ double hours = 0; + + // abs(minutes) < ⌈(2**53) / 60⌉ double minutes = 0; + + // abs(seconds) < (2**53) double seconds = 0; + + // abs(milliseconds) < (2**53) * (1000**1) double milliseconds = 0; + + // abs(microseconds) < (2**53) * (1000**2) double microseconds = 0; + + // abs(nanoseconds) < (2**53) * (1000**3) double nanoseconds = 0; constexpr bool operator==(const Duration& other) const { @@ -575,104 +726,59 @@ inline DateDuration Duration::toDateDuration() const { } /** - * Time duration represents the difference between times. Each duration - * component is an integer and all components must have the same sign. - */ -struct TimeDuration final { - // abs(days) < ⌈(2**53) / (24 * 60 * 60)⌉ - int64_t days = 0; - - // abs(hours) < ⌈(2**53) / (60 * 60)⌉ - int64_t hours = 0; - - // abs(minutes) < ⌈(2**53) / 60⌉ - int64_t minutes = 0; - - // abs(seconds) < (2**53) - int64_t seconds = 0; - - // abs(milliseconds) < (2**53) * (1000**1) - int64_t milliseconds = 0; - - // abs(microseconds) < (2**53) * (1000**2) - double microseconds = 0; - - // abs(nanoseconds) < (2**53) * (1000**3) - double nanoseconds = 0; - - constexpr Duration toDuration() const { - return {0, - 0, - 0, - double(days), - double(hours), - double(minutes), - double(seconds), - double(milliseconds), - microseconds, - nanoseconds}; - } -}; - -/** - * Normalized time duration with a seconds value in the range + * Time duration with a seconds value in the range * [-9'007'199'254'740'991, +9'007'199'254'740'991] and a nanoseconds value in * the range [0, 999'999'999]. */ -struct NormalizedTimeDuration final - : SecondsAndNanoseconds { - constexpr NormalizedTimeDuration& operator+=( - const NormalizedTimeDuration& other) { +struct TimeDuration final : SecondsAndNanoseconds { + constexpr TimeDuration& operator+=(const TimeDuration& other) { *this = add(*this, other); return *this; } - constexpr NormalizedTimeDuration& operator-=( - const NormalizedTimeDuration& other) { + constexpr TimeDuration& operator-=(const TimeDuration& other) { *this = subtract(*this, other); return *this; } - constexpr NormalizedTimeDuration operator+( - const NormalizedTimeDuration& other) const { + constexpr TimeDuration operator+(const TimeDuration& other) const { return add(*this, other); } - constexpr NormalizedTimeDuration operator-( - const NormalizedTimeDuration& other) const { + constexpr TimeDuration operator-(const TimeDuration& other) const { return subtract(*this, other); } - constexpr NormalizedTimeDuration operator-() const { return negate(*this); } + constexpr TimeDuration operator-() const { return negate(*this); } /** - * Returns the maximum normalized time duration value. + * Returns the maximum time duration value. */ - static constexpr NormalizedTimeDuration max() { + static constexpr TimeDuration max() { constexpr int64_t seconds = 0x1f'ffff'ffff'ffff; constexpr int64_t nanos = 999'999'999; - return {seconds, nanos}; + return {{seconds, nanos}}; } /** - * Returns the minimum normalized time duration value. + * Returns the minimum time duration value. */ - static constexpr NormalizedTimeDuration min() { return -max(); } + static constexpr TimeDuration min() { return -max(); } }; /** - * Duration represents the difference between dates or times. Each duration - * component is an integer and all components must have the same sign. + * Internal duration represents the difference between dates or times. Each + * duration component is an integer and all components must have the same sign. */ -struct NormalizedDuration final { +struct InternalDuration final { DateDuration date; - NormalizedTimeDuration time; + TimeDuration time; - constexpr bool operator==(const NormalizedDuration& other) const { + constexpr bool operator==(const InternalDuration& other) const { return date == other.date && time == other.time; } - constexpr bool operator!=(const NormalizedDuration& other) const { + constexpr bool operator!=(const InternalDuration& other) const { return !(*this == other); } }; diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.cpp index 6525eb1d9d6..b309c5c38bf 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.cpp @@ -6,7 +6,6 @@ #include "builtin/temporal/TimeZone.h" -#include "mozilla/Array.h" #include "mozilla/Assertions.h" #include "mozilla/intl/TimeZone.h" #include "mozilla/Likely.h" @@ -18,16 +17,14 @@ #include #include -#include #include +#include #include -#include "jsnum.h" -#include "jspubtd.h" +#include "jsdate.h" #include "jstypes.h" #include "NamespaceImports.h" -#include "builtin/Array.h" #include "builtin/intl/CommonFunctions.h" #include "builtin/intl/FormatBuffer.h" #include "builtin/intl/SharedIntlData.h" @@ -40,66 +37,120 @@ #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" -#include "builtin/temporal/Wrapped.h" #include "builtin/temporal/ZonedDateTime.h" -#include "gc/AllocKind.h" #include "gc/Barrier.h" #include "gc/GCContext.h" #include "gc/GCEnum.h" #include "gc/Tracer.h" #include "js/AllocPolicy.h" -#include "js/CallArgs.h" -#include "js/CallNonGenericMethod.h" #include "js/Class.h" -#include "js/ComparisonOperators.h" -#include "js/Date.h" #include "js/ErrorReport.h" -#include "js/ForOfIterator.h" #include "js/friend/ErrorMessages.h" #include "js/Printer.h" -#include "js/PropertyDescriptor.h" -#include "js/PropertySpec.h" #include "js/RootingAPI.h" #include "js/StableStringChars.h" -#include "threading/ProtectedData.h" -#include "vm/ArrayObject.h" #include "vm/BytecodeUtil.h" #include "vm/Compartment.h" #include "vm/DateTime.h" -#include "vm/GlobalObject.h" -#include "vm/Interpreter.h" #include "vm/JSAtomState.h" #include "vm/JSContext.h" #include "vm/JSObject.h" -#include "vm/PlainObject.h" #include "vm/Runtime.h" #include "vm/StringType.h" #include "vm/JSObject-inl.h" -#include "vm/NativeObject-inl.h" -#include "vm/ObjectOperations-inl.h" using namespace js; using namespace js::temporal; -static inline bool IsTimeZone(Handle v) { - return v.isObject() && v.toObject().is(); -} - void js::temporal::TimeZoneValue::trace(JSTracer* trc) { TraceNullableRoot(trc, &object_, "TimeZoneValue::object"); } -void js::temporal::TimeZoneRecord::trace(JSTracer* trc) { - receiver_.trace(trc); - TraceNullableRoot(trc, &getOffsetNanosecondsFor_, - "TimeZoneMethods::getOffsetNanosecondsFor"); - TraceNullableRoot(trc, &getPossibleInstantsFor_, - "TimeZoneMethods::getPossibleInstantsFor"); +/** + * FormatOffsetTimeZoneIdentifier ( offsetMinutes [ , style ] ) + */ +static JSLinearString* FormatOffsetTimeZoneIdentifier(JSContext* cx, + int32_t offsetMinutes) { + MOZ_ASSERT(std::abs(offsetMinutes) < UnitsPerDay(TemporalUnit::Minute)); + + // Step 1. + char sign = offsetMinutes >= 0 ? '+' : '-'; + + // Step 2. + int32_t absoluteMinutes = std::abs(offsetMinutes); + + // Step 3. + int32_t hour = absoluteMinutes / 60; + + // Step 4. + int32_t minute = absoluteMinutes % 60; + + // Step 5. (Inlined FormatTimeString). + // + // Format: "sign hour{2} : minute{2}" + char result[] = { + sign, char('0' + (hour / 10)), char('0' + (hour % 10)), + ':', char('0' + (minute / 10)), char('0' + (minute % 10)), + }; + + // Step 6. + return NewStringCopyN(cx, result, std::size(result)); +} + +static TimeZoneObject* CreateTimeZoneObject( + JSContext* cx, Handle identifier, + Handle primaryIdentifier) { + // TODO: Implement a built-in time zone object cache. + + auto* object = NewObjectWithGivenProto(cx, nullptr); + if (!object) { + return nullptr; + } + + object->setFixedSlot(TimeZoneObject::IDENTIFIER_SLOT, + StringValue(identifier)); + + object->setFixedSlot(TimeZoneObject::PRIMARY_IDENTIFIER_SLOT, + StringValue(primaryIdentifier)); + + object->setFixedSlot(TimeZoneObject::OFFSET_MINUTES_SLOT, UndefinedValue()); + + return object; +} + +static TimeZoneObject* CreateTimeZoneObject(JSContext* cx, + int32_t offsetMinutes) { + // TODO: It's unclear if offset time zones should also be cached. Real world + // experience will tell if a cache should be added. + + MOZ_ASSERT(std::abs(offsetMinutes) < UnitsPerDay(TemporalUnit::Minute)); + + Rooted identifier( + cx, FormatOffsetTimeZoneIdentifier(cx, offsetMinutes)); + if (!identifier) { + return nullptr; + } + + auto* object = NewObjectWithGivenProto(cx, nullptr); + if (!object) { + return nullptr; + } + + object->setFixedSlot(TimeZoneObject::IDENTIFIER_SLOT, + StringValue(identifier)); + + object->setFixedSlot(TimeZoneObject::PRIMARY_IDENTIFIER_SLOT, + UndefinedValue()); + + object->setFixedSlot(TimeZoneObject::OFFSET_MINUTES_SLOT, + Int32Value(offsetMinutes)); + + return object; } static mozilla::UniquePtr CreateIntlTimeZone( - JSContext* cx, JSString* identifier) { + JSContext* cx, JSLinearString* identifier) { JS::AutoStableStringChars stableChars(cx); if (!stableChars.initTwoByte(cx, identifier)) { return nullptr; @@ -115,20 +166,23 @@ static mozilla::UniquePtr CreateIntlTimeZone( } static mozilla::intl::TimeZone* GetOrCreateIntlTimeZone( - JSContext* cx, Handle timeZone) { + JSContext* cx, Handle timeZone) { + MOZ_ASSERT(!timeZone.isOffset()); + // Obtain a cached mozilla::intl::TimeZone object. - if (auto* tz = timeZone->getTimeZone()) { + if (auto* tz = timeZone.getTimeZone()) { return tz; } - auto* tz = CreateIntlTimeZone(cx, timeZone->identifier()).release(); + auto* tz = CreateIntlTimeZone(cx, timeZone.primaryIdentifier()).release(); if (!tz) { return nullptr; } - timeZone->setTimeZone(tz); - intl::AddICUCellMemory(timeZone, - TimeZoneObjectMaybeBuiltin::EstimatedMemoryUse); + auto* obj = timeZone.get().toTimeZoneObject(); + obj->setTimeZone(tz); + + intl::AddICUCellMemory(obj, TimeZoneObject::EstimatedMemoryUse); return tz; } @@ -136,9 +190,8 @@ static mozilla::intl::TimeZone* GetOrCreateIntlTimeZone( * IsValidTimeZoneName ( timeZone ) * IsAvailableTimeZoneName ( timeZone ) */ -bool js::temporal::IsValidTimeZoneName( - JSContext* cx, Handle timeZone, - MutableHandle validatedTimeZone) { +static bool IsValidTimeZoneName(JSContext* cx, Handle timeZone, + MutableHandle validatedTimeZone) { intl::SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref(); if (!sharedIntlData.validateTimeZoneName(cx, timeZone, validatedTimeZone)) { @@ -158,7 +211,7 @@ bool js::temporal::IsValidTimeZoneName( * * ES2024 Intl draft rev 74ca7099f103d143431b2ea422ae640c6f43e3e6 */ -JSString* js::temporal::CanonicalizeTimeZoneName( +static JSLinearString* CanonicalizeTimeZoneName( JSContext* cx, Handle timeZone) { // Step 1. (Not applicable, the input is already a valid IANA time zone.) #ifdef DEBUG @@ -222,11 +275,9 @@ JSString* js::temporal::CanonicalizeTimeZoneName( "Unsupported canonical time zone"); #endif - // Step 3. - if (StringEqualsLiteral(ianaTimeZone, "Etc/UTC") || - StringEqualsLiteral(ianaTimeZone, "Etc/GMT")) { - return cx->names().UTC; - } + // Step 3. (Links to UTC are handled by SharedIntlData.) + MOZ_ASSERT(!StringEqualsLiteral(ianaTimeZone, "Etc/UTC")); + MOZ_ASSERT(!StringEqualsLiteral(ianaTimeZone, "Etc/GMT")); // We don't need to check against "GMT", because ICU uses the tzdata rearguard // format, where "GMT" is a link to "Etc/GMT". @@ -241,11 +292,13 @@ JSString* js::temporal::CanonicalizeTimeZoneName( * IsAvailableTimeZoneName ( timeZone ) * CanonicalizeTimeZoneName ( timeZone ) */ -JSString* js::temporal::ValidateAndCanonicalizeTimeZoneName( - JSContext* cx, Handle timeZone) { +static bool ValidateAndCanonicalizeTimeZoneName( + JSContext* cx, Handle timeZone, + MutableHandle identifier, + MutableHandle primaryIdentifier) { Rooted validatedTimeZone(cx); if (!IsValidTimeZoneName(cx, timeZone, &validatedTimeZone)) { - return nullptr; + return false; } if (!validatedTimeZone) { @@ -254,49 +307,139 @@ JSString* js::temporal::ValidateAndCanonicalizeTimeZoneName( JSMSG_TEMPORAL_TIMEZONE_INVALID_IDENTIFIER, chars.get()); } + return false; + } + + auto* canonical = CanonicalizeTimeZoneName(cx, validatedTimeZone); + if (!canonical) { + return false; + } + + identifier.set(validatedTimeZone); + primaryIdentifier.set(canonical); + return true; +} + +static bool SystemTimeZoneOffset(JSContext* cx, int32_t* offset) { + auto rawOffset = + DateTimeInfo::getRawOffsetMs(DateTimeInfo::forceUTC(cx->realm())); + if (rawOffset.isErr()) { + intl::ReportInternalError(cx); + return false; + } + + *offset = rawOffset.unwrap(); + return true; +} + +/** + * SystemTimeZoneIdentifier ( ) + * + * Returns the IANA time zone name for the host environment's current time zone. + */ +JSLinearString* js::temporal::SystemTimeZoneIdentifier(JSContext* cx) { + intl::FormatBuffer formatBuffer(cx); + auto result = DateTimeInfo::timeZoneId(DateTimeInfo::forceUTC(cx->realm()), + formatBuffer); + if (result.isErr()) { + intl::ReportInternalError(cx, result.unwrapErr()); return nullptr; } - return CanonicalizeTimeZoneName(cx, validatedTimeZone); + Rooted timeZone(cx, formatBuffer.toString(cx)); + if (!timeZone) { + return nullptr; + } + + Rooted validTimeZone(cx); + if (!IsValidTimeZoneName(cx, timeZone, &validTimeZone)) { + return nullptr; + } + if (validTimeZone) { + return CanonicalizeTimeZoneName(cx, validTimeZone); + } + + // See DateTimeFormat.js for the JS implementation. + // TODO: Move the JS implementation into C++. + + // Before defaulting to "UTC", try to represent the system time zone using + // the Etc/GMT + offset format. This format only accepts full hour offsets. + int32_t offset; + if (!SystemTimeZoneOffset(cx, &offset)) { + return nullptr; + } + + constexpr int32_t msPerHour = 60 * 60 * 1000; + int32_t offsetHours = std::abs(offset / msPerHour); + int32_t offsetHoursFraction = offset % msPerHour; + if (offsetHoursFraction == 0 && offsetHours < 24) { + // Etc/GMT + offset uses POSIX-style signs, i.e. a positive offset + // means a location west of GMT. + constexpr std::string_view etcGMT = "Etc/GMT"; + + char offsetString[etcGMT.length() + 3]; + + size_t n = etcGMT.copy(offsetString, etcGMT.length()); + offsetString[n++] = offset < 0 ? '+' : '-'; + if (offsetHours >= 10) { + offsetString[n++] = char('0' + (offsetHours / 10)); + } + offsetString[n++] = char('0' + (offsetHours % 10)); + + MOZ_ASSERT(n == etcGMT.length() + 2 || n == etcGMT.length() + 3); + + timeZone = NewStringCopyN(cx, offsetString, n); + if (!timeZone) { + return nullptr; + } + + // Check if the fallback is valid. + if (!IsValidTimeZoneName(cx, timeZone, &validTimeZone)) { + return nullptr; + } + if (validTimeZone) { + return CanonicalizeTimeZoneName(cx, validTimeZone); + } + } + + // Fallback to "UTC" if everything else fails. + return cx->names().UTC; } -class EpochInstantList final { - // GetNamedTimeZoneEpochNanoseconds can return up-to two elements. - static constexpr size_t MaxLength = 2; +/** + * SystemTimeZoneIdentifier ( ) + */ +bool js::temporal::SystemTimeZone(JSContext* cx, + MutableHandle result) { + Rooted identifier(cx, SystemTimeZoneIdentifier(cx)); + if (!identifier) { + return false; + } - mozilla::Array array_ = {}; - size_t length_ = 0; + auto* timeZone = CreateTimeZoneObject(cx, identifier, identifier); + if (!timeZone) { + return false; + } - public: - EpochInstantList() = default; - - size_t length() const { return length_; } - - void append(const Instant& instant) { array_[length_++] = instant; } - - auto& operator[](size_t i) { return array_[i]; } - const auto& operator[](size_t i) const { return array_[i]; } - - auto begin() const { return array_.begin(); } - auto end() const { return array_.begin() + length_; } -}; + result.set(TimeZoneValue(timeZone)); + return true; +} /** - * GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, - * hour, minute, second, millisecond, microsecond, nanosecond ) + * GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, isoDateTime ) */ -static bool GetNamedTimeZoneEpochNanoseconds( - JSContext* cx, Handle timeZone, - const PlainDateTime& dateTime, EpochInstantList& instants) { - MOZ_ASSERT(timeZone->offsetMinutes().isUndefined()); - MOZ_ASSERT(IsValidISODateTime(dateTime)); - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); - MOZ_ASSERT(instants.length() == 0); +static bool GetNamedTimeZoneEpochNanoseconds(JSContext* cx, + Handle timeZone, + const ISODateTime& isoDateTime, + PossibleEpochNanoseconds* result) { + MOZ_ASSERT(!timeZone.isOffset()); + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); // FIXME: spec issue - assert ISODateTimeWithinLimits instead of // IsValidISODate - int64_t ms = MakeDate(dateTime); + int64_t ms = MakeDate(isoDateTime); auto* tz = GetOrCreateIntlTimeZone(cx, timeZone); if (!tz) { @@ -332,9 +475,9 @@ static bool GetNamedTimeZoneEpochNanoseconds( } if (formerOffset == latterOffset) { - auto instant = GetUTCEpochNanoseconds( - dateTime, InstantSpan::fromMilliseconds(formerOffset)); - instants.append(instant); + auto epochNs = GetUTCEpochNanoseconds(isoDateTime) - + EpochDuration::fromMilliseconds(formerOffset); + *result = PossibleEpochNanoseconds{epochNs}; return true; } @@ -345,23 +488,22 @@ static bool GetNamedTimeZoneEpochNanoseconds( // Skipped time. if (disambiguationOffset == formerOffset) { + *result = {}; return true; } // Repeated time. - for (auto offset : {formerOffset, latterOffset}) { - auto instant = - GetUTCEpochNanoseconds(dateTime, InstantSpan::fromMilliseconds(offset)); - instants.append(instant); - } - - MOZ_ASSERT(instants.length() == 2); - - // Ensure the returned instants are sorted in numerical order. - if (instants[0] > instants[1]) { - std::swap(instants[0], instants[1]); + auto formerInstant = GetUTCEpochNanoseconds(isoDateTime) - + EpochDuration::fromMilliseconds(formerOffset); + auto latterInstant = GetUTCEpochNanoseconds(isoDateTime) - + EpochDuration::fromMilliseconds(latterOffset); + + // Ensure the returned epoch nanoseconds are sorted in numerical order. + if (formerInstant > latterInstant) { + std::swap(formerInstant, latterInstant); } + *result = PossibleEpochNanoseconds{formerInstant, latterInstant}; return true; } @@ -369,12 +511,12 @@ static bool GetNamedTimeZoneEpochNanoseconds( * GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds ) */ static bool GetNamedTimeZoneOffsetNanoseconds( - JSContext* cx, Handle timeZone, - const Instant& epochInstant, int64_t* offset) { - MOZ_ASSERT(timeZone->offsetMinutes().isUndefined()); + JSContext* cx, Handle timeZone, + const EpochNanoseconds& epochNanoseconds, int64_t* offset) { + MOZ_ASSERT(!timeZone.isOffset()); // Round down (floor) to the previous full milliseconds. - int64_t millis = epochInstant.floorToMilliseconds(); + int64_t millis = epochNanoseconds.floorToMilliseconds(); auto* tz = GetOrCreateIntlTimeZone(cx, timeZone); if (!tz) { @@ -398,11 +540,11 @@ static bool GetNamedTimeZoneOffsetNanoseconds( /** * GetNamedTimeZoneNextTransition ( timeZoneIdentifier, epochNanoseconds ) */ -static bool GetNamedTimeZoneNextTransition(JSContext* cx, - Handle timeZone, - const Instant& epochInstant, - mozilla::Maybe* result) { - MOZ_ASSERT(timeZone->offsetMinutes().isUndefined()); +bool js::temporal::GetNamedTimeZoneNextTransition( + JSContext* cx, Handle timeZone, + const EpochNanoseconds& epochNanoseconds, + mozilla::Maybe* result) { + MOZ_ASSERT(!timeZone.isOffset()); // Round down (floor) to the previous full millisecond. // @@ -410,7 +552,7 @@ static bool GetNamedTimeZoneNextTransition(JSContext* cx, // the default configuration doesn't enable it, therefore it's safe to round // to milliseconds here. In addition to that, ICU also only supports // transitions at millisecond precision. - int64_t millis = epochInstant.floorToMilliseconds(); + int64_t millis = epochNanoseconds.floorToMilliseconds(); auto* tz = GetOrCreateIntlTimeZone(cx, timeZone); if (!tz) { @@ -429,8 +571,8 @@ static bool GetNamedTimeZoneNextTransition(JSContext* cx, return true; } - auto transitionInstant = Instant::fromMilliseconds(*transition); - if (!IsValidEpochInstant(transitionInstant)) { + auto transitionInstant = EpochNanoseconds::fromMilliseconds(*transition); + if (!IsValidEpochNanoseconds(transitionInstant)) { *result = mozilla::Nothing(); return true; } @@ -442,10 +584,11 @@ static bool GetNamedTimeZoneNextTransition(JSContext* cx, /** * GetNamedTimeZonePreviousTransition ( timeZoneIdentifier, epochNanoseconds ) */ -static bool GetNamedTimeZonePreviousTransition( - JSContext* cx, Handle timeZone, - const Instant& epochInstant, mozilla::Maybe* result) { - MOZ_ASSERT(timeZone->offsetMinutes().isUndefined()); +bool js::temporal::GetNamedTimeZonePreviousTransition( + JSContext* cx, Handle timeZone, + const EpochNanoseconds& epochNanoseconds, + mozilla::Maybe* result) { + MOZ_ASSERT(!timeZone.isOffset()); // Round up (ceil) to the next full millisecond. // @@ -453,7 +596,7 @@ static bool GetNamedTimeZonePreviousTransition( // the default configuration doesn't enable it, therefore it's safe to round // to milliseconds here. In addition to that, ICU also only supports // transitions at millisecond precision. - int64_t millis = epochInstant.ceilToMilliseconds(); + int64_t millis = epochNanoseconds.ceilToMilliseconds(); auto* tz = GetOrCreateIntlTimeZone(cx, timeZone); if (!tz) { @@ -472,8 +615,8 @@ static bool GetNamedTimeZonePreviousTransition( return true; } - auto transitionInstant = Instant::fromMilliseconds(*transition); - if (!IsValidEpochInstant(transitionInstant)) { + auto transitionInstant = EpochNanoseconds::fromMilliseconds(*transition); + if (!IsValidEpochNanoseconds(transitionInstant)) { *result = mozilla::Nothing(); return true; } @@ -483,153 +626,53 @@ static bool GetNamedTimeZonePreviousTransition( } /** - * FormatOffsetTimeZoneIdentifier ( offsetMinutes [ , style ] ) + * GetStartOfDay ( timeZone, isoDate ) */ -static JSString* FormatOffsetTimeZoneIdentifier(JSContext* cx, - int32_t offsetMinutes) { - MOZ_ASSERT(std::abs(offsetMinutes) < UnitsPerDay(TemporalUnit::Minute)); +bool js::temporal::GetStartOfDay(JSContext* cx, Handle timeZone, + const ISODate& isoDate, + EpochNanoseconds* result) { + MOZ_ASSERT(IsValidISODate(isoDate)); // Step 1. - char sign = offsetMinutes >= 0 ? '+' : '-'; + auto isoDateTime = ISODateTime{isoDate, {}}; // Step 2. - int32_t absoluteMinutes = std::abs(offsetMinutes); + PossibleEpochNanoseconds possibleEpochNs; + if (!GetPossibleEpochNanoseconds(cx, timeZone, isoDateTime, + &possibleEpochNs)) { + return false; + } + MOZ_ASSERT(ISODateTimeWithinLimits(isoDateTime)); // Step 3. - int32_t hour = absoluteMinutes / 60; + if (!possibleEpochNs.empty()) { + *result = possibleEpochNs[0]; + return true; + } // Step 4. - int32_t minute = absoluteMinutes % 60; + MOZ_ASSERT(!timeZone.isOffset()); - // Step 5. (Inlined FormatTimeString). - // - // Format: "sign hour{2} : minute{2}" - char result[] = { - sign, char('0' + (hour / 10)), char('0' + (hour % 10)), - ':', char('0' + (minute / 10)), char('0' + (minute % 10)), - }; + constexpr auto oneDay = EpochDuration::fromDays(1); + + // Step 5. + auto previousDayEpochNs = GetUTCEpochNanoseconds(isoDateTime) - oneDay; + mozilla::Maybe transition{}; + if (!GetNamedTimeZoneNextTransition(cx, timeZone, previousDayEpochNs, + &transition)) { + return false; + } // Step 6. - return NewStringCopyN(cx, result, std::size(result)); + MOZ_ASSERT(transition, "time zone transition not found"); + + // Step 7. + *result = *transition; + return true; } /** - * CreateTemporalTimeZone ( identifier [ , newTarget ] ) - */ -static TimeZoneObject* CreateTemporalTimeZone(JSContext* cx, - const CallArgs& args, - Handle identifier, - Handle offsetMinutes) { - MOZ_ASSERT(offsetMinutes.isUndefined() || offsetMinutes.isInt32()); - MOZ_ASSERT_IF(offsetMinutes.isInt32(), std::abs(offsetMinutes.toInt32()) < - UnitsPerDay(TemporalUnit::Minute)); - - // Steps 1-2. - Rooted proto(cx); - if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_TimeZone, &proto)) { - return nullptr; - } - - auto* timeZone = NewObjectWithClassProto(cx, proto); - if (!timeZone) { - return nullptr; - } - - // Step 4.a. (Not applicable in our implementation.) - - // Steps 3.a or 4.b. - timeZone->setFixedSlot(TimeZoneObject::IDENTIFIER_SLOT, - StringValue(identifier)); - - // Step 3.b or 4.c. - timeZone->setFixedSlot(TimeZoneObject::OFFSET_MINUTES_SLOT, offsetMinutes); - - // Step 5. - return timeZone; -} - -static BuiltinTimeZoneObject* CreateBuiltinTimeZone( - JSContext* cx, Handle identifier) { - // TODO: Implement a built-in time zone object cache. - - auto* object = NewObjectWithGivenProto(cx, nullptr); - if (!object) { - return nullptr; - } - - object->setFixedSlot(BuiltinTimeZoneObject::IDENTIFIER_SLOT, - StringValue(identifier)); - - object->setFixedSlot(BuiltinTimeZoneObject::OFFSET_MINUTES_SLOT, - UndefinedValue()); - - return object; -} - -static BuiltinTimeZoneObject* CreateBuiltinTimeZone(JSContext* cx, - int32_t offsetMinutes) { - // TODO: It's unclear if offset time zones should also be cached. Real world - // experience will tell if a cache should be added. - - MOZ_ASSERT(std::abs(offsetMinutes) < UnitsPerDay(TemporalUnit::Minute)); - - Rooted identifier( - cx, FormatOffsetTimeZoneIdentifier(cx, offsetMinutes)); - if (!identifier) { - return nullptr; - } - - auto* object = NewObjectWithGivenProto(cx, nullptr); - if (!object) { - return nullptr; - } - - object->setFixedSlot(BuiltinTimeZoneObject::IDENTIFIER_SLOT, - StringValue(identifier)); - - object->setFixedSlot(BuiltinTimeZoneObject::OFFSET_MINUTES_SLOT, - Int32Value(offsetMinutes)); - - return object; -} - -/** - * CreateTemporalTimeZone ( identifier [ , newTarget ] ) - */ -static TimeZoneObject* CreateTemporalTimeZone( - JSContext* cx, Handle timeZone) { - // Steps 1-2. - auto* object = NewBuiltinClassInstance(cx); - if (!object) { - return nullptr; - } - - // Step 4.a. (Not applicable in our implementation.) - - // Steps 3.a or 4.b. - object->setFixedSlot( - TimeZoneObject::IDENTIFIER_SLOT, - timeZone->getFixedSlot(BuiltinTimeZoneObject::IDENTIFIER_SLOT)); - - // Step 3.b or 4.c. - object->setFixedSlot( - TimeZoneObject::OFFSET_MINUTES_SLOT, - timeZone->getFixedSlot(BuiltinTimeZoneObject::OFFSET_MINUTES_SLOT)); - - // Step 5. - return object; -} - -/** - * CreateTemporalTimeZone ( identifier [ , newTarget ] ) - */ -BuiltinTimeZoneObject* js::temporal::CreateTemporalTimeZone( - JSContext* cx, Handle identifier) { - return ::CreateBuiltinTimeZone(cx, identifier); -} - -/** - * ToTemporalTimeZoneSlotValue ( temporalTimeZoneLike ) + * ToTemporalTimeZoneIdentifier ( temporalTimeZoneLike ) */ bool js::temporal::ToTemporalTimeZone(JSContext* cx, Handle string, @@ -637,18 +680,8 @@ bool js::temporal::ToTemporalTimeZone(JSContext* cx, // Steps 1-3. (Not applicable) // Steps 4-5. - if (string.name()) { - // Steps 4.a-c. (Not applicable in our implementation.) - - // Steps 4.d-e. - Rooted timeZoneName( - cx, ValidateAndCanonicalizeTimeZoneName(cx, string.name())); - if (!timeZoneName) { - return false; - } - - // Steps 4.f and 5. - auto* obj = ::CreateBuiltinTimeZone(cx, timeZoneName); + if (!string.name()) { + auto* obj = CreateTimeZoneObject(cx, string.offset()); if (!obj) { return false; } @@ -657,8 +690,16 @@ bool js::temporal::ToTemporalTimeZone(JSContext* cx, return true; } - // Steps 4.b-c and 8. - auto* obj = ::CreateBuiltinTimeZone(cx, string.offset()); + // Steps 6-8. + Rooted identifier(cx); + Rooted primaryIdentifier(cx); + if (!ValidateAndCanonicalizeTimeZoneName(cx, string.name(), &identifier, + &primaryIdentifier)) { + return false; + } + + // Step 9. + auto* obj = CreateTimeZoneObject(cx, identifier, primaryIdentifier); if (!obj) { return false; } @@ -668,85 +709,29 @@ bool js::temporal::ToTemporalTimeZone(JSContext* cx, } /** - * ObjectImplementsTemporalTimeZoneProtocol ( object ) - */ -static bool ObjectImplementsTemporalTimeZoneProtocol(JSContext* cx, - Handle object, - bool* result) { - // Step 1. (Not applicable in our implementation.) - MOZ_ASSERT(!object->canUnwrapAs(), - "TimeZone objects handled in the caller"); - - // Step 2. - for (auto key : { - &JSAtomState::getOffsetNanosecondsFor, - &JSAtomState::getPossibleInstantsFor, - &JSAtomState::id, - }) { - // Step 2.a. - bool has; - if (!HasProperty(cx, object, cx->names().*key, &has)) { - return false; - } - if (!has) { - *result = false; - return true; - } - } - - // Step 3. - *result = true; - return true; -} - -/** - * ToTemporalTimeZoneSlotValue ( temporalTimeZoneLike ) + * ToTemporalTimeZoneIdentifier ( temporalTimeZoneLike ) */ bool js::temporal::ToTemporalTimeZone(JSContext* cx, Handle temporalTimeZoneLike, MutableHandle result) { // Step 1. - Rooted timeZoneLike(cx, temporalTimeZoneLike); - if (timeZoneLike.isObject()) { - Rooted obj(cx, &timeZoneLike.toObject()); - - // Step 1.b. (Partial) - if (obj->canUnwrapAs()) { - result.set(TimeZoneValue(obj)); - return true; - } + if (temporalTimeZoneLike.isObject()) { + JSObject* obj = &temporalTimeZoneLike.toObject(); // Step 1.a. if (auto* zonedDateTime = obj->maybeUnwrapIf()) { result.set(zonedDateTime->timeZone()); return result.wrap(cx); } - - // Step 1.b. - bool implementsTimeZoneProtocol; - if (!ObjectImplementsTemporalTimeZoneProtocol( - cx, obj, &implementsTimeZoneProtocol)) { - return false; - } - if (!implementsTimeZoneProtocol) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_OBJECT, - "Temporal.TimeZone", obj->getClass()->name); - return false; - } - - // Step 1.c. - result.set(TimeZoneValue(obj)); - return true; } // Step 2. - if (!timeZoneLike.isString()) { + if (!temporalTimeZoneLike.isString()) { ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, - timeZoneLike, nullptr, "not a string"); + temporalTimeZoneLike, nullptr, "not a string"); return false; } - Rooted identifier(cx, timeZoneLike.toString()); + Rooted identifier(cx, temporalTimeZoneLike.toString()); // Step 3. Rooted timeZoneName(cx); @@ -754,207 +739,31 @@ bool js::temporal::ToTemporalTimeZone(JSContext* cx, return false; } - // Steps 4-8. + // Steps 4-9. return ToTemporalTimeZone(cx, timeZoneName, result); } /** - * ToTemporalTimeZoneObject ( timeZoneSlotValue ) + * GetOffsetNanosecondsFor ( timeZone, epochNs ) */ -JSObject* js::temporal::ToTemporalTimeZoneObject( - JSContext* cx, Handle timeZone) { - // Step 1. - if (timeZone.isObject()) { - return timeZone.toObject(); - } +bool js::temporal::GetOffsetNanosecondsFor(JSContext* cx, + Handle timeZone, + const EpochNanoseconds& epochNs, + int64_t* offsetNanoseconds) { + // Step 1. (Not applicable) // Step 2. - return CreateTemporalTimeZone(cx, timeZone.toString()); -} - -/** - * ToTemporalTimeZoneIdentifier ( timeZoneSlotValue ) - */ -JSString* js::temporal::ToTemporalTimeZoneIdentifier( - JSContext* cx, Handle timeZone) { - // Step 1. - if (timeZone.isString()) { - // Step 1.a. (Not applicable in our implementation.) - - // Step 1.b. - return timeZone.toString()->identifier(); - } - - // Step 2. - Rooted timeZoneObj(cx, timeZone.toObject()); - Rooted identifier(cx); - if (!GetProperty(cx, timeZoneObj, timeZoneObj, cx->names().id, &identifier)) { - return nullptr; - } - - // Step 3. - if (!identifier.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, identifier, - nullptr, "not a string"); - return nullptr; - } - - // Step 4. - return identifier.toString(); -} - -static bool TimeZone_getOffsetNanosecondsFor(JSContext* cx, unsigned argc, - Value* vp); - -static bool TimeZone_getPossibleInstantsFor(JSContext* cx, unsigned argc, - Value* vp); - -/** - * TimeZoneMethodsRecordLookup ( timeZoneRec, methodName ) - */ -static bool TimeZoneMethodsRecordLookup(JSContext* cx, - MutableHandle timeZone, - TimeZoneMethod methodName) { - // Step 1. (Not applicable in our implementation.) - - // Steps 2-4. - auto object = timeZone.receiver().toObject(); - - auto lookup = [&](Handle name, JSNative native, - MutableHandle result) { - auto* method = GetMethod(cx, object, name); - if (!method) { - return false; - } - - // As an optimization we only store the method if the receiver is either - // a custom time zone object or if the method isn't the default, built-in - // time zone method. - if (!object->is() || !IsNativeFunction(method, native)) { - result.set(method); - } - return true; - }; - - switch (methodName) { - // Steps 2 and 4. - case TimeZoneMethod::GetOffsetNanosecondsFor: - return lookup(cx->names().getOffsetNanosecondsFor, - TimeZone_getOffsetNanosecondsFor, - timeZone.getOffsetNanosecondsFor()); - - // Steps 3 and 4. - case TimeZoneMethod::GetPossibleInstantsFor: - return lookup(cx->names().getPossibleInstantsFor, - TimeZone_getPossibleInstantsFor, - timeZone.getPossibleInstantsFor()); - } - - MOZ_CRASH("invalid time zone method"); -} - -/** - * CreateTimeZoneMethodsRecord ( timeZone, methods ) - */ -bool js::temporal::CreateTimeZoneMethodsRecord( - JSContext* cx, Handle timeZone, - mozilla::EnumSet methods, - MutableHandle result) { - MOZ_ASSERT(!methods.isEmpty()); - - // Step 1. - result.set(TimeZoneRecord{timeZone}); - -#ifdef DEBUG - // Remember the set of looked-up methods for assertions. - result.get().lookedUp() += methods; -#endif - - // Built-in time zones don't perform observable lookups. - if (timeZone.isString()) { - return true; - } - - // Step 2. - for (auto method : methods) { - if (!TimeZoneMethodsRecordLookup(cx, result, method)) { - return false; - } - } - - // Step 3. - return true; -} - -bool js::temporal::WrapTimeZoneValueObject(JSContext* cx, - MutableHandle timeZone) { - // First handle the common case when |timeZone| is TimeZoneObjectMaybeBuiltin - // from the current compartment. - if (MOZ_LIKELY(timeZone->is() && - timeZone->compartment() == cx->compartment())) { - return true; - } - - // If it's not a built-in time zone, simply wrap the object into the current - // compartment. - auto* unwrappedTimeZone = timeZone->maybeUnwrapIf(); - if (!unwrappedTimeZone) { - return cx->compartment()->wrap(cx, timeZone); - } - - // If this is a built-in time zone from a different compartment, create a - // fresh copy using the current compartment. - // - // We create a fresh copy, so we don't have to support the cross-compartment - // case, which makes detection of "string" time zones easier. - - const auto& offsetMinutes = unwrappedTimeZone->offsetMinutes(); - if (offsetMinutes.isInt32()) { - auto* obj = CreateBuiltinTimeZone(cx, offsetMinutes.toInt32()); - if (!obj) { - return false; - } - - timeZone.set(obj); - return true; - } - MOZ_ASSERT(offsetMinutes.isUndefined()); - - Rooted identifier(cx, unwrappedTimeZone->identifier()); - if (!cx->compartment()->wrap(cx, &identifier)) { - return false; - } - - auto* obj = ::CreateBuiltinTimeZone(cx, identifier); - if (!obj) { - return false; - } - - timeZone.set(obj); - return true; -} - -/** - * Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( instant ) - */ -static bool BuiltinGetOffsetNanosecondsFor( - JSContext* cx, Handle timeZone, - const Instant& instant, int64_t* offsetNanoseconds) { - // Steps 1-3. (Not applicable.) - - // Step 4. - if (timeZone->offsetMinutes().isInt32()) { - int32_t offset = timeZone->offsetMinutes().toInt32(); + if (timeZone.isOffset()) { + int32_t offset = timeZone.offsetMinutes(); MOZ_ASSERT(std::abs(offset) < UnitsPerDay(TemporalUnit::Minute)); *offsetNanoseconds = int64_t(offset) * ToNanoseconds(TemporalUnit::Minute); return true; } - MOZ_ASSERT(timeZone->offsetMinutes().isUndefined()); - // Step 5. + // Step 3. int64_t offset; - if (!GetNamedTimeZoneOffsetNanoseconds(cx, timeZone, instant, &offset)) { + if (!GetNamedTimeZoneOffsetNanoseconds(cx, timeZone, epochNs, &offset)) { return false; } MOZ_ASSERT(std::abs(offset) < ToNanoseconds(TemporalUnit::Day)); @@ -963,873 +772,219 @@ static bool BuiltinGetOffsetNanosecondsFor( return true; } -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -static bool GetOffsetNanosecondsForSlow(JSContext* cx, - Handle timeZone, - Handle> instant, - int64_t* offsetNanoseconds) { - // Step 1. (Inlined call to TimeZoneMethodsRecordCall) - Rooted fval(cx, ObjectValue(*timeZone.getOffsetNanosecondsFor())); - auto thisv = timeZone.receiver().toObject(); - Rooted instantVal(cx, ObjectValue(*instant)); - Rooted rval(cx); - if (!Call(cx, fval, thisv, instantVal, &rval)) { - return false; - } - - // Step 2. (Not applicable) - - // Step 3. - if (!rval.isNumber()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, rval, - nullptr, "not a number"); - return false; - } - - // Steps 4-6. - double num = rval.toNumber(); - if (!IsInteger(num) || std::abs(num) >= ToNanoseconds(TemporalUnit::Day)) { - ToCStringBuf cbuf; - const char* numStr = NumberToCString(&cbuf, num); - - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_TIMEZONE_NANOS_RANGE, numStr); - return false; - } - - // Step 7. - *offsetNanoseconds = int64_t(num); - return true; -} - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -bool js::temporal::GetOffsetNanosecondsFor( - JSContext* cx, Handle timeZone, - Handle> instant, int64_t* offsetNanoseconds) { - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Step 2. (Reordered) - auto getOffsetNanosecondsFor = timeZone.getOffsetNanosecondsFor(); - if (!getOffsetNanosecondsFor) { - auto* unwrapped = instant.unwrap(cx); - if (!unwrapped) { - return false; - } - auto instant = ToInstant(unwrapped); - auto builtin = timeZone.receiver().toTimeZoneObjectMaybeBuiltin(); - - return BuiltinGetOffsetNanosecondsFor(cx, builtin, instant, - offsetNanoseconds); - } - - // Steps 1 and 3-7. - return ::GetOffsetNanosecondsForSlow(cx, timeZone, instant, - offsetNanoseconds); -} - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -bool js::temporal::GetOffsetNanosecondsFor( - JSContext* cx, Handle timeZone, - Handle> instant, int64_t* offsetNanoseconds) { - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - }, - &timeZoneRec)) { - return false; - } - - return GetOffsetNanosecondsFor(cx, timeZoneRec, instant, offsetNanoseconds); -} - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -bool js::temporal::GetOffsetNanosecondsFor(JSContext* cx, - Handle timeZone, - const Instant& instant, - int64_t* offsetNanoseconds) { - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Step 2. (Reordered) - auto getOffsetNanosecondsFor = timeZone.getOffsetNanosecondsFor(); - if (!getOffsetNanosecondsFor) { - auto builtin = timeZone.receiver().toTimeZoneObjectMaybeBuiltin(); - return BuiltinGetOffsetNanosecondsFor(cx, builtin, instant, - offsetNanoseconds); - } - - // Steps 1 and 3-7. - Rooted obj(cx, CreateTemporalInstant(cx, instant)); - if (!obj) { - return false; - } - return ::GetOffsetNanosecondsForSlow(cx, timeZone, obj, offsetNanoseconds); -} - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -bool js::temporal::GetOffsetNanosecondsFor(JSContext* cx, - Handle timeZone, - const Instant& instant, - int64_t* offsetNanoseconds) { - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - }, - &timeZoneRec)) { - return false; - } - - return GetOffsetNanosecondsFor(cx, timeZoneRec, instant, offsetNanoseconds); -} - -/** - * FormatUTCOffsetNanoseconds ( offsetNanoseconds ) - */ -JSString* js::temporal::FormatUTCOffsetNanoseconds(JSContext* cx, - int64_t offsetNanoseconds) { - MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - - // Step 1. - char sign = offsetNanoseconds >= 0 ? '+' : '-'; - - // Step 2. - int64_t absoluteNanoseconds = std::abs(offsetNanoseconds); - - // Step 6. (Reordered) - int32_t subSecondNanoseconds = int32_t(absoluteNanoseconds % 1'000'000'000); - - // Step 5. (Reordered) - int32_t quotient = int32_t(absoluteNanoseconds / 1'000'000'000); - int32_t second = quotient % 60; - - // Step 4. (Reordered) - quotient /= 60; - int32_t minute = quotient % 60; - - // Step 3. - int32_t hour = quotient / 60; - MOZ_ASSERT(hour < 24, "time zone offset mustn't exceed 24-hours"); - - // Format: "sign hour{2} : minute{2} : second{2} . fractional{9}" - constexpr size_t maxLength = 1 + 2 + 1 + 2 + 1 + 2 + 1 + 9; - char result[maxLength]; - - size_t n = 0; - - // Steps 7-8. (Inlined FormatTimeString). - result[n++] = sign; - result[n++] = char('0' + (hour / 10)); - result[n++] = char('0' + (hour % 10)); - result[n++] = ':'; - result[n++] = char('0' + (minute / 10)); - result[n++] = char('0' + (minute % 10)); - - if (second != 0 || subSecondNanoseconds != 0) { - result[n++] = ':'; - result[n++] = char('0' + (second / 10)); - result[n++] = char('0' + (second % 10)); - - if (uint32_t fractional = subSecondNanoseconds) { - result[n++] = '.'; - - uint32_t k = 100'000'000; - do { - result[n++] = char('0' + (fractional / k)); - fractional %= k; - k /= 10; - } while (fractional); - } - } - - MOZ_ASSERT(n <= maxLength); - - // Step 9. - return NewStringCopyN(cx, result, n); -} - -/** - * GetOffsetStringFor ( timeZoneRec, instant ) - */ -JSString* js::temporal::GetOffsetStringFor(JSContext* cx, - Handle timeZone, - const Instant& instant) { - // Step 1. - int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { - return nullptr; - } - MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - - // Step 2. - return FormatUTCOffsetNanoseconds(cx, offsetNanoseconds); -} - -/** - * GetOffsetStringFor ( timeZoneRec, instant ) - */ -JSString* js::temporal::GetOffsetStringFor( - JSContext* cx, Handle timeZone, - Handle> instant) { - // Step 1. - int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { - return nullptr; - } - MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - - // Step 2. - return FormatUTCOffsetNanoseconds(cx, offsetNanoseconds); -} - /** * TimeZoneEquals ( one, two ) */ -bool js::temporal::TimeZoneEquals(JSContext* cx, Handle one, - Handle two, bool* equals) { - // Steps 1-3. (Not applicable) +bool js::temporal::TimeZoneEquals(const TimeZoneValue& one, + const TimeZoneValue& two) { + // Steps 1-3. (Not applicable in our implementation.) // Step 4. - if (!EqualStrings(cx, one, two, equals)) { - return false; - } - if (*equals) { - return true; + if (!one.isOffset() && !two.isOffset()) { + return EqualStrings(one.primaryIdentifier(), two.primaryIdentifier()); } // Step 5. - Rooted timeZoneOne(cx); - if (!ParseTimeZoneIdentifier(cx, one, &timeZoneOne)) { - return false; + if (one.isOffset() && two.isOffset()) { + return one.offsetMinutes() == two.offsetMinutes(); } // Step 6. - Rooted timeZoneTwo(cx); - if (!ParseTimeZoneIdentifier(cx, two, &timeZoneTwo)) { - return false; - } - - // Step 7. - if (timeZoneOne.name() && timeZoneTwo.name()) { - // Step 7.a. - Rooted validTimeZoneOne(cx); - if (!IsValidTimeZoneName(cx, timeZoneOne.name(), &validTimeZoneOne)) { - return false; - } - if (!validTimeZoneOne) { - *equals = false; - return true; - } - - // Step 7.b. - Rooted validTimeZoneTwo(cx); - if (!IsValidTimeZoneName(cx, timeZoneTwo.name(), &validTimeZoneTwo)) { - return false; - } - if (!validTimeZoneTwo) { - *equals = false; - return true; - } - - // Step 7.c and 9. - Rooted canonicalOne( - cx, CanonicalizeTimeZoneName(cx, validTimeZoneOne)); - if (!canonicalOne) { - return false; - } - - JSString* canonicalTwo = CanonicalizeTimeZoneName(cx, validTimeZoneTwo); - if (!canonicalTwo) { - return false; - } - - return EqualStrings(cx, canonicalOne, canonicalTwo, equals); - } - - // Step 8.a. - if (!timeZoneOne.name() && !timeZoneTwo.name()) { - *equals = (timeZoneOne.offset() == timeZoneTwo.offset()); - return true; - } - - // Step 9. - *equals = false; - return true; + return false; } -/** - * TimeZoneEquals ( one, two ) - */ -bool js::temporal::TimeZoneEquals(JSContext* cx, Handle one, - Handle two, bool* equals) { - // Step 1. - if (one.isObject() && two.isObject() && one.toObject() == two.toObject()) { - *equals = true; - return true; - } - - // Step 2. - Rooted timeZoneOne(cx, ToTemporalTimeZoneIdentifier(cx, one)); - if (!timeZoneOne) { - return false; - } - - // Step 3. - Rooted timeZoneTwo(cx, ToTemporalTimeZoneIdentifier(cx, two)); - if (!timeZoneTwo) { - return false; - } - - // Steps 4-9. - return TimeZoneEquals(cx, timeZoneOne, timeZoneTwo, equals); -} - -// ES2019 draft rev 0ceb728a1adbffe42b26972a6541fd7f398b1557 -// 5.2.5 Mathematical Operations -static inline double PositiveModulo(double dividend, double divisor) { - MOZ_ASSERT(divisor > 0); - MOZ_ASSERT(std::isfinite(divisor)); - - double result = std::fmod(dividend, divisor); - if (result < 0) { - result += divisor; - } - return result + (+0.0); -} - -/* ES5 15.9.1.10. */ -static double HourFromTime(double t) { - return PositiveModulo(std::floor(t / msPerHour), HoursPerDay); -} - -static double MinFromTime(double t) { - return PositiveModulo(std::floor(t / msPerMinute), MinutesPerHour); -} - -static double SecFromTime(double t) { - return PositiveModulo(std::floor(t / msPerSecond), SecondsPerMinute); -} - -static double msFromTime(double t) { return PositiveModulo(t, msPerSecond); } - /** * GetISOPartsFromEpoch ( epochNanoseconds ) */ -static PlainDateTime GetISOPartsFromEpoch(const Instant& instant) { - // TODO: YearFromTime/MonthFromTime/DayFromTime recompute the same values - // multiple times. Consider adding a new function avoids this. - +static ISODateTime GetISOPartsFromEpoch( + const EpochNanoseconds& epochNanoseconds, int64_t offsetNanoseconds) { // Step 1. - MOZ_ASSERT(IsValidEpochInstant(instant)); + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); + MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); + + auto totalNanoseconds = + epochNanoseconds + EpochDuration::fromNanoseconds(offsetNanoseconds); // Step 2. - int32_t remainderNs = instant.nanoseconds % 1'000'000; + int32_t remainderNs = totalNanoseconds.nanoseconds % 1'000'000; + + // Step 10. (Reordered) + // + // Reordered so the compiler can merge the divisons in steps 2, 3, and 10. + int32_t millisecond = totalNanoseconds.nanoseconds / 1'000'000; // Step 3. - double epochMilliseconds = double(instant.floorToMilliseconds()); + int64_t epochMilliseconds = totalNanoseconds.floorToMilliseconds(); - // Step 4. - int32_t year = int32_t(JS::YearFromTime(epochMilliseconds)); + // Steps 4-6. + auto [year, month, day] = ToYearMonthDay(epochMilliseconds); - // Step 5. - int32_t month = int32_t(JS::MonthFromTime(epochMilliseconds)) + 1; + // Steps 7-9. + auto [hour, minute, second] = ToHourMinuteSecond(epochMilliseconds); - // Step 6. - int32_t day = int32_t(JS::DayFromTime(epochMilliseconds)); + // Step 10. (Moved above) - // Step 7. - int32_t hour = int32_t(HourFromTime(epochMilliseconds)); - - // Step 8. - int32_t minute = int32_t(MinFromTime(epochMilliseconds)); - - // Step 9. - int32_t second = int32_t(SecFromTime(epochMilliseconds)); - - // Step 10. - int32_t millisecond = int32_t(msFromTime(epochMilliseconds)); - - // Step 11. + // Steps 11-12. int32_t microsecond = remainderNs / 1000; - // Step 12. + // Step 13. int32_t nanosecond = remainderNs % 1000; - // Step 13. - PlainDateTime result = { - {year, month, day}, - {hour, minute, second, millisecond, microsecond, nanosecond}}; + // Step 14. + auto isoDate = ISODate{year, month + 1, day}; + MOZ_ASSERT(IsValidISODate(isoDate)); - // Always valid when the epoch nanoseconds are within the representable limit. - MOZ_ASSERT(IsValidISODateTime(result)); + // Step 15. + auto time = Time{hour, minute, second, millisecond, microsecond, nanosecond}; + MOZ_ASSERT(IsValidTime(time)); + + // Step 16. + auto result = ISODateTime{isoDate, time}; + + // Always within date-time limits when the epoch nanoseconds are within limit. MOZ_ASSERT(ISODateTimeWithinLimits(result)); return result; } /** - * BalanceISODateTime ( year, month, day, hour, minute, second, millisecond, - * microsecond, nanosecond ) + * GetISODateTimeFor ( timeZone, epochNs ) */ -static PlainDateTime BalanceISODateTime(const PlainDateTime& dateTime, - int64_t nanoseconds) { - MOZ_ASSERT(IsValidISODateTime(dateTime)); - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); - MOZ_ASSERT(std::abs(nanoseconds) < ToNanoseconds(TemporalUnit::Day)); - - const auto& [date, time] = dateTime; - - // Step 1. - auto balancedTime = BalanceTime(time, nanoseconds); - MOZ_ASSERT(std::abs(balancedTime.days) <= 1); - - // Step 2. - auto balancedDate = - BalanceISODate(date.year, date.month, date.day + balancedTime.days); - - // Step 3. - return {balancedDate, balancedTime.time}; -} - -/** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -static PlainDateTimeObject* GetPlainDateTimeFor( - JSContext* cx, Handle timeZone, - Handle> instant, Handle calendar) { - // Step 1. (Not applicable in our implementation.) - - // Steps 2-3. - int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { - return nullptr; - } - - // Step 4. +ISODateTime js::temporal::GetISODateTimeFor(const EpochNanoseconds& epochNs, + int64_t offsetNanoseconds) { + MOZ_ASSERT(IsValidEpochNanoseconds(epochNs)); MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - auto* unwrappedInstant = instant.unwrap(cx); - if (!unwrappedInstant) { - return nullptr; - } - - // Steps 5-7. - auto dateTime = - GetPlainDateTimeFor(ToInstant(unwrappedInstant), offsetNanoseconds); - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); - - return CreateTemporalDateTime(cx, dateTime, calendar); -} - -/** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -PlainDateTime js::temporal::GetPlainDateTimeFor(const Instant& instant, - int64_t offsetNanoseconds) { - // Steps 1-3. (Not applicable) - - // Step 4. - MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - - // TODO: Steps 5-6 can be combined into a single operation to improve perf. - - // Step 5. - PlainDateTime dateTime = GetISOPartsFromEpoch(instant); - - // Step 6. - auto balanced = BalanceISODateTime(dateTime, offsetNanoseconds); - MOZ_ASSERT(ISODateTimeWithinLimits(balanced)); - - // Step 7. - return balanced; -} - -/** - * GetPlainDateTimeFor ( timeZone, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -bool js::temporal::GetPlainDateTimeFor(JSContext* cx, - Handle timeZone, - const Instant& instant, - PlainDateTime* result) { - MOZ_ASSERT(IsValidEpochInstant(instant)); - - // Step 1. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); + // Step 1. (Not applicable) // Steps 2-3. + return GetISOPartsFromEpoch(epochNs, offsetNanoseconds); +} + +/** + * GetISODateTimeFor ( timeZone, epochNs ) + */ +bool js::temporal::GetISODateTimeFor(JSContext* cx, + Handle timeZone, + const EpochNanoseconds& epochNs, + ISODateTime* result) { + MOZ_ASSERT(IsValidEpochNanoseconds(epochNs)); + + // Step 1. int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { + if (!GetOffsetNanosecondsFor(cx, timeZone, epochNs, &offsetNanoseconds)) { return false; } - - // Step 4. MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - // Steps 5-7. - *result = GetPlainDateTimeFor(instant, offsetNanoseconds); + // Steps 2-3. + *result = GetISODateTimeFor(epochNs, offsetNanoseconds); return true; } /** - * GetPlainDateTimeFor ( timeZone, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) + * GetPossibleEpochNanoseconds ( timeZone, isoDateTime ) */ -bool js::temporal::GetPlainDateTimeFor(JSContext* cx, - Handle timeZone, - const Instant& instant, - PlainDateTime* result) { - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - }, - &timeZoneRec)) { +bool js::temporal::GetPossibleEpochNanoseconds( + JSContext* cx, Handle timeZone, + const ISODateTime& isoDateTime, PossibleEpochNanoseconds* result) { + // TODO: https://github.com/tc39/proposal-temporal/pull/3014 + if (!ISODateTimeWithinLimits(isoDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); return false; } - return GetPlainDateTimeFor(cx, timeZoneRec, instant, result); -} + // Step 1. (Not applicable) -/** - * GetPlainDateTimeFor ( timeZone, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -PlainDateTimeObject* js::temporal::GetPlainDateTimeFor( - JSContext* cx, Handle timeZone, const Instant& instant, - Handle calendar) { - // Steps 1-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, timeZone, instant, &dateTime)) { - return nullptr; - } - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); - - // Step 7. - return CreateTemporalDateTime(cx, dateTime, calendar); -} - -/** - * GetPlainDateTimeFor ( timeZone, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -PlainDateTimeObject* js::temporal::GetPlainDateTimeFor( - JSContext* cx, const Instant& instant, Handle calendar, - int64_t offsetNanoseconds) { - MOZ_ASSERT(IsValidEpochInstant(instant)); - - // Steps 1-6. - auto dateTime = GetPlainDateTimeFor(instant, offsetNanoseconds); - MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); - - // Step 7. - return CreateTemporalDateTime(cx, dateTime, calendar); -} - -/** - * Temporal.TimeZone.prototype.getPossibleInstantsFor ( dateTime ) - */ -static bool BuiltinGetPossibleInstantsFor( - JSContext* cx, Handle timeZone, - const PlainDateTime& dateTime, EpochInstantList& possibleInstants) { - MOZ_ASSERT(possibleInstants.length() == 0); - - // Steps 1-3. (Not applicable) - - // Step 4. - if (timeZone->offsetMinutes().isInt32()) { - int32_t offsetMin = timeZone->offsetMinutes().toInt32(); + // Step 2. + PossibleEpochNanoseconds possibleEpochNanoseconds; + if (timeZone.isOffset()) { + int32_t offsetMin = timeZone.offsetMinutes(); MOZ_ASSERT(std::abs(offsetMin) < UnitsPerDay(TemporalUnit::Minute)); - // Step 4.a. - auto epochInstant = - GetUTCEpochNanoseconds(dateTime, InstantSpan::fromMinutes(offsetMin)); + // Step 2.a. + auto epochInstant = GetUTCEpochNanoseconds(isoDateTime) - + EpochDuration::fromMinutes(offsetMin); - // Step 4.b. - possibleInstants.append(epochInstant); + // Step 2.b. + possibleEpochNanoseconds = PossibleEpochNanoseconds{epochInstant}; } else { - // Step 5. - if (!GetNamedTimeZoneEpochNanoseconds(cx, timeZone, dateTime, - possibleInstants)) { + // Step 3. + if (!GetNamedTimeZoneEpochNanoseconds(cx, timeZone, isoDateTime, + &possibleEpochNanoseconds)) { return false; } } - MOZ_ASSERT(possibleInstants.length() <= 2); + MOZ_ASSERT(possibleEpochNanoseconds.length() <= 2); - // Step 7.b. - for (const auto& epochInstant : possibleInstants) { - if (!IsValidEpochInstant(epochInstant)) { + // Step 4. + for (const auto& epochInstant : possibleEpochNanoseconds) { + if (!IsValidEpochNanoseconds(epochInstant)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_INSTANT_INVALID); return false; } } - // Steps 6-8. (Handled in the caller). - return true; -} - -static bool BuiltinGetPossibleInstantsFor( - JSContext* cx, Handle timeZone, - const PlainDateTime& dateTime, MutableHandle list) { - // Temporal.TimeZone.prototype.getInstantFor, step 4. - EpochInstantList possibleInstants; - if (!BuiltinGetPossibleInstantsFor(cx, timeZone, dateTime, - possibleInstants)) { - return false; - } - - // Temporal.TimeZone.prototype.getInstantFor, step 7. - for (const auto& possibleInstant : possibleInstants) { - auto* instant = CreateTemporalInstant(cx, possibleInstant); - if (!instant) { - return false; - } - - if (!list.append(instant)) { - return false; - } - } - return true; -} - -/** - * GetPossibleInstantsFor ( timeZoneRec, dateTime ) - */ -static bool GetPossibleInstantsForSlow( - JSContext* cx, Handle timeZone, - Handle> dateTime, - MutableHandle list) { - MOZ_ASSERT(list.empty()); - - // Step 1. (Inlined call to TimeZoneMethodsRecordCall) - Rooted fval(cx, ObjectValue(*timeZone.getPossibleInstantsFor())); - auto thisv = timeZone.receiver().toObject(); - Rooted arg(cx, ObjectValue(*dateTime)); - Rooted rval(cx); - if (!Call(cx, fval, thisv, arg, &rval)) { - return false; - } - - // Step 2. (Not applicable) - - // Step 3. - JS::ForOfIterator iterator(cx); - if (!iterator.init(rval)) { - return false; - } - - // Step 4. (Not applicable in our implementation.) - // Step 5. - auto min = Instant::max(); - auto max = Instant::min(); - Rooted nextValue(cx); - while (true) { - // Step 5.a. - bool done; - if (!iterator.next(&nextValue, &done)) { - return false; - } - - // Step 5.b. - if (done) { - // Steps 5.b.i-ii. - if (list.length() > 1) { - // Steps 5.b.ii.1-4. (Not applicable in our implementation.) - - // Step 5.b.ii.5. - constexpr auto nsPerDay = - InstantSpan::fromNanoseconds(ToNanoseconds(TemporalUnit::Day)); - if ((max - min).abs() > nsPerDay) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_TIMEZONE_OFFSET_SHIFT_ONE_DAY); - return false; - } - } - - // Step 5.b.iii. - return true; - } - - // Step 5.d. (Reordered) - if (nextValue.isObject()) { - JSObject* obj = &nextValue.toObject(); - if (auto* unwrapped = obj->maybeUnwrapIf()) { - auto instant = ToInstant(unwrapped); - min = std::min(min, instant); - max = std::max(max, instant); - - if (!list.append(obj)) { - return false; - } - continue; - } - } - - // Step 5.c.1. - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, nextValue, - nullptr, "not an instant"); - - // Step 5.c.2. - iterator.closeThrow(); - return false; - } + *result = possibleEpochNanoseconds; + return true; } /** - * GetPossibleInstantsFor ( timeZoneRec, dateTime ) + * AddTime ( time, timeDuration ) */ -static bool GetPossibleInstantsFor( - JSContext* cx, Handle timeZone, - Handle> dateTimeObj, - const PlainDateTime& dateTime, MutableHandle list) { - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); - - // Step 2. (Reordered) - auto getPossibleInstantsFor = timeZone.getPossibleInstantsFor(); - if (!getPossibleInstantsFor) { - bool arrayIterationSane; - if (timeZone.receiver().isString()) { - // "String" time zones don't perform observable array iteration. - arrayIterationSane = true; - } else { - // "Object" time zones need to ensure array iteration is still sane. - if (!IsArrayIterationSane(cx, &arrayIterationSane)) { - return false; - } - } - - if (arrayIterationSane) { - auto builtin = timeZone.receiver().toTimeZoneObjectMaybeBuiltin(); - return BuiltinGetPossibleInstantsFor(cx, builtin, dateTime, list); - } - } - - // Steps 1 and 3-5. - return GetPossibleInstantsForSlow(cx, timeZone, dateTimeObj, list); -} - -/** - * GetPossibleInstantsFor ( timeZoneRec, dateTime ) - */ -bool js::temporal::GetPossibleInstantsFor( - JSContext* cx, Handle timeZone, - Handle dateTime, - MutableHandle list) { - // Step 2. (Reordered) - auto getPossibleInstantsFor = timeZone.getPossibleInstantsFor(); - if (!getPossibleInstantsFor) { - bool arrayIterationSane; - if (timeZone.receiver().isString()) { - // "String" time zones don't perform observable array iteration. - arrayIterationSane = true; - } else { - // "Object" time zones need to ensure array iteration is still sane. - if (!IsArrayIterationSane(cx, &arrayIterationSane)) { - return false; - } - } - - if (arrayIterationSane) { - auto builtin = timeZone.receiver().toTimeZoneObjectMaybeBuiltin(); - return BuiltinGetPossibleInstantsFor(cx, builtin, - ToPlainDateTime(dateTime), list); - } - } - - Rooted dateTimeObj( - cx, CreateTemporalDateTime(cx, ToPlainDateTime(dateTime), - dateTime.calendar())); - if (!dateTimeObj) { - return false; - } - - // Steps 1 and 3-5. - return GetPossibleInstantsForSlow(cx, timeZone, dateTimeObj, list); -} - -/** - * AddTime ( hour, minute, second, millisecond, microsecond, nanosecond, hours, - * minutes, seconds, milliseconds, microseconds, nanoseconds ) - */ -static auto AddTime(const PlainTime& time, int64_t nanoseconds) { +static auto AddTime(const Time& time, int64_t nanoseconds) { MOZ_ASSERT(IsValidTime(time)); MOZ_ASSERT(std::abs(nanoseconds) <= ToNanoseconds(TemporalUnit::Day)); - // Steps 1-3. + // Steps 1-2. return BalanceTime(time, nanoseconds); } /** - * DisambiguatePossibleInstants ( possibleInstants, timeZoneRec, dateTime, - * disambiguation ) + * DisambiguatePossibleEpochNanoseconds ( possibleEpochNs, timeZone, + * isoDateTime, disambiguation ) */ -bool js::temporal::DisambiguatePossibleInstants( - JSContext* cx, Handle possibleInstants, - Handle timeZone, const PlainDateTime& dateTime, - TemporalDisambiguation disambiguation, - MutableHandle> result) { - // Step 1. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); +bool js::temporal::DisambiguatePossibleEpochNanoseconds( + JSContext* cx, const PossibleEpochNanoseconds& possibleEpochNs, + Handle timeZone, const ISODateTime& isoDateTime, + TemporalDisambiguation disambiguation, EpochNanoseconds* result) { + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); - // Step 2. - MOZ_ASSERT_IF(possibleInstants.empty() && - disambiguation != TemporalDisambiguation::Reject, - TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Steps 3-4. - if (possibleInstants.length() == 1) { - result.set(possibleInstants[0]); + // Steps 1-2. + if (possibleEpochNs.length() == 1) { + *result = possibleEpochNs.front(); return true; } - // Steps 5-6. - if (!possibleInstants.empty()) { - // Step 5.a. + // Steps 3-4. + if (!possibleEpochNs.empty()) { + // Step 3.a. if (disambiguation == TemporalDisambiguation::Earlier || disambiguation == TemporalDisambiguation::Compatible) { - result.set(possibleInstants[0]); + *result = possibleEpochNs.front(); return true; } - // Step 5.b. + // Step 3.b. if (disambiguation == TemporalDisambiguation::Later) { - size_t last = possibleInstants.length() - 1; - result.set(possibleInstants[last]); + *result = possibleEpochNs.back(); return true; } - // Step 5.c. + // Step 3.c. MOZ_ASSERT(disambiguation == TemporalDisambiguation::Reject); - // Step 5.d. + // Step 3.d. JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_TIMEZONE_INSTANT_AMBIGUOUS); return false; } - // Step 7. + // Step 5. if (disambiguation == TemporalDisambiguation::Reject) { // TODO: Improve error message to say the date was skipped. JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, @@ -1837,820 +992,169 @@ bool js::temporal::DisambiguatePossibleInstants( return false; } - constexpr auto oneDay = - InstantSpan::fromNanoseconds(ToNanoseconds(TemporalUnit::Day)); + constexpr auto oneDay = EpochDuration::fromDays(1); - // Step 8. - auto epochNanoseconds = GetUTCEpochNanoseconds(dateTime); + auto epochNanoseconds = GetUTCEpochNanoseconds(isoDateTime); - // Steps 9 and 11. + // Step 6 and 8-9. auto dayBefore = epochNanoseconds - oneDay; + MOZ_ASSERT(IsValidEpochNanoseconds(dayBefore)); - // Step 10. - if (!IsValidEpochInstant(dayBefore)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INSTANT_INVALID); - return false; - } - - // Step 12 and 14. + // Step 7 and 10-11. auto dayAfter = epochNanoseconds + oneDay; + MOZ_ASSERT(IsValidEpochNanoseconds(dayAfter)); - // Step 13. - if (!IsValidEpochInstant(dayAfter)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INSTANT_INVALID); - return false; - } - - // Step 15. + // Step 12. int64_t offsetBefore; if (!GetOffsetNanosecondsFor(cx, timeZone, dayBefore, &offsetBefore)) { return false; } MOZ_ASSERT(std::abs(offsetBefore) < ToNanoseconds(TemporalUnit::Day)); - // Step 16. + // Step 13. int64_t offsetAfter; if (!GetOffsetNanosecondsFor(cx, timeZone, dayAfter, &offsetAfter)) { return false; } MOZ_ASSERT(std::abs(offsetAfter) < ToNanoseconds(TemporalUnit::Day)); - // Step 17. + // Step 14. int64_t nanoseconds = offsetAfter - offsetBefore; - // Step 18. - if (std::abs(nanoseconds) > ToNanoseconds(TemporalUnit::Day)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_TIMEZONE_OFFSET_SHIFT_ONE_DAY); - return false; - } + // Step 15. + MOZ_ASSERT(std::abs(nanoseconds) <= ToNanoseconds(TemporalUnit::Day)); - // Step 19. + // Step 16. if (disambiguation == TemporalDisambiguation::Earlier) { - // Steps 19.a-b. - auto earlierTime = ::AddTime(dateTime.time, -nanoseconds); + // Steps 16.a-b. + auto earlierTime = ::AddTime(isoDateTime.time, -nanoseconds); MOZ_ASSERT(std::abs(earlierTime.days) <= 1, "subtracting nanoseconds is at most one day"); - // Step 19.c. - auto earlierDate = BalanceISODate(dateTime.date.year, dateTime.date.month, - dateTime.date.day + earlierTime.days); + // Step 16.c. + auto earlierDate = BalanceISODate(isoDateTime.date, earlierTime.days); - // Step 19.d. - Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - Rooted earlierDateTime( - cx, - PlainDateTimeWithCalendar{{earlierDate, earlierTime.time}, calendar}); + // Step 16.d. + auto earlierDateTime = ISODateTime{earlierDate, earlierTime.time}; - // Step 19.e. - Rooted earlierInstants(cx, InstantVector(cx)); - if (!GetPossibleInstantsFor(cx, timeZone, earlierDateTime, - &earlierInstants)) { + // Step 16.e. + PossibleEpochNanoseconds earlierEpochNs; + if (!GetPossibleEpochNanoseconds(cx, timeZone, earlierDateTime, + &earlierEpochNs)) { return false; } - // Step 19.f. - if (earlierInstants.empty()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_TIMEZONE_INSTANT_AMBIGUOUS); - return false; - } + // Step 16.f. + MOZ_ASSERT(!earlierEpochNs.empty()); - // Step 19.g. - result.set(earlierInstants[0]); + // Step 16.g. + *result = earlierEpochNs.front(); return true; } - // Step 20. + // Step 17. MOZ_ASSERT(disambiguation == TemporalDisambiguation::Compatible || disambiguation == TemporalDisambiguation::Later); - // Steps 21-22. - auto laterTime = ::AddTime(dateTime.time, nanoseconds); + // Steps 18-19. + auto laterTime = ::AddTime(isoDateTime.time, nanoseconds); MOZ_ASSERT(std::abs(laterTime.days) <= 1, "adding nanoseconds is at most one day"); - // Step 23. - auto laterDate = BalanceISODate(dateTime.date.year, dateTime.date.month, - dateTime.date.day + laterTime.days); + // Step 20. + auto laterDate = BalanceISODate(isoDateTime.date, laterTime.days); - // Step 24. - Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - Rooted laterDateTime( - cx, PlainDateTimeWithCalendar{{laterDate, laterTime.time}, calendar}); + // Step 21. + auto laterDateTime = ISODateTime{laterDate, laterTime.time}; + + // Step 22. + PossibleEpochNanoseconds laterEpochNs; + if (!GetPossibleEpochNanoseconds(cx, timeZone, laterDateTime, + &laterEpochNs)) { + return false; + } + + // Steps 23-24. + MOZ_ASSERT(!laterEpochNs.empty()); // Step 25. - Rooted laterInstants(cx, InstantVector(cx)); - if (!GetPossibleInstantsFor(cx, timeZone, laterDateTime, &laterInstants)) { - return false; - } - - // Steps 26-27. - if (laterInstants.empty()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_TIMEZONE_INSTANT_AMBIGUOUS); - return false; - } - - // Step 28. - size_t last = laterInstants.length() - 1; - result.set(laterInstants[last]); + *result = laterEpochNs.back(); return true; } /** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) + * GetEpochNanosecondsFor ( timeZone, isoDateTime, disambiguation ) */ -static bool GetInstantFor(JSContext* cx, Handle timeZone, - Handle> dateTime, - TemporalDisambiguation disambiguation, - MutableHandle> result) { +bool js::temporal::GetEpochNanosecondsFor(JSContext* cx, + Handle timeZone, + const ISODateTime& isoDateTime, + TemporalDisambiguation disambiguation, + EpochNanoseconds* result) { // Step 1. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Step 2. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); - - auto* unwrappedDateTime = dateTime.unwrap(cx); - if (!unwrappedDateTime) { - return false; - } - auto plainDateTime = ToPlainDateTime(unwrappedDateTime); - - // Step 3. - Rooted possibleInstants(cx, InstantVector(cx)); - if (!GetPossibleInstantsFor(cx, timeZone, dateTime, plainDateTime, - &possibleInstants)) { - return false; - } - - // Step 4. - return DisambiguatePossibleInstants(cx, possibleInstants, timeZone, - plainDateTime, disambiguation, result); -} - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -static bool GetInstantFor(JSContext* cx, Handle timeZone, - Handle> dateTime, - TemporalDisambiguation disambiguation, - MutableHandle> result) { - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZoneRec)) { - return false; - } - - return GetInstantFor(cx, timeZoneRec, dateTime, disambiguation, result); -} - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -bool js::temporal::GetInstantFor(JSContext* cx, Handle timeZone, - Handle dateTime, - TemporalDisambiguation disambiguation, - Instant* result) { - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZoneRec)) { - return false; - } - - Rooted> instant(cx); - if (!::GetInstantFor(cx, timeZoneRec, dateTime, disambiguation, &instant)) { - return false; - } - - auto* unwrappedInstant = instant.unwrap(cx); - if (!unwrappedInstant) { - return false; - } - - *result = ToInstant(unwrappedInstant); - return true; -} - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -bool js::temporal::GetInstantFor(JSContext* cx, Handle timeZone, - Handle dateTime, - TemporalDisambiguation disambiguation, - Instant* result) { - // Step 1. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Step 2. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); - - // Step 3. - Rooted possibleInstants(cx, InstantVector(cx)); - if (!GetPossibleInstantsFor(cx, timeZone, dateTime, &possibleInstants)) { - return false; - } - - // Step 4. - Rooted> instant(cx); - if (!DisambiguatePossibleInstants(cx, possibleInstants, timeZone, - ToPlainDateTime(dateTime), disambiguation, - &instant)) { - return false; - } - - auto* unwrappedInstant = instant.unwrap(cx); - if (!unwrappedInstant) { - return false; - } - - *result = ToInstant(unwrappedInstant); - return true; -} - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -bool js::temporal::GetInstantFor(JSContext* cx, Handle timeZone, - Handle dateTime, - TemporalDisambiguation disambiguation, - Instant* result) { - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZoneRec)) { - return false; - } - - return GetInstantFor(cx, timeZoneRec, dateTime, disambiguation, result); -} - -/** - * IsOffsetTimeZoneIdentifier ( offsetString ) - * - * Return true if |offsetString| is the prefix of a time zone offset string. - * Time zone offset strings are be parsed through the |TimeZoneUTCOffsetName| - * production. - * - * TimeZoneUTCOffsetName : - * UTCOffsetMinutePrecision - * - * UTCOffsetMinutePrecision : - * Sign Hour[+Padded] - * Sign Hour[+Padded] TimeSeparator[+Extended] MinuteSecond - * Sign Hour[+Padded] TimeSeparator[~Extended] MinuteSecond - * - * Sign : - * ASCIISign - * U+2212 - * - * ASCIISign : one of + - - * - * NOTE: IANA time zone identifiers can't start with |Sign|. - */ -static bool IsOffsetTimeZoneIdentifierPrefix(JSLinearString* offsetString) { - // Empty string can't be the prefix of |TimeZoneUTCOffsetName|. - if (offsetString->empty()) { - return false; - } - - // Return true iff |offsetString| starts with |Sign|. - char16_t ch = offsetString->latin1OrTwoByteChar(0); - return ch == '+' || ch == '-' || ch == 0x2212; -} - -/** - * Temporal.TimeZone ( identifier ) - */ -static bool TimeZoneConstructor(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. - if (!ThrowIfNotConstructing(cx, args, "Temporal.TimeZone")) { + PossibleEpochNanoseconds possibleEpochNs; + if (!GetPossibleEpochNanoseconds(cx, timeZone, isoDateTime, + &possibleEpochNs)) { return false; } // Step 2. - if (!args.requireAtLeast(cx, "Temporal.TimeZone", 1)) { - return false; + return DisambiguatePossibleEpochNanoseconds( + cx, possibleEpochNs, timeZone, isoDateTime, disambiguation, result); +} + +bool js::temporal::WrapTimeZoneValueObject( + JSContext* cx, MutableHandle timeZone) { + // Handle the common case when |timeZone| is from the current compartment. + if (MOZ_LIKELY(timeZone->compartment() == cx->compartment())) { + return true; } - if (!args[0].isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, args[0], - nullptr, "not a string"); - return false; - } - - Rooted identifier(cx, args[0].toString()->ensureLinear(cx)); - if (!identifier) { - return false; - } - - Rooted canonical(cx); - Rooted offsetMinutes(cx); - if (IsOffsetTimeZoneIdentifierPrefix(identifier)) { - // Step 3. - int32_t minutes; - if (!ParseTimeZoneOffsetString(cx, identifier, &minutes)) { - return false; - } - MOZ_ASSERT(std::abs(minutes) < UnitsPerDay(TemporalUnit::Minute)); - - canonical = FormatOffsetTimeZoneIdentifier(cx, minutes); - if (!canonical) { + if (timeZone->isOffset()) { + auto* obj = CreateTimeZoneObject(cx, timeZone->offsetMinutes()); + if (!obj) { return false; } - offsetMinutes.setInt32(minutes); - } else { - // Step 4. - canonical = ValidateAndCanonicalizeTimeZoneName(cx, identifier); - if (!canonical) { - return false; - } - - offsetMinutes.setUndefined(); + timeZone.set(obj); + return true; } - // Step 5. - auto* timeZone = CreateTemporalTimeZone(cx, args, canonical, offsetMinutes); - if (!timeZone) { + Rooted identifier(cx, timeZone->identifier()); + if (!cx->compartment()->wrap(cx, &identifier)) { return false; } - args.rval().setObject(*timeZone); - return true; -} - -/** - * Temporal.TimeZone.from ( item ) - */ -static bool TimeZone_from(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // Step 1. - Rooted timeZone(cx); - if (!ToTemporalTimeZone(cx, args.get(0), &timeZone)) { + Rooted primaryIdentifier(cx, timeZone->primaryIdentifier()); + if (!cx->compartment()->wrap(cx, &primaryIdentifier)) { return false; } - // Step 2. - auto* obj = ToTemporalTimeZoneObject(cx, timeZone); + Rooted identifierLinear(cx, identifier->ensureLinear(cx)); + if (!identifierLinear) { + return false; + } + + Rooted primaryIdentifierLinear( + cx, primaryIdentifier->ensureLinear(cx)); + if (!primaryIdentifierLinear) { + return false; + } + + auto* obj = + CreateTimeZoneObject(cx, identifierLinear, primaryIdentifierLinear); if (!obj) { return false; } - args.rval().setObject(*obj); + timeZone.set(obj); return true; } -/** - * Temporal.TimeZone.prototype.equals ( timeZoneLike ) - */ -static bool TimeZone_equals(JSContext* cx, const CallArgs& args) { - Rooted timeZone(cx, &args.thisv().toObject()); - - // Step 3. - Rooted other(cx); - if (!ToTemporalTimeZone(cx, args.get(0), &other)) { - return false; - } - - // Step 4. - bool equals; - if (!TimeZoneEquals(cx, timeZone, other, &equals)) { - return false; - } - - args.rval().setBoolean(equals); - return true; -} - -/** - * Temporal.TimeZone.prototype.equals ( timeZoneLike ) - */ -static bool TimeZone_equals(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( instant ) - */ -static bool TimeZone_getOffsetNanosecondsFor(JSContext* cx, - const CallArgs& args) { - Rooted timeZone( - cx, &args.thisv().toObject().as()); - - // Step 3. - Instant instant; - if (!ToTemporalInstant(cx, args.get(0), &instant)) { - return false; - } - - // Steps 4-5. - int64_t offset; - if (!BuiltinGetOffsetNanosecondsFor(cx, timeZone, instant, &offset)) { - return false; - } - - args.rval().setNumber(offset); - return true; -} - -/** - * Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( instant ) - */ -static bool TimeZone_getOffsetNanosecondsFor(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.TimeZone.prototype.getOffsetStringFor ( instant ) - */ -static bool TimeZone_getOffsetStringFor(JSContext* cx, const CallArgs& args) { - Rooted timeZone(cx, &args.thisv().toObject()); - - // Step 3. - Rooted> instant(cx, - ToTemporalInstant(cx, args.get(0))); - if (!instant) { - return false; - } - - // Step 4. - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - }, - &timeZoneRec)) { - return false; - } - - // Step 5. - JSString* str = GetOffsetStringFor(cx, timeZoneRec, instant); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; -} - -/** - * Temporal.TimeZone.prototype.getOffsetStringFor ( instant ) - */ -static bool TimeZone_getOffsetStringFor(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - -/** - * Temporal.TimeZone.prototype.getPlainDateTimeFor ( instant [, calendarLike ] ) - */ -static bool TimeZone_getPlainDateTimeFor(JSContext* cx, const CallArgs& args) { - Rooted timeZone(cx, &args.thisv().toObject()); - - // Step 3. - Rooted> instant(cx, - ToTemporalInstant(cx, args.get(0))); - if (!instant) { - return false; - } - - // Step 4. - Rooted calendar(cx); - if (!ToTemporalCalendarWithISODefault(cx, args.get(1), &calendar)) { - return false; - } - - // Steps 5-6. - auto* result = GetPlainDateTimeFor(cx, timeZone, instant, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.TimeZone.prototype.getPlainDateTimeFor ( instant [, calendarLike ] ) - */ -static bool TimeZone_getPlainDateTimeFor(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - -/** - * Temporal.TimeZone.prototype.getInstantFor ( dateTime [ , options ] ) - */ -static bool TimeZone_getInstantFor(JSContext* cx, const CallArgs& args) { - Rooted timeZone(cx, &args.thisv().toObject()); - - // Step 3. - Rooted> dateTime( - cx, ToTemporalDateTime(cx, args.get(0))); - if (!dateTime) { - return false; - } - - // Steps 4-5. - auto disambiguation = TemporalDisambiguation::Compatible; - if (args.hasDefined(1)) { - // Step 4. - Rooted options( - cx, RequireObjectArg(cx, "options", "getInstantFor", args[1])); - if (!options) { - return false; - } - - // Step 5. - if (!GetTemporalDisambiguationOption(cx, options, &disambiguation)) { - return false; - } - } - - // Steps 6-7. - Rooted> result(cx); - if (!::GetInstantFor(cx, timeZone, dateTime, disambiguation, &result)) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.TimeZone.prototype.getInstantFor ( dateTime [ , options ] ) - */ -static bool TimeZone_getInstantFor(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.TimeZone.prototype.getPossibleInstantsFor ( dateTime ) - */ -static bool TimeZone_getPossibleInstantsFor(JSContext* cx, - const CallArgs& args) { - Rooted timeZone( - cx, &args.thisv().toObject().as()); - - // Step 3. - PlainDateTime dateTime; - if (!ToTemporalDateTime(cx, args.get(0), &dateTime)) { - return false; - } - - // Steps 4-5. - EpochInstantList possibleInstants; - if (!BuiltinGetPossibleInstantsFor(cx, timeZone, dateTime, - possibleInstants)) { - return false; - } - - // Step 6. - size_t length = possibleInstants.length(); - Rooted result(cx, NewDenseFullyAllocatedArray(cx, length)); - if (!result) { - return false; - } - result->ensureDenseInitializedLength(0, length); - - // Step 7. - for (size_t i = 0; i < length; i++) { - // Step 7.a. (Already performed in step 4 in our implementation.) - MOZ_ASSERT(IsValidEpochInstant(possibleInstants[i])); - - // Step 7.b. - auto* instant = CreateTemporalInstant(cx, possibleInstants[i]); - if (!instant) { - return false; - } - - // Step 7.c. - result->initDenseElement(i, ObjectValue(*instant)); - } - - // Step 8. - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.TimeZone.prototype.getPossibleInstantsFor ( dateTime ) - */ -static bool TimeZone_getPossibleInstantsFor(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.TimeZone.prototype.getNextTransition ( startingPoint ) - */ -static bool TimeZone_getNextTransition(JSContext* cx, const CallArgs& args) { - Rooted timeZone( - cx, &args.thisv().toObject().as()); - - // Step 3. - Instant startingPoint; - if (!ToTemporalInstant(cx, args.get(0), &startingPoint)) { - return false; - } - - // Step 4. - if (!timeZone->offsetMinutes().isUndefined()) { - args.rval().setNull(); - return true; - } - - // Step 5. - mozilla::Maybe transition; - if (!GetNamedTimeZoneNextTransition(cx, timeZone, startingPoint, - &transition)) { - return false; - } - - // Step 6. - if (!transition) { - args.rval().setNull(); - return true; - } - - // Step 7. - auto* instant = CreateTemporalInstant(cx, *transition); - if (!instant) { - return false; - } - - args.rval().setObject(*instant); - return true; -} - -/** - * Temporal.TimeZone.prototype.getNextTransition ( startingPoint ) - */ -static bool TimeZone_getNextTransition(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.TimeZone.prototype.getPreviousTransition ( startingPoint ) - */ -static bool TimeZone_getPreviousTransition(JSContext* cx, - const CallArgs& args) { - Rooted timeZone( - cx, &args.thisv().toObject().as()); - - // Step 3. - Instant startingPoint; - if (!ToTemporalInstant(cx, args.get(0), &startingPoint)) { - return false; - } - - // Step 4. - if (!timeZone->offsetMinutes().isUndefined()) { - args.rval().setNull(); - return true; - } - - // Step 5. - mozilla::Maybe transition; - if (!GetNamedTimeZonePreviousTransition(cx, timeZone, startingPoint, - &transition)) { - return false; - } - - // Step 6. - if (!transition) { - args.rval().setNull(); - return true; - } - - // Step 7. - auto* instant = CreateTemporalInstant(cx, *transition); - if (!instant) { - return false; - } - - args.rval().setObject(*instant); - return true; -} - -/** - * Temporal.TimeZone.prototype.getPreviousTransition ( startingPoint ) - */ -static bool TimeZone_getPreviousTransition(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - -/** - * Temporal.TimeZone.prototype.toString ( ) - */ -static bool TimeZone_toString(JSContext* cx, const CallArgs& args) { - auto* timeZone = &args.thisv().toObject().as(); - - // Steps 3-4. - args.rval().setString(timeZone->identifier()); - return true; -} - -/** - * Temporal.TimeZone.prototype.toString ( ) - */ -static bool TimeZone_toString(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * Temporal.TimeZone.prototype.toJSON ( ) - */ -static bool TimeZone_toJSON(JSContext* cx, const CallArgs& args) { - auto* timeZone = &args.thisv().toObject().as(); - - // Steps 3-4. - args.rval().setString(timeZone->identifier()); - return true; -} - -/** - * Temporal.TimeZone.prototype.toJSON ( ) - */ -static bool TimeZone_toJSON(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -/** - * get Temporal.TimeZone.prototype.id - */ -static bool TimeZone_id(JSContext* cx, const CallArgs& args) { - auto* timeZone = &args.thisv().toObject().as(); - - // Steps 3-4. - args.rval().setString(timeZone->identifier()); - return true; -} - -/** - * get Temporal.TimeZone.prototype.id - */ -static bool TimeZone_id(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - -void js::temporal::TimeZoneObjectMaybeBuiltin::finalize(JS::GCContext* gcx, - JSObject* obj) { +void js::temporal::TimeZoneObject::finalize(JS::GCContext* gcx, JSObject* obj) { MOZ_ASSERT(gcx->onMainThread()); - if (auto* timeZone = obj->as().getTimeZone()) { - intl::RemoveICUCellMemory(gcx, obj, TimeZoneObject::EstimatedMemoryUse); + if (auto* timeZone = obj->as().getTimeZone()) { + intl::RemoveICUCellMemory(gcx, obj, EstimatedMemoryUse); delete timeZone; } } @@ -2671,66 +1175,6 @@ const JSClassOps TimeZoneObject::classOps_ = { const JSClass TimeZoneObject::class_ = { "Temporal.TimeZone", JSCLASS_HAS_RESERVED_SLOTS(TimeZoneObject::SLOT_COUNT) | - JSCLASS_HAS_CACHED_PROTO(JSProto_TimeZone) | JSCLASS_FOREGROUND_FINALIZE, &TimeZoneObject::classOps_, - &TimeZoneObject::classSpec_, -}; - -const JSClass& TimeZoneObject::protoClass_ = PlainObject::class_; - -static const JSFunctionSpec TimeZone_methods[] = { - JS_FN("from", TimeZone_from, 1, 0), - JS_FS_END, -}; - -static const JSFunctionSpec TimeZone_prototype_methods[] = { - JS_FN("equals", TimeZone_equals, 1, 0), - JS_FN("getOffsetNanosecondsFor", TimeZone_getOffsetNanosecondsFor, 1, 0), - JS_FN("getOffsetStringFor", TimeZone_getOffsetStringFor, 1, 0), - JS_FN("getPlainDateTimeFor", TimeZone_getPlainDateTimeFor, 1, 0), - JS_FN("getInstantFor", TimeZone_getInstantFor, 1, 0), - JS_FN("getPossibleInstantsFor", TimeZone_getPossibleInstantsFor, 1, 0), - JS_FN("getNextTransition", TimeZone_getNextTransition, 1, 0), - JS_FN("getPreviousTransition", TimeZone_getPreviousTransition, 1, 0), - JS_FN("toString", TimeZone_toString, 0, 0), - JS_FN("toJSON", TimeZone_toJSON, 0, 0), - JS_FS_END, -}; - -static const JSPropertySpec TimeZone_prototype_properties[] = { - JS_PSG("id", TimeZone_id, 0), - JS_STRING_SYM_PS(toStringTag, "Temporal.TimeZone", JSPROP_READONLY), - JS_PS_END, -}; - -const ClassSpec TimeZoneObject::classSpec_ = { - GenericCreateConstructor, - GenericCreatePrototype, - TimeZone_methods, - nullptr, - TimeZone_prototype_methods, - TimeZone_prototype_properties, - nullptr, - ClassSpec::DontDefineConstructor, -}; - -const JSClassOps BuiltinTimeZoneObject::classOps_ = { - nullptr, // addProperty - nullptr, // delProperty - nullptr, // enumerate - nullptr, // newEnumerate - nullptr, // resolve - nullptr, // mayResolve - BuiltinTimeZoneObject::finalize, // finalize - nullptr, // call - nullptr, // construct - nullptr, // trace -}; - -const JSClass BuiltinTimeZoneObject::class_ = { - "Temporal.BuiltinTimeZone", - JSCLASS_HAS_RESERVED_SLOTS(BuiltinTimeZoneObject::SLOT_COUNT) | - JSCLASS_FOREGROUND_FINALIZE, - &BuiltinTimeZoneObject::classOps_, }; diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.h index f13421111ab..6f587cf8bc5 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/TimeZone.h @@ -9,49 +9,56 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" -#include "mozilla/EnumSet.h" +#include "mozilla/Maybe.h" +#include #include #include -#include "builtin/temporal/Wrapped.h" -#include "js/GCVector.h" +#include "builtin/temporal/TemporalTypes.h" #include "js/RootingAPI.h" #include "js/TypeDecls.h" #include "js/Value.h" #include "vm/JSObject.h" #include "vm/NativeObject.h" +#include "vm/StringType.h" -class JSLinearString; class JS_PUBLIC_API JSTracer; struct JSClassOps; -namespace js { -struct ClassSpec; -} - namespace mozilla::intl { class TimeZone; } namespace js::temporal { -class TimeZoneObjectMaybeBuiltin : public NativeObject { +class TimeZoneObject : public NativeObject { public: + static const JSClass class_; + static constexpr uint32_t IDENTIFIER_SLOT = 0; - static constexpr uint32_t OFFSET_MINUTES_SLOT = 1; - static constexpr uint32_t INTL_TIMEZONE_SLOT = 2; - static constexpr uint32_t SLOT_COUNT = 3; + static constexpr uint32_t PRIMARY_IDENTIFIER_SLOT = 1; + static constexpr uint32_t OFFSET_MINUTES_SLOT = 2; + static constexpr uint32_t INTL_TIMEZONE_SLOT = 3; + static constexpr uint32_t SLOT_COUNT = 4; // Estimated memory use for intl::TimeZone (see IcuMemoryUsage). static constexpr size_t EstimatedMemoryUse = 6840; - JSString* identifier() const { - return getFixedSlot(IDENTIFIER_SLOT).toString(); + bool isOffset() const { return getFixedSlot(OFFSET_MINUTES_SLOT).isInt32(); } + + JSLinearString* identifier() const { + return &getFixedSlot(IDENTIFIER_SLOT).toString()->asLinear(); } - const auto& offsetMinutes() const { - return getFixedSlot(OFFSET_MINUTES_SLOT); + JSLinearString* primaryIdentifier() const { + MOZ_ASSERT(!isOffset()); + return &getFixedSlot(PRIMARY_IDENTIFIER_SLOT).toString()->asLinear(); + } + + int32_t offsetMinutes() const { + MOZ_ASSERT(isOffset()); + return getFixedSlot(OFFSET_MINUTES_SLOT).toInt32(); } mozilla::intl::TimeZone* getTimeZone() const { @@ -66,85 +73,61 @@ class TimeZoneObjectMaybeBuiltin : public NativeObject { setFixedSlot(INTL_TIMEZONE_SLOT, JS::PrivateValue(timeZone)); } - protected: + private: + static const JSClassOps classOps_; + static void finalize(JS::GCContext* gcx, JSObject* obj); }; -class TimeZoneObject : public TimeZoneObjectMaybeBuiltin { - public: - static const JSClass class_; - static const JSClass& protoClass_; - - private: - static const JSClassOps classOps_; - static const ClassSpec classSpec_; -}; - -class BuiltinTimeZoneObject : public TimeZoneObjectMaybeBuiltin { - public: - static const JSClass class_; - - private: - static const JSClassOps classOps_; -}; - } /* namespace js::temporal */ -template <> -inline bool JSObject::is() const { - return is() || - is(); -} - namespace js::temporal { /** - * Temporal time zones can be either objects or strings. Objects are either - * instances of `Temporal.TimeZone` or user-defined time zones. Strings are - * either canonical time zone identifiers or time zone offset strings. + * Temporal time zones are either available named time zones or offset time + * zones. * - * Examples of valid Temporal time zones: - * - Any object - * - "UTC" - * - "America/New_York" + * The identifier of an available named time zones is an available named + * time zone identifier, which is either a primary time zone identifier or a + * non-primary time zone identifier. + * + * The identifier of an offset time zone is an offset time zone identifier. + * + * Temporal methods always return the normalized format of a time zone + * identifier. Available named time zone identifier are always in normalized + * format. + * + * Examples of valid available time zone identifiers in normalized format: + * - "UTC" (primary identifier) + * - "Etc/UTC" (non-primary identifier) + * - "America/New_York" (primary identifier) * - "+00:00" * - * Examples of invalid Temporal time zones: - * - Number values + * Examples of valid available time zone identifiers in non-normalized format: + * - "+00" + * - "-00:00" + * + * Examples of invalid available time zone identifiers: * - "utc" (wrong case) - * - "Etc/UTC" (canonical name is "UTC") - * - "+00" (missing minutes part) * - "+00:00:00" (sub-minute precision) * - "+00:00:01" (sub-minute precision) - * - "-00:00" (wrong sign for zero offset) - * - * String-valued Temporal time zones are an optimization to avoid allocating - * `Temporal.TimeZone` objects when creating `Temporal.ZonedDateTime` objects. - * For example `Temporal.ZonedDateTime.from("1970-01-01[UTC]")` doesn't require - * to allocate a fresh `Temporal.TimeZone` object for the "UTC" time zone. - * - * The specification creates new `Temporal.TimeZone` objects whenever any - * operation is performed on a string-valued Temporal time zone. This newly - * created object can't be accessed by the user and implementations are expected - * to optimize away the allocation. * * The following two implementation approaches are possible: * - * 1. Represent string-valued time zones as JSStrings. Additionally keep a - * mapping from JSString to `mozilla::intl::TimeZone` to avoid repeatedly - * creating new `mozilla::intl::TimeZone` for time zone operations. Offset - * string time zones have to be special cased, because they don't use + * 1. Represent time zones as JSStrings. Additionally keep a mapping from + * JSString to `mozilla::intl::TimeZone` to avoid repeatedly creating new + * `mozilla::intl::TimeZone` for time zone operations. Offset string time + * zones have to be special cased, because they don't use * `mozilla::intl::TimeZone`. Either detect offset strings by checking the * time zone identifier or store offset strings as the offset in minutes * value to avoid reparsing the offset string again and again. - * 2. Represent string-valued time zones as `Temporal.TimeZone`-like objects. - * These internal `Temporal.TimeZone`-like objects must not be exposed to - * user-code. + * 2. Represent time zones as objects which hold `mozilla::intl::TimeZone` in + * an internal slot. * * Option 2 is a bit easier to implement, so we use this approach for now. */ class MOZ_STACK_CLASS TimeZoneValue final { - JSObject* object_ = nullptr; + TimeZoneObject* object_ = nullptr; public: /** @@ -153,24 +136,17 @@ class MOZ_STACK_CLASS TimeZoneValue final { TimeZoneValue() = default; /** - * Initialize this TimeZoneValue with a "string" time zone object. + * Initialize this TimeZoneValue with a time zone object. */ - explicit TimeZoneValue(BuiltinTimeZoneObject* timeZone) : object_(timeZone) { - MOZ_ASSERT(isString()); + explicit TimeZoneValue(TimeZoneObject* timeZone) : object_(timeZone) { + MOZ_ASSERT(object_); } /** - * Initialize this TimeZoneValue with an "object" time zone object. + * Initialize this TimeZoneValue from a slot Value. */ - explicit TimeZoneValue(JSObject* timeZone) : object_(timeZone) { - MOZ_ASSERT(isObject()); - } - - /** - * Initialize this TimeZoneValue from a slot Value, which must be either a - * "string" or "object" time zone object. - */ - explicit TimeZoneValue(const JS::Value& value) : object_(&value.toObject()) {} + explicit TimeZoneValue(const JS::Value& value) + : object_(&value.toObject().as()) {} /** * Return true if this TimeZoneValue is not null. @@ -178,58 +154,51 @@ class MOZ_STACK_CLASS TimeZoneValue final { explicit operator bool() const { return !!object_; } /** - * Return true if this TimeZoneValue is a "string" time zone. + * Return true if this TimeZoneValue is an offset time zone. */ - bool isString() const { - return object_ && object_->is(); - } - - /** - * Return true if this TimeZoneValue is an "object" time zone. - */ - bool isObject() const { return object_ && !isString(); } - - /** - * Return true if this TimeZoneValue holds a TimeZoneObjectMaybeBuiltin. - */ - bool isTimeZoneObjectMaybeBuiltin() const { - return object_ && object_->is(); - } - - /** - * Return this "string" time zone. - */ - auto* toString() const { - MOZ_ASSERT(isString()); - return &object_->as(); - } - - /** - * Return this "object" time zone. - */ - JSObject* toObject() const { - MOZ_ASSERT(isObject()); - return object_; - } - - /** - * Return the underlying object as a TimeZoneObjectMaybeBuiltin. - */ - auto* toTimeZoneObjectMaybeBuiltin() const { - MOZ_ASSERT(isTimeZoneObjectMaybeBuiltin()); - return &object_->as(); - } - - /** - * Return the Value representation of this TimeZoneValue. - */ - JS::Value toValue() const { - if (isString()) { - return JS::StringValue(toString()->identifier()); - } - + bool isOffset() const { MOZ_ASSERT(object_); - return JS::ObjectValue(*object_); + return object_->isOffset(); + } + + /** + * Return the offset of an offset time zone. + */ + auto offsetMinutes() const { + MOZ_ASSERT(object_); + return object_->offsetMinutes(); + } + + /** + * Return the time zone identifier. + */ + auto* identifier() const { + MOZ_ASSERT(object_); + return object_->identifier(); + } + + /** + * Return the primary time zone identifier of a named time zone. + */ + auto* primaryIdentifier() const { + MOZ_ASSERT(object_); + return object_->primaryIdentifier(); + } + + /** + * Return the time zone implementation. + */ + auto* getTimeZone() const { + MOZ_ASSERT(object_); + return object_->getTimeZone(); + } + + /** + * Return the underlying TimeZoneObject. + */ + auto* toTimeZoneObject() const { + MOZ_ASSERT(object_); + return object_; } /** @@ -248,281 +217,147 @@ class MOZ_STACK_CLASS TimeZoneValue final { void trace(JSTracer* trc); }; -enum class TimeZoneMethod { - GetOffsetNanosecondsFor, - GetPossibleInstantsFor, -}; +class PossibleEpochNanoseconds final { + // GetPossibleEpochNanoseconds can return up-to two elements. + static constexpr size_t MaxLength = 2; -class MOZ_STACK_CLASS TimeZoneRecord final { - TimeZoneValue receiver_; + std::array array_ = {}; + size_t length_ = 0; - // Null unless non-builtin time zone methods are used. - JSObject* getOffsetNanosecondsFor_ = nullptr; - JSObject* getPossibleInstantsFor_ = nullptr; - -#ifdef DEBUG - mozilla::EnumSet lookedUp_{}; -#endif + void append(const EpochNanoseconds& epochNs) { array_[length_++] = epochNs; } public: - /** - * Default initialize this TimeZoneRecord. - */ - TimeZoneRecord() = default; + PossibleEpochNanoseconds() = default; - explicit TimeZoneRecord(const TimeZoneValue& receiver) - : receiver_(receiver) {} - - const auto& receiver() const { return receiver_; } - auto* getOffsetNanosecondsFor() const { return getOffsetNanosecondsFor_; } - auto* getPossibleInstantsFor() const { return getPossibleInstantsFor_; } - -#ifdef DEBUG - auto& lookedUp() const { return lookedUp_; } - auto& lookedUp() { return lookedUp_; } -#endif - - // Helper methods for (Mutable)WrappedPtrOperations. - auto* receiverDoNotUse() const { return &receiver_; } - auto* getOffsetNanosecondsForDoNotUse() const { - return &getOffsetNanosecondsFor_; + explicit PossibleEpochNanoseconds(const EpochNanoseconds& epochNs) { + append(epochNs); } - auto* getOffsetNanosecondsForDoNotUse() { return &getOffsetNanosecondsFor_; } - auto* getPossibleInstantsForDoNotUse() const { - return &getPossibleInstantsFor_; - } - auto* getPossibleInstantsForDoNotUse() { return &getPossibleInstantsFor_; } - // Trace implementation. - void trace(JSTracer* trc); + explicit PossibleEpochNanoseconds(const EpochNanoseconds& earlier, + const EpochNanoseconds& later) { + MOZ_ASSERT(earlier <= later); + append(earlier); + append(later); + } + + size_t length() const { return length_; } + bool empty() const { return length_ == 0; } + + const auto& operator[](size_t i) const { return array_[i]; } + + auto begin() const { return array_.begin(); } + auto end() const { return array_.begin() + length_; } + + const auto& front() const { + MOZ_ASSERT(length_ > 0); + return array_[0]; + } + const auto& back() const { + MOZ_ASSERT(length_ > 0); + return array_[length_ - 1]; + } }; -struct Instant; struct ParsedTimeZone; -struct PlainDateTime; -class CalendarValue; -class InstantObject; -class PlainDateTimeObject; -class PlainDateTimeWithCalendar; enum class TemporalDisambiguation; /** - * IsValidTimeZoneName ( timeZone ) - * IsAvailableTimeZoneName ( timeZone ) + * SystemTimeZoneIdentifier ( ) */ -bool IsValidTimeZoneName(JSContext* cx, JS::Handle timeZone, - JS::MutableHandle validatedTimeZone); +JSLinearString* SystemTimeZoneIdentifier(JSContext* cx); /** - * CanonicalizeTimeZoneName ( timeZone ) + * SystemTimeZoneIdentifier ( ) */ -JSString* CanonicalizeTimeZoneName(JSContext* cx, - JS::Handle timeZone); +bool SystemTimeZone(JSContext* cx, JS::MutableHandle result); /** - * IsValidTimeZoneName ( timeZone ) - * IsAvailableTimeZoneName ( timeZone ) - * CanonicalizeTimeZoneName ( timeZone ) - */ -JSString* ValidateAndCanonicalizeTimeZoneName(JSContext* cx, - JS::Handle timeZone); - -/** - * CreateTemporalTimeZone ( identifier [ , newTarget ] ) - */ -BuiltinTimeZoneObject* CreateTemporalTimeZone(JSContext* cx, - JS::Handle identifier); - -/** - * ToTemporalTimeZoneSlotValue ( temporalTimeZoneLike ) + * ToTemporalTimeZoneIdentifier ( temporalTimeZoneLike ) */ bool ToTemporalTimeZone(JSContext* cx, JS::Handle temporalTimeZoneLike, JS::MutableHandle result); /** - * ToTemporalTimeZoneSlotValue ( temporalTimeZoneLike ) + * ToTemporalTimeZoneIdentifier ( temporalTimeZoneLike ) */ bool ToTemporalTimeZone(JSContext* cx, JS::Handle string, JS::MutableHandle result); -/** - * ToTemporalTimeZoneObject ( timeZoneSlotValue ) - */ -JSObject* ToTemporalTimeZoneObject(JSContext* cx, - JS::Handle timeZone); - -/** - * ToTemporalTimeZoneIdentifier ( timeZoneSlotValue ) - */ -JSString* ToTemporalTimeZoneIdentifier(JSContext* cx, - JS::Handle timeZone); - /** * TimeZoneEquals ( one, two ) */ -bool TimeZoneEquals(JSContext* cx, JS::Handle one, - JS::Handle two, bool* equals); +bool TimeZoneEquals(const TimeZoneValue& one, const TimeZoneValue& two); /** - * TimeZoneEquals ( one, two ) + * GetISODateTimeFor ( timeZone, epochNs ) */ -bool TimeZoneEquals(JSContext* cx, JS::Handle one, - JS::Handle two, bool* equals); +ISODateTime GetISODateTimeFor(const EpochNanoseconds& epochNs, + int64_t offsetNanoseconds); /** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) + * GetISODateTimeFor ( timeZone, epochNs ) */ -PlainDateTimeObject* GetPlainDateTimeFor(JSContext* cx, - JS::Handle timeZone, - const Instant& instant, - JS::Handle calendar); +bool GetISODateTimeFor(JSContext* cx, JS::Handle timeZone, + const EpochNanoseconds& epochNs, ISODateTime* result); /** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) + * GetEpochNanosecondsFor ( timeZone, isoDateTime, disambiguation ) */ -PlainDateTimeObject* GetPlainDateTimeFor(JSContext* cx, const Instant& instant, - JS::Handle calendar, - int64_t offsetNanoseconds); +bool GetEpochNanosecondsFor(JSContext* cx, JS::Handle timeZone, + const ISODateTime& isoDateTime, + TemporalDisambiguation disambiguation, + EpochNanoseconds* result); /** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -PlainDateTime GetPlainDateTimeFor(const Instant& instant, - int64_t offsetNanoseconds); - -/** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -bool GetPlainDateTimeFor(JSContext* cx, JS::Handle timeZone, - const Instant& instant, PlainDateTime* result); - -/** - * GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , - * precalculatedOffsetNanoseconds ] ) - */ -bool GetPlainDateTimeFor(JSContext* cx, JS::Handle timeZone, - const Instant& instant, PlainDateTime* result); - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -bool GetInstantFor(JSContext* cx, JS::Handle timeZone, - JS::Handle dateTime, - TemporalDisambiguation disambiguation, Instant* result); - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -bool GetInstantFor(JSContext* cx, JS::Handle timeZone, - JS::Handle dateTime, - TemporalDisambiguation disambiguation, Instant* result); - -/** - * GetInstantFor ( timeZoneRec, dateTime, disambiguation ) - */ -bool GetInstantFor(JSContext* cx, JS::Handle timeZone, - JS::Handle dateTime, - TemporalDisambiguation disambiguation, Instant* result); - -/** - * FormatUTCOffsetNanoseconds ( offsetNanoseconds ) - */ -JSString* FormatUTCOffsetNanoseconds(JSContext* cx, int64_t offsetNanoseconds); - -/** - * GetOffsetStringFor ( timeZoneRec, instant ) - */ -JSString* GetOffsetStringFor(JSContext* cx, JS::Handle timeZone, - const Instant& instant); - -/** - * GetOffsetStringFor ( timeZoneRec, instant ) - */ -JSString* GetOffsetStringFor(JSContext* cx, JS::Handle timeZone, - JS::Handle> instant); - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -bool GetOffsetNanosecondsFor(JSContext* cx, JS::Handle timeZone, - JS::Handle> instant, - int64_t* offsetNanoseconds); - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) + * GetOffsetNanosecondsFor ( timeZone, epochNs ) */ bool GetOffsetNanosecondsFor(JSContext* cx, JS::Handle timeZone, - JS::Handle> instant, + const EpochNanoseconds& epochNs, int64_t* offsetNanoseconds); /** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) + * GetPossibleEpochNanoseconds ( timeZone, isoDateTime ) */ -bool GetOffsetNanosecondsFor(JSContext* cx, JS::Handle timeZone, - const Instant& instant, - int64_t* offsetNanoseconds); - -/** - * GetOffsetNanosecondsFor ( timeZoneRec, instant ) - */ -bool GetOffsetNanosecondsFor(JSContext* cx, JS::Handle timeZone, - const Instant& instant, - int64_t* offsetNanoseconds); - -using InstantVector = JS::StackGCVector>; - -/** - * GetPossibleInstantsFor ( timeZoneRec, dateTime ) - */ -bool GetPossibleInstantsFor(JSContext* cx, JS::Handle timeZone, - JS::Handle dateTime, - JS::MutableHandle list); - -/** - * DisambiguatePossibleInstants ( possibleInstants, timeZoneRec, dateTime, - * disambiguation ) - */ -bool DisambiguatePossibleInstants( - JSContext* cx, JS::Handle possibleInstants, - JS::Handle timeZone, const PlainDateTime& dateTime, - TemporalDisambiguation disambiguation, - JS::MutableHandle> result); - -/** - * CreateTimeZoneMethodsRecord ( timeZone, methods ) - */ -bool CreateTimeZoneMethodsRecord(JSContext* cx, +bool GetPossibleEpochNanoseconds(JSContext* cx, JS::Handle timeZone, - mozilla::EnumSet methods, - JS::MutableHandle result); - -#ifdef DEBUG -/** - * TimeZoneMethodsRecordHasLookedUp ( timeZoneRec, methodName ) - */ -inline bool TimeZoneMethodsRecordHasLookedUp(const TimeZoneRecord& timeZone, - TimeZoneMethod methodName) { - // Steps 1-4. - return timeZone.lookedUp().contains(methodName); -} -#endif + const ISODateTime& isoDateTime, + PossibleEpochNanoseconds* result); /** - * TimeZoneMethodsRecordIsBuiltin ( timeZoneRec ) + * DisambiguatePossibleEpochNanoseconds ( possibleEpochNs, timeZone, + * isoDateTime, disambiguation ) */ -inline bool TimeZoneMethodsRecordIsBuiltin(const TimeZoneRecord& timeZone) { - // Steps 1-2. - return timeZone.receiver().isString(); -} +bool DisambiguatePossibleEpochNanoseconds( + JSContext* cx, const PossibleEpochNanoseconds& possibleEpochNs, + JS::Handle timeZone, const ISODateTime& isoDateTime, + TemporalDisambiguation disambiguation, EpochNanoseconds* result); + +/** + * GetNamedTimeZoneNextTransition ( timeZoneIdentifier, epochNanoseconds ) + */ +bool GetNamedTimeZoneNextTransition(JSContext* cx, + JS::Handle timeZone, + const EpochNanoseconds& epochNanoseconds, + mozilla::Maybe* result); + +/** + * GetNamedTimeZonePreviousTransition ( timeZoneIdentifier, epochNanoseconds ) + */ +bool GetNamedTimeZonePreviousTransition( + JSContext* cx, JS::Handle timeZone, + const EpochNanoseconds& epochNanoseconds, + mozilla::Maybe* result); + +/** + * GetStartOfDay ( timeZone, isoDate ) + */ +bool GetStartOfDay(JSContext* cx, JS::Handle timeZone, + const ISODate& isoDate, EpochNanoseconds* result); // Helper for MutableWrappedPtrOperations. bool WrapTimeZoneValueObject(JSContext* cx, - JS::MutableHandle timeZone); + JS::MutableHandle timeZone); } /* namespace js::temporal */ @@ -537,29 +372,15 @@ class WrappedPtrOperations { public: explicit operator bool() const { return !!container(); } - bool isString() const { return container().isString(); } + bool isOffset() const { return container().isOffset(); } - bool isObject() const { return container().isObject(); } + auto offsetMinutes() const { return container().offsetMinutes(); } - JS::Handle toString() const { - MOZ_ASSERT(container().isString()); - auto h = JS::Handle::fromMarkedLocation(container().address()); - return h.template as(); - } + auto* identifier() const { return container().identifier(); } - JS::Handle toObject() const { - MOZ_ASSERT(container().isObject()); - return JS::Handle::fromMarkedLocation(container().address()); - } + auto* primaryIdentifier() const { return container().primaryIdentifier(); } - JS::Handle - toTimeZoneObjectMaybeBuiltin() const { - MOZ_ASSERT(container().isTimeZoneObjectMaybeBuiltin()); - auto h = JS::Handle::fromMarkedLocation(container().address()); - return h.template as(); - } - - JS::Value toValue() const { return container().toValue(); } + auto* getTimeZone() const { return container().getTimeZone(); } JS::Value toSlotValue() const { return container().toSlotValue(); } }; @@ -574,53 +395,13 @@ class MutableWrappedPtrOperations * Wrap the time zone value into the current compartment. */ bool wrap(JSContext* cx) { - MOZ_ASSERT(container().isString() || container().isObject()); - auto mh = - JS::MutableHandle::fromMarkedLocation(container().address()); + MOZ_ASSERT(container()); + auto mh = JS::MutableHandle::fromMarkedLocation( + container().address()); return temporal::WrapTimeZoneValueObject(cx, mh); } }; -template -class WrappedPtrOperations { - const auto& container() const { - return static_cast(this)->get(); - } - - public: - JS::Handle receiver() const { - return JS::Handle::fromMarkedLocation( - container().receiverDoNotUse()); - } - - JS::Handle getOffsetNanosecondsFor() const { - return JS::Handle::fromMarkedLocation( - container().getOffsetNanosecondsForDoNotUse()); - } - - JS::Handle getPossibleInstantsFor() const { - return JS::Handle::fromMarkedLocation( - container().getPossibleInstantsForDoNotUse()); - } -}; - -template -class MutableWrappedPtrOperations - : public WrappedPtrOperations { - auto& container() { return static_cast(this)->get(); } - - public: - JS::MutableHandle getOffsetNanosecondsFor() { - return JS::MutableHandle::fromMarkedLocation( - container().getOffsetNanosecondsForDoNotUse()); - } - - JS::MutableHandle getPossibleInstantsFor() { - return JS::MutableHandle::fromMarkedLocation( - container().getPossibleInstantsForDoNotUse()); - } -}; - } /* namespace js */ #endif /* builtin_temporal_TimeZone_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.cpp index 3b93a8739d4..d3ac9d67c05 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.cpp @@ -11,24 +11,22 @@ #include #include #include -#include -#include +#include #include "builtin/temporal/Calendar.h" #include "builtin/temporal/Crash.h" #include "builtin/temporal/Instant.h" #include "builtin/temporal/PlainDate.h" +#include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/PlainMonthDay.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ZonedDateTime.h" -#include "gc/Policy.h" #include "js/RootingAPI.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/StringType.h" using namespace js; @@ -45,6 +43,8 @@ enum class TemporalStringFormat { Instant, }; +enum class Critical : bool { No, Yes }; + class TemporalStringBuilder { JSStringBuilder sb_; @@ -145,9 +145,19 @@ class TemporalStringBuilder { } } - auto* finishString() { return sb_.finishString(); } + bool appendCalendarAnnnotation(std::string_view id, Critical critical) { + std::string_view start = bool(critical) ? "[!u-ca=" : "[u-ca="; + return sb_.append(start.data(), start.length()) && + sb_.append(id.data(), id.length()) && sb_.append(']'); + } - auto& builder() { return sb_; } + bool appendTimeZoneAnnnotation(const JSLinearString* id, Critical critical) { + std::string_view start = bool(critical) ? "[!" : "["; + return sb_.append(start.data(), start.length()) && sb_.append(id) && + sb_.append(']'); + } + + auto* finishString() { return sb_.finishString(); } }; /** @@ -199,8 +209,8 @@ static void FormatFractionalSeconds(TemporalStringBuilder& result, /** * FormatTimeString ( hour, minute, second, subSecondNanoseconds, precision ) */ -static void FormatTimeString(TemporalStringBuilder& result, - const PlainTime& time, Precision precision) { +static void FormatTimeString(TemporalStringBuilder& result, const Time& time, + Precision precision) { // Step 1. result.appendTwoDigit(time.hour); @@ -220,7 +230,7 @@ static void FormatTimeString(TemporalStringBuilder& result, } static void FormatDateString(TemporalStringBuilder& result, - const PlainDate& date) { + const ISODate& date) { result.appendYear(date.year); result.append('-'); result.appendTwoDigit(date.month); @@ -229,7 +239,7 @@ static void FormatDateString(TemporalStringBuilder& result, } static void FormatDateTimeString(TemporalStringBuilder& result, - const PlainDateTime& dateTime, + const ISODateTime& dateTime, Precision precision) { FormatDateString(result, dateTime.date); result.append('T'); @@ -296,101 +306,55 @@ static void FormatDateTimeUTCOffsetRounded(TemporalStringBuilder& result, * FormatCalendarAnnotation ( id, showCalendar ) */ static bool FormatCalendarAnnotation(TemporalStringBuilder& result, - JSLinearString* id, + const CalendarValue& calendar, ShowCalendar showCalendar) { switch (showCalendar) { case ShowCalendar::Never: return true; case ShowCalendar::Auto: { - if (StringEqualsLiteral(id, "iso8601")) { + if (calendar.identifier() == CalendarId::ISO8601) { return true; } [[fallthrough]]; } case ShowCalendar::Always: { - auto& sb = result.builder(); - return sb.append("[u-ca=") && sb.append(id) && sb.append(']'); + auto id = CalendarIdentifier(calendar); + return result.appendCalendarAnnnotation(id, Critical::No); } case ShowCalendar::Critical: { - auto& sb = result.builder(); - return sb.append("[!u-ca=") && sb.append(id) && sb.append(']'); + auto id = CalendarIdentifier(calendar); + return result.appendCalendarAnnnotation(id, Critical::Yes); } } MOZ_CRASH("bad calendar option"); } -/** - * MaybeFormatCalendarAnnotation ( calendar, showCalendar ) - */ -static bool MaybeFormatCalendarAnnotation(JSContext* cx, - TemporalStringBuilder& result, - Handle calendar, - ShowCalendar showCalendar) { - // Step 1. - if (showCalendar == ShowCalendar::Never) { - return true; - } - - // Step 2. - JSLinearString* calendarIdentifier = - ToTemporalCalendarIdentifier(cx, calendar); - if (!calendarIdentifier) { - return false; - } - - // Step 3. - return FormatCalendarAnnotation(result, calendarIdentifier, showCalendar); -} - static bool FormatTimeZoneAnnotation(TemporalStringBuilder& result, - JSLinearString* id, + const TimeZoneValue& timeZone, ShowTimeZoneName showTimeZone) { switch (showTimeZone) { case ShowTimeZoneName::Never: return true; - case ShowTimeZoneName::Auto: { - auto& sb = result.builder(); - return sb.append("[") && sb.append(id) && sb.append(']'); - } + case ShowTimeZoneName::Auto: + return result.appendTimeZoneAnnnotation(timeZone.identifier(), + Critical::No); - case ShowTimeZoneName::Critical: { - auto& sb = result.builder(); - return sb.append("[!") && sb.append(id) && sb.append(']'); - } + case ShowTimeZoneName::Critical: + return result.appendTimeZoneAnnnotation(timeZone.identifier(), + Critical::Yes); } MOZ_CRASH("bad time zone option"); } -static bool MaybeFormatTimeZoneAnnotation(JSContext* cx, - TemporalStringBuilder& result, - Handle timeZone, - ShowTimeZoneName showTimeZone) { - if (showTimeZone == ShowTimeZoneName::Never) { - return true; - } - - JSString* timeZoneIdentifier = ToTemporalTimeZoneIdentifier(cx, timeZone); - if (!timeZoneIdentifier) { - return false; - } - - JSLinearString* linearTimeZoneId = timeZoneIdentifier->ensureLinear(cx); - if (!linearTimeZoneId) { - return false; - } - - return FormatTimeZoneAnnotation(result, linearTimeZoneId, showTimeZone); -} - /** * TemporalInstantToString ( instant, timeZone, precision ) */ JSString* js::temporal::TemporalInstantToString(JSContext* cx, - Handle instant, + const EpochNanoseconds& epochNs, Handle timeZone, Precision precision) { TemporalStringBuilder result(cx, TemporalStringFormat::Instant); @@ -398,37 +362,32 @@ JSString* js::temporal::TemporalInstantToString(JSContext* cx, return nullptr; } - // Steps 1-2. (Not applicable in our implementation.) - - // Steps 3-6. + // Steps 1-2. int64_t offsetNanoseconds = 0; if (timeZone) { - // Steps 3-4. (Not applicable) - - // Steps 5-6. - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { + if (!GetOffsetNanosecondsFor(cx, timeZone, epochNs, &offsetNanoseconds)) { return nullptr; } MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); } - // Step 7. - auto dateTime = GetPlainDateTimeFor(ToInstant(instant), offsetNanoseconds); + // Step 3. (Not applicable in our implementation.) - // Step 8. (Inlined TemporalDateTimeToString) + // Step 4. + auto dateTime = GetISODateTimeFor(epochNs, offsetNanoseconds); + + // Step 5. (Inlined ISODateTimeToString) FormatDateTimeString(result, dateTime, precision); - // Steps 9-10. + // Steps 6-7. Rooted timeZoneString(cx); if (!timeZone) { - // Step 9.a. result.append('Z'); } else { - // Step 10.a. FormatDateTimeUTCOffsetRounded(result, offsetNanoseconds); } - // Step 11. + // Step 8. return result.finishString(); } @@ -438,71 +397,64 @@ JSString* js::temporal::TemporalInstantToString(JSContext* cx, JSString* js::temporal::TemporalDateToString( JSContext* cx, Handle temporalDate, ShowCalendar showCalendar) { - auto date = ToPlainDate(temporalDate); - - // Steps 1-2. (Not applicable in our implementation.) + auto date = temporalDate->date(); TemporalStringBuilder result(cx, TemporalStringFormat::Date); if (!result.reserve()) { return nullptr; } - // Steps 3-5. + // Steps 1-3. FormatDateString(result, date); - // Step 6. - Rooted calendar(cx, temporalDate->calendar()); - if (!MaybeFormatCalendarAnnotation(cx, result, calendar, showCalendar)) { + // Step 4. + if (!FormatCalendarAnnotation(result, temporalDate->calendar(), + showCalendar)) { return nullptr; } - // Step 7. + // Step 5. return result.finishString(); } /** - * TemporalDateTimeToString ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar, precision, showCalendar ) + * ISODateTimeToString ( isoDateTime, calendar, precision, showCalendar ) */ -JSString* js::temporal::TemporalDateTimeToString(JSContext* cx, - const PlainDateTime& dateTime, - Handle calendar, - Precision precision, - ShowCalendar showCalendar) { +JSString* js::temporal::ISODateTimeToString(JSContext* cx, + const ISODateTime& isoDateTime, + Handle calendar, + Precision precision, + ShowCalendar showCalendar) { + MOZ_ASSERT(IsValidISODateTime(isoDateTime)); + TemporalStringBuilder result(cx, TemporalStringFormat::DateTime); if (!result.reserve()) { return nullptr; } - // Step 1. (Not applicable in our implementation.) + // Steps 1-5. + FormatDateTimeString(result, isoDateTime, precision); - // Steps 2-6. - FormatDateTimeString(result, dateTime, precision); - - // Step 7. - if (!MaybeFormatCalendarAnnotation(cx, result, calendar, showCalendar)) { + // Step 6. + if (!FormatCalendarAnnotation(result, calendar, showCalendar)) { return nullptr; } - // Step 8. + // Step 7. return result.finishString(); } /** - * TemporalTimeToString ( hour, minute, second, millisecond, microsecond, - * nanosecond, precision ) + * TimeRecordToString ( time, precision ) */ -JSString* js::temporal::TemporalTimeToString(JSContext* cx, - const PlainTime& time, - Precision precision) { - // Step 1. (Not applicable in our implementation.) - +JSString* js::temporal::TimeRecordToString(JSContext* cx, const Time& time, + Precision precision) { TemporalStringBuilder result(cx, TemporalStringFormat::Time); if (!result.reserve()) { return nullptr; } - // Steps 2-3. + // Steps 1-2. FormatTimeString(result, time, precision); return result.finishString(); @@ -514,38 +466,16 @@ JSString* js::temporal::TemporalTimeToString(JSContext* cx, JSString* js::temporal::TemporalMonthDayToString( JSContext* cx, Handle monthDay, ShowCalendar showCalendar) { - // Steps 1-2. (Not applicable in our implementation.) - TemporalStringBuilder result(cx, TemporalStringFormat::MonthDay); if (!result.reserve()) { return nullptr; } - // Step 6. (Reordered) - Rooted calendar(cx, monthDay->calendar()); - JSString* str = ToTemporalCalendarIdentifier(cx, calendar); - if (!str) { - return nullptr; - } - - Rooted calendarIdentifier(cx, str->ensureLinear(cx)); - if (!calendarIdentifier) { - return nullptr; - } - - // Steps 3-5 and 7. - auto date = ToPlainDate(monthDay); + // Steps 1-4. + auto date = monthDay->date(); if (showCalendar == ShowCalendar::Always || showCalendar == ShowCalendar::Critical || - !StringEqualsLiteral(calendarIdentifier, "iso8601")) { - // FIXME: spec issue - don't print "year" part when showCalendar is "never". - // - // ```js - // let cal = new Proxy({id: "cal"}, {has(t, pk) { return true; }}); - // let pmd = new Temporal.PlainMonthDay(8, 1, cal); - // pmd.toString({calendarName: "never"}) - // ``` - + monthDay->calendar().identifier() != CalendarId::ISO8601) { FormatDateString(result, date); } else { result.appendTwoDigit(date.month); @@ -553,12 +483,12 @@ JSString* js::temporal::TemporalMonthDayToString( result.appendTwoDigit(date.day); } - // Steps 8-9. - if (!FormatCalendarAnnotation(result, calendarIdentifier, showCalendar)) { + // Steps 5-6. + if (!FormatCalendarAnnotation(result, monthDay->calendar(), showCalendar)) { return nullptr; } - // Step 10. + // Step 7. return result.finishString(); } @@ -568,38 +498,16 @@ JSString* js::temporal::TemporalMonthDayToString( JSString* js::temporal::TemporalYearMonthToString( JSContext* cx, Handle yearMonth, ShowCalendar showCalendar) { - // Steps 1-2. (Not applicable in our implementation.) - TemporalStringBuilder result(cx, TemporalStringFormat::YearMonth); if (!result.reserve()) { return nullptr; } - // Step 6. (Reordered) - Rooted calendar(cx, yearMonth->calendar()); - JSString* str = ToTemporalCalendarIdentifier(cx, calendar); - if (!str) { - return nullptr; - } - - Rooted calendarIdentifier(cx, str->ensureLinear(cx)); - if (!calendarIdentifier) { - return nullptr; - } - - // Steps 3-5 and 7. - auto date = ToPlainDate(yearMonth); + // Steps 1-4. + auto date = yearMonth->date(); if (showCalendar == ShowCalendar::Always || showCalendar == ShowCalendar::Critical || - !StringEqualsLiteral(calendarIdentifier, "iso8601")) { - // FIXME: spec issue - don't print "day" part when showCalendar is "never". - // - // ```js - // let cal = new Proxy({id: "cal"}, {has(t, pk) { return true; }}); - // let pym = new Temporal.PlainYearMonth(2023, 8, cal); - // pym.toString({calendarName: "never"}) - // ``` - + yearMonth->calendar().identifier() != CalendarId::ISO8601) { FormatDateString(result, date); } else { result.appendYear(date.year); @@ -607,12 +515,12 @@ JSString* js::temporal::TemporalYearMonthToString( result.appendTwoDigit(date.month); } - // Steps 8-9. - if (!FormatCalendarAnnotation(result, calendarIdentifier, showCalendar)) { + // Steps 5-6. + if (!FormatCalendarAnnotation(result, yearMonth->calendar(), showCalendar)) { return nullptr; } - // Step 10. + // Step 7. return result.finishString(); } @@ -632,42 +540,42 @@ JSString* js::temporal::TemporalZonedDateTimeToString( // Steps 1-3. (Not applicable in our implementation.) - // Step 4. - auto ns = RoundTemporalInstant(zonedDateTime.instant(), increment, unit, - roundingMode); + // Steps 4-5. + auto epochNs = RoundTemporalInstant(zonedDateTime.epochNanoseconds(), + increment, unit, roundingMode); - // Step 5. + // Step 6. auto timeZone = zonedDateTime.timeZone(); - // Steps 6-8. + // Step 7. int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, ns, &offsetNanoseconds)) { + if (!GetOffsetNanosecondsFor(cx, timeZone, epochNs, &offsetNanoseconds)) { return nullptr; } MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - // Step 9. - auto temporalDateTime = GetPlainDateTimeFor(ns, offsetNanoseconds); + // Step 8. + auto isoDateTime = GetISODateTimeFor(epochNs, offsetNanoseconds); - // Step 10. (Inlined TemporalDateTimeToString) - FormatDateTimeString(result, temporalDateTime, precision); + // Step 9. (Inlined ISODateTimeToString) + FormatDateTimeString(result, isoDateTime, precision); - // Steps 11-12. + // Steps 10-11. if (showOffset != ShowOffset::Never) { FormatDateTimeUTCOffsetRounded(result, offsetNanoseconds); } - // Steps 13-14. - if (!MaybeFormatTimeZoneAnnotation(cx, result, timeZone, showTimeZone)) { + // Steps 12-13. + if (!FormatTimeZoneAnnotation(result, timeZone, showTimeZone)) { + return nullptr; + } + + // Step 14. + if (!FormatCalendarAnnotation(result, zonedDateTime.calendar(), + showCalendar)) { return nullptr; } // Step 15. - if (!MaybeFormatCalendarAnnotation(cx, result, zonedDateTime.calendar(), - showCalendar)) { - return nullptr; - } - - // Step 16. return result.finishString(); } diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.h index 02db9e74638..3716b344cd5 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/ToString.h @@ -22,14 +22,15 @@ class PlainYearMonthObject; class TimeZoneValue; class ZonedDateTime; -struct PlainDateTime; -struct PlainTime; +struct EpochNanoseconds; +struct ISODateTime; +struct Time; /** * TemporalInstantToString ( instant, timeZone, precision ) */ JSString* TemporalInstantToString(JSContext* cx, - JS::Handle instant, + const EpochNanoseconds& epochNs, JS::Handle timeZone, Precision precision); @@ -41,20 +42,17 @@ JSString* TemporalDateToString(JSContext* cx, ShowCalendar showCalendar); /** - * TemporalDateTimeToString ( isoYear, isoMonth, isoDay, hour, minute, second, - * millisecond, microsecond, nanosecond, calendar, precision, showCalendar ) + * ISODateTimeToString ( isoDateTime, calendar, precision, showCalendar ) */ -JSString* TemporalDateTimeToString(JSContext* cx, const PlainDateTime& dateTime, - JS::Handle calendar, - Precision precision, - ShowCalendar showCalendar); +JSString* ISODateTimeToString(JSContext* cx, const ISODateTime& isoDateTime, + JS::Handle calendar, + Precision precision, ShowCalendar showCalendar); /** - * TemporalTimeToString ( hour, minute, second, millisecond, microsecond, - * nanosecond, precision ) + * TimeRecordToString ( time, precision ) */ -JSString* TemporalTimeToString(JSContext* cx, const PlainTime& time, - Precision precision); +JSString* TimeRecordToString(JSContext* cx, const Time& time, + Precision precision); /** * TemporalMonthDayToString ( monthDay, showCalendar ) diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.cpp deleted file mode 100644 index ca0ec9f8b19..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "builtin/temporal/Wrapped.h" - -#include "jsfriendapi.h" - -#include "js/ErrorReport.h" -#include "js/friend/ErrorMessages.h" -#include "js/Wrapper.h" - -void js::temporal::ReportDeadWrapperOrAccessDenied(JSContext* cx, - JSObject* obj) { - if (JS_IsDeadWrapper(obj)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT); - } else { - ReportAccessDenied(cx); - } -} diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.h deleted file mode 100644 index 904a9b3ac92..00000000000 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/Wrapped.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef builtin_temporal_Wrapped_h -#define builtin_temporal_Wrapped_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include - -#include "gc/Tracer.h" -#include "js/RootingAPI.h" -#include "vm/JSObject.h" -#include "vm/NativeObject.h" - -namespace js::temporal { - -/** - * Type to represent possibly wrapped objects from a different compartment. - * - * This can be used to represent specific JSObject sub-classes in return types - * without having to pass unwrapped objects around. - */ -template -class MOZ_STACK_CLASS Wrapped final { - static_assert(std::is_pointer_v); - static_assert(std::is_convertible_v); - - using U = std::remove_pointer_t; - - JSObject* ptr_ = nullptr; - - public: - Wrapped() = default; - - MOZ_IMPLICIT Wrapped(decltype(nullptr)) : ptr_(nullptr) {} - - MOZ_IMPLICIT Wrapped(T ptr) : ptr_(ptr) { - // No assertion needed when the object already has the correct type. - } - - MOZ_IMPLICIT Wrapped(JSObject* ptr) : ptr_(ptr) { - // Ensure the caller passed a valid pointer. - MOZ_ASSERT_IF(ptr_, ptr_->canUnwrapAs()); - } - - template - MOZ_IMPLICIT Wrapped( - const JS::Rooted& root, - std::enable_if_t, int> dummy = 0) - : Wrapped(root.get()) {} - - MOZ_IMPLICIT Wrapped(const JS::Rooted& root) - : Wrapped(root.get()) {} - - template - MOZ_IMPLICIT Wrapped( - const JS::Handle& root, - std::enable_if_t, int> dummy = 0) - : Wrapped(root.get()) {} - - MOZ_IMPLICIT Wrapped(const JS::Handle& root) - : Wrapped(root.get()) {} - - template - MOZ_IMPLICIT Wrapped( - const JS::MutableHandle& root, - std::enable_if_t, int> dummy = 0) - : Wrapped(root.get()) {} - - MOZ_IMPLICIT Wrapped(const JS::MutableHandle& root) - : Wrapped(root.get()) {} - - Wrapped& operator=(decltype(nullptr)) { - ptr_ = nullptr; - return *this; - } - - Wrapped& operator=(T ptr) { - ptr_ = ptr; - return *this; - } - - explicit operator bool() const { return !!ptr_; } - - JSObject* operator->() const { return ptr_; } - - JSObject& operator*() const { return *ptr_; } - - JSObject* get() const { return ptr_; } - - operator JSObject*() const { return get(); } - - auto address() const { return &ptr_; } - - U& unwrap() const { - MOZ_ASSERT(ptr_); - - // Direct unwrap because the constructor already verified the object can be - // unwrapped. - // - // We use JSObject::unwrapAs() instead of JSObject::maybeUnwrapIf(), because - // this is an unrooted Wrapped, so hazard analysis will ensure that no - // wrappers have been invalidated, because wrapper invalidation generally - // only happens in the same case as GC. - // - // Rooted Wrapped are accessed through their WrappedPtrOperations - // specialization, which uses JSObject::maybeUnwrapIf() to handle the - // wrapper invalidation case correctly. - return ptr_->unwrapAs(); - } - - U* unwrapOrNull() const { - // Direct unwrap because the constructor already verified the object can be - // unwrapped. - // - // See Wrapped::unwrap() for why we don't call maybeUnwrapIf() here. - return ptr_ ? &ptr_->unwrapAs() : nullptr; - } - - void trace(JSTracer* trc) { TraceNullableRoot(trc, &ptr_, "Wrapped::ptr_"); } -}; - -void ReportDeadWrapperOrAccessDenied(JSContext* cx, JSObject* obj); - -} /* namespace js::temporal */ - -namespace js { -template -class WrappedPtrOperations, Container> { - using U = std::remove_pointer_t; - - const auto& wrapped() const { - return static_cast(this)->get(); - } - - public: - explicit operator bool() const { return !!wrapped(); } - - JSObject* operator->() const { return wrapped().get(); } - - JSObject& operator*() const { return *wrapped().get(); } - - JS::Handle object() const { - return JS::Handle::fromMarkedLocation(wrapped().address()); - } - - operator JS::Handle() const { return object(); } - - [[nodiscard]] U* unwrap(JSContext* cx) const { - JSObject* obj = wrapped().get(); - - // Call JSObject::maybeUnwrapIf() instead of JSObject::unwrapAs() in case - // |obj| is an invalidated wrapper. - if (auto* unwrapped = obj->maybeUnwrapIf()) { - return unwrapped; - } - - temporal::ReportDeadWrapperOrAccessDenied(cx, obj); - return nullptr; - } -}; -} // namespace js - -#endif /* builtin_temporal_Wrapped_h */ diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.cpp b/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.cpp index e6c14db3bb9..66eb1d82990 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.cpp +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.cpp @@ -7,50 +7,46 @@ #include "builtin/temporal/ZonedDateTime.h" #include "mozilla/Assertions.h" +#include "mozilla/EnumSet.h" #include "mozilla/Maybe.h" +#include #include -#include #include #include "jspubtd.h" #include "NamespaceImports.h" +#include "builtin/intl/DateTimeFormat.h" #include "builtin/temporal/Calendar.h" +#include "builtin/temporal/CalendarFields.h" #include "builtin/temporal/Duration.h" #include "builtin/temporal/Instant.h" -#include "builtin/temporal/Int96.h" +#include "builtin/temporal/Int128.h" #include "builtin/temporal/PlainDate.h" #include "builtin/temporal/PlainDateTime.h" #include "builtin/temporal/PlainMonthDay.h" #include "builtin/temporal/PlainTime.h" #include "builtin/temporal/PlainYearMonth.h" #include "builtin/temporal/Temporal.h" -#include "builtin/temporal/TemporalFields.h" #include "builtin/temporal/TemporalParser.h" #include "builtin/temporal/TemporalRoundingMode.h" #include "builtin/temporal/TemporalTypes.h" #include "builtin/temporal/TemporalUnit.h" #include "builtin/temporal/TimeZone.h" #include "builtin/temporal/ToString.h" -#include "builtin/temporal/Wrapped.h" -#include "ds/IdValuePair.h" #include "gc/AllocKind.h" #include "gc/Barrier.h" -#include "js/AllocPolicy.h" +#include "gc/GCEnum.h" #include "js/CallArgs.h" #include "js/CallNonGenericMethod.h" #include "js/Class.h" -#include "js/ComparisonOperators.h" #include "js/ErrorReport.h" #include "js/friend/ErrorMessages.h" -#include "js/GCVector.h" -#include "js/Id.h" #include "js/Printer.h" #include "js/PropertyDescriptor.h" #include "js/PropertySpec.h" #include "js/RootingAPI.h" -#include "js/TracingAPI.h" #include "js/Value.h" #include "vm/BigIntType.h" #include "vm/BytecodeUtil.h" @@ -58,14 +54,11 @@ #include "vm/JSAtomState.h" #include "vm/JSContext.h" #include "vm/JSObject.h" -#include "vm/ObjectOperations.h" #include "vm/PlainObject.h" #include "vm/StringType.h" -#include "vm/JSContext-inl.h" #include "vm/JSObject-inl.h" #include "vm/NativeObject-inl.h" -#include "vm/ObjectOperations-inl.h" using namespace js; using namespace js::temporal; @@ -89,149 +82,289 @@ static int64_t RoundNanosecondsToMinutesIncrement(int64_t offsetNanoseconds) { } /** - * InterpretISODateTimeOffset ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond, offsetBehaviour, offsetNanoseconds, - * timeZoneRec, disambiguation, offsetOption, matchBehaviour ) + * InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, + * offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ) */ bool js::temporal::InterpretISODateTimeOffset( - JSContext* cx, const PlainDateTime& dateTime, - OffsetBehaviour offsetBehaviour, int64_t offsetNanoseconds, - Handle timeZone, TemporalDisambiguation disambiguation, - TemporalOffset offsetOption, MatchBehaviour matchBehaviour, - Instant* result) { + JSContext* cx, const ISODateTime& dateTime, OffsetBehaviour offsetBehaviour, + int64_t offsetNanoseconds, Handle timeZone, + TemporalDisambiguation disambiguation, TemporalOffset offsetOption, + MatchBehaviour matchBehaviour, EpochNanoseconds* result) { MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); + MOZ_ASSERT(IsValidISODateTime(dateTime)); - // Step 1. - MOZ_ASSERT(IsValidISODate(dateTime.date)); - - // Step 2. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // Step 3. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); - - // Step 4. - Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); - Rooted temporalDateTime(cx); - if (!CreateTemporalDateTime(cx, dateTime, calendar, &temporalDateTime)) { + // FIXME: spec issue - avoid calling with date-time outside of limits + // https://github.com/tc39/proposal-temporal/pull/3014 + if (!ISODateTimeWithinLimits(dateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); return false; } - // Step 5. + // Steps 1-2. (Not applicable in our implementation.) + + // Step 3. if (offsetBehaviour == OffsetBehaviour::Wall || (offsetBehaviour == OffsetBehaviour::Option && offsetOption == TemporalOffset::Ignore)) { - // Steps 5.a-b. - return GetInstantFor(cx, timeZone, temporalDateTime, disambiguation, - result); + // Steps 3.a-b. + return GetEpochNanosecondsFor(cx, timeZone, dateTime, disambiguation, + result); } - // Step 6. + // Step 4. if (offsetBehaviour == OffsetBehaviour::Exact || (offsetBehaviour == OffsetBehaviour::Option && offsetOption == TemporalOffset::Use)) { - // Step 6.a. - auto epochNanoseconds = GetUTCEpochNanoseconds( - dateTime, InstantSpan::fromNanoseconds(offsetNanoseconds)); + // Step 4.a. + auto epochNanoseconds = GetUTCEpochNanoseconds(dateTime) - + EpochDuration::fromNanoseconds(offsetNanoseconds); - // Step 6.b. - if (!IsValidEpochInstant(epochNanoseconds)) { + // Step 4.b. + if (!IsValidEpochNanoseconds(epochNanoseconds)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_INSTANT_INVALID); return false; } - // Step 6.c. + // Step 4.c. *result = epochNanoseconds; return true; } - // Step 7. + // Step 5. MOZ_ASSERT(offsetBehaviour == OffsetBehaviour::Option); - // Step 8. + // Step 6. MOZ_ASSERT(offsetOption == TemporalOffset::Prefer || offsetOption == TemporalOffset::Reject); - // Step 9. - Rooted possibleInstants(cx, InstantVector(cx)); - if (!GetPossibleInstantsFor(cx, timeZone, temporalDateTime, - &possibleInstants)) { + // Step 7. + PossibleEpochNanoseconds possibleEpochNs; + if (!GetPossibleEpochNanoseconds(cx, timeZone, dateTime, &possibleEpochNs)) { return false; } - // Step 10. - if (!possibleInstants.empty()) { - // Step 10.a. - Rooted> candidate(cx); - for (size_t i = 0; i < possibleInstants.length(); i++) { - candidate = possibleInstants[i]; + // Step 8.a. + for (const auto& candidate : possibleEpochNs) { + // Step 8.a.i. + int64_t candidateNanoseconds; + if (!GetOffsetNanosecondsFor(cx, timeZone, candidate, + &candidateNanoseconds)) { + return false; + } + MOZ_ASSERT(std::abs(candidateNanoseconds) < + ToNanoseconds(TemporalUnit::Day)); - // Step 10.a.i. - int64_t candidateNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, candidate, - &candidateNanoseconds)) { - return false; - } - MOZ_ASSERT(std::abs(candidateNanoseconds) < - ToNanoseconds(TemporalUnit::Day)); + // Step 8.a.ii. + if (candidateNanoseconds == offsetNanoseconds) { + *result = candidate; + return true; + } - // Step 10.a.ii. - if (candidateNanoseconds == offsetNanoseconds) { - auto* unwrapped = candidate.unwrap(cx); - if (!unwrapped) { - return false; - } + // Step 8.a.iii. + if (matchBehaviour == MatchBehaviour::MatchMinutes) { + // Step 8.a.iii.1. + int64_t roundedCandidateNanoseconds = + RoundNanosecondsToMinutesIncrement(candidateNanoseconds); - *result = ToInstant(unwrapped); + // Step 8.a.iii.2. + if (roundedCandidateNanoseconds == offsetNanoseconds) { + // Step 8.a.iii.2.a. + *result = candidate; return true; } - - // Step 10.a.iii. - if (matchBehaviour == MatchBehaviour::MatchMinutes) { - // Step 10.a.iii.1. - int64_t roundedCandidateNanoseconds = - RoundNanosecondsToMinutesIncrement(candidateNanoseconds); - - // Step 10.a.iii.2. - if (roundedCandidateNanoseconds == offsetNanoseconds) { - auto* unwrapped = candidate.unwrap(cx); - if (!unwrapped) { - return false; - } - - // Step 10.a.iii.2.a. - *result = ToInstant(unwrapped); - return true; - } - } } } - // Step 11. + // Step 9. if (offsetOption == TemporalOffset::Reject) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_ZONED_DATE_TIME_NO_TIME_FOUND); return false; } - // Step 12. - Rooted> instant(cx); - if (!DisambiguatePossibleInstants(cx, possibleInstants, timeZone, - ToPlainDateTime(temporalDateTime), - disambiguation, &instant)) { + // Step 10. + return DisambiguatePossibleEpochNanoseconds(cx, possibleEpochNs, timeZone, + dateTime, disambiguation, result); +} + +/** + * InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, + * offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ) + */ +bool js::temporal::InterpretISODateTimeOffset( + JSContext* cx, const ISODate& isoDate, OffsetBehaviour offsetBehaviour, + int64_t offsetNanoseconds, Handle timeZone, + TemporalDisambiguation disambiguation, TemporalOffset offsetOption, + MatchBehaviour matchBehaviour, EpochNanoseconds* result) { + MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); + MOZ_ASSERT(IsValidISODate(isoDate)); + + // Step 1. (Not applicable in our implementation.) + + // Step 2.a. + MOZ_ASSERT(offsetBehaviour == OffsetBehaviour::Wall); + + // Step 2.b. + MOZ_ASSERT(offsetNanoseconds == 0); + + // Step 2.c. + return GetStartOfDay(cx, timeZone, isoDate, result); +} + +struct ZonedDateTimeOptions { + TemporalDisambiguation disambiguation = TemporalDisambiguation::Compatible; + TemporalOffset offset = TemporalOffset::Reject; + TemporalOverflow overflow = TemporalOverflow::Constrain; +}; + +/** + * ToTemporalZonedDateTime ( item [ , options ] ) + */ +static bool ToTemporalZonedDateTimeOptions(JSContext* cx, Handle options, + ZonedDateTimeOptions* result) { + if (options.isUndefined()) { + *result = {}; + return true; + } + + // NOTE: |options| are only passed from `Temporal.ZonedDateTime.from`. + + Rooted resolvedOptions( + cx, RequireObjectArg(cx, "options", "from", options)); + if (!resolvedOptions) { return false; } - auto* unwrappedInstant = instant.unwrap(cx); - if (!unwrappedInstant) { + auto disambiguation = TemporalDisambiguation::Compatible; + if (!GetTemporalDisambiguationOption(cx, resolvedOptions, &disambiguation)) { return false; } - // Step 13. - *result = ToInstant(unwrappedInstant); + auto offset = TemporalOffset::Reject; + if (!GetTemporalOffsetOption(cx, resolvedOptions, &offset)) { + return false; + } + + auto overflow = TemporalOverflow::Constrain; + if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) { + return false; + } + + *result = {disambiguation, offset, overflow}; + return true; +} + +/** + * ToTemporalZonedDateTime ( item [ , options ] ) + */ +static bool ToTemporalZonedDateTime(JSContext* cx, Handle item, + Handle options, + MutableHandle result) { + // Step 1. (Not applicable in our implementation.) + + // Step 2. + auto offsetBehaviour = OffsetBehaviour::Option; + + // Step 3. + auto matchBehaviour = MatchBehaviour::MatchExactly; + + // Step 4.a. + if (auto* zonedDateTime = item->maybeUnwrapIf()) { + auto epochNs = zonedDateTime->epochNanoseconds(); + Rooted timeZone(cx, zonedDateTime->timeZone()); + Rooted calendar(cx, zonedDateTime->calendar()); + + if (!timeZone.wrap(cx)) { + return false; + } + if (!calendar.wrap(cx)) { + return false; + } + + // Steps 4.a.i-v. + ZonedDateTimeOptions ignoredOptions; + if (!ToTemporalZonedDateTimeOptions(cx, options, &ignoredOptions)) { + return false; + } + + // Step 4.a.vi. + result.set(ZonedDateTime{epochNs, timeZone, calendar}); + return true; + } + + // Step 4.b. + Rooted calendar(cx); + if (!GetTemporalCalendarWithISODefault(cx, item, &calendar)) { + return false; + } + + // Step 4.c. + Rooted fields(cx); + if (!PrepareCalendarFields(cx, calendar, item, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + CalendarField::Hour, + CalendarField::Minute, + CalendarField::Second, + CalendarField::Millisecond, + CalendarField::Microsecond, + CalendarField::Nanosecond, + CalendarField::Offset, + CalendarField::TimeZone, + }, + {CalendarField::TimeZone}, &fields)) { + return false; + } + + // Step 4.d. + auto timeZone = fields.timeZone(); + + // Step 4.e. + auto offsetString = fields.offset(); + + // Step 4.f. + if (!fields.has(CalendarField::Offset)) { + offsetBehaviour = OffsetBehaviour::Wall; + } + + // Steps 4.g-j. + ZonedDateTimeOptions resolvedOptions; + if (!ToTemporalZonedDateTimeOptions(cx, options, &resolvedOptions)) { + return false; + } + auto [disambiguation, offsetOption, overflow] = resolvedOptions; + + // Step 4.k. + ISODateTime dateTime; + if (!InterpretTemporalDateTimeFields(cx, calendar, fields, overflow, + &dateTime)) { + return false; + } + + // Step 6. + int64_t offsetNanoseconds = 0; + + // Step 7. + if (offsetBehaviour == OffsetBehaviour::Option) { + offsetNanoseconds = int64_t(offsetString); + } + + // Step 8. + EpochNanoseconds epochNanoseconds; + if (!InterpretISODateTimeOffset( + cx, dateTime, offsetBehaviour, offsetNanoseconds, timeZone, + disambiguation, offsetOption, matchBehaviour, &epochNanoseconds)) { + return false; + } + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); + + // Step 9. + result.set(ZonedDateTime{epochNanoseconds, timeZone, calendar}); return true; } @@ -239,273 +372,123 @@ bool js::temporal::InterpretISODateTimeOffset( * ToTemporalZonedDateTime ( item [ , options ] ) */ static bool ToTemporalZonedDateTime(JSContext* cx, Handle item, - Handle maybeOptions, + Handle options, MutableHandle result) { - // Step 1. (Not applicable in our implementation) + // Step 1. (Not applicable in our implementation.) // Step 2. - Rooted maybeResolvedOptions(cx); - if (maybeOptions) { - maybeResolvedOptions = SnapshotOwnProperties(cx, maybeOptions); - if (!maybeResolvedOptions) { - return false; - } - } - - // Step 3. auto offsetBehaviour = OffsetBehaviour::Option; - // Step 4. + // Step 3. auto matchBehaviour = MatchBehaviour::MatchExactly; - // Step 7. (Reordered) - int64_t offsetNanoseconds = 0; - - // Step 5. - Rooted calendar(cx); - Rooted timeZone(cx); - PlainDateTime dateTime; - auto disambiguation = TemporalDisambiguation::Compatible; - auto offsetOption = TemporalOffset::Reject; + // Step 4. if (item.isObject()) { Rooted itemObj(cx, &item.toObject()); + return ToTemporalZonedDateTime(cx, itemObj, options, result); + } - // Step 5.a. - if (auto* zonedDateTime = itemObj->maybeUnwrapIf()) { - auto instant = ToInstant(zonedDateTime); - Rooted timeZone(cx, zonedDateTime->timeZone()); - Rooted calendar(cx, zonedDateTime->calendar()); + // Step 5.a. + if (!item.isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, + nullptr, "not a string"); + return false; + } + Rooted string(cx, item.toString()); - if (!timeZone.wrap(cx)) { - return false; - } - if (!calendar.wrap(cx)) { - return false; - } + // Case 1: 19700101Z[+02:00] + // { [[Z]]: true, [[OffsetString]]: undefined, [[Name]]: "+02:00" } + // + // Case 2: 19700101+00:00[+02:00] + // { [[Z]]: false, [[OffsetString]]: "+00:00", [[Name]]: "+02:00" } + // + // Case 3: 19700101[+02:00] + // { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: "+02:00" } + // + // Case 4: 19700101Z[Europe/Berlin] + // { [[Z]]: true, [[OffsetString]]: undefined, [[Name]]: "Europe/Berlin" } + // + // Case 5: 19700101+00:00[Europe/Berlin] + // { [[Z]]: false, [[OffsetString]]: "+00:00", [[Name]]: "Europe/Berlin" } + // + // Case 6: 19700101[Europe/Berlin] + // { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: "Europe/Berlin" } - result.set(ZonedDateTime{instant, timeZone, calendar}); - return true; - } + // Steps 5.b-c. + Rooted parsed(cx); + if (!ParseTemporalZonedDateTimeString(cx, string, &parsed)) { + return false; + } - // Step 5.b. - if (!GetTemporalCalendarWithISODefault(cx, itemObj, &calendar)) { + // Step 5.d. + MOZ_ASSERT(parsed.timeZoneAnnotation()); + + // Step 5.e. + Rooted timeZone(cx); + if (!ToTemporalTimeZone(cx, parsed.timeZoneAnnotation(), &timeZone)) { + return false; + } + + // Step 5.f. (Not applicable in our implementation.) + + // Step 5.g. + if (parsed.isUTC()) { + offsetBehaviour = OffsetBehaviour::Exact; + } + + // Step 5.h. + else if (!parsed.hasOffset()) { + offsetBehaviour = OffsetBehaviour::Wall; + } + + // Steps 5.i-k. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (parsed.calendar()) { + if (!CanonicalizeCalendar(cx, parsed.calendar(), &calendar)) { return false; } + } - // Step 5.c. - Rooted calendarRec(cx); - if (!CreateCalendarMethodsRecord(cx, calendar, - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - }, - &calendarRec)) { + // Step 5.l. + matchBehaviour = MatchBehaviour::MatchMinutes; + + // Steps 5.m-p. + ZonedDateTimeOptions resolvedOptions; + if (!ToTemporalZonedDateTimeOptions(cx, options, &resolvedOptions)) { + return false; + } + auto [disambiguation, offsetOption, overflow] = resolvedOptions; + + // Steps 5.q-r. (Not applicable in our implementation.) + + // Step 6. + int64_t offsetNanoseconds = 0; + + // Step 7. + if (offsetBehaviour == OffsetBehaviour::Option) { + MOZ_ASSERT(parsed.hasOffset()); + offsetNanoseconds = parsed.timeZoneOffset(); + } + + // Step 8. + EpochNanoseconds epochNanoseconds; + if (parsed.isStartOfDay()) { + if (!InterpretISODateTimeOffset(cx, parsed.dateTime().date, offsetBehaviour, + offsetNanoseconds, timeZone, disambiguation, + offsetOption, matchBehaviour, + &epochNanoseconds)) { return false; } - - // Step 5.d. - Rooted fields( - cx, PrepareCalendarFields(cx, calendarRec, itemObj, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - { - TemporalField::Hour, - TemporalField::Microsecond, - TemporalField::Millisecond, - TemporalField::Minute, - TemporalField::Nanosecond, - TemporalField::Offset, - TemporalField::Second, - TemporalField::TimeZone, - }, - {TemporalField::TimeZone})); - if (!fields) { - return false; - } - - // Step 5.e. - Rooted timeZoneValue(cx); - if (!GetProperty(cx, fields, fields, cx->names().timeZone, - &timeZoneValue)) { - return false; - } - - // Step 5.f. - if (!ToTemporalTimeZone(cx, timeZoneValue, &timeZone)) { - return false; - } - - // Step 5.g. - Rooted offsetValue(cx); - if (!GetProperty(cx, fields, fields, cx->names().offset, &offsetValue)) { - return false; - } - - // Step 5.h. - MOZ_ASSERT(offsetValue.isString() || offsetValue.isUndefined()); - - // Step 5.i. - Rooted offsetString(cx); - if (offsetValue.isString()) { - offsetString = offsetValue.toString(); - } else { - offsetBehaviour = OffsetBehaviour::Wall; - } - - if (maybeResolvedOptions) { - // Steps 5.j-k. - if (!GetTemporalDisambiguationOption(cx, maybeResolvedOptions, - &disambiguation)) { - return false; - } - - // Step 5.l. - if (!GetTemporalOffsetOption(cx, maybeResolvedOptions, &offsetOption)) { - return false; - } - - // Step 5.m. - if (!InterpretTemporalDateTimeFields(cx, calendarRec, fields, - maybeResolvedOptions, &dateTime)) { - return false; - } - } else { - // Steps 5.j-l. (Not applicable) - - // Step 5.k. - if (!InterpretTemporalDateTimeFields(cx, calendarRec, fields, - &dateTime)) { - return false; - } - } - - // Step 8. - if (offsetBehaviour == OffsetBehaviour::Option) { - if (!ParseDateTimeUTCOffset(cx, offsetString, &offsetNanoseconds)) { - return false; - } - } } else { - // Step 6.a. - if (!item.isString()) { - ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item, - nullptr, "not a string"); + if (!InterpretISODateTimeOffset( + cx, parsed.dateTime(), offsetBehaviour, offsetNanoseconds, timeZone, + disambiguation, offsetOption, matchBehaviour, &epochNanoseconds)) { return false; } - Rooted string(cx, item.toString()); - - // Case 1: 19700101Z[+02:00] - // { [[Z]]: true, [[OffsetString]]: undefined, [[Name]]: "+02:00" } - // - // Case 2: 19700101+00:00[+02:00] - // { [[Z]]: false, [[OffsetString]]: "+00:00", [[Name]]: "+02:00" } - // - // Case 3: 19700101[+02:00] - // { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: "+02:00" } - // - // Case 4: 19700101Z[Europe/Berlin] - // { [[Z]]: true, [[OffsetString]]: undefined, [[Name]]: "Europe/Berlin" } - // - // Case 5: 19700101+00:00[Europe/Berlin] - // { [[Z]]: false, [[OffsetString]]: "+00:00", [[Name]]: "Europe/Berlin" } - // - // Case 6: 19700101[Europe/Berlin] - // { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: "Europe/Berlin" } - - // Steps 6.b-c. - bool isUTC; - bool hasOffset; - int64_t timeZoneOffset; - Rooted timeZoneAnnotation(cx); - Rooted calendarString(cx); - if (!ParseTemporalZonedDateTimeString( - cx, string, &dateTime, &isUTC, &hasOffset, &timeZoneOffset, - &timeZoneAnnotation, &calendarString)) { - return false; - } - - // Step 6.d. - MOZ_ASSERT(timeZoneAnnotation); - - // Step 6.e. - if (!ToTemporalTimeZone(cx, timeZoneAnnotation, &timeZone)) { - return false; - } - - // Step 6.f. (Not applicable in our implementation.) - - // Step 6.g. - if (isUTC) { - offsetBehaviour = OffsetBehaviour::Exact; - } - - // Step 6.h. - else if (!hasOffset) { - offsetBehaviour = OffsetBehaviour::Wall; - } - - // Steps 6.i-l. - if (calendarString) { - if (!ToBuiltinCalendar(cx, calendarString, &calendar)) { - return false; - } - } else { - calendar.set(CalendarValue(CalendarId::ISO8601)); - } - - // Step 6.m. - matchBehaviour = MatchBehaviour::MatchMinutes; - - if (maybeResolvedOptions) { - // Step 6.n. - if (!GetTemporalDisambiguationOption(cx, maybeResolvedOptions, - &disambiguation)) { - return false; - } - - // Step 6.o. - if (!GetTemporalOffsetOption(cx, maybeResolvedOptions, &offsetOption)) { - return false; - } - - // Step 6.p. - TemporalOverflow ignored; - if (!GetTemporalOverflowOption(cx, maybeResolvedOptions, &ignored)) { - return false; - } - } - - // Step 8. - if (offsetBehaviour == OffsetBehaviour::Option) { - MOZ_ASSERT(hasOffset); - offsetNanoseconds = timeZoneOffset; - } } + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); // Step 9. - Rooted timeZoneRec(cx); - if (!CreateTimeZoneMethodsRecord(cx, timeZone, - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZoneRec)) { - return false; - } - - // Step 10. - Instant epochNanoseconds; - if (!InterpretISODateTimeOffset( - cx, dateTime, offsetBehaviour, offsetNanoseconds, timeZoneRec, - disambiguation, offsetOption, matchBehaviour, &epochNanoseconds)) { - return false; - } - - // Step 11. result.set(ZonedDateTime{epochNanoseconds, timeZone, calendar}); return true; } @@ -515,20 +498,7 @@ static bool ToTemporalZonedDateTime(JSContext* cx, Handle item, */ static bool ToTemporalZonedDateTime(JSContext* cx, Handle item, MutableHandle result) { - return ToTemporalZonedDateTime(cx, item, nullptr, result); -} - -/** - * ToTemporalZonedDateTime ( item [ , options ] ) - */ -static ZonedDateTimeObject* ToTemporalZonedDateTime( - JSContext* cx, Handle item, Handle maybeOptions) { - Rooted result(cx); - if (!ToTemporalZonedDateTime(cx, item, maybeOptions, &result)) { - return nullptr; - } - return CreateTemporalZonedDateTime(cx, result.instant(), result.timeZone(), - result.calendar()); + return ToTemporalZonedDateTime(cx, item, UndefinedHandleValue, result); } /** @@ -548,26 +518,28 @@ static ZonedDateTimeObject* CreateTemporalZonedDateTime( return nullptr; } - auto* obj = NewObjectWithClassProto(cx, proto); - if (!obj) { + auto* object = NewObjectWithClassProto(cx, proto); + if (!object) { return nullptr; } // Step 4. - auto instant = ToInstant(epochNanoseconds); - obj->setFixedSlot(ZonedDateTimeObject::SECONDS_SLOT, - NumberValue(instant.seconds)); - obj->setFixedSlot(ZonedDateTimeObject::NANOSECONDS_SLOT, - Int32Value(instant.nanoseconds)); + auto epochNs = ToEpochNanoseconds(epochNanoseconds); + object->setFixedSlot(ZonedDateTimeObject::SECONDS_SLOT, + NumberValue(epochNs.seconds)); + object->setFixedSlot(ZonedDateTimeObject::NANOSECONDS_SLOT, + Int32Value(epochNs.nanoseconds)); // Step 5. - obj->setFixedSlot(ZonedDateTimeObject::TIMEZONE_SLOT, timeZone.toSlotValue()); + object->setFixedSlot(ZonedDateTimeObject::TIMEZONE_SLOT, + timeZone.toSlotValue()); // Step 6. - obj->setFixedSlot(ZonedDateTimeObject::CALENDAR_SLOT, calendar.toSlotValue()); + object->setFixedSlot(ZonedDateTimeObject::CALENDAR_SLOT, + calendar.toSlotValue()); // Step 7. - return obj; + return object; } /** @@ -575,702 +547,211 @@ static ZonedDateTimeObject* CreateTemporalZonedDateTime( * newTarget ] ) */ ZonedDateTimeObject* js::temporal::CreateTemporalZonedDateTime( - JSContext* cx, const Instant& instant, Handle timeZone, - Handle calendar) { + JSContext* cx, const EpochNanoseconds& epochNanoseconds, + Handle timeZone, Handle calendar) { // Step 1. - MOZ_ASSERT(IsValidEpochInstant(instant)); + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); // Steps 2-3. - auto* obj = NewBuiltinClassInstance(cx); - if (!obj) { + auto* object = NewBuiltinClassInstance(cx); + if (!object) { return nullptr; } // Step 4. - obj->setFixedSlot(ZonedDateTimeObject::SECONDS_SLOT, - NumberValue(instant.seconds)); - obj->setFixedSlot(ZonedDateTimeObject::NANOSECONDS_SLOT, - Int32Value(instant.nanoseconds)); + object->setFixedSlot(ZonedDateTimeObject::SECONDS_SLOT, + NumberValue(epochNanoseconds.seconds)); + object->setFixedSlot(ZonedDateTimeObject::NANOSECONDS_SLOT, + Int32Value(epochNanoseconds.nanoseconds)); // Step 5. - obj->setFixedSlot(ZonedDateTimeObject::TIMEZONE_SLOT, timeZone.toSlotValue()); + object->setFixedSlot(ZonedDateTimeObject::TIMEZONE_SLOT, + timeZone.toSlotValue()); // Step 6. - obj->setFixedSlot(ZonedDateTimeObject::CALENDAR_SLOT, calendar.toSlotValue()); + object->setFixedSlot(ZonedDateTimeObject::CALENDAR_SLOT, + calendar.toSlotValue()); // Step 7. - return obj; -} - -struct PlainDateTimeAndInstant { - PlainDateTime dateTime; - Instant instant; -}; - -/** - * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ , - * overflow ] ) - */ -static bool AddDaysToZonedDateTime(JSContext* cx, const Instant& instant, - const PlainDateTime& dateTime, - Handle timeZone, - Handle calendar, int64_t days, - TemporalOverflow overflow, - PlainDateTimeAndInstant* result) { - // Step 1. (Not applicable in our implementation.) - - // Step 2. (Not applicable) - - // Step 3. - if (days == 0) { - *result = {dateTime, instant}; - return true; - } - - // Step 4. - PlainDate addedDate; - if (!AddISODate(cx, dateTime.date, {0, 0, 0, days}, overflow, &addedDate)) { - return false; - } - - // Step 5. - Rooted dateTimeResult(cx); - if (!CreateTemporalDateTime(cx, {addedDate, dateTime.time}, calendar, - &dateTimeResult)) { - return false; - } - - // Step 6. - Instant instantResult; - if (!GetInstantFor(cx, timeZone, dateTimeResult, - TemporalDisambiguation::Compatible, &instantResult)) { - return false; - } - - // Step 7. - *result = {ToPlainDateTime(dateTimeResult), instantResult}; - return true; + return object; } /** - * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ , - * overflow ] ) + * CreateTemporalZonedDateTime ( epochNanoseconds, timeZone, calendar [ , + * newTarget ] ) */ -bool js::temporal::AddDaysToZonedDateTime( - JSContext* cx, const Instant& instant, const PlainDateTime& dateTime, - Handle timeZone, Handle calendar, - int64_t days, TemporalOverflow overflow, Instant* result) { - // Steps 1-7. - PlainDateTimeAndInstant dateTimeAndInstant; - if (!::AddDaysToZonedDateTime(cx, instant, dateTime, timeZone, calendar, days, - overflow, &dateTimeAndInstant)) { - return false; - } - - *result = dateTimeAndInstant.instant; - return true; +static auto* CreateTemporalZonedDateTime(JSContext* cx, + Handle zonedDateTime) { + return CreateTemporalZonedDateTime(cx, zonedDateTime.epochNanoseconds(), + zonedDateTime.timeZone(), + zonedDateTime.calendar()); } /** - * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ , - * overflow ] ) + * AddZonedDateTime ( epochNanoseconds, timeZone, calendar, duration, overflow ) */ -bool js::temporal::AddDaysToZonedDateTime(JSContext* cx, const Instant& instant, - const PlainDateTime& dateTime, - Handle timeZone, - Handle calendar, - int64_t days, Instant* result) { - // Step 2. - auto overflow = TemporalOverflow::Constrain; - - // Steps 1 and 3-7. - return AddDaysToZonedDateTime(cx, instant, dateTime, timeZone, calendar, days, - overflow, result); -} - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -static bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds, - Handle timeZone, - Handle calendar, - const NormalizedDuration& duration, - mozilla::Maybe dateTime, - Handle maybeOptions, Instant* result) { - MOZ_ASSERT(IsValidEpochInstant(epochNanoseconds)); +static bool AddZonedDateTime(JSContext* cx, Handle zonedDateTime, + const InternalDuration& duration, + TemporalOverflow overflow, + EpochNanoseconds* result) { MOZ_ASSERT(IsValidDuration(duration)); // Step 1. - MOZ_ASSERT(TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetPossibleInstantsFor)); + if (duration.date == DateDuration{}) { + // Step 1.a. + return AddInstant(cx, zonedDateTime.epochNanoseconds(), duration.time, + result); + } - // Steps 2-3. - MOZ_ASSERT_IF(!dateTime, - TimeZoneMethodsRecordHasLookedUp( - timeZone, TimeZoneMethod::GetOffsetNanosecondsFor)); + // Step 2. + ISODateTime isoDateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &isoDateTime)) { + return false; + } - // Steps 4-5. (Not applicable in our implementation) + // Step 3. + ISODate addedDate; + if (!CalendarDateAdd(cx, zonedDateTime.calendar(), isoDateTime.date, + duration.date, overflow, &addedDate)) { + return false; + } + + // Step 4. + auto intermediateDateTime = ISODateTime{addedDate, isoDateTime.time}; + + // Step 5. + if (!ISODateTimeWithinLimits(intermediateDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } // Step 6. - if (duration.date == DateDuration{}) { - // Step 6.a. - return AddInstant(cx, epochNanoseconds, duration.time, result); + EpochNanoseconds intermediateNs; + if (!GetEpochNanosecondsFor( + cx, zonedDateTime.timeZone(), intermediateDateTime, + TemporalDisambiguation::Compatible, &intermediateNs)) { + return false; } - // Step 7. (Not applicable in our implementation) + // Step 7. + return AddInstant(cx, intermediateNs, duration.time, result); +} - // Steps 8-9. - PlainDateTime temporalDateTime; - if (dateTime) { - // Step 8.a. - temporalDateTime = *dateTime; - } else { - // Step 9.a. - if (!GetPlainDateTimeFor(cx, timeZone, epochNanoseconds, - &temporalDateTime)) { - return false; - } +/** + * AddZonedDateTime ( epochNanoseconds, timeZone, calendar, duration, overflow ) + */ +bool js::temporal::AddZonedDateTime(JSContext* cx, + Handle zonedDateTime, + const InternalDuration& duration, + EpochNanoseconds* result) { + return ::AddZonedDateTime(cx, zonedDateTime, duration, + TemporalOverflow::Constrain, result); +} + +/** + * DifferenceZonedDateTime ( ns1, ns2, timeZone, calendar, largestUnit ) + */ +static bool DifferenceZonedDateTime(JSContext* cx, const EpochNanoseconds& ns1, + const EpochNanoseconds& ns2, + Handle timeZone, + Handle calendar, + TemporalUnit largestUnit, + InternalDuration* result) { + MOZ_ASSERT(IsValidEpochNanoseconds(ns1)); + MOZ_ASSERT(IsValidEpochNanoseconds(ns2)); + + // Steps 1. + if (ns1 == ns2) { + *result = InternalDuration{{}, {}}; + return true; } - auto& [date, time] = temporalDateTime; - // Step 10. - if (duration.date.years == 0 && duration.date.months == 0 && - duration.date.weeks == 0) { + // Step 2. + ISODateTime startDateTime; + if (!GetISODateTimeFor(cx, timeZone, ns1, &startDateTime)) { + return false; + } + + // Steps 2-3. + ISODateTime endDateTime; + if (!GetISODateTimeFor(cx, timeZone, ns2, &endDateTime)) { + return false; + } + + // Step 4. + int32_t sign = (ns2 - ns1 < EpochDuration{}) ? -1 : 1; + + // Step 5. + int32_t maxDayCorrection = 1 + (sign > 0); + + // Step 6. + int32_t dayCorrection = 0; + + // Step 7. + auto timeDuration = DifferenceTime(startDateTime.time, endDateTime.time); + + // Step 8. + if (TimeDurationSign(timeDuration) == -sign) { + dayCorrection += 1; + } + + // Steps 9-10. + while (dayCorrection <= maxDayCorrection) { // Step 10.a. - auto overflow = TemporalOverflow::Constrain; - if (maybeOptions) { - if (!GetTemporalOverflowOption(cx, maybeOptions, &overflow)) { - return false; - } - } + auto intermediateDate = + BalanceISODate(endDateTime.date, -dayCorrection * sign); // Step 10.b. - Instant intermediate; - if (!AddDaysToZonedDateTime(cx, epochNanoseconds, temporalDateTime, - timeZone, calendar.receiver(), - duration.date.days, overflow, &intermediate)) { + auto intermediateDateTime = + ISODateTime{intermediateDate, startDateTime.time}; + if (!ISODateTimeWithinLimits(intermediateDateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); return false; } // Step 10.c. - return AddInstant(cx, intermediate, duration.time, result); - } - - // Step 11. - MOZ_ASSERT( - CalendarMethodsRecordHasLookedUp(calendar, CalendarMethod::DateAdd)); - - // Step 12. - const auto& datePart = date; - - // Step 13. - const auto& dateDuration = duration.date; - - // Step 14. - PlainDate addedDate; - if (maybeOptions) { - if (!temporal::CalendarDateAdd(cx, calendar, datePart, dateDuration, - maybeOptions, &addedDate)) { - return false; - } - } else { - if (!CalendarDateAdd(cx, calendar, datePart, dateDuration, &addedDate)) { - return false; - } - } - - // Step 15. - Rooted intermediateDateTime(cx); - if (!CreateTemporalDateTime(cx, {addedDate, time}, calendar.receiver(), - &intermediateDateTime)) { - return false; - } - - // Step 16. - Instant intermediateInstant; - if (!GetInstantFor(cx, timeZone, intermediateDateTime, - TemporalDisambiguation::Compatible, - &intermediateInstant)) { - return false; - } - - // Step 17. - return AddInstant(cx, intermediateInstant, duration.time, result); -} - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -static bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds, - Handle timeZone, - Handle calendar, - const NormalizedDuration& duration, - Handle maybeOptions, Instant* result) { - return ::AddZonedDateTime(cx, epochNanoseconds, timeZone, calendar, duration, - mozilla::Nothing(), maybeOptions, result); -} - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool js::temporal::AddZonedDateTime(JSContext* cx, - const Instant& epochNanoseconds, - Handle timeZone, - Handle calendar, - const NormalizedDuration& duration, - Instant* result) { - return ::AddZonedDateTime(cx, epochNanoseconds, timeZone, calendar, duration, - mozilla::Nothing(), nullptr, result); -} - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool js::temporal::AddZonedDateTime(JSContext* cx, - const Instant& epochNanoseconds, - Handle timeZone, - Handle calendar, - const NormalizedDuration& duration, - const PlainDateTime& dateTime, - Instant* result) { - return ::AddZonedDateTime(cx, epochNanoseconds, timeZone, calendar, duration, - mozilla::SomeRef(dateTime), nullptr, result); -} - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool js::temporal::AddZonedDateTime(JSContext* cx, - const Instant& epochNanoseconds, - Handle timeZone, - Handle calendar, - const DateDuration& duration, - Instant* result) { - return ::AddZonedDateTime(cx, epochNanoseconds, timeZone, calendar, - {duration, {}}, mozilla::Nothing(), nullptr, - result); -} - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool js::temporal::AddZonedDateTime(JSContext* cx, - const Instant& epochNanoseconds, - Handle timeZone, - Handle calendar, - const DateDuration& duration, - const PlainDateTime& dateTime, - Instant* result) { - return ::AddZonedDateTime(cx, epochNanoseconds, timeZone, calendar, - {duration, {}}, mozilla::SomeRef(dateTime), nullptr, - result); -} - -/** - * NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , - * precalculatedPlainDateTime ] ) - */ -static bool NormalizedTimeDurationToDays( - JSContext* cx, const NormalizedTimeDuration& duration, - Handle zonedRelativeTo, Handle timeZone, - mozilla::Maybe precalculatedPlainDateTime, - NormalizedTimeAndDays* result) { - MOZ_ASSERT(IsValidNormalizedTimeDuration(duration)); - - // Step 1. - int32_t sign = NormalizedTimeDurationSign(duration); - - // Step 2. - if (sign == 0) { - *result = {int64_t(0), int64_t(0), ToNanoseconds(TemporalUnit::Day)}; - return true; - } - - // Step 3. - const auto& startNs = zonedRelativeTo.instant(); - - // Step 5. - Instant endNs; - if (!AddInstant(cx, startNs, duration, &endNs)) { - return false; - } - - // Steps 4 and 7. - PlainDateTime startDateTime; - if (!precalculatedPlainDateTime) { - if (!GetPlainDateTimeFor(cx, timeZone, startNs, &startDateTime)) { - return false; - } - } else { - startDateTime = *precalculatedPlainDateTime; - } - - // Steps 6 and 8. - PlainDateTime endDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, endNs, &endDateTime)) { - return false; - } - - // Steps 9-10. (Not applicable in our implementation.) - - // Step 11. - int32_t days = DaysUntil(startDateTime.date, endDateTime.date); - MOZ_ASSERT(std::abs(days) <= MaxEpochDaysDuration); - - // Step 12. - int32_t timeSign = CompareTemporalTime(startDateTime.time, endDateTime.time); - - // Steps 13-14. - if (days > 0 && timeSign > 0) { - days -= 1; - } else if (days < 0 && timeSign < 0) { - days += 1; - } - - // Step 15. - PlainDateTimeAndInstant relativeResult; - if (!::AddDaysToZonedDateTime(cx, startNs, startDateTime, timeZone, - zonedRelativeTo.calendar(), days, - TemporalOverflow::Constrain, &relativeResult)) { - return false; - } - MOZ_ASSERT(IsValidISODateTime(relativeResult.dateTime)); - MOZ_ASSERT(IsValidEpochInstant(relativeResult.instant)); - - // Step 16. - if (sign > 0 && days > 0 && relativeResult.instant > endNs) { - // Step 16.a. - days -= 1; - - // Step 16.b. - if (!::AddDaysToZonedDateTime( - cx, startNs, startDateTime, timeZone, zonedRelativeTo.calendar(), - days, TemporalOverflow::Constrain, &relativeResult)) { - return false; - } - MOZ_ASSERT(IsValidISODateTime(relativeResult.dateTime)); - MOZ_ASSERT(IsValidEpochInstant(relativeResult.instant)); - - // Step 16.c. - if (days > 0 && relativeResult.instant > endNs) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT); - return false; - } - MOZ_ASSERT_IF(days > 0, relativeResult.instant <= endNs); - } - - MOZ_ASSERT_IF(days == 0, relativeResult.instant == startNs); - - // Step 17. (Inlined NormalizedTimeDurationFromEpochNanosecondsDifference) - auto ns = endNs - relativeResult.instant; - MOZ_ASSERT(IsValidInstantSpan(ns)); - - // Step 18. - PlainDateTimeAndInstant oneDayFarther; - if (!::AddDaysToZonedDateTime(cx, relativeResult.instant, - relativeResult.dateTime, timeZone, - zonedRelativeTo.calendar(), sign, - TemporalOverflow::Constrain, &oneDayFarther)) { - return false; - } - MOZ_ASSERT(IsValidISODateTime(oneDayFarther.dateTime)); - MOZ_ASSERT(IsValidEpochInstant(oneDayFarther.instant)); - - // Step 19. (Inlined NormalizedTimeDurationFromEpochNanosecondsDifference) - auto dayLengthNs = oneDayFarther.instant - relativeResult.instant; - MOZ_ASSERT(IsValidInstantSpan(dayLengthNs)); - - // clang-format off - // - // ns = endNs - relativeResult.instant - // dayLengthNs = oneDayFarther.instant - relativeResult.instant - // oneDayLess = ns - dayLengthNs - // = (endNs - relativeResult.instant) - (oneDayFarther.instant - relativeResult.instant) - // = endNs - relativeResult.instant - oneDayFarther.instant + relativeResult.instant - // = endNs - oneDayFarther.instant - // - // |endNs| and |oneDayFarther.instant| are both valid epoch instant values, - // so the difference |oneDayLess| is a valid epoch instant difference value. - // - // clang-format on - - // Step 20. (Inlined SubtractNormalizedTimeDuration) - auto oneDayLess = ns - dayLengthNs; - MOZ_ASSERT(IsValidInstantSpan(oneDayLess)); - MOZ_ASSERT(oneDayLess == (endNs - oneDayFarther.instant)); - - // Step 21. - if (oneDayLess == InstantSpan{} || - ((oneDayLess < InstantSpan{}) == (sign < 0))) { - // Step 21.a. - ns = oneDayLess; - - // Step 21.b. - relativeResult = oneDayFarther; - - // Step 21.c. - days += sign; - - // Step 21.d. - PlainDateTimeAndInstant oneDayFarther; - if (!::AddDaysToZonedDateTime( - cx, relativeResult.instant, relativeResult.dateTime, timeZone, - zonedRelativeTo.calendar(), sign, TemporalOverflow::Constrain, - &oneDayFarther)) { - return false; - } - MOZ_ASSERT(IsValidISODateTime(oneDayFarther.dateTime)); - MOZ_ASSERT(IsValidEpochInstant(oneDayFarther.instant)); - - // Step 21.e. (Inlined NormalizedTimeDurationFromEpochNanosecondsDifference) - dayLengthNs = oneDayFarther.instant - relativeResult.instant; - MOZ_ASSERT(IsValidInstantSpan(dayLengthNs)); - - // clang-format off - // - // ns = oneDayLess' - // = endNs - oneDayFarther.instant' - // relativeResult.instant = oneDayFarther.instant' - // dayLengthNs = oneDayFarther.instant - relativeResult.instant - // = oneDayFarther.instant - oneDayFarther.instant' - // oneDayLess = ns - dayLengthNs - // = (endNs - oneDayFarther.instant') - (oneDayFarther.instant - oneDayFarther.instant') - // = endNs - oneDayFarther.instant' - oneDayFarther.instant + oneDayFarther.instant' - // = endNs - oneDayFarther.instant - // - // Where |oneDayLess'| and |oneDayFarther.instant'| denote the variables - // from before this if-statement block. - // - // |endNs| and |oneDayFarther.instant| are both valid epoch instant values, - // so the difference |oneDayLess| is a valid epoch instant difference value. - // - // clang-format on - - // Step 21.f. - auto oneDayLess = ns - dayLengthNs; - if (oneDayLess == InstantSpan{} || - ((oneDayLess < InstantSpan{}) == (sign < 0))) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT); - return false; - } - } - - // Step 22. - if (days < 0 && sign > 0) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCORRECT_SIGN, - "days"); - return false; - } - - // Step 23. - if (days > 0 && sign < 0) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCORRECT_SIGN, - "days"); - return false; - } - - MOZ_ASSERT(IsValidInstantSpan(dayLengthNs)); - MOZ_ASSERT(IsValidInstantSpan(ns)); - - // Steps 24-25. - if (sign < 0) { - if (ns > InstantSpan{}) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCORRECT_SIGN, - "nanoseconds"); - return false; - } - } else { - MOZ_ASSERT(ns >= InstantSpan{}); - } - - // Steps 26-27. - dayLengthNs = dayLengthNs.abs(); - MOZ_ASSERT(ns.abs() < dayLengthNs); - - // Step 28. - constexpr auto maxDayLength = Int128{1} << 53; - auto dayLengthNanos = dayLengthNs.toNanoseconds(); - if (dayLengthNanos >= maxDayLength) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCORRECT_SIGN, - "days"); - return false; - } - - auto timeNanos = ns.toNanoseconds(); - MOZ_ASSERT(timeNanos == Int128{int64_t(timeNanos)}, - "abs(ns) < dayLengthNs < 2**53 implies that |ns| fits in int64"); - - // Step 29. - static_assert(std::numeric_limits::max() <= - ((int64_t(1) << 53) / (24 * 60 * 60))); - - // Step 30. - *result = {int64_t(days), int64_t(timeNanos), int64_t(dayLengthNanos)}; - return true; -} - -/** - * NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , - * precalculatedPlainDateTime ] ) - */ -bool js::temporal::NormalizedTimeDurationToDays( - JSContext* cx, const NormalizedTimeDuration& duration, - Handle zonedRelativeTo, Handle timeZone, - NormalizedTimeAndDays* result) { - return ::NormalizedTimeDurationToDays(cx, duration, zonedRelativeTo, timeZone, - mozilla::Nothing(), result); -} - -/** - * NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , - * precalculatedPlainDateTime ] ) - */ -bool js::temporal::NormalizedTimeDurationToDays( - JSContext* cx, const NormalizedTimeDuration& duration, - Handle zonedRelativeTo, Handle timeZone, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedTimeAndDays* result) { - return ::NormalizedTimeDurationToDays( - cx, duration, zonedRelativeTo, timeZone, - mozilla::SomeRef(precalculatedPlainDateTime), result); -} - -/** - * DifferenceZonedDateTime ( ns1, ns2, timeZoneRec, calendarRec, largestUnit, - * options, precalculatedPlainDateTime ) - */ -static bool DifferenceZonedDateTime( - JSContext* cx, const Instant& ns1, const Instant& ns2, - Handle timeZone, Handle calendar, - TemporalUnit largestUnit, Handle maybeOptions, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result) { - MOZ_ASSERT(IsValidEpochInstant(ns1)); - MOZ_ASSERT(IsValidEpochInstant(ns2)); - - // Steps 1. - if (ns1 == ns2) { - *result = CreateNormalizedDurationRecord({}, {}); - return true; - } - - // FIXME: spec issue - precalculatedPlainDateTime is never undefined - // https://github.com/tc39/proposal-temporal/issues/2822 - - // Steps 2-3. - const auto& startDateTime = precalculatedPlainDateTime; - - // Steps 4-5. - PlainDateTime endDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, ns2, &endDateTime)) { - return false; - } - - // Step 6. - int32_t sign = (ns2 - ns1 < InstantSpan{}) ? -1 : 1; - - // Step 7. - int32_t maxDayCorrection = 1 + (sign > 0); - - // Step 8. - int32_t dayCorrection = 0; - - // Step 9. - auto timeDuration = DifferenceTime(startDateTime.time, endDateTime.time); - - // Step 10. - if (NormalizedTimeDurationSign(timeDuration) == -sign) { - dayCorrection += 1; - } - - // Steps 11-12. - Rooted intermediateDateTime(cx); - while (dayCorrection <= maxDayCorrection) { - // Step 12.a. - auto intermediateDate = - BalanceISODate(endDateTime.date.year, endDateTime.date.month, - endDateTime.date.day - dayCorrection * sign); - - // FIXME: spec issue - CreateTemporalDateTime is fallible - // https://github.com/tc39/proposal-temporal/issues/2824 - - // Step 12.b. - if (!CreateTemporalDateTime(cx, {intermediateDate, startDateTime.time}, - calendar.receiver(), &intermediateDateTime)) { + EpochNanoseconds intermediateNs; + if (!GetEpochNanosecondsFor(cx, timeZone, intermediateDateTime, + TemporalDisambiguation::Compatible, + &intermediateNs)) { return false; } - // Steps 12.c-d. - Instant intermediateInstant; - if (!GetInstantFor(cx, timeZone, intermediateDateTime, - TemporalDisambiguation::Compatible, - &intermediateInstant)) { - return false; - } + // Step 10.d. + auto timeDuration = + TimeDurationFromEpochNanosecondsDifference(ns2, intermediateNs); - // Step 12.e. - auto norm = NormalizedTimeDurationFromEpochNanosecondsDifference( - ns2, intermediateInstant); + // Step 10.e. + int32_t timeSign = TimeDurationSign(timeDuration); - // Step 12.f. - int32_t timeSign = NormalizedTimeDurationSign(norm); - - // Step 12.g. + // Step 10.f. if (sign != -timeSign) { - // Step 13.a. - const auto& date1 = startDateTime.date; - MOZ_ASSERT(ISODateTimeWithinLimits(date1)); - - // Step 13.b. - const auto& date2 = intermediateDate; - MOZ_ASSERT(ISODateTimeWithinLimits(date2)); - - // Step 13.c. + // Step 12. auto dateLargestUnit = std::min(largestUnit, TemporalUnit::Day); - // Steps 13.d-e. - // - // The spec performs an unnecessary copy operation. As an optimization, we - // omit this copy. - auto untilOptions = maybeOptions; - - // Step 13.f. + // Step 13. DateDuration dateDifference; - if (untilOptions) { - if (!DifferenceDate(cx, calendar, date1, date2, dateLargestUnit, - untilOptions, &dateDifference)) { - return false; - } - } else { - if (!DifferenceDate(cx, calendar, date1, date2, dateLargestUnit, - &dateDifference)) { - return false; - } + if (!CalendarDateUntil(cx, calendar, startDateTime.date, intermediateDate, + dateLargestUnit, &dateDifference)) { + return false; } - // Step 13.g. - return CreateNormalizedDurationRecord(cx, dateDifference, norm, result); + // Step 14. + MOZ_ASSERT(DateDurationSign(dateDifference) * + TimeDurationSign(timeDuration) >= + 0); + *result = {dateDifference, timeDuration}; + return true; } - // Step 12.h. + // Step 10.g. dayCorrection += 1; } - // Steps 14-15. + // Step 11. JS_ReportErrorNumberASCII( cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT); @@ -1278,60 +759,97 @@ static bool DifferenceZonedDateTime( } /** - * DifferenceZonedDateTime ( ns1, ns2, timeZoneRec, calendarRec, largestUnit, - * options, precalculatedPlainDateTime ) + * DifferenceZonedDateTimeWithRounding ( ns1, ns2, timeZone, calendar, + * largestUnit, roundingIncrement, smallestUnit, roundingMode ) */ -bool js::temporal::DifferenceZonedDateTime( - JSContext* cx, const Instant& ns1, const Instant& ns2, - Handle timeZone, Handle calendar, - TemporalUnit largestUnit, const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result) { - return ::DifferenceZonedDateTime(cx, ns1, ns2, timeZone, calendar, - largestUnit, nullptr, - precalculatedPlainDateTime, result); -} +bool js::temporal::DifferenceZonedDateTimeWithRounding( + JSContext* cx, JS::Handle zonedDateTime, + const EpochNanoseconds& ns2, const DifferenceSettings& settings, + InternalDuration* result) { + MOZ_ASSERT(IsValidEpochNanoseconds(ns2)); + MOZ_ASSERT(settings.smallestUnit >= settings.largestUnit); + + const auto& ns1 = zonedDateTime.epochNanoseconds(); + auto timeZone = zonedDateTime.timeZone(); + auto calendar = zonedDateTime.calendar(); -/** - * TimeZoneEquals ( one, two ) - */ -static bool TimeZoneEqualsOrThrow(JSContext* cx, Handle one, - Handle two) { // Step 1. - if (one.isObject() && two.isObject() && one.toObject() == two.toObject()) { + if (settings.largestUnit > TemporalUnit::Day) { + // Step 1.a. + auto difference = + DifferenceInstant(ns1, ns2, settings.roundingIncrement, + settings.smallestUnit, settings.roundingMode); + *result = InternalDuration{{}, difference}; return true; } // Step 2. - Rooted timeZoneOne(cx, ToTemporalTimeZoneIdentifier(cx, one)); - if (!timeZoneOne) { + InternalDuration difference; + if (!DifferenceZonedDateTime(cx, ns1, ns2, timeZone, calendar, + settings.largestUnit, &difference)) { return false; } // Step 3. - Rooted timeZoneTwo(cx, ToTemporalTimeZoneIdentifier(cx, two)); - if (!timeZoneTwo) { - return false; - } - - // Steps 4-9. - bool equals; - if (!TimeZoneEquals(cx, timeZoneOne, timeZoneTwo, &equals)) { - return false; - } - if (equals) { + if (settings.smallestUnit == TemporalUnit::Nanosecond && + settings.roundingIncrement == Increment{1}) { + // Step 3.a. + *result = difference; return true; } - // Throw an error when the time zone identifiers don't match. Used when - // unequal time zones throw a RangeError. - if (auto charsOne = QuoteString(cx, timeZoneOne)) { - if (auto charsTwo = QuoteString(cx, timeZoneTwo)) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_TIMEZONE_INCOMPATIBLE, - charsOne.get(), charsTwo.get()); - } + // Step 4. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, timeZone, ns1, &dateTime)) { + return false; } - return false; + + // Step 5. + return RoundRelativeDuration( + cx, difference, ns2, dateTime, timeZone, calendar, settings.largestUnit, + settings.roundingIncrement, settings.smallestUnit, settings.roundingMode, + result); +} + +/** + * DifferenceZonedDateTimeWithTotal ( ns1, ns2, timeZone, calendar, unit ) + */ +bool js::temporal::DifferenceZonedDateTimeWithTotal( + JSContext* cx, JS::Handle zonedDateTime, + const EpochNanoseconds& ns2, TemporalUnit unit, double* result) { + MOZ_ASSERT(IsValidEpochNanoseconds(ns2)); + + const auto& ns1 = zonedDateTime.epochNanoseconds(); + auto timeZone = zonedDateTime.timeZone(); + auto calendar = zonedDateTime.calendar(); + + // Step 1. + if (unit > TemporalUnit::Day) { + // Step 1.a. + auto difference = TimeDurationFromEpochNanosecondsDifference(ns2, ns1); + MOZ_ASSERT(IsValidEpochDuration(difference.to())); + + // Step 1.b. + *result = TotalTimeDuration(difference, unit); + return true; + } + + // Step 2. + InternalDuration difference; + if (!DifferenceZonedDateTime(cx, ns1, ns2, timeZone, calendar, unit, + &difference)) { + return false; + } + + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, timeZone, ns1, &dateTime)) { + return false; + } + + // Step 5. + return TotalRelativeDuration(cx, difference, ns2, dateTime, timeZone, + calendar, unit, result); } /** @@ -1343,23 +861,25 @@ static bool DifferenceTemporalZonedDateTime(JSContext* cx, Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Step 1. (Not applicable in our implementation.) - - // Step 2. + // Step 1. Rooted other(cx); if (!ToTemporalZonedDateTime(cx, args.get(0), &other)) { return false; } - // Step 3. - if (!CalendarEqualsOrThrow(cx, zonedDateTime.calendar(), other.calendar())) { + // Step 2. + if (!CalendarEquals(zonedDateTime.calendar(), other.calendar())) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, + CalendarIdentifier(zonedDateTime.calendar()).data(), + CalendarIdentifier(other.calendar()).data()); return false; } - // Steps 4-5. - Rooted resolvedOptions(cx); + // Steps 3-4. DifferenceSettings settings; if (args.hasDefined(1)) { + // Step 3. Rooted options( cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); if (!options) { @@ -1367,19 +887,13 @@ static bool DifferenceTemporalZonedDateTime(JSContext* cx, } // Step 4. - resolvedOptions = SnapshotOwnProperties(cx, options); - if (!resolvedOptions) { - return false; - } - - // Step 5. if (!GetDifferenceSettings( - cx, operation, resolvedOptions, TemporalUnitGroup::DateTime, + cx, operation, options, TemporalUnitGroup::DateTime, TemporalUnit::Nanosecond, TemporalUnit::Hour, &settings)) { return false; } } else { - // Steps 4-5. + // Steps 3-4. settings = { TemporalUnit::Nanosecond, TemporalUnit::Hour, @@ -1388,44 +902,52 @@ static bool DifferenceTemporalZonedDateTime(JSContext* cx, }; } - // Step 6. + // Step 5. if (settings.largestUnit > TemporalUnit::Day) { MOZ_ASSERT(settings.smallestUnit >= settings.largestUnit); - // Step 6.a. - auto difference = DifferenceInstant( - zonedDateTime.instant(), other.instant(), settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode); + // Step 5.a. + auto timeDuration = + DifferenceInstant(zonedDateTime.epochNanoseconds(), + other.epochNanoseconds(), settings.roundingIncrement, + settings.smallestUnit, settings.roundingMode); - // Step 6.b. - TimeDuration balancedTime; - if (!BalanceTimeDuration(cx, difference, settings.largestUnit, - &balancedTime)) { + // Step 5.b. + Duration result; + if (!TemporalDurationFromInternal(cx, timeDuration, settings.largestUnit, + &result)) { return false; } - // Step 6.c. - auto duration = balancedTime.toDuration(); + // Step 5.c. if (operation == TemporalDifference::Since) { - duration = duration.negate(); + result = result.negate(); } - auto* result = CreateTemporalDuration(cx, duration); - if (!result) { + // Step 5.d. + auto* obj = CreateTemporalDuration(cx, result); + if (!obj) { return false; } - args.rval().setObject(*result); + args.rval().setObject(*obj); return true; } - // Steps 7-8. - if (!TimeZoneEqualsOrThrow(cx, zonedDateTime.timeZone(), other.timeZone())) { + // Steps 6-7. + if (!TimeZoneEquals(zonedDateTime.timeZone(), other.timeZone())) { + if (auto one = QuoteString(cx, zonedDateTime.timeZone().identifier())) { + if (auto two = QuoteString(cx, other.timeZone().identifier())) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_TIMEZONE_INCOMPATIBLE, + one.get(), two.get()); + } + } return false; } - // Step 9. - if (zonedDateTime.instant() == other.instant()) { + // Step 8. + if (zonedDateTime.epochNanoseconds() == other.epochNanoseconds()) { auto* obj = CreateTemporalDuration(cx, {}); if (!obj) { return false; @@ -1435,128 +957,29 @@ static bool DifferenceTemporalZonedDateTime(JSContext* cx, return true; } + // Step 9. + InternalDuration internalDuration; + if (!DifferenceZonedDateTimeWithRounding(cx, zonedDateTime, + other.epochNanoseconds(), settings, + &internalDuration)) { + return false; + } + MOZ_ASSERT(IsValidDuration(internalDuration)); + // Step 10. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { + Duration result; + if (!TemporalDurationFromInternal(cx, internalDuration, TemporalUnit::Hour, + &result)) { return false; } // Step 11. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, zonedDateTime.calendar(), - { - CalendarMethod::DateAdd, - CalendarMethod::DateUntil, - }, - &calendar)) { - return false; - } - - // Steps 12-13. - PlainDateTime precalculatedPlainDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, zonedDateTime.instant(), - &precalculatedPlainDateTime)) { - return false; - } - - // Step 14. - Rooted plainRelativeTo( - cx, CreateTemporalDate(cx, precalculatedPlainDateTime.date, - calendar.receiver())); - if (!plainRelativeTo) { - return false; - } - - // Step 15. - NormalizedDuration difference; - if (!::DifferenceZonedDateTime(cx, zonedDateTime.instant(), other.instant(), - timeZone, calendar, settings.largestUnit, - resolvedOptions, precalculatedPlainDateTime, - &difference)) { - return false; - } - - // Step 16. - bool roundingGranularityIsNoop = - settings.smallestUnit == TemporalUnit::Nanosecond && - settings.roundingIncrement == Increment{1}; - - // Step 17. - if (!roundingGranularityIsNoop) { - // Steps 17.a-b. - NormalizedDuration roundResult; - if (!RoundDuration(cx, difference, settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode, - plainRelativeTo, calendar, zonedDateTime, timeZone, - precalculatedPlainDateTime, &roundResult)) { - return false; - } - - // Step 17.c. - NormalizedTimeAndDays timeAndDays; - if (!NormalizedTimeDurationToDays(cx, roundResult.time, zonedDateTime, - timeZone, &timeAndDays)) { - return false; - } - - // Step 17.d. - int64_t days = roundResult.date.days + timeAndDays.days; - - // Step 17.e. - auto toAdjust = NormalizedDuration{ - { - roundResult.date.years, - roundResult.date.months, - roundResult.date.weeks, - days, - }, - NormalizedTimeDuration::fromNanoseconds(timeAndDays.time), - }; - NormalizedDuration adjustResult; - if (!AdjustRoundedDurationDays(cx, toAdjust, settings.roundingIncrement, - settings.smallestUnit, settings.roundingMode, - zonedDateTime, calendar, timeZone, - precalculatedPlainDateTime, &adjustResult)) { - return false; - } - - // Step 17.f. - DateDuration balanceResult; - if (!temporal::BalanceDateDurationRelative( - cx, adjustResult.date, settings.largestUnit, settings.smallestUnit, - plainRelativeTo, calendar, &balanceResult)) { - return false; - } - - // Step 17.g. - if (!CombineDateAndNormalizedTimeDuration(cx, balanceResult, - adjustResult.time, &difference)) { - return false; - } - } - - // Step 18. - auto timeDuration = BalanceTimeDuration(difference.time, TemporalUnit::Hour); - - // Step 19. - auto duration = Duration{ - double(difference.date.years), double(difference.date.months), - double(difference.date.weeks), double(difference.date.days), - double(timeDuration.hours), double(timeDuration.minutes), - double(timeDuration.seconds), double(timeDuration.milliseconds), - timeDuration.microseconds, timeDuration.nanoseconds, - }; if (operation == TemporalDifference::Since) { - duration = duration.negate(); + result = result.negate(); } - MOZ_ASSERT(IsValidDuration(duration)); - auto* obj = CreateTemporalDuration(cx, duration); + // Step 12. + auto* obj = CreateTemporalDuration(cx, result); if (!obj) { return false; } @@ -1565,76 +988,63 @@ static bool DifferenceTemporalZonedDateTime(JSContext* cx, return true; } -enum class ZonedDateTimeDuration { Add, Subtract }; - /** - * AddDurationToOrSubtractDurationFromZonedDateTime ( operation, zonedDateTime, - * temporalDurationLike, options ) + * AddDurationToZonedDateTime ( operation, zonedDateTime, temporalDurationLike, + * options ) */ -static bool AddDurationToOrSubtractDurationFromZonedDateTime( - JSContext* cx, ZonedDateTimeDuration operation, const CallArgs& args) { +static bool AddDurationToZonedDateTime(JSContext* cx, + TemporalAddDuration operation, + const CallArgs& args) { Rooted zonedDateTime( cx, &args.thisv().toObject().as()); - // Step 1. (Not applicable in our implementation.) + // Step 1. + Duration duration; + if (!ToTemporalDuration(cx, args.get(0), &duration)) { + return false; + } // Step 2. - Duration duration; - if (!ToTemporalDurationRecord(cx, args.get(0), &duration)) { - return false; + if (operation == TemporalAddDuration::Subtract) { + duration = duration.negate(); } - // Step 3. - Rooted options(cx); + // Steps 3-4. + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { - const char* name = - operation == ZonedDateTimeDuration::Add ? "add" : "subtract"; - options = RequireObjectArg(cx, "options", name, args[1]); - } else { - options = NewPlainObjectWithProto(cx, nullptr); - } - if (!options) { - return false; - } + // Step 3. + Rooted options( + cx, RequireObjectArg(cx, "options", ToName(operation), args[1])); + if (!options) { + return false; + } - // Step 4. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; + // Step 4. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { + return false; + } } // Step 5. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, zonedDateTime.calendar(), - { - CalendarMethod::DateAdd, - }, - &calendar)) { - return false; - } + auto calendar = zonedDateTime.calendar(); // Step 6. - if (operation == ZonedDateTimeDuration::Subtract) { - duration = duration.negate(); - } - auto normalized = CreateNormalizedDurationRecord(duration); + auto timeZone = zonedDateTime.timeZone(); // Step 7. - Instant resultInstant; - if (!::AddZonedDateTime(cx, zonedDateTime.instant(), timeZone, calendar, - normalized, options, &resultInstant)) { - return false; - } - MOZ_ASSERT(IsValidEpochInstant(resultInstant)); + auto internalDuration = ToInternalDurationRecord(duration); // Step 8. - auto* result = CreateTemporalZonedDateTime( - cx, resultInstant, timeZone.receiver(), calendar.receiver()); + EpochNanoseconds epochNanoseconds; + if (!::AddZonedDateTime(cx, zonedDateTime, internalDuration, overflow, + &epochNanoseconds)) { + return false; + } + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); + + // Step 9. + auto* result = + CreateTemporalZonedDateTime(cx, epochNanoseconds, timeZone, calendar); if (!result) { return false; } @@ -1644,7 +1054,72 @@ static bool AddDurationToOrSubtractDurationFromZonedDateTime( } /** - * Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ) + * FormatUTCOffsetNanoseconds ( offsetNanoseconds ) + */ +static JSString* FormatUTCOffsetNanoseconds(JSContext* cx, + int64_t offsetNanoseconds) { + MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); + + // Step 1. + char sign = offsetNanoseconds >= 0 ? '+' : '-'; + + // Step 2. + int64_t absoluteNanoseconds = std::abs(offsetNanoseconds); + + // Step 6. (Reordered) + int32_t subSecondNanoseconds = int32_t(absoluteNanoseconds % 1'000'000'000); + + // Step 5. (Reordered) + int32_t quotient = int32_t(absoluteNanoseconds / 1'000'000'000); + int32_t second = quotient % 60; + + // Step 4. (Reordered) + quotient /= 60; + int32_t minute = quotient % 60; + + // Step 3. + int32_t hour = quotient / 60; + MOZ_ASSERT(hour < 24, "time zone offset mustn't exceed 24-hours"); + + // Format: "sign hour{2} : minute{2} : second{2} . fractional{9}" + constexpr size_t maxLength = 1 + 2 + 1 + 2 + 1 + 2 + 1 + 9; + char result[maxLength]; + + size_t n = 0; + + // Steps 7-8. (Inlined FormatTimeString). + result[n++] = sign; + result[n++] = char('0' + (hour / 10)); + result[n++] = char('0' + (hour % 10)); + result[n++] = ':'; + result[n++] = char('0' + (minute / 10)); + result[n++] = char('0' + (minute % 10)); + + if (second != 0 || subSecondNanoseconds != 0) { + result[n++] = ':'; + result[n++] = char('0' + (second / 10)); + result[n++] = char('0' + (second % 10)); + + if (uint32_t fractional = subSecondNanoseconds) { + result[n++] = '.'; + + uint32_t k = 100'000'000; + do { + result[n++] = char('0' + (fractional / k)); + fractional %= k; + k /= 10; + } while (fractional); + } + } + + MOZ_ASSERT(n <= maxLength); + + // Step 9. + return NewStringCopyN(cx, result, n); +} + +/** + * Temporal.ZonedDateTime ( epochNanoseconds, timeZone [ , calendar ] ) */ static bool ZonedDateTimeConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1668,18 +1143,43 @@ static bool ZonedDateTimeConstructor(JSContext* cx, unsigned argc, Value* vp) { } // Step 4. - Rooted timeZone(cx); - if (!ToTemporalTimeZone(cx, args.get(1), &timeZone)) { + if (!args.get(1).isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args.get(1), + nullptr, "not a string"); return false; } // Step 5. - Rooted calendar(cx); - if (!ToTemporalCalendarWithISODefault(cx, args.get(2), &calendar)) { + Rooted timeZoneString(cx, args[1].toString()); + Rooted timeZoneParse(cx); + if (!ParseTimeZoneIdentifier(cx, timeZoneString, &timeZoneParse)) { return false; } - // Step 6. + // Steps 6-7. + Rooted timeZone(cx); + if (!ToTemporalTimeZone(cx, timeZoneParse, &timeZone)) { + return false; + } + + // Steps 8-10. + Rooted calendar(cx, CalendarValue(CalendarId::ISO8601)); + if (args.hasDefined(2)) { + // Step 9. + if (!args[2].isString()) { + ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args[2], + nullptr, "not a string"); + return false; + } + + // Step 10. + Rooted calendarString(cx, args[2].toString()); + if (!CanonicalizeCalendar(cx, calendarString, &calendar)) { + return false; + } + } + + // Step 11. auto* obj = CreateTemporalZonedDateTime(cx, args, epochNanoseconds, timeZone, calendar); if (!obj) { @@ -1697,64 +1197,12 @@ static bool ZonedDateTime_from(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Step 1. - Rooted options(cx); - if (args.hasDefined(1)) { - options = RequireObjectArg(cx, "options", "from", args[1]); - if (!options) { - return false; - } + Rooted zonedDateTime(cx); + if (!ToTemporalZonedDateTime(cx, args.get(0), args.get(1), &zonedDateTime)) { + return false; } - // Step 2. - if (args.get(0).isObject()) { - JSObject* item = &args[0].toObject(); - if (auto* zonedDateTime = item->maybeUnwrapIf()) { - auto epochInstant = ToInstant(zonedDateTime); - Rooted timeZone(cx, zonedDateTime->timeZone()); - Rooted calendar(cx, zonedDateTime->calendar()); - - if (!timeZone.wrap(cx)) { - return false; - } - if (!calendar.wrap(cx)) { - return false; - } - - if (options) { - // Steps 2.a-b. - TemporalDisambiguation ignoredDisambiguation; - if (!GetTemporalDisambiguationOption(cx, options, - &ignoredDisambiguation)) { - return false; - } - - // Step 2.c. - TemporalOffset ignoredOffset; - if (!GetTemporalOffsetOption(cx, options, &ignoredOffset)) { - return false; - } - - // Step 2.d. - TemporalOverflow ignoredOverflow; - if (!GetTemporalOverflowOption(cx, options, &ignoredOverflow)) { - return false; - } - } - - // Step 2.e. - auto* result = - CreateTemporalZonedDateTime(cx, epochInstant, timeZone, calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; - } - } - - // Step 3. - auto* result = ToTemporalZonedDateTime(cx, args.get(0), options); + auto* result = CreateTemporalZonedDateTime(cx, zonedDateTime); if (!result) { return false; } @@ -1782,8 +1230,8 @@ static bool ZonedDateTime_compare(JSContext* cx, unsigned argc, Value* vp) { } // Step 3. - const auto& oneNs = one.instant(); - const auto& twoNs = two.instant(); + const auto& oneNs = one.epochNanoseconds(); + const auto& twoNs = two.epochNanoseconds(); args.rval().setInt32(oneNs > twoNs ? 1 : oneNs < twoNs ? -1 : 0); return true; } @@ -1795,13 +1243,13 @@ static bool ZonedDateTime_calendarId(JSContext* cx, const CallArgs& args) { auto* zonedDateTime = &args.thisv().toObject().as(); // Step 3. - Rooted calendar(cx, zonedDateTime->calendar()); - auto* calendarId = ToTemporalCalendarIdentifier(cx, calendar); - if (!calendarId) { + auto* str = + NewStringCopy(cx, CalendarIdentifier(zonedDateTime->calendar())); + if (!str) { return false; } - args.rval().setString(calendarId); + args.rval().setString(str); return true; } @@ -1822,13 +1270,7 @@ static bool ZonedDateTime_timeZoneId(JSContext* cx, const CallArgs& args) { auto* zonedDateTime = &args.thisv().toObject().as(); // Step 3. - Rooted timeZone(cx, zonedDateTime->timeZone()); - auto* timeZoneId = ToTemporalTimeZoneIdentifier(cx, timeZone); - if (!timeZoneId) { - return false; - } - - args.rval().setString(timeZoneId); + args.rval().setString(zonedDateTime->timeZone().identifier()); return true; } @@ -1849,15 +1291,15 @@ static bool ZonedDateTime_era(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarEra(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Step 4. + return CalendarEra(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } /** @@ -1876,15 +1318,16 @@ static bool ZonedDateTime_eraYear(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Steps 7-9. - return CalendarEraYear(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Steps 4-6. + return CalendarEraYear(cx, zonedDateTime.calendar(), dateTime.date, + args.rval()); } /** @@ -1903,15 +1346,15 @@ static bool ZonedDateTime_year(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarYear(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Step 4. + return CalendarYear(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } /** @@ -1930,15 +1373,16 @@ static bool ZonedDateTime_month(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarMonth(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Step 4. + return CalendarMonth(cx, zonedDateTime.calendar(), dateTime.date, + args.rval()); } /** @@ -1957,15 +1401,16 @@ static bool ZonedDateTime_monthCode(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarMonthCode(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Step 4. + return CalendarMonthCode(cx, zonedDateTime.calendar(), dateTime.date, + args.rval()); } /** @@ -1985,25 +1430,15 @@ static bool ZonedDateTime_day(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Step 4. (Reordered) - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, zonedDateTime.calendar(), - { - CalendarMethod::Day, - }, - &calendar)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Steps 3 and 5-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { - return false; - } - - // Step 7. - return CalendarDay(cx, calendar, dateTime, args.rval()); + // Step 4. + return CalendarDay(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } /** @@ -2022,14 +1457,14 @@ static bool ZonedDateTime_hour(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. + // Step 4. args.rval().setInt32(dateTime.time.hour); return true; } @@ -2050,14 +1485,14 @@ static bool ZonedDateTime_minute(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. + // Step 4. args.rval().setInt32(dateTime.time.minute); return true; } @@ -2078,14 +1513,14 @@ static bool ZonedDateTime_second(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. + // Step 4. args.rval().setInt32(dateTime.time.second); return true; } @@ -2106,14 +1541,14 @@ static bool ZonedDateTime_millisecond(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. + // Step 4. args.rval().setInt32(dateTime.time.millisecond); return true; } @@ -2135,14 +1570,14 @@ static bool ZonedDateTime_microsecond(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. + // Step 4. args.rval().setInt32(dateTime.time.microsecond); return true; } @@ -2164,14 +1599,14 @@ static bool ZonedDateTime_nanosecond(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. + // Step 4. args.rval().setInt32(dateTime.time.nanosecond); return true; } @@ -2186,31 +1621,6 @@ static bool ZonedDateTime_nanosecond(JSContext* cx, unsigned argc, Value* vp) { args); } -/** - * get Temporal.ZonedDateTime.prototype.epochSeconds - */ -static bool ZonedDateTime_epochSeconds(JSContext* cx, const CallArgs& args) { - auto* zonedDateTime = &args.thisv().toObject().as(); - - // Step 3. - auto instant = ToInstant(zonedDateTime); - - // Steps 4-5. - args.rval().setNumber(instant.seconds); - return true; -} - -/** - * get Temporal.ZonedDateTime.prototype.epochSeconds - */ -static bool ZonedDateTime_epochSeconds(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - /** * get Temporal.ZonedDateTime.prototype.epochMilliseconds */ @@ -2219,10 +1629,10 @@ static bool ZonedDateTime_epochMilliseconds(JSContext* cx, auto* zonedDateTime = &args.thisv().toObject().as(); // Step 3. - auto instant = ToInstant(zonedDateTime); + auto epochNs = zonedDateTime->epochNanoseconds(); // Steps 4-5. - args.rval().setNumber(instant.floorToMilliseconds()); + args.rval().setNumber(epochNs.floorToMilliseconds()); return true; } @@ -2237,39 +1647,6 @@ static bool ZonedDateTime_epochMilliseconds(JSContext* cx, unsigned argc, cx, args); } -/** - * get Temporal.ZonedDateTime.prototype.epochMicroseconds - */ -static bool ZonedDateTime_epochMicroseconds(JSContext* cx, - const CallArgs& args) { - auto* zonedDateTime = &args.thisv().toObject().as(); - - // Step 3. - auto instant = ToInstant(zonedDateTime); - - // Step 4. - auto* microseconds = - BigInt::createFromInt64(cx, instant.floorToMicroseconds()); - if (!microseconds) { - return false; - } - - // Step 5. - args.rval().setBigInt(microseconds); - return true; -} - -/** - * get Temporal.ZonedDateTime.prototype.epochMicroseconds - */ -static bool ZonedDateTime_epochMicroseconds(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - /** * get Temporal.ZonedDateTime.prototype.epochNanoseconds */ @@ -2278,7 +1655,7 @@ static bool ZonedDateTime_epochNanoseconds(JSContext* cx, auto* zonedDateTime = &args.thisv().toObject().as(); // Step 3. - auto* nanoseconds = ToEpochNanoseconds(cx, ToInstant(zonedDateTime)); + auto* nanoseconds = ToBigInt(cx, zonedDateTime->epochNanoseconds()); if (!nanoseconds) { return false; } @@ -2305,15 +1682,16 @@ static bool ZonedDateTime_dayOfWeek(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarDayOfWeek(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Step 4. + return CalendarDayOfWeek(cx, zonedDateTime.calendar(), dateTime.date, + args.rval()); } /** @@ -2333,15 +1711,16 @@ static bool ZonedDateTime_dayOfYear(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarDayOfYear(cx, zonedDateTime.calendar(), dateTime, args.rval()); + // Step 4. + return CalendarDayOfYear(cx, zonedDateTime.calendar(), dateTime.date, + args.rval()); } /** @@ -2361,15 +1740,15 @@ static bool ZonedDateTime_weekOfYear(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Steps 7-9. - return CalendarWeekOfYear(cx, zonedDateTime.calendar(), dateTime, + // Steps 4-6. + return CalendarWeekOfYear(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2390,15 +1769,15 @@ static bool ZonedDateTime_yearOfWeek(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Steps 7-9. - return CalendarYearOfWeek(cx, zonedDateTime.calendar(), dateTime, + // Steps 4-6. + return CalendarYearOfWeek(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2420,66 +1799,50 @@ static bool ZonedDateTime_hoursInDay(JSContext* cx, const CallArgs& args) { cx, ZonedDateTime{&args.thisv().toObject().as()}); // Step 3. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; - } + auto timeZone = zonedDateTime.timeZone(); // Step 4. - const auto& instant = zonedDateTime.instant(); + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, timeZone, zonedDateTime.epochNanoseconds(), + &dateTime)) { + return false; + } // Step 5. - PlainDateTime temporalDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, instant, &temporalDateTime)) { + const auto& today = dateTime.date; + + // Step 6. + auto tomorrow = BalanceISODate(today, 1); + if (!ISODateWithinLimits(tomorrow)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return false; } - // Steps 6-8. - const auto& date = temporalDateTime.date; - Rooted isoCalendar(cx, CalendarValue(CalendarId::ISO8601)); + // Step 7. + EpochNanoseconds todayNs; + if (!GetStartOfDay(cx, timeZone, today, &todayNs)) { + return false; + } + + // Step 8. + EpochNanoseconds tomorrowNs; + if (!GetStartOfDay(cx, timeZone, tomorrow, &tomorrowNs)) { + return false; + } // Step 9. - Rooted today(cx); - if (!CreateTemporalDateTime(cx, {date, {}}, isoCalendar, &today)) { - return false; - } + auto diff = tomorrowNs - todayNs; + MOZ_ASSERT(diff.abs() <= EpochDuration::fromDays(2), + "maximum day length for repeated days doesn't exceed two days"); - // Step 10. - auto tomorrowFields = BalanceISODate(date.year, date.month, date.day + 1); + static_assert(EpochDuration::fromDays(2).toNanoseconds() < Int128{INT64_MAX}, + "two days in nanoseconds fits into int64_t"); - // Step 11. - Rooted tomorrow(cx); - if (!CreateTemporalDateTime(cx, {tomorrowFields, {}}, isoCalendar, - &tomorrow)) { - return false; - } - - // Step 12. - Instant todayInstant; - if (!GetInstantFor(cx, timeZone, today, TemporalDisambiguation::Compatible, - &todayInstant)) { - return false; - } - - // Step 13. - Instant tomorrowInstant; - if (!GetInstantFor(cx, timeZone, tomorrow, TemporalDisambiguation::Compatible, - &tomorrowInstant)) { - return false; - } - - // Step 14. - auto diff = tomorrowInstant - todayInstant; - MOZ_ASSERT(IsValidInstantSpan(diff)); - - // Step 15. - constexpr auto nsPerHour = Int128{ToNanoseconds(TemporalUnit::Hour)}; - args.rval().setNumber(FractionToDouble(diff.toNanoseconds(), nsPerHour)); + // Step 10. (Inlined TotalTimeDuration) + constexpr auto nsPerHour = ToNanoseconds(TemporalUnit::Hour); + args.rval().setNumber( + FractionToDouble(int64_t(diff.toNanoseconds()), nsPerHour)); return true; } @@ -2500,15 +1863,15 @@ static bool ZonedDateTime_daysInWeek(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarDaysInWeek(cx, zonedDateTime.calendar(), dateTime, + // Step 4. + return CalendarDaysInWeek(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2529,15 +1892,15 @@ static bool ZonedDateTime_daysInMonth(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarDaysInMonth(cx, zonedDateTime.calendar(), dateTime, + // Step 4. + return CalendarDaysInMonth(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2558,15 +1921,15 @@ static bool ZonedDateTime_daysInYear(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarDaysInYear(cx, zonedDateTime.calendar(), dateTime, + // Step 4. + return CalendarDaysInYear(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2587,15 +1950,15 @@ static bool ZonedDateTime_monthsInYear(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarMonthsInYear(cx, zonedDateTime.calendar(), dateTime, + // Step 4. + return CalendarMonthsInYear(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2617,15 +1980,15 @@ static bool ZonedDateTime_inLeapYear(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime dateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &dateTime)) { + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { return false; } - // Step 7. - return CalendarInLeapYear(cx, zonedDateTime.calendar(), dateTime, + // Step 4. + return CalendarInLeapYear(cx, zonedDateTime.calendar(), dateTime.date, args.rval()); } @@ -2648,14 +2011,10 @@ static bool ZonedDateTime_offsetNanoseconds(JSContext* cx, cx, ZonedDateTime{&args.thisv().toObject().as()}); // Step 3. - auto timeZone = zonedDateTime.timeZone(); - - // Step 4. - const auto& instant = zonedDateTime.instant(); - - // Step 5. int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { + if (!GetOffsetNanosecondsFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), + &offsetNanoseconds)) { return false; } MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); @@ -2683,13 +2042,16 @@ static bool ZonedDateTime_offset(JSContext* cx, const CallArgs& args) { cx, ZonedDateTime{&args.thisv().toObject().as()}); // Step 3. - auto timeZone = zonedDateTime.timeZone(); + int64_t offsetNanoseconds; + if (!GetOffsetNanosecondsFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), + &offsetNanoseconds)) { + return false; + } + MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); // Step 4. - const auto& instant = zonedDateTime.instant(); - - // Step 5. - JSString* str = GetOffsetStringFor(cx, timeZone, instant); + JSString* str = FormatUTCOffsetNanoseconds(cx, offsetNanoseconds); if (!str) { return false; } @@ -2727,184 +2089,104 @@ static bool ZonedDateTime_with(JSContext* cx, const CallArgs& args) { } // Step 4. - Rooted resolvedOptions(cx); + const auto& epochNs = zonedDateTime.epochNanoseconds(); + + // Step 5. + auto timeZone = zonedDateTime.timeZone(); + + // Step 6. + auto calendar = zonedDateTime.calendar(); + + // Step 7. + int64_t offsetNanoseconds; + if (!GetOffsetNanosecondsFor(cx, timeZone, epochNs, &offsetNanoseconds)) { + return false; + } + + // Step 8. + auto dateTime = GetISODateTimeFor(epochNs, offsetNanoseconds); + MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); + + // Step 9. + Rooted date(cx, PlainDate{dateTime.date, calendar}); + Rooted fields(cx); + if (!ISODateToFields(cx, date, &fields)) { + return false; + } + + // Steps 10-16. + fields.setHour(dateTime.time.hour); + fields.setMinute(dateTime.time.minute); + fields.setSecond(dateTime.time.second); + fields.setMillisecond(dateTime.time.millisecond); + fields.setMicrosecond(dateTime.time.microsecond); + fields.setNanosecond(dateTime.time.nanosecond); + fields.setOffset(OffsetField{offsetNanoseconds}); + + // Step 17. + Rooted partialZonedDateTime(cx); + if (!PreparePartialCalendarFields(cx, calendar, temporalZonedDateTimeLike, + { + CalendarField::Year, + CalendarField::Month, + CalendarField::MonthCode, + CalendarField::Day, + CalendarField::Hour, + CalendarField::Minute, + CalendarField::Second, + CalendarField::Millisecond, + CalendarField::Microsecond, + CalendarField::Nanosecond, + CalendarField::Offset, + }, + &partialZonedDateTime)) { + return false; + } + MOZ_ASSERT(!partialZonedDateTime.keys().isEmpty()); + + // Step 18. + fields = CalendarMergeFields(calendar, fields, partialZonedDateTime); + + // Steps 19-22. + auto disambiguation = TemporalDisambiguation::Compatible; + auto offset = TemporalOffset::Prefer; + auto overflow = TemporalOverflow::Constrain; if (args.hasDefined(1)) { + // Step 19. Rooted options(cx, RequireObjectArg(cx, "options", "with", args[1])); if (!options) { return false; } - resolvedOptions = SnapshotOwnProperties(cx, options); - } else { - resolvedOptions = NewPlainObjectWithProto(cx, nullptr); - } - if (!resolvedOptions) { - return false; - } - // Step 5. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, zonedDateTime.calendar(), - { - CalendarMethod::DateFromFields, - CalendarMethod::Fields, - CalendarMethod::MergeFields, - }, - &calendar)) { - return false; - } + // Step 20. + if (!GetTemporalDisambiguationOption(cx, options, &disambiguation)) { + return false; + } - // Step 6. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; - } + // Step 21. + if (!GetTemporalOffsetOption(cx, options, &offset)) { + return false; + } - // Step 7. - const auto& instant = zonedDateTime.instant(); - - // Step 8. - int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { - return false; - } - - // Step 9. - Rooted dateTime( - cx, - GetPlainDateTimeFor(cx, instant, calendar.receiver(), offsetNanoseconds)); - if (!dateTime) { - return false; - } - - // Step 10. - Rooted fields(cx); - JS::RootedVector fieldNames(cx); - if (!PrepareCalendarFieldsAndFieldNames(cx, calendar, dateTime, - { - CalendarField::Day, - CalendarField::Month, - CalendarField::MonthCode, - CalendarField::Year, - }, - &fields, &fieldNames)) { - return false; - } - - // Steps 11-16. - struct TimeField { - using FieldName = ImmutableTenuredPtr JSAtomState::*; - - FieldName name; - int32_t value; - } timeFields[] = { - {&JSAtomState::hour, dateTime->isoHour()}, - {&JSAtomState::minute, dateTime->isoMinute()}, - {&JSAtomState::second, dateTime->isoSecond()}, - {&JSAtomState::millisecond, dateTime->isoMillisecond()}, - {&JSAtomState::microsecond, dateTime->isoMicrosecond()}, - {&JSAtomState::nanosecond, dateTime->isoNanosecond()}, - }; - - Rooted timeFieldValue(cx); - for (const auto& timeField : timeFields) { - Handle name = cx->names().*(timeField.name); - timeFieldValue.setInt32(timeField.value); - - if (!DefineDataProperty(cx, fields, name, timeFieldValue)) { + // Step 22. + if (!GetTemporalOverflowOption(cx, options, &overflow)) { return false; } } - // Step 17. - JSString* fieldsOffset = FormatUTCOffsetNanoseconds(cx, offsetNanoseconds); - if (!fieldsOffset) { - return false; - } - - timeFieldValue.setString(fieldsOffset); - if (!DefineDataProperty(cx, fields, cx->names().offset, timeFieldValue)) { - return false; - } - - // Step 18. - if (!AppendSorted(cx, fieldNames.get(), - { - TemporalField::Hour, - TemporalField::Microsecond, - TemporalField::Millisecond, - TemporalField::Minute, - TemporalField::Nanosecond, - TemporalField::Offset, - TemporalField::Second, - })) { - return false; - } - - // Step 19. - Rooted partialZonedDateTime( - cx, - PreparePartialTemporalFields(cx, temporalZonedDateTimeLike, fieldNames)); - if (!partialZonedDateTime) { - return false; - } - - // Step 20. - Rooted mergedFields( - cx, CalendarMergeFields(cx, calendar, fields, partialZonedDateTime)); - if (!mergedFields) { - return false; - } - - // Step 21. - fields = PrepareTemporalFields(cx, mergedFields, fieldNames, - {TemporalField::Offset}); - if (!fields) { - return false; - } - - // Step 22-23. - auto disambiguation = TemporalDisambiguation::Compatible; - if (!GetTemporalDisambiguationOption(cx, resolvedOptions, &disambiguation)) { - return false; - } - - // Step 24. - auto offset = TemporalOffset::Prefer; - if (!GetTemporalOffsetOption(cx, resolvedOptions, &offset)) { - return false; - } - - // Step 25. - PlainDateTime dateTimeResult; - if (!InterpretTemporalDateTimeFields(cx, calendar, fields, resolvedOptions, + // Step 23. + ISODateTime dateTimeResult; + if (!InterpretTemporalDateTimeFields(cx, calendar, fields, overflow, &dateTimeResult)) { return false; } - // Step 26. - Rooted offsetString(cx); - if (!GetProperty(cx, fields, fields, cx->names().offset, &offsetString)) { - return false; - } + // Step 24. + int64_t newOffsetNanoseconds = int64_t(fields.offset()); - // Step 27. - MOZ_ASSERT(offsetString.isString()); - - // Step 28. - Rooted offsetStr(cx, offsetString.toString()); - int64_t newOffsetNanoseconds; - if (!ParseDateTimeUTCOffset(cx, offsetStr, &newOffsetNanoseconds)) { - return false; - } - - // Step 29. - Instant epochNanoseconds; + // Step 25. + EpochNanoseconds epochNanoseconds; if (!InterpretISODateTimeOffset( cx, dateTimeResult, OffsetBehaviour::Option, newOffsetNanoseconds, timeZone, disambiguation, offset, MatchBehaviour::MatchExactly, @@ -2912,9 +2194,9 @@ static bool ZonedDateTime_with(JSContext* cx, const CallArgs& args) { return false; } - // Step 30. - auto* result = CreateTemporalZonedDateTime( - cx, epochNanoseconds, timeZone.receiver(), calendar.receiver()); + // Step 26. + auto* result = + CreateTemporalZonedDateTime(cx, epochNanoseconds, timeZone, calendar); if (!result) { return false; } @@ -2940,52 +2222,50 @@ static bool ZonedDateTime_withPlainTime(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Step 3. (Inlined ToTemporalTimeOrMidnight) - PlainTime time = {}; - if (args.hasDefined(0)) { + // Step 3. + auto timeZone = zonedDateTime.timeZone(); + + // Step 4. + auto calendar = zonedDateTime.calendar(); + + // Step 5. + ISODateTime isoDateTime; + if (!GetISODateTimeFor(cx, timeZone, zonedDateTime.epochNanoseconds(), + &isoDateTime)) { + return false; + } + + // Steps 6-7. + EpochNanoseconds epochNs; + if (!args.hasDefined(0)) { + // Step 6.a. + if (!GetStartOfDay(cx, timeZone, isoDateTime.date, &epochNs)) { + return false; + } + } else { + // Step 7.a. + Time time; if (!ToTemporalTime(cx, args[0], &time)) { return false; } + + // Step 7.b. + auto resultISODateTime = ISODateTime{isoDateTime.date, time}; + if (!ISODateTimeWithinLimits(resultISODateTime)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID); + return false; + } + + // Step 7.c. + if (!GetEpochNanosecondsFor(cx, timeZone, resultISODateTime, + TemporalDisambiguation::Compatible, &epochNs)) { + return false; + } } - // Step 4. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; - } - - // Steps 5 and 7. - PlainDateTime plainDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, zonedDateTime.instant(), - &plainDateTime)) { - return false; - } - - // Step 6. - auto calendar = zonedDateTime.calendar(); - // Step 8. - Rooted resultPlainDateTime(cx); - if (!CreateTemporalDateTime(cx, {plainDateTime.date, time}, calendar, - &resultPlainDateTime)) { - return false; - } - - // Step 9. - Instant instant; - if (!GetInstantFor(cx, timeZone, resultPlainDateTime, - TemporalDisambiguation::Compatible, &instant)) { - return false; - } - - // Step 10. - auto* result = - CreateTemporalZonedDateTime(cx, instant, timeZone.receiver(), calendar); + auto* result = CreateTemporalZonedDateTime(cx, epochNs, timeZone, calendar); if (!result) { return false; } @@ -3005,81 +2285,6 @@ static bool ZonedDateTime_withPlainTime(JSContext* cx, unsigned argc, cx, args); } -/** - * Temporal.ZonedDateTime.prototype.withPlainDate ( plainDateLike ) - */ -static bool ZonedDateTime_withPlainDate(JSContext* cx, const CallArgs& args) { - Rooted zonedDateTime( - cx, ZonedDateTime{&args.thisv().toObject().as()}); - - // Step 3. - Rooted plainDate(cx); - if (!ToTemporalDate(cx, args.get(0), &plainDate)) { - return false; - } - auto date = plainDate.date(); - - // Step 4. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; - } - - // Steps 5-6. - PlainDateTime plainDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, zonedDateTime.instant(), - &plainDateTime)) { - return false; - } - - // Step 7. - Rooted calendar(cx); - if (!ConsolidateCalendars(cx, zonedDateTime.calendar(), plainDate.calendar(), - &calendar)) { - return false; - } - - // Step 8. - Rooted resultPlainDateTime(cx); - if (!CreateTemporalDateTime(cx, {date, plainDateTime.time}, calendar, - &resultPlainDateTime)) { - return false; - } - - // Step 9. - Instant instant; - if (!GetInstantFor(cx, timeZone, resultPlainDateTime, - TemporalDisambiguation::Compatible, &instant)) { - return false; - } - - // Step 10. - auto* result = - CreateTemporalZonedDateTime(cx, instant, timeZone.receiver(), calendar); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.ZonedDateTime.prototype.withPlainDate ( plainDateLike ) - */ -static bool ZonedDateTime_withPlainDate(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - /** * Temporal.ZonedDateTime.prototype.withTimeZone ( timeZoneLike ) */ @@ -3095,7 +2300,7 @@ static bool ZonedDateTime_withTimeZone(JSContext* cx, const CallArgs& args) { // Step 4. auto* result = CreateTemporalZonedDateTime( - cx, zonedDateTime.instant(), timeZone, zonedDateTime.calendar()); + cx, zonedDateTime.epochNanoseconds(), timeZone, zonedDateTime.calendar()); if (!result) { return false; } @@ -3130,7 +2335,7 @@ static bool ZonedDateTime_withCalendar(JSContext* cx, const CallArgs& args) { // Step 4. auto* result = CreateTemporalZonedDateTime( - cx, zonedDateTime.instant(), zonedDateTime.timeZone(), calendar); + cx, zonedDateTime.epochNanoseconds(), zonedDateTime.timeZone(), calendar); if (!result) { return false; } @@ -3154,8 +2359,8 @@ static bool ZonedDateTime_withCalendar(JSContext* cx, unsigned argc, * Temporal.ZonedDateTime.prototype.add ( temporalDurationLike [ , options ] ) */ static bool ZonedDateTime_add(JSContext* cx, const CallArgs& args) { - return AddDurationToOrSubtractDurationFromZonedDateTime( - cx, ZonedDateTimeDuration::Add, args); + // Step 3. + return AddDurationToZonedDateTime(cx, TemporalAddDuration::Add, args); } /** @@ -3172,8 +2377,8 @@ static bool ZonedDateTime_add(JSContext* cx, unsigned argc, Value* vp) { * ] ) */ static bool ZonedDateTime_subtract(JSContext* cx, const CallArgs& args) { - return AddDurationToOrSubtractDurationFromZonedDateTime( - cx, ZonedDateTimeDuration::Subtract, args); + // Step 3. + return AddDurationToZonedDateTime(cx, TemporalAddDuration::Subtract, args); } /** @@ -3297,9 +2502,9 @@ static bool ZonedDateTime_round(JSContext* cx, const CallArgs& args) { if (smallestUnit == TemporalUnit::Nanosecond && roundingIncrement == Increment{1}) { // Step 13.a. - auto* result = CreateTemporalZonedDateTime(cx, zonedDateTime.instant(), - zonedDateTime.timeZone(), - zonedDateTime.calendar()); + auto* result = CreateTemporalZonedDateTime( + cx, zonedDateTime.epochNanoseconds(), zonedDateTime.timeZone(), + zonedDateTime.calendar()); if (!result) { return false; } @@ -3309,116 +2514,93 @@ static bool ZonedDateTime_round(JSContext* cx, const CallArgs& args) { } // Step 14. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; - } + auto thisNs = zonedDateTime.epochNanoseconds(); - // Step 16. (Reordered) + // Step 15. + auto timeZone = zonedDateTime.timeZone(); + + // Step 16. auto calendar = zonedDateTime.calendar(); - // Steps 15 and 17. - int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, zonedDateTime.instant(), - &offsetNanoseconds)) { + // Step 17. + ISODateTime isoDateTime; + if (!GetISODateTimeFor(cx, timeZone, thisNs, &isoDateTime)) { return false; } - MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); - // Step 18. - auto temporalDateTime = - GetPlainDateTimeFor(zonedDateTime.instant(), offsetNanoseconds); - - // Step 19. - Instant epochNanoseconds; + // Steps 18-19. + EpochNanoseconds epochNanoseconds; if (smallestUnit == TemporalUnit::Day) { - // Step 19.a. - Rooted isoCalendar(cx, CalendarValue(CalendarId::ISO8601)); - Rooted dtStart(cx); - if (!CreateTemporalDateTime(cx, {temporalDateTime.date, {}}, isoCalendar, - &dtStart)) { + // Step 18.a. + const auto& dateStart = isoDateTime.date; + + // Step 18.b. + auto dateEnd = BalanceISODate(dateStart, 1); + if (!ISODateWithinLimits(dateEnd)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_PLAIN_DATE_INVALID); return false; } - // Step 19.b. - auto dateEnd = - BalanceISODate(temporalDateTime.date.year, temporalDateTime.date.month, - temporalDateTime.date.day + 1); - - // Step 19.c. - Rooted dtEnd(cx); - if (!CreateTemporalDateTime(cx, {dateEnd, {}}, isoCalendar, &dtEnd)) { + // Step 18.c. + EpochNanoseconds startNs; + if (!GetStartOfDay(cx, timeZone, dateStart, &startNs)) { return false; } - // Step 19.d. - const auto& thisNs = zonedDateTime.instant(); + // Step 18.d. + MOZ_ASSERT(thisNs >= startNs); - // Steps 19.e-f. - Instant startNs; - if (!GetInstantFor(cx, timeZone, dtStart, - TemporalDisambiguation::Compatible, &startNs)) { + // Step 18.e. + EpochNanoseconds endNs; + if (!GetStartOfDay(cx, timeZone, dateEnd, &endNs)) { return false; } - // Step 19.g. - if (thisNs < startNs) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT); - return false; - } + // Step 18.f. + MOZ_ASSERT(thisNs < endNs); - // Steps 19.h-i. - Instant endNs; - if (!GetInstantFor(cx, timeZone, dtEnd, TemporalDisambiguation::Compatible, - &endNs)) { - return false; - } - - // Step 19.j. - if (thisNs >= endNs) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT); - return false; - } - - // Step 19.k. + // Step 18.g. auto dayLengthNs = endNs - startNs; - MOZ_ASSERT(IsValidInstantSpan(dayLengthNs)); - MOZ_ASSERT(dayLengthNs > InstantSpan{}, "dayLengthNs is positive"); + MOZ_ASSERT(IsValidEpochDuration(dayLengthNs)); + MOZ_ASSERT(dayLengthNs > EpochDuration{}, "dayLengthNs is positive"); - // Step 19.l. (Inlined NormalizedTimeDurationFromEpochNanosecondsDifference) + // Step 18.h. (Inlined TimeDurationFromEpochNanosecondsDifference) auto dayProgressNs = thisNs - startNs; - MOZ_ASSERT(IsValidInstantSpan(dayProgressNs)); - MOZ_ASSERT(dayProgressNs >= InstantSpan{}, "dayProgressNs is non-negative"); + MOZ_ASSERT(IsValidEpochDuration(dayProgressNs)); + MOZ_ASSERT(dayProgressNs >= EpochDuration{}, + "dayProgressNs is non-negative"); MOZ_ASSERT(startNs <= thisNs && thisNs < endNs); MOZ_ASSERT(dayProgressNs < dayLengthNs); + MOZ_ASSERT(dayLengthNs <= EpochDuration::fromDays(2), + "maximum day length for repeated days"); - // Step 19.m. (Inlined RoundNormalizedTimeDurationToIncrement) - auto rounded = - RoundNumberToIncrement(dayProgressNs.toNanoseconds(), - dayLengthNs.toNanoseconds(), roundingMode); - auto roundedDaysNs = InstantSpan::fromNanoseconds(rounded); - MOZ_ASSERT(roundedDaysNs == InstantSpan{} || roundedDaysNs == dayLengthNs); - MOZ_ASSERT(IsValidInstantSpan(roundedDaysNs)); + // Step 18.i. (Inlined RoundTimeDurationToIncrement) + auto rounded = RoundNumberToIncrement( + static_cast(dayProgressNs.toNanoseconds()), + static_cast(dayLengthNs.toNanoseconds()), roundingMode); + auto roundedDaysNs = EpochDuration::fromNanoseconds(rounded); + MOZ_ASSERT(roundedDaysNs == EpochDuration{} || + roundedDaysNs == dayLengthNs); + MOZ_ASSERT(IsValidEpochDuration(roundedDaysNs)); - // Step 19.n. + // Step 18.j. (Inlined AddTimeDurationToEpochNanoseconds) epochNanoseconds = startNs + roundedDaysNs; MOZ_ASSERT(epochNanoseconds == startNs || epochNanoseconds == endNs); } else { - // Step 20.a. - auto roundResult = RoundISODateTime(temporalDateTime, roundingIncrement, + // Step 19.a. + auto roundResult = RoundISODateTime(isoDateTime, roundingIncrement, smallestUnit, roundingMode); - // Step 20.b. + // Step 19.b. + int64_t offsetNanoseconds; + if (!GetOffsetNanosecondsFor(cx, timeZone, thisNs, &offsetNanoseconds)) { + return false; + } + MOZ_ASSERT(std::abs(offsetNanoseconds) < ToNanoseconds(TemporalUnit::Day)); + + // Step 19.c. if (!InterpretISODateTimeOffset( cx, roundResult, OffsetBehaviour::Option, offsetNanoseconds, timeZone, TemporalDisambiguation::Compatible, @@ -3427,11 +2609,11 @@ static bool ZonedDateTime_round(JSContext* cx, const CallArgs& args) { return false; } } - MOZ_ASSERT(IsValidEpochInstant(epochNanoseconds)); + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); - // Step 22. - auto* result = CreateTemporalZonedDateTime(cx, epochNanoseconds, - timeZone.receiver(), calendar); + // Step 20. + auto* result = + CreateTemporalZonedDateTime(cx, epochNanoseconds, timeZone, calendar); if (!result) { return false; } @@ -3463,15 +2645,9 @@ static bool ZonedDateTime_equals(JSContext* cx, const CallArgs& args) { } // Steps 4-6. - bool equals = zonedDateTime.instant() == other.instant(); - if (equals && !TimeZoneEquals(cx, zonedDateTime.timeZone(), other.timeZone(), - &equals)) { - return false; - } - if (equals && !CalendarEquals(cx, zonedDateTime.calendar(), other.calendar(), - &equals)) { - return false; - } + bool equals = zonedDateTime.epochNanoseconds() == other.epochNanoseconds() && + TimeZoneEquals(zonedDateTime.timeZone(), other.timeZone()) && + CalendarEquals(zonedDateTime.calendar(), other.calendar()); args.rval().setBoolean(equals); return true; @@ -3581,16 +2757,12 @@ static bool ZonedDateTime_toLocaleString(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Step 3. - JSString* str = TemporalZonedDateTimeToString( - cx, zonedDateTime, Precision::Auto(), ShowCalendar::Auto, - ShowTimeZoneName::Auto, ShowOffset::Auto); - if (!str) { - return false; - } - - args.rval().setString(str); - return true; + // Steps 3-6. + Handle required = cx->names().any; + Handle defaults = cx->names().all; + Rooted timeZone(cx, + StringValue(zonedDateTime.timeZone().identifier())); + return TemporalObjectToLocaleString(cx, args, required, defaults, timeZone); } /** @@ -3649,45 +2821,26 @@ static bool ZonedDateTime_startOfDay(JSContext* cx, const CallArgs& args) { cx, ZonedDateTime{&args.thisv().toObject().as()}); // Step 3. - Rooted timeZone(cx); - if (!CreateTimeZoneMethodsRecord(cx, zonedDateTime.timeZone(), - { - TimeZoneMethod::GetOffsetNanosecondsFor, - TimeZoneMethod::GetPossibleInstantsFor, - }, - &timeZone)) { - return false; - } + auto timeZone = zonedDateTime.timeZone(); // Step 4. auto calendar = zonedDateTime.calendar(); // Step 5. - const auto& instant = zonedDateTime.instant(); + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, timeZone, zonedDateTime.epochNanoseconds(), + &dateTime)) { + return false; + } - // Steps 5-6. - PlainDateTime temporalDateTime; - if (!GetPlainDateTimeFor(cx, timeZone, instant, &temporalDateTime)) { + // Step 6. + EpochNanoseconds epochNs; + if (!GetStartOfDay(cx, timeZone, dateTime.date, &epochNs)) { return false; } // Step 7. - Rooted startDateTime(cx); - if (!CreateTemporalDateTime(cx, {temporalDateTime.date, {}}, calendar, - &startDateTime)) { - return false; - } - - // Step 8. - Instant startInstant; - if (!GetInstantFor(cx, timeZone, startDateTime, - TemporalDisambiguation::Compatible, &startInstant)) { - return false; - } - - // Step 9. - auto* result = CreateTemporalZonedDateTime(cx, startInstant, - timeZone.receiver(), calendar); + auto* result = CreateTemporalZonedDateTime(cx, epochNs, timeZone, calendar); if (!result) { return false; } @@ -3706,15 +2859,96 @@ static bool ZonedDateTime_startOfDay(JSContext* cx, unsigned argc, Value* vp) { args); } +/** + * Temporal.ZonedDateTime.prototype.getTimeZoneTransition ( directionParam ) + */ +static bool ZonedDateTime_getTimeZoneTransition(JSContext* cx, + const CallArgs& args) { + Rooted zonedDateTime( + cx, ZonedDateTime{&args.thisv().toObject().as()}); + + // Step 3. + auto timeZone = zonedDateTime.timeZone(); + + // Steps 4-7. + auto direction = Direction::Next; + if (args.get(0).isString()) { + // Steps 5 and 7. + Rooted directionString(cx, args[0].toString()); + if (!GetDirectionOption(cx, directionString, &direction)) { + return false; + } + } else { + // Steps 4 and 6. + Rooted options(cx, RequireObjectArg(cx, "getTimeZoneTransition", + "direction", args.get(0))); + if (!options) { + return false; + } + + // Step 7. + if (!GetDirectionOption(cx, options, &direction)) { + return false; + } + } + + // Step 8. + if (timeZone.isOffset()) { + args.rval().setNull(); + return true; + } + + // Steps 9-10. + mozilla::Maybe transition; + if (direction == Direction::Next) { + if (!GetNamedTimeZoneNextTransition( + cx, timeZone, zonedDateTime.epochNanoseconds(), &transition)) { + return false; + } + } else { + if (!GetNamedTimeZonePreviousTransition( + cx, timeZone, zonedDateTime.epochNanoseconds(), &transition)) { + return false; + } + } + + // Step 11. + if (!transition) { + args.rval().setNull(); + return true; + } + + // Step 12. + auto* result = CreateTemporalZonedDateTime(cx, *transition, timeZone, + zonedDateTime.calendar()); + if (!result) { + return false; + } + + args.rval().setObject(*result); + return true; +} + +/** + * Temporal.ZonedDateTime.prototype.getTimeZoneTransition ( directionParam ) + */ +static bool ZonedDateTime_getTimeZoneTransition(JSContext* cx, unsigned argc, + Value* vp) { + // Steps 1-2. + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + /** * Temporal.ZonedDateTime.prototype.toInstant ( ) */ static bool ZonedDateTime_toInstant(JSContext* cx, const CallArgs& args) { auto* zonedDateTime = &args.thisv().toObject().as(); - auto instant = ToInstant(zonedDateTime); + auto epochNs = zonedDateTime->epochNanoseconds(); // Step 3. - auto* result = CreateTemporalInstant(cx, instant); + auto* result = CreateTemporalInstant(cx, epochNs); if (!result) { return false; } @@ -3740,14 +2974,14 @@ static bool ZonedDateTime_toPlainDate(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime temporalDateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &temporalDateTime)) { + // Step 3. + ISODateTime temporalDateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &temporalDateTime)) { return false; } - // Step 7. + // Step 4. auto* result = CreateTemporalDate(cx, temporalDateTime.date, zonedDateTime.calendar()); if (!result) { @@ -3775,14 +3009,14 @@ static bool ZonedDateTime_toPlainTime(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-6. - PlainDateTime temporalDateTime; - if (!GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), - zonedDateTime.instant(), &temporalDateTime)) { + // Step 3. + ISODateTime temporalDateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &temporalDateTime)) { return false; } - // Step 7. + // Step 4. auto* result = CreateTemporalTime(cx, temporalDateTime.time); if (!result) { return false; @@ -3809,10 +3043,16 @@ static bool ZonedDateTime_toPlainDateTime(JSContext* cx, const CallArgs& args) { Rooted zonedDateTime( cx, ZonedDateTime{&args.thisv().toObject().as()}); - // Steps 3-5. - auto* result = - GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), zonedDateTime.instant(), - zonedDateTime.calendar()); + // Step 3. + ISODateTime dateTime; + if (!GetISODateTimeFor(cx, zonedDateTime.timeZone(), + zonedDateTime.epochNanoseconds(), &dateTime)) { + return false; + } + MOZ_ASSERT(ISODateTimeWithinLimits(dateTime)); + + // Step 4. + auto* result = CreateTemporalDateTime(cx, dateTime, zonedDateTime.calendar()); if (!result) { return false; } @@ -3832,304 +3072,6 @@ static bool ZonedDateTime_toPlainDateTime(JSContext* cx, unsigned argc, cx, args); } -/** - * Temporal.ZonedDateTime.prototype.toPlainYearMonth ( ) - */ -static bool ZonedDateTime_toPlainYearMonth(JSContext* cx, - const CallArgs& args) { - Rooted zonedDateTime( - cx, ZonedDateTime{&args.thisv().toObject().as()}); - - // Step 3. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, zonedDateTime.calendar(), - { - CalendarMethod::Fields, - CalendarMethod::YearMonthFromFields, - }, - &calendar)) { - return false; - } - - // Steps 4-6. - Rooted temporalDateTime( - cx, - GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), zonedDateTime.instant(), - zonedDateTime.calendar())); - if (!temporalDateTime) { - return false; - } - - // Step 7. - Rooted fields( - cx, - PrepareCalendarFields(cx, calendar, temporalDateTime, - {CalendarField::MonthCode, CalendarField::Year})); - if (!fields) { - return false; - } - - // Steps 8-9. - auto result = CalendarYearMonthFromFields(cx, calendar, fields); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.ZonedDateTime.prototype.toPlainYearMonth ( ) - */ -static bool ZonedDateTime_toPlainYearMonth(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.ZonedDateTime.prototype.toPlainMonthDay ( ) - */ -static bool ZonedDateTime_toPlainMonthDay(JSContext* cx, const CallArgs& args) { - Rooted zonedDateTime( - cx, ZonedDateTime{&args.thisv().toObject().as()}); - - // Step 3. - Rooted calendar(cx); - if (!CreateCalendarMethodsRecord(cx, zonedDateTime.calendar(), - { - CalendarMethod::Fields, - CalendarMethod::MonthDayFromFields, - }, - &calendar)) { - return false; - } - - // Steps 4-6. - Rooted temporalDateTime( - cx, - GetPlainDateTimeFor(cx, zonedDateTime.timeZone(), zonedDateTime.instant(), - zonedDateTime.calendar())); - if (!temporalDateTime) { - return false; - } - - // Step 7. - Rooted fields( - cx, - PrepareCalendarFields(cx, calendar, temporalDateTime, - {CalendarField::Day, CalendarField::MonthCode})); - if (!fields) { - return false; - } - - // Steps 8-9. - auto result = CalendarMonthDayFromFields(cx, calendar, fields); - if (!result) { - return false; - } - - args.rval().setObject(*result); - return true; -} - -/** - * Temporal.ZonedDateTime.prototype.toPlainMonthDay ( ) - */ -static bool ZonedDateTime_toPlainMonthDay(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.ZonedDateTime.prototype.getISOFields ( ) - */ -static bool ZonedDateTime_getISOFields(JSContext* cx, const CallArgs& args) { - Rooted zonedDateTime( - cx, ZonedDateTime{&args.thisv().toObject().as()}); - - // Step 3. - Rooted fields(cx, IdValueVector(cx)); - - // Step 4. - const auto& instant = zonedDateTime.instant(); - - // Step 5. - auto calendar = zonedDateTime.calendar(); - - // Step 6. - auto timeZone = zonedDateTime.timeZone(); - - // Step 7. - int64_t offsetNanoseconds; - if (!GetOffsetNanosecondsFor(cx, timeZone, instant, &offsetNanoseconds)) { - return false; - } - - // Step 8. - auto temporalDateTime = GetPlainDateTimeFor(instant, offsetNanoseconds); - - // Step 9. - Rooted offset(cx, - FormatUTCOffsetNanoseconds(cx, offsetNanoseconds)); - if (!offset) { - return false; - } - - // Step 10. - Rooted cal(cx); - if (!ToTemporalCalendar(cx, calendar, &cal)) { - return false; - } - if (!fields.emplaceBack(NameToId(cx->names().calendar), cal)) { - return false; - } - - // Step 11. - if (!fields.emplaceBack(NameToId(cx->names().isoDay), - Int32Value(temporalDateTime.date.day))) { - return false; - } - - // Step 12. - if (!fields.emplaceBack(NameToId(cx->names().isoHour), - Int32Value(temporalDateTime.time.hour))) { - return false; - } - - // Step 13. - if (!fields.emplaceBack(NameToId(cx->names().isoMicrosecond), - Int32Value(temporalDateTime.time.microsecond))) { - return false; - } - - // Step 14. - if (!fields.emplaceBack(NameToId(cx->names().isoMillisecond), - Int32Value(temporalDateTime.time.millisecond))) { - return false; - } - - // Step 15. - if (!fields.emplaceBack(NameToId(cx->names().isoMinute), - Int32Value(temporalDateTime.time.minute))) { - return false; - } - - // Step 16. - if (!fields.emplaceBack(NameToId(cx->names().isoMonth), - Int32Value(temporalDateTime.date.month))) { - return false; - } - - // Step 17. - if (!fields.emplaceBack(NameToId(cx->names().isoNanosecond), - Int32Value(temporalDateTime.time.nanosecond))) { - return false; - } - - // Step 18. - if (!fields.emplaceBack(NameToId(cx->names().isoSecond), - Int32Value(temporalDateTime.time.second))) { - return false; - } - - // Step 19. - if (!fields.emplaceBack(NameToId(cx->names().isoYear), - Int32Value(temporalDateTime.date.year))) { - return false; - } - - // Step 20. - if (!fields.emplaceBack(NameToId(cx->names().offset), StringValue(offset))) { - return false; - } - - // Step 21. - if (!fields.emplaceBack(NameToId(cx->names().timeZone), timeZone.toValue())) { - return false; - } - - // Step 22. - auto* obj = NewPlainObjectWithUniqueNames(cx, fields); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.ZonedDateTime.prototype.getISOFields ( ) - */ -static bool ZonedDateTime_getISOFields(JSContext* cx, unsigned argc, - Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod( - cx, args); -} - -/** - * Temporal.ZonedDateTime.prototype.getCalendar ( ) - */ -static bool ZonedDateTime_getCalendar(JSContext* cx, const CallArgs& args) { - auto* zonedDateTime = &args.thisv().toObject().as(); - Rooted calendar(cx, zonedDateTime->calendar()); - - // Step 3. - auto* obj = ToTemporalCalendarObject(cx, calendar); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.ZonedDateTime.prototype.getCalendar ( ) - */ -static bool ZonedDateTime_getCalendar(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - -/** - * Temporal.ZonedDateTime.prototype.getTimeZone ( ) - */ -static bool ZonedDateTime_getTimeZone(JSContext* cx, const CallArgs& args) { - auto* zonedDateTime = &args.thisv().toObject().as(); - Rooted timeZone(cx, zonedDateTime->timeZone()); - - // Step 3. - auto* obj = ToTemporalTimeZoneObject(cx, timeZone); - if (!obj) { - return false; - } - - args.rval().setObject(*obj); - return true; -} - -/** - * Temporal.ZonedDateTime.prototype.getTimeZone ( ) - */ -static bool ZonedDateTime_getTimeZone(JSContext* cx, unsigned argc, Value* vp) { - // Steps 1-2. - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, - args); -} - const JSClass ZonedDateTimeObject::class_ = { "Temporal.ZonedDateTime", JSCLASS_HAS_RESERVED_SLOTS(ZonedDateTimeObject::SLOT_COUNT) | @@ -4149,7 +3091,6 @@ static const JSFunctionSpec ZonedDateTime_methods[] = { static const JSFunctionSpec ZonedDateTime_prototype_methods[] = { JS_FN("with", ZonedDateTime_with, 1, 0), JS_FN("withPlainTime", ZonedDateTime_withPlainTime, 0, 0), - JS_FN("withPlainDate", ZonedDateTime_withPlainDate, 1, 0), JS_FN("withTimeZone", ZonedDateTime_withTimeZone, 1, 0), JS_FN("withCalendar", ZonedDateTime_withCalendar, 1, 0), JS_FN("add", ZonedDateTime_add, 1, 0), @@ -4163,15 +3104,11 @@ static const JSFunctionSpec ZonedDateTime_prototype_methods[] = { JS_FN("toJSON", ZonedDateTime_toJSON, 0, 0), JS_FN("valueOf", ZonedDateTime_valueOf, 0, 0), JS_FN("startOfDay", ZonedDateTime_startOfDay, 0, 0), + JS_FN("getTimeZoneTransition", ZonedDateTime_getTimeZoneTransition, 1, 0), JS_FN("toInstant", ZonedDateTime_toInstant, 0, 0), JS_FN("toPlainDate", ZonedDateTime_toPlainDate, 0, 0), JS_FN("toPlainTime", ZonedDateTime_toPlainTime, 0, 0), JS_FN("toPlainDateTime", ZonedDateTime_toPlainDateTime, 0, 0), - JS_FN("toPlainYearMonth", ZonedDateTime_toPlainYearMonth, 0, 0), - JS_FN("toPlainMonthDay", ZonedDateTime_toPlainMonthDay, 0, 0), - JS_FN("getISOFields", ZonedDateTime_getISOFields, 0, 0), - JS_FN("getCalendar", ZonedDateTime_getCalendar, 0, 0), - JS_FN("getTimeZone", ZonedDateTime_getTimeZone, 0, 0), JS_FS_END, }; @@ -4190,9 +3127,7 @@ static const JSPropertySpec ZonedDateTime_prototype_properties[] = { JS_PSG("millisecond", ZonedDateTime_millisecond, 0), JS_PSG("microsecond", ZonedDateTime_microsecond, 0), JS_PSG("nanosecond", ZonedDateTime_nanosecond, 0), - JS_PSG("epochSeconds", ZonedDateTime_epochSeconds, 0), JS_PSG("epochMilliseconds", ZonedDateTime_epochMilliseconds, 0), - JS_PSG("epochMicroseconds", ZonedDateTime_epochMicroseconds, 0), JS_PSG("epochNanoseconds", ZonedDateTime_epochNanoseconds, 0), JS_PSG("dayOfWeek", ZonedDateTime_dayOfWeek, 0), JS_PSG("dayOfYear", ZonedDateTime_dayOfYear, 0), diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.h b/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.h index 7d75a332014..c5c29062441 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.h +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/ZonedDateTime.h @@ -40,16 +40,17 @@ class ZonedDateTimeObject : public NativeObject { static constexpr uint32_t CALENDAR_SLOT = 3; static constexpr uint32_t SLOT_COUNT = 4; - int64_t seconds() const { + /** + * Extract the epoch nanoseconds fields from this ZonedDateTime object. + */ + EpochNanoseconds epochNanoseconds() const { double seconds = getFixedSlot(SECONDS_SLOT).toNumber(); MOZ_ASSERT(-8'640'000'000'000 <= seconds && seconds <= 8'640'000'000'000); - return int64_t(seconds); - } - int32_t nanoseconds() const { int32_t nanoseconds = getFixedSlot(NANOSECONDS_SLOT).toInt32(); MOZ_ASSERT(0 <= nanoseconds && nanoseconds <= 999'999'999); - return nanoseconds; + + return {{int64_t(seconds), nanoseconds}}; } TimeZoneValue timeZone() const { @@ -63,33 +64,30 @@ class ZonedDateTimeObject : public NativeObject { private: static const ClassSpec classSpec_; }; -/** - * Extract the instant fields from the ZonedDateTime object. - */ -inline Instant ToInstant(const ZonedDateTimeObject* zonedDateTime) { - return {zonedDateTime->seconds(), zonedDateTime->nanoseconds()}; -} class MOZ_STACK_CLASS ZonedDateTime final { - Instant instant_; + EpochNanoseconds epochNanoseconds_; TimeZoneValue timeZone_; CalendarValue calendar_; public: ZonedDateTime() = default; - ZonedDateTime(const Instant& instant, const TimeZoneValue& timeZone, - const CalendarValue& calendar) - : instant_(instant), timeZone_(timeZone), calendar_(calendar) { - MOZ_ASSERT(IsValidEpochInstant(instant)); + ZonedDateTime(const EpochNanoseconds& epochNanoseconds, + const TimeZoneValue& timeZone, const CalendarValue& calendar) + : epochNanoseconds_(epochNanoseconds), + timeZone_(timeZone), + calendar_(calendar) { + MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); MOZ_ASSERT(timeZone); MOZ_ASSERT(calendar); } explicit ZonedDateTime(const ZonedDateTimeObject* obj) - : ZonedDateTime(ToInstant(obj), obj->timeZone(), obj->calendar()) {} + : ZonedDateTime(obj->epochNanoseconds(), obj->timeZone(), + obj->calendar()) {} - const auto& instant() const { return instant_; } + const auto& epochNanoseconds() const { return epochNanoseconds_; } const auto& timeZone() const { return timeZone_; } @@ -106,9 +104,9 @@ class MOZ_STACK_CLASS ZonedDateTime final { const auto* calendarDoNotUse() const { return &calendar_; } }; +struct DifferenceSettings; enum class TemporalDisambiguation; enum class TemporalOffset; -enum class TemporalOverflow; enum class TemporalUnit; /** @@ -116,122 +114,56 @@ enum class TemporalUnit; * newTarget ] ) */ ZonedDateTimeObject* CreateTemporalZonedDateTime( - JSContext* cx, const Instant& instant, JS::Handle timeZone, - JS::Handle calendar); + JSContext* cx, const EpochNanoseconds& epochNanoseconds, + JS::Handle timeZone, JS::Handle calendar); /** - * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ , - * overflow ] ) + * AddZonedDateTime ( epochNanoseconds, timeZone, calendar, duration, overflow ) */ -bool AddDaysToZonedDateTime(JSContext* cx, const Instant& instant, - const PlainDateTime& dateTime, - JS::Handle timeZone, - JS::Handle calendar, int64_t days, - TemporalOverflow overflow, Instant* result); +bool AddZonedDateTime(JSContext* cx, JS::Handle zonedDateTime, + const InternalDuration& duration, + EpochNanoseconds* result); /** - * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ , - * overflow ] ) + * DifferenceZonedDateTimeWithRounding ( ns1, ns2, timeZone, calendar, + * largestUnit, roundingIncrement, smallestUnit, roundingMode ) */ -bool AddDaysToZonedDateTime(JSContext* cx, const Instant& instant, - const PlainDateTime& dateTime, - JS::Handle timeZone, - JS::Handle calendar, int64_t days, - Instant* result); +bool DifferenceZonedDateTimeWithRounding( + JSContext* cx, JS::Handle zonedDateTime, + const EpochNanoseconds& ns2, const DifferenceSettings& settings, + InternalDuration* result); /** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) + * DifferenceZonedDateTimeWithTotal ( ns1, ns2, timeZone, calendar, unit ) */ -bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds, - JS::Handle timeZone, - JS::Handle calendar, - const NormalizedDuration& duration, Instant* result); - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds, - JS::Handle timeZone, - JS::Handle calendar, - const NormalizedDuration& duration, - const PlainDateTime& dateTime, Instant* result); - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds, - JS::Handle timeZone, - JS::Handle calendar, - const DateDuration& duration, Instant* result); - -/** - * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, - * weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] ) - */ -bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds, - JS::Handle timeZone, - JS::Handle calendar, - const DateDuration& duration, - const PlainDateTime& dateTime, Instant* result); - -/** - * DifferenceZonedDateTime ( ns1, ns2, timeZoneRec, calendarRec, largestUnit, - * options, precalculatedPlainDateTime ) - */ -bool DifferenceZonedDateTime(JSContext* cx, const Instant& ns1, - const Instant& ns2, - JS::Handle timeZone, - JS::Handle calendar, - TemporalUnit largestUnit, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedDuration* result); - -struct NormalizedTimeAndDays final { - int64_t days = 0; - int64_t time = 0; - int64_t dayLength = 0; -}; - -/** - * NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , - * precalculatedPlainDateTime ] ) - */ -bool NormalizedTimeDurationToDays(JSContext* cx, - const NormalizedTimeDuration& duration, - JS::Handle zonedRelativeTo, - JS::Handle timeZone, - NormalizedTimeAndDays* result); - -/** - * NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , - * precalculatedPlainDateTime ] ) - */ -bool NormalizedTimeDurationToDays( - JSContext* cx, const NormalizedTimeDuration& duration, - JS::Handle zonedRelativeTo, - JS::Handle timeZone, - const PlainDateTime& precalculatedPlainDateTime, - NormalizedTimeAndDays* result); +bool DifferenceZonedDateTimeWithTotal(JSContext* cx, + JS::Handle zonedDateTime, + const EpochNanoseconds& ns2, + TemporalUnit unit, double* result); enum class OffsetBehaviour { Option, Exact, Wall }; enum class MatchBehaviour { MatchExactly, MatchMinutes }; /** - * InterpretISODateTimeOffset ( year, month, day, hour, minute, second, - * millisecond, microsecond, nanosecond, offsetBehaviour, offsetNanoseconds, - * timeZoneRec, disambiguation, offsetOption, matchBehaviour ) + * InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, + * offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ) */ -bool InterpretISODateTimeOffset(JSContext* cx, const PlainDateTime& dateTime, - OffsetBehaviour offsetBehaviour, - int64_t offsetNanoseconds, - JS::Handle timeZone, - TemporalDisambiguation disambiguation, - TemporalOffset offsetOption, - MatchBehaviour matchBehaviour, Instant* result); +bool InterpretISODateTimeOffset( + JSContext* cx, const ISODateTime& dateTime, OffsetBehaviour offsetBehaviour, + int64_t offsetNanoseconds, JS::Handle timeZone, + TemporalDisambiguation disambiguation, TemporalOffset offsetOption, + MatchBehaviour matchBehaviour, EpochNanoseconds* result); + +/** + * InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, + * offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ) + */ +bool InterpretISODateTimeOffset( + JSContext* cx, const ISODate& isoDate, OffsetBehaviour offsetBehaviour, + int64_t offsetNanoseconds, JS::Handle timeZone, + TemporalDisambiguation disambiguation, TemporalOffset offsetOption, + MatchBehaviour matchBehaviour, EpochNanoseconds* result); } /* namespace js::temporal */ @@ -246,7 +178,9 @@ class WrappedPtrOperations { public: explicit operator bool() const { return bool(container()); } - const auto& instant() const { return container().instant(); } + const auto& epochNanoseconds() const { + return container().epochNanoseconds(); + } JS::Handle timeZone() const { return JS::Handle::fromMarkedLocation( diff --git a/src/third_party/mozjs/extract/js/src/builtin/temporal/moz.build b/src/third_party/mozjs/extract/js/src/builtin/temporal/moz.build index 3c09960783e..6885074f65c 100644 --- a/src/third_party/mozjs/extract/js/src/builtin/temporal/moz.build +++ b/src/third_party/mozjs/extract/js/src/builtin/temporal/moz.build @@ -12,24 +12,26 @@ LOCAL_INCLUDES += ["!../..", "../.."] include("../../js-config.mozbuild") include("../../js-cxxflags.mozbuild") -if CONFIG["JS_HAS_TEMPORAL_API"]: - UNIFIED_SOURCES += [ - "Calendar.cpp", - "Duration.cpp", - "Instant.cpp", - "Int128.cpp", - "Int96.cpp", - "PlainDate.cpp", - "PlainDateTime.cpp", - "PlainMonthDay.cpp", - "PlainTime.cpp", - "PlainYearMonth.cpp", - "Temporal.cpp", - "TemporalFields.cpp", - "TemporalNow.cpp", - "TemporalParser.cpp", - "TimeZone.cpp", - "ToString.cpp", - "Wrapped.cpp", - "ZonedDateTime.cpp", - ] +LOCAL_INCLUDES += [ + "/intl/icu_capi/bindings/c", +] + +UNIFIED_SOURCES += [ + "Calendar.cpp", + "CalendarFields.cpp", + "Duration.cpp", + "Instant.cpp", + "Int128.cpp", + "Int96.cpp", + "PlainDate.cpp", + "PlainDateTime.cpp", + "PlainMonthDay.cpp", + "PlainTime.cpp", + "PlainYearMonth.cpp", + "Temporal.cpp", + "TemporalNow.cpp", + "TemporalParser.cpp", + "TimeZone.cpp", + "ToString.cpp", + "ZonedDateTime.cpp", +] diff --git a/src/third_party/mozjs/extract/js/src/debugger/DebugAPI.h b/src/third_party/mozjs/extract/js/src/debugger/DebugAPI.h index 67f3b62883f..1180ee3302a 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/DebugAPI.h +++ b/src/third_party/mozjs/extract/js/src/debugger/DebugAPI.h @@ -225,6 +225,12 @@ class DebugAPI { [[nodiscard]] static inline bool onResumeFrame(JSContext* cx, AbstractFramePtr frame); + // Called when Wasm frame is suspended by JS PI. + static void onSuspendWasmFrame(JSContext* cx, wasm::DebugFrame* debugFrame); + + // Called when Wasm frame is resumed by JS PI. + static void onResumeWasmFrame(JSContext* cx, const FrameIter& iter); + static inline NativeResumeMode onNativeCall(JSContext* cx, const CallArgs& args, CallReason reason); diff --git a/src/third_party/mozjs/extract/js/src/debugger/DebugScript.cpp b/src/third_party/mozjs/extract/js/src/debugger/DebugScript.cpp index 610784c228a..1db8d9deff1 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/DebugScript.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/DebugScript.cpp @@ -44,7 +44,9 @@ namespace js { const JSClass DebugScriptObject::class_ = { "DebugScriptObject", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_BACKGROUND_FINALIZE, - &classOps_, JS_NULL_CLASS_SPEC}; + &classOps_, + JS_NULL_CLASS_SPEC, +}; const JSClassOps DebugScriptObject::classOps_ = { nullptr, // addProperty diff --git a/src/third_party/mozjs/extract/js/src/debugger/DebugScript.h b/src/third_party/mozjs/extract/js/src/debugger/DebugScript.h index 176ea3b80cc..bf08141470a 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/DebugScript.h +++ b/src/third_party/mozjs/extract/js/src/debugger/DebugScript.h @@ -150,8 +150,7 @@ class DebugScriptObject : public NativeObject { }; // A weak map from JSScripts to DebugScriptObjects. -class DebugScriptMap - : public WeakMap, HeapPtr> { +class DebugScriptMap : public WeakMap { public: explicit DebugScriptMap(JSContext* cx) : WeakMap(cx) {} }; diff --git a/src/third_party/mozjs/extract/js/src/debugger/Debugger.cpp b/src/third_party/mozjs/extract/js/src/debugger/Debugger.cpp index 44bd1a8eaa5..2ff6743d73f 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Debugger.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/Debugger.cpp @@ -12,8 +12,9 @@ #include "mozilla/HashTable.h" // for HashSet<>::Range, HashMapEntry #include "mozilla/Maybe.h" // for Maybe, Nothing, Some #include "mozilla/ScopeExit.h" // for MakeScopeExit, ScopeExit +#include "mozilla/Sprintf.h" // for SprintfLiteral #include "mozilla/ThreadLocal.h" // for ThreadLocal -#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration +#include "mozilla/TimeStamp.h" // for TimeStamp #include "mozilla/UniquePtr.h" // for UniquePtr #include "mozilla/Variant.h" // for AsVariant, AsVariantTemporary #include "mozilla/Vector.h" // for Vector, Vector<>::ConstRange @@ -29,11 +30,14 @@ #include "jsapi.h" // for CallArgs, CallArgsFromVp #include "jstypes.h" // for JS_PUBLIC_API -#include "builtin/Array.h" // for NewDenseFullyAllocatedArray -#include "debugger/DebugAPI.h" // for ResumeMode, DebugAPI -#include "debugger/DebuggerMemory.h" // for DebuggerMemory -#include "debugger/DebugScript.h" // for DebugScript -#include "debugger/Environment.h" // for DebuggerEnvironment +#include "builtin/Array.h" // for NewDenseFullyAllocatedArray +#include "debugger/DebugAPI.h" // for ResumeMode, DebugAPI +#include "debugger/DebuggerMemory.h" // for DebuggerMemory +#include "debugger/DebugScript.h" // for DebugScript +#include "debugger/Environment.h" // for DebuggerEnvironment +#ifdef MOZ_EXECUTION_TRACING +# include "debugger/ExecutionTracer.h" // for ExecutionTracer::onEnterFrame, ExecutionTracer::onLeaveFrame +#endif #include "debugger/Frame.h" // for DebuggerFrame #include "debugger/NoExecute.h" // for EnterDebuggeeNoExecute #include "debugger/Object.h" // for DebuggerObject @@ -71,7 +75,7 @@ #include "js/Promise.h" // for AutoDebuggerJobQueueInterruption #include "js/PropertyAndElement.h" // for JS_GetProperty #include "js/Proxy.h" // for PropertyDescriptor -#include "js/SourceText.h" // for SourceOwnership, SourceText +#include "js/SourceText.h" // for SourceText #include "js/StableStringChars.h" // for AutoStableStringChars #include "js/UbiNode.h" // for Node, RootList, Edge #include "js/UbiNodeBreadthFirst.h" // for BreadthFirst @@ -151,9 +155,6 @@ using namespace js; using JS::AutoStableStringChars; using JS::CompileOptions; -using JS::SourceOwnership; -using JS::SourceText; -using JS::dbg::AutoEntryMonitor; using JS::dbg::Builder; using mozilla::AsVariant; using mozilla::DebugOnly; @@ -161,7 +162,6 @@ using mozilla::MakeScopeExit; using mozilla::Maybe; using mozilla::Nothing; using mozilla::Some; -using mozilla::TimeDuration; using mozilla::TimeStamp; /*** Utils ******************************************************************/ @@ -301,7 +301,7 @@ static void PropagateForcedReturn(JSContext* cx, AbstractFramePtr frame, return false; case ResumeMode::Terminate: - cx->clearPendingException(); + cx->reportUncatchableException(); return false; case ResumeMode::Return: @@ -903,6 +903,11 @@ bool Debugger::hasAnyLiveHooks() const { /* static */ bool DebugAPI::slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame) { +#ifdef MOZ_EXECUTION_TRACING + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer().onEnterFrame(cx, frame); + } +#endif return Debugger::dispatchResumptionHook( cx, frame, [frame](Debugger* dbg) -> bool { @@ -914,6 +919,11 @@ bool DebugAPI::slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame) { /* static */ bool DebugAPI::slowPathOnResumeFrame(JSContext* cx, AbstractFramePtr frame) { +#ifdef MOZ_EXECUTION_TRACING + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer().onEnterFrame(cx, frame); + } +#endif // Don't count on this method to be called every time a generator is // resumed! This is called only if the frame's debuggee bit is set, // i.e. the script has breakpoints or the frame is stepping. @@ -1039,7 +1049,7 @@ NativeResumeMode DebugAPI::slowPathOnNativeCall(JSContext* cx, return NativeResumeMode::Abort; case ResumeMode::Terminate: - cx->clearPendingException(); + cx->reportUncatchableException(); return NativeResumeMode::Abort; case ResumeMode::Return: @@ -1117,6 +1127,11 @@ class MOZ_RAII AutoSetGeneratorRunning { /* static */ bool DebugAPI::slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame, const jsbytecode* pc, bool frameOk) { +#ifdef MOZ_EXECUTION_TRACING + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer().onLeaveFrame(cx, frame); + } +#endif MOZ_ASSERT_IF(!frame.isWasmDebugFrame(), pc); mozilla::DebugOnly> debuggeeGlobal = cx->global(); @@ -2529,6 +2544,36 @@ void DebugAPI::onNewScript(JSContext* cx, HandleScript script) { }); } +/* static */ +void DebugAPI::onSuspendWasmFrame(JSContext* cx, wasm::DebugFrame* debugFrame) { + AbstractFramePtr frame = AbstractFramePtr(debugFrame); + JS::AutoAssertNoGC nogc; + for (Realm::DebuggerVectorEntry& entry : frame.global()->getDebuggers(nogc)) { + Debugger* dbg = entry.dbg; + if (Debugger::FrameMap::Ptr p = dbg->frames.lookup(frame)) { + DebuggerFrame* frameObj = p->value(); + frameObj->suspendWasmFrame(cx->gcContext()); + } + } +} + +/* static */ +void DebugAPI::onResumeWasmFrame(JSContext* cx, const FrameIter& iter) { + AbstractFramePtr frame = iter.abstractFramePtr(); + MOZ_RELEASE_ASSERT(frame.isWasmDebugFrame()); + JS::AutoAssertNoGC nogc; + for (Realm::DebuggerVectorEntry& entry : frame.global()->getDebuggers(nogc)) { + Debugger* dbg = entry.dbg; + if (Debugger::FrameMap::Ptr p = dbg->frames.lookup(frame)) { + DebuggerFrame* frameObj = p->value(); + AutoEnterOOMUnsafeRegion oomUnsafe; + if (!frameObj->resume(iter)) { + oomUnsafe.crash("DebugAPI::onResumeWasmFrame"); + } + } + } +} + void DebugAPI::slowPathOnNewWasmInstance( JSContext* cx, Handle wasmInstance) { Debugger::dispatchQuietHook( @@ -3235,6 +3280,8 @@ static bool UpdateExecutionObservabilityOfScriptsInZone( AutoSuppressProfilerSampling suppressProfilerSampling(cx); + CancelOffThreadBaselineCompile(zone); + JS::GCContext* gcx = cx->gcContext(); Vector scripts(cx); @@ -3881,7 +3928,7 @@ void DebugAPI::traceFramesWithLiveHooks(JSTracer* tracer) { for (Debugger::FrameMap::Range r = dbg->frames.all(); !r.empty(); r.popFront()) { HeapPtr& frameobj = r.front().value(); - MOZ_ASSERT(frameobj->isOnStack()); + MOZ_ASSERT(frameobj->isOnStackOrSuspendedWasmStack()); if (frameobj->hasAnyHooks()) { TraceEdge(tracer, &frameobj, "Debugger.Frame with live hooks"); } @@ -4008,7 +4055,7 @@ void Debugger::trace(JSTracer* trc) { for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) { HeapPtr& frameobj = r.front().value(); TraceEdge(trc, &frameobj, "live Debugger.Frame"); - MOZ_ASSERT(frameobj->isOnStack()); + MOZ_ASSERT(frameobj->isOnStackOrSuspendedWasmStack()); } allocationsLog.trace(trc); @@ -4116,7 +4163,7 @@ bool DebugAPI::findSweepGroupEdges(JSRuntime* rt) { template bool DebuggerWeakMap::findSweepGroupEdges() { + InvisibleKeysOk>::findSweepGroupEdges(Zone* atomsZone) { Zone* debuggerZone = zone(); MOZ_ASSERT(debuggerZone->isGCMarking()); for (Enum e(*this); !e.empty(); e.popFront()) { @@ -4130,7 +4177,7 @@ bool DebuggerWeakMaprealm()->isTracingExecution()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DEBUG_EXCLUSIVE_EXECUTION_TRACE_COVERAGE); + return false; + } + dbg->collectCoverageInfo = ToBoolean(args[0]); IsObserving observing = dbg->collectCoverageInfo ? Observing : NotObserving; @@ -5133,7 +5189,8 @@ void Debugger::removeDebuggeeGlobal(JS::GCContext* gcx, GlobalObject* global, Debugger::removeAllocationsTracking(*global); } - if (!global->realm()->hasDebuggers()) { + if (!global->realm()->hasDebuggers() && + !global->realm()->isTracingExecution()) { global->realm()->unsetIsDebuggee(); } else { global->realm()->updateDebuggerObservesAllExecution(); @@ -5314,18 +5371,15 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase { } else if (lineProperty.isNumber()) { if (displayURL.isUndefined() && url.isUndefined() && !hasSource) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_QUERY_LINE_WITHOUT_URL); + JSMSG_QUERY_LINE_WITHOUT_URL, + "'line' property"); return false; } - double doubleLine = lineProperty.toNumber(); - uint32_t uintLine = (uint32_t)doubleLine; - if (doubleLine <= 0 || uintLine != doubleLine) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_DEBUG_BAD_LINE); + if (!parsePositiveInteger(lineProperty, line, JSMSG_DEBUG_BAD_LINE)) { return false; } hasLine = true; - line = uintLine; + lineEnd = line; } else { JS_ReportErrorNumberASCII( cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, @@ -5333,6 +5387,63 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase { return false; } + // Check for a 'start' property. + RootedValue startProperty(cx); + if (!GetProperty(cx, query, query, cx->names().start, &startProperty)) { + return false; + } + if (startProperty.isObject()) { + Rooted startObject(cx, &startProperty.toObject()); + if (!parseLineColumnObject(startObject, "start", line, columnStart)) { + return false; + } + hasLine = true; + } else if (!startProperty.isUndefined()) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, + "query object's 'start' property", "neither undefined nor an object"); + return false; + } + + // Check for a 'end' property. + RootedValue endProperty(cx); + if (!GetProperty(cx, query, query, cx->names().end, &endProperty)) { + return false; + } + if (endProperty.isObject()) { + Rooted endObject(cx, &endProperty.toObject()); + if (!parseLineColumnObject(endObject, "end", lineEnd, columnEnd)) { + return false; + } + } else if (!endProperty.isUndefined()) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, + "query object's 'end' property", "neither undefined nor an object"); + return false; + } + + if (startProperty.isUndefined() ^ endProperty.isUndefined()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_QUERY_USE_START_AND_END_TOGETHER); + return false; + } + + if (!startProperty.isUndefined()) { + // endProperty is also not undefined here + if (displayURL.isUndefined() && url.isUndefined() && !hasSource) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_QUERY_LINE_WITHOUT_URL, + "'start' and 'end' properties"); + return false; + } + } + + if (hasLine && lineEnd < line) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_QUERY_START_LINE_IS_AFTER_END); + return false; + } + // Check for an 'innermost' property. PropertyName* innermostName = cx->names().innermost; RootedValue innermostProperty(cx); @@ -5531,6 +5642,8 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase { } private: + static const uint32_t LINE_CONSTRAINT_NOT_PROVIDED = 0; + /* If this is a string, matching scripts have urls equal to it. */ RootedValue url; @@ -5549,22 +5662,32 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase { bool hasSource = false; Rooted source; - /* True if the query contained a 'line' property. */ + /* True if the query contained a 'line' or 'start' property. */ bool hasLine = false; - /* The line matching scripts must cover. */ - uint32_t line = 0; + /* The start line of the target range, inclusive. A script's lines must + * overlap the target line range or it will be filtered out by the query. */ + uint32_t line = LINE_CONSTRAINT_NOT_PROVIDED; + + /* The end line of the target range, inclusive. A script's lines must overlap + * the target line range or it will be filtered out by the query. */ + uint32_t lineEnd = LINE_CONSTRAINT_NOT_PROVIDED; + + Maybe columnStart; + + Maybe columnEnd; // As a performance optimization (and to avoid delazifying as many scripts), - // we would like to know the source offset of the target line. + // we would like to know the source offset of the target range start line. // // Since we do not have a simple way to compute this precisely, we instead // track a lower-bound of the offset value. As we collect SourceExtent // examples with (line,column) <-> sourceStart mappings, we can improve the - // bound. The target line is within the range [sourceOffsetLowerBound, Inf). + // bound. The target range start line is within the range + // [sourceOffsetLowerBound, Inf). // // NOTE: Using a SourceExtent for updating the bound happens independently of - // if the script matches the target line or not in the in the end. + // if the script matches the target range start line or not in the end. mutable uint32_t sourceOffsetLowerBound = 0; /* True if the query has an 'innermost' property whose value is true. */ @@ -5610,30 +5733,112 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase { return true; } + template + bool parseLineColumnObject( + Handle obj, const char (&propName)[N], uint32_t& lineOut, + Maybe& columnOut) { + RootedValue lineProp(cx); + if (!GetProperty(cx, obj, obj, cx->names().line, &lineProp)) { + return false; + } + if (!lineProp.isNumber()) { + static const char propMessageFormat[] = + "query object's '%s.line' property"; + char propMessage[N - 1 /* propName's terminating null */ + + sizeof(propMessageFormat) - 2 /* '%s' is replaced */]; + DebugOnly checkLen = + SprintfLiteral(propMessage, propMessageFormat, propName); + MOZ_ASSERT(checkLen == sizeof(propMessage) - 1 /* terminating null */); + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_UNEXPECTED_TYPE, propMessage, + "not a number"); + return false; + } + if (!parsePositiveInteger(lineProp, lineOut, JSMSG_DEBUG_BAD_LINE)) { + return false; + } + + RootedValue columnProp(cx); + if (!GetProperty(cx, obj, obj, cx->names().column, &columnProp)) { + return false; + } + if (!columnProp.isUndefined()) { + if (!columnProp.isNumber()) { + static const char propMessageFormat[] = + "query object's '%s.column' property"; + char propMessage[N - 1 /* propName's terminating null */ + + sizeof(propMessageFormat) - + 2 /* '%s' is replaced */]; + DebugOnly checkLen = + SprintfLiteral(propMessage, propMessageFormat, propName); + MOZ_ASSERT(checkLen == sizeof(propMessage) - 1 /* terminating null */); + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_UNEXPECTED_TYPE, propMessage, + "not a number"); + return false; + } + uint32_t uintColumn = 0; + if (!parsePositiveInteger(columnProp, uintColumn, + JSMSG_BAD_COLUMN_NUMBER)) { + return false; + } + if (uintColumn > JS::LimitedColumnNumberOneOrigin::Limit) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_BAD_COLUMN_NUMBER); + return false; + } + columnOut.emplace(JS::LimitedColumnNumberOneOrigin(uintColumn)); + } + return true; + } + + bool parsePositiveInteger(Handle numberProp, uint32_t& result, + JSErrNum errorNumber) { + double doubleVal = numberProp.toNumber(); + uint32_t uintVal = (uint32_t)doubleVal; + if (doubleVal <= 0 || uintVal != doubleVal) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, errorNumber); + return false; + } + result = uintVal; + return true; + } + void updateSourceOffsetLowerBound(const SourceExtent& extent) { - // We trying to find the offset of (target-line, 0) so just ignore any - // extents on target line to keep things simple. - MOZ_ASSERT(extent.lineno <= line); - if (extent.lineno == line) { + // We trying to find the offset of (target-range-start-line, 0), so ignore + // any scripts within the target range. + MOZ_ASSERT(line != LINE_CONSTRAINT_NOT_PROVIDED && + lineEnd != LINE_CONSTRAINT_NOT_PROVIDED); + MOZ_ASSERT(extent.lineno <= lineEnd); + if (extent.lineno >= line) { return; } // The extent.sourceStart position is now definitely *before* the target - // line, so update sourceOffsetLowerBound if extent.sourceStart is a tighter - // bound. + // range start line, so update sourceOffsetLowerBound if extent.sourceStart + // is a tighter bound. if (extent.sourceStart > sourceOffsetLowerBound) { sourceOffsetLowerBound = extent.sourceStart; } } - // A partial match is a script that starts before the target line, but may or - // may not end before it. If we can prove the script definitely ends before - // the target line, we may return false here. + // A partial match is a script that starts before the target range ends, but + // may or may not end before the target range starts. We can also return false + // if we can prove the script ends before the target range starts. bool scriptIsPartialLineMatch(BaseScript* script) { const SourceExtent& extent = script->extent(); - // Check that start of script is before or on target line. - if (extent.lineno > line) { + // We only know for sure that the script is outside the target line range + // if the start of script is after the target end line, because we don't + // know how many lines the script has yet. + MOZ_ASSERT(line != LINE_CONSTRAINT_NOT_PROVIDED && + lineEnd != LINE_CONSTRAINT_NOT_PROVIDED); + MOZ_ASSERT(line <= lineEnd); + if (extent.lineno > lineEnd) { + return false; + } + if (columnEnd.isSome() && script->lineno() == lineEnd && + script->column() > columnEnd.value()) { return false; } @@ -5643,15 +5848,21 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase { updateSourceOffsetLowerBound(script->extent()); // As an optional performance optimization, we rule out any script that ends - // before the lower-bound on where target line exists. + // before the lower-bound on where target range start line exists. return extent.sourceEnd > sourceOffsetLowerBound; } - // True if any part of script source is on the target line. + // True if any part of script source overlaps the target range. bool scriptIsLineMatch(JSScript* script) { MOZ_ASSERT(scriptIsPartialLineMatch(script)); - uint32_t lineCount = GetScriptLineExtent(script); + JS::LimitedColumnNumberOneOrigin scriptEndColumn; + uint32_t lineCount = GetScriptLineExtent(script, &scriptEndColumn); + if (columnStart.isSome() && script->lineno() + lineCount - 1 == line) { + if (scriptEndColumn <= columnStart.value()) { + return false; + } + } return (script->lineno() + lineCount > line); } @@ -5952,7 +6163,12 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery { public: /* Construct an ObjectQuery to use matching scripts for |dbg|. */ ObjectQuery(JSContext* cx, Debugger* dbg) - : objects(cx), cx(cx), dbg(dbg), className(cx) {} + : objects(cx), + cx(cx), + dbg(dbg), + queryType(QueryType::None), + jsClassName(cx), + unwrappedCtorOrProto(cx) {} /* The vector that we are accumulating results in. */ RootedObjectVector objects; @@ -5970,14 +6186,12 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery { if (!GetProperty(cx, query, query, cx->names().class_, &cls)) { return false; } - if (!cls.isUndefined()) { - if (!cls.isString()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_UNEXPECTED_TYPE, - "query object's 'class' property", - "neither undefined nor a string"); - return false; - } + + if (cls.isUndefined()) { + return true; + } + + if (cls.isString()) { JSLinearString* str = cls.toString()->ensureLinear(cx); if (!str) { return false; @@ -5985,17 +6199,55 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery { if (!StringIsAscii(str)) { JS_ReportErrorNumberASCII( cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, - "query object's 'class' property", + "query object's 'class' property string", "not a string containing only ASCII characters"); return false; } - className = cls; + jsClassName = cls; + queryType = QueryType::JSClassName; + return true; } - return true; + + if (cls.isObject()) { + JS::Rooted obj(cx, &cls.toObject()); + obj = UncheckedUnwrap(obj); + if (JS_IsDeadWrapper(obj)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DEAD_OBJECT); + return false; + } + if (!obj->is()) { + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, + "query object's 'class' property object", "not Debugger.Object"); + return false; + } + + unwrappedCtorOrProto = obj->as().referent(); + unwrappedCtorOrProto = UncheckedUnwrap(unwrappedCtorOrProto); + if (JS_IsDeadWrapper(unwrappedCtorOrProto)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DEAD_OBJECT); + return false; + } + queryType = QueryType::CtorOrProto; + return true; + } + + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, + "query object's 'class' property", + "none of JSClass name string, constructor/prototype debuggee object, " + "or undefined"); + return false; } /* Set up this ObjectQuery appropriately for a missing query argument. */ - void omittedQuery() { className.setUndefined(); } + void omittedQuery() { + jsClassName.setUndefined(); + unwrappedCtorOrProto = nullptr; + queryType = QueryType::None; + } /* * Traverse the heap to find all relevant objects and add them to the @@ -6028,8 +6280,12 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery { Traversal traversal(cx, *this, nogc); traversal.wantNames = false; - return traversal.addStart(JS::ubi::Node(&rootList)) && - traversal.traverse(); + if (!traversal.addStart(JS::ubi::Node(&rootList)) || + !traversal.traverse()) { + ReportOutOfMemory(cx); + return false; + } + return true; } } @@ -6083,16 +6339,72 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery { JSObject* obj = referent.as(); - if (!className.isUndefined()) { - const char* objClassName = obj->getClass()->name; - if (strcmp(objClassName, classNameCString.get()) != 0) { - return true; + switch (queryType) { + case QueryType::None: + break; + case QueryType::JSClassName: { + const char* objJSClassName = obj->getClass()->name; + if (strcmp(objJSClassName, jsClassNameCString.get()) != 0) { + return true; + } + break; } + case QueryType::CtorOrProto: + if (!hasConstructorOrPrototype(obj, unwrappedCtorOrProto, cx)) { + return true; + } + break; } return objects.append(obj); } + // Returns true if `obj` is confirmed to have `ctorOrProto` as its + // constructor or prototype in the prototype chain. + // + // If it requires side-effect-ful operation for accessing the constructor or + // prototype, this can return false even if `obj instanceof ctorOrProto` is + // actually `true`. + static bool hasConstructorOrPrototype(JSObject* obj, JSObject* ctorOrProto, + JSContext* cx) { + obj = UncheckedUnwrap(obj); + + while (true) { + if (!obj->hasStaticPrototype()) { + // Dynamic prototype cannot be matched without side-effect. + break; + } + + JSObject* proto = obj->staticPrototype(); + if (!proto) { + break; + } + proto = UncheckedUnwrap(proto); + if (proto == ctorOrProto) { + return true; + } + + JS::Value ctorVal; + bool result; + { + AutoRealm ar(cx, proto); + result = GetPropertyPure(cx, proto, NameToId(cx->names().constructor), + &ctorVal); + } + if (result && ctorVal.isObject()) { + JSObject* ctor = &ctorVal.toObject(); + ctor = UncheckedUnwrap(ctor); + if (ctor == ctorOrProto) { + return true; + } + } + + obj = proto; + } + + return false; + } + private: /* The context in which we should do our work. */ JSContext* cx; @@ -6100,23 +6412,35 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery { /* The debugger for which we conduct queries. */ Debugger* dbg; - /* - * If this is non-null, matching objects will have a class whose name is - * this property. - */ - RootedValue className; + enum class QueryType { + /* No filtering. */ + None, - /* The className member, as a C string. */ - UniqueChars classNameCString; + /* Match objects with given JSClass name. */ + JSClassName, + + /* Match objects with given object as constructor or prototype. */ + CtorOrProto, + }; + QueryType queryType; + + /* Matching objects will have a JSClass whose name is this property. */ + RootedValue jsClassName; + + /* The jsClassName member, as a C string. */ + UniqueChars jsClassNameCString; + + /* Matching objects will have given object as constructor or prototype. */ + JS::Rooted unwrappedCtorOrProto; /* * Given that either omittedQuery or parseQuery has been called, prepare the * query for matching objects. */ bool prepareQuery() { - if (className.isString()) { - classNameCString = JS_EncodeStringToASCII(cx, className.toString()); - if (!classNameCString) { + if (jsClassName.isString()) { + jsClassNameCString = JS_EncodeStringToASCII(cx, jsClassName.toString()); + if (!jsClassNameCString) { return false; } } @@ -6316,8 +6640,7 @@ bool Debugger::isCompilableUnit(JSContext* cx, unsigned argc, Value* vp) { } frontend::Parser parser( - &fc, options, chars.twoByteChars(), length, - /* foldConstants = */ true, compilationState, + &fc, options, chars.twoByteChars(), length, compilationState, /* syntaxParser = */ nullptr); if (!parser.checkOptions() || parser.parse().isErr()) { // We ran into an error. If it was because we ran out of memory we report @@ -6566,7 +6889,8 @@ const JSPropertySpec Debugger::properties[] = { setInspectNativeCallArguments), JS_DEBUG_PSG("memory", getMemory), JS_STRING_SYM_PS(toStringTag, "Debugger", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec Debugger::methods[] = { JS_DEBUG_FN("addDebuggee", addDebuggee, 1), @@ -6592,10 +6916,13 @@ const JSFunctionSpec Debugger::methods[] = { enableUnlimitedStacksCapturing, 1), JS_DEBUG_FN("disableUnlimitedStacksCapturing", disableUnlimitedStacksCapturing, 1), - JS_FS_END}; + JS_FS_END, +}; const JSFunctionSpec Debugger::static_methods[]{ - JS_FN("isCompilableUnit", Debugger::isCompilableUnit, 1, 0), JS_FS_END}; + JS_FN("isCompilableUnit", Debugger::isCompilableUnit, 1, 0), + JS_FS_END, +}; DebuggerScript* Debugger::newDebuggerScript( JSContext* cx, Handle referent) { @@ -6889,7 +7216,9 @@ void DebuggerDebuggeeLink::clearLinkSlot() { } const JSClass DebuggerDebuggeeLink::class_ = { - "DebuggerDebuggeeLink", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS)}; + "DebuggerDebuggeeLink", + JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), +}; /* static */ bool DebugAPI::handleBaselineOsr(JSContext* cx, InterpreterFrame* from, @@ -6991,15 +7320,6 @@ Builder::Object Builder::newObject(JSContext* cx) { return Object(cx, *this, obj); } -/*** JS::dbg::AutoEntryMonitor **********************************************/ - -AutoEntryMonitor::AutoEntryMonitor(JSContext* cx) - : cx_(cx), savedMonitor_(cx->entryMonitor) { - cx->entryMonitor = this; -} - -AutoEntryMonitor::~AutoEntryMonitor() { cx_->entryMonitor = savedMonitor_; } - /*** Glue *******************************************************************/ extern JS_PUBLIC_API bool JS_DefineDebuggerObject(JSContext* cx, diff --git a/src/third_party/mozjs/extract/js/src/debugger/Debugger.h b/src/third_party/mozjs/extract/js/src/debugger/Debugger.h index 537e47b913d..f162d3a6d59 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Debugger.h +++ b/src/third_party/mozjs/extract/js/src/debugger/Debugger.h @@ -285,9 +285,9 @@ class Completion { Variant variant; }; -typedef HashSet, - StableCellHasher>, ZoneAllocPolicy> - WeakGlobalObjectSet; +using WeakGlobalObjectSet = + HashSet, + StableCellHasher>, ZoneAllocPolicy>; #ifdef DEBUG extern void CheckDebuggeeThing(BaseScript* script, bool invisibleOk); @@ -336,15 +336,15 @@ extern void CheckDebuggeeThing(JSObject* obj, bool invisibleOk); * beacomes a debuggee again later, new Frame objects are created.) */ template -class DebuggerWeakMap : private WeakMap, HeapPtr> { +class DebuggerWeakMap : private WeakMap { private: - using Key = HeapPtr; - using Value = HeapPtr; + using Key = Referent*; + using Value = Wrapper*; JS::Compartment* compartment; public: - typedef WeakMap Base; + using Base = WeakMap; using ReferentType = Referent; using WrapperType = Wrapper; @@ -399,7 +399,7 @@ class DebuggerWeakMap : private WeakMap, HeapPtr> { } } - bool findSweepGroupEdges() override; + bool findSweepGroupEdges(JS::Zone* atomsZone) override; private: #ifdef JS_GC_ZEAL @@ -428,7 +428,7 @@ class MOZ_RAII EvalOptions { EnvKind kind_; public: - explicit EvalOptions(EnvKind kind) : kind_(kind){}; + explicit EvalOptions(EnvKind kind) : kind_(kind) {}; ~EvalOptions() = default; const char* filename() const { return filename_.get(); } unsigned lineno() const { return lineno_; } @@ -466,8 +466,8 @@ using Env = JSObject; // does point to something okay. Instead, we immediately build an instance of // this type from the Cell* and use that instead, so we can benefit from // Variant's static checks. -typedef mozilla::Variant - DebuggerScriptReferent; +using DebuggerScriptReferent = + mozilla::Variant; // The referent of a Debugger.Source. // @@ -479,8 +479,8 @@ typedef mozilla::Variant // The DebuggerSource object actually simply stores a Cell* in its private // pointer. See the comments for DebuggerScriptReferent for the rationale for // this type. -typedef mozilla::Variant - DebuggerSourceReferent; +using DebuggerSourceReferent = + mozilla::Variant; template class MOZ_RAII DebuggerList { @@ -744,14 +744,17 @@ class Debugger : private mozilla::LinkedListElement { * soon as they leave the stack (see slowPathOnLeaveFrame) and in * removeDebuggee. * + * Wasm JS PI allows suspending/resuming a portion of the stack, only + * frame pointers and activations are changed. The stack frames are still + * live, and shall be present in the frames map if DebuggerFrame is created. + * * We don't trace the keys of this map (the frames are on the stack and * thus necessarily live), but we do trace the values. It's like a WeakMap * that way, but since stack frames are not gc-things, the implementation * has to be different. */ - typedef HashMap, - DefaultHasher, ZoneAllocPolicy> - FrameMap; + using FrameMap = HashMap, + DefaultHasher, ZoneAllocPolicy>; FrameMap frames; /* @@ -778,8 +781,8 @@ class Debugger : private mozilla::LinkedListElement { * An entry in this table exists if and only if the Debugger.Frame's * GENERATOR_INFO_SLOT is set. */ - typedef DebuggerWeakMap - GeneratorWeakMap; + using GeneratorWeakMap = + DebuggerWeakMap; GeneratorWeakMap generatorFrames; // An ephemeral map from BaseScript* to Debugger.Script instances. @@ -790,28 +793,28 @@ class Debugger : private mozilla::LinkedListElement { // The map from debuggee source script objects to their Debugger.Source // instances. - typedef DebuggerWeakMap - SourceWeakMap; + using SourceWeakMap = + DebuggerWeakMap; SourceWeakMap sources; // The map from debuggee objects to their Debugger.Object instances. - typedef DebuggerWeakMap ObjectWeakMap; + using ObjectWeakMap = DebuggerWeakMap; ObjectWeakMap objects; // The map from debuggee Envs to Debugger.Environment instances. - typedef DebuggerWeakMap EnvironmentWeakMap; + using EnvironmentWeakMap = DebuggerWeakMap; EnvironmentWeakMap environments; // The map from WasmInstanceObjects to synthesized Debugger.Script // instances. - typedef DebuggerWeakMap - WasmInstanceScriptWeakMap; + using WasmInstanceScriptWeakMap = + DebuggerWeakMap; WasmInstanceScriptWeakMap wasmInstanceScripts; // The map from WasmInstanceObjects to synthesized Debugger.Source // instances. - typedef DebuggerWeakMap - WasmInstanceSourceWeakMap; + using WasmInstanceSourceWeakMap = + DebuggerWeakMap; WasmInstanceSourceWeakMap wasmInstanceSources; class QueryBase; @@ -922,6 +925,7 @@ class Debugger : private mozilla::LinkedListElement { static const JSPropertySpec properties[]; static const JSFunctionSpec methods[]; + static const JSPropertySpec static_properties[]; static const JSFunctionSpec static_methods[]; /** diff --git a/src/third_party/mozjs/extract/js/src/debugger/DebuggerMemory.cpp b/src/third_party/mozjs/extract/js/src/debugger/DebuggerMemory.cpp index 6a6c2d81235..e6080251816 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/DebuggerMemory.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/DebuggerMemory.cpp @@ -37,9 +37,6 @@ using namespace js; -using mozilla::Maybe; -using mozilla::Nothing; - /* static */ DebuggerMemory* DebuggerMemory::create(JSContext* cx, Debugger* dbg) { Value memoryProtoValue = @@ -71,7 +68,9 @@ bool DebuggerMemory::construct(JSContext* cx, unsigned argc, Value* vp) { } /* static */ const JSClass DebuggerMemory::class_ = { - "Memory", JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_COUNT)}; + "Memory", + JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_COUNT), +}; /* static */ DebuggerMemory* DebuggerMemory::checkThis(JSContext* cx, CallArgs& args) { @@ -434,8 +433,11 @@ bool DebuggerMemory::CallData::takeCensus() { JS_DEBUG_PSG("allocationsLogOverflowed", getAllocationsLogOverflowed), JS_DEBUG_PSGS("onGarbageCollection", getOnGarbageCollection, setOnGarbageCollection), - JS_PS_END}; + JS_PS_END, +}; /* static */ const JSFunctionSpec DebuggerMemory::methods[] = { JS_DEBUG_FN("drainAllocationsLog", drainAllocationsLog, 0), - JS_DEBUG_FN("takeCensus", takeCensus, 0), JS_FS_END}; + JS_DEBUG_FN("takeCensus", takeCensus, 0), + JS_FS_END, +}; diff --git a/src/third_party/mozjs/extract/js/src/debugger/Environment.cpp b/src/third_party/mozjs/extract/js/src/debugger/Environment.cpp index 8549b474717..ef352fc4438 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Environment.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/Environment.cpp @@ -65,7 +65,8 @@ const JSClassOps DebuggerEnvironment::classOps_ = { const JSClass DebuggerEnvironment::class_ = { "Environment", JSCLASS_HAS_RESERVED_SLOTS(DebuggerEnvironment::RESERVED_SLOTS), - &classOps_}; + &classOps_, +}; void DebuggerEnvironment::trace(JSTracer* trc) { // There is a barrier on private pointers, so the Unbarriered marking @@ -366,12 +367,16 @@ const JSPropertySpec DebuggerEnvironment::properties_[] = { JS_DEBUG_PSG("calleeScript", calleeScriptGetter), JS_DEBUG_PSG("inspectable", inspectableGetter), JS_DEBUG_PSG("optimizedOut", optimizedOutGetter), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec DebuggerEnvironment::methods_[] = { - JS_DEBUG_FN("names", namesMethod, 0), JS_DEBUG_FN("find", findMethod, 1), + JS_DEBUG_FN("names", namesMethod, 0), + JS_DEBUG_FN("find", findMethod, 1), JS_DEBUG_FN("getVariable", getVariableMethod, 1), - JS_DEBUG_FN("setVariable", setVariableMethod, 2), JS_FS_END}; + JS_DEBUG_FN("setVariable", setVariableMethod, 2), + JS_FS_END, +}; /* static */ NativeObject* DebuggerEnvironment::initClass(JSContext* cx, diff --git a/src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.cpp b/src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.cpp new file mode 100644 index 00000000000..06fc0a0395f --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.cpp @@ -0,0 +1,516 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "debugger/ExecutionTracer.h" + +#include "debugger/Frame.h" // DebuggerFrameType +#include "vm/ObjectOperations.h" // DefineDataElement +#include "vm/Time.h" + +#include "debugger/Debugger-inl.h" +#include "vm/Stack-inl.h" + +using namespace js; + +enum class OutOfLineEntryType : uint8_t { + ScriptURL, + Atom, +}; + +enum class InlineEntryType : uint8_t { + StackFunctionEnter, + StackFunctionLeave, + LabelEnter, + LabelLeave, + Error, +}; + +MOZ_RUNINIT mozilla::Vector ExecutionTracer::globalInstances; +MOZ_RUNINIT Mutex + ExecutionTracer::globalInstanceLock(mutexid::ExecutionTracerGlobalLock); + +static JS::ExecutionTrace::ImplementationType GetImplementation( + AbstractFramePtr frame) { + if (frame.isBaselineFrame()) { + return JS::ExecutionTrace::ImplementationType::Baseline; + } + + if (frame.isRematerializedFrame()) { + return JS::ExecutionTrace::ImplementationType::Ion; + } + + if (frame.isWasmDebugFrame()) { + return JS::ExecutionTrace::ImplementationType::Wasm; + } + + return JS::ExecutionTrace::ImplementationType::Interpreter; +} + +static DebuggerFrameType GetFrameType(AbstractFramePtr frame) { + // Indirect eval frames are both isGlobalFrame() and isEvalFrame(), so the + // order of checks here is significant. + if (frame.isEvalFrame()) { + return DebuggerFrameType::Eval; + } + + if (frame.isGlobalFrame()) { + return DebuggerFrameType::Global; + } + + if (frame.isFunctionFrame()) { + return DebuggerFrameType::Call; + } + + if (frame.isModuleFrame()) { + return DebuggerFrameType::Module; + } + + if (frame.isWasmDebugFrame()) { + return DebuggerFrameType::WasmCall; + } + + MOZ_CRASH("Unknown frame type"); +} + +[[nodiscard]] static bool GetFunctionName(JSContext* cx, + JS::Handle fun, + JS::MutableHandle result) { + if (!fun->getDisplayAtom(cx, result)) { + return false; + } + + if (result) { + cx->markAtom(result); + } + return true; +} + +static double GetNowMilliseconds() { + return (mozilla::TimeStamp::Now() - mozilla::TimeStamp::ProcessCreation()) + .ToMilliseconds(); +} + +void ExecutionTracer::handleError(JSContext* cx) { + inlineData_.beginWritingEntry(); + inlineData_.write(uint8_t(InlineEntryType::Error)); + inlineData_.finishWritingEntry(); + cx->clearPendingException(); + cx->suspendExecutionTracing(); +} + +void ExecutionTracer::writeScriptUrl(ScriptSource* scriptSource) { + outOfLineData_.beginWritingEntry(); + outOfLineData_.write(uint8_t(OutOfLineEntryType::ScriptURL)); + outOfLineData_.write(scriptSource->id()); + + if (scriptSource->hasDisplayURL()) { + outOfLineData_.writeCString( + scriptSource->displayURL()); + } else { + const char* filename = + scriptSource->filename() ? scriptSource->filename() : ""; + outOfLineData_.writeCString(filename); + } + outOfLineData_.finishWritingEntry(); +} + +bool ExecutionTracer::writeAtom(JSContext* cx, JS::Handle atom, + uint32_t id) { + outOfLineData_.beginWritingEntry(); + outOfLineData_.write(uint8_t(OutOfLineEntryType::Atom)); + outOfLineData_.write(id); + + if (!atom) { + outOfLineData_.writeEmptyString(); + } else { + if (!outOfLineData_.writeString(cx, atom)) { + return false; + } + } + outOfLineData_.finishWritingEntry(); + return true; +} + +bool ExecutionTracer::writeFunctionFrame(JSContext* cx, + AbstractFramePtr frame) { + JS::Rooted fn(cx, frame.callee()); + TracingCaches& caches = cx->caches().tracingCaches; + if (fn->baseScript()) { + uint32_t scriptSourceId = fn->baseScript()->scriptSource()->id(); + TracingCaches::GetOrPutResult scriptSourceRes = + caches.putScriptSourceIfMissing(scriptSourceId); + if (scriptSourceRes == TracingCaches::GetOrPutResult::OOM) { + ReportOutOfMemory(cx); + return false; + } + if (scriptSourceRes == TracingCaches::GetOrPutResult::NewlyAdded) { + writeScriptUrl(fn->baseScript()->scriptSource()); + } + inlineData_.write(fn->baseScript()->lineno()); + inlineData_.write(fn->baseScript()->column().oneOriginValue()); + inlineData_.write(scriptSourceId); + inlineData_.write( + fn->baseScript()->realm()->creationOptions().profilerRealmID()); + } else { + // In the case of no baseScript, we just fill it out with 0s. 0 is an + // invalid script source ID, so it is distinguishable from a real one + inlineData_.write(uint32_t(0)); // line number + inlineData_.write(uint32_t(0)); // column + inlineData_.write(uint32_t(0)); // script source id + } + + JS::Rooted functionName(cx); + if (!GetFunctionName(cx, fn, &functionName)) { + return false; + } + uint32_t functionNameId = 0; + TracingCaches::GetOrPutResult fnNameRes = + caches.getOrPutAtom(functionName, &functionNameId); + if (fnNameRes == TracingCaches::GetOrPutResult::OOM) { + ReportOutOfMemory(cx); + return false; + } + if (fnNameRes == TracingCaches::GetOrPutResult::NewlyAdded) { + if (!writeAtom(cx, functionName, functionNameId)) { + // It's worth noting here that this will leave the caches out of sync + // with what has actually been written into the out of line data. + // This is a normal and allowed situation for the tracer, so we have + // no special handling here for it. However, if we ever want to make + // a stronger guarantee in the future, we need to revisit this. + return false; + } + } + + inlineData_.write(functionNameId); + inlineData_.write(uint8_t(GetImplementation(frame))); + inlineData_.write(GetNowMilliseconds()); + return true; +} + +void ExecutionTracer::onEnterFrame(JSContext* cx, AbstractFramePtr frame) { + LockGuard guard(bufferLock_); + + DebuggerFrameType type = GetFrameType(frame); + if (type == DebuggerFrameType::Call) { + if (frame.isFunctionFrame() && !frame.callee()->isSelfHostedBuiltin()) { + inlineData_.beginWritingEntry(); + inlineData_.write(uint8_t(InlineEntryType::StackFunctionEnter)); + if (!writeFunctionFrame(cx, frame)) { + handleError(cx); + return; + } + + inlineData_.finishWritingEntry(); + } + } +} + +void ExecutionTracer::onLeaveFrame(JSContext* cx, AbstractFramePtr frame) { + LockGuard guard(bufferLock_); + + DebuggerFrameType type = GetFrameType(frame); + if (type == DebuggerFrameType::Call) { + if (frame.isFunctionFrame() && !frame.callee()->isSelfHostedBuiltin()) { + inlineData_.beginWritingEntry(); + inlineData_.write(uint8_t(InlineEntryType::StackFunctionLeave)); + if (!writeFunctionFrame(cx, frame)) { + handleError(cx); + return; + } + inlineData_.finishWritingEntry(); + } + } +} + +template +void ExecutionTracer::onEnterLabel(const CharType* eventType) { + LockGuard guard(bufferLock_); + + inlineData_.beginWritingEntry(); + inlineData_.write(uint8_t(InlineEntryType::LabelEnter)); + inlineData_.writeCString(eventType); + inlineData_.write(GetNowMilliseconds()); + inlineData_.finishWritingEntry(); +} + +template +void ExecutionTracer::onLeaveLabel(const CharType* eventType) { + LockGuard guard(bufferLock_); + + inlineData_.beginWritingEntry(); + inlineData_.write(uint8_t(InlineEntryType::LabelLeave)); + inlineData_.writeCString(eventType); + inlineData_.write(GetNowMilliseconds()); + inlineData_.finishWritingEntry(); +} + +bool ExecutionTracer::readFunctionFrame( + JS::ExecutionTrace::EventKind kind, + JS::ExecutionTrace::TracedEvent& event) { + MOZ_ASSERT(kind == JS::ExecutionTrace::EventKind::FunctionEnter || + kind == JS::ExecutionTrace::EventKind::FunctionLeave); + + event.kind = kind; + + uint8_t implementation; + inlineData_.read(&event.functionEvent.lineNumber); + inlineData_.read(&event.functionEvent.column); + inlineData_.read(&event.functionEvent.scriptId); + inlineData_.read(&event.functionEvent.realmID); + inlineData_.read(&event.functionEvent.functionNameId); + inlineData_.read(&implementation); + inlineData_.read(&event.time); + + event.functionEvent.implementation = + JS::ExecutionTrace::ImplementationType(implementation); + + return true; +} + +bool ExecutionTracer::readLabel(JS::ExecutionTrace::EventKind kind, + JS::ExecutionTrace::TracedEvent& event, + TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer) { + MOZ_ASSERT(kind == JS::ExecutionTrace::EventKind::LabelEnter || + kind == JS::ExecutionTrace::EventKind::LabelLeave); + + event.kind = kind; + size_t index; + if (!inlineData_.readString(scratchBuffer, stringBuffer, &index)) { + return false; + } + event.labelEvent.label = index; + + double time; + inlineData_.read(&time); + event.time = time; + + return true; +} + +bool ExecutionTracer::readInlineEntry( + mozilla::Vector& events, + TracingScratchBuffer& scratchBuffer, mozilla::Vector& stringBuffer) { + uint8_t entryType; + inlineData_.read(&entryType); + + switch (InlineEntryType(entryType)) { + case InlineEntryType::StackFunctionEnter: + case InlineEntryType::StackFunctionLeave: { + JS::ExecutionTrace::EventKind kind; + if (InlineEntryType(entryType) == InlineEntryType::StackFunctionEnter) { + kind = JS::ExecutionTrace::EventKind::FunctionEnter; + } else { + kind = JS::ExecutionTrace::EventKind::FunctionLeave; + } + JS::ExecutionTrace::TracedEvent event; + if (!readFunctionFrame(kind, event)) { + return false; + } + + if (!events.append(std::move(event))) { + return false; + } + return true; + } + case InlineEntryType::LabelEnter: + case InlineEntryType::LabelLeave: { + JS::ExecutionTrace::EventKind kind; + if (InlineEntryType(entryType) == InlineEntryType::LabelEnter) { + kind = JS::ExecutionTrace::EventKind::LabelEnter; + } else { + kind = JS::ExecutionTrace::EventKind::LabelLeave; + } + + JS::ExecutionTrace::TracedEvent event; + if (!readLabel(kind, event, scratchBuffer, stringBuffer)) { + return false; + } + + if (!events.append(std::move(event))) { + return false; + } + + return true; + } + case InlineEntryType::Error: { + JS::ExecutionTrace::TracedEvent event; + event.kind = JS::ExecutionTrace::EventKind::Error; + + if (!events.append(std::move(event))) { + return false; + } + + return true; + } + default: + return false; + } +} + +bool ExecutionTracer::readOutOfLineEntry( + mozilla::HashMap& scriptUrls, + mozilla::HashMap& atoms, + TracingScratchBuffer& scratchBuffer, mozilla::Vector& stringBuffer) { + uint8_t entryType; + outOfLineData_.read(&entryType); + + switch (OutOfLineEntryType(entryType)) { + case OutOfLineEntryType::ScriptURL: { + uint32_t id; + outOfLineData_.read(&id); + + size_t index; + if (!outOfLineData_.readString(scratchBuffer, stringBuffer, &index)) { + return false; + } + + if (!scriptUrls.put(id, index)) { + return false; + } + + return true; + } + case OutOfLineEntryType::Atom: { + uint32_t id; + outOfLineData_.read(&id); + + size_t index; + if (!outOfLineData_.readString(scratchBuffer, stringBuffer, &index)) { + return false; + } + + if (!atoms.put(id, index)) { + return false; + } + + return true; + } + default: + return false; + } +} + +bool ExecutionTracer::readInlineEntries( + mozilla::Vector& events, + TracingScratchBuffer& scratchBuffer, mozilla::Vector& stringBuffer) { + while (inlineData_.readable()) { + inlineData_.beginReadingEntry(); + if (!readInlineEntry(events, scratchBuffer, stringBuffer)) { + inlineData_.skipEntry(); + return false; + } + inlineData_.finishReadingEntry(); + } + return true; +} + +bool ExecutionTracer::readOutOfLineEntries( + mozilla::HashMap& scriptUrls, + mozilla::HashMap& atoms, + TracingScratchBuffer& scratchBuffer, mozilla::Vector& stringBuffer) { + while (outOfLineData_.readable()) { + outOfLineData_.beginReadingEntry(); + if (!readOutOfLineEntry(scriptUrls, atoms, scratchBuffer, stringBuffer)) { + outOfLineData_.skipEntry(); + return false; + } + outOfLineData_.finishReadingEntry(); + } + return true; +} + +bool ExecutionTracer::getNativeTrace( + JS::ExecutionTrace::TracedJSContext& context, + TracingScratchBuffer& scratchBuffer, mozilla::Vector& stringBuffer) { + LockGuard guard(bufferLock_); + + if (!readOutOfLineEntries(context.scriptUrls, context.atoms, scratchBuffer, + stringBuffer)) { + return false; + } + + if (!readInlineEntries(context.events, scratchBuffer, stringBuffer)) { + return false; + } + + return true; +} + +bool ExecutionTracer::getNativeTraceForAllContexts(JS::ExecutionTrace& trace) { + LockGuard guard(globalInstanceLock); + TracingScratchBuffer scratchBuffer; + for (ExecutionTracer* tracer : globalInstances) { + JS::ExecutionTrace::TracedJSContext* context = nullptr; + for (JS::ExecutionTrace::TracedJSContext& t : trace.contexts) { + if (t.id == tracer->threadId_) { + context = &t; + break; + } + } + if (!context) { + if (!trace.contexts.append(JS::ExecutionTrace::TracedJSContext())) { + return false; + } + context = &trace.contexts[trace.contexts.length() - 1]; + context->id = tracer->threadId_; + } + if (!tracer->getNativeTrace(*context, scratchBuffer, trace.stringBuffer)) { + return false; + } + } + + return true; +} + +void JS_TracerEnterLabelTwoByte(JSContext* cx, const char16_t* label) { + CHECK_THREAD(cx); + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer() + .onEnterLabel(label); + } +} + +void JS_TracerEnterLabelLatin1(JSContext* cx, const char* label) { + CHECK_THREAD(cx); + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer().onEnterLabel( + label); + } +} + +void JS_TracerLeaveLabelTwoByte(JSContext* cx, const char16_t* label) { + CHECK_THREAD(cx); + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer() + .onLeaveLabel(label); + } +} + +void JS_TracerLeaveLabelLatin1(JSContext* cx, const char* label) { + CHECK_THREAD(cx); + if (cx->hasExecutionTracer()) { + cx->getExecutionTracer().onLeaveLabel( + label); + } +} + +bool JS_TracerIsTracing(JSContext* cx) { return cx->hasExecutionTracer(); } + +bool JS_TracerBeginTracing(JSContext* cx) { + CHECK_THREAD(cx); + return cx->enableExecutionTracing(); +} + +bool JS_TracerEndTracing(JSContext* cx) { + CHECK_THREAD(cx); + cx->disableExecutionTracing(); + return true; +} + +bool JS_TracerSnapshotTrace(JS::ExecutionTrace& trace) { + return ExecutionTracer::getNativeTraceForAllContexts(trace); +} diff --git a/src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.h b/src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.h new file mode 100644 index 00000000000..2328de68185 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/debugger/ExecutionTracer.h @@ -0,0 +1,477 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef debugger_ExecutionTracer_h +#define debugger_ExecutionTracer_h + +#include "mozilla/Assertions.h" // MOZ_DIAGNOSTIC_ASSERT, MOZ_ASSERT +#include "mozilla/BaseProfilerUtils.h" // profiler_current_thread_id +#include "mozilla/MathAlgorithms.h" // mozilla::IsPowerOfTwo +#include "mozilla/Maybe.h" // mozilla::Maybe, mozilla::Some, mozilla::Nothing +#include "mozilla/Span.h" +#include "mozilla/TimeStamp.h" + +#include // std::numeric_limits +#include // size_t +#include // uint8_t, uint16_t + +#include "js/CharacterEncoding.h" // JS::UTF8Chars +#include "js/Debug.h" // JS::ExecutionTrace +#include "js/RootingAPI.h" // JS::Rooted +#include "js/Utility.h" // js_malloc, js_free +#include "js/Value.h" // JS::Value +#include "vm/JSContext.h" // JSContext +#include "vm/Stack.h" // js::AbstractFramePtr + +namespace js { + +enum class TracerStringEncoding { + Latin1, + TwoByte, + UTF8, +}; + +using TracingScratchBuffer = mozilla::Vector; + +// TODO: it should be noted that part of this design is informed by the fact +// that it evolved from a prototype which wrote this data from a content +// process and read it from the parent process, allowing the parent process to +// display the trace in real time as the program executes. Bug 1910182 tracks +// the next steps for making that prototype a reality. +template +class TracingBuffer { + static_assert(mozilla::IsPowerOfTwo(BUFFER_SIZE)); + + // BUFFER_SIZE is the size of the underlying ring buffer, and BUFFER_MASK + // masks off indices into it in order to wrap around + static const size_t BUFFER_MASK = BUFFER_SIZE - 1; + + // The entry header is just a u16 that holds the size of the entry in bytes. + // This is used for asserting the integrity of the data as well as for + // skipping the read head forward if it's going to be overwritten by the + // write head + static const size_t ENTRY_HEADER_SIZE = sizeof(uint16_t); + + // The underlying ring buffer + uint8_t* buffer_ = nullptr; + + // NOTE: The following u64s are unwrapped indices into the ring buffer, so + // they must always be masked off with BUFFER_MASK before using them to + // access buffer_: + + // Represents how much has been written into the ring buffer and is ready + // for reading + uint64_t writeHead_ = 0; + + // Represents how much has been read from the ring buffer + uint64_t readHead_ = 0; + + // When not equal to writeHead_, this represents unfinished write progress + // into the buffer. After each entry successfully finished writing, + // writeHead_ is set to this value + uint64_t uncommittedWriteHead_ = 0; + + // Similar to uncommittedWriteHead_, but for the purposes of reading + uint64_t uncommittedReadHead_ = 0; + + bool ensureScratchBufferSize(TracingScratchBuffer& scratchBuffer, + size_t requiredSize) { + if (scratchBuffer.length() >= requiredSize) { + return true; + } + return scratchBuffer.growByUninitialized(requiredSize - + scratchBuffer.length()); + } + + public: + ~TracingBuffer() { + if (buffer_) { + js_free(buffer_); + } + } + + bool init() { + buffer_ = static_cast(js_malloc(BUFFER_SIZE)); + return buffer_ != nullptr; + } + + bool readable() { return writeHead_ > readHead_; } + + void beginWritingEntry() { + // uncommittedWriteHead_ can be > writeHead_ if a previous write failed. + // In that case, this effectively discards whatever was written during that + // time + MOZ_ASSERT(uncommittedWriteHead_ >= writeHead_); + uncommittedWriteHead_ = writeHead_; + uncommittedWriteHead_ += ENTRY_HEADER_SIZE; + } + + void finishWritingEntry() { + MOZ_ASSERT(uncommittedWriteHead_ - writeHead_ <= + std::numeric_limits::max()); + uint16_t entryHeader = uint16_t(uncommittedWriteHead_ - writeHead_); + writeBytesAtOffset(reinterpret_cast(&entryHeader), + sizeof(entryHeader), writeHead_); + writeHead_ = uncommittedWriteHead_; + } + + void beginReadingEntry() { + MOZ_ASSERT(uncommittedReadHead_ == readHead_); + // We will read the entry header (still pointed to by readHead_) from + // inside finishReadingEntry + uncommittedReadHead_ += ENTRY_HEADER_SIZE; + } + + void finishReadingEntry() { + uint16_t entryHeader; + readBytesAtOffset(reinterpret_cast(&entryHeader), + sizeof(entryHeader), readHead_); + size_t read = uncommittedReadHead_ - readHead_; + + MOZ_RELEASE_ASSERT(entryHeader == uint16_t(read)); + readHead_ += entryHeader; + uncommittedReadHead_ = readHead_; + } + + void skipEntry() { + uint16_t entryHeader; + readBytesAtOffset(reinterpret_cast(&entryHeader), + sizeof(entryHeader), readHead_); + readHead_ += entryHeader; + uncommittedReadHead_ = readHead_; + } + + void writeBytesAtOffset(const uint8_t* bytes, size_t length, + uint64_t offset) { + MOZ_ASSERT(offset + length <= readHead_ + BUFFER_SIZE); + + size_t maskedWriteHead = offset & BUFFER_MASK; + if (maskedWriteHead + length > BUFFER_SIZE) { + size_t firstChunk = BUFFER_SIZE - maskedWriteHead; + memcpy(buffer_ + maskedWriteHead, bytes, firstChunk); + memcpy(buffer_, bytes + firstChunk, length - firstChunk); + } else { + memcpy(buffer_ + maskedWriteHead, bytes, length); + } + } + + void writeBytes(const uint8_t* bytes, size_t length) { + // Skip the read head forward if we're about to overwrite unread entries + while (MOZ_UNLIKELY(uncommittedWriteHead_ + length > + readHead_ + BUFFER_SIZE)) { + skipEntry(); + } + + writeBytesAtOffset(bytes, length, uncommittedWriteHead_); + uncommittedWriteHead_ += length; + } + + template + void write(T val) { + // No magic hidden work allowed here - we are just reducing duplicate code + // serializing integers and floats. + static_assert(std::is_arithmetic_v); + writeBytes(reinterpret_cast(&val), sizeof(T)); + } + + void writeEmptyString() { + write(uint8_t(TracerStringEncoding::Latin1)); + write(uint32_t(0)); // length + } + + bool writeString(JSContext* cx, JS::Handle str) { + TracerStringEncoding encoding; + if (str->hasLatin1Chars()) { + encoding = TracerStringEncoding::Latin1; + } else { + encoding = TracerStringEncoding::TwoByte; + } + + // TODO: if ropes are common we can certainly serialize them without + // linearizing - this is just easy + JSLinearString* linear = str->ensureLinear(cx); + if (!linear) { + return false; + } + write(uint8_t(encoding)); + size_t length = linear->length(); + MOZ_ASSERT(length <= std::numeric_limits::max()); + write(uint32_t(length)); + size_t size = length; + JS::AutoAssertNoGC nogc; + const uint8_t* charBuffer = nullptr; + if (encoding == TracerStringEncoding::TwoByte) { + size *= sizeof(char16_t); + charBuffer = reinterpret_cast(linear->twoByteChars(nogc)); + } else { + charBuffer = reinterpret_cast(linear->latin1Chars(nogc)); + } + writeBytes(charBuffer, size); + return true; + } + + template + void writeCString(const CharType* chars) { + size_t length = std::char_traits::length(chars); + static_assert(sizeof(CharType) == 1 || + Encoding == TracerStringEncoding::TwoByte); + static_assert(sizeof(CharType) <= 2); + write(uint8_t(Encoding)); + MOZ_ASSERT(length <= std::numeric_limits::max()); + write(uint32_t(length)); + const size_t size = length * sizeof(CharType); + writeBytes(reinterpret_cast(chars), size); + } + + void readBytesAtOffset(uint8_t* bytes, size_t length, uint64_t offset) { + size_t maskedReadHead = offset & BUFFER_MASK; + if (maskedReadHead + length > BUFFER_SIZE) { + size_t firstChunk = BUFFER_SIZE - maskedReadHead; + memcpy(bytes, buffer_ + maskedReadHead, firstChunk); + memcpy(bytes + firstChunk, buffer_, length - firstChunk); + } else { + memcpy(bytes, buffer_ + maskedReadHead, length); + } + } + + void readBytes(uint8_t* bytes, size_t length) { + readBytesAtOffset(bytes, length, uncommittedReadHead_); + uncommittedReadHead_ += length; + } + + template + void read(T* val) { + static_assert(std::is_arithmetic_v); + readBytes(reinterpret_cast(val), sizeof(T)); + } + + // Reads a string from our buffer into the stringBuffer. Converts everything + // to null-terminated UTF-8 + bool readString(TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer, size_t* index) { + uint8_t encodingByte; + read(&encodingByte); + TracerStringEncoding encoding = TracerStringEncoding(encodingByte); + + uint32_t length; + read(&length); + + *index = stringBuffer.length(); + + if (length == 0) { + if (!stringBuffer.append('\0')) { + return false; + } + return true; + } + + if (encoding == TracerStringEncoding::UTF8) { + size_t reserveLength = length + 1; + if (!stringBuffer.growByUninitialized(reserveLength)) { + return false; + } + char* writePtr = stringBuffer.end() - reserveLength; + readBytes(reinterpret_cast(writePtr), length); + writePtr[length] = '\0'; + } else if (encoding == TracerStringEncoding::Latin1) { + if (!ensureScratchBufferSize(scratchBuffer, length)) { + return false; + } + readBytes(reinterpret_cast(scratchBuffer.begin()), length); + + // A single latin-1 code point maps to either 1 or 2 UTF-8 code units. + // The + 1 is for the null terminator. + size_t reserveLength = length * 2 + 1; + if (!stringBuffer.reserve(stringBuffer.length() + reserveLength)) { + return false; + } + char* writePtr = stringBuffer.end(); + + size_t convertedLength = mozilla::ConvertLatin1toUtf8( + mozilla::Span(scratchBuffer.begin(), length), + mozilla::Span(writePtr, reserveLength)); + writePtr[convertedLength] = 0; + + // We reserved above, which just grows the capacity but not the length. + // This just commits the exact length increase. + if (!stringBuffer.growByUninitialized(convertedLength + 1)) { + return false; + } + } else { + MOZ_ASSERT(encoding == TracerStringEncoding::TwoByte); + if (!ensureScratchBufferSize(scratchBuffer, length * sizeof(char16_t))) { + return false; + } + readBytes(reinterpret_cast(scratchBuffer.begin()), + length * sizeof(char16_t)); + + // Non-surrogate-paired single UTF-16 code unit maps to 1 to 3 UTF-8 + // code units. Surrogate paired UTF-16 code units map to 4 to 6 UTF-8 + // code units. + size_t reserveLength = length * 3 + 1; + if (!stringBuffer.reserve(stringBuffer.length() + reserveLength)) { + return false; + } + char* writePtr = stringBuffer.end(); + + size_t convertedLength = mozilla::ConvertUtf16toUtf8( + mozilla::Span( + reinterpret_cast(scratchBuffer.begin()), length), + mozilla::Span(writePtr, reserveLength)); + writePtr[convertedLength] = 0; + + // We reserved above, which just grows the capacity but not the length. + // This just commits the exact length increase. + if (!stringBuffer.growByUninitialized(convertedLength + 1)) { + return false; + } + } + + return true; + } +}; + +// These sizes are to some degree picked out of a hat, and eventually it might +// be nice to make them configurable. For reference, I measured it costing +// 145MB to open gdocs and create an empty document, so 256MB is just some +// extra wiggle room for complex use cases. +using InlineDataBuffer = TracingBuffer<1 << 28>; + +// The size for the out of line data is much smaller, so I just picked a size +// that was much smaller but big enough that I didn't see us running out of it +// when playing around on various complex apps. Again, it would be great in the +// future for this to be configurable. +using OutOfLineDataBuffer = TracingBuffer<1 << 22>; + +// An ExecutionTracer is responsible for recording JS execution while it is +// enabled to a set of ring buffers, and providing that information as a JS +// object when requested. See Debugger.md (collectNativeTrace) for more details. +class ExecutionTracer { + private: + // The fields below should only be accessed while we hold the lock. + static Mutex globalInstanceLock MOZ_UNANNOTATED; + static mozilla::Vector globalInstances; + + // The buffers below should only be accessed while we hold the lock. + Mutex bufferLock_ MOZ_UNANNOTATED; + + // This holds the actual entries, one for each push or pop of a frame or label + InlineDataBuffer inlineData_; + + // This holds data that may be duplicated across entries, like script URLs or + // function names. This should generally be much smaller in terms of raw + // bytes. Note however that we can still wrap around this buffer and lose + // entries - the system is best effort, and the consumer must accomodate the + // fact that entries from inlineData_ may reference expired data from + // outOfLineData_ + OutOfLineDataBuffer outOfLineData_; + + // This is just an ID that allows the profiler to easily correlate the trace + // for a given context with the correct thread in the output profile. + // We're operating on the assumption that there is one JSContext per thread, + // which should be true enough for our uses in Firefox, but doesn't have to + // be true everywhere. + mozilla::baseprofiler::BaseProfilerThreadId threadId_; + + // When we encounter an error during tracing, we write one final Error entry + // and suspend tracing indefinitely. This allows the consumer to get some + // information about what led up to the error, while preventing any + // additional future overhead. An alternative to this approach would be to + // clean up all of our buffers on error, but since the user must have elected + // to turn on tracing, we assume that they would rather have a greater chance + // of more information about what led up to the error rather than a greater + // chance of avoiding a crash due to OOM. + void handleError(JSContext* cx); + + void writeScriptUrl(ScriptSource* scriptSource); + + // Writes an atom into the outOfLineData_, associating it with the specified + // id. In practice, `id` comes from an atom id inside a cache in the + // JSContext which is incremented each time a new atom is registered and + // cleared when tracing is done. + bool writeAtom(JSContext* cx, JS::Handle atom, uint32_t id); + bool writeFunctionFrame(JSContext* cx, AbstractFramePtr frame); + + // The below functions read data from the inlineData_ and outOfLineData_ ring + // buffers into structs to be consumed by clients of the + // JS_TracerSnapshotTrace API. + bool readFunctionFrame(JS::ExecutionTrace::EventKind kind, + JS::ExecutionTrace::TracedEvent& event); + bool readLabel(JS::ExecutionTrace::EventKind kind, + JS::ExecutionTrace::TracedEvent& event, + TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer); + bool readInlineEntry(mozilla::Vector& events, + TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer); + bool readOutOfLineEntry(mozilla::HashMap& scriptUrls, + mozilla::HashMap& atoms, + TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer); + bool readInlineEntries( + mozilla::Vector& events, + TracingScratchBuffer& scratchBuffer, mozilla::Vector& stringBuffer); + bool readOutOfLineEntries(mozilla::HashMap& scriptUrls, + mozilla::HashMap& atoms, + TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer); + + public: + ExecutionTracer() : bufferLock_(mutexid::ExecutionTracerInstanceLock) {} + + ~ExecutionTracer() { + LockGuard guard(globalInstanceLock); + + globalInstances.eraseIfEqual(this); + } + + mozilla::baseprofiler::BaseProfilerThreadId threadId() const { + return threadId_; + } + + bool init() { + LockGuard guard(globalInstanceLock); + LockGuard guard2(bufferLock_); + + threadId_ = mozilla::baseprofiler::profiler_current_thread_id(); + + if (!inlineData_.init()) { + return false; + } + if (!outOfLineData_.init()) { + return false; + } + + if (!globalInstances.append(this)) { + return false; + } + + return true; + } + + void onEnterFrame(JSContext* cx, AbstractFramePtr frame); + void onLeaveFrame(JSContext* cx, AbstractFramePtr frame); + + template + void onEnterLabel(const CharType* eventType); + template + void onLeaveLabel(const CharType* eventType); + + // Reads the execution trace from the underlying ring buffers and outputs it + // into a native struct. For more information about this struct, see + // js/public/Debug.h + bool getNativeTrace(JS::ExecutionTrace::TracedJSContext& context, + TracingScratchBuffer& scratchBuffer, + mozilla::Vector& stringBuffer); + + // Calls getNativeTrace for every JSContext in the process, populating the + // provided ExecutionTrace with the result. + static bool getNativeTraceForAllContexts(JS::ExecutionTrace& trace); +}; + +} // namespace js + +#endif /* debugger_ExecutionTracer_h */ diff --git a/src/third_party/mozjs/extract/js/src/debugger/Frame.cpp b/src/third_party/mozjs/extract/js/src/debugger/Frame.cpp index 63978b90ab2..c5c15e2be8d 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Frame.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/Frame.cpp @@ -12,7 +12,7 @@ #include "mozilla/Range.h" // for Range #include "mozilla/RangedPtr.h" // for RangedPtr #include "mozilla/Result.h" // for Result -#include "mozilla/ScopeExit.h" // for MakeScopeExit, ScopeExit +#include "mozilla/ScopeExit.h" // for ScopeExit #include "mozilla/ThreadLocal.h" // for ThreadLocal #include "mozilla/Vector.h" // for Vector @@ -41,6 +41,7 @@ #include "jit/JSJitFrameIter.h" // for InlineFrameIterator #include "jit/RematerializedFrame.h" // for RematerializedFrame #include "js/CallArgs.h" // for CallArgs +#include "js/EnvironmentChain.h" // JS::EnvironmentChain #include "js/friend/ErrorMessages.h" // for GetErrorMessage, JSMSG_* #include "js/GCVector.h" // for JS::StackGCVector #include "js/Object.h" // for SetReservedSlot @@ -54,7 +55,7 @@ #include "vm/AsyncIteration.h" // for AsyncGeneratorObject #include "vm/BytecodeUtil.h" // for JSDVG_SEARCH_STACK #include "vm/Compartment.h" // for Compartment -#include "vm/EnvironmentObject.h" // for IsGlobalLexicalEnvironment +#include "vm/EnvironmentObject.h" // for GlobalLexicalEnvironmentObject #include "vm/GeneratorObject.h" // for AbstractGeneratorObject #include "vm/GlobalObject.h" // for GlobalObject #include "vm/Interpreter.h" // for Call, ExecuteKernel @@ -96,7 +97,6 @@ using JS::AutoStableStringChars; using JS::CompileOptions; using JS::SourceOwnership; using JS::SourceText; -using mozilla::MakeScopeExit; using mozilla::Maybe; ScriptedOnStepHandler::ScriptedOnStepHandler(JSObject* object) @@ -196,12 +196,15 @@ const JSClass DebuggerFrame::class_ = { // We require foreground finalization so we can destruct GeneratorInfo's // HeapPtrs. JSCLASS_FOREGROUND_FINALIZE, - &DebuggerFrame::classOps_}; + &DebuggerFrame::classOps_, +}; enum { JSSLOT_DEBUGARGUMENTS_FRAME, JSSLOT_DEBUGARGUMENTS_COUNT }; const JSClass DebuggerArguments::class_ = { - "Arguments", JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGARGUMENTS_COUNT)}; + "Arguments", + JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGARGUMENTS_COUNT), +}; bool DebuggerFrame::resume(const FrameIter& iter) { FrameIter::Data* data = iter.copyData(); @@ -212,6 +215,10 @@ bool DebuggerFrame::resume(const FrameIter& iter) { return true; } +void DebuggerFrame::suspendWasmFrame(JS::GCContext* gcx) { + freeFrameIterData(gcx); +} + bool DebuggerFrame::hasAnyHooks() const { return !getReservedSlot(ONSTEP_HANDLER_SLOT).isUndefined() || !getReservedSlot(ONPOP_HANDLER_SLOT).isUndefined(); @@ -927,7 +934,7 @@ bool DebuggerFrame::getArguments(JSContext* cx, Handle frame, return true; } -static JSObject* CreateBindingsEnv( +static WithEnvironmentObject* CreateBindingsEnv( JSContext* cx, JS::Handle enclosingEnv, JS::Handle> bindingKeys, JS::Handle> bindingValues) { @@ -948,17 +955,12 @@ static JSObject* CreateBindingsEnv( } } - RootedObjectVector envChain(cx); + JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No); if (!envChain.append(bindingsObj)) { return nullptr; } - JS::Rooted newEnv(cx); - if (!CreateObjectsForEnvironmentChain(cx, envChain, enclosingEnv, &newEnv)) { - return nullptr; - } - - return newEnv; + return CreateObjectsForEnvironmentChain(cx, envChain, enclosingEnv); } /* @@ -1032,83 +1034,83 @@ static bool EvaluateInEnv( return false; } - JS::Rooted env(cx, envArg); - if (evalOptions.kind() == EvalOptions::EnvKind::FrameWithExtraBindings || - evalOptions.kind() == - EvalOptions::EnvKind::GlobalWithExtraInnerBindings) { - // NOTE: GlobalWithExtraOuterBindings case is handled in separately below. - env = CreateBindingsEnv(cx, env, bindingKeys, bindingValues); - if (!env) { - return false; + // Compile the script and compute the environment object. + JS::Rooted script(cx); + JS::Rooted env(cx); + switch (evalOptions.kind()) { + case EvalOptions::EnvKind::FrameWithExtraBindings: { + env = CreateBindingsEnv(cx, envArg, bindingKeys, bindingValues); + if (!env) { + return false; + } + [[fallthrough]]; } - } + case EvalOptions::EnvKind::Frame: { + // Default to |envArg| when no extra bindings are used. + if (!env) { + env = envArg; + } - if (evalOptions.kind() == EvalOptions::EnvKind::Frame || - evalOptions.kind() == EvalOptions::EnvKind::FrameWithExtraBindings) { - options.setNonSyntacticScope(true); + options.setNonSyntacticScope(true); - Rooted scope(cx, - GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic)); - if (!scope) { - return false; + Rooted scope( + cx, GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic)); + if (!scope) { + return false; + } + + script = frontend::CompileEvalScript(cx, options, srcBuf, scope, env); + if (!script) { + return false; + } + break; } + case EvalOptions::EnvKind::Global: { + AutoReportFrontendContext fc(cx); + script = frontend::CompileGlobalScript(cx, &fc, options, srcBuf, + ScopeKind::Global); + if (!script) { + return false; + } - RootedScript script( - cx, frontend::CompileEvalScript(cx, options, srcBuf, scope, env)); - if (!script) { - return false; + env = envArg; + break; } + case EvalOptions::EnvKind::GlobalWithExtraOuterBindings: { + // Do not consider executeInGlobal{,WithBindings} as an eval, but instead + // as executing a series of statements at the global level. This is to + // circumvent the fresh lexical scope that all eval have, so that the + // users of executeInGlobal{,WithBindings}, like the web console, may add + // new bindings to the global scope. - return ExecuteKernel(cx, script, env, frame, rval); - } + MOZ_ASSERT(envArg == &cx->global()->lexicalEnvironment()); - // Do not consider executeInGlobal{,WithBindings} as an eval, but instead - // as executing a series of statements at the global level. This is to - // circumvent the fresh lexical scope that all eval have, so that the - // users of executeInGlobal{,WithBindings}, like the web console, may add new - // bindings to the global scope. + options.setNonSyntacticScope(true); - if (evalOptions.kind() == - EvalOptions::EnvKind::GlobalWithExtraOuterBindings) { - options.setNonSyntacticScope(true); - - MOZ_ASSERT(env == &cx->global()->lexicalEnvironment()); - - JS::Rooted bindingsEnv(cx); - - AutoReportFrontendContext fc(cx); - RootedScript script(cx, frontend::CompileGlobalScriptWithExtraBindings( - cx, &fc, options, srcBuf, bindingKeys, - bindingValues, &bindingsEnv)); - if (!script) { - return false; + AutoReportFrontendContext fc(cx); + script = frontend::CompileGlobalScriptWithExtraBindings( + cx, &fc, options, srcBuf, bindingKeys, bindingValues, &env); + if (!script) { + return false; + } + break; } + case EvalOptions::EnvKind::GlobalWithExtraInnerBindings: { + env = CreateBindingsEnv(cx, envArg, bindingKeys, bindingValues); + if (!env) { + return false; + } - return ExecuteKernel(cx, script, bindingsEnv, frame, rval); - } + options.setNonSyntacticScope(true); - if (evalOptions.kind() == - EvalOptions::EnvKind::GlobalWithExtraInnerBindings) { - options.setNonSyntacticScope(true); - - AutoReportFrontendContext fc(cx); - RootedScript script(cx, - frontend::CompileGlobalScript(cx, &fc, options, srcBuf, - ScopeKind::NonSyntactic)); - if (!script) { - return false; + AutoReportFrontendContext fc(cx); + script = frontend::CompileGlobalScript(cx, &fc, options, srcBuf, + ScopeKind::NonSyntactic); + if (!script) { + return false; + } + break; } - - return ExecuteKernel(cx, script, env, frame, rval); - } - - MOZ_ASSERT(evalOptions.kind() == EvalOptions::EnvKind::Global); - - AutoReportFrontendContext fc(cx); - RootedScript script(cx, frontend::CompileGlobalScript( - cx, &fc, options, srcBuf, ScopeKind::Global)); - if (!script) { - return false; } return ExecuteKernel(cx, script, env, frame, rval); @@ -1133,14 +1135,14 @@ Result js::DebuggerGenericEval( case EvalOptions::EnvKind::Global: MOZ_ASSERT(!iter); MOZ_ASSERT(envArg); - MOZ_ASSERT(IsGlobalLexicalEnvironment(envArg)); + MOZ_ASSERT(envArg->is()); MOZ_ASSERT(!bindings); break; case EvalOptions::EnvKind::GlobalWithExtraInnerBindings: case EvalOptions::EnvKind::GlobalWithExtraOuterBindings: MOZ_ASSERT(!iter); MOZ_ASSERT(envArg); - MOZ_ASSERT(IsGlobalLexicalEnvironment(envArg)); + MOZ_ASSERT(envArg->is()); MOZ_ASSERT(bindings); break; } @@ -1227,11 +1229,18 @@ Result DebuggerFrame::eval(JSContext* cx, } bool DebuggerFrame::isOnStack() const { - // Note: this is equivalent to checking frameIterData() != nullptr, but works - // also when called from the trace hook during a moving GC. + // Note: this is equivalent to checking frameIterData() != nullptr. return !getFixedSlot(FRAME_ITER_SLOT).isUndefined(); } +bool DebuggerFrame::isOnStackOrSuspendedWasmStack() const { + // Note: this is equivalent to checking `frameIterData() != nullptr && + // !hasGeneratorInfo()`, but works also when called from the trace hook + // during a moving GC. + return !getFixedSlot(FRAME_ITER_SLOT).isUndefined() || + getFixedSlot(GENERATOR_INFO_SLOT).isUndefined(); +} + OnStepHandler* DebuggerFrame::onStepHandler() const { return maybePtrFromReservedSlot(ONSTEP_HANDLER_SLOT); } @@ -2029,11 +2038,14 @@ const JSPropertySpec DebuggerFrame::properties_[] = { JS_DEBUG_PSG("implementation", implementationGetter), JS_DEBUG_PSGS("onStep", onStepGetter, onStepSetter), JS_DEBUG_PSGS("onPop", onPopGetter, onPopSetter), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec DebuggerFrame::methods_[] = { JS_DEBUG_FN("eval", evalMethod, 1), - JS_DEBUG_FN("evalWithBindings", evalWithBindingsMethod, 1), JS_FS_END}; + JS_DEBUG_FN("evalWithBindings", evalWithBindingsMethod, 1), + JS_FS_END, +}; JSObject* js::IdVectorToArray(JSContext* cx, HandleIdVector ids) { if (MOZ_UNLIKELY(ids.length() > UINT32_MAX)) { diff --git a/src/third_party/mozjs/extract/js/src/debugger/Frame.h b/src/third_party/mozjs/extract/js/src/debugger/Frame.h index 44ee39d9db8..2ff64f81e12 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Frame.h +++ b/src/third_party/mozjs/extract/js/src/debugger/Frame.h @@ -191,6 +191,7 @@ class DebuggerFrame : public NativeObject { [[nodiscard]] static DebuggerFrame* check(JSContext* cx, HandleValue thisv); bool isOnStack() const; + bool isOnStackOrSuspendedWasmStack() const; bool isSuspended() const; @@ -252,6 +253,11 @@ class DebuggerFrame : public NativeObject { */ bool resume(const FrameIter& iter); + /* + * Called when JS PI sets aside the suspendable stack frames. + */ + void suspendWasmFrame(JS::GCContext* gcx); + bool hasAnyHooks() const; Debugger* owner() const; diff --git a/src/third_party/mozjs/extract/js/src/debugger/Object.cpp b/src/third_party/mozjs/extract/js/src/debugger/Object.cpp index 358e27ed547..911fb187581 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Object.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/Object.cpp @@ -100,7 +100,10 @@ const JSClassOps DebuggerObject::classOps_ = { }; const JSClass DebuggerObject::class_ = { - "Object", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), &classOps_}; + "Object", + JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), + &classOps_, +}; void DebuggerObject::trace(JSTracer* trc) { // There is a barrier on private pointers, so the Unbarriered marking @@ -1276,46 +1279,56 @@ bool DebuggerObject::CallData::createSource() { bool isScriptElement = ToBoolean(v); - JS::CompileOptions compileOptions(cx); - compileOptions.lineno = startLine; - compileOptions.column = JS::ColumnNumberOneOrigin(startColumn); - - if (!JS::StringHasLatin1Chars(url)) { - JS_ReportErrorASCII(cx, "URL must be a narrow string"); + if (!JS_GetProperty(cx, options, "forceEnableAsmJS", &v)) { return false; } - UniqueChars urlChars = JS_EncodeStringToUTF8(cx, url); - if (!urlChars) { - return false; - } - compileOptions.setFile(urlChars.get()); - - Vector sourceMapURLChars(cx); - if (sourceMapURL) { - if (!CopyStringToVector(cx, sourceMapURL, sourceMapURLChars)) { - return false; - } - compileOptions.setSourceMapURL(sourceMapURLChars.begin()); - } - - if (isScriptElement) { - // The introduction type must be a statically allocated string. - compileOptions.setIntroductionType("inlineScript"); - } - - AutoStableStringChars linearChars(cx); - if (!linearChars.initTwoByte(cx, text)) { - return false; - } - JS::SourceText srcBuf; - if (!srcBuf.initMaybeBorrowed(cx, linearChars)) { - return false; - } + bool forceEnableAsmJS = ToBoolean(v); RootedScript script(cx); { AutoRealm ar(cx, referent); + + JS::CompileOptions compileOptions(cx); + compileOptions.lineno = startLine; + compileOptions.column = JS::ColumnNumberOneOrigin(startColumn); + if (forceEnableAsmJS) { + compileOptions.setAsmJSOption(JS::AsmJSOption::Enabled); + } + + if (!JS::StringHasLatin1Chars(url)) { + JS_ReportErrorASCII(cx, "URL must be a narrow string"); + return false; + } + + UniqueChars urlChars = JS_EncodeStringToUTF8(cx, url); + if (!urlChars) { + return false; + } + compileOptions.setFile(urlChars.get()); + + Vector sourceMapURLChars(cx); + if (sourceMapURL) { + if (!CopyStringToVector(cx, sourceMapURL, sourceMapURLChars)) { + return false; + } + compileOptions.setSourceMapURL(sourceMapURLChars.begin()); + } + + if (isScriptElement) { + // The introduction type must be a statically allocated string. + compileOptions.setIntroductionType("inlineScript"); + } + + AutoStableStringChars linearChars(cx); + if (!linearChars.initTwoByte(cx, text)) { + return false; + } + JS::SourceText srcBuf; + if (!srcBuf.initMaybeBorrowed(cx, linearChars)) { + return false; + } + script = JS::Compile(cx, compileOptions, srcBuf); if (!script) { return false; @@ -1516,7 +1529,8 @@ const JSPropertySpec DebuggerObject::properties_[] = { JS_DEBUG_PSG("isProxy", isProxyGetter), JS_DEBUG_PSG("proxyTarget", proxyTargetGetter), JS_DEBUG_PSG("proxyHandler", proxyHandlerGetter), - JS_PS_END}; + JS_PS_END, +}; const JSPropertySpec DebuggerObject::promiseProperties_[] = { JS_DEBUG_PSG("isPromise", isPromiseGetter), @@ -1529,7 +1543,8 @@ const JSPropertySpec DebuggerObject::promiseProperties_[] = { JS_DEBUG_PSG("promiseResolutionSite", promiseResolutionSiteGetter), JS_DEBUG_PSG("promiseID", promiseIDGetter), JS_DEBUG_PSG("promiseDependentPromises", promiseDependentPromisesGetter), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec DebuggerObject::methods_[] = { JS_DEBUG_FN("isExtensible", isExtensibleMethod, 0), @@ -1565,7 +1580,8 @@ const JSFunctionSpec DebuggerObject::methods_[] = { JS_DEBUG_FN("unsafeDereference", unsafeDereferenceMethod, 0), JS_DEBUG_FN("unwrap", unwrapMethod, 0), JS_DEBUG_FN("getPromiseReactions", getPromiseReactionsMethod, 0), - JS_FS_END}; + JS_FS_END, +}; /* static */ NativeObject* DebuggerObject::initClass(JSContext* cx, diff --git a/src/third_party/mozjs/extract/js/src/debugger/Script.cpp b/src/third_party/mozjs/extract/js/src/debugger/Script.cpp index fc522b261c8..140d0cae073 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Script.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/Script.cpp @@ -50,6 +50,7 @@ #include "wasm/WasmJS.h" // for WasmInstanceObject #include "wasm/WasmTypeDecls.h" // for Bytes +#include "gc/Marking-inl.h" // for MaybeForwardedObjectIs #include "vm/BytecodeUtil-inl.h" // for BytecodeRangeWithPosition #include "vm/JSAtomUtils-inl.h" // for PrimitiveValueToId #include "vm/JSObject-inl.h" // for NewBuiltinClassInstance, NewObjectWithGivenProto, NewTenuredObjectWithGivenProto @@ -76,7 +77,10 @@ const JSClassOps DebuggerScript::classOps_ = { }; const JSClass DebuggerScript::class_ = { - "Script", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), &classOps_}; + "Script", + JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), + &classOps_, +}; void DebuggerScript::trace(JSTracer* trc) { // This comes from a private pointer, so no barrier needed. @@ -94,7 +98,7 @@ void DebuggerScript::trace(JSTracer* trc) { TraceManuallyBarrieredCrossCompartmentEdge( trc, this, &wasm, "Debugger.Script wasm referent"); if (wasm != cell->as()) { - MOZ_ASSERT(wasm->is()); + MOZ_ASSERT(gc::MaybeForwardedObjectIs(wasm)); setReservedSlotGCThingAsPrivateUnbarriered(SCRIPT_SLOT, wasm); } } @@ -735,6 +739,9 @@ class DebuggerScript::GetPossibleBreakpointsMatcher { return false; } *result->addressOfValueForTranscode() = tmp; + if (!result->valid()) { + return false; + } return true; } bool parseSizeTValue(HandleValue value, size_t* result) { @@ -863,9 +870,10 @@ class DebuggerScript::GetPossibleBreakpointsMatcher { } if (!parseColumnValue(minColumnValue, &minColumn)) { - JS_ReportErrorNumberASCII( - cx_, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, - "getPossibleBreakpoints' 'minColumn'", "not a positive integer"); + JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, + JSMSG_UNEXPECTED_TYPE, + "getPossibleBreakpoints' 'minColumn'", + "not a positive integer in valid range"); return false; } } @@ -889,9 +897,10 @@ class DebuggerScript::GetPossibleBreakpointsMatcher { } if (!parseColumnValue(maxColumnValue, &maxColumn)) { - JS_ReportErrorNumberASCII( - cx_, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, - "getPossibleBreakpoints' 'maxColumn'", "not a positive integer"); + JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, + JSMSG_UNEXPECTED_TYPE, + "getPossibleBreakpoints' 'maxColumn'", + "not a positive integer in valid range"); return false; } } @@ -1479,7 +1488,6 @@ static bool BytecodeIsEffectful(JSScript* script, size_t offset) { case JSOp::CanSkipAwait: #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT case JSOp::AddDisposable: - case JSOp::DisposeDisposables: #endif return true; @@ -1500,6 +1508,10 @@ static bool BytecodeIsEffectful(JSScript* script, size_t offset) { case JSOp::Try: case JSOp::Throw: case JSOp::ThrowWithStack: +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + case JSOp::TakeDisposeCapability: + case JSOp::CreateSuppressedError: +#endif case JSOp::Goto: case JSOp::TableSwitch: case JSOp::Case: @@ -1527,6 +1539,8 @@ static bool BytecodeIsEffectful(JSScript* script, size_t offset) { case JSOp::Ne: case JSOp::StrictEq: case JSOp::StrictNe: + case JSOp::StrictConstantEq: + case JSOp::StrictConstantNe: case JSOp::Lt: case JSOp::Le: case JSOp::Gt: @@ -1595,8 +1609,9 @@ static bool BytecodeIsEffectful(JSScript* script, size_t offset) { case JSOp::GetName: case JSOp::GetIntrinsic: case JSOp::GetImport: - case JSOp::BindGName: case JSOp::BindName: + case JSOp::BindUnqualifiedName: + case JSOp::BindUnqualifiedGName: case JSOp::BindVar: case JSOp::Dup: case JSOp::Dup2: @@ -1689,15 +1704,6 @@ static bool BytecodeIsEffectful(JSScript* script, size_t offset) { case JSOp::GetRval: case JSOp::ThrowMsg: case JSOp::ForceInterpreter: -#ifdef ENABLE_RECORD_TUPLE - case JSOp::InitRecord: - case JSOp::AddRecordProperty: - case JSOp::AddRecordSpread: - case JSOp::FinishRecord: - case JSOp::InitTuple: - case JSOp::AddTupleElement: - case JSOp::FinishTuple: -#endif return false; case JSOp::InitAliasedLexical: { @@ -2479,7 +2485,8 @@ const JSPropertySpec DebuggerScript::properties_[] = { JS_DEBUG_PSG("mainOffset", getMainOffset), JS_DEBUG_PSG("global", getGlobal), JS_DEBUG_PSG("format", getFormat), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec DebuggerScript::methods_[] = { JS_DEBUG_FN("getChildScripts", getChildScripts, 0), @@ -2501,4 +2508,6 @@ const JSFunctionSpec DebuggerScript::methods_[] = { JS_DEBUG_FN("getAllOffsets", getAllOffsets, 0), JS_DEBUG_FN("getAllColumnOffsets", getAllColumnOffsets, 0), JS_DEBUG_FN("getLineOffsets", getLineOffsets, 1), - JS_DEBUG_FN("getOffsetLocation", getOffsetLocation, 0), JS_FS_END}; + JS_DEBUG_FN("getOffsetLocation", getOffsetLocation, 0), + JS_FS_END, +}; diff --git a/src/third_party/mozjs/extract/js/src/debugger/Source.cpp b/src/third_party/mozjs/extract/js/src/debugger/Source.cpp index 3136a4add1e..9fc414fe5ee 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/Source.cpp +++ b/src/third_party/mozjs/extract/js/src/debugger/Source.cpp @@ -68,7 +68,10 @@ const JSClassOps DebuggerSource::classOps_ = { }; const JSClass DebuggerSource::class_ = { - "Source", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), &classOps_}; + "Source", + JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS), + &classOps_, +}; /* static */ NativeObject* DebuggerSource::initClass(JSContext* cx, @@ -278,14 +281,13 @@ bool DebuggerSource::CallData::getBinary() { return false; } - const wasm::Bytes& bytecode = instance.debug().bytecode(); + const wasm::BytecodeSource& bytecode = instance.debug().bytecode(); RootedObject arr(cx, JS_NewUint8Array(cx, bytecode.length())); if (!arr) { return false; } - memcpy(arr->as().dataPointerUnshared(), bytecode.begin(), - bytecode.length()); + bytecode.copyTo((uint8_t*)arr->as().dataPointerUnshared()); args.rval().setObject(*arr); return true; @@ -393,7 +395,11 @@ struct DebuggerSourceGetDisplayURLMatcher { return ss->hasDisplayURL() ? ss->displayURL() : nullptr; } ReturnType match(Handle wasmInstance) { - return wasmInstance->instance().metadata().displayURL(); + return wasmInstance->instance().codeMetaForAsmJS() + ? wasmInstance->instance() + .codeMetaForAsmJS() + ->displayURL() // asm.js + : nullptr; // wasm } }; @@ -687,7 +693,10 @@ const JSPropertySpec DebuggerSource::properties_[] = { JS_DEBUG_PSG("introductionType", getIntroductionType), JS_DEBUG_PSG("elementAttributeName", getElementProperty), JS_DEBUG_PSGS("sourceMapURL", getSourceMapURL, setSourceMapURL), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec DebuggerSource::methods_[] = { - JS_DEBUG_FN("reparse", reparse, 0), JS_FS_END}; + JS_DEBUG_FN("reparse", reparse, 0), + JS_FS_END, +}; diff --git a/src/third_party/mozjs/extract/js/src/debugger/moz.build b/src/third_party/mozjs/extract/js/src/debugger/moz.build index c8c162bcbdd..9fcb90c6acd 100644 --- a/src/third_party/mozjs/extract/js/src/debugger/moz.build +++ b/src/third_party/mozjs/extract/js/src/debugger/moz.build @@ -29,3 +29,6 @@ UNIFIED_SOURCES = [ "Script.cpp", "Source.cpp", ] + +if CONFIG["MOZ_EXECUTION_TRACING"]: + UNIFIED_SOURCES += ["ExecutionTracer.cpp"] diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/autospider.py b/src/third_party/mozjs/extract/js/src/devtools/automation/autospider.py index edd7c5597fa..1c24b43278b 100755 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/autospider.py +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/autospider.py @@ -181,9 +181,10 @@ OBJDIR = os.path.abspath(OBJDIR) OUTDIR = os.path.join(OBJDIR, "out") MAKE = env.get("MAKE", "make") PYTHON = sys.executable +MACH = os.path.join(DIR.source, "mach") for d in DIR._fields: - info("DIR.{name} = {dir}".format(name=d, dir=getattr(DIR, d))) + info(f"DIR.{d} = {getattr(DIR, d)}") def ensure_dir_exists( @@ -377,6 +378,13 @@ def run_command(command, check=False, **kwargs): return stdout, stderr, status +def run_mach_command(command, check=False, **kwargs): + _stdout, _stderr, status = run_command( + [PYTHON, MACH] + command, check=check, **kwargs + ) + return status + + # Replacement strings in environment variables. REPLACEMENTS = { "DIR": DIR.scripts, @@ -390,6 +398,12 @@ REPLACEMENTS = { for k, v in variant.get("env", {}).items(): env[k] = v.format(**REPLACEMENTS) +# Do similar substitution for the extra_args keyed lists. +extra_args = {"jit-test": [], "jstests": [], "gdb": []} +extra_args.update(variant.get("extra-args", {})) +for v in extra_args.values(): + v[:] = [arg.format(**REPLACEMENTS) for arg in v] + if AUTOMATION: # Currently only supported on linux64. if platform.system() == "Linux" and word_bits == 64: @@ -428,17 +442,17 @@ if use_minidump: if injector_lib is None: use_minidump = False - info("use_minidump is {}".format(use_minidump)) + info(f"use_minidump is {use_minidump}") info(" MINIDUMP_SAVE_PATH={}".format(env["MINIDUMP_SAVE_PATH"])) - info(" injector lib is {}".format(injector_lib)) + info(f" injector lib is {injector_lib}") info(" MINIDUMP_STACKWALK={}".format(env.get("MINIDUMP_STACKWALK"))) mozconfig = os.path.join(DIR.source, "mozconfig.autospider") -CONFIGURE_ARGS += " --prefix={OBJDIR}/dist".format(OBJDIR=quote(OBJDIR)) +CONFIGURE_ARGS += f" --prefix={quote(OBJDIR)}/dist" # Generate a mozconfig. -with open(mozconfig, "wt") as fh: +with open(mozconfig, "w") as fh: if AUTOMATION and platform.system() == "Windows": fh.write('. "$topsrcdir/build/mozconfig.clang-cl"\n') fh.write("ac_add_options --enable-project=js\n") @@ -447,11 +461,9 @@ with open(mozconfig, "wt") as fh: env["MOZCONFIG"] = mozconfig -mach = os.path.join(DIR.source, "mach") - if not args.nobuild: # Do the build - run_command([sys.executable, mach, "build"], check=True) + run_mach_command(["build"], check=True) if use_minidump: # Convert symbols to breakpad format. @@ -460,10 +472,8 @@ if not args.nobuild: cmd_env["RUSTC_COMMIT"] = "0" cmd_env["MOZ_CRASHREPORTER"] = "1" cmd_env["MOZ_AUTOMATION_BUILD_SYMBOLS"] = "1" - run_command( + run_mach_command( [ - sys.executable, - mach, "build", "recurse_syms", ], @@ -485,19 +495,14 @@ def run_test_command(command, **kwargs): def run_jsapitests(args): - jsapi_test_binary = os.path.join(OBJDIR, "dist", "bin", "jsapi-tests") test_env = env.copy() - test_env["TOPSRCDIR"] = DIR.source if use_minidump and platform.system() == "Linux": test_env["LD_PRELOAD"] = injector_lib - st = run_test_command([jsapi_test_binary] + args, env=test_env) + st = run_mach_command(["jsapi-tests"], env=test_env) if st < 0: - print( - "PROCESS-CRASH | {} | application crashed".format( - " ".join(["jsapi-tests"] + args) - ) - ) - print("Return code: {}".format(st)) + info = " ".join(["jsapi-tests"] + args) + print(f"PROCESS-CRASH | {info} | application crashed") + print(f"Return code: {st}") return st @@ -549,13 +554,9 @@ jstest_workers = worker_max jittest_workers = worker_max if platform.system() == "Windows": jstest_workers = min(worker_max, 16) - env["JSTESTS_EXTRA_ARGS"] = "-j{} ".format(jstest_workers) + env.get( - "JSTESTS_EXTRA_ARGS", "" - ) + extra_args["jstests"].append(f"-j{jstest_workers}") jittest_workers = min(worker_max, 8) - env["JITTEST_EXTRA_ARGS"] = "-j{} ".format(jittest_workers) + env.get( - "JITTEST_EXTRA_ARGS", "" - ) + extra_args["jit-test"].append(f"-j{jittest_workers}") print( f"using {jstest_workers}/{worker_max} workers for jstests, " f"{jittest_workers}/{worker_max} for jittest" @@ -567,12 +568,12 @@ if use_minidump: # cross-compiling from 64- to 32-bit, that will fail and produce stderr # output when running any 64-bit commands, which breaks eg mozconfig # processing. So use the --dll command line mechanism universally. - for v in ("JSTESTS_EXTRA_ARGS", "JITTEST_EXTRA_ARGS"): - env[v] = "--args='--dll %s' %s" % (injector_lib, env.get(v, "")) + for suite in ("jstests", "jit-test"): + extra_args[suite].append(f"--args=--dll {injector_lib}") -# Report longest running jit-tests in automation. -env["JITTEST_EXTRA_ARGS"] = "--show-slow " + env.get("JITTEST_EXTRA_ARGS", "") -env["JSTESTS_EXTRA_ARGS"] = "--show-slow " + env.get("JSTESTS_EXTRA_ARGS", "") +# Report longest running tests in automation. +for suite in ("jstests", "jit-test"): + extra_args[suite].append("--show-slow") # Always run all enabled tests, even if earlier ones failed. But return the # first failed status. @@ -582,22 +583,45 @@ if "checks" in test_suites: results.append(("make check", run_test_command([MAKE, "check"]))) if "jittest" in test_suites: - results.append(("make check-jit-test", run_test_command([MAKE, "check-jit-test"]))) + auto_args = [] + if AUTOMATION: + auto_args = [ + "--no-slow", + "--no-progress", + "--format=automation", + "--timeout=300", + "--jitflags=all", + ] + results.append( + ( + "mach jit-test", + run_mach_command(["jit-test", "--", *auto_args, *extra_args["jit-test"]]), + ) + ) if "jsapitests" in test_suites: st = run_jsapitests([]) if st == 0: st = run_jsapitests(["--frontend-only"]) results.append(("jsapi-tests", st)) if "jstests" in test_suites: - results.append(("jstests", run_test_command([MAKE, "check-jstests"]))) + auto_args = [] + if AUTOMATION: + auto_args = ["--no-progress", "--format=automation", "--timeout=300"] + results.append( + ( + "mach jstests", + run_mach_command(["jstests", "--", *auto_args, *extra_args["jstests"]]), + ) + ) if "gdb" in test_suites: test_script = os.path.join(DIR.js_src, "gdb", "run-tests.py") auto_args = ["-s", "-o", "--no-progress"] if AUTOMATION else [] - extra_args = env.get("GDBTEST_EXTRA_ARGS", "").split(" ") results.append( ( "gdb", - run_test_command([PYTHON, test_script, *auto_args, *extra_args, OBJDIR]), + run_test_command( + [PYTHON, test_script, *auto_args, *extra_args["gdb"], OBJDIR] + ), ) ) @@ -668,9 +692,8 @@ if args.variant == "wasi": # Generate stacks from minidumps. if use_minidump: - run_command( + run_mach_command( [ - mach, "python", "--virtualenv=build", os.path.join(DIR.source, "testing/mozbase/mozcrash/mozcrash/mozcrash.py"), diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jittest-known-failure.txt b/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jittest-known-failure.txt deleted file mode 100644 index 8d32545934a..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jittest-known-failure.txt +++ /dev/null @@ -1,4 +0,0 @@ -# https://github.com/mozilla-spidermonkey/jsparagus/issues/641 -class/class-static-01.js -class/class-static-02.js -class/class-static-03.js diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure-and-slow.txt b/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure-and-slow.txt deleted file mode 100644 index 7d905ca6c78..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure-and-slow.txt +++ /dev/null @@ -1,81 +0,0 @@ -# https://github.com/mozilla-spidermonkey/jsparagus/issues/635 -test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-objectliteral.js - -# https://github.com/mozilla-spidermonkey/jsparagus/issues/641 -test262/language/expressions/function/static-init-await-binding.js -test262/language/expressions/generators/static-init-await-binding.js -test262/language/expressions/object/ident-name-prop-name-literal-await-static-init.js -test262/language/expressions/object/identifier-shorthand-static-init-await-valid.js -test262/language/expressions/object/method-definition/static-init-await-binding-accessor.js -test262/language/expressions/object/method-definition/static-init-await-binding-generator.js -test262/language/expressions/object/method-definition/static-init-await-binding-normal.js -test262/language/statements/class/static-init-abrupt.js -test262/language/statements/class/static-init-arguments-functions.js -test262/language/statements/class/static-init-arguments-methods.js -test262/language/statements/class/static-init-await-binding-valid.js -test262/language/statements/class/static-init-expr-new-target.js -test262/language/statements/class/static-init-expr-this.js -test262/language/statements/class/static-init-scope-lex-close.js -test262/language/statements/class/static-init-scope-var-close.js -test262/language/statements/class/static-init-scope-var-derived.js -test262/language/statements/class/static-init-scope-var-open.js -test262/language/statements/class/static-init-statement-list-optional.js -test262/language/statements/class/static-init-super-property.js -test262/language/statements/const/static-init-await-binding-valid.js -test262/language/statements/function/static-init-await-binding-valid.js -test262/language/statements/let/static-init-await-binding-valid.js -test262/language/statements/try/static-init-await-binding-valid.js -test262/language/statements/variable/dstr/ary-ptrn-elem-id-static-init-await-valid.js -test262/language/statements/variable/dstr/obj-ptrn-elem-id-static-init-await-valid.js -test262/language/statements/variable/static-init-await-binding-valid.js - -# https://github.com/mozilla-spidermonkey/jsparagus/issues/650 -test262/language/expressions/dynamic-import/2nd-param-assert-enumeration-abrupt.js -test262/language/expressions/dynamic-import/2nd-param-assert-enumeration.js -test262/language/expressions/dynamic-import/2nd-param-assert-non-object.js -test262/language/expressions/dynamic-import/2nd-param-assert-undefined.js -test262/language/expressions/dynamic-import/2nd-param-assert-value-abrupt.js -test262/language/expressions/dynamic-import/2nd-param-assert-value-non-string.js -test262/language/expressions/dynamic-import/2nd-param-evaluation-abrupt-return.js -test262/language/expressions/dynamic-import/2nd-param-evaluation-abrupt-throw.js -test262/language/expressions/dynamic-import/2nd-param-evaluation-sequence.js -test262/language/expressions/dynamic-import/2nd-param-get-assert-error.js -test262/language/expressions/dynamic-import/2nd-param-in.js -test262/language/expressions/dynamic-import/2nd-param-non-object.js -test262/language/expressions/dynamic-import/2nd-param-trailing-comma-fulfill.js -test262/language/expressions/dynamic-import/2nd-param-trailing-comma-reject.js -test262/language/expressions/dynamic-import/2nd-param-yield-expr.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-labeled-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-labeled-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-do-while-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-do-while-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-braceless-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-braceless-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-return-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-return-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-braceless-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-braceless-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-expression-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-expression-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/top-level-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/top-level-trailing-comma-second.js -test262/language/expressions/dynamic-import/trailing-comma-fulfill.js -test262/language/expressions/dynamic-import/trailing-comma-reject.js - -# slow -non262/String/normalize-generateddata-part0.js -non262/String/normalize-generateddata-part1-not-listed.js -non262/String/normalize-generateddata-part1.js -non262/String/normalize-generateddata-part2.js -non262/String/normalize-generateddata-part3.js -non262/regress/regress-155081-2.js diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure.txt b/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure.txt deleted file mode 100644 index 7a3be5c2110..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-known-failure.txt +++ /dev/null @@ -1,73 +0,0 @@ -# https://github.com/mozilla-spidermonkey/jsparagus/issues/635 -test262/language/expressions/assignmenttargettype/parenthesized-primaryexpression-objectliteral.js - -# https://github.com/mozilla-spidermonkey/jsparagus/issues/641 -test262/language/expressions/function/static-init-await-binding.js -test262/language/expressions/generators/static-init-await-binding.js -test262/language/expressions/object/ident-name-prop-name-literal-await-static-init.js -test262/language/expressions/object/identifier-shorthand-static-init-await-valid.js -test262/language/expressions/object/method-definition/static-init-await-binding-accessor.js -test262/language/expressions/object/method-definition/static-init-await-binding-generator.js -test262/language/expressions/object/method-definition/static-init-await-binding-normal.js -test262/language/statements/class/static-init-abrupt.js -test262/language/statements/class/static-init-arguments-functions.js -test262/language/statements/class/static-init-arguments-methods.js -test262/language/statements/class/static-init-await-binding-valid.js -test262/language/statements/class/static-init-expr-new-target.js -test262/language/statements/class/static-init-expr-this.js -test262/language/statements/class/static-init-scope-lex-close.js -test262/language/statements/class/static-init-scope-var-close.js -test262/language/statements/class/static-init-scope-var-derived.js -test262/language/statements/class/static-init-scope-var-open.js -test262/language/statements/class/static-init-statement-list-optional.js -test262/language/statements/class/static-init-super-property.js -test262/language/statements/const/static-init-await-binding-valid.js -test262/language/statements/function/static-init-await-binding-valid.js -test262/language/statements/let/static-init-await-binding-valid.js -test262/language/statements/try/static-init-await-binding-valid.js -test262/language/statements/variable/dstr/ary-ptrn-elem-id-static-init-await-valid.js -test262/language/statements/variable/dstr/obj-ptrn-elem-id-static-init-await-valid.js -test262/language/statements/variable/static-init-await-binding-valid.js - -# https://github.com/mozilla-spidermonkey/jsparagus/issues/650 -test262/language/expressions/dynamic-import/2nd-param-assert-enumeration-abrupt.js -test262/language/expressions/dynamic-import/2nd-param-assert-enumeration.js -test262/language/expressions/dynamic-import/2nd-param-assert-non-object.js -test262/language/expressions/dynamic-import/2nd-param-assert-undefined.js -test262/language/expressions/dynamic-import/2nd-param-assert-value-abrupt.js -test262/language/expressions/dynamic-import/2nd-param-assert-value-non-string.js -test262/language/expressions/dynamic-import/2nd-param-evaluation-abrupt-return.js -test262/language/expressions/dynamic-import/2nd-param-evaluation-abrupt-throw.js -test262/language/expressions/dynamic-import/2nd-param-evaluation-sequence.js -test262/language/expressions/dynamic-import/2nd-param-get-assert-error.js -test262/language/expressions/dynamic-import/2nd-param-in.js -test262/language/expressions/dynamic-import/2nd-param-non-object.js -test262/language/expressions/dynamic-import/2nd-param-trailing-comma-fulfill.js -test262/language/expressions/dynamic-import/2nd-param-trailing-comma-reject.js -test262/language/expressions/dynamic-import/2nd-param-yield-expr.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-labeled-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-labeled-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-block-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-do-while-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-do-while-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-braceless-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-braceless-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-else-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-return-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-return-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-function-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-braceless-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-braceless-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-if-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-expression-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-expression-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/nested-with-trailing-comma-second.js -test262/language/expressions/dynamic-import/syntax/valid/top-level-trailing-comma-first.js -test262/language/expressions/dynamic-import/syntax/valid/top-level-trailing-comma-second.js -test262/language/expressions/dynamic-import/trailing-comma-fulfill.js -test262/language/expressions/dynamic-import/trailing-comma-reject.js diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/arm64-sim b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/arm64-sim index bbaec58fac1..76c68b02cd3 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/arm64-sim +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/arm64-sim @@ -2,9 +2,9 @@ "configure-args": "--enable-simulator=arm64 --enable-rust-simd", "optimize": true, "debug": true, - "env": { - "JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/arm64-jstests-slow.txt", - "JITTEST_EXTRA_ARGS": "--ignore-timeouts={DIR}/arm64-jittests-timeouts.txt --jitflags=none --args=--baseline-eager -x ion/ -x asm.js/" + "extra-args": { + "jstests": ["--exclude-file={DIR}/arm64-jstests-slow.txt"], + "jit-test": ["--ignore-timeouts={DIR}/arm64-jittests-timeouts.txt", "--jitflags=none", "--args=--baseline-eager", "-x", "ion/", "-x", "asm.js/"] }, "bits": 64 } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/compacting b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/compacting index 911cfa1c493..463224ed537 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/compacting +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/compacting @@ -3,9 +3,11 @@ "optimize": true, "debug": true, "env": { - "JS_GC_ZEAL": "IncrementalMultipleSlices", - "JITTEST_EXTRA_ARGS": "--jitflags=debug --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt", - "JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/cgc-jstests-slow.txt" + "JS_GC_ZEAL": "IncrementalMultipleSlices" + }, + "extra-args": { + "jit-test": ["--jitflags=debug", "--ignore-timeouts={DIR}/cgc-jittest-timeouts.txt"], + "jstests": ["--exclude-file={DIR}/cgc-jstests-slow.txt"] }, "skip-tests": { "win32": ["jstests"], diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzilli b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzilli index 61605e3a968..a121e404158 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzilli +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzilli @@ -4,8 +4,8 @@ "debug": true, "nspr": false, "compiler": "clang", - "env": { - "JITTEST_EXTRA_ARGS": "--jitflags=ion" + "extra-args": { + "jit-test": ["--jitflags=ion"] }, "skip-tests": { "all": ["jstests"] diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzing b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzing index 146b89e3554..03796348d31 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzing +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/fuzzing @@ -4,10 +4,12 @@ "debug": false, "compiler": "clang", "env": { - "JITTEST_EXTRA_ARGS": "--jitflags=none", - "JSTESTS_EXTRA_ARGS": "--jitflags=none", "LLVM_SYMBOLIZER": "{MOZ_FETCHES_DIR}/llvm-symbolizer/bin/llvm-symbolizer", "ASAN_SYMBOLIZER_PATH": "{MOZ_FETCHES_DIR}/llvm-symbolizer/bin/llvm-symbolizer" }, + "extra-args": { + "jit-test": ["--jitflags=none"], + "jstests": ["--jitflags=none"] + }, "use_minidump": false } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/gdb b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/gdb index d86d2656805..866fb96979f 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/gdb +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/gdb @@ -9,8 +9,8 @@ "extra-tests": { "all": ["gdb"] }, - "env": { - "GDBTEST_EXTRA_ARGS": "--exclude=unwind" + "extra-args": { + "gdb": ["--exclude=unwind"] }, "use_minidump": false } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/msan b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/msan index e85e67dfb5e..1624f4f265d 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/msan +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/msan @@ -4,10 +4,12 @@ "debug": false, "compiler": "clang", "env": { - "JITTEST_EXTRA_ARGS": "--jitflags=interp --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt", - "JSTESTS_EXTRA_ARGS": "--jitflags=interp --exclude-file={DIR}/cgc-jstests-slow.txt", "MSAN_OPTIONS": "external_symbolizer_path={MOZ_FETCHES_DIR}/llvm-symbolizer/bin/llvm-symbolizer:log_path={OUTDIR}/sanitize_log" }, + "extra-args": { + "jit-test": ["--jitflags=interp", "--ignore-timeouts={DIR}/cgc-jittest-timeouts.txt"], + "jstests": ["--jitflags=interp", "--exclude-file={DIR}/cgc-jstests-slow.txt"] + }, "ignore-test-failures": "true", "max-errors": 7, "use_minidump": false diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/nonunified b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/nonunified index f675a0c670d..08859b65577 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/nonunified +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/nonunified @@ -1,9 +1,6 @@ { "configure-args": "--enable-warnings-as-errors --enable-rust-simd --disable-unified-build", "debug": true, - "env": { - "JS_SMOOSH_DISABLE_OPCODE_CHECK": "1" - }, "skip-tests": { "all": ["jstests", "jittest", "checks"] } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/plain b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/plain index f2aaf776c98..e25eb40b2b8 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/plain +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/plain @@ -2,8 +2,8 @@ "configure-args": "--enable-rust-simd", "optimize": true, "compiler": "gcc", - "env": { - "JSTESTS_EXTRA_ARGS": "--jitflags=jstests --run-slow-tests", - "JITTEST_EXTRA_ARGS": "--slow" + "extra-args": { + "jstests": ["--jitflags=jstests", "--run-slow-tests"], + "jit-test": ["--slow"] } } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rootanalysis b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rootanalysis index 4424e55a801..2eaff98c785 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rootanalysis +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rootanalysis @@ -3,8 +3,10 @@ "optimize": true, "debug": true, "env": { - "JS_GC_ZEAL": "GenerationalGC", - "JITTEST_EXTRA_ARGS": "--args='--gc-param=semispaceNurseryEnabled=1'", - "JSTESTS_EXTRA_ARGS": "--jitflags=debug --args='--gc-param=semispaceNurseryEnabled=1'" + "JS_GC_ZEAL": "GenerationalGC;CheckHeapBeforeMinorGC" + }, + "extra-args": { + "jit-test": ["--args=--gc-param=semispaceNurseryEnabled=1"], + "jstests": ["--jitflags=debug", "--args=--gc-param=semispaceNurseryEnabled=1"] } } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rtdebug b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rtdebug deleted file mode 100644 index d3450261ff6..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/rtdebug +++ /dev/null @@ -1,8 +0,0 @@ -{ - "debug": true, - "optimize": true, - "configure-args": "--enable-record-tuple", - "skip-tests": { - "all": ["jittest", "jsapitests", "checks"] - } -} diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/smoosh b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/smoosh deleted file mode 100644 index 148c2f8c21d..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/smoosh +++ /dev/null @@ -1,8 +0,0 @@ -{ - "configure-args": "--enable-rust-simd --enable-smoosh", - "optimize": true, - "env": { - "JSTESTS_EXTRA_ARGS": "--args='--smoosh' --jitflags=jstests --exclude-file={DIR}/smoosh-jstests-known-failure.txt", - "JITTEST_EXTRA_ARGS": "--args='--smoosh' --exclude-file={DIR}/smoosh-jittest-known-failure.txt" - } -} diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/smooshdebug b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/smooshdebug deleted file mode 100644 index 07b50cf9179..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/smooshdebug +++ /dev/null @@ -1,8 +0,0 @@ -{ - "configure-args": "--enable-rust-simd --enable-smoosh", - "debug": true, - "env": { - "JSTESTS_EXTRA_ARGS": "--args='--smoosh' --jitflags=debug --exclude-file={DIR}/smoosh-jstests-known-failure-and-slow.txt", - "JITTEST_EXTRA_ARGS": "--args='--smoosh' --exclude-file={DIR}/smoosh-jittest-known-failure.txt" - } -} diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/temporaldebug b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/temporaldebug deleted file mode 100644 index c4582c0af5e..00000000000 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/temporaldebug +++ /dev/null @@ -1,7 +0,0 @@ -{ - "configure-args": "--with-temporal-api --enable-rust-simd", - "debug": true, - "env": { - "JSTESTS_EXTRA_ARGS": "--jitflags=debug" - } -} diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/tsan b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/tsan index 69b2d87ef92..c1890b2ba7f 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/tsan +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/tsan @@ -4,9 +4,11 @@ "debug": false, "compiler": "clang", "env": { - "LLVM_SYMBOLIZER": "{MOZ_FETCHES_DIR}/llvm-symbolizer/bin/llvm-symbolizer", - "JITTEST_EXTRA_ARGS": "--jitflags=tsan --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt --unusable-error-status --exclude-from={DIR}/tsan-slow.txt", - "JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/cgc-jstests-slow.txt" + "LLVM_SYMBOLIZER": "{MOZ_FETCHES_DIR}/llvm-symbolizer/bin/llvm-symbolizer" + }, + "extra-args": { + "jit-test": ["--jitflags=tsan", "--ignore-timeouts={DIR}/cgc-jittest-timeouts.txt", "--unusable-error-status", "--exclude-from={DIR}/tsan-slow.txt"], + "jstests": ["--exclude-file={DIR}/cgc-jstests-slow.txt"] }, "use_minidump": false } diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi index 18fb91ba4e6..7d4a090b1f7 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi @@ -4,8 +4,8 @@ "debug": false, "nspr": false, "compiler": "clang", - "env": { - "JITTEST_EXTRA_ARGS": "--jitflags=none" + "extra-args": { + "jit-test": ["--jitflags=none"] }, "skip-tests": { "all": ["jstests", "jittest", "jsapitests"] diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-intl b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-intl index dbaaffff665..dcd53992b3e 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-intl +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-intl @@ -4,8 +4,8 @@ "debug": false, "nspr": false, "compiler": "clang", - "env": { - "JITTEST_EXTRA_ARGS": "--jitflags=none" + "extra-args": { + "jit-test": ["--jitflags=none"] }, "skip-tests": { "all": ["jstests", "jittest", "jsapitests"] diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-pbl b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-pbl index 2c2cf31f357..4d55e91d7a6 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-pbl +++ b/src/third_party/mozjs/extract/js/src/devtools/automation/variants/wasi-pbl @@ -4,8 +4,8 @@ "debug": false, "nspr": false, "compiler": "clang", - "env": { - "JITTEST_EXTRA_ARGS": "--jitflags=none" + "extra-args": { + "jit-test": ["--jitflags=none"] }, "skip-tests": { "all": ["jstests", "jittest", "jsapitests"] diff --git a/src/third_party/mozjs/extract/js/src/devtools/gc/gc-test.py b/src/third_party/mozjs/extract/js/src/devtools/gc/gc-test.py index 80a8d78b770..1f9874f8d29 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/gc/gc-test.py +++ b/src/third_party/mozjs/extract/js/src/devtools/gc/gc-test.py @@ -185,7 +185,7 @@ if __name__ == "__main__": if OPTIONS.baseline_path: baseline_map = [] - fh = open(OPTIONS.baseline_path, "r") + fh = open(OPTIONS.baseline_path) baseline_map = json.load(fh) fh.close() compare(current=bench_map, baseline=baseline_map) diff --git a/src/third_party/mozjs/extract/js/src/devtools/iongraph/iongraph b/src/third_party/mozjs/extract/js/src/devtools/iongraph/iongraph index e90e2460e70..1879742ce94 100755 --- a/src/third_party/mozjs/extract/js/src/devtools/iongraph/iongraph +++ b/src/third_party/mozjs/extract/js/src/devtools/iongraph/iongraph @@ -71,10 +71,11 @@ class Graph(GraphWidget): print(self.type, '{', file=f) # Use the pass name as the graph title (at the top). + legend = 'movable, guard, in worklist, recovered on bailout' print('labelloc = t;', file=f) print('labelfontsize = 30;', file=f) - print('label = "%s - %s";' % (self.func['name'], self.name), file=f) - + print('label = <%s - %s
%s
 >;' % (self.func['name'], self.name, legend), file=f) + # Output graph properties. for p in self.props: print(' ' + str(p) + '=' + str(self.props[p]), file=f) @@ -148,7 +149,8 @@ def getInstructionRow(inst): instLabel = '%s' % (instId, instId) # Middle column: instruction name. - instName = html.escape(inst['opcode']) + instName = inst['opcode'].replace('->', '→').replace('<-', '←') + instName = html.escape(instName) if 'attributes' in inst: if 'RecoveredOnBailout' in inst['attributes']: instName = '%s' % instName @@ -163,20 +165,29 @@ def getInstructionRow(inst): # Right column: instruction MIRType. instType = '' if 'type' in inst and inst['type'] != "None": - instType = '%s' % html.escape(inst['type']) + instType = '%s' % html.escape(inst['type']) return '%s%s%s' % (instLabel, instName, instType) # block obj -> HTML-formatted string def getBlockLabel(b): - s = '<' + s = '<
' if 'blockUseCount' in b: - blockUseCount = "(Count: %s)" % str(b['blockUseCount']) + blockUseCount = " (Count: %s)" % str(b['blockUseCount']) else: blockUseCount = "" - blockTitle = 'Block %s %s' % (str(b['number']), blockUseCount) + blockAttr = "" + if 'attributes' in b: + if 'backedge' in b['attributes']: + blockAttr = ' (backedge)' + if 'loopheader' in b['attributes']: + blockAttr = ' (loop header)' + if 'splitedge' in b['attributes']: + blockAttr = " (split edge)" + + blockTitle = 'Block %s%s%s' % (str(b['number']), blockUseCount, blockAttr) blockTitle = '' % blockTitle s += '%s' % blockTitle @@ -217,9 +228,9 @@ def buildGraphForIR(name, func, ir, mir): node.addprops({'shape':'box', 'label':getBlockLabel(bactive)}) if 'backedge' in b['attributes']: - node.addprops({'color':'red'}) + node.addprops({'color':'crimson'}) if 'loopheader' in b['attributes']: - node.addprops({'color':'green'}) + node.addprops({'color':'limegreen'}) if 'splitedge' in b['attributes']: node.addprops({'style':'dashed'}) @@ -346,6 +357,10 @@ def parsenums(numstr): return [int(x) for x in numstr.split(',')] +def parsenames(namestr): + return namestr and namestr.split(',') + + def validate(args): if not shutil.which('dot'): sys.stderr.write("ERROR: graphviz (dot) is not installed\n") @@ -372,6 +387,7 @@ def gen(args): sys.stderr.write("generating graphviz...\n") funcnums = parsenums(args.funcnum) + funcnames = parsenames(args.funcname) passnums = parsenums(args.passnum) with tempfile.TemporaryDirectory() as tmpdir: for i in range(0, len(ion['functions'])): @@ -379,6 +395,8 @@ def gen(args): if funcnums and i not in funcnums: continue + if funcnames and func['name'] not in funcnames: + continue gtl = buildOnlyFinalPass(func) if args.final else buildGraphs(func) @@ -446,10 +464,29 @@ def js_and_gen(args): gen(args) +def jittest_and_gen(args): + validate(args) + + testargs = args.remaining[1:] + testenv = os.environ.copy() + flags = (testenv['IONFLAGS'] if 'IONFLAGS' in testenv else 'logs').split(',') + if 'logs' not in flags: + flags.append('logs') + testenv['IONFLAGS'] = ','.join(flags) + jittest_path = os.path.join("js", "src", "jit-test", "jit_test.py") + cmd = " ".join([sys.executable, jittest_path, shutil.which("js"), "--one", *testargs]) + print("Command:", cmd) + subprocess.run(cmd, env=testenv, shell=True, check=True) + + args.input = '/tmp/ion.json' + gen(args) + + def add_main_arguments(parser): parser.add_argument('-o', '--outdir', help='The directory in which to store the output file(s).', default='.') parser.add_argument('-f', '--funcnum', help='Only operate on the specified function(s), by index. Multiple functions can be separated by commas, e.g. `1,5,234`.') + parser.add_argument('-n', '--funcname', help='Only operate on the specified function(s), by name. Multiple functions can be separated by commas, e.g. `foo,bar,baz`.') parser.add_argument('-p', '--passnum', help='Only operate on the specified pass(es), by index. Multiple passes can be separated by commas, e.g. `1,5,234`.') parser.add_argument('--format', help='The output file format (pdf by default). `pdf` will merge all the graphs for each function into a single PDF; all other formats will produce a single file per graph.', choices=['gv', 'pdf', 'pdfs', 'png', 'svg'], default='pdf') @@ -467,7 +504,10 @@ def main(): js = subparsers.add_parser('js', formatter_class=argparse.RawDescriptionHelpFormatter, help='Subcommand: Run js and iongraph together in one call.', description='Run js and iongraph together in one call. Arguments before the -- separator are for iongraph, while arguments after the -- will be passed to js.\n\nexample:\n iongraph js --funcnum 1 -- -m mymodule.mjs') - + jittest = subparsers.add_parser('jit-test', formatter_class=argparse.RawDescriptionHelpFormatter, + help='Subcommand: Run jit-test and iongraph together in one call.', + description='Run jit-test and iongraph together in one call. Arguments before the -- separator are for iongraph, while arguments after the -- will be passed to jit-test.\n\nexample:\n iongraph jit-test --funcnum 1 -- category/test.js') + add_main_arguments(parser) parser.add_argument('input', help='The JSON log file generated by IonMonkey. (Default: /tmp/ion.json)', nargs='?', default='/tmp/ion.json') @@ -478,6 +518,10 @@ def main(): js.add_argument('remaining', nargs=argparse.REMAINDER) js.set_defaults(func=js_and_gen) + add_main_arguments(jittest) + jittest.add_argument('remaining', nargs=argparse.REMAINDER) + jittest.set_defaults(func=jittest_and_gen) + args = parser.parse_args() args.func(args) diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/analyze.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/analyze.py index dd37991d410..961d2d36ad3 100755 --- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/analyze.py +++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/analyze.py @@ -13,13 +13,9 @@ import argparse import os import subprocess import sys +from shlex import quote from subprocess import Popen -try: - from shlex import quote -except ImportError: - from pipes import quote - def execfile(thefile, globals): exec(compile(open(thefile).read(), filename=thefile, mode="exec"), globals) @@ -266,7 +262,7 @@ def run_job(name, config): raise if final_status != 0: - raise Exception("job {} returned status {}".format(name, final_status)) + raise Exception(f"job {name} returned status {final_status}") def spawn_command(cmdspec, job, name, config): diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/annotations.js b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/annotations.js index 7aedc7edace..230e2eee7ae 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/annotations.js +++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/annotations.js @@ -12,7 +12,9 @@ var ignoreIndirectCalls = { "aMallocSizeOf" : true, "__conv" : true, "__convf" : true, - "callback_newtable" : true, + "callback_newtable": true, + "gLogAddRefFunc": true, + "gLogReleaseFunc": true, }; // Types that when constructed with no arguments, are "safe" values (they do @@ -126,6 +128,15 @@ function fieldCallCannotGC(csu, fullfield) return true; if (fullfield in ignoreCallees) return true; + + // Example: fmt::v11::detail::buffer.grow_ + if (/^fmt\b.*::buffer/.test(fullfield)) + return true; + // Example: fmt::v11::detail::custom_value.format + // Example: fmt::v11::detail::custom_value, wchar_t> >.format + if (/^fmt\b.*::custom_value<.*>/.test(fullfield)) + return true; + return false; } diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/explain.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/explain.py index 2fb45e07f93..60ed97e7d72 100755 --- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/explain.py +++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/explain.py @@ -150,7 +150,7 @@ def sourcelink(symbol=None, loc=None, range=None): def quoted_dict(d): - return {k: escape(v) for k, v in d.items() if type(v) == str} + return {k: escape(v) for k, v in d.items() if type(v) is str} num_hazards = 0 @@ -330,7 +330,7 @@ try: print_footer(html) -except IOError as e: +except OSError as e: print("Failed: %s" % str(e)) if args.verbose: diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mach_commands.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mach_commands.py index c2fc1980c91..4036d99ebaa 100644 --- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mach_commands.py +++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mach_commands.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -327,7 +325,7 @@ def gather_hazard_data(command_context, **kwargs): work_dir = get_work_dir(command_context, project, kwargs["work_dir"]) ensure_dir_exists(work_dir) - with open(os.path.join(work_dir, "defaults.py"), "wt") as fh: + with open(os.path.join(work_dir, "defaults.py"), "w") as fh: data = textwrap.dedent( """\ analysis_scriptdir = "{script_dir}" @@ -547,7 +545,7 @@ def annotated_source(filename, query): line0 = int(line0) line1 = int(line1) - fh = open(filename, "rt") + fh = open(filename) out = "
"
     for lineno, line in enumerate(fh, 1):
@@ -633,7 +631,7 @@ def view_hazards(command_context, project, haz_objdir, work_dir, port, serve_onl
                     if len(tops) > 0:
                         break  # Found a file underneath a root.
             else:
-                raise IOError("not found")
+                raise OSError("not found")
 
             html = annotated_source(fullpath, request.query)
             log("serve '{req}' -> 200 {path}")
@@ -642,7 +640,7 @@ def view_hazards(command_context, project, haz_objdir, work_dir, port, serve_onl
                 {"Content-type": "text/html", "Content-length": len(html)},
                 html,
             )
-        except (IOError, ValueError):
+        except (OSError, ValueError):
             log("serve '{req}' -> 404 {path}", logging.ERROR)
             return (
                 404,
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mozconfig.haz_shell b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mozconfig.haz_shell
index 68741f0454f..ab8dab6e730 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mozconfig.haz_shell
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/mozconfig.haz_shell
@@ -7,8 +7,6 @@
 # .
 
 ac_add_options --enable-ctypes
-ac_add_options --enable-optimize
-ac_add_options --disable-debug
 ac_add_options --enable-project=js
 ac_add_options --enable-nspr-build
 ac_add_options --disable-jemalloc
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/run-test.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/run-test.py
index b4835efec5e..9301fd8fbcc 100755
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/run-test.py
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/run-test.py
@@ -131,7 +131,7 @@ for path in tests:
     os.chdir(outdir)
     for xdb in glob("*.xdb"):
         os.unlink(xdb)
-    print("START TEST {}".format(name), flush=True)
+    print(f"START TEST {name}", flush=True)
     testpath = os.path.join(indir, "test.py")
     testscript = open(testpath).read()
     testcode = compile(testscript, testpath, "exec")
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/graph/test.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/graph/test.py
index f78500f200e..5589b784bfd 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/graph/test.py
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/graph/test.py
@@ -24,7 +24,7 @@ assert callgraph.calleeGraph[f][h]
 assert callgraph.calleeGraph[g][f]
 assert callgraph.calleeGraph[g][h]
 
-node = ["void n{}(int32)".format(i) for i in range(10)]
+node = [f"void n{i}(int32)" for i in range(10)]
 mnode = [callgraph.unmangledToMangled.get(f) for f in node]
 for src, dst in [
     (1, 2),
@@ -51,4 +51,4 @@ rroots = set(
 )
 assert len(set([node[1], node[2]]) & rroots) == 1
 assert len(set([node[4], node[5]]) & rroots) == 1
-assert len(rroots) == 4, "rroots = {}".format(rroots)  # n1, n4, f, self_recursive
+assert len(rroots) == 4, f"rroots = {rroots}"  # n1, n4, f, self_recursive
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/source.cpp b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/source.cpp
index fe991653af2..df5d96bf18b 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/source.cpp
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/source.cpp
@@ -69,6 +69,8 @@ void GC() {
   invisible();
 }
 
+extern Cell* makecell();
+
 extern void usecell(Cell*);
 
 extern bool flipcoin();
@@ -564,3 +566,11 @@ void aggr_init_safe() {
   GC();
   auto [ok, nogc] = pair_returning_function();
 }
+
+void stack_array() {
+  Cell* array[] = {makecell(), makecell()};
+  Cell* array2[] = {makecell(), makecell()};
+  GC();
+  usecell(array[1]);
+  // Never use array2.
+}
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/test.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/test.py
index c4e9549305e..587ece07581 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/test.py
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/hazards/test.py
@@ -119,3 +119,10 @@ assert "Cell* refptr_test10()" in haz_functions
 
 assert "void aggr_init_safe()" not in haz_functions
 assert "void aggr_init_unsafe()" in haz_functions
+
+# stack_array tests.
+
+assert "void stack_array()" in haz_functions
+haz_vars = byfunc["void stack_array()"]
+assert "array" in haz_vars
+assert "array2" not in haz_vars
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/testlib.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/testlib.py
index e08b236e4f3..7d7bf181512 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/testlib.py
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/testlib.py
@@ -38,7 +38,7 @@ def extract_unmangled(func):
     return func.split("$")[-1]
 
 
-class Test(object):
+class Test:
     def __init__(self, indir, outdir, cfg, verbose=0):
         self.indir = indir
         self.outdir = outdir
@@ -56,12 +56,7 @@ class Test(object):
         env["CCACHE_DISABLE"] = "1"
         if "-fexceptions" not in options and "-fno-exceptions" not in options:
             options += " -fno-exceptions"
-        cmd = "{CXX} -c {source} -O3 -std=c++17 -fplugin={sixgill} -fplugin-arg-xgill-mangle=1 {options}".format(  # NOQA: E501
-            source=self.infile(source),
-            CXX=self.cfg.cxx,
-            sixgill=self.cfg.sixgill_plugin,
-            options=options,
-        )
+        cmd = f"{self.cfg.cxx} -c {self.infile(source)} -O3 -std=c++17 -fplugin={self.cfg.sixgill_plugin} -fplugin-arg-xgill-mangle=1 {options}"
         if self.cfg.verbose > 0:
             print("Running %s" % cmd)
         subprocess.check_call(["sh", "-c", cmd])
@@ -89,12 +84,10 @@ class Test(object):
 
     def run_analysis_script(self, startPhase="gcTypes", upto=None):
         open("defaults.py", "w").write(
-            """\
+            f"""\
 analysis_scriptdir = '{scriptdir}'
-sixgill_bin = '{bindir}'
-""".format(
-                scriptdir=scriptdir, bindir=self.cfg.sixgill_bin
-            )
+sixgill_bin = '{self.cfg.sixgill_bin}'
+"""
         )
         cmd = [
             sys.executable,
@@ -118,7 +111,7 @@ sixgill_bin = '{bindir}'
 
     def load_text_file(self, filename, extract=lambda l: l):
         fullpath = os.path.join(self.outdir, filename)
-        values = (extract(line.strip()) for line in open(fullpath, "r"))
+        values = (extract(line.strip()) for line in open(fullpath))
         return list(filter(lambda _: _ is not None, values))
 
     def load_json_file(self, filename, reviver=None):
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/source.cpp b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/source.cpp
index c8a2d4aa731..2e962f81de7 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/source.cpp
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/source.cpp
@@ -156,12 +156,16 @@ void rvalue_ref_arg_not_ok(World::NS::Unsafe&& unsafe4) {
 
 void shared_ptr_hazard() {
   Cell* unsafe5 = f();
-  { auto p = std::make_shared(); }
+  {
+    auto p = std::make_shared();
+  }
   usecell(unsafe5);
 }
 
 void shared_ptr_no_hazard() {
   Cell* safe6 = f();
-  { auto p = std::make_shared(); }
+  {
+    auto p = std::make_shared();
+  }
   usecell(safe6);
 }
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/test.py b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/test.py
index 4a2b985abf1..0fa3750731d 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/test.py
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/types/test.py
@@ -1,6 +1,5 @@
 # flake8: noqa: F821
 
-from collections import defaultdict
 
 test.compile("source.cpp")
 test.run_analysis_script()
diff --git a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/virtual/source.cpp b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/virtual/source.cpp
index 980546f38d0..06b36b9ac12 100644
--- a/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/virtual/source.cpp
+++ b/src/third_party/mozjs/extract/js/src/devtools/rootAnalysis/t/virtual/source.cpp
@@ -138,7 +138,7 @@ class nsISupports {
 
 class nsIPrincipal : public nsISupports {
  public:
-  ~nsIPrincipal() override{};
+  ~nsIPrincipal() override {};
 };
 
 struct JSPrincipals {
diff --git a/src/third_party/mozjs/extract/js/src/ds/BitArray.h b/src/third_party/mozjs/extract/js/src/ds/BitArray.h
index f8a6aad4552..c9e88928e85 100644
--- a/src/third_party/mozjs/extract/js/src/ds/BitArray.h
+++ b/src/third_party/mozjs/extract/js/src/ds/BitArray.h
@@ -53,7 +53,7 @@ class BitArray {
   WordT map[numSlots];
 
  public:
-  constexpr BitArray() : map(){};
+  constexpr BitArray() : map() {};
 
   void clear(bool value) {
     memset(map, value ? 0xFF : 0, sizeof(map));
diff --git a/src/third_party/mozjs/extract/js/src/ds/Bitmap.h b/src/third_party/mozjs/extract/js/src/ds/Bitmap.h
index f564e2a3288..4b1c9d8d160 100644
--- a/src/third_party/mozjs/extract/js/src/ds/Bitmap.h
+++ b/src/third_party/mozjs/extract/js/src/ds/Bitmap.h
@@ -94,7 +94,7 @@ class SparseBitmap {
   // are in |other|.
   static size_t wordIntersectCount(size_t blockWord, const DenseBitmap& other) {
     long count = other.numWords() - blockWord;
-    return std::min((size_t)WordsInBlock, std::max(count, 0));
+    return static_cast(std::clamp(count, 0l, (long)WordsInBlock));
   }
 
   BitBlock& createBlock(Data::AddPtr p, size_t blockId,
diff --git a/src/third_party/mozjs/extract/js/src/ds/InlineTable.h b/src/third_party/mozjs/extract/js/src/ds/InlineTable.h
index fe6fd222957..0460f2d1d1d 100644
--- a/src/third_party/mozjs/extract/js/src/ds/InlineTable.h
+++ b/src/third_party/mozjs/extract/js/src/ds/InlineTable.h
@@ -8,6 +8,7 @@
 #define ds_InlineTable_h
 
 #include "mozilla/Maybe.h"
+#include "mozilla/Variant.h"
 
 #include 
 
@@ -18,37 +19,8 @@ namespace js {
 
 namespace detail {
 
-// The InlineTable below needs an abstract way of testing keys for
-// tombstone values, and to set a key in an entry to a tombstone.
-// This is provided by the KeyPolicy generic type argument, which
-// has a default implementation for pointers provided below.
-
-// A default implementation of a KeyPolicy for some types (only pointer
-// types for now).
-//
-// The `KeyPolicy` type parameter informs an InlineTable of how to
-// check for tombstone values and to set tombstone values within
-// the domain of key (entry).
-//
-// A `KeyPolicy` for some key type `K` must provide two static methods:
-//   static bool isTombstone(const K& key);
-//   static void setToTombstone(K& key);
-template 
-class DefaultKeyPolicy;
-
-template 
-class DefaultKeyPolicy {
-  DefaultKeyPolicy() = delete;
-  DefaultKeyPolicy(const T*&) = delete;
-
- public:
-  static bool isTombstone(T* const& ptr) { return ptr == nullptr; }
-  static void setToTombstone(T*& ptr) { ptr = nullptr; }
-};
-
 template 
+          typename HashPolicy, typename AllocPolicy, size_t InlineEntries>
 class InlineTable : private AllocPolicy {
  private:
   using TablePtr = typename Table::Ptr;
@@ -56,91 +28,115 @@ class InlineTable : private AllocPolicy {
   using TableRange = typename Table::Range;
   using Lookup = typename HashPolicy::Lookup;
 
-  size_t inlNext_;
-  size_t inlCount_;
-  InlineEntry inl_[InlineEntries];
-  Table table_;
-
+  struct InlineArray {
+    uint32_t count = 0;
+    InlineEntry inl[InlineEntries];
+  };
+  mozilla::Variant data_{InlineArray()};
 #ifdef DEBUG
-  template 
-  static bool keyNonZero(const Key& key) {
-    // Zero as tombstone means zero keys are invalid.
-    return !!key;
-  }
+  // Used to check that entries aren't added/removed while using Ptr/AddPtr or
+  // Range. Similar to HashTable::mMutationCount.
+  uint64_t mutationCount_ = 0;
 #endif
 
+#ifndef DEBUG
+  // If this assertion fails, you should probably increase InlineEntries because
+  // an extra inline entry could likely be added "for free".
+  static_assert(sizeof(InlineArray) + sizeof(InlineEntry) >= sizeof(Table),
+                "Space for additional inline elements in InlineTable?");
+#endif
+
+  InlineArray& inlineArray() { return data_.template as(); }
+  const InlineArray& inlineArray() const {
+    return data_.template as();
+  }
+  Table& table() { return data_.template as
%s
(); } + const Table& table() const { return data_.template as
(); } + InlineEntry* inlineStart() { MOZ_ASSERT(!usingTable()); - return inl_; + return inlineArray().inl; } const InlineEntry* inlineStart() const { MOZ_ASSERT(!usingTable()); - return inl_; + return inlineArray().inl; } InlineEntry* inlineEnd() { MOZ_ASSERT(!usingTable()); - return inl_ + inlNext_; + return inlineArray().inl + inlineArray().count; } const InlineEntry* inlineEnd() const { MOZ_ASSERT(!usingTable()); - return inl_ + inlNext_; + return inlineArray().inl + inlineArray().count; } - bool usingTable() const { return inlNext_ > InlineEntries; } + bool usingTable() const { return data_.template is
(); } + + void bumpMutationCount() { +#ifdef DEBUG + mutationCount_++; +#endif + } [[nodiscard]] bool switchToTable() { - MOZ_ASSERT(inlNext_ == InlineEntries); + MOZ_ASSERT(inlineArray().count == InlineEntries); - table_.clearAndCompact(); + Table table(*static_cast(this)); - InlineEntry* end = inlineEnd(); + // This is called before adding the next element, so reserve space for it + // too. + if (!table.reserve(InlineEntries + 1)) { + return false; + } + + InlineEntry* end = inlineStart() + InlineEntries; for (InlineEntry* it = inlineStart(); it != end; ++it) { - if (it->key && !it->moveTo(table_)) { + // Note: don't use putNewInfallible because hashing can be fallible too. + if (!it->moveTo(table)) { return false; } } - inlNext_ = InlineEntries + 1; - MOZ_ASSERT(table_.count() == inlCount_); + MOZ_ASSERT(table.count() == InlineEntries); + data_.template emplace
(std::move(table)); MOZ_ASSERT(usingTable()); + bumpMutationCount(); return true; } - [[nodiscard]] MOZ_NEVER_INLINE bool switchAndAdd(const InlineEntry& entry) { - if (!switchToTable()) { - return false; - } - - return entry.putNew(table_); - } - public: static const size_t SizeOfInlineEntries = sizeof(InlineEntry) * InlineEntries; explicit InlineTable(AllocPolicy a = AllocPolicy()) - : AllocPolicy(std::move(a)), inlNext_(0), inlCount_(0), table_(a) {} + : AllocPolicy(std::move(a)) {} class Ptr { friend class InlineTable; - protected: MOZ_INIT_OUTSIDE_CTOR Entry entry_; MOZ_INIT_OUTSIDE_CTOR TablePtr tablePtr_; MOZ_INIT_OUTSIDE_CTOR InlineEntry* inlPtr_; MOZ_INIT_OUTSIDE_CTOR bool isInlinePtr_; +#ifdef DEBUG + uint64_t mutationCount_ = 0xbadbad; +#endif - explicit Ptr(TablePtr p) - : entry_(p.found() ? &*p : nullptr), - tablePtr_(p), - isInlinePtr_(false) {} + Ptr(const InlineTable& table, TablePtr p) + : entry_(p.found() ? &*p : nullptr), tablePtr_(p), isInlinePtr_(false) { +#ifdef DEBUG + mutationCount_ = table.mutationCount_; +#endif + } - explicit Ptr(InlineEntry* inlineEntry) - : entry_(inlineEntry), inlPtr_(inlineEntry), isInlinePtr_(true) {} - - void operator==(const Ptr& other); + Ptr(const InlineTable& table, InlineEntry* inlineEntry) + : entry_(inlineEntry), inlPtr_(inlineEntry), isInlinePtr_(true) { +#ifdef DEBUG + mutationCount_ = table.mutationCount_; +#endif + } public: // Leaves Ptr uninitialized. @@ -159,19 +155,6 @@ class InlineTable : private AllocPolicy { explicit operator bool() const { return found(); } - bool operator==(const Ptr& other) const { - MOZ_ASSERT(found() && other.found()); - if (isInlinePtr_ != other.isInlinePtr_) { - return false; - } - if (isInlinePtr_) { - return inlPtr_ == other.inlPtr_; - } - return tablePtr_ == other.tablePtr_; - } - - bool operator!=(const Ptr& other) const { return !(*this == other); } - Entry& operator*() { MOZ_ASSERT(found()); return entry_; @@ -186,24 +169,34 @@ class InlineTable : private AllocPolicy { class AddPtr { friend class InlineTable; - protected: MOZ_INIT_OUTSIDE_CTOR Entry entry_; MOZ_INIT_OUTSIDE_CTOR TableAddPtr tableAddPtr_; MOZ_INIT_OUTSIDE_CTOR InlineEntry* inlAddPtr_; MOZ_INIT_OUTSIDE_CTOR bool isInlinePtr_; // Indicates whether inlAddPtr is a found result or an add pointer. MOZ_INIT_OUTSIDE_CTOR bool inlPtrFound_; +#ifdef DEBUG + uint64_t mutationCount_ = 0xbadbad; +#endif - AddPtr(InlineEntry* ptr, bool found) + AddPtr(const InlineTable& table, InlineEntry* ptr, bool found) : entry_(ptr), inlAddPtr_(ptr), isInlinePtr_(true), - inlPtrFound_(found) {} + inlPtrFound_(found) { +#ifdef DEBUG + mutationCount_ = table.mutationCount_; +#endif + } - explicit AddPtr(const TableAddPtr& p) + AddPtr(const InlineTable& table, const TableAddPtr& p) : entry_(p.found() ? &*p : nullptr), tableAddPtr_(p), - isInlinePtr_(false) {} + isInlinePtr_(false) { +#ifdef DEBUG + mutationCount_ = table.mutationCount_; +#endif + } public: AddPtr() = default; @@ -214,19 +207,6 @@ class InlineTable : private AllocPolicy { explicit operator bool() const { return found(); } - bool operator==(const AddPtr& other) const { - MOZ_ASSERT(found() && other.found()); - if (isInlinePtr_ != other.isInlinePtr_) { - return false; - } - if (isInlinePtr_) { - return inlAddPtr_ == other.inlAddPtr_; - } - return tableAddPtr_ == other.tableAddPtr_; - } - - bool operator!=(const AddPtr& other) const { return !(*this == other); } - Entry& operator*() { MOZ_ASSERT(found()); return entry_; @@ -238,59 +218,59 @@ class InlineTable : private AllocPolicy { } }; - size_t count() const { return usingTable() ? table_.count() : inlCount_; } + size_t count() const { + return usingTable() ? table().count() : inlineArray().count; + } - bool empty() const { return usingTable() ? table_.empty() : !inlCount_; } + bool empty() const { + return usingTable() ? table().empty() : !inlineArray().count; + } void clear() { - inlNext_ = 0; - inlCount_ = 0; + data_.template emplace(); + bumpMutationCount(); } MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& l) { - MOZ_ASSERT(keyNonZero(l)); - if (usingTable()) { - return Ptr(table_.lookup(l)); + return Ptr(*this, table().lookup(l)); } InlineEntry* end = inlineEnd(); for (InlineEntry* it = inlineStart(); it != end; ++it) { - if (it->key && HashPolicy::match(it->key, l)) { - return Ptr(it); + if (HashPolicy::match(it->key, l)) { + return Ptr(*this, it); } } - return Ptr(nullptr); + return Ptr(*this, nullptr); } MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& l) { - MOZ_ASSERT(keyNonZero(l)); - if (usingTable()) { - return AddPtr(table_.lookupForAdd(l)); + return AddPtr(*this, table().lookupForAdd(l)); } InlineEntry* end = inlineEnd(); for (InlineEntry* it = inlineStart(); it != end; ++it) { - if (it->key && HashPolicy::match(it->key, l)) { - return AddPtr(it, true); + if (HashPolicy::match(it->key, l)) { + return AddPtr(*this, it, true); } } // The add pointer that's returned here may indicate the limit entry of // the linear space, in which case the |add| operation will initialize // the table if necessary and add the entry there. - return AddPtr(inlineEnd(), false); + return AddPtr(*this, inlineEnd(), false); } template [[nodiscard]] MOZ_ALWAYS_INLINE bool add(AddPtr& p, KeyInput&& key, Args&&... args) { MOZ_ASSERT(!p); - MOZ_ASSERT(keyNonZero(key)); + MOZ_ASSERT(p.mutationCount_ == mutationCount_); if (p.isInlinePtr_) { InlineEntry* addPtr = p.inlAddPtr_; @@ -301,8 +281,12 @@ class InlineTable : private AllocPolicy { if (!switchToTable()) { return false; } - return table_.putNew(std::forward(key), - std::forward(args)...); + if (!table().putNew(std::forward(key), + std::forward(args)...)) { + return false; + } + bumpMutationCount(); + return true; } MOZ_ASSERT(!p.found()); @@ -313,26 +297,37 @@ class InlineTable : private AllocPolicy { } addPtr->update(std::forward(key), std::forward(args)...); - ++inlCount_; - ++inlNext_; + inlineArray().count++; + bumpMutationCount(); return true; } - return table_.add(p.tableAddPtr_, std::forward(key), - std::forward(args)...); + if (!table().add(p.tableAddPtr_, std::forward(key), + std::forward(args)...)) { + return false; + } + bumpMutationCount(); + return true; } void remove(Ptr& p) { MOZ_ASSERT(p); + MOZ_ASSERT(p.mutationCount_ == mutationCount_); if (p.isInlinePtr_) { - MOZ_ASSERT(inlCount_ > 0); - MOZ_ASSERT(!KeyPolicy::isTombstone(p.inlPtr_->key)); - KeyPolicy::setToTombstone(p.inlPtr_->key); - --inlCount_; - return; + InlineArray& arr = inlineArray(); + MOZ_ASSERT(arr.count > 0); + InlineEntry* last = &arr.inl[arr.count - 1]; + MOZ_ASSERT(p.inlPtr_ <= last); + if (p.inlPtr_ != last) { + // Removing an entry that's not the last one. Move the last entry. + *p.inlPtr_ = std::move(*last); + } + arr.count--; + } else { + MOZ_ASSERT(usingTable()); + table().remove(p.tablePtr_); } - MOZ_ASSERT(usingTable()); - table_.remove(p.tablePtr_); + bumpMutationCount(); } void remove(const Lookup& l) { @@ -344,32 +339,42 @@ class InlineTable : private AllocPolicy { class Range { friend class InlineTable; - protected: mozilla::Maybe tableRange_; // `Nothing` if `isInline_==true` InlineEntry* cur_; InlineEntry* end_; bool isInline_; +#ifdef DEBUG + const InlineTable* table_ = nullptr; + uint64_t mutationCount_ = 0xbadbad; +#endif - explicit Range(TableRange r) + Range(const InlineTable& table, TableRange r) : tableRange_(mozilla::Some(r)), cur_(nullptr), end_(nullptr), isInline_(false) { MOZ_ASSERT(!isInlineRange()); +#ifdef DEBUG + table_ = &table; + mutationCount_ = table.mutationCount_; +#endif } - Range(const InlineEntry* begin, const InlineEntry* end) + Range(const InlineTable& table, const InlineEntry* begin, + const InlineEntry* end) : tableRange_(mozilla::Nothing()), cur_(const_cast(begin)), end_(const_cast(end)), isInline_(true) { - advancePastNulls(cur_); MOZ_ASSERT(isInlineRange()); +#ifdef DEBUG + table_ = &table; + mutationCount_ = table.mutationCount_; +#endif } bool assertInlineRangeInvariants() const { MOZ_ASSERT(uintptr_t(cur_) <= uintptr_t(end_)); - MOZ_ASSERT_IF(cur_ != end_, !KeyPolicy::isTombstone(cur_->key)); return true; } @@ -378,27 +383,20 @@ class InlineTable : private AllocPolicy { return isInline_; } - void advancePastNulls(InlineEntry* begin) { - InlineEntry* newCur = begin; - while (newCur < end_ && KeyPolicy::isTombstone(newCur->key)) { - ++newCur; - } - MOZ_ASSERT(uintptr_t(newCur) <= uintptr_t(end_)); - cur_ = newCur; - } - void bumpCurPtr() { MOZ_ASSERT(isInlineRange()); - advancePastNulls(cur_ + 1); + cur_++; } public: bool empty() const { + MOZ_ASSERT(table_->mutationCount_ == mutationCount_); return isInlineRange() ? cur_ == end_ : tableRange_->empty(); } Entry front() { MOZ_ASSERT(!empty()); + MOZ_ASSERT(table_->mutationCount_ == mutationCount_); if (isInlineRange()) { return Entry(cur_); } @@ -407,6 +405,7 @@ class InlineTable : private AllocPolicy { void popFront() { MOZ_ASSERT(!empty()); + MOZ_ASSERT(table_->mutationCount_ == mutationCount_); if (isInlineRange()) { bumpCurPtr(); } else { @@ -416,8 +415,8 @@ class InlineTable : private AllocPolicy { }; Range all() const { - return usingTable() ? Range(table_.all()) - : Range(inlineStart(), inlineEnd()); + return usingTable() ? Range(*this, table().all()) + : Range(*this, inlineStart(), inlineEnd()); } }; @@ -425,14 +424,12 @@ class InlineTable : private AllocPolicy { // A map with InlineEntries number of entries kept inline in an array. // -// The Key type must be zeroable as zeros are used as tombstone keys. // The Value type must have a default constructor. // // The API is very much like HashMap's. template , - typename AllocPolicy = TempAllocPolicy, - typename KeyPolicy = detail::DefaultKeyPolicy> + typename AllocPolicy = TempAllocPolicy> class InlineMap { using Map = HashMap; @@ -484,7 +481,7 @@ class InlineMap { }; using Impl = detail::InlineTable; + AllocPolicy, InlineEntries>; Impl impl_; @@ -542,14 +539,12 @@ class InlineMap { // A set with InlineEntries number of entries kept inline in an array. // -// The T type must be zeroable as zeros are used as tombstone keys. // The T type must have a default constructor. // -// The API is very much like HashMap's. +// The API is very much like HashSet's. template , - typename AllocPolicy = TempAllocPolicy, - typename KeyPolicy = detail::DefaultKeyPolicy> + typename AllocPolicy = TempAllocPolicy> class InlineSet { using Set = HashSet; @@ -589,7 +584,7 @@ class InlineSet { }; using Impl = detail::InlineTable; + AllocPolicy, InlineEntries>; Impl impl_; diff --git a/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.cpp b/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.cpp index 8f73c04b946..da024012ef0 100644 --- a/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.cpp +++ b/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.cpp @@ -23,9 +23,9 @@ namespace js { namespace detail { /* static */ -UniquePtr BumpChunk::newWithCapacity(size_t size) { +UniquePtr BumpChunk::newWithCapacity(size_t size, arena_id_t arena) { MOZ_DIAGNOSTIC_ASSERT(size >= sizeof(BumpChunk)); - void* mem = js_malloc(size); + void* mem = js_arena_malloc(arena, size); if (!mem) { return nullptr; } @@ -185,7 +185,8 @@ LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n, : NextSize(defaultChunkSize_, smallAllocsSize_); // Create a new BumpChunk, and allocate space for it. - UniqueBumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize); + UniqueBumpChunk result = + detail::BumpChunk::newWithCapacity(chunkSize, arena_); if (!result) { return nullptr; } @@ -370,6 +371,13 @@ void LifoAlloc::transferFrom(LifoAlloc* other) { MOZ_ASSERT(!markCount); MOZ_ASSERT(!other->markCount); + // This assertion is not really necessary, and if it is getting in your way + // please feel free to just delete it, but it should generally point you in + // a decent direction. LifoAllocs are entirely capable of having a mix of + // allocations from different arenas, this is just a heuristic that we + // expect will yield better performance. + MOZ_ASSERT(arena_ == other->arena_); + // Transferred chunks are not counted as part of |smallAllocsSize| as this // could introduce bias in the |NextSize| heuristics, leading to // over-allocations in *this* LifoAlloc. As well, to avoid interference with diff --git a/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.h b/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.h index 872a10c86f0..44e760bcbb1 100644 --- a/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.h +++ b/src/third_party/mozjs/extract/js/src/ds/LifoAlloc.h @@ -516,7 +516,7 @@ class BumpChunk : public SingleLinkedListElement { // This function is the only way to allocate and construct a chunk. It // returns a UniquePtr to the newly allocated chunk. The size given as // argument includes the space needed for the header of the chunk. - static UniquePtr newWithCapacity(size_t size); + static UniquePtr newWithCapacity(size_t size, arena_id_t arena); // Report allocation. size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { @@ -699,6 +699,17 @@ class LifoAlloc { // now-unused, or transferred (which followed their own growth patterns). size_t smallAllocsSize_; + // Arena to use for the allocations from this LifoAlloc. This is typically + // MallocArena for main-thread-focused LifoAllocs and BackgroundMallocArena + // for background-thread-focused LifoAllocs. + // If you are unsure at the time of authorship whether this LifoAlloc will be + // mostly on or mostly off the main thread, just take a guess, and that + // will be fine. There should be no serious consequences for getting this + // wrong unless your system is very hot and makes heavy use of its LifoAlloc. + // In that case, run both options through a try run of Speedometer 3 or + // whatever is most current and pick whichever performs better. + arena_id_t arena_; + #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) bool fallibleScope_; #endif @@ -766,8 +777,9 @@ class LifoAlloc { [[nodiscard]] bool ensureUnusedApproximateColdPath(size_t n, size_t total); public: - explicit LifoAlloc(size_t defaultChunkSize) - : peakSize_(0) + LifoAlloc(size_t defaultChunkSize, arena_id_t arena) + : peakSize_(0), + arena_(arena) #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) , fallibleScope_(true) @@ -800,9 +812,8 @@ class LifoAlloc { // Frees all held memory. void freeAll(); - static const unsigned HUGE_ALLOCATION = 50 * 1024 * 1024; void freeAllIfHugeAndUnused() { - if (markCount == 0 && curSize_ > HUGE_ALLOCATION) { + if (markCount == 0 && isHuge()) { freeAll(); } } @@ -988,6 +999,9 @@ class LifoAlloc { return empty && oversize_.empty(); } + static const unsigned HUGE_ALLOCATION = 50 * 1024 * 1024; + bool isHuge() const { return curSize_ > HUGE_ALLOCATION; } + // Return the number of bytes remaining to allocate in the current chunk. // e.g. How many bytes we can allocate before needing a new block. size_t availableInCurrentChunk() const { diff --git a/src/third_party/mozjs/extract/js/src/ds/OrderedHashTable.h b/src/third_party/mozjs/extract/js/src/ds/OrderedHashTable.h deleted file mode 100644 index 9dd3e216d3e..00000000000 --- a/src/third_party/mozjs/extract/js/src/ds/OrderedHashTable.h +++ /dev/null @@ -1,1150 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef ds_OrderedHashTable_h -#define ds_OrderedHashTable_h - -/* - * Define two collection templates, js::OrderedHashMap and js::OrderedHashSet. - * They are like js::HashMap and js::HashSet except that: - * - * - Iterating over an Ordered hash table visits the entries in the order in - * which they were inserted. This means that unlike a HashMap, the behavior - * of an OrderedHashMap is deterministic (as long as the HashPolicy methods - * are effect-free and consistent); the hashing is a pure performance - * optimization. - * - * - Range objects over Ordered tables remain valid even when entries are - * added or removed or the table is resized. (However in the case of - * removing entries, note the warning on class Range below.) - * - * - The API is a little different, so it's not a drop-in replacement. - * In particular, the hash policy is a little different. - * Also, the Ordered templates lack the Ptr and AddPtr types. - * - * Hash policies - * - * See the comment about "Hash policy" in HashTable.h for general features that - * hash policy classes must provide. Hash policies for OrderedHashMaps and Sets - * differ in that the hash() method takes an extra argument: - * static js::HashNumber hash(Lookup, const HashCodeScrambler&); - * They must additionally provide a distinguished "empty" key value and the - * following static member functions: - * bool isEmpty(const Key&); - * void makeEmpty(Key*); - */ - -#include "mozilla/HashFunctions.h" -#include "mozilla/Likely.h" -#include "mozilla/Maybe.h" -#include "mozilla/MemoryReporting.h" -#include "mozilla/TemplateLib.h" - -#include -#include - -#include "gc/Barrier.h" -#include "js/GCPolicyAPI.h" -#include "js/HashTable.h" - -class JSTracer; - -namespace js { - -namespace detail { - -/* - * detail::OrderedHashTable is the underlying data structure used to implement - * both OrderedHashMap and OrderedHashSet. Programs should use one of those two - * templates rather than OrderedHashTable. - */ -template -class OrderedHashTable { - public: - using Key = typename Ops::KeyType; - using Lookup = typename Ops::Lookup; - - struct Data { - T element; - Data* chain; - - Data(const T& e, Data* c) : element(e), chain(c) {} - Data(T&& e, Data* c) : element(std::move(e)), chain(c) {} - }; - - class Range; - friend class Range; - - private: - Data** hashTable; // hash table (has hashBuckets() elements) - Data* data; // data vector, an array of Data objects - // data[0:dataLength] are constructed - uint32_t dataLength; // number of constructed elements in data - uint32_t dataCapacity; // size of data, in elements - uint32_t liveCount; // dataLength less empty (removed) entries - uint32_t hashShift; // multiplicative hash shift - - // List of all live Ranges on this table in malloc memory. Populated when - // ranges are created. - Range* ranges; - - // List of all live Ranges on this table in the GC nursery. Populated when - // ranges are created. This is cleared at the start of minor GC and rebuilt - // when ranges are moved. - Range* nurseryRanges; - - AllocPolicy alloc; - mozilla::HashCodeScrambler hcs; // don't reveal pointer hash codes - - // TODO: This should be templated on a functor type and receive lambda - // arguments but this causes problems for the hazard analysis builds. See - // bug 1398213. - template - void forEachRange(uint32_t arg = 0) { - Range* next; - for (Range* r = ranges; r; r = next) { - next = r->next; - f(r, arg); - } - for (Range* r = nurseryRanges; r; r = next) { - next = r->next; - f(r, arg); - } - } - - public: - OrderedHashTable(AllocPolicy ap, mozilla::HashCodeScrambler hcs) - : hashTable(nullptr), - data(nullptr), - dataLength(0), - dataCapacity(0), - liveCount(0), - hashShift(0), - ranges(nullptr), - nurseryRanges(nullptr), - alloc(std::move(ap)), - hcs(hcs) {} - - [[nodiscard]] bool init() { - MOZ_ASSERT(!hashTable, "init must be called at most once"); - - uint32_t buckets = initialBuckets(); - Data** tableAlloc = alloc.template pod_malloc(buckets); - if (!tableAlloc) { - return false; - } - for (uint32_t i = 0; i < buckets; i++) { - tableAlloc[i] = nullptr; - } - - uint32_t capacity = uint32_t(buckets * fillFactor()); - Data* dataAlloc = alloc.template pod_malloc(capacity); - if (!dataAlloc) { - alloc.free_(tableAlloc, buckets); - return false; - } - - // clear() requires that members are assigned only after all allocation - // has succeeded, and that this->ranges is left untouched. - hashTable = tableAlloc; - data = dataAlloc; - dataLength = 0; - dataCapacity = capacity; - liveCount = 0; - hashShift = js::kHashNumberBits - initialBucketsLog2(); - MOZ_ASSERT(hashBuckets() == buckets); - return true; - } - - ~OrderedHashTable() { - forEachRange(); - if (hashTable) { - // |hashBuckets()| isn't valid when |hashTable| hasn't been created. - alloc.free_(hashTable, hashBuckets()); - } - freeData(data, dataLength, dataCapacity); - } - - size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - size_t size = 0; - if (hashTable) { - size += mallocSizeOf(hashTable); - } - if (data) { - size += mallocSizeOf(data); - } - return size; - } - - /* Return the number of elements in the table. */ - uint32_t count() const { return liveCount; } - - /* True if any element matches l. */ - bool has(const Lookup& l) const { return lookup(l) != nullptr; } - - /* Return a pointer to the element, if any, that matches l, or nullptr. */ - T* get(const Lookup& l) { - Data* e = lookup(l, prepareHash(l)); - return e ? &e->element : nullptr; - } - - /* Return a pointer to the element, if any, that matches l, or nullptr. */ - const T* get(const Lookup& l) const { - return const_cast(this)->get(l); - } - - /* - * If the table already contains an entry that matches |element|, - * replace that entry with |element|. Otherwise add a new entry. - * - * On success, return true, whether there was already a matching element or - * not. On allocation failure, return false. If this returns false, it - * means the element was not added to the table. - */ - template - [[nodiscard]] bool put(ElementInput&& element) { - HashNumber h = prepareHash(Ops::getKey(element)); - if (Data* e = lookup(Ops::getKey(element), h)) { - e->element = std::forward(element); - return true; - } - - if (dataLength == dataCapacity && !rehashOnFull()) { - return false; - } - - auto [entry, chain] = addEntry(h); - new (entry) Data(std::forward(element), chain); - return true; - } - - /* - * If the table contains an entry that matches |element| then return a pointer - * to it, otherwise add a new entry. - */ - template - [[nodiscard]] T* getOrAdd(ElementInput&& element) { - HashNumber h = prepareHash(Ops::getKey(element)); - if (Data* e = lookup(Ops::getKey(element), h)) { - return &e->element; - } - - if (dataLength == dataCapacity && !rehashOnFull()) { - return nullptr; - } - - auto [entry, chain] = addEntry(h); - new (entry) Data(std::forward(element), chain); - return &entry->element; - } - - /* - * If the table contains an element matching l, remove it and set *foundp - * to true. Otherwise set *foundp to false. - * - * Return true on success, false if we tried to shrink the table and hit an - * allocation failure. Even if this returns false, *foundp is set correctly - * and the matching element was removed. Shrinking is an optimization and - * it's OK for it to fail. - */ - bool remove(const Lookup& l, bool* foundp) { - // Note: This could be optimized so that removing the last entry, - // data[dataLength - 1], decrements dataLength. LIFO use cases would - // benefit. - - // If a matching entry exists, empty it. - Data* e = lookup(l, prepareHash(l)); - if (e == nullptr) { - *foundp = false; - return true; - } - - *foundp = true; - return remove(e); - } - - bool remove(Data* e) { - MOZ_ASSERT(uint32_t(e - data) < dataCapacity); - - liveCount--; - Ops::makeEmpty(&e->element); - - // Update active Ranges. - uint32_t pos = e - data; - forEachRange<&Range::onRemove>(pos); - - // If many entries have been removed, try to shrink the table. - if (hashBuckets() > initialBuckets() && - liveCount < dataLength * minDataFill()) { - if (!rehash(hashShift + 1)) { - return false; - } - } - - return true; - } - - /* - * Remove all entries. - * - * Returns false on OOM, leaving the OrderedHashTable and any live Ranges - * in the old state. - * - * The effect on live Ranges is the same as removing all entries; in - * particular, those Ranges are still live and will see any entries added - * after a successful clear(). - */ - [[nodiscard]] bool clear() { - if (dataLength != 0) { - Data** oldHashTable = hashTable; - Data* oldData = data; - uint32_t oldHashBuckets = hashBuckets(); - uint32_t oldDataLength = dataLength; - uint32_t oldDataCapacity = dataCapacity; - - hashTable = nullptr; - if (!init()) { - // init() only mutates members on success; see comment above. - hashTable = oldHashTable; - return false; - } - - alloc.free_(oldHashTable, oldHashBuckets); - freeData(oldData, oldDataLength, oldDataCapacity); - forEachRange<&Range::onClear>(); - } - - MOZ_ASSERT(hashTable); - MOZ_ASSERT(data); - MOZ_ASSERT(dataLength == 0); - MOZ_ASSERT(liveCount == 0); - return true; - } - - /* - * Ranges are used to iterate over OrderedHashTables. - * - * Suppose 'Map' is some instance of OrderedHashMap, and 'map' is a Map. - * Then you can walk all the key-value pairs like this: - * - * for (Map::Range r = map.all(); !r.empty(); r.popFront()) { - * Map::Entry& pair = r.front(); - * ... do something with pair ... - * } - * - * Ranges remain valid for the lifetime of the OrderedHashTable, even if - * entries are added or removed or the table is resized. Don't do anything - * to a Range, except destroy it, after the OrderedHashTable has been - * destroyed. (We support destroying the two objects in either order to - * humor the GC, bless its nondeterministic heart.) - * - * Warning: The behavior when the current front() entry is removed from the - * table is subtly different from js::HashTable<>::Enum::removeFront()! - * HashTable::Enum doesn't skip any entries when you removeFront() and then - * popFront(). OrderedHashTable::Range does! (This is useful for using a - * Range to implement JS Map.prototype.iterator.) - * - * The workaround is to call popFront() as soon as possible, - * before there's any possibility of modifying the table: - * - * for (Map::Range r = map.all(); !r.empty(); ) { - * Key key = r.front().key; // this won't modify map - * Value val = r.front().value; // this won't modify map - * r.popFront(); - * // ...do things that might modify map... - * } - */ - class Range { - friend class OrderedHashTable; - - // Cannot be a reference since we need to be able to do - // |offsetof(Range, ht)|. - OrderedHashTable* ht; - - /* The index of front() within ht->data. */ - uint32_t i; - - /* - * The number of nonempty entries in ht->data to the left of front(). - * This is used when the table is resized or compacted. - */ - uint32_t count; - - /* - * Links in the doubly-linked list of active Ranges on ht. - * - * prevp points to the previous Range's .next field; - * or to ht->ranges if this is the first Range in the list. - * next points to the next Range; - * or nullptr if this is the last Range in the list. - * - * Invariant: *prevp == this. - */ - Range** prevp; - Range* next; - - /* - * Create a Range over all the entries in ht. - * (This is private on purpose. End users must use ht->all().) - */ - Range(OrderedHashTable* ht, Range** listp) - : ht(ht), i(0), count(0), prevp(listp), next(*listp) { - *prevp = this; - if (next) { - next->prevp = &next; - } - seek(); - MOZ_ASSERT(valid()); - } - - public: - Range(const Range& other, bool inNursery) - : ht(other.ht), - i(other.i), - count(other.count), - prevp(inNursery ? &ht->nurseryRanges : &ht->ranges), - next(*prevp) { - *prevp = this; - if (next) { - next->prevp = &next; - } - MOZ_ASSERT(valid()); - } - - ~Range() { - if (!prevp) { - // Head of removed nursery ranges. - return; - } - *prevp = next; - if (next) { - next->prevp = prevp; - } - } - - protected: - // Prohibit copy assignment. - Range& operator=(const Range& other) = delete; - - void seek() { - while (i < ht->dataLength && - Ops::isEmpty(Ops::getKey(ht->data[i].element))) { - i++; - } - } - - /* - * The hash table calls this when an entry is removed. - * j is the index of the removed entry. - */ - void onRemove(uint32_t j) { - MOZ_ASSERT(valid()); - if (j < i) { - count--; - } - if (j == i) { - seek(); - } - } - - /* - * The hash table calls this when the table is resized or compacted. - * Since |count| is the number of nonempty entries to the left of - * front(), discarding the empty entries will not affect count, and it - * will make i and count equal. - */ - void onCompact() { - MOZ_ASSERT(valid()); - i = count; - } - - /* The hash table calls this when cleared. */ - void onClear() { - MOZ_ASSERT(valid()); - i = count = 0; - } - -#ifdef DEBUG - bool valid() const { return /* *prevp == this && */ next != this; } -#endif - - void onTableDestroyed() { - MOZ_ASSERT(valid()); - prevp = &next; - next = this; - MOZ_ASSERT(!valid()); - } - - public: - bool empty() const { - MOZ_ASSERT(valid()); - return i >= ht->dataLength; - } - - /* - * Return the first element in the range. This must not be called if - * this->empty(). - * - * Warning: Removing an entry from the table also removes it from any - * live Ranges, and a Range can become empty that way, rendering - * front() invalid. If in doubt, check empty() before calling front(). - */ - const T& front() const { - MOZ_ASSERT(valid()); - MOZ_ASSERT(!empty()); - return ht->data[i].element; - } - - /* - * Remove the first element from this range. - * This must not be called if this->empty(). - * - * Warning: Removing an entry from the table also removes it from any - * live Ranges, and a Range can become empty that way, rendering - * popFront() invalid. If in doubt, check empty() before calling - * popFront(). - */ - void popFront() { - MOZ_ASSERT(valid()); - MOZ_ASSERT(!empty()); - MOZ_ASSERT(!Ops::isEmpty(Ops::getKey(ht->data[i].element))); - count++; - i++; - seek(); - } - - static size_t offsetOfHashTable() { return offsetof(Range, ht); } - static size_t offsetOfI() { return offsetof(Range, i); } - static size_t offsetOfCount() { return offsetof(Range, count); } - static size_t offsetOfPrevP() { return offsetof(Range, prevp); } - static size_t offsetOfNext() { return offsetof(Range, next); } - - static void onTableDestroyed(Range* range, uint32_t arg) { - range->onTableDestroyed(); - } - static void onRemove(Range* range, uint32_t arg) { range->onRemove(arg); } - static void onClear(Range* range, uint32_t arg) { range->onClear(); } - static void onCompact(Range* range, uint32_t arg) { range->onCompact(); } - }; - - class MutableRange : public Range { - MutableRange(OrderedHashTable* ht, Range** listp) : Range(ht, listp) {} - friend class OrderedHashTable; - - public: - T& front() { - MOZ_ASSERT(this->valid()); - MOZ_ASSERT(!this->empty()); - return this->ht->data[this->i].element; - } - - void rekeyFront(const Key& k) { - MOZ_ASSERT(this->valid()); - this->ht->rekey(&this->ht->data[this->i], k); - } - }; - - Range all() const { - // Range operates on a mutable table but its interface does not permit - // modification of the contents of the table. - auto* self = const_cast(this); - return Range(self, &self->ranges); - } - MutableRange mutableAll() { return MutableRange(this, &ranges); } - - void trace(JSTracer* trc) { - for (uint32_t i = 0; i < dataLength; i++) { - if (!Ops::isEmpty(Ops::getKey(data[i].element))) { - Ops::trace(trc, this, i, data[i].element); - } - } - } - - // For use by the implementation of Ops::trace. - template - void traceKey(JSTracer* trc, uint32_t index, Key& key) { - MOZ_ASSERT(index < dataLength); - using MutableKey = std::remove_const_t; - using UnbarrieredKey = typename RemoveBarrier::Type; - UnbarrieredKey newKey = key; - JS::GCPolicy::trace(trc, &newKey, "OrderedHashMap key"); - if (newKey != key) { - rekey(&data[index], newKey); - } - } - template - void traceValue(JSTracer* trc, Value& value) { - JS::GCPolicy::trace(trc, &value, "OrderedHashMap value"); - } - - /* - * Allocate a new Range, possibly in nursery memory. The buffer must be - * large enough to hold a Range object. - */ - Range* createRange(void* buffer, bool inNursery) const { - auto* self = const_cast(this); - Range** listp = inNursery ? &self->nurseryRanges : &self->ranges; - new (buffer) Range(self, listp); - return static_cast(buffer); - } - - void destroyNurseryRanges() { - if (nurseryRanges) { - nurseryRanges->prevp = nullptr; - } - nurseryRanges = nullptr; - } - -#ifdef DEBUG - bool hasNurseryRanges() const { return nurseryRanges; } -#endif - - /* - * Change the value of the given key. - * - * This calls Ops::hash on both the current key and the new key. - * Ops::hash on the current key must return the same hash code as - * when the entry was added to the table. - */ - void rekeyOneEntry(const Key& current, const Key& newKey, const T& element) { - if (current == newKey) { - return; - } - - HashNumber currentHash = prepareHash(current); - Data* entry = lookup(current, currentHash); - MOZ_ASSERT(entry); - - HashNumber oldHash = currentHash >> hashShift; - HashNumber newHash = prepareHash(newKey) >> hashShift; - - entry->element = element; - - // Remove this entry from its old hash chain. (If this crashes - // reading nullptr, it would mean we did not find this entry on - // the hash chain where we expected it. That probably means the - // key's hash code changed since it was inserted, breaking the - // hash code invariant.) - Data** ep = &hashTable[oldHash]; - while (*ep != entry) { - ep = &(*ep)->chain; - } - *ep = entry->chain; - - // Add it to the new hash chain. We could just insert it at the - // beginning of the chain. Instead, we do a bit of work to - // preserve the invariant that hash chains always go in reverse - // insertion order (descending memory order). No code currently - // depends on this invariant, so it's fine to kill it if - // needed. - ep = &hashTable[newHash]; - while (*ep && *ep > entry) { - ep = &(*ep)->chain; - } - entry->chain = *ep; - *ep = entry; - } - - static size_t offsetOfDataLength() { - return offsetof(OrderedHashTable, dataLength); - } - static size_t offsetOfData() { return offsetof(OrderedHashTable, data); } - static constexpr size_t offsetOfHashTable() { - return offsetof(OrderedHashTable, hashTable); - } - static constexpr size_t offsetOfHashShift() { - return offsetof(OrderedHashTable, hashShift); - } - static constexpr size_t offsetOfLiveCount() { - return offsetof(OrderedHashTable, liveCount); - } - static constexpr size_t offsetOfDataElement() { - static_assert(offsetof(Data, element) == 0, - "RangeFront and RangePopFront depend on offsetof(Data, " - "element) being 0"); - return offsetof(Data, element); - } - static constexpr size_t offsetOfDataChain() { return offsetof(Data, chain); } - static constexpr size_t sizeofData() { return sizeof(Data); } - - static constexpr size_t offsetOfHcsK0() { - return offsetof(OrderedHashTable, hcs) + - mozilla::HashCodeScrambler::offsetOfMK0(); - } - static constexpr size_t offsetOfHcsK1() { - return offsetof(OrderedHashTable, hcs) + - mozilla::HashCodeScrambler::offsetOfMK1(); - } - - private: - /* Logarithm base 2 of the number of buckets in the hash table initially. */ - static uint32_t initialBucketsLog2() { return 1; } - static uint32_t initialBuckets() { return 1 << initialBucketsLog2(); } - - /* - * The maximum load factor (mean number of entries per bucket). - * It is an invariant that - * dataCapacity == floor(hashBuckets() * fillFactor()). - * - * The fill factor should be between 2 and 4, and it should be chosen so that - * the fill factor times sizeof(Data) is close to but <= a power of 2. - * This fixed fill factor was chosen to make the size of the data - * array, in bytes, close to a power of two when sizeof(T) is 16. - */ - static constexpr double fillFactor() { return 8.0 / 3.0; } - - /* - * The minimum permitted value of (liveCount / dataLength). - * If that ratio drops below this value, we shrink the table. - */ - static double minDataFill() { return 0.25; } - - public: - HashNumber prepareHash(const Lookup& l) const { - return mozilla::ScrambleHashCode(Ops::hash(l, hcs)); - } - - private: - /* The size of hashTable, in elements. Always a power of two. */ - uint32_t hashBuckets() const { - return 1 << (js::kHashNumberBits - hashShift); - } - - static void destroyData(Data* data, uint32_t length) { - for (Data* p = data + length; p != data;) { - (--p)->~Data(); - } - } - - void freeData(Data* data, uint32_t length, uint32_t capacity) { - destroyData(data, length); - alloc.free_(data, capacity); - } - - Data* lookup(const Lookup& l, HashNumber h) { - for (Data* e = hashTable[h >> hashShift]; e; e = e->chain) { - if (Ops::match(Ops::getKey(e->element), l)) { - return e; - } - } - return nullptr; - } - - const Data* lookup(const Lookup& l) const { - return const_cast(this)->lookup(l, prepareHash(l)); - } - - std::tuple addEntry(HashNumber hash) { - MOZ_ASSERT(dataLength < dataCapacity); - hash >>= hashShift; - liveCount++; - Data* entry = &data[dataLength++]; - Data* chain = hashTable[hash]; - hashTable[hash] = entry; - return std::make_tuple(entry, chain); - } - - /* This is called after rehashing the table. */ - void compacted() { - // If we had any empty entries, compacting may have moved live entries - // to the left within |data|. Notify all live Ranges of the change. - forEachRange<&Range::onCompact>(); - } - - /* Compact the entries in |data| and rehash them. */ - void rehashInPlace() { - for (uint32_t i = 0, N = hashBuckets(); i < N; i++) { - hashTable[i] = nullptr; - } - Data* wp = data; - Data* end = data + dataLength; - for (Data* rp = data; rp != end; rp++) { - if (!Ops::isEmpty(Ops::getKey(rp->element))) { - HashNumber h = prepareHash(Ops::getKey(rp->element)) >> hashShift; - if (rp != wp) { - wp->element = std::move(rp->element); - } - wp->chain = hashTable[h]; - hashTable[h] = wp; - wp++; - } - } - MOZ_ASSERT(wp == data + liveCount); - - while (wp != end) { - (--end)->~Data(); - } - dataLength = liveCount; - compacted(); - } - - [[nodiscard]] bool rehashOnFull() { - MOZ_ASSERT(dataLength == dataCapacity); - - // If the hashTable is more than 1/4 deleted data, simply rehash in - // place to free up some space. Otherwise, grow the table. - uint32_t newHashShift = - liveCount >= dataCapacity * 0.75 ? hashShift - 1 : hashShift; - return rehash(newHashShift); - } - - /* - * Grow, shrink, or compact both |hashTable| and |data|. - * - * On success, this returns true, dataLength == liveCount, and there are no - * empty elements in data[0:dataLength]. On allocation failure, this - * leaves everything as it was and returns false. - */ - [[nodiscard]] bool rehash(uint32_t newHashShift) { - // If the size of the table is not changing, rehash in place to avoid - // allocating memory. - if (newHashShift == hashShift) { - rehashInPlace(); - return true; - } - - // Ensure the new capacity fits into INT32_MAX. - constexpr size_t maxCapacityLog2 = - mozilla::tl::FloorLog2::value; - static_assert(maxCapacityLog2 < kHashNumberBits); - - // Fail if |(js::kHashNumberBits - newHashShift) > maxCapacityLog2|. - // - // Reorder |kHashNumberBits| so both constants are on the right-hand side. - if (MOZ_UNLIKELY(newHashShift < (js::kHashNumberBits - maxCapacityLog2))) { - alloc.reportAllocOverflow(); - return false; - } - - size_t newHashBuckets = size_t(1) << (js::kHashNumberBits - newHashShift); - Data** newHashTable = alloc.template pod_malloc(newHashBuckets); - if (!newHashTable) { - return false; - } - for (uint32_t i = 0; i < newHashBuckets; i++) { - newHashTable[i] = nullptr; - } - - uint32_t newCapacity = uint32_t(newHashBuckets * fillFactor()); - Data* newData = alloc.template pod_malloc(newCapacity); - if (!newData) { - alloc.free_(newHashTable, newHashBuckets); - return false; - } - - Data* wp = newData; - Data* end = data + dataLength; - for (Data* p = data; p != end; p++) { - if (!Ops::isEmpty(Ops::getKey(p->element))) { - HashNumber h = prepareHash(Ops::getKey(p->element)) >> newHashShift; - new (wp) Data(std::move(p->element), newHashTable[h]); - newHashTable[h] = wp; - wp++; - } - } - MOZ_ASSERT(wp == newData + liveCount); - - alloc.free_(hashTable, hashBuckets()); - freeData(data, dataLength, dataCapacity); - - hashTable = newHashTable; - data = newData; - dataLength = liveCount; - dataCapacity = newCapacity; - hashShift = newHashShift; - MOZ_ASSERT(hashBuckets() == newHashBuckets); - - compacted(); - return true; - } - - // Change the key of the front entry. - // - // This calls Ops::hash on both the current key and the new key. Ops::hash on - // the current key must return the same hash code as when the entry was added - // to the table. - void rekey(Data* entry, const Key& k) { - HashNumber oldHash = prepareHash(Ops::getKey(entry->element)) >> hashShift; - HashNumber newHash = prepareHash(k) >> hashShift; - Ops::setKey(entry->element, k); - if (newHash != oldHash) { - // Remove this entry from its old hash chain. (If this crashes reading - // nullptr, it would mean we did not find this entry on the hash chain - // where we expected it. That probably means the key's hash code changed - // since it was inserted, breaking the hash code invariant.) - Data** ep = &hashTable[oldHash]; - while (*ep != entry) { - ep = &(*ep)->chain; - } - *ep = entry->chain; - - // Add it to the new hash chain. We could just insert it at the beginning - // of the chain. Instead, we do a bit of work to preserve the invariant - // that hash chains always go in reverse insertion order (descending - // memory order). No code currently depends on this invariant, so it's - // fine to kill it if needed. - ep = &hashTable[newHash]; - while (*ep && *ep > entry) { - ep = &(*ep)->chain; - } - entry->chain = *ep; - *ep = entry; - } - } - - // Not copyable. - OrderedHashTable& operator=(const OrderedHashTable&) = delete; - OrderedHashTable(const OrderedHashTable&) = delete; -}; - -} // namespace detail - -template -class OrderedHashMap { - public: - class Entry { - template - friend class detail::OrderedHashTable; - void operator=(const Entry& rhs) { - const_cast(key) = rhs.key; - value = rhs.value; - } - - void operator=(Entry&& rhs) { - MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); - const_cast(key) = std::move(rhs.key); - value = std::move(rhs.value); - } - - public: - Entry() : key(), value() {} - explicit Entry(const Key& k) : key(k), value() {} - template - Entry(const Key& k, V&& v) : key(k), value(std::forward(v)) {} - Entry(Entry&& rhs) : key(std::move(rhs.key)), value(std::move(rhs.value)) {} - - const Key key; - Value value; - - static size_t offsetOfKey() { return offsetof(Entry, key); } - static size_t offsetOfValue() { return offsetof(Entry, value); } - }; - - private: - struct MapOps; - using Impl = detail::OrderedHashTable; - - struct MapOps : OrderedHashPolicy { - using KeyType = Key; - static void makeEmpty(Entry* e) { - OrderedHashPolicy::makeEmpty(const_cast(&e->key)); - - // Clear the value. Destroying it is another possibility, but that - // would complicate class Entry considerably. - e->value = Value(); - } - static const Key& getKey(const Entry& e) { return e.key; } - static void setKey(Entry& e, const Key& k) { const_cast(e.key) = k; } - static void trace(JSTracer* trc, Impl* table, uint32_t index, - Entry& entry) { - table->traceKey(trc, index, entry.key); - table->traceValue(trc, entry.value); - } - }; - - Impl impl; - - public: - using Lookup = typename Impl::Lookup; - using Range = typename Impl::Range; - using MutableRange = typename Impl::MutableRange; - - OrderedHashMap(AllocPolicy ap, mozilla::HashCodeScrambler hcs) - : impl(std::move(ap), hcs) {} - [[nodiscard]] bool init() { return impl.init(); } - uint32_t count() const { return impl.count(); } - bool has(const Lookup& key) const { return impl.has(key); } - Range all() const { return impl.all(); } - MutableRange mutableAll() { return impl.mutableAll(); } - const Entry* get(const Lookup& key) const { return impl.get(key); } - Entry* get(const Lookup& key) { return impl.get(key); } - bool remove(const Lookup& key, bool* foundp) { - return impl.remove(key, foundp); - } - // Remove an entry returned by get(). - bool remove(Entry* entry) { - static_assert(offsetof(typename Impl::Data, element) == 0); - auto* data = reinterpret_cast(entry); - return impl.remove(data); - } - [[nodiscard]] bool clear() { return impl.clear(); } - - template - [[nodiscard]] bool put(K&& key, V&& value) { - return impl.put(Entry(std::forward(key), std::forward(value))); - } - - template - [[nodiscard]] Entry* getOrAdd(K&& key) { - return impl.getOrAdd(Entry(std::forward(key))); - } - - HashNumber hash(const Lookup& key) const { return impl.prepareHash(key); } - - template - mozilla::Maybe rekeyOneEntry(Lookup& current, GetNewKey&& getNewKey) { - // TODO: This is inefficient because we also look up the entry in - // impl.rekeyOneEntry below. - const Entry* e = get(current); - if (!e) { - return mozilla::Nothing(); - } - - Key newKey = getNewKey(current); - impl.rekeyOneEntry(current, newKey, Entry(newKey, e->value)); - return mozilla::Some(newKey); - } - - Range* createRange(void* buffer, bool inNursery) const { - return impl.createRange(buffer, inNursery); - } - - void destroyNurseryRanges() { impl.destroyNurseryRanges(); } -#ifdef DEBUG - bool hasNurseryRanges() const { return impl.hasNurseryRanges(); } -#endif - - void trace(JSTracer* trc) { impl.trace(trc); } - - static size_t offsetOfEntryKey() { return Entry::offsetOfKey(); } - static size_t offsetOfImplDataLength() { return Impl::offsetOfDataLength(); } - static size_t offsetOfImplData() { return Impl::offsetOfData(); } - static constexpr size_t offsetOfImplHashTable() { - return Impl::offsetOfHashTable(); - } - static constexpr size_t offsetOfImplHashShift() { - return Impl::offsetOfHashShift(); - } - static constexpr size_t offsetOfImplLiveCount() { - return Impl::offsetOfLiveCount(); - } - static constexpr size_t offsetOfImplDataElement() { - return Impl::offsetOfDataElement(); - } - static constexpr size_t offsetOfImplDataChain() { - return Impl::offsetOfDataChain(); - } - static constexpr size_t sizeofImplData() { return Impl::sizeofData(); } - - static constexpr size_t offsetOfImplHcsK0() { return Impl::offsetOfHcsK0(); } - static constexpr size_t offsetOfImplHcsK1() { return Impl::offsetOfHcsK1(); } - - size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return impl.sizeOfExcludingThis(mallocSizeOf); - } - size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); - } -}; - -template -class OrderedHashSet { - private: - struct SetOps; - using Impl = detail::OrderedHashTable; - - struct SetOps : OrderedHashPolicy { - using KeyType = const T; - static const T& getKey(const T& v) { return v; } - static void setKey(const T& e, const T& v) { const_cast(e) = v; } - static void trace(JSTracer* trc, Impl* table, uint32_t index, T& entry) { - table->traceKey(trc, index, entry); - } - }; - - Impl impl; - - public: - using Lookup = typename Impl::Lookup; - using Range = typename Impl::Range; - using MutableRange = typename Impl::MutableRange; - - explicit OrderedHashSet(AllocPolicy ap, mozilla::HashCodeScrambler hcs) - : impl(std::move(ap), hcs) {} - [[nodiscard]] bool init() { return impl.init(); } - uint32_t count() const { return impl.count(); } - bool has(const Lookup& value) const { return impl.has(value); } - Range all() const { return impl.all(); } - MutableRange mutableAll() { return impl.mutableAll(); } - template - [[nodiscard]] bool put(Input&& value) { - return impl.put(std::forward(value)); - } - bool remove(const Lookup& value, bool* foundp) { - return impl.remove(value, foundp); - } - [[nodiscard]] bool clear() { return impl.clear(); } - - HashNumber hash(const Lookup& value) const { return impl.prepareHash(value); } - - template - mozilla::Maybe rekeyOneEntry(Lookup& current, GetNewKey&& getNewKey) { - // TODO: This is inefficient because we also look up the entry in - // impl.rekeyOneEntry below. - if (!has(current)) { - return mozilla::Nothing(); - } - - T newKey = getNewKey(current); - impl.rekeyOneEntry(current, newKey, newKey); - return mozilla::Some(newKey); - } - - Range* createRange(void* buffer, bool inNursery) const { - return impl.createRange(buffer, inNursery); - } - - void destroyNurseryRanges() { impl.destroyNurseryRanges(); } -#ifdef DEBUG - bool hasNurseryRanges() const { return impl.hasNurseryRanges(); } -#endif - - void trace(JSTracer* trc) { impl.trace(trc); } - - static size_t offsetOfEntryKey() { return 0; } - static size_t offsetOfImplDataLength() { return Impl::offsetOfDataLength(); } - static size_t offsetOfImplData() { return Impl::offsetOfData(); } - static constexpr size_t offsetOfImplHashTable() { - return Impl::offsetOfHashTable(); - } - static constexpr size_t offsetOfImplHashShift() { - return Impl::offsetOfHashShift(); - } - static constexpr size_t offsetOfImplLiveCount() { - return Impl::offsetOfLiveCount(); - } - static constexpr size_t offsetOfImplDataElement() { - return Impl::offsetOfDataElement(); - } - static constexpr size_t offsetOfImplDataChain() { - return Impl::offsetOfDataChain(); - } - static constexpr size_t sizeofImplData() { return Impl::sizeofData(); } - - static constexpr size_t offsetOfImplHcsK0() { return Impl::offsetOfHcsK0(); } - static constexpr size_t offsetOfImplHcsK1() { return Impl::offsetOfHcsK1(); } - - size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return impl.sizeOfExcludingThis(mallocSizeOf); - } - size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); - } -}; - -} // namespace js - -#endif /* ds_OrderedHashTable_h */ diff --git a/src/third_party/mozjs/extract/js/src/ds/PriorityQueue.h b/src/third_party/mozjs/extract/js/src/ds/PriorityQueue.h index 9ed4788a5b5..c1944f4d9f1 100644 --- a/src/third_party/mozjs/extract/js/src/ds/PriorityQueue.h +++ b/src/third_party/mozjs/extract/js/src/ds/PriorityQueue.h @@ -16,8 +16,8 @@ namespace js { * Inserting elements and removing the highest priority one are both O(log n). * * Template parameters are the same as for Vector, with the addition that P - * must have a static priority(const T&) method which returns higher numbers - * for higher priority elements. + * must have a static higherPriority(const T& a, const T& b) method which + * returns true if |a| has a higher priority than |b|. */ template @@ -37,6 +37,27 @@ class PriorityQueue { bool empty() const { return heap.empty(); } + // highest and popHighest are used to enforce necessary move semantics for + // working with UniquePtrs in a queue, and should be used together Example: + // UniquePtr<...> x = std::move(queue.highest()); + // queue.popHighest(); + T& highest() { + MOZ_ASSERT(!empty()); + return heap[0]; + } + + void popHighest() { + if (heap.length() == 1) { + heap.popBack(); + return; + } + std::swap(heap[0], heap.back()); + heap.popBack(); + siftDown(0); + } + + // removeHighest cannot be used with UniquePtrs, and should only be used for + // other datatypes. T removeHighest() { T highest = heap[0]; T last = heap.popCopy(); @@ -47,16 +68,16 @@ class PriorityQueue { return highest; } - [[nodiscard]] bool insert(const T& v) { - if (!heap.append(v)) { + [[nodiscard]] bool insert(T&& v) { + if (!heap.append(std::move(v))) { return false; } siftUp(heap.length() - 1); return true; } - void infallibleInsert(const T& v) { - heap.infallibleAppend(v); + void infallibleInsert(T&& v) { + heap.infallibleAppend(std::move(v)); siftUp(heap.length() - 1); } @@ -81,15 +102,15 @@ class PriorityQueue { if (left < heap.length()) { if (right < heap.length()) { - if (P::priority(heap[n]) < P::priority(heap[right]) && - P::priority(heap[left]) < P::priority(heap[right])) { + if (P::higherPriority(heap[right], heap[n]) && + P::higherPriority(heap[right], heap[left])) { swap(n, right); n = right; continue; } } - if (P::priority(heap[n]) < P::priority(heap[left])) { + if (P::higherPriority(heap[left], heap[n])) { swap(n, left); n = left; continue; @@ -104,7 +125,7 @@ class PriorityQueue { while (n > 0) { size_t parent = (n - 1) / 2; - if (P::priority(heap[parent]) > P::priority(heap[n])) { + if (P::higherPriority(heap[parent], heap[n])) { break; } @@ -113,11 +134,7 @@ class PriorityQueue { } } - void swap(size_t a, size_t b) { - T tmp = heap[a]; - heap[a] = heap[b]; - heap[b] = tmp; - } + void swap(size_t a, size_t b) { std::swap(heap[a], heap[b]); } }; } /* namespace js */ diff --git a/src/third_party/mozjs/extract/js/src/ds/SinglyLinkedList.h b/src/third_party/mozjs/extract/js/src/ds/SinglyLinkedList.h index dab9261d1cc..6928a0f9218 100644 --- a/src/third_party/mozjs/extract/js/src/ds/SinglyLinkedList.h +++ b/src/third_party/mozjs/extract/js/src/ds/SinglyLinkedList.h @@ -18,21 +18,33 @@ namespace js { * the list itself. * * Requires T has field |T::next| for the link pointer. + * + * The list only stores a pointer to the last element. Since the list is + * circular, that provides access to the first element and allows insertion at + * the start and end of the list. */ template class SinglyLinkedList { T* last_ = nullptr; public: + // Create an empty list. SinglyLinkedList() { static_assert(std::is_same_v, "SinglyLinkedList requires T has a next field of type T*"); MOZ_ASSERT(isEmpty()); } - SinglyLinkedList(T* first, T* last) : last_(last) { - MOZ_ASSERT(!last_->next); - last_->next = first; + // Create a list from an existing non-circular linked list from |first| to + // |last|. + SinglyLinkedList(T* first, T* last) { + MOZ_ASSERT(first); + MOZ_ASSERT(last); + MOZ_ASSERT(!last->next); + last->next = first; + last_ = last; + checkContains(first); + checkContains(last); } // It's not possible for elements to be present in more than one list, so copy @@ -41,12 +53,15 @@ class SinglyLinkedList { SinglyLinkedList& operator=(const SinglyLinkedList& other) = delete; SinglyLinkedList(SinglyLinkedList&& other) { + MOZ_ASSERT(&other != this); std::swap(last_, other.last_); MOZ_ASSERT(other.isEmpty()); } SinglyLinkedList& operator=(SinglyLinkedList&& other) { + MOZ_ASSERT(&other != this); MOZ_ASSERT(isEmpty()); - return *new (this) SinglyLinkedList(std::move(other)); + std::swap(last_, other.last_); + return *this; } ~SinglyLinkedList() { MOZ_ASSERT(isEmpty()); } @@ -98,15 +113,18 @@ class SinglyLinkedList { void moveFrontToBack() { MOZ_ASSERT(!isEmpty()); last_ = last_->next; + MOZ_ASSERT(!isEmpty()); } void append(SinglyLinkedList&& other) { + MOZ_ASSERT(&other != this); + if (other.isEmpty()) { return; } if (isEmpty()) { - new (this) SinglyLinkedList(std::move(other)); + *this = std::move(other); return; } @@ -117,14 +135,80 @@ class SinglyLinkedList { other.last_ = nullptr; } + void prepend(SinglyLinkedList&& other) { + MOZ_ASSERT(&other != this); + + if (other.isEmpty()) { + return; + } + + if (isEmpty()) { + *this = std::move(other); + return; + } + + T* firstElement = first(); + last()->next = other.first(); + other.last()->next = firstElement; + other.last_ = nullptr; + } + + // Remove all elements between |fromExclusive| and |toInclusive|. Return the + // removed list segment as a non-circular linked list. + // + // The fact that the first parameter is exclusive is a requirement for + // implementing this in constant time for a singly linked list. + T* removeRange(T* fromExclusive, T* toInclusive) { + MOZ_ASSERT(fromExclusive); + MOZ_ASSERT(toInclusive); + MOZ_ASSERT(fromExclusive != toInclusive); + MOZ_ASSERT(!isEmpty()); + +#ifdef DEBUG + size_t index = 0; + size_t fromIndex = SIZE_MAX; + size_t toIndex = SIZE_MAX; + for (T* element = first(); element; element = element->next) { + if (element == fromExclusive) { + fromIndex = index; + } + if (element == toInclusive) { + toIndex = index; + } + index++; + if (index == 100) { + break; + } + } + if (index < 100) { + MOZ_ASSERT(fromIndex != SIZE_MAX); + MOZ_ASSERT(toIndex != SIZE_MAX); + MOZ_ASSERT(fromIndex < toIndex); + } +#endif + + T* result = fromExclusive->next; + fromExclusive->next = toInclusive->next; + toInclusive->next = nullptr; + + if (last_ == toInclusive) { + last_ = fromExclusive; + } + + return result; + } + // template class Iterator { T* i = nullptr; T* last = nullptr; public: + Iterator() = default; explicit Iterator(const SinglyLinkedList& list) : i(list.first()), last(list.last()) {} + Iterator(const SinglyLinkedList& list, T* first) + : i(first), last(list.last()) {} bool done() const { return !i; } void next() { MOZ_ASSERT(!done()); @@ -141,6 +225,27 @@ class SinglyLinkedList { Iterator iter() const { return Iterator(*this); } + Iterator iterFrom(T* fromInclusive) { + checkContains(fromInclusive); + return Iterator(*this, fromInclusive); + } + + void checkContains(T* element) { +#ifdef DEBUG + size_t i = 0; + for (Iterator iter(*this); !iter.done(); iter.next()) { + if (iter.get() == element) { + return; // Found. + } + i++; + if (i == 100) { + return; // Limit time spent checking. + } + } + MOZ_CRASH("Element not found"); +#endif + } + // Extracts a non-circular linked list and clears this object. T* release() { if (isEmpty()) { diff --git a/src/third_party/mozjs/extract/js/src/ds/SlimLinkedList.h b/src/third_party/mozjs/extract/js/src/ds/SlimLinkedList.h new file mode 100644 index 00000000000..30be1ab9a9c --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/ds/SlimLinkedList.h @@ -0,0 +1,439 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * The classes SlimLinkedList and SlimLinkedListElement provide a + * type-safe doubly-linked list class which uses one word for the list and two + * words for each element (for comparison mozilla::LinkedList uses three words + * for the list and for each element due to padding). + * + * This aims to be a replacement for mozilla::LinkedList although the interface + * is not identical. In particular most actions are implemented as methods on + * the list itself as opposed to the element. + * + * Private element inheritance is not supported; clients must publicly derive + * from LinkedListElement. + */ + +#ifndef ds_SlimLinkedList_h +#define ds_SlimLinkedList_h + +#include "mozilla/Assertions.h" + +#include +#include + +namespace js { + +template +class SlimLinkedListElement; + +template +class SlimLinkedList; + +template +class SlimLinkedListElement { + using ElementPtr = T*; + using ConstElementPtr = const T*; + + // Tag bit used to indicate the start/end of the list. The tag is set on the + // prev_ pointer of the first node and the next_ pointer of the last node in + // the list. + static constexpr uintptr_t EndTag = 1; + + uintptr_t next_ = 0; + uintptr_t prev_ = 0; + + friend class js::SlimLinkedList; + + static uintptr_t UntaggedPtr(ElementPtr ptr) { + MOZ_ASSERT((uintptr_t(ptr) & EndTag) == 0); + return uintptr_t(ptr); + } + static uintptr_t GetTag(uintptr_t taggedPtr) { return taggedPtr & EndTag; } + static ElementPtr GetPtr(uintptr_t taggedPtr) { + return reinterpret_cast(uintptr_t(taggedPtr) & ~EndTag); + } + static ConstElementPtr GetConstPtr(uintptr_t taggedPtr) { + return reinterpret_cast(uintptr_t(taggedPtr) & ~EndTag); + } + + static void LinkElements(ElementPtr a, ElementPtr b, uintptr_t maybeTag = 0) { + MOZ_ASSERT((maybeTag & ~EndTag) == 0); + a->next_ = UntaggedPtr(b) | maybeTag; + b->prev_ = UntaggedPtr(a) | maybeTag; + } + + public: + SlimLinkedListElement() = default; + + ~SlimLinkedListElement() { MOZ_ASSERT(!isInList()); } + + SlimLinkedListElement(const SlimLinkedListElement& other) = delete; + SlimLinkedListElement& operator=(const SlimLinkedListElement& other) = + delete; + + // Don't allow moving elements that are part of a list. + SlimLinkedListElement(SlimLinkedListElement&& other) { + MOZ_ASSERT(this != &other); + MOZ_ASSERT(!isInList()); + MOZ_ASSERT(!other.isInList()); + } + SlimLinkedListElement& operator=(SlimLinkedListElement&& other) { + MOZ_ASSERT(this != &other); + MOZ_ASSERT(!isInList()); + MOZ_ASSERT(!other.isInList()); + return *this; + } + + bool isInList() const { + MOZ_ASSERT(bool(next_) == bool(prev_)); + return next_; + } + + bool isLast() const { + MOZ_ASSERT(isInList()); + return GetTag(next_); + } + + bool isFirst() const { + MOZ_ASSERT(isInList()); + return GetTag(prev_); + } + + ElementPtr getNext() { return isLast() ? nullptr : getNextUnchecked(); } + ConstElementPtr getNext() const { + return isLast() ? nullptr : getNextUnchecked(); + } + + ElementPtr getPrev() { return isFirst() ? nullptr : getPrevUnchecked(); } + ConstElementPtr getPrev() const { + return isFirst() ? nullptr : getPrevUnchecked(); + } + + private: + ElementPtr getNextUnchecked() { return GetPtr(next_); } + ConstElementPtr getNextUnchecked() const { return GetConstPtr(next_); }; + ElementPtr getPrevUnchecked() { return GetPtr(prev_); } + ConstElementPtr getPrevUnchecked() const { return GetConstPtr(prev_); }; + + ElementPtr thisElement() { return static_cast(this); } + + void makeSingleton() { + MOZ_ASSERT(!isInList()); + LinkElements(thisElement(), thisElement(), EndTag); + } + + void insertAfter(ElementPtr newElement) { + insertListAfter(newElement, newElement); + } + + /* + * Insert the list of elements from |listFirst| to |listLast| between |this| + * and the next element |next|. Any tag goes between |listLast| and |next|. + */ + void insertListAfter(ElementPtr listFirst, ElementPtr listLast) { + MOZ_ASSERT(isInList()); + MOZ_ASSERT_IF(listFirst != listLast, + listFirst->getPrevUnchecked() == listLast); + MOZ_ASSERT_IF(listFirst != listLast, + listLast->getNextUnchecked() == listFirst); + + ElementPtr next = GetPtr(next_); + uintptr_t tag = GetTag(next_); + + LinkElements(thisElement(), listFirst); + LinkElements(listLast, next, tag); + } + + void insertBefore(ElementPtr newElement) { + insertListBefore(newElement, newElement); + } + + /* + * Insert the list of elements from |listFirst| to |listLast| between the + * previous element |prev| and |this|. Any tag goes between |prev| and + * |listFirst|. + */ + void insertListBefore(ElementPtr listFirst, ElementPtr listLast) { + MOZ_ASSERT(isInList()); + MOZ_ASSERT_IF(listFirst != listLast, + listFirst->getPrevUnchecked() == listLast); + MOZ_ASSERT_IF(listFirst != listLast, + listLast->getNextUnchecked() == listFirst); + + ElementPtr prev = GetPtr(prev_); + uintptr_t tag = GetTag(prev_); + + LinkElements(prev, listFirst, tag); + LinkElements(listLast, thisElement()); + } + + /* + * Remove element |this| from its containing list. + */ + void remove() { + MOZ_ASSERT(isInList()); + + ElementPtr prev = GetPtr(prev_); + ElementPtr next = GetPtr(next_); + uintptr_t tag = GetTag(prev_) | GetTag(next_); + + LinkElements(prev, next, tag); + + next_ = 0; + prev_ = 0; + } +}; + +template +class SlimLinkedList { + using ElementPtr = T*; + using ConstElementPtr = const T*; + + ElementPtr first_ = nullptr; + + public: + template + class Iterator { + Type current_; + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + + explicit Iterator(Type current) : current_(current) {} + + Type operator*() const { return current_; } + + const Iterator& operator++() { + current_ = current_->getNext(); + return *this; + } + + bool operator==(const Iterator& other) const { + return current_ == other.current_; + } + bool operator!=(const Iterator& other) const { return !(*this == other); } + }; + + SlimLinkedList() = default; + + SlimLinkedList(const SlimLinkedList& other) = delete; + SlimLinkedList& operator=(const SlimLinkedList& other) = delete; + + SlimLinkedList(SlimLinkedList&& other) { + MOZ_ASSERT(this != &other); + MOZ_ASSERT(isEmpty()); + std::swap(first_, other.first_); + } + SlimLinkedList& operator=(SlimLinkedList&& other) { + MOZ_ASSERT(this != &other); + MOZ_ASSERT(isEmpty()); + std::swap(first_, other.first_); + return *this; + } + + ~SlimLinkedList() { MOZ_ASSERT(isEmpty()); } + + /* + * Add |newElement| to the front of the list. + */ + void pushFront(ElementPtr newElement) { + if (isEmpty()) { + newElement->makeSingleton(); + } else { + first_->insertBefore(newElement); + } + first_ = newElement; + } + + /* + * Add |newElement| to the back of the list. + */ + void pushBack(ElementPtr newElement) { + if (isEmpty()) { + newElement->makeSingleton(); + first_ = newElement; + return; + } + + getLast()->insertAfter(newElement); + } + + /* + * Move all elements from list |other| to the end of this list. |other| is + * left empty. + */ + void append(SlimLinkedList&& other) { + MOZ_ASSERT(this != &other); + if (other.isEmpty()) { + return; + } + + if (isEmpty()) { + *this = std::move(other); + return; + } + + getLast()->insertListAfter(other.getFirst(), other.getLast()); + other.first_ = nullptr; + } + + /* + * Move all elements from list |other| to the start of this list. |other| is + * left empty. + */ + void prepend(SlimLinkedList&& other) { + MOZ_ASSERT(this != &other); + if (other.isEmpty()) { + return; + } + + if (isEmpty()) { + *this = std::move(other); + return; + } + + getFirst()->insertListBefore(other.getFirst(), other.getLast()); + first_ = other.first_; + other.first_ = nullptr; + } + + /* + * Get the first element of the list, or nullptr if the list is empty. + */ + ElementPtr getFirst() { return first_; } + ConstElementPtr getFirst() const { return first_; } + + /* + * Get the last element of the list, or nullptr if the list is empty. + */ + ElementPtr getLast() { + return isEmpty() ? nullptr : first_->getPrevUnchecked(); + } + ConstElementPtr getLast() const { + return isEmpty() ? nullptr : first_->getPrevUnchecked(); + } + + /* + * Get and remove the first element of the list. If the list is empty, return + * nullptr. + */ + ElementPtr popFirst() { + if (isEmpty()) { + return nullptr; + } + + ElementPtr result = first_; + first_ = result->getNext(); + result->remove(); + return result; + } + + /* + * Get and remove the last element of the list. If the list is empty, return + * nullptr. + */ + ElementPtr popLast() { + if (isEmpty()) { + return nullptr; + } + + ElementPtr result = getLast(); + if (result == first_) { + first_ = nullptr; + } + result->remove(); + return result; + } + + /* + * Return true if the list is empty, or false otherwise. + */ + bool isEmpty() const { return !first_; } + + /* + * Returns whether the given element is in the list. + */ + bool contains(ConstElementPtr aElm) const { + return std::find(begin(), end(), aElm) != end(); + } + + /* + * Remove |element| from this list. + */ + void remove(ElementPtr element) { + checkContains(element); + if (element == first_) { + first_ = element->getNext(); + } + element->remove(); + } + + void checkContains(ElementPtr element) { +#ifdef DEBUG + size_t i = 0; + for (const auto& e : *this) { + if (e == element) { + return; // Found. + } + if (i == 100) { + return; // Limit time spent checking. + } + } + MOZ_CRASH("Element not found"); +#endif + } + + /* + * Remove all the elements from the list. + * + * This runs in time linear to the list's length, because we have to mark + * each element as not in the list. + */ + void clear() { + while (popFirst()) { + } + } + + /* + * Remove all the elements from the list, calling |func| on each one first. On + * return the list is empty. + */ + template + void drain(F&& func) { + while (ElementPtr element = popFirst()) { + func(element); + } + } + + /** + * Return the length of elements in the list. + */ + size_t length() const { return std::distance(begin(), end()); } + + /* + * Allow range-based iteration: + * + * for (MyElementPtr* elt : myList) { ... } + */ + Iterator begin() { return Iterator(getFirst()); } + Iterator begin() const { + return Iterator(getFirst()); + } + Iterator end() { return Iterator(nullptr); } + Iterator end() const { + return Iterator(nullptr); + } +}; + +} /* namespace js */ + +#endif /* ds_SlimLinkedList_h */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/AsyncEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/AsyncEmitter.h index 778f708c4fe..69d19994e0b 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/AsyncEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/AsyncEmitter.h @@ -157,7 +157,7 @@ class MOZ_STACK_CLASS AsyncEmitter { [[nodiscard]] bool emitFinalYield(); public: - explicit AsyncEmitter(BytecodeEmitter* bce) : bce_(bce){}; + explicit AsyncEmitter(BytecodeEmitter* bce) : bce_(bce) {}; [[nodiscard]] bool prepareForParamsWithoutExpressionOrDestructuring(); [[nodiscard]] bool prepareForParamsWithExpressionOrDestructuring(); diff --git a/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.cpp b/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.cpp index 9ecf8fb2d35..3c5ac3b615e 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.cpp @@ -16,9 +16,6 @@ #include "frontend/BytecodeEmitter.h" #include "frontend/CompilationStencil.h" // ExtensibleCompilationStencil, ExtraBindingInfoVector, CompilationInput, CompilationGCOutput #include "frontend/EitherParser.h" -#ifdef JS_ENABLE_SMOOSH -# include "frontend/Frontend2.h" // Smoosh -#endif #include "frontend/FrontendContext.h" // AutoReportFrontendContext #include "frontend/ModuleSharedContext.h" #include "frontend/ParserAtom.h" // ParserAtomsTable, TaggedParserAtomIndex @@ -28,7 +25,9 @@ #include "js/AllocPolicy.h" // js::SystemAllocPolicy, ReportOutOfMemory #include "js/CharacterEncoding.h" // JS_EncodeStringToUTF8 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin +#include "js/EnvironmentChain.h" // JS::SupportUnscopables #include "js/ErrorReport.h" // JS_ReportErrorASCII +#include "js/experimental/CompileScript.h" // JS::CompileGlobalScriptToStencil, JS::CompileModuleScriptToStencil #include "js/experimental/JSStencil.h" #include "js/GCVector.h" // JS::StackGCVector #include "js/Id.h" // JS::PropertyKey @@ -48,7 +47,6 @@ #include "vm/ModuleBuilder.h" // js::ModuleBuilder #include "vm/NativeObject.h" // NativeDefineDataProperty #include "vm/PlainObject.h" // NewPlainObjectWithProto -#include "vm/StencilCache.h" // DelazificationCache #include "vm/Time.h" // AutoIncrementalTimer #include "wasm/AsmJS.h" @@ -201,53 +199,101 @@ class MOZ_STACK_CLASS ScriptCompiler : public SourceAwareCompiler { [[nodiscard]] bool popupateExtraBindingsFields(GlobalSharedContext* globalsc); }; -#ifdef JS_ENABLE_SMOOSH -[[nodiscard]] static bool TrySmoosh( - JSContext* cx, FrontendContext* fc, CompilationInput& input, - JS::SourceText& srcBuf, - UniquePtr& stencilOut) { - MOZ_ASSERT(!stencilOut); - - if (!cx->options().trySmoosh()) { - return true; +static already_AddRefed CreateInitialStencilAndDelazifications( + FrontendContext* fc, CompilationStencil* initial) { + RefPtr stencils = + fc->getAllocator()->new_(); + if (!stencils) { + return nullptr; } - - JSRuntime* rt = cx->runtime(); - if (!Smoosh::tryCompileGlobalScriptToExtensibleStencil(cx, fc, input, srcBuf, - stencilOut)) { - return false; + if (!stencils->init(fc, initial)) { + return nullptr; } + return stencils.forget(); +} - if (cx->options().trackNotImplemented()) { - if (stencilOut) { - rt->parserWatcherFile.put("1"); - } else { - rt->parserWatcherFile.put("0"); +using BytecodeCompilerOutput = + mozilla::Variant, CompilationGCOutput*>; + +static bool ConvertGlobalScriptStencilMaybeInstantiate( + JSContext* maybeCx, FrontendContext* fc, CompilationInput& input, + ExtensibleCompilationStencil&& extensibleStencil, + CompilationStencil** initialStencilOut, + InitialStencilAndDelazifications** stencilsOut, + CompilationGCOutput* gcOutput) { + RefPtr initialStencil; + if (input.options.populateDelazificationCache() || initialStencilOut || + stencilsOut) { + auto extensibleStencilOnHeap = + fc->getAllocator()->make_unique( + std::move(extensibleStencil)); + if (!extensibleStencilOnHeap) { + return false; + } + + initialStencil = fc->getAllocator()->new_( + std::move(extensibleStencilOnHeap)); + if (!initialStencil) { + return false; + } + + if (initialStencilOut) { + *initialStencilOut = initialStencil.get(); + (*initialStencilOut)->AddRef(); } } - if (!stencilOut) { - fprintf(stderr, "Falling back!\n"); - return true; + RefPtr stencils; + if (input.options.populateDelazificationCache() || stencilsOut) { + stencils = CreateInitialStencilAndDelazifications(fc, initialStencil.get()); + if (!stencils) { + return false; + } + + if (stencilsOut) { + *stencilsOut = stencils.get(); + (*stencilsOut)->AddRef(); + } } - return stencilOut->source->assignSource(fc, input.options, srcBuf); -} + if (input.options.populateDelazificationCache()) { + // NOTE: Delazification can be triggered from off-thread compilation. + StartOffThreadDelazification(maybeCx, input.options, stencils.get()); + + // When we are trying to validate whether on-demand delazification + // generate the same stencil as concurrent delazification, we want to + // parse everything eagerly off-thread ahead of re-parsing everything on + // demand, to compare the outcome. + // + // This option works only from main-thread compilation, to avoid + // dead-lock. + if (input.options.waitForDelazificationCache() && maybeCx) { + WaitForAllDelazifyTasks(maybeCx->runtime()); + } + } + + if (gcOutput) { + MOZ_ASSERT(maybeCx); + if (stencils) { + if (!InstantiateStencils(maybeCx, input, *stencils.get(), *gcOutput)) { + return false; + } + } else { + MOZ_ASSERT(!initialStencilOut); + BorrowingCompilationStencil borrowingStencil(extensibleStencil); + if (!InstantiateStencils(maybeCx, input, borrowingStencil, *gcOutput)) { + return false; + } + } + } -[[nodiscard]] static bool TrySmoosh( - JSContext* cx, FrontendContext* fc, CompilationInput& input, - JS::SourceText& srcBuf, - UniquePtr& stencilOut) { - MOZ_ASSERT(!stencilOut); return true; } -#endif // JS_ENABLE_SMOOSH - -using BytecodeCompilerOutput = - mozilla::Variant, - RefPtr, CompilationGCOutput*>; static constexpr ExtraBindingInfoVector* NoExtraBindings = nullptr; +static constexpr CompilationStencil** NoInitialStencilOut = nullptr; +static constexpr InitialStencilAndDelazifications** NoStencilsOut = nullptr; +static constexpr CompilationGCOutput* NoGCOutput = nullptr; // Compile global script, and return it as one of: // * ExtensibleCompilationStencil (without instantiation) @@ -259,50 +305,9 @@ template CompilationInput& input, ScopeBindingCache* scopeCache, JS::SourceText& srcBuf, ScopeKind scopeKind, ExtraBindingInfoVector* maybeExtraBindings, - BytecodeCompilerOutput& output) { -#ifdef JS_ENABLE_SMOOSH - if (maybeCx) { - UniquePtr extensibleStencil; - if (!TrySmoosh(maybeCx, fc, input, srcBuf, extensibleStencil)) { - return false; - } - if (extensibleStencil) { - if (input.options.populateDelazificationCache()) { - BorrowingCompilationStencil borrowingStencil(*extensibleStencil); - StartOffThreadDelazification(maybeCx, input.options, borrowingStencil); - - // When we are trying to validate whether on-demand delazification - // generate the same stencil as concurrent delazification, we want to - // parse everything eagerly off-thread ahead of re-parsing everything on - // demand, to compare the outcome. - if (input.options.waitForDelazificationCache()) { - WaitForAllDelazifyTasks(maybeCx->runtime()); - } - } - if (output.is>()) { - output.as>() = - std::move(extensibleStencil); - } else if (output.is>()) { - RefPtr stencil = - fc->getAllocator()->new_( - std::move(extensibleStencil)); - if (!stencil) { - return false; - } - - output.as>() = std::move(stencil); - } else { - BorrowingCompilationStencil borrowingStencil(*extensibleStencil); - if (!InstantiateStencils(maybeCx, input, borrowingStencil, - *(output.as()))) { - return false; - } - } - return true; - } - } -#endif // JS_ENABLE_SMOOSH - + CompilationStencil** initialStencilOut, + InitialStencilAndDelazifications** stencilsOut, + CompilationGCOutput* gcOutput) { if (input.options.selfHostingMode) { if (!input.initForSelfHostingGlobal(fc)) { return false; @@ -337,60 +342,10 @@ template return false; } - if (input.options.populateDelazificationCache()) { - // NOTE: Delazification can be triggered from off-thread compilation. - BorrowingCompilationStencil borrowingStencil(compiler.stencil()); - StartOffThreadDelazification(maybeCx, input.options, borrowingStencil); - - // When we are trying to validate whether on-demand delazification - // generate the same stencil as concurrent delazification, we want to - // parse everything eagerly off-thread ahead of re-parsing everything on - // demand, to compare the outcome. - // - // This option works only from main-thread compilation, to avoid - // dead-lock. - if (input.options.waitForDelazificationCache() && maybeCx) { - WaitForAllDelazifyTasks(maybeCx->runtime()); - } - } - - if (output.is>()) { - auto stencil = - fc->getAllocator()->make_unique( - std::move(compiler.stencil())); - if (!stencil) { - return false; - } - output.as>() = std::move(stencil); - } else if (output.is>()) { - Maybe pseudoFrame; - if (maybeCx) { - pseudoFrame.emplace(maybeCx, "script emit", - JS::ProfilingCategoryPair::JS_Parsing); - } - - auto extensibleStencil = - fc->getAllocator()->make_unique( - std::move(compiler.stencil())); - if (!extensibleStencil) { - return false; - } - - RefPtr stencil = - fc->getAllocator()->new_( - std::move(extensibleStencil)); - if (!stencil) { - return false; - } - - output.as>() = std::move(stencil); - } else { - MOZ_ASSERT(maybeCx); - BorrowingCompilationStencil borrowingStencil(compiler.stencil()); - if (!InstantiateStencils(maybeCx, input, borrowingStencil, - *(output.as()))) { - return false; - } + if (!ConvertGlobalScriptStencilMaybeInstantiate( + maybeCx, fc, input, std::move(compiler.stencil()), initialStencilOut, + stencilsOut, gcOutput)) { + return false; } assertException.reset(); @@ -398,70 +353,110 @@ template } template -static already_AddRefed CompileGlobalScriptToStencilImpl( +static already_AddRefed +CompileGlobalScriptToStencilWithInputImpl( JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, CompilationInput& input, ScopeBindingCache* scopeCache, JS::SourceText& srcBuf, ScopeKind scopeKind) { - using OutputType = RefPtr; - BytecodeCompilerOutput output((OutputType())); + RefPtr stencil; if (!CompileGlobalScriptToStencilAndMaybeInstantiate( maybeCx, fc, tempLifoAlloc, input, scopeCache, srcBuf, scopeKind, - NoExtraBindings, output)) { + NoExtraBindings, getter_AddRefs(stencil), NoGCOutput)) { return nullptr; } - return output.as().forget(); + return stencil.forget(); } -already_AddRefed frontend::CompileGlobalScriptToStencil( - JSContext* cx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf, ScopeKind scopeKind) { - return CompileGlobalScriptToStencilImpl(cx, fc, tempLifoAlloc, input, - scopeCache, srcBuf, scopeKind); -} - -already_AddRefed frontend::CompileGlobalScriptToStencil( +already_AddRefed +frontend::CompileGlobalScriptToStencilWithInput( JSContext* cx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, CompilationInput& input, ScopeBindingCache* scopeCache, JS::SourceText& srcBuf, ScopeKind scopeKind) { - return CompileGlobalScriptToStencilImpl(cx, fc, tempLifoAlloc, input, - scopeCache, srcBuf, scopeKind); -} - -template -static UniquePtr -CompileGlobalScriptToExtensibleStencilImpl(JSContext* maybeCx, - FrontendContext* fc, - CompilationInput& input, - ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf, - ScopeKind scopeKind) { - using OutputType = UniquePtr; - BytecodeCompilerOutput output((OutputType())); + RefPtr stencil; if (!CompileGlobalScriptToStencilAndMaybeInstantiate( - maybeCx, fc, maybeCx->tempLifoAlloc(), input, scopeCache, srcBuf, - scopeKind, NoExtraBindings, output)) { + cx, fc, tempLifoAlloc, input, scopeCache, srcBuf, scopeKind, + NoExtraBindings, getter_AddRefs(stencil), NoStencilsOut, + NoGCOutput)) { return nullptr; } - return std::move(output.as()); + return stencil.forget(); } -UniquePtr -frontend::CompileGlobalScriptToExtensibleStencil( - JSContext* maybeCx, FrontendContext* fc, CompilationInput& input, - ScopeBindingCache* scopeCache, JS::SourceText& srcBuf, - ScopeKind scopeKind) { - return CompileGlobalScriptToExtensibleStencilImpl( - maybeCx, fc, input, scopeCache, srcBuf, scopeKind); +template +static already_AddRefed CompileGlobalScriptToStencilImpl( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { + ScopeKind scopeKind = + options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global; + + AutoReportFrontendContext fc(cx); + + NoScopeBindingCache scopeCache; + Rooted input(cx, CompilationInput(options)); + RefPtr stencils; + if (!CompileGlobalScriptToStencilAndMaybeInstantiate( + cx, &fc, cx->tempLifoAlloc(), input.get(), &scopeCache, srcBuf, + scopeKind, NoExtraBindings, NoInitialStencilOut, + getter_AddRefs(stencils), NoGCOutput)) { + return nullptr; + } + return stencils.forget(); } -UniquePtr -frontend::CompileGlobalScriptToExtensibleStencil( - JSContext* cx, FrontendContext* fc, CompilationInput& input, - ScopeBindingCache* scopeCache, JS::SourceText& srcBuf, - ScopeKind scopeKind) { - return CompileGlobalScriptToExtensibleStencilImpl(cx, fc, input, scopeCache, - srcBuf, scopeKind); +already_AddRefed JS::CompileGlobalScriptToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { + return CompileGlobalScriptToStencilImpl(cx, options, srcBuf); +} + +already_AddRefed JS::CompileGlobalScriptToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { + return CompileGlobalScriptToStencilImpl(cx, options, srcBuf); +} + +template +static already_AddRefed CompileGlobalScriptToStencilImpl( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { + ScopeKind scopeKind = + options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global; + + NoScopeBindingCache scopeCache; + js::LifoAlloc tempLifoAlloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE, + js::BackgroundMallocArena); + CompilationInput compilationInput(options); + RefPtr stencils; + if (!CompileGlobalScriptToStencilAndMaybeInstantiate( + nullptr, fc, tempLifoAlloc, compilationInput, &scopeCache, srcBuf, + scopeKind, NoExtraBindings, NoInitialStencilOut, + getter_AddRefs(stencils), NoGCOutput)) { + JS_HAZ_VALUE_IS_GC_SAFE(compilationInput); + return nullptr; + } + // CompilationInput initialized with CompileGlobalScriptToStencil only + // references information from the JS::Stencil context and the + // ref-counted ScriptSource, which are both GC-free. + JS_HAZ_VALUE_IS_GC_SAFE(compilationInput); + return stencils.forget(); +} + +already_AddRefed JS::CompileGlobalScriptToStencil( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { +#ifdef DEBUG + fc->assertNativeStackLimitThread(); +#endif + return CompileGlobalScriptToStencilImpl(fc, options, srcBuf); +} + +already_AddRefed JS::CompileGlobalScriptToStencil( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { +#ifdef DEBUG + fc->assertNativeStackLimitThread(); +#endif + return CompileGlobalScriptToStencilImpl(fc, options, srcBuf); } static void FireOnNewScript(JSContext* cx, @@ -472,21 +467,29 @@ static void FireOnNewScript(JSContext* cx, } } -bool frontend::InstantiateStencils(JSContext* cx, CompilationInput& input, - const CompilationStencil& stencil, - CompilationGCOutput& gcOutput) { +static inline ScriptSource* getSource(const CompilationStencil& stencil) { + return stencil.source; +} + +static inline ScriptSource* getSource( + const InitialStencilAndDelazifications& stencils) { + return stencils.getInitial()->source; +} + +template +bool InstantiateStencilsImpl(JSContext* cx, CompilationInput& input, T& stencil, + CompilationGCOutput& gcOutput) { { AutoGeckoProfilerEntry pseudoFrame(cx, "stencil instantiate", JS::ProfilingCategoryPair::JS_Parsing); - if (!CompilationStencil::instantiateStencils(cx, input, stencil, - gcOutput)) { + if (!T::instantiateStencils(cx, input, stencil, gcOutput)) { return false; } } // Enqueue an off-thread source compression task after finishing parsing. - if (!stencil.source->tryCompressOffThread(cx)) { + if (!getSource(stencil)->tryCompressOffThread(cx)) { return false; } @@ -497,6 +500,18 @@ bool frontend::InstantiateStencils(JSContext* cx, CompilationInput& input, return true; } +bool frontend::InstantiateStencils(JSContext* cx, CompilationInput& input, + const CompilationStencil& stencil, + CompilationGCOutput& gcOutput) { + return InstantiateStencilsImpl(cx, input, stencil, gcOutput); +} + +bool frontend::InstantiateStencils(JSContext* cx, CompilationInput& input, + InitialStencilAndDelazifications& stencils, + CompilationGCOutput& gcOutput) { + return InstantiateStencilsImpl(cx, input, stencils, gcOutput); +} + template static JSScript* CompileGlobalScriptImpl( JSContext* cx, FrontendContext* fc, @@ -504,11 +519,11 @@ static JSScript* CompileGlobalScriptImpl( ScopeKind scopeKind, ExtraBindingInfoVector* maybeExtraBindings) { Rooted input(cx, CompilationInput(options)); Rooted gcOutput(cx); - BytecodeCompilerOutput output(gcOutput.address()); NoScopeBindingCache scopeCache; if (!CompileGlobalScriptToStencilAndMaybeInstantiate( cx, fc, cx->tempLifoAlloc(), input.get(), &scopeCache, srcBuf, - scopeKind, maybeExtraBindings, output)) { + scopeKind, maybeExtraBindings, NoInitialStencilOut, NoStencilsOut, + gcOutput.address())) { return nullptr; } return gcOutput.get().script; @@ -612,8 +627,8 @@ static WithEnvironmentObject* CreateExtraBindingsEnvironment( } JS::Rooted globalLexical(cx, &cx->global()->lexicalEnvironment()); - return WithEnvironmentObject::createNonSyntactic(cx, extraBindingsObj, - globalLexical); + return WithEnvironmentObject::createNonSyntactic( + cx, extraBindingsObj, globalLexical, JS::SupportUnscopables::No); } JSScript* frontend::CompileGlobalScriptWithExtraBindings( @@ -804,8 +819,7 @@ bool SourceAwareCompiler::createSourceAndParser(FrontendContext* fc) { CanLazilyParse(compilationState_.input.options)); if (compilationState_.canLazilyParse) { syntaxParser.emplace(fc_, options, sourceBuffer_.units(), - sourceBuffer_.length(), - /* foldConstants = */ false, compilationState_, + sourceBuffer_.length(), compilationState_, /* syntaxParser = */ nullptr); if (!syntaxParser->checkOptions()) { return false; @@ -813,8 +827,7 @@ bool SourceAwareCompiler::createSourceAndParser(FrontendContext* fc) { } parser.emplace(fc_, options, sourceBuffer_.units(), sourceBuffer_.length(), - /* foldConstants = */ true, compilationState_, - syntaxParser.ptrOr(nullptr)); + compilationState_, syntaxParser.ptrOr(nullptr)); parser->ss = compilationState_.source.get(); return parser->checkOptions(); } @@ -1163,15 +1176,7 @@ template return false; } - if (output.is>()) { - auto stencil = - fc->getAllocator()->make_unique( - std::move(compiler.stencil())); - if (!stencil) { - return false; - } - output.as>() = std::move(stencil); - } else if (output.is>()) { + if (output.is>()) { Maybe pseudoFrame; if (maybeCx) { pseudoFrame.emplace(maybeCx, "script emit", @@ -1220,54 +1225,78 @@ already_AddRefed ParseModuleToStencilImpl( return output.as().forget(); } -already_AddRefed frontend::ParseModuleToStencil( - JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - SourceText& srcBuf) { - return ParseModuleToStencilImpl(maybeCx, fc, tempLifoAlloc, input, scopeCache, - srcBuf); -} +template +static already_AddRefed CompileModuleScriptToStencilImpl( + JSContext* cx, const JS::ReadOnlyCompileOptions& optionsInput, + JS::SourceText& srcBuf) { + JS::CompileOptions options(cx, optionsInput); + options.setModule(); -already_AddRefed frontend::ParseModuleToStencil( - JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - SourceText& srcBuf) { - return ParseModuleToStencilImpl(maybeCx, fc, tempLifoAlloc, input, scopeCache, - srcBuf); -} + AutoReportFrontendContext fc(cx); -template -UniquePtr ParseModuleToExtensibleStencilImpl( - JSContext* cx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - SourceText& srcBuf) { - using OutputType = UniquePtr; - BytecodeCompilerOutput output((OutputType())); - if (!ParseModuleToStencilAndMaybeInstantiate(cx, fc, tempLifoAlloc, input, - scopeCache, srcBuf, output)) { + NoScopeBindingCache scopeCache; + Rooted input(cx, CompilationInput(options)); + RefPtr stencil = ParseModuleToStencilImpl( + cx, &fc, cx->tempLifoAlloc(), input.get(), &scopeCache, srcBuf); + if (!stencil) { return nullptr; } - return std::move(output.as()); + return CreateInitialStencilAndDelazifications(&fc, stencil.get()); } -UniquePtr -frontend::ParseModuleToExtensibleStencil(JSContext* cx, FrontendContext* fc, - js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, - ScopeBindingCache* scopeCache, - SourceText& srcBuf) { - return ParseModuleToExtensibleStencilImpl(cx, fc, tempLifoAlloc, input, - scopeCache, srcBuf); +already_AddRefed JS::CompileModuleScriptToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { + return CompileModuleScriptToStencilImpl(cx, options, srcBuf); } -UniquePtr -frontend::ParseModuleToExtensibleStencil(JSContext* cx, FrontendContext* fc, - js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, - ScopeBindingCache* scopeCache, - SourceText& srcBuf) { - return ParseModuleToExtensibleStencilImpl(cx, fc, tempLifoAlloc, input, - scopeCache, srcBuf); +already_AddRefed JS::CompileModuleScriptToStencil( + JSContext* cx, const JS::ReadOnlyCompileOptions& options, + JS::SourceText& srcBuf) { + return CompileModuleScriptToStencilImpl(cx, options, srcBuf); +} + +template +static already_AddRefed CompileModuleScriptToStencilImpl( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput, + JS::SourceText& srcBuf) { + JS::CompileOptions options(nullptr, optionsInput); + options.setModule(); + + frontend::CompilationInput compilationInput(options); + + NoScopeBindingCache scopeCache; + js::LifoAlloc tempLifoAlloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE, + js::BackgroundMallocArena); + RefPtr stencil = ParseModuleToStencilImpl( + nullptr, fc, tempLifoAlloc, compilationInput, &scopeCache, srcBuf); + if (!stencil) { + JS_HAZ_VALUE_IS_GC_SAFE(compilationInput); + return nullptr; + } + // CompilationInput initialized with ParseModuleToStencil only + // references information from the JS::Stencil context and the + // ref-counted ScriptSource, which are both GC-free. + JS_HAZ_VALUE_IS_GC_SAFE(compilationInput); + return CreateInitialStencilAndDelazifications(fc, stencil.get()); +} + +already_AddRefed JS::CompileModuleScriptToStencil( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput, + JS::SourceText& srcBuf) { +#ifdef DEBUG + fc->assertNativeStackLimitThread(); +#endif + return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf); +} + +already_AddRefed JS::CompileModuleScriptToStencil( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput, + JS::SourceText& srcBuf) { +#ifdef DEBUG + fc->assertNativeStackLimitThread(); +#endif + return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf); } template @@ -1307,25 +1336,12 @@ ModuleObject* frontend::CompileModule(JSContext* cx, FrontendContext* fc, } static bool InstantiateLazyFunction(JSContext* cx, CompilationInput& input, - CompilationStencil& stencil, - BytecodeCompilerOutput& output) { - // We do check the type, but do not write anything to it as this is not - // necessary for lazy function, as the script is patched inside the - // JSFunction when instantiating. - MOZ_ASSERT(output.is()); - MOZ_ASSERT(!output.as()); - + const CompilationStencil& stencil) { mozilla::DebugOnly lazyFlags = static_cast(input.immutableFlags()); Rooted gcOutput(cx); - if (input.source->hasEncoder()) { - if (!input.source->addDelazificationToIncrementalEncoding(cx, stencil)) { - return false; - } - } - if (!CompilationStencil::instantiateStencils(cx, input, stencil, gcOutput.get())) { return false; @@ -1345,91 +1361,25 @@ static bool InstantiateLazyFunction(JSContext* cx, CompilationInput& input, return true; } -enum class GetCachedResult { - // Similar to return false. - Error, - - // We have not found any entry. - NotFound, - - // We have found an entry, and set everything according to the desired - // BytecodeCompilerOutput out-param. - Found -}; - -// When we have a cache hit, the addPtr out-param would evaluate to a true-ish -// value. -static GetCachedResult GetCachedLazyFunctionStencilMaybeInstantiate( - JSContext* maybeCx, FrontendContext* fc, CompilationInput& input, - BytecodeCompilerOutput& output) { - RefPtr stencil; - { - DelazificationCache& cache = DelazificationCache::getSingleton(); - auto guard = cache.isSourceCached(input.source); - if (!guard) { - return GetCachedResult::NotFound; - } - - // Before releasing the guard, which is locking the cache, we increment the - // reference counter such that we do not reclaim the CompilationStencil - // while we are instantiating it. - StencilContext key(input.source, input.extent()); - stencil = cache.lookup(guard, key); - if (!stencil) { - return GetCachedResult::NotFound; - } - } - - if (output.is>()) { - output.as>() = stencil; - return GetCachedResult::Found; - } - - if (output.is>()) { - auto extensible = - fc->getAllocator()->make_unique(input); - if (!extensible) { - return GetCachedResult::Error; - } - if (!extensible->cloneFrom(fc, *stencil)) { - return GetCachedResult::Error; - } - - output.as>() = - std::move(extensible); - return GetCachedResult::Found; - } - - MOZ_ASSERT(maybeCx); - - if (!InstantiateLazyFunction(maybeCx, input, *stencil, output)) { - return GetCachedResult::Error; - } - - return GetCachedResult::Found; -} - +// Compile lazy functinn specified by a pair of `units` + `length`, and +// optionally instantiate. +// +// If `stencils` is provided, the result of delazification is stored into it. +// +// If `borrowOut` is provided, a borrowing pointer is returned. +// +// If `borrowOut` is not provided, the function is instantiated. +// In this case, `maybeCx` should be provided and `input` should be initialized +// with a BaseScript. template static bool CompileLazyFunctionToStencilMaybeInstantiate( JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, CompilationInput& input, ScopeBindingCache* scopeCache, const Unit* units, - size_t length, BytecodeCompilerOutput& output) { + size_t length, InitialStencilAndDelazifications* stencils, + const CompilationStencil** borrowOut) { MOZ_ASSERT(input.source); AutoAssertReportedException assertException(maybeCx, fc); - if (input.options.consumeDelazificationCache()) { - auto res = GetCachedLazyFunctionStencilMaybeInstantiate(maybeCx, fc, input, - output); - switch (res) { - case GetCachedResult::Error: - return false; - case GetCachedResult::Found: - assertException.reset(); - return true; - case GetCachedResult::NotFound: - break; - } - } InheritThis inheritThis = input.functionFlags().isArrow() ? InheritThis::Yes : InheritThis::No; @@ -1443,7 +1393,6 @@ static bool CompileLazyFunctionToStencilMaybeInstantiate( } Parser parser(fc, input.options, units, length, - /* foldConstants = */ true, compilationState, /* syntaxParser = */ nullptr); if (!parser.checkOptions()) { @@ -1479,17 +1428,11 @@ static bool CompileLazyFunctionToStencilMaybeInstantiate( .setAllowRelazify(); } - if (input.options.checkDelazificationCache()) { - using OutputType = RefPtr; - BytecodeCompilerOutput cached((OutputType())); - auto res = GetCachedLazyFunctionStencilMaybeInstantiate(nullptr, fc, input, - cached); - if (res == GetCachedResult::Error) { - return false; - } - // Cached results might be removed by GCs. - if (res == GetCachedResult::Found) { - auto& concurrentSharedData = cached.as().get()->sharedData; + if (stencils && input.options.checkDelazificationCache()) { + const CompilationStencil* cached = + stencils->getDelazificationFor(input.extent()); + if (cached) { + auto& concurrentSharedData = cached->sharedData; auto concurrentData = concurrentSharedData.isSingle() ? concurrentSharedData.asSingle()->get()->immutableData() @@ -1508,21 +1451,7 @@ static bool CompileLazyFunctionToStencilMaybeInstantiate( } } - if (output.is>()) { - auto stencil = - fc->getAllocator()->make_unique( - std::move(compilationState)); - if (!stencil) { - return false; - } - output.as>() = std::move(stencil); - } else if (output.is>()) { - Maybe pseudoFrame; - if (maybeCx) { - pseudoFrame.emplace(maybeCx, "script emit", - JS::ProfilingCategoryPair::JS_Parsing); - } - + if (borrowOut) { auto extensibleStencil = fc->getAllocator()->make_unique( std::move(compilationState)); @@ -1537,12 +1466,34 @@ static bool CompileLazyFunctionToStencilMaybeInstantiate( return false; } - output.as>() = std::move(stencil); + *borrowOut = stencils->storeDelazification(std::move(stencil)); } else { MOZ_ASSERT(maybeCx); - BorrowingCompilationStencil borrowingStencil(compilationState); - if (!InstantiateLazyFunction(maybeCx, input, borrowingStencil, output)) { - return false; + if (stencils) { + auto extensibleStencil = + maybeCx->make_unique( + std::move(compilationState)); + if (!extensibleStencil) { + return false; + } + + RefPtr stencil = + maybeCx->new_(std::move(extensibleStencil)); + if (!stencil) { + return false; + } + + const CompilationStencil* borrowed = + stencils->storeDelazification(std::move(stencil)); + + if (!InstantiateLazyFunction(maybeCx, input, *borrowed)) { + return false; + } + } else { + BorrowingCompilationStencil borrowingStencil(compilationState); + if (!InstantiateLazyFunction(maybeCx, input, borrowingStencil)) { + return false; + } } } @@ -1564,6 +1515,29 @@ static bool DelazifyCanonicalScriptedFunctionImpl(JSContext* cx, AutoIncrementalTimer timer(cx->realm()->timers.delazificationTime); + JS::CompileOptions options(cx); + options.setMutedErrors(lazy->mutedErrors()) + .setFileAndLine(lazy->filename(), lazy->lineno()) + .setColumn(JS::ColumnNumberOneOrigin(lazy->column())) + .setScriptSourceOffset(lazy->sourceStart()) + .setNoScriptRval(false) + .setSelfHostingMode(false) + .setEagerDelazificationStrategy(lazy->delazificationMode()); + + Rooted input(cx, CompilationInput(options)); + input.get().initFromLazy(cx, lazy, ss); + + RefPtr stencils = + lazy->sourceObject()->maybeGetStencils(); + + if (stencils && input.get().options.consumeDelazificationCache()) { + const CompilationStencil* cached = + stencils->getDelazificationFor(input.get().extent()); + if (cached) { + return InstantiateLazyFunction(cx, input.get(), *cached); + } + } + size_t sourceStart = lazy->sourceStart(); size_t sourceLength = lazy->sourceEnd() - lazy->sourceStart(); @@ -1580,23 +1554,9 @@ static bool DelazifyCanonicalScriptedFunctionImpl(JSContext* cx, return false; } - JS::CompileOptions options(cx); - options.setMutedErrors(lazy->mutedErrors()) - .setFileAndLine(lazy->filename(), lazy->lineno()) - .setColumn(JS::ColumnNumberOneOrigin(lazy->column())) - .setScriptSourceOffset(lazy->sourceStart()) - .setNoScriptRval(false) - .setSelfHostingMode(false) - .setEagerDelazificationStrategy(lazy->delazificationMode()); - - Rooted input(cx, CompilationInput(options)); - input.get().initFromLazy(cx, lazy, ss); - - CompilationGCOutput* unusedGcOutput = nullptr; - BytecodeCompilerOutput output(unusedGcOutput); return CompileLazyFunctionToStencilMaybeInstantiate( cx, fc, cx->tempLifoAlloc(), input.get(), scopeCache, units.get(), - sourceLength, output); + sourceLength, stencils, nullptr); } bool frontend::DelazifyCanonicalScriptedFunction(JSContext* cx, @@ -1626,12 +1586,19 @@ bool frontend::DelazifyCanonicalScriptedFunction(JSContext* cx, } template -static already_AddRefed -DelazifyCanonicalScriptedFunctionImpl( +static const CompilationStencil* DelazifyCanonicalScriptedFunctionImpl( FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, const JS::PrefableCompileOptions& prefableOptions, ScopeBindingCache* scopeCache, CompilationStencil& context, - ScriptIndex scriptIndex, DelazifyFailureReason* failureReason) { + ScriptIndex scriptIndex, InitialStencilAndDelazifications* stencils, + DelazifyFailureReason* failureReason) { + MOZ_ASSERT(stencils); + + const CompilationStencil* cached = stencils->getDelazificationAt(scriptIndex); + if (cached) { + return cached; + } + ScriptStencilRef script{context, scriptIndex}; const ScriptStencilExtra& extra = script.scriptExtra(); @@ -1670,36 +1637,36 @@ DelazifyCanonicalScriptedFunctionImpl( JS_HAZ_NON_GC_POINTER CompilationInput input(options); input.initFromStencil(context, scriptIndex, ss); - using OutputType = RefPtr; - BytecodeCompilerOutput output((OutputType())); + const CompilationStencil* borrow; if (!CompileLazyFunctionToStencilMaybeInstantiate( nullptr, fc, tempLifoAlloc, input, scopeCache, units.get(), - sourceLength, output)) { + sourceLength, stencils, &borrow)) { *failureReason = DelazifyFailureReason::Other; return nullptr; } - return output.as().forget(); + + return borrow; } -already_AddRefed -frontend::DelazifyCanonicalScriptedFunction( +const CompilationStencil* frontend::DelazifyCanonicalScriptedFunction( FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, const JS::PrefableCompileOptions& prefableOptions, ScopeBindingCache* scopeCache, CompilationStencil& context, - ScriptIndex scriptIndex, DelazifyFailureReason* failureReason) { + ScriptIndex scriptIndex, InitialStencilAndDelazifications* stencils, + DelazifyFailureReason* failureReason) { ScriptSource* ss = context.source; if (ss->hasSourceType()) { // UTF-8 source text. return DelazifyCanonicalScriptedFunctionImpl( fc, tempLifoAlloc, prefableOptions, scopeCache, context, scriptIndex, - failureReason); + stencils, failureReason); } // UTF-16 source text. MOZ_ASSERT(ss->hasSourceType()); return DelazifyCanonicalScriptedFunctionImpl( fc, tempLifoAlloc, prefableOptions, scopeCache, context, scriptIndex, - failureReason); + stencils, failureReason); } static JSFunction* CompileStandaloneFunction( diff --git a/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.h b/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.h index 6576e23519c..6be3df7b4b8 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.h +++ b/src/third_party/mozjs/extract/js/src/frontend/BytecodeCompiler.h @@ -118,38 +118,28 @@ namespace frontend { struct CompilationInput; struct CompilationStencil; struct ExtensibleCompilationStencil; +struct InitialStencilAndDelazifications; struct CompilationGCOutput; class ScopeBindingCache; -// Compile a script of the given source using the given options. -extern already_AddRefed CompileGlobalScriptToStencil( - JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf, ScopeKind scopeKind); - -extern already_AddRefed CompileGlobalScriptToStencil( - JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf, ScopeKind scopeKind); - -extern UniquePtr -CompileGlobalScriptToExtensibleStencil(JSContext* maybeCx, FrontendContext* fc, - CompilationInput& input, - ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf, - ScopeKind scopeKind); - -extern UniquePtr -CompileGlobalScriptToExtensibleStencil( - JSContext* maybeCx, FrontendContext* fc, CompilationInput& input, - ScopeBindingCache* scopeCache, JS::SourceText& srcBuf, - ScopeKind scopeKind); +// Compile a script of the given source using the given CompilationInput. +extern already_AddRefed +CompileGlobalScriptToStencilWithInput(JSContext* maybeCx, FrontendContext* fc, + js::LifoAlloc& tempLifoAlloc, + CompilationInput& input, + ScopeBindingCache* scopeCache, + JS::SourceText& srcBuf, + ScopeKind scopeKind); [[nodiscard]] extern bool InstantiateStencils(JSContext* cx, CompilationInput& input, const CompilationStencil& stencil, CompilationGCOutput& gcOutput); +[[nodiscard]] extern bool InstantiateStencils( + JSContext* cx, CompilationInput& input, + InitialStencilAndDelazifications& stencils, CompilationGCOutput& gcOutput); + // Perform CompileGlobalScriptToStencil and InstantiateStencils at the // same time, skipping some extra copy. extern JSScript* CompileGlobalScript(JSContext* cx, FrontendContext* fc, @@ -201,26 +191,6 @@ ModuleObject* CompileModule(JSContext* cx, FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, JS::SourceText& srcBuf); -// Parse a module of the given source. This is an internal API; if you want to -// compile a module as a user, use CompileModule above. -already_AddRefed ParseModuleToStencil( - JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf); -already_AddRefed ParseModuleToStencil( - JSContext* maybeCx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf); - -UniquePtr ParseModuleToExtensibleStencil( - JSContext* cx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf); -UniquePtr ParseModuleToExtensibleStencil( - JSContext* cx, FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, - CompilationInput& input, ScopeBindingCache* scopeCache, - JS::SourceText& srcBuf); - // // Compile a single function. The source in srcBuf must match the ECMA-262 // FunctionExpression production. @@ -273,11 +243,15 @@ enum class DelazifyFailureReason { Other, }; -extern already_AddRefed DelazifyCanonicalScriptedFunction( +// Delazify a function specified by a pair of `context` + `scriptIndex`, and +// store the delazification stencil into `stencils`, and return a borrowing +// pointer for the delazification. +extern const CompilationStencil* DelazifyCanonicalScriptedFunction( FrontendContext* fc, js::LifoAlloc& tempLifoAlloc, const JS::PrefableCompileOptions& prefableOptions, ScopeBindingCache* scopeCache, CompilationStencil& context, - ScriptIndex scriptIndex, DelazifyFailureReason* failureReason); + ScriptIndex scriptIndex, InitialStencilAndDelazifications* stencils, + DelazifyFailureReason* failureReason); // Certain compile options will disable the syntax parser entirely. inline bool CanLazilyParse(const JS::ReadOnlyCompileOptions& options) { diff --git a/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.cpp index ae8c241bcd8..5373aa1dcf8 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.cpp @@ -13,9 +13,8 @@ #include "mozilla/Casting.h" // mozilla::AssertedCast #include "mozilla/DebugOnly.h" // mozilla::DebugOnly #include "mozilla/FloatingPoint.h" // mozilla::NumberEqualsInt32, mozilla::NumberIsInt32 -#include "mozilla/HashTable.h" // mozilla::HashSet -#include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some} -#include "mozilla/PodOperations.h" // mozilla::PodCopy +#include "mozilla/HashTable.h" // mozilla::HashSet +#include "mozilla/Maybe.h" // mozilla::{Maybe,Nothing,Some} #include "mozilla/Saturate.h" #include "mozilla/Variant.h" // mozilla::AsVariant @@ -63,17 +62,18 @@ #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOffset #include "js/friend/ErrorMessages.h" // JSMSG_* #include "js/friend/StackLimits.h" // AutoCheckRecursionLimit -#include "util/StringBuffer.h" // StringBuffer +#include "util/StringBuilder.h" // StringBuilder #include "vm/BytecodeUtil.h" // JOF_*, IsArgOp, IsLocalOp, SET_UINT24, SET_ICINDEX, BytecodeFallsThrough, BytecodeIsJumpTarget -#include "vm/CompletionKind.h" // CompletionKind -#include "vm/FunctionPrefixKind.h" // FunctionPrefixKind -#include "vm/GeneratorObject.h" // AbstractGeneratorObject -#include "vm/Opcodes.h" // JSOp, JSOpLength_* -#include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary -#include "vm/Scope.h" // GetScopeDataTrailingNames -#include "vm/SharedStencil.h" // ScopeNote -#include "vm/ThrowMsgKind.h" // ThrowMsgKind -#include "vm/TypeofEqOperand.h" // TypeofEqOperand +#include "vm/CompletionKind.h" // CompletionKind +#include "vm/ConstantCompareOperand.h" // ConstantCompareOperand +#include "vm/FunctionPrefixKind.h" // FunctionPrefixKind +#include "vm/GeneratorObject.h" // AbstractGeneratorObject +#include "vm/Opcodes.h" // JSOp, JSOpLength_* +#include "vm/PropMap.h" // SharedPropMap::MaxPropsForNonDictionary +#include "vm/Scope.h" // GetScopeDataTrailingNames +#include "vm/SharedStencil.h" // ScopeNote +#include "vm/ThrowMsgKind.h" // ThrowMsgKind +#include "vm/TypeofEqOperand.h" // TypeofEqOperand using namespace js; using namespace js::frontend; @@ -85,7 +85,6 @@ using mozilla::Maybe; using mozilla::Nothing; using mozilla::NumberEqualsInt32; using mozilla::NumberIsInt32; -using mozilla::PodCopy; using mozilla::Some; static bool ParseNodeRequiresSpecialLineNumberNotes(ParseNode* pn) { @@ -282,7 +281,7 @@ bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, } #ifdef DEBUG -bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) { +bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) const { if (IsCheckStrictOp(op) && !sc->strict()) { return false; } @@ -295,6 +294,7 @@ bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) { bool BytecodeEmitter::emit1(JSOp op) { MOZ_ASSERT(checkStrictOrSloppy(op)); + MOZ_ASSERT(GetOpLength(op) == 1); BytecodeOffset offset; if (!emitCheck(op, 1, &offset)) { @@ -309,6 +309,7 @@ bool BytecodeEmitter::emit1(JSOp op) { bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) { MOZ_ASSERT(checkStrictOrSloppy(op)); + MOZ_ASSERT(GetOpLength(op) == 2); BytecodeOffset offset; if (!emitCheck(op, 2, &offset)) { @@ -324,6 +325,7 @@ bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) { bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) { MOZ_ASSERT(checkStrictOrSloppy(op)); + MOZ_ASSERT(GetOpLength(op) == 3); /* These should filter through emitVarOp. */ MOZ_ASSERT(!IsArgOp(op)); @@ -656,7 +658,7 @@ bool BytecodeEmitter::updateSourceCoordNotesIfNonLiteral(ParseNode* node) { return updateSourceCoordNotes(node->pn_pos.begin); } -uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) { +uint32_t BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) const { // Try to give the JSOp::LoopHead the same line number as the next // instruction. nextpn is often a block, in which case the next instruction // typically comes from the first statement inside. @@ -824,24 +826,7 @@ bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) { return true; } -JSOp BytecodeEmitter::strictifySetNameOp(JSOp op) { - switch (op) { - case JSOp::SetName: - if (sc->strict()) { - op = JSOp::StrictSetName; - } - break; - case JSOp::SetGName: - if (sc->strict()) { - op = JSOp::StrictSetGName; - } - break; - default:; - } - return op; -} - -bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) { +bool BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) const { AutoCheckRecursionLimit recursion(fc); if (!recursion.check(fc)) { return false; @@ -1076,12 +1061,6 @@ restart: } return true; -#ifdef ENABLE_RECORD_TUPLE - case ParseNodeKind::RecordExpr: - case ParseNodeKind::TupleExpr: - MOZ_CRASH("Record and Tuple are not supported yet"); -#endif - #ifdef ENABLE_DECORATORS case ParseNodeKind::DecoratorList: MOZ_CRASH("Decorators are not supported yet"); @@ -1390,16 +1369,16 @@ restart: "BytecodeEmitter::checkSideEffects"); } -bool BytecodeEmitter::isInLoop() { +bool BytecodeEmitter::isInLoop() const { return findInnermostNestableControl(); } -bool BytecodeEmitter::checkSingletonContext() { +bool BytecodeEmitter::checkSingletonContext() const { MOZ_ASSERT_IF(sc->treatAsRunOnce(), sc->isTopLevelContext()); return sc->treatAsRunOnce() && !isInLoop(); } -bool BytecodeEmitter::needsImplicitThis() { +bool BytecodeEmitter::needsImplicitThis() const { // Short-circuit if there is an enclosing 'with' scope. if (sc->inWith()) { return true; @@ -1416,10 +1395,10 @@ bool BytecodeEmitter::needsImplicitThis() { return false; } -size_t BytecodeEmitter::countThisEnvironmentHops() { +size_t BytecodeEmitter::countThisEnvironmentHops() const { unsigned numHops = 0; - for (BytecodeEmitter* current = this; current; current = current->parent) { + for (const auto* current = this; current; current = current->parent) { for (EmitterScope* es = current->innermostEmitterScope(); es; es = es->enclosingInFrame()) { if (es->scope(current).is()) { @@ -1472,7 +1451,8 @@ bool BytecodeEmitter::emitSuperBase() { return emit1(JSOp::SuperBase); } -void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) { +void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, + ...) const { uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset; va_list args; @@ -1484,7 +1464,8 @@ void BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) { va_end(args); } -void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, ...) { +void BytecodeEmitter::reportError(uint32_t offset, unsigned errorNumber, + ...) const { va_list args; va_start(args, errorNumber); @@ -1763,43 +1744,41 @@ bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) { return true; } -bool BytecodeEmitter::emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key, - ElemOpEmitter& eoe) { - if (exprOrSuper->isKind(ParseNodeKind::SuperBase)) { - if (!eoe.prepareForObj()) { - // [stack] - return false; - } - UnaryNode* base = &exprOrSuper->as(); - if (!emitGetThisForSuperBase(base)) { - // [stack] THIS - return false; - } - if (!eoe.prepareForKey()) { - // [stack] THIS - return false; - } - if (!emitTree(key)) { - // [stack] THIS KEY - return false; - } - - return true; - } +bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, + ElemOpEmitter& eoe) { + ParseNode* exprOrSuper = &elem->expression(); + ParseNode* key = &elem->key(); if (!eoe.prepareForObj()) { // [stack] return false; } - if (!emitTree(exprOrSuper)) { - // [stack] OBJ - return false; + + if (elem->isSuper()) { + auto* base = &exprOrSuper->as(); + if (!emitGetThisForSuperBase(base)) { + // [stack] THIS + return false; + } + } else { + if (!emitTree(exprOrSuper)) { + // [stack] OBJ + return false; + } } + if (!eoe.prepareForKey()) { + // [stack] # if Super + // [stack] THIS? THIS + // [stack] # otherwise // [stack] OBJ? OBJ return false; } + if (!emitTree(key)) { + // [stack] # if Super + // [stack] THIS? THIS KEY + // [stack] # otherwise // [stack] OBJ? OBJ KEY return false; } @@ -1815,12 +1794,6 @@ bool BytecodeEmitter::emitElemOpBase(JSOp op) { return true; } -bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper, - ElemOpEmitter& eoe) { - MOZ_ASSERT(isSuper == elem->expression().isKind(ParseNodeKind::SuperBase)); - return emitObjAndKey(&elem->expression(), &elem->key(), eoe); -} - static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) { switch (kind) { case ParseNodeKind::PostIncrementExpr: @@ -1859,7 +1832,7 @@ bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) { ElemOpEmitter eoe( this, ConvertIncDecKind(kind), isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (!emitElemObjAndKey(elemExpr, isSuper, eoe)) { + if (!emitElemObjAndKey(elemExpr, eoe)) { // [stack] # if Super // [stack] THIS KEY // [stack] # otherwise @@ -2445,6 +2418,12 @@ bool BytecodeEmitter::emitScript(ParseNode* body) { switchToMain(); +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (!emitterScope.prepareForModuleDisposableScopeBody(this)) { + return false; + } +#endif + if (topLevelAwait) { if (!topLevelAwait->prepareForBody()) { return false; @@ -2461,20 +2440,18 @@ bool BytecodeEmitter::emitScript(ParseNode* body) { } } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (!emitterScope.emitModuleDisposableScopeBodyEnd(this)) { + return false; + } +#endif + if (topLevelAwait) { if (!topLevelAwait->emitEndModule()) { return false; } } -#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - if (emitterScope.hasDisposables()) { - if (!emit1(JSOp::DisposeDisposables)) { - return false; - } - } -#endif - if (!markSimpleBreakpoint()) { return false; } @@ -2545,7 +2522,7 @@ bool BytecodeEmitter::emitCheckIsCallable() { } #endif -bool BytecodeEmitter::getNslots(uint32_t* nslots) { +bool BytecodeEmitter::getNslots(uint32_t* nslots) const { uint64_t nslots64 = maxFixedSlots + static_cast(bytecodeSection().maxStackDepth()); if (nslots64 > UINT32_MAX) { @@ -2601,23 +2578,63 @@ bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) { return fse.intoStencil(); } +class js::frontend::DestructuringLHSRef { + struct None { + size_t numReferenceSlots() const { return 0; } + }; + + mozilla::Variant + emitter_ = AsVariant(None{}); + + public: + template + void from(T&& emitter) { + emitter_.emplace(std::forward(emitter)); + } + + template + T& emitter() { + return emitter_.as(); + } + + /** + * Return the number of values pushed onto the stack. + */ + size_t numReferenceSlots() const { + return emitter_.match([](auto& e) { return e.numReferenceSlots(); }); + } +}; + bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, - size_t* emitted) { + DestructuringFlavor flav, + DestructuringLHSRef& lref) { #ifdef DEBUG int depth = bytecodeSection().stackDepth(); #endif switch (target->getKind()) { - case ParseNodeKind::Name: case ParseNodeKind::ArrayExpr: case ParseNodeKind::ObjectExpr: // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object // subpatterns here, since emitSetOrInitializeDestructuring does the - // recursion when setting or initializing the value. Getting reference - // doesn't recurse. - *emitted = 0; + // recursion when setting or initializing the value. break; + case ParseNodeKind::Name: { + auto* name = &target->as(); + NameOpEmitter noe(this, name->atom(), + flav == DestructuringFlavor::Assignment + ? NameOpEmitter::Kind::SimpleAssignment + : NameOpEmitter::Kind::Initialize); + if (!noe.prepareForRhs()) { + return false; + } + + lref.from(std::move(noe)); + return true; + } + case ParseNodeKind::ArgumentsLength: case ParseNodeKind::DotExpr: { PropertyAccess* prop = &target->as(); @@ -2648,8 +2665,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, return false; } - // SUPERBASE was pushed onto THIS in poe.prepareForRhs above. - *emitted = 1 + isSuper; + lref.from(std::move(poe)); break; } @@ -2660,7 +2676,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (!emitElemObjAndKey(elem, isSuper, eoe)) { + if (!emitElemObjAndKey(elem, eoe)) { // [stack] # if Super // [stack] THIS KEY // [stack] # otherwise @@ -2675,8 +2691,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, return false; } - // SUPERBASE was pushed onto KEY in eoe.prepareForRhs above. - *emitted = 2 + isSuper; + lref.from(std::move(eoe)); break; } @@ -2692,7 +2707,8 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, // [stack] OBJ NAME return false; } - *emitted = xoe.numReferenceSlots(); + + lref.from(std::move(xoe)); break; } @@ -2707,13 +2723,14 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind"); } - MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted)); + MOZ_ASSERT(bytecodeSection().stackDepth() == + depth + int(lref.numReferenceSlots())); return true; } bool BytecodeEmitter::emitSetOrInitializeDestructuring( - ParseNode* target, DestructuringFlavor flav) { + ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) { // Now emit the lvalue opcode sequence. If the lvalue is a nested // destructuring initialiser-form, call ourselves to handle it, then pop // the matched value. Otherwise emit an lvalue bytecode sequence followed @@ -2730,51 +2747,14 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring( break; case ParseNodeKind::Name: { - auto name = target->as().name(); - NameLocation loc = lookupName(name); - NameOpEmitter::Kind kind; - switch (flav) { - case DestructuringFlavor::Declaration: - kind = NameOpEmitter::Kind::Initialize; - break; + // The environment is already pushed by emitDestructuringLHSRef. + // [stack] ENV? VAL + auto& noe = lref.emitter(); - case DestructuringFlavor::Assignment: - kind = NameOpEmitter::Kind::SimpleAssignment; - break; - } - - NameOpEmitter noe(this, name, loc, kind); - if (!noe.prepareForRhs()) { - // [stack] V ENV? - return false; - } - if (noe.emittedBindOp()) { - // This is like ordinary assignment, but with one difference. - // - // In `a = b`, we first determine a binding for `a` (using - // JSOp::BindName or JSOp::BindGName), then we evaluate `b`, then - // a JSOp::SetName instruction. - // - // In `[a] = [b]`, per spec, `b` is evaluated first, then we - // determine a binding for `a`. Then we need to do assignment-- - // but the operands are on the stack in the wrong order for - // JSOp::SetProp, so we have to add a JSOp::Swap. - // - // In the cases where we are emitting a name op, emit a swap - // because of this. - if (!emit1(JSOp::Swap)) { - // [stack] ENV V - return false; - } - } else { - // In cases of emitting a frame slot or environment slot, - // nothing needs be done. - } if (!noe.emitAssignment()) { - // [stack] V + // [stack] VAL return false; } - break; } @@ -2785,16 +2765,11 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring( // [stack] THIS SUPERBASE VAL // [stack] # otherwise // [stack] OBJ VAL - PropertyAccess* prop = &target->as(); - bool isSuper = prop->isSuper(); - PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment, - isSuper ? PropOpEmitter::ObjKind::Super - : PropOpEmitter::ObjKind::Other); - if (!poe.skipObjAndRhs()) { - return false; - } - // [stack] # VAL + auto& poe = lref.emitter(); + auto* prop = &target->as(); + if (!poe.emitAssignment(prop->key().atom())) { + // [stack] # VAL return false; } break; @@ -2806,15 +2781,8 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring( // [stack] THIS KEY SUPERBASE VAL // [stack] # otherwise // [stack] OBJ KEY VAL - PropertyByValue* elem = &target->as(); - bool isSuper = elem->isSuper(); - MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); - ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, - isSuper ? ElemOpEmitter::ObjKind::Super - : ElemOpEmitter::ObjKind::Other); - if (!eoe.skipObjAndKeyAndRhs()) { - return false; - } + auto& eoe = lref.emitter(); + if (!eoe.emitAssignment()) { // [stack] VAL return false; @@ -2825,12 +2793,8 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring( case ParseNodeKind::PrivateMemberExpr: { // The reference is already pushed by emitDestructuringLHSRef. // [stack] OBJ NAME VAL - PrivateMemberAccess* privateExpr = &target->as(); - PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment, - privateExpr->privateName().name()); - if (!xoe.skipReference()) { - return false; - } + auto& xoe = lref.emitter(); + if (!xoe.emitAssignment()) { // [stack] VAL return false; @@ -2859,7 +2823,7 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring( } JSOp BytecodeEmitter::getIterCallOp(JSOp callOp, - SelfHostedIter selfHostedIter) { + SelfHostedIter selfHostedIter) const { if (emitterMode == BytecodeEmitter::SelfHosting) { MOZ_ASSERT(selfHostedIter != SelfHostedIter::Deny); @@ -3131,9 +3095,7 @@ bool BytecodeEmitter::emitAnonymousFunctionWithName( if (node->is()) { // Function doesn't have 'name' property at this point. // Set function's name at compile time. - if (!setFunName(node->as().funbox(), name)) { - return false; - } + setFunName(node->as().funbox(), name); return emitTree(node); } @@ -3169,20 +3131,17 @@ bool BytecodeEmitter::emitAnonymousFunctionWithComputedName( return emitClass(&node->as(), ClassNameKind::ComputedName); } -bool BytecodeEmitter::setFunName(FunctionBox* funbox, - TaggedParserAtomIndex name) { +void BytecodeEmitter::setFunName(FunctionBox* funbox, + TaggedParserAtomIndex name) const { // The inferred name may already be set if this function is an interpreted // lazy function and we OOM'ed after we set the inferred name the first // time. if (funbox->hasInferredName()) { MOZ_ASSERT(!funbox->emitBytecode); MOZ_ASSERT(funbox->displayAtom() == name); - - return true; + } else { + funbox->setInferredName(name); } - - funbox->setInferredName(name); - return true; } bool BytecodeEmitter::emitInitializer(ParseNode* initializer, @@ -3381,6 +3340,7 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, idx += 1; continue; } + MOZ_ASSERT(member->isKind(ParseNodeKind::Name)); if (!emit1(JSOp::Dup)) { // [stack] LENGTH OBJ OBJ @@ -3438,7 +3398,13 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, return false; } - if (!emitSetOrInitializeDestructuring(member, flav)) { + DestructuringLHSRef lref; + if (!emitDestructuringLHSRef(member, flav, lref)) { + // [stack] LENGTH OBJ + return false; + } + + if (!emitSetOrInitializeDestructuring(member, flav, lref)) { // [stack] LENGTH OBJ return false; } @@ -3525,14 +3491,12 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, pndefault = subpattern->as().right(); } - // Number of stack slots emitted for the LHS reference. - size_t emitted = 0; - // Spec requires LHS reference to be evaluated first. + DestructuringLHSRef lref; bool isElision = lhsPattern->isKind(ParseNodeKind::Elision); if (!isElision) { - auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) { - return bce->emitDestructuringLHSRef(lhsPattern, &emitted); + auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { + return bce->emitDestructuringLHSRef(lhsPattern, flav, lref); // [stack] ... OBJ NEXT ITER DONE LREF* }; if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) { @@ -3540,6 +3504,9 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, } } + // Number of stack slots emitted for the LHS reference. + size_t emitted = lref.numReferenceSlots(); + // Pick the DONE value to the top of the stack. if (emitted) { if (!emitPickN(emitted)) { @@ -3622,8 +3589,8 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, return false; } - auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) { - return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); + auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { + return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref); // [stack] ... OBJ NEXT ITER TRUE }; if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { @@ -3747,8 +3714,8 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, } if (!isElision) { - auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) { - return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); + auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) { + return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref); // [stack] ... OBJ NEXT ITER DONE }; @@ -3823,10 +3790,13 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, return false; } + // To understand why we chose '4', please see the discussion on Bug 1948959. + const uint8_t estimatedRestSize = 4; + bool needsRestPropertyExcludedSet = pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread); if (needsRestPropertyExcludedSet) { - if (!emitDestructuringObjRestExclusionSet(pattern)) { + if (!emitDestructuringObjRestExclusionSet(pattern, estimatedRestSize)) { // [stack] ... RHS SET return false; } @@ -3839,6 +3809,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, for (ParseNode* member : pattern->contents()) { ParseNode* subpattern; + bool hasKeyOnStack = false; if (member->isKind(ParseNodeKind::MutateProto) || member->isKind(ParseNodeKind::Spread)) { subpattern = member->as().kid(); @@ -3849,6 +3820,16 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) || member->isKind(ParseNodeKind::Shorthand)); subpattern = member->as().right(); + + // Computed property names are evaluated before the subpattern. + ParseNode* key = member->as().left(); + if (key->isKind(ParseNodeKind::ComputedName)) { + if (!emitComputedPropertyName(&key->as())) { + // [stack] ... SET? RHS KEY + return false; + } + hasKeyOnStack = true; + } } ParseNode* lhs = subpattern; @@ -3858,18 +3839,19 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, pndefault = subpattern->as().right(); } - // Number of stack slots emitted for the LHS reference. - size_t emitted = 0; - // Spec requires LHS reference to be evaluated first. - if (!emitDestructuringLHSRef(lhs, &emitted)) { - // [stack] ... SET? RHS LREF* + DestructuringLHSRef lref; + if (!emitDestructuringLHSRef(lhs, flav, lref)) { + // [stack] ... SET? RHS KEY? LREF* return false; } + // Number of stack slots emitted for the LHS reference. + size_t emitted = lref.numReferenceSlots(); + // Duplicate the value being destructured to use as a reference base. - if (!emitDupAt(emitted)) { - // [stack] ... SET? RHS LREF* RHS + if (!emitDupAt(emitted + hasKeyOnStack)) { + // [stack] ... SET? RHS KEY? LREF* RHS return false; } @@ -3878,7 +3860,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, return false; } - if (!emit1(JSOp::NewInit)) { + if (!emit2(JSOp::NewInit, estimatedRestSize)) { // [stack] ... SET? RHS LREF* RHS TARGET return false; } @@ -3906,7 +3888,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, } // Destructure TARGET per this member's lhs. - if (!emitSetOrInitializeDestructuring(lhs, flav)) { + if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) { // [stack] ... RHS return false; } @@ -3945,8 +3927,9 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, // Otherwise this is a computed property name. BigInt keys are parsed // as (synthetic) computed property names, too. MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName)); + MOZ_ASSERT(hasKeyOnStack); - if (!emitComputedPropertyName(&key->as())) { + if (!emit2(JSOp::Pick, emitted + 1)) { // [stack] ... SET? RHS LREF* RHS KEY return false; } @@ -3992,7 +3975,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, } // Destructure PROP per this member's lhs. - if (!emitSetOrInitializeDestructuring(lhs, flav)) { + if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) { // [stack] ... SET? RHS return false; } @@ -4038,7 +4021,8 @@ static bool IsDestructuringRestExclusionSetObjLiteralCompatible( return true; } -bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) { +bool BytecodeEmitter::emitDestructuringObjRestExclusionSet( + ListNode* pattern, uint8_t estimatedRestSize) { MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr)); MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread)); @@ -4050,7 +4034,7 @@ bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) { } } else { // Take the slow but sure way and start off with a blank object. - if (!emit1(JSOp::NewInit)) { + if (!emit2(JSOp::NewInit, estimatedRestSize)) { // [stack] OBJ return false; } @@ -4255,9 +4239,14 @@ bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl, #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT if (declList->isKind(ParseNodeKind::UsingDecl)) { - UsingEmitter uem(this); - - if (!uem.prepareForAssignment(UsingEmitter::Kind::Sync)) { + if (!innermostEmitterScope()->prepareForDisposableAssignment( + UsingHint::Sync)) { + // [stack] ENV? V + return false; + } + } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) { + if (!innermostEmitterScope()->prepareForDisposableAssignment( + UsingHint::Async)) { // [stack] ENV? V return false; } @@ -4290,9 +4279,9 @@ bool BytecodeEmitter::emitAssignmentRhs( // The RHS value to assign is already on the stack, i.e., the next enumeration // value in a for-in or for-of loop. Offset is the location in the stack of the -// already-emitted rhs. If we emitted a JSOp::BindName or JSOp::BindGName, then -// the scope is on the top of the stack and we need to dig one deeper to get -// the right RHS value. +// already-emitted rhs. If we emitted a JSOp::BindUnqualifiedName or +// JSOp::BindUnqualifiedGName, then the scope is on the top of the stack and we +// need to dig one deeper to get the right RHS value. bool BytecodeEmitter::emitAssignmentRhs(uint8_t offset) { if (offset != 1) { return emitPickN(offset - 1); @@ -4440,7 +4429,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, : ElemOpEmitter::Kind::SimpleAssignment, isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (!emitElemObjAndKey(elem, isSuper, *eoe)) { + if (!emitElemObjAndKey(elem, *eoe)) { // [stack] # if Super // [stack] THIS KEY // [stack] # otherwise @@ -4756,7 +4745,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) { isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (!emitElemObjAndKey(elem, isSuper, *eoe)) { + if (!emitElemObjAndKey(elem, *eoe)) { // [stack] # if Super // [stack] THIS KEY // [stack] # otherwise @@ -5261,7 +5250,21 @@ MOZ_NEVER_INLINE bool BytecodeEmitter::emitLexicalScope( kind = lexicalScope->kind(); } - if (!lse.emitScope(kind, lexicalScope->scopeBindings())) { +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + BlockKind blockKind = BlockKind::Other; + if (body->isKind(ParseNodeKind::ForStmt) && + body->as().head()->isKind(ParseNodeKind::ForOf)) { + MOZ_ASSERT(kind == ScopeKind::Lexical); + blockKind = BlockKind::ForOf; + } +#endif + + if (!lse.emitScope(kind, lexicalScope->scopeBindings() +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + , + blockKind +#endif + )) { return false; } @@ -5806,9 +5809,14 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) { #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT if (declarationList->isKind(ParseNodeKind::UsingDecl)) { - UsingEmitter uem(this); - - if (!uem.prepareForAssignment(UsingEmitter::Kind::Sync)) { + if (!innermostEmitterScope()->prepareForDisposableAssignment( + UsingHint::Sync)) { + // [stack] ENV? V + return false; + } + } else if (declarationList->isKind(ParseNodeKind::AwaitUsingDecl)) { + if (!innermostEmitterScope()->prepareForDisposableAssignment( + UsingHint::Async)) { // [stack] ENV? V return false; } @@ -5852,12 +5860,20 @@ bool BytecodeEmitter::emitForOf(ForNode* forOfLoop, // Certain builtins (e.g. Array.from) are implemented in self-hosting // as for-of loops. auto selfHostedIter = getSelfHostedIterFor(forHeadExpr); +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + ForOfEmitter::HeadUsingDeclarationKind headUsingDeclKind = + ForOfEmitter::HeadUsingDeclarationKind::None; + if (forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl)) { + headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Sync; + } else if (forOfHead->kid1()->isKind(ParseNodeKind::AwaitUsingDecl)) { + headUsingDeclKind = ForOfEmitter::HeadUsingDeclarationKind::Async; + } +#endif + ForOfEmitter forOf(this, headLexicalEmitterScope, selfHostedIter, iterKind #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT , - forOfHead->kid1()->isKind(ParseNodeKind::UsingDecl) - ? ForOfEmitter::HasUsingDeclarationInHead::Yes - : ForOfEmitter::HasUsingDeclarationInHead::No + headUsingDeclKind #endif ); @@ -5882,7 +5898,8 @@ bool BytecodeEmitter::emitForOf(ForNode* forOfLoop, MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::LetDecl) || forOfTarget->isKind(ParseNodeKind::ConstDecl) #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - || forOfTarget->isKind(ParseNodeKind::UsingDecl) + || forOfTarget->isKind(ParseNodeKind::UsingDecl) || + forOfTarget->isKind(ParseNodeKind::AwaitUsingDecl) #endif ); } @@ -7258,20 +7275,20 @@ bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) { propExpr->as().isSuper() ? PropOpEmitter::ObjKind::Super : PropOpEmitter::ObjKind::Other); + + if (!poe.prepareForObj()) { + return false; + } + if (propExpr->isSuper()) { - // The expression |delete super.foo;| has to evaluate |super.foo|, - // which could throw if |this| hasn't yet been set by a |super(...)| - // call or the super-base is not an object, before throwing a - // ReferenceError for attempting to delete a super-reference. - UnaryNode* base = &propExpr->expression().as(); + // The expression |delete super.foo;| has to evaluate |super.foo|, which + // could throw if |this| hasn't yet been set by a |super(...)| call. + auto* base = &propExpr->expression().as(); if (!emitGetThisForSuperBase(base)) { // [stack] THIS return false; } } else { - if (!poe.prepareForObj()) { - return false; - } if (!emitPropLHS(propExpr)) { // [stack] OBJ return false; @@ -7292,44 +7309,21 @@ bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) { bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) { MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)); - PropertyByValue* elemExpr = &deleteNode->kid()->as(); + auto* elemExpr = &deleteNode->kid()->as(); bool isSuper = elemExpr->isSuper(); - DebugOnly isPrivate = - elemExpr->key().isKind(ParseNodeKind::PrivateName); - MOZ_ASSERT(!isPrivate); + MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName)); ElemOpEmitter eoe( this, ElemOpEmitter::Kind::Delete, isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (isSuper) { - // The expression |delete super[foo];| has to evaluate |super[foo]|, - // which could throw if |this| hasn't yet been set by a |super(...)| - // call, or trigger side-effects when evaluating ToPropertyKey(foo), - // or also throw when the super-base is not an object, before throwing - // a ReferenceError for attempting to delete a super-reference. - if (!eoe.prepareForObj()) { - // [stack] - return false; - } - UnaryNode* base = &elemExpr->expression().as(); - if (!emitGetThisForSuperBase(base)) { - // [stack] THIS - return false; - } - if (!eoe.prepareForKey()) { - // [stack] THIS - return false; - } - if (!emitTree(&elemExpr->key())) { - // [stack] THIS KEY - return false; - } - } else { - if (!emitElemObjAndKey(elemExpr, false, eoe)) { - // [stack] OBJ KEY - return false; - } + if (!emitElemObjAndKey(elemExpr, eoe)) { + // [stack] # if Super + // [stack] THIS KEY + // [stack] # otherwise + // [stack] OBJ KEY + return false; } + if (!eoe.emitDelete()) { // [stack] # if Super // [stack] THIS @@ -8172,7 +8166,7 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall, bool isSuper = elem->isSuper(); MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); - if (!emitElemObjAndKey(elem, isSuper, eoe)) { + if (!emitElemObjAndKey(elem, eoe)) { // [stack] # if Super // [stack] THIS? THIS KEY // [stack] # otherwise @@ -8250,7 +8244,7 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall, ParseNode* BytecodeEmitter::getCoordNode(ParseNode* callNode, ParseNode* calleeNode, JSOp op, - ListNode* argsList) { + ListNode* argsList) const { ParseNode* coordNode = callNode; if (op == JSOp::Call || op == JSOp::SpreadCall) { // Default to using the location of the `(` itself. @@ -8410,6 +8404,85 @@ bool BytecodeEmitter::emitOptionalCall(CallNode* callNode, OptionalEmitter& oe, return true; } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +bool BytecodeEmitter::emitSelfHostedDisposeResources(CallNode* callNode, + DisposalKind kind) { + ListNode* argsList = callNode->args(); + MOZ_ASSERT(argsList->count() == 2); + + ParseNode* resourcesNode = argsList->head(); + ParseNode* countNode = resourcesNode->pn_next; + + DisposalEmitter de(this, bool(kind)); + + if (!emit1(JSOp::False)) { + // [stack] THROWING + return false; + } + + if (!emit1(JSOp::Undefined)) { + // [stack] THROWING UNDEF + return false; + } + + if (!de.prepareForDisposeCapability()) { + // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF + return false; + } + + if (!emitTree(resourcesNode)) { + // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES + return false; + } + + if (!emitTree(countNode)) { + // [stack] RVAL? NEEDS-AWAIT? HAS-AWAITED? THROWING UNDEF RESOURCES COUNT + return false; + } + + if (!de.emitEnd(*innermostEmitterScope())) { + // [stack] EXC THROWING + return false; + } + + // [stack] EXC THROWING + + InternalIfEmitter ifThrow(this); + + if (!ifThrow.emitThenElse()) { + // [stack] EXC + return false; + } + + if (!emit1(JSOp::Throw)) { + // [stack] + return false; + } + + if (!ifThrow.emitElse()) { + // [stack] EXC + return false; + } + + if (!emit1(JSOp::Pop)) { + // [stack] + return false; + } + + if (!ifThrow.emitEnd()) { + // [stack] + return false; + } + + if (!emit1(JSOp::Undefined)) { + // [stack] RVAL + return false; + } + + return true; +} +#endif + bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) { /* * Emit callable invocation or operator new (constructor call) code. @@ -8508,6 +8581,16 @@ bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) { if (calleeName == TaggedParserAtomIndex::WellKnown::IteratorClose()) { return emitSelfHostedIteratorClose(callNode); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (calleeName == + TaggedParserAtomIndex::WellKnown::DisposeResourcesAsync()) { + return emitSelfHostedDisposeResources(callNode, DisposalKind::Async); + } + if (calleeName == + TaggedParserAtomIndex::WellKnown::DisposeResourcesSync()) { + return emitSelfHostedDisposeResources(callNode, DisposalKind::Sync); + } +#endif #ifdef DEBUG if (calleeName == TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() || @@ -8633,12 +8716,104 @@ bool BytecodeEmitter::emitRightAssociative(ListNode* node) { return true; } +Maybe ParseNodeToConstantCompareOperand( + ParseNode* constant) { + switch (constant->getKind()) { + case ParseNodeKind::NumberExpr: { + double d = constant->as().value(); + int32_t ival; + if (NumberEqualsInt32(d, &ival)) { + if (ConstantCompareOperand::CanEncodeInt32ValueAsOperand(ival)) { + return Some(ConstantCompareOperand((int8_t)ival)); + } + } + return Nothing(); + } + case ParseNodeKind::TrueExpr: + case ParseNodeKind::FalseExpr: + return Some( + ConstantCompareOperand(constant->isKind(ParseNodeKind::TrueExpr))); + case ParseNodeKind::NullExpr: + return Some( + ConstantCompareOperand(ConstantCompareOperand::EncodedType::Null)); + case ParseNodeKind::RawUndefinedExpr: + return Some(ConstantCompareOperand( + ConstantCompareOperand::EncodedType::Undefined)); + default: + return Nothing(); + } +} + +bool BytecodeEmitter::tryEmitConstantEq(ListNode* node, JSOp op, + bool* emitted) { + // We ignore long chains of === or !==, we + // only optimise cases a === b or a !== b + if (node->count() != 2) { + *emitted = false; + return true; + } + + JSOp constantOp; + switch (op) { + case JSOp::StrictEq: + constantOp = JSOp::StrictConstantEq; + break; + case JSOp::StrictNe: + constantOp = JSOp::StrictConstantNe; + break; + default: + *emitted = false; + return true; + } + + ParseNode* left = node->head(); + ParseNode* right = node->head()->pn_next; + + ParseNode* expressionNode; + ParseNode* constantNode; + if (left->isConstant()) { + expressionNode = right; + constantNode = left; + } else if (right->isConstant()) { + expressionNode = left; + constantNode = right; + } else { + *emitted = false; + return true; + } + + Maybe operand = + ParseNodeToConstantCompareOperand(constantNode); + if (operand.isNothing()) { + *emitted = false; + return true; + } + + if (!emitTree(expressionNode)) { + return false; + } + + if (!emitUint16Operand(constantOp, operand->rawValue())) { + return false; + } + + *emitted = true; + return true; +} + bool BytecodeEmitter::emitLeftAssociative(ListNode* node) { + JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind()); + bool constantEqEmitted = false; + if (!tryEmitConstantEq(node, op, &constantEqEmitted)) { + return false; + } + if (constantEqEmitted) { + return true; + } // Left-associative operator chain. if (!emitTree(node->head())) { return false; } - JSOp op = BinaryOpParseNodeKindToJSOp(node->getKind()); ParseNode* nextExpr = node->head()->pn_next; do { if (!updateSourceCoordNotesIfNonLiteral(nextExpr)) { @@ -9161,9 +9336,8 @@ bool BytecodeEmitter::emitConditionalExpression( // constant name or numeric index, there is no accessor specified, and the value // can be encoded by an ObjLiteral instruction (constant number, string, // boolean, null/undefined). -void BytecodeEmitter::isPropertyListObjLiteralCompatible(ListNode* obj, - bool* withValues, - bool* withoutValues) { +void BytecodeEmitter::isPropertyListObjLiteralCompatible( + ListNode* obj, bool* withValues, bool* withoutValues) const { bool keysOK = true; bool valuesOK = true; uint32_t propCount = 0; @@ -9230,7 +9404,7 @@ void BytecodeEmitter::isPropertyListObjLiteralCompatible(ListNode* obj, *withoutValues = keysOK; } -bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) { +bool BytecodeEmitter::isArrayObjLiteralCompatible(ListNode* array) const { for (ParseNode* elem : array->contents()) { if (elem->isKind(ParseNodeKind::Spread)) { return false; @@ -9865,7 +10039,7 @@ bool BytecodeEmitter::emitObjLiteralArray(ListNode* array) { return true; } -bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) { +bool BytecodeEmitter::isRHSObjLiteralCompatible(ParseNode* value) const { return value->isKind(ParseNodeKind::NumberExpr) || value->isKind(ParseNodeKind::TrueExpr) || value->isKind(ParseNodeKind::FalseExpr) || @@ -9931,7 +10105,7 @@ static bool HasDecorators(ParseNode* member) { #endif mozilla::Maybe BytecodeEmitter::setupMemberInitializers( - ListNode* classMembers, FieldPlacement placement) { + ListNode* classMembers, FieldPlacement placement) const { bool isStatic = placement == FieldPlacement::Static; size_t numFields = 0; @@ -10214,7 +10388,7 @@ bool BytecodeEmitter::emitCreateMemberInitializers(ClassEmitter& ce, TaggedParserAtomIndex name = classMethod->name().as().atom(); AccessorType accessorType = classMethod->accessorType(); - StringBuffer storedMethodName(fc); + StringBuilder storedMethodName(fc); if (!storedMethodName.append(parserAtoms(), name)) { return false; } @@ -10492,7 +10666,7 @@ bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce, // private method body. TaggedParserAtomIndex name = classMethod->name().as().atom(); AccessorType accessorType = classMethod->accessorType(); - StringBuffer storedMethodName(fc); + StringBuilder storedMethodName(fc); if (!storedMethodName.append(parserAtoms(), name)) { return false; } @@ -10665,8 +10839,9 @@ bool BytecodeEmitter::emitPrivateMethodInitializer( return true; } -const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall() { - for (BytecodeEmitter* current = this; current; current = current->parent) { +const MemberInitializers& BytecodeEmitter::findMemberInitializersForCall() + const { + for (const auto* current = this; current; current = current->parent) { if (current->sc->isFunctionBox()) { FunctionBox* funbox = current->sc->asFunctionBox(); @@ -11384,127 +11559,6 @@ bool BytecodeEmitter::emitSpreadIntoArray(UnaryNode* elem) { return true; } -#ifdef ENABLE_RECORD_TUPLE -bool BytecodeEmitter::emitRecordLiteral(ListNode* record) { - if (!emitUint32Operand(JSOp::InitRecord, record->count())) { - // [stack] RECORD - return false; - } - - for (ParseNode* propdef : record->contents()) { - if (propdef->isKind(ParseNodeKind::Spread)) { - if (!emitTree(propdef->as().kid())) { - // [stack] RECORD SPREADEE - return false; - } - if (!emit1(JSOp::AddRecordSpread)) { - // [stack] RECORD - return false; - } - } else { - BinaryNode* prop = &propdef->as(); - - ParseNode* key = prop->left(); - ParseNode* value = prop->right(); - - switch (key->getKind()) { - case ParseNodeKind::ObjectPropertyName: - if (!emitStringOp(JSOp::String, key->as().atom())) { - return false; - } - break; - case ParseNodeKind::ComputedName: - if (!emitTree(key->as().kid())) { - return false; - } - break; - default: - MOZ_ASSERT(key->isKind(ParseNodeKind::StringExpr) || - key->isKind(ParseNodeKind::NumberExpr) || - key->isKind(ParseNodeKind::BigIntExpr)); - if (!emitTree(key)) { - return false; - } - break; - } - // [stack] RECORD KEY - - if (!emitTree(value)) { - // [stack] RECORD KEY VALUE - return false; - } - - if (!emit1(JSOp::AddRecordProperty)) { - // [stack] RECORD - return false; - } - } - } - - if (!emit1(JSOp::FinishRecord)) { - // [stack] RECORD - return false; - } - - return true; -} - -bool BytecodeEmitter::emitTupleLiteral(ListNode* tuple) { - if (!emitUint32Operand(JSOp::InitTuple, tuple->count())) { - // [stack] TUPLE - return false; - } - - for (ParseNode* elt : tuple->contents()) { - if (elt->isKind(ParseNodeKind::Spread)) { - ParseNode* expr = elt->as().kid(); - auto selfHostedIter = getSelfHostedIterFor(expr); - - if (!emitIterable(expr, selfHostedIter)) { - // [stack] TUPLE ITERABLE - return false; - } - if (!emitIterator(selfHostedIter)) { - // [stack] TUPLE NEXT ITER - return false; - } - if (!emit2(JSOp::Pick, 2)) { - // [stack] NEXT ITER TUPLE - return false; - } - if (!emitSpread(selfHostedIter, /* spreadeeStackItems = */ 1, - JSOp::AddTupleElement)) { - // [stack] TUPLE - return false; - } - } else { - // Update location to throw errors about non-primitive elements - // in the correct position. - if (!updateSourceCoordNotesIfNonLiteral(elt)) { - return false; - } - - if (!emitTree(elt)) { - // [stack] TUPLE VALUE - return false; - } - - if (!emit1(JSOp::AddTupleElement)) { - // [stack] TUPLE - return false; - } - } - } - - if (!emit1(JSOp::FinishTuple)) { - // [stack] TUPLE - return false; - } - - return true; -} -#endif - static inline JSOp UnaryOpParseNodeKindToJSOp(ParseNodeKind pnk) { switch (pnk) { case ParseNodeKind::ThrowStmt: @@ -11616,15 +11670,7 @@ bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) { type = JSTYPE_SYMBOL; } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) { type = JSTYPE_BIGINT; - } -#ifdef ENABLE_RECORD_TUPLE - else if (typeName == TaggedParserAtomIndex::WellKnown::record()) { - type = JSTYPE_RECORD; - } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) { - type = JSTYPE_TUPLE; - } -#endif - else { + } else { *emitted = false; return true; } @@ -11876,7 +11922,8 @@ bool BytecodeEmitter::emitLexicalInitialization(TaggedParserAtomIndex name) { // The caller has pushed the RHS to the top of the stack. Assert that the // binding can be initialized without a binding object on the stack, and that - // no JSOp::BindName or JSOp::BindGName ops were emitted. + // no JSOp::BindUnqualifiedName or JSOp::BindUnqualifiedGName ops were + // emitted. MOZ_ASSERT(noe.loc().isLexical() || noe.loc().isSynthetic() || noe.loc().isPrivateMethod()); MOZ_ASSERT(!noe.emittedBindOp()); @@ -12067,7 +12114,15 @@ bool BytecodeEmitter::emitClass( return false; } } else { - if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack)) { + int membersCount = 0; + for (ParseNode* node : classMembers->contents()) { + if (node->getKind() == ParseNodeKind::ClassField) { + membersCount++; + } + } + membersCount = (membersCount > 255) ? 255 : membersCount; + if (!ce.emitClass(innerName, nameForAnonymousClass, hasNameOnStack, + uint8_t(membersCount))) { // [stack] HOMEOBJ return false; } @@ -12178,9 +12233,7 @@ bool BytecodeEmitter::emitClass( bool needsHomeObject = ctor->funbox()->needsHomeObject(); // HERITAGE is consumed inside emitFunction. if (nameKind == ClassNameKind::InferredName) { - if (!setFunName(ctor->funbox(), nameForAnonymousClass)) { - return false; - } + setFunName(ctor->funbox(), nameForAnonymousClass); } if (!emitFunction(ctor, isDerived)) { // [stack] HOMEOBJ CTOR @@ -12209,6 +12262,7 @@ bool BytecodeEmitter::emitClass( } if (!emitUnpickN(2)) { // [stack] ADDINIT? UNDEFINED CTOR HOMEOBJ + return false; } #endif @@ -12726,7 +12780,7 @@ bool BytecodeEmitter::emitTree( ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (!emitElemObjAndKey(elem, isSuper, eoe)) { + if (!emitElemObjAndKey(elem, eoe)) { // [stack] # if Super // [stack] THIS KEY // [stack] # otherwise @@ -12783,6 +12837,7 @@ bool BytecodeEmitter::emitTree( } break; #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + case ParseNodeKind::AwaitUsingDecl: case ParseNodeKind::UsingDecl: if (!emitDeclarationList(&pn->as())) { return false; @@ -12974,20 +13029,6 @@ bool BytecodeEmitter::emitTree( } break; -#ifdef ENABLE_RECORD_TUPLE - case ParseNodeKind::RecordExpr: - if (!emitRecordLiteral(&pn->as())) { - return false; - } - break; - - case ParseNodeKind::TupleExpr: - if (!emitTupleLiteral(&pn->as())) { - return false; - } - break; -#endif - case ParseNodeKind::PropertyNameExpr: case ParseNodeKind::PosHolder: MOZ_FALLTHROUGH_ASSERT( @@ -13171,7 +13212,8 @@ bool BytecodeEmitter::intoScriptStencil(ScriptIndex scriptIndex) { return true; } -SelfHostedIter BytecodeEmitter::getSelfHostedIterFor(ParseNode* parseNode) { +SelfHostedIter BytecodeEmitter::getSelfHostedIterFor( + ParseNode* parseNode) const { if (emitterMode == BytecodeEmitter::SelfHosting && parseNode->isKind(ParseNodeKind::CallExpr)) { auto* callee = parseNode->as().callee(); diff --git a/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.h index c1e9ded9ed7..68cc3019bbb 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/BytecodeEmitter.h @@ -55,6 +55,7 @@ namespace frontend { class BytecodeOffset; class CallOrNewEmitter; class ClassEmitter; +class DestructuringLHSRef; class ElemOpEmitter; class EmitterScope; class ErrorReporter; @@ -424,12 +425,12 @@ struct MOZ_STACK_CLASS BytecodeEmitter { return true; } - bool isInLoop(); - [[nodiscard]] bool checkSingletonContext(); + bool isInLoop() const; + [[nodiscard]] bool checkSingletonContext() const; - bool needsImplicitThis(); + bool needsImplicitThis() const; - size_t countThisEnvironmentHops(); + size_t countThisEnvironmentHops() const; [[nodiscard]] bool emitThisEnvironmentCallee(); [[nodiscard]] bool emitSuperBase(); @@ -452,8 +453,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter { } } - void reportError(ParseNode* pn, unsigned errorNumber, ...); - void reportError(uint32_t offset, unsigned errorNumber, ...); + void reportError(ParseNode* pn, unsigned errorNumber, ...) const; + void reportError(uint32_t offset, unsigned errorNumber, ...) const; // Fill in a ScriptStencil using this BCE data. bool intoScriptStencil(ScriptIndex scriptIndex); @@ -468,10 +469,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter { // statement, we define useless code as code with no side effects, because // the main effect, the value left on the stack after the code executes, // will be discarded by a pop bytecode. - [[nodiscard]] bool checkSideEffects(ParseNode* pn, bool* answer); + [[nodiscard]] bool checkSideEffects(ParseNode* pn, bool* answer) const; #ifdef DEBUG - [[nodiscard]] bool checkStrictOrSloppy(JSOp op); + [[nodiscard]] bool checkStrictOrSloppy(JSOp op) const; #endif // Add TryNote to the tryNoteList array. The start and end offset are @@ -521,7 +522,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { // Calculate the `nslots` value for ImmutableScriptData constructor parameter. // Fails if it overflows. - [[nodiscard]] bool getNslots(uint32_t* nslots); + [[nodiscard]] bool getNslots(uint32_t* nslots) const; // Emit function code for the tree rooted at body. [[nodiscard]] bool emitFunctionScript(FunctionNode* funNode); @@ -532,8 +533,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool updateSourceCoordNotes(uint32_t offset); [[nodiscard]] bool updateSourceCoordNotesIfNonLiteral(ParseNode* node); - JSOp strictifySetNameOp(JSOp op); - [[nodiscard]] bool emitCheck(JSOp op, ptrdiff_t delta, BytecodeOffset* offset); @@ -610,7 +609,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr); [[nodiscard]] bool emitCallIncDec(UnaryNode* incDec); - uint32_t getOffsetForLoop(ParseNode* nextpn); + uint32_t getOffsetForLoop(ParseNode* nextpn) const; enum class GotoKind { Break, Continue }; [[nodiscard]] bool emitGoto(NestableControl* target, GotoKind kind); @@ -641,8 +640,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter { // values) or in template mode (field names only, no values) for the property // list? void isPropertyListObjLiteralCompatible(ListNode* obj, bool* withValues, - bool* withoutValues); - bool isArrayObjLiteralCompatible(ListNode* array); + bool* withoutValues) const; + bool isArrayObjLiteralCompatible(ListNode* array) const; [[nodiscard]] bool emitPropertyList(ListNode* obj, PropertyEmitter& pe, PropListType type); @@ -656,13 +655,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitObjLiteralArray(ListNode* array); // Is a field value JSOp::Object-compatible? - [[nodiscard]] bool isRHSObjLiteralCompatible(ParseNode* value); + [[nodiscard]] bool isRHSObjLiteralCompatible(ParseNode* value) const; [[nodiscard]] bool emitObjLiteralValue(ObjLiteralWriter& writer, ParseNode* value); mozilla::Maybe setupMemberInitializers( - ListNode* classMembers, FieldPlacement placement); + ListNode* classMembers, FieldPlacement placement) const; [[nodiscard]] bool emitCreateFieldKeys(ListNode* obj, FieldPlacement placement); [[nodiscard]] bool emitCreateMemberInitializers(ClassEmitter& ce, @@ -673,7 +672,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { bool hasHeritage #endif ); - const MemberInitializers& findMemberInitializersForCall(); + const MemberInitializers& findMemberInitializersForCall() const; [[nodiscard]] bool emitInitializeInstanceMembers( bool isDerivedClassConstructor); [[nodiscard]] bool emitInitializeStaticFields(ListNode* classMembers); @@ -751,9 +750,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitComputedPropertyName(UnaryNode* computedPropName); - [[nodiscard]] bool emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key, - ElemOpEmitter& eoe); - // Emit bytecode to put operands for a JSOp::GetElem/CallElem/SetElem/DelElem // opcode onto the stack in the right order. In the case of SetElem, the // value to be assigned must already be pushed. @@ -761,7 +757,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitElemOperands(PropertyByValue* elem, EmitElemOption opts); - [[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, + [[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem, ElemOpEmitter& eoe); [[nodiscard]] bool emitElemOpBase(JSOp op); @@ -790,20 +786,21 @@ struct MOZ_STACK_CLASS BytecodeEmitter { // If the lhs expression is object property |OBJ.prop|, it emits |OBJ|. // If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|. // If there's nothing to evaluate for the reference, it emits nothing. - // |emitted| parameter receives the number of values pushed onto the stack. [[nodiscard]] bool emitDestructuringLHSRef(ParseNode* target, - size_t* emitted); + DestructuringFlavor flav, + DestructuringLHSRef& lref); // emitSetOrInitializeDestructuring assumes the lhs expression's reference // and the to-be-destructured value has been pushed on the stack. It emits // code to destructure a single lhs expression (either a name or a compound // []/{} expression). - [[nodiscard]] bool emitSetOrInitializeDestructuring(ParseNode* target, - DestructuringFlavor flav); + [[nodiscard]] bool emitSetOrInitializeDestructuring( + ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref); // emitDestructuringObjRestExclusionSet emits the property exclusion set // for the rest-property in an object pattern. - [[nodiscard]] bool emitDestructuringObjRestExclusionSet(ListNode* pattern); + [[nodiscard]] bool emitDestructuringObjRestExclusionSet(ListNode* pattern, + uint8_t setSize); // emitDestructuringOps assumes the to-be-destructured value has been // pushed on the stack and emits code to destructure each part of a [] or @@ -822,7 +819,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { // two in the latter case) elements from the stack. [[nodiscard]] bool emitCopyDataProperties(CopyOption option); - JSOp getIterCallOp(JSOp callOp, SelfHostedIter selfHostedIter); + JSOp getIterCallOp(JSOp callOp, SelfHostedIter selfHostedIter) const; // Push the operands for emit(Async)Iterator onto the stack. [[nodiscard]] bool emitIterable(ParseNode* value, @@ -872,7 +869,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitAnonymousFunctionWithComputedName( ParseNode* node, FunctionPrefixKind prefixKind); - [[nodiscard]] bool setFunName(FunctionBox* fun, TaggedParserAtomIndex name); + void setFunName(FunctionBox* fun, TaggedParserAtomIndex name) const; [[nodiscard]] bool emitInitializer(ParseNode* initializer, ParseNode* pattern); @@ -929,6 +926,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitUnary(UnaryNode* unaryNode); [[nodiscard]] bool emitRightAssociative(ListNode* node); + [[nodiscard]] bool tryEmitConstantEq(ListNode* node, JSOp op, bool* emitted); [[nodiscard]] bool emitLeftAssociative(ListNode* node); [[nodiscard]] bool emitPrivateInExpr(ListNode* node); [[nodiscard]] bool emitShortCircuit(ListNode* node, ValueUsage valueUsage); @@ -942,7 +940,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] ParseNode* getCoordNode(ParseNode* callNode, ParseNode* calleeNode, JSOp op, - ListNode* argsList); + ListNode* argsList) const; [[nodiscard]] bool emitArguments(ListNode* argsList, bool isCall, bool isSpread, CallOrNewEmitter& cone); @@ -969,6 +967,11 @@ struct MOZ_STACK_CLASS BytecodeEmitter { [[nodiscard]] bool emitSelfHostedSetCanonicalName(CallNode* callNode); [[nodiscard]] bool emitSelfHostedArgumentsLength(CallNode* callNode); [[nodiscard]] bool emitSelfHostedGetArgument(CallNode* callNode); +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + enum class DisposalKind : bool { Sync, Async }; + [[nodiscard]] bool emitSelfHostedDisposeResources(CallNode* callNode, + DisposalKind kind); +#endif #ifdef DEBUG void assertSelfHostedExpectedTopLevel(ParseNode* node); void assertSelfHostedUnsafeGetReservedSlot(ListNode* argsList); @@ -1045,11 +1048,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter { CallOrNewEmitter& cone, OptionalEmitter& oe); -#ifdef ENABLE_RECORD_TUPLE - [[nodiscard]] bool emitRecordLiteral(ListNode* record); - [[nodiscard]] bool emitTupleLiteral(ListNode* tuple); -#endif - [[nodiscard]] bool emitExportDefault(BinaryNode* exportNode); [[nodiscard]] bool emitReturnRval() { return emit1(JSOp::RetRval); } @@ -1076,7 +1074,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { #endif private: - [[nodiscard]] SelfHostedIter getSelfHostedIterFor(ParseNode* parseNode); + [[nodiscard]] SelfHostedIter getSelfHostedIterFor(ParseNode* parseNode) const; [[nodiscard]] bool emitSelfHostedGetBuiltinConstructorOrPrototype( CallNode* callNode, bool isConstructor); diff --git a/src/third_party/mozjs/extract/js/src/frontend/BytecodeSection.h b/src/third_party/mozjs/extract/js/src/frontend/BytecodeSection.h index 0e7ed3d4475..be0668534b2 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/BytecodeSection.h +++ b/src/third_party/mozjs/extract/js/src/frontend/BytecodeSection.h @@ -105,7 +105,7 @@ struct MOZ_STACK_CLASS GCThingList { uint32_t length() const { return vector.length(); } - const ScriptThingsStackVector& objects() { return vector; } + const ScriptThingsStackVector& objects() const { return vector; } AbstractScopePtr getScope(size_t index) const; @@ -172,8 +172,8 @@ static constexpr size_t MaxSrcNotesLength = INT32_MAX; // Have a few inline elements, so as to avoid heap allocation for tiny // sequences. See bug 1390526. -typedef Vector BytecodeVector; -typedef Vector SrcNotesVector; +using BytecodeVector = Vector; +using SrcNotesVector = Vector; // Bytecode and all data directly associated with specific opcode/index inside // bytecode is stored in this class. diff --git a/src/third_party/mozjs/extract/js/src/frontend/CompilationStencil.h b/src/third_party/mozjs/extract/js/src/frontend/CompilationStencil.h index c1e98f47540..721b7ed45f8 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/CompilationStencil.h +++ b/src/third_party/mozjs/extract/js/src/frontend/CompilationStencil.h @@ -171,29 +171,29 @@ class InputScope { }; inline InputScope enclosing() const; bool hasOnChain(ScopeKind kind) const { - return scope_.match( - [=](const Scope* ptr) { return ptr->hasOnChain(kind); }, - [=](const ScopeStencilRef& ref) { - ScopeStencilRef it = ref; - while (true) { - const ScopeStencil& scope = it.scope(); - if (scope.kind() == kind) { - return true; - } - if (scope.kind() == ScopeKind::Module && - kind == ScopeKind::Global) { - return true; - } - if (!scope.hasEnclosing()) { - break; - } - new (&it) ScopeStencilRef{ref.context_, scope.enclosing()}; - } - return false; - }, - [=](const FakeStencilGlobalScope&) { - return kind == ScopeKind::Global; - }); + return scope_.match([=](const Scope* ptr) { return ptr->hasOnChain(kind); }, + [=](const ScopeStencilRef& ref) { + ScopeStencilRef it = ref; + while (true) { + const ScopeStencil& scope = it.scope(); + if (scope.kind() == kind) { + return true; + } + if (scope.kind() == ScopeKind::Module && + kind == ScopeKind::Global) { + return true; + } + if (!scope.hasEnclosing()) { + break; + } + new (&it) ScopeStencilRef{ref.context_, + scope.enclosing()}; + } + return false; + }, + [=](const FakeStencilGlobalScope&) { + return kind == ScopeKind::Global; + }); } uint32_t environmentChainLength() const { return scope_.match( @@ -341,7 +341,15 @@ class InputScript { bool isStencil() const { return script_.match([](const BaseScript* ptr) { return false; }, [](const ScriptStencilRef&) { return true; }); - }; + } + + ScriptSourceObject* sourceObject() const { + return script_.match( + [](const BaseScript* ptr) { return ptr->sourceObject(); }, + [](const ScriptStencilRef&) { + return static_cast(nullptr); + }); + } }; // Iterator for walking the scope chain, this is identical to ScopeIter but @@ -1142,7 +1150,7 @@ struct CompilationStencil { // modes. // // See: JS::StencilAddRef/Release - mutable mozilla::Atomic refCount{0}; + mutable mozilla::Atomic refCount_{0}; private: // On-heap ExtensibleCompilationStencil that this CompilationStencil owns, @@ -1164,7 +1172,8 @@ struct CompilationStencil { StorageType storageType = StorageType::Owned; // Value of CanLazilyParse(CompilationInput) on compilation. - // Used during instantiation. + // Used during instantiation, and also queried by + // InitialStencilAndDelazifications. bool canLazilyParse = false; // If this stencil is a delazification, this identifies location of the @@ -1223,13 +1232,16 @@ struct CompilationStencil { // Construct a CompilationStencil explicit CompilationStencil(ScriptSource* source) - : alloc(LifoAllocChunkSize), source(source) {} + : alloc(LifoAllocChunkSize, js::BackgroundMallocArena), source(source) {} // Take the ownership of on-heap ExtensibleCompilationStencil and // borrow from it. explicit CompilationStencil( UniquePtr&& extensibleStencil); + void AddRef(); + void Release(); + protected: void borrowFromExtensibleCompilationStencil( ExtensibleCompilationStencil& extensibleStencil); @@ -1270,15 +1282,9 @@ struct CompilationStencil { [[nodiscard]] bool delazifySelfHostedFunction(JSContext* cx, CompilationAtomCache& atomCache, ScriptIndexRange range, + Handle name, JS::Handle fun); - [[nodiscard]] bool serializeStencils(JSContext* cx, CompilationInput& input, - JS::TranscodeBuffer& buf, - bool* succeededOut = nullptr) const; - [[nodiscard]] bool deserializeStencils( - FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - const JS::TranscodeRange& range, bool* succeededOut = nullptr); - // To avoid any misuses, make sure this is neither copyable or assignable. CompilationStencil(const CompilationStencil&) = delete; CompilationStencil(CompilationStencil&&) = delete; @@ -1288,7 +1294,7 @@ struct CompilationStencil { ~CompilationStencil() { // We can mix UniquePtr<..> and RefPtr<..>. This asserts that a UniquePtr // does not delete a reference-counted stencil. - MOZ_ASSERT(!refCount); + MOZ_ASSERT(!refCount_); } #endif @@ -1308,7 +1314,9 @@ struct CompilationStencil { bool isModule() const; - bool hasMultipleReference() const { return refCount > 1; } + bool hasAsmJS() const; + + bool hasMultipleReference() const { return refCount_ > 1; } bool hasOwnedBorrow() const { return storageType == StorageType::OwnedExtensible; @@ -1333,6 +1341,151 @@ struct CompilationStencil { #endif }; +// A Map from a function key to the ScriptIndex in the initial stencil. +class FunctionKeyToScriptIndexMap { + using FunctionKey = SourceExtent::FunctionKey; + mozilla::HashMap, js::SystemAllocPolicy> + map_; + + template + [[nodiscard]] bool init(FrontendContext* fc, const T& scriptExtra, + size_t scriptExtraSize); + + public: + FunctionKeyToScriptIndexMap() = default; + + [[nodiscard]] bool init(FrontendContext* fc, + const CompilationStencil* initial); + [[nodiscard]] bool init(FrontendContext* fc, + const ExtensibleCompilationStencil* initial); + + mozilla::Maybe get(FunctionKey key) const; + + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { + return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); + } +}; + +// A class to Associate the initial stencil and the delazifications. +// +// This struct is initialized with the initial stencil, with an empty set of +// delazifications. +// The delazifications_ vector is fixed-size, pre-allocated for each script +// stencil, excluding the top-level script. +// +// The delazifications_ vector elements are initialized with nullptr, and +// monotonically populated with each delazification result. +// Only the first delazification for the given function is used. +// +// This struct is supposed to be read/write from multiple threads, and all +// operations, except init, are thread-safe. +struct InitialStencilAndDelazifications { + private: + using FunctionKey = SourceExtent::FunctionKey; + + // Shared reference to the initial stencil. + RefPtr initial_; + + // Exclusively owning pointers for delazifications. + // + // The i-th element is for ScriptIndex(i-1). + // + // If the initial stencil is known to be fully-parsed, this vector is + // 0-sized and unused. + Vector, 0, js::SystemAllocPolicy> + delazifications_; + + // A Map from a function key to the ScriptIndex in the initial stencil. + // + // If the initial stencil is known to be fully-parsed, this map is + // uninitialized and unused + FunctionKeyToScriptIndexMap functionKeyToInitialScriptIndex_; + + mutable mozilla::Atomic refCount_{0}; + + public: + InitialStencilAndDelazifications() = default; + ~InitialStencilAndDelazifications(); + + void AddRef(); + void Release(); + + [[nodiscard]] bool init(FrontendContext* fc, + const CompilationStencil* initial); + + // Get the initial stencil. + // As long as this instance is initialized, this returns non-null pointer. + const CompilationStencil* getInitial() const; + + // Returns true if the initial stencil is compiled with + // CanLazilyParse(CompilationInput). + // + // If this returns false: + // * the delazifications_ vector is not allocated + // * the functionKeyToInitialScriptIndex_ is not initialized + // * getDelazificationAt and storeDelazification shouldn't be called + // * getMerged shouldn't be called, and getInitial should be used instead + bool canLazilyParse() const { return initial_->canLazilyParse; } + + // Return the delazification stencil if it's already populated. + // Returns nullptr otherwise. + // + // The functionIndex parameter is the index of the corresponding script + // stencil (0-indexed, with the index 0 being the top-level script). + // + // if the extent is used instead, it calculates functionIndex and returns + // the delazification stencil if the functionIndex is found and it's already + // populated. + // Returns nullptr otherwise. + const CompilationStencil* getDelazificationAt(size_t functionIndex) const; + const CompilationStencil* getDelazificationFor( + const SourceExtent& extent) const; + + // Try storing the delazification stencil. + // + // The `delazification` stencil should have only one ref count. + // + // If the function was not yet delazified and populated, the `delazification` + // is stored into the vector and the ownership is transferred to the vector, + // and the same `delazification`'s pointer is returned. + // + // If the function was already delazified and stored, the passed + // `delazification` is discared, and the already delazified stencil's pointer + // is returned. + // + // This function is infallible and never returns nullptr. + const CompilationStencil* storeDelazification( + RefPtr&& delazification); + + // Create single CompilationStencil that reflects the initial stencil + // and the all delazifications. + // + // Returns nullptr if any error happens, and sets exception on the + // FrontendContext. + CompilationStencil* getMerged(FrontendContext* fc) const; + + bool hasAsmJS() const; + + // Instantiate the initial stencil and all delazifications populated so far. + [[nodiscard]] static bool instantiateStencils( + JSContext* cx, CompilationInput& input, + InitialStencilAndDelazifications& stencils, + CompilationGCOutput& gcOutput); + + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { + return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); + } + +#if defined(DEBUG) || defined(JS_JITSPEW) + void dump() const; + void dump(js::JSONPrinter& json) const; + void dumpFields(js::JSONPrinter& json) const; +#endif +}; + // The top level struct of stencil specialized for extensible case. // Used as the temporary storage during compilation, an the compilation output. // @@ -1368,7 +1521,7 @@ struct ExtensibleCompilationStencil { Vector scopeNames; Vector regExpData; - Vector bigIntData; + BigIntStencilVector bigIntData; Vector objLiteralData; // Table of parser atoms for this compilation. @@ -1389,7 +1542,8 @@ struct ExtensibleCompilationStencil { ExtensibleCompilationStencil(ExtensibleCompilationStencil&& other) noexcept : canLazilyParse(other.canLazilyParse), functionKey(other.functionKey), - alloc(CompilationStencil::LifoAllocChunkSize), + alloc(CompilationStencil::LifoAllocChunkSize, + js::BackgroundMallocArena), source(std::move(other.source)), scriptData(std::move(other.scriptData)), scriptExtra(std::move(other.scriptExtra)), @@ -1462,6 +1616,8 @@ struct ExtensibleCompilationStencil { bool isModule() const; + bool hasAsmJS() const; + inline size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); @@ -1963,15 +2119,8 @@ struct CompilationStencilMerger { // nullptr. UniquePtr initial_; - // A Map from function key to the ScriptIndex in the initial stencil. - using FunctionKeyToScriptIndexMap = - mozilla::HashMap, - js::SystemAllocPolicy>; FunctionKeyToScriptIndexMap functionKeyToInitialScriptIndex_; - [[nodiscard]] bool buildFunctionKeyToIndex(FrontendContext* fc); - ScriptIndex getInitialScriptIndexFor( const CompilationStencil& delazification) const; @@ -1994,6 +2143,14 @@ struct CompilationStencilMerger { [[nodiscard]] bool addDelazification( FrontendContext* fc, const CompilationStencil& delazification); + // Merge the delazification stencil into the initial stencil if the + // delazification stencil can be merged. + // + // If the delazification's enclosing function is not yet merged, this does + // do nothing. + [[nodiscard]] bool maybeAddDelazification( + FrontendContext* fc, const CompilationStencil& delazification); + ExtensibleCompilationStencil& getResult() const { return *initial_; } UniquePtr takeResult() { return std::move(initial_); @@ -2088,4 +2245,16 @@ const ScriptStencilExtra& ScriptStencilRef::scriptExtra() const { } // namespace frontend } // namespace js +namespace mozilla { +template <> +struct RefPtrTraits { + static void AddRef(js::frontend::CompilationStencil* stencil) { + stencil->AddRef(); + } + static void Release(js::frontend::CompilationStencil* stencil) { + stencil->Release(); + } +}; +} // namespace mozilla + #endif // frontend_CompilationStencil_h diff --git a/src/third_party/mozjs/extract/js/src/frontend/CompileScript.cpp b/src/third_party/mozjs/extract/js/src/frontend/CompileScript.cpp deleted file mode 100644 index b561d7d1247..00000000000 --- a/src/third_party/mozjs/extract/js/src/frontend/CompileScript.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "js/experimental/CompileScript.h" - -#include "frontend/BytecodeCompiler.h" // frontend::{CompileGlobalScriptToStencil, ParseModuleToStencil} -#include "frontend/CompilationStencil.h" // frontend::{CompilationStencil,CompilationInput} -#include "frontend/FrontendContext.h" // frontend::FrontendContext -#include "frontend/ScopeBindingCache.h" // frontend::NoScopeBindingCache -#include "js/friend/StackLimits.h" // js::StackLimitMargin -#include "js/SourceText.h" // JS::SourceText - -using namespace js; -using namespace js::frontend; - -JS_PUBLIC_API FrontendContext* JS::NewFrontendContext() { - MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running, - "must call JS_Init prior to creating any FrontendContexts"); - - return js::NewFrontendContext(); -} - -JS_PUBLIC_API void JS::DestroyFrontendContext(FrontendContext* fc) { - return js::DestroyFrontendContext(fc); -} - -JS_PUBLIC_API void JS::SetNativeStackQuota(JS::FrontendContext* fc, - JS::NativeStackSize stackSize) { - fc->setStackQuota(stackSize); -} - -JS_PUBLIC_API JS::NativeStackSize JS::ThreadStackQuotaForSize( - size_t stackSize) { - // Set the stack quota to 10% less that the actual size. - static constexpr double RatioWithoutMargin = 0.9; - - MOZ_ASSERT(double(stackSize) * (1 - RatioWithoutMargin) > - js::MinimumStackLimitMargin); - - return JS::NativeStackSize(double(stackSize) * RatioWithoutMargin); -} - -JS_PUBLIC_API bool JS::HadFrontendErrors(JS::FrontendContext* fc) { - return fc->hadErrors(); -} - -JS_PUBLIC_API bool JS::ConvertFrontendErrorsToRuntimeErrors( - JSContext* cx, JS::FrontendContext* fc, - const JS::ReadOnlyCompileOptions& options) { - return fc->convertToRuntimeError(cx); -} - -JS_PUBLIC_API const JSErrorReport* JS::GetFrontendErrorReport( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options) { - if (!fc->maybeError().isSome()) { - return nullptr; - } - return fc->maybeError().ptr(); -} - -JS_PUBLIC_API bool JS::HadFrontendOverRecursed(JS::FrontendContext* fc) { - return fc->hadOverRecursed(); -} - -JS_PUBLIC_API bool JS::HadFrontendOutOfMemory(JS::FrontendContext* fc) { - return fc->hadOutOfMemory(); -} - -JS_PUBLIC_API bool JS::HadFrontendAllocationOverflow(JS::FrontendContext* fc) { - return fc->hadAllocationOverflow(); -} - -JS_PUBLIC_API void JS::ClearFrontendErrors(JS::FrontendContext* fc) { - fc->clearErrors(); -} - -JS_PUBLIC_API size_t JS::GetFrontendWarningCount(JS::FrontendContext* fc) { - return fc->warnings().length(); -} - -JS_PUBLIC_API const JSErrorReport* JS::GetFrontendWarningAt( - JS::FrontendContext* fc, size_t index, - const JS::ReadOnlyCompileOptions& options) { - return &fc->warnings()[index]; -} - -template -static already_AddRefed CompileGlobalScriptToStencilImpl( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { - ScopeKind scopeKind = - options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global; - - JS::SourceText data(std::move(srcBuf)); - - frontend::CompilationInput compilationInput(options); - - frontend::NoScopeBindingCache scopeCache; - LifoAlloc tempLifoAlloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE); - RefPtr stencil_ = frontend::CompileGlobalScriptToStencil( - nullptr, fc, tempLifoAlloc, compilationInput, &scopeCache, data, - scopeKind); - // CompilationInput initialized with CompileGlobalScriptToStencil only - // references information from the JS::Stencil context and the - // ref-counted ScriptSource, which are both GC-free. - JS_HAZ_VALUE_IS_GC_SAFE(compilationInput); - return stencil_.forget(); -} - -template -static already_AddRefed CompileModuleScriptToStencilImpl( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput, - JS::SourceText& srcBuf) { - JS::CompileOptions options(nullptr, optionsInput); - options.setModule(); - - frontend::CompilationInput compilationInput(options); - - NoScopeBindingCache scopeCache; - js::LifoAlloc tempLifoAlloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE); - RefPtr stencil = ParseModuleToStencil( - nullptr, fc, tempLifoAlloc, compilationInput, &scopeCache, srcBuf); - // CompilationInput initialized with ParseModuleToStencil only - // references information from the JS::Stencil context and the - // ref-counted ScriptSource, which are both GC-free. - JS_HAZ_VALUE_IS_GC_SAFE(compilationInput); - if (!stencil) { - return nullptr; - } - - // Convert the UniquePtr to a RefPtr and increment the count (to 1). - return stencil.forget(); -} - -already_AddRefed JS::CompileGlobalScriptToStencil( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { -#ifdef DEBUG - fc->assertNativeStackLimitThread(); -#endif - return CompileGlobalScriptToStencilImpl(fc, options, srcBuf); -} - -already_AddRefed JS::CompileGlobalScriptToStencil( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { -#ifdef DEBUG - fc->assertNativeStackLimitThread(); -#endif - return CompileGlobalScriptToStencilImpl(fc, options, srcBuf); -} - -already_AddRefed JS::CompileModuleScriptToStencil( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput, - JS::SourceText& srcBuf) { -#ifdef DEBUG - fc->assertNativeStackLimitThread(); -#endif - return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf); -} - -already_AddRefed JS::CompileModuleScriptToStencil( - JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& optionsInput, - JS::SourceText& srcBuf) { -#ifdef DEBUG - fc->assertNativeStackLimitThread(); -#endif - return CompileModuleScriptToStencilImpl(fc, optionsInput, srcBuf); -} - -bool JS::PrepareForInstantiate(JS::FrontendContext* fc, JS::Stencil& stencil, - JS::InstantiationStorage& storage) { - if (!storage.gcOutput_) { - storage.gcOutput_ = - fc->getAllocator() - ->new_(); - if (!storage.gcOutput_) { - return false; - } - } - return CompilationStencil::prepareForInstantiate(fc, stencil, - *storage.gcOutput_); -} diff --git a/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.cpp index d607667e266..20b927b5100 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.cpp @@ -26,7 +26,8 @@ DecoratorEmitter::DecoratorEmitter(BytecodeEmitter* bce) : bce_(bce) {} // A helper function to read the decorators in reverse order to how they were // parsed. bool DecoratorEmitter::reverseDecoratorsToApplicationOrder( - const ListNode* decorators, DecoratorsVector& vec) { + const ListNode* decorators, DecoratorsVector& vec) const { + MOZ_ASSERT(!decorators->empty()); if (!vec.resize(decorators->count())) { ReportOutOfMemory(bce_->fc); return false; diff --git a/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.h index c5e90c7985c..9a5305c2104 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/DecoratorEmitter.h @@ -74,7 +74,7 @@ class MOZ_STACK_CLASS DecoratorEmitter { using DecoratorsVector = js::Vector; [[nodiscard]] bool reverseDecoratorsToApplicationOrder( - const ListNode* decorators, DecoratorsVector& vec); + const ListNode* decorators, DecoratorsVector& vec) const; }; } /* namespace js::frontend */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.cpp index 0d563e466da..307aaccd783 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.cpp @@ -48,31 +48,38 @@ bool ElemOpEmitter::prepareForKey() { bool ElemOpEmitter::emitGet() { MOZ_ASSERT(state_ == State::Key); - // Inc/dec and compound assignment use the KEY twice, but if it's an object, - // it must be converted ToPropertyKey only once, per spec. - if (isIncDec() || isCompoundAssignment()) { - if (!bce_->emit1(JSOp::ToPropertyKey)) { - // [stack] # if Super - // [stack] THIS KEY - // [stack] # otherwise - // [stack] OBJ KEY - return false; - } - } - if (isSuper()) { if (!bce_->emitSuperBase()) { // [stack] THIS? THIS KEY SUPERBASE return false; } } + + // Inc/dec and compound assignment use the KEY twice, but if it's an object, + // it must be converted by ToPropertyKey only once, per spec. if (isIncDec() || isCompoundAssignment()) { if (isSuper()) { + if (!bce_->emit1(JSOp::Swap)) { + // [stack] THIS SUPERBASE KEY + return false; + } + if (!bce_->emit1(JSOp::ToPropertyKey)) { + // [stack] THIS SUPERBASE KEY + return false; + } + if (!bce_->emit1(JSOp::Swap)) { + // [stack] THIS KEY SUPERBASE + return false; + } if (!bce_->emitDupAt(2, 3)) { // [stack] THIS KEY SUPERBASE THIS KEY SUPERBASE return false; } } else { + if (!bce_->emit1(JSOp::ToPropertyKey)) { + // [stack] OBJ KEY + return false; + } if (!bce_->emit1(JSOp::Dup2)) { // [stack] OBJ KEY OBJ KEY return false; @@ -131,25 +138,11 @@ bool ElemOpEmitter::prepareForRhs() { return true; } -bool ElemOpEmitter::skipObjAndKeyAndRhs() { - MOZ_ASSERT(state_ == State::Start); - MOZ_ASSERT(isSimpleAssignment() || isPropInit()); - -#ifdef DEBUG - state_ = State::Rhs; -#endif - return true; -} - bool ElemOpEmitter::emitDelete() { MOZ_ASSERT(state_ == State::Key); MOZ_ASSERT(isDelete()); if (isSuper()) { - if (!bce_->emit1(JSOp::ToPropertyKey)) { - // [stack] THIS KEY - return false; - } if (!bce_->emitSuperBase()) { // [stack] THIS KEY SUPERBASE return false; diff --git a/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.h index cf528bf3125..e16c68cf6f4 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ElemOpEmitter.h @@ -9,6 +9,8 @@ #include "mozilla/Attributes.h" +#include + namespace js { namespace frontend { @@ -142,38 +144,36 @@ class MOZ_STACK_CLASS ElemOpEmitter { #ifdef DEBUG // The state of this emitter. // - // skipObjAndKeyAndRhs - // +------------------------------------------------+ - // | | - // +-------+ | prepareForObj +-----+ prepareForKey +-----+ | - // | Start |-+-------------->| Obj |-------------->| Key |-+ | - // +-------+ +-----+ +-----+ | | - // | | - // +-------------------------------------------------------+ | - // | | - // | [Get] | - // | [Call] | - // | emitGet +-----+ | - // +---------->| Get | | - // | +-----+ | - // | | - // | [Delete] | - // | emitDelete +--------+ | - // +------------->| Delete | | - // | +--------+ | - // | | - // | [PostIncrement] | - // | [PreIncrement] | - // | [PostDecrement] | - // | [PreDecrement] | - // | emitIncDec +--------+ | - // +------------->| IncDec | | - // | +--------+ | - // | +-------------------+ - // | [SimpleAssignment] | - // | [PropInit] | - // | prepareForRhs v +-----+ - // +--------------------->+-------------->+->| Rhs |-+ + // + // +-------+ prepareForObj +-----+ prepareForKey +-----+ + // | Start |---------------->| Obj |-------------->| Key |-+ + // +-------+ +-----+ +-----+ | + // | + // +-------------------------------------------------------+ + // | + // | [Get] + // | [Call] + // | emitGet +-----+ + // +---------->| Get | + // | +-----+ + // | + // | [Delete] + // | emitDelete +--------+ + // +------------->| Delete | + // | +--------+ + // | + // | [PostIncrement] + // | [PreIncrement] + // | [PostDecrement] + // | [PreDecrement] + // | emitIncDec +--------+ + // +------------->| IncDec | + // | +--------+ + // | + // | [SimpleAssignment] + // | [PropInit] + // | prepareForRhs +-----+ + // +--------------------->+----------------->| Rhs |-+ // | ^ +-----+ | // | | | // | | +-------------+ @@ -200,7 +200,7 @@ class MOZ_STACK_CLASS ElemOpEmitter { // After calling emitIncDec. IncDec, - // After calling prepareForRhs or skipObjAndKeyAndRhs. + // After calling prepareForRhs. Rhs, // After calling emitAssignment. @@ -252,13 +252,14 @@ class MOZ_STACK_CLASS ElemOpEmitter { [[nodiscard]] bool emitGet(); [[nodiscard]] bool prepareForRhs(); - [[nodiscard]] bool skipObjAndKeyAndRhs(); [[nodiscard]] bool emitDelete(); [[nodiscard]] bool emitAssignment(); [[nodiscard]] bool emitIncDec(ValueUsage valueUsage); + + size_t numReferenceSlots() const { return 2 + isSuper(); } }; } /* namespace frontend */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.cpp b/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.cpp index 51d27d61421..352d6d37111 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.cpp @@ -7,9 +7,11 @@ #include "frontend/EmitterScope.h" #include "frontend/AbstractScopePtr.h" +#include "frontend/BytecodeControlStructures.h" #include "frontend/BytecodeEmitter.h" #include "frontend/ModuleSharedContext.h" #include "frontend/TDZCheckCache.h" +#include "frontend/UsingEmitter.h" #include "js/friend/ErrorMessages.h" // JSMSG_* #include "vm/EnvironmentObject.h" // ClassBodyLexicalEnvironmentObject @@ -333,8 +335,50 @@ void EmitterScope::dump(BytecodeEmitter* bce) { fprintf(stdout, "\n"); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +bool EmitterScope::prepareForDisposableScopeBody(BytecodeEmitter* bce) { + if (hasDisposables()) { + if (!usingEmitter_->prepareForDisposableScopeBody(blockKind_)) { + return false; + } + } + return true; +} + +bool EmitterScope::prepareForModuleDisposableScopeBody(BytecodeEmitter* bce) { + return prepareForDisposableScopeBody(bce); +} + +bool EmitterScope::prepareForDisposableAssignment(UsingHint hint) { + MOZ_ASSERT(hasDisposables()); + return usingEmitter_->prepareForAssignment(hint); +} + +bool EmitterScope::emitDisposableScopeBodyEnd(BytecodeEmitter* bce) { + // For-of loops emit the dispose loop in the different place and timing. + // (See ForOfEmitter::emitInitialize, + // ForOfLoopControl::emitPrepareForNonLocalJumpFromScope and + // ForOfLoopControl::emitEndCodeNeedingIteratorClose()) + if (hasDisposables() && (blockKind_ != BlockKind::ForOf)) { + if (!usingEmitter_->emitEnd()) { + return false; + } + } + return true; +} + +bool EmitterScope::emitModuleDisposableScopeBodyEnd(BytecodeEmitter* bce) { + return emitDisposableScopeBodyEnd(bce); +} +#endif + bool EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind, - LexicalScope::ParserData* bindings) { + LexicalScope::ParserData* bindings +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + , + BlockKind blockKind +#endif +) { MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda); MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); @@ -360,6 +404,11 @@ bool EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind, if (!tdzCache->noteTDZCheck(bce, bi.name(), CheckTDZ)) { return false; } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (bi.kind() == BindingKind::Using) { + setHasDisposables(bce); + } +#endif } updateFrameFixedSlots(bce, bi); @@ -395,6 +444,17 @@ bool EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind, return false; } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + MOZ_ASSERT_IF(blockKind_ != BlockKind::Other, kind == ScopeKind::Lexical); + MOZ_ASSERT_IF(kind != ScopeKind::Lexical, blockKind_ == BlockKind::Other); + + blockKind_ = blockKind; + + if (!prepareForDisposableScopeBody(bce)) { + return false; + } +#endif + return checkEnvironmentChainLength(bce); } @@ -846,6 +906,12 @@ bool EmitterScope::enterModule(BytecodeEmitter* bce, return false; } } + +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (bi.kind() == BindingKind::Using) { + setHasDisposables(bce); + } +#endif } updateFrameFixedSlots(bce, bi); @@ -928,8 +994,8 @@ bool EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) { case ScopeKind::ClassBody: #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - if (hasDisposables()) { - if (!bce->emit1(JSOp::DisposeDisposables)) { + if (!nonLocal) { + if (!emitDisposableScopeBodyEnd(bce)) { return false; } } diff --git a/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.h b/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.h index 1c5c939c1a5..ba1abb9d429 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.h +++ b/src/third_party/mozjs/extract/js/src/frontend/EmitterScope.h @@ -16,6 +16,9 @@ #include "frontend/NameAnalysisTypes.h" #include "frontend/NameCollections.h" #include "frontend/Stencil.h" +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +# include "frontend/UsingEmitter.h" +#endif #include "vm/Opcodes.h" // JSOp #include "vm/SharedStencil.h" // GCThingIndex @@ -46,7 +49,10 @@ class EmitterScope : public Nestable { bool hasEnvironment_; #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - bool hasDisposables_ = false; + mozilla::Maybe usingEmitter_; + + private: + BlockKind blockKind_ = BlockKind::Other; #endif // The number of enclosing environments. Used for error checking. @@ -109,13 +115,26 @@ class EmitterScope : public Nestable { return clearFrameSlotRange(bce, JSOp::Uninitialized, slotStart, slotEnd); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + void setHasDisposables(BytecodeEmitter* bce) { + if (!usingEmitter_.isSome()) { + usingEmitter_.emplace(bce); + } + } +#endif + public: explicit EmitterScope(BytecodeEmitter* bce); void dump(BytecodeEmitter* bce); [[nodiscard]] bool enterLexical(BytecodeEmitter* bce, ScopeKind kind, - LexicalScope::ParserData* bindings); + LexicalScope::ParserData* bindings +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + , + BlockKind blockKind = BlockKind::Other +#endif + ); [[nodiscard]] bool enterClassBody(BytecodeEmitter* bce, ScopeKind kind, ClassBodyScope::ParserData* bindings); [[nodiscard]] bool enterNamedLambda(BytecodeEmitter* bce, @@ -147,11 +166,25 @@ class EmitterScope : public Nestable { bool hasEnvironment() const { return hasEnvironment_; } #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - bool hasDisposables() const { return hasDisposables_; } + private: + // Disposable Scope here refers to any scope + // with using bindings in it for now that is + // a lexical scope and a module scope. + [[nodiscard]] bool prepareForDisposableScopeBody(BytecodeEmitter* bce); - bool setHasDisposables() { - hasDisposables_ = true; - return true; + [[nodiscard]] bool emitDisposableScopeBodyEnd(BytecodeEmitter* bce); + + public: + [[nodiscard]] bool prepareForModuleDisposableScopeBody(BytecodeEmitter* bce); + + [[nodiscard]] bool emitModuleDisposableScopeBodyEnd(BytecodeEmitter* bce); + + [[nodiscard]] bool prepareForDisposableAssignment(UsingHint hint); + + bool hasDisposables() const { return usingEmitter_.isSome(); } + + bool hasAsyncDisposables() const { + return hasDisposables() && usingEmitter_->hasAwaitUsing(); } #endif diff --git a/src/third_party/mozjs/extract/js/src/frontend/ExpressionStatementEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/ExpressionStatementEmitter.cpp index bb00c831b13..48905d3f5f6 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ExpressionStatementEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ExpressionStatementEmitter.cpp @@ -12,8 +12,6 @@ using namespace js; using namespace js::frontend; -using mozilla::Maybe; - ExpressionStatementEmitter::ExpressionStatementEmitter(BytecodeEmitter* bce, ValueUsage valueUsage) : bce_(bce), valueUsage_(valueUsage) {} diff --git a/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.cpp b/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.cpp index 562929f35b2..f60b4c319e6 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.cpp @@ -6,7 +6,6 @@ #include "frontend/FoldConstants.h" -#include "mozilla/FloatingPoint.h" #include "mozilla/Maybe.h" // mozilla::Maybe #include "mozilla/Try.h" // MOZ_TRY* @@ -19,22 +18,19 @@ #include "frontend/Parser-macros.h" // MOZ_TRY_VAR_OR_RETURN #include "frontend/ParserAtom.h" // ParserAtomsTable, TaggedParserAtomIndex #include "js/Conversions.h" -#include "js/Stack.h" // JS::NativeStackLimit -#include "util/StringBuffer.h" // StringBuffer +#include "js/Stack.h" // JS::NativeStackLimit +#include "util/StringBuilder.h" // StringBuilder using namespace js; using namespace js::frontend; -using JS::GenericNaN; using JS::ToInt32; using JS::ToUint32; -using mozilla::IsNegative; -using mozilla::NegativeInfinity; -using mozilla::PositiveInfinity; struct FoldInfo { FrontendContext* fc; ParserAtomsTable& parserAtoms; + BigIntStencilVector& bigInts; FullParseHandler* handler; }; @@ -466,12 +462,6 @@ restart: case ParseNodeKind::LastUnused: case ParseNodeKind::Limit: MOZ_CRASH("unexpected sentinel ParseNodeKind in node"); - -#ifdef ENABLE_RECORD_TUPLE - case ParseNodeKind::RecordExpr: - case ParseNodeKind::TupleExpr: - MOZ_CRASH("Record and Tuple are not supported yet"); -#endif } MOZ_CRASH("invalid node kind"); @@ -531,7 +521,7 @@ static bool IsEffectless(ParseNode* node) { enum Truthiness { Truthy, Falsy, Unknown }; -static Truthiness Boolish(ParseNode* pn) { +static Truthiness Boolish(const FoldInfo& info, ParseNode* pn) { switch (pn->getKind()) { case ParseNodeKind::NumberExpr: return (pn->as().value() != 0 && @@ -540,7 +530,8 @@ static Truthiness Boolish(ParseNode* pn) { : Falsy; case ParseNodeKind::BigIntExpr: - return (pn->as().isZero()) ? Falsy : Truthy; + return info.bigInts[pn->as().index()].isZero() ? Falsy + : Truthy; case ParseNodeKind::StringExpr: case ParseNodeKind::TemplateStringExpr: @@ -583,7 +574,7 @@ static bool SimplifyCondition(FoldInfo info, ParseNode** nodePtr) { // constant-folded. ParseNode* node = *nodePtr; - if (Truthiness t = Boolish(node); t != Unknown) { + if (Truthiness t = Boolish(info, node); t != Unknown) { // We can turn function nodes into constant nodes here, but mutating // function nodes is tricky --- in particular, mutating a function node // that appears on a method list corrupts the method list. However, @@ -725,6 +716,21 @@ static bool FoldUnaryArithmetic(FoldInfo info, ParseNode** nodePtr) { info.handler->newNumber(d, NoDecimal, node->pn_pos))) { return false; } + } else if (expr->is()) { + auto* literal = &expr->as(); + auto& bigInt = info.bigInts[literal->index()]; + + if (node->isKind(ParseNodeKind::BitNotExpr)) { + if (bigInt.inplaceBitNot()) { + return TryReplaceNode(nodePtr, literal); + } + } else if (node->isKind(ParseNodeKind::NegExpr)) { + if (bigInt.inplaceNegate()) { + return TryReplaceNode(nodePtr, literal); + } + } else { + MOZ_ASSERT(node->isKind(ParseNodeKind::PosExpr)); // nothing to do + } } return true; @@ -742,7 +748,7 @@ static bool FoldAndOrCoalesce(FoldInfo info, ParseNode** nodePtr) { bool isCoalesceNode = node->isKind(ParseNodeKind::CoalesceExpr); ParseNode** elem = node->unsafeHeadReference(); do { - Truthiness t = Boolish(*elem); + Truthiness t = Boolish(info, *elem); // If we don't know the constant-folded node's truthiness, we can't // reduce this node with its surroundings. Continue folding any @@ -854,7 +860,7 @@ static bool FoldConditional(FoldInfo info, ParseNode** nodePtr) { } // Try to constant-fold based on the condition expression. - Truthiness t = Boolish(*expr); + Truthiness t = Boolish(info, *expr); if (t == Unknown) { continue; } @@ -920,7 +926,7 @@ static bool FoldIf(FoldInfo info, ParseNode** nodePtr) { // Eliminate the consequent or alternative if the condition has // constant truthiness. - Truthiness t = Boolish(*expr); + Truthiness t = Boolish(info, *expr); if (t == Unknown) { continue; } @@ -1234,8 +1240,8 @@ static bool FoldAdd(FoldInfo info, ParseNode** nodePtr) { MOZ_ASSERT((*current)->isKind(ParseNodeKind::StringExpr)); // To avoid unnecessarily copy when there's no strings after the - // first item, lazily construct StringBuffer and append the first item. - mozilla::Maybe accum; + // first item, lazily construct StringBuilder and append the first item. + mozilla::Maybe accum; TaggedParserAtomIndex firstAtom; firstAtom = (*current)->as().atom(); @@ -1323,15 +1329,17 @@ class FoldVisitor : public RewritingParseNodeVisitor { using Base = RewritingParseNodeVisitor; ParserAtomsTable& parserAtoms; + BigIntStencilVector& bigInts; FullParseHandler* handler; - FoldInfo info() const { return FoldInfo{fc_, parserAtoms, handler}; } + FoldInfo info() const { return FoldInfo{fc_, parserAtoms, bigInts, handler}; } public: FoldVisitor(FrontendContext* fc, ParserAtomsTable& parserAtoms, - FullParseHandler* handler) + BigIntStencilVector& bigInts, FullParseHandler* handler) : RewritingParseNodeVisitor(fc), parserAtoms(parserAtoms), + bigInts(bigInts), handler(handler) {} bool visitElemExpr(ParseNode*& pn) { @@ -1578,15 +1586,17 @@ class FoldVisitor : public RewritingParseNodeVisitor { }; static bool Fold(FrontendContext* fc, ParserAtomsTable& parserAtoms, - FullParseHandler* handler, ParseNode** pnp) { - FoldVisitor visitor(fc, parserAtoms, handler); + BigIntStencilVector& bigInts, FullParseHandler* handler, + ParseNode** pnp) { + FoldVisitor visitor(fc, parserAtoms, bigInts, handler); return visitor.visit(*pnp); } static bool Fold(FoldInfo info, ParseNode** pnp) { - return Fold(info.fc, info.parserAtoms, info.handler, pnp); + return Fold(info.fc, info.parserAtoms, info.bigInts, info.handler, pnp); } bool frontend::FoldConstants(FrontendContext* fc, ParserAtomsTable& parserAtoms, - ParseNode** pnp, FullParseHandler* handler) { - return Fold(fc, parserAtoms, handler, pnp); + BigIntStencilVector& bigInts, ParseNode** pnp, + FullParseHandler* handler) { + return Fold(fc, parserAtoms, bigInts, handler, pnp); } diff --git a/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.h b/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.h index 836e2986ebe..ae18abc5038 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.h +++ b/src/third_party/mozjs/extract/js/src/frontend/FoldConstants.h @@ -7,6 +7,7 @@ #ifndef frontend_FoldConstants_h #define frontend_FoldConstants_h +#include "frontend/Stencil.h" #include "frontend/SyntaxParseHandler.h" namespace js { @@ -29,16 +30,18 @@ class ParserAtomsTable; // // Usage: // MOZ_TRY_VAR(pn, parser->statement()); -// if (!FoldConstants(fc, parserAtoms, &pn, parser)) { +// if (!FoldConstants(fc, parserAtoms, bigInts, &pn, parser)) { // return errorResult(); // } [[nodiscard]] extern bool FoldConstants(FrontendContext* fc, ParserAtomsTable& parserAtoms, + BigIntStencilVector& bigInts, ParseNode** pnp, FullParseHandler* handler); [[nodiscard]] inline bool FoldConstants(FrontendContext* fc, ParserAtomsTable& parserAtoms, + BigIntStencilVector& bigInts, typename SyntaxParseHandler::Node* pnp, SyntaxParseHandler* handler) { return true; diff --git a/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.cpp index 655ac590cab..ae9f71a429b 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.cpp @@ -9,6 +9,7 @@ #include "frontend/BytecodeEmitter.h" #include "frontend/EmitterScope.h" #include "frontend/ParserAtom.h" // TaggedParserAtomIndex +#include "frontend/UsingEmitter.h" #include "vm/Opcodes.h" #include "vm/StencilEnums.h" // TryNoteKind @@ -22,24 +23,30 @@ ForOfEmitter::ForOfEmitter(BytecodeEmitter* bce, SelfHostedIter selfHostedIter, IteratorKind iterKind #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT , - HasUsingDeclarationInHead hasUsingDeclarationInHead + HeadUsingDeclarationKind usingDeclarationInHead #endif ) : bce_(bce), selfHostedIter_(selfHostedIter), iterKind_(iterKind), - headLexicalEmitterScope_(headLexicalEmitterScope) { + headLexicalEmitterScope_(headLexicalEmitterScope) #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - MOZ_ASSERT_IF(hasUsingDeclarationInHead == HasUsingDeclarationInHead::Yes, - headLexicalEmitterScope->hasEnvironment()); - if (hasUsingDeclarationInHead == HasUsingDeclarationInHead::Yes) { - // The using bindings are closed over and stored in the lexical environment - // object for headLexicalEmitterScope. - // Mark that the environment has disposables for them to be disposed on - // every iteration. - MOZ_ASSERT(headLexicalEmitterScope == bce_->innermostEmitterScope()); - bce_->innermostEmitterScope()->setHasDisposables(); - } + , + usingDeclarationInHead_(usingDeclarationInHead) +#endif +{ +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // The using bindings are closed over and stored in the lexical environment + // object for headLexicalEmitterScope. + // Mark that the environment has disposables for them to be disposed on + // every iteration. + MOZ_ASSERT_IF(usingDeclarationInHead != HeadUsingDeclarationKind::None, + headLexicalEmitterScope->hasEnvironment() && + headLexicalEmitterScope == bce_->innermostEmitterScope() && + headLexicalEmitterScope->hasDisposables()); + MOZ_ASSERT_IF( + headLexicalEmitterScope && headLexicalEmitterScope->hasDisposables(), + usingDeclarationInHead != HeadUsingDeclarationKind::None); #endif } @@ -106,23 +113,20 @@ bool ForOfEmitter::emitInitialize(uint32_t forPos) { if (headLexicalEmitterScope_->hasEnvironment()) { #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - if (headLexicalEmitterScope_->hasDisposables()) { - // Before recreation of the lexical environment, we must dispose - // the disposables of the previous iteration. - // - // Emitting the bytecode to dispose over here means - // that we will have one extra disposal at the start of the loop which - // is a no op because there arent any disposables added yet. - // - // There also wouldn't be a dispose operation for the environment - // object recreated for the last iteration, where it leaves the loop - // before evaluating the body statement. - // - // TODO: Move the handling of emitting this bytecode to UsingEmitter - // (bug 1900756) - if (!bce_->emit1(JSOp::DisposeDisposables)) { - return false; - } + // Before recreation of the lexical environment, we must dispose + // the disposables of the previous iteration. + // + // Emitting the bytecode to dispose over here means + // that we will have one extra disposal at the start of the loop which + // is a no op because there arent any disposables added yet. + // + // There also wouldn't be a dispose operation for the environment + // object recreated for the last iteration, where it leaves the loop + // before evaluating the body statement. + if (!loopInfo_->prepareForForOfLoopIteration( + bce_, headLexicalEmitterScope_, + usingDeclarationInHead_ == HeadUsingDeclarationKind::Async)) { + return false; } #endif if (!bce_->emitInternedScopeOp(headLexicalEmitterScope_->index(), diff --git a/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.h index 040a2db7f52..3bcb54a3957 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ForOfEmitter.h @@ -92,7 +92,13 @@ class MOZ_STACK_CLASS ForOfEmitter { public: #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - enum class HasUsingDeclarationInHead { No, Yes }; + enum class HeadUsingDeclarationKind { None, Sync, Async }; + + private: + HeadUsingDeclarationKind usingDeclarationInHead_ = + HeadUsingDeclarationKind::None; + + public: #endif ForOfEmitter(BytecodeEmitter* bce, @@ -100,7 +106,7 @@ class MOZ_STACK_CLASS ForOfEmitter { SelfHostedIter selfHostedIter, IteratorKind iterKind #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT , - HasUsingDeclarationInHead hasUsingDeclarationInHead + HeadUsingDeclarationKind usingDeclarationInHead #endif ); diff --git a/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.cpp b/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.cpp index 6a0e743b6fb..08513ac1626 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.cpp @@ -7,6 +7,7 @@ #include "frontend/ForOfLoopControl.h" #include "frontend/BytecodeEmitter.h" // BytecodeEmitter +#include "frontend/EmitterScope.h" // EmitterScope #include "frontend/IfEmitter.h" // InternalIfEmitter #include "vm/CompletionKind.h" // CompletionKind #include "vm/Opcodes.h" // JSOp @@ -37,17 +38,44 @@ bool ForOfLoopControl::emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) { return true; } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +bool ForOfLoopControl::prepareForForOfLoopIteration( + BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope, + bool hasAwaitUsing) { + MOZ_ASSERT(headLexicalEmitterScope); + if (headLexicalEmitterScope->hasDisposables()) { + forOfDisposalEmitter_.emplace(bce, hasAwaitUsing); + return forOfDisposalEmitter_->prepareForForOfLoopIteration(); + } + return true; +} +#endif + bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) { if (!tryCatch_->emitCatch(TryEmitter::ExceptionStack::Yes)) { // [stack] ITER ... EXCEPTION STACK return false; } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // Explicit Resource Management Proposal + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset + // Step 9.i.i.1 Set result to + // Completion(DisposeResources(iterationEnv.[[DisposeCapability]], result)). + if (forOfDisposalEmitter_.isSome()) { + if (!forOfDisposalEmitter_->emitEnd()) { + // [stack] ITER ... EXCEPTION STACK + return false; + } + } +#endif + unsigned slotFromTop = bce->bytecodeSection().stackDepth() - iterDepth_; if (!bce->emitDupAt(slotFromTop)) { // [stack] ITER ... EXCEPTION STACK ITER return false; } + if (!emitIteratorCloseInInnermostScopeWithTryNote(bce, CompletionKind::Throw)) { return false; // ITER ... EXCEPTION STACK @@ -162,16 +190,36 @@ bool ForOfLoopControl::emitPrepareForNonLocalJumpFromScope( return false; } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // Explicit Resource Management Proposal + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset + // Step 9.k.i. Set result to + // Completion(DisposeResources(iterationEnv.[[DisposeCapability]], result)). + NonLocalIteratorCloseUsingEmitter disposeBeforeIterClose(bce); + + if (!disposeBeforeIterClose.prepareForIteratorClose(currentScope)) { + // [stack] EXC-DISPOSE? DISPOSE-THROWING? ITER + return false; + } +#endif + if (!bce->emit1(JSOp::Dup)) { - // [stack] ITER ITER + // [stack] EXC-DISPOSE? DISPOSE-THROWING? ITER ITER return false; } *tryNoteStart = bce->bytecodeSection().offset(); if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) { + // [stack] EXC-DISPOSE? DISPOSE-THROWING? ITER + return false; + } + +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (!disposeBeforeIterClose.emitEnd()) { // [stack] ITER return false; } +#endif if (isTarget) { // At the level of the target block, there's bytecode after the diff --git a/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.h b/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.h index 5ffda9a8ba8..e7870ae4f76 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ForOfLoopControl.h @@ -15,7 +15,10 @@ #include "frontend/IteratorKind.h" // IteratorKind #include "frontend/SelfHostedIter.h" // SelfHostedIter #include "frontend/TryEmitter.h" // TryEmitter -#include "vm/CompletionKind.h" // CompletionKind +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +# include "frontend/UsingEmitter.h" // ForOfDisposalEmitter +#endif +#include "vm/CompletionKind.h" // CompletionKind namespace js { namespace frontend { @@ -68,10 +71,20 @@ class ForOfLoopControl : public LoopControl { IteratorKind iterKind_; +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + mozilla::Maybe forOfDisposalEmitter_; +#endif + public: ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, SelfHostedIter selfHostedIter, IteratorKind iterKind); +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + [[nodiscard]] bool prepareForForOfLoopIteration( + BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope, + bool hasAwaitUsing); +#endif + [[nodiscard]] bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce); [[nodiscard]] bool emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce); diff --git a/src/third_party/mozjs/extract/js/src/frontend/Frontend2.cpp b/src/third_party/mozjs/extract/js/src/frontend/Frontend2.cpp deleted file mode 100644 index 025d676a4b0..00000000000 --- a/src/third_party/mozjs/extract/js/src/frontend/Frontend2.cpp +++ /dev/null @@ -1,703 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "frontend/Frontend2.h" - -#include "mozilla/Maybe.h" // mozilla::Maybe -#include "mozilla/OperatorNewExtensions.h" // mozilla::KnownNotNull -#include "mozilla/Range.h" // mozilla::Range -#include "mozilla/Span.h" // mozilla::Span -#include "mozilla/Variant.h" // mozilla::AsVariant - -#include // size_t -#include // uint8_t, uint32_t - -#include "jsapi.h" - -#include "frontend/AbstractScopePtr.h" // ScopeIndex -#include "frontend/BytecodeSection.h" // EmitScriptThingsVector -#include "frontend/CompilationStencil.h" // CompilationState, CompilationStencil -#include "frontend/FrontendContext.h" // AutoReportFrontendContext -#include "frontend/Parser.h" // NewEmptyLexicalScopeData, NewEmptyGlobalScopeData, NewEmptyVarScopeData, NewEmptyFunctionScopeData -#include "frontend/ParserAtom.h" // ParserAtomsTable, TaggedParserAtomIndex -#include "frontend/ScriptIndex.h" // ScriptIndex -#include "frontend/smoosh_generated.h" // CVec, Smoosh*, smoosh_* -#include "frontend/SourceNotes.h" // SrcNote -#include "frontend/Stencil.h" // ScopeStencil, RegExpIndex -#include "frontend/TokenStream.h" // TokenStreamAnyChars -#include "irregexp/RegExpAPI.h" // irregexp::CheckPatternSyntax -#include "js/CharacterEncoding.h" // JS::UTF8Chars, UTF8CharsToNewTwoByteCharsZ, JS::ConstUTF8CharsZ -#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin, JS::LimitedColumnNumberOneOrigin -#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* -#include "js/GCAPI.h" // JS::AutoCheckCannotGC -#include "js/HeapAPI.h" // JS::GCCellPtr -#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags -#include "js/RootingAPI.h" // JS::MutableHandle -#include "js/UniquePtr.h" // js::UniquePtr -#include "js/Utility.h" // JS::UniqueTwoByteChars, StringBufferArena -#include "vm/JSScript.h" // JSScript -#include "vm/Scope.h" // GetScopeDataTrailingNames -#include "vm/ScopeKind.h" // ScopeKind -#include "vm/SharedStencil.h" // ImmutableScriptData, ScopeNote, TryNote, GCThingIndex - -using mozilla::Utf8Unit; - -using namespace js::gc; -using namespace js::frontend; -using namespace js; - -namespace js { - -namespace frontend { - -// Given the result of SmooshMonkey's parser, Convert the list of atoms into -// the list of ParserAtoms. -bool ConvertAtoms(JSContext* cx, FrontendContext* fc, - const SmooshResult& result, - CompilationState& compilationState, - Vector& allAtoms) { - size_t numAtoms = result.all_atoms_len; - - if (!allAtoms.reserve(numAtoms)) { - return false; - } - - for (size_t i = 0; i < numAtoms; i++) { - auto s = reinterpret_cast( - smoosh_get_atom_at(result, i)); - auto len = smoosh_get_atom_len_at(result, i); - auto atom = compilationState.parserAtoms.internUtf8(fc, s, len); - if (!atom) { - return false; - } - // We don't collect atomization information in smoosh yet. - // Assume it needs to be atomized. - compilationState.parserAtoms.markUsedByStencil(atom, - ParserAtom::Atomize::Yes); - allAtoms.infallibleAppend(atom); - } - - return true; -} - -void CopyBindingNames(JSContext* cx, CVec& from, - Vector& allAtoms, - ParserBindingName* to) { - // We're setting trailing array's content before setting its length. - JS::AutoCheckCannotGC nogc(cx); - - size_t numBindings = from.len; - for (size_t i = 0; i < numBindings; i++) { - SmooshBindingName& name = from.data[i]; - new (mozilla::KnownNotNull, &to[i]) ParserBindingName( - allAtoms[name.name], name.is_closed_over, name.is_top_level_function); - } -} - -void CopyBindingNames(JSContext* cx, CVec>& from, - Vector& allAtoms, - ParserBindingName* to) { - // We're setting trailing array's content before setting its length. - JS::AutoCheckCannotGC nogc(cx); - - size_t numBindings = from.len; - for (size_t i = 0; i < numBindings; i++) { - COption& maybeName = from.data[i]; - if (maybeName.IsSome()) { - SmooshBindingName& name = maybeName.AsSome(); - new (mozilla::KnownNotNull, &to[i]) ParserBindingName( - allAtoms[name.name], name.is_closed_over, name.is_top_level_function); - } else { - new (mozilla::KnownNotNull, &to[i]) - ParserBindingName(TaggedParserAtomIndex::null(), false, false); - } - } -} - -// Given the result of SmooshMonkey's parser, convert a list of scope data -// into a list of ScopeStencil. -bool ConvertScopeStencil(JSContext* cx, FrontendContext* fc, - const SmooshResult& result, - Vector& allAtoms, - CompilationState& compilationState) { - LifoAlloc& alloc = compilationState.alloc; - - if (result.scopes.len > TaggedScriptThingIndex::IndexLimit) { - ReportAllocationOverflow(fc); - return false; - } - - for (size_t i = 0; i < result.scopes.len; i++) { - SmooshScopeData& scopeData = result.scopes.data[i]; - ScopeIndex index; - - switch (scopeData.tag) { - case SmooshScopeData::Tag::Global: { - auto& global = scopeData.AsGlobal(); - - size_t numBindings = global.bindings.len; - GlobalScope::ParserData* data = - NewEmptyGlobalScopeData(fc, alloc, numBindings); - if (!data) { - return false; - } - - CopyBindingNames(cx, global.bindings, allAtoms, - GetScopeDataTrailingNamesPointer(data)); - - data->slotInfo.letStart = global.let_start; - data->slotInfo.constStart = global.const_start; - data->length = numBindings; - - if (!ScopeStencil::createForGlobalScope( - fc, compilationState, ScopeKind::Global, data, &index)) { - return false; - } - break; - } - case SmooshScopeData::Tag::Var: { - auto& var = scopeData.AsVar(); - - size_t numBindings = var.bindings.len; - - VarScope::ParserData* data = - NewEmptyVarScopeData(fc, alloc, numBindings); - if (!data) { - return false; - } - - CopyBindingNames(cx, var.bindings, allAtoms, - GetScopeDataTrailingNamesPointer(data)); - - // NOTE: data->slotInfo.nextFrameSlot is set in - // ScopeStencil::createForVarScope. - - data->length = numBindings; - - uint32_t firstFrameSlot = var.first_frame_slot; - ScopeIndex enclosingIndex(var.enclosing); - if (!ScopeStencil::createForVarScope( - fc, compilationState, ScopeKind::FunctionBodyVar, data, - firstFrameSlot, var.function_has_extensible_scope, - mozilla::Some(enclosingIndex), &index)) { - return false; - } - break; - } - case SmooshScopeData::Tag::Lexical: { - auto& lexical = scopeData.AsLexical(); - - size_t numBindings = lexical.bindings.len; - LexicalScope::ParserData* data = - NewEmptyLexicalScopeData(fc, alloc, numBindings); - if (!data) { - return false; - } - - CopyBindingNames(cx, lexical.bindings, allAtoms, - GetScopeDataTrailingNamesPointer(data)); - - // NOTE: data->slotInfo.nextFrameSlot is set in - // ScopeStencil::createForLexicalScope. - - data->slotInfo.constStart = lexical.const_start; - data->length = numBindings; - - uint32_t firstFrameSlot = lexical.first_frame_slot; - ScopeIndex enclosingIndex(lexical.enclosing); - if (!ScopeStencil::createForLexicalScope( - fc, compilationState, ScopeKind::Lexical, data, firstFrameSlot, - mozilla::Some(enclosingIndex), &index)) { - return false; - } - break; - } - case SmooshScopeData::Tag::Function: { - auto& function = scopeData.AsFunction(); - - size_t numBindings = function.bindings.len; - FunctionScope::ParserData* data = - NewEmptyFunctionScopeData(fc, alloc, numBindings); - if (!data) { - return false; - } - - CopyBindingNames(cx, function.bindings, allAtoms, - GetScopeDataTrailingNamesPointer(data)); - - // NOTE: data->slotInfo.nextFrameSlot is set in - // ScopeStencil::createForFunctionScope. - - if (function.has_parameter_exprs) { - data->slotInfo.setHasParameterExprs(); - } - data->slotInfo.nonPositionalFormalStart = - function.non_positional_formal_start; - data->slotInfo.varStart = function.var_start; - data->length = numBindings; - - bool hasParameterExprs = function.has_parameter_exprs; - bool needsEnvironment = function.non_positional_formal_start; - ScriptIndex functionIndex = ScriptIndex(function.function_index); - bool isArrow = function.is_arrow; - - ScopeIndex enclosingIndex(function.enclosing); - if (!ScopeStencil::createForFunctionScope( - fc, compilationState, data, hasParameterExprs, needsEnvironment, - functionIndex, isArrow, mozilla::Some(enclosingIndex), - &index)) { - return false; - } - break; - } - } - - // `ConvertGCThings` depends on this condition. - MOZ_ASSERT(index == i); - } - - return true; -} - -// Given the result of SmooshMonkey's parser, convert a list of RegExp data -// into a list of RegExpStencil. -bool ConvertRegExpData(JSContext* cx, FrontendContext* fc, - const SmooshResult& result, - CompilationState& compilationState) { - auto len = result.regexps.len; - if (len == 0) { - return true; - } - - if (len > TaggedScriptThingIndex::IndexLimit) { - ReportAllocationOverflow(fc); - return false; - } - - if (!compilationState.regExpData.reserve(len)) { - js::ReportOutOfMemory(fc); - return false; - } - - for (size_t i = 0; i < len; i++) { - SmooshRegExpItem& item = result.regexps.data[i]; - auto s = smoosh_get_slice_at(result, item.pattern); - auto len = smoosh_get_slice_len_at(result, item.pattern); - - JS::RegExpFlags::Flag flags = JS::RegExpFlag::NoFlags; - if (item.global) { - flags |= JS::RegExpFlag::Global; - } - if (item.ignore_case) { - flags |= JS::RegExpFlag::IgnoreCase; - } - if (item.multi_line) { - flags |= JS::RegExpFlag::Multiline; - } - if (item.dot_all) { - flags |= JS::RegExpFlag::DotAll; - } - if (item.sticky) { - flags |= JS::RegExpFlag::Sticky; - } - if (item.unicode) { - flags |= JS::RegExpFlag::Unicode; - } - - // FIXME: This check should be done at parse time. - size_t length; - JS::UniqueTwoByteChars pattern( - UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(s, len), &length, - StringBufferArena) - .get()); - if (!pattern) { - return false; - } - - mozilla::Range range(pattern.get(), length); - - TokenStreamAnyChars ts(fc, compilationState.input.options, - /* smg = */ nullptr); - - // See Parser::newRegExp. - - if (!irregexp::CheckPatternSyntax(cx->tempLifoAlloc(), fc->stackLimit(), ts, - range, flags)) { - return false; - } - - const mozilla::Utf8Unit* sUtf8 = - reinterpret_cast(s); - auto atom = compilationState.parserAtoms.internUtf8(fc, sUtf8, len); - if (!atom) { - return false; - } - - // RegExp patterm must be atomized. - compilationState.parserAtoms.markUsedByStencil(atom, - ParserAtom::Atomize::Yes); - compilationState.regExpData.infallibleEmplaceBack(atom, - JS::RegExpFlags(flags)); - } - - return true; -} - -// Convert SmooshImmutableScriptData into ImmutableScriptData. -UniquePtr ConvertImmutableScriptData( - JSContext* cx, const SmooshImmutableScriptData& smooshScriptData, - bool isFunction) { - Vector scopeNotes; - if (!scopeNotes.resize(smooshScriptData.scope_notes.len)) { - return nullptr; - } - for (size_t i = 0; i < smooshScriptData.scope_notes.len; i++) { - SmooshScopeNote& scopeNote = smooshScriptData.scope_notes.data[i]; - scopeNotes[i].index = GCThingIndex(scopeNote.index); - scopeNotes[i].start = scopeNote.start; - scopeNotes[i].length = scopeNote.length; - scopeNotes[i].parent = scopeNote.parent; - } - - AutoReportFrontendContext fc(cx); - return ImmutableScriptData::new_( - &fc, smooshScriptData.main_offset, smooshScriptData.nfixed, - smooshScriptData.nslots, GCThingIndex(smooshScriptData.body_scope_index), - smooshScriptData.num_ic_entries, isFunction, smooshScriptData.fun_length, - 0, - mozilla::Span(smooshScriptData.bytecode.data, - smooshScriptData.bytecode.len), - mozilla::Span(), mozilla::Span(), - scopeNotes, mozilla::Span()); -} - -// Given the result of SmooshMonkey's parser, convert a list of GC things -// used by a script into ScriptThingsVector. -bool ConvertGCThings(JSContext* cx, FrontendContext* fc, - const SmooshResult& result, - const SmooshScriptStencil& smooshScript, - CompilationState& compilationState, - Vector& allAtoms, - ScriptIndex scriptIndex) { - size_t ngcthings = smooshScript.gcthings.len; - - // If there are no things, avoid the allocation altogether. - if (ngcthings == 0) { - return true; - } - - TaggedScriptThingIndex* cursor = nullptr; - if (!compilationState.allocateGCThingsUninitialized(fc, scriptIndex, - ngcthings, &cursor)) { - return false; - } - - for (size_t i = 0; i < ngcthings; i++) { - SmooshGCThing& item = smooshScript.gcthings.data[i]; - - // Pointer to the uninitialized element. - void* raw = &cursor[i]; - - switch (item.tag) { - case SmooshGCThing::Tag::Null: { - new (raw) TaggedScriptThingIndex(); - break; - } - case SmooshGCThing::Tag::Atom: { - new (raw) TaggedScriptThingIndex(allAtoms[item.AsAtom()]); - break; - } - case SmooshGCThing::Tag::Function: { - new (raw) TaggedScriptThingIndex(ScriptIndex(item.AsFunction())); - break; - } - case SmooshGCThing::Tag::Scope: { - new (raw) TaggedScriptThingIndex(ScopeIndex(item.AsScope())); - break; - } - case SmooshGCThing::Tag::RegExp: { - new (raw) TaggedScriptThingIndex(RegExpIndex(item.AsRegExp())); - break; - } - } - } - - return true; -} - -// Given the result of SmooshMonkey's parser, convert a specific script -// or function to a StencilScript, given a fixed set of source atoms. -// -// The StencilScript would then be in charge of handling the lifetime and -// (until GC things gets removed from stencil) tracing API of the GC. -bool ConvertScriptStencil(JSContext* cx, FrontendContext* fc, - const SmooshResult& result, - const SmooshScriptStencil& smooshScript, - Vector& allAtoms, - CompilationState& compilationState, - ScriptIndex scriptIndex) { - using ImmutableFlags = js::ImmutableScriptFlagsEnum; - - const JS::ReadOnlyCompileOptions& options = compilationState.input.options; - - ScriptStencil& script = compilationState.scriptData[scriptIndex]; - ScriptStencilExtra& scriptExtra = compilationState.scriptExtra[scriptIndex]; - - scriptExtra.immutableFlags = - ImmutableScriptFlags(smooshScript.immutable_flags); - - // FIXME: The following flags should be set in jsparagus. - scriptExtra.immutableFlags.setFlag(ImmutableFlags::SelfHosted, - options.selfHostingMode); - scriptExtra.immutableFlags.setFlag(ImmutableFlags::ForceStrict, - options.forceStrictMode()); - scriptExtra.immutableFlags.setFlag(ImmutableFlags::HasNonSyntacticScope, - options.nonSyntacticScope); - - if (&smooshScript == &result.scripts.data[0]) { - scriptExtra.immutableFlags.setFlag(ImmutableFlags::TreatAsRunOnce, - options.isRunOnce); - scriptExtra.immutableFlags.setFlag(ImmutableFlags::NoScriptRval, - options.noScriptRval); - } - - bool isFunction = - scriptExtra.immutableFlags.hasFlag(ImmutableFlags::IsFunction); - - if (smooshScript.immutable_script_data.IsSome()) { - auto index = smooshScript.immutable_script_data.AsSome(); - auto immutableScriptData = ConvertImmutableScriptData( - cx, result.script_data_list.data[index], isFunction); - if (!immutableScriptData) { - return false; - } - - auto sharedData = SharedImmutableScriptData::createWith( - fc, std::move(immutableScriptData)); - if (!sharedData) { - return false; - } - - if (!compilationState.sharedData.addAndShare(fc, scriptIndex, sharedData)) { - return false; - } - - script.setHasSharedData(); - } - - scriptExtra.extent.sourceStart = smooshScript.extent.source_start; - scriptExtra.extent.sourceEnd = smooshScript.extent.source_end; - scriptExtra.extent.toStringStart = smooshScript.extent.to_string_start; - scriptExtra.extent.toStringEnd = smooshScript.extent.to_string_end; - scriptExtra.extent.lineno = smooshScript.extent.lineno; - scriptExtra.extent.column = - JS::LimitedColumnNumberOneOrigin(1 + smooshScript.extent.column); - - if (isFunction) { - if (smooshScript.fun_name.IsSome()) { - script.functionAtom = allAtoms[smooshScript.fun_name.AsSome()]; - } - script.functionFlags = FunctionFlags(smooshScript.fun_flags); - scriptExtra.nargs = smooshScript.fun_nargs; - if (smooshScript.lazy_function_enclosing_scope_index.IsSome()) { - script.setLazyFunctionEnclosingScopeIndex(ScopeIndex( - smooshScript.lazy_function_enclosing_scope_index.AsSome())); - } - if (smooshScript.was_function_emitted) { - script.setWasEmittedByEnclosingScript(); - } - } - - if (!ConvertGCThings(cx, fc, result, smooshScript, compilationState, allAtoms, - scriptIndex)) { - return false; - } - - return true; -} - -// Free given SmooshResult on leaving scope. -class AutoFreeSmooshResult { - SmooshResult* result_; - - public: - AutoFreeSmooshResult() = delete; - - explicit AutoFreeSmooshResult(SmooshResult* result) : result_(result) {} - ~AutoFreeSmooshResult() { - if (result_) { - smoosh_free(*result_); - } - } -}; - -// Free given SmooshParseResult on leaving scope. -class AutoFreeSmooshParseResult { - SmooshParseResult* result_; - - public: - AutoFreeSmooshParseResult() = delete; - - explicit AutoFreeSmooshParseResult(SmooshParseResult* result) - : result_(result) {} - ~AutoFreeSmooshParseResult() { - if (result_) { - smoosh_free_parse_result(*result_); - } - } -}; - -void InitSmoosh() { smoosh_init(); } - -void ReportSmooshCompileError(JSContext* cx, FrontendContext* fc, - ErrorMetadata&& metadata, int errorNumber, ...) { - va_list args; - va_start(args, errorNumber); - ReportCompileErrorUTF8(fc, std::move(metadata), /* notes = */ nullptr, - errorNumber, &args); - va_end(args); -} - -/* static */ -bool Smoosh::tryCompileGlobalScriptToExtensibleStencil( - JSContext* cx, FrontendContext* fc, CompilationInput& input, - JS::SourceText& srcBuf, - UniquePtr& stencilOut) { - // FIXME: check info members and return with *unimplemented = true - // if any field doesn't match to smoosh_run. - - auto bytes = reinterpret_cast(srcBuf.get()); - size_t length = srcBuf.length(); - - SmooshCompileOptions compileOptions; - compileOptions.no_script_rval = input.options.noScriptRval; - - SmooshResult result = smoosh_run(bytes, length, &compileOptions); - AutoFreeSmooshResult afsr(&result); - - if (result.error.data) { - ErrorMetadata metadata; - metadata.filename = JS::ConstUTF8CharsZ(""); - metadata.lineNumber = 1; - metadata.columnNumber = JS::ColumnNumberOneOrigin(); - metadata.isMuted = false; - ReportSmooshCompileError(cx, fc, std::move(metadata), - JSMSG_SMOOSH_COMPILE_ERROR, - reinterpret_cast(result.error.data)); - return false; - } - - if (result.unimplemented) { - MOZ_ASSERT(!stencilOut); - return true; - } - - if (!input.initForGlobal(fc)) { - return false; - } - - LifoAllocScope parserAllocScope(&cx->tempLifoAlloc()); - - Vector allAtoms(fc); - CompilationState compilationState(fc, parserAllocScope, input); - if (!ConvertAtoms(cx, fc, result, compilationState, allAtoms)) { - return false; - } - - if (!ConvertScopeStencil(cx, fc, result, allAtoms, compilationState)) { - return false; - } - - if (!ConvertRegExpData(cx, fc, result, compilationState)) { - return false; - } - - auto len = result.scripts.len; - if (len == 0) { - // FIXME: What does it mean to have no scripts? - MOZ_ASSERT(!stencilOut); - return true; - } - - if (len > TaggedScriptThingIndex::IndexLimit) { - ReportAllocationOverflow(fc); - return false; - } - - if (!compilationState.scriptData.resize(len)) { - js::ReportOutOfMemory(fc); - return false; - } - - if (!compilationState.scriptExtra.resize(len)) { - js::ReportOutOfMemory(fc); - return false; - } - - // NOTE: Currently we don't support delazification or standalone function. - // Once we support, fix the following loop to include 0-th item - // and check if it's function. - MOZ_ASSERT_IF(result.scripts.len > 0, result.scripts.data[0].fun_flags == 0); - for (size_t i = 1; i < result.scripts.len; i++) { - auto& script = result.scripts.data[i]; - if (script.immutable_script_data.IsSome()) { - compilationState.nonLazyFunctionCount++; - } - } - - if (!compilationState.prepareSharedDataStorage(fc)) { - return false; - } - - for (size_t i = 0; i < len; i++) { - if (!ConvertScriptStencil(cx, fc, result, result.scripts.data[i], allAtoms, - compilationState, ScriptIndex(i))) { - return false; - } - } - - auto stencil = - fc->getAllocator()->make_unique( - std::move(compilationState)); - if (!stencil) { - return false; - } - - stencilOut = std::move(stencil); - return true; -} - -bool SmooshParseScript(JSContext* cx, const uint8_t* bytes, size_t length) { - SmooshParseResult result = smoosh_test_parse_script(bytes, length); - AutoFreeSmooshParseResult afspr(&result); - if (result.error.data) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - result.unimplemented ? JSMSG_SMOOSH_UNIMPLEMENTED - : JSMSG_SMOOSH_COMPILE_ERROR, - reinterpret_cast(result.error.data)); - return false; - } - - return true; -} - -bool SmooshParseModule(JSContext* cx, const uint8_t* bytes, size_t length) { - SmooshParseResult result = smoosh_test_parse_module(bytes, length); - AutoFreeSmooshParseResult afspr(&result); - if (result.error.data) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - result.unimplemented ? JSMSG_SMOOSH_UNIMPLEMENTED - : JSMSG_SMOOSH_COMPILE_ERROR, - reinterpret_cast(result.error.data)); - return false; - } - - return true; -} - -} // namespace frontend - -} // namespace js diff --git a/src/third_party/mozjs/extract/js/src/frontend/Frontend2.h b/src/third_party/mozjs/extract/js/src/frontend/Frontend2.h deleted file mode 100644 index 6d14de999c6..00000000000 --- a/src/third_party/mozjs/extract/js/src/frontend/Frontend2.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sts=2 et sw=2 tw=80: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef frontend_Frontend2_h -#define frontend_Frontend2_h - -#include "mozilla/Utf8.h" // mozilla::Utf8Unit - -#include // size_t -#include // uint8_t - -#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions -#include "js/RootingAPI.h" // JS::Handle -#include "js/SourceText.h" // JS::SourceText -#include "js/UniquePtr.h" // js::UniquePtr -#include "vm/JSScript.h" // JSScript - -struct JSContext; - -struct SmooshResult; - -namespace js { - -class ScriptSourceObject; -class FrontendContext; - -namespace frontend { - -struct CompilationInput; -struct ExtensibleCompilationStencil; -struct CompilationGCOutput; -struct CompilationState; - -// This is declarated as a class mostly to solve dependency around `friend` -// declarations in the simple way. -class Smoosh { - public: - [[nodiscard]] static bool tryCompileGlobalScriptToExtensibleStencil( - JSContext* cx, FrontendContext* fc, CompilationInput& input, - JS::SourceText& srcBuf, - UniquePtr& stencilOut); -}; - -// Initialize SmooshMonkey globals, such as the logging system. -void InitSmoosh(); - -// Use the SmooshMonkey frontend to parse and free the generated AST. Returns -// true if no error were detected while parsing. -[[nodiscard]] bool SmooshParseScript(JSContext* cx, const uint8_t* bytes, - size_t length); -[[nodiscard]] bool SmooshParseModule(JSContext* cx, const uint8_t* bytes, - size_t length); - -} // namespace frontend - -} // namespace js - -#endif /* frontend_Frontend2_h */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/FrontendContext.cpp b/src/third_party/mozjs/extract/js/src/frontend/FrontendContext.cpp index aeb12efe933..9d971a59201 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/FrontendContext.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/FrontendContext.cpp @@ -7,7 +7,7 @@ #include "frontend/FrontendContext.h" #ifdef _WIN32 -# include +# include "util/WindowsWrapper.h" # include // GetCurrentThreadId #else # include // pthread_self @@ -15,7 +15,8 @@ #include "gc/GC.h" #include "js/AllocPolicy.h" // js::ReportOutOfMemory -#include "js/friend/StackLimits.h" // js::ReportOverRecursed, js::MinimumStackLimitMargin +#include "js/experimental/CompileScript.h" +#include "js/friend/StackLimits.h" // js::ReportOverRecursed, js::MinimumStackLimitMargin, js::StackLimitMargin #include "js/Modules.h" #include "util/DifferentialTesting.h" #include "util/NativeStack.h" // GetNativeStackBase @@ -66,6 +67,22 @@ void FrontendContext::setStackQuota(JS::NativeStackSize stackSize) { #endif } +JS_PUBLIC_API void JS::SetNativeStackQuota(JS::FrontendContext* fc, + JS::NativeStackSize stackSize) { + fc->setStackQuota(stackSize); +} + +JS_PUBLIC_API JS::NativeStackSize JS::ThreadStackQuotaForSize( + size_t stackSize) { + // Set the stack quota to 10% less that the actual size. + static constexpr double RatioWithoutMargin = 0.9; + + MOZ_ASSERT(double(stackSize) * (1 - RatioWithoutMargin) > + js::MinimumStackLimitMargin); + + return JS::NativeStackSize(double(stackSize) * RatioWithoutMargin); +} + bool FrontendContext::allocateOwnedPool() { MOZ_ASSERT(!nameCollectionPool_); @@ -84,11 +101,19 @@ bool FrontendContext::hadErrors() const { return errors_.hadErrors(); } +JS_PUBLIC_API bool JS::HadFrontendErrors(JS::FrontendContext* fc) { + return fc->hadErrors(); +} + void FrontendContext::clearErrors() { MOZ_ASSERT(!maybeCx_); return errors_.clearErrors(); } +JS_PUBLIC_API void JS::ClearFrontendErrors(JS::FrontendContext* fc) { + fc->clearErrors(); +} + void FrontendContext::clearWarnings() { return errors_.clearWarnings(); } void* FrontendContext::onOutOfMemory(AllocFunction allocFunc, arena_id_t arena, @@ -200,10 +225,18 @@ bool FrontendContext::convertToRuntimeError( return true; } +JS_PUBLIC_API bool JS::ConvertFrontendErrorsToRuntimeErrors( + JSContext* cx, JS::FrontendContext* fc, + const JS::ReadOnlyCompileOptions& options) { + return fc->convertToRuntimeError(cx); +} + #ifdef DEBUG static size_t GetTid() { # if defined(_WIN32) return size_t(GetCurrentThreadId()); +# elif defined(__wasm__) + return 1; # else return size_t(pthread_self()); # endif @@ -268,8 +301,19 @@ FrontendContext* js::NewFrontendContext() { return fc.release(); } +JS_PUBLIC_API FrontendContext* JS::NewFrontendContext() { + MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running, + "must call JS_Init prior to creating any FrontendContexts"); + + return js::NewFrontendContext(); +} + void js::DestroyFrontendContext(FrontendContext* fc) { js_delete_poison(fc); } +JS_PUBLIC_API void JS::DestroyFrontendContext(FrontendContext* fc) { + return js::DestroyFrontendContext(fc); +} + #ifdef DEBUG void FrontendContext::checkAndUpdateFrontendContextRecursionLimit(void* sp) { // For the js::MinimumStackLimitMargin to be effective, it should be larger @@ -303,3 +347,33 @@ void js::CheckAndUpdateFrontendContextRecursionLimit(FrontendContext* fc, fc->checkAndUpdateFrontendContextRecursionLimit(sp); } #endif + +JS_PUBLIC_API const JSErrorReport* JS::GetFrontendErrorReport( + JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options) { + if (!fc->maybeError().isSome()) { + return nullptr; + } + return fc->maybeError().ptr(); +} + +JS_PUBLIC_API bool JS::HadFrontendOverRecursed(JS::FrontendContext* fc) { + return fc->hadOverRecursed(); +} + +JS_PUBLIC_API bool JS::HadFrontendOutOfMemory(JS::FrontendContext* fc) { + return fc->hadOutOfMemory(); +} + +JS_PUBLIC_API bool JS::HadFrontendAllocationOverflow(JS::FrontendContext* fc) { + return fc->hadAllocationOverflow(); +} + +JS_PUBLIC_API size_t JS::GetFrontendWarningCount(JS::FrontendContext* fc) { + return fc->warnings().length(); +} + +JS_PUBLIC_API const JSErrorReport* JS::GetFrontendWarningAt( + JS::FrontendContext* fc, size_t index, + const JS::ReadOnlyCompileOptions& options) { + return &fc->warnings()[index]; +} diff --git a/src/third_party/mozjs/extract/js/src/frontend/FullParseHandler.h b/src/third_party/mozjs/extract/js/src/frontend/FullParseHandler.h index 9209ba4d670..8a45ca28459 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/FullParseHandler.h +++ b/src/third_party/mozjs/extract/js/src/frontend/FullParseHandler.h @@ -185,9 +185,8 @@ class FullParseHandler { return newResult(value, decimalPoint, pos); } - BigIntLiteralResult newBigInt(BigIntIndex index, bool isZero, - const TokenPos& pos) { - return newResult(index, isZero, pos); + BigIntLiteralResult newBigInt(BigIntIndex index, const TokenPos& pos) { + return newResult(index, pos); } BooleanLiteralResult newBooleanLiteral(bool cond, const TokenPos& pos) { @@ -336,9 +335,7 @@ class FullParseHandler { [[nodiscard]] bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) { - MOZ_ASSERT( - literal->isKind(ParseNodeKind::ArrayExpr) || - IF_RECORD_TUPLE(literal->isKind(ParseNodeKind::TupleExpr), false)); + MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr)); UnaryNodeType spread; MOZ_TRY_VAR_OR_RETURN(spread, newSpread(begin, inner), false); @@ -348,10 +345,8 @@ class FullParseHandler { } void addArrayElement(ListNodeType literal, Node element) { - MOZ_ASSERT( - literal->isKind(ParseNodeKind::ArrayExpr) || - literal->isKind(ParseNodeKind::CallSiteObj) || - IF_RECORD_TUPLE(literal->isKind(ParseNodeKind::TupleExpr), false)); + MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr) || + literal->isKind(ParseNodeKind::CallSiteObj)); if (!element->isConstant()) { literal->setHasNonConstInitializer(); } @@ -387,18 +382,6 @@ class FullParseHandler { TokenPos(begin, begin + 1)); } -#ifdef ENABLE_RECORD_TUPLE - ListNodeResult newRecordLiteral(uint32_t begin) { - return newResult(ParseNodeKind::RecordExpr, - TokenPos(begin, begin + 1)); - } - - ListNodeResult newTupleLiteral(uint32_t begin) { - return newResult(ParseNodeKind::TupleExpr, - TokenPos(begin, begin + 1)); - } -#endif - ClassNodeResult newClass(Node name, Node heritage, LexicalScopeNodeType memberBlock, #ifdef ENABLE_DECORATORS @@ -452,9 +435,7 @@ class FullParseHandler { } void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) { - MOZ_ASSERT( - literal->isKind(ParseNodeKind::ObjectExpr) || - IF_RECORD_TUPLE(literal->isKind(ParseNodeKind::RecordExpr), false)); + MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); MOZ_ASSERT(propdef->isKind(ParseNodeKind::PropertyDefinition)); if (!propdef->right()->isConstant()) { @@ -474,9 +455,7 @@ class FullParseHandler { [[nodiscard]] bool addShorthand(ListNodeType literal, NameNodeType name, NameNodeType expr) { - MOZ_ASSERT( - literal->isKind(ParseNodeKind::ObjectExpr) || - IF_RECORD_TUPLE(literal->isKind(ParseNodeKind::RecordExpr), false)); + MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); MOZ_ASSERT(name->isKind(ParseNodeKind::ObjectPropertyName)); MOZ_ASSERT(expr->isKind(ParseNodeKind::Name)); MOZ_ASSERT(name->atom() == expr->atom()); @@ -491,9 +470,7 @@ class FullParseHandler { [[nodiscard]] bool addSpreadProperty(ListNodeType literal, uint32_t begin, Node inner) { - MOZ_ASSERT( - literal->isKind(ParseNodeKind::ObjectExpr) || - IF_RECORD_TUPLE(literal->isKind(ParseNodeKind::RecordExpr), false)); + MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr)); literal->setHasNonConstInitializer(); ParseNode* spread; diff --git a/src/third_party/mozjs/extract/js/src/frontend/GenerateReservedWords.py b/src/third_party/mozjs/extract/js/src/frontend/GenerateReservedWords.py index 5a4456389e7..3811edcaed7 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/GenerateReservedWords.py +++ b/src/third_party/mozjs/extract/js/src/frontend/GenerateReservedWords.py @@ -13,7 +13,7 @@ def read_reserved_word_list( reserved_word_list = [] index = 0 - with open(filename, "r") as f: + with open(filename) as f: for line in f: m = macro_pat.search(line) if m: @@ -107,22 +107,22 @@ def generate_letter_switch(opt, unprocessed_columns, reserved_word_list, columns index, word = reserved_word_list[0] if unprocessed_columns == 0: - line(opt, "JSRW_GOT_MATCH({}) /* {} */".format(index, word)) + line(opt, f"JSRW_GOT_MATCH({index}) /* {word} */") return if unprocessed_columns > opt["char_tail_test_threshold"]: - line(opt, "JSRW_TEST_GUESS({}) /* {} */".format(index, word)) + line(opt, f"JSRW_TEST_GUESS({index}) /* {word} */") return conds = [] for column in columns[0:unprocessed_columns]: quoted = repr(word[column]) - conds.append("JSRW_AT({})=={}".format(column, quoted)) + conds.append(f"JSRW_AT({column})=={quoted}") line(opt, "if ({}) {{".format(" && ".join(conds))) indent(opt) - line(opt, "JSRW_GOT_MATCH({}) /* {} */".format(index, word)) + line(opt, f"JSRW_GOT_MATCH({index}) /* {word} */") dedent(opt) line(opt, "}") @@ -143,14 +143,14 @@ def generate_letter_switch(opt, unprocessed_columns, reserved_word_list, columns list_per_column = split_list_per_column(reserved_word_list, optimal_column) if not use_if: - line(opt, "switch (JSRW_AT({})) {{".format(optimal_column)) + line(opt, f"switch (JSRW_AT({optimal_column})) {{") for char, reserved_word_list_per_column in list_per_column: quoted = repr(char) if use_if: - line(opt, "if (JSRW_AT({}) == {}) {{".format(optimal_column, quoted)) + line(opt, f"if (JSRW_AT({optimal_column}) == {quoted}) {{") else: - line(opt, " case {}:".format(quoted)) + line(opt, f" case {quoted}:") indent(opt) generate_letter_switch( @@ -185,12 +185,10 @@ def generate_switch(opt, reserved_word_list): line(opt, "/*") line( opt, - " * Generating switch for the list of {} entries:".format( - len(reserved_word_list) - ), + f" * Generating switch for the list of {len(reserved_word_list)} entries:", ) for index, word in reserved_word_list: - line(opt, " * {}".format(word)) + line(opt, f" * {word}") line(opt, " */") list_per_length = split_list_per_length(reserved_word_list) @@ -204,9 +202,9 @@ def generate_switch(opt, reserved_word_list): for length, reserved_word_list_per_length in list_per_length: if use_if: - line(opt, "if (JSRW_LENGTH() == {}) {{".format(length)) + line(opt, f"if (JSRW_LENGTH() == {length}) {{") else: - line(opt, " case {}:".format(length)) + line(opt, f" case {length}:") indent(opt) generate_letter_switch(opt, length, reserved_word_list_per_length) diff --git a/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.cpp index aeda8df9de2..938843e1d65 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.cpp @@ -12,13 +12,23 @@ using namespace js::frontend; LexicalScopeEmitter::LexicalScopeEmitter(BytecodeEmitter* bce) : bce_(bce) {} bool LexicalScopeEmitter::emitScope(ScopeKind kind, - LexicalScope::ParserData* bindings) { + LexicalScope::ParserData* bindings +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + , + BlockKind blockKind +#endif +) { MOZ_ASSERT(state_ == State::Start); MOZ_ASSERT(bindings); tdzCache_.emplace(bce_); emitterScope_.emplace(bce_); - if (!emitterScope_->enterLexical(bce_, kind, bindings)) { + if (!emitterScope_->enterLexical(bce_, kind, bindings +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + , + blockKind +#endif + )) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.h index 379ecc0a89b..f135f812605 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/LexicalScopeEmitter.h @@ -82,7 +82,12 @@ class MOZ_STACK_CLASS LexicalScopeEmitter { const EmitterScope& emitterScope() const { return *emitterScope_; } [[nodiscard]] bool emitScope(ScopeKind kind, - LexicalScope::ParserData* bindings); + LexicalScope::ParserData* bindings +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + , + BlockKind blockKind = BlockKind::Other +#endif + ); [[nodiscard]] bool emitEmptyScope(); [[nodiscard]] bool emitEnd(); diff --git a/src/third_party/mozjs/extract/js/src/frontend/NameAnalysisTypes.h b/src/third_party/mozjs/extract/js/src/frontend/NameAnalysisTypes.h index 5d7f7231af9..d37657ca13b 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/NameAnalysisTypes.h +++ b/src/third_party/mozjs/extract/js/src/frontend/NameAnalysisTypes.h @@ -124,13 +124,10 @@ static inline BindingKind DeclarationKindToBindingKind(DeclarationKind kind) { return BindingKind::Let; case DeclarationKind::Const: -#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - // We treat using as a const for now. (Bug 1897609) - case DeclarationKind::AwaitUsing: -#endif return BindingKind::Const; #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + case DeclarationKind::AwaitUsing: case DeclarationKind::Using: return BindingKind::Using; #endif @@ -196,7 +193,7 @@ class DeclaredNameInfo { // enforce creating an environment object whenever we encounter // a using declaration. This is temporary for prototyping // this must be optimized. (Bug 1899502) - if (kind == DeclarationKind::Using) { + if (kind == DeclarationKind::Using || kind == DeclarationKind::AwaitUsing) { closedOver_ = true; } #endif diff --git a/src/third_party/mozjs/extract/js/src/frontend/NameCollections.h b/src/third_party/mozjs/extract/js/src/frontend/NameCollections.h index 57806a69849..fff7b42f005 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/NameCollections.h +++ b/src/third_party/mozjs/extract/js/src/frontend/NameCollections.h @@ -23,29 +23,7 @@ #include "js/Utility.h" // js_new, js_delete #include "js/Vector.h" // Vector -namespace js { - -namespace detail { - -// For InlineMap. -// See DefaultKeyPolicy definition in InlineTable.h for more details. -template <> -class DefaultKeyPolicy { - public: - DefaultKeyPolicy() = delete; - DefaultKeyPolicy(const frontend::TrivialTaggedParserAtomIndex&) = delete; - - static bool isTombstone(const frontend::TrivialTaggedParserAtomIndex& atom) { - return atom.isNull(); - } - static void setToTombstone(frontend::TrivialTaggedParserAtomIndex& atom) { - atom = frontend::TrivialTaggedParserAtomIndex::null(); - } -}; - -} // namespace detail - -namespace frontend { +namespace js::frontend { class FunctionBox; @@ -449,7 +427,6 @@ class PooledVectorPtr : public PooledCollectionPtr { } }; -} // namespace frontend -} // namespace js +} // namespace js::frontend #endif // frontend_NameCollections_h diff --git a/src/third_party/mozjs/extract/js/src/frontend/NameFunctions.cpp b/src/third_party/mozjs/extract/js/src/frontend/NameFunctions.cpp index 46b5bb074c8..8a89de8283e 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/NameFunctions.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/NameFunctions.cpp @@ -14,7 +14,7 @@ #include "frontend/ParserAtom.h" // ParserAtomsTable #include "frontend/SharedContext.h" #include "util/Poison.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" using namespace js; using namespace js::frontend; @@ -40,7 +40,7 @@ class NameResolver : public ParseNodeVisitor { // When naming a function, the buffer where the name is built. // When we are not under resolveFun, buf_ is empty. - StringBuffer buf_; + StringBuilder buf_; /* Test whether a ParseNode represents a function invocation */ bool isCall(ParseNode* pn) { diff --git a/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.cpp index f36c7a2028b..a6d34d091ed 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.cpp @@ -29,22 +29,39 @@ NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, TaggedParserAtomIndex name, bool NameOpEmitter::emitGet() { MOZ_ASSERT(state_ == State::Start); + bool needsImplicitThis = false; + if (isCall()) { + switch (loc_.kind()) { + case NameLocation::Kind::Dynamic: + if (bce_->needsImplicitThis()) { + needsImplicitThis = true; + break; + } + [[fallthrough]]; + case NameLocation::Kind::Global: + MOZ_ASSERT(bce_->outermostScope().hasNonSyntacticScopeOnChain() == + bce_->sc->hasNonSyntacticScope()); + needsImplicitThis = bce_->sc->hasNonSyntacticScope(); + break; + case NameLocation::Kind::Intrinsic: + case NameLocation::Kind::NamedLambdaCallee: + case NameLocation::Kind::Import: + case NameLocation::Kind::ArgumentSlot: + case NameLocation::Kind::FrameSlot: + case NameLocation::Kind::EnvironmentCoordinate: + case NameLocation::Kind::DebugEnvironmentCoordinate: + case NameLocation::Kind::DynamicAnnexBVar: + break; + } + } + switch (loc_.kind()) { - case NameLocation::Kind::Dynamic: - if (!bce_->emitAtomOp(JSOp::GetName, name_)) { - // [stack] VAL - return false; - } - break; - case NameLocation::Kind::Global: { + case NameLocation::Kind::Global: MOZ_ASSERT(bce_->outermostScope().hasNonSyntacticScopeOnChain() == bce_->sc->hasNonSyntacticScope()); - if (bce_->sc->hasNonSyntacticScope()) { - if (!bce_->emitAtomOp(JSOp::GetName, name_)) { - // [stack] VAL - return false; - } - } else { + if (!bce_->sc->hasNonSyntacticScope()) { + MOZ_ASSERT(!needsImplicitThis); + // Some names on the global are not configurable and have fixed values // which we can emit instead. if (name_ == TaggedParserAtomIndex::WellKnown::undefined()) { @@ -61,13 +78,34 @@ bool NameOpEmitter::emitGet() { } } else { if (!bce_->emitAtomOp(JSOp::GetGName, name_)) { - // [stack] VAL + // [stack] VAL return false; } } + break; + } + [[fallthrough]]; + case NameLocation::Kind::Dynamic: + if (needsImplicitThis) { + if (!bce_->emitAtomOp(JSOp::BindName, name_)) { + // [stack] ENV + return false; + } + if (!bce_->emit1(JSOp::Dup)) { + // [stack] ENV ENV + return false; + } + if (!bce_->emitAtomOp(JSOp::GetBoundName, name_)) { + // [stack] ENV V + return false; + } + } else { + if (!bce_->emitAtomOp(JSOp::GetName, name_)) { + // [stack] VAL + return false; + } } break; - } case NameLocation::Kind::Intrinsic: if (name_ == TaggedParserAtomIndex::WellKnown::undefined()) { if (!bce_->emit1(JSOp::Undefined)) { @@ -135,16 +173,16 @@ bool NameOpEmitter::emitGet() { } if (isCall()) { - MOZ_ASSERT(bce_->outermostScope().hasNonSyntacticScopeOnChain() == - bce_->sc->hasNonSyntacticScope()); switch (loc_.kind()) { case NameLocation::Kind::Dynamic: case NameLocation::Kind::Global: MOZ_ASSERT(bce_->emitterMode != BytecodeEmitter::SelfHosting); - if (bce_->needsImplicitThis() || bce_->sc->hasNonSyntacticScope()) { - MOZ_ASSERT_IF(bce_->needsImplicitThis(), - loc_.kind() == NameLocation::Kind::Dynamic); - if (!bce_->emitAtomOp(JSOp::ImplicitThis, name_)) { + if (needsImplicitThis) { + if (!bce_->emit1(JSOp::Swap)) { + // [stack] CALLEE ENV + return false; + } + if (!bce_->emit1(JSOp::ImplicitThis)) { // [stack] CALLEE THIS return false; } @@ -196,23 +234,21 @@ bool NameOpEmitter::prepareForRhs() { switch (loc_.kind()) { case NameLocation::Kind::Dynamic: case NameLocation::Kind::Import: - case NameLocation::Kind::DynamicAnnexBVar: if (!bce_->makeAtomIndex(name_, ParserAtom::Atomize::Yes, &atomIndex_)) { return false; } - if (loc_.kind() == NameLocation::Kind::DynamicAnnexBVar) { - // Annex B vars always go on the nearest variable environment, - // even if lexical environments in between contain same-named - // bindings. - if (!bce_->emit1(JSOp::BindVar)) { - // [stack] ENV - return false; - } - } else { - if (!bce_->emitAtomOp(JSOp::BindName, atomIndex_)) { - // [stack] ENV - return false; - } + if (!bce_->emitAtomOp(JSOp::BindUnqualifiedName, atomIndex_)) { + // [stack] ENV + return false; + } + emittedBindOp_ = true; + break; + case NameLocation::Kind::DynamicAnnexBVar: + // Annex B vars always go on the nearest variable environment, even if + // lexical environments in between contain same-named bindings. + if (!bce_->emit1(JSOp::BindVar)) { + // [stack] ENV + return false; } emittedBindOp_ = true; break; @@ -225,16 +261,16 @@ bool NameOpEmitter::prepareForRhs() { if (loc_.isLexical() && isInitialize()) { // InitGLexical always gets the global lexical scope. It doesn't - // need a BindName/BindGName. + // need a BindUnqualifiedName/BindUnqualifiedGName. MOZ_ASSERT(bce_->innermostScope().is()); - } else if (bce_->sc->hasNonSyntacticScope()) { - if (!bce_->emitAtomOp(JSOp::BindName, atomIndex_)) { - // [stack] ENV - return false; - } - emittedBindOp_ = true; } else { - if (!bce_->emitAtomOp(JSOp::BindGName, atomIndex_)) { + JSOp op; + if (bce_->sc->hasNonSyntacticScope()) { + op = JSOp::BindUnqualifiedName; + } else { + op = JSOp::BindUnqualifiedGName; + } + if (!bce_->emitAtomOp(op, atomIndex_)) { // [stack] ENV return false; } @@ -242,15 +278,10 @@ bool NameOpEmitter::prepareForRhs() { } break; case NameLocation::Kind::Intrinsic: - break; case NameLocation::Kind::NamedLambdaCallee: - break; case NameLocation::Kind::ArgumentSlot: - break; case NameLocation::Kind::FrameSlot: - break; case NameLocation::Kind::DebugEnvironmentCoordinate: - break; case NameLocation::Kind::EnvironmentCoordinate: break; } @@ -270,7 +301,7 @@ bool NameOpEmitter::prepareForRhs() { // [stack] ENV ENV return false; } - if (!bce_->emitAtomOp(JSOp::GetBoundName, name_)) { + if (!bce_->emitAtomOp(JSOp::GetBoundName, atomIndex_)) { // [stack] ENV V return false; } @@ -288,6 +319,24 @@ bool NameOpEmitter::prepareForRhs() { return true; } +JSOp NameOpEmitter::strictifySetNameOp(JSOp op) const { + switch (op) { + case JSOp::SetName: + if (bce_->sc->strict()) { + op = JSOp::StrictSetName; + } + break; + case JSOp::SetGName: + if (bce_->sc->strict()) { + op = JSOp::StrictSetGName; + } + break; + default: + MOZ_CRASH("Invalid SetName op"); + } + return op; +} + #if defined(__clang__) && defined(XP_WIN) && \ (defined(_M_X64) || defined(__x86_64__)) // Work around a CPU bug. See bug 1524257. @@ -296,12 +345,22 @@ __attribute__((__aligned__(32))) bool NameOpEmitter::emitAssignment() { MOZ_ASSERT(state_ == State::Rhs); + // [stack] # If emittedBindOp_ + // [stack] ENV V + // [stack] # else + // [stack] V + switch (loc_.kind()) { case NameLocation::Kind::Dynamic: case NameLocation::Kind::Import: + MOZ_ASSERT(emittedBindOp_); + if (!bce_->emitAtomOp(strictifySetNameOp(JSOp::SetName), atomIndex_)) { + return false; + } + break; case NameLocation::Kind::DynamicAnnexBVar: - if (!bce_->emitAtomOp(bce_->strictifySetNameOp(JSOp::SetName), - atomIndex_)) { + MOZ_ASSERT(emittedBindOp_); + if (!bce_->emitAtomOp(strictifySetNameOp(JSOp::SetName), name_)) { return false; } break; @@ -311,9 +370,9 @@ bool NameOpEmitter::emitAssignment() { MOZ_ASSERT(bce_->outermostScope().hasNonSyntacticScopeOnChain() == bce_->sc->hasNonSyntacticScope()); if (bce_->sc->hasNonSyntacticScope()) { - op = bce_->strictifySetNameOp(JSOp::SetName); + op = strictifySetNameOp(JSOp::SetName); } else { - op = bce_->strictifySetNameOp(JSOp::SetGName); + op = strictifySetNameOp(JSOp::SetGName); } } else { op = JSOp::InitGLexical; @@ -390,25 +449,21 @@ bool NameOpEmitter::emitAssignment() { return false; } } - } - if (loc_.bindingKind() == BindingKind::NamedLambdaCallee) { + } else if (loc_.bindingKind() == BindingKind::NamedLambdaCallee) { // Assigning to the named lambda is a no-op in sloppy mode and throws // in strict mode. + if (!bce_->sc->strict()) { + break; + } op = JSOp::ThrowSetConst; - if (bce_->sc->strict()) { - if (!bce_->emitAtomOp(op, name_)) { - return false; - } + } + if (op == JSOp::ThrowSetConst) { + if (!bce_->emitAtomOp(op, name_)) { + return false; } } else { - if (op == JSOp::ThrowSetConst) { - if (!bce_->emitAtomOp(op, name_)) { - return false; - } - } else { - if (!bce_->emitEnvCoordOp(op, loc_.environmentCoordinate())) { - return false; - } + if (!bce_->emitEnvCoordOp(op, loc_.environmentCoordinate())) { + return false; } } if (op == JSOp::InitAliasedLexical) { diff --git a/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.h index 62d632a321b..56c54260333 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/NameOpEmitter.h @@ -9,6 +9,8 @@ #include "mozilla/Attributes.h" +#include + #include "frontend/NameAnalysisTypes.h" #include "frontend/ParserAtom.h" // TaggedParserAtomIndex #include "vm/SharedStencil.h" // GCThingIndex @@ -165,6 +167,8 @@ class MOZ_STACK_CLASS NameOpEmitter { [[nodiscard]] bool isInitialize() const { return kind_ == Kind::Initialize; } + JSOp strictifySetNameOp(JSOp op) const; + public: [[nodiscard]] bool emittedBindOp() const { return emittedBindOp_; } @@ -174,6 +178,8 @@ class MOZ_STACK_CLASS NameOpEmitter { [[nodiscard]] bool prepareForRhs(); [[nodiscard]] bool emitAssignment(); [[nodiscard]] bool emitIncDec(ValueUsage valueUsage); + + size_t numReferenceSlots() const { return emittedBindOp(); } }; } /* namespace frontend */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/ObjLiteral.cpp b/src/third_party/mozjs/extract/js/src/frontend/ObjLiteral.cpp index 62772c4fc7e..5aef653b954 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ObjLiteral.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ObjLiteral.cpp @@ -108,15 +108,62 @@ static void InterpretObjLiteralValue( } } +static uint32_t CountNonIndexPropertiesUpTo( + const mozilla::Span literalInsns, uint32_t limit) { + ObjLiteralReader reader(literalInsns); + + uint32_t count = 0; + while (count < limit) { + // Make sure `insn` doesn't live across GC. + ObjLiteralInsn insn; + if (!reader.readInsn(&insn)) { + break; + } + if (!insn.getKey().isArrayIndex()) { + count++; + } + } + + return count; +} + enum class PropertySetKind { UniqueNames, Normal, }; template -bool InterpretObjLiteralObj(JSContext* cx, Handle obj, - const frontend::CompilationAtomCache& atomCache, - const mozilla::Span literalInsns) { +static gc::AllocKind AllocKindForObjectLiteral( + const mozilla::Span literalInsns, uint32_t propCount) { + // Use NewObjectGCKind for empty object literals to reserve some fixed slots + // for new properties. This improves performance for common patterns such as + // |Object.assign({}, ...)|. + if (propCount == 0) { + return NewObjectGCKind(); + } + + // Don't reserve object slots for index properties that don't use them. + if (kind == PropertySetKind::Normal) { + propCount = + CountNonIndexPropertiesUpTo(literalInsns, gc::MaxGCObjectFixedSlots); + } + + return gc::GetGCObjectKind(propCount); +} + +template +JSObject* InterpretObjLiteralObj( + JSContext* cx, const frontend::CompilationAtomCache& atomCache, + const mozilla::Span literalInsns, uint32_t propertyCount) { + gc::AllocKind allocKind = + AllocKindForObjectLiteral(literalInsns, propertyCount); + + Rooted obj( + cx, NewPlainObjectWithAllocKind(cx, allocKind, TenuredObject)); + if (!obj) { + return nullptr; + } + ObjLiteralReader reader(literalInsns); RootedId propId(cx); @@ -144,49 +191,30 @@ bool InterpretObjLiteralObj(JSContext* cx, Handle obj, if constexpr (kind == PropertySetKind::UniqueNames) { if (!AddDataPropertyToPlainObject(cx, obj, propId, propVal)) { - return false; + return nullptr; } } else { if (!NativeDefineDataProperty(cx, obj, propId, propVal, JSPROP_ENUMERATE)) { - return false; + return nullptr; } } } - return true; -} -static gc::AllocKind AllocKindForObjectLiteral(uint32_t propCount) { - // Use NewObjectGCKind for empty object literals to reserve some fixed slots - // for new properties. This improves performance for common patterns such as - // |Object.assign({}, ...)|. - return (propCount == 0) ? NewObjectGCKind() : gc::GetGCObjectKind(propCount); + return obj; } static JSObject* InterpretObjLiteralObj( JSContext* cx, const frontend::CompilationAtomCache& atomCache, const mozilla::Span literalInsns, ObjLiteralFlags flags, uint32_t propertyCount) { - gc::AllocKind allocKind = AllocKindForObjectLiteral(propertyCount); - - Rooted obj( - cx, NewPlainObjectWithAllocKind(cx, allocKind, TenuredObject)); - if (!obj) { - return nullptr; - } - if (!flags.hasFlag(ObjLiteralFlag::HasIndexOrDuplicatePropName)) { - if (!InterpretObjLiteralObj( - cx, obj, atomCache, literalInsns)) { - return nullptr; - } - } else { - if (!InterpretObjLiteralObj(cx, obj, atomCache, - literalInsns)) { - return nullptr; - } + return InterpretObjLiteralObj( + cx, atomCache, literalInsns, propertyCount); } - return obj; + + return InterpretObjLiteralObj( + cx, atomCache, literalInsns, propertyCount); } static JSObject* InterpretObjLiteralArray( @@ -286,7 +314,11 @@ template Shape* InterpretObjLiteralShape(JSContext* cx, const frontend::CompilationAtomCache& atomCache, const mozilla::Span literalInsns, - uint32_t numFixedSlots) { + uint32_t propertyCount) { + gc::AllocKind allocKind = + AllocKindForObjectLiteral(literalInsns, propertyCount); + uint32_t numFixedSlots = GetGCKindSlots(allocKind); + ObjLiteralReader reader(literalInsns); Rooted map(cx); @@ -342,15 +374,12 @@ static Shape* InterpretObjLiteralShape( JSContext* cx, const frontend::CompilationAtomCache& atomCache, const mozilla::Span literalInsns, ObjLiteralFlags flags, uint32_t propertyCount) { - gc::AllocKind allocKind = AllocKindForObjectLiteral(propertyCount); - uint32_t numFixedSlots = GetGCKindSlots(allocKind); - if (!flags.hasFlag(ObjLiteralFlag::HasIndexOrDuplicatePropName)) { return InterpretObjLiteralShape( - cx, atomCache, literalInsns, numFixedSlots); + cx, atomCache, literalInsns, propertyCount); } return InterpretObjLiteralShape( - cx, atomCache, literalInsns, numFixedSlots); + cx, atomCache, literalInsns, propertyCount); } JS::GCCellPtr ObjLiteralStencil::create( diff --git a/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.cpp index d507c6f6d40..1c364bc6847 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.cpp @@ -412,7 +412,8 @@ bool ObjectEmitter::emitObject(size_t propertyCount) { // Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing // a new object and defining (in source order) each property on the object // (or mutating the object's [[Prototype]], in the case of __proto__). - if (!bce_->emit1(JSOp::NewInit)) { + uint8_t propCount = (propertyCount > 255) ? 255 : uint8_t(propertyCount); + if (!bce_->emit2(JSOp::NewInit, propCount)) { // [stack] OBJ return false; } @@ -505,7 +506,7 @@ bool ClassEmitter::emitBodyScope(ClassBodyScope::ParserData* scopeBindings) { bool ClassEmitter::emitClass(TaggedParserAtomIndex name, TaggedParserAtomIndex nameForAnonymousClass, - bool hasNameOnStack) { + bool hasNameOnStack, uint8_t membersCount) { MOZ_ASSERT(propertyState_ == PropertyState::Start); MOZ_ASSERT(classState_ == ClassState::Start || classState_ == ClassState::Scope || @@ -520,7 +521,7 @@ bool ClassEmitter::emitClass(TaggedParserAtomIndex name, hasNameOnStack_ = hasNameOnStack; isDerived_ = false; - if (!bce_->emit1(JSOp::NewInit)) { + if (!bce_->emit2(JSOp::NewInit, membersCount)) { // [stack] HOMEOBJ return false; } diff --git a/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.h index 833eb4a1a42..82de4b3a35c 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ObjectEmitter.h @@ -819,7 +819,7 @@ class MOZ_STACK_CLASS ClassEmitter : public PropertyEmitter { // If true the name is on the stack (only for anonymous classes) [[nodiscard]] bool emitClass(TaggedParserAtomIndex name, TaggedParserAtomIndex nameForAnonymousClass, - bool hasNameOnStack); + bool hasNameOnStack, uint8_t membersCount); [[nodiscard]] bool emitDerivedClass( TaggedParserAtomIndex name, TaggedParserAtomIndex nameForAnonymousClass, bool hasNameOnStack); diff --git a/src/third_party/mozjs/extract/js/src/frontend/ParseContext.h b/src/third_party/mozjs/extract/js/src/frontend/ParseContext.h index 21620b30fe3..44c3887381b 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ParseContext.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ParseContext.h @@ -598,7 +598,11 @@ class ParseContext : public Nestable { } #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - bool isUsingSyntaxAllowed() { return !atGlobalLevel() || atModuleTopLevel(); } + bool isUsingSyntaxAllowed() { + bool isInSwitch = innermostStatement() && + innermostStatement()->kind() == StatementKind::Switch; + return (!atGlobalLevel() || atModuleTopLevel()) && !isInSwitch; + } #endif void setSuperScopeNeedsHomeObject() { diff --git a/src/third_party/mozjs/extract/js/src/frontend/ParseNode.h b/src/third_party/mozjs/extract/js/src/frontend/ParseNode.h index 6e1627ec93d..29963c73cca 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ParseNode.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ParseNode.h @@ -107,8 +107,6 @@ class FunctionBox; F(NullExpr, NullLiteral) \ F(RawUndefinedExpr, RawUndefinedLiteral) \ F(ThisExpr, UnaryNode) \ - IF_RECORD_TUPLE(F(RecordExpr, ListNode)) \ - IF_RECORD_TUPLE(F(TupleExpr, ListNode)) \ F(Function, FunctionNode) \ F(Module, ModuleNode) \ F(IfStmt, TernaryNode) \ @@ -1292,17 +1290,13 @@ class ListNode : public ParseNode { void setHasNonConstInitializer() { MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr) || - isKind(ParseNodeKind::ObjectExpr) || - IF_RECORD_TUPLE(isKind(ParseNodeKind::TupleExpr), false) || - IF_RECORD_TUPLE(isKind(ParseNodeKind::RecordExpr), false)); + isKind(ParseNodeKind::ObjectExpr)); xflags |= hasNonConstInitializerBit; } void unsetHasNonConstInitializer() { MOZ_ASSERT(isKind(ParseNodeKind::ArrayExpr) || - isKind(ParseNodeKind::ObjectExpr) || - IF_RECORD_TUPLE(isKind(ParseNodeKind::TupleExpr), false) || - IF_RECORD_TUPLE(isKind(ParseNodeKind::RecordExpr), false)); + isKind(ParseNodeKind::ObjectExpr)); xflags &= ~hasNonConstInitializerBit; } @@ -1648,13 +1642,10 @@ class NumericLiteral : public ParseNode { class BigIntLiteral : public ParseNode { BigIntIndex index_; - bool isZero_; public: - BigIntLiteral(BigIntIndex index, bool isZero, const TokenPos& pos) - : ParseNode(ParseNodeKind::BigIntExpr, pos), - index_(index), - isZero_(isZero) {} + BigIntLiteral(BigIntIndex index, const TokenPos& pos) + : ParseNode(ParseNodeKind::BigIntExpr, pos), index_(index) {} static bool test(const ParseNode& node) { return node.isKind(ParseNodeKind::BigIntExpr); @@ -1673,8 +1664,6 @@ class BigIntLiteral : public ParseNode { #endif BigIntIndex index() { return index_; } - - bool isZero() const { return isZero_; } }; template diff --git a/src/third_party/mozjs/extract/js/src/frontend/Parser.cpp b/src/third_party/mozjs/extract/js/src/frontend/Parser.cpp index b37c7f10cc5..a70003fb017 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/Parser.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/Parser.cpp @@ -49,9 +49,9 @@ #include "js/ErrorReport.h" // JSErrorBase #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/HashTable.h" -#include "js/RegExpFlags.h" // JS::RegExpFlags -#include "js/Stack.h" // JS::NativeStackLimit -#include "util/StringBuffer.h" // StringBuffer +#include "js/RegExpFlags.h" // JS::RegExpFlags +#include "js/Stack.h" // JS::NativeStackLimit +#include "util/StringBuilder.h" // StringBuilder #include "vm/BytecodeUtil.h" #include "vm/FunctionFlags.h" // js::FunctionFlags #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind @@ -164,11 +164,10 @@ void ParserSharedBase::dumpAtom(TaggedParserAtomIndex index) const { ParserBase::ParserBase(FrontendContext* fc, const ReadOnlyCompileOptions& options, - bool foldConstants, CompilationState& compilationState) + CompilationState& compilationState) : ParserSharedBase(fc, compilationState, ParserSharedBase::Kind::Parser), anyChars(fc, options, this), ss(nullptr), - foldConstants_(foldConstants), #ifdef DEBUG checkOptionsCalled_(false), #endif @@ -197,9 +196,8 @@ JSAtom* ParserBase::liftParserAtomToJSAtom(TaggedParserAtomIndex index) { template PerHandlerParser::PerHandlerParser( FrontendContext* fc, const ReadOnlyCompileOptions& options, - bool foldConstants, CompilationState& compilationState, - void* internalSyntaxParser) - : ParserBase(fc, options, foldConstants, compilationState), + CompilationState& compilationState, void* internalSyntaxParser) + : ParserBase(fc, options, compilationState), handler_(fc, compilationState), internalSyntaxParser_(internalSyntaxParser) { MOZ_ASSERT(compilationState.isInitialStencil() == @@ -209,9 +207,9 @@ PerHandlerParser::PerHandlerParser( template GeneralParser::GeneralParser( FrontendContext* fc, const ReadOnlyCompileOptions& options, - const Unit* units, size_t length, bool foldConstants, - CompilationState& compilationState, SyntaxParser* syntaxParser) - : Base(fc, options, foldConstants, compilationState, syntaxParser), + const Unit* units, size_t length, CompilationState& compilationState, + SyntaxParser* syntaxParser) + : Base(fc, options, compilationState, syntaxParser), tokenStream(fc, &compilationState.parserAtoms, options, units, length) {} template @@ -410,18 +408,6 @@ GeneralParser::parse() { return errorResult(); } - if (foldConstants_) { - Node node = stmtList; - // Don't constant-fold inside "use asm" code, as this could create a parse - // tree that doesn't type-check as asm.js. - if (!pc_->useAsmOrInsideUseAsm()) { - if (!FoldConstants(this->fc_, this->parserAtoms(), &node, &handler_)) { - return errorResult(); - } - } - stmtList = handler_.asListNode(node); - } - return stmtList; } @@ -1056,7 +1042,7 @@ static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( template static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( SlotInfo& slotInfo, ParserBindingName* start, ParserBindingName* cursor, - UnsignedInteger SlotInfo::*field, const ParserBindingNameVector& bindings, + UnsignedInteger SlotInfo::* field, const ParserBindingNameVector& bindings, Step&&... step) { slotInfo.*field = AssertedCast(PointerRangeSize(start, cursor)); @@ -1447,9 +1433,13 @@ static Maybe NewVarScopeData(FrontendContext* fc, return Nothing(); } } else { - MOZ_ASSERT( - bi.kind() == BindingKind::Let || bi.kind() == BindingKind::Const, - "bad var scope BindingKind"); + MOZ_ASSERT(bi.kind() == BindingKind::Let || + bi.kind() == BindingKind::Const +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + || bi.kind() == BindingKind::Using +#endif + , + "bad var scope BindingKind"); } } @@ -1838,7 +1828,8 @@ Parser::evalBody(EvalSharedContext* evalsc) { // Don't constant-fold inside "use asm" code, as this could create a parse // tree that doesn't type-check as asm.js. if (!pc_->useAsmOrInsideUseAsm()) { - if (!FoldConstants(this->fc_, this->parserAtoms(), &node, &handler_)) { + if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, + &handler_)) { return errorResult(); } } @@ -1903,7 +1894,8 @@ FullParseHandler::ListNodeResult Parser::globalBody( // Don't constant-fold inside "use asm" code, as this could create a parse // tree that doesn't type-check as asm.js. if (!pc_->useAsmOrInsideUseAsm()) { - if (!FoldConstants(this->fc_, this->parserAtoms(), &node, &handler_)) { + if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, + &handler_)) { return errorResult(); } } @@ -2024,12 +2016,6 @@ FullParseHandler::ModuleNodeResult Parser::moduleBody( ->value() ->setClosedOver(); - if (options().deoptimizeModuleGlobalVars) { - for (BindingIter bi = modulepc.varScope().bindings(pc_); bi; bi++) { - bi.setClosedOver(); - } - } - if (!CheckParseTree(this->fc_, alloc_, stmtList)) { return errorResult(); } @@ -2038,7 +2024,8 @@ FullParseHandler::ModuleNodeResult Parser::moduleBody( // Don't constant-fold inside "use asm" code, as this could create a parse // tree that doesn't type-check as asm.js. if (!pc_->useAsmOrInsideUseAsm()) { - if (!FoldConstants(this->fc_, this->parserAtoms(), &node, &handler_)) { + if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, + &handler_)) { return errorResult(); } } @@ -2431,7 +2418,8 @@ Parser::standaloneFunction( // Don't constant-fold inside "use asm" code, as this could create a parse // tree that doesn't type-check as asm.js. if (!pc_->useAsmOrInsideUseAsm()) { - if (!FoldConstants(this->fc_, this->parserAtoms(), &node, &handler_)) { + if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, + &handler_)) { return errorResult(); } } @@ -2576,8 +2564,9 @@ bool GeneralParser::matchOrInsertSemicolon( } #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - if (!this->pc_->isUsingSyntaxAllowed() && - anyChars.currentToken().type == TokenKind::Using) { + if (options().explicitResourceManagement() && + anyChars.currentToken().type == TokenKind::Using && + !this->pc_->isUsingSyntaxAllowed()) { error(JSMSG_USING_OUTSIDE_BLOCK_OR_MODULE); return false; } @@ -2628,7 +2617,7 @@ bool ParserBase::leaveInnerFunction(ParseContext* outerpc) { TaggedParserAtomIndex ParserBase::prefixAccessorName( PropertyType propType, TaggedParserAtomIndex propAtom) { - StringBuffer prefixed(fc_); + StringBuilder prefixed(fc_); if (propType == PropertyType::Setter) { if (!prefixed.append("set ")) { return TaggedParserAtomIndex::null(); @@ -3463,7 +3452,8 @@ Parser::standaloneLazyFunction( // Don't constant-fold inside "use asm" code, as this could create a parse // tree that doesn't type-check as asm.js. if (!pc_->useAsmOrInsideUseAsm()) { - if (!FoldConstants(this->fc_, this->parserAtoms(), &node, &handler_)) { + if (!FoldConstants(this->fc_, this->parserAtoms(), this->bigInts(), &node, + &handler_)) { return errorResult(); } } @@ -4334,7 +4324,7 @@ GeneralParser::bindingIdentifierOrPattern( } if (!TokenKindIsPossibleIdentifierName(tt)) { - error(JSMSG_NO_VARIABLE_NAME); + error(JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); return errorResult(); } @@ -4377,7 +4367,7 @@ GeneralParser::objectBindingPattern( } if (!TokenKindIsPossibleIdentifierName(tt)) { - error(JSMSG_NO_VARIABLE_NAME); + error(JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); return errorResult(); } @@ -4454,7 +4444,7 @@ GeneralParser::objectBindingPattern( return errorResult(); } } else { - errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME); + errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); return errorResult(); } } @@ -4770,7 +4760,7 @@ GeneralParser::declarationName(DeclarationKind declKind, Node* forInOrOfExpression) { // Anything other than possible identifier is an error. if (!TokenKindIsPossibleIdentifier(tt)) { - error(JSMSG_NO_VARIABLE_NAME); + error(JSMSG_NO_VARIABLE_NAME, TokenKindToDesc(tt)); return errorResult(); } @@ -4838,6 +4828,13 @@ GeneralParser::declarationName(DeclarationKind declKind, errorAt(namePos.begin, JSMSG_BAD_CONST_DECL); return errorResult(); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + if (declKind == DeclarationKind::Using || + declKind == DeclarationKind::AwaitUsing) { + errorAt(namePos.begin, JSMSG_BAD_USING_DECL); + return errorResult(); + } +#endif } } @@ -5004,7 +5001,7 @@ bool GeneralParser::withClause(ListNodeType attributesSet) { anyChars.isCurrentTokenType(TokenKind::With)); if (!options().importAttributes()) { - error(JSMSG_IMPORT_ASSERTIONS_NOT_SUPPORTED); + error(JSMSG_IMPORT_ATTRIBUTES_NOT_SUPPORTED); return false; } @@ -5363,8 +5360,7 @@ GeneralParser::importDeclaration() { MOZ_TRY_VAR(importAttributeList, handler_.newList(ParseNodeKind::ImportAttributeList, pos())); - if (tt == TokenKind::With || - (tt == TokenKind::Assert && options().importAttributesAssertSyntax())) { + if (tt == TokenKind::With) { tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); if (!withClause(importAttributeList)) { @@ -5412,8 +5408,13 @@ GeneralParser::importDeclarationOrImportExpr( template bool Parser::checkExportedName( TaggedParserAtomIndex exportName) { - if (!pc_->sc()->asModuleContext()->builder.hasExportedName(exportName)) { - return true; + switch (pc_->sc()->asModuleContext()->builder.noteExportedName(exportName)) { + case ModuleBuilder::NoteExportedNameResult::Success: + return true; + case ModuleBuilder::NoteExportedNameResult::OutOfMemory: + return false; + case ModuleBuilder::NoteExportedNameResult::AlreadyDeclared: + break; } UniqueChars str = this->parserAtoms().toPrintableString(exportName); @@ -5733,8 +5734,7 @@ GeneralParser::exportFrom(uint32_t begin, Node specList) { ListNodeType importAttributeList; MOZ_TRY_VAR(importAttributeList, handler_.newList(ParseNodeKind::ImportAttributeList, pos())); - if (tt == TokenKind::With || - (tt == TokenKind::Assert && options().importAttributesAssertSyntax())) { + if (tt == TokenKind::With) { tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); if (!withClause(importAttributeList)) { @@ -6540,7 +6540,7 @@ bool GeneralParser::forHeadStart( tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); } #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - else if (tt == TokenKind::Await) { + else if (tt == TokenKind::Await && options().explicitResourceManagement()) { if (!pc_->isAsync()) { if (pc_->atModuleTopLevel()) { if (!options().topLevelAwait) { @@ -6582,7 +6582,7 @@ bool GeneralParser::forHeadStart( anyChars.ungetToken(); // put back await token } } - } else if (tt == TokenKind::Using) { + } else if (tt == TokenKind::Using && options().explicitResourceManagement()) { tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); // Look ahead to find either a 'of' token or if not identifier @@ -7709,19 +7709,19 @@ bool GeneralParser::classMember( propType == PropertyType::FieldWithAccessor) { if (isStatic) { if (propAtom == TaggedParserAtomIndex::WellKnown::prototype()) { - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_CLASS_STATIC_PROTO); return false; } } if (propAtom == TaggedParserAtomIndex::WellKnown::constructor()) { - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); return false; } if (handler_.isPrivateName(propName)) { if (propAtom == TaggedParserAtomIndex::WellKnown::hash_constructor_()) { - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); return false; } @@ -7747,7 +7747,7 @@ bool GeneralParser::classMember( // ... // Step 3. Let privateStateDesc be the string-concatenation of name // and " accessor storage". - StringBuffer privateStateDesc(fc_); + StringBuilder privateStateDesc(fc_); if (!privateStateDesc.append(this->parserAtoms(), propAtom)) { return false; } @@ -7868,7 +7868,7 @@ bool GeneralParser::classMember( propType != PropertyType::GeneratorMethod && propType != PropertyType::AsyncMethod && propType != PropertyType::AsyncGeneratorMethod) { - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_BAD_CLASS_MEMBER_DEF); return false; } @@ -7876,11 +7876,11 @@ bool GeneralParser::classMember( !isStatic && propAtom == TaggedParserAtomIndex::WellKnown::constructor(); if (isConstructor) { if (propType != PropertyType::Method) { - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); return false; } if (classStmt.constructorBox) { - errorAt(propNameOffset, JSMSG_DUPLICATE_PROPERTY, "constructor"); + errorAt(propNameOffset, JSMSG_DUPLICATE_CONSTRUCTOR); return false; } propType = hasHeritage == HasHeritage::Yes @@ -7888,7 +7888,7 @@ bool GeneralParser::classMember( : PropertyType::Constructor; } else if (isStatic && propAtom == TaggedParserAtomIndex::WellKnown::prototype()) { - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_CLASS_STATIC_PROTO); return false; } @@ -7972,7 +7972,7 @@ bool GeneralParser::classMember( if (handler_.isPrivateName(propName)) { if (propAtom == TaggedParserAtomIndex::WellKnown::hash_constructor_()) { // #constructor is an invalid private name. - errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF); + errorAt(propNameOffset, JSMSG_BAD_CONSTRUCTOR_DEF); return false; } @@ -8963,7 +8963,7 @@ GeneralParser::synthesizePrivateMethodInitializer( // Synthesize a name for the lexical variable that will store the // accessor body. - StringBuffer storedMethodName(fc_); + StringBuilder storedMethodName(fc_); if (!storedMethodName.append(this->parserAtoms(), propAtom)) { return errorResult(); } @@ -9132,7 +9132,7 @@ GeneralParser::synthesizeAccessor( // // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter // 2. Let setter be CreateBuiltinFunction(setterClosure, 1, "set", « »). - StringBuffer storedMethodName(fc_); + StringBuilder storedMethodName(fc_); if (!storedMethodName.append(accessorType == AccessorType::Getter ? "get" : "set")) { return errorResult(); @@ -9670,34 +9670,38 @@ GeneralParser::statementListItem( if (tt == TokenKind::Await && pc_->isAsync()) { #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - // Try finding evidence of a AwaitUsingDeclaration the syntax for which - // would be: - // await [no LineTerminator here] using [no LineTerminator here] - // identifier + if (options().explicitResourceManagement()) { + // Try finding evidence of a AwaitUsingDeclaration the syntax for + // which + // would be: + // await [no LineTerminator here] using [no LineTerminator here] + // identifier - TokenKind nextTokUsing = TokenKind::Eof; - // Scan with regex modifier because when its await expression, `/` - // should be treated as a regexp. - if (!tokenStream.peekTokenSameLine(&nextTokUsing, - TokenStream::SlashIsRegExp)) { - return errorResult(); - } - - if (nextTokUsing == TokenKind::Using && - this->pc_->isUsingSyntaxAllowed()) { - tokenStream.consumeKnownToken(nextTokUsing, - TokenStream::SlashIsRegExp); - TokenKind nextTokIdentifier = TokenKind::Eof; - // Here we can use the Div modifier because if the next token is using - // then a `/` as the next token can only be considered a division. - if (!tokenStream.peekTokenSameLine(&nextTokIdentifier)) { + TokenKind nextTokUsing = TokenKind::Eof; + // Scan with regex modifier because when its await expression, `/` + // should be treated as a regexp. + if (!tokenStream.peekTokenSameLine(&nextTokUsing, + TokenStream::SlashIsRegExp)) { return errorResult(); } - if (TokenKindIsPossibleIdentifier(nextTokIdentifier)) { - return lexicalDeclaration(yieldHandling, - DeclarationKind::AwaitUsing); + + if (nextTokUsing == TokenKind::Using && + this->pc_->isUsingSyntaxAllowed()) { + tokenStream.consumeKnownToken(nextTokUsing, + TokenStream::SlashIsRegExp); + TokenKind nextTokIdentifier = TokenKind::Eof; + // Here we can use the Div modifier because if the next token is + // using then a `/` as the next token can only be considered a + // division. + if (!tokenStream.peekTokenSameLine(&nextTokIdentifier)) { + return errorResult(); + } + if (TokenKindIsPossibleIdentifier(nextTokIdentifier)) { + return lexicalDeclaration(yieldHandling, + DeclarationKind::AwaitUsing); + } + anyChars.ungetToken(); // put back using. } - anyChars.ungetToken(); // put back using. } #endif return expressionStatement(yieldHandling); @@ -9826,7 +9830,8 @@ GeneralParser::statementListItem( if (!tokenStream.peekTokenSameLine(&nextTok)) { return errorResult(); } - if (!TokenKindIsPossibleIdentifier(nextTok) || + if (!options().explicitResourceManagement() || + !TokenKindIsPossibleIdentifier(nextTok) || !this->pc_->isUsingSyntaxAllowed()) { if (!tokenStream.peekToken(&nextTok)) { return errorResult(); @@ -11647,26 +11652,23 @@ Parser::newBigInt() { return errorResult(); } - BigIntIndex index(this->compilationState_.bigIntData.length()); + BigIntIndex index(this->bigInts().length()); if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) { ReportAllocationOverflow(fc_); return errorResult(); } - if (!this->compilationState_.bigIntData.emplaceBack()) { + if (!this->bigInts().emplaceBack()) { js::ReportOutOfMemory(this->fc_); return errorResult(); } - if (!this->compilationState_.bigIntData[index].init( - this->fc_, this->stencilAlloc(), chars)) { + if (!this->bigInts()[index].init(this->fc_, this->stencilAlloc(), chars)) { return errorResult(); } - bool isZero = this->compilationState_.bigIntData[index].isZero(); - // Should the operations below fail, the buffer held by data will // be cleaned up by the CompilationState destructor. - return handler_.newBigInt(index, isZero, pos()); + return handler_.newBigInt(index, pos()); } template @@ -12002,8 +12004,7 @@ GeneralParser::propertyName( static bool TokenKindCanStartPropertyName(TokenKind tt) { return TokenKindIsPossibleIdentifierName(tt) || tt == TokenKind::String || tt == TokenKind::Number || tt == TokenKind::LeftBracket || - tt == TokenKind::Mul || tt == TokenKind::BigInt || - tt == TokenKind::PrivateName; + tt == TokenKind::BigInt || tt == TokenKind::PrivateName; } template @@ -12069,7 +12070,7 @@ GeneralParser::propertyOrMethodName( if (!tokenStream.peekTokenSameLine(&tt)) { return errorResult(); } - if (TokenKindCanStartPropertyName(tt)) { + if (TokenKindCanStartPropertyName(tt) || tt == TokenKind::Mul) { isAsync = true; tokenStream.consumeKnownToken(tt); ltok = tt; @@ -12161,15 +12162,6 @@ GeneralParser::propertyOrMethodName( if (tt == TokenKind::LeftParen) { anyChars.ungetToken(); -#ifdef ENABLE_RECORD_TUPLE - if (propertyNameContext == PropertyNameInRecord) { - // Record & Tuple proposal, section 7.1.1: - // RecordPropertyDefinition doesn't cover methods - error(JSMSG_BAD_PROP_ID); - return errorResult(); - } -#endif - #ifdef ENABLE_DECORATORS if (hasAccessor) { error(JSMSG_BAD_PROP_ID); @@ -12488,192 +12480,6 @@ GeneralParser::objectLiteral(YieldHandling yieldHandling, return literal; } -#ifdef ENABLE_RECORD_TUPLE -template -typename ParseHandler::ListNodeResult -GeneralParser::recordLiteral(YieldHandling yieldHandling) { - MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::HashCurly)); - - uint32_t openedPos = pos().begin; - - ListNodeType literal; - MOZ_TRY_VAR(literal, handler_.newRecordLiteral(pos().begin)); - - TaggedParserAtomIndex propAtom; - for (;;) { - TokenKind tt; - if (!tokenStream.peekToken(&tt)) { - return errorResult(); - } - if (tt == TokenKind::RightCurly) { - break; - } - - if (tt == TokenKind::TripleDot) { - tokenStream.consumeKnownToken(TokenKind::TripleDot); - uint32_t begin = pos().begin; - - TokenPos innerPos; - if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) { - return errorResult(); - } - - Node inner; - MOZ_TRY_VAR(inner, - assignExpr(InAllowed, yieldHandling, TripledotProhibited)); - - if (!handler_.addSpreadProperty(literal, begin, inner)) { - return errorResult(); - } - } else { - TokenPos namePos = anyChars.nextToken().pos; - - PropertyType propType; - Node propName; - MOZ_TRY_VAR(propName, - propertyOrMethodName(yieldHandling, PropertyNameInRecord, - /* maybeDecl */ Nothing(), literal, - &propType, &propAtom)); - - if (propType == PropertyType::Normal) { - TokenPos exprPos; - if (!tokenStream.peekTokenPos(&exprPos, TokenStream::SlashIsRegExp)) { - return errorResult(); - } - - Node propExpr; - MOZ_TRY_VAR(propExpr, - assignExpr(InAllowed, yieldHandling, TripledotProhibited)); - - if (propAtom == TaggedParserAtomIndex::WellKnown::proto_()) { - errorAt(namePos.begin, JSMSG_RECORD_NO_PROTO); - return errorResult(); - } - - BinaryNodeType propDef; - MOZ_TRY_VAR(propDef, - handler_.newPropertyDefinition(propName, propExpr)); - - handler_.addPropertyDefinition(literal, propDef); - } else if (propType == PropertyType::Shorthand) { - /* - * Support |var o = #{x, y}| as initializer shorthand for - * |var o = #{x: x, y: y}|. - */ - TaggedParserAtomIndex name = identifierReference(yieldHandling); - if (!name) { - return errorResult(); - } - - NameNodeType nameExpr; - MOZ_TRY_VAR(nameExpr, identifierReference(name)); - - if (!handler_.addShorthand(literal, handler_.asNameNode(propName), - nameExpr)) { - return errorResult(); - } - } else { - error(JSMSG_BAD_PROP_ID); - return errorResult(); - } - } - - bool matched; - if (!tokenStream.matchToken(&matched, TokenKind::Comma, - TokenStream::SlashIsInvalid)) { - return errorResult(); - } - if (!matched) { - break; - } - } - - if (!mustMatchToken( - TokenKind::RightCurly, [this, openedPos](TokenKind actual) { - this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST, - JSMSG_CURLY_OPENED, openedPos); - })) { - return errorResult(); - } - - handler_.setEndPosition(literal, pos().end); - return literal; -} - -template -typename ParseHandler::ListNodeResult -GeneralParser::tupleLiteral(YieldHandling yieldHandling) { - MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::HashBracket)); - - uint32_t begin = pos().begin; - ListNodeType literal; - MOZ_TRY_VAR(literal, handler_.newTupleLiteral(begin)); - - for (uint32_t index = 0;; index++) { - if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) { - error(JSMSG_ARRAY_INIT_TOO_BIG); - return errorResult(); - } - - TokenKind tt; - if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) { - return errorResult(); - } - if (tt == TokenKind::RightBracket) { - break; - } - - if (tt == TokenKind::TripleDot) { - tokenStream.consumeKnownToken(TokenKind::TripleDot, - TokenStream::SlashIsRegExp); - uint32_t begin = pos().begin; - - TokenPos innerPos; - if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) { - return errorResult(); - } - - Node inner; - MOZ_TRY_VAR(inner, - assignExpr(InAllowed, yieldHandling, TripledotProhibited)); - - if (!handler_.addSpreadElement(literal, begin, inner)) { - return errorResult(); - } - } else { - TokenPos elementPos; - if (!tokenStream.peekTokenPos(&elementPos, TokenStream::SlashIsRegExp)) { - return errorResult(); - } - - Node element; - MOZ_TRY_VAR(element, - assignExpr(InAllowed, yieldHandling, TripledotProhibited)); - handler_.addArrayElement(literal, element); - } - - bool matched; - if (!tokenStream.matchToken(&matched, TokenKind::Comma, - TokenStream::SlashIsRegExp)) { - return errorResult(); - } - if (!matched) { - break; - } - } - - if (!mustMatchToken(TokenKind::RightBracket, [this, begin](TokenKind actual) { - this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST, - JSMSG_BRACKET_OPENED, begin); - })) { - return errorResult(); - } - - handler_.setEndPosition(literal, pos().end); - return literal; -} -#endif - template typename ParseHandler::FunctionNodeResult GeneralParser::methodDefinition( @@ -12894,14 +12700,6 @@ GeneralParser::primaryExpr( case TokenKind::LeftCurly: return objectLiteral(yieldHandling, possibleError); -#ifdef ENABLE_RECORD_TUPLE - case TokenKind::HashCurly: - return recordLiteral(yieldHandling); - - case TokenKind::HashBracket: - return tupleLiteral(yieldHandling); -#endif - #ifdef ENABLE_DECORATORS case TokenKind::At: return classDefinition(yieldHandling, ClassExpression, NameRequired); diff --git a/src/third_party/mozjs/extract/js/src/frontend/Parser.h b/src/third_party/mozjs/extract/js/src/frontend/Parser.h index 9cf19cdaf45..c166fc76010 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/Parser.h +++ b/src/third_party/mozjs/extract/js/src/frontend/Parser.h @@ -267,6 +267,11 @@ class MOZ_STACK_CLASS ParserSharedBase { return compilationState_.parserAtoms; } + BigIntStencilVector& bigInts() { return compilationState_.bigIntData; } + const BigIntStencilVector& bigInts() const { + return compilationState_.bigIntData; + } + LifoAlloc& stencilAlloc() { return compilationState_.alloc; } const UsedNameTracker& usedNames() { return usedNames_; } @@ -285,9 +290,6 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase, ScriptSource* ss; - // Perform constant-folding; must be true when interfacing with the emitter. - const bool foldConstants_ : 1; - protected: #if DEBUG /* Our fallible 'checkOptions' member function has been called. */ @@ -324,7 +326,7 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase, friend class AutoInParametersOfAsyncFunction; ParserBase(FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - bool foldConstants, CompilationState& compilationState); + CompilationState& compilationState); ~ParserBase(); bool checkOptions(); @@ -475,16 +477,16 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase { // are less likely to select this overload. PerHandlerParser(FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - bool foldConstants, CompilationState& compilationState, + CompilationState& compilationState, void* internalSyntaxParser); protected: template PerHandlerParser(FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - bool foldConstants, CompilationState& compilationState, + CompilationState& compilationState, GeneralParser* syntaxParser) - : PerHandlerParser(fc, options, foldConstants, compilationState, + : PerHandlerParser(fc, options, compilationState, static_cast(syntaxParser)) {} static typename ParseHandler::NullNode null() { return ParseHandler::null(); } @@ -719,7 +721,6 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { using Base::finishClassBodyScope; using Base::finishFunctionScopes; using Base::finishLexicalScope; - using Base::foldConstants_; using Base::getFilename; using Base::hasValidSimpleStrictParameterNames; using Base::isUnexpectedEOF_; @@ -930,7 +931,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { public: GeneralParser(FrontendContext* fc, const JS::ReadOnlyCompileOptions& options, - const Unit* units, size_t length, bool foldConstants, + const Unit* units, size_t length, CompilationState& compilationState, SyntaxParser* syntaxParser); inline void setAwaitHandling(AwaitHandling awaitHandling); @@ -1418,9 +1419,6 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { PropertyNameInLiteral, PropertyNameInPattern, PropertyNameInClass, -#ifdef ENABLE_RECORD_TUPLE - PropertyNameInRecord -#endif }; NodeResult propertyName(YieldHandling yieldHandling, PropertyNameContext propertyNameContext, @@ -1442,11 +1440,6 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { ListNodeResult objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError); -#ifdef ENABLE_RECORD_TUPLE - ListNodeResult recordLiteral(YieldHandling yieldHandling); - ListNodeResult tupleLiteral(YieldHandling yieldHandling); -#endif - BinaryNodeResult bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling); NameNodeResult bindingIdentifier(DeclarationKind kind, diff --git a/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.cpp b/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.cpp index 7ac91ba5984..4bf2d528db5 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.cpp @@ -13,11 +13,11 @@ #include "jsnum.h" // CharsToNumber #include "frontend/CompilationStencil.h" -#include "js/GCAPI.h" // JS::AutoSuppressGCAnalysis -#include "js/Printer.h" // Sprinter, QuoteString -#include "util/Identifier.h" // IsIdentifier -#include "util/StringBuffer.h" // StringBuffer -#include "util/Text.h" // AsciiDigitToNumber +#include "js/GCAPI.h" // JS::AutoSuppressGCAnalysis +#include "js/Printer.h" // Sprinter, QuoteString +#include "util/Identifier.h" // IsIdentifier +#include "util/StringBuilder.h" // StringBuilder +#include "util/Text.h" // AsciiDigitToNumber #include "util/Unicode.h" #include "vm/JSContext.h" #include "vm/Runtime.h" @@ -737,7 +737,8 @@ bool ParserAtomsTable::isExtendedUnclonedSelfHostedFunctionName( case WellKnownAtomId::dollar_ArraySpecies_: case WellKnownAtomId::dollar_ArrayValues_: case WellKnownAtomId::dollar_RegExpFlagsGetter_: - case WellKnownAtomId::dollar_RegExpToString_: { + case WellKnownAtomId::dollar_RegExpToString_: + case WellKnownAtomId::dollar_SharedArrayBufferSpecies_: { #ifdef DEBUG const auto& info = GetWellKnownAtomInfo(index.toWellKnownAtomId()); MOZ_ASSERT(info.content[0] == @@ -1121,36 +1122,36 @@ JSAtom* ParserAtomsTable::toJSAtom(JSContext* cx, FrontendContext* fc, return cx->staticStrings().getUint(s); } -bool ParserAtomsTable::appendTo(StringBuffer& buffer, +bool ParserAtomsTable::appendTo(StringBuilder& sb, TaggedParserAtomIndex index) const { if (index.isParserAtomIndex()) { const auto* atom = getParserAtom(index.toParserAtomIndex()); size_t length = atom->length(); - return atom->hasLatin1Chars() ? buffer.append(atom->latin1Chars(), length) - : buffer.append(atom->twoByteChars(), length); + return atom->hasLatin1Chars() ? sb.append(atom->latin1Chars(), length) + : sb.append(atom->twoByteChars(), length); } if (index.isWellKnownAtomId()) { const auto& info = GetWellKnownAtomInfo(index.toWellKnownAtomId()); - return buffer.append(info.content, info.length); + return sb.append(info.content, info.length); } if (index.isLength1StaticParserString()) { Latin1Char content[1]; getLength1Content(index.toLength1StaticParserString(), content); - return buffer.append(content[0]); + return sb.append(content[0]); } if (index.isLength2StaticParserString()) { char content[2]; getLength2Content(index.toLength2StaticParserString(), content); - return buffer.append(content, 2); + return sb.append(content, 2); } MOZ_ASSERT(index.isLength3StaticParserString()); char content[3]; getLength3Content(index.toLength3StaticParserString(), content); - return buffer.append(content, 3); + return sb.append(content, 3); } bool InstantiateMarkedAtoms(JSContext* cx, FrontendContext* fc, @@ -1214,7 +1215,7 @@ bool InstantiateMarkedAtomsAsPermanent(JSContext* cx, FrontendContext* fc, } /* static */ -WellKnownParserAtoms WellKnownParserAtoms::singleton_; +MOZ_RUNINIT WellKnownParserAtoms WellKnownParserAtoms::singleton_; template TaggedParserAtomIndex WellKnownParserAtoms::lookupChar16Seq( diff --git a/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.h b/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.h index ef1aae07a74..0da6fd5d5b3 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.h +++ b/src/third_party/mozjs/extract/js/src/frontend/ParserAtom.h @@ -45,7 +45,7 @@ namespace js { class AtomSet; class JS_PUBLIC_API GenericPrinter; class LifoAlloc; -class StringBuffer; +class StringBuilder; namespace frontend { @@ -786,7 +786,7 @@ class ParserAtomsTable { JSAtom* toWellKnownJSAtom(JSContext* cx, TaggedParserAtomIndex index) const; public: - bool appendTo(StringBuffer& buffer, TaggedParserAtomIndex index) const; + bool appendTo(StringBuilder& sb, TaggedParserAtomIndex index) const; public: #if defined(DEBUG) || defined(JS_JITSPEW) diff --git a/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.cpp index c10463eb56a..d28d6f029bf 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.cpp @@ -100,19 +100,6 @@ bool PrivateOpEmitter::emitReference() { return true; } -bool PrivateOpEmitter::skipReference() { - MOZ_ASSERT(state_ == State::Start); - - if (!init()) { - return false; - } - -#ifdef DEBUG - state_ = State::Reference; -#endif - return true; -} - bool PrivateOpEmitter::emitGet() { MOZ_ASSERT(state_ == State::Reference); @@ -250,7 +237,7 @@ bool PrivateOpEmitter::emitAssignment() { } } - JSOp setOp = isFieldInit() ? JSOp::InitElem : JSOp::StrictSetElem; + JSOp setOp = isFieldInit() ? JSOp::InitHiddenElem : JSOp::StrictSetElem; if (!bce_->emitElemOpBase(setOp)) { // [stack] RHS return false; diff --git a/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.h index 558541b05c3..09c80218ea1 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/PrivateOpEmitter.h @@ -114,8 +114,7 @@ class MOZ_STACK_CLASS PrivateOpEmitter { #ifdef DEBUG // The state of this emitter. // - // emitReference - // +-------+ skipReference +-----------+ + // +-------+ emitReference +-----------+ // | Start |---------------->| Reference | // +-------+ +-----+-----+ // | @@ -144,7 +143,7 @@ class MOZ_STACK_CLASS PrivateOpEmitter { // The initial state. Start, - // After calling emitReference or skipReference. + // After calling emitReference. Reference, // After calling emitGet. @@ -216,13 +215,12 @@ class MOZ_STACK_CLASS PrivateOpEmitter { [[nodiscard]] bool emitBrandCheck(); [[nodiscard]] bool emitReference(); - [[nodiscard]] bool skipReference(); [[nodiscard]] bool emitGet(); [[nodiscard]] bool emitGetForCallOrNew(); [[nodiscard]] bool emitAssignment(); [[nodiscard]] bool emitIncDec(ValueUsage valueUsage); - [[nodiscard]] size_t numReferenceSlots() { return 2; } + size_t numReferenceSlots() const { return 2; } }; } /* namespace frontend */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.cpp index ff08bd85804..9e420bd6ab1 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.cpp @@ -112,19 +112,8 @@ bool PropOpEmitter::prepareForRhs() { return true; } -bool PropOpEmitter::skipObjAndRhs() { - MOZ_ASSERT(state_ == State::Start); - MOZ_ASSERT(isSimpleAssignment() || isPropInit()); - -#ifdef DEBUG - state_ = State::Rhs; -#endif - return true; -} - bool PropOpEmitter::emitDelete(TaggedParserAtomIndex prop) { - MOZ_ASSERT_IF(!isSuper(), state_ == State::Obj); - MOZ_ASSERT_IF(isSuper(), state_ == State::Start); + MOZ_ASSERT(state_ == State::Obj); MOZ_ASSERT(isDelete()); if (!prepareAtomIndex(prop)) { diff --git a/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.h index 76402025ea0..91a182685fa 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/PropOpEmitter.h @@ -9,6 +9,8 @@ #include "mozilla/Attributes.h" +#include + #include "vm/SharedStencil.h" // GCThingIndex namespace js { @@ -128,39 +130,37 @@ class MOZ_STACK_CLASS PropOpEmitter { #ifdef DEBUG // The state of this emitter. // - // skipObjAndRhs - // +----------------------------+ - // | | - // +-------+ | prepareForObj +-----+ | - // | Start |-+-------------->| Obj |-+ | - // +-------+ +-----+ | | - // | | - // +---------------------------------+ | - // | | - // | | - // | [Get] | - // | [Call] | - // | emitGet +-----+ | - // +---------->| Get | | - // | +-----+ | - // | | - // | [Delete] | - // | emitDelete +--------+ | - // +------------->| Delete | | - // | +--------+ | - // | | - // | [PostIncrement] | - // | [PreIncrement] | - // | [PostDecrement] | - // | [PreDecrement] | - // | emitIncDec +--------+ | - // +------------->| IncDec | | - // | +--------+ | - // | | - // | [SimpleAssignment] | - // | [PropInit] | - // | prepareForRhs | +-----+ - // +--------------------->+-------------->+->| Rhs |-+ + // + // +-------+ prepareForObj +-----+ + // | Start |---------------->| Obj |-+ + // +-------+ +-----+ | + // | + // +---------------------------------+ + // | + // | + // | [Get] + // | [Call] + // | emitGet +-----+ + // +---------->| Get | + // | +-----+ + // | + // | [Delete] + // | emitDelete +--------+ + // +------------->| Delete | + // | +--------+ + // | + // | [PostIncrement] + // | [PreIncrement] + // | [PostDecrement] + // | [PreDecrement] + // | emitIncDec +--------+ + // +------------->| IncDec | + // | +--------+ + // | + // | [SimpleAssignment] + // | [PropInit] + // | prepareForRhs +-----+ + // +--------------------->+----------------->| Rhs |-+ // | ^ +-----+ | // | | | // | | +---------+ @@ -184,7 +184,7 @@ class MOZ_STACK_CLASS PropOpEmitter { // After calling emitIncDec. IncDec, - // After calling prepareForRhs or skipObjAndRhs. + // After calling prepareForRhs. Rhs, // After calling emitAssignment. @@ -237,7 +237,6 @@ class MOZ_STACK_CLASS PropOpEmitter { [[nodiscard]] bool emitGet(TaggedParserAtomIndex prop); [[nodiscard]] bool prepareForRhs(); - [[nodiscard]] bool skipObjAndRhs(); [[nodiscard]] bool emitDelete(TaggedParserAtomIndex prop); @@ -246,6 +245,8 @@ class MOZ_STACK_CLASS PropOpEmitter { [[nodiscard]] bool emitIncDec(TaggedParserAtomIndex prop, ValueUsage valueUsage); + + size_t numReferenceSlots() const { return 1 + isSuper(); } }; } /* namespace frontend */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/SharedContext.h b/src/third_party/mozjs/extract/js/src/frontend/SharedContext.h index ab0606527e2..cdedfec08a9 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/SharedContext.h +++ b/src/third_party/mozjs/extract/js/src/frontend/SharedContext.h @@ -261,9 +261,9 @@ class SharedContext { bool hasExplicitUseStrict() const { return hasExplicitUseStrict_; } void setExplicitUseStrict() { hasExplicitUseStrict_ = true; } - ImmutableScriptFlags immutableFlags() { return immutableFlags_; } + ImmutableScriptFlags immutableFlags() const { return immutableFlags_; } - bool allBindingsClosedOver() { return bindingsAccessedDynamically(); } + bool allBindingsClosedOver() const { return bindingsAccessedDynamically(); } // The ImmutableFlag tracks if the entire script is strict, while the // localStrict flag indicates the current region (such as class body) should @@ -277,7 +277,7 @@ class SharedContext { return retVal; } - bool isEligibleForArgumentsLength() { + bool isEligibleForArgumentsLength() const { return eligibleForArgumentsLength && !bindingsAccessedDynamically(); } void setIneligibleForArgumentsLength() { eligibleForArgumentsLength = false; } @@ -564,7 +564,7 @@ class FunctionBox : public SuspendableContext { bool isInterpreted() const { return flags_.hasBaseScript(); } - FunctionFlags::FunctionKind kind() { return flags_.kind(); } + FunctionFlags::FunctionKind kind() const { return flags_.kind(); } bool hasInferredName() const { return flags_.hasInferredName(); } bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); } @@ -681,7 +681,7 @@ class FunctionBox : public SuspendableContext { } } - uint16_t length() { return length_; } + uint16_t length() const { return length_; } void setLength(uint16_t length) { length_ = length; } void setArgCount(uint16_t args) { @@ -689,7 +689,7 @@ class FunctionBox : public SuspendableContext { nargs_ = args; } - size_t nargs() { return nargs_; } + size_t nargs() const { return nargs_; } const MemberInitializers& memberInitializers() const { MOZ_ASSERT(useMemberInitializers()); @@ -704,7 +704,7 @@ class FunctionBox : public SuspendableContext { } } - ScriptIndex index() { return funcDataIndex_; } + ScriptIndex index() const { return funcDataIndex_; } void finishScriptFlags(); void copyFunctionFields(ScriptStencil& script); diff --git a/src/third_party/mozjs/extract/js/src/frontend/Stencil.cpp b/src/third_party/mozjs/extract/js/src/frontend/Stencil.cpp index 2514af26bc2..67005e94619 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/Stencil.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/Stencil.cpp @@ -8,6 +8,7 @@ #include "mozilla/AlreadyAddRefed.h" // already_AddRefed #include "mozilla/Assertions.h" // MOZ_RELEASE_ASSERT +#include "mozilla/CheckedInt.h" // mozilla::CheckedInt #include "mozilla/Maybe.h" // mozilla::Maybe #include "mozilla/OperatorNewExtensions.h" // mozilla::KnownNotNull #include "mozilla/PodOperations.h" // mozilla::PodCopy @@ -31,21 +32,27 @@ #include "frontend/StencilXdr.h" // XDRStencilEncoder, XDRStencilDecoder #include "gc/AllocKind.h" // gc::AllocKind #include "gc/Tracer.h" // TraceNullableRoot +#include "jit/BaselineJIT.h" // jit::BaselineScript +#include "jit/JitRuntime.h" // jit::JitRuntime +#include "jit/JitScript.h" // AutoKeepJitScripts #include "js/CallArgs.h" // JSNative #include "js/CompileOptions.h" // JS::DecodeOptions, JS::ReadOnlyDecodeOptions -#include "js/experimental/JSStencil.h" // JS::Stencil -#include "js/GCAPI.h" // JS::AutoCheckCannotGC -#include "js/Printer.h" // js::Fprinter -#include "js/RealmOptions.h" // JS::RealmBehaviors -#include "js/RootingAPI.h" // Rooted -#include "js/Transcoding.h" // JS::TranscodeBuffer -#include "js/Utility.h" // js_malloc, js_calloc, js_free -#include "js/Value.h" // ObjectValue -#include "js/WasmModule.h" // JS::WasmModule -#include "vm/BigIntType.h" // ParseBigIntLiteral, BigIntLiteralIsZero +#include "js/experimental/CompileScript.h" // JS::PrepareForInstantiate +#include "js/experimental/JSStencil.h" // JS::Stencil +#include "js/GCAPI.h" // JS::AutoCheckCannotGC +#include "js/Prefs.h" // JS::Prefs +#include "js/Printer.h" // js::Fprinter +#include "js/RealmOptions.h" // JS::RealmBehaviors +#include "js/RootingAPI.h" // Rooted +#include "js/Transcoding.h" // JS::TranscodeBuffer +#include "js/Utility.h" // js_malloc, js_calloc, js_free +#include "js/Value.h" // ObjectValue +#include "js/WasmModule.h" // JS::WasmModule +#include "vm/BigIntType.h" // ParseBigIntLiteral, BigInt::createFromInt64 #include "vm/BindingKind.h" // BindingKind #include "vm/EnvironmentObject.h" #include "vm/GeneratorAndAsyncKind.h" // GeneratorKind, FunctionAsyncKind +#include "vm/JSAtomUtils.h" // AtomToPrintableString #include "vm/JSContext.h" // JSContext #include "vm/JSFunction.h" // JSFunction, GetFunctionPrototype, NewFunctionWithProto #include "vm/JSObject.h" // JSObject, TenuredObject @@ -61,8 +68,10 @@ #include "vm/StringType.h" // JSAtom, js::CopyChars #include "wasm/AsmJS.h" // InstantiateAsmJS +#include "jit/JitScript-inl.h" // AutoKeepJitScripts constructor #include "vm/EnvironmentObject-inl.h" // JSObject::enclosingEnvironment #include "vm/JSFunction-inl.h" // JSFunction::create +#include "vm/JSScript-inl.h" // JSScript::baselineScript using namespace js; using namespace js::frontend; @@ -2615,7 +2624,7 @@ void CompilationStencil::assertBorrowingFromExtensibleCompilationStencil( CompilationStencil::CompilationStencil( UniquePtr&& extensibleStencil) - : alloc(LifoAllocChunkSize) { + : alloc(LifoAllocChunkSize, js::BackgroundMallocArena) { ownedBorrowStencil = std::move(extensibleStencil); storageType = StorageType::OwnedExtensible; @@ -2839,7 +2848,7 @@ JSFunction* CompilationStencil::instantiateSelfHostedLazyFunction( bool CompilationStencil::delazifySelfHostedFunction( JSContext* cx, CompilationAtomCache& atomCache, ScriptIndexRange range, - HandleFunction fun) { + Handle name, HandleFunction fun) { // Determine the equivalent ScopeIndex range by looking at the outermost scope // of the scripts defining the range. Take special care if this is the last // script in the list. @@ -2852,6 +2861,7 @@ bool CompilationStencil::delazifySelfHostedFunction( ScopeIndex scopeLimit = (range.limit < scriptData.size()) ? getOutermostScope(range.limit) : ScopeIndex(scopeData.size()); + Rooted jitCacheKey(cx, name); // Prepare to instantiate by allocating the output arrays. We also set a base // index to avoid allocations in most cases. @@ -2924,11 +2934,92 @@ bool CompilationStencil::delazifySelfHostedFunction( // `InstantiateTopLevel` helper and directly create the JSScript. Our // caller also handles the `AllowRelazify` flag for us since self-hosted // delazification is a special case. - if (!JSScript::fromStencil(cx, atomCache, *this, gcOutput.get(), - range.start)) { + Rooted script( + cx, + JSScript::fromStencil(cx, atomCache, *this, gcOutput.get(), range.start)); + if (!script) { return false; } + if (JS::Prefs::experimental_self_hosted_cache()) { + // We eagerly baseline-compile self-hosted functions, and cache their + // JitCode for reuse across the runtime. If the cache already contains an + // entry for this function, update the JitScript. If not, compile it now and + // store it in the cache. + UniqueChars nameStr; + if (JS_SHOULD_LOG(selfHosted, Debug)) { + nameStr = AtomToPrintableString(cx, name); + } + auto& jitCache = cx->runtime()->selfHostJitCache.ref(); + auto v = jitCache.readonlyThreadsafeLookup(jitCacheKey); + if (v && v->value()->method()) { + JS_LOG(selfHosted, Debug, + "self_hosted_cache: reusing JIT code for script '%s'", + nameStr.get()); + + if (!cx->zone()->ensureJitZoneExists(cx)) { + return false; + } + jit::AutoKeepJitScripts keepJitScript(cx); + if (!script->ensureHasJitScript(cx, keepJitScript)) { + return false; + } + MOZ_ASSERT(!script->hasBaselineScript()); + + // JSScript destroys its BaselineScript on finalize, so we need another + // copy here (for now) + jit::BaselineScript* baselineScript = + jit::BaselineScript::Copy(cx, v->value()); + if (!baselineScript) { + return false; + } + mozilla::DebugOnly instrumentationEnabled = + cx->runtime()->jitRuntime()->isProfilerInstrumentationEnabled( + cx->runtime()); + MOZ_ASSERT(instrumentationEnabled == + baselineScript->isProfilerInstrumentationOn()); + script->jitScript()->setBaselineScript(script, baselineScript); + } else if (jit::IsBaselineJitEnabled(cx) && script->canBaselineCompile() && + !script->hasBaselineScript() && + jit::CanBaselineInterpretScript(script)) { + JS_LOG(selfHosted, Debug, + "self_hosted_cache: new JIT code entry for script '%s'", + nameStr.get()); + + if (!cx->zone()->ensureJitZoneExists(cx)) { + return false; + } + + jit::AutoKeepJitScripts keep(cx); + if (!script->ensureHasJitScript(cx, keep)) { + return false; + } + + jit::BaselineOptions options( + {jit::BaselineOption::ForceMainThreadCompilation}); + jit::MethodStatus result = + jit::BaselineCompile(cx, script.get(), options); + if (result != jit::Method_Compiled) { + return false; + } + MOZ_ASSERT(script->hasBaselineScript()); + + jit::BaselineScript* baselineScript = + jit::BaselineScript::Copy(cx, script->baselineScript()); + if (!baselineScript) { + return false; + } + if (!jitCache.put(jitCacheKey, baselineScript)) { + return false; + } + } else { + JS_LOG(selfHosted, Debug, + "self_hosted_cache: script '%s' is not eligible for Baseline " + "compilation", + nameStr.get()); + } + } + // Phase 6: Update lazy scripts. // NOTE: Self-hosting is always fully parsed so there is nothing to do here. @@ -2956,75 +3047,37 @@ bool CompilationStencil::prepareForInstantiate( stencil.scopeData.size()); } -bool CompilationStencil::serializeStencils(JSContext* cx, - CompilationInput& input, - JS::TranscodeBuffer& buf, - bool* succeededOut) const { - if (succeededOut) { - *succeededOut = false; - } - AutoReportFrontendContext fc(cx); - XDRStencilEncoder encoder(&fc, buf); - - XDRResult res = encoder.codeStencil(*this); - if (res.isErr()) { - if (JS::IsTranscodeFailureResult(res.unwrapErr())) { - buf.clear(); - return true; +bool JS::PrepareForInstantiate(JS::FrontendContext* fc, JS::Stencil& stencil, + JS::InstantiationStorage& storage) { + if (!storage.gcOutput_) { + storage.gcOutput_ = + fc->getAllocator() + ->new_(); + if (!storage.gcOutput_) { + return false; } - MOZ_ASSERT(res.unwrapErr() == JS::TranscodeResult::Throw); - - return false; } - if (succeededOut) { - *succeededOut = true; - } - return true; -} - -bool CompilationStencil::deserializeStencils( - FrontendContext* fc, const JS::ReadOnlyCompileOptions& compileOptions, - const JS::TranscodeRange& range, bool* succeededOut) { - if (succeededOut) { - *succeededOut = false; - } - MOZ_ASSERT(parserAtomData.empty()); - XDRStencilDecoder decoder(fc, range); - JS::DecodeOptions options(compileOptions); - - XDRResult res = decoder.codeStencil(options, *this); - if (res.isErr()) { - if (JS::IsTranscodeFailureResult(res.unwrapErr())) { - return true; - } - MOZ_ASSERT(res.unwrapErr() == JS::TranscodeResult::Throw); - - return false; - } - - if (succeededOut) { - *succeededOut = true; - } - return true; + return CompilationStencil::prepareForInstantiate(fc, *stencil.getInitial(), + *storage.gcOutput_); } ExtensibleCompilationStencil::ExtensibleCompilationStencil(ScriptSource* source) - : alloc(CompilationStencil::LifoAllocChunkSize), + : alloc(CompilationStencil::LifoAllocChunkSize, js::BackgroundMallocArena), source(source), parserAtoms(alloc) {} ExtensibleCompilationStencil::ExtensibleCompilationStencil( CompilationInput& input) : canLazilyParse(CanLazilyParse(input.options)), - alloc(CompilationStencil::LifoAllocChunkSize), + alloc(CompilationStencil::LifoAllocChunkSize, js::BackgroundMallocArena), source(input.source), parserAtoms(alloc) {} ExtensibleCompilationStencil::ExtensibleCompilationStencil( const JS::ReadOnlyCompileOptions& options, RefPtr source) : canLazilyParse(CanLazilyParse(options)), - alloc(CompilationStencil::LifoAllocChunkSize), + alloc(CompilationStencil::LifoAllocChunkSize, js::BackgroundMallocArena), source(std::move(source)), parserAtoms(alloc) {} @@ -3429,7 +3482,7 @@ bool ExtensibleCompilationStencil::cloneFromImpl(FrontendContext* fc, return false; } for (size_t i = 0; i < bigIntSize; i++) { - if (!bigIntData[i].init(fc, alloc, other.bigIntData[i].source())) { + if (!bigIntData[i].init(fc, alloc, other.bigIntData[i])) { return false; } } @@ -3500,7 +3553,7 @@ bool ExtensibleCompilationStencil::steal(FrontendContext* fc, MOZ_ASSERT(alloc.isEmpty()); using StorageType = CompilationStencil::StorageType; StorageType storageType = other->storageType; - if (other->refCount > 1) { + if (other->hasMultipleReference()) { storageType = StorageType::Borrowed; } @@ -3548,7 +3601,7 @@ bool ExtensibleCompilationStencil::steal(FrontendContext* fc, #ifdef DEBUG other->assertNoExternalDependency(); - MOZ_ASSERT(other->refCount == 1); + MOZ_ASSERT(!other->hasMultipleReference()); #endif // If CompilationStencil has no external dependency, @@ -3621,44 +3674,306 @@ bool ExtensibleCompilationStencil::isModule() const { return scriptExtra[CompilationStencil::TopLevelIndex].isModule(); } +bool CompilationStencil::hasAsmJS() const { return asmJS; } + +bool ExtensibleCompilationStencil::hasAsmJS() const { return asmJS; } + +bool InitialStencilAndDelazifications::hasAsmJS() const { + return initial_->hasAsmJS(); +} + +InitialStencilAndDelazifications::~InitialStencilAndDelazifications() { + MOZ_ASSERT(refCount_ == 0); + + for (size_t i = 0; i < delazifications_.length(); i++) { + CompilationStencil* delazification = delazifications_[i].exchange(nullptr); + if (delazification) { + delazification->Release(); + } + } +} + +void InitialStencilAndDelazifications::AddRef() { refCount_++; } + +void InitialStencilAndDelazifications::Release() { + MOZ_RELEASE_ASSERT(refCount_ > 0); + if (--refCount_ == 0) { + js_delete(this); + } +} + +bool InitialStencilAndDelazifications::init(FrontendContext* fc, + const CompilationStencil* initial) { + MOZ_ASSERT(initial->isInitialStencil()); + + initial_ = initial; + + if (!canLazilyParse()) { + // If the initial stencil is known to be fully-parsed, delazification + // never happens, and the delazifications_ vector and the + // functionKeyToInitialScriptIndex_ map is never used. + return true; + } + + if (!delazifications_.resize(initial_->scriptData.size())) { + ReportOutOfMemory(fc); + return false; + } + + return functionKeyToInitialScriptIndex_.init(fc, initial_); +} + +const CompilationStencil* InitialStencilAndDelazifications::getInitial() const { + return initial_.get(); +} + +const CompilationStencil* InitialStencilAndDelazifications::getDelazificationAt( + size_t functionIndex) const { + MOZ_ASSERT(canLazilyParse()); + MOZ_ASSERT(functionIndex > 0); + + return delazifications_[functionIndex - 1]; +} + +const CompilationStencil* +InitialStencilAndDelazifications::getDelazificationFor( + const SourceExtent& extent) const { + MOZ_ASSERT(canLazilyParse()); + auto maybeIndex = + functionKeyToInitialScriptIndex_.get(extent.toFunctionKey()); + MOZ_ASSERT(maybeIndex, + "The extent parameter should be for a function inside the script"); + return getDelazificationAt(*maybeIndex); +} + +const CompilationStencil* InitialStencilAndDelazifications::storeDelazification( + RefPtr&& delazification) { + MOZ_ASSERT(!delazification->hasMultipleReference()); + MOZ_ASSERT(canLazilyParse()); + + auto maybeIndex = + functionKeyToInitialScriptIndex_.get(delazification->functionKey); + MOZ_ASSERT(maybeIndex); + size_t functionIndex = *maybeIndex; + + CompilationStencil* raw = delazification.forget().take(); + if (delazifications_[functionIndex - 1].compareExchange(nullptr, raw)) { + return raw; + } + + raw->Release(); + return delazifications_[functionIndex - 1]; +} + +CompilationStencil* InitialStencilAndDelazifications::getMerged( + FrontendContext* fc) const { + MOZ_ASSERT(canLazilyParse()); + + UniquePtr extensibleStencil( + fc->getAllocator()->new_(initial_->source)); + if (!extensibleStencil) { + return nullptr; + } + + if (!extensibleStencil->cloneFrom(fc, *initial_)) { + return nullptr; + } + + CompilationStencilMerger merger; + if (!merger.setInitial(fc, std::move(extensibleStencil))) { + return nullptr; + } + + for (const auto& delazification : delazifications_) { + if (!delazification) { + continue; + } + + // NOTE: The delazifications_ vector can be modified by other threads + // during the iteration. + // The enclosing delazification's is not guaranteed to be iterated + // over in this iteration. + // If the enclosing function wasn't merged, all inner functions are + // ignored inside maybeAddDelazification. + if (!merger.maybeAddDelazification(fc, *delazification)) { + return nullptr; + } + } + + UniquePtr merged = merger.takeResult(); + return fc->getAllocator()->new_(std::move(merged)); +} + +/* static */ +bool InitialStencilAndDelazifications::instantiateStencils( + JSContext* cx, CompilationInput& input, + InitialStencilAndDelazifications& stencils, CompilationGCOutput& gcOutput) { + if (!CompilationStencil::instantiateStencils(cx, input, *stencils.initial_, + gcOutput)) { + return false; + } + + if (input.options.populateDelazificationCache()) { + RefPtr stencilsPtr = &stencils; + ScriptSourceObject* sso = gcOutput.script->sourceObject(); + MOZ_ASSERT(!sso->maybeGetStencils()); + if (!stencils.hasAsmJS()) { + sso->setStencils(stencilsPtr.forget()); + sso->setSharingDelazifications(); + } + } + + // At this point, gcOutput.script contains the top-level script, and + // gcOutput.functions[i] contains i-th function, where 0-th item is + // always nullptr. + // gcOutput.functions[i]->baseScript() is either JSScript or lazy script. + for (size_t i = 0, length = stencils.delazifications_.length(); i < length; + i++) { + const auto& delazification = stencils.delazifications_[i]; + if (!delazification) { + continue; + } + + ScriptIndex scriptIndex = ScriptIndex(i + 1); + JS::Rooted fun(cx, gcOutput.functions[scriptIndex]); + if (!fun->baseScript()->isReadyForDelazification()) { + // NOTE: The delazifications_ vector can be modified by other threads + // during the iteration. + // The enclosing delazification's is not guaranteed to be iterated + // over in this iteration. + // If the enclosing function wasn't instantiated, ignore all inner + // functions. + continue; + } + + JS::Rooted inputForFunc(cx, + CompilationInput(input.options)); + inputForFunc.get().initFromLazy(cx, fun->baseScript(), input.source); + + // TODO: The preparation can be shared across iterations. + JS::Rooted gcOutputForFunc(cx); + if (!CompilationStencil::instantiateStencils( + cx, inputForFunc.get(), *delazification, gcOutputForFunc.get())) { + return false; + } + } + + return true; +} + +size_t InitialStencilAndDelazifications::sizeOfExcludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t size = 0; + + if (initial_) { + // The initial stencil can be shared between multiple owners, but + // in most case this instance is considered as the main owner, in term + // of the memory reporting. + size += initial_->sizeOfExcludingThis(mallocSizeOf); + } + + size += delazifications_.sizeOfExcludingThis(mallocSizeOf); + + for (const auto& delazification : delazifications_) { + if (!delazification) { + continue; + } + + // Delazifications are exclusively owned by this instance. + size += (*delazification).sizeOfExcludingThis(mallocSizeOf); + } + + size += functionKeyToInitialScriptIndex_.sizeOfExcludingThis(mallocSizeOf); + + return size; +} + mozilla::Span ScriptStencil::gcthings( const CompilationStencil& stencil) const { return stencil.gcThingData.Subspan(gcThingsOffset, gcThingsLength); } -bool BigIntStencil::init(FrontendContext* fc, LifoAlloc& alloc, - const mozilla::Span buf) { -#ifdef DEBUG - // Assert we have no separators; if we have a separator then the algorithm - // used in BigInt::literalIsZero will be incorrect. - for (char16_t c : buf) { - MOZ_ASSERT(c != '_'); - } -#endif +bool BigIntStencil::initFromChars(FrontendContext* fc, LifoAlloc& alloc, + mozilla::Span buf) { + MOZ_ASSERT(ParseBigInt64Literal(buf).isNothing(), + "int64-sized BigInts are stored inline"); + size_t length = buf.size(); + MOZ_ASSERT(length > 0); + char16_t* p = alloc.template newArrayUninitialized(length); if (!p) { ReportOutOfMemory(fc); return false; } mozilla::PodCopy(p, buf.data(), length); - source_ = mozilla::Span(p, length); + bigInt_ = mozilla::AsVariant(mozilla::Span(p, length)); return true; } +bool BigIntStencil::init(FrontendContext* fc, LifoAlloc& alloc, + mozilla::Span buf) { + if (auto int64 = ParseBigInt64Literal(buf)) { + bigInt_ = mozilla::AsVariant(*int64); + return true; + } + return initFromChars(fc, alloc, buf); +} + +bool BigIntStencil::init(FrontendContext* fc, LifoAlloc& alloc, + const BigIntStencil& other) { + if (other.bigInt_.is()) { + bigInt_ = other.bigInt_; + return true; + } + return initFromChars(fc, alloc, other.source()); +} + BigInt* BigIntStencil::createBigInt(JSContext* cx) const { - mozilla::Range source(source_.data(), source_.size()); - return js::ParseBigIntLiteral(cx, source); + return bigInt_.match( + [cx](mozilla::Span source) { + return js::ParseBigIntLiteral(cx, source); + }, + [cx](int64_t int64) { + // BigInts are stored in the script's data vector and therefore need to + // be allocated in the tenured heap. + constexpr gc::Heap heap = gc::Heap::Tenured; + return BigInt::createFromInt64(cx, int64, heap); + }); } bool BigIntStencil::isZero() const { - mozilla::Range source(source_.data(), source_.size()); - return js::BigIntLiteralIsZero(source); + return bigInt_.match([](mozilla::Span) { return false; }, + [](int64_t int64) { return int64 == 0; }); +} + +bool BigIntStencil::inplaceNegate() { + return bigInt_.match([](mozilla::Span) { return false; }, + [](int64_t& int64) { + auto negated = -mozilla::CheckedInt{int64}; + if (!negated.isValid()) { + return false; + } + int64 = negated.value(); + return true; + }); +} + +bool BigIntStencil::inplaceBitNot() { + return bigInt_.match([](mozilla::Span) { return false; }, + [](int64_t& int64) { + int64 = ~int64; + return true; + }); } #ifdef DEBUG bool BigIntStencil::isContainedIn(const LifoAlloc& alloc) const { - return alloc.contains(source_.data()); + return bigInt_.match( + [&alloc](mozilla::Span source) { + return alloc.contains(source.data()); + }, + [](int64_t) { return true; }); } #endif @@ -3869,9 +4184,13 @@ void BigIntStencil::dump(js::JSONPrinter& json) const { } void BigIntStencil::dumpCharsNoQuote(GenericPrinter& out) const { - for (char16_t c : source_) { - out.putChar(char(c)); - } + bigInt_.match( + [&out](mozilla::Span source) { + for (char16_t c : source) { + out.putChar(char(c)); + } + }, + [&out](int64_t int64) { out.printf("%" PRId64, int64); }); } void ScopeStencil::dump() const { @@ -4597,9 +4916,7 @@ struct DumpOptionsFields { static void DumpOptionsFields(js::JSONPrinter& json, const JS::ReadOnlyCompileOptions& options) { - struct DumpOptionsFields printer { - json - }; + struct DumpOptionsFields printer{json}; options.dumpWith(printer); } @@ -4838,6 +5155,44 @@ void ExtensibleCompilationStencil::dumpAtom(TaggedParserAtomIndex index) { borrowingStencil.dumpAtom(index); } +void InitialStencilAndDelazifications::dump() const { + js::Fprinter out(stderr); + js::JSONPrinter json(out); + dump(json); + out.put("\n"); +} + +void InitialStencilAndDelazifications::dump(js::JSONPrinter& json) const { + json.beginObject(); + dumpFields(json); + json.endObject(); +} + +void InitialStencilAndDelazifications::dumpFields(js::JSONPrinter& json) const { + if (initial_) { + json.beginObjectProperty("initial_"); + initial_->dumpFields(json); + json.endObject(); + } else { + json.nullProperty("initial_"); + } + + for (size_t i = 0; i < delazifications_.length(); i++) { + const CompilationStencil* delazification = delazifications_[i]; + + char index[64]; + SprintfLiteral(index, "ScriptIndex(%zu)", i + 1); + + if (delazification) { + json.beginObjectProperty(index); + delazification->dumpFields(json); + json.endObject(); + } else { + json.nullProperty(index); + } + } +} + #endif // defined(DEBUG) || defined(JS_JITSPEW) JSString* CompilationAtomCache::getExistingStringAt( @@ -5053,15 +5408,25 @@ void CompilationState::markGhost( } } -bool CompilationStencilMerger::buildFunctionKeyToIndex(FrontendContext* fc) { - if (!functionKeyToInitialScriptIndex_.reserve(initial_->scriptExtra.length() - - 1)) { +ScriptIndex CompilationStencilMerger::getInitialScriptIndexFor( + const CompilationStencil& delazification) const { + auto maybeIndex = + functionKeyToInitialScriptIndex_.get(delazification.functionKey); + MOZ_ASSERT(maybeIndex); + return *maybeIndex; +} + +template +bool FunctionKeyToScriptIndexMap::init(FrontendContext* fc, + const T& scriptExtra, + size_t scriptExtraSize) { + if (!map_.reserve(scriptExtraSize - 1)) { ReportOutOfMemory(fc); return false; } - for (size_t i = 1; i < initial_->scriptExtra.length(); i++) { - const auto& extra = initial_->scriptExtra[i]; + for (size_t i = 1; i < scriptExtraSize; i++) { + const auto& extra = scriptExtra[i]; auto key = extra.extent.toFunctionKey(); // There can be multiple ScriptStencilExtra with same extent if @@ -5071,7 +5436,7 @@ bool CompilationStencilMerger::buildFunctionKeyToIndex(FrontendContext* fc) { // // Already reserved above, but OOMTest can hit failure mode in // HashTable::add. - if (!functionKeyToInitialScriptIndex_.put(key, ScriptIndex(i))) { + if (!map_.put(key, ScriptIndex(i))) { ReportOutOfMemory(fc); return false; } @@ -5080,11 +5445,28 @@ bool CompilationStencilMerger::buildFunctionKeyToIndex(FrontendContext* fc) { return true; } -ScriptIndex CompilationStencilMerger::getInitialScriptIndexFor( - const CompilationStencil& delazification) const { - auto p = functionKeyToInitialScriptIndex_.lookup(delazification.functionKey); - MOZ_ASSERT(p); - return p->value(); +bool FunctionKeyToScriptIndexMap::init(FrontendContext* fc, + const CompilationStencil* initial) { + return init(fc, initial->scriptExtra, initial->scriptExtra.size()); +} + +bool FunctionKeyToScriptIndexMap::init( + FrontendContext* fc, const ExtensibleCompilationStencil* initial) { + return init(fc, initial->scriptExtra, initial->scriptExtra.length()); +} + +mozilla::Maybe FunctionKeyToScriptIndexMap::get( + FunctionKey key) const { + auto p = map_.readonlyThreadsafeLookup(key); + if (!p) { + return mozilla::Nothing(); + } + return mozilla::Some(p->value()); +} + +size_t FunctionKeyToScriptIndexMap::sizeOfExcludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + return map_.shallowSizeOfExcludingThis(mallocSizeOf); } bool CompilationStencilMerger::buildAtomIndexMap( @@ -5111,7 +5493,7 @@ bool CompilationStencilMerger::setInitial( initial_ = std::move(initial); - return buildFunctionKeyToIndex(fc); + return functionKeyToInitialScriptIndex_.init(fc, initial_.get()); } template bigIntData.reserve(bigIntOffset + delazification.bigIntData.size())) { js::ReportOutOfMemory(fc); @@ -5338,7 +5720,7 @@ bool CompilationStencilMerger::addDelazification( } for (const auto& data : delazification.bigIntData) { initial_->bigIntData.infallibleEmplaceBack(); - if (!initial_->bigIntData.back().init(fc, initial_->alloc, data.source())) { + if (!initial_->bigIntData.back().init(fc, initial_->alloc, data)) { return false; } } @@ -5446,84 +5828,36 @@ bool CompilationStencilMerger::addDelazification( // asm.js shouldn't appear inside delazification, given asm.js forces // full-parse. - MOZ_ASSERT(!delazification.asmJS); + MOZ_ASSERT(!delazification.hasAsmJS()); failureCase.release(); return true; } -void JS::StencilAddRef(JS::Stencil* stencil) { stencil->refCount++; } -void JS::StencilRelease(JS::Stencil* stencil) { - MOZ_RELEASE_ASSERT(stencil->refCount > 0); - if (--stencil->refCount == 0) { - js_delete(stencil); +bool CompilationStencilMerger::maybeAddDelazification( + FrontendContext* fc, const CompilationStencil& delazification) { + auto delazifiedFunctionIndex = getInitialScriptIndexFor(delazification); + auto& destFun = initial_->scriptData[delazifiedFunctionIndex]; + + if (!destFun.hasLazyFunctionEnclosingScopeIndex()) { + // The enclosing function is still lazy, and this inner function cannot + // be added. + return true; + } + + return addDelazification(fc, delazification); +} + +void CompilationStencil::AddRef() { refCount_++; } +void CompilationStencil::Release() { + MOZ_RELEASE_ASSERT(refCount_ > 0); + if (--refCount_ == 0) { + js_delete(this); } } -template -static already_AddRefed CompileGlobalScriptToStencilImpl( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { - ScopeKind scopeKind = - options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global; - - AutoReportFrontendContext fc(cx); - NoScopeBindingCache scopeCache; - Rooted input(cx, CompilationInput(options)); - RefPtr stencil = js::frontend::CompileGlobalScriptToStencil( - cx, &fc, cx->tempLifoAlloc(), input.get(), &scopeCache, srcBuf, - scopeKind); - if (!stencil) { - return nullptr; - } - - // Convert the UniquePtr to a RefPtr and increment the count (to 1). - return stencil.forget(); -} - -already_AddRefed JS::CompileGlobalScriptToStencil( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { - return CompileGlobalScriptToStencilImpl(cx, options, srcBuf); -} - -already_AddRefed JS::CompileGlobalScriptToStencil( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { - return CompileGlobalScriptToStencilImpl(cx, options, srcBuf); -} - -template -static already_AddRefed CompileModuleScriptToStencilImpl( - JSContext* cx, const JS::ReadOnlyCompileOptions& optionsInput, - JS::SourceText& srcBuf) { - JS::CompileOptions options(cx, optionsInput); - options.setModule(); - - AutoReportFrontendContext fc(cx); - NoScopeBindingCache scopeCache; - Rooted input(cx, CompilationInput(options)); - RefPtr stencil = js::frontend::ParseModuleToStencil( - cx, &fc, cx->tempLifoAlloc(), input.get(), &scopeCache, srcBuf); - if (!stencil) { - return nullptr; - } - - // Convert the UniquePtr to a RefPtr and increment the count (to 1). - return stencil.forget(); -} - -already_AddRefed JS::CompileModuleScriptToStencil( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { - return CompileModuleScriptToStencilImpl(cx, options, srcBuf); -} - -already_AddRefed JS::CompileModuleScriptToStencil( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, - JS::SourceText& srcBuf) { - return CompileModuleScriptToStencilImpl(cx, options, srcBuf); -} +void JS::StencilAddRef(JS::Stencil* stencil) { stencil->AddRef(); } +void JS::StencilRelease(JS::Stencil* stencil) { stencil->Release(); } JS_PUBLIC_API JSScript* JS::InstantiateGlobalStencil( JSContext* cx, const JS::InstantiateOptions& options, JS::Stencil* stencil, @@ -5544,8 +5878,9 @@ JS_PUBLIC_API JSScript* JS::InstantiateGlobalStencil( return gcOutput.get().script; } -JS_PUBLIC_API bool JS::StencilIsBorrowed(Stencil* stencil) { - return stencil->storageType == CompilationStencil::StorageType::Borrowed; +JS_PUBLIC_API bool JS::StencilIsBorrowed(JS::Stencil* stencil) { + return stencil->getInitial()->storageType == + CompilationStencil::StorageType::Borrowed; } JS_PUBLIC_API JSObject* JS::InstantiateModuleStencil( @@ -5568,47 +5903,6 @@ JS_PUBLIC_API JSObject* JS::InstantiateModuleStencil( return gcOutput.get().module; } -JS::TranscodeResult JS::EncodeStencil(JSContext* cx, JS::Stencil* stencil, - TranscodeBuffer& buffer) { - AutoReportFrontendContext fc(cx); - XDRStencilEncoder encoder(&fc, buffer); - XDRResult res = encoder.codeStencil(*stencil); - if (res.isErr()) { - return res.unwrapErr(); - } - return TranscodeResult::Ok; -} - -JS::TranscodeResult JS::DecodeStencil(JSContext* cx, - const JS::ReadOnlyDecodeOptions& options, - const JS::TranscodeRange& range, - JS::Stencil** stencilOut) { - AutoReportFrontendContext fc(cx); - return JS::DecodeStencil(&fc, options, range, stencilOut); -} - -JS::TranscodeResult JS::DecodeStencil(JS::FrontendContext* fc, - const JS::ReadOnlyDecodeOptions& options, - const JS::TranscodeRange& range, - JS::Stencil** stencilOut) { - RefPtr source = fc->getAllocator()->new_(); - if (!source) { - return TranscodeResult::Throw; - } - RefPtr stencil( - fc->getAllocator()->new_(source)); - if (!stencil) { - return TranscodeResult::Throw; - } - XDRStencilDecoder decoder(fc, range); - XDRResult res = decoder.codeStencil(options, *stencil); - if (res.isErr()) { - return res.unwrapErr(); - } - *stencilOut = stencil.forget().take(); - return TranscodeResult::Ok; -} - JS_PUBLIC_API size_t JS::SizeOfStencil(Stencil* stencil, mozilla::MallocSizeOf mallocSizeOf) { return stencil->sizeOfIncludingThis(mallocSizeOf); @@ -5620,3 +5914,11 @@ JS::InstantiationStorage::~InstantiationStorage() { gcOutput_ = nullptr; } } + +bool JS::IsStencilCacheable(JS::Stencil* stencil) { + if (stencil->hasAsmJS()) { + return false; + } + + return true; +} diff --git a/src/third_party/mozjs/extract/js/src/frontend/Stencil.h b/src/third_party/mozjs/extract/js/src/frontend/Stencil.h index b5baa8e6c40..4470c36c4c7 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/Stencil.h +++ b/src/third_party/mozjs/extract/js/src/frontend/Stencil.h @@ -11,6 +11,7 @@ #include "mozilla/Maybe.h" // mozilla::{Maybe, Nothing} #include "mozilla/MemoryReporting.h" // mozilla::MallocSizeOf #include "mozilla/Span.h" // mozilla::Span +#include "mozilla/Variant.h" // mozilla::Variant #include // size_t #include // char16_t, uint8_t, uint16_t, uint32_t @@ -19,17 +20,18 @@ #include "frontend/ObjLiteral.h" // ObjLiteralStencil #include "frontend/ParserAtom.h" // TaggedParserAtomIndex #include "frontend/ScriptIndex.h" // ScriptIndex -#include "frontend/TypedIndex.h" // TypedIndex -#include "js/AllocPolicy.h" // SystemAllocPolicy -#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin -#include "js/RefCounted.h" // AtomicRefCounted -#include "js/RegExpFlags.h" // JS::RegExpFlags -#include "js/RootingAPI.h" // Handle -#include "js/TypeDecls.h" // JSContext -#include "js/UniquePtr.h" // js::UniquePtr -#include "js/Utility.h" // UniqueTwoByteChars -#include "js/Vector.h" // js::Vector -#include "vm/FunctionFlags.h" // FunctionFlags +#include "frontend/TaggedParserAtomIndexHasher.h" // frontend::TaggedParserAtomIndexHasher +#include "frontend/TypedIndex.h" // TypedIndex +#include "js/AllocPolicy.h" // SystemAllocPolicy +#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin +#include "js/RefCounted.h" // AtomicRefCounted +#include "js/RegExpFlags.h" // JS::RegExpFlags +#include "js/RootingAPI.h" // Handle +#include "js/TypeDecls.h" // JSContext +#include "js/UniquePtr.h" // js::UniquePtr +#include "js/Utility.h" // UniqueTwoByteChars +#include "js/Vector.h" // js::Vector +#include "vm/FunctionFlags.h" // FunctionFlags #include "vm/Scope.h" // Scope, BaseScopeData, FunctionScope, LexicalScope, VarScope, GlobalScope, EvalScope, ModuleScope #include "vm/ScopeKind.h" // ScopeKind #include "vm/SharedStencil.h" // ImmutableScriptFlags, GCThingIndex, js::SharedImmutableScriptData, MemberInitializers, SourceExtent @@ -245,19 +247,39 @@ class BigIntStencil { // Source of the BigInt literal. // It's not null-terminated, and also trailing 'n' suffix is not included. - mozilla::Span source_; + // + // Int64-sized BigInt values are directly stored inline as int64_t. + mozilla::Variant, int64_t> bigInt_{int64_t{}}; + + // Methods used by XDR. + mozilla::Span& source() { + if (bigInt_.is()) { + bigInt_ = mozilla::AsVariant(mozilla::Span{}); + } + return bigInt_.as>(); + } + const mozilla::Span& source() const { + return bigInt_.as>(); + } + + [[nodiscard]] bool initFromChars(FrontendContext* fc, LifoAlloc& alloc, + mozilla::Span buf); public: BigIntStencil() = default; [[nodiscard]] bool init(FrontendContext* fc, LifoAlloc& alloc, - const mozilla::Span buf); + mozilla::Span buf); + + [[nodiscard]] bool init(FrontendContext* fc, LifoAlloc& alloc, + const BigIntStencil& other); BigInt* createBigInt(JSContext* cx) const; + // Methods used by constant-folding. bool isZero() const; - - mozilla::Span source() const { return source_; } + bool inplaceNegate(); + bool inplaceBitNot(); #ifdef DEBUG bool isContainedIn(const LifoAlloc& alloc) const; @@ -270,6 +292,8 @@ class BigIntStencil { #endif }; +using BigIntStencilVector = Vector; + class ScopeStencil { friend class StencilXDR; friend class InputScope; @@ -511,11 +535,20 @@ class StencilModuleImportAttribute { StencilModuleImportAttribute(TaggedParserAtomIndex key, TaggedParserAtomIndex value) : key(key), value(value) {} + + bool operator!=(const StencilModuleImportAttribute& rhs) const { + return key != rhs.key || value != rhs.value; + } + + bool operator==(const StencilModuleImportAttribute& rhs) const { + return !(*this != rhs); + } }; class StencilModuleRequest { public: TaggedParserAtomIndex specifier; + TaggedParserAtomIndex firstUnsupportedAttributeKey; using ImportAttributeVector = Vector; @@ -530,7 +563,8 @@ class StencilModuleRequest { } StencilModuleRequest(const StencilModuleRequest& other) - : specifier(other.specifier) { + : specifier(other.specifier), + firstUnsupportedAttributeKey(other.firstUnsupportedAttributeKey) { AutoEnterOOMUnsafeRegion oomUnsafe; if (!attributes.appendAll(other.attributes)) { oomUnsafe.crash("StencilModuleRequest::StencilModuleRequest"); @@ -538,19 +572,63 @@ class StencilModuleRequest { } StencilModuleRequest(StencilModuleRequest&& other) noexcept - : specifier(other.specifier), attributes(std::move(other.attributes)) {} + : specifier(other.specifier), + firstUnsupportedAttributeKey(other.firstUnsupportedAttributeKey), + attributes(std::move(other.attributes)) {} StencilModuleRequest& operator=(StencilModuleRequest& other) { specifier = other.specifier; + firstUnsupportedAttributeKey = other.firstUnsupportedAttributeKey; attributes = std::move(other.attributes); return *this; } StencilModuleRequest& operator=(StencilModuleRequest&& other) noexcept { specifier = other.specifier; + firstUnsupportedAttributeKey = other.firstUnsupportedAttributeKey; attributes = std::move(other.attributes); return *this; } + + bool operator==(const StencilModuleRequest& other) const { + size_t attrLen = attributes.length(); + if (specifier != other.specifier || + firstUnsupportedAttributeKey != other.firstUnsupportedAttributeKey || + attrLen != other.attributes.length()) { + return false; + } + + for (size_t i = 0; i < attrLen; i++) { + if (attributes[i] != other.attributes[i]) { + return false; + } + } + + return true; + } + + bool operator!=(const StencilModuleRequest& other) const { + return !(*this == other); + } +}; + +struct StencilModuleRequestHasher { + using Key = js::frontend::StencilModuleRequest; + using Lookup = Key; + + static HashNumber hash(const Lookup& l) { + HashNumber hash = 0; + size_t attrLen = l.attributes.length(); + for (size_t i = 0; i < attrLen; i++) { + hash = mozilla::AddToHash( + hash, TaggedParserAtomIndexHasher::hash(l.attributes[i].key), + TaggedParserAtomIndexHasher::hash(l.attributes[i].value)); + } + return mozilla::AddToHash(hash, + TaggedParserAtomIndexHasher::hash(l.specifier)); + } + + static bool match(const Key& k, const Lookup& l) { return k == l; } }; class MaybeModuleRequestIndex { diff --git a/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.cpp b/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.cpp index 878903233e9..b02dfedf3eb 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.cpp @@ -8,6 +8,7 @@ #include "mozilla/ArrayUtils.h" // mozilla::ArrayEqual #include "mozilla/OperatorNewExtensions.h" // mozilla::KnownNotNull +#include "mozilla/RefPtr.h" // RefPtr #include "mozilla/ScopeExit.h" // mozilla::MakeScopeExit #include "mozilla/Try.h" // MOZ_TRY @@ -18,9 +19,14 @@ #include "ds/LifoAlloc.h" // LifoAlloc #include "frontend/CompilationStencil.h" // CompilationStencil, ExtensibleCompilationStencil -#include "frontend/ScriptIndex.h" // ScriptIndex -#include "vm/Scope.h" // SizeOfParserScopeData -#include "vm/StencilEnums.h" // js::ImmutableScriptFlagsEnum +#include "frontend/FrontendContext.h" // FrontendContext, AutoReportFrontendContext +#include "frontend/ScriptIndex.h" // ScriptIndex +#include "js/CompileOptions.h" // JS::ReadOnlyDecodeOptions +#include "js/experimental/JSStencil.h" // ScriptIndex +#include "js/Transcoding.h" // JS::TranscodeBuffer, JS::TranscodeRange, JS::TranscodeResult +#include "vm/JSScript.h" // ScriptSource +#include "vm/Scope.h" // SizeOfParserScopeData +#include "vm/StencilEnums.h" // js::ImmutableScriptFlagsEnum using namespace js; using namespace js::frontend; @@ -180,11 +186,26 @@ template BigIntStencil& stencil) { uint32_t size; if (mode == XDR_ENCODE) { - size = stencil.source_.size(); + size = stencil.bigInt_.match( + [](mozilla::Span source) { return source.size(); }, + [](int64_t) { return size_t(0); }); } MOZ_TRY(xdr->codeUint32(&size)); - return XDRSpanContent(xdr, alloc, stencil.source_, size); + // Zero-length size indicates inline storage for int64-sized BigInts. + if (size == 0) { + uint64_t num; + if (mode == XDR_ENCODE) { + num = static_cast(stencil.bigInt_.as()); + } + MOZ_TRY(xdr->codeUint64(&num)); + if (mode == XDR_DECODE) { + stencil.bigInt_.as() = static_cast(num); + } + return Ok(); + } + + return XDRSpanContent(xdr, alloc, stencil.source(), size); } template @@ -577,6 +598,7 @@ template /* static */ XDRResult StencilXDR::codeModuleRequest( XDRState* xdr, StencilModuleRequest& stencil) { MOZ_TRY(xdr->codeUint32(stencil.specifier.rawDataRef())); + MOZ_TRY(xdr->codeUint32(stencil.firstUnsupportedAttributeKey.rawDataRef())); MOZ_TRY(XDRVectorContent(xdr, stencil.attributes)); return Ok(); @@ -758,7 +780,7 @@ static XDRResult CodeMarker(XDRState* xdr, SectionMarker marker) { template /* static */ XDRResult StencilXDR::codeCompilationStencil( XDRState* xdr, CompilationStencil& stencil) { - MOZ_ASSERT(!stencil.asmJS); + MOZ_ASSERT(!stencil.hasAsmJS()); if constexpr (mode == XDR_DECODE) { const auto& options = static_cast(xdr)->options(); @@ -1450,33 +1472,41 @@ XDRResult XDRStencilEncoder::codeStencil( return codeStencil(stencil.source, stencil); } -void StencilIncrementalEncoderPtr::reset() { - if (merger_) { - js_delete(merger_); +static JS::TranscodeResult EncodeStencilImpl( + JS::FrontendContext* fc, const frontend::CompilationStencil* initial, + JS::TranscodeBuffer& buffer) { + XDRStencilEncoder encoder(fc, buffer); + XDRResult res = encoder.codeStencil(*initial); + if (res.isErr()) { + return res.unwrapErr(); } - merger_ = nullptr; + return JS::TranscodeResult::Ok; } -bool StencilIncrementalEncoderPtr::setInitial( - JSContext* cx, - UniquePtr&& initial) { - MOZ_ASSERT(!merger_); - +JS::TranscodeResult JS::EncodeStencil(JSContext* cx, JS::Stencil* stencil, + JS::TranscodeBuffer& buffer) { AutoReportFrontendContext fc(cx); - merger_ = fc.getAllocator()->new_(); - if (!merger_) { - return false; + + const CompilationStencil* initial; + UniquePtr merged; + if (stencil->canLazilyParse()) { + merged.reset(stencil->getMerged(&fc)); + if (!merged) { + return TranscodeResult::Throw; + } + initial = merged.get(); + } else { + initial = stencil->getInitial(); } - return merger_->setInitial( - &fc, - std::forward>(initial)); + return EncodeStencilImpl(&fc, initial, buffer); } -bool StencilIncrementalEncoderPtr::addDelazification( - JSContext* cx, const frontend::CompilationStencil& delazification) { +JS::TranscodeResult js::EncodeStencil(JSContext* cx, + frontend::CompilationStencil* stencil, + JS::TranscodeBuffer& buffer) { AutoReportFrontendContext fc(cx); - return merger_->addDelazification(&fc, delazification); + return EncodeStencilImpl(&fc, stencil, buffer); } XDRResult XDRStencilDecoder::codeStencil( @@ -1512,6 +1542,59 @@ XDRResult XDRStencilDecoder::codeStencil( return Ok(); } +JS::TranscodeResult JS::DecodeStencil(JSContext* cx, + const JS::ReadOnlyDecodeOptions& options, + const JS::TranscodeRange& range, + JS::Stencil** stencilOut) { + AutoReportFrontendContext fc(cx); + return JS::DecodeStencil(&fc, options, range, stencilOut); +} + +JS::TranscodeResult JS::DecodeStencil(JS::FrontendContext* fc, + const JS::ReadOnlyDecodeOptions& options, + const JS::TranscodeRange& range, + JS::Stencil** stencilOut) { + RefPtr stencil; + JS::TranscodeResult result = + js::DecodeStencil(fc, options, range, getter_AddRefs(stencil)); + if (result != TranscodeResult::Ok) { + return result; + } + + RefPtr stencils = + fc->getAllocator()->new_(); + if (!stencils) { + return TranscodeResult::Throw; + } + if (!stencils->init(fc, stencil.get())) { + return TranscodeResult::Throw; + } + stencils.forget(stencilOut); + return TranscodeResult::Ok; +} + +JS::TranscodeResult js::DecodeStencil( + JS::FrontendContext* fc, const JS::ReadOnlyDecodeOptions& options, + const JS::TranscodeRange& range, + frontend::CompilationStencil** stencilOut) { + RefPtr source = fc->getAllocator()->new_(); + if (!source) { + return JS::TranscodeResult::Throw; + } + RefPtr stencil = + fc->getAllocator()->new_(source); + if (!stencil) { + return JS::TranscodeResult::Throw; + } + XDRStencilDecoder decoder(fc, range); + XDRResult res = decoder.codeStencil(options, *stencil); + if (res.isErr()) { + return res.unwrapErr(); + } + stencil.forget(stencilOut); + return JS::TranscodeResult::Ok; +} + template /* static */ XDRResult StencilXDR::codeCompilationStencil( XDRState* xdr, CompilationStencil& stencil); @@ -1520,7 +1603,7 @@ template /* static */ XDRResult StencilXDR::codeCompilationStencil( /* static */ XDRResult StencilXDR::checkCompilationStencil( XDRStencilEncoder* encoder, const CompilationStencil& stencil) { - if (stencil.asmJS) { + if (stencil.hasAsmJS()) { return encoder->fail(JS::TranscodeResult::Failure_AsmJSNotSupported); } @@ -1529,7 +1612,7 @@ template /* static */ XDRResult StencilXDR::codeCompilationStencil( /* static */ XDRResult StencilXDR::checkCompilationStencil( const ExtensibleCompilationStencil& stencil) { - if (stencil.asmJS) { + if (stencil.hasAsmJS()) { return mozilla::Err(JS::TranscodeResult::Failure_AsmJSNotSupported); } diff --git a/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.h b/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.h index 6f87fa1d2cc..fa387509a4d 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.h +++ b/src/third_party/mozjs/extract/js/src/frontend/StencilXdr.h @@ -11,7 +11,9 @@ #include "frontend/ParserAtom.h" // ParserAtom, ParserAtomSpan #include "frontend/Stencil.h" // BitIntStencil, ScopeStencil, BaseParserScopeData -#include "vm/Xdr.h" // XDRMode, XDRResult, XDRState +#include "js/CompileOptions.h" // JS::ReadOnlyDecodeOptions, JS::ReadOnlyDecodeOptions +#include "js/Transcoding.h" // JS::TranscodeBuffer, JS::TranscodeRange, JS::TranscodeResult +#include "vm/Xdr.h" // XDRMode, XDRResult, XDRState namespace JS { @@ -216,6 +218,15 @@ class XDRStencilEncoder : public XDRState { XDRResult codeStencil(const frontend::CompilationStencil& stencil); }; +JS::TranscodeResult EncodeStencil(JSContext* cx, + frontend::CompilationStencil* stencil, + JS::TranscodeBuffer& buffer); + +JS::TranscodeResult DecodeStencil(JS::FrontendContext* fc, + const JS::ReadOnlyDecodeOptions& options, + const JS::TranscodeRange& range, + frontend::CompilationStencil** stencilOut); + } /* namespace js */ #endif /* frontend_StencilXdr_h */ diff --git a/src/third_party/mozjs/extract/js/src/frontend/SwitchEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/SwitchEmitter.cpp index 9c3ad7aa7df..42f96cc4240 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/SwitchEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/SwitchEmitter.cpp @@ -396,11 +396,14 @@ bool SwitchEmitter::emitEnd() { return false; } - emitterScope_.reset(); tdzCacheLexical_.reset(); controlInfo_.reset(); + // LIFO construction order is enforced hence we should reset the + // emitterScope_ after controlInfo_ has been reset. + emitterScope_.reset(); + state_ = State::End; return true; } diff --git a/src/third_party/mozjs/extract/js/src/frontend/SyntaxParseHandler.h b/src/third_party/mozjs/extract/js/src/frontend/SyntaxParseHandler.h index ab2d938b70d..c004d4e566d 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/SyntaxParseHandler.h +++ b/src/third_party/mozjs/extract/js/src/frontend/SyntaxParseHandler.h @@ -346,12 +346,6 @@ class SyntaxParseHandler { return NodeUnparenthesizedObject; } -#ifdef ENABLE_RECORD_TUPLE - ListNodeResult newRecordLiteral(uint32_t begin) { return NodeGeneric; } - - ListNodeResult newTupleLiteral(uint32_t begin) { return NodeGeneric; } -#endif - ListNodeResult newClassMemberList(uint32_t begin) { return NodeGeneric; } ClassNamesResult newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; @@ -695,6 +689,7 @@ class SyntaxParseHandler { MOZ_ASSERT(kind != ParseNodeKind::ParamsBody); #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT MOZ_ASSERT(kind != ParseNodeKind::UsingDecl); + MOZ_ASSERT(kind != ParseNodeKind::AwaitUsingDecl); #endif return NodeGeneric; } @@ -711,7 +706,8 @@ class SyntaxParseHandler { MOZ_ASSERT(kind == ParseNodeKind::LetDecl || kind == ParseNodeKind::ConstDecl #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT - || kind == ParseNodeKind::UsingDecl + || kind == ParseNodeKind::UsingDecl || + kind == ParseNodeKind::AwaitUsingDecl #endif ); return NodeLexicalDeclaration; diff --git a/src/third_party/mozjs/extract/js/src/frontend/Token.h b/src/third_party/mozjs/extract/js/src/frontend/Token.h index da011699359..e7f20ba9a58 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/Token.h +++ b/src/third_party/mozjs/extract/js/src/frontend/Token.h @@ -135,7 +135,7 @@ struct Token { /** The token's position in the overall script. */ TokenPos pos; - union { + union U { private: friend struct Token; @@ -151,6 +151,9 @@ struct Token { /** Regular expression flags; use charBuffer to access source chars. */ JS::RegExpFlags reflags; + + public: + U() {}; } u; #ifdef DEBUG diff --git a/src/third_party/mozjs/extract/js/src/frontend/TokenKind.h b/src/third_party/mozjs/extract/js/src/frontend/TokenKind.h index cbe87fe3935..177f98507b1 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/TokenKind.h +++ b/src/third_party/mozjs/extract/js/src/frontend/TokenKind.h @@ -9,7 +9,7 @@ #include -#include "js/TypeDecls.h" // IF_RECORD_TUPLE +#include "js/TypeDecls.h" // IF_DECORATORS /* * List of token kinds and their ranges. @@ -70,10 +70,8 @@ MACRO(TripleDot, "'...'") /* rest arguments and spread operator */ \ MACRO(OptionalChain, "'?.'") \ MACRO(LeftBracket, "'['") \ - IF_RECORD_TUPLE(MACRO(HashBracket, "'#['")) \ MACRO(RightBracket, "']'") \ MACRO(LeftCurly, "'{'") \ - IF_RECORD_TUPLE(MACRO(HashCurly, "'#{'")) \ MACRO(RightCurly, "'}'") \ MACRO(LeftParen, "'('") \ MACRO(RightParen, "')'") \ diff --git a/src/third_party/mozjs/extract/js/src/frontend/TokenStream.cpp b/src/third_party/mozjs/extract/js/src/frontend/TokenStream.cpp index 6157aac3325..ff067cc9ac0 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/TokenStream.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/TokenStream.cpp @@ -2975,17 +2975,6 @@ template break; case '#': { -#ifdef ENABLE_RECORD_TUPLE - if (matchCodeUnit('{')) { - simpleKind = TokenKind::HashCurly; - break; - } - if (matchCodeUnit('[')) { - simpleKind = TokenKind::HashBracket; - break; - } -#endif - TokenStart start(this->sourceUnits, -1); const Unit* identStart = this->sourceUnits.addressOfNextCodeUnit() - 1; IdentifierEscapes sawEscape; @@ -3604,7 +3593,7 @@ bool TokenStreamSpecific::getStringOrTemplateToken( unit = char16_t(val); break; } // default - } // switch (AssertedCast(CodeUnitValue(toUnit(unit)))) + } // switch (AssertedCast(CodeUnitValue(toUnit(unit)))) if (!this->charBuffer.append(unit)) { return false; diff --git a/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.cpp index 20fb29db637..60b4563bb11 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.cpp @@ -29,12 +29,19 @@ TryEmitter::TryEmitter(BytecodeEmitter* bce, Kind kind, ControlKind controlKind) state_(State::Start) #endif { - if (controlKind_ == ControlKind::Syntactic) { + MOZ_ASSERT_IF(controlKind_ == ControlKind::Disposal, + kind_ == Kind::TryFinally); + + if (requiresControlInfo()) { controlInfo_.emplace( bce_, hasFinally() ? StatementKind::Finally : StatementKind::Try); } } +#ifdef DEBUG +bool TryEmitter::hasControlInfo() { return controlInfo_.isSome(); } +#endif + bool TryEmitter::emitTry() { MOZ_ASSERT(state_ == State::Start); @@ -332,5 +339,5 @@ bool TryEmitter::emitEnd() { } bool TryEmitter::shouldUpdateRval() const { - return controlKind_ == ControlKind::Syntactic && !bce_->sc->noScriptRval(); + return requiresControlInfo() && !bce_->sc->noScriptRval(); } diff --git a/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.h index b74157bb0e7..f29bc2ad0cc 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/TryEmitter.h @@ -108,7 +108,17 @@ class MOZ_STACK_CLASS TryEmitter { // // For syntactic try-catch-finally, Syntactic should be used. // For non-syntactic try-catch-finally, NonSyntactic should be used. - enum class ControlKind { Syntactic, NonSyntactic }; + // For non-syntactic try-catch-finally for Explicit Resource Management + // Disposal kind should be used. + enum class ControlKind { + Syntactic, + NonSyntactic, + + // Disposal kind is exactly same in behaviour of Syntactic kind, it is + // used enabling try-finally scope for Explicit Resource Management + // Proposal. (https://arai-a.github.io/ecma262-compare/?pr=3000) + Disposal, + }; private: BytecodeEmitter* bce_; @@ -187,14 +197,15 @@ class MOZ_STACK_CLASS TryEmitter { return kind_ == Kind::TryCatchFinally || kind_ == Kind::TryFinally; } + bool requiresControlInfo() const { + return controlKind_ == ControlKind::Syntactic || + controlKind_ == ControlKind::Disposal; + } + BytecodeOffset offsetAfterTryOp() const { return tryOpOffset_ + BytecodeOffsetDiff(JSOpLength_Try); } - // Returns true if catch and finally blocks should handle the frame's - // return value. - bool shouldUpdateRval() const; - // Jump to the finally block. After the finally block executes, // fall through to the code following the finally block. [[nodiscard]] bool emitJumpToFinallyWithFallthrough(); @@ -202,6 +213,14 @@ class MOZ_STACK_CLASS TryEmitter { public: TryEmitter(BytecodeEmitter* bce, Kind kind, ControlKind controlKind); + // Returns true if catch and finally blocks should handle the frame's + // return value. + bool shouldUpdateRval() const; + +#ifdef DEBUG + bool hasControlInfo(); +#endif + [[nodiscard]] bool emitTry(); enum class ExceptionStack : bool { diff --git a/src/third_party/mozjs/extract/js/src/frontend/TypedIndex.h b/src/third_party/mozjs/extract/js/src/frontend/TypedIndex.h index c75d59ae3db..fb877441fd9 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/TypedIndex.h +++ b/src/third_party/mozjs/extract/js/src/frontend/TypedIndex.h @@ -18,7 +18,7 @@ namespace frontend { template struct TypedIndex { TypedIndex() = default; - constexpr explicit TypedIndex(uint32_t index) : index(index){}; + constexpr explicit TypedIndex(uint32_t index) : index(index) {}; uint32_t index = 0; diff --git a/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.cpp index 5ccd9446226..6946c1cf2ed 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.cpp @@ -7,141 +7,1402 @@ #include "frontend/BytecodeEmitter.h" #include "frontend/EmitterScope.h" #include "frontend/IfEmitter.h" -#include "vm/ThrowMsgKind.h" +#include "frontend/TryEmitter.h" +#include "frontend/WhileEmitter.h" using namespace js; using namespace js::frontend; UsingEmitter::UsingEmitter(BytecodeEmitter* bce) : bce_(bce) {} -bool UsingEmitter::emitCheckDisposeMethod(JS::SymbolCode hint) { - // [stack] VAL +bool UsingEmitter::emitTakeDisposeCapability() { + if (!bce_->emit1(JSOp::TakeDisposeCapability)) { + // [stack] RESOURCES-OR-UNDEF + return false; + } + + if (!bce_->emit1(JSOp::IsNullOrUndefined)) { + // [stack] RESOURCES-OR-UNDEF IS-UNDEF + return false; + } + + InternalIfEmitter ifUndefined(bce_); + + if (!ifUndefined.emitThenElse()) { + // [stack] UNDEFINED + return false; + } + + if (!bce_->emit1(JSOp::Zero)) { + // [stack] UNDEFINED 0 + return false; + } + + if (!ifUndefined.emitElse()) { + // [stack] RESOURCES + return false; + } - // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-getdisposemethod - // Step 2. Else, - // Step 2.a. Let method be ? GetMethod(V, @@dispose). if (!bce_->emit1(JSOp::Dup)) { - // [stack] VAL VAL + // [stack] RESOURCES RESOURCES return false; } - if (!bce_->emit2(JSOp::Symbol, uint8_t(hint))) { - // [stack] VAL VAL @@dispose + if (!bce_->emitAtomOp(JSOp::GetProp, + TaggedParserAtomIndex::WellKnown::length())) { + // [stack] RESOURCES COUNT return false; } - if (!bce_->emit1(JSOp::GetElem)) { - // [stack] VAL VAL[@@dispose] - return false; - } - - if (!bce_->emitCheckIsCallable()) { - // [stack] VAL VAL[@@dispose] IS_CALLABLE_RESULT - return false; - } - - InternalIfEmitter ifCallable(bce_); - - if (!ifCallable.emitThenElse()) { - // [stack] VAL VAL[@@dispose] - return false; - } - - if (!bce_->emit1(JSOp::Pop)) { - // [stack] VAL - return false; - } - - if (!ifCallable.emitElse()) { - // [stack] VAL VAL[@@dispose] - return false; - } - - if (!bce_->emit1(JSOp::Pop)) { - // [stack] VAL - return false; - } - - if (!bce_->emit2(JSOp::ThrowMsg, - uint8_t(ThrowMsgKind::UsingWithoutDispose))) { - // [stack] VAL - return false; - } - - if (!ifCallable.emitEnd()) { - // [stack] VAL + if (!ifUndefined.emitEnd()) { + // [stack] RESOURCES COUNT return false; } return true; } -bool UsingEmitter::prepareForAssignment(Kind kind) { - JS::SymbolCode symdispose; - switch (kind) { - case Kind::Sync: - symdispose = JS::SymbolCode::dispose; - break; - case Kind::Async: - MOZ_CRASH("Async disposal not implemented"); - default: - MOZ_CRASH("Invalid kind"); - } +bool UsingEmitter::emitThrowIfException() { + // [stack] EXC THROWING - bce_->innermostEmitterScope()->setHasDisposables(); + InternalIfEmitter ifThrow(bce_); - // [stack] VAL - - // Explicit Resource Management Proposal - // CreateDisposableResource ( V, hint [ , method ] ) - // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource - // Step 1. If method is not present, then - // (implicit) - // Step 1.a. If V is either null or undefined, then - if (!bce_->emit1(JSOp::IsNullOrUndefined)) { - // [stack] VAL IS_NULL_OR_UNDEFINED_RESULT + if (!ifThrow.emitThenElse()) { + // [stack] EXC return false; } - InternalIfEmitter ifValueNullOrUndefined(bce_); + if (!bce_->emit1(JSOp::Throw)) { + // [stack] + return false; + } + + if (!ifThrow.emitElse()) { + // [stack] EXC + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] + return false; + } + + if (!ifThrow.emitEnd()) { + // [stack] + return false; + } + + return true; +} + +bool DisposalEmitter::emitResourcePropertyAccess(TaggedParserAtomIndex prop, + unsigned resourcesFromTop) { + // [stack] # if resourcesFromTop == 1 + // [stack] RESOURCES INDEX + // [stack] # if resourcesFromTop > 1 + // [stack] RESOURCES INDEX ... (resourcesFromTop - 1 values) + MOZ_ASSERT(resourcesFromTop >= 1); + + if (!bce_->emitDupAt(resourcesFromTop, 2)) { + // [stack] RESOURCES INDEX ... RESOURCES INDEX + return false; + } + + if (!bce_->emit1(JSOp::GetElem)) { + // [stack] RESOURCES INDEX ... RESOURCE + return false; + } + + if (!bce_->emitAtomOp(JSOp::GetProp, prop)) { + // [stack] RESOURCES INDEX ... VALUE + return false; + } + + return true; +} + +// Explicit Resource Management Proposal +// DisposeResources ( disposeCapability, completion ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposeresources +// Steps 1-2. +bool DisposalEmitter::prepareForDisposeCapability() { + MOZ_ASSERT(state_ == State::Start); + + // [stack] THROWING EXC + + if (hasAsyncDisposables_) { + // Step 1. Let needsAwait be false. + if (!bce_->emit1(JSOp::False)) { + // [stack] THROWING EXC NEEDS-AWAIT + return false; + } + + // Step 2. Let hasAwaited be false. + if (!bce_->emit1(JSOp::False)) { + // [stack] THROWING EXC NEEDS-AWAIT HAS-AWAITED + return false; + } + + if (!bce_->emitPickN(3)) { + // [stack] EXC NEEDS-AWAIT HAS-AWAITED THROWING + return false; + } + + if (!bce_->emitPickN(3)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC + return false; + } + } + + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC + +#ifdef DEBUG + state_ = State::DisposeCapability; +#endif + return true; +} + +// Explicit Resource Management Proposal +// DisposeResources ( disposeCapability, completion ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposeresources +// Steps 3-5, 7. +// +// This implementation of DisposeResources is designed for using and await using +// syntax as well as for disposals in DisposableStack and AsyncDisposableStack, +// it covers the complete algorithm as defined in the spec for both sync and +// async disposals as necessary in bytecode. +bool DisposalEmitter::emitEnd(EmitterScope& es) { + MOZ_ASSERT(state_ == State::DisposeCapability); + + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES COUNT + + // For the purpose of readbility some values are omitted from + // the stack comments and are assumed to be present, + // we mention the values in the comments as and when they are being + // operated upon. + + // [stack] ... RESOURCES COUNT + + // We do the iteration in reverse order as per spec, + // there can be the case when count is 0 and hence index + // below becomes -1 but the loop condition will ensure + // no code is executed in that case. + if (!bce_->emit1(JSOp::Dec)) { + // [stack] ... RESOURCES INDEX + return false; + } + + InternalWhileEmitter wh(bce_); + + // Step 3. For each element resource of + // disposeCapability.[[DisposableResourceStack]], in reverse list order, do + if (!wh.emitCond()) { + // [stack] ... RESOURCES INDEX + return false; + } + + if (!bce_->emit1(JSOp::Dup)) { + // [stack] ... RESOURCES INDEX INDEX + return false; + } + + if (!bce_->emit1(JSOp::Zero)) { + // [stack] ... RESOURCES INDEX INDEX 0 + return false; + } + + if (!bce_->emit1(JSOp::Ge)) { + // [stack] ... RESOURCES INDEX BOOL + return false; + } + + if (!wh.emitBody()) { + // [stack] ... RESOURCES INDEX + return false; + } + + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES INDEX + + if (hasAsyncDisposables_) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX + + // Step 3.b. Let hint be resource.[[Hint]]. + // (reordered) + // Step 3.d. If hint is sync-dispose and needsAwait is true and hasAwaited + // is false, then + if (!emitResourcePropertyAccess(TaggedParserAtomIndex::WellKnown::hint())) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX HINT + return false; + } + + // [stack] NEEDS-AWAIT HAS-AWAITED ... HINT + + static_assert(uint8_t(UsingHint::Sync) == 0, "Sync hint must be 0"); + static_assert(uint8_t(UsingHint::Async) == 1, "Async hint must be 1"); + if (!bce_->emit1(JSOp::Not)) { + // [stack] NEEDS-AWAIT HAS-AWAITED ... IS-SYNC + return false; + } + + if (!bce_->emitDupAt(6, 2)) { + // [stack] NEEDS-AWAIT HAS-AWAITED ... IS-SYNC NEEDS-AWAIT HAS-AWAITED + return false; + } + + // [stack] ... IS-SYNC NEEDS-AWAIT HAS-AWAITED + + if (!bce_->emit1(JSOp::Not)) { + // [stack] ... IS-SYNC NEEDS-AWAIT (!HAS-AWAITED) + return false; + } + + // The use of BitAnd is a simple optimisation to avoid having + // jumps if we were to implement this using && operator. The value + // IS-SYNC is integer 0 or 1 (see static_assert above) and + // NEEDS-AWAIT and HAS-AWAITED are boolean values. thus + // the result of the operation is either 0 or 1 which is + // truthy value that can be consumed by the IfEmitter. + if (!bce_->emit1(JSOp::BitAnd)) { + // [stack] ... IS-SYNC (NEEDS-AWAIT & !HAS-AWAITED) + return false; + } + + if (!bce_->emit1(JSOp::BitAnd)) { + // [stack] ... (IS-SYNC & NEEDS-AWAIT & !HAS-AWAITED) + return false; + } + + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX AWAIT-NEEDED + + InternalIfEmitter ifNeedsSyncDisposeUndefinedAwaited(bce_); + + if (!ifNeedsSyncDisposeUndefinedAwaited.emitThen()) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX + return false; + } + + // Step 3.d.i. Perform ! Await(undefined). + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX UNDEF + return false; + } + + if (!bce_->emitAwaitInScope(es)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX RESOLVED + return false; + } + + // Step 3.d.ii. Set needsAwait to false. + if (!bce_->emitPickN(6)) { + // [stack] HAS-AWAITED THROWING EXC RESOURCES INDEX RESOLVED NEEDS-AWAIT + return false; + } + + if (!bce_->emitPopN(2)) { + // [stack] HAS-AWAITED THROWING EXC RESOURCES INDEX + return false; + } + + if (!bce_->emit1(JSOp::False)) { + // [stack] HAS-AWAITED THROWING EXC RESOURCES INDEX NEEDS-AWAIT + return false; + } + + if (!bce_->emitUnpickN(5)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX + return false; + } + + if (!ifNeedsSyncDisposeUndefinedAwaited.emitEnd()) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX + return false; + } + } + + // [stack] ... RESOURCES INDEX + + // Step 3.c. Let method be resource.[[DisposeMethod]]. + // (reordered) + // Step 3.e. If method is not undefined, then + if (!emitResourcePropertyAccess(TaggedParserAtomIndex::WellKnown::method())) { + // [stack] ... RESOURCES INDEX METHOD + return false; + } + + if (!bce_->emit1(JSOp::IsNullOrUndefined)) { + // [stack] ... RESOURCES INDEX METHOD IS-UNDEF + return false; + } + + InternalIfEmitter ifMethodNotUndefined(bce_); + + if (!ifMethodNotUndefined.emitThenElse(IfEmitter::ConditionKind::Negative)) { + // [stack] ... RESOURCES INDEX METHOD + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] ... RESOURCES INDEX + return false; + } + + TryEmitter tryCall(bce_, TryEmitter::Kind::TryCatch, + TryEmitter::ControlKind::NonSyntactic); + + if (!tryCall.emitTry()) { + // [stack] ... RESOURCES INDEX + return false; + } + + // Step 3.c. Let method be resource.[[DisposeMethod]]. + // (reordered) + if (!emitResourcePropertyAccess(TaggedParserAtomIndex::WellKnown::method())) { + // [stack] ... RESOURCES INDEX METHOD + return false; + } + + // Step 3.a. Let value be resource.[[ResourceValue]]. + // (reordered) + if (!emitResourcePropertyAccess(TaggedParserAtomIndex::WellKnown::value(), + 2)) { + // [stack] ... RESOURCES INDEX METHOD VALUE + return false; + } + + // Step 3.e.i. Let result be Completion(Call(method, value)). + if (!bce_->emitCall(JSOp::Call, 0)) { + // [stack] ... RESOURCES INDEX RESULT + return false; + } + + if (hasAsyncDisposables_) { + // Step 3.e.ii. If result is a normal completion and hint is async-dispose, + // then + if (!emitResourcePropertyAccess(TaggedParserAtomIndex::WellKnown::hint(), + 2)) { + // [stack] ... RESOURCES INDEX RESULT HINT + return false; + } + + // Hint value is either 0 or 1, which can be consumed by the IfEmitter, + // see static_assert above. + // [stack] ... RESOURCES INDEX RESULT IS-ASYNC + + InternalIfEmitter ifAsyncDispose(bce_); + + if (!ifAsyncDispose.emitThen()) { + // [stack] ... RESOURCES INDEX RESULT + return false; + } + + // [stack] NEEDS-AWAIT THROWING EXC RESOURCES INDEX RESULT HAS-AWAITED + + // Step 3.e.ii.2. Set hasAwaited to true. (reordered) + if (!bce_->emitPickN(5)) { + // [stack] NEEDS-AWAIT THROWING EXC RESOURCES INDEX RESULT HAS-AWAITED + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] NEEDS-AWAIT THROWING EXC RESOURCES INDEX RESULT + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] NEEDS-AWAIT THROWING EXC RESOURCES INDEX RESULT HAS-AWAITED + return false; + } + + if (!bce_->emitUnpickN(5)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX RESULT + return false; + } + + // Step 3.e.ii.1. Set result to Completion(Await(result.[[Value]])). + if (!bce_->emitAwaitInScope(es)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX RESOLVED + return false; + } + + if (!ifAsyncDispose.emitEnd()) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX RESULT + return false; + } + } + + // [stack] ... THROWING EXC RESOURCES INDEX RESULT + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] ... THROWING EXC RESOURCES INDEX + return false; + } + + // Step 3.e.iii. If result is a throw completion, then + if (!tryCall.emitCatch()) { + // [stack] ... THROWING EXC RESOURCES INDEX EXC2 + return false; + } + + if (!bce_->emitPickN(3)) { + // [stack] ... THROWING RESOURCES INDEX EXC2 EXC + return false; + } + + if (bce_->sc->isSuspendableContext() && + bce_->sc->asSuspendableContext()->isGenerator()) { + // [stack] ... THROWING RESOURCES INDEX EXC2 EXC + + // Generator closure is implemented by throwing a magic value + // thus when we have a throw completion we must check whether + // the pending exception is a generator closing exception and overwrite + // it with the normal exception here or else we will end up exposing + // the magic value to user program. + if (!bce_->emit1(JSOp::IsGenClosing)) { + // [stack] ... THROWING RESOURCES INDEX EXC2 EXC GEN-CLOSING + return false; + } + + if (!bce_->emit1(JSOp::Not)) { + // [stack] ... THROWING RESOURCES INDEX EXC2 EXC !GEN-CLOSING + return false; + } + + if (!bce_->emitPickN(5)) { + // [stack] ... RESOURCES INDEX EXC2 EXC (!GEN-CLOSING) THROWING + return false; + } + + if (!bce_->emit1(JSOp::BitAnd)) { + // [stack] ... RESOURCES INDEX EXC2 EXC (!GEN-CLOSING & THROWING) + return false; + } + } else { + if (!bce_->emitPickN(4)) { + // [stack] ... RESOURCES INDEX EXC2 EXC THROWING + return false; + } + } + + // [stack] NEEDS-AWAIT? HAS-AWAITED? RESOURCES INDEX EXC2 EXC THROWING + + InternalIfEmitter ifException(bce_); + + // Step 3.e.iii.1. If completion is a throw completion, then + if (!ifException.emitThenElse()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? RESOURCES INDEX EXC2 EXC + return false; + } + + // Step 3.e.iii.1.a-f + if (!bce_->emit1(JSOp::CreateSuppressedError)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? RESOURCES INDEX SUPPRESSED + return false; + } + + if (!bce_->emitUnpickN(2)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? SUPPRESSED RESOURCED INDEX + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? SUPPRESSED RESOURCED INDEX THROWING + return false; + } + + if (!bce_->emitUnpickN(3)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING SUPPRESSED RESOURCED INDEX + return false; + } + + // Step 3.e.iii.2. Else, + // Step 3.e.iii.2.a. Set completion to result. + if (!ifException.emitElse()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? RESOURCES INDEX EXC2 EXC + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? RESOURCES INDEX EXC2 + return false; + } + + if (!bce_->emitUnpickN(2)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? EXC2 RESOURCES INDEX + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? EXC2 RESOURCES INDEX THROWING + return false; + } + + if (!bce_->emitUnpickN(3)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC2 RESOURCES INDEX + return false; + } + + if (!ifException.emitEnd()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES INDEX + return false; + } + + if (!tryCall.emitEnd()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES INDEX + return false; + } + + // [stack] ... THROWING EXC RESOURCES INDEX + + // Step 3.f. Else, + // Step 3.f.i. Assert: hint is async-dispose. + // (implicit) + if (!ifMethodNotUndefined.emitElse()) { + // [stack] ... THROWING EXC RESOURCES INDEX METHOD + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] ... THROWING EXC RESOURCES INDEX + return false; + } + + if (hasAsyncDisposables_) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX + + // Step 3.f.ii. Set needsAwait to true. + if (!bce_->emitPickN(5)) { + // [stack] HAS-AWAITED THROWING EXC RESOURCES INDEX NEEDS-AWAIT + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] HAS-AWAITED THROWING EXC RESOURCES INDEX + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] HAS-AWAITED THROWING EXC RESOURCES INDEX NEEDS-AWAIT + return false; + } + + if (!bce_->emitUnpickN(5)) { + // [stack] NEEDS-AWAIT HAS-AWAITED THROWING EXC RESOURCES INDEX + return false; + } + } + + if (!ifMethodNotUndefined.emitEnd()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES INDEX + return false; + } + + if (!bce_->emit1(JSOp::Dec)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES INDEX + return false; + } + + if (!wh.emitEnd()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES INDEX + return false; + } + + if (!bce_->emitPopN(2)) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC + return false; + } + + if (hasAsyncDisposables_) { + // Step 4. If needsAwait is true and hasAwaited is false, then + if (!bce_->emitPickN(3)) { + // [stack] HAS-AWAITED THROWING EXC NEEDS-AWAIT + return false; + } + + if (!bce_->emitPickN(3)) { + // [stack] THROWING EXC NEEDS-AWAIT HAS-AWAITED + return false; + } + + if (!bce_->emit1(JSOp::Not)) { + // [stack] THROWING EXC NEEDS-AWAIT (!HAS-AWAITED) + return false; + } + + if (!bce_->emit1(JSOp::BitAnd)) { + // [stack] THROWING EXC (NEEDS-AWAIT & !HAS-AWAITED) + return false; + } + + InternalIfEmitter ifNeedsUndefinedAwait(bce_); + + if (!ifNeedsUndefinedAwait.emitThen()) { + // [stack] THROWING EXC + return false; + } + + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] THROWING EXC UNDEF + return false; + } + + if (!bce_->emitAwaitInScope(es)) { + // [stack] THROWING EXC RESOLVED + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] THROWING EXC + return false; + } + + if (!ifNeedsUndefinedAwait.emitEnd()) { + // [stack] THROWING EXC + return false; + } + } + + // Step 7. Return ? completion. + if (!bce_->emit1(JSOp::Swap)) { + // [stack] EXC THROWING + return false; + } + +#ifdef DEBUG + state_ = State::End; +#endif + return true; +} + +bool UsingEmitter::emitDisposeResourcesForEnvironment(EmitterScope& es) { + // [stack] THROWING EXC + + DisposalEmitter de(bce_, hasAwaitUsing_); + if (!de.prepareForDisposeCapability()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC + return false; + } + + // Explicit Resource Management Proposal + // DisposeResources ( disposeCapability, completion ) + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposeresources + // + // Step 6. Set disposeCapability.[[DisposableResourceStack]] to a new empty + // List. + if (!emitTakeDisposeCapability()) { + // [stack] NEEDS-AWAIT? HAS-AWAITED? THROWING EXC RESOURCES COUNT + return false; + } + + if (!de.emitEnd(es)) { + // [stack] EXC THROWING + return false; + } + + return true; +} + +bool UsingEmitter::prepareForDisposableScopeBody(BlockKind blockKind) { + MOZ_ASSERT(state_ == State::Start); + + // For-of loops are already wrapped in try-catch and have special case + // handling for the same. + // See ForOfLoopControl::emitEndCodeNeedingIteratorClose. + if (blockKind != BlockKind::ForOf) { + tryEmitter_.emplace(bce_, TryEmitter::Kind::TryFinally, + TryEmitter::ControlKind::Disposal); + if (!tryEmitter_->emitTry()) { + return false; + } + } + +#ifdef DEBUG + state_ = State::DisposableScopeBody; +#endif + return true; +} + +// Explicit Resource Management Proposal +// GetDisposeMethod ( V, hint ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-getdisposemethod +// Steps 1.a-1.b.i., 2-3. +bool UsingEmitter::emitGetDisposeMethod(UsingHint hint) { + // [stack] VAL + + // Step 1. If hint is async-dispose, then + if (hint == UsingHint::Async) { + // Step 1.a. Let method be ? GetMethod(V, @@asyncDispose). + if (!bce_->emit1(JSOp::Dup)) { + // [stack] VAL VAL + return false; + } + + if (!bce_->emit1(JSOp::Dup)) { + // [stack] VAL VAL VAL + return false; + } + + if (!bce_->emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::asyncDispose))) { + // [stack] VAL VAL VAL SYMBOL + return false; + } + + if (!bce_->emit1(JSOp::GetElem)) { + // [stack] VAL VAL ASYNC-DISPOSE + return false; + } + + // Step 1.b. If method is undefined, then + // GetMethod returns undefined if the function is null but + // since we do not do the conversion here we check for + // null or undefined here. + if (!bce_->emit1(JSOp::IsNullOrUndefined)) { + // [stack] VAL VAL ASYNC-DISPOSE IS-NULL-OR-UNDEF + return false; + } + + InternalIfEmitter ifAsyncDisposeNullOrUndefined(bce_); + + if (!ifAsyncDisposeNullOrUndefined.emitThenElse()) { + // [stack] VAL VAL ASYNC-DISPOSE + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] VAL VAL + return false; + } + + if (!bce_->emit1(JSOp::Dup)) { + // [stack] VAL VAL VAL + return false; + } + + if (!bce_->emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::dispose))) { + // [stack] VAL VAL VAL SYMBOL + return false; + } + + // Step 1.b.i. Set method to ? GetMethod(V, @@dispose). + if (!bce_->emit1(JSOp::GetElem)) { + // [stack] VAL VAL DISPOSE + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] VAL VAL DISPOSE NEEDS-CLOSURE + return false; + } + + if (!ifAsyncDisposeNullOrUndefined.emitElse()) { + // [stack] VAL VAL ASYNC-DISPOSE + return false; + } + + if (!bce_->emit1(JSOp::False)) { + // [stack] VAL VAL ASYNC-DISPOSE NEEDS-CLOSURE + return false; + } + + if (!ifAsyncDisposeNullOrUndefined.emitEnd()) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE + return false; + } + + } else { + MOZ_ASSERT(hint == UsingHint::Sync); + + // Step 2. Else, + // Step 2.a. Let method be ? GetMethod(V, @@dispose). + if (!bce_->emit1(JSOp::Dup)) { + // [stack] VAL VAL + return false; + } + + if (!bce_->emit1(JSOp::Dup)) { + // [stack] VAL VAL VAL + return false; + } + + if (!bce_->emit2(JSOp::Symbol, uint8_t(JS::SymbolCode::dispose))) { + // [stack] VAL VAL VAL SYMBOL + return false; + } + + if (!bce_->emit1(JSOp::GetElem)) { + // [stack] VAL VAL DISPOSE + return false; + } + + if (!bce_->emit1(JSOp::False)) { + // [stack] VAL VAL DISPOSE NEEDS-CLOSURE + return false; + } + } + + if (!bce_->emitDupAt(1)) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE METHOD + return false; + } + + // According to spec GetMethod throws TypeError if the method is not callable + // and returns undefined if the value is either undefined or null. + // but the caller of this function, emitCreateDisposableResource is + // supposed to throw TypeError as well if returned value is undefined, + // thus we combine the steps here. + if (!bce_->emitCheckIsCallable()) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE METHOD IS-CALLABLE + return false; + } + + InternalIfEmitter ifMethodNotCallable(bce_); + + if (!ifMethodNotCallable.emitThen(IfEmitter::ConditionKind::Negative)) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE METHOD + return false; + } + + if (!bce_->emit2(JSOp::ThrowMsg, uint8_t(ThrowMsgKind::DisposeNotCallable))) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE METHOD + return false; + } + + if (!ifMethodNotCallable.emitEnd()) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE METHOD + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE + return false; + } + + return true; +} + +// Explicit Resource Management Proposal +// CreateDisposableResource ( V, hint [ , method ] ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource +bool UsingEmitter::emitCreateDisposableResource(UsingHint hint) { + // [stack] VAL + + // Step 1. If method is not present, then (implicit) + // Step 1.a. If V is either null or undefined, then + if (!bce_->emit1(JSOp::IsNullOrUndefined)) { + // [stack] VAL IS-NULL-OR-UNDEF + return false; + } + + InternalIfEmitter ifNullUndefined(bce_); + + if (!ifNullUndefined.emitThenElse()) { + // [stack] VAL + return false; + } + + // Step 1.a.i. Set V to undefined. + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] VAL UNDEF + return false; + } + + // Step 1.a.ii. Set method to undefined. + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] VAL UNDEF UNDEF + return false; + } + + if (!bce_->emit1(JSOp::False)) { + // [stack] VAL UNDEF UNDEF NEEDS-CLOSURE + return false; + } // Step 1.b. Else, - if (!ifValueNullOrUndefined.emitThen(IfEmitter::ConditionKind::Negative)) { - // [stack] VAL + if (!ifNullUndefined.emitElse()) { + // [stack] VAL return false; } // Step 1.b.i. If V is not an Object, throw a TypeError exception. if (!bce_->emitCheckIsObj(CheckIsObjectKind::Disposable)) { - // [stack] VAL + // [stack] VAL return false; } // Step 1.b.ii. Set method to ? GetDisposeMethod(V, hint). // Step 1.b.iii. If method is undefined, throw a TypeError exception. - if (!emitCheckDisposeMethod(symdispose)) { - // [stack] VAL + if (!emitGetDisposeMethod(hint)) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE return false; } - if (!ifValueNullOrUndefined.emitEnd()) { - // [stack] VAL - return false; - } - - // Step 1.a.i. Set V to undefined. - // Step 3. Return the DisposableResource Record { [[ResourceValue]]: V, - // [[Hint]]: hint, [[DisposeMethod]]: method }. - // - // AddDisposableResource ( disposeCapability, V, hint [ , method ] ) - // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-adddisposableresource - // Step 3. Append resource to disposeCapability.[[DisposableResourceStack]]. - // TODO: All the steps performed by the generated bytecode here would need to - // be unified into this AddDisposableResource opcode. (Bug 1899717) - if (!bce_->emit1(JSOp::AddDisposable)) { - // [stack] VAL + if (!ifNullUndefined.emitEnd()) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE return false; } return true; } + +// Explicit Resource Management Proposal +// 7.5.4 AddDisposableResource ( disposeCapability, V, hint [ , method ] ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-adddisposableresource +// Steps 1, 3-4. +bool UsingEmitter::prepareForAssignment(UsingHint hint) { + MOZ_ASSERT(state_ == State::DisposableScopeBody); + MOZ_ASSERT(bce_->innermostEmitterScope()->hasDisposables()); + + if (hint == UsingHint::Async) { + setHasAwaitUsing(true); + } + + // [stack] VAL + + // Step 1. If method is not present, then (implicit) + // Step 1.a. If V is either null or undefined and hint is sync-dispose, return + // unused. + if (hint == UsingHint::Sync) { + if (!bce_->emit1(JSOp::IsNullOrUndefined)) { + // [stack] VAL IS-NULL-OR-UNDEF + return false; + } + + if (!bce_->emit1(JSOp::Not)) { + // [stack] VAL !IS-NULL-OR-UNDEF + return false; + } + } else { + MOZ_ASSERT(hint == UsingHint::Async); + if (!bce_->emit1(JSOp::True)) { + // [stack] VAL TRUE + return false; + } + } + + // [stack] VAL SHOULD-CREATE-RESOURCE + + InternalIfEmitter ifCreateResource(bce_); + + if (!ifCreateResource.emitThen()) { + // [stack] VAL + return false; + } + + // Step 1.c. Let resource be ? CreateDisposableResource(V, hint). + if (!emitCreateDisposableResource(hint)) { + // [stack] VAL VAL METHOD NEEDS-CLOSURE + return false; + } + + // Step 3. Append resource to disposeCapability.[[DisposableResourceStack]]. + if (!bce_->emit2(JSOp::AddDisposable, uint8_t(hint))) { + // [stack] VAL + return false; + } + + if (!ifCreateResource.emitEnd()) { + // [stack] VAL + return false; + } + + // Step 4. Return unused. + return true; +} + +bool ForOfDisposalEmitter::prepareForForOfLoopIteration() { + MOZ_ASSERT(state_ == State::Start); + EmitterScope* es = bce_->innermostEmitterScopeNoCheck(); + MOZ_ASSERT(es->hasDisposables()); + + if (!bce_->emit1(JSOp::False)) { + // [stack] THROWING + return false; + } + + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] THROWING UNDEF + return false; + } + + if (!emitDisposeResourcesForEnvironment(*es)) { + // [stack] EXC THROWING + return false; + } + + if (!emitThrowIfException()) { + // [stack] + return false; + } + +#ifdef DEBUG + state_ = State::Iteration; +#endif + return true; +} + +bool ForOfDisposalEmitter::emitEnd() { + MOZ_ASSERT(state_ == State::Iteration); + EmitterScope* es = bce_->innermostEmitterScopeNoCheck(); + MOZ_ASSERT(es->hasDisposables()); + + // [stack] EXC STACK + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] STACK EXC + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] STACK EXC THROWING + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] STACK THROWING EXC + return false; + } + + if (!emitDisposeResourcesForEnvironment(*es)) { + // [stack] STACK EXC THROWING + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] STACK EXC + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] EXC STACK + return false; + } + +#ifdef DEBUG + state_ = State::End; +#endif + return true; +} + +bool UsingEmitter::emitEnd() { + MOZ_ASSERT(state_ == State::DisposableScopeBody); + EmitterScope* es = bce_->innermostEmitterScopeNoCheck(); + MOZ_ASSERT(es->hasDisposables()); + MOZ_ASSERT(tryEmitter_.isSome()); + + if (!tryEmitter_->emitFinally()) { + // [stack] EXC-OR-RESUME STACK THROWING RVAL? + return false; + } + + if (!bce_->emitDupAt(tryEmitter_->shouldUpdateRval() ? 1 : 0)) { + // [stack] EXC-OR-RESUME STACK THROWING RVAL? THROWING + return false; + } + + InternalIfEmitter ifThrowing(bce_); + + if (!ifThrowing.emitThenElse()) { + // [stack] EXC STACK THROWING RVAL? + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] EXC STACK THROWING RVAL? THROWING + return false; + } + + if (!bce_->emitDupAt(tryEmitter_->shouldUpdateRval() ? 4 : 3)) { + // [stack] EXC STACK THROWING RVAL? THROWING EXC + return false; + } + + if (!ifThrowing.emitElse()) { + // [stack] RESUME STACK THROWING RVAL? + return false; + } + + if (!bce_->emit1(JSOp::False)) { + // [stack] RESUME STACK THROWING RVAL? THROWING + return false; + } + + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] RESUME STACK THROWING RVAL? THROWING UNDEF + return false; + } + + if (!ifThrowing.emitEnd()) { + // [stack] EXC-OR-RESUME STACK THROWING RVAL? THROWING EXC-OR-UNDEF + return false; + } + + if (!emitDisposeResourcesForEnvironment(*es)) { + // [stack] EXC-OR-RESUME STACK THROWING RVAL? DISPOSAL-EXC DISPOSAL-THROWING + return false; + } + + if (bce_->sc->isSuspendableContext() && + bce_->sc->asSuspendableContext()->isGenerator()) { + // [stack] ... DISP-EXC DISP-THROWING + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] ... DISP-THROWING DISP-EXC + return false; + } + + if (!bce_->emit1(JSOp::IsGenClosing)) { + // [stack] ... DISP-THROWING DISP-EXC GEN-CLOSING + return false; + } + + if (!bce_->emit1(JSOp::Not)) { + // [stack] ... DISP-THROWING DISP-EXC !GEN-CLOSING + return false; + } + + if (!bce_->emitPickN(2)) { + // [stack] ... DISP-EXC !GEN-CLOSING DISP-THROWING + return false; + } + + if (!bce_->emit1(JSOp::BitAnd)) { + // [stack] ... DISP-EXC (DISP-THROWING & !GEN-CLOSING) + return false; + } + } + + if (!emitThrowIfException()) { + // [stack] EXC-OR-RESUME STACK THROWING RVAL? + return false; + } + + if (!tryEmitter_->emitEnd()) { + // [stack] + return false; + } + +#ifdef DEBUG + state_ = State::End; +#endif + return true; +} + +// Explicit Resource Management Proposal +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset +// Step 9.k.i. +bool NonLocalIteratorCloseUsingEmitter::prepareForIteratorClose( + EmitterScope& es) { + MOZ_ASSERT(state_ == State::Start); + // In this function we prepare for the closure of the iterator but first + // emitting the dispose loop and preseving exceptions on the stack and after + // that emitting a try to wrap the iterator closure code that shall come after + // this. + if (!es.hasDisposables()) { +#ifdef DEBUG + state_ = State::IteratorClose; +#endif + return true; + } + + setHasAwaitUsing(es.hasAsyncDisposables()); + + // [stack] ITER + + if (!bce_->emit1(JSOp::False)) { + // [stack] THROWING + return false; + } + + if (!bce_->emit1(JSOp::Undefined)) { + // [stack] THROWING UNDEF + return false; + } + + if (!emitDisposeResourcesForEnvironment(es)) { + // [stack] ITER EXC-DISPOSE DISPOSE-THROWING + return false; + } + + if (!bce_->emitPickN(2)) { + // [stack] EXC-DISPOSE DISPOSE-THROWING ITER + return false; + } + + tryClosingIterator_.emplace(bce_, TryEmitter::Kind::TryCatch, + TryEmitter::ControlKind::NonSyntactic); + + if (!tryClosingIterator_->emitTry()) { + // [stack] EXC-DISPOSE DISPOSE-THROWING ITER + return false; + } + +#ifdef DEBUG + state_ = State::IteratorClose; +#endif + return true; +} + +// Explicit Resource Management Proposal +// 7.4.9 IteratorClose ( iteratorRecord, completion ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-iteratorclose&secAll=true +// Steps 5-6. +// +// 7.4.11 AsyncIteratorClose ( iteratorRecord, completion ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asynciteratorclose&secAll=true +// Steps 5-6. +bool NonLocalIteratorCloseUsingEmitter::emitEnd() { + // This function handles the steps after the iterator close operation which + // may or may not have thrown. note that prepareForIteratorClose would have + // already wrapped the iterator closure with a try and have preserved any + // exception by the disposal operation on the stack now this function does the + // equivalent of the following pseudocode (consider excDispose and + // disposeThrowing and iter equal to corresponding values left on stack by + // prepareForIteratorClose): + // + // + // let excToThrow, throwing = disposeThrowing; + // try { + // IteratorClose(iter); + // } catch (excIterClose) { + // throwing = true; + // if (disposeThrowing) { + // excToThrow = excDispose; + // } else { + // excToThrow = excIterClose; + // } + // } + // if (throwing) { + // throw excToThrow; + // } + // + MOZ_ASSERT(state_ == State::IteratorClose); + + if (!tryClosingIterator_.isSome()) { +#ifdef DEBUG + state_ = State::End; +#endif + return true; + } + + // [stack] EXC-DISPOSE DISPOSE-THROWING ITER + + if (!tryClosingIterator_->emitCatch()) { + // [stack] EXC-DISPOSE DISPOSE-THROWING ITER EXC-ITER-CLOSE + return false; + } + + if (!bce_->emitPickN(2)) { + // [stack] EXC-DISPOSE ITER EXC-ITER-CLOSE DISPOSE-THROWING + return false; + } + + InternalIfEmitter ifDisposeWasThrowing(bce_); + + if (!ifDisposeWasThrowing.emitThenElse()) { + // [stack] EXC-DISPOSE ITER EXC-ITER-CLOSE + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] EXC-DISPOSE ITER + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] EXC-DISPOSE ITER THROWING + return false; + } + + // This swap operation is to make the stack state consistent with the + // the non-throwing case. + if (!bce_->emit1(JSOp::Swap)) { + // [stack] EXC-DISPOSE THROWING ITER + return false; + } + + if (!ifDisposeWasThrowing.emitElse()) { + // [stack] EXC-DISPOSE ITER EXC-ITER-CLOSE + return false; + } + + if (!bce_->emitPickN(2)) { + // [stack] ITER EXC-ITER-CLOSE EXC-DISPOSE + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] ITER EXC-ITER-CLOSE + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] EXC-ITER-CLOSE ITER + return false; + } + + if (!bce_->emit1(JSOp::True)) { + // [stack] EXC-ITER-CLOSE ITER THROWING + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] EXC-ITER-CLOSE THROWING ITER + return false; + } + + if (!ifDisposeWasThrowing.emitEnd()) { + // [stack] EXC THROWING ITER + return false; + } + + if (!tryClosingIterator_->emitEnd()) { + // [stack] EXC THROWING ITER + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] EXC ITER THROWING + return false; + } + + InternalIfEmitter ifThrowing(bce_); + + if (!ifThrowing.emitThenElse()) { + // [stack] EXC ITER + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] ITER EXC + return false; + } + + if (!bce_->emit1(JSOp::Throw)) { + // [stack] ITER + return false; + } + + if (!ifThrowing.emitElse()) { + // [stack] EXC ITER + return false; + } + + if (!bce_->emit1(JSOp::Swap)) { + // [stack] ITER EXC + return false; + } + + if (!bce_->emit1(JSOp::Pop)) { + // [stack] ITER + return false; + } + + if (!ifThrowing.emitEnd()) { + // [stack] ITER + return false; + } + +#ifdef DEBUG + state_ = State::End; +#endif + return true; +} diff --git a/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.h index 01ea34ce1a8..374db8e3331 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/UsingEmitter.h @@ -6,27 +6,261 @@ #define frontend_UsingEmitter_h #include "mozilla/Attributes.h" +#include "mozilla/Maybe.h" + +#include "frontend/TryEmitter.h" +#include "vm/UsingHint.h" namespace js::frontend { struct BytecodeEmitter; +class EmitterScope; -class MOZ_STACK_CLASS UsingEmitter { +// This enum simply refers to the kind of block we are operating in. The present +// use case of this is for disposal related code to special case the handling of +// disposals in different blocks. +enum class BlockKind : uint8_t { + ForOf, + + // Other here refers to any generic block which doesnt require any + // special handling. + Other +}; + +// Class for emitting bytecode for disposal loops. +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposeresources +// +// Usage: (check for the return value is omitted for simplicity) +// +// at the point where the disposal loop is needed +// DisposalEmitter de(bce, hasAsyncDisposables, initialCompletion); +// de.prepareForDisposeCapability(); +// emit_DisposeCapability(); +// de.emitEnd(es); +// +class MOZ_STACK_CLASS DisposalEmitter { private: BytecodeEmitter* bce_; + bool hasAsyncDisposables_; - // TODO: add state transition graph and state - // management for this emitter. +#ifdef DEBUG + // The state of this emitter. + // + // +-------+ prepareForDisposeCapability +-----------------------------+ + // | Start |------------------------------>| prepareForDisposeCapability |--+ + // +-------+ +-----------------------------+ | + // | + // +----------------------------------------------------------------------+ + // | + // | emitEnd +-----+ + // +---------->| End | + // +-----+ + enum class State { + // The initial state. + Start, + + // After calling prepareForDisposeCapability. + DisposeCapability, + + // After calling emitEnd. + End + }; + State state_ = State::Start; +#endif + + [[nodiscard]] bool emitResourcePropertyAccess(TaggedParserAtomIndex prop, + unsigned resourcesFromTop = 1); public: - enum Kind { Sync, Async }; + DisposalEmitter(BytecodeEmitter* bce, bool hasAsyncDisposables) + : bce_(bce), hasAsyncDisposables_(hasAsyncDisposables) {} + [[nodiscard]] bool prepareForDisposeCapability(); + + [[nodiscard]] bool emitEnd(EmitterScope& es); +}; + +// Class for emitting bytecode for using declarations. +// +// Usage: (check for the return value is omitted for simplicity) +// +// at the point of scope start +// UsingEmitter ue(bce); +// ue.prepareForDisposableScopeBody(); +// +// at the point of using decl assignment, e.g. `using x = y;` +// ue.prepareForAssignment(UsingHint::Normal); +// emit_Assignment(); +// +// at points requiring non-local jumps, like break, continue +// ue.emitNonLocalJump(¤tScope); +// +// at the point of scope end +// ue.emitEnd(); +class MOZ_STACK_CLASS UsingEmitter { + private: + mozilla::Maybe tryEmitter_; + + bool hasAwaitUsing_ = false; + +#ifdef DEBUG + // The state of this emitter. + // + // +-------+ prepareForDisposableScopeBody + // | Start |---------------------------------+ + // +-------+ | + // | + // +---------------------------------------+ + // | + // | +---------------------+ emitEnd +-----+ + // +-->+-->| DisposableScopeBody |--+----------->| End | + // ^ +---------------------+ | +-----+ + // | | + // | prepareForAssignment | + // +<---------------------------+ + // ^ | + // | emitNonLocalJump | + // +----------------------------+ + // + enum class State { + // The initial state. + Start, + + // After calling prepareForDisposableScopeBody. + DisposableScopeBody, + + // After calling emitEnd. + End + }; + State state_ = State::Start; +#endif + + [[nodiscard]] bool emitGetDisposeMethod(UsingHint hint); + + [[nodiscard]] bool emitCreateDisposableResource(UsingHint hint); + + [[nodiscard]] bool emitTakeDisposeCapability(); + + protected: + BytecodeEmitter* bce_; + + [[nodiscard]] bool emitThrowIfException(); + + [[nodiscard]] bool emitDisposeResourcesForEnvironment(EmitterScope& es); + + public: explicit UsingEmitter(BytecodeEmitter* bce); - [[nodiscard]] bool prepareForAssignment(Kind kind); + bool hasAwaitUsing() const { return hasAwaitUsing_; } + void setHasAwaitUsing(bool hasAwaitUsing) { hasAwaitUsing_ = hasAwaitUsing; } + + [[nodiscard]] bool prepareForDisposableScopeBody(BlockKind blockKind); + + [[nodiscard]] bool prepareForAssignment(UsingHint hint); + + [[nodiscard]] bool emitEnd(); +}; + +// This is a version of UsingEmitter specialized to help emit code for +// using declarations in for-of loop heads e.g.: `for (using x of y) {}`. +// +// Usage: (check for the return value is omitted for simplicity) +// +// at the point of the for-of loop head +// ForOfDisposalEmitter disposeBeforeIter(bce, hasAwaitUsing); +// disposeBeforeIter.prepareForForOfLoopIteration(); +// emit_Loop(); +// +// at the point of loop end +// prepare_IteratorClose(); +// disposeBeforeIter.emitEnd(); +// +class MOZ_STACK_CLASS ForOfDisposalEmitter : protected UsingEmitter { private: - bool emitCheckDisposeMethod(JS::SymbolCode hint); +#ifdef DEBUG + // The state of this emitter. + // + // +-------+ prepareForForOfLoopIteration +-----------+ + // | Start |-------------------------------->| Iteration |--+ + // +-------+ +-----------+ | + // | + // +------------------------------------------------------+ + // | + // | emitEnd +-----+ + // +---------->| End | + // +-----+ + enum class State { + // The initial state. + Start, + + // After calling prepareForForOfLoopIteration. + Iteration, + + // After calling emitEnd. + End + }; + State state_ = State::Start; +#endif + public: + explicit ForOfDisposalEmitter(BytecodeEmitter* bce, bool hasAwaitUsing) + : UsingEmitter(bce) { + setHasAwaitUsing(hasAwaitUsing); + } + + [[nodiscard]] bool prepareForForOfLoopIteration(); + + [[nodiscard]] bool emitEnd(); +}; + +// This is a version of UsingEmitter specialized to help emit code for +// non-local jumps in for-of loops for closing iterators. +// +// Usage: (check for the return value is omitted for simplicity) +// +// at the point of IteratorClose inside non-local jump +// NonLocalIteratorCloseUsingEmitter disposeBeforeIterClose(bce); +// disposeBeforeIterClose.prepareForIteratorClose(¤tScope); +// emit_IteratorClose(); +// disposeBeforeIterClose.emitEnd(¤tScope); +// +class MOZ_STACK_CLASS NonLocalIteratorCloseUsingEmitter + : protected UsingEmitter { + private: + mozilla::Maybe tryClosingIterator_; + +#ifdef DEBUG + // The state of this emitter. + // + // +-------+ prepareForIteratorClose +-------------------------+ + // | Start |-------------------------->| prepareForIteratorClose |--+ + // +-------+ +-------------------------+ | + // | + // +--------------------------------------------------------------+ + // | + // | emitEnd +-----+ + // +---------->| End | + // +-----+ + enum class State { + // The initial state. + Start, + + // After calling prepareForIteratorClose. + IteratorClose, + + // After calling emitEnd. + End + }; + State state_ = State::Start; +#endif + + public: + explicit NonLocalIteratorCloseUsingEmitter(BytecodeEmitter* bce) + : UsingEmitter(bce) {} + + [[nodiscard]] bool prepareForIteratorClose(EmitterScope& es); + + [[nodiscard]] bool emitEnd(); }; } // namespace js::frontend diff --git a/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.cpp b/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.cpp index 5b5fd13cd0f..3dead1d72b0 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.cpp +++ b/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.cpp @@ -84,7 +84,7 @@ bool WhileEmitter::emitEnd() { return true; } -#ifdef ENABLE_DECORATORS +#if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) bool InternalWhileEmitter::emitCond() { MOZ_ASSERT(state_ == State::Start); diff --git a/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.h b/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.h index 7c21dc313b3..d97a83c0e56 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.h +++ b/src/third_party/mozjs/extract/js/src/frontend/WhileEmitter.h @@ -35,7 +35,7 @@ struct BytecodeEmitter; // wh.emitEnd(); // class MOZ_STACK_CLASS WhileEmitter { -#ifdef ENABLE_DECORATORS +#if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) protected: #endif BytecodeEmitter* bce_; @@ -87,7 +87,7 @@ class MOZ_STACK_CLASS WhileEmitter { [[nodiscard]] bool emitEnd(); }; -#ifdef ENABLE_DECORATORS +#if defined(ENABLE_DECORATORS) || defined(ENABLE_EXPLICIT_RESOURCE_MANAGEMENT) // This version is for emitting the condition in synthesized code that // does not have a corresponding location in the source code. class MOZ_STACK_CLASS InternalWhileEmitter : public WhileEmitter { diff --git a/src/third_party/mozjs/extract/js/src/frontend/align_stack_comment.py b/src/third_party/mozjs/extract/js/src/frontend/align_stack_comment.py index 6e279a90c63..60895f9630f 100755 --- a/src/third_party/mozjs/extract/js/src/frontend/align_stack_comment.py +++ b/src/third_party/mozjs/extract/js/src/frontend/align_stack_comment.py @@ -49,18 +49,14 @@ def align_stack_comment(path): if head_len > ALIGNMENT_COLUMN: print( - "Warning: line {} overflows from alignment column {}: {}".format( - line_num, ALIGNMENT_COLUMN, head_len - ), + f"Warning: line {line_num} overflows from alignment column {ALIGNMENT_COLUMN}: {head_len}", file=sys.stderr, ) line_len = max(head_len, ALIGNMENT_COLUMN) + comment_len if line_len > MAX_CHARS_PER_LINE: print( - "Warning: line {} overflows from {} chars: {}".format( - line_num, MAX_CHARS_PER_LINE, line_len - ), + f"Warning: line {line_num} overflows from {MAX_CHARS_PER_LINE} chars: {line_len}", file=sys.stderr, ) @@ -78,15 +74,15 @@ def align_stack_comment(path): lines.append(line) print( - "Info: Minimum column number for [stack]: {}".format(max_head_len), + f"Info: Minimum column number for [stack]: {max_head_len}", file=sys.stderr, ) print( - "Info: Alignment column number for [stack]: {}".format(ALIGNMENT_COLUMN), + f"Info: Alignment column number for [stack]: {ALIGNMENT_COLUMN}", file=sys.stderr, ) print( - "Info: Max length of stack transition comments: {}".format(max_comment_len), + f"Info: Max length of stack transition comments: {max_comment_len}", file=sys.stderr, ) diff --git a/src/third_party/mozjs/extract/js/src/frontend/moz.build b/src/third_party/mozjs/extract/js/src/frontend/moz.build index 1b2e0c707f3..d9b0e5c526e 100644 --- a/src/third_party/mozjs/extract/js/src/frontend/moz.build +++ b/src/third_party/mozjs/extract/js/src/frontend/moz.build @@ -33,9 +33,6 @@ else: inputs=["ReservedWords.h"], ) -if CONFIG["JS_ENABLE_SMOOSH"]: - CbindgenHeader("smoosh_generated.h", inputs=["/js/src/frontend/smoosh"]) - UNIFIED_SOURCES += [ "AbstractScopePtr.cpp", "AsyncEmitter.cpp", @@ -45,7 +42,6 @@ UNIFIED_SOURCES += [ "BytecodeSection.cpp", "CallOrNewEmitter.cpp", "CForEmitter.cpp", - "CompileScript.cpp", "DefaultEmitter.cpp", "DoWhileEmitter.cpp", "ElemOpEmitter.cpp", @@ -83,11 +79,6 @@ UNIFIED_SOURCES += [ "WhileEmitter.cpp", ] -if CONFIG["JS_ENABLE_SMOOSH"]: - UNIFIED_SOURCES += [ - "Frontend2.cpp", - ] - if CONFIG["ENABLE_DECORATORS"]: UNIFIED_SOURCES += [ "DecoratorEmitter.cpp", diff --git a/src/third_party/mozjs/extract/js/src/fuzz-tests/differential-parsing.js b/src/third_party/mozjs/extract/js/src/fuzz-tests/differential-parsing.js deleted file mode 100644 index 1a61175721d..00000000000 --- a/src/third_party/mozjs/extract/js/src/fuzz-tests/differential-parsing.js +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// This file is used to detect and find cases where the Visage's parser is -// accepting more inputs than SpiderMonkey's parser. -// -// 1. Find new cases: -// -// To find new cases, we have to build with libFuzzer. The JS Shell can easily -// be built with libFuzzer by adding --enable-fuzzing to the configure script -// command line. -// -// Create a directory, and copy all test cases from the JS shell to this -// directory: -// -// $ mkdir fuzzer-input -// $ cd fuzzer-input -// $ find ../ -name \*.js -print0 | xargs -I '{}' -0 -n1 cp '{}' $(pwd) -// -// Once the JS Shell is built, set the FUZZER environment variable to this -// script location. -// -// $ FUZZER="./fuzz-tests/differential-parsing.js" build.dir/dist/bin/js -- \ -// -use_value_profile=1 -print_pcs=1 -timeout=5 -max_len=32 -only_ascii=1 \ -// ./fuzzer-input -// -// 2. Test a crashing test case: -// -// Once a new crashing test case is found, this script can be used to -// reproduce the crashing conditions. -// -// To do so, you need a JS Shell and to load this script and use the testFile -// function with the location of the crashing file. -// -// $ build.dir/dist/bin/js -// js> load("./fuzz-tests/differential-parsing.js"); -// js> testFile("./crash-42"); -// Parse Script C++: fail -// Parse Module C++: fail -// Parse Script Rust: succeed -// Parse Module Rust: fail -// Hit MOZ_CRASH(Rust accept more than C++) -// - -/* global crash, os, parse, timeout */ - -// This global will hold the current fuzzing buffer for each iteration. -var fuzzBuf; - -function timed(sec, f) { - // If the function `f` takes more than 3 seconds, then the evaluation ends - // prematurely and returns in libFuzzer handler without considering this - // test case as interesting. - timeout(sec, function() { - return false; - }); - f(); - - // Remove the timeout handler, to not kill future executions. - timeout(-1); -} - -var parseScriptCpp = { module: false, smoosh: false }; -var parseScriptRust = { module: false, smoosh: true }; -var parseModuleRust = { module: true, smoosh: true }; -var parseModuleCpp = { module: true, smoosh: false }; -function test(code, verbose = false) { - var isScriptCpp = false, - isModuleCpp = false, - isScriptRust = false, - isModuleRust = false; - try { - parse(code, parseScriptCpp); - isScriptCpp = true; - if (verbose) { - console.log("Parse Script C++: succeed"); - } - } catch (exc) { - if (verbose) { - console.log("Parse Script C++: fail"); - } - } - try { - parse(code, parseModuleCpp); - isModuleCpp = true; - if (verbose) { - console.log("Parse Module C++: succeed"); - } - } catch (exc) { - if (verbose) { - console.log("Parse Module C++: fail"); - } - } - try { - parse(code, parseScriptRust); - isScriptRust = true; - if (verbose) { - console.log("Parse Script Rust: succeed"); - } - } catch (exc) { - if (verbose) { - console.log("Parse Script Rust: fail"); - } - } - try { - parse(code, parseModuleRust); - isModuleRust = true; - if (verbose) { - console.log("Parse Module Rust: succeed"); - } - } catch (exc) { - if (verbose) { - console.log("Parse Module Rust: fail"); - } - } - if ((isScriptRust && !isScriptCpp) || (isModuleRust && !isModuleCpp)) { - crash("Rust accept more than C++"); - } -} - -function JSFuzzIterate() { - // This function is called per iteration. You must ensure that: - // - // 1) Each of your actions/decisions is only based on fuzzBuf, - // in particular not on Math.random(), Date/Time or other - // external inputs. - // - // 2) Your actions should be deterministic. The same fuzzBuf - // should always lead to the same set of actions/decisions. - // - // 3) You can modify the global where needed, but ensure that - // each iteration is isolated from one another by cleaning - // any modifications to the global after each iteration. - // In particular, iterations must not depend on or influence - // each other in any way (see also 1)). - // - // 4) You must catch all exceptions. - let code = String.fromCharCode(...fuzzBuf); - timed(3, _ => test(code)); - return 0; -} - -function testFile(file) { - let content = os.file.readFile(file); - test(content, true); -} diff --git a/src/third_party/mozjs/extract/js/src/fuzz-tests/gluesmith/Cargo.toml b/src/third_party/mozjs/extract/js/src/fuzz-tests/gluesmith/Cargo.toml index d22ac49f2ea..7edb1035afe 100644 --- a/src/third_party/mozjs/extract/js/src/fuzz-tests/gluesmith/Cargo.toml +++ b/src/third_party/mozjs/extract/js/src/fuzz-tests/gluesmith/Cargo.toml @@ -1,10 +1,11 @@ [package] +edition = "2015" name = "gluesmith" version = "0.1.0" authors = ["Christian Holler"] license = "MPL-2.0" [dependencies] -wasm-smith = "0.205.0" +wasm-smith = "0.219.1" arbitrary = { version = "1.0.0", features = ["derive"] } libc = "0.2" diff --git a/src/third_party/mozjs/extract/js/src/fuzz-tests/testWasm.cpp b/src/third_party/mozjs/extract/js/src/fuzz-tests/testWasm.cpp index 5dd6bcbea00..6a2da4f7f2d 100644 --- a/src/third_party/mozjs/extract/js/src/fuzz-tests/testWasm.cpp +++ b/src/third_party/mozjs/extract/js/src/fuzz-tests/testWasm.cpp @@ -36,6 +36,20 @@ extern "C" { size_t gluesmith(uint8_t* data, size_t size, uint8_t* out, size_t maxsize); } +// Filter and set only "always" preferences. "startup" preferences are +// not allowed to be set after JS_Init. +struct PrefsSetters { +#define JS_PREF_SETTER(NAME, CPP_NAME, TYPE, SETTER_NAME, IS_STARTUP) \ + template \ + static void set_##CPP_NAME(T value) { \ + if constexpr (!IS_STARTUP) { \ + JS::Prefs::SETTER_NAME(value); \ + } \ + } + FOR_EACH_JS_PREF(JS_PREF_SETTER) +#undef JS_PREF_SETTER +}; + static int testWasmInit(int* argc, char*** argv) { bool wasmHasSupport = WASM_HAS_SUPPORT(gCx); if (!wasmHasSupport || !wasm::HasSupport(gCx)) { @@ -44,7 +58,7 @@ static int testWasmInit(int* argc, char*** argv) { #define WASM_FEATURE(NAME, LOWER_NAME, COMPILE_PRED, COMPILER_PRED, FLAG_PRED, \ FLAG_FORCE_ON, FLAG_FUZZ_ON, PREF) \ - JS::Prefs::setAtStartup_wasm_##PREF(FLAG_FUZZ_ON); + PrefsSetters::set_wasm_##PREF(FLAG_FUZZ_ON); JS_FOR_WASM_FEATURES(WASM_FEATURE) #undef WASM_FEATURE @@ -253,6 +267,7 @@ static int testWasmFuzz(const uint8_t* buf, size_t size) { !bytecode->append(&buf[currentIndex], moduleLen)) { return 0; } + BytecodeSource bytecodeSource(bytecode->begin(), bytecode->length()); currentIndex += moduleLen; @@ -267,7 +282,8 @@ static int testWasmFuzz(const uint8_t* buf, size_t size) { UniqueChars error; UniqueCharsVector warnings; SharedModule module = - CompileBuffer(*compileArgs, *bytecode, &error, &warnings); + CompileBuffer(*compileArgs, BytecodeBufferOrSource(bytecodeSource), + &error, &warnings); if (!module) { // We should always have a valid module if we are using wasm-smith. Check // that no error is reported, signalling an OOM. @@ -277,7 +293,7 @@ static int testWasmFuzz(const uint8_t* buf, size_t size) { // At this point we have a valid module and we should try to ensure // that its import requirements are met for instantiation. - const ImportVector& importVec = module->imports(); + const ImportVector& importVec = module->moduleMeta().imports; // Empty native function used to fill in function import slots if we // run out of functions exported by other modules. diff --git a/src/third_party/mozjs/extract/js/src/fuzz-tests/tests.cpp b/src/third_party/mozjs/extract/js/src/fuzz-tests/tests.cpp index 7b288bec9ac..b730db188ea 100644 --- a/src/third_party/mozjs/extract/js/src/fuzz-tests/tests.cpp +++ b/src/third_party/mozjs/extract/js/src/fuzz-tests/tests.cpp @@ -23,12 +23,15 @@ using namespace mozilla; -JS::PersistentRootedObject gGlobal; +MOZ_RUNINIT JS::PersistentRootedObject gGlobal; JSContext* gCx = nullptr; static const JSClass* getGlobalClass() { - static const JSClass c = {"global", JSCLASS_GLOBAL_FLAGS, - &JS::DefaultGlobalClassOps}; + static const JSClass c = { + "global", + JSCLASS_GLOBAL_FLAGS, + &JS::DefaultGlobalClassOps, + }; return &c; } @@ -73,7 +76,6 @@ static void jsfuzz_uninit(JSContext* cx) { int main(int argc, char* argv[]) { // Override prefs for fuzz-tests. - JS::Prefs::setAtStartup_weakrefs(true); JS::Prefs::setAtStartup_experimental_weakrefs_expose_cleanupSome(true); if (!JS_Init()) { diff --git a/src/third_party/mozjs/extract/js/src/gc/AllocKind.h b/src/third_party/mozjs/extract/js/src/gc/AllocKind.h index f73352e557e..1de8545ae7a 100644 --- a/src/third_party/mozjs/extract/js/src/gc/AllocKind.h +++ b/src/third_party/mozjs/extract/js/src/gc/AllocKind.h @@ -51,7 +51,7 @@ namespace gc { // - their JS::TraceKind // - their C++ base type // - a C++ type of the correct size -// - whether they can be finalized on the background thread +// - their FinalizeKind (see above) // - whether they can be allocated in the nursery (this is true for foreground // finalized objects but these will can only actually be allocated in the // nursery if JSCLASS_SKIP_NURSERY_FINALIZE is set) @@ -59,60 +59,75 @@ namespace gc { // clang-format off #define FOR_EACH_OBJECT_ALLOCKIND(D) \ - /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \ - D(FUNCTION, Object, JSObject, JSObject_Slots4, true, true, true) \ - D(FUNCTION_EXTENDED, Object, JSObject, JSObject_Slots7, true, true, true) \ - D(OBJECT0, Object, JSObject, JSObject_Slots0, false, true, true) \ - D(OBJECT0_BACKGROUND, Object, JSObject, JSObject_Slots0, true, true, true) \ - D(OBJECT2, Object, JSObject, JSObject_Slots2, false, true, true) \ - D(OBJECT2_BACKGROUND, Object, JSObject, JSObject_Slots2, true, true, true) \ - D(ARRAYBUFFER4, Object, JSObject, JSObject_Slots4, true, true, true) \ - D(OBJECT4, Object, JSObject, JSObject_Slots4, false, true, true) \ - D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4, true, true, true) \ - D(ARRAYBUFFER8, Object, JSObject, JSObject_Slots8, true, true, true) \ - D(OBJECT8, Object, JSObject, JSObject_Slots8, false, true, true) \ - D(OBJECT8_BACKGROUND, Object, JSObject, JSObject_Slots8, true, true, true) \ - D(ARRAYBUFFER12, Object, JSObject, JSObject_Slots12, true, true, true) \ - D(OBJECT12, Object, JSObject, JSObject_Slots12, false, true, true) \ - D(OBJECT12_BACKGROUND, Object, JSObject, JSObject_Slots12, true, true, true) \ - D(ARRAYBUFFER16, Object, JSObject, JSObject_Slots16, true, true, true) \ - D(OBJECT16, Object, JSObject, JSObject_Slots16, false, true, true) \ - D(OBJECT16_BACKGROUND, Object, JSObject, JSObject_Slots16, true, true, true) + /* AllocKind TraceKind TypeName SizedType Finalize Nursery Compact */ \ + D(FUNCTION, Object, JSObject, JSObject_Slots4, None, true, true) \ + D(FUNCTION_EXTENDED, Object, JSObject, JSObject_Slots7, None, true, true) \ + D(OBJECT0, Object, JSObject, JSObject_Slots0, None, true, true) \ + D(OBJECT0_FOREGROUND, Object, JSObject, JSObject_Slots0, Foreground, true, true) \ + D(OBJECT0_BACKGROUND, Object, JSObject, JSObject_Slots0, Background, true, true) \ + D(OBJECT2, Object, JSObject, JSObject_Slots2, None, true, true) \ + D(OBJECT2_FOREGROUND, Object, JSObject, JSObject_Slots2, Foreground, true, true) \ + D(OBJECT2_BACKGROUND, Object, JSObject, JSObject_Slots2, Background, true, true) \ + D(ARRAYBUFFER4, Object, JSObject, JSObject_Slots4, Background, true, true) \ + D(OBJECT4, Object, JSObject, JSObject_Slots4, None, true, true) \ + D(OBJECT4_FOREGROUND, Object, JSObject, JSObject_Slots4, Foreground, true, true) \ + D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4, Background, true, true) \ + D(ARRAYBUFFER8, Object, JSObject, JSObject_Slots8, Background, true, true) \ + D(OBJECT8, Object, JSObject, JSObject_Slots8, None, true, true) \ + D(OBJECT8_FOREGROUND, Object, JSObject, JSObject_Slots8, Foreground, true, true) \ + D(OBJECT8_BACKGROUND, Object, JSObject, JSObject_Slots8, Background, true, true) \ + D(ARRAYBUFFER12, Object, JSObject, JSObject_Slots12, Background, true, true) \ + D(OBJECT12, Object, JSObject, JSObject_Slots12, None, true, true) \ + D(OBJECT12_FOREGROUND, Object, JSObject, JSObject_Slots12, Foreground, true, true) \ + D(OBJECT12_BACKGROUND, Object, JSObject, JSObject_Slots12, Background, true, true) \ + D(ARRAYBUFFER16, Object, JSObject, JSObject_Slots16, Background, true, true) \ + D(OBJECT16, Object, JSObject, JSObject_Slots16, None, true, true) \ + D(OBJECT16_FOREGROUND, Object, JSObject, JSObject_Slots16, Foreground, true, true) \ + D(OBJECT16_BACKGROUND, Object, JSObject, JSObject_Slots16, Background, true, true) #define FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \ - /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \ - D(SCRIPT, Script, js::BaseScript, js::BaseScript, false, false, true) \ - D(SHAPE, Shape, js::Shape, js::SizedShape, true, false, true) \ - D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, true, false, true) \ - D(GETTER_SETTER, GetterSetter, js::GetterSetter, js::GetterSetter, true, false, true) \ - D(COMPACT_PROP_MAP, PropMap, js::CompactPropMap, js::CompactPropMap, true, false, true) \ - D(NORMAL_PROP_MAP, PropMap, js::NormalPropMap, js::NormalPropMap, true, false, true) \ - D(DICT_PROP_MAP, PropMap, js::DictionaryPropMap, js::DictionaryPropMap, true, false, true) \ - D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, true, false, true) \ - D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, false) \ - D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, false) \ - D(SYMBOL, Symbol, JS::Symbol, JS::Symbol, true, false, false) \ - D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode, false, false, false) \ - D(SCOPE, Scope, js::Scope, js::Scope, true, false, true) \ - D(REGEXP_SHARED, RegExpShared, js::RegExpShared, js::RegExpShared, true, false, true) + /* AllocKind TraceKind TypeName SizedType Finalize Nursery Compact */ \ + D(SCRIPT, Script, js::BaseScript, js::BaseScript, Foreground, false, true) \ + D(SHAPE, Shape, js::Shape, js::SizedShape, Background, false, true) \ + D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, None, false, true) \ + D(GETTER_SETTER, GetterSetter, js::GetterSetter, js::GetterSetter, None, false, true) \ + D(COMPACT_PROP_MAP, PropMap, js::CompactPropMap, js::CompactPropMap, Background, false, true) \ + D(NORMAL_PROP_MAP, PropMap, js::NormalPropMap, js::NormalPropMap, Background, false, true) \ + D(DICT_PROP_MAP, PropMap, js::DictionaryPropMap, js::DictionaryPropMap, Background, false, true) \ + D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, Background, false, true) \ + D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, None, false, false) \ + D(ATOM, String, js::NormalAtom, js::NormalAtom, Background, false, false) \ + D(SYMBOL, Symbol, JS::Symbol, JS::Symbol, None, false, false) \ + D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode, Foreground, false, false) \ + D(SCOPE, Scope, js::Scope, js::Scope, Background, false, true) \ + D(REGEXP_SHARED, RegExpShared, js::RegExpShared, js::RegExpShared, Background, false, true) #define FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \ - /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \ - D(BIGINT, BigInt, JS::BigInt, JS::BigInt, true, true, true) + /* AllocKind TraceKind TypeName SizedType Finalize Nursery Compact */ \ + D(BIGINT, BigInt, JS::BigInt, JS::BigInt, Background, true, true) #define FOR_EACH_NURSERY_STRING_ALLOCKIND(D) \ - D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString, true, true, true) \ - D(STRING, String, JSString, JSString, true, true, true) + /* AllocKind TraceKind TypeName SizedType Finalize Nursery Compact */ \ + D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString, None, true, true) \ + D(STRING, String, JSString, JSString, Background, true, true) + +#define FOR_EACH_BUFFER_ALLOCKIND(D) \ + /* AllocKind TraceKind TypeName SizedType Finalize Nursery Compact */ \ + D(BUFFER16, SmallBuffer, js::gc::SmallBuffer, js::gc::SmallBufferN<16>, None, false, true) \ + D(BUFFER32, SmallBuffer, js::gc::SmallBuffer, js::gc::SmallBufferN<32>, None, false, true) \ + D(BUFFER64, SmallBuffer, js::gc::SmallBuffer, js::gc::SmallBufferN<64>, None, false, true) \ + D(BUFFER128, SmallBuffer, js::gc::SmallBuffer, js::gc::SmallBufferN<128>, None, false, true) // clang-format on -#define FOR_EACH_NONOBJECT_ALLOCKIND(D) \ - FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \ - FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \ +#define FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(D) \ + FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \ + FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \ FOR_EACH_NURSERY_STRING_ALLOCKIND(D) #define FOR_EACH_ALLOCKIND(D) \ FOR_EACH_OBJECT_ALLOCKIND(D) \ - FOR_EACH_NONOBJECT_ALLOCKIND(D) + FOR_EACH_BUFFER_ALLOCKIND(D) \ + FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(D) #define DEFINE_ALLOC_KIND(allocKind, _1, _2, _3, _4, _5, _6) allocKind, enum class AllocKind : uint8_t { @@ -122,7 +137,12 @@ enum class AllocKind : uint8_t { OBJECT_LIMIT, OBJECT_LAST = OBJECT_LIMIT - 1, - FOR_EACH_NONOBJECT_ALLOCKIND(DEFINE_ALLOC_KIND) + FOR_EACH_BUFFER_ALLOCKIND(DEFINE_ALLOC_KIND) + + BUFFER_LIMIT, + BUFFER_LAST = BUFFER_LIMIT - 1, + + FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(DEFINE_ALLOC_KIND) LIMIT, LAST = LIMIT - 1, @@ -130,7 +150,9 @@ enum class AllocKind : uint8_t { INVALID = LIMIT, FIRST = 0, - OBJECT_FIRST = FUNCTION // Hardcoded to first object kind. + OBJECT_FIRST = FUNCTION, // Hardcoded to first object kind. + + BUFFER_FIRST = BUFFER16 // clang-format on }; #undef DEFINE_ALLOC_KIND @@ -153,6 +175,19 @@ constexpr size_t AllocKindCount = size_t(AllocKind::LIMIT); */ enum class Heap : uint8_t { Default = 0, Tenured = 1 }; +enum class FinalizeKind { + // Cells are not finalized. Arenas containing these cells are swept on a + // background thread. + None = 0, + + // Requires foreground finalization. May have client-supplied finalizer. + Foreground, + + // Does not require foreground finalization but is non-trivial. May have + // client-supplied finalizer. Finalized on a background thread. + Background +}; + constexpr bool IsAllocKind(AllocKind kind) { return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT; } @@ -167,6 +202,10 @@ constexpr bool IsObjectAllocKind(AllocKind kind) { return kind >= AllocKind::OBJECT_FIRST && kind <= AllocKind::OBJECT_LAST; } +constexpr bool IsBufferAllocKind(AllocKind kind) { + return kind > AllocKind::OBJECT_LAST && kind <= AllocKind::BUFFER_LAST; +} + constexpr bool IsShapeAllocKind(AllocKind kind) { return kind == AllocKind::SHAPE; } @@ -217,13 +256,12 @@ using ObjectAllocKindArray = */ template struct MapTypeToAllocKind {}; -#define EXPAND_MAPTYPETOALLOCKIND(allocKind, traceKind, type, sizedType, \ - bgFinal, nursery, compact) \ - template <> \ - struct MapTypeToAllocKind { \ - static const AllocKind kind = AllocKind::allocKind; \ +#define EXPAND_MAPTYPETOALLOCKIND(allocKind, _1, type, _2, _3, _4, _5) \ + template <> \ + struct MapTypeToAllocKind { \ + static const AllocKind kind = AllocKind::allocKind; \ }; -FOR_EACH_NONOBJECT_ALLOCKIND(EXPAND_MAPTYPETOALLOCKIND) +FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(EXPAND_MAPTYPETOALLOCKIND) #undef EXPAND_MAPTYPETOALLOCKIND template <> @@ -266,8 +304,7 @@ struct MapTypeToAllocKind { constexpr JS::TraceKind MapAllocToTraceKind(AllocKind kind) { constexpr JS::TraceKind map[] = { -#define EXPAND_ELEMENT(allocKind, traceKind, type, sizedType, bgFinal, \ - nursery, compact) \ +#define EXPAND_ELEMENT(_1, traceKind, _2, _3, _4, _5, _6) \ JS::TraceKind::traceKind, FOR_EACH_ALLOCKIND(EXPAND_ELEMENT) #undef EXPAND_ELEMENT @@ -292,22 +329,36 @@ constexpr bool IsNurseryAllocable(AllocKind kind) { return map[size_t(kind)]; } -constexpr bool IsBackgroundFinalized(AllocKind kind) { +constexpr FinalizeKind GetFinalizeKind(AllocKind kind) { MOZ_ASSERT(IsValidAllocKind(kind)); - constexpr bool map[] = { -#define DEFINE_BACKGROUND_FINALIZED(_1, _2, _3, _4, bgFinal, _5, _6) bgFinal, - FOR_EACH_ALLOCKIND(DEFINE_BACKGROUND_FINALIZED) -#undef DEFINE_BACKGROUND_FINALIZED + constexpr FinalizeKind map[] = { +#define DEFINE_FINALIZE_KIND(_1, _2, _3, _4, finalizeKind, _5, _6) \ + FinalizeKind::finalizeKind, + FOR_EACH_ALLOCKIND(DEFINE_FINALIZE_KIND) +#undef DEFINE_FINALIZE_KIND }; - static_assert(std::size(map) == AllocKindCount, - "IsBackgroundFinalized sanity check"); + static_assert(std::size(map) == AllocKindCount); return map[size_t(kind)]; } +constexpr bool IsFinalizedKind(AllocKind kind) { + return GetFinalizeKind(kind) != FinalizeKind::None; +} + constexpr bool IsForegroundFinalized(AllocKind kind) { - return !IsBackgroundFinalized(kind); + return GetFinalizeKind(kind) == FinalizeKind::Foreground; +} + +constexpr bool IsBackgroundFinalized(AllocKind kind) { + return GetFinalizeKind(kind) == FinalizeKind::Background; +} + +// Arenas containing cells of kind FinalizeKind::None and +// FinalizeKind::Background are swept on a background thread. +constexpr bool IsBackgroundSwept(AllocKind kind) { + return !IsForegroundFinalized(kind); } constexpr bool IsCompactingKind(AllocKind kind) { diff --git a/src/third_party/mozjs/extract/js/src/gc/Allocator-inl.h b/src/third_party/mozjs/extract/js/src/gc/Allocator-inl.h index 6a59a6dd6d5..7f69f8d80e2 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Allocator-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/Allocator-inl.h @@ -99,6 +99,65 @@ T* CellAllocator::NewObject(JSContext* cx, gc::AllocKind kind, gc::Heap heap, return new (mozilla::KnownNotNull, cell) T(); } +template +/* static */ +T* CellAllocator::NewTenuredCell(JSContext* cx, Args&&... args) { + gc::AllocKind kind = gc::MapTypeToAllocKind::kind; + MOZ_ASSERT(Arena::thingSize(kind) == sizeof(T)); + void* cell = AllocTenuredCell(cx, kind); + if (MOZ_UNLIKELY(!cell)) { + return nullptr; + } + return new (mozilla::KnownNotNull, cell) T(std::forward(args)...); +} + +#if defined(DEBUG) || defined(JS_GC_ZEAL) || defined(JS_OOM_BREAKPOINT) + +// This serves as a single point to perform some unrelated checks that happens +// before every allocation. Performs the following: +// +// - checks we can't GC inside a JS::AutoAssertNoGC region +// - runs a zeal GC if needed +// +// This is a no-op in release builds. +// +// This is only called on paths where GC is allowed. +inline void PreAllocGCChecks(JSContext* cx) { + // Crash if we could perform a GC action when it is not safe. + if (!cx->suppressGC) { + cx->verifyIsSafeToGC(); + } + +# ifdef JS_GC_ZEAL + GCRuntime* gc = &cx->runtime()->gc; + if (gc->needZealousGC()) { + gc->runDebugGC(); + } +# endif +} + +inline bool CheckForSimulatedFailure(JSContext* cx, AllowGC allowGC) { + // For testing out of memory conditions. + if (js::oom::ShouldFailWithOOM()) { + // If we are doing a fallible allocation, percolate up the OOM instead of + // reporting it. + if (allowGC) { + ReportOutOfMemory(cx); + } + return false; + } + + return true; +} +#else + +inline void PreAllocGCChecks(JSContext* cx) {} +inline bool CheckForSimulatedFailure(JSContext* cx, AllowGC allowGC) { + return true; +} + +#endif // DEBUG || JS_GC_ZEAL || JS_OOM_BREAKPOINT + template /* static */ void* CellAllocator::AllocNurseryOrTenuredCell(JSContext* cx, @@ -110,8 +169,14 @@ void* CellAllocator::AllocNurseryOrTenuredCell(JSContext* cx, MOZ_ASSERT(thingSize == Arena::thingSize(allocKind)); MOZ_ASSERT_IF(site && site->initialHeap() == Heap::Tenured, heap == Heap::Tenured); + MOZ_ASSERT(!cx->zone()->isAtomsZone()); + MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); - if (!PreAllocChecks(cx, allocKind)) { + if constexpr (allowGC) { + PreAllocGCChecks(cx); + } + + if (!CheckForSimulatedFailure(cx, allowGC)) { return nullptr; } @@ -135,7 +200,7 @@ void* CellAllocator::AllocNurseryOrTenuredCell(JSContext* cx, site); } - return TryNewTenuredCell(cx, allocKind, thingSize); + return AllocTenuredCellForNurseryAlloc(cx, allocKind); } /* static */ @@ -149,17 +214,6 @@ MOZ_ALWAYS_INLINE gc::Heap CellAllocator::CheckedHeap(gc::Heap heap) { return heap; } -template -/* static */ -T* CellAllocator::NewTenuredCell(JSContext* cx, Args&&... args) { - gc::AllocKind kind = gc::MapTypeToAllocKind::kind; - void* cell = AllocTenuredCell(cx, kind, sizeof(T)); - if (MOZ_UNLIKELY(!cell)) { - return nullptr; - } - return new (mozilla::KnownNotNull, cell) T(std::forward(args)...); -} - } // namespace gc } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/gc/Allocator.cpp b/src/third_party/mozjs/extract/js/src/gc/Allocator.cpp index 27db9eb8a06..d3b00c72b83 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Allocator.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Allocator.cpp @@ -27,7 +27,6 @@ #include "vm/JSContext-inl.h" #include "vm/JSScript-inl.h" -using mozilla::TimeDuration; using mozilla::TimeStamp; using namespace js; @@ -113,7 +112,7 @@ MOZ_NEVER_INLINE void* CellAllocator::RetryNurseryAlloc(JSContext* cx, } // As a final fallback, allocate the cell in the tenured heap. - return TryNewTenuredCell(cx, allocKind, thingSize); + return AllocTenuredCellForNurseryAlloc(cx, allocKind); } template void* CellAllocator::RetryNurseryAlloc(JSContext* cx, @@ -127,52 +126,75 @@ template void* CellAllocator::RetryNurseryAlloc(JSContext* cx, size_t thingSize, AllocSite* site); -template -void* gc::CellAllocator::AllocTenuredCell(JSContext* cx, gc::AllocKind kind, - size_t size) { - MOZ_ASSERT(!IsNurseryAllocable(kind)); - MOZ_ASSERT(size == Arena::thingSize(kind)); +static inline void MajorGCIfRequested(JSContext* cx) { + // Invoking the interrupt callback can fail and we can't usefully + // handle that here. Just check in case we need to collect instead. + if (cx->hasPendingInterrupt(InterruptReason::MajorGC)) { + cx->runtime()->gc.gcIfRequested(); + } +} - if (!PreAllocChecks(cx, kind)) { +template +MOZ_NEVER_INLINE void* gc::CellAllocator::AllocTenuredCellForNurseryAlloc( + JSContext* cx, gc::AllocKind kind) { + if constexpr (allowGC) { + MajorGCIfRequested(cx); + } + + return AllocTenuredCellUnchecked(cx->zone(), kind); +} +template void* gc::CellAllocator::AllocTenuredCellForNurseryAlloc( + JSContext*, AllocKind); +template void* gc::CellAllocator::AllocTenuredCellForNurseryAlloc( + JSContext*, AllocKind); + +#ifdef DEBUG +static bool IsAtomsZoneKind(AllocKind kind) { + return kind == AllocKind::ATOM || kind == AllocKind::FAT_INLINE_ATOM || + kind == AllocKind::SYMBOL; +} +#endif + +template +void* gc::CellAllocator::AllocTenuredCell(JSContext* cx, gc::AllocKind kind) { + MOZ_ASSERT(!IsNurseryAllocable(kind)); + MOZ_ASSERT_IF(cx->zone()->isAtomsZone(), + IsAtomsZoneKind(kind) || kind == AllocKind::JITCODE); + MOZ_ASSERT_IF(!cx->zone()->isAtomsZone(), !IsAtomsZoneKind(kind)); + MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); + + if constexpr (allowGC) { + PreAllocGCChecks(cx); + } + + if (!CheckForSimulatedFailure(cx, allowGC)) { return nullptr; } - return TryNewTenuredCell(cx, kind, size); + if constexpr (allowGC) { + MajorGCIfRequested(cx); + } + + return AllocTenuredCellUnchecked(cx->zone(), kind); } -template void* gc::CellAllocator::AllocTenuredCell(JSContext*, AllocKind, - size_t); -template void* gc::CellAllocator::AllocTenuredCell(JSContext*, AllocKind, - size_t); +template void* gc::CellAllocator::AllocTenuredCell(JSContext*, AllocKind); +template void* gc::CellAllocator::AllocTenuredCell(JSContext*, + AllocKind); template /* static */ -void* CellAllocator::TryNewTenuredCell(JSContext* cx, AllocKind kind, - size_t thingSize) { - if constexpr (allowGC) { - // Invoking the interrupt callback can fail and we can't usefully - // handle that here. Just check in case we need to collect instead. - if (cx->hasPendingInterrupt(InterruptReason::MajorGC)) { - cx->runtime()->gc.gcIfRequested(); - } - } - +void* CellAllocator::AllocTenuredCellUnchecked(JS::Zone* zone, AllocKind kind) { // Bump allocate in the arena's current free-list span. - Zone* zone = cx->zone(); void* ptr = zone->arenas.freeLists().allocate(kind); if (MOZ_UNLIKELY(!ptr)) { - // Get the next available free list and allocate out of it. This may - // acquire a new arena, which will lock the chunk list. If there are no - // chunks available it may also allocate new memory directly. - ptr = GCRuntime::refillFreeList(cx, kind); + // Get the next available free list and allocate out of it. This may acquire + // a new arena, which will lock the chunk list. If there are no chunks + // available it may also allocate new memory directly. + ptr = GCRuntime::refillFreeList(zone, kind); if (MOZ_UNLIKELY(!ptr)) { if constexpr (allowGC) { - cx->runtime()->gc.attemptLastDitchGC(cx); - ptr = TryNewTenuredCell(cx, kind, thingSize); - if (ptr) { - return ptr; - } - ReportOutOfMemory(cx); + return RetryTenuredAlloc(zone, kind); } return nullptr; @@ -180,7 +202,7 @@ void* CellAllocator::TryNewTenuredCell(JSContext* cx, AllocKind kind, } #ifdef DEBUG - CheckIncrementalZoneState(cx, ptr); + CheckIncrementalZoneState(zone, ptr); #endif gcprobes::TenuredAlloc(ptr, kind); @@ -192,14 +214,26 @@ void* CellAllocator::TryNewTenuredCell(JSContext* cx, AllocKind kind, return ptr; } -template void* CellAllocator::TryNewTenuredCell(JSContext* cx, - AllocKind kind, - size_t thingSize); -template void* CellAllocator::TryNewTenuredCell(JSContext* cx, - AllocKind kind, - size_t thingSize); +template void* CellAllocator::AllocTenuredCellUnchecked(JS::Zone* zone, + AllocKind kind); +template void* CellAllocator::AllocTenuredCellUnchecked(JS::Zone* zone, + AllocKind kind); +/* static */ +MOZ_NEVER_INLINE void* CellAllocator::RetryTenuredAlloc(JS::Zone* zone, + AllocKind kind) { + JSRuntime* runtime = zone->runtimeFromMainThread(); + runtime->gc.attemptLastDitchGC(); -void GCRuntime::attemptLastDitchGC(JSContext* cx) { + void* ptr = AllocTenuredCellUnchecked(zone, kind); + if (!ptr) { + ReportOutOfMemory(runtime->mainContextFromOwnThread()); + return nullptr; + } + + return ptr; +} + +void GCRuntime::attemptLastDitchGC() { // Either there was no memory available for a new chunk or the heap hit its // size limit. Try to perform an all-compartments, non-incremental, shrinking // GC and wait for it to finish. @@ -209,7 +243,7 @@ void GCRuntime::attemptLastDitchGC(JSContext* cx) { return; } - JS::PrepareForFullGC(cx); + JS::PrepareForFullGC(rt->mainContextFromOwnThread()); gc(JS::GCOptions::Shrink, JS::GCReason::LAST_DITCH); waitBackgroundAllocEnd(); waitBackgroundFreeEnd(); @@ -217,68 +251,6 @@ void GCRuntime::attemptLastDitchGC(JSContext* cx) { lastLastDitchTime = mozilla::TimeStamp::Now(); } -#ifdef DEBUG -static bool IsAtomsZoneKind(AllocKind kind) { - return kind == AllocKind::ATOM || kind == AllocKind::FAT_INLINE_ATOM || - kind == AllocKind::SYMBOL; -} -#endif - -#if defined(DEBUG) || defined(JS_GC_ZEAL) || defined(JS_OOM_BREAKPOINT) - -static inline void CheckAllocZone(Zone* zone, AllocKind kind) { - MOZ_ASSERT_IF(zone->isAtomsZone(), - IsAtomsZoneKind(kind) || kind == AllocKind::JITCODE); - MOZ_ASSERT_IF(!zone->isAtomsZone(), !IsAtomsZoneKind(kind)); -} - -// This serves as a single point to perform a bunch of unrelated work that -// happens before every allocation. Performs the following testing functions: -// -// - checks we can't GC inside a JS::AutoAssertNoGC region -// - runs a zeal GC if needed -// - possibly fails the allocation for OOM testing -// -// This is a no-op in release builds. -template -bool CellAllocator::PreAllocChecks(JSContext* cx, AllocKind kind) { - MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); - - CheckAllocZone(cx->zone(), kind); - - // Crash if we could perform a GC action when it is not safe. - if (allowGC && !cx->suppressGC) { - cx->verifyIsSafeToGC(); - } - -# ifdef JS_GC_ZEAL - if constexpr (allowGC) { - GCRuntime* gc = &cx->runtime()->gc; - if (gc->needZealousGC()) { - gc->runDebugGC(); - } - } -# endif - - // For testing out of memory conditions. - if (js::oom::ShouldFailWithOOM()) { - // If we are doing a fallible allocation, percolate up the OOM instead of - // reporting it. - if constexpr (allowGC) { - ReportOutOfMemory(cx); - } - return false; - } - - return true; -} -template bool CellAllocator::PreAllocChecks(JSContext* cx, - AllocKind kind); -template bool CellAllocator::PreAllocChecks(JSContext* cx, - AllocKind kind); - -#endif // DEBUG || JS_GC_ZEAL || JS_OOM_BREAKPOINT - #ifdef JS_GC_ZEAL /* static */ @@ -330,11 +302,11 @@ AllocSite* CellAllocator::MaybeGenerateMissingAllocSite(JSContext* cx, #ifdef DEBUG /* static */ -void CellAllocator::CheckIncrementalZoneState(JSContext* cx, void* ptr) { +void CellAllocator::CheckIncrementalZoneState(JS::Zone* zone, void* ptr) { MOZ_ASSERT(ptr); TenuredCell* cell = reinterpret_cast(ptr); - TenuredChunkBase* chunk = detail::GetCellChunkBase(cell); - if (cx->zone()->isGCMarkingOrSweeping()) { + ArenaChunkBase* chunk = detail::GetCellChunkBase(cell); + if (zone->isGCMarkingOrSweeping()) { MOZ_ASSERT(chunk->markBits.isMarkedBlack(cell)); } else { MOZ_ASSERT(!chunk->markBits.isMarkedAny(cell)); @@ -367,71 +339,91 @@ void GCRuntime::startBackgroundAllocTaskIfIdle() { } /* static */ -void* GCRuntime::refillFreeList(JSContext* cx, AllocKind thingKind) { - MOZ_ASSERT(cx->zone()->arenas.freeLists().isEmpty(thingKind)); +void* GCRuntime::refillFreeList(JS::Zone* zone, AllocKind thingKind) { + MOZ_ASSERT(zone->arenas.freeLists().isEmpty(thingKind)); // It should not be possible to allocate on the main thread while we are // inside a GC. - MOZ_ASSERT(!JS::RuntimeHeapIsBusy(), "allocating while under GC"); + MOZ_ASSERT(!JS::RuntimeHeapIsCollecting(), "allocating while under GC"); - return cx->zone()->arenas.refillFreeListAndAllocate( - thingKind, ShouldCheckThresholds::CheckThresholds); + return zone->arenas.refillFreeListAndAllocate( + thingKind, ShouldCheckThresholds::CheckThresholds, StallAndRetry::No); } /* static */ void* GCRuntime::refillFreeListInGC(Zone* zone, AllocKind thingKind) { - // Called by compacting GC to refill a free list while we are in a GC. - MOZ_ASSERT(JS::RuntimeHeapIsCollecting()); + // Called when tenuring nursery cells and during compacting GC. MOZ_ASSERT_IF(!JS::RuntimeHeapIsMinorCollecting(), !zone->runtimeFromMainThread()->gc.isBackgroundSweeping()); + // Since this needs to succeed we pass StallAndRetry::Yes. return zone->arenas.refillFreeListAndAllocate( - thingKind, ShouldCheckThresholds::DontCheckThresholds); + thingKind, ShouldCheckThresholds::DontCheckThresholds, + StallAndRetry::Yes); } void* ArenaLists::refillFreeListAndAllocate( - AllocKind thingKind, ShouldCheckThresholds checkThresholds) { + AllocKind thingKind, ShouldCheckThresholds checkThresholds, + StallAndRetry stallAndRetry) { MOZ_ASSERT(freeLists().isEmpty(thingKind)); - JSRuntime* rt = runtimeFromAnyThread(); + GCRuntime* gc = &runtimeFromAnyThread()->gc; - mozilla::Maybe maybeLock; - - // See if we can proceed without taking the GC lock. - if (concurrentUse(thingKind) != ConcurrentUse::None) { - maybeLock.emplace(rt); - } - - Arena* arena = arenaList(thingKind).takeNextArena(); +retry_loop: + Arena* arena = arenaList(thingKind).takeInitialNonFullArena(); if (arena) { // Empty arenas should be immediately freed. MOZ_ASSERT(!arena->isEmpty()); - return freeLists().setArenaAndAllocate(arena, thingKind); } - // Parallel threads have their own ArenaLists, but chunks are shared; - // if we haven't already, take the GC lock now to avoid racing. - if (maybeLock.isNothing()) { - maybeLock.emplace(rt); + // If we have just finished background sweep then merge the swept arenas in + // and retry. + if (MOZ_UNLIKELY(concurrentUse(thingKind) == + ConcurrentUse::BackgroundFinalizeFinished)) { + ArenaList sweptArenas; + { + AutoLockGC lock(gc); + sweptArenas = std::move(collectingArenaList(thingKind)); + } + concurrentUse(thingKind) = ConcurrentUse::None; + if (!sweptArenas.isEmpty()) { + mergeSweptArenas(thingKind, sweptArenas); + goto retry_loop; + } } - TenuredChunk* chunk = rt->gc.pickChunk(maybeLock.ref()); + // Use the current chunk if set. + ArenaChunk* chunk = gc->currentChunk_; + MOZ_ASSERT_IF(chunk, gc->isCurrentChunk(chunk)); + if (!chunk) { - return nullptr; + // The chunk lists can be accessed by background sweeping and background + // chunk allocation. Take the GC lock to synchronize access. + AutoLockGCBgAlloc lock(gc); + + chunk = gc->pickChunk(stallAndRetry, lock); + if (!chunk) { + return nullptr; + } + + gc->setCurrentChunk(chunk, lock); } + MOZ_ASSERT(gc->isCurrentChunk(chunk)); + // Although our chunk should definitely have enough space for another arena, - // there are other valid reasons why TenuredChunk::allocateArena() may fail. - arena = rt->gc.allocateArena(chunk, zone_, thingKind, checkThresholds, - maybeLock.ref()); + // there are other valid reasons why ArenaChunk::allocateArena() may fail. + arena = gc->allocateArena(chunk, zone_, thingKind, checkThresholds); if (!arena) { return nullptr; } + arena->init(gc, zone_, thingKind); + ArenaList& al = arenaList(thingKind); - MOZ_ASSERT(al.isCursorAtEnd()); - al.insertBeforeCursor(arena); + MOZ_ASSERT(!al.hasNonFullArenas()); + al.pushBack(arena); return freeLists().setArenaAndAllocate(arena, thingKind); } @@ -447,7 +439,7 @@ inline void* FreeLists::setArenaAndAllocate(Arena* arena, AllocKind kind) { FreeSpan* span = arena->getFirstFreeSpan(); freeLists_[kind] = span; - Zone* zone = arena->zone; + Zone* zone = arena->zone(); if (MOZ_UNLIKELY(zone->isGCMarkingOrSweeping())) { arena->arenaAllocatedDuringGC(); } @@ -463,14 +455,14 @@ void Arena::arenaAllocatedDuringGC() { // incremental GC will be marked black by pre-marking all free cells in the // arena we are about to allocate from. - MOZ_ASSERT(zone->isGCMarkingOrSweeping()); + MOZ_ASSERT(zone()->isGCMarkingOrSweeping()); for (ArenaFreeCellIter cell(this); !cell.done(); cell.next()) { MOZ_ASSERT(!cell->isMarkedAny()); cell->markBlack(); } } -// /////////// TenuredChunk -> Arena Allocator /////////////////////////////// +// /////////// ArenaChunk -> Arena Allocator ///////////////////////////////// bool GCRuntime::wantBackgroundAllocation(const AutoLockGC& lock) const { // To minimize memory waste, we do not want to run the background chunk @@ -481,10 +473,10 @@ bool GCRuntime::wantBackgroundAllocation(const AutoLockGC& lock) const { (fullChunks(lock).count() + availableChunks(lock).count()) >= 4; } -Arena* GCRuntime::allocateArena(TenuredChunk* chunk, Zone* zone, +// Allocate a new arena but don't initialize it. +Arena* GCRuntime::allocateArena(ArenaChunk* chunk, Zone* zone, AllocKind thingKind, - ShouldCheckThresholds checkThresholds, - const AutoLockGC& lock) { + ShouldCheckThresholds checkThresholds) { MOZ_ASSERT(chunk->hasAvailableArenas()); // Fail the allocation if we are over our heap size limits. @@ -493,8 +485,16 @@ Arena* GCRuntime::allocateArena(TenuredChunk* chunk, Zone* zone, return nullptr; } - Arena* arena = chunk->allocateArena(this, zone, thingKind, lock); - zone->gcHeapSize.addGCArena(heapSize); + Arena* arena = chunk->allocateArena(this, zone, thingKind); + + if (IsBufferAllocKind(thingKind)) { + // Try to keep GC scheduling the same to minimize benchmark noise. + // Keep this in sync with Arena::release. + size_t usableSize = ArenaSize - Arena::firstThingOffset(thingKind); + zone->mallocHeapSize.addBytes(usableSize); + } else { + zone->gcHeapSize.addGCArena(heapSize); + } // Trigger an incremental slice if needed. if (checkThresholds != ShouldCheckThresholds::DontCheckThresholds) { @@ -504,9 +504,11 @@ Arena* GCRuntime::allocateArena(TenuredChunk* chunk, Zone* zone, return arena; } -Arena* TenuredChunk::allocateArena(GCRuntime* gc, Zone* zone, - AllocKind thingKind, - const AutoLockGC& lock) { +Arena* ArenaChunk::allocateArena(GCRuntime* gc, Zone* zone, + AllocKind thingKind) { + MOZ_ASSERT(info.isCurrentChunk); + MOZ_ASSERT(hasAvailableArenas()); + if (info.numArenasFreeCommitted == 0) { commitOnePage(gc); MOZ_ASSERT(info.numArenasFreeCommitted == ArenasPerPage); @@ -515,35 +517,19 @@ Arena* TenuredChunk::allocateArena(GCRuntime* gc, Zone* zone, MOZ_ASSERT(info.numArenasFreeCommitted > 0); Arena* arena = fetchNextFreeArena(gc); - arena->init(zone, thingKind, lock); - updateChunkListAfterAlloc(gc, lock); + updateCurrentChunkAfterAlloc(gc); verify(); return arena; } -template -static inline size_t FindFirstBitSet( - const mozilla::BitSet& bitset) { - MOZ_ASSERT(!bitset.IsEmpty()); - - const auto& words = bitset.Storage(); - for (size_t i = 0; i < words.Length(); i++) { - uint32_t word = words[i]; - if (word) { - return i * 32 + mozilla::CountTrailingZeroes32(word); - } - } - - MOZ_CRASH("No bits found"); -} - -void TenuredChunk::commitOnePage(GCRuntime* gc) { +void ArenaChunk::commitOnePage(GCRuntime* gc) { MOZ_ASSERT(info.numArenasFreeCommitted == 0); MOZ_ASSERT(info.numArenasFree >= ArenasPerPage); - uint32_t pageIndex = FindFirstBitSet(decommittedPages); + uint32_t pageIndex = decommittedPages.FindFirst(); + MOZ_ASSERT(pageIndex < PagesPerChunk); MOZ_ASSERT(decommittedPages[pageIndex]); if (DecommitEnabled()) { @@ -553,55 +539,60 @@ void TenuredChunk::commitOnePage(GCRuntime* gc) { decommittedPages[pageIndex] = false; for (size_t i = 0; i < ArenasPerPage; i++) { - size_t arenaIndex = pageIndex * ArenasPerPage + i; + size_t arenaIndex = pageToArenaIndex(pageIndex) + i; MOZ_ASSERT(!freeCommittedArenas[arenaIndex]); freeCommittedArenas[arenaIndex] = true; - arenas[arenaIndex].setAsNotAllocated(); ++info.numArenasFreeCommitted; - gc->updateOnArenaFree(); } verify(); } -inline void GCRuntime::updateOnFreeArenaAlloc(const TenuredChunkInfo& info) { - MOZ_ASSERT(info.numArenasFreeCommitted <= numArenasFreeCommitted); - --numArenasFreeCommitted; -} - -Arena* TenuredChunk::fetchNextFreeArena(GCRuntime* gc) { +Arena* ArenaChunk::fetchNextFreeArena(GCRuntime* gc) { MOZ_ASSERT(info.numArenasFreeCommitted > 0); MOZ_ASSERT(info.numArenasFreeCommitted <= info.numArenasFree); - size_t index = FindFirstBitSet(freeCommittedArenas); - MOZ_ASSERT(freeCommittedArenas[index]); + size_t index = freeCommittedArenas.FindFirst(); + MOZ_ASSERT(index < ArenasPerChunk); + MOZ_ASSERT(freeCommittedArenas[index]); freeCommittedArenas[index] = false; - --info.numArenasFreeCommitted; - --info.numArenasFree; - gc->updateOnFreeArenaAlloc(info); return &arenas[index]; } -// /////////// System -> TenuredChunk Allocator ////////////////////////////// +// /////////// System -> ArenaChunk Allocator //////////////////////////////// -TenuredChunk* GCRuntime::getOrAllocChunk(AutoLockGCBgAlloc& lock) { - TenuredChunk* chunk = emptyChunks(lock).pop(); - if (chunk) { +ArenaChunk* GCRuntime::takeOrAllocChunk(StallAndRetry stallAndRetry, + AutoLockGCBgAlloc& lock) { + ArenaChunk* chunk = getOrAllocChunk(stallAndRetry, lock); + if (!chunk) { + return nullptr; + } + + emptyChunks(lock).remove(chunk); + return chunk; +} + +ArenaChunk* GCRuntime::getOrAllocChunk(StallAndRetry stallAndRetry, + AutoLockGCBgAlloc& lock) { + ArenaChunk* chunk; + if (!emptyChunks(lock).empty()) { + chunk = emptyChunks(lock).head(); // Reinitialize ChunkBase; arenas are all free and may or may not be // committed. SetMemCheckKind(chunk, sizeof(ChunkBase), MemCheckKind::MakeUndefined); - chunk->initBaseForTenuredChunk(rt); - MOZ_ASSERT(chunk->unused()); + chunk->initBaseForArenaChunk(rt); + MOZ_ASSERT(chunk->isEmpty()); } else { - void* ptr = TenuredChunk::allocate(this); + void* ptr = ArenaChunk::allocate(this, stallAndRetry); if (!ptr) { return nullptr; } - chunk = TenuredChunk::emplace(ptr, this, /* allMemoryCommitted = */ true); - MOZ_ASSERT(chunk->info.numArenasFreeCommitted == 0); + chunk = ArenaChunk::emplace(ptr, this, /* allMemoryCommitted = */ true); + MOZ_ASSERT(chunk->isEmpty()); + emptyChunks(lock).push(chunk); } if (wantBackgroundAllocation(lock)) { @@ -611,9 +602,10 @@ TenuredChunk* GCRuntime::getOrAllocChunk(AutoLockGCBgAlloc& lock) { return chunk; } -void GCRuntime::recycleChunk(TenuredChunk* chunk, const AutoLockGC& lock) { +void GCRuntime::recycleChunk(ArenaChunk* chunk, const AutoLockGC& lock) { #ifdef DEBUG - MOZ_ASSERT(chunk->unused()); + MOZ_ASSERT(chunk->isEmpty()); + MOZ_ASSERT(!chunk->info.isCurrentChunk); chunk->verify(); #endif @@ -624,25 +616,24 @@ void GCRuntime::recycleChunk(TenuredChunk* chunk, const AutoLockGC& lock) { emptyChunks(lock).push(chunk); } -TenuredChunk* GCRuntime::pickChunk(AutoLockGCBgAlloc& lock) { +ArenaChunk* GCRuntime::pickChunk(StallAndRetry stallAndRetry, + AutoLockGCBgAlloc& lock) { if (availableChunks(lock).count()) { - return availableChunks(lock).head(); + ArenaChunk* chunk = availableChunks(lock).head(); + availableChunks(lock).remove(chunk); + return chunk; } - TenuredChunk* chunk = getOrAllocChunk(lock); + ArenaChunk* chunk = takeOrAllocChunk(stallAndRetry, lock); if (!chunk) { return nullptr; } #ifdef DEBUG chunk->verify(); - MOZ_ASSERT(chunk->unused()); - MOZ_ASSERT(!fullChunks(lock).contains(chunk)); - MOZ_ASSERT(!availableChunks(lock).contains(chunk)); + MOZ_ASSERT(chunk->isEmpty()); #endif - availableChunks(lock).push(chunk); - return chunk; } @@ -658,22 +649,22 @@ void BackgroundAllocTask::run(AutoLockHelperThreadState& lock) { AutoLockGC gcLock(gc); while (!isCancelled() && gc->wantBackgroundAllocation(gcLock)) { - TenuredChunk* chunk; + ArenaChunk* chunk; { AutoUnlockGC unlock(gcLock); - void* ptr = TenuredChunk::allocate(gc); + void* ptr = ArenaChunk::allocate(gc, StallAndRetry::No); if (!ptr) { break; } - chunk = TenuredChunk::emplace(ptr, gc, /* allMemoryCommitted = */ true); + chunk = ArenaChunk::emplace(ptr, gc, /* allMemoryCommitted = */ true); } chunkPool_.ref().push(chunk); } } /* static */ -void* TenuredChunk::allocate(GCRuntime* gc) { - void* chunk = MapAlignedPages(ChunkSize, ChunkSize); +void* ArenaChunk::allocate(GCRuntime* gc, StallAndRetry stallAndRetry) { + void* chunk = MapAlignedPages(ChunkSize, ChunkSize, stallAndRetry); if (!chunk) { return nullptr; } @@ -691,8 +682,8 @@ static inline bool ShouldDecommitNewChunk(bool allMemoryCommitted, return !allMemoryCommitted || !state.inHighFrequencyGCMode(); } -TenuredChunk* TenuredChunk::emplace(void* ptr, GCRuntime* gc, - bool allMemoryCommitted) { +ArenaChunk* ArenaChunk::emplace(void* ptr, GCRuntime* gc, + bool allMemoryCommitted) { /* The chunk may still have some regions marked as no-access. */ MOZ_MAKE_MEM_UNDEFINED(ptr, ChunkSize); @@ -702,30 +693,29 @@ TenuredChunk* TenuredChunk::emplace(void* ptr, GCRuntime* gc, */ Poison(ptr, JS_FRESH_TENURED_PATTERN, ChunkSize, MemCheckKind::MakeUndefined); - TenuredChunk* chunk = new (mozilla::KnownNotNull, ptr) TenuredChunk(gc->rt); + ArenaChunk* chunk = new (mozilla::KnownNotNull, ptr) ArenaChunk(gc->rt); if (ShouldDecommitNewChunk(allMemoryCommitted, gc->schedulingState)) { // Decommit the arenas. We do this after poisoning so that if the OS does // not have to recycle the pages, we still get the benefit of poisoning. chunk->decommitAllArenas(); } else { - // The chunk metadata is initialized as decommitted regardless, to avoid - // having to initialize the arenas at this time. - chunk->initAsDecommitted(); + chunk->initAsCommitted(); } + MOZ_ASSERT(chunk->isEmpty()); chunk->verify(); return chunk; } -void TenuredChunk::decommitAllArenas() { - MOZ_ASSERT(unused()); +void ArenaChunk::decommitAllArenas() { + MOZ_ASSERT(isEmpty()); MarkPagesUnusedSoft(&arenas[0], ArenasPerChunk * ArenaSize); initAsDecommitted(); } -void TenuredChunkBase::initAsDecommitted() { +void ArenaChunkBase::initAsDecommitted() { // Set the state of all arenas to free and decommitted. They might not // actually be decommitted, but in that case the re-commit operation is a // no-op so it doesn't matter. @@ -734,3 +724,13 @@ void TenuredChunkBase::initAsDecommitted() { info.numArenasFree = ArenasPerChunk; info.numArenasFreeCommitted = 0; } + +void ArenaChunkBase::initAsCommitted() { + // Set the state of all arenas to free and committed. They might have + // been decommitted, but in that case the re-commit operation is a + // no-op so it doesn't matter. + decommittedPages.ResetAll(); + freeCommittedArenas.SetAll(); + info.numArenasFree = ArenasPerChunk; + info.numArenasFreeCommitted = ArenasPerChunk; +} diff --git a/src/third_party/mozjs/extract/js/src/gc/Allocator.h b/src/third_party/mozjs/extract/js/src/gc/Allocator.h index 1b69a979866..e9e2ba574fc 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Allocator.h +++ b/src/third_party/mozjs/extract/js/src/gc/Allocator.h @@ -4,6 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// SpiderMonkey GC allocation API. + #ifndef gc_Allocator_h #define gc_Allocator_h @@ -13,6 +15,7 @@ #include "gc/AllocKind.h" #include "gc/GCEnum.h" +#include "js/HeapAPI.h" #include "js/TypeDecls.h" namespace js { @@ -20,6 +23,7 @@ namespace gc { class AllocSite; struct Cell; +class BufferAllocator; class TenuredCell; class TenuringTracer; @@ -49,27 +53,53 @@ class CellAllocator { // before calling any function that can potentially trigger GC. This will // ensure that GC tracing never sees junk values stored in the partially // initialized thing. - template + template static inline T* NewCell(JSContext* cx, Args&&... args); + friend class BufferAllocator; private: + // Allocate a string. Use cx->newCell([heap]). + // + // Use for nursery-allocatable strings. Returns a value cast to the correct + // type. Non-nursery-allocatable strings will go through the fallback + // tenured-only allocation path. + template + static T* NewString(JSContext* cx, Heap heap, Args&&... args); + + template + static T* NewBigInt(JSContext* cx, Heap heap); + + template + static T* NewObject(JSContext* cx, AllocKind kind, Heap heap, + const JSClass* clasp, AllocSite* site = nullptr); + + // Allocate all other kinds of GC thing. + template + static T* NewTenuredCell(JSContext* cx, Args&&... args); + + // Allocate a cell in the nursery, unless |heap| is Heap::Tenured or nursery + // allocation is disabled for |traceKind| in the current zone. + template + static void* AllocNurseryOrTenuredCell(JSContext* cx, AllocKind allocKind, + size_t thingSize, Heap heap, + AllocSite* site); + friend class TenuringTracer; + template static void* RetryNurseryAlloc(JSContext* cx, JS::TraceKind traceKind, AllocKind allocKind, size_t thingSize, AllocSite* site); template - static void* TryNewTenuredCell(JSContext* cx, AllocKind kind, - size_t thingSize); + static void* AllocTenuredCellForNurseryAlloc(JSContext* cx, AllocKind kind); -#if defined(DEBUG) || defined(JS_GC_ZEAL) || defined(JS_OOM_BREAKPOINT) + // Allocate a cell in the tenured heap. template - static bool PreAllocChecks(JSContext* cx, AllocKind kind); -#else + static void* AllocTenuredCell(JSContext* cx, AllocKind kind); + template - static bool PreAllocChecks(JSContext* cx, AllocKind kind) { - return true; - } -#endif + static void* AllocTenuredCellUnchecked(JS::Zone* zone, AllocKind kind); + + static void* RetryTenuredAlloc(JS::Zone* zone, AllocKind kind); #ifdef JS_GC_ZEAL static AllocSite* MaybeGenerateMissingAllocSite(JSContext* cx, @@ -78,43 +108,39 @@ class CellAllocator { #endif #ifdef DEBUG - static void CheckIncrementalZoneState(JSContext* cx, void* ptr); + static void CheckIncrementalZoneState(JS::Zone* zone, void* ptr); #endif - static inline gc::Heap CheckedHeap(gc::Heap heap); - - // Allocate a cell in the nursery, unless |heap| is Heap::Tenured or nursery - // allocation is disabled for |traceKind| in the current zone. - template - static void* AllocNurseryOrTenuredCell(JSContext* cx, gc::AllocKind allocKind, - size_t thingSize, gc::Heap heap, - AllocSite* site); - friend class TenuringTracer; - - // Allocate a cell in the tenured heap. - template - static void* AllocTenuredCell(JSContext* cx, gc::AllocKind kind, size_t size); - - // Allocate a string. Use cx->newCell([heap]). - // - // Use for nursery-allocatable strings. Returns a value cast to the correct - // type. Non-nursery-allocatable strings will go through the fallback - // tenured-only allocation path. - template - static T* NewString(JSContext* cx, gc::Heap heap, Args&&... args); - - template - static T* NewBigInt(JSContext* cx, Heap heap); - - template - static T* NewObject(JSContext* cx, gc::AllocKind kind, gc::Heap heap, - const JSClass* clasp, gc::AllocSite* site = nullptr); - - // Allocate all other kinds of GC thing. - template - static T* NewTenuredCell(JSContext* cx, Args&&... args); + static inline Heap CheckedHeap(Heap heap); }; +// Buffer allocator public API. + +size_t GetGoodAllocSize(size_t requiredBytes); +size_t GetGoodPower2AllocSize(size_t requiredBytes); +size_t GetGoodElementCount(size_t requiredCount, size_t elementSize); +size_t GetGoodPower2ElementCount(size_t requiredCount, size_t elementSize); +void* AllocBuffer(JS::Zone* zone, size_t bytes, bool nurseryOwned); +void* ReallocBuffer(JS::Zone* zone, void* alloc, size_t bytes, + bool nurseryOwned); +void FreeBuffer(JS::Zone* zone, void* alloc); + +// Indicate whether |alloc| is a buffer allocation as opposed to a fixed size GC +// cell. Does not work for malloced memory. +bool IsBufferAlloc(void* alloc); + +bool IsNurseryOwned(JS::Zone* zone, void* alloc); + +size_t GetAllocSize(JS::Zone* zone, void* alloc); + +// Buffer allocator GC-internal API. + +void* AllocBufferInGC(JS::Zone* zone, size_t bytes, bool nurseryOwned); +bool IsBufferAllocMarkedBlack(JS::Zone* zone, void* alloc); +void TraceBufferEdgeInternal(JSTracer* trc, Cell* owner, void** bufferp, + const char* name); +void MarkTenuredBuffer(JS::Zone* zone, void* alloc); + } // namespace gc } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/gc/ArenaList-inl.h b/src/third_party/mozjs/extract/js/src/gc/ArenaList-inl.h index 06e7d9f3d97..083418a4094 100644 --- a/src/third_party/mozjs/extract/js/src/gc/ArenaList-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/ArenaList-inl.h @@ -12,142 +12,18 @@ #include "gc/Heap.h" #include "gc/Zone.h" -inline js::gc::ArenaList::ArenaList() { clear(); } - -inline js::gc::ArenaList::ArenaList(ArenaList&& other) { moveFrom(other); } - -inline js::gc::ArenaList::~ArenaList() { MOZ_ASSERT(isEmpty()); } - -void js::gc::ArenaList::moveFrom(ArenaList& other) { - other.check(); - - head_ = other.head_; - cursorp_ = other.isCursorAtHead() ? &head_ : other.cursorp_; - other.clear(); - - check(); +bool js::gc::ArenaList::hasNonFullArenas() const { + // Non-full arenas are kept at the start so we can check the first one. + return !isEmpty() && !first()->isFull(); } -js::gc::ArenaList& js::gc::ArenaList::operator=(ArenaList&& other) { - MOZ_ASSERT(isEmpty()); - moveFrom(other); - return *this; -} - -inline js::gc::ArenaList::ArenaList(Arena* head, Arena* arenaBeforeCursor) - : head_(head), - cursorp_(arenaBeforeCursor ? &arenaBeforeCursor->next : &head_) { - check(); -} - -// This does checking just of |head_| and |cursorp_|. -void js::gc::ArenaList::check() const { -#ifdef DEBUG - // If the list is empty, it must have this form. - MOZ_ASSERT_IF(!head_, cursorp_ == &head_); - - // If there's an arena following the cursor, it must not be full. - Arena* cursor = *cursorp_; - MOZ_ASSERT_IF(cursor, cursor->hasFreeThings()); -#endif -} - -void js::gc::ArenaList::clear() { - head_ = nullptr; - cursorp_ = &head_; - check(); -} - -bool js::gc::ArenaList::isEmpty() const { - check(); - return !head_; -} - -js::gc::Arena* js::gc::ArenaList::head() const { - check(); - return head_; -} - -bool js::gc::ArenaList::isCursorAtHead() const { - check(); - return cursorp_ == &head_; -} - -bool js::gc::ArenaList::isCursorAtEnd() const { - check(); - return !*cursorp_; -} - -js::gc::Arena* js::gc::ArenaList::arenaAfterCursor() const { - check(); - return *cursorp_; -} - -js::gc::Arena* js::gc::ArenaList::takeNextArena() { - check(); - Arena* arena = *cursorp_; - if (!arena) { - return nullptr; - } - cursorp_ = &arena->next; - check(); - return arena; -} - -void js::gc::ArenaList::insertAtCursor(Arena* a) { - check(); - a->next = *cursorp_; - *cursorp_ = a; - // At this point, the cursor is sitting before |a|. Move it after |a| - // if necessary. - if (!a->hasFreeThings()) { - cursorp_ = &a->next; - } - check(); -} - -void js::gc::ArenaList::insertBeforeCursor(Arena* a) { - check(); - a->next = *cursorp_; - *cursorp_ = a; - cursorp_ = &a->next; - check(); -} - -js::gc::ArenaList& js::gc::ArenaList::insertListWithCursorAtEnd( - ArenaList& other) { - check(); - other.check(); - MOZ_ASSERT(other.isCursorAtEnd()); - - if (other.isEmpty()) { - return *this; - } - - // Insert the full arenas of |other| after those of |this|. - *other.cursorp_ = *cursorp_; - *cursorp_ = other.head_; - cursorp_ = other.cursorp_; - check(); - - other.clear(); - return *this; -} - -js::gc::Arena* js::gc::ArenaList::takeFirstArena() { - check(); - Arena* arena = head_; - if (!arena) { +js::gc::Arena* js::gc::ArenaList::takeInitialNonFullArena() { + Arena* arena = first(); + if (!arena || arena->isFull()) { return nullptr; } - head_ = arena->next; - arena->next = nullptr; - if (cursorp_ == &arena->next) { - cursorp_ = &head_; - } - - check(); + moveFrontToBack(); return arena; } @@ -213,8 +89,13 @@ void js::gc::SortedArenaList::insertAt(Arena* arena, size_t nfree) { } } +bool js::gc::SortedArenaList::hasEmptyArenas() const { + return !buckets[emptyIndex()].isEmpty(); +} + void js::gc::SortedArenaList::extractEmptyTo(Arena** destListHeadPtr) { MOZ_ASSERT(!isConvertedToArenaList); + MOZ_ASSERT(destListHeadPtr); check(); Bucket& bucket = buckets[emptyIndex()]; @@ -242,16 +123,15 @@ js::gc::ArenaList js::gc::SortedArenaList::convertToArenaList( } } - // The cursor of the returned ArenaList needs to be between the last full - // arena and the first arena with space. Record that here. - Arena* lastFullArena = buckets[0].last(); - - Bucket result; - for (size_t i = 0; i < bucketsUsed(); ++i) { - result.append(std::move(buckets[i])); + // The returned ArenaList needs to contain all non-full arenas in order + // of increasing free space, followed by all full arenas. + ArenaList result; + size_t used = bucketsUsed(); + for (size_t i = 1; i <= used; ++i) { + size_t bucket = i % used; // [1, used) then 0. + result.append(std::move(buckets[bucket])); } - - return ArenaList(result.release(), lastFullArena); + return result; } void js::gc::SortedArenaList::restoreFromArenaList( @@ -264,20 +144,23 @@ void js::gc::SortedArenaList::restoreFromArenaList( // Group the ArenaList elements into SinglyLinkedList buckets, where the // boundaries between buckets are retrieved from |bucketLast|. - Arena* remaining = list.head(); - list.clear(); + Arena* remaining = list.release(); - for (size_t i = 0; i < bucketsUsed(); i++) { - MOZ_ASSERT(buckets[i].isEmpty()); - if (bucketLast[i]) { + size_t used = bucketsUsed(); + for (size_t i = 1; i <= used; ++i) { + size_t bucket = i % used; // [1, used) then 0. + MOZ_ASSERT(buckets[bucket].isEmpty()); + if (bucketLast[bucket]) { + MOZ_ASSERT(remaining); Arena* first = remaining; - Arena* last = bucketLast[i]; + Arena* last = bucketLast[bucket]; remaining = last->next; last->next = nullptr; - new (&buckets[i]) Bucket(first, last); + new (&buckets[bucket]) Bucket(first, last); } } + MOZ_ASSERT(!remaining); check(); } @@ -362,17 +245,12 @@ JSRuntime* js::gc::ArenaLists::runtimeFromAnyThread() { } js::gc::Arena* js::gc::ArenaLists::getFirstArena(AllocKind thingKind) const { - return arenaList(thingKind).head(); + return arenaList(thingKind).first(); } js::gc::Arena* js::gc::ArenaLists::getFirstCollectingArena( AllocKind thingKind) const { - return collectingArenaList(thingKind).head(); -} - -js::gc::Arena* js::gc::ArenaLists::getArenaAfterCursor( - AllocKind thingKind) const { - return arenaList(thingKind).arenaAfterCursor(); + return collectingArenaList(thingKind).first(); } bool js::gc::ArenaLists::arenaListsAreEmpty() const { @@ -392,11 +270,7 @@ bool js::gc::ArenaLists::arenaListsAreEmpty() const { } bool js::gc::ArenaLists::doneBackgroundFinalize(AllocKind kind) const { - return concurrentUse(kind) != ConcurrentUse::BackgroundFinalize; -} - -bool js::gc::ArenaLists::needBackgroundFinalizeWait(AllocKind kind) const { - return concurrentUse(kind) == ConcurrentUse::BackgroundFinalize; + return concurrentUse(kind) == ConcurrentUse::None; } void js::gc::ArenaLists::clearFreeLists() { freeLists().clear(); } diff --git a/src/third_party/mozjs/extract/js/src/gc/ArenaList.h b/src/third_party/mozjs/extract/js/src/gc/ArenaList.h index cbde5118b18..c78cb9baa1c 100644 --- a/src/third_party/mozjs/extract/js/src/gc/ArenaList.h +++ b/src/third_party/mozjs/extract/js/src/gc/ArenaList.h @@ -11,17 +11,23 @@ #ifndef gc_ArenaList_h #define gc_ArenaList_h +#include + #include "ds/SinglyLinkedList.h" #include "gc/AllocKind.h" +#include "gc/Memory.h" #include "js/GCAPI.h" #include "js/HeapAPI.h" #include "js/TypeDecls.h" #include "threading/ProtectedData.h" +namespace JS { +class SliceBudget; +} + namespace js { class Nursery; -class SliceBudget; namespace gcstats { struct Statistics; @@ -30,6 +36,8 @@ struct Statistics; namespace gc { class Arena; +class ArenaIter; +class ArenaIterInGC; class AutoGatherSweptArenas; class BackgroundUnmarkTask; struct FinalizePhase; @@ -37,17 +45,34 @@ class FreeSpan; class TenuredCell; class TenuringTracer; +// Whether or not to release empty arenas while sweeping. +enum class ReleaseEmpty : bool { No = false, Yes = true }; + /* - * Arena lists contain a singly linked lists of arenas starting from a head - * pointer. + * Arena lists contain a singly linked lists of arenas. * - * They also have a cursor, which conceptually lies on arena boundaries, - * i.e. before the first arena, between two arenas, or after the last arena. + * Arenas with free space are positioned at the front of the list, sorted in + * order of increasing free space (which is the order we intend to use them): * - * Arenas are sorted in order of increasing free space, with the cursor before - * the first arena with any free space. This provides a convenient way of - * getting the next arena with free space when allocating. The cursor is updated - * when this happens to point to the following arena. + * For example, the following shows a possible arrangement of arenas with count + * of used cells on Y axis: + * + * | +----+----+----+----+----+ + * | | | | | | | + * | | | | | | | + * +----+----+ | | | | | | + * | | +----+ | | | | | | + * | | | +----+ | | | | | | + * | | | | | | | | | | | + * | | | | +----+ | | | | | | + * | | | | | | | | | | | | + * | | | | | +----+----+ | | | | | | + * | | | | | | | +----+ | | | | | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * This provides a convenient way of getting the next arena with free space when + * allocating: the arena at the front of the list is taken, marked as fully + * allocated and moved to the end of the list. * * The ordering is chosen to try and fill up arenas as much as possible and * leave more empty arenas to be reclaimed when their contents die. @@ -56,85 +81,21 @@ class TenuringTracer; * lists may be cleared, leaving arenas previously used for allocation partially * full. Sorting order is restored during sweeping. */ -class ArenaList { - // The cursor is implemented via an indirect pointer, |cursorp_|, to allow - // for efficient list insertion at the cursor point and other list - // manipulations. - // - // - If the list is empty: |head| is null, |cursorp_| points to |head|, and - // therefore |*cursorp_| is null. - // - // - If the list is not empty: |head| is non-null, and... - // - // - If the cursor is at the start of the list: |cursorp_| points to - // |head|, and therefore |*cursorp_| points to the first arena. - // - // - If cursor is at the end of the list: |cursorp_| points to the |next| - // field of the last arena, and therefore |*cursorp_| is null. - // - // - If the cursor is at neither the start nor the end of the list: - // |cursorp_| points to the |next| field of the arena preceding the - // cursor, and therefore |*cursorp_| points to the arena following the - // cursor. - // - // |cursorp_| is never null. - // - Arena* head_; - Arena** cursorp_; - - // Transfers the contents of |other| to this list and clears |other|. - inline void moveFrom(ArenaList& other); - +class ArenaList : public SinglyLinkedList { public: - inline ArenaList(); - inline ArenaList(ArenaList&& other); - inline ~ArenaList(); + inline bool hasNonFullArenas() const; - inline ArenaList& operator=(ArenaList&& other); + // This returns the first arena if it has any free space, moving it to the + // back of the list. If there are no arenas or if the first one is full then + // return nullptr. + inline Arena* takeInitialNonFullArena(); - // It doesn't make sense for arenas to be present in more than one list, so - // list copy operations are not provided. - ArenaList(const ArenaList& other) = delete; - ArenaList& operator=(const ArenaList& other) = delete; + std::pair pickArenasToRelocate(AllocKind kind, + size_t& arenaTotalOut, + size_t& relocTotalOut); - inline ArenaList(Arena* head, Arena* arenaBeforeCursor); - - inline void check() const; - - inline void clear(); - inline bool isEmpty() const; - - // This returns nullptr if the list is empty. - inline Arena* head() const; - - inline bool isCursorAtHead() const; - inline bool isCursorAtEnd() const; - - // This can return nullptr. - inline Arena* arenaAfterCursor() const; - - // This returns the arena after the cursor and moves the cursor past it. - inline Arena* takeNextArena(); - - // This does two things. - // - Inserts |a| at the cursor. - // - Leaves the cursor sitting just before |a|, if |a| is not full, or just - // after |a|, if |a| is full. - inline void insertAtCursor(Arena* a); - - // Inserts |a| at the cursor, then moves the cursor past it. - inline void insertBeforeCursor(Arena* a); - - // This inserts the contents of |other|, which must be full, at the cursor of - // |this| and clears |other|. - inline ArenaList& insertListWithCursorAtEnd(ArenaList& other); - - inline Arena* takeFirstArena(); - - Arena* removeRemainingArenas(Arena** arenap); - Arena** pickArenasToRelocate(size_t& arenaTotalOut, size_t& relocTotalOut); Arena* relocateArenas(Arena* toRelocate, Arena* relocated, - js::SliceBudget& sliceBudget, + JS::SliceBudget& sliceBudget, gcstats::Statistics& stats); #ifdef DEBUG @@ -188,6 +149,8 @@ class SortedArenaList { // Inserts an arena, which has room for |nfree| more things, in its bucket. inline void insertAt(Arena* arena, size_t nfree); + inline bool hasEmptyArenas() const; + // Remove any empty arenas and prepend them to the list pointed to by // |destListHeadPtr|. inline void extractEmptyTo(Arena** destListHeadPtr); @@ -233,7 +196,7 @@ class MOZ_RAII AutoGatherSweptArenas { AutoGatherSweptArenas(JS::Zone* zone, AllocKind kind); ~AutoGatherSweptArenas(); - Arena* sweptArenas() const; + ArenaList& sweptArenas() { return linked; } }; enum class ShouldCheckThresholds { @@ -278,10 +241,13 @@ class FreeLists { }; class ArenaLists { - enum class ConcurrentUse : uint32_t { None, BackgroundFinalize }; + enum class ConcurrentUse : uint32_t { + None, + BackgroundFinalize, + BackgroundFinalizeFinished + }; - using ConcurrentUseState = - mozilla::Atomic; + using ConcurrentUseState = mozilla::Atomic; JS::Zone* zone_; @@ -321,12 +287,10 @@ class ArenaLists { inline Arena* getFirstArena(AllocKind thingKind) const; inline Arena* getFirstCollectingArena(AllocKind thingKind) const; - inline Arena* getArenaAfterCursor(AllocKind thingKind) const; inline bool arenaListsAreEmpty() const; inline bool doneBackgroundFinalize(AllocKind kind) const; - inline bool needBackgroundFinalizeWait(AllocKind kind) const; /* Clear the free lists so we won't try to allocate from swept arenas. */ inline void clearFreeLists(); @@ -342,15 +306,23 @@ class ArenaLists { void checkEmptyArenaList(AllocKind kind); bool relocateArenas(Arena*& relocatedListOut, JS::GCReason reason, - js::SliceBudget& sliceBudget, gcstats::Statistics& stats); + JS::SliceBudget& sliceBudget, gcstats::Statistics& stats); void queueForegroundObjectsForSweep(JS::GCContext* gcx); void queueForegroundThingsForSweep(); + bool foregroundFinalize(JS::GCContext* gcx, AllocKind thingKind, + JS::SliceBudget& sliceBudget, + SortedArenaList& sweepList); + template + void backgroundFinalize(JS::GCContext* gcx, AllocKind kind, + Arena** empty = nullptr); + Arena* takeSweptEmptyArenas(); - void mergeFinalizedArenas(AllocKind thingKind, - SortedArenaList& finalizedArenas); + void mergeBackgroundSweptArenas(); + void maybeMergeSweptArenas(AllocKind thingKind); + void mergeSweptArenas(AllocKind thingKind, ArenaList& sweptArenas); void moveArenasToCollectingLists(); void mergeArenasFromCollectingLists(); @@ -384,8 +356,11 @@ class ArenaLists { void initBackgroundSweep(AllocKind thingKind); void* refillFreeListAndAllocate(AllocKind thingKind, - ShouldCheckThresholds checkThresholds); + ShouldCheckThresholds checkThresholds, + StallAndRetry stallAndRetry); + friend class ArenaIter; + friend class ArenaIterInGC; friend class BackgroundUnmarkTask; friend class GCRuntime; friend class js::Nursery; diff --git a/src/third_party/mozjs/extract/js/src/gc/AtomMarking.cpp b/src/third_party/mozjs/extract/js/src/gc/AtomMarking.cpp index a5b7eb1acf4..932906f700e 100644 --- a/src/third_party/mozjs/extract/js/src/gc/AtomMarking.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/AtomMarking.cpp @@ -8,6 +8,7 @@ #include +#include "gc/GCLock.h" #include "gc/PublicIterators.h" #include "gc/GC-inl.h" @@ -47,29 +48,61 @@ namespace gc { // bits for space between things being unused when things are larger than a // single Cell. -void AtomMarkingRuntime::registerArena(Arena* arena, const AutoLockGC& lock) { - MOZ_ASSERT(arena->getThingSize() != 0); - MOZ_ASSERT(arena->getThingSize() % CellAlignBytes == 0); - MOZ_ASSERT(arena->zone->isAtomsZone()); - +size_t AtomMarkingRuntime::allocateIndex(GCRuntime* gc) { // We need to find a range of bits from the atoms bitmap for this arena. + // Try to merge background swept free indexes if necessary. + if (freeArenaIndexes.ref().empty()) { + mergePendingFreeArenaIndexes(gc); + } + // Look for a free range of bits compatible with this arena. - if (freeArenaIndexes.ref().length()) { - arena->atomBitmapStart() = freeArenaIndexes.ref().popCopy(); - return; + if (!freeArenaIndexes.ref().empty()) { + return freeArenaIndexes.ref().popCopy(); } // Allocate a range of bits from the end for this arena. - arena->atomBitmapStart() = allocatedWords; + size_t index = allocatedWords; allocatedWords += ArenaBitmapWords; + return index; } -void AtomMarkingRuntime::unregisterArena(Arena* arena, const AutoLockGC& lock) { - MOZ_ASSERT(arena->zone->isAtomsZone()); +void AtomMarkingRuntime::freeIndex(size_t index, const AutoLockGC& lock) { + MOZ_ASSERT((index % ArenaBitmapWords) == 0); + MOZ_ASSERT(index < allocatedWords); + + bool wasEmpty = pendingFreeArenaIndexes.ref().empty(); + MOZ_ASSERT_IF(wasEmpty, !hasPendingFreeArenaIndexes); + + if (!pendingFreeArenaIndexes.ref().append(index)) { + // Leak these atom bits if we run out of memory. + return; + } + + if (wasEmpty) { + hasPendingFreeArenaIndexes = true; + } +} + +void AtomMarkingRuntime::mergePendingFreeArenaIndexes(GCRuntime* gc) { + MOZ_ASSERT(CurrentThreadCanAccessRuntime(gc->rt)); + if (!hasPendingFreeArenaIndexes) { + return; + } + + AutoLockGC lock(gc); + MOZ_ASSERT(!pendingFreeArenaIndexes.ref().empty()); + + hasPendingFreeArenaIndexes = false; + + if (freeArenaIndexes.ref().empty()) { + std::swap(freeArenaIndexes.ref(), pendingFreeArenaIndexes.ref()); + return; + } // Leak these atom bits if we run out of memory. - (void)freeArenaIndexes.ref().emplaceBack(arena->atomBitmapStart()); + (void)freeArenaIndexes.ref().appendAll(pendingFreeArenaIndexes.ref()); + pendingFreeArenaIndexes.ref().clear(); } void AtomMarkingRuntime::refineZoneBitmapsForCollectedZones( @@ -307,7 +340,7 @@ bool AtomMarkingRuntime::valueIsMarked(Zone* zone, const Value& value) { return atomIsMarked(zone, value.toSymbol()); } - MOZ_ASSERT_IF(value.isGCThing(), value.hasObjectPayload() || + MOZ_ASSERT_IF(value.isGCThing(), value.isObject() || value.isPrivateGCThing() || value.isBigInt()); return true; diff --git a/src/third_party/mozjs/extract/js/src/gc/AtomMarking.h b/src/third_party/mozjs/extract/js/src/gc/AtomMarking.h index e5d8ef84185..7b08a96418d 100644 --- a/src/third_party/mozjs/extract/js/src/gc/AtomMarking.h +++ b/src/third_party/mozjs/extract/js/src/gc/AtomMarking.h @@ -7,6 +7,8 @@ #ifndef gc_AtomMarking_h #define gc_AtomMarking_h +#include "mozilla/Atomics.h" + #include "NamespaceImports.h" #include "js/Vector.h" #include "threading/ProtectedData.h" @@ -24,8 +26,12 @@ class GCRuntime; // This class manages state used for marking atoms during GCs. // See AtomMarking.cpp for details. class AtomMarkingRuntime { - // Unused arena atom bitmap indexes. Protected by the GC lock. - js::GCLockData> freeArenaIndexes; + // Unused arena atom bitmap indexes. + js::MainThreadData> freeArenaIndexes; + + // Background sweep state for |freeArenaIndexes|. + js::GCLockData> pendingFreeArenaIndexes; + mozilla::Atomic hasPendingFreeArenaIndexes; inline void markChildren(JSContext* cx, JSAtom*); inline void markChildren(JSContext* cx, JS::Symbol* symbol); @@ -37,11 +43,13 @@ class AtomMarkingRuntime { AtomMarkingRuntime() : allocatedWords(0) {} - // Mark an arena as holding things in the atoms zone. - void registerArena(Arena* arena, const AutoLockGC& lock); + // Allocate an index in the atom marking bitmap for a new arena. + size_t allocateIndex(GCRuntime* gc); - // Mark an arena as no longer holding things in the atoms zone. - void unregisterArena(Arena* arena, const AutoLockGC& lock); + // Free an index in the atom marking bitmap. + void freeIndex(size_t index, const AutoLockGC& lock); + + void mergePendingFreeArenaIndexes(GCRuntime* gc); // Update the atom marking bitmaps in all collected zones according to the // atoms zone mark bits. diff --git a/src/third_party/mozjs/extract/js/src/gc/Barrier.cpp b/src/third_party/mozjs/extract/js/src/gc/Barrier.cpp index 36fb3f6caef..8ab0f862c24 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Barrier.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Barrier.cpp @@ -60,11 +60,20 @@ void HeapSlot::assertPreconditionForPostWriteBarrier( } } +bool CurrentThreadIsBaselineCompiling() { + jit::JitContext* jcx = jit::MaybeGetJitContext(); + return jcx && jcx->inBaselineBackend(); +} + bool CurrentThreadIsIonCompiling() { jit::JitContext* jcx = jit::MaybeGetJitContext(); return jcx && jcx->inIonBackend(); } +bool CurrentThreadIsOffThreadCompiling() { + return CurrentThreadIsBaselineCompiling() || CurrentThreadIsIonCompiling(); +} + #endif // DEBUG #if !MOZ_IS_GCC @@ -74,8 +83,6 @@ template struct JS_PUBLIC_API StableCellHasher; } // namespace js -// Post-write barrier, used by the C++ Heap implementation. - JS_PUBLIC_API void JS::HeapObjectPostWriteBarrier(JSObject** objp, JSObject* prev, JSObject* next) { @@ -83,28 +90,7 @@ JS_PUBLIC_API void JS::HeapObjectPostWriteBarrier(JSObject** objp, js::InternalBarrierMethods::postBarrier(objp, prev, next); } -JS_PUBLIC_API void JS::HeapStringPostWriteBarrier(JSString** strp, - JSString* prev, - JSString* next) { - MOZ_ASSERT(strp); - js::InternalBarrierMethods::postBarrier(strp, prev, next); -} - -JS_PUBLIC_API void JS::HeapBigIntPostWriteBarrier(JS::BigInt** bip, - JS::BigInt* prev, - JS::BigInt* next) { - MOZ_ASSERT(bip); - js::InternalBarrierMethods::postBarrier(bip, prev, next); -} - -JS_PUBLIC_API void JS::HeapValuePostWriteBarrier(JS::Value* valuep, - const Value& prev, - const Value& next) { - MOZ_ASSERT(valuep); - js::InternalBarrierMethods::postBarrier(valuep, prev, next); -} - -// Combined pre- and post-write barriers, used by the rust Heap +// Combined pre- and post-write barriers, used by the C++ Heap // implementation. JS_PUBLIC_API void JS::HeapObjectWriteBarriers(JSObject** objp, JSObject* prev, diff --git a/src/third_party/mozjs/extract/js/src/gc/Barrier.h b/src/third_party/mozjs/extract/js/src/gc/Barrier.h index 7669611d1c0..20d90ca4be8 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Barrier.h +++ b/src/third_party/mozjs/extract/js/src/gc/Barrier.h @@ -290,7 +290,7 @@ * * Barriers for use outside of the JS engine call into the same barrier * implementations at InternalBarrierMethods::post via an indirect call to - * Heap(.+)PostWriteBarrier. + * Heap(.+)WriteBarriers. * * These clases are designed to be used to wrap GC thing pointers or values that * act like them (i.e. JS::Value and jsid). It is possible to use them for @@ -364,7 +364,7 @@ struct InternalBarrierMethods { namespace gc { MOZ_ALWAYS_INLINE void ValuePostWriteBarrier(Value* vp, const Value& prev, const Value& next) { - MOZ_ASSERT(!CurrentThreadIsIonCompiling()); + MOZ_ASSERT(!CurrentThreadIsOffThreadCompiling()); MOZ_ASSERT(vp); // If the target needs an entry, add it. @@ -617,11 +617,13 @@ class GCPtr : public WriteBarriered { #ifdef DEBUG ~GCPtr() { - // No barriers are necessary as this only happens when the GC is sweeping. + // No barriers are necessary as this only happens when the GC is sweeping or + // before this has been initialized (see above comment). // // If this assertion fails you may need to make the containing object use a // HeapPtr instead, as this can be deleted from outside of GC. - MOZ_ASSERT(CurrentThreadIsGCSweeping() || CurrentThreadIsGCFinalizing()); + MOZ_ASSERT(CurrentThreadIsGCSweeping() || CurrentThreadIsGCFinalizing() || + this->value == JS::SafelyInitialized::create()); Poison(this, JS_FREED_HEAP_PTR_PATTERN, sizeof(*this), MemCheckKind::MakeNoAccess); @@ -769,7 +771,7 @@ template class GCStructPtr : public BarrieredBase { public: // This is sometimes used to hold tagged pointers. - static constexpr uintptr_t MaxTaggedPointer = 0x2; + static constexpr uintptr_t MaxTaggedPointer = 0x5; GCStructPtr() : BarrieredBase(JS::SafelyInitialized::create()) {} diff --git a/src/third_party/mozjs/extract/js/src/gc/BufferAllocator-inl.h b/src/third_party/mozjs/extract/js/src/gc/BufferAllocator-inl.h new file mode 100644 index 00000000000..4c05b41936f --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/gc/BufferAllocator-inl.h @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef gc_BufferAllocator_inl_h +#define gc_BufferAllocator_inl_h + +#include "gc/BufferAllocator.h" + +#include "mozilla/Atomics.h" +#include "mozilla/MathAlgorithms.h" + +#include "ds/SlimLinkedList.h" +#include "gc/Cell.h" +#include "js/HeapAPI.h" + +#include "gc/Allocator-inl.h" + +namespace js::gc { + +// todo: rename +static constexpr size_t MinAllocSize = MinCellSize; // 16 bytes + +static constexpr size_t MaxSmallAllocSize = + 1 << (BufferAllocator::MinMediumAllocShift - 1); +static constexpr size_t MinMediumAllocSize = + 1 << BufferAllocator::MinMediumAllocShift; +static constexpr size_t MaxMediumAllocSize = + 1 << BufferAllocator::MaxMediumAllocShift; + +/* static */ +inline bool BufferAllocator::IsSmallAllocSize(size_t bytes) { + return bytes <= MaxSmallAllocSize; +} + +/* static */ +inline bool BufferAllocator::IsLargeAllocSize(size_t bytes) { + return bytes > MaxMediumAllocSize; +} + +/* static */ +inline size_t BufferAllocator::GetGoodAllocSize(size_t requiredBytes) { + requiredBytes = std::max(requiredBytes, MinAllocSize); + + if (IsLargeAllocSize(requiredBytes)) { + return RoundUp(requiredBytes, ChunkSize); + } + + // TODO: Support more sizes than powers of 2 + return mozilla::RoundUpPow2(requiredBytes); +} + +/* static */ +size_t BufferAllocator::GetGoodPower2AllocSize(size_t requiredBytes) { + requiredBytes = std::max(requiredBytes, MinAllocSize); + + return mozilla::RoundUpPow2(requiredBytes); +} + +/* static */ +size_t BufferAllocator::GetGoodElementCount(size_t requiredElements, + size_t elementSize) { + size_t requiredBytes = requiredElements * elementSize; + size_t goodSize = GetGoodAllocSize(requiredBytes); + return goodSize / elementSize; +} + +/* static */ +size_t BufferAllocator::GetGoodPower2ElementCount(size_t requiredElements, + size_t elementSize) { + size_t requiredBytes = requiredElements * elementSize; + size_t goodSize = GetGoodPower2AllocSize(requiredBytes); + return goodSize / elementSize; +} + +inline size_t GetGoodAllocSize(size_t requiredBytes) { + return BufferAllocator::GetGoodAllocSize(requiredBytes); +} + +inline size_t GetGoodElementCount(size_t requiredCount, size_t elementSize) { + return BufferAllocator::GetGoodElementCount(requiredCount, elementSize); +} + +inline size_t GetGoodPower2AllocSize(size_t requiredBytes) { + return BufferAllocator::GetGoodPower2AllocSize(requiredBytes); +} + +inline size_t GetGoodPower2ElementCount(size_t requiredCount, + size_t elementSize) { + return BufferAllocator::GetGoodPower2ElementCount(requiredCount, elementSize); +} + +inline void* AllocBuffer(JS::Zone* zone, size_t bytes, bool nurseryOwned) { + if (js::oom::ShouldFailWithOOM()) { + return nullptr; + } + + return zone->bufferAllocator.alloc(bytes, nurseryOwned); +} + +inline void* AllocBufferInGC(JS::Zone* zone, size_t bytes, bool nurseryOwned) { + return zone->bufferAllocator.allocInGC(bytes, nurseryOwned); +} + +inline void* ReallocBuffer(JS::Zone* zone, void* alloc, size_t bytes, + bool nurseryOwned) { + if (js::oom::ShouldFailWithOOM()) { + return nullptr; + } + + return zone->bufferAllocator.realloc(alloc, bytes, nurseryOwned); +} + +inline void FreeBuffer(JS::Zone* zone, void* alloc) { + return zone->bufferAllocator.free(alloc); +} + +inline bool IsBufferAlloc(void* alloc) { + return BufferAllocator::IsBufferAlloc(alloc); +} + +inline size_t GetAllocSize(JS::Zone* zone, void* alloc) { + return zone->bufferAllocator.getAllocSize(alloc); +} + +inline bool IsNurseryOwned(JS::Zone* zone, void* alloc) { + return zone->bufferAllocator.isNurseryOwned(alloc); +} + +inline bool IsBufferAllocMarkedBlack(JS::Zone* zone, void* alloc) { + return zone->bufferAllocator.isMarkedBlack(alloc); +} + +inline void TraceBufferEdgeInternal(JSTracer* trc, Cell* owner, void** bufferp, + const char* name) { + owner->zoneFromAnyThread()->bufferAllocator.traceEdge(trc, owner, bufferp, + name); +} + +inline void MarkTenuredBuffer(JS::Zone* zone, void* alloc) { + zone->bufferAllocator.markTenuredAlloc(alloc); +} + +} // namespace js::gc + +#endif // gc_BufferAllocator_inl_h diff --git a/src/third_party/mozjs/extract/js/src/gc/BufferAllocator.cpp b/src/third_party/mozjs/extract/js/src/gc/BufferAllocator.cpp new file mode 100644 index 00000000000..b36e9173725 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/gc/BufferAllocator.cpp @@ -0,0 +1,2822 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gc/BufferAllocator-inl.h" + +#include "mozilla/PodOperations.h" +#include "mozilla/ScopeExit.h" + +#ifdef XP_DARWIN +# include +# include +#endif + +#include "gc/GCInternals.h" +#include "gc/GCLock.h" +#include "gc/PublicIterators.h" +#include "gc/Zone.h" +#include "js/HeapAPI.h" +#include "util/Poison.h" + +#include "gc/Heap-inl.h" +#include "gc/Marking-inl.h" + +using namespace js; +using namespace js::gc; + +namespace js::gc { + +struct alignas(CellAlignBytes) LargeBuffer + : public SlimLinkedListElement { + void* alloc; + size_t bytes; + bool isNurseryOwned; + bool allocatedDuringCollection = false; + +#ifdef DEBUG + uint32_t checkValue = LargeBufferCheckValue; +#endif + + LargeBuffer(void* alloc, size_t bytes, bool nurseryOwned) + : alloc(alloc), bytes(bytes), isNurseryOwned(nurseryOwned) { + MOZ_ASSERT((bytes % ChunkSize) == 0); + } + + inline void check() const; + + inline SmallBuffer* headerCell(); + +#ifdef DEBUG + inline Zone* zone(); + inline Zone* zoneFromAnyThread(); +#endif + + void* data() { return alloc; } + size_t allocBytes() const { return bytes; } + bool isPointerWithinAllocation(void* ptr) const; +}; + +bool SmallBuffer::isNurseryOwned() const { + return header_.get() & NURSERY_OWNED_BIT; +} + +void SmallBuffer::setNurseryOwned(bool value) { + header_.set(value ? NURSERY_OWNED_BIT : 0); +} + +size_t SmallBuffer::allocBytes() const { + return arena()->getThingSize() - sizeof(SmallBuffer); +} + +inline void LargeBuffer::check() const { + MOZ_ASSERT(checkValue == LargeBufferCheckValue); +} + +BufferAllocator::AutoLock::AutoLock(GCRuntime* gc) + : LockGuard(gc->bufferAllocatorLock) {} + +BufferAllocator::AutoLock::AutoLock(BufferAllocator* allocator) + : LockGuard(allocator->lock()) {} + +// Describes a free region in a buffer chunk. This structure is stored at the +// end of the region. +// +// Medium allocations are made in FreeRegions in increasing address order. The +// final allocation will contain the now empty and unused FreeRegion structure. +// FreeRegions are stored in buckets based on their size in FreeLists. Each +// bucket is a linked list of FreeRegions. +struct BufferAllocator::FreeRegion + : public SlimLinkedListElement { + uintptr_t startAddr; + bool hasDecommittedPages; + +#ifdef DEBUG + uint32_t checkValue = FreeRegionCheckValue; +#endif + + explicit FreeRegion(uintptr_t startAddr, bool decommitted = false) + : startAddr(startAddr), hasDecommittedPages(decommitted) {} + + static FreeRegion* fromEndOffset(BufferChunk* chunk, uintptr_t endOffset) { + MOZ_ASSERT(endOffset <= ChunkSize); + return fromEndAddr(uintptr_t(chunk) + endOffset); + } + static FreeRegion* fromEndAddr(uintptr_t endAddr) { + MOZ_ASSERT((endAddr % MinMediumAllocSize) == 0); + auto* region = reinterpret_cast(endAddr - sizeof(FreeRegion)); + region->check(); + return region; + } + + void check() const { MOZ_ASSERT(checkValue == FreeRegionCheckValue); } + + uintptr_t getEnd() const { return uintptr_t(this + 1); } + size_t size() const { return getEnd() - startAddr; } +}; + +// A chunk containing medium buffer allocations for a single zone. Unlike +// ArenaChunk, allocations from different zones do not share chunks. +struct BufferChunk : public ChunkBase, + public SlimLinkedListElement { +#ifdef DEBUG + MainThreadData zone; +#endif + + MainThreadOrGCTaskData allocatedDuringCollection; + MainThreadData hasNurseryOwnedAllocs; + MainThreadOrGCTaskData hasNurseryOwnedAllocsAfterSweep; + + static constexpr size_t MaxAllocsPerChunk = ChunkSize / MinMediumAllocSize; + using PerAllocByteArray = uint8_t[MaxAllocsPerChunk]; + PerAllocByteArray sizeClassArray; + + // Mark bitmap: one bit minimum per allocation, no gray bits. + static constexpr size_t BytesPerMarkBit = MinMediumAllocSize; + using BufferMarkBitmap = MarkBitmap; + MainThreadOrGCTaskData markBits; + + using PerAllocBitmap = mozilla::BitSet; + using AtomicPerAllocBitmap = + mozilla::BitSet>; + + MainThreadOrGCTaskData allocBitmap; + MainThreadOrGCTaskData nurseryOwnedBitmap; + + static constexpr size_t PagesPerChunk = ChunkSize / PageSize; + using PerPageBitmap = mozilla::BitSet; + MainThreadOrGCTaskData decommittedPages; + + static BufferChunk* from(void* alloc) { + ChunkBase* chunk = js::gc::detail::GetGCAddressChunkBase(alloc); + MOZ_ASSERT(chunk->kind == ChunkKind::MediumBuffers); + return static_cast(chunk); + } + + explicit BufferChunk(Zone* zone); + ~BufferChunk(); + + void checkAlloc(const void* alloc) const; + + const void* ptrFromOffset(uintptr_t offset) const; + + void setAllocated(void* alloc, bool allocated); + bool isAllocated(const void* alloc) const; + bool isAllocated(uintptr_t offset) const; + + void setNurseryOwned(void* alloc, bool nurseryOwned); + bool isNurseryOwned(const void* alloc) const; + + void setSizeClass(void* alloc, size_t sizeClass); + size_t sizeClass(const void* alloc) const; + size_t allocBytes(const void* alloc) const; + + // Find next/previous allocations from |offset|. Return ChunkSize on failure. + size_t findNextAllocated(uintptr_t offset) const; + size_t findPrevAllocated(uintptr_t offset) const; + + bool isPointerWithinAllocation(void* ptr) const; + + private: + uintptr_t ptrToOffset(const void* alloc) const; +}; + +constexpr size_t FirstMediumAllocOffset = + RoundUp(sizeof(BufferChunk), MinMediumAllocSize); + +// Iterate allocations in a BufferChunk. +class BufferChunkIter { + BufferChunk* chunk; + size_t offset = FirstMediumAllocOffset; + size_t size = 0; + + public: + explicit BufferChunkIter(BufferChunk* chunk) : chunk(chunk) { settle(); } + bool done() const { return offset == ChunkSize; } + void next() { + MOZ_ASSERT(!done()); + offset += size; + MOZ_ASSERT(offset <= ChunkSize); + if (!done()) { + settle(); + } + } + size_t getOffset() const { + MOZ_ASSERT(!done()); + return offset; + } + void* get() const { + MOZ_ASSERT(!done()); + MOZ_ASSERT(offset < ChunkSize); + MOZ_ASSERT((offset % MinMediumAllocSize) == 0); + return reinterpret_cast(uintptr_t(chunk) + offset); + } + operator void*() { return get(); } + + private: + void settle() { + offset = chunk->findNextAllocated(offset); + if (!done()) { + size = chunk->allocBytes(get()); + } + } +}; + +static void CheckHighBitsOfPointer(void* ptr) { +#ifdef JS_64BIT + // We require bit 48 and higher be clear. + MOZ_DIAGNOSTIC_ASSERT((uintptr_t(ptr) >> 47) == 0); +#endif +} + +BufferAllocator::FreeLists::FreeLists(FreeLists&& other) { + MOZ_ASSERT(this != &other); + assertEmpty(); + std::swap(lists, other.lists); + std::swap(available, other.available); + other.assertEmpty(); +} + +BufferAllocator::FreeLists& BufferAllocator::FreeLists::operator=( + FreeLists&& other) { + MOZ_ASSERT(this != &other); + assertEmpty(); + std::swap(lists, other.lists); + std::swap(available, other.available); + other.assertEmpty(); + return *this; +} + +size_t BufferAllocator::FreeLists::getFirstAvailableSizeClass( + size_t minSizeClass) const { + size_t result = available.FindNext(minSizeClass); + MOZ_ASSERT(result >= minSizeClass); + MOZ_ASSERT_IF(result != SIZE_MAX, !lists[result].isEmpty()); + return result; +} + +BufferAllocator::FreeRegion* BufferAllocator::FreeLists::getFirstRegion( + size_t sizeClass) { + MOZ_ASSERT(!lists[sizeClass].isEmpty()); + return lists[sizeClass].getFirst(); +} + +void BufferAllocator::FreeLists::pushFront(size_t sizeClass, + FreeRegion* region) { + MOZ_ASSERT(sizeClass < MediumAllocClasses); + lists[sizeClass].pushFront(region); + available[sizeClass] = true; +} + +void BufferAllocator::FreeLists::pushBack(size_t sizeClass, + FreeRegion* region) { + MOZ_ASSERT(sizeClass < MediumAllocClasses); + lists[sizeClass].pushBack(region); + available[sizeClass] = true; +} + +void BufferAllocator::FreeLists::append(FreeLists&& other) { + for (size_t i = 0; i < MediumAllocClasses; i++) { + if (!other.lists[i].isEmpty()) { + lists[i].append(std::move(other.lists[i])); + available[i] = true; + } + } + other.available.ResetAll(); + other.assertEmpty(); +} + +void BufferAllocator::FreeLists::prepend(FreeLists&& other) { + for (size_t i = 0; i < MediumAllocClasses; i++) { + if (!other.lists[i].isEmpty()) { + lists[i].prepend(std::move(other.lists[i])); + available[i] = true; + } + } + other.available.ResetAll(); + other.assertEmpty(); +} + +void BufferAllocator::FreeLists::remove(size_t sizeClass, FreeRegion* region) { + MOZ_ASSERT(sizeClass < MediumAllocClasses); + lists[sizeClass].remove(region); + available[sizeClass] = !lists[sizeClass].isEmpty(); +} + +void BufferAllocator::FreeLists::clear() { + for (auto& freeList : lists) { + new (&freeList) FreeList; // clear() is less efficient. + } + available.ResetAll(); +} + +template +void BufferAllocator::FreeLists::eraseIf(Pred&& pred) { + for (size_t i = 0; i < MediumAllocClasses; i++) { + FreeList& freeList = lists[i]; + FreeRegion* region = freeList.getFirst(); + while (region) { + FreeRegion* next = region->getNext(); + if (pred(region)) { + freeList.remove(region); + } + region = next; + } + available[i] = !freeList.isEmpty(); + } +} + +inline void BufferAllocator::FreeLists::assertEmpty() const { +#ifdef DEBUG + for (size_t i = 0; i < MediumAllocClasses; i++) { + MOZ_ASSERT(lists[i].isEmpty()); + } + MOZ_ASSERT(available.IsEmpty()); +#endif +} + +inline void BufferAllocator::FreeLists::assertContains( + size_t sizeClass, FreeRegion* region) const { +#ifdef DEBUG + MOZ_ASSERT(available[sizeClass]); + MOZ_ASSERT(lists[sizeClass].contains(region)); +#endif +} + +inline void BufferAllocator::FreeLists::checkAvailable() const { +#ifdef DEBUG + for (size_t i = 0; i < MediumAllocClasses; i++) { + MOZ_ASSERT(available[i] == !lists[i].isEmpty()); + } +#endif +} + +} // namespace js::gc + +MOZ_ALWAYS_INLINE void PoisonAlloc(void* alloc, uint8_t value, size_t bytes, + MemCheckKind kind) { +#ifndef EARLY_BETA_OR_EARLIER + // Limit poisoning in release builds. + bytes = std::min(bytes, size_t(256)); +#endif + AlwaysPoison(alloc, value, bytes, kind); +} + +BufferChunk::BufferChunk(Zone* zone) + : ChunkBase(zone->runtimeFromMainThread(), ChunkKind::MediumBuffers) { + mozilla::PodArrayZero(sizeClassArray); +#ifdef DEBUG + this->zone = zone; + MOZ_ASSERT(allocBitmap.ref().IsEmpty()); + MOZ_ASSERT(nurseryOwnedBitmap.ref().IsEmpty()); + MOZ_ASSERT(decommittedPages.ref().IsEmpty()); +#endif +} + +BufferChunk::~BufferChunk() { +#ifdef DEBUG + MOZ_ASSERT(allocBitmap.ref().IsEmpty()); + MOZ_ASSERT(nurseryOwnedBitmap.ref().IsEmpty()); + for (const auto& sizeClass : sizeClassArray) { + MOZ_ASSERT(sizeClass == 0); + } +#endif +} + +uintptr_t BufferChunk::ptrToOffset(const void* alloc) const { + checkAlloc(alloc); + + uintptr_t offset = uintptr_t(alloc) & ChunkMask; + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + + return offset; +} + +const void* BufferChunk::ptrFromOffset(uintptr_t offset) const { + void* alloc = reinterpret_cast(uintptr_t(this) + offset); + checkAlloc(alloc); + return alloc; +} + +void BufferChunk::checkAlloc(const void* alloc) const { + MOZ_ASSERT((uintptr_t(alloc) & ~ChunkMask) == uintptr_t(this)); + MOZ_ASSERT((uintptr_t(alloc) % MinMediumAllocSize) == 0); +} + +void BufferChunk::setAllocated(void* alloc, bool allocated) { + uintptr_t offset = ptrToOffset(alloc); + size_t bit = offset / MinMediumAllocSize; + MOZ_ASSERT(allocBitmap.ref()[bit] != allocated); + allocBitmap.ref()[bit] = allocated; +} + +bool BufferChunk::isAllocated(const void* alloc) const { + return isAllocated(ptrToOffset(alloc)); +} + +bool BufferChunk::isAllocated(uintptr_t offset) const { + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + MOZ_ASSERT(offset < ChunkSize); + + size_t bit = offset / MinMediumAllocSize; + return allocBitmap.ref()[bit]; +} + +size_t BufferChunk::findNextAllocated(uintptr_t offset) const { + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + MOZ_ASSERT(offset < ChunkSize); + + size_t bit = offset / MinMediumAllocSize; + size_t next = allocBitmap.ref().FindNext(bit); + if (next == SIZE_MAX) { + return ChunkSize; + } + + return next * MinMediumAllocSize; +} + +size_t BufferChunk::findPrevAllocated(uintptr_t offset) const { + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + MOZ_ASSERT(offset < ChunkSize); + + size_t bit = offset / MinMediumAllocSize; + size_t prev = allocBitmap.ref().FindPrev(bit); + if (prev == SIZE_MAX) { + return ChunkSize; + } + + return prev * MinMediumAllocSize; +} + +void BufferChunk::setNurseryOwned(void* alloc, bool nurseryOwned) { + MOZ_ASSERT(isAllocated(alloc)); + uintptr_t offset = ptrToOffset(alloc); + size_t bit = offset / MinMediumAllocSize; + nurseryOwnedBitmap.ref()[bit] = nurseryOwned; +} + +bool BufferChunk::isNurseryOwned(const void* alloc) const { + MOZ_ASSERT(isAllocated(alloc)); + uintptr_t offset = ptrToOffset(alloc); + size_t bit = offset / MinMediumAllocSize; + return nurseryOwnedBitmap.ref()[bit]; +} + +void BufferChunk::setSizeClass(void* alloc, size_t sizeClass) { + MOZ_ASSERT(isAllocated(alloc)); + uintptr_t offset = ptrToOffset(alloc); + size_t index = offset / MinMediumAllocSize; + MOZ_ASSERT(index < std::size(sizeClassArray)); + sizeClassArray[index] = sizeClass; +} + +size_t BufferChunk::sizeClass(const void* alloc) const { + MOZ_ASSERT(isAllocated(alloc)); + uintptr_t offset = ptrToOffset(alloc); + size_t index = offset / MinMediumAllocSize; + MOZ_ASSERT(index < std::size(sizeClassArray)); + return sizeClassArray[index]; +} + +size_t BufferChunk::allocBytes(const void* alloc) const { + return BufferAllocator::SizeClassBytes(sizeClass(alloc)); +} + +BufferAllocator::BufferAllocator(Zone* zone) + : zone(zone), + sweptMediumMixedChunks(lock()), + sweptMediumTenuredChunks(lock()), + sweptMediumNurseryFreeLists(lock()), + sweptMediumTenuredFreeLists(lock()), + sweptLargeTenuredAllocs(lock()), + minorState(State::NotCollecting), + majorState(State::NotCollecting), + minorSweepingFinished(lock()), + majorSweepingFinished(lock()) {} + +BufferAllocator::~BufferAllocator() { +#ifdef DEBUG + checkGCStateNotInUse(); + MOZ_ASSERT(mediumMixedChunks.ref().isEmpty()); + MOZ_ASSERT(mediumTenuredChunks.ref().isEmpty()); + mediumFreeLists.ref().assertEmpty(); + MOZ_ASSERT(largeNurseryAllocs.ref().isEmpty()); + MOZ_ASSERT(largeTenuredAllocs.ref().isEmpty()); +#endif +} + +bool BufferAllocator::isEmpty() const { + MOZ_ASSERT(!zone->wasGCStarted() || zone->isGCFinished()); + MOZ_ASSERT(minorState == State::NotCollecting); + MOZ_ASSERT(majorState == State::NotCollecting); + return mediumMixedChunks.ref().isEmpty() && + mediumTenuredChunks.ref().isEmpty() && + largeNurseryAllocs.ref().isEmpty() && + largeTenuredAllocs.ref().isEmpty(); +} + +Mutex& BufferAllocator::lock() const { + return zone->runtimeFromAnyThread()->gc.bufferAllocatorLock; +} + +void* BufferAllocator::alloc(size_t bytes, bool nurseryOwned) { + MOZ_ASSERT_IF(zone->isGCMarkingOrSweeping(), majorState == State::Marking); + + if (IsLargeAllocSize(bytes)) { + return allocLarge(bytes, nurseryOwned, false); + } + + if (IsSmallAllocSize(bytes)) { + return allocSmall(bytes, nurseryOwned); + } + + return allocMedium(bytes, nurseryOwned, false); +} + +void* BufferAllocator::allocInGC(size_t bytes, bool nurseryOwned) { + // Currently this is used during tenuring only. + MOZ_ASSERT(minorState == State::Marking); + + MOZ_ASSERT_IF(zone->isGCMarkingOrSweeping(), majorState == State::Marking); + + void* result; + if (IsLargeAllocSize(bytes)) { + result = allocLarge(bytes, nurseryOwned, true); + } else if (IsSmallAllocSize(bytes)) { + result = allocSmallInGC(bytes, nurseryOwned); + } else { + result = allocMedium(bytes, nurseryOwned, true); + } + + if (!result) { + return nullptr; + } + + // Barrier to mark nursery-owned allocations that happen during collection. We + // don't need to do this for tenured-owned allocations because we don't sweep + // tenured-owned allocations that happened after the start of a major + // collection. + if (nurseryOwned) { + markNurseryOwnedAlloc(result, false); + } + + return result; +} + +/* static */ +SmallBuffer* BufferAllocator::GetSmallBuffer(void* alloc) { + MOZ_ASSERT(BufferAllocator::IsSmallAlloc(alloc)); + auto* buffer = + reinterpret_cast(uintptr_t(alloc) - sizeof(SmallBuffer)); + buffer->check(); + return buffer; +} + +inline SmallBuffer* LargeBuffer::headerCell() { + return BufferAllocator::GetSmallBuffer(this); +} + +#ifdef DEBUG + +inline Zone* LargeBuffer::zone() { return headerCell()->zone(); } + +inline Zone* LargeBuffer::zoneFromAnyThread() { + return headerCell()->zoneFromAnyThread(); +} + +#endif + +#ifdef XP_DARWIN +static inline void VirtualCopyPages(void* dst, const void* src, size_t bytes) { + MOZ_ASSERT((uintptr_t(dst) & PageMask) == 0); + MOZ_ASSERT((uintptr_t(src) & PageMask) == 0); + MOZ_ASSERT(bytes >= ChunkSize); + + kern_return_t r = vm_copy(mach_task_self(), vm_address_t(src), + vm_size_t(bytes), vm_address_t(dst)); + if (r != KERN_SUCCESS) { + MOZ_CRASH("vm_copy() failed"); + } +} +#endif + +void* BufferAllocator::realloc(void* alloc, size_t bytes, bool nurseryOwned) { + // Reallocate a buffer. This has the same semantics as standard libarary + // realloc: if |ptr| is null it creates a new allocation, and if it fails it + // returns |nullptr| and the original |ptr| is still valid. + + if (!alloc) { + return this->alloc(bytes, nurseryOwned); + } + + MOZ_ASSERT(isNurseryOwned(alloc) == nurseryOwned); + MOZ_ASSERT_IF(zone->isGCMarkingOrSweeping(), majorState == State::Marking); + + bytes = GetGoodAllocSize(bytes); + + size_t currentBytes; + if (IsLargeAlloc(alloc)) { + LargeBuffer* buffer = lookupLargeBuffer(alloc); + currentBytes = buffer->allocBytes(); + + // We can shrink large allocations (on some platforms). + if (bytes < buffer->allocBytes() && IsLargeAllocSize(bytes)) { + if (shrinkLarge(buffer, bytes)) { + return alloc; + } + } + } else if (IsMediumAlloc(alloc)) { + BufferChunk* chunk = BufferChunk::from(alloc); + currentBytes = chunk->allocBytes(alloc); + + // We can grow or shrink medium allocations. + if (bytes < currentBytes && !IsSmallAllocSize(bytes)) { + if (shrinkMedium(alloc, bytes)) { + return alloc; + } + } + + if (bytes > currentBytes && !IsLargeAllocSize(bytes)) { + if (growMedium(alloc, bytes)) { + return alloc; + } + } + } else { + SmallBuffer* buffer = GetSmallBuffer(alloc); + currentBytes = buffer->allocBytes(); + } + + if (bytes == currentBytes) { + return alloc; + } + + void* newAlloc = this->alloc(bytes, nurseryOwned); + if (!newAlloc) { + return nullptr; + } + + auto freeGuard = mozilla::MakeScopeExit([&]() { free(alloc); }); + + size_t bytesToCopy = std::min(bytes, currentBytes); + +#ifdef XP_DARWIN + if (bytesToCopy >= ChunkSize) { + MOZ_ASSERT(IsLargeAlloc(alloc)); + MOZ_ASSERT(IsLargeAlloc(newAlloc)); + VirtualCopyPages(newAlloc, alloc, bytesToCopy); + return newAlloc; + } +#endif + + memcpy(newAlloc, alloc, bytesToCopy); + return newAlloc; +} + +void BufferAllocator::free(void* alloc) { + MOZ_ASSERT(alloc); + + if (IsLargeAlloc(alloc)) { + freeLarge(alloc); + return; + } + + if (IsMediumAlloc(alloc)) { + freeMedium(alloc); + return; + } + + // Can't free small allocations. +} + +/* static */ +bool BufferAllocator::IsBufferAlloc(void* alloc) { + // Precondition: |alloc| is a pointer to a buffer allocation, a GC thing or a + // direct nursery allocation returned by Nursery::allocateBuffer. + + if (IsLargeAlloc(alloc)) { + return true; + } + + ChunkKind chunkKind = detail::GetGCAddressChunkBase(alloc)->getKind(); + if (chunkKind == ChunkKind::MediumBuffers) { + return true; + } + + if (chunkKind == ChunkKind::TenuredArenas) { + auto* arena = reinterpret_cast(uintptr_t(alloc) & ~ArenaMask); + return IsBufferAllocKind(arena->getAllocKind()); + } + + return false; +} + +size_t BufferAllocator::getAllocSize(void* alloc) { + if (IsLargeAlloc(alloc)) { + LargeBuffer* buffer = lookupLargeBuffer(alloc); + return buffer->allocBytes(); + } + + if (IsSmallAlloc(alloc)) { + SmallBuffer* cell = GetSmallBuffer(alloc); + return cell->allocBytes(); + } + + MOZ_ASSERT(IsMediumAlloc(alloc)); + BufferChunk* chunk = BufferChunk::from(alloc); + return chunk->allocBytes(alloc); +} + +bool BufferAllocator::isNurseryOwned(void* alloc) { + if (IsLargeAlloc(alloc)) { + LargeBuffer* buffer = lookupLargeBuffer(alloc); + return buffer->isNurseryOwned; + } + + if (IsSmallAlloc(alloc)) { + // This is always false because we currently make such allocations directly + // in the nursery. + SmallBuffer* cell = GetSmallBuffer(alloc); + return cell->isNurseryOwned(); + } + + BufferChunk* chunk = BufferChunk::from(alloc); + return chunk->isNurseryOwned(alloc); +} + +void BufferAllocator::markNurseryOwnedAlloc(void* alloc, bool ownerWasTenured) { + MOZ_ASSERT(alloc); + MOZ_ASSERT(isNurseryOwned(alloc)); + MOZ_ASSERT(minorState == State::Marking); + + if (IsLargeAlloc(alloc)) { + LargeBuffer* buffer = lookupLargeBuffer(alloc); + MOZ_ASSERT(buffer->zone() == zone); + markLargeNurseryOwnedBuffer(buffer, ownerWasTenured); + return; + } + + if (IsSmallAlloc(alloc)) { + SmallBuffer* buffer = GetSmallBuffer(alloc); + markSmallNurseryOwnedBuffer(buffer, ownerWasTenured); + return; + } + + MOZ_ASSERT(IsMediumAlloc(alloc)); + markMediumNurseryOwnedBuffer(alloc, ownerWasTenured); +} + +void BufferAllocator::markSmallNurseryOwnedBuffer(SmallBuffer* buffer, + bool ownerWasTenured) { + MOZ_ASSERT(buffer->zone() == zone); + + if (ownerWasTenured) { + buffer->setNurseryOwned(false); + } + + // Heap size is tracked as part of GC heap for small allocations. +} + +void BufferAllocator::markMediumNurseryOwnedBuffer(void* alloc, + bool ownerWasTenured) { + BufferChunk* chunk = BufferChunk::from(alloc); + MOZ_ASSERT(chunk->zone == zone); + MOZ_ASSERT(chunk->hasNurseryOwnedAllocs); + MOZ_ASSERT(chunk->isAllocated(alloc)); + + if (ownerWasTenured) { + // Change the allocation to a tenured owned one. This prevents sweeping in a + // minor collection. + chunk->setNurseryOwned(alloc, false); + size_t size = chunk->allocBytes(alloc); + updateHeapSize(size, false, false); + return; + } + + chunk->markBits.ref().markIfUnmarked(alloc, MarkColor::Black); +} + +void BufferAllocator::markLargeNurseryOwnedBuffer(LargeBuffer* buffer, + bool ownerWasTenured) { + largeNurseryAllocsToSweep.ref().remove(buffer); + + if (ownerWasTenured) { + buffer->isNurseryOwned = false; + buffer->allocatedDuringCollection = majorState != State::NotCollecting; + largeTenuredAllocs.ref().pushBack(buffer); + size_t usableSize = buffer->allocBytes(); + updateHeapSize(usableSize, false, false); + return; + } + + largeNurseryAllocs.ref().pushBack(buffer); +} + +bool BufferAllocator::isMarkedBlack(void* alloc) { + if (IsLargeAlloc(alloc)) { + return isLargeAllocMarked(alloc); + } + + if (IsSmallAlloc(alloc)) { + SmallBuffer* cell = GetSmallBuffer(alloc); + MOZ_ASSERT(!cell->isMarkedGray()); + return cell->isMarkedBlack(); + } + + MOZ_ASSERT(IsMediumAlloc(alloc)); + BufferChunk* chunk = BufferChunk::from(alloc); + MOZ_ASSERT(chunk->isAllocated(alloc)); + return chunk->markBits.ref().isMarkedBlack(alloc); +} + +void BufferAllocator::traceEdge(JSTracer* trc, Cell* owner, void** bufferp, + const char* name) { + // Buffers are conceptually part of the owning cell and are not reported to + // the tracer. + + // TODO: This should be unified with the rest of the tracing system. + + MOZ_ASSERT(owner); + MOZ_ASSERT(bufferp); + + void* buffer = *bufferp; + MOZ_ASSERT(buffer); + + if (!IsLargeAlloc(buffer) && + js::gc::detail::GetGCAddressChunkBase(buffer)->isNurseryChunk()) { + // JSObject slots and elements can be allocated in the nursery and this is + // handled separately. + return; + } + + MOZ_ASSERT(IsBufferAlloc(buffer)); + + if (IsLargeAlloc(buffer)) { + traceLargeAlloc(trc, owner, bufferp, name); + return; + } + + if (IsSmallAlloc(buffer)) { + traceSmallAlloc(trc, owner, bufferp, name); + return; + } + + traceMediumAlloc(trc, owner, bufferp, name); +} + +void BufferAllocator::traceSmallAlloc(JSTracer* trc, Cell* owner, void** allocp, + const char* name) { + void* alloc = *allocp; + SmallBuffer* cell = GetSmallBuffer(alloc); + TraceManuallyBarrieredEdge(trc, &cell, name); + if (cell != GetSmallBuffer(alloc)) { + *allocp = cell->data(); + } +} + +void BufferAllocator::traceMediumAlloc(JSTracer* trc, Cell* owner, + void** allocp, const char* name) { + void* alloc = *allocp; + BufferChunk* chunk = BufferChunk::from(alloc); + + if (trc->isTenuringTracer()) { + if (chunk->isNurseryOwned(alloc)) { + markMediumNurseryOwnedBuffer(alloc, owner->isTenured()); + } + return; + } + + if (trc->isMarkingTracer()) { + if (!chunk->isNurseryOwned(alloc)) { + markMediumTenuredAlloc(alloc); + } + return; + } +} + +void BufferAllocator::traceLargeAlloc(JSTracer* trc, Cell* owner, void** allocp, + const char* name) { + void* alloc = *allocp; + LargeBuffer* buffer = lookupLargeBuffer(alloc); + + // Trace small buffer that holds large buffer metadata. + // For moving GC the table is updated in fixupAfterMovingGC(). + traceSmallAlloc(trc, owner, reinterpret_cast(&buffer), "LargeBuffer"); + + if (trc->isTenuringTracer()) { + if (isNurseryOwned(alloc)) { + markLargeNurseryOwnedBuffer(buffer, owner->isTenured()); + } + return; + } + + if (trc->isMarkingTracer()) { + if (!isNurseryOwned(alloc)) { + markLargeTenuredBuffer(buffer); + } + return; + } +} + +bool BufferAllocator::markTenuredAlloc(void* alloc) { + MOZ_ASSERT(alloc); + MOZ_ASSERT(!isNurseryOwned(alloc)); + + if (IsLargeAlloc(alloc)) { + LargeBuffer* buffer = lookupLargeBuffer(alloc); + return markLargeTenuredBuffer(buffer); + } + + if (IsSmallAlloc(alloc)) { + return markSmallTenuredAlloc(alloc); + } + + return markMediumTenuredAlloc(alloc); +} + +bool BufferAllocator::markSmallTenuredAlloc(void* alloc) { + SmallBuffer* cell = GetSmallBuffer(alloc); + return cell->markIfUnmarkedThreadSafe(MarkColor::Black); +} + +bool BufferAllocator::markMediumTenuredAlloc(void* alloc) { + BufferChunk* chunk = BufferChunk::from(alloc); + MOZ_ASSERT(chunk->isAllocated(alloc)); + if (chunk->allocatedDuringCollection) { + // Will not be swept, already counted as marked. + return false; + } + + return chunk->markBits.ref().markIfUnmarkedThreadSafe(alloc, + MarkColor::Black); +} + +void BufferAllocator::startMinorCollection(MaybeLock& lock) { + maybeMergeSweptData(lock); + +#ifdef DEBUG + MOZ_ASSERT(minorState == State::NotCollecting); + if (majorState == State::NotCollecting) { + checkGCStateNotInUse(lock); + } +#endif + + // Large allocations that are marked when tracing the nursery will be moved + // back to the main list. + MOZ_ASSERT(largeNurseryAllocsToSweep.ref().isEmpty()); + std::swap(largeNurseryAllocs.ref(), largeNurseryAllocsToSweep.ref()); + + minorState = State::Marking; +} + +bool BufferAllocator::startMinorSweeping() { + // Called during minor GC. Operates on the active allocs/chunks lists. The 'to + // sweep' lists do not contain nursery owned allocations. + +#ifdef DEBUG + MOZ_ASSERT(minorState == State::Marking); + { + AutoLock lock(this); + MOZ_ASSERT(!minorSweepingFinished); + MOZ_ASSERT(sweptMediumMixedChunks.ref().isEmpty()); + } + for (LargeBuffer* buffer : largeNurseryAllocs.ref()) { + MOZ_ASSERT(buffer->isNurseryOwned); + } + for (LargeBuffer* buffer : largeNurseryAllocsToSweep.ref()) { + MOZ_ASSERT(buffer->isNurseryOwned); + } +#endif + + // Check whether there are any medium chunks containing nursery owned + // allocations that need to be swept. + if (mediumMixedChunks.ref().isEmpty() && + largeNurseryAllocsToSweep.ref().isEmpty()) { + // Nothing more to do. Don't transition to sweeping state. + minorState = State::NotCollecting; + return false; + } + + // TODO: There are more efficient ways to remove the free regions in nursery + // chunks from the free lists, but all require some more bookkeeping. I don't + // know how much difference such a change would make. + // + // Some possibilities are: + // - maintain a separate list of free regions in each chunk and use that to + // remove those regions in nursery chunks + // - have separate free lists for nursery/tenured chunks + // - keep free regions at different ends of the free list depending on chunk + // kind + mediumFreeLists.ref().eraseIf([](FreeRegion* region) { + return BufferChunk::from(region)->hasNurseryOwnedAllocs; + }); + + mediumMixedChunksToSweep.ref() = std::move(mediumMixedChunks.ref()); + + minorState = State::Sweeping; + + return true; +} + +void BufferAllocator::sweepForMinorCollection() { + // Called on a background thread. + + MOZ_ASSERT(minorState.refNoCheck() == State::Sweeping); + { + AutoLock lock(this); + MOZ_ASSERT(sweptMediumMixedChunks.ref().isEmpty()); + } + + while (!mediumMixedChunksToSweep.ref().isEmpty()) { + BufferChunk* chunk = mediumMixedChunksToSweep.ref().popFirst(); + FreeLists sweptFreeLists; + if (sweepChunk(chunk, OwnerKind::Nursery, false, sweptFreeLists)) { + { + AutoLock lock(this); + sweptMediumMixedChunks.ref().pushBack(chunk); + if (chunk->hasNurseryOwnedAllocsAfterSweep) { + sweptMediumNurseryFreeLists.ref().append(std::move(sweptFreeLists)); + } else { + sweptMediumTenuredFreeLists.ref().append(std::move(sweptFreeLists)); + } + } + + // Signal to the main thread that swept data is available by setting this + // relaxed atomic flag. + hasMinorSweepDataToMerge = true; + } + } + + // Bug 1961749: Freeing large buffers can be slow so it might be worth + // splitting sweeping into two phases so that all zones get their medium + // buffers swept and made available for allocation before any large buffers + // are freed. + // Alternatively this could happen in parallel to sweeping medium buffers. + + while (!largeNurseryAllocsToSweep.ref().isEmpty()) { + LargeBuffer* buffer = largeNurseryAllocsToSweep.ref().popFirst(); + MaybeLock lock(std::in_place, this); + unmapLarge(buffer, true, lock); + } + + // Signal to main thread to update minorState. + { + AutoLock lock(this); + MOZ_ASSERT(!minorSweepingFinished); + minorSweepingFinished = true; + hasMinorSweepDataToMerge = true; + } +} + +void BufferAllocator::startMajorCollection(MaybeLock& lock) { + maybeMergeSweptData(lock); + +#ifdef DEBUG + MOZ_ASSERT(majorState == State::NotCollecting); + checkGCStateNotInUse(lock); + + // Everything is tenured since we just evicted the nursery, or will be by the + // time minor sweeping finishes. + MOZ_ASSERT(mediumMixedChunks.ref().isEmpty()); + MOZ_ASSERT(largeNurseryAllocs.ref().isEmpty()); +#endif + + mediumTenuredChunksToSweep.ref() = std::move(mediumTenuredChunks.ref()); + largeTenuredAllocsToSweep.ref() = std::move(largeTenuredAllocs.ref()); + + // Clear the active free lists to prevent further allocation in chunks that + // will be swept. + mediumFreeLists.ref().clear(); + + if (minorState == State::Sweeping) { + // Ensure swept nursery chunks are moved to the mediumTenuredChunks lists in + // mergeSweptData. + majorStartedWhileMinorSweeping = true; + } + +#ifdef DEBUG + MOZ_ASSERT(mediumTenuredChunks.ref().isEmpty()); + mediumFreeLists.ref().assertEmpty(); + MOZ_ASSERT(largeTenuredAllocs.ref().isEmpty()); +#endif + + majorState = State::Marking; +} + +void BufferAllocator::startMajorSweeping(MaybeLock& lock) { + // Called when a zone transitions from marking to sweeping. + +#ifdef DEBUG + MOZ_ASSERT(majorState == State::Marking); + MOZ_ASSERT(zone->isGCFinished()); + MOZ_ASSERT(!majorSweepingFinished.refNoCheck()); +#endif + + maybeMergeSweptData(lock); + MOZ_ASSERT(!majorStartedWhileMinorSweeping); + + majorState = State::Sweeping; +} + +void BufferAllocator::sweepForMajorCollection(bool shouldDecommit) { + // Called on a background thread. + + MOZ_ASSERT(majorState.refNoCheck() == State::Sweeping); + + while (!mediumTenuredChunksToSweep.ref().isEmpty()) { + BufferChunk* chunk = mediumTenuredChunksToSweep.ref().popFirst(); + FreeLists sweptFreeLists; + if (sweepChunk(chunk, OwnerKind::Tenured, shouldDecommit, sweptFreeLists)) { + { + AutoLock lock(this); + sweptMediumTenuredChunks.ref().pushBack(chunk); + sweptMediumTenuredFreeLists.ref().append(std::move(sweptFreeLists)); + } + + // Signal to the main thread that swept data is available by setting this + // relaxed atomic flag. + hasMinorSweepDataToMerge = true; + } + } + + // It's tempting to try and optimize this by moving the allocations between + // lists when they are marked, in the same way as for nursery sweeping. This + // would require synchronizing the list modification when marking in parallel, + // so is probably not worth it. + LargeAllocList sweptList; + while (!largeTenuredAllocsToSweep.ref().isEmpty()) { + LargeBuffer* buffer = largeTenuredAllocsToSweep.ref().popFirst(); + if (sweepLargeTenured(buffer)) { + sweptList.pushBack(buffer); + } + } + + // It would be possible to add these to the output list as we sweep but + // there's currently no advantage to that. + AutoLock lock(this); + sweptLargeTenuredAllocs.ref() = std::move(sweptList); + + // Signal to main thread to update majorState. + MOZ_ASSERT(!majorSweepingFinished); + majorSweepingFinished = true; +} + +static void ClearAllocatedDuringCollection(SlimLinkedList& list) { + for (auto* buffer : list) { + buffer->allocatedDuringCollection = false; + } +} +static void ClearAllocatedDuringCollection(SlimLinkedList& list) { + for (auto* element : list) { + element->allocatedDuringCollection = false; + } +} + +void BufferAllocator::finishMajorCollection(const AutoLock& lock) { + // This can be called in any state: + // + // - NotCollecting: after major sweeping has finished and the state has been + // reset to NotCollecting in mergeSweptData. + // + // - Marking: if collection was aborted and startMajorSweeping was not + // called. + // + // - Sweeping: if sweeping has finished and mergeSweptData has not been + // called yet. + + MOZ_ASSERT_IF(majorState == State::Sweeping, majorSweepingFinished); + + if (minorState == State::Sweeping || majorState == State::Sweeping) { + mergeSweptData(lock); + } + + if (majorState == State::Marking) { + abortMajorSweeping(lock); + } + +#ifdef DEBUG + checkGCStateNotInUse(lock); +#endif +} + +void BufferAllocator::abortMajorSweeping(const AutoLock& lock) { + // We have aborted collection without sweeping this zone. Restore or rebuild + // the original state. + + MOZ_ASSERT(majorState == State::Marking); + MOZ_ASSERT(sweptMediumTenuredChunks.ref().isEmpty()); + + clearAllocatedDuringCollectionState(lock); + + for (BufferChunk* chunk : mediumTenuredChunksToSweep.ref()) { + chunk->markBits.ref().clear(); + } + + // Rebuild free lists for chunks we didn't end up sweeping. + for (BufferChunk* chunk : mediumTenuredChunksToSweep.ref()) { + MOZ_ALWAYS_TRUE( + sweepChunk(chunk, OwnerKind::None, false, mediumFreeLists.ref())); + } + + mediumTenuredChunks.ref().prepend( + std::move(mediumTenuredChunksToSweep.ref())); + largeTenuredAllocs.ref().prepend(std::move(largeTenuredAllocsToSweep.ref())); + + majorState = State::NotCollecting; +} + +void BufferAllocator::clearAllocatedDuringCollectionState( + const AutoLock& lock) { + ClearAllocatedDuringCollection(mediumMixedChunks.ref()); + ClearAllocatedDuringCollection(mediumTenuredChunks.ref()); + // This flag is not set for large nursery-owned allocations. + ClearAllocatedDuringCollection(largeTenuredAllocs.ref()); +} + +void BufferAllocator::maybeMergeSweptData() { + if (minorState == State::Sweeping || majorState == State::Sweeping) { + mergeSweptData(); + } +} + +void BufferAllocator::mergeSweptData() { + AutoLock lock(this); + mergeSweptData(lock); +} + +void BufferAllocator::maybeMergeSweptData(MaybeLock& lock) { + if (minorState == State::Sweeping || majorState == State::Sweeping) { + if (lock.isNothing()) { + lock.emplace(this); + } + mergeSweptData(lock.ref()); + } +} + +void BufferAllocator::mergeSweptData(const AutoLock& lock) { + MOZ_ASSERT(minorState == State::Sweeping || majorState == State::Sweeping); + + if (majorSweepingFinished) { + clearAllocatedDuringCollectionState(lock); + + if (minorState == State::Sweeping) { + majorFinishedWhileMinorSweeping = true; + } + } + + // Merge swept chunks that previously contained nursery owned allocations. If + // semispace nursery collection is in use then these chunks may contain both + // nursery and tenured-owned allocations, otherwise all allocations will be + // tenured-owned. + while (!sweptMediumMixedChunks.ref().isEmpty()) { + BufferChunk* chunk = sweptMediumMixedChunks.ref().popLast(); + MOZ_ASSERT(chunk->hasNurseryOwnedAllocs); + chunk->hasNurseryOwnedAllocs = chunk->hasNurseryOwnedAllocsAfterSweep; + + MOZ_ASSERT_IF( + majorState == State::NotCollecting && !majorFinishedWhileMinorSweeping, + !chunk->allocatedDuringCollection); + if (majorFinishedWhileMinorSweeping) { + chunk->allocatedDuringCollection = false; + } + + if (chunk->hasNurseryOwnedAllocs) { + mediumMixedChunks.ref().pushFront(chunk); + } else if (majorStartedWhileMinorSweeping) { + mediumTenuredChunksToSweep.ref().pushFront(chunk); + } else { + mediumTenuredChunks.ref().pushFront(chunk); + } + } + + // Merge swept chunks that did not contain nursery owned allocations. +#ifdef DEBUG + for (BufferChunk* chunk : sweptMediumTenuredChunks.ref()) { + MOZ_ASSERT(!chunk->hasNurseryOwnedAllocs); + MOZ_ASSERT(!chunk->hasNurseryOwnedAllocsAfterSweep); + MOZ_ASSERT(!chunk->allocatedDuringCollection); + } +#endif + mediumTenuredChunks.ref().prepend(std::move(sweptMediumTenuredChunks.ref())); + + mediumFreeLists.ref().prepend(std::move(sweptMediumNurseryFreeLists.ref())); + if (!majorStartedWhileMinorSweeping) { + mediumFreeLists.ref().prepend(std::move(sweptMediumTenuredFreeLists.ref())); + } else { + sweptMediumTenuredFreeLists.ref().clear(); + } + + largeTenuredAllocs.ref().prepend(std::move(sweptLargeTenuredAllocs.ref())); + + hasMinorSweepDataToMerge = false; + + if (minorSweepingFinished) { + MOZ_ASSERT(minorState == State::Sweeping); + minorState = State::NotCollecting; + minorSweepingFinished = false; + majorStartedWhileMinorSweeping = false; + majorFinishedWhileMinorSweeping = false; + +#ifdef DEBUG + for (BufferChunk* chunk : mediumMixedChunks.ref()) { + verifyChunk(chunk, true); + } + for (BufferChunk* chunk : mediumTenuredChunks.ref()) { + verifyChunk(chunk, false); + } +#endif + } + + if (majorSweepingFinished) { + MOZ_ASSERT(majorState == State::Sweeping); + majorState = State::NotCollecting; + majorSweepingFinished = false; + + MOZ_ASSERT(mediumTenuredChunksToSweep.ref().isEmpty()); + } +} + +void BufferAllocator::prepareForMovingGC() { + maybeMergeSweptData(); + + MOZ_ASSERT(majorState == State::NotCollecting); + MOZ_ASSERT(minorState == State::NotCollecting); + MOZ_ASSERT(largeNurseryAllocsToSweep.ref().isEmpty()); + MOZ_ASSERT(largeTenuredAllocsToSweep.ref().isEmpty()); + +#ifdef DEBUG + MOZ_ASSERT(!movingGCInProgress); + movingGCInProgress = true; +#endif + + // Remove large buffer metadata objects from their linked lists so we can move + // them without breaking the links. + for (auto i = largeAllocMap.ref().iter(); !i.done(); i.next()) { + LargeBuffer* buffer = i.get().value(); + if (buffer->isNurseryOwned) { + largeNurseryAllocs.ref().remove(buffer); + } else { + largeTenuredAllocs.ref().remove(buffer); + } + } + + MOZ_ASSERT(largeNurseryAllocs.ref().isEmpty()); + MOZ_ASSERT(largeTenuredAllocs.ref().isEmpty()); +} + +void BufferAllocator::fixupAfterMovingGC() { +#ifdef DEBUG + MOZ_ASSERT(movingGCInProgress); + movingGCInProgress = false; +#endif + + // Update our pointers to large allocation metadata objects and return them to + // their lists. + for (auto i = largeAllocMap.ref().iter(); !i.done(); i.next()) { + LargeBuffer* buffer = i.get().value(); + SmallBuffer* headerCell = buffer->headerCell(); + if (IsForwarded(headerCell)) { + headerCell = Forwarded(headerCell); + buffer = static_cast(headerCell->data()); + i.get().value() = buffer; + } + + MOZ_ASSERT(!buffer->isInList()); + if (buffer->isNurseryOwned) { + largeNurseryAllocs.ref().pushBack(buffer); + } else { + largeTenuredAllocs.ref().pushBack(buffer); + } + } +} + +void BufferAllocator::clearMarkStateAfterBarrierVerification() { + MOZ_ASSERT(!zone->wasGCStarted()); + + maybeMergeSweptData(); + MOZ_ASSERT(minorState == State::NotCollecting); + MOZ_ASSERT(majorState == State::NotCollecting); + + for (auto* chunks : {&mediumMixedChunks.ref(), &mediumTenuredChunks.ref()}) { + for (auto* chunk : *chunks) { + chunk->markBits.ref().clear(); + } + } +} + +bool BufferAllocator::isPointerWithinMediumOrLargeBuffer(void* ptr) { + maybeMergeSweptData(); + + for (const auto* chunks : + {&mediumMixedChunks.ref(), &mediumTenuredChunks.ref()}) { + for (auto* chunk : *chunks) { + if (chunk->isPointerWithinAllocation(ptr)) { + return true; + } + } + } + + if (majorState == State::Marking) { + for (auto* chunk : mediumTenuredChunksToSweep.ref()) { + if (chunk->isPointerWithinAllocation(ptr)) { + return true; + } + } + } + + // Note we cannot safely access data that is being swept on another thread. + + for (const auto* allocs : + {&largeNurseryAllocs.ref(), &largeTenuredAllocs.ref()}) { + for (auto* alloc : *allocs) { + if (alloc->isPointerWithinAllocation(ptr)) { + return true; + } + } + } + + return false; +} + +bool BufferChunk::isPointerWithinAllocation(void* ptr) const { + uintptr_t offset = uintptr_t(ptr) - uintptr_t(this); + if (offset >= ChunkSize || offset < FirstMediumAllocOffset) { + return false; + } + + uintptr_t allocOffset = findPrevAllocated(offset); + MOZ_ASSERT(allocOffset <= ChunkSize); + if (allocOffset == ChunkSize) { + return false; + } + + const void* alloc = ptrFromOffset(allocOffset); + size_t size = allocBytes(alloc); + + return offset < allocOffset + size; +} + +bool LargeBuffer::isPointerWithinAllocation(void* ptr) const { + return uintptr_t(ptr) - uintptr_t(alloc) < bytes; +} + +#ifdef DEBUG + +void BufferAllocator::checkGCStateNotInUse() { + maybeMergeSweptData(); + AutoLock lock(this); // Some fields are protected by this lock. + checkGCStateNotInUse(lock); +} + +void BufferAllocator::checkGCStateNotInUse(MaybeLock& maybeLock) { + if (maybeLock.isNothing()) { + // Some fields are protected by this lock. + maybeLock.emplace(this); + } + + checkGCStateNotInUse(maybeLock.ref()); +} + +void BufferAllocator::checkGCStateNotInUse(const AutoLock& lock) { + MOZ_ASSERT(majorState == State::NotCollecting); + bool isNurserySweeping = minorState == State::Sweeping; + + checkChunkListGCStateNotInUse(mediumMixedChunks.ref(), true, false); + checkChunkListGCStateNotInUse(mediumTenuredChunks.ref(), false, false); + + if (isNurserySweeping) { + checkChunkListGCStateNotInUse(sweptMediumMixedChunks.ref(), true, + majorFinishedWhileMinorSweeping); + checkChunkListGCStateNotInUse(sweptMediumTenuredChunks.ref(), false, false); + } else { + MOZ_ASSERT(mediumMixedChunksToSweep.ref().isEmpty()); + MOZ_ASSERT(largeNurseryAllocsToSweep.ref().isEmpty()); + + MOZ_ASSERT(sweptMediumMixedChunks.ref().isEmpty()); + MOZ_ASSERT(sweptMediumTenuredChunks.ref().isEmpty()); + sweptMediumNurseryFreeLists.ref().assertEmpty(); + sweptMediumTenuredFreeLists.ref().assertEmpty(); + + MOZ_ASSERT(!majorStartedWhileMinorSweeping); + MOZ_ASSERT(!majorFinishedWhileMinorSweeping); + MOZ_ASSERT(!hasMinorSweepDataToMerge); + MOZ_ASSERT(!minorSweepingFinished); + MOZ_ASSERT(!majorSweepingFinished); + } + + MOZ_ASSERT(mediumTenuredChunksToSweep.ref().isEmpty()); + + checkAllocListGCStateNotInUse(largeNurseryAllocs.ref(), true); + checkAllocListGCStateNotInUse(largeTenuredAllocs.ref(), false); + + MOZ_ASSERT(largeTenuredAllocsToSweep.ref().isEmpty()); + MOZ_ASSERT(sweptLargeTenuredAllocs.ref().isEmpty()); + + MOZ_ASSERT(!movingGCInProgress); +} + +void BufferAllocator::checkChunkListGCStateNotInUse( + BufferChunkList& chunks, bool hasNurseryOwnedAllocs, + bool allowAllocatedDuringCollection) { + for (BufferChunk* chunk : chunks) { + checkChunkGCStateNotInUse(chunk, allowAllocatedDuringCollection); + verifyChunk(chunk, hasNurseryOwnedAllocs); + } +} + +void BufferAllocator::checkChunkGCStateNotInUse( + BufferChunk* chunk, bool allowAllocatedDuringCollection) { + MOZ_ASSERT_IF(!allowAllocatedDuringCollection, + !chunk->allocatedDuringCollection); + + static constexpr size_t StepBytes = MinMediumAllocSize; + + // Check nothing's marked. + uintptr_t chunkAddr = uintptr_t(chunk); + auto& markBits = chunk->markBits.ref(); + for (size_t offset = 0; offset < ChunkSize; offset += StepBytes) { + void* alloc = reinterpret_cast(chunkAddr + offset); + MOZ_ASSERT(!markBits.isMarkedBlack(alloc)); + } +} + +void BufferAllocator::verifyChunk(BufferChunk* chunk, + bool hasNurseryOwnedAllocs) { + MOZ_ASSERT(chunk->hasNurseryOwnedAllocs == hasNurseryOwnedAllocs); + + static constexpr size_t StepBytes = MinMediumAllocSize; + + size_t freeOffset = FirstMediumAllocOffset; + + for (BufferChunkIter iter(chunk); !iter.done(); iter.next()) { + // Check any free region preceding this allocation. + size_t offset = iter.getOffset(); + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + if (offset > freeOffset) { + verifyFreeRegion(chunk, offset, offset - freeOffset); + } + + // Check this allocation. + void* alloc = iter.get(); + MOZ_ASSERT_IF(chunk->isNurseryOwned(alloc), hasNurseryOwnedAllocs); + size_t bytes = SizeClassBytes(chunk->sizeClass(alloc)); + uintptr_t endOffset = offset + bytes; + MOZ_ASSERT(endOffset <= ChunkSize); + for (size_t i = offset + StepBytes; i < endOffset; i += StepBytes) { + MOZ_ASSERT(!chunk->isAllocated(i)); + } + + freeOffset = endOffset; + } + + // Check any free region following the last allocation. + if (freeOffset < ChunkSize) { + verifyFreeRegion(chunk, ChunkSize, ChunkSize - freeOffset); + } +} + +void BufferAllocator::verifyFreeRegion(BufferChunk* chunk, uintptr_t endOffset, + size_t expectedSize) { + auto* freeRegion = FreeRegion::fromEndOffset(chunk, endOffset); + MOZ_ASSERT(freeRegion->isInList()); + MOZ_ASSERT(freeRegion->size() == expectedSize); +} + +void BufferAllocator::checkAllocListGCStateNotInUse(LargeAllocList& list, + bool isNurseryOwned) { + for (LargeBuffer* buffer : list) { + MOZ_ASSERT(buffer->isNurseryOwned == isNurseryOwned); + MOZ_ASSERT_IF(!isNurseryOwned, !buffer->allocatedDuringCollection); + } +} + +#endif + +void* BufferAllocator::allocSmall(size_t bytes, bool nurseryOwned) { + AllocKind kind = AllocKindForSmallAlloc(bytes); + + void* ptr = CellAllocator::AllocTenuredCellUnchecked(zone, kind); + if (!ptr) { + return nullptr; + } + + //MONGODB MODIFICATION: Moves placement new call within SmallBuffer to resolve compilation error using GCC. + auto* cell = SmallBuffer::create(ptr); + cell->setNurseryOwned(nurseryOwned); + MOZ_ASSERT(cell->isNurseryOwned() == nurseryOwned); + void* alloc = cell->data(); + + MOZ_ASSERT(IsSmallAlloc(alloc)); + MOZ_ASSERT(getAllocSize(alloc) >= bytes); + MOZ_ASSERT(getAllocSize(alloc) < 2 * bytes); + + return alloc; +} + +/* static */ +void* BufferAllocator::allocSmallInGC(size_t bytes, bool nurseryOwned) { + AllocKind kind = AllocKindForSmallAlloc(bytes); + + void* ptr = AllocateTenuredCellInGC(zone, kind); + if (!ptr) { + return nullptr; + } + + //MONGODB MODIFICATION: Moves placement new call within SmallBuffer to resolve compilation error using GCC. + auto* cell = SmallBuffer::create(ptr);; + cell->setNurseryOwned(nurseryOwned); + void* alloc = cell->data(); + + MOZ_ASSERT(IsSmallAlloc(alloc)); + MOZ_ASSERT(getAllocSize(alloc) >= bytes); + MOZ_ASSERT(getAllocSize(alloc) < 2 * bytes); + + return alloc; +} + +/* static */ +AllocKind BufferAllocator::AllocKindForSmallAlloc(size_t bytes) { + bytes = std::max(bytes, MinAllocSize); + MOZ_ASSERT(bytes <= MaxSmallAllocSize); + + size_t logBytes = mozilla::CeilingLog2(bytes); + MOZ_ASSERT(bytes <= (size_t(1) << logBytes)); + + MOZ_ASSERT(logBytes >= mozilla::CeilingLog2(MinAllocSize)); + size_t kindIndex = logBytes - mozilla::CeilingLog2(MinAllocSize); + + AllocKind kind = AllocKind(size_t(AllocKind::BUFFER_FIRST) + kindIndex); + MOZ_ASSERT(IsBufferAllocKind(kind)); + + return kind; +} + +/* static */ +bool BufferAllocator::IsSmallAlloc(void* alloc) { + MOZ_ASSERT(IsBufferAlloc(alloc)); + + // Test for large buffers before calling this so we can assume |alloc| is + // inside a chunk. + MOZ_ASSERT(!IsLargeAlloc(alloc)); + + ChunkBase* chunk = detail::GetGCAddressChunkBase(alloc); + return chunk->getKind() == ChunkKind::TenuredArenas; +} + +void* BufferAllocator::allocMedium(size_t bytes, bool nurseryOwned, bool inGC) { + MOZ_ASSERT(!IsSmallAllocSize(bytes)); + MOZ_ASSERT(!IsLargeAllocSize(bytes)); + bytes = mozilla::RoundUpPow2(std::max(bytes, MinMediumAllocSize)); + + // Get size class from |bytes|. + size_t sizeClass = SizeClassForAlloc(bytes); + MOZ_ASSERT(SizeClassBytes(sizeClass) == GetGoodAllocSize(bytes)); + + void* alloc = bumpAllocOrRetry(sizeClass, inGC); + if (!alloc) { + return nullptr; + } + + BufferChunk* chunk = BufferChunk::from(alloc); + chunk->setAllocated(alloc, true); + + MOZ_ASSERT(!chunk->isNurseryOwned(alloc)); + chunk->setNurseryOwned(alloc, nurseryOwned); + + MOZ_ASSERT(chunk->sizeClass(alloc) == 0); + chunk->setSizeClass(alloc, sizeClass); + + if (nurseryOwned && !chunk->hasNurseryOwnedAllocs) { + mediumTenuredChunks.ref().remove(chunk); + chunk->hasNurseryOwnedAllocs = true; + mediumMixedChunks.ref().pushBack(chunk); + } + + MOZ_ASSERT(!chunk->markBits.ref().isMarkedBlack(alloc)); + + if (!nurseryOwned) { + bool checkThresholds = !inGC; + updateHeapSize(bytes, checkThresholds, false); + } + + chunk->checkAlloc(alloc); + return alloc; +} + +void* BufferAllocator::bumpAllocOrRetry(size_t sizeClass, bool inGC) { + void* ptr = bumpAlloc(sizeClass); + if (ptr) { + return ptr; + } + + if (hasMinorSweepDataToMerge) { + // Avoid taking the lock unless we know there is data to merge. This reduces + // context switches. + mergeSweptData(); + ptr = bumpAlloc(sizeClass); + if (ptr) { + return ptr; + } + } + + if (!allocNewChunk(inGC)) { + return nullptr; + } + + ptr = bumpAlloc(sizeClass); + MOZ_ASSERT(ptr); + return ptr; +} + +void* BufferAllocator::bumpAlloc(size_t sizeClass) { + size_t requestedBytes = SizeClassBytes(sizeClass); + + mediumFreeLists.ref().checkAvailable(); + + // Find smallest suitable size class that has free regions. + sizeClass = mediumFreeLists.ref().getFirstAvailableSizeClass(sizeClass); + if (sizeClass == SIZE_MAX) { + return nullptr; + } + + FreeRegion* region = mediumFreeLists.ref().getFirstRegion(sizeClass); + void* ptr = allocFromRegion(region, requestedBytes, sizeClass); + updateFreeListsAfterAlloc(&mediumFreeLists.ref(), region, sizeClass); + return ptr; +} + +void* BufferAllocator::allocFromRegion(FreeRegion* region, + size_t requestedBytes, + size_t sizeClass) { + uintptr_t start = region->startAddr; + MOZ_ASSERT(region->getEnd() > start); + MOZ_ASSERT(region->size() >= SizeClassBytes(sizeClass)); + MOZ_ASSERT((region->size() % MinMediumAllocSize) == 0); + + // Ensure whole region is commited. + if (region->hasDecommittedPages) { + recommitRegion(region); + } + + // Allocate from start of region. + void* ptr = reinterpret_cast(start); + start += requestedBytes; + MOZ_ASSERT(region->getEnd() >= start); + + // Update region start. + region->startAddr = start; + + return ptr; +} + +void BufferAllocator::updateFreeListsAfterAlloc(FreeLists* freeLists, + FreeRegion* region, + size_t sizeClass) { + // Updates |freeLists| after an allocation of class |sizeClass| from |region|. + + freeLists->assertContains(sizeClass, region); + + // If the region is still valid for further allocations of this size class + // then there's nothing to do. + size_t classBytes = SizeClassBytes(sizeClass); + size_t newSize = region->size(); + MOZ_ASSERT((newSize % MinMediumAllocSize) == 0); + if (newSize >= classBytes) { + return; + } + + // Remove region from this free list. + freeLists->remove(sizeClass, region); + + // If the region is now empty then we're done. + if (newSize == 0) { + return; + } + + // Otherwise region is now too small. Move it to the appropriate bucket for + // its reduced size. + size_t newSizeClass = SizeClassForFreeRegion(newSize); + MOZ_ASSERT(newSize >= SizeClassBytes(newSizeClass)); + MOZ_ASSERT(newSizeClass < sizeClass); + freeLists->pushFront(newSizeClass, region); +} + +void BufferAllocator::recommitRegion(FreeRegion* region) { + MOZ_ASSERT(region->hasDecommittedPages); + MOZ_ASSERT(DecommitEnabled()); + + BufferChunk* chunk = BufferChunk::from(region); + uintptr_t startAddr = RoundUp(region->startAddr, PageSize); + uintptr_t endAddr = RoundDown(uintptr_t(region), PageSize); + + size_t startPage = (startAddr - uintptr_t(chunk)) / PageSize; + size_t endPage = (endAddr - uintptr_t(chunk)) / PageSize; + + // If the start of the region does not lie on a page boundary the page it is + // in should be committed as it must either contain the start of the chunk, a + // FreeRegion or an allocation. + MOZ_ASSERT_IF((region->startAddr % PageSize) != 0, + !chunk->decommittedPages.ref()[startPage - 1]); + + // The end of the region should be committed as it holds FreeRegion |region|. + MOZ_ASSERT(!chunk->decommittedPages.ref()[endPage]); + + MarkPagesInUseSoft(reinterpret_cast(startAddr), endAddr - startAddr); + for (size_t i = startPage; i != endPage; i++) { + chunk->decommittedPages.ref()[i] = false; + } + + region->hasDecommittedPages = false; +} + +static inline StallAndRetry ShouldStallAndRetry(bool inGC) { + return inGC ? StallAndRetry::Yes : StallAndRetry::No; +} + +bool BufferAllocator::allocNewChunk(bool inGC) { + GCRuntime* gc = &zone->runtimeFromMainThread()->gc; + AutoLockGCBgAlloc lock(gc); + ArenaChunk* baseChunk = gc->takeOrAllocChunk(ShouldStallAndRetry(inGC), lock); + if (!baseChunk) { + return false; + } + + CheckHighBitsOfPointer(baseChunk); + + // Ensure all memory is initially committed. + if (!baseChunk->decommittedPages.IsEmpty()) { + MOZ_ASSERT(DecommitEnabled()); + MarkPagesInUseSoft(baseChunk, ChunkSize); + } + + // Unpoison past the ChunkBase header. + void* ptr = reinterpret_cast(uintptr_t(baseChunk) + sizeof(ChunkBase)); + size_t size = ChunkSize - sizeof(ChunkBase); + SetMemCheckKind(ptr, size, MemCheckKind::MakeUndefined); + + BufferChunk* chunk = new (baseChunk) BufferChunk(zone); + chunk->allocatedDuringCollection = majorState != State::NotCollecting; + + mediumTenuredChunks.ref().pushBack(chunk); + + uintptr_t freeStart = uintptr_t(chunk) + FirstMediumAllocOffset; + uintptr_t freeEnd = uintptr_t(chunk) + ChunkSize; + + size_t sizeClass = SizeClassForFreeRegion(freeEnd - freeStart); + + ptr = reinterpret_cast(freeEnd - sizeof(FreeRegion)); + FreeRegion* region = new (ptr) FreeRegion(freeStart); + MOZ_ASSERT(region->getEnd() == freeEnd); + mediumFreeLists.ref().pushFront(sizeClass, region); + + return true; +} + +bool BufferAllocator::sweepChunk(BufferChunk* chunk, OwnerKind ownerKindToSweep, + bool shouldDecommit, FreeLists& freeLists) { + // Find all regions of free space in |chunk| and add them to the swept free + // lists. + + // TODO: Ideally we'd arrange things so we allocate from most-full chunks + // first. This could happen by sweeping all chunks and then sorting them by + // how much free space they had and then adding their free regions to the free + // lists in that order. + + GCRuntime* gc = &zone->runtimeFromAnyThread()->gc; + + bool hasNurseryOwnedAllocs = false; + + size_t freeStart = FirstMediumAllocOffset; + bool sweptAny = false; + size_t mallocHeapBytesFreed = 0; + + for (BufferChunkIter iter(chunk); !iter.done(); iter.next()) { + void* alloc = iter.get(); + + size_t bytes = chunk->allocBytes(alloc); + uintptr_t allocEnd = iter.getOffset() + bytes; + + bool nurseryOwned = chunk->isNurseryOwned(alloc); + OwnerKind ownerKind = OwnerKind(uint8_t(nurseryOwned)); + MOZ_ASSERT_IF(nurseryOwned, ownerKind == OwnerKind::Nursery); + MOZ_ASSERT_IF(!nurseryOwned, ownerKind == OwnerKind::Tenured); + bool canSweep = ownerKind == ownerKindToSweep; + bool shouldSweep = canSweep && !chunk->markBits.ref().isMarkedBlack(alloc); + + if (shouldSweep) { + // Dead. Update allocated bitmap, metadata and heap size accounting. + if (!nurseryOwned) { + mallocHeapBytesFreed += bytes; + } + chunk->setNurseryOwned(alloc, false); + chunk->setSizeClass(alloc, 0); + chunk->setAllocated(alloc, false); + PoisonAlloc(alloc, JS_SWEPT_TENURED_PATTERN, bytes, + MemCheckKind::MakeUndefined); + sweptAny = true; + } else { + // Alive. Add any free space before this allocation. + uintptr_t allocStart = iter.getOffset(); + if (freeStart != allocStart) { + addSweptRegion(chunk, freeStart, allocStart, shouldDecommit, !sweptAny, + freeLists); + } + freeStart = allocEnd; + if (canSweep) { + chunk->markBits.ref().unmarkOneBit(alloc, ColorBit::BlackBit); + } + if (nurseryOwned) { + MOZ_ASSERT(ownerKindToSweep == OwnerKind::Nursery); + hasNurseryOwnedAllocs = true; + } + sweptAny = false; + } + } + + if (mallocHeapBytesFreed) { + zone->mallocHeapSize.removeBytes(mallocHeapBytesFreed, true); + } + + if (freeStart == FirstMediumAllocOffset && + ownerKindToSweep != OwnerKind::None) { + // Chunk is empty. Give it back to the system. + bool allMemoryCommitted = chunk->decommittedPages.ref().IsEmpty(); + chunk->~BufferChunk(); + ArenaChunk* tenuredChunk = + ArenaChunk::emplace(chunk, gc, allMemoryCommitted); + AutoLockGC lock(gc); + gc->recycleChunk(tenuredChunk, lock); + return false; + } + + // Add any free space from the last allocation to the end of the chunk. + if (freeStart != ChunkSize) { + addSweptRegion(chunk, freeStart, ChunkSize, shouldDecommit, !sweptAny, + freeLists); + } + + chunk->hasNurseryOwnedAllocsAfterSweep = hasNurseryOwnedAllocs; + + return true; +} + +void BufferAllocator::addSweptRegion(BufferChunk* chunk, uintptr_t freeStart, + uintptr_t freeEnd, bool shouldDecommit, + bool expectUnchanged, + FreeLists& freeLists) { + // Add the region from |freeStart| to |freeEnd| to the appropriate swept free + // list based on its size. + + MOZ_ASSERT(freeStart >= FirstMediumAllocOffset); + MOZ_ASSERT(freeStart < freeEnd); + MOZ_ASSERT(freeEnd <= ChunkSize); + MOZ_ASSERT((freeStart % MinMediumAllocSize) == 0); + MOZ_ASSERT((freeEnd % MinMediumAllocSize) == 0); + MOZ_ASSERT_IF(shouldDecommit, DecommitEnabled()); + + // Decommit pages if |shouldDecommit| was specified, but leave space for + // the FreeRegion structure at the end. + bool anyDecommitted = false; + uintptr_t decommitStart = RoundUp(freeStart, PageSize); + uintptr_t decommitEnd = RoundDown(freeEnd - sizeof(FreeRegion), PageSize); + size_t endPage = decommitEnd / PageSize; + if (shouldDecommit && decommitEnd > decommitStart) { + void* ptr = reinterpret_cast(decommitStart + uintptr_t(chunk)); + MarkPagesUnusedSoft(ptr, decommitEnd - decommitStart); + size_t startPage = decommitStart / PageSize; + for (size_t i = startPage; i != endPage; i++) { + chunk->decommittedPages.ref()[i] = true; + } + anyDecommitted = true; + } else { + // Check for any previously decommitted pages. + uintptr_t startPage = RoundDown(freeStart, PageSize) / PageSize; + for (size_t i = startPage; i != endPage; i++) { + if (chunk->decommittedPages.ref()[i]) { + anyDecommitted = true; + } + } + } + + // The last page must have previously been either a live allocation or a + // FreeRegion, so it must already be committed. + MOZ_ASSERT(!chunk->decommittedPages.ref()[endPage]); + + freeStart += uintptr_t(chunk); + freeEnd += uintptr_t(chunk); + + size_t sizeClass = SizeClassForFreeRegion(freeEnd - freeStart); + addFreeRegion(&freeLists, sizeClass, freeStart, freeEnd, anyDecommitted, + ListPosition::Back, expectUnchanged); +} + +void BufferAllocator::freeMedium(void* alloc) { + // Free a medium sized allocation. This coalesces the free space with any + // neighboring free regions. Coalescing is necessary for resize to work + // properly. + + BufferChunk* chunk = BufferChunk::from(alloc); + MOZ_ASSERT(chunk->zone == zone); + + size_t bytes = chunk->allocBytes(alloc); + PoisonAlloc(alloc, JS_FREED_BUFFER_PATTERN, bytes, + MemCheckKind::MakeUndefined); + + if (isSweepingChunk(chunk)) { + return; // We can't free if the chunk is currently being swept. + } + + // Update heap size for tenured owned allocations. + if (!chunk->isNurseryOwned(alloc)) { + bool updateRetained = + majorState == State::Marking && !chunk->allocatedDuringCollection; + zone->mallocHeapSize.removeBytes(bytes, updateRetained); + } + + // Update metadata. + chunk->setNurseryOwned(alloc, false); + chunk->setSizeClass(alloc, 0); + + // Set region as not allocated and then clear mark bit. + chunk->setAllocated(alloc, false); + + // TODO: Since the mark bits are atomic, it's probably OK to unmark even if + // the chunk is currently being swept. If we get lucky the memory will be + // freed sooner. + chunk->markBits.ref().unmarkOneBit(alloc, ColorBit::BlackBit); + + FreeLists* freeLists = getChunkFreeLists(chunk); + + uintptr_t startAddr = uintptr_t(alloc); + uintptr_t endAddr = startAddr + bytes; + + // First check whether there is a free region following the allocation. + FreeRegion* region; + uintptr_t endOffset = endAddr & ChunkMask; + if (endOffset == 0 || chunk->isAllocated(endOffset)) { + // The allocation abuts the end of the chunk or another allocation. Add the + // allocation as a new free region. + // + // The new region is added to the front of relevant list so as to reuse + // recently freed memory preferentially. This may reduce fragmentation. See + // "The Memory Fragmentation Problem: Solved?" by Johnstone et al. + size_t sizeClass = SizeClassForFreeRegion(bytes); + region = addFreeRegion(freeLists, sizeClass, startAddr, endAddr, false, + ListPosition::Front); + } else { + // There is a free region following this allocation. Expand the existing + // region down to cover the newly freed space. + region = findFollowingFreeRegion(endAddr); + MOZ_ASSERT(region->startAddr == endAddr); + updateFreeRegionStart(freeLists, region, startAddr); + } + + // Next check for any preceding free region and coalesce. + FreeRegion* precRegion = findPrecedingFreeRegion(startAddr); + if (precRegion) { + if (freeLists) { + size_t sizeClass = SizeClassForFreeRegion(precRegion->size()); + freeLists->remove(sizeClass, precRegion); + } + + updateFreeRegionStart(freeLists, region, precRegion->startAddr); + if (precRegion->hasDecommittedPages) { + region->hasDecommittedPages = true; + } + } +} + +bool BufferAllocator::isSweepingChunk(BufferChunk* chunk) { + if (minorState == State::Sweeping && chunk->hasNurseryOwnedAllocs) { + // We are currently sweeping nursery owned allocations. + + // TODO: We could set a flag for nursery chunks allocated during minor + // collection to allow operations on chunks that are not being swept here. + + if (!hasMinorSweepDataToMerge) { +#ifdef DEBUG + { + AutoLock lock(this); + MOZ_ASSERT_IF(!hasMinorSweepDataToMerge, !minorSweepingFinished); + } +#endif + + // Likely no data to merge so don't bother taking the lock. + return true; + } + + // Merge swept data and recheck. + // + // TODO: It would be good to know how often this helps and if it is + // worthwhile. + mergeSweptData(); + if (minorState == State::Sweeping && chunk->hasNurseryOwnedAllocs) { + return true; + } + } + + if (majorState == State::Sweeping && !chunk->allocatedDuringCollection) { + // We are currently sweeping tenured owned allocations. + return true; + } + + return false; +} + +BufferAllocator::FreeRegion* BufferAllocator::addFreeRegion( + FreeLists* freeLists, size_t sizeClass, uintptr_t start, uintptr_t end, + bool anyDecommitted, ListPosition position, + bool expectUnchanged /* = false */) { +#ifdef DEBUG + MOZ_ASSERT(end - start >= SizeClassBytes(sizeClass)); + if (expectUnchanged) { + // We didn't free any allocations so there should already be a FreeRegion + // from |start| to |end|. + auto* region = FreeRegion::fromEndAddr(end); + region->check(); + MOZ_ASSERT(region->startAddr == start); + } +#endif + + void* ptr = reinterpret_cast(end - sizeof(FreeRegion)); + FreeRegion* region = new (ptr) FreeRegion(start, anyDecommitted); + MOZ_ASSERT(region->getEnd() == end); + + if (freeLists) { + if (position == ListPosition::Front) { + freeLists->pushFront(sizeClass, region); + } else { + freeLists->pushBack(sizeClass, region); + } + } + + return region; +} + +void BufferAllocator::updateFreeRegionStart(FreeLists* freeLists, + FreeRegion* region, + uintptr_t newStart) { + MOZ_ASSERT((newStart & ~ChunkMask) == (uintptr_t(region) & ~ChunkMask)); + MOZ_ASSERT(region->startAddr != newStart); + + size_t oldSize = region->size(); + region->startAddr = newStart; + + if (!freeLists) { + return; + } + + size_t currentSizeClass = SizeClassForFreeRegion(oldSize); + size_t newSizeClass = SizeClassForFreeRegion(region->size()); + if (currentSizeClass != newSizeClass) { + freeLists->remove(currentSizeClass, region); + freeLists->pushFront(newSizeClass, region); + } +} + +bool BufferAllocator::growMedium(void* alloc, size_t newBytes) { + MOZ_ASSERT(!IsSmallAllocSize(newBytes)); + MOZ_ASSERT(!IsLargeAllocSize(newBytes)); + newBytes = std::max(newBytes, MinMediumAllocSize); + MOZ_ASSERT(newBytes == GetGoodAllocSize(newBytes)); + + BufferChunk* chunk = BufferChunk::from(alloc); + MOZ_ASSERT(chunk->zone == zone); + + if (isSweepingChunk(chunk)) { + return false; // We can't grow if the chunk is currently being swept. + } + + size_t currentBytes = SizeClassBytes(chunk->sizeClass(alloc)); + MOZ_ASSERT(newBytes > currentBytes); + + uintptr_t endOffset = (uintptr_t(alloc) & ChunkMask) + currentBytes; + MOZ_ASSERT(endOffset <= ChunkSize); + if (endOffset == ChunkSize) { + return false; // Can't extend because we're at the end of the chunk. + } + + size_t endAddr = uintptr_t(chunk) + endOffset; + if (chunk->isAllocated(endOffset)) { + return false; // Can't extend because we abut another allocation. + } + + FreeRegion* region = findFollowingFreeRegion(endAddr); + MOZ_ASSERT(region->startAddr == endAddr); + + size_t extraBytes = newBytes - currentBytes; + if (region->size() < extraBytes) { + return false; // Can't extend because following free region is too small. + } + + size_t sizeClass = SizeClassForFreeRegion(region->size()); + + allocFromRegion(region, extraBytes, sizeClass); + + // If the allocation is in a chunk where we've cleared the free lists before + // sweeping we don't need to update the free lists. + if (FreeLists* freeLists = getChunkFreeLists(chunk)) { + updateFreeListsAfterAlloc(freeLists, region, sizeClass); + } + + chunk->setSizeClass(alloc, SizeClassForAlloc(newBytes)); + if (!chunk->isNurseryOwned(alloc)) { + bool updateRetained = + majorState == State::Marking && !chunk->allocatedDuringCollection; + updateHeapSize(extraBytes, true, updateRetained); + } + + return true; +} + +bool BufferAllocator::shrinkMedium(void* alloc, size_t newBytes) { + MOZ_ASSERT(!IsSmallAllocSize(newBytes)); + MOZ_ASSERT(!IsLargeAllocSize(newBytes)); + newBytes = std::max(newBytes, MinMediumAllocSize); + MOZ_ASSERT(newBytes == GetGoodAllocSize(newBytes)); + + BufferChunk* chunk = BufferChunk::from(alloc); + MOZ_ASSERT(chunk->zone == zone); + + if (isSweepingChunk(chunk)) { + return false; // We can't shrink if the chunk is currently being swept. + } + + size_t currentBytes = chunk->allocBytes(alloc); + if (newBytes == currentBytes) { + // Requested size is the same after adjusting to a valid medium alloc size. + return false; + } + + MOZ_ASSERT(newBytes < currentBytes); + size_t sizeChange = currentBytes - newBytes; + + // Update allocation size. + chunk->setSizeClass(alloc, SizeClassForAlloc(newBytes)); + if (!chunk->isNurseryOwned(alloc)) { + bool updateRetained = + majorState == State::Marking && !chunk->allocatedDuringCollection; + zone->mallocHeapSize.removeBytes(sizeChange, updateRetained); + } + + uintptr_t startOffset = uintptr_t(alloc) & ChunkMask; + uintptr_t oldEndOffset = startOffset + currentBytes; + uintptr_t newEndOffset = startOffset + newBytes; + MOZ_ASSERT(oldEndOffset <= ChunkSize); + + // Poison freed memory. + uintptr_t chunkAddr = uintptr_t(chunk); + PoisonAlloc(reinterpret_cast(chunkAddr + newEndOffset), + JS_SWEPT_TENURED_PATTERN, sizeChange, + MemCheckKind::MakeUndefined); + + FreeLists* freeLists = getChunkFreeLists(chunk); + + // If we abut another allocation then add a new free region. + if (oldEndOffset == ChunkSize || chunk->isAllocated(oldEndOffset)) { + size_t sizeClass = SizeClassForFreeRegion(sizeChange); + uintptr_t freeStart = chunkAddr + newEndOffset; + uintptr_t freeEnd = chunkAddr + oldEndOffset; + addFreeRegion(freeLists, sizeClass, freeStart, freeEnd, false, + ListPosition::Front); + return true; + } + + // Otherwise find the following free region and extend it down. + FreeRegion* region = findFollowingFreeRegion(chunkAddr + oldEndOffset); + MOZ_ASSERT(region->startAddr == chunkAddr + oldEndOffset); + updateFreeRegionStart(freeLists, region, chunkAddr + newEndOffset); + + return true; +} + +BufferAllocator::FreeLists* BufferAllocator::getChunkFreeLists( + BufferChunk* chunk) { + MOZ_ASSERT_IF(majorState == State::Sweeping, + chunk->allocatedDuringCollection); + + if (majorState == State::Marking && !chunk->allocatedDuringCollection) { + // The chunk has been queued for sweeping and the free lists cleared. + return nullptr; + } + + return &mediumFreeLists.ref(); +} + +BufferAllocator::FreeRegion* BufferAllocator::findFollowingFreeRegion( + uintptr_t startAddr) { + // Find the free region that starts at |startAddr|, which is not allocated and + // not at the end of the chunk. Always returns a region. + + uintptr_t offset = uintptr_t(startAddr) & ChunkMask; + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + MOZ_ASSERT(offset < ChunkSize); + MOZ_ASSERT((offset % MinMediumAllocSize) == 0); + + BufferChunk* chunk = BufferChunk::from(reinterpret_cast(startAddr)); + MOZ_ASSERT(!chunk->isAllocated(offset)); // Already marked as not allocated. + offset = chunk->findNextAllocated(offset); + MOZ_ASSERT(offset <= ChunkSize); + + auto* region = FreeRegion::fromEndOffset(chunk, offset); + MOZ_ASSERT(region->startAddr == startAddr); + + return region; +} + +BufferAllocator::FreeRegion* BufferAllocator::findPrecedingFreeRegion( + uintptr_t endAddr) { + // Find the free region, if any, that ends at |endAddr|, which may be + // allocated or at the start of the chunk. + + uintptr_t offset = uintptr_t(endAddr) & ChunkMask; + MOZ_ASSERT(offset >= FirstMediumAllocOffset); + MOZ_ASSERT(offset < ChunkSize); + MOZ_ASSERT((offset % MinMediumAllocSize) == 0); + + if (offset == FirstMediumAllocOffset) { + return nullptr; // Already at start of chunk. + } + + BufferChunk* chunk = BufferChunk::from(reinterpret_cast(endAddr)); + MOZ_ASSERT(!chunk->isAllocated(offset)); + offset = chunk->findPrevAllocated(offset); + + if (offset != ChunkSize) { + // Found a preceding allocation. + const void* alloc = chunk->ptrFromOffset(offset); + size_t bytes = SizeClassBytes(chunk->sizeClass(alloc)); + MOZ_ASSERT(uintptr_t(alloc) + bytes <= endAddr); + if (uintptr_t(alloc) + bytes == endAddr) { + // No free space between preceding allocation and |endAddr|. + return nullptr; + } + } + + auto* region = FreeRegion::fromEndAddr(endAddr); + +#ifdef DEBUG + region->check(); + if (offset != ChunkSize) { + const void* alloc = chunk->ptrFromOffset(offset); + size_t bytes = chunk->allocBytes(alloc); + MOZ_ASSERT(region->startAddr == uintptr_t(alloc) + bytes); + } else { + MOZ_ASSERT(region->startAddr == uintptr_t(chunk) + FirstMediumAllocOffset); + } +#endif + + return region; +} + +/* static */ +size_t BufferAllocator::SizeClassForAlloc(size_t bytes) { + MOZ_ASSERT(bytes >= MinMediumAllocSize); + MOZ_ASSERT(bytes <= MaxMediumAllocSize); + + size_t log2Size = mozilla::CeilingLog2(bytes); + MOZ_ASSERT((size_t(1) << log2Size) >= bytes); + MOZ_ASSERT(MinMediumAllocShift == mozilla::CeilingLog2(MinMediumAllocSize)); + MOZ_ASSERT(log2Size >= MinMediumAllocShift); + size_t sizeClass = log2Size - MinMediumAllocShift; + MOZ_ASSERT(sizeClass < MediumAllocClasses); + return sizeClass; +} + +/* static */ +size_t BufferAllocator::SizeClassForFreeRegion(size_t bytes) { + MOZ_ASSERT(bytes >= MinMediumAllocSize); + MOZ_ASSERT(bytes < ChunkSize); + + size_t log2Size = mozilla::FloorLog2(bytes); + MOZ_ASSERT((size_t(1) << log2Size) <= bytes); + MOZ_ASSERT(log2Size >= MinMediumAllocShift); + size_t sizeClass = + std::min(log2Size - MinMediumAllocShift, MediumAllocClasses - 1); + MOZ_ASSERT(sizeClass < MediumAllocClasses); + + return sizeClass; +} + +/* static */ +inline size_t BufferAllocator::SizeClassBytes(size_t sizeClass) { + MOZ_ASSERT(sizeClass < MediumAllocClasses); + // MONGODB MODIFICATION: Make 64-bit shift explicit for MSVC + return (size_t)1 << (sizeClass + MinMediumAllocShift); +} + +/* static */ +bool BufferAllocator::IsMediumAlloc(void* alloc) { + ChunkBase* chunk = js::gc::detail::GetGCAddressChunkBase(alloc); + return chunk->getKind() == ChunkKind::MediumBuffers; +} + +bool BufferAllocator::needLockToAccessBufferMap() const { + MOZ_ASSERT(CurrentThreadCanAccessZone(zone) || CurrentThreadIsPerformingGC()); + return minorState.refNoCheck() == State::Sweeping || + majorState.refNoCheck() == State::Sweeping; +} + +LargeBuffer* BufferAllocator::lookupLargeBuffer(void* alloc) { + MaybeLock lock; + return lookupLargeBuffer(alloc, lock); +} + +LargeBuffer* BufferAllocator::lookupLargeBuffer(void* alloc, MaybeLock& lock) { + MOZ_ASSERT(lock.isNothing()); + if (needLockToAccessBufferMap()) { + lock.emplace(this); + } + + auto ptr = largeAllocMap.ref().lookup(alloc); + MOZ_ASSERT(ptr); + LargeBuffer* buffer = ptr->value(); + MOZ_ASSERT(buffer->data() == alloc); + MOZ_ASSERT(buffer->zoneFromAnyThread() == zone); + return buffer; +} + +void* BufferAllocator::allocLarge(size_t bytes, bool nurseryOwned, bool inGC) { + bytes = RoundUp(bytes, ChunkSize); + MOZ_ASSERT(bytes > MaxMediumAllocSize); + MOZ_ASSERT(bytes >= bytes); + + // Allocate a small buffer the size of a LargeBuffer to hold the metadata. + static_assert(sizeof(LargeBuffer) <= MaxSmallAllocSize); + void* bufferPtr = allocSmall(sizeof(LargeBuffer), nurseryOwned); + if (!bufferPtr) { + return nullptr; + } + + // Large allocations are aligned to the chunk size, even if they are smaller + // than a chunk. This allows us to tell large buffer allocations apart by + // looking at the pointer alignment. + void* alloc = MapAlignedPages(bytes, ChunkSize, ShouldStallAndRetry(inGC)); + if (!alloc) { + return nullptr; + } + auto freeGuard = mozilla::MakeScopeExit([&]() { UnmapPages(alloc, bytes); }); + + CheckHighBitsOfPointer(alloc); + + auto* buffer = new (bufferPtr) LargeBuffer(alloc, bytes, nurseryOwned); + + { + MaybeLock lock; + if (needLockToAccessBufferMap()) { + lock.emplace(this); + } + if (!largeAllocMap.ref().putNew(alloc, buffer)) { + return nullptr; + } + } + + freeGuard.release(); + + if (nurseryOwned) { + largeNurseryAllocs.ref().pushBack(buffer); + } else { + buffer->allocatedDuringCollection = majorState != State::NotCollecting; + largeTenuredAllocs.ref().pushBack(buffer); + } + + // Update memory accounting and trigger an incremental slice if needed. + if (!nurseryOwned) { + bool checkThresholds = !inGC; + updateHeapSize(bytes, checkThresholds, false); + } + + MOZ_ASSERT(IsLargeAlloc(alloc)); + return alloc; +} + +void BufferAllocator::updateHeapSize(size_t bytes, bool checkThresholds, + bool updateRetainedSize) { + // Update memory accounting and trigger an incremental slice if needed. + // TODO: This will eventually be attributed to gcHeapSize. + zone->mallocHeapSize.addBytes(bytes, updateRetainedSize); + if (checkThresholds) { + GCRuntime* gc = &zone->runtimeFromAnyThread()->gc; + gc->maybeTriggerGCAfterMalloc(zone); + } +} + +/* static */ +bool BufferAllocator::IsLargeAlloc(void* alloc) { + return (uintptr_t(alloc) & ChunkMask) == 0; +} + +bool BufferAllocator::isLargeAllocMarked(void* alloc) { + LargeBuffer* buffer = lookupLargeBuffer(alloc); + return buffer->headerCell()->isMarkedAny(); +} + +bool BufferAllocator::markLargeTenuredBuffer(LargeBuffer* buffer) { + MOZ_ASSERT(!buffer->isNurseryOwned); + + if (buffer->allocatedDuringCollection) { + return false; + } + + // Bug 1961755: This method can return false positives. A fully atomic version + // would be preferable in this case. + return buffer->headerCell()->markIfUnmarkedThreadSafe(MarkColor::Black); +} + +bool BufferAllocator::sweepLargeTenured(LargeBuffer* buffer) { + MOZ_ASSERT(!buffer->isNurseryOwned); + MOZ_ASSERT(buffer->zoneFromAnyThread() == zone); + MOZ_ASSERT(!buffer->isInList()); + + if (buffer->headerCell()->isMarkedAny()) { + return true; + } + + MaybeLock lock(std::in_place, this); + unmapLarge(buffer, true, lock); + return false; +} + +void BufferAllocator::freeLarge(void* alloc) { + MaybeLock lock; + LargeBuffer* buffer = lookupLargeBuffer(alloc, lock); + MOZ_ASSERT(buffer->zone() == zone); + + DebugOnlyPoison(alloc, JS_FREED_BUFFER_PATTERN, buffer->allocBytes(), + MemCheckKind::MakeUndefined); + + if (!buffer->isNurseryOwned && majorState == State::Sweeping && + !buffer->allocatedDuringCollection) { + return; // Large allocations are currently being swept. + } + + MOZ_ASSERT(buffer->isInList()); + + if (buffer->isNurseryOwned) { + largeNurseryAllocs.ref().remove(buffer); + } else if (majorState == State::Marking && + !buffer->allocatedDuringCollection) { + largeTenuredAllocsToSweep.ref().remove(buffer); + } else { + largeTenuredAllocs.ref().remove(buffer); + } + + unmapLarge(buffer, false, lock); +} + +bool BufferAllocator::shrinkLarge(LargeBuffer* buffer, size_t newBytes) { + MOZ_ASSERT(IsLargeAllocSize(newBytes)); +#ifdef XP_WIN + // Can't unmap part of a region mapped with VirtualAlloc on Windows. + // + // It is possible to decommit the physical pages so we could do that and + // track virtual size as well as committed size. This would also allow us to + // grow the allocation again if necessary. + return false; +#else + MOZ_ASSERT(buffer->zone() == zone); + + if (!buffer->isNurseryOwned && majorState == State::Sweeping && + !buffer->allocatedDuringCollection) { + return false; // Large allocations are currently being swept. + } + + MOZ_ASSERT(buffer->isInList()); + + newBytes = RoundUp(newBytes, ChunkSize); + size_t oldBytes = buffer->bytes; + MOZ_ASSERT(oldBytes > newBytes); + size_t shrinkBytes = oldBytes - newBytes; + + if (!buffer->isNurseryOwned) { + zone->mallocHeapSize.removeBytes(shrinkBytes, false); + } + + buffer->bytes = newBytes; + + void* endPtr = reinterpret_cast(uintptr_t(buffer->data()) + newBytes); + UnmapPages(endPtr, shrinkBytes); + + return true; +#endif +} + +void BufferAllocator::unmapLarge(LargeBuffer* buffer, bool isSweeping, + MaybeLock& lock) { + MOZ_ASSERT(buffer->zoneFromAnyThread() == zone); + MOZ_ASSERT(!buffer->isInList()); + MOZ_ASSERT_IF(isSweeping || needLockToAccessBufferMap(), lock.isSome()); + +#ifdef DEBUG + auto ptr = largeAllocMap.ref().lookup(buffer->data()); + MOZ_ASSERT(ptr && ptr->value() == buffer); +#endif + largeAllocMap.ref().remove(buffer->data()); + + // Drop the lock now we've updated the map. + lock.reset(); + + size_t bytes = buffer->bytes; + + if (!buffer->isNurseryOwned) { + zone->mallocHeapSize.removeBytes(bytes, isSweeping); + } + + UnmapPages(buffer->data(), bytes); +} + +#include "js/Printer.h" +#include "util/GetPidProvider.h" + +static const char* const BufferAllocatorStatsPrefix = "BufAllc:"; + +#define FOR_EACH_BUFFER_STATS_FIELD(_) \ + _("PID", 7, "%7zu", pid) \ + _("Runtime", 14, "0x%12p", runtime) \ + _("Timestamp", 10, "%10.6f", timestamp.ToSeconds()) \ + _("Reason", 20, "%-20.20s", reason) \ + _("", 2, "%2s", "") \ + _("TotalKB", 8, "%8zu", totalBytes / 1024) \ + _("UsedKB", 8, "%8zu", usedBytes / 1024) \ + _("FreeKB", 8, "%8zu", freeBytes / 1024) \ + _("Zs", 3, "%3zu", zoneCount) \ + _("", 7, "%7s", "") \ + _("MNCs", 6, "%6zu", mediumMixedChunks) \ + _("MTCs", 6, "%6zu", mediumTenuredChunks) \ + _("FRs", 6, "%6zu", freeRegions) \ + _("LNAs", 6, "%6zu", largeNurseryAllocs) \ + _("LTAs", 6, "%6zu", largeTenuredAllocs) + +/* static */ +void BufferAllocator::printStatsHeader(FILE* file) { + Sprinter sprinter; + if (!sprinter.init()) { + return; + } + sprinter.put(BufferAllocatorStatsPrefix); + +#define PRINT_METADATA_NAME(name, width, _1, _2) \ + sprinter.printf(" %-*s", width, name); + + FOR_EACH_BUFFER_STATS_FIELD(PRINT_METADATA_NAME) +#undef PRINT_METADATA_NAME + + sprinter.put("\n"); + + JS::UniqueChars str = sprinter.release(); + if (!str) { + return; + } + fputs(str.get(), file); +} + +/* static */ +void BufferAllocator::printStats(GCRuntime* gc, mozilla::TimeStamp creationTime, + bool isMajorGC, FILE* file) { + Sprinter sprinter; + if (!sprinter.init()) { + return; + } + sprinter.put(BufferAllocatorStatsPrefix); + + size_t pid = getpid(); + JSRuntime* runtime = gc->rt; + mozilla::TimeDuration timestamp = mozilla::TimeStamp::Now() - creationTime; + const char* reason = isMajorGC ? "post major slice" : "pre minor GC"; + + size_t zoneCount = 0; + size_t usedBytes = 0; + size_t freeBytes = 0; + size_t adminBytes = 0; + size_t mediumMixedChunks = 0; + size_t mediumTenuredChunks = 0; + size_t freeRegions = 0; + size_t largeNurseryAllocs = 0; + size_t largeTenuredAllocs = 0; + for (AllZonesIter zone(gc); !zone.done(); zone.next()) { + zoneCount++; + zone->bufferAllocator.getStats(usedBytes, freeBytes, adminBytes, + mediumMixedChunks, mediumTenuredChunks, + freeRegions, largeNurseryAllocs, + largeTenuredAllocs); + } + + size_t totalBytes = usedBytes + freeBytes + adminBytes; + +#define PRINT_FIELD_VALUE(_1, _2, format, value) \ + sprinter.printf(" " format, value); + + FOR_EACH_BUFFER_STATS_FIELD(PRINT_FIELD_VALUE) +#undef PRINT_FIELD_VALUE + + sprinter.put("\n"); + + JS::UniqueChars str = sprinter.release(); + if (!str) { + return; + } + + fputs(str.get(), file); +} + +size_t BufferAllocator::getSizeOfNurseryBuffers() { + maybeMergeSweptData(); + + MOZ_ASSERT(minorState == State::NotCollecting); + MOZ_ASSERT(majorState == State::NotCollecting); + + size_t bytes = 0; + + for (BufferChunk* chunk : mediumMixedChunks.ref()) { + for (BufferChunkIter alloc(chunk); !alloc.done(); alloc.next()) { + if (chunk->isNurseryOwned(alloc)) { + bytes += chunk->allocBytes(alloc); + } + } + } + + for (const LargeBuffer* buffer : largeNurseryAllocs.ref()) { + bytes += buffer->allocBytes(); + } + + return bytes; +} + +void BufferAllocator::addSizeOfExcludingThis(size_t* usedBytesOut, + size_t* freeBytesOut, + size_t* adminBytesOut) { + maybeMergeSweptData(); + + MOZ_ASSERT(minorState == State::NotCollecting); + MOZ_ASSERT(majorState == State::NotCollecting); + + size_t usedBytes = 0; + size_t freeBytes = 0; + size_t adminBytes = 0; + size_t mediumMixedChunks = 0; + size_t mediumTenuredChunks = 0; + size_t freeRegions = 0; + size_t largeNurseryAllocs = 0; + size_t largeTenuredAllocs = 0; + getStats(usedBytes, freeBytes, adminBytes, mediumMixedChunks, + mediumTenuredChunks, freeRegions, largeNurseryAllocs, + largeTenuredAllocs); + + *usedBytesOut += usedBytes; + *freeBytesOut += freeBytes; + *adminBytesOut += adminBytes; +} + +void BufferAllocator::getStats(size_t& usedBytes, size_t& freeBytes, + size_t& adminBytes, + size_t& mediumNurseryChunkCount, + size_t& mediumTenuredChunkCount, + size_t& freeRegions, + size_t& largeNurseryAllocCount, + size_t& largeTenuredAllocCount) { + maybeMergeSweptData(); + + MOZ_ASSERT(minorState == State::NotCollecting); + + for (const BufferChunk* chunk : mediumMixedChunks.ref()) { + (void)chunk; + mediumNurseryChunkCount++; + usedBytes += ChunkSize - FirstMediumAllocOffset; + adminBytes += FirstMediumAllocOffset; + } + for (const BufferChunk* chunk : mediumTenuredChunks.ref()) { + (void)chunk; + mediumTenuredChunkCount++; + usedBytes += ChunkSize - FirstMediumAllocOffset; + adminBytes += FirstMediumAllocOffset; + } + for (const LargeBuffer* buffer : largeNurseryAllocs.ref()) { + largeNurseryAllocCount++; + usedBytes += buffer->allocBytes(); + adminBytes += sizeof(LargeBuffer); + } + for (const LargeBuffer* buffer : largeTenuredAllocs.ref()) { + largeTenuredAllocCount++; + usedBytes += buffer->allocBytes(); + adminBytes += sizeof(LargeBuffer); + } + for (const FreeList& freeList : mediumFreeLists.ref()) { + for (const FreeRegion* region : freeList) { + freeRegions++; + size_t size = region->size(); + MOZ_ASSERT(usedBytes >= size); + usedBytes -= size; + freeBytes += size; + } + } +} + +JS::ubi::Node::Size JS::ubi::Concrete::size( + mozilla::MallocSizeOf mallocSizeOf) const { + return get().allocBytes(); +} + +const char16_t JS::ubi::Concrete::concreteTypeName[] = + u"SmallBuffer"; diff --git a/src/third_party/mozjs/extract/js/src/gc/BufferAllocator.h b/src/third_party/mozjs/extract/js/src/gc/BufferAllocator.h new file mode 100644 index 00000000000..e3a96147636 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/gc/BufferAllocator.h @@ -0,0 +1,526 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// GC-internal header file for the buffer allocator. + +#ifndef gc_BufferAllocator_h +#define gc_BufferAllocator_h + +#include "mozilla/Array.h" +#include "mozilla/Atomics.h" +#include "mozilla/BitSet.h" +#include "mozilla/HashTable.h" +#include "mozilla/Maybe.h" +#include "mozilla/TimeStamp.h" + +#include +#include +#include + +#include "jstypes.h" // JS_PUBLIC_API + +#include "ds/SlimLinkedList.h" +#include "js/HeapAPI.h" +#include "threading/LockGuard.h" +#include "threading/Mutex.h" +#include "threading/ProtectedData.h" + +class JS_PUBLIC_API JSTracer; + +namespace JS { +class JS_PUBLIC_API Zone; +} // namespace JS + +namespace js { + +class GCMarker; +class Nursery; + +namespace gc { + +enum class AllocKind : uint8_t; + +struct BufferChunk; +struct Cell; +class GCRuntime; +struct LargeBuffer; + +// BufferAllocator allocates dynamically sized blocks of memory which can be +// reclaimed by the garbage collector and are associated with GC things. +// +// Although these blocks can be reclaimed by GC, explicit free and resize is +// also supported. This is important for buffers that can grow or shrink. +// +// The allocator uses a different strategy depending on the size of the +// allocation requested. There are three size ranges, divided as follows: +// +// Size: Kind: Allocator implementation: +// 16 B - 128 B Small Uses the cell (arena) allocator +// 256 B - 512 KB Medium Uses a free list allocator +// 1 MB - Large Uses the OS page allocator (e.g. mmap) +// +// The smallest supported allocation size is 16 bytes. This will be used for a +// dynamic slots allocation with zero slots to set a unique ID on a native +// object. This will be the size of two Values, i.e. 16 bytes. +// +// Supported operations +// -------------------- +// +// - Allocate a buffer. Buffers are always owned by a GC cell, and the +// allocator tracks whether the owner is in the nursery or the tenured heap. +// +// - Trace an edge to buffer. When the owning cell is traced it must trace the +// edge to the buffer. This will mark the buffer in a GC and prevent it from +// being swept. +// +// - Free a buffer. This allows uniquely owned buffers to be freed and reused +// without waiting for the next GC. It is a hint only and is not supported +// for all buffer kinds. +// +// - Reallocate a buffer. This allows uniquely owned buffers to be resized, +// possibly in-place. This is important for performance on some benchmarks. +// +// Integration with the rest of the GC +// ----------------------------------- +// +// The GC calls the allocator at several points during minor and major GC (at +// the start, when sweeping starts and at the end). Allocations are swept on a +// background thread and the memory used by unmarked allocations is reclaimed. +// +// The allocator tries hard to avoid locking, and where it is necessary tries to +// minimize the time spent holding locks. A lock is required to allocate a chunk +// but after that no locks are required to allocate on the main thread, even +// when off-thread sweeping is taking place. This is achieved by moving data to +// be swept to separate containers from those used for allocation on the main +// thread. Synchronization is required to merge data about swept allocations at +// the end of sweeping. +// +// Small allocations +// ----------------- +// +// These are implemented by the cell allocator and are allocated in arenas (slab +// allocation). +// +// Note: currently we do not allocate these in the nursery because nursery-owned +// buffers are allocated directly in the nursery without going through this +// allocation API. +// +// Medium allocations +// ------------------ +// +// These are allocated in their own zone-specific chunks using a segregated free +// list strategy. This is the main part of the allocator. +// +// The requested allocation size is used to pick a size class, which is used to +// index into an array giving a list of free regions of suitable size. The first +// region in the list is used and its start address updated; it may also be +// moved to a different list if it is now empty or too small to satisfy further +// allocations for this size class. A bitmap in the chunk header is used to +// track the start offsets of allocations. +// +// Sweeping works by processing a list of chunks, scanning each one for +// allocated but unmarked buffers and rebuilding the free region data for that +// chunk. Sweeping happens separately for minor and major GC and only +// nursery-owned or tenured-owned buffers are swept at one time. This means that +// chunks containing nursery-owned allocations are swept twice during a major +// GC, once to sweep nursery-owned allocations and once for tenured-owned +// allocations. This is required because the sweeping happens at different +// times. +// +// Chunks containing nursery-owned buffers are stored in a separate list to +// chunks that only contain tenured-owned buffers to reduce the number of chunks +// that need to be swept for minor GC. They are stored in |mediumMixedChunks| +// and are moved to |mediumMixedChunksToSweep| at the start of minor GC. They +// are then swept on a background thread and are placed in +// |sweptMediumMixedChunks| if they are not freed. From there they can merged +// back into one of the main thread lists (since they may no longer contain +// nursery-owned buffers). +// +// Chunks containing tenured-owned buffers are stored in |mediumTenuredChunks| +// and are moved to |mediumTenuredChunksToSweep| at the start of major GC. They +// are unavailable for allocation after this point and will be swept on a +// background thread and placed in |sweptMediumTenuredChunks| if they are not +// freed. From there they will be merged back into |mediumTenuredChunks|. This +// means that allocation during an incremental GC will allocate a new +// chunk. +// +// Merging swept data requires taking a lock and so only happens when +// necessary. This happens when a new chunk is needed or at various points +// during GC. During sweeping no additional synchronization is required for +// allocation. +// +// Since major GC requires doing a minor GC at the start and we don't want to +// have to wait for minor GC sweeping to finish there is an optimization where +// chunks containing nursery-owned buffers swept as part of minor GC at the +// start of a major GC are moved directly from |sweptMediumMixedChunks| to +// |mediumTenuredChunksToSweep| at the end of minor GC sweeping. This is +// controlled by the |majorStartedWhileMinorSweeping| flag. +// +// Similarly, if a major GC finishes while minor GC is sweeping then rather than +// waiting for it to finish we set the |majorFinishedWhileMinorSweeping| flag so +// that we clear the |allocatedDuringCollection| for these chunks the end of the +// minor sweeping. +// +// Free works by extending neighboring free regions to cover the freed +// allocation or adding a new one if necessary. Free regions are found by +// checking the allocated bitmap. Free is not supported if the containing chunk +// is currently being swept off-thread. +// +// Reallocation works by resizing in place if possible. It is always possible to +// shrink a medium allocation in place if the target size is still +// medium. In-place growth is possible if there is enough free space following +// the allocation. This is not supported if the containing chunk is currently +// being swept off-thread. If not possible, a new allocation is made and the +// contents of the buffer copied. +// +// Large allocations +// ----------------- +// +// These are implemented using the OS page allocator. Allocations of this size +// are relatively rare and not much attempt is made to optimize them. They are +// chunk aligned which allows them to be distinguished from the other allocation +// kinds by checking the low bits the pointer. +// +// Naming conventions +// ------------------ +// +// The following conventions are used in the code: +// - alloc: client pointer to allocated memory +// - buffer: pointer to per-allocation metadata +// + +class BufferAllocator : public SlimLinkedListElement { + public: + static constexpr size_t MinMediumAllocShift = 8; // 256 B + static constexpr size_t MaxMediumAllocShift = 19; // 512 KB + + static constexpr size_t MediumAllocClasses = + MaxMediumAllocShift - MinMediumAllocShift + 1; + + // An RAII guard to lock and unlock the buffer allocator lock. + class AutoLock : public LockGuard { + public: + explicit AutoLock(GCRuntime* gc); + explicit AutoLock(BufferAllocator* allocator); + friend class UnlockGuard; + }; + + // A lock guard that is locked only when needed. + using MaybeLock = mozilla::Maybe; + + private: + using BufferChunkList = SlimLinkedList; + + struct FreeRegion; + using FreeList = SlimLinkedList; + + // Segregated free list: an array of free lists, one per size class. + class FreeLists { + using FreeListArray = mozilla::Array; + FreeListArray lists; + mozilla::BitSet available; + + public: + FreeLists() = default; + + FreeLists(FreeLists&& other); + FreeLists& operator=(FreeLists&& other); + + using const_iterator = FreeListArray::const_iterator; + auto begin() const { return lists.begin(); } + auto end() const { return lists.end(); } + + // Returns SIZE_MAX if none available. + size_t getFirstAvailableSizeClass(size_t minSizeClass) const; + + FreeRegion* getFirstRegion(size_t sizeClass); + + void pushFront(size_t sizeClass, FreeRegion* region); + void pushBack(size_t sizeClass, FreeRegion* region); + + void append(FreeLists&& other); + void prepend(FreeLists&& other); + + void remove(size_t sizeClass, FreeRegion* region); + + void clear(); + + template + void eraseIf(Pred&& pred); + + void assertEmpty() const; + void assertContains(size_t sizeClass, FreeRegion* region) const; + void checkAvailable() const; + }; + + using LargeAllocList = SlimLinkedList; + + using LargeAllocMap = + mozilla::HashMap>; + + enum class State : uint8_t { NotCollecting, Marking, Sweeping }; + + enum class OwnerKind : uint8_t { Tenured = 0, Nursery, None }; + + // The zone this allocator is associated with. + MainThreadOrGCTaskData zone; + + // Chunks that contain medium buffers. May contain both nursery-owned and + // tenured-owned buffers. + MainThreadData mediumMixedChunks; + + // Chunks that contain only tenured-owned medium sized buffers. + MainThreadData mediumTenuredChunks; + + // Free lists for medium sized buffers. Used for allocation. + MainThreadData mediumFreeLists; + + // Chunks that may contain nursery-owned buffers waiting to be swept during a + // minor GC. Populated from |mediumMixedChunks|. + MainThreadOrGCTaskData mediumMixedChunksToSweep; + + // Chunks that contain only tenured-owned buffers waiting to be swept during a + // major GC. Populated from |mediumTenuredChunks|. + MainThreadOrGCTaskData mediumTenuredChunksToSweep; + + // Chunks that have been swept and their associated free lists. + MutexData sweptMediumMixedChunks; + MutexData sweptMediumTenuredChunks; + MutexData sweptMediumNurseryFreeLists; + MutexData sweptMediumTenuredFreeLists; + + // List of large nursery-owned buffers. + MainThreadData largeNurseryAllocs; + + // List of large tenured-owned buffers. + MainThreadData largeTenuredAllocs; + + // Map from allocation pointer to buffer metadata for large buffers. + // Access requires holding the mutex during sweeping. + MainThreadOrGCTaskData largeAllocMap; + + // Large buffers waiting to be swept. + MainThreadOrGCTaskData largeNurseryAllocsToSweep; + MainThreadOrGCTaskData largeTenuredAllocsToSweep; + + // Large buffers that have been swept. + MutexData sweptLargeTenuredAllocs; + + // Flag to indicate that data from minor sweeping is available to be + // merged. This includes chunks in the sweptMediumMixedChunks or + // sweptMediumTenuredChunks lists and the minorSweepingFinished flag. + mozilla::Atomic hasMinorSweepDataToMerge; + + // GC state for minor and major GC. + MainThreadData minorState; + MainThreadData majorState; + + // Flags to tell the main thread that sweeping has finished and the state + // should be updated. + MutexData minorSweepingFinished; + MutexData majorSweepingFinished; + + // A major GC was started while a minor GC was still sweeping. Chunks by the + // minor GC will be moved directly to the list of chunks to sweep for the + // major GC. This happens for the minor GC at the start of every major GC. + MainThreadData majorStartedWhileMinorSweeping; + + // A major GC finished while a minor GC was still sweeping. Some post major GC + // cleanup will be deferred to the end of the minor sweeping. + MainThreadData majorFinishedWhileMinorSweeping; + +#ifdef DEBUG + MainThreadData movingGCInProgress; +#endif + + public: + explicit BufferAllocator(JS::Zone* zone); + ~BufferAllocator(); + + static inline size_t GetGoodAllocSize(size_t requiredBytes); + static inline size_t GetGoodElementCount(size_t requiredElements, + size_t elementSize); + static inline size_t GetGoodPower2AllocSize(size_t requiredBytes); + static inline size_t GetGoodPower2ElementCount(size_t requiredElements, + size_t elementSize); + static bool IsBufferAlloc(void* alloc); + + void* alloc(size_t bytes, bool nurseryOwned); + void* allocInGC(size_t bytes, bool nurseryOwned); + void* realloc(void* alloc, size_t bytes, bool nurseryOwned); + void free(void* alloc); + size_t getAllocSize(void* alloc); + bool isNurseryOwned(void* alloc); + + void startMinorCollection(MaybeLock& lock); + bool startMinorSweeping(); + void sweepForMinorCollection(); + + void startMajorCollection(MaybeLock& lock); + void startMajorSweeping(MaybeLock& lock); + void sweepForMajorCollection(bool shouldDecommit); + void finishMajorCollection(const AutoLock& lock); + void prepareForMovingGC(); + void fixupAfterMovingGC(); + void clearMarkStateAfterBarrierVerification(); + + bool isEmpty() const; + + void traceEdge(JSTracer* trc, Cell* owner, void** bufferp, const char* name); + bool markTenuredAlloc(void* alloc); + bool isMarkedBlack(void* alloc); + + // For debugging, used to implement GetMarkInfo. Returns false for allocations + // being swept on another thread. + bool isPointerWithinMediumOrLargeBuffer(void* ptr); + + Mutex& lock() const; + + size_t getSizeOfNurseryBuffers(); + + void addSizeOfExcludingThis(size_t* usedBytesOut, size_t* freeBytesOut, + size_t* adminBytesOut); + + static void printStatsHeader(FILE* file); + static void printStats(GCRuntime* gc, mozilla::TimeStamp creationTime, + bool isMajorGC, FILE* file); + void getStats(size_t& usedBytes, size_t& freeBytes, size_t& adminBytes, + size_t& mediumNurseryChunkCount, + size_t& mediumTenuredChunkCount, size_t& freeRegions, + size_t& largeNurseryAllocCount, size_t& largeTenuredAllocCount); + +#ifdef DEBUG + void checkGCStateNotInUse(); + void checkGCStateNotInUse(MaybeLock& lock); + void checkGCStateNotInUse(const AutoLock& lock); +#endif + + private: + void markNurseryOwnedAlloc(void* alloc, bool ownerWasTenured); + friend class js::Nursery; + + void maybeMergeSweptData(); + void maybeMergeSweptData(MaybeLock& lock); + void mergeSweptData(); + void mergeSweptData(const AutoLock& lock); + void abortMajorSweeping(const AutoLock& lock); + void clearAllocatedDuringCollectionState(const AutoLock& lock); + + // Small allocation methods: + + static inline bool IsSmallAllocSize(size_t bytes); + static bool IsSmallAlloc(void* alloc); + + static SmallBuffer* GetSmallBuffer(void* alloc); + friend struct LargeBuffer; + + void* allocSmall(size_t bytes, bool nurseryOwned); + void* allocSmallInGC(size_t bytes, bool nurseryOwned); + void traceSmallAlloc(JSTracer* trc, Cell* owner, void** allocp, + const char* name); + void markSmallNurseryOwnedBuffer(SmallBuffer* buffer, bool ownerWasTenured); + bool markSmallTenuredAlloc(void* alloc); + + static AllocKind AllocKindForSmallAlloc(size_t bytes); + + // Medium allocation methods: + + static bool IsMediumAlloc(void* alloc); + + void* allocMedium(size_t bytes, bool nurseryOwned, bool inGC); + void* bumpAllocOrRetry(size_t sizeClass, bool inGC); + void* bumpAlloc(size_t sizeClass); + void* allocFromRegion(FreeRegion* region, size_t requestedBytes, + size_t sizeClass); + void updateFreeListsAfterAlloc(FreeLists* freeLists, FreeRegion* region, + size_t sizeClass); + void recommitRegion(FreeRegion* region); + bool allocNewChunk(bool inGC); + bool sweepChunk(BufferChunk* chunk, OwnerKind ownerKindToSweep, + bool shouldDecommit, FreeLists& freeLists); + void addSweptRegion(BufferChunk* chunk, uintptr_t freeStart, + uintptr_t freeEnd, bool shouldDecommit, + bool expectUnchanged, FreeLists& freeLists); + void freeMedium(void* alloc); + bool growMedium(void* alloc, size_t newBytes); + bool shrinkMedium(void* alloc, size_t newBytes); + FreeRegion* findFollowingFreeRegion(uintptr_t start); + FreeRegion* findPrecedingFreeRegion(uintptr_t start); + enum class ListPosition { Front, Back }; + FreeRegion* addFreeRegion(FreeLists* freeLists, size_t sizeClass, + uintptr_t start, uintptr_t end, bool anyDecommitted, + ListPosition position, + bool expectUnchanged = false); + void updateFreeRegionStart(FreeLists* freeLists, FreeRegion* region, + uintptr_t newStart); + FreeLists* getChunkFreeLists(BufferChunk* chunk); + bool isSweepingChunk(BufferChunk* chunk); + void traceMediumAlloc(JSTracer* trc, Cell* owner, void** allocp, + const char* name); + bool isMediumBufferNurseryOwned(void* alloc) const; + void markMediumNurseryOwnedBuffer(void* alloc, bool ownerWasTenured); + bool markMediumTenuredAlloc(void* alloc); + + // Get the size class for an allocation. This rounds up to a class that is + // large enough to hold the required size. + static size_t SizeClassForAlloc(size_t bytes); + + // Get the maximum size class of allocations that can use a free region. This + // rounds down to the largest class that can fit in this region. + static size_t SizeClassForFreeRegion(size_t bytes); + + static size_t SizeClassBytes(size_t sizeClass); + friend struct BufferChunk; + + // Large allocation methods: + + static inline bool IsLargeAllocSize(size_t bytes); + static bool IsLargeAlloc(void* alloc); + + void* allocLarge(size_t bytes, bool nurseryOwned, bool inGC); + bool sweepLargeTenured(LargeBuffer* buffer); + void freeLarge(void* alloc); + bool shrinkLarge(LargeBuffer* buffer, size_t newBytes); + void unmapLarge(LargeBuffer* buffer, bool isSweeping, MaybeLock& lock); + void traceLargeAlloc(JSTracer* trc, Cell* owner, void** allocp, + const char* name); + void markLargeNurseryOwnedBuffer(LargeBuffer* buffer, bool ownerWasTenured); + bool markLargeTenuredBuffer(LargeBuffer* buffer); + bool isLargeAllocMarked(void* alloc); + + // Lookup a large buffer by pointer in the map. + LargeBuffer* lookupLargeBuffer(void* alloc); + LargeBuffer* lookupLargeBuffer(void* alloc, MaybeLock& lock); + bool needLockToAccessBufferMap() const; + + void updateHeapSize(size_t bytes, bool checkThresholds, + bool updateRetainedSize); + +#ifdef DEBUG + void checkChunkListGCStateNotInUse(BufferChunkList& chunks, + bool hasNurseryOwnedAllocs, + bool allowAllocatedDuringCollection); + void checkChunkGCStateNotInUse(BufferChunk* chunk, + bool allowAllocatedDuringCollection); + void checkAllocListGCStateNotInUse(LargeAllocList& list, bool isNurseryOwned); + void verifyChunk(BufferChunk* chunk, bool hasNurseryOwnedAllocs); + void verifyFreeRegion(BufferChunk* chunk, uintptr_t endOffset, + size_t expectedSize); +#endif +}; + +// Internal data structures defined here so that users can get their size. + +#ifdef DEBUG +// Magic check values used debug builds. +static constexpr uint32_t LargeBufferCheckValue = 0xBFA110C2; +static constexpr uint32_t FreeRegionCheckValue = 0xBFA110C3; +#endif + +} // namespace gc +} // namespace js + +#endif // gc_BufferAllocator_h diff --git a/src/third_party/mozjs/extract/js/src/gc/Cell.h b/src/third_party/mozjs/extract/js/src/gc/Cell.h index 05f38d7c839..4594d38c98e 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Cell.h +++ b/src/third_party/mozjs/extract/js/src/gc/Cell.h @@ -32,9 +32,11 @@ extern bool RuntimeFromMainThreadIsHeapMajorCollecting( JS::shadow::Zone* shadowZone); #ifdef DEBUG -// Barriers can't be triggered during backend Ion compilation, which may run on -// a helper thread. +// Barriers can't be triggered during offthread baseline or Ion +// compilation, which may run on a helper thread. +extern bool CurrentThreadIsBaselineCompiling(); extern bool CurrentThreadIsIonCompiling(); +extern bool CurrentThreadIsOffThreadCompiling(); #endif extern void TraceManuallyBarrieredGenericPointerEdge(JSTracer* trc, @@ -240,9 +242,7 @@ class TenuredCell : public Cell { return true; } - TenuredChunk* chunk() const { - return static_cast(Cell::chunk()); - } + ArenaChunk* chunk() const { return static_cast(Cell::chunk()); } // Mark bit management. MOZ_ALWAYS_INLINE bool isMarkedAny() const; @@ -253,7 +253,7 @@ class TenuredCell : public Cell { // The return value indicates if the cell went from unmarked to marked. MOZ_ALWAYS_INLINE bool markIfUnmarked( MarkColor color = MarkColor::Black) const; - MOZ_ALWAYS_INLINE bool markIfUnmarkedAtomic(MarkColor color) const; + MOZ_ALWAYS_INLINE bool markIfUnmarkedThreadSafe(MarkColor color) const; MOZ_ALWAYS_INLINE void markBlack() const; MOZ_ALWAYS_INLINE void markBlackAtomic() const; MOZ_ALWAYS_INLINE void copyMarkBitsFrom(const TenuredCell* src); @@ -298,7 +298,8 @@ class TenuredCell : public Cell { // Default implementation for kinds that don't require fixup. void fixupAfterMovingGC() {} - static inline CellColor getColor(MarkBitmap* bitmap, const TenuredCell* cell); + static inline CellColor getColor(ChunkMarkBitmap* bitmap, + const TenuredCell* cell); #ifdef DEBUG inline bool isAligned() const; @@ -352,7 +353,7 @@ inline JSRuntime* Cell::runtimeFromAnyThread() const { inline uintptr_t Cell::address() const { uintptr_t addr = uintptr_t(this); MOZ_ASSERT(addr % CellAlignBytes == 0); - MOZ_ASSERT(TenuredChunk::withinValidRange(addr)); + MOZ_ASSERT(ArenaChunk::withinValidRange(addr)); return addr; } @@ -429,7 +430,7 @@ MOZ_ALWAYS_INLINE CellColor TenuredCell::color() const { } /* static */ -inline CellColor TenuredCell::getColor(MarkBitmap* bitmap, +inline CellColor TenuredCell::getColor(ChunkMarkBitmap* bitmap, const TenuredCell* cell) { // Note that this method isn't synchronised so may give surprising results if // the mark bitmap is being modified concurrently. @@ -445,27 +446,6 @@ inline CellColor TenuredCell::getColor(MarkBitmap* bitmap, return CellColor::White; } -bool TenuredCell::markIfUnmarked(MarkColor color /* = Black */) const { - return chunk()->markBits.markIfUnmarked(this, color); -} - -bool TenuredCell::markIfUnmarkedAtomic(MarkColor color) const { - return chunk()->markBits.markIfUnmarkedAtomic(this, color); -} - -void TenuredCell::markBlack() const { chunk()->markBits.markBlack(this); } -void TenuredCell::markBlackAtomic() const { - chunk()->markBits.markBlackAtomic(this); -} - -void TenuredCell::copyMarkBitsFrom(const TenuredCell* src) { - MarkBitmap& markBits = chunk()->markBits; - markBits.copyMarkBit(this, src, ColorBit::BlackBit); - markBits.copyMarkBit(this, src, ColorBit::GrayOrBlackBit); -} - -void TenuredCell::unmark() { chunk()->markBits.unmark(this); } - inline Arena* TenuredCell::arena() const { MOZ_ASSERT(isTenured()); uintptr_t addr = address(); @@ -480,15 +460,15 @@ JS::TraceKind TenuredCell::getTraceKind() const { } JS::Zone* TenuredCell::zone() const { - JS::Zone* zone = arena()->zone; + JS::Zone* zone = zoneFromAnyThread(); MOZ_ASSERT(CurrentThreadIsGCMarking() || CurrentThreadCanAccessZone(zone)); return zone; } -JS::Zone* TenuredCell::zoneFromAnyThread() const { return arena()->zone; } +JS::Zone* TenuredCell::zoneFromAnyThread() const { return arena()->zone(); } bool TenuredCell::isInsideZone(JS::Zone* zone) const { - return zone == arena()->zone; + return zone == zoneFromAnyThread(); } // Read barrier and pre-write barrier implementation for GC cells. @@ -528,9 +508,20 @@ MOZ_ALWAYS_INLINE void ReadBarrierImpl(Cell* thing) { } } +#ifdef DEBUG +static bool PreWriteBarrierAllowed() { + JS::GCContext* gcx = MaybeGetGCContext(); + if (!gcx || !gcx->isPreWriteBarrierAllowed()) { + return false; + } + + return gcx->onMainThread() || gcx->gcUse() == gc::GCUse::Sweeping || + gcx->gcUse() == gc::GCUse::Finalizing; +} +#endif + MOZ_ALWAYS_INLINE void PreWriteBarrierImpl(TenuredCell* thing) { - MOZ_ASSERT(CurrentThreadIsMainThread() || CurrentThreadIsGCSweeping() || - CurrentThreadIsGCFinalizing()); + MOZ_ASSERT(PreWriteBarrierAllowed()); MOZ_ASSERT(thing); // Barriers can be triggered on the main thread while collecting, but are @@ -568,7 +559,7 @@ template MOZ_ALWAYS_INLINE void PreWriteBarrier(JS::Zone* zone, T* data, const F& traceFn) { MOZ_ASSERT(data); - MOZ_ASSERT(!CurrentThreadIsIonCompiling()); + MOZ_ASSERT(!CurrentThreadIsOffThreadCompiling()); MOZ_ASSERT(!CurrentThreadIsGCMarking()); auto* shadowZone = JS::shadow::Zone::from(zone); @@ -896,6 +887,37 @@ inline bool TenuredThingIsMarkedAny(Cell* thing) { return thing->asTenured().isMarkedAny(); } +class alignas(gc::CellAlignBytes) SmallBuffer : public TenuredCell { + public: + //MONGODB MODIFICATION: Moves placement new call within SmallBuffer to resolve compilation error using GCC. + static SmallBuffer* create(void* ptr){ + return new (ptr) SmallBuffer(); + } + + static constexpr uintptr_t NURSERY_OWNED_BIT = Bit(3); + + void check() const {} // No check value. + + bool isNurseryOwned() const; + void setNurseryOwned(bool value); + + static const JS::TraceKind TraceKind = JS::TraceKind::SmallBuffer; + void traceChildren(JSTracer* trc) { + // TODO: Generic tracing not supported for sized allocations. + // GCRuntime::checkForCompartmentMismatches ends up calling this because it + // iterates all GC cells. + } + + size_t allocBytes() const; + void* data() { return this + 1; } +}; +template +struct SmallBufferN : public SmallBuffer { + uint8_t data[bytes]; +}; +static_assert(sizeof(SmallBufferN<16>) == 16 + sizeof(SmallBuffer)); +static_assert(sizeof(SmallBufferN<128>) == 128 + sizeof(SmallBuffer)); + } /* namespace gc */ } /* namespace js */ diff --git a/src/third_party/mozjs/extract/js/src/gc/Compacting.cpp b/src/third_party/mozjs/extract/js/src/gc/Compacting.cpp index b42162b2e34..eec1719c1a2 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Compacting.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Compacting.cpp @@ -36,6 +36,8 @@ using namespace js::gc; using mozilla::Maybe; +using JS::SliceBudget; + bool GCRuntime::canRelocateZone(Zone* zone) const { return !zone->isAtomsZone(); } @@ -134,72 +136,86 @@ static bool ShouldRelocateAllArenas(JS::GCReason reason) { } /* - * Choose which arenas to relocate all cells from. Return an arena cursor that - * can be passed to removeRemainingArenas(). + * Choose which arenas to relocate all cells from. + * + * Return a pair of arena pointers indicating the arenas to relocate that can be + * passed to removeRange(), or null pointers if nothing can be relocated. */ -Arena** ArenaList::pickArenasToRelocate(size_t& arenaTotalOut, - size_t& relocTotalOut) { +std::pair ArenaList::pickArenasToRelocate( + AllocKind kind, size_t& arenaTotalOut, size_t& relocTotalOut) { // Relocate the greatest number of arenas such that the number of used cells // in relocated arenas is less than or equal to the number of free cells in // unrelocated arenas. In other words we only relocate cells we can move // into existing arenas, and we choose the least full areans to relocate. // - // This is made easier by the fact that the arena list has been sorted in - // descending order of number of used cells, so we will always relocate a - // tail of the arena list. All we need to do is find the point at which to - // start relocating. + // This is made easier by the fact that the start of the arena list has been + // sorted in descending order of number of used cells, so we will always + // relocate a sublist of the arena list. All we need to do is find the points + // at which to start and end relocating. - check(); - - if (isCursorAtEnd()) { - return nullptr; + if (!hasNonFullArenas()) { + // All arenas are full so no compacting is possible. + return {nullptr, nullptr}; } - Arena** arenap = cursorp_; // Next arena to consider for relocation. - size_t previousFreeCells = 0; // Count of free cells before arenap. - size_t followingUsedCells = 0; // Count of used cells after arenap. - size_t fullArenaCount = 0; // Number of full arenas (not relocated). - size_t nonFullArenaCount = - 0; // Number of non-full arenas (considered for relocation). - size_t arenaIndex = 0; // Index of the next arena to consider. + // Count non-full and full arenas and total used cells, and find the last + // non-full arena. + size_t fullArenaCount = 0; // Number of full arenas (not relocated). + size_t nonFullArenaCount = 0; // Number of non-full arenas to consider. + size_t totalUsedCells = 0; // Total used cells in non-full arenas. + Arena* lastNonFullArena = nullptr; - for (Arena* arena = head_; arena != *cursorp_; arena = arena->next) { + Iterator arena = iter(); + for (; !arena.done(); arena.next()) { + if (arena->isFull()) { + break; + } + + MOZ_ASSERT(!arena->isFull()); + nonFullArenaCount++; + totalUsedCells += arena->countUsedCells(); + lastNonFullArena = arena.get(); + } + for (; !arena.done(); arena.next()) { + // It's likely that the final arena is not full but we ignore that. fullArenaCount++; } - for (Arena* arena = *cursorp_; arena; arena = arena->next) { - followingUsedCells += arena->countUsedCells(); - nonFullArenaCount++; - } + size_t previousFreeCells = 0; // Total free cells before arena. + size_t followingUsedCells = + totalUsedCells; // Total used cells in non full arenas afterwards. + size_t relocCount = nonFullArenaCount; // Number of arenas to relocate. + Arena* prev = nullptr; // The previous arena considered. - mozilla::DebugOnly lastFreeCells(0); - size_t cellsPerArena = Arena::thingsPerArena((*arenap)->getAllocKind()); + const size_t cellsPerArena = Arena::thingsPerArena(kind); - while (*arenap) { - Arena* arena = *arenap; + // Examine the initial part of the list containing non-full arenas. + for (arena = iter(); prev != lastNonFullArena; + prev = arena.get(), arena.next()) { if (followingUsedCells <= previousFreeCells) { + // We have found the point where cells in the following non-full arenas + // can be relocated into the free space in previous arenas. We're done. break; } size_t freeCells = arena->countFreeCells(); + MOZ_ASSERT(freeCells != 0); size_t usedCells = cellsPerArena - freeCells; followingUsedCells -= usedCells; -#ifdef DEBUG - MOZ_ASSERT(freeCells >= lastFreeCells); - lastFreeCells = freeCells; -#endif previousFreeCells += freeCells; - arenap = &arena->next; - arenaIndex++; + MOZ_ASSERT(relocCount != 0); + relocCount--; } - size_t relocCount = nonFullArenaCount - arenaIndex; - MOZ_ASSERT(relocCount < nonFullArenaCount); - MOZ_ASSERT((relocCount == 0) == (!*arenap)); + MOZ_ASSERT((relocCount == 0) == (prev == lastNonFullArena)); arenaTotalOut += fullArenaCount + nonFullArenaCount; relocTotalOut += relocCount; - return arenap; + if (relocCount == 0) { + return {nullptr, nullptr}; + } + + return {prev, lastNonFullArena}; } #ifdef DEBUG @@ -259,19 +275,20 @@ static void RelocateCell(Zone* zone, TenuredCell* src, AllocKind thingKind, dst->copyMarkBitsFrom(src); // Poison the source cell contents except for the forwarding flag and pointer - // which will be stored in the first word. We can't do this for native object - // with fixed elements because this would overwrite the element flags and - // these are needed when updating COW elements referred to by other objects. + // which will be stored in the first word. We can't do this for buffer + // allocations as these can be used as native object dynamic elements and this + // would overwrite the elements flags which are needed when updating the + // dynamic elements pointer. #ifdef DEBUG - JSObject* srcObj = IsObjectAllocKind(thingKind) - ? static_cast(static_cast(src)) - : nullptr; - bool doNotPoison = - srcObj && ((srcObj->is() && - srcObj->as().hasFixedElements()) || - (srcObj->is() && - srcObj->as().isDataInline())); - if (!doNotPoison) { + bool poison = true; + if (IsObjectAllocKind(thingKind)) { + JSObject* srcObj = static_cast(static_cast(src)); + poison = !(srcObj->is() && + srcObj->as().isDataInline()); + } else if (IsBufferAllocKind(thingKind)) { + poison = false; + } + if (poison) { AlwaysPoison(reinterpret_cast(src) + sizeof(uintptr_t), JS_MOVED_TENURED_PATTERN, thingSize - sizeof(uintptr_t), MemCheckKind::MakeNoAccess); @@ -287,7 +304,7 @@ static void RelocateArena(Arena* arena, SliceBudget& sliceBudget) { MOZ_ASSERT(!arena->onDelayedMarkingList()); MOZ_ASSERT(arena->bufferedCells()->isEmpty()); - Zone* zone = arena->zone; + Zone* zone = arena->zone(); AllocKind thingKind = arena->getAllocKind(); size_t thingSize = arena->getThingSize(); @@ -315,8 +332,6 @@ static void RelocateArena(Arena* arena, SliceBudget& sliceBudget) { Arena* ArenaList::relocateArenas(Arena* toRelocate, Arena* relocated, SliceBudget& sliceBudget, gcstats::Statistics& stats) { - check(); - while (Arena* arena = toRelocate) { toRelocate = arena->next; RelocateArena(arena, sliceBudget); @@ -326,8 +341,6 @@ Arena* ArenaList::relocateArenas(Arena* toRelocate, Arena* relocated, stats.count(gcstats::COUNT_ARENA_RELOCATED); } - check(); - return relocated; } @@ -375,33 +388,33 @@ bool ArenaLists::relocateArenas(Arena*& relocatedListOut, JS::GCReason reason, clearFreeLists(); if (ShouldRelocateAllArenas(reason)) { - zone_->prepareForCompacting(); + zone_->prepareForMovingGC(); for (auto kind : allocKindsToRelocate) { ArenaList& al = arenaList(kind); - Arena* allArenas = al.head(); - al.clear(); + Arena* allArenas = al.release(); relocatedListOut = al.relocateArenas(allArenas, relocatedListOut, sliceBudget, stats); } } else { size_t arenaCount = 0; size_t relocCount = 0; - AllAllocKindArray toRelocate; + AllAllocKindArray> rangeToRelocate; for (auto kind : allocKindsToRelocate) { - toRelocate[kind] = - arenaList(kind).pickArenasToRelocate(arenaCount, relocCount); + rangeToRelocate[kind] = + arenaList(kind).pickArenasToRelocate(kind, arenaCount, relocCount); } if (!ShouldRelocateZone(arenaCount, relocCount, reason)) { return false; } - zone_->prepareForCompacting(); + zone_->prepareForMovingGC(); for (auto kind : allocKindsToRelocate) { - if (toRelocate[kind]) { + if (rangeToRelocate[kind].first) { ArenaList& al = arenaList(kind); - Arena* arenas = al.removeRemainingArenas(toRelocate[kind]); + const auto& range = rangeToRelocate[kind]; + Arena* arenas = al.removeRange(range.first, range.second); relocatedListOut = al.relocateArenas(arenas, relocatedListOut, sliceBudget, stats); } @@ -419,7 +432,7 @@ bool GCRuntime::relocateArenas(Zone* zone, JS::GCReason reason, MOZ_ASSERT(!zone->isPreservingCode()); MOZ_ASSERT(canRelocateZone(zone)); - js::CancelOffThreadIonCompile(rt, JS::Zone::Compact); + js::CancelOffThreadCompile(rt, JS::Zone::Compact); if (!zone->arenas.relocateArenas(relocatedListOut, reason, sliceBudget, stats())) { @@ -432,7 +445,10 @@ bool GCRuntime::relocateArenas(Zone* zone, JS::GCReason reason, for (auto kind : CompactingAllocKinds()) { ArenaList& al = zone->arenas.arenaList(kind); size_t freeCells = 0; - for (Arena* arena = al.arenaAfterCursor(); arena; arena = arena->next) { + for (auto arena = al.iter(); !arena.done(); arena.next()) { + if (arena->isFull()) { + break; + } freeCells += arena->countFreeCells(); } MOZ_ASSERT(freeCells < Arena::thingsPerArena(kind)); @@ -449,16 +465,12 @@ MovingTracer::MovingTracer(JSRuntime* rt) template inline void MovingTracer::onEdge(T** thingp, const char* name) { T* thing = *thingp; - if (thing->runtimeFromAnyThread() == runtime() && IsForwarded(thing)) { + if (IsForwarded(thing)) { + MOZ_ASSERT(thing->runtimeFromAnyThread() == runtime()); *thingp = Forwarded(thing); } } -void Zone::prepareForCompacting() { - JS::GCContext* gcx = runtimeFromMainThread()->gcContext(); - discardJitCode(gcx); -} - void GCRuntime::sweepZoneAfterCompacting(MovingTracer* trc, Zone* zone) { MOZ_ASSERT(zone->isGCCompacting()); @@ -553,10 +565,12 @@ static size_t UpdateArenaListSegmentPointers(GCRuntime* gc, MOZ_ASSERT(arenas.begin); MovingTracer trc(gc->rt); size_t count = 0; - for (Arena* arena = arenas.begin; arena != arenas.end; arena = arena->next) { + Arena* arena = arenas.begin; + do { UpdateArenaPointers(&trc, arena); count++; - } + arena = arena->next; + } while (arena != arenas.end); return count * 256; } @@ -569,10 +583,15 @@ class ArenasToUpdate { #endif public: - explicit ArenasToUpdate(Zone* zone); - ArenasToUpdate(Zone* zone, const AllocKinds& kinds); + ArenasToUpdate(Zone* zone, const AllocKinds& kinds) + : kinds(kinds), zone(zone) { + settle(); + } - bool done() const { return !segmentBegin; } + bool done() const { + MOZ_ASSERT_IF(!segmentBegin, endOfArenaList); + return !segmentBegin; + } ArenaListSegment get() const { MOZ_ASSERT(!done()); @@ -582,11 +601,12 @@ class ArenasToUpdate { void next(); private: - Maybe kinds; // Selects which thing kinds to update. + AllocKinds kinds; // Selects which thing kinds to update. Zone* zone; // Zone to process. AllocKind kind = AllocKind::FIRST; // Current alloc kind to process. Arena* segmentBegin = nullptr; Arena* segmentEnd = nullptr; + bool endOfArenaList = true; static AllocKind nextAllocKind(AllocKind i) { return AllocKind(uint8_t(i) + 1); @@ -596,27 +616,22 @@ class ArenasToUpdate { void findSegmentEnd(); }; -ArenasToUpdate::ArenasToUpdate(Zone* zone) : zone(zone) { settle(); } - -ArenasToUpdate::ArenasToUpdate(Zone* zone, const AllocKinds& kinds) - : kinds(Some(kinds)), zone(zone) { - settle(); -} - void ArenasToUpdate::settle() { // Called when we have set |kind| to a new kind. Sets |arena| to the next // arena or null if there are no more arenas to update. MOZ_ASSERT(!segmentBegin); + MOZ_ASSERT(endOfArenaList); for (; kind < AllocKind::LIMIT; kind = nextAllocKind(kind)) { - if (kinds && !kinds.ref().contains(kind)) { + if (!kinds.contains(kind)) { continue; } Arena* arena = zone->arenas.getFirstArena(kind); if (arena) { segmentBegin = arena; + endOfArenaList = false; findSegmentEnd(); break; } @@ -625,10 +640,19 @@ void ArenasToUpdate::settle() { void ArenasToUpdate::findSegmentEnd() { // Take up to MaxArenasToProcess arenas from the list starting at - // |segmentBegin| and set |segmentEnd|. + // |segmentBegin| and set |segmentEnd| and |endOfArenaList|. + MOZ_ASSERT(segmentBegin); + MOZ_ASSERT(!endOfArenaList); + Arena* arena = segmentBegin; - for (size_t i = 0; arena && i < MaxArenasToProcess; i++) { + Arena* firstArena = zone->arenas.getFirstArena(kind); + for (size_t i = 0; i < MaxArenasToProcess; i++) { arena = arena->next; + if (arena == firstArena) { + // We have reached the end of the circular linked list. + endOfArenaList = true; + break; + } } segmentEnd = arena; } @@ -636,12 +660,13 @@ void ArenasToUpdate::findSegmentEnd() { void ArenasToUpdate::next() { MOZ_ASSERT(!done()); - segmentBegin = segmentEnd; - if (segmentBegin) { + if (!endOfArenaList) { + segmentBegin = segmentEnd; findSegmentEnd(); return; } + segmentBegin = nullptr; kind = nextAllocKind(kind); settle(); } @@ -678,25 +703,22 @@ void GCRuntime::updateCellPointers(Zone* zone, AllocKinds kinds) { } // After cells have been relocated any pointers to a cell's old locations must -// be updated to point to the new location. This happens by iterating through +// be updated to point to the new location. This happens by iterating through // all cells in heap and tracing their children (non-recursively) to update // them. // // This is complicated by the fact that updating a GC thing sometimes depends on -// making use of other GC things. After a moving GC these things may not be in -// a valid state since they may contain pointers which have not been updated -// yet. +// making use of other GC things. After a moving GC these things may not be in a +// valid state since they may contain pointers which have not been updated yet. // -// The main dependencies are: +// The main remaining dependency is: // // - Updating a JSObject makes use of its shape -// - Updating a typed object makes use of its type descriptor object // -// This means we require at least three phases for update: +// This means we require at least two phases for update: // -// 1) shapes -// 2) typed object type descriptor objects -// 3) all other objects +// 1) a phase including shapes +// 2) a phase including all JS objects // // Also, there can be data races calling IsForwarded() on the new location of a // cell whose first word is being updated in parallel on another thread. This @@ -704,7 +726,7 @@ void GCRuntime::updateCellPointers(Zone* zone, AllocKinds kinds) { // cell. Otherwise this can be avoided by updating different kinds of cell in // different phases. // -// Since we want to minimize the number of phases, arrange kinds into three +// Since we want to minimize the number of phases, arrange kinds into two // arbitrary phases. static constexpr AllocKinds UpdatePhaseOne{AllocKind::SCRIPT, @@ -719,31 +741,34 @@ static constexpr AllocKinds UpdatePhaseOne{AllocKind::SCRIPT, AllocKind::NORMAL_PROP_MAP, AllocKind::DICT_PROP_MAP}; -// UpdatePhaseTwo is typed object descriptor objects. - -static constexpr AllocKinds UpdatePhaseThree{AllocKind::FUNCTION, - AllocKind::FUNCTION_EXTENDED, - AllocKind::OBJECT0, - AllocKind::OBJECT0_BACKGROUND, - AllocKind::OBJECT2, - AllocKind::OBJECT2_BACKGROUND, - AllocKind::ARRAYBUFFER4, - AllocKind::OBJECT4, - AllocKind::OBJECT4_BACKGROUND, - AllocKind::ARRAYBUFFER8, - AllocKind::OBJECT8, - AllocKind::OBJECT8_BACKGROUND, - AllocKind::ARRAYBUFFER12, - AllocKind::OBJECT12, - AllocKind::OBJECT12_BACKGROUND, - AllocKind::ARRAYBUFFER16, - AllocKind::OBJECT16, - AllocKind::OBJECT16_BACKGROUND}; +static constexpr AllocKinds UpdatePhaseTwo{AllocKind::FUNCTION, + AllocKind::FUNCTION_EXTENDED, + AllocKind::OBJECT0, + AllocKind::OBJECT0_FOREGROUND, + AllocKind::OBJECT0_BACKGROUND, + AllocKind::OBJECT2, + AllocKind::OBJECT2_FOREGROUND, + AllocKind::OBJECT2_BACKGROUND, + AllocKind::ARRAYBUFFER4, + AllocKind::OBJECT4, + AllocKind::OBJECT4_FOREGROUND, + AllocKind::OBJECT4_BACKGROUND, + AllocKind::ARRAYBUFFER8, + AllocKind::OBJECT8, + AllocKind::OBJECT8_FOREGROUND, + AllocKind::OBJECT8_BACKGROUND, + AllocKind::ARRAYBUFFER12, + AllocKind::OBJECT12, + AllocKind::OBJECT12_FOREGROUND, + AllocKind::OBJECT12_BACKGROUND, + AllocKind::ARRAYBUFFER16, + AllocKind::OBJECT16, + AllocKind::OBJECT16_FOREGROUND, + AllocKind::OBJECT16_BACKGROUND}; void GCRuntime::updateAllCellPointers(MovingTracer* trc, Zone* zone) { updateCellPointers(zone, UpdatePhaseOne); - - updateCellPointers(zone, UpdatePhaseThree); + updateCellPointers(zone, UpdatePhaseTwo); } /* @@ -878,11 +903,19 @@ void GCRuntime::clearRelocatedArenasWithoutUnlocking(Arena* arenaList, // - if they were allocated since the start of the GC. bool allArenasRelocated = ShouldRelocateAllArenas(reason); bool updateRetainedSize = !allArenasRelocated && !arena->isNewlyCreated(); - arena->zone->gcHeapSize.removeBytes(ArenaSize, updateRetainedSize, - heapSize); + Zone* zone = arena->zone(); + if (IsBufferAllocKind(arena->getAllocKind())) { + size_t usableBytes = ArenaSize - arena->getFirstThingOffset(); + zone->mallocHeapSize.removeBytes(usableBytes, updateRetainedSize); + } else { + zone->gcHeapSize.removeBytes(ArenaSize, updateRetainedSize, heapSize); + } + + // There is no atom marking bitmap index to free. + MOZ_ASSERT(!zone->isAtomsZone()); // Release the arena but don't return it to the chunk yet. - arena->release(lock); + arena->release(); } } diff --git a/src/third_party/mozjs/extract/js/src/gc/FinalizationObservers.cpp b/src/third_party/mozjs/extract/js/src/gc/FinalizationObservers.cpp index 3a7a1146452..0b1a727d4f6 100644 --- a/src/third_party/mozjs/extract/js/src/gc/FinalizationObservers.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/FinalizationObservers.cpp @@ -284,6 +284,9 @@ void FinalizationObservers::updateForRemovedRecord( void GCRuntime::nukeFinalizationRecordWrapper( JSObject* wrapper, FinalizationRecordObject* record) { + // The target of the nuked wrapper may be gray, and that's OK. + AutoTouchingGrayThings atgt; + if (record->isInRecordMap()) { FinalizationRegistryObject::unregisterRecord(record); FinalizationObservers* observers = wrapper->zone()->finalizationObservers(); @@ -300,14 +303,21 @@ void GCRuntime::queueFinalizationRegistryForCleanup( return; } - // Derive the incumbent global by unwrapping the incumbent global object and - // then getting its global. - JSObject* object = UncheckedUnwrapWithoutExpose(queue->incumbentObject()); - MOZ_ASSERT(object); - GlobalObject* incumbentGlobal = &object->nonCCWGlobal(); + JSObject* unwrappedHostDefineData = nullptr; + + if (JSObject* wrapped = queue->getHostDefinedData()) { + unwrappedHostDefineData = UncheckedUnwrapWithoutExpose(wrapped); + MOZ_ASSERT(unwrappedHostDefineData); + // If the hostDefined object becomes a dead wrapper here, the target global + // has already gone, and the finalization callback won't do anything to it + // anyway. + if (JS_IsDeadWrapper(unwrappedHostDefineData)) { + return; + } + } callHostCleanupFinalizationRegistryCallback(queue->doCleanupFunction(), - incumbentGlobal); + unwrappedHostDefineData); // The queue object may be gray, and that's OK. AutoTouchingGrayThings atgt; diff --git a/src/third_party/mozjs/extract/js/src/gc/GC-inl.h b/src/third_party/mozjs/extract/js/src/gc/GC-inl.h index 00de3187780..27f087279ed 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GC-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/GC-inl.h @@ -23,34 +23,15 @@ namespace js::gc { class AutoAssertEmptyNursery; -class ArenaListIter { - Arena* arena; - - public: - explicit ArenaListIter(Arena* head) : arena(head) {} - bool done() const { return !arena; } - Arena* get() const { - MOZ_ASSERT(!done()); - return arena; - } - void next() { - MOZ_ASSERT(!done()); - arena = arena->next; - } - - operator Arena*() const { return get(); } - Arena* operator->() const { return get(); } -}; - // Iterate all arenas in a zone of the specified kind, for use by the GC. // // Since the GC never iterates arenas during foreground sweeping we can skip // traversing foreground swept arenas. -class ArenaIterInGC : public ChainedIterator { +class ArenaIterInGC : public ChainedIterator { public: ArenaIterInGC(JS::Zone* zone, AllocKind kind) - : ChainedIterator(zone->arenas.getFirstArena(kind), - zone->arenas.getFirstCollectingArena(kind)) { + : ChainedIterator(zone->arenas.arenaList(kind), + zone->arenas.collectingArenaList(kind)) { #ifdef DEBUG MOZ_ASSERT(JS::RuntimeHeapIsMajorCollecting()); GCRuntime& gc = zone->runtimeFromMainThread()->gc; @@ -65,13 +46,13 @@ class ArenaIterInGC : public ChainedIterator { // Most uses of this happen when we are not in incremental GC but the debugger // can iterate scripts at any time. class ArenaIter : public AutoGatherSweptArenas, - public ChainedIterator { + public ChainedIterator { public: ArenaIter(JS::Zone* zone, AllocKind kind) : AutoGatherSweptArenas(zone, kind), - ChainedIterator(zone->arenas.getFirstArena(kind), - zone->arenas.getFirstCollectingArena(kind), - sweptArenas()) {} + ChainedIterator(zone->arenas.arenaList(kind), + zone->arenas.collectingArenaList(kind), sweptArenas()) { + } }; class ArenaCellIter { @@ -172,9 +153,11 @@ class ZoneAllCellIter { // against other threads iterating or allocating. However, we do have // background finalization; we may have to wait for this to finish if // it's currently active. - if (IsBackgroundFinalized(kind) && - zone->arenas.needBackgroundFinalizeWait(kind)) { - rt->gc.waitBackgroundSweepEnd(); + if (IsBackgroundFinalized(kind)) { + ArenaLists& arenas = zone->arenas; + if (zone->isGCFinished() && !arenas.doneBackgroundFinalize(kind)) { + rt->gc.waitBackgroundSweepEnd(); + } } iter.emplace(zone, kind); } diff --git a/src/third_party/mozjs/extract/js/src/gc/GC.cpp b/src/third_party/mozjs/extract/js/src/gc/GC.cpp index 58dad9654d7..d04fe65be20 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GC.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/GC.cpp @@ -192,6 +192,7 @@ #include "gc/GC-inl.h" +#include "mozilla/glue/Debug.h" #include "mozilla/Range.h" #include "mozilla/ScopeExit.h" #include "mozilla/TextUtils.h" @@ -247,6 +248,7 @@ #include "vm/JSContext-inl.h" #include "vm/Realm-inl.h" #include "vm/Stack-inl.h" +#include "vm/StringType-inl.h" using namespace js; using namespace js::gc; @@ -259,20 +261,9 @@ using mozilla::Some; using mozilla::TimeDuration; using mozilla::TimeStamp; -using JS::AutoGCRooter; - -const AllocKind gc::slotsToThingKind[] = { - // clang-format off - /* 0 */ AllocKind::OBJECT0, AllocKind::OBJECT2, AllocKind::OBJECT2, AllocKind::OBJECT4, - /* 4 */ AllocKind::OBJECT4, AllocKind::OBJECT8, AllocKind::OBJECT8, AllocKind::OBJECT8, - /* 8 */ AllocKind::OBJECT8, AllocKind::OBJECT12, AllocKind::OBJECT12, AllocKind::OBJECT12, - /* 12 */ AllocKind::OBJECT12, AllocKind::OBJECT16, AllocKind::OBJECT16, AllocKind::OBJECT16, - /* 16 */ AllocKind::OBJECT16 - // clang-format on -}; - -static_assert(std::size(slotsToThingKind) == SLOTS_TO_THING_KIND_LIMIT, - "We have defined a slot count for each kind."); +using JS::SliceBudget; +using JS::TimeBudget; +using JS::WorkBudget; // A table converting an object size in "slots" (increments of // sizeof(js::Value)) to the total number of bytes in the corresponding @@ -295,7 +286,7 @@ const uint32_t gc::slotsToAllocKindBytes[] = { // clang-format on }; -static_assert(std::size(slotsToAllocKindBytes) == SLOTS_TO_THING_KIND_LIMIT); +static_assert(std::size(slotsToAllocKindBytes) == std::size(slotsToThingKind)); MOZ_THREAD_LOCAL(JS::GCContext*) js::TlsGCContext; @@ -307,6 +298,7 @@ JS::GCContext::~GCContext() { MOZ_ASSERT(gcUse() == GCUse::None); MOZ_ASSERT(!gcSweepZone()); MOZ_ASSERT(!isTouchingGrayThings()); + MOZ_ASSERT(isPreWriteBarrierAllowed()); } void JS::GCContext::poisonJitCode() { @@ -322,23 +314,17 @@ void GCRuntime::verifyAllChunks() { fullChunks(lock).verifyChunks(); availableChunks(lock).verifyChunks(); emptyChunks(lock).verifyChunks(); + if (currentChunk_) { + MOZ_ASSERT(currentChunk_->info.isCurrentChunk); + currentChunk_->verify(); + } else { + MOZ_ASSERT(pendingFreeCommittedArenas.ref().IsEmpty()); + } } #endif void GCRuntime::setMinEmptyChunkCount(uint32_t value, const AutoLockGC& lock) { minEmptyChunkCount_ = value; - if (minEmptyChunkCount_ > maxEmptyChunkCount_) { - maxEmptyChunkCount_ = minEmptyChunkCount_; - } - MOZ_ASSERT(maxEmptyChunkCount_ >= minEmptyChunkCount_); -} - -void GCRuntime::setMaxEmptyChunkCount(uint32_t value, const AutoLockGC& lock) { - maxEmptyChunkCount_ = value; - if (minEmptyChunkCount_ > maxEmptyChunkCount_) { - minEmptyChunkCount_ = maxEmptyChunkCount_; - } - MOZ_ASSERT(maxEmptyChunkCount_ >= minEmptyChunkCount_); } inline bool GCRuntime::tooManyEmptyChunks(const AutoLockGC& lock) { @@ -347,28 +333,30 @@ inline bool GCRuntime::tooManyEmptyChunks(const AutoLockGC& lock) { ChunkPool GCRuntime::expireEmptyChunkPool(const AutoLockGC& lock) { MOZ_ASSERT(emptyChunks(lock).verify()); - MOZ_ASSERT(minEmptyChunkCount(lock) <= maxEmptyChunkCount(lock)); ChunkPool expired; - while (tooManyEmptyChunks(lock)) { - TenuredChunk* chunk = emptyChunks(lock).pop(); - prepareToFreeChunk(chunk->info); - expired.push(chunk); + if (isShrinkingGC()) { + std::swap(expired, emptyChunks(lock)); + } else { + while (tooManyEmptyChunks(lock)) { + ArenaChunk* chunk = emptyChunks(lock).pop(); + prepareToFreeChunk(chunk->info); + expired.push(chunk); + } } MOZ_ASSERT(expired.verify()); MOZ_ASSERT(emptyChunks(lock).verify()); - MOZ_ASSERT(emptyChunks(lock).count() <= maxEmptyChunkCount(lock)); MOZ_ASSERT(emptyChunks(lock).count() <= minEmptyChunkCount(lock)); return expired; } static void FreeChunkPool(ChunkPool& pool) { for (ChunkPool::Iter iter(pool); !iter.done();) { - TenuredChunk* chunk = iter.get(); + ArenaChunk* chunk = iter.get(); iter.next(); pool.remove(chunk); - MOZ_ASSERT(chunk->unused()); + MOZ_ASSERT(chunk->isEmpty()); UnmapPages(static_cast(chunk), ChunkSize); } MOZ_ASSERT(pool.count() == 0); @@ -378,26 +366,43 @@ void GCRuntime::freeEmptyChunks(const AutoLockGC& lock) { FreeChunkPool(emptyChunks(lock)); } -inline void GCRuntime::prepareToFreeChunk(TenuredChunkInfo& info) { - MOZ_ASSERT(numArenasFreeCommitted >= info.numArenasFreeCommitted); - numArenasFreeCommitted -= info.numArenasFreeCommitted; +inline void GCRuntime::prepareToFreeChunk(ArenaChunkInfo& info) { + MOZ_ASSERT(info.numArenasFree == ArenasPerChunk); stats().count(gcstats::COUNT_DESTROY_CHUNK); #ifdef DEBUG - /* - * Let FreeChunkPool detect a missing prepareToFreeChunk call before it - * frees chunk. - */ + // Let FreeChunkPool detect a missing prepareToFreeChunk call before it frees + // chunk. info.numArenasFreeCommitted = 0; #endif } +void GCRuntime::releaseArenaList(ArenaList& arenaList, const AutoLockGC& lock) { + releaseArenas(arenaList.release(), lock); +} + +void GCRuntime::releaseArenas(Arena* arena, const AutoLockGC& lock) { + Arena* next; + for (; arena; arena = next) { + next = arena->next; + releaseArena(arena, lock); + } +} + void GCRuntime::releaseArena(Arena* arena, const AutoLockGC& lock) { MOZ_ASSERT(arena->allocated()); MOZ_ASSERT(!arena->onDelayedMarkingList()); MOZ_ASSERT(TlsGCContext.get()->isFinalizing()); - arena->zone->gcHeapSize.removeGCArena(heapSize); - arena->release(lock); + if (IsBufferAllocKind(arena->getAllocKind())) { + size_t usableBytes = ArenaSize - arena->getFirstThingOffset(); + arena->zone()->mallocHeapSize.removeBytes(usableBytes, true); + } else { + arena->zone()->gcHeapSize.removeBytes(ArenaSize, true, heapSize); + } + if (arena->zone()->isAtomsZone()) { + arena->freeAtomMarkingBitmapIndex(this, lock); + } + arena->release(); arena->chunk()->releaseArena(this, arena, lock); } @@ -416,18 +421,15 @@ GCRuntime::GCRuntime(JSRuntime* rt) markingThreadCount(1), createBudgetCallback(nullptr), minEmptyChunkCount_(TuningDefaults::MinEmptyChunkCount), - maxEmptyChunkCount_(TuningDefaults::MaxEmptyChunkCount), rootsHash(256), nextCellUniqueId_(LargestTaggedNullCellPointer + 1), // Ensure disjoint from null tagged pointers. - numArenasFreeCommitted(0), verifyPreData(nullptr), lastGCStartTime_(TimeStamp::Now()), lastGCEndTime_(TimeStamp::Now()), incrementalGCEnabled(TuningDefaults::IncrementalGCEnabled), perZoneGCEnabled(TuningDefaults::PerZoneGCEnabled), numActiveZoneIters(0), - cleanUpEverything(false), grayBitsValid(true), majorGCTriggerReason(JS::GCReason::NO_REASON), minorGCNumber(0), @@ -446,11 +448,14 @@ GCRuntime::GCRuntime(JSRuntime* rt) hadShutdownGC(false), #endif requestSliceAfterBackgroundTask(false), - lifoBlocksToFree((size_t)JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), + lifoBlocksToFree((size_t)JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE, + js::BackgroundMallocArena), lifoBlocksToFreeAfterFullMinorGC( - (size_t)JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), + (size_t)JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE, + js::BackgroundMallocArena), lifoBlocksToFreeAfterNextMinorGC( - (size_t)JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), + (size_t)JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE, + js::BackgroundMallocArena), sweepGroupIndex(0), sweepGroups(nullptr), currentSweepGroup(nullptr), @@ -469,8 +474,8 @@ GCRuntime::GCRuntime(JSRuntime* rt) markingValidator(nullptr), #endif defaultTimeBudgetMS_(TuningDefaults::DefaultTimeBudgetMS), - incrementalAllowed(true), compactingEnabled(TuningDefaults::CompactingEnabled), + nurseryEnabled(TuningDefaults::NurseryEnabled), parallelMarkingEnabled(TuningDefaults::ParallelMarkingEnabled), rootsRemoved(false), #ifdef JS_GC_ZEAL @@ -488,6 +493,7 @@ GCRuntime::GCRuntime(JSRuntime* rt) lock(mutexid::GCLock), storeBufferLock(mutexid::StoreBuffer), delayedMarkingLock(mutexid::GCDelayedMarkingLock), + bufferAllocatorLock(mutexid::BufferAllocator), allocTask(this, emptyChunks_.ref()), unmarkTask(this), markTask(this), @@ -604,6 +610,7 @@ const char gc::ZealModeHelpText[] = " 1: (RootsChange) Collect when roots are added or removed\n" " 2: (Alloc) Collect when every N allocations (default: 100)\n" " 4: (VerifierPre) Verify pre write barriers between instructions\n" +" 5: (VerifierPost) Verify post write barriers after minor GC\n" " 6: (YieldBeforeRootMarking) Incremental GC in two slices that yields\n" " before root marking\n" " 7: (GenerationalGC) Collect the nursery every N nursery allocations\n" @@ -633,11 +640,13 @@ const char gc::ZealModeHelpText[] = " 24: (CheckWeakMapMarking) Check weak map marking invariants after every\n" " GC\n" " 25: (YieldWhileGrayMarking) Incremental GC in two slices that yields\n" -" during gray marking\n"; +" during gray marking\n" +" 26: (CheckHeapBeforeMinorGC) Check for invariant violations before every\n" +" minor GC\n"; // clang-format on // The set of zeal modes that yield at specific points in collection. -static const EnumSet YieldPointZealModes = { +static constexpr EnumSet YieldPointZealModes = { ZealMode::YieldBeforeRootMarking, ZealMode::YieldBeforeMarking, ZealMode::YieldBeforeSweeping, @@ -649,19 +658,19 @@ static const EnumSet YieldPointZealModes = { ZealMode::YieldWhileGrayMarking}; // The set of zeal modes that control incremental slices. -static const EnumSet IncrementalSliceZealModes = +static constexpr EnumSet IncrementalSliceZealModes = YieldPointZealModes + EnumSet{ZealMode::IncrementalMultipleSlices}; // The set of zeal modes that trigger GC periodically. -static const EnumSet PeriodicGCZealModes = - IncrementalSliceZealModes + EnumSet{ZealMode::Alloc, - ZealMode::GenerationalGC, - ZealMode::Compact}; +static constexpr EnumSet PeriodicGCZealModes = + IncrementalSliceZealModes + + EnumSet{ZealMode::Alloc, ZealMode::VerifierPost, + ZealMode::GenerationalGC, ZealMode::Compact}; // The set of zeal modes that are mutually exclusive. All of these trigger GC // except VerifierPre. -static const EnumSet ExclusiveZealModes = +static constexpr EnumSet ExclusiveZealModes = PeriodicGCZealModes + EnumSet{ZealMode::VerifierPre}; void GCRuntime::setZeal(uint8_t zeal, uint32_t frequency) { @@ -782,12 +791,15 @@ static bool PrintZealHelpAndFail() { return false; } -bool GCRuntime::parseAndSetZeal(const char* str) { - // Set the zeal mode from a string consisting of one or more mode specifiers - // separated by ';', optionally followed by a ',' and the trigger frequency. - // The mode specifiers can by a mode name or its number. +bool GCRuntime::parseZeal(const char* str, size_t len, ZealSettings* zeal, + bool* invalid) { + CharRange text(str, len); - auto text = CharRange(str, strlen(str)); + // The zeal mode setting is a string consisting of one or more mode + // specifiers separated by ';', optionally followed by a ',' and the trigger + // frequency. The mode specifiers can by a mode name or its number. + + *invalid = false; CharRangeVector parts; if (!SplitStringBy(text, ',', &parts)) { @@ -795,12 +807,14 @@ bool GCRuntime::parseAndSetZeal(const char* str) { } if (parts.length() == 0 || parts.length() > 2) { - return PrintZealHelpAndFail(); + *invalid = true; + return true; } uint32_t frequency = JS::ShellDefaultGCZealFrequency; if (parts.length() == 2 && !ParseZealModeNumericParam(parts[1], &frequency)) { - return PrintZealHelpAndFail(); + *invalid = true; + return true; } CharRangeVector modes; @@ -813,9 +827,30 @@ bool GCRuntime::parseAndSetZeal(const char* str) { if (!ParseZealModeName(descr, &mode) && !(ParseZealModeNumericParam(descr, &mode) && mode <= unsigned(ZealMode::Limit))) { - return PrintZealHelpAndFail(); + *invalid = true; + return true; } + if (!zeal->append(ZealSetting{uint8_t(mode), frequency})) { + return false; + } + } + + return true; +} + +bool GCRuntime::parseAndSetZeal(const char* str) { + ZealSettings zeal; + bool invalid = false; + if (!parseZeal(str, strlen(str), &zeal, &invalid)) { + return false; + } + + if (invalid) { + return PrintZealHelpAndFail(); + } + + for (auto [mode, frequency] : zeal) { setZeal(mode, frequency); } @@ -861,20 +896,6 @@ void GCRuntime::clearZealMode(ZealMode mode) { MOZ_ASSERT(!hasZealMode(mode)); } -const char* js::gc::AllocKindName(AllocKind kind) { - static const char* const names[] = { -# define EXPAND_THING_NAME(allocKind, _1, _2, _3, _4, _5, _6) #allocKind, - FOR_EACH_ALLOCKIND(EXPAND_THING_NAME) -# undef EXPAND_THING_NAME - }; - static_assert(std::size(names) == AllocKindCount, - "names array should have an entry for every AllocKind"); - - size_t i = size_t(kind); - MOZ_ASSERT(i < std::size(names)); - return names[i]; -} - void js::gc::DumpArenaInfo() { fprintf(stderr, "Arena header size: %zu\n\n", ArenaHeaderSize); @@ -889,11 +910,26 @@ void js::gc::DumpArenaInfo() { } #endif // JS_GC_ZEAL + // +const char* js::gc::AllocKindName(AllocKind kind) { + static const char* const names[] = { +#define EXPAND_THING_NAME(allocKind, _1, _2, _3, _4, _5, _6) #allocKind, + FOR_EACH_ALLOCKIND(EXPAND_THING_NAME) +#undef EXPAND_THING_NAME + }; + static_assert(std::size(names) == AllocKindCount, + "names array should have an entry for every AllocKind"); + + size_t i = size_t(kind); + MOZ_ASSERT(i < std::size(names)); + return names[i]; +} bool GCRuntime::init(uint32_t maxbytes) { MOZ_ASSERT(!wasInitialized()); MOZ_ASSERT(SystemPageSize()); + Arena::staticAsserts(); Arena::checkLookupTables(); if (!TlsGCContext.init()) { @@ -1006,6 +1042,11 @@ void GCRuntime::finish() { zones().clear(); + { + AutoLockGC lock(this); + clearCurrentChunk(lock); + } + FreeChunkPool(fullChunks_.ref()); FreeChunkPool(availableChunks_.ref()); FreeChunkPool(emptyChunks_.ref()); @@ -1079,8 +1120,9 @@ void GCRuntime::restoreSharedAtomsZone() { MOZ_ASSERT(rt->isMainRuntime()); MOZ_ASSERT(rt->childRuntimeCount == 0); + // Insert at start to preserve invariant that atoms zones come first. AutoEnterOOMUnsafeRegion oomUnsafe; - if (!zones().append(sharedAtomsZone_)) { + if (!zones().insert(zones().begin(), sharedAtomsZone_)) { oomUnsafe.crash("restoreSharedAtomsZone"); } @@ -1094,6 +1136,13 @@ bool GCRuntime::setParameter(JSContext* cx, JSGCParamKey key, uint32_t value) { FinishGC(cx); waitBackgroundSweepEnd(); + // Special case: if there is still an `AutoDisableGenerationalGC` active (eg + // from the --no-ggc command-line flag), then do not allow controlling the + // state of the nursery. Done here where cx is available. + if (key == JSGC_NURSERY_ENABLED && cx->generationalDisabled > 0) { + return false; + } + AutoLockGC lock(this); return setParameter(key, value, lock); } @@ -1118,6 +1167,11 @@ bool GCRuntime::setParameter(JSGCParamKey key, uint32_t value, case JSGC_COMPACTING_ENABLED: compactingEnabled = value != 0; break; + case JSGC_NURSERY_ENABLED: { + AutoUnlockGC unlock(lock); + setNurseryEnabled(value != 0); + break; + } case JSGC_PARALLEL_MARKING_ENABLED: setParallelMarkingEnabled(value != 0); break; @@ -1134,9 +1188,6 @@ bool GCRuntime::setParameter(JSGCParamKey key, uint32_t value, case JSGC_MIN_EMPTY_CHUNK_COUNT: setMinEmptyChunkCount(value, lock); break; - case JSGC_MAX_EMPTY_CHUNK_COUNT: - setMaxEmptyChunkCount(value, lock); - break; default: if (IsGCThreadParameter(key)) { return setThreadParameter(key, value, lock); @@ -1209,6 +1260,9 @@ void GCRuntime::resetParameter(JSGCParamKey key, AutoLockGC& lock) { case JSGC_COMPACTING_ENABLED: compactingEnabled = TuningDefaults::CompactingEnabled; break; + case JSGC_NURSERY_ENABLED: + setNurseryEnabled(TuningDefaults::NurseryEnabled); + break; case JSGC_PARALLEL_MARKING_ENABLED: setParallelMarkingEnabled(TuningDefaults::ParallelMarkingEnabled); break; @@ -1226,9 +1280,6 @@ void GCRuntime::resetParameter(JSGCParamKey key, AutoLockGC& lock) { case JSGC_MIN_EMPTY_CHUNK_COUNT: setMinEmptyChunkCount(TuningDefaults::MinEmptyChunkCount, lock); break; - case JSGC_MAX_EMPTY_CHUNK_COUNT: - setMaxEmptyChunkCount(TuningDefaults::MaxEmptyChunkCount, lock); - break; default: if (IsGCThreadParameter(key)) { resetThreadParameter(key, lock); @@ -1288,8 +1339,10 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) { case JSGC_PER_ZONE_GC_ENABLED: return perZoneGCEnabled; case JSGC_UNUSED_CHUNKS: + clearCurrentChunk(lock); return uint32_t(emptyChunks(lock).count()); case JSGC_TOTAL_CHUNKS: + clearCurrentChunk(lock); return uint32_t(fullChunks(lock).count() + availableChunks(lock).count() + emptyChunks(lock).count()); case JSGC_SLICE_TIME_BUDGET_MS: @@ -1298,10 +1351,10 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) { return uint32_t(defaultTimeBudgetMS_); case JSGC_MIN_EMPTY_CHUNK_COUNT: return minEmptyChunkCount(lock); - case JSGC_MAX_EMPTY_CHUNK_COUNT: - return maxEmptyChunkCount(lock); case JSGC_COMPACTING_ENABLED: return compactingEnabled; + case JSGC_NURSERY_ENABLED: + return nursery().isEnabled(); case JSGC_PARALLEL_MARKING_ENABLED: return parallelMarkingEnabled; case JSGC_INCREMENTAL_WEAKMAP_ENABLED: @@ -1324,6 +1377,8 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) { return markingThreadCount; case JSGC_SYSTEM_PAGE_SIZE_KB: return SystemPageSize() / 1024; + case JSGC_HIGH_FREQUENCY_MODE: + return schedulingState.inHighFrequencyGCMode(); default: return tunables.getParameter(key); } @@ -1347,6 +1402,17 @@ void GCRuntime::setIncrementalGCEnabled(bool enabled) { incrementalGCEnabled = enabled; } +void GCRuntime::setNurseryEnabled(bool enabled) { + if (enabled) { + nursery().enable(); + } else { + if (nursery().isEnabled()) { + minorGC(JS::GCReason::EVICT_NURSERY); + nursery().disable(); + } + } +} + void GCRuntime::updateHelperThreadCount() { if (!CanUseExtraThreads()) { // startTask will run the work on the main thread if the count is 1. @@ -1564,7 +1630,7 @@ bool GCRuntime::addBlackRootsTracer(JSTraceDataOp traceOp, void* data) { void GCRuntime::removeBlackRootsTracer(JSTraceDataOp traceOp, void* data) { // Can be called from finalizers - MOZ_ALWAYS_TRUE(EraseCallback(blackRootTracers.ref(), traceOp)); + MOZ_ALWAYS_TRUE(EraseCallback(blackRootTracers.ref(), traceOp, data)); } void GCRuntime::setGrayRootsTracer(JSGrayRootsTracer traceOp, void* data) { @@ -1623,11 +1689,11 @@ void GCRuntime::setHostCleanupFinalizationRegistryCallback( } void GCRuntime::callHostCleanupFinalizationRegistryCallback( - JSFunction* doCleanup, GlobalObject* incumbentGlobal) { + JSFunction* doCleanup, JSObject* hostDefinedData) { JS::AutoSuppressGCAnalysis nogc; const auto& callback = hostCleanupFinalizationRegistryCallback.ref(); if (callback.op) { - callback.op(doCleanup, incumbentGlobal, callback.data); + callback.op(doCleanup, hostDefinedData, callback.data); } } @@ -2011,15 +2077,21 @@ bool GCRuntime::checkEagerAllocTrigger(const HeapSize& size, } bool GCRuntime::shouldDecommit() const { - // If we're doing a shrinking GC we always decommit to release as much memory - // as possible. - if (cleanUpEverything) { - return true; + switch (gcOptions()) { + case JS::GCOptions::Normal: + // If we are allocating heavily enough to trigger "high frequency" GC then + // skip decommit so that we do not compete with the mutator. + return !schedulingState.inHighFrequencyGCMode(); + case JS::GCOptions::Shrink: + // If we're doing a shrinking GC we always decommit to release as much + // memory as possible. + return true; + case JS::GCOptions::Shutdown: + // There's no point decommitting as we are about to free everything. + return false; } - // If we are allocating heavily enough to trigger "high frequency" GC then - // skip decommit so that we do not compete with the mutator. - return !schedulingState.inHighFrequencyGCMode(); + MOZ_CRASH("Unexpected GCOptions value"); } void GCRuntime::startDecommit() { @@ -2038,7 +2110,7 @@ void GCRuntime::startDecommit() { // Verify that all entries in the empty chunks pool are unused. for (ChunkPool::Iter chunk(emptyChunks(lock)); !chunk.done(); chunk.next()) { - MOZ_ASSERT(chunk->unused()); + MOZ_ASSERT(chunk->isEmpty()); } } #endif @@ -2102,14 +2174,14 @@ void js::gc::BackgroundDecommitTask::run(AutoLockHelperThreadState& lock) { gc->maybeRequestGCAfterBackgroundTask(lock); } -static inline bool CanDecommitWholeChunk(TenuredChunk* chunk) { - return chunk->unused() && chunk->info.numArenasFreeCommitted != 0; +static inline bool CanDecommitWholeChunk(ArenaChunk* chunk) { + return chunk->isEmpty() && chunk->info.numArenasFreeCommitted != 0; } // Called from a background thread to decommit free arenas. Releases the GC // lock. void GCRuntime::decommitEmptyChunks(const bool& cancel, AutoLockGC& lock) { - Vector chunksToDecommit; + Vector chunksToDecommit; for (ChunkPool::Iter chunk(emptyChunks(lock)); !chunk.done(); chunk.next()) { if (CanDecommitWholeChunk(chunk) && !chunksToDecommit.append(chunk)) { onOutOfMallocMemory(lock); @@ -2117,7 +2189,7 @@ void GCRuntime::decommitEmptyChunks(const bool& cancel, AutoLockGC& lock) { } } - for (TenuredChunk* chunk : chunksToDecommit) { + for (ArenaChunk* chunk : chunksToDecommit) { if (cancel) { break; } @@ -2150,7 +2222,7 @@ void GCRuntime::decommitFreeArenas(const bool& cancel, AutoLockGC& lock) { // it is dangerous to iterate the available list directly, as the active // thread could modify it concurrently. Instead, we build and pass an // explicit Vector containing the Chunks we want to visit. - Vector chunksToDecommit; + Vector chunksToDecommit; for (ChunkPool::Iter chunk(availableChunks(lock)); !chunk.done(); chunk.next()) { if (chunk->info.numArenasFreeCommitted != 0 && @@ -2160,7 +2232,21 @@ void GCRuntime::decommitFreeArenas(const bool& cancel, AutoLockGC& lock) { } } - for (TenuredChunk* chunk : chunksToDecommit) { + for (ArenaChunk* chunk : chunksToDecommit) { + MOZ_ASSERT(chunk->getKind() == ChunkKind::TenuredArenas); + MOZ_ASSERT(!chunk->isEmpty()); + + if (chunk->info.isCurrentChunk) { + // Chunk has become current chunk while lock was released. + continue; + } + + if (!chunk->hasAvailableArenas()) { + // Chunk has become full while lock was released. + continue; + } + + MOZ_ASSERT(availableChunks(lock).contains(chunk)); chunk->decommitFreeArenas(this, cancel, lock); } } @@ -2179,8 +2265,8 @@ void GCRuntime::decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock) { void GCRuntime::maybeRequestGCAfterBackgroundTask( const AutoLockHelperThreadState& lock) { if (requestSliceAfterBackgroundTask) { - // Trigger a slice so the main thread can continue the collection - // immediately. + // Request a slice. The main thread may continue the collection immediately + // or it may yield to let the embedding schedule a slice. requestSliceAfterBackgroundTask = false; requestMajorGC(JS::GCReason::BG_TASK_FINISHED); } @@ -2215,10 +2301,12 @@ void GCRuntime::queueAllLifoBlocksForFreeAfterMinorGC(LifoAlloc* lifo) { lifoBlocksToFreeAfterFullMinorGC.ref().transferFrom(lifo); } -void GCRuntime::queueBuffersForFreeAfterMinorGC(Nursery::BufferSet& buffers) { +void GCRuntime::queueBuffersForFreeAfterMinorGC( + Nursery::BufferSet& buffers, Nursery::StringBufferVector& stringBuffers) { AutoLockHelperThreadState lock; - if (!buffersToFreeAfterMinorGC.ref().empty()) { + if (!buffersToFreeAfterMinorGC.ref().empty() || + !stringBuffersToReleaseAfterMinorGC.ref().empty()) { // In the rare case that this hasn't processed the buffers from a previous // minor GC we have to wait here. MOZ_ASSERT(!freeTask.isIdle(lock)); @@ -2227,6 +2315,9 @@ void GCRuntime::queueBuffersForFreeAfterMinorGC(Nursery::BufferSet& buffers) { MOZ_ASSERT(buffersToFreeAfterMinorGC.ref().empty()); std::swap(buffersToFreeAfterMinorGC.ref(), buffers); + + MOZ_ASSERT(stringBuffersToReleaseAfterMinorGC.ref().empty()); + std::swap(stringBuffersToReleaseAfterMinorGC.ref(), stringBuffers); } void Realm::destroy(JS::GCContext* gcx) { @@ -2342,6 +2433,10 @@ void GCRuntime::sweepZones(JS::GCContext* gcx, bool destroyingRuntime) { assertBackgroundSweepingFinished(); + // Host destroy callbacks can access the store buffer, e.g. when resizing hash + // tables containing nursery pointers. + AutoLockStoreBuffer lock(rt); + // Sweep zones following the atoms zone. MOZ_ASSERT(zones()[0]->isAtomsZone()); Zone** read = zones().begin() + 1; @@ -2354,8 +2449,9 @@ void GCRuntime::sweepZones(JS::GCContext* gcx, bool destroyingRuntime) { if (zone->wasGCStarted()) { MOZ_ASSERT(!zone->isQueuedForBackgroundSweep()); AutoSetThreadIsSweeping threadIsSweeping(zone); - const bool zoneIsDead = - zone->arenas.arenaListsAreEmpty() && !zone->hasMarkedRealms(); + const bool zoneIsDead = zone->arenas.arenaListsAreEmpty() && + zone->bufferAllocator.isEmpty() && + !zone->hasMarkedRealms(); MOZ_ASSERT_IF(destroyingRuntime, zoneIsDead); if (zoneIsDead) { zone->arenas.checkEmptyFreeLists(); @@ -2417,26 +2513,48 @@ bool GCRuntime::shouldPreserveJITCode(Realm* realm, JS::GCReason reason, bool canAllocateMoreCode, bool isActiveCompartment) { - if (cleanUpEverything) { + // During shutdown, we must clean everything up, for the sake of leak + // detection. + if (isShutdownGC()) { return false; } + + // A shrinking GC is trying to clear out as much as it can, and so we should + // not preserve JIT code here! + if (isShrinkingGC()) { + return false; + } + + // We are close to our allocatable code limit, so let's try to clean it out. if (!canAllocateMoreCode) { return false; } + // The topmost frame of JIT code is in this compartment, and so we should + // try to preserve this zone's code. if (isActiveCompartment) { return true; } + + // The gcPreserveJitCode testing function was used. if (alwaysPreserveCode) { return true; } + + // This realm explicitly requested we try to preserve its JIT code. if (realm->preserveJitCode()) { return true; } + + // If we're currently animating, and we've already discarded code recently + // we can preserve jit code; however we shouldn't hold onto JIT code forever + // during animation. if (IsCurrentlyAnimating(realm->lastAnimationTime, currentTime) && DiscardedCodeRecently(realm->zone(), currentTime)) { return true; } + + // GC Invoked via a testing function. if (reason == JS::GCReason::DEBUG_GC) { return true; } @@ -2523,13 +2641,6 @@ void GCRuntime::checkForCompartmentMismatches() { } #endif -static bool ShouldCleanUpEverything(JS::GCOptions options) { - // During shutdown, we must clean everything up, for the sake of leak - // detection. When a runtime has no contexts, or we're doing a GC before a - // shutdown CC, those are strong indications that we're shutting down. - return options == JS::GCOptions::Shutdown || options == JS::GCOptions::Shrink; -} - static bool ShouldUseBackgroundThreads(bool isIncremental, JS::GCReason reason) { bool shouldUse = isIncremental && CanUseExtraThreads(); @@ -2545,11 +2656,9 @@ void GCRuntime::startCollection(JS::GCReason reason) { reason == JS::GCReason::XPCONNECT_SHUTDOWN /* Bug 1650075 */); initialReason = reason; - cleanUpEverything = ShouldCleanUpEverything(gcOptions()); isCompacting = shouldCompact(); rootsRemoved = false; sweepGroupIndex = 0; - lastGCStartTime_ = TimeStamp::Now(); #ifdef DEBUG if (isShutdownGC()) { @@ -2634,11 +2743,13 @@ bool GCRuntime::prepareZonesForCollection(JS::GCReason reason, return any; } -void GCRuntime::discardJITCodeForGC() { +// Update JIT Code state for GC: A few different actions are combined here to +// minimize the number of iterations over zones & scripts that required. +void GCRuntime::maybeDiscardJitCodeForGC() { size_t nurserySiteResetCount = 0; size_t pretenuredSiteResetCount = 0; - js::CancelOffThreadIonCompile(rt, JS::Zone::Prepare); + js::CancelOffThreadCompile(rt, JS::Zone::Prepare); for (GCZonesIter zone(this); !zone.done(); zone.next()) { gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_DISCARD_CODE); @@ -2649,11 +2760,11 @@ void GCRuntime::discardJITCodeForGC() { bool resetPretenuredSites = pz.shouldResetPretenuredAllocSites(); if (!zone->isPreservingCode()) { - Zone::DiscardOptions options; + Zone::JitDiscardOptions options; options.discardJitScripts = true; options.resetNurseryAllocSites = resetNurserySites; options.resetPretenuredAllocSites = resetPretenuredSites; - zone->discardJitCode(rt->gcContext(), options); + zone->forceDiscardJitCode(rt->gcContext(), options); } else if (resetNurserySites || resetPretenuredSites) { zone->resetAllocSitesAndInvalidate(resetNurserySites, resetPretenuredSites); @@ -2796,22 +2907,28 @@ void BackgroundUnmarkTask::initZones() { } } -void BackgroundUnmarkTask::run(AutoLockHelperThreadState& helperTheadLock) { - AutoUnlockHelperThreadState unlock(helperTheadLock); +void BackgroundUnmarkTask::run(AutoLockHelperThreadState& lock) { + { + AutoUnlockHelperThreadState unlock(lock); + unmark(); + zones.clear(); + } + gc->maybeRequestGCAfterBackgroundTask(lock); +} + +void BackgroundUnmarkTask::unmark() { for (Zone* zone : zones) { for (auto kind : AllAllocKinds()) { ArenaList& arenas = zone->arenas.collectingArenaList(kind); - for (ArenaListIter arena(arenas.head()); !arena.done(); arena.next()) { + for (auto arena = arenas.iter(); !arena.done(); arena.next()) { arena->unmarkAll(); if (isCancelled()) { - break; + return; } } } } - - zones.clear(); } void GCRuntime::endPreparePhase(JS::GCReason reason) { @@ -2871,10 +2988,7 @@ void GCRuntime::endPreparePhase(JS::GCReason reason) { AutoUnlockHelperThreadState unlock(helperLock); - // Discard JIT code. For incremental collections, the sweep phase may - // also discard JIT code. - discardJITCodeForGC(); - haveDiscardedJITCodeThisSlice = true; + maybeDiscardJitCodeForGC(); /* * We must purge the runtime at the beginning of an incremental GC. The @@ -2889,8 +3003,11 @@ void GCRuntime::endPreparePhase(JS::GCReason reason) { } // This will start background free for lifo blocks queued by purgeRuntime, - // even if there's nothing in the nursery. + // even if there's nothing in the nursery. Record the number of the minor GC + // so we can check whether we need to wait for it to finish or whether a + // subsequent minor GC already did this. collectNurseryFromMajorGC(reason); + initialMinorGCNumber = minorGCNumber; { gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::PREPARE); @@ -2965,37 +3082,43 @@ void GCRuntime::beginMarkPhase(AutoGCSession& session) { queueMarkColor.reset(); #endif - for (GCZonesIter zone(this); !zone.done(); zone.next()) { - // In an incremental GC, clear the arena free lists to ensure that - // subsequent allocations refill them and end up marking new cells black. - // See arenaAllocatedDuringGC(). - zone->arenas.clearFreeLists(); + { + BufferAllocator::MaybeLock lock; + for (GCZonesIter zone(this); !zone.done(); zone.next()) { + // In an incremental GC, clear the arena free lists to ensure that + // subsequent allocations refill them and end up marking new cells black. + // See arenaAllocatedDuringGC(). + zone->arenas.clearFreeLists(); #ifdef JS_GC_ZEAL - if (hasZealMode(ZealMode::YieldBeforeRootMarking)) { - for (auto kind : AllAllocKinds()) { - for (ArenaIter arena(zone, kind); !arena.done(); arena.next()) { - arena->checkNoMarkedCells(); + if (hasZealMode(ZealMode::YieldBeforeRootMarking)) { + for (auto kind : AllAllocKinds()) { + for (ArenaIter arena(zone, kind); !arena.done(); arena.next()) { + arena->checkNoMarkedCells(); + } } } - } #endif - // Incremental marking barriers are enabled at this point. - zone->changeGCState(Zone::Prepare, zone->initialMarkingState()); + // Incremental marking barriers are enabled at this point. + zone->changeGCState(Zone::Prepare, zone->initialMarkingState()); - // Merge arenas allocated during the prepare phase, then move all arenas to - // the collecting arena lists. - zone->arenas.mergeArenasFromCollectingLists(); - zone->arenas.moveArenasToCollectingLists(); + // Merge arenas allocated during the prepare phase, then move all arenas + // to the collecting arena lists. + zone->arenas.mergeArenasFromCollectingLists(); + zone->arenas.moveArenasToCollectingLists(); - for (RealmsInZoneIter realm(zone); !realm.done(); realm.next()) { - realm->clearAllocatedDuringGC(); + // Prepare sized allocator for major GC. + zone->bufferAllocator.startMajorCollection(lock); + + for (RealmsInZoneIter realm(zone); !realm.done(); realm.next()) { + realm->clearAllocatedDuringGC(); + } } } updateSchedulingStateOnGCStart(); - stats().measureInitialHeapSize(); + stats().measureInitialHeapSizes(); useParallelMarking = SingleThreadedMarking; if (canMarkInParallel() && initParallelMarking()) { @@ -3211,6 +3334,11 @@ void GCRuntime::clearTestMarkQueue() { size_t GCRuntime::testMarkQueuePos() const { return queuePos; } +size_t GCRuntime::testMarkQueueRemaining() const { + MOZ_ASSERT(queuePos <= testMarkQueue.length()); + return testMarkQueue.length() - queuePos; +} + #endif GCRuntime::MarkQueueProgress GCRuntime::processTestMarkQueue() { @@ -3288,12 +3416,13 @@ GCRuntime::MarkQueueProgress GCRuntime::processTestMarkQueue() { } // Mark the object. - AutoEnterOOMUnsafeRegion oomUnsafe; if (!marker().markOneObjectForTest(obj)) { // If we overflowed the stack here and delayed marking, then we won't be // testing what we think we're testing. MOZ_ASSERT(obj->asTenured().arena()->onDelayedMarkingList()); - oomUnsafe.crash("Overflowed stack while marking test queue"); + printf_stderr( + "Hit mark stack limit while marking test queue; test results may " + "be invalid"); } } else if (val.isString()) { JSLinearString* str = &val.toString()->asLinear(); @@ -3335,6 +3464,10 @@ GCRuntime::MarkQueueProgress GCRuntime::processTestMarkQueue() { } } } + + // Once the queue is complete, do not force a mark color (since the next time + // the queue is processed, it should not be forcing one.) + queueMarkColor.reset(); #endif return QueueComplete; @@ -3367,19 +3500,19 @@ void GCRuntime::finishCollection(JS::GCReason reason) { TimeStamp currentTime = TimeStamp::Now(); - updateSchedulingStateAfterCollection(currentTime); + updateSchedulingStateOnGCEnd(currentTime); for (GCZonesIter zone(this); !zone.done(); zone.next()) { zone->changeGCState(Zone::Finished, Zone::NoGC); zone->notifyObservingDebuggers(); + zone->gcNextGraphNode = nullptr; + zone->gcNextGraphComponent = nullptr; } #ifdef JS_GC_ZEAL clearSelectedForMarking(); #endif - schedulingState.updateHighFrequencyMode(lastGCEndTime_, currentTime, - tunables); lastGCEndTime_ = currentTime; checkGCStateNotInUse(); @@ -3404,6 +3537,9 @@ void GCRuntime::checkGCStateNotInUse() { MOZ_ASSERT(!zone->wasGCStarted()); MOZ_ASSERT(!zone->needsIncrementalBarrier()); MOZ_ASSERT(!zone->isOnList()); + MOZ_ASSERT(!zone->gcNextGraphNode); + MOZ_ASSERT(!zone->gcNextGraphComponent); + zone->bufferAllocator.checkGCStateNotInUse(); } MOZ_ASSERT(zonesToMaybeCompact.ref().isEmpty()); @@ -3456,7 +3592,7 @@ void GCRuntime::maybeStopPretenuring() { } } -void GCRuntime::updateSchedulingStateAfterCollection(TimeStamp currentTime) { +void GCRuntime::updateSchedulingStateOnGCEnd(TimeStamp currentTime) { TimeDuration totalGCTime = stats().totalGCTime(); size_t totalInitialBytes = stats().initialCollectedBytes(); @@ -3593,16 +3729,19 @@ GCRuntime::IncrementalResult GCRuntime::resetIncrementalGC( switch (incrementalState) { case State::NotActive: - case State::MarkRoots: case State::Finish: MOZ_CRASH("Unexpected GC state in resetIncrementalGC"); break; case State::Prepare: unmarkTask.cancelAndWait(); + cancelRequestedGCAfterBackgroundTask(); + [[fallthrough]]; + case State::MarkRoots: + // We haven't done any marking yet at this point. for (GCZonesIter zone(this); !zone.done(); zone.next()) { - zone->changeGCState(Zone::Prepare, Zone::NoGC); + zone->changeGCState(zone->gcState(), Zone::NoGC); zone->clearGCSliceThresholds(); zone->arenas.clearFreeLists(); zone->arenas.mergeArenasFromCollectingLists(); @@ -3623,11 +3762,20 @@ GCRuntime::IncrementalResult GCRuntime::resetIncrementalGC( resetGrayList(c); } - for (GCZonesIter zone(this); !zone.done(); zone.next()) { - zone->changeGCState(zone->initialMarkingState(), Zone::NoGC); - zone->clearGCSliceThresholds(); - zone->arenas.unmarkPreMarkedFreeCells(); - zone->arenas.mergeArenasFromCollectingLists(); + // Wait for sweeping of nursery owned sized allocations to finish. + nursery().joinSweepTask(); + + { + BufferAllocator::AutoLock lock(this); + for (GCZonesIter zone(this); !zone.done(); zone.next()) { + zone->changeGCState(zone->initialMarkingState(), Zone::NoGC); + zone->clearGCSliceThresholds(); + zone->arenas.unmarkPreMarkedFreeCells(); + zone->arenas.mergeArenasFromCollectingLists(); + + // Merge sized alloc data structures back without sweeping them. + zone->bufferAllocator.finishMajorCollection(lock); + } } { @@ -3679,7 +3827,11 @@ GCRuntime::IncrementalResult GCRuntime::resetIncrementalGC( stats().reset(reason); - return IncrementalResult::ResetIncremental; + if (reason == GCAbortReason::AbortRequested) { + return IncrementalResult::Abort; + } + + return IncrementalResult::Reset; } AutoDisableBarriers::AutoDisableBarriers(GCRuntime* gc) : gc(gc) { @@ -3744,7 +3896,6 @@ void GCRuntime::incrementalSlice(SliceBudget& budget, JS::GCReason reason, initialState = incrementalState; isIncremental = !budget.isUnlimited(); useBackgroundThreads = ShouldUseBackgroundThreads(isIncremental, reason); - haveDiscardedJITCodeThisSlice = false; #ifdef JS_GC_ZEAL // Do the incremental collection type specified by zeal mode if the collection @@ -3788,12 +3939,23 @@ void GCRuntime::incrementalSlice(SliceBudget& budget, JS::GCReason reason, [[fallthrough]]; case State::Prepare: - if (waitForBackgroundTask(unmarkTask, budget, shouldPauseMutator, - DontTriggerSliceWhenFinished) == NotFinished) { + if (waitForBackgroundTask(unmarkTask, budget, shouldPauseMutator) == + NotFinished) { break; } incrementalState = State::MarkRoots; + + if (isIncremental && initialState == State::Prepare && + reason == JS::GCReason::BG_TASK_FINISHED) { + // The next slice may be long so wait for the embedding to schedule it + // rather than doing it as soon as unmarking finishes. This can happen + // when the embedding's GC callback sees this slice end with work + // available. + MOZ_ASSERT(hasForegroundWork()); + break; + } + [[fallthrough]]; case State::MarkRoots: @@ -3883,13 +4045,38 @@ void GCRuntime::incrementalSlice(SliceBudget& budget, JS::GCReason reason, [[fallthrough]]; case State::Finalize: - if (waitForBackgroundTask(sweepTask, budget, shouldPauseMutator, - TriggerSliceWhenFinished) == NotFinished) { + if (waitForBackgroundTask(sweepTask, budget, shouldPauseMutator) == + NotFinished) { break; } + for (GCZonesIter zone(this); !zone.done(); zone.next()) { + zone->arenas.mergeBackgroundSweptArenas(); + } + + { + BufferAllocator::AutoLock lock(this); + for (GCZonesIter zone(this); !zone.done(); zone.next()) { + zone->bufferAllocator.finishMajorCollection(lock); + } + } + + atomMarking.mergePendingFreeArenaIndexes(this); + + { + AutoLockGC lock(this); + clearCurrentChunk(lock); + } + assertBackgroundSweepingFinished(); + // Ensure freeing of nursery owned sized allocations from the initial + // minor GC has finished. + MOZ_ASSERT(minorGCNumber >= initialMinorGCNumber); + if (minorGCNumber == initialMinorGCNumber) { + MOZ_ASSERT(nursery().sweepTaskIsIdle()); + } + { // Sweep the zones list now that background finalization is finished to // remove and free dead zones, compartments and realms. @@ -3919,6 +4106,7 @@ void GCRuntime::incrementalSlice(SliceBudget& budget, JS::GCReason reason, beginCompactPhase(); } + nursery().joinSweepTask(); if (compactPhase(reason, budget, session) == NotFinished) { break; } @@ -3932,8 +4120,8 @@ void GCRuntime::incrementalSlice(SliceBudget& budget, JS::GCReason reason, [[fallthrough]]; case State::Decommit: - if (waitForBackgroundTask(decommitTask, budget, shouldPauseMutator, - TriggerSliceWhenFinished) == NotFinished) { + if (waitForBackgroundTask(decommitTask, budget, shouldPauseMutator) == + NotFinished) { break; } @@ -3984,9 +4172,9 @@ bool GCRuntime::hasForegroundWork() const { } } -IncrementalProgress GCRuntime::waitForBackgroundTask( - GCParallelTask& task, const SliceBudget& budget, bool shouldPauseMutator, - ShouldTriggerSliceWhenFinished triggerSlice) { +IncrementalProgress GCRuntime::waitForBackgroundTask(GCParallelTask& task, + const SliceBudget& budget, + bool shouldPauseMutator) { // Wait here in non-incremental collections, or if we want to pause the // mutator to let the GC catch up. if (budget.isUnlimited() || shouldPauseMutator) { @@ -3998,14 +4186,12 @@ IncrementalProgress GCRuntime::waitForBackgroundTask( task.join(deadline); } - // In incremental collections, yield if the task has not finished and - // optionally request a slice to notify us when this happens. + // In incremental collections, yield if the task has not finished and request + // a slice to notify us when this happens. if (!budget.isUnlimited()) { AutoLockHelperThreadState lock; if (task.wasStarted(lock)) { - if (triggerSlice) { - requestSliceAfterBackgroundTask = true; - } + requestSliceAfterBackgroundTask = true; return NotFinished; } @@ -4014,23 +4200,11 @@ IncrementalProgress GCRuntime::waitForBackgroundTask( MOZ_ASSERT(task.isIdle()); - if (triggerSlice) { - cancelRequestedGCAfterBackgroundTask(); - } + cancelRequestedGCAfterBackgroundTask(); return Finished; } -GCAbortReason gc::IsIncrementalGCUnsafe(JSRuntime* rt) { - MOZ_ASSERT(!rt->mainContextFromOwnThread()->suppressGC); - - if (!rt->gc.isIncrementalGCAllowed()) { - return GCAbortReason::IncrementalDisabled; - } - - return GCAbortReason::None; -} - inline void GCRuntime::checkZoneIsScheduled(Zone* zone, JS::GCReason reason, const char* trigger) { #ifdef DEBUG @@ -4076,13 +4250,11 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC( } if (!budget.isUnlimited()) { - GCAbortReason unsafeReason = IsIncrementalGCUnsafe(rt); - if (unsafeReason == GCAbortReason::None) { - if (reason == JS::GCReason::COMPARTMENT_REVIVED) { - unsafeReason = GCAbortReason::CompartmentRevived; - } else if (!incrementalGCEnabled) { - unsafeReason = GCAbortReason::ModeChange; - } + GCAbortReason unsafeReason = GCAbortReason::None; + if (reason == JS::GCReason::COMPARTMENT_REVIVED) { + unsafeReason = GCAbortReason::CompartmentRevived; + } else if (!incrementalGCEnabled) { + unsafeReason = GCAbortReason::ModeChange; } if (unsafeReason != GCAbortReason::None) { @@ -4138,7 +4310,9 @@ GCRuntime::IncrementalResult GCRuntime::budgetIncrementalGC( return IncrementalResult::Ok; } -bool GCRuntime::maybeIncreaseSliceBudget(SliceBudget& budget) { +bool GCRuntime::maybeIncreaseSliceBudget(SliceBudget& budget, + TimeStamp sliceStartTime, + TimeStamp gcStartTime) { if (js::SupportDifferentialTesting()) { return false; } @@ -4148,7 +4322,8 @@ bool GCRuntime::maybeIncreaseSliceBudget(SliceBudget& budget) { } bool wasIncreasedForLongCollections = - maybeIncreaseSliceBudgetForLongCollections(budget); + maybeIncreaseSliceBudgetForLongCollections(budget, sliceStartTime, + gcStartTime); bool wasIncreasedForUgentCollections = maybeIncreaseSliceBudgetForUrgentCollections(budget); @@ -4170,7 +4345,7 @@ static bool ExtendBudget(SliceBudget& budget, double newDuration) { } bool GCRuntime::maybeIncreaseSliceBudgetForLongCollections( - SliceBudget& budget) { + SliceBudget& budget, TimeStamp sliceStartTime, TimeStamp gcStartTime) { // For long-running collections, enforce a minimum time budget that increases // linearly with time up to a maximum. @@ -4182,7 +4357,7 @@ bool GCRuntime::maybeIncreaseSliceBudgetForLongCollections( const BudgetAtTime MinBudgetStart{1500, 0.0}; const BudgetAtTime MinBudgetEnd{2500, 100.0}; - double totalTime = (TimeStamp::Now() - lastGCStartTime()).ToMilliseconds(); + double totalTime = (sliceStartTime - gcStartTime).ToMilliseconds(); double minBudget = LinearInterpolate(totalTime, MinBudgetStart.time, MinBudgetStart.budget, @@ -4312,7 +4487,7 @@ void GCRuntime::maybeCallGCCallback(JSGCStatus status, JS::GCReason reason) { // At the end of a GC, clear out the fullGCRequested state. At the start, // restore the previous setting. - fullGCRequested = (status == JSGC_END) ? false : savedFullGCRequested; + fullGCRequested = savedFullGCRequested; if (gcCallbackDepth == 0) { // Ensure any zone that was originally scheduled stays scheduled. @@ -4343,7 +4518,8 @@ MOZ_NEVER_INLINE GCRuntime::IncrementalResult GCRuntime::gcCycle( // Background finalization and decommit are finished by definition before we // can start a new major GC. Background allocation may still be running, but // that's OK because chunk pools are protected by the GC lock. - if (!isIncrementalGCInProgress()) { + bool firstSlice = !isIncrementalGCInProgress(); + if (firstSlice) { assertBackgroundSweepingFinished(); MOZ_ASSERT(decommitTask.isIdle()); } @@ -4351,10 +4527,27 @@ MOZ_NEVER_INLINE GCRuntime::IncrementalResult GCRuntime::gcCycle( // Note that GC callbacks are allowed to re-enter GC. AutoCallGCCallbacks callCallbacks(*this, reason); + // Reset the fullGCRequested flag at the end of GC. + auto resetFullFlag = MakeScopeExit([&] { + if (!isIncrementalGCInProgress()) { + fullGCRequested = false; + } + }); + + // Record GC start time and update global scheduling state. + TimeStamp now = TimeStamp::Now(); + if (firstSlice) { + schedulingState.updateHighFrequencyModeOnGCStart( + gcOptions(), lastGCStartTime_, now, tunables); + lastGCStartTime_ = now; + } + schedulingState.updateHighFrequencyModeOnSliceStart(gcOptions(), reason); + // Increase slice budget for long running collections before it is recorded by // AutoGCSlice. SliceBudget budget(budgetArg); - bool budgetWasIncreased = maybeIncreaseSliceBudget(budget); + bool budgetWasIncreased = + maybeIncreaseSliceBudget(budget, now, lastGCStartTime_); ScheduleZones(this, reason); @@ -4369,13 +4562,15 @@ MOZ_NEVER_INLINE GCRuntime::IncrementalResult GCRuntime::gcCycle( IncrementalResult result = budgetIncrementalGC(nonincrementalByAPI, reason, budget); - if (result == IncrementalResult::ResetIncremental) { - if (incrementalState == State::NotActive) { - // The collection was reset and has finished. - return result; - } + if (result != IncrementalResult::Ok && incrementalState == State::NotActive) { + // The collection was reset or aborted and has finished. + return result; + } - // The collection was reset but we must finish up some remaining work. + if (result == IncrementalResult::Reset) { + // The collection was reset but we must finish up some remaining work. This + // happens with the reset reason, after which a new collection will be + // started. reason = JS::GCReason::RESET; } @@ -4389,7 +4584,7 @@ MOZ_NEVER_INLINE GCRuntime::IncrementalResult GCRuntime::gcCycle( incrementalSlice(budget, reason, budgetWasIncreased); gcprobes::MajorGCEnd(); - MOZ_ASSERT_IF(result == IncrementalResult::ResetIncremental, + MOZ_ASSERT_IF(result == IncrementalResult::Reset, !isIncrementalGCInProgress()); return result; } @@ -4568,8 +4763,6 @@ void GCRuntime::collect(bool nonincrementalByAPI, const SliceBudget& budget, AutoMaybeLeaveAtomsZone leaveAtomsZone(rt->mainContextFromOwnThread()); AutoSetZoneSliceThresholds sliceThresholds(this); - schedulingState.updateHighFrequencyModeForReason(reason); - if (!isIncrementalGCInProgress() && tunables.balancedHeapLimitsEnabled()) { updateAllocationRates(); } @@ -4579,7 +4772,8 @@ void GCRuntime::collect(bool nonincrementalByAPI, const SliceBudget& budget, IncrementalResult cycleResult = gcCycle(nonincrementalByAPI, budget, reason); - if (reason == JS::GCReason::ABORT_GC) { + if (cycleResult == IncrementalResult::Abort) { + MOZ_ASSERT(reason == JS::GCReason::ABORT_GC); MOZ_ASSERT(!isIncrementalGCInProgress()); stats().log("GC aborted by request"); break; @@ -4595,7 +4789,7 @@ void GCRuntime::collect(bool nonincrementalByAPI, const SliceBudget& budget, */ repeat = false; if (!isIncrementalGCInProgress()) { - if (cycleResult == ResetIncremental) { + if (cycleResult == IncrementalResult::Reset) { repeat = true; } else if (rootsRemoved && isShutdownGC()) { /* Need to re-schedule all zones for GC. */ @@ -4614,12 +4808,14 @@ void GCRuntime::collect(bool nonincrementalByAPI, const SliceBudget& budget, } #ifdef JS_GC_ZEAL - if (hasZealMode(ZealMode::CheckHeapAfterGC)) { - gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::TRACE_HEAP); - CheckHeapAfterGC(rt); - } - if (hasZealMode(ZealMode::CheckGrayMarking) && !isIncrementalGCInProgress()) { - MOZ_RELEASE_ASSERT(CheckGrayMarkingState(rt)); + if (!isIncrementalGCInProgress()) { + if (hasZealMode(ZealMode::CheckHeapAfterGC)) { + gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::TRACE_HEAP); + CheckHeapAfterGC(rt); + } + if (hasZealMode(ZealMode::CheckGrayMarking)) { + MOZ_RELEASE_ASSERT(CheckGrayMarkingState(rt)); + } } #endif stats().log("GC slice ending in state %s", StateName(incrementalState)); @@ -4658,7 +4854,7 @@ void GCRuntime::gc(JS::GCOptions options, JS::GCReason reason) { } void GCRuntime::startGC(JS::GCOptions options, JS::GCReason reason, - const js::SliceBudget& budget) { + const SliceBudget& budget) { MOZ_ASSERT(!isIncrementalGCInProgress()); setGCOptions(options); @@ -4675,7 +4871,7 @@ void GCRuntime::setGCOptions(JS::GCOptions options) { maybeGcOptions = Some(options); } -void GCRuntime::gcSlice(JS::GCReason reason, const js::SliceBudget& budget) { +void GCRuntime::gcSlice(JS::GCReason reason, const SliceBudget& budget) { MOZ_ASSERT(isIncrementalGCInProgress()); collect(false, budget, reason); } @@ -4736,11 +4932,22 @@ void GCRuntime::debugGCSlice(const SliceBudget& budget) { collect(false, budget, JS::GCReason::DEBUG_GC); } -/* Schedule a full GC unless a zone will already be collected. */ void js::PrepareForDebugGC(JSRuntime* rt) { - if (!ZonesSelected(&rt->gc)) { - JS::PrepareForFullGC(rt->mainContextFromOwnThread()); + // If zones have already been scheduled then use them. + if (ZonesSelected(&rt->gc)) { + return; } + + // If we already started a GC then continue with the same set of zones. This + // prevents resetting an ongoing GC when new zones are added. + JSContext* cx = rt->mainContextFromOwnThread(); + if (JS::IsIncrementalGCInProgress(cx)) { + JS::PrepareForIncrementalGC(cx); + return; + } + + // Otherwise schedule all zones. + JS::PrepareForFullGC(rt->mainContextFromOwnThread()); } void GCRuntime::onOutOfMallocMemory() { @@ -4792,6 +4999,8 @@ void GCRuntime::minorGC(JS::GCReason reason, gcstats::PhaseKind phase) { #ifdef JS_GC_ZEAL if (hasZealMode(ZealMode::CheckHeapAfterGC)) { gcstats::AutoPhase ap(stats(), phase); + waitBackgroundSweepEnd(); + waitBackgroundDecommitEnd(); CheckHeapAfterGC(rt); } #endif @@ -4827,6 +5036,14 @@ void GCRuntime::collectNursery(JS::GCOptions options, JS::GCReason reason, MOZ_ASSERT(nursery().isEmpty()); startBackgroundFreeAfterMinorGC(); } + + // Disabling the nursery triggers pre-barriers when we discard JIT + // code. Normally we don't allow any barriers in a major GC and there is an + // assertion to check this in PreWriteBarrier. For the case where we disable + // the nursery during a major GC, set up a minor GC session to silence the + // assertion. + AutoGCSession session(this, JS::HeapState::MinorCollecting); + nursery().disable(); } } @@ -4846,8 +5063,7 @@ void GCRuntime::startBackgroundFreeAfterMinorGC() { &lifoBlocksToFreeAfterFullMinorGC.ref()); } - if (lifoBlocksToFree.ref().isEmpty() && - buffersToFreeAfterMinorGC.ref().empty()) { + if (!hasBuffersForBackgroundFree()) { return; } @@ -5016,7 +5232,8 @@ void GCRuntime::runDebugGC() { return; } - if (hasZealMode(ZealMode::GenerationalGC)) { + if (hasZealMode(ZealMode::VerifierPost) || + hasZealMode(ZealMode::GenerationalGC)) { return minorGC(JS::GCReason::DEBUG_GC); } @@ -5111,6 +5328,9 @@ AutoAssertNoNurseryAlloc::~AutoAssertNoNurseryAlloc() { #ifdef JSGC_HASH_TABLE_CHECKS void GCRuntime::checkHashTablesAfterMovingGC() { + waitBackgroundSweepEnd(); + waitBackgroundDecommitEnd(); + /* * Check that internal hash tables no longer have any pointers to things * that have been moved. diff --git a/src/third_party/mozjs/extract/js/src/gc/GC.h b/src/third_party/mozjs/extract/js/src/gc/GC.h index 428433d24bb..68f85e30827 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GC.h +++ b/src/third_party/mozjs/extract/js/src/gc/GC.h @@ -31,7 +31,7 @@ class Nursery; namespace gc { class Arena; -class TenuredChunk; +class ArenaChunk; } /* namespace gc */ @@ -65,8 +65,8 @@ class TenuredChunk; _("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \ _("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \ _("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \ - _("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \ _("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \ + _("nurseryEnabled", JSGC_NURSERY_ENABLED, true) \ _("parallelMarkingEnabled", JSGC_PARALLEL_MARKING_ENABLED, true) \ _("parallelMarkingThresholdMB", JSGC_PARALLEL_MARKING_THRESHOLD_MB, true) \ _("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \ @@ -76,6 +76,7 @@ class TenuredChunk; JSGC_NURSERY_EAGER_COLLECTION_THRESHOLD_PERCENT, true) \ _("nurseryEagerCollectionTimeoutMS", \ JSGC_NURSERY_EAGER_COLLECTION_TIMEOUT_MS, true) \ + _("nurseryMaxTimeGoalMS", JSGC_NURSERY_MAX_TIME_GOAL_MS, true) \ _("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \ _("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \ _("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \ @@ -87,7 +88,8 @@ class TenuredChunk; _("markingThreadCount", JSGC_MARKING_THREAD_COUNT, false) \ _("systemPageSizeKB", JSGC_SYSTEM_PAGE_SIZE_KB, false) \ _("semispaceNurseryEnabled", JSGC_SEMISPACE_NURSERY_ENABLED, true) \ - _("generateMissingAllocSites", JSGC_GENERATE_MISSING_ALLOC_SITES, true) + _("generateMissingAllocSites", JSGC_GENERATE_MISSING_ALLOC_SITES, true) \ + _("highFrequencyMode", JSGC_HIGH_FREQUENCY_MODE, false) // Get the key and writability give a GC parameter name. extern bool GetGCParameterInfo(const char* name, JSGCParamKey* keyOut, @@ -110,7 +112,7 @@ extern unsigned NotifyGCPreSwap(JSObject* a, JSObject* b); extern void NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned removedFlags); -using IterateChunkCallback = void (*)(JSRuntime*, void*, gc::TenuredChunk*, +using IterateChunkCallback = void (*)(JSRuntime*, void*, gc::ArenaChunk*, const JS::AutoRequireNoGC&); using IterateZoneCallback = void (*)(JSRuntime*, void*, JS::Zone*, const JS::AutoRequireNoGC&); @@ -167,7 +169,7 @@ void FinishGC(JSContext* cx, JS::GCReason = JS::GCReason::FINISH_GC); void WaitForBackgroundTasks(JSContext* cx); -enum VerifierType { PreBarrierVerifier }; +enum VerifierType { PreBarrierVerifier, PostBarrierVerifier }; #ifdef JS_GC_ZEAL diff --git a/src/third_party/mozjs/extract/js/src/gc/GCAPI.cpp b/src/third_party/mozjs/extract/js/src/gc/GCAPI.cpp index dcd08fd67b6..84f1ab0eeec 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCAPI.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/GCAPI.cpp @@ -94,7 +94,7 @@ void PreventGCDuringInteractiveDebug() { TlsContext.get()->suppressGC++; } #endif void js::ReleaseAllJITCode(JS::GCContext* gcx) { - js::CancelOffThreadIonCompile(gcx->runtime()); + js::CancelOffThreadCompile(gcx->runtime()); for (ZonesIter zone(gcx->runtime(), SkipAtoms); !zone.done(); zone.next()) { zone->forceDiscardJitCode(gcx); @@ -102,6 +102,8 @@ void js::ReleaseAllJITCode(JS::GCContext* gcx) { jitZone->discardStubs(); } } + + gcx->runtime()->clearSelfHostedJitCache(); } AutoSuppressGC::AutoSuppressGC(JSContext* cx) @@ -302,7 +304,7 @@ JS_PUBLIC_API void JS::NonIncrementalGC(JSContext* cx, JS::GCOptions options, JS_PUBLIC_API void JS::StartIncrementalGC(JSContext* cx, JS::GCOptions options, GCReason reason, - const js::SliceBudget& budget) { + const JS::SliceBudget& budget) { AssertHeapIsIdle(); CHECK_THREAD(cx); CheckGCOptions(options); @@ -311,7 +313,7 @@ JS_PUBLIC_API void JS::StartIncrementalGC(JSContext* cx, JS::GCOptions options, } JS_PUBLIC_API void JS::IncrementalGCSlice(JSContext* cx, GCReason reason, - const js::SliceBudget& budget) { + const JS::SliceBudget& budget) { AssertHeapIsIdle(); CHECK_THREAD(cx); @@ -431,13 +433,8 @@ JS_PUBLIC_API void JS::SetLowMemoryState(JSContext* cx, bool newState) { return cx->runtime()->gc.setLowMemoryState(newState); } -JS_PUBLIC_API void JS::DisableIncrementalGC(JSContext* cx) { - cx->runtime()->gc.disallowIncrementalGC(); -} - JS_PUBLIC_API bool JS::IsIncrementalGCEnabled(JSContext* cx) { - GCRuntime& gc = cx->runtime()->gc; - return gc.isIncrementalGCEnabled() && gc.isIncrementalGCAllowed(); + return cx->runtime()->gc.isIncrementalGCEnabled(); } JS_PUBLIC_API bool JS::IsIncrementalGCInProgress(JSContext* cx) { diff --git a/src/third_party/mozjs/extract/js/src/gc/GCContext.h b/src/third_party/mozjs/extract/js/src/gc/GCContext.h index 8c74a81e0c6..5484406c144 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCContext.h +++ b/src/third_party/mozjs/extract/js/src/gc/GCContext.h @@ -26,6 +26,7 @@ namespace gc { class AutoSetThreadGCUse; class AutoSetThreadIsSweeping; +class AutoDisallowPreWriteBarrier; enum class GCUse { // This thread is not running in the garbage collector. @@ -76,6 +77,7 @@ class GCContext { js::gc::GCUse gcUse_ = js::gc::GCUse::None; friend class js::gc::AutoSetThreadGCUse; friend class js::gc::AutoSetThreadIsSweeping; + friend class js::gc::AutoDisallowPreWriteBarrier; #ifdef DEBUG // The specific zone currently being swept, if any. @@ -84,6 +86,9 @@ class GCContext { // Whether this thread is currently manipulating possibly-gray GC things. size_t isTouchingGrayThings_ = false; friend class js::AutoTouchingGrayThings; + + // Whether it's safe to perform pre-write barriers. + bool preWriteBarrierAllowed_ = true; #endif public: @@ -110,6 +115,7 @@ class GCContext { Zone* gcSweepZone() const { return gcSweepZone_; } bool isTouchingGrayThings() const { return isTouchingGrayThings_; } + bool isPreWriteBarrierAllowed() const { return preWriteBarrierAllowed_; } #endif // Deprecated. Where possible, memory should be tracked against the owning GC diff --git a/src/third_party/mozjs/extract/js/src/gc/GCEnum.h b/src/third_party/mozjs/extract/js/src/gc/GCEnum.h index f2cae7a0e5f..77da0659115 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCEnum.h +++ b/src/third_party/mozjs/extract/js/src/gc/GCEnum.h @@ -56,6 +56,7 @@ enum class State { D(RootsChange, 1) \ D(Alloc, 2) \ D(VerifierPre, 4) \ + D(VerifierPost, 5) \ D(YieldBeforeRootMarking, 6) \ D(GenerationalGC, 7) \ D(YieldBeforeMarking, 8) \ @@ -73,7 +74,8 @@ enum class State { D(YieldBeforeSweepingNonObjects, 22) \ D(YieldBeforeSweepingPropMapTrees, 23) \ D(CheckWeakMapMarking, 24) \ - D(YieldWhileGrayMarking, 25) + D(YieldWhileGrayMarking, 25) \ + D(CheckHeapBeforeMinorGC, 26) enum class ZealMode { #define ZEAL_MODE(name, value) name = value, @@ -108,10 +110,8 @@ enum class GCAbortReason { #define JS_FOR_EACH_INTERNAL_MEMORY_USE(_) \ _(ArrayBufferContents) \ _(StringContents) \ - _(ObjectElements) \ - _(ObjectSlots) \ _(ScriptPrivateData) \ - _(MapObjectTable) \ + _(MapObjectData) \ _(BigIntDigits) \ _(ScopeData) \ _(WeakMapObject) \ diff --git a/src/third_party/mozjs/extract/js/src/gc/GCInternals.h b/src/third_party/mozjs/extract/js/src/gc/GCInternals.h index c69b342f1e4..c03d24aaaa2 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCInternals.h +++ b/src/third_party/mozjs/extract/js/src/gc/GCInternals.h @@ -19,11 +19,15 @@ #include "gc/Cell.h" #include "gc/GC.h" #include "gc/GCContext.h" +#include "gc/GCMarker.h" #include "vm/GeckoProfiler.h" #include "vm/HelperThreads.h" #include "vm/JSContext.h" namespace js { + +class GCMarker; + namespace gc { /* @@ -191,8 +195,6 @@ class MOZ_RAII AutoRunParallelTask : public GCParallelTask { } }; -GCAbortReason IsIncrementalGCUnsafe(JSRuntime* rt); - #ifdef JS_GC_ZEAL class MOZ_RAII AutoStopVerifyingBarriers { @@ -299,6 +301,28 @@ class AutoSetThreadIsSweeping : public AutoSetThreadGCUseT { #endif }; +class MOZ_RAII AutoDisallowPreWriteBarrier { + public: + explicit AutoDisallowPreWriteBarrier(JS::GCContext* gcx) { +#ifdef DEBUG + gcx_ = gcx; + MOZ_ASSERT(gcx->preWriteBarrierAllowed_); + gcx->preWriteBarrierAllowed_ = false; +#endif + } + ~AutoDisallowPreWriteBarrier() { +#ifdef DEBUG + MOZ_ASSERT(!gcx_->preWriteBarrierAllowed_); + gcx_->preWriteBarrierAllowed_ = true; +#endif + } + + private: +#ifdef DEBUG + JS::GCContext* gcx_; +#endif +}; + #ifdef JSGC_HASH_TABLE_CHECKS void CheckHashTablesAfterMovingGC(JSRuntime* rt); void CheckHeapAfterGC(JSRuntime* rt); @@ -323,6 +347,16 @@ struct MinorSweepingTracer final friend class GenericTracerImpl; }; +class MOZ_RAII AutoUpdateMarkStackRanges { + GCMarker& marker_; + + public: + explicit AutoUpdateMarkStackRanges(GCMarker& marker) : marker_(marker) { + marker_.updateRangesAtStartOfSlice(); + } + ~AutoUpdateMarkStackRanges() { marker_.updateRangesAtEndOfSlice(); } +}; + extern void DelayCrossCompartmentGrayMarking(GCMarker* maybeMarker, JSObject* src); diff --git a/src/third_party/mozjs/extract/js/src/gc/GCMarker.h b/src/third_party/mozjs/extract/js/src/gc/GCMarker.h index 3e48e43fcec..281d40e91b9 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCMarker.h +++ b/src/third_party/mozjs/extract/js/src/gc/GCMarker.h @@ -9,19 +9,23 @@ #include "mozilla/Maybe.h" #include "mozilla/Variant.h" +#include "mozilla/XorShift128PlusRNG.h" -#include "ds/OrderedHashTable.h" #include "gc/Barrier.h" +#include "js/HashTable.h" #include "js/TracingAPI.h" #include "js/TypeDecls.h" #include "threading/ProtectedData.h" class JSRope; +namespace JS { +class SliceBudget; +} + namespace js { class GCMarker; -class SliceBudget; class WeakMapBase; #ifdef DEBUG @@ -49,17 +53,6 @@ class MarkStackIter; class ParallelMarker; class UnmarkGrayTracer; -struct EphemeronEdgeTableHashPolicy { - using Lookup = Cell*; - static HashNumber hash(const Lookup& v, - const mozilla::HashCodeScrambler& hcs) { - return hcs.scramble(mozilla::HashGeneric(v)); - } - static bool match(Cell* const& k, const Lookup& l) { return k == l; } - static bool isEmpty(Cell* const& v) { return !v; } - static void makeEmpty(Cell** vp) { *vp = nullptr; } -}; - // Ephemeron edges have two source nodes and one target, and mark the target // with the minimum (least-marked) color of the sources. Currently, one of // those sources will always be a WeakMapBase, so this will refer to its color @@ -74,9 +67,8 @@ struct EphemeronEdge { using EphemeronEdgeVector = Vector; -using EphemeronEdgeTable = - OrderedHashMap; +using EphemeronEdgeTable = HashMap, js::SystemAllocPolicy>; /* * The mark stack. Pointers in this stack are "gray" in the GC sense, but @@ -103,6 +95,7 @@ class MarkStack { enum Tag { SlotsOrElementsRangeTag = 0, // Must match SlotsOrElementsKind::Unused. ObjectTag, + SymbolTag, JitCodeTag, ScriptTag, TempRopeTag, @@ -121,12 +114,14 @@ class MarkStack { Cell* ptr() const; + explicit TaggedPtr(uintptr_t bits); + public: - TaggedPtr() = default; TaggedPtr(Tag tag, Cell* ptr); + static TaggedPtr fromBits(uintptr_t bits); + uintptr_t asBits() const; Tag tag() const; - uintptr_t tagUnchecked() const; template T* as() const; @@ -136,23 +131,30 @@ class MarkStack { void assertValid() const; }; - struct SlotsOrElementsRange { + class SlotsOrElementsRange { + uintptr_t startAndKind_; + TaggedPtr ptr_; + + static constexpr size_t StartShift = 2; + static constexpr size_t KindMask = (1 << StartShift) - 1; + + SlotsOrElementsRange(uintptr_t startAndKind, uintptr_t ptr); + + public: SlotsOrElementsRange(SlotsOrElementsKind kind, JSObject* obj, size_t start); + static SlotsOrElementsRange fromBits(uintptr_t startAndKind, uintptr_t ptr); + void assertValid() const; + uintptr_t asBits0() const; + uintptr_t asBits1() const; + SlotsOrElementsKind kind() const; size_t start() const; TaggedPtr ptr() const; void setStart(size_t newStart); void setEmpty(); - - private: - static constexpr size_t StartShift = 2; - static constexpr size_t KindMask = (1 << StartShift) - 1; - - uintptr_t startAndKind_; - TaggedPtr ptr_; }; MarkStack(); @@ -163,20 +165,20 @@ class MarkStack { void swap(MarkStack& other); - // The unit for MarkStack::capacity() is mark stack words. - size_t capacity() { return stack().length(); } + // The unit for capacity is mark stack words. + size_t capacity() const { return capacity_; } +#ifdef JS_GC_ZEAL + void setMaxCapacity(size_t maxCapacity); +#endif size_t position() const { return topIndex_; } [[nodiscard]] bool init(); [[nodiscard]] bool resetStackCapacity(); -#ifdef JS_GC_ZEAL - void setMaxCapacity(size_t maxCapacity); -#endif - template [[nodiscard]] bool push(T* ptr); + void infalliblePush(const SlotsOrElementsRange& range); void infalliblePush(JSObject* obj, SlotsOrElementsKind kind, size_t start); [[nodiscard]] bool push(const TaggedPtr& ptr); void infalliblePush(const TaggedPtr& ptr); @@ -199,29 +201,42 @@ class MarkStack { [[nodiscard]] bool ensureSpace(size_t count); - static void moveWork(MarkStack& dst, MarkStack& src); + static size_t moveWork(GCMarker* marker, MarkStack& dst, MarkStack& src, + bool allowDistribute); size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; private: - using StackVector = Vector; - const StackVector& stack() const { return stack_.ref(); } - StackVector& stack() { return stack_.ref(); } + uintptr_t at(size_t index) const { + MOZ_ASSERT(topIndex_ <= capacity_); + MOZ_ASSERT(index < topIndex_); + return stack_[index]; + } + uintptr_t* ptr(size_t index) { + MOZ_ASSERT(topIndex_ <= capacity_); + MOZ_ASSERT(index <= topIndex_); + return stack_ + index; + } - /* Grow the stack, ensuring there is space for at least count elements. */ + // Return a pointer to the first unused word beyond the top of the stack. + uintptr_t* end() { return ptr(topIndex_); } + + // Grow the stack, ensuring there is space to push |count| more words. [[nodiscard]] bool enlarge(size_t count); [[nodiscard]] bool resize(size_t newCapacity); - TaggedPtr* topPtr(); + TaggedPtr peekPtr() const; - const TaggedPtr& peekPtr() const; [[nodiscard]] bool pushTaggedPtr(Tag tag, Cell* ptr); bool indexIsEntryBase(size_t index) const; - // Vector containing allocated stack memory. Unused beyond topIndex_. - MainThreadOrGCTaskData stack_; + // Area of memory containing the stack. + MainThreadOrGCTaskData stack_; + + // Size of the stack in words. + MainThreadOrGCTaskData capacity_; // Index of the top of the stack. MainThreadOrGCTaskData topIndex_; @@ -256,12 +271,13 @@ class MOZ_STACK_CLASS MarkStackIter { void next(); MarkStack::Tag peekTag() const; + MarkStack::TaggedPtr peekPtr() const; bool isSlotsOrElementsRange() const; - MarkStack::SlotsOrElementsRange& slotsOrElementsRange(); + MarkStack::SlotsOrElementsRange slotsOrElementsRange() const; + void setSlotsOrElementsRange(const MarkStack::SlotsOrElementsRange& range); private: size_t position() const; - MarkStack::TaggedPtr peekPtr() const; }; // Bitmask of options to parameterize MarkingTracerT. @@ -371,7 +387,7 @@ class GCMarker { void reset(); [[nodiscard]] bool markUntilBudgetExhausted( - SliceBudget& budget, + JS::SliceBudget& budget, gc::ShouldReportMarkTime reportTime = gc::ReportMarkTime); void setRootMarkingMode(bool newState); @@ -397,12 +413,12 @@ class GCMarker { bool markOneObjectForTest(JSObject* obj); #endif - bool markCurrentColorInParallel(SliceBudget& budget); + bool markCurrentColorInParallel(JS::SliceBudget& budget); template - bool markOneColor(SliceBudget& budget); + bool markOneColor(JS::SliceBudget& budget); - static void moveWork(GCMarker* dst, GCMarker* src); + static size_t moveWork(GCMarker* dst, GCMarker* src, bool allowDistribute); [[nodiscard]] bool initStack(); void resetStackCapacity(); @@ -449,7 +465,7 @@ class GCMarker { friend class gc::AutoUpdateMarkStackRanges; template - bool processMarkStackTop(SliceBudget& budget); + bool processMarkStackTop(JS::SliceBudget& budget); friend class gc::GCRuntime; // Helper methods that coerce their second argument to the base pointer @@ -471,6 +487,9 @@ class GCMarker { template bool markAndTraversePrivateGCThing(JSObject* source, gc::TenuredCell* target); + template + bool markAndTraverseSymbol(JSObject* source, JS::Symbol* target); + template void checkTraversedEdge(S source, T* target); @@ -534,7 +553,7 @@ class GCMarker { #endif template - bool doMarking(SliceBudget& budget, gc::ShouldReportMarkTime reportTime); + bool doMarking(JS::SliceBudget& budget, gc::ShouldReportMarkTime reportTime); void delayMarkingChildrenOnOOM(gc::Cell* cell); @@ -580,6 +599,9 @@ class GCMarker { */ MainThreadOrGCTaskData incrementalWeakMapMarkingEnabled; + /* Random number generator state. */ + MainThreadOrGCTaskData random; + #ifdef DEBUG private: /* Assert that start and stop are called with correct ordering. */ diff --git a/src/third_party/mozjs/extract/js/src/gc/GCParallelTask.h b/src/third_party/mozjs/extract/js/src/gc/GCParallelTask.h index 44d02d82a9d..d5776dd7e0b 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCParallelTask.h +++ b/src/third_party/mozjs/extract/js/src/gc/GCParallelTask.h @@ -127,7 +127,7 @@ class GCParallelTask : private mozilla::LinkedListElement, protected: // A flag to signal a request for early completion of the off-thread task. - mozilla::Atomic cancel_; + mozilla::Atomic cancel_; public: explicit GCParallelTask(gc::GCRuntime* gc, gcstats::PhaseKind phaseKind, @@ -203,6 +203,8 @@ class GCParallelTask : private mozilla::LinkedListElement, state_ == State::Dispatched; } + const char* getName() override { return "GCParallelTask"; } + protected: // Override this method to provide the task's functionality. virtual void run(AutoLockHelperThreadState& lock) = 0; diff --git a/src/third_party/mozjs/extract/js/src/gc/GCRuntime.h b/src/third_party/mozjs/extract/js/src/gc/GCRuntime.h index 122e5f3ebee..652b0332c0c 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GCRuntime.h +++ b/src/third_party/mozjs/extract/js/src/gc/GCRuntime.h @@ -19,6 +19,7 @@ #include "gc/GCMarker.h" #include "gc/GCParallelTask.h" #include "gc/IteratorUtils.h" +#include "gc/Memory.h" #include "gc/Nursery.h" #include "gc/Scheduling.h" #include "gc/Statistics.h" @@ -49,7 +50,7 @@ class AutoCallGCCallbacks; class AutoGCSession; class AutoHeapSession; class AutoTraceSession; -struct FinalizePhase; +class BufferAllocator; class MarkingValidator; struct MovingTracer; class ParallelMarkTask; @@ -62,7 +63,7 @@ struct SweepAction { struct Args { GCRuntime* gc; JS::GCContext* gcx; - SliceBudget& budget; + JS::SliceBudget& budget; }; virtual ~SweepAction() = default; @@ -72,7 +73,7 @@ struct SweepAction { }; class ChunkPool { - TenuredChunk* head_; + ArenaChunk* head_; size_t count_; public: @@ -97,52 +98,52 @@ class ChunkPool { bool empty() const { return !head_; } size_t count() const { return count_; } - TenuredChunk* head() { + ArenaChunk* head() { MOZ_ASSERT(head_); return head_; } - TenuredChunk* pop(); - void push(TenuredChunk* chunk); - TenuredChunk* remove(TenuredChunk* chunk); + ArenaChunk* pop(); + void push(ArenaChunk* chunk); + ArenaChunk* remove(ArenaChunk* chunk); void sort(); private: - TenuredChunk* mergeSort(TenuredChunk* list, size_t count); + ArenaChunk* mergeSort(ArenaChunk* list, size_t count); bool isSorted() const; #ifdef DEBUG public: - bool contains(TenuredChunk* chunk) const; + bool contains(ArenaChunk* chunk) const; bool verify() const; void verifyChunks() const; #endif public: // Pool mutation does not invalidate an Iter unless the mutation - // is of the TenuredChunk currently being visited by the Iter. + // is of the ArenaChunk currently being visited by the Iter. class Iter { public: explicit Iter(ChunkPool& pool) : current_(pool.head_) {} bool done() const { return !current_; } void next(); - TenuredChunk* get() const { return current_; } - operator TenuredChunk*() const { return get(); } - TenuredChunk* operator->() const { return get(); } + ArenaChunk* get() const { return current_; } + operator ArenaChunk*() const { return get(); } + ArenaChunk* operator->() const { return get(); } private: - TenuredChunk* current_; + ArenaChunk* current_; }; }; class BackgroundMarkTask : public GCParallelTask { public: explicit BackgroundMarkTask(GCRuntime* gc); - void setBudget(const SliceBudget& budget) { this->budget = budget; } + void setBudget(const JS::SliceBudget& budget) { this->budget = budget; } void run(AutoLockHelperThreadState& lock) override; private: - SliceBudget budget; + JS::SliceBudget budget; }; class BackgroundUnmarkTask : public GCParallelTask { @@ -151,6 +152,9 @@ class BackgroundUnmarkTask : public GCParallelTask { void initZones(); void run(AutoLockHelperThreadState& lock) override; + private: + void unmark(); + ZoneVector zones; }; @@ -336,18 +340,18 @@ class GCRuntime { void gc(JS::GCOptions options, JS::GCReason reason); void startGC(JS::GCOptions options, JS::GCReason reason, - const SliceBudget& budget); - void gcSlice(JS::GCReason reason, const SliceBudget& budget); + const JS::SliceBudget& budget); + void gcSlice(JS::GCReason reason, const JS::SliceBudget& budget); void finishGC(JS::GCReason reason); void abortGC(); - void startDebugGC(JS::GCOptions options, const SliceBudget& budget); - void debugGCSlice(const SliceBudget& budget); + void startDebugGC(JS::GCOptions options, const JS::SliceBudget& budget); + void debugGCSlice(const JS::SliceBudget& budget); void runDebugGC(); void notifyRootsRemoved(); enum TraceOrMarkRuntime { TraceRuntime, MarkRuntime }; - void traceRuntime(JSTracer* trc, AutoTraceSession& session); + void traceRuntime(JSTracer* trc, AutoHeapSession& session); void traceRuntimeForMinorGC(JSTracer* trc, AutoGCSession& session); void purgeRuntimeForMinorGC(); @@ -370,6 +374,10 @@ class GCRuntime { return nursery_.refNoCheck().addressOfPosition(); } + void* addressOfNurseryAllocatedSites() { + return nursery_.refNoCheck().addressOfNurseryAllocatedSites(); + } + const void* addressOfLastBufferedWholeCell() { return storeBuffer_.refNoCheck().addressOfLastBufferedWholeCell(); } @@ -380,10 +388,19 @@ class GCRuntime { uint32_t* nextScheduled); void setZeal(uint8_t zeal, uint32_t frequency); void unsetZeal(uint8_t zeal); + // Note that currently, different modes cannot have different frequencies. + struct ZealSetting { + uint8_t mode; + uint32_t frequency; + }; + using ZealSettings = js::Vector; + bool parseZeal(const char* str, size_t len, ZealSettings* zeal, + bool* invalid); bool parseAndSetZeal(const char* str); void setNextScheduled(uint32_t count); void verifyPreBarriers(); void maybeVerifyPreBarriers(bool always); + void verifyPostBarriers(); bool selectForMarking(JSObject* object); void clearSelectedForMarking(); void setDeterministic(bool enable); @@ -409,7 +426,9 @@ class GCRuntime { bool isForegroundSweeping() const { return state() == State::Sweep; } bool isBackgroundSweeping() const { return sweepTask.wasStarted(); } bool isBackgroundMarking() const { return markTask.wasStarted(); } + bool isBackgroundDecommitting() const { return decommitTask.wasStarted(); } void waitBackgroundSweepEnd(); + void waitBackgroundDecommitEnd(); void waitBackgroundAllocEnd() { allocTask.cancelAndWait(); } void waitBackgroundFreeEnd(); void waitForBackgroundTasks(); @@ -432,10 +451,8 @@ class GCRuntime { void setAlwaysPreserveCode() { alwaysPreserveCode = true; } - bool isIncrementalGCAllowed() const { return incrementalAllowed; } - void disallowIncrementalGC() { incrementalAllowed = false; } - void setIncrementalGCEnabled(bool enabled); + void setNurseryEnabled(bool enabled); bool isIncrementalGCEnabled() const { return incrementalGCEnabled; } bool isPerZoneGCEnabled() const { return perZoneGCEnabled; } @@ -472,8 +489,8 @@ class GCRuntime { void removeFinalizeCallback(JSFinalizeCallback callback); void setHostCleanupFinalizationRegistryCallback( JSHostCleanupFinalizationRegistryCallback callback, void* data); - void callHostCleanupFinalizationRegistryCallback( - JSFunction* doCleanup, GlobalObject* incumbentGlobal); + void callHostCleanupFinalizationRegistryCallback(JSFunction* doCleanup, + JSObject* hostDefinedData); [[nodiscard]] bool addWeakPointerZonesCallback( JSWeakPointerZonesCallback callback, void* data); void removeWeakPointerZonesCallback(JSWeakPointerZonesCallback callback); @@ -545,9 +562,6 @@ class GCRuntime { double computeHeapGrowthFactor(size_t lastBytes); size_t computeTriggerBytes(double growthFactor, size_t lastBytes); - inline void updateOnFreeArenaAlloc(const TenuredChunkInfo& info); - void updateOnArenaFree() { ++numArenasFreeCommitted; } - ChunkPool& fullChunks(const AutoLockGC& lock) { return fullChunks_.ref(); } ChunkPool& availableChunks(const AutoLockGC& lock) { return availableChunks_.ref(); @@ -564,20 +578,31 @@ class GCRuntime { } using NonEmptyChunksIter = ChainedIterator; NonEmptyChunksIter allNonEmptyChunks(const AutoLockGC& lock) { + clearCurrentChunk(lock); return NonEmptyChunksIter(availableChunks(lock), fullChunks(lock)); } uint32_t minEmptyChunkCount(const AutoLockGC& lock) const { return minEmptyChunkCount_; } - uint32_t maxEmptyChunkCount(const AutoLockGC& lock) const { - return maxEmptyChunkCount_; - } + void setCurrentChunk(ArenaChunk* chunk, const AutoLockGC& lock); + void clearCurrentChunk(const AutoLockGC& lock); #ifdef DEBUG + bool isCurrentChunk(ArenaChunk* chunk) const { + return chunk == currentChunk_; + } void verifyAllChunks(); #endif - TenuredChunk* getOrAllocChunk(AutoLockGCBgAlloc& lock); - void recycleChunk(TenuredChunk* chunk, const AutoLockGC& lock); + // Get a free chunk or allocate one if needed. The chunk is left in the empty + // chunks pool. + ArenaChunk* getOrAllocChunk(StallAndRetry stallAndRetry, + AutoLockGCBgAlloc& lock); + + // Get or allocate a free chunk, removing it from the empty chunks pool. + ArenaChunk* takeOrAllocChunk(StallAndRetry stallAndRetry, + AutoLockGCBgAlloc& lock); + + void recycleChunk(ArenaChunk* chunk, const AutoLockGC& lock); #ifdef JS_GC_ZEAL void startVerifyPreBarriers(); @@ -585,6 +610,8 @@ class GCRuntime { void finishVerifier(); bool isVerifyPreBarriersEnabled() const { return verifyPreData.refNoCheck(); } bool shouldYieldForZeal(ZealMode mode); + void verifyPostBarriers(AutoHeapSession& session); + void checkHeapBeforeMinorGC(AutoHeapSession& session); #else bool isVerifyPreBarriersEnabled() const { return false; } #endif @@ -597,6 +624,8 @@ class GCRuntime { // the given kind. (TraceKind::Null means to ignore the kind.) bool isPointerWithinTenuredCell( void* ptr, JS::TraceKind traceKind = JS::TraceKind::Null); + // Crawl the heap to check whether an arbitary pointer is within a buffer. + bool isPointerWithinBufferAlloc(void* ptr); #ifdef DEBUG bool hasZone(Zone* target); @@ -605,10 +634,15 @@ class GCRuntime { // Queue memory memory to be freed on a background thread if possible. void queueUnusedLifoBlocksForFree(LifoAlloc* lifo); void queueAllLifoBlocksForFreeAfterMinorGC(LifoAlloc* lifo); - void queueBuffersForFreeAfterMinorGC(Nursery::BufferSet& buffers); + void queueBuffersForFreeAfterMinorGC( + Nursery::BufferSet& buffers, Nursery::StringBufferVector& stringBuffers); // Public here for ReleaseArenaLists and FinalizeTypedArenas. void releaseArena(Arena* arena, const AutoLockGC& lock); + void releaseArenas(Arena* arena, const AutoLockGC& lock); + void releaseArenaList(ArenaList& arenaList, const AutoLockGC& lock); + + Arena* releaseSomeEmptyArenas(Zone* zone, Arena* emptyArenas); // Allocator internals. static void* refillFreeListInGC(Zone* zone, AllocKind thingKind); @@ -632,6 +666,7 @@ class GCRuntime { void joinTask(GCParallelTask& task, AutoLockHelperThreadState& lock); void updateHelperThreadCount(); size_t parallelWorkerCount() const; + void maybeRequestGCAfterBackgroundTask(const AutoLockHelperThreadState& lock); // GC parallel task dispatch infrastructure. size_t getMaxParallelThreads() const; @@ -656,8 +691,8 @@ class GCRuntime { void updateAllocationRates(); // Allocator internals - static void* refillFreeList(JSContext* cx, AllocKind thingKind); - void attemptLastDitchGC(JSContext* cx); + static void* refillFreeList(JS::Zone* zone, AllocKind thingKind); + void attemptLastDitchGC(); // Test mark queue. #ifdef DEBUG @@ -666,15 +701,24 @@ class GCRuntime { [[nodiscard]] bool appendTestMarkQueue(const JS::Value& value); void clearTestMarkQueue(); size_t testMarkQueuePos() const; + size_t testMarkQueueRemaining() const; #endif private: - enum IncrementalResult { ResetIncremental = 0, Ok }; + enum class IncrementalResult { Reset = 0, Abort, Ok }; + bool hasBuffersForBackgroundFree() const { + return !lifoBlocksToFree.ref().isEmpty() || + !buffersToFreeAfterMinorGC.ref().empty() || + !stringBuffersToReleaseAfterMinorGC.ref().empty(); + } + + // Returns false on failure without raising an exception. [[nodiscard]] bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock); void resetParameter(JSGCParamKey key, AutoLockGC& lock); uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock); + // Returns false on failure without raising an exception. bool setThreadParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock); void resetThreadParameter(JSGCParamKey key, AutoLockGC& lock); void updateThreadDataStructures(AutoLockGC& lock); @@ -685,15 +729,14 @@ class GCRuntime { const HeapThreshold& heapThreshold); void updateSchedulingStateOnGCStart(); - void updateSchedulingStateAfterCollection(mozilla::TimeStamp currentTime); + void updateSchedulingStateOnGCEnd(mozilla::TimeStamp currentTime); void updateAllGCStartThresholds(); // For ArenaLists::allocateFromArena() friend class ArenaLists; - TenuredChunk* pickChunk(AutoLockGCBgAlloc& lock); - Arena* allocateArena(TenuredChunk* chunk, Zone* zone, AllocKind kind, - ShouldCheckThresholds checkThresholds, - const AutoLockGC& lock); + ArenaChunk* pickChunk(StallAndRetry stallAndRetry, AutoLockGCBgAlloc& lock); + Arena* allocateArena(ArenaChunk* chunk, Zone* zone, AllocKind kind, + ShouldCheckThresholds checkThresholds); /* * Return the list of chunks that can be released outside the GC lock. @@ -703,22 +746,25 @@ class GCRuntime { bool tooManyEmptyChunks(const AutoLockGC& lock); ChunkPool expireEmptyChunkPool(const AutoLockGC& lock); void freeEmptyChunks(const AutoLockGC& lock); - void prepareToFreeChunk(TenuredChunkInfo& info); + void prepareToFreeChunk(ArenaChunkInfo& info); void setMinEmptyChunkCount(uint32_t value, const AutoLockGC& lock); - void setMaxEmptyChunkCount(uint32_t value, const AutoLockGC& lock); friend class BackgroundAllocTask; bool wantBackgroundAllocation(const AutoLockGC& lock) const; void startBackgroundAllocTaskIfIdle(); void requestMajorGC(JS::GCReason reason); - SliceBudget defaultBudget(JS::GCReason reason, int64_t millis); - bool maybeIncreaseSliceBudget(SliceBudget& budget); - bool maybeIncreaseSliceBudgetForLongCollections(SliceBudget& budget); - bool maybeIncreaseSliceBudgetForUrgentCollections(SliceBudget& budget); + JS::SliceBudget defaultBudget(JS::GCReason reason, int64_t millis); + bool maybeIncreaseSliceBudget(JS::SliceBudget& budget, + mozilla::TimeStamp sliceStartTime, + mozilla::TimeStamp gcStartTime); + bool maybeIncreaseSliceBudgetForLongCollections( + JS::SliceBudget& budget, mozilla::TimeStamp sliceStartTime, + mozilla::TimeStamp gcStartTime); + bool maybeIncreaseSliceBudgetForUrgentCollections(JS::SliceBudget& budget); IncrementalResult budgetIncrementalGC(bool nonincrementalByAPI, JS::GCReason reason, - SliceBudget& budget); + JS::SliceBudget& budget); void checkZoneIsScheduled(Zone* zone, JS::GCReason reason, const char* trigger); IncrementalResult resetIncrementalGC(GCAbortReason reason); @@ -735,7 +781,7 @@ class GCRuntime { void setGCOptions(JS::GCOptions options); - void collect(bool nonincrementalByAPI, const SliceBudget& budget, + void collect(bool nonincrementalByAPI, const JS::SliceBudget& budget, JS::GCReason reason) JS_HAZ_GC_CALL; /* @@ -748,11 +794,11 @@ class GCRuntime { * * Ok otherwise. */ [[nodiscard]] IncrementalResult gcCycle(bool nonincrementalByAPI, - const SliceBudget& budgetArg, + const JS::SliceBudget& budgetArg, JS::GCReason reason); bool shouldRepeatForDeadZone(JS::GCReason reason); - void incrementalSlice(SliceBudget& budget, JS::GCReason reason, + void incrementalSlice(JS::SliceBudget& budget, JS::GCReason reason, bool budgetWasIncreased); bool mightSweepInThisSlice(bool nonIncremental); @@ -776,7 +822,7 @@ class GCRuntime { const mozilla::TimeStamp& currentTime, JS::GCReason reason, bool canAllocateMoreCode, bool isActiveCompartment); - void discardJITCodeForGC(); + void maybeDiscardJitCodeForGC(); void startBackgroundFreeAfterMinorGC(); void relazifyFunctionsForShrinkingGC(); void purgePropMapTablesForShrinkingGC(); @@ -787,7 +833,7 @@ class GCRuntime { void traceEmbeddingBlackRoots(JSTracer* trc); void traceEmbeddingGrayRoots(JSTracer* trc); IncrementalProgress traceEmbeddingGrayRoots(JSTracer* trc, - SliceBudget& budget); + JS::SliceBudget& budget); void checkNoRuntimeRoots(AutoGCSession& session); void maybeDoCycleCollection(); void findDeadCompartments(); @@ -798,7 +844,7 @@ class GCRuntime { AllowParallelMarking = true }; IncrementalProgress markUntilBudgetExhausted( - SliceBudget& sliceBudget, + JS::SliceBudget& sliceBudget, ParallelMarking allowParallelMarking = SingleThreadedMarking, ShouldReportMarkTime reportTime = ReportMarkTime); bool canMarkInParallel() const; @@ -827,10 +873,9 @@ class GCRuntime { void forEachDelayedMarkingArena(F&& f); template - IncrementalProgress markWeakReferences(SliceBudget& budget); - IncrementalProgress markWeakReferencesInCurrentGroup(SliceBudget& budget); - template - IncrementalProgress markGrayRoots(SliceBudget& budget, + IncrementalProgress markWeakReferences(JS::SliceBudget& budget); + IncrementalProgress markWeakReferencesInCurrentGroup(JS::SliceBudget& budget); + IncrementalProgress markGrayRoots(JS::SliceBudget& budget, gcstats::PhaseKind phase); void markBufferedGrayRoots(JS::Zone* zone); IncrementalProgress markAllWeakReferences(); @@ -851,22 +896,22 @@ class GCRuntime { void groupZonesForSweeping(JS::GCReason reason); [[nodiscard]] bool findSweepGroupEdges(); [[nodiscard]] bool addEdgesForMarkQueue(); - void getNextSweepGroup(); + void moveToNextSweepGroup(); void resetGrayList(Compartment* comp); IncrementalProgress beginMarkingSweepGroup(JS::GCContext* gcx, - SliceBudget& budget); + JS::SliceBudget& budget); IncrementalProgress markGrayRootsInCurrentGroup(JS::GCContext* gcx, - SliceBudget& budget); - IncrementalProgress markGray(JS::GCContext* gcx, SliceBudget& budget); + JS::SliceBudget& budget); + IncrementalProgress markGray(JS::GCContext* gcx, JS::SliceBudget& budget); IncrementalProgress endMarkingSweepGroup(JS::GCContext* gcx, - SliceBudget& budget); + JS::SliceBudget& budget); void markIncomingGrayCrossCompartmentPointers(); IncrementalProgress beginSweepingSweepGroup(JS::GCContext* gcx, - SliceBudget& budget); + JS::SliceBudget& budget); void initBackgroundSweep(Zone* zone, JS::GCContext* gcx, - const FinalizePhase& phase); + const AllocKinds& kinds); IncrementalProgress markDuringSweeping(JS::GCContext* gcx, - SliceBudget& budget); + JS::SliceBudget& budget); void updateAtomsBitmap(); void sweepCCWrappers(); void sweepRealmGlobals(); @@ -882,27 +927,28 @@ class GCRuntime { void traceWeakFinalizationObserverEdges(JSTracer* trc, Zone* zone); void sweepWeakRefs(); IncrementalProgress endSweepingSweepGroup(JS::GCContext* gcx, - SliceBudget& budget); - IncrementalProgress performSweepActions(SliceBudget& sliceBudget); + JS::SliceBudget& budget); + IncrementalProgress performSweepActions(JS::SliceBudget& sliceBudget); void startSweepingAtomsTable(); - IncrementalProgress sweepAtomsTable(JS::GCContext* gcx, SliceBudget& budget); - IncrementalProgress sweepWeakCaches(JS::GCContext* gcx, SliceBudget& budget); + IncrementalProgress sweepAtomsTable(JS::GCContext* gcx, + JS::SliceBudget& budget); + IncrementalProgress sweepWeakCaches(JS::GCContext* gcx, + JS::SliceBudget& budget); IncrementalProgress finalizeAllocKind(JS::GCContext* gcx, - SliceBudget& budget); - bool foregroundFinalize(JS::GCContext* gcx, Zone* zone, AllocKind thingKind, - js::SliceBudget& sliceBudget, - SortedArenaList& sweepList); - IncrementalProgress sweepPropMapTree(JS::GCContext* gcx, SliceBudget& budget); + JS::SliceBudget& budget); + IncrementalProgress sweepPropMapTree(JS::GCContext* gcx, + JS::SliceBudget& budget); void endSweepPhase(bool destroyingRuntime); void queueZonesAndStartBackgroundSweep(ZoneList&& zones); void sweepFromBackgroundThread(AutoLockHelperThreadState& lock); void startBackgroundFree(); void freeFromBackgroundThread(AutoLockHelperThreadState& lock); void sweepBackgroundThings(ZoneList& zones); - void backgroundFinalize(JS::GCContext* gcx, Zone* zone, AllocKind kind, - Arena** empty); void prepareForSweepSlice(JS::GCReason reason); void assertBackgroundSweepingFinished(); +#ifdef DEBUG + bool zoneInCurrentSweepGroup(Zone* zone) const; +#endif bool allCCVisibleZonesWereCollected(); void sweepZones(JS::GCContext* gcx, bool destroyingRuntime); @@ -916,14 +962,14 @@ class GCRuntime { bool shouldCompact(); void beginCompactPhase(); IncrementalProgress compactPhase(JS::GCReason reason, - SliceBudget& sliceBudget, + JS::SliceBudget& sliceBudget, AutoGCSession& session); void endCompactPhase(); void sweepZoneAfterCompacting(MovingTracer* trc, Zone* zone); bool canRelocateZone(Zone* zone) const; [[nodiscard]] bool relocateArenas(Zone* zone, JS::GCReason reason, Arena*& relocatedListOut, - SliceBudget& sliceBudget); + JS::SliceBudget& sliceBudget); void updateCellPointers(Zone* zone, AllocKinds kinds); void updateAllCellPointers(MovingTracer* trc, Zone* zone); void updateZonePointersToRelocatedCells(Zone* zone); @@ -943,21 +989,10 @@ class GCRuntime { void releaseHeldRelocatedArenasWithoutUnlocking(const AutoLockGC& lock); #endif - /* - * Whether to immediately trigger a slice after a background task - * finishes. This may not happen at a convenient time, so the consideration is - * whether the slice will run quickly or may take a long time. - */ - enum ShouldTriggerSliceWhenFinished : bool { - DontTriggerSliceWhenFinished = false, - TriggerSliceWhenFinished = true - }; + IncrementalProgress waitForBackgroundTask(GCParallelTask& task, + const JS::SliceBudget& budget, + bool shouldPauseMutator); - IncrementalProgress waitForBackgroundTask( - GCParallelTask& task, const SliceBudget& budget, bool shouldPauseMutator, - ShouldTriggerSliceWhenFinished triggerSlice); - - void maybeRequestGCAfterBackgroundTask(const AutoLockHelperThreadState& lock); void cancelRequestedGCAfterBackgroundTask(); void finishCollection(JS::GCReason reason); void maybeStopPretenuring(); @@ -1073,9 +1108,18 @@ class GCRuntime { // so as to reduce the cost of operations on the available lists. GCLockData fullChunks_; + // The chunk currently being allocated from. If non-null this is at the head + // of the available chunks list and has isCurrentChunk set to true. Can be + // accessed without taking the GC lock. + MainThreadData currentChunk_; + + // Bitmap for arenas in the current chunk that have been freed by background + // sweeping but not yet merged into the chunk's freeCommittedArenas. + GCLockData pendingFreeCommittedArenas; + friend class ArenaChunk; + /* * JSGC_MIN_EMPTY_CHUNK_COUNT - * JSGC_MAX_EMPTY_CHUNK_COUNT * * Controls the number of empty chunks reserved for future allocation. * @@ -1083,17 +1127,12 @@ class GCRuntime { * background decommit task. */ GCLockData minEmptyChunkCount_; - GCLockData maxEmptyChunkCount_; MainThreadData rootsHash; // An incrementing id used to assign unique ids to cells that require one. MainThreadData nextCellUniqueId_; - /* - * Number of the committed arenas in all GC chunks including empty chunks. - */ - mozilla::Atomic numArenasFreeCommitted; MainThreadData verifyPreData; MainThreadData lastGCStartTime_; @@ -1105,9 +1144,6 @@ class GCRuntime { mozilla::Atomic numActiveZoneIters; - /* During shutdown, the GC needs to clean up every possible object. */ - MainThreadData cleanUpEverything; - /* * The gray bits can become invalid if UnmarkGray overflows the stack. A * full GC will reset this bit, since it fills in all the gray bits. @@ -1184,10 +1220,6 @@ class GCRuntime { // thread. MainThreadData useBackgroundThreads; - // Whether we have already discarded JIT code for all collected zones in this - // slice. - MainThreadData haveDiscardedJITCodeThisSlice; - #ifdef DEBUG /* Shutdown has started. Further collections must be shutdown collections. */ MainThreadData hadShutdownGC; @@ -1212,6 +1244,11 @@ class GCRuntime { MainThreadData lifoBlocksToFreeAfterFullMinorGC; MainThreadData lifoBlocksToFreeAfterNextMinorGC; HelperThreadLockData buffersToFreeAfterMinorGC; + HelperThreadLockData + stringBuffersToReleaseAfterMinorGC; + + /* The number of the minor GC peformed at the start of major GC. */ + MainThreadData initialMinorGCNumber; /* Index of current sweep group (for stats). */ MainThreadData sweepGroupIndex; @@ -1293,19 +1330,21 @@ class GCRuntime { MainThreadData defaultTimeBudgetMS_; /* - * We disable incremental GC if we encounter a Class with a trace hook - * that does not implement write barriers. - */ - MainThreadData incrementalAllowed; - - /* - * Whether compacting GC can is enabled globally. + * Whether compacting GC is enabled globally. * * JSGC_COMPACTING_ENABLED * pref: javascript.options.mem.gc_compacting */ MainThreadData compactingEnabled; + /* + * Whether generational GC is enabled globally. + * + * JSGC_NURSERY_ENABLED + * pref: javascript.options.mem.gc_generational + */ + MainThreadData nurseryEnabled; + /* * Whether parallel marking is enabled globally. * @@ -1407,6 +1446,14 @@ class GCRuntime { /* Lock used to synchronise access to delayed marking state. */ Mutex delayedMarkingLock MOZ_UNANNOTATED; + /* + * Lock used by buffer allocators to synchronise data passed back to the main + * thread by background sweeping. + */ + Mutex bufferAllocatorLock MOZ_UNANNOTATED; + friend class BufferAllocator; + friend class AutoLock; + friend class BackgroundSweepTask; friend class BackgroundFreeTask; diff --git a/src/third_party/mozjs/extract/js/src/gc/GenerateStatsPhases.py b/src/third_party/mozjs/extract/js/src/gc/GenerateStatsPhases.py index ee62a3b533a..69a5b773200 100644 --- a/src/third_party/mozjs/extract/js/src/gc/GenerateStatsPhases.py +++ b/src/third_party/mozjs/extract/js/src/gc/GenerateStatsPhases.py @@ -178,7 +178,7 @@ PhaseKindGraphRoots = [ "Sweep Compartments", 20, [ - addPhaseKind("SWEEP_DISCARD_CODE", "Sweep Discard Code", 21), + addPhaseKind("SWEEP_JIT_SCRIPTS", "Sweep JitScripts", 21), addPhaseKind("SWEEP_INNER_VIEWS", "Sweep Inner Views", 22), addPhaseKind( "SWEEP_CC_WRAPPER", "Sweep Cross Compartment Wrappers", 23 @@ -201,8 +201,6 @@ PhaseKindGraphRoots = [ getPhaseKind("JOIN_PARALLEL_TASKS"), ], ), - addPhaseKind("FINALIZE_OBJECT", "Finalize Objects", 33), - addPhaseKind("FINALIZE_NON_OBJECT", "Finalize Non-objects", 34), addPhaseKind("SWEEP_PROP_MAP", "Sweep PropMap Tree", 77), addPhaseKind("FINALIZE_END", "Finalize End Callback", 38), addPhaseKind("DESTROY", "Deallocate", 39), diff --git a/src/third_party/mozjs/extract/js/src/gc/Heap-inl.h b/src/third_party/mozjs/extract/js/src/gc/Heap-inl.h index 30937a72365..d62ac4ef3ad 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Heap-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/Heap-inl.h @@ -14,57 +14,256 @@ #include "util/Poison.h" #include "vm/Runtime.h" -inline void js::gc::Arena::init(JS::Zone* zoneArg, AllocKind kind, - const AutoLockGC& lock) { -#ifdef DEBUG - MOZ_MAKE_MEM_DEFINED(&zone, sizeof(zone)); - MOZ_ASSERT((uintptr_t(zone) & 0xff) == JS_FREED_ARENA_PATTERN); -#endif - - MOZ_ASSERT(firstFreeSpan.isEmpty()); - MOZ_ASSERT(!allocated()); - MOZ_ASSERT(!onDelayedMarkingList_); - MOZ_ASSERT(!hasDelayedBlackMarking_); - MOZ_ASSERT(!hasDelayedGrayMarking_); - MOZ_ASSERT(!nextDelayedMarkingArena_); +inline void js::gc::Arena::init(GCRuntime* gc, JS::Zone* zone, AllocKind kind) { + MOZ_ASSERT(zone); + MOZ_ASSERT(IsValidAllocKind(kind)); MOZ_MAKE_MEM_UNDEFINED(this, ArenaSize); - zone = zoneArg; allocKind = kind; + zone_ = zone; + next = nullptr; isNewlyCreated_ = 1; onDelayedMarkingList_ = 0; hasDelayedBlackMarking_ = 0; hasDelayedGrayMarking_ = 0; nextDelayedMarkingArena_ = 0; - if (zone->isAtomsZone()) { - zone->runtimeFromAnyThread()->gc.atomMarking.registerArena(this, lock); + if (zone_->isAtomsZone()) { + atomBitmapStart() = gc->atomMarking.allocateIndex(gc); } else { bufferedCells() = &ArenaCellSet::Empty; } - setAsFullyUnused(); + setAsFullyUnused(); // Initializes firstFreeSpan. #ifdef DEBUG checkNoMarkedCells(); #endif } -inline void js::gc::Arena::release(const AutoLockGC& lock) { - if (zone->isAtomsZone()) { - zone->runtimeFromAnyThread()->gc.atomMarking.unregisterArena(this, lock); - } - setAsNotAllocated(); +inline void js::gc::Arena::freeAtomMarkingBitmapIndex(GCRuntime* gc, + const AutoLockGC& lock) { + MOZ_ASSERT(zone_->isAtomsZone()); + gc->atomMarking.freeIndex(atomBitmapStart(), lock); +#ifdef DEBUG + atomBitmapStart() = 0; // Also zeroed by write to bufferedCells_ in release. +#endif +} + +inline void js::gc::Arena::release() { + MOZ_ASSERT(allocated()); + + // Clients should call freeAtomMarkingBitmapIndex() if necessary. + MOZ_ASSERT_IF(zone_->isAtomsZone(), atomBitmapStart_ == 0); + + // Poison zone pointer to highlight UAF on released arenas in crash data. + AlwaysPoison(&zone_, JS_FREED_ARENA_PATTERN, sizeof(zone_), + MemCheckKind::MakeNoAccess); + + firstFreeSpan.initAsEmpty(); + allocKind = AllocKind::LIMIT; + onDelayedMarkingList_ = 0; + hasDelayedBlackMarking_ = 0; + hasDelayedGrayMarking_ = 0; + nextDelayedMarkingArena_ = 0; + bufferedCells_ = nullptr; + + MOZ_ASSERT(!allocated()); } inline js::gc::ArenaCellSet*& js::gc::Arena::bufferedCells() { - MOZ_ASSERT(zone && !zone->isAtomsZone()); + MOZ_ASSERT(zone_ && !zone_->isAtomsZone()); return bufferedCells_; } inline size_t& js::gc::Arena::atomBitmapStart() { - MOZ_ASSERT(zone && zone->isAtomsZone()); + MOZ_ASSERT(zone_ && zone_->isAtomsZone()); return atomBitmapStart_; } +// Mark bitmap API: + +// Unless noted otherwise, the following methods that update the mark bits are +// not thread safe and must not be called in parallel with each other. +// +// They use separate read and write operations to avoid an unnecessarily strict +// atomic update on the marking bitmap. +// +// They may be called in parallel with read operations on the mark bitmap where +// there is no required ordering between the operations. This happens when gray +// unmarking occurs in parallel with background sweeping. + +// The return value indicates if the cell went from unmarked to marked. +template +MOZ_ALWAYS_INLINE bool +js::gc::MarkBitmap::markIfUnmarked( + const void* cell, MarkColor color) { + MarkBitmapWord* word; + uintptr_t mask; + getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); + if (*word & mask) { + return false; + } + if (color == MarkColor::Black) { + uintptr_t bits = *word; + *word = bits | mask; + } else { + // We use getMarkWordAndMask to recalculate both mask and word as doing just + // mask << color may overflow the mask. + getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask); + if (*word & mask) { + return false; + } + uintptr_t bits = *word; + *word = bits | mask; + } + return true; +} + +// This version of the method is safe in the face of concurrent writes to the +// mark bitmap but if two threads attempt to mark the same cell at the same time +// then both calls can succeed and return true. +// +// This method is used for parallel marking where the extra synchronization +// required to avoid this results in worse performance overall. +template +MOZ_ALWAYS_INLINE bool +js::gc::MarkBitmap::markIfUnmarkedThreadSafe( + const void* cell, MarkColor color) { + MarkBitmapWord* word; + uintptr_t mask; + getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); + if (*word & mask) { + return false; + } + if (color == MarkColor::Black) { + *word |= mask; + } else { + // We use getMarkWordAndMask to recalculate both mask and word as doing just + // mask << color may overflow the mask. + getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask); + if (*word & mask) { + return false; + } + *word |= mask; + } + return true; +} + +template +MOZ_ALWAYS_INLINE void +js::gc::MarkBitmap::markBlack( + const void* cell) { + MarkBitmapWord* word; + uintptr_t mask; + getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); + uintptr_t bits = *word; + *word = bits | mask; +} + +template +MOZ_ALWAYS_INLINE void +js::gc::MarkBitmap::markBlackAtomic( + const void* cell) { + MarkBitmapWord* word; + uintptr_t mask; + getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); + *word |= mask; +} + +template +MOZ_ALWAYS_INLINE void +js::gc::MarkBitmap::copyMarkBit( + TenuredCell* dst, const TenuredCell* src, ColorBit colorBit) { + ArenaChunkBase* srcChunk = detail::GetCellChunkBase(src); + MarkBitmapWord* srcWord; + uintptr_t srcMask; + srcChunk->markBits.getMarkWordAndMask(src, colorBit, &srcWord, &srcMask); + + MarkBitmapWord* dstWord; + uintptr_t dstMask; + getMarkWordAndMask(dst, colorBit, &dstWord, &dstMask); + + uintptr_t bits = *dstWord; + bits &= ~dstMask; + if (*srcWord & srcMask) { + bits |= dstMask; + } + *dstWord = bits; +} + +template +MOZ_ALWAYS_INLINE void +js::gc::MarkBitmap::unmark( + const void* cell) { + unmarkOneBit(cell, ColorBit::BlackBit); + unmarkOneBit(cell, ColorBit::GrayOrBlackBit); +} + +template +MOZ_ALWAYS_INLINE void +js::gc::MarkBitmap::unmarkOneBit( + const void* cell, ColorBit colorBit) { + MarkBitmapWord* word; + uintptr_t mask; + uintptr_t bits; + getMarkWordAndMask(cell, colorBit, &word, &mask); + bits = *word; + *word = bits & ~mask; +} + +template +inline js::gc::MarkBitmapWord* +js::gc::MarkBitmap::arenaBits(Arena* arena) { + static_assert( + ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD, + "We assume that the part of the bitmap corresponding to the arena " + "has the exact number of words so we do not need to deal with a word " + "that covers bits from two arenas."); + + MarkBitmapWord* word; + uintptr_t unused; + getMarkWordAndMask(arena, ColorBit::BlackBit, &word, &unused); + return word; +} + +template +void js::gc::MarkBitmap::copyFrom( + const MarkBitmap& other) { + for (size_t i = 0; i < WordCount; i++) { + bitmap[i] = uintptr_t(other.bitmap[i]); + } +} + +template +void js::gc::MarkBitmap::clear() { + for (size_t i = 0; i < WordCount; i++) { + bitmap[i] = 0; + } +} + +bool js::gc::TenuredCell::markIfUnmarked(MarkColor color /* = Black */) const { + return chunk()->markBits.markIfUnmarked(this, color); +} + +bool js::gc::TenuredCell::markIfUnmarkedThreadSafe(MarkColor color) const { + return chunk()->markBits.markIfUnmarkedThreadSafe(this, color); +} + +void js::gc::TenuredCell::markBlack() const { + chunk()->markBits.markBlack(this); +} + +void js::gc::TenuredCell::markBlackAtomic() const { + chunk()->markBits.markBlackAtomic(this); +} + +void js::gc::TenuredCell::copyMarkBitsFrom(const TenuredCell* src) { + ChunkMarkBitmap& markBits = chunk()->markBits; + markBits.copyMarkBit(this, src, ColorBit::BlackBit); + markBits.copyMarkBit(this, src, ColorBit::GrayOrBlackBit); +} + +void js::gc::TenuredCell::unmark() { chunk()->markBits.unmark(this); } + #endif diff --git a/src/third_party/mozjs/extract/js/src/gc/Heap.cpp b/src/third_party/mozjs/extract/js/src/gc/Heap.cpp index 2e7ecfe1d7b..9e17c063362 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Heap.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Heap.cpp @@ -14,7 +14,7 @@ * - ArenaList * - FreeLists * - ArenaLists - * - TenuredChunk + * - ArenaChunk * - ChunkPool */ @@ -23,6 +23,7 @@ #include "gc/GCLock.h" #include "gc/Memory.h" #include "jit/Assembler.h" +#include "threading/Thread.h" #include "vm/BigIntType.h" #include "vm/RegExpShared.h" #include "vm/Scope.h" @@ -92,6 +93,31 @@ const uint8_t Arena::ThingsPerArena[] = { #undef EXPAND_THINGS_PER_ARENA }; +bool Arena::allocated() const { +#if defined(DEBUG) && defined(MOZ_VALGRIND) + // In debug builds, valgrind complains about the access to `allocKind` even + // though it is legitimate, so temporarily disable reporting of addressing + // errors in that range. Note this doesn't change the state of the address + // range, as tracked by valgrind, so subsequent checking against its state is + // unaffected. See bug 1932412. + VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(&allocKind, sizeof(void*)); +#endif + + size_t arenaIndex = ArenaChunk::arenaIndex(this); + size_t pageIndex = ArenaChunk::arenaToPageIndex(arenaIndex); + bool result = !chunk()->decommittedPages[pageIndex] && + !chunk()->freeCommittedArenas[arenaIndex] && + IsValidAllocKind(allocKind); + MOZ_ASSERT_IF(result, zone_); + MOZ_ASSERT_IF(result, (uintptr_t(zone_) & 7) == 0); + +#if defined(DEBUG) && defined(MOZ_VALGRIND) + // Reenable error reporting for the range we just said to ignore. + VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(&allocKind, sizeof(void*)); +#endif + return result; +} + void Arena::unmarkAll() { MarkBitmapWord* arenaBits = chunk()->markBits.arenaBits(this); for (size_t i = 0; i < ArenaBitmapWords; i++) { @@ -140,6 +166,13 @@ void Arena::staticAsserts() { "We haven't defined all offsets."); static_assert(std::size(ThingsPerArena) == AllocKindCount, "We haven't defined all counts."); + static_assert(ArenaZoneOffset == offsetof(Arena, zone_), + "The hardcoded API zone offset must match the actual offset."); + static_assert(sizeof(Arena) == ArenaSize, + "ArenaSize must match the actual size of the Arena structure."); + static_assert( + offsetof(Arena, data) == ArenaHeaderSize, + "ArenaHeaderSize must match the actual size of the header fields."); } /* static */ @@ -155,34 +188,20 @@ void Arena::checkLookupTables() { #ifdef DEBUG void js::gc::ArenaList::dump() { - fprintf(stderr, "ArenaList %p:", this); - if (cursorp_ == &head_) { - fprintf(stderr, " *"); - } - for (Arena* arena = head(); arena; arena = arena->next) { - fprintf(stderr, " %p", arena); - if (cursorp_ == &arena->next) { - fprintf(stderr, " *"); + fprintf(stderr, "ArenaList %p:\n", this); + for (auto arena = iter(); !arena.done(); arena.next()) { + fprintf(stderr, " %p %zu", arena.get(), arena->countFreeCells()); + if (arena->isEmpty()) { + fprintf(stderr, " (empty)"); } + if (arena->isFull()) { + fprintf(stderr, " (full)"); + } + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); } #endif -Arena* ArenaList::removeRemainingArenas(Arena** arenap) { - // This is only ever called to remove arenas that are after the cursor, so - // we don't need to update it. -#ifdef DEBUG - for (Arena* arena = *arenap; arena; arena = arena->next) { - MOZ_ASSERT(cursorp_ != &arena->next); - } -#endif - Arena* remainingArenas = *arenap; - *arenap = nullptr; - check(); - return remainingArenas; -} - AutoGatherSweptArenas::AutoGatherSweptArenas(JS::Zone* zone, AllocKind kind) { GCRuntime& gc = zone->runtimeFromMainThread()->gc; sortedList = gc.maybeGetForegroundFinalizedArenas(zone, kind); @@ -196,13 +215,13 @@ AutoGatherSweptArenas::AutoGatherSweptArenas(JS::Zone* zone, AllocKind kind) { } AutoGatherSweptArenas::~AutoGatherSweptArenas() { - if (sortedList) { - sortedList->restoreFromArenaList(linked, bucketLastPointers); + if (!sortedList) { + MOZ_ASSERT(linked.isEmpty()); + return; } - linked.clear(); -} -Arena* AutoGatherSweptArenas::sweptArenas() const { return linked.head(); } + sortedList->restoreFromArenaList(linked, bucketLastPointers); +} FreeLists::FreeLists() { for (auto i : AllAllocKinds()) { @@ -220,20 +239,6 @@ ArenaLists::ArenaLists(Zone* zone) } } -void ReleaseArenas(JSRuntime* rt, Arena* arena, const AutoLockGC& lock) { - Arena* next; - for (; arena; arena = next) { - next = arena->next; - rt->gc.releaseArena(arena, lock); - } -} - -void ReleaseArenaList(JSRuntime* rt, ArenaList& arenaList, - const AutoLockGC& lock) { - ReleaseArenas(rt, arenaList.head(), lock); - arenaList.clear(); -} - ArenaLists::~ArenaLists() { AutoLockGC lock(runtime()); @@ -243,10 +248,10 @@ ArenaLists::~ArenaLists() { * the background finalization is disabled. */ MOZ_ASSERT(concurrentUse(i) == ConcurrentUse::None); - ReleaseArenaList(runtime(), arenaList(i), lock); + runtime()->gc.releaseArenaList(arenaList(i), lock); } - ReleaseArenas(runtime(), savedEmptyArenas, lock); + runtime()->gc.releaseArenas(savedEmptyArenas, lock); } void ArenaLists::moveArenasToCollectingLists() { @@ -260,8 +265,7 @@ void ArenaLists::moveArenasToCollectingLists() { void ArenaLists::mergeArenasFromCollectingLists() { for (AllocKind kind : AllAllocKinds()) { - collectingArenaList(kind).insertListWithCursorAtEnd(arenaList(kind)); - arenaList(kind) = std::move(collectingArenaList(kind)); + arenaList(kind).prepend(std::move(collectingArenaList(kind))); MOZ_ASSERT(collectingArenaList(kind).isEmpty()); } } @@ -312,12 +316,12 @@ void ArenaLists::checkNoArenasToUpdateForKind(AllocKind kind) { #endif } -inline bool TenuredChunk::canDecommitPage(size_t pageIndex) const { +inline bool ArenaChunk::canDecommitPage(size_t pageIndex) const { if (decommittedPages[pageIndex]) { return false; } - size_t arenaIndex = pageIndex * ArenasPerPage; + size_t arenaIndex = pageToArenaIndex(pageIndex); for (size_t i = 0; i < ArenasPerPage; i++) { if (!freeCommittedArenas[arenaIndex + i]) { return false; @@ -327,89 +331,89 @@ inline bool TenuredChunk::canDecommitPage(size_t pageIndex) const { return true; } -void TenuredChunk::decommitFreeArenas(GCRuntime* gc, const bool& cancel, - AutoLockGC& lock) { +void ArenaChunk::decommitFreeArenas(GCRuntime* gc, const bool& cancel, + AutoLockGC& lock) { MOZ_ASSERT(DecommitEnabled()); + MOZ_ASSERT(!info.isCurrentChunk); for (size_t i = 0; i < PagesPerChunk; i++) { if (cancel) { break; } - if (canDecommitPage(i) && !decommitOneFreePage(gc, i, lock)) { + if (!canDecommitPage(i)) { + continue; + } + + if (!decommitOneFreePage(gc, i, lock)) { + break; + } + + { + // Give main thread a chance to take the lock. + AutoUnlockGC unlock(lock); + ThisThread::SleepMilliseconds(0); + } + + // Re-check whether the chunk is being used for allocation after releasing + // the lock. + if (info.isCurrentChunk) { break; } } } -void TenuredChunk::recycleArena(Arena* arena, SortedArenaList& dest, - size_t thingsPerArena) { - arena->setAsFullyUnused(); - dest.insertAt(arena, thingsPerArena); -} +void ArenaChunk::releaseArena(GCRuntime* gc, Arena* arena, + const AutoLockGC& lock) { + if (info.isCurrentChunk) { + // The main thread is allocating out of this chunk without holding the + // lock. Don't touch any data structures it is using but add the arena to a + // pending set. This will be merged back by mergePendingFreeArenas. + auto& bitmap = gc->pendingFreeCommittedArenas.ref(); + MOZ_ASSERT(!bitmap[arenaIndex(arena)]); + bitmap[arenaIndex(arena)] = true; + return; + } -void TenuredChunk::releaseArena(GCRuntime* gc, Arena* arena, - const AutoLockGC& lock) { MOZ_ASSERT(!arena->allocated()); MOZ_ASSERT(!freeCommittedArenas[arenaIndex(arena)]); freeCommittedArenas[arenaIndex(arena)] = true; - ++info.numArenasFreeCommitted; - ++info.numArenasFree; - gc->updateOnArenaFree(); + updateFreeCountsAfterFree(gc, 1, true, lock); verify(); - - updateChunkListAfterFree(gc, 1, lock); } -bool TenuredChunk::decommitOneFreePage(GCRuntime* gc, size_t pageIndex, - AutoLockGC& lock) { +bool ArenaChunk::decommitOneFreePage(GCRuntime* gc, size_t pageIndex, + const AutoLockGC& lock) { MOZ_ASSERT(DecommitEnabled()); MOZ_ASSERT(canDecommitPage(pageIndex)); + MOZ_ASSERT(info.numArenasFree >= info.numArenasFreeCommitted); MOZ_ASSERT(info.numArenasFreeCommitted >= ArenasPerPage); - // Temporarily mark the page as allocated while we decommit. + if (oom::ShouldFailWithOOM()) { + return false; + } + + if (!MarkPagesUnusedSoft(pageAddress(pageIndex), PageSize)) { + return false; + } + + // Mark the page as decommited. + decommittedPages[pageIndex] = true; for (size_t i = 0; i < ArenasPerPage; i++) { - size_t arenaIndex = pageIndex * ArenasPerPage + i; + size_t arenaIndex = pageToArenaIndex(pageIndex) + i; MOZ_ASSERT(freeCommittedArenas[arenaIndex]); freeCommittedArenas[arenaIndex] = false; } info.numArenasFreeCommitted -= ArenasPerPage; - info.numArenasFree -= ArenasPerPage; - updateChunkListAfterAlloc(gc, lock); verify(); - bool ok; - { - AutoUnlockGC unlock(lock); - ok = !oom::ShouldFailWithOOM() && - MarkPagesUnusedSoft(pageAddress(pageIndex), PageSize); - } - - // Mark the page as decommited if successful or restore the original free - // state. - if (ok) { - decommittedPages[pageIndex] = true; - } else { - for (size_t i = 0; i < ArenasPerPage; i++) { - size_t arenaIndex = pageIndex * ArenasPerPage + i; - MOZ_ASSERT(!freeCommittedArenas[arenaIndex]); - freeCommittedArenas[arenaIndex] = true; - } - info.numArenasFreeCommitted += ArenasPerPage; - } - - info.numArenasFree += ArenasPerPage; - updateChunkListAfterFree(gc, ArenasPerPage, lock); - - verify(); - - return ok; + return true; } -void TenuredChunk::decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock) { +void ArenaChunk::decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock) { MOZ_ASSERT(DecommitEnabled()); for (size_t i = 0; i < PagesPerChunk; i++) { @@ -427,7 +431,7 @@ void TenuredChunk::decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock) { decommittedPages[i] = true; for (size_t j = 0; j < ArenasPerPage; ++j) { - size_t arenaIndex = i * ArenasPerPage + j; + size_t arenaIndex = pageToArenaIndex(i) + j; MOZ_ASSERT(freeCommittedArenas[arenaIndex]); freeCommittedArenas[arenaIndex] = false; } @@ -437,29 +441,138 @@ void TenuredChunk::decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock) { verify(); } -void TenuredChunk::updateChunkListAfterAlloc(GCRuntime* gc, - const AutoLockGC& lock) { - if (MOZ_UNLIKELY(!hasAvailableArenas())) { +void ArenaChunk::updateFreeCountsAfterAlloc(GCRuntime* gc, + size_t numArenasAlloced, + const AutoLockGC& lock) { + MOZ_ASSERT(!info.isCurrentChunk); + MOZ_ASSERT(numArenasAlloced > 0); + + bool wasEmpty = isEmpty(); + + MOZ_ASSERT(info.numArenasFree >= numArenasAlloced); + MOZ_ASSERT(info.numArenasFreeCommitted >= numArenasAlloced); + info.numArenasFreeCommitted -= numArenasAlloced; + info.numArenasFree -= numArenasAlloced; + + if (MOZ_UNLIKELY(wasEmpty)) { + gc->emptyChunks(lock).remove(this); + gc->availableChunks(lock).push(this); + return; + } + + if (MOZ_UNLIKELY(isFull())) { gc->availableChunks(lock).remove(this); gc->fullChunks(lock).push(this); + return; + } + + MOZ_ASSERT(gc->availableChunks(lock).contains(this)); +} + +void ArenaChunk::updateCurrentChunkAfterAlloc(GCRuntime* gc) { + MOZ_ASSERT(info.isCurrentChunk); // Can access without holding lock. + MOZ_ASSERT(gc->isCurrentChunk(this)); + + MOZ_ASSERT(info.numArenasFree >= 1); + MOZ_ASSERT(info.numArenasFreeCommitted >= 1); + info.numArenasFreeCommitted--; + info.numArenasFree--; + + if (MOZ_UNLIKELY(isFull())) { + AutoLockGC lock(gc); + mergePendingFreeArenas(gc, lock); + if (isFull()) { + gc->clearCurrentChunk(lock); + } } } -void TenuredChunk::updateChunkListAfterFree(GCRuntime* gc, size_t numArenasFree, - const AutoLockGC& lock) { - if (info.numArenasFree == numArenasFree) { +void ArenaChunk::updateFreeCountsAfterFree(GCRuntime* gc, size_t numArenasFreed, + bool wasCommitted, + const AutoLockGC& lock) { + MOZ_ASSERT(!info.isCurrentChunk); + MOZ_ASSERT(numArenasFreed > 0); + MOZ_ASSERT(info.numArenasFree + numArenasFreed <= ArenasPerChunk); + MOZ_ASSERT(info.numArenasFreeCommitted + numArenasFreed <= ArenasPerChunk); + + bool wasFull = isFull(); + + info.numArenasFree += numArenasFreed; + if (wasCommitted) { + info.numArenasFreeCommitted += numArenasFreed; + } + + if (MOZ_UNLIKELY(wasFull)) { gc->fullChunks(lock).remove(this); gc->availableChunks(lock).push(this); - } else if (!unused()) { - MOZ_ASSERT(gc->availableChunks(lock).contains(this)); - } else { - MOZ_ASSERT(unused()); + return; + } + + if (MOZ_UNLIKELY(isEmpty())) { gc->availableChunks(lock).remove(this); gc->recycleChunk(this, lock); + return; } + + MOZ_ASSERT(gc->availableChunks(lock).contains(this)); } -TenuredChunk* ChunkPool::pop() { +void GCRuntime::setCurrentChunk(ArenaChunk* chunk, const AutoLockGC& lock) { + MOZ_ASSERT(!currentChunk_); + MOZ_ASSERT(pendingFreeCommittedArenas.ref().IsEmpty()); + MOZ_ASSERT(chunk); + MOZ_ASSERT(!chunk->info.isCurrentChunk); + + currentChunk_ = chunk; + chunk->info.isCurrentChunk = true; // Lock needed here. +} + +void GCRuntime::clearCurrentChunk(const AutoLockGC& lock) { + MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt)); + + ArenaChunk* chunk = currentChunk_; + if (!chunk) { + return; + } + + chunk->mergePendingFreeArenas(this, lock); + + MOZ_ASSERT(chunk->info.isCurrentChunk); + chunk->info.isCurrentChunk = false; // Lock needed here. + currentChunk_ = nullptr; + + if (chunk->isFull()) { + fullChunks(lock).push(chunk); + return; + } + + if (chunk->isEmpty()) { + emptyChunks(lock).push(chunk); + return; + } + + MOZ_ASSERT(chunk->hasAvailableArenas()); + availableChunks(lock).push(chunk); +} + +void ArenaChunk::mergePendingFreeArenas(GCRuntime* gc, const AutoLockGC& lock) { + MOZ_ASSERT(info.isCurrentChunk); + + auto& bitmap = gc->pendingFreeCommittedArenas.ref(); + if (bitmap.IsEmpty()) { + return; + } + + MOZ_ASSERT((freeCommittedArenas & bitmap).IsEmpty()); + size_t count = bitmap.Count(); + freeCommittedArenas |= bitmap; + bitmap.ResetAll(); + + info.numArenasFree += count; + info.numArenasFreeCommitted += count; +} + +ArenaChunk* ChunkPool::pop() { MOZ_ASSERT(bool(head_) == bool(count_)); if (!count_) { return nullptr; @@ -467,7 +580,7 @@ TenuredChunk* ChunkPool::pop() { return remove(head_); } -void ChunkPool::push(TenuredChunk* chunk) { +void ChunkPool::push(ArenaChunk* chunk) { MOZ_ASSERT(!chunk->info.next); MOZ_ASSERT(!chunk->info.prev); @@ -479,7 +592,7 @@ void ChunkPool::push(TenuredChunk* chunk) { ++count_; } -TenuredChunk* ChunkPool::remove(TenuredChunk* chunk) { +ArenaChunk* ChunkPool::remove(ArenaChunk* chunk) { MOZ_ASSERT(count_ > 0); MOZ_ASSERT(contains(chunk)); @@ -507,8 +620,8 @@ void ChunkPool::sort() { head_ = mergeSort(head(), count()); // Fixup prev pointers. - TenuredChunk* prev = nullptr; - for (TenuredChunk* cur = head_; cur; cur = cur->info.next) { + ArenaChunk* prev = nullptr; + for (ArenaChunk* cur = head_; cur; cur = cur->info.next) { cur->info.prev = prev; prev = cur; } @@ -518,7 +631,7 @@ void ChunkPool::sort() { MOZ_ASSERT(isSorted()); } -TenuredChunk* ChunkPool::mergeSort(TenuredChunk* list, size_t count) { +ArenaChunk* ChunkPool::mergeSort(ArenaChunk* list, size_t count) { MOZ_ASSERT(bool(list) == bool(count)); if (count < 2) { @@ -528,10 +641,10 @@ TenuredChunk* ChunkPool::mergeSort(TenuredChunk* list, size_t count) { size_t half = count / 2; // Split; - TenuredChunk* front = list; - TenuredChunk* back; + ArenaChunk* front = list; + ArenaChunk* back; { - TenuredChunk* cur = list; + ArenaChunk* cur = list; for (size_t i = 0; i < half - 1; i++) { MOZ_ASSERT(cur); cur = cur->info.next; @@ -545,7 +658,7 @@ TenuredChunk* ChunkPool::mergeSort(TenuredChunk* list, size_t count) { // Merge list = nullptr; - TenuredChunk** cur = &list; + ArenaChunk** cur = &list; while (front || back) { if (!front) { *cur = back; @@ -574,7 +687,7 @@ TenuredChunk* ChunkPool::mergeSort(TenuredChunk* list, size_t count) { bool ChunkPool::isSorted() const { uint32_t last = 1; - for (TenuredChunk* cursor = head_; cursor; cursor = cursor->info.next) { + for (ArenaChunk* cursor = head_; cursor; cursor = cursor->info.next) { if (cursor->info.numArenasFree < last) { return false; } @@ -585,9 +698,9 @@ bool ChunkPool::isSorted() const { #ifdef DEBUG -bool ChunkPool::contains(TenuredChunk* chunk) const { +bool ChunkPool::contains(ArenaChunk* chunk) const { verify(); - for (TenuredChunk* cursor = head_; cursor; cursor = cursor->info.next) { + for (ArenaChunk* cursor = head_; cursor; cursor = cursor->info.next) { if (cursor == chunk) { return true; } @@ -598,7 +711,7 @@ bool ChunkPool::contains(TenuredChunk* chunk) const { bool ChunkPool::verify() const { MOZ_ASSERT(bool(head_) == bool(count_)); uint32_t count = 0; - for (TenuredChunk* cursor = head_; cursor; + for (ArenaChunk* cursor = head_; cursor; cursor = cursor->info.next, ++count) { MOZ_ASSERT_IF(cursor->info.prev, cursor->info.prev->info.next == cursor); MOZ_ASSERT_IF(cursor->info.next, cursor->info.next->info.prev == cursor); @@ -608,19 +721,20 @@ bool ChunkPool::verify() const { } void ChunkPool::verifyChunks() const { - for (TenuredChunk* chunk = head_; chunk; chunk = chunk->info.next) { + for (ArenaChunk* chunk = head_; chunk; chunk = chunk->info.next) { chunk->verify(); + MOZ_ASSERT(!chunk->info.isCurrentChunk); } } -void TenuredChunk::verify() const { +void ArenaChunk::verify() const { // Check the mark bits for each arena are aligned to the cache line size. - static_assert((offsetof(TenuredChunk, arenas) % ArenaSize) == 0); + static_assert((offsetof(ArenaChunk, arenas) % ArenaSize) == 0); constexpr size_t CellBytesPerMarkByte = CellBytesPerMarkBit * 8; static_assert((ArenaSize % CellBytesPerMarkByte) == 0); constexpr size_t MarkBytesPerArena = ArenaSize / CellBytesPerMarkByte; static_assert((MarkBytesPerArena % TypicalCacheLineSize) == 0); - static_assert((offsetof(TenuredChunk, markBits) % TypicalCacheLineSize) == 0); + static_assert((offsetof(ArenaChunk, markBits) % TypicalCacheLineSize) == 0); MOZ_ASSERT(info.numArenasFree <= ArenasPerChunk); MOZ_ASSERT(info.numArenasFreeCommitted <= info.numArenasFree); @@ -633,8 +747,8 @@ void TenuredChunk::verify() const { MOZ_ASSERT(freeCommittedCount == info.numArenasFreeCommitted); for (size_t i = 0; i < ArenasPerChunk; ++i) { - MOZ_ASSERT(!(decommittedPages[pageIndex(i)] && freeCommittedArenas[i])); - MOZ_ASSERT_IF(freeCommittedArenas[i], !arenas[i].allocated()); + MOZ_ASSERT( + !(decommittedPages[arenaToPageIndex(i)] && freeCommittedArenas[i])); } } diff --git a/src/third_party/mozjs/extract/js/src/gc/Heap.h b/src/third_party/mozjs/extract/js/src/gc/Heap.h index 3b90a91c523..d84393ad896 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Heap.h +++ b/src/third_party/mozjs/extract/js/src/gc/Heap.h @@ -10,6 +10,7 @@ #include "mozilla/DebugOnly.h" #include "gc/AllocKind.h" +#include "gc/Memory.h" #include "gc/Pretenuring.h" #include "js/HeapAPI.h" #include "js/TypeDecls.h" @@ -157,7 +158,6 @@ class alignas(ArenaSize) Arena { */ FreeSpan firstFreeSpan; - public: /* * One of the AllocKind constants or AllocKind::LIMIT when the arena does * not contain any GC things and is on the list of empty arenas in the GC @@ -170,8 +170,9 @@ class alignas(ArenaSize) Arena { * of this field must match the ArenaZoneOffset stored in js/HeapAPI.h, * as is statically asserted below. */ - JS::Zone* zone; + JS::Zone* zone_; + public: /* * Arena::next has two purposes: when unallocated, it points to the next * available Arena. When allocated, it points to the next Arena in the same @@ -228,7 +229,10 @@ class alignas(ArenaSize) Arena { */ uint8_t data[ArenaSize - ArenaHeaderSize]; - void init(JS::Zone* zoneArg, AllocKind kind, const AutoLockGC& lock); + // Create a free arena in uninitialized committed memory. + void init(GCRuntime* gc, JS::Zone* zone, AllocKind kind); + + JS::Zone* zone() const { return zone_; } // Sets |firstFreeSpan| to the Arena's entire valid range, and // also sets the next span stored at |firstFreeSpan.last| as empty. @@ -240,27 +244,14 @@ class alignas(ArenaSize) Arena { last->initAsEmpty(); } - // Initialize an arena to its unallocated state. For arenas that were - // previously allocated for some zone, use release() instead. - void setAsNotAllocated() { - firstFreeSpan.initAsEmpty(); + // Unregister the associated atom marking bitmap index for an arena in the + // atoms zone. + inline void freeAtomMarkingBitmapIndex(GCRuntime* gc, const AutoLockGC& lock); - // Poison zone pointer to highlight UAF on released arenas in crash data. - AlwaysPoison(&zone, JS_FREED_ARENA_PATTERN, sizeof(zone), - MemCheckKind::MakeNoAccess); - - allocKind = AllocKind::LIMIT; - onDelayedMarkingList_ = 0; - hasDelayedBlackMarking_ = 0; - hasDelayedGrayMarking_ = 0; - nextDelayedMarkingArena_ = 0; - bufferedCells_ = nullptr; - - MOZ_ASSERT(!allocated()); - } - - // Return an allocated arena to its unallocated state. - inline void release(const AutoLockGC& lock); + // Return an allocated arena to its unallocated (free) state. + // For arenas in the atoms zone, freeAtomMarkingBitmapIndex() must be called + // first. + inline void release(); uintptr_t address() const { checkAddress(); @@ -269,15 +260,15 @@ class alignas(ArenaSize) Arena { inline void checkAddress() const; - inline TenuredChunk* chunk() const; + inline ArenaChunk* chunk() const; - bool allocated() const { - MOZ_ASSERT(IsAllocKind(AllocKind(allocKind))); - return IsValidAllocKind(AllocKind(allocKind)); - } + // Return whether this arena is in the 'allocated' state, meaning that it has + // been initialized by calling init() and has a zone and alloc kind set. + // This is mostly used for assertions. + bool allocated() const; AllocKind getAllocKind() const { - MOZ_ASSERT(allocated()); + MOZ_ASSERT(IsValidAllocKind(allocKind)); return allocKind; } @@ -316,7 +307,8 @@ class alignas(ArenaSize) Arena { firstFreeSpan.last == lastThingOffset(kind); } - bool hasFreeThings() const { return !firstFreeSpan.isEmpty(); } + bool isFull() const { return firstFreeSpan.isEmpty(); } + bool hasFreeThings() const { return !isFull(); } size_t numFreeThings(size_t thingSize) const { firstFreeSpan.checkSpan(this); @@ -414,7 +406,7 @@ class alignas(ArenaSize) Arena { inline ArenaCellSet*& bufferedCells(); inline size_t& atomBitmapStart(); - template + template size_t finalize(JS::GCContext* gcx, AllocKind thingKind, size_t thingSize); static void staticAsserts(); @@ -435,16 +427,6 @@ class alignas(ArenaSize) Arena { #endif }; -static_assert(ArenaZoneOffset == offsetof(Arena, zone), - "The hardcoded API zone offset must match the actual offset."); - -static_assert(sizeof(Arena) == ArenaSize, - "ArenaSize must match the actual size of the Arena structure."); - -static_assert( - offsetof(Arena, data) == ArenaHeaderSize, - "ArenaHeaderSize must match the actual size of the header fields."); - inline Arena* FreeSpan::getArena() { Arena* arena = getArenaUnchecked(); arena->checkAddress(); @@ -484,185 +466,53 @@ inline void FreeSpan::checkRange(uintptr_t first, uintptr_t last, #endif } -// Mark bitmap API: - -MOZ_ALWAYS_INLINE bool MarkBitmap::markBit(const TenuredCell* cell, - ColorBit colorBit) { - MarkBitmapWord* word; - uintptr_t mask; - getMarkWordAndMask(cell, colorBit, &word, &mask); - return *word & mask; -} - -MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedAny(const TenuredCell* cell) { - return markBit(cell, ColorBit::BlackBit) || - markBit(cell, ColorBit::GrayOrBlackBit); -} - -MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedBlack(const TenuredCell* cell) { - return markBit(cell, ColorBit::BlackBit); -} - -MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedGray(const TenuredCell* cell) { - return !markBit(cell, ColorBit::BlackBit) && - markBit(cell, ColorBit::GrayOrBlackBit); -} - -// The following methods that update the mark bits are not thread safe and must -// not be called in parallel with each other. -// -// They use separate read and write operations to avoid an unnecessarily strict -// atomic update on the marking bitmap. -// -// They may be called in parallel with read operations on the mark bitmap where -// there is no required ordering between the operations. This happens when gray -// unmarking occurs in parallel with background sweeping. - -// The return value indicates if the cell went from unmarked to marked. -MOZ_ALWAYS_INLINE bool MarkBitmap::markIfUnmarked(const TenuredCell* cell, - MarkColor color) { - MarkBitmapWord* word; - uintptr_t mask; - getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); - if (*word & mask) { - return false; - } - if (color == MarkColor::Black) { - uintptr_t bits = *word; - *word = bits | mask; - } else { - // We use getMarkWordAndMask to recalculate both mask and word as doing just - // mask << color may overflow the mask. - getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask); - if (*word & mask) { - return false; - } - uintptr_t bits = *word; - *word = bits | mask; - } - return true; -} - -MOZ_ALWAYS_INLINE bool MarkBitmap::markIfUnmarkedAtomic(const TenuredCell* cell, - MarkColor color) { - // This version of the method is safe in the face of concurrent writes to the - // mark bitmap but may return false positives. The extra synchronisation - // necessary to avoid this resulted in worse performance overall. - - MarkBitmapWord* word; - uintptr_t mask; - getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); - if (*word & mask) { - return false; - } - if (color == MarkColor::Black) { - *word |= mask; - } else { - // We use getMarkWordAndMask to recalculate both mask and word as doing just - // mask << color may overflow the mask. - getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask); - if (*word & mask) { - return false; - } - *word |= mask; - } - return true; -} - -MOZ_ALWAYS_INLINE void MarkBitmap::markBlack(const TenuredCell* cell) { - MarkBitmapWord* word; - uintptr_t mask; - getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); - uintptr_t bits = *word; - *word = bits | mask; -} - -MOZ_ALWAYS_INLINE void MarkBitmap::markBlackAtomic(const TenuredCell* cell) { - MarkBitmapWord* word; - uintptr_t mask; - getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); - *word |= mask; -} - -MOZ_ALWAYS_INLINE void MarkBitmap::copyMarkBit(TenuredCell* dst, - const TenuredCell* src, - ColorBit colorBit) { - TenuredChunkBase* srcChunk = detail::GetCellChunkBase(src); - MarkBitmapWord* srcWord; - uintptr_t srcMask; - srcChunk->markBits.getMarkWordAndMask(src, colorBit, &srcWord, &srcMask); - - MarkBitmapWord* dstWord; - uintptr_t dstMask; - getMarkWordAndMask(dst, colorBit, &dstWord, &dstMask); - - uintptr_t bits = *dstWord; - bits &= ~dstMask; - if (*srcWord & srcMask) { - bits |= dstMask; - } - *dstWord = bits; -} - -MOZ_ALWAYS_INLINE void MarkBitmap::unmark(const TenuredCell* cell) { - MarkBitmapWord* word; - uintptr_t mask; - uintptr_t bits; - getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask); - bits = *word; - *word = bits & ~mask; - getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask); - bits = *word; - *word = bits & ~mask; -} - -inline MarkBitmapWord* MarkBitmap::arenaBits(Arena* arena) { - static_assert( - ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD, - "We assume that the part of the bitmap corresponding to the arena " - "has the exact number of words so we do not need to deal with a word " - "that covers bits from two arenas."); - - MarkBitmapWord* word; - uintptr_t unused; - getMarkWordAndMask(reinterpret_cast(arena->address()), - ColorBit::BlackBit, &word, &unused); - return word; -} - /* - * A chunk in the tenured heap. TenuredChunks contain arenas and associated data + * A chunk in the tenured heap. ArenaChunks contain arenas and associated data * structures (mark bitmap, delayed marking state). */ -class TenuredChunk : public TenuredChunkBase { +class ArenaChunk : public ArenaChunkBase { Arena arenas[ArenasPerChunk]; friend class GCRuntime; friend class MarkingValidator; public: - static TenuredChunk* fromAddress(uintptr_t addr) { + static ArenaChunk* fromAddress(uintptr_t addr) { addr &= ~ChunkMask; - return reinterpret_cast(addr); + return reinterpret_cast(addr); } static bool withinValidRange(uintptr_t addr) { uintptr_t offset = addr & ChunkMask; - if (TenuredChunk::fromAddress(addr)->isNurseryChunk()) { + if (ArenaChunk::fromAddress(addr)->isNurseryChunk()) { return offset >= sizeof(ChunkBase) && offset < ChunkSize; } - return offset >= offsetof(TenuredChunk, arenas) && offset < ChunkSize; + return offset >= offsetof(ArenaChunk, arenas) && offset < ChunkSize; } static size_t arenaIndex(const Arena* arena) { uintptr_t addr = arena->address(); - MOZ_ASSERT(!TenuredChunk::fromAddress(addr)->isNurseryChunk()); + MOZ_ASSERT(!ArenaChunk::fromAddress(addr)->isNurseryChunk()); MOZ_ASSERT(withinValidRange(addr)); uintptr_t offset = addr & ChunkMask; - return (offset - offsetof(TenuredChunk, arenas)) >> ArenaShift; + return (offset - offsetof(ArenaChunk, arenas)) >> ArenaShift; } - explicit TenuredChunk(JSRuntime* runtime) : TenuredChunkBase(runtime) {} + static size_t pageIndex(const Arena* arena) { + return arenaToPageIndex(arenaIndex(arena)); + } + + static size_t arenaToPageIndex(size_t arenaIndex) { + static_assert((offsetof(ArenaChunk, arenas) % PageSize) == 0, + "First arena should be on a page boundary"); + return arenaIndex / ArenasPerPage; + } + + static size_t pageToArenaIndex(size_t pageIndex) { + return pageIndex * ArenasPerPage; + } + + explicit ArenaChunk(JSRuntime* runtime) : ArenaChunkBase(runtime) {} uintptr_t address() const { uintptr_t addr = reinterpret_cast(this); @@ -670,34 +520,35 @@ class TenuredChunk : public TenuredChunkBase { return addr; } - bool unused() const { return info.numArenasFree == ArenasPerChunk; } + bool isEmpty() const { return info.numArenasFree == ArenasPerChunk; } - bool hasAvailableArenas() const { return info.numArenasFree != 0; } + bool hasAvailableArenas() const { return !isFull(); } + bool isFull() const { return info.numArenasFree == 0; } bool isNurseryChunk() const { return storeBuffer; } - Arena* allocateArena(GCRuntime* gc, JS::Zone* zone, AllocKind kind, - const AutoLockGC& lock); + Arena* allocateArena(GCRuntime* gc, JS::Zone* zone, AllocKind kind); void releaseArena(GCRuntime* gc, Arena* arena, const AutoLockGC& lock); - void recycleArena(Arena* arena, SortedArenaList& dest, size_t thingsPerArena); void decommitFreeArenas(GCRuntime* gc, const bool& cancel, AutoLockGC& lock); [[nodiscard]] bool decommitOneFreePage(GCRuntime* gc, size_t pageIndex, - AutoLockGC& lock); + const AutoLockGC& lock); void decommitAllArenas(); // This will decommit each unused not-already decommitted arena. It performs a // system call for each arena but is only used during OOM. void decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock); - static void* allocate(GCRuntime* gc); - static TenuredChunk* emplace(void* ptr, GCRuntime* gc, - bool allMemoryCommitted); + static void* allocate(GCRuntime* gc, StallAndRetry stallAndRetry); + static ArenaChunk* emplace(void* ptr, GCRuntime* gc, bool allMemoryCommitted); /* Unlink and return the freeArenasHead. */ Arena* fetchNextFreeArena(GCRuntime* gc); + // Merge arenas freed by background sweeping into the main free arenas bitmap. + void mergePendingFreeArenas(GCRuntime* gc, const AutoLockGC& lock); + #ifdef DEBUG void verify() const; #else @@ -707,9 +558,15 @@ class TenuredChunk : public TenuredChunkBase { private: void commitOnePage(GCRuntime* gc); - void updateChunkListAfterAlloc(GCRuntime* gc, const AutoLockGC& lock); - void updateChunkListAfterFree(GCRuntime* gc, size_t numArenasFree, - const AutoLockGC& lock); + void updateFreeCountsAfterAlloc(GCRuntime* gc, size_t numArenasAlloced, + const AutoLockGC& lock); + void updateFreeCountsAfterFree(GCRuntime* gc, size_t numArenasFreed, + bool wasCommitted, const AutoLockGC& lock); + + // Like updateFreeCountsAfterFree, but operates on the GCRuntime's current + // chunk. Does not take the lock unless the chunk is full or if we need to + // move the chunk between pools. + void updateCurrentChunkAfterAlloc(GCRuntime* gc); // Check if all arenas in a page are free. bool canDecommitPage(size_t pageIndex) const; @@ -721,16 +578,8 @@ class TenuredChunk : public TenuredChunkBase { // build. bool isPageFree(const Arena* arena) const; - // Get the page index of the arena. - size_t pageIndex(const Arena* arena) const { - return pageIndex(arenaIndex(arena)); - } - size_t pageIndex(size_t arenaIndex) const { - return arenaIndex / ArenasPerPage; - } - - Arena* pageAddress(size_t pageIndex) { - return &arenas[pageIndex * ArenasPerPage]; + void* pageAddress(size_t pageIndex) { + return &arenas[pageToArenaIndex(pageIndex)]; } }; @@ -738,11 +587,11 @@ inline void Arena::checkAddress() const { mozilla::DebugOnly addr = uintptr_t(this); MOZ_ASSERT(addr); MOZ_ASSERT(!(addr & ArenaMask)); - MOZ_ASSERT(TenuredChunk::withinValidRange(addr)); + MOZ_ASSERT(ArenaChunk::withinValidRange(addr)); } -inline TenuredChunk* Arena::chunk() const { - return TenuredChunk::fromAddress(address()); +inline ArenaChunk* Arena::chunk() const { + return ArenaChunk::fromAddress(address()); } // Cell header stored before all nursery cells. @@ -796,15 +645,17 @@ enum class MarkInfo : int { BLACK = 0, GRAY = 1, UNMARKED = -1, - NURSERY = -2, - UNKNOWN = -3, + NURSERY_FROMSPACE = -2, + NURSERY_TOSPACE = -3, // Unused if semispace disabled. + UNKNOWN = -4, + BUFFER = -5, }; // For calling from gdb only: given a pointer that is either in the nursery // (possibly pointing to a buffer, not necessarily a Cell) or a tenured Cell, -// return its mark color or NURSERY or UNKNOWN. UNKONWN is only for non-Cell -// pointers, and means it is not in the nursery (so could be malloced or stack -// or whatever.) +// return its mark color or UNMARKED if it is tenured, otherwise the region of +// memory that contains it. UNKNOWN is only for non-Cell pointers, and means it +// is not in the nursery (so could be malloced or stack or whatever.) MOZ_NEVER_INLINE MarkInfo GetMarkInfo(void* vp); // Sample usage from gdb: diff --git a/src/third_party/mozjs/extract/js/src/gc/Marking-inl.h b/src/third_party/mozjs/extract/js/src/gc/Marking-inl.h index 90f63376573..5fae4fd2bfd 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Marking-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/Marking-inl.h @@ -12,6 +12,7 @@ #include #include "gc/RelocationOverlay.h" +#include "gc/Zone.h" #include "js/Id.h" #include "js/Value.h" #include "vm/StringType.h" @@ -34,11 +35,6 @@ struct TaggedPtr { if (!obj) { return JS::NullValue(); } -#ifdef ENABLE_RECORD_TUPLE - if (MaybeForwardedIsExtendedPrimitive(*obj)) { - return JS::ExtendedPrimitiveValue(*obj); - } -#endif return JS::ObjectValue(*obj); } static JS::Value wrap(JSString* str) { return JS::StringValue(str); } diff --git a/src/third_party/mozjs/extract/js/src/gc/Marking.cpp b/src/third_party/mozjs/extract/js/src/gc/Marking.cpp index b29f98761a4..5135177f6a2 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Marking.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Marking.cpp @@ -16,6 +16,9 @@ #include #include +#include "jsmath.h" + +#include "gc/BufferAllocator.h" #include "gc/GCInternals.h" #include "gc/ParallelMarking.h" #include "gc/TraceKind.h" @@ -25,6 +28,7 @@ #include "util/Poison.h" #include "vm/GeneratorObject.h" +#include "gc/BufferAllocator-inl.h" #include "gc/GC-inl.h" #include "gc/PrivateIterators-inl.h" #include "gc/TraceMethods-inl.h" @@ -35,10 +39,10 @@ using namespace js; using namespace js::gc; using JS::MapTypeToTraceKind; +using JS::SliceBudget; using mozilla::DebugOnly; using mozilla::IntegerRange; -using mozilla::PodCopy; // [SMDOC] GC Tracing // @@ -137,7 +141,8 @@ void js::CheckTracedThing(JSTracer* trc, T* thing) { JS::TracerKind kind = trc->kind(); MOZ_ASSERT(kind == JS::TracerKind::Tenuring || kind == JS::TracerKind::MinorSweeping || - kind == JS::TracerKind::Moving); + kind == JS::TracerKind::Moving || + kind == JS::TracerKind::HeapCheck); thing = Forwarded(thing); } @@ -235,38 +240,41 @@ template void CheckTracedThing(JSTracer*, const wasm::AnyRef&); static inline bool ShouldMarkCrossCompartment(GCMarker* marker, JSObject* src, Cell* dstCell, const char* name) { - MarkColor color = marker->markColor(); - - if (!dstCell->isTenured()) { #ifdef DEBUG + if (src->isMarkedGray() && !dstCell->isTenured()) { // Bug 1743098: This shouldn't be possible but it does seem to happen. Log // some useful information in debug builds. - if (color != MarkColor::Black) { - SEprinter printer; - printer.printf( - "ShouldMarkCrossCompartment: cross compartment edge '%s' from gray " - "object to nursery thing\n", - name); - printer.put("src: "); - src->dump(printer); - printer.put("dst: "); - dstCell->dump(printer); - } + SEprinter printer; + printer.printf( + "ShouldMarkCrossCompartment: cross compartment edge '%s' from gray " + "object to nursery thing\n", + name); + printer.put("src: "); + src->dump(printer); + printer.put("dst: "); + dstCell->dump(printer); + MOZ_CRASH("Found cross compartment edge from gray object to nursery thing"); + } #endif - MOZ_ASSERT(color == MarkColor::Black); + + CellColor targetColor = AsCellColor(marker->markColor()); + CellColor currentColor = dstCell->color(); + if (currentColor >= targetColor) { + // Cell is already sufficiently marked. Nothing to do. return false; } - TenuredCell& dst = dstCell->asTenured(); + TenuredCell& dst = dstCell->asTenured(); JS::Zone* dstZone = dst.zone(); if (!src->zone()->isGCMarking() && !dstZone->isGCMarking()) { return false; } - if (color == MarkColor::Black) { + if (targetColor == CellColor::Black) { // Check our sweep groups are correct: we should never have to // mark something in a zone that we have started sweeping. - MOZ_ASSERT_IF(!dst.isMarkedBlack(), !dstZone->isGCSweeping()); + MOZ_ASSERT(currentColor < CellColor::Black); + MOZ_ASSERT(!dstZone->isGCSweeping()); /* * Having black->gray edges violates our promise to the cycle collector so @@ -286,7 +294,7 @@ static inline bool ShouldMarkCrossCompartment(GCMarker* marker, JSObject* src, * We handle the first case before returning whereas the second case happens * as part of normal marking. */ - if (dst.isMarkedGray() && !dstZone->isGCMarking()) { + if (currentColor == CellColor::Gray && !dstZone->isGCMarking()) { UnmarkGrayGCThingUnchecked(marker, JS::GCCellPtr(&dst, dst.getTraceKind())); return false; @@ -296,7 +304,8 @@ static inline bool ShouldMarkCrossCompartment(GCMarker* marker, JSObject* src, } // Check our sweep groups are correct as above. - MOZ_ASSERT_IF(!dst.isMarkedAny(), !dstZone->isGCSweeping()); + MOZ_ASSERT(currentColor == CellColor::White); + MOZ_ASSERT(!dstZone->isGCSweeping()); if (dstZone->isGCMarkingBlackOnly()) { /* @@ -304,9 +313,7 @@ static inline bool ShouldMarkCrossCompartment(GCMarker* marker, JSObject* src, * but it will be later, so record the cell so it can be marked gray * at the appropriate time. */ - if (!dst.isMarkedAny()) { - DelayCrossCompartmentGrayMarking(marker, src); - } + DelayCrossCompartmentGrayMarking(marker, src); return false; } @@ -745,7 +752,7 @@ void GCMarker::markEphemeronEdges(EphemeronEdgeVector& edges, } } - // The above marking always goes through markAndPush, which will not cause + // The above marking always goes through pushThing, which will not cause // 'edges' to be appended to while iterating. MOZ_ASSERT(edges.length() == initialLength); @@ -783,12 +790,12 @@ void GCMarker::markImplicitEdges(T* markedThing) { MOZ_ASSERT(!zone->isGCSweeping()); auto& ephemeronTable = zone->gcEphemeronEdges(); - auto* p = ephemeronTable.get(markedThing); + auto p = ephemeronTable.lookup(markedThing); if (!p) { return; } - EphemeronEdgeVector& edges = p->value; + EphemeronEdgeVector& edges = p->value(); // markedThing might be a key in a debugger weakmap, which can end up marking // values that are in a different compartment. @@ -1032,7 +1039,8 @@ template void GCMarker::traverse(JS::Symbol* thing) { #ifdef NIGHTLY_BUILD if constexpr (bool(opts & MarkingOptions::MarkImplicitEdges)) { - markImplicitEdges(thing); + pushThing(thing); + return; } #endif traceChildren(thing); @@ -1073,6 +1081,10 @@ template void GCMarker::traverse(BaseScript* thing) { pushThing(thing); } +template +void GCMarker::traverse(SmallBuffer* thing) { + // Buffer contents are traced by their owning GC thing. +} template void js::GCMarker::traceChildren(T* thing) { @@ -1182,6 +1194,19 @@ MOZ_NEVER_INLINE bool js::GCMarker::markAndTraversePrivateGCThing( return true; } +template +bool js::GCMarker::markAndTraverseSymbol(JSObject* source, JS::Symbol* target) { + this->markAndTraverseEdge(source, target); + + // Ensure stack headroom in case we pushed. + if (MOZ_UNLIKELY(!stack.ensureSpace(ValueRangeWords))) { + delayMarkingChildrenOnOOM(source); + return false; + } + + return true; +} + template bool js::GCMarker::mark(T* thing) { if (!thing->isTenured()) { @@ -1202,7 +1227,7 @@ bool js::GCMarker::mark(T* thing) { TraceKindCanBeGray::value ? markColor() : MarkColor::Black; if constexpr (bool(opts & MarkingOptions::ParallelMarking)) { - return thing->asTenured().markIfUnmarkedAtomic(color); + return thing->asTenured().markIfUnmarkedThreadSafe(color); } return thing->asTenured().markIfUnmarked(color); @@ -1234,11 +1259,11 @@ static gcstats::PhaseKind GrayMarkingPhaseForCurrentPhase( } } -void GCMarker::moveWork(GCMarker* dst, GCMarker* src) { +size_t GCMarker::moveWork(GCMarker* dst, GCMarker* src, bool allowDistribute) { MOZ_ASSERT(dst->stack.isEmpty()); MOZ_ASSERT(src->canDonateWork()); - MarkStack::moveWork(dst->stack, src->stack); + return MarkStack::moveWork(src, dst->stack, src->stack, allowDistribute); } bool GCMarker::initStack() { @@ -1312,16 +1337,6 @@ bool GCMarker::doMarking(SliceBudget& budget, ShouldReportMarkTime reportTime) { return true; } -class MOZ_RAII gc::AutoUpdateMarkStackRanges { - GCMarker& marker_; - - public: - explicit AutoUpdateMarkStackRanges(GCMarker& marker) : marker_(marker) { - marker_.updateRangesAtStartOfSlice(); - } - ~AutoUpdateMarkStackRanges() { marker_.updateRangesAtEndOfSlice(); } -}; - template bool GCMarker::markOneColor(SliceBudget& budget) { AutoSetMarkColor setColor(*this, color); @@ -1337,7 +1352,7 @@ bool GCMarker::markOneColor(SliceBudget& budget) { } bool GCMarker::markCurrentColorInParallel(SliceBudget& budget) { - AutoUpdateMarkStackRanges updateRanges(*this); + MOZ_ASSERT(stack.elementsRangesAreValid); ParallelMarker::AtomicCount& waitingTaskCount = parallelMarker_->waitingTaskCountRef(); @@ -1405,42 +1420,50 @@ static inline size_t NumUsedDynamicSlots(NativeObject* obj) { } void GCMarker::updateRangesAtStartOfSlice() { + MOZ_ASSERT(!stack.elementsRangesAreValid); + for (MarkStackIter iter(stack); !iter.done(); iter.next()) { if (iter.isSlotsOrElementsRange()) { - MarkStack::SlotsOrElementsRange& range = iter.slotsOrElementsRange(); + MarkStack::SlotsOrElementsRange range = iter.slotsOrElementsRange(); JSObject* obj = range.ptr().asRangeObject(); if (!obj->is()) { + // The object owning the range was swapped with a non-native object by + // the mutator. The barriers at the end of JSObject::swap ensure that + // everything gets marked so there's nothing to do here. range.setEmpty(); + iter.setSlotsOrElementsRange(range); } else if (range.kind() == SlotsOrElementsKind::Elements) { NativeObject* obj = &range.ptr().asRangeObject()->as(); size_t index = range.start(); size_t numShifted = obj->getElementsHeader()->numShiftedElements(); index -= std::min(numShifted, index); range.setStart(index); + iter.setSlotsOrElementsRange(range); } } } #ifdef DEBUG - MOZ_ASSERT(!stack.elementsRangesAreValid); stack.elementsRangesAreValid = true; #endif } void GCMarker::updateRangesAtEndOfSlice() { + MOZ_ASSERT(stack.elementsRangesAreValid); + for (MarkStackIter iter(stack); !iter.done(); iter.next()) { if (iter.isSlotsOrElementsRange()) { - MarkStack::SlotsOrElementsRange& range = iter.slotsOrElementsRange(); + MarkStack::SlotsOrElementsRange range = iter.slotsOrElementsRange(); if (range.kind() == SlotsOrElementsKind::Elements) { NativeObject* obj = &range.ptr().asRangeObject()->as(); size_t numShifted = obj->getElementsHeader()->numShiftedElements(); range.setStart(range.start() + numShifted); + iter.setSlotsOrElementsRange(range); } } } #ifdef DEBUG - MOZ_ASSERT(stack.elementsRangesAreValid); stack.elementsRangesAreValid = false; #endif } @@ -1515,6 +1538,20 @@ inline bool GCMarker::processMarkStackTop(SliceBudget& budget) { goto scan_obj; } + case MarkStack::SymbolTag: { +#ifdef NIGHTLY_BUILD + auto* symbol = ptr.as(); + if constexpr (bool(opts & MarkingOptions::MarkImplicitEdges)) { + markImplicitEdges(symbol); + } + AutoSetTracingSource asts(tracer(), symbol); + symbol->traceChildren(tracer()); + return true; +#else + MOZ_CRASH("symbols-as-weakmap-keys is enabled only on Nightly"); +#endif + } + case MarkStack::JitCodeTag: { auto* code = ptr.as(); AutoSetTracingSource asts(tracer(), code); @@ -1558,8 +1595,8 @@ scan_value_range: if (v.isString()) { markAndTraverseEdge(obj, v.toString()); - } else if (v.hasObjectPayload()) { - JSObject* obj2 = &v.getObjectPayload(); + } else if (v.isObject()) { + JSObject* obj2 = &v.toObject(); #ifdef DEBUG if (!obj2) { fprintf(stderr, @@ -1578,7 +1615,9 @@ scan_value_range: goto scan_obj; } } else if (v.isSymbol()) { - markAndTraverseEdge(obj, v.toSymbol()); + if (!markAndTraverseSymbol(obj, v.toSymbol())) { + return true; + } } else if (v.isBigInt()) { markAndTraverseEdge(obj, v.toBigInt()); } else { @@ -1617,6 +1656,16 @@ scan_obj: { unsigned nslots = nobj->slotSpan(); + if (nobj->hasDynamicSlots()) { + ObjectSlots* slots = nobj->getSlotsHeader(); + MarkTenuredBuffer(nobj->zone(), slots); + } + + if (nobj->hasDynamicElements()) { + void* elements = nobj->getUnshiftedElementsHeader(); + MarkTenuredBuffer(nobj->zone(), elements); + } + if (!nobj->hasEmptyElements()) { base = nobj->getDenseElements(); kind = SlotsOrElementsKind::Elements; @@ -1665,6 +1714,10 @@ struct MapTypeToMarkStackTag { static const auto value = MarkStack::ObjectTag; }; template <> +struct MapTypeToMarkStackTag { + static const auto value = MarkStack::SymbolTag; +}; +template <> struct MapTypeToMarkStackTag { static const auto value = MarkStack::JitCodeTag; }; @@ -1682,12 +1735,17 @@ inline MarkStack::TaggedPtr::TaggedPtr(Tag tag, Cell* ptr) assertValid(); } -inline uintptr_t MarkStack::TaggedPtr::asBits() const { return bits; } - -inline uintptr_t MarkStack::TaggedPtr::tagUnchecked() const { - return bits & TagMask; +/* static */ +inline MarkStack::TaggedPtr MarkStack::TaggedPtr::fromBits(uintptr_t bits) { + return TaggedPtr(bits); } +inline MarkStack::TaggedPtr::TaggedPtr(uintptr_t bits) : bits(bits) { + assertValid(); +} + +inline uintptr_t MarkStack::TaggedPtr::asBits() const { return bits; } + inline MarkStack::Tag MarkStack::TaggedPtr::tag() const { auto tag = Tag(bits & TagMask); MOZ_ASSERT(tag <= LastTag); @@ -1731,6 +1789,19 @@ inline MarkStack::SlotsOrElementsRange::SlotsOrElementsRange( MOZ_ASSERT(start() == startArg); } +/* static */ +inline MarkStack::SlotsOrElementsRange +MarkStack::SlotsOrElementsRange::fromBits(uintptr_t startAndKind, + uintptr_t ptr) { + return SlotsOrElementsRange(startAndKind, ptr); +} + +inline MarkStack::SlotsOrElementsRange::SlotsOrElementsRange( + uintptr_t startAndKind, uintptr_t ptr) + : startAndKind_(startAndKind), ptr_(TaggedPtr::fromBits(ptr)) { + assertValid(); +} + inline void MarkStack::SlotsOrElementsRange::assertValid() const { ptr_.assertValid(); MOZ_ASSERT(TagIsRangeTag(ptr_.tag())); @@ -1750,7 +1821,11 @@ inline void MarkStack::SlotsOrElementsRange::setStart(size_t newStart) { } inline void MarkStack::SlotsOrElementsRange::setEmpty() { - TaggedPtr entry = TaggedPtr(ObjectTag, ptr().asRangeObject()); + // Replace this SlotsOrElementsRange with something that's valid for marking + // but doesn't involve accessing this range, which is now invalid. This + // replaces the two-word range with two single-word entries for the owning + // object. + TaggedPtr entry(ObjectTag, ptr().asRangeObject()); ptr_ = entry; startAndKind_ = entry.asBits(); } @@ -1759,12 +1834,24 @@ inline MarkStack::TaggedPtr MarkStack::SlotsOrElementsRange::ptr() const { return ptr_; } +inline uintptr_t MarkStack::SlotsOrElementsRange::asBits0() const { + return startAndKind_; +} + +inline uintptr_t MarkStack::SlotsOrElementsRange::asBits1() const { + return ptr_.asBits(); +} + MarkStack::MarkStack() { MOZ_ASSERT(isEmpty()); } -MarkStack::~MarkStack() { MOZ_ASSERT(isEmpty()); } +MarkStack::~MarkStack() { + MOZ_ASSERT(isEmpty()); + clearAndFreeStack(); +} void MarkStack::swap(MarkStack& other) { std::swap(stack_, other.stack_); + std::swap(capacity_, other.capacity_); std::swap(topIndex_, other.topIndex_); #ifdef JS_GC_ZEAL std::swap(maxCapacity_, other.maxCapacity_); @@ -1819,18 +1906,22 @@ MOZ_ALWAYS_INLINE bool MarkStack::indexIsEntryBase(size_t index) const { // startAndKind_ word can be interpreted as such, which is arranged by making // SlotsOrElementsRangeTag zero and all SlotsOrElementsKind tags non-zero. - MOZ_ASSERT(index < position()); - return stack()[index].tagUnchecked() != SlotsOrElementsRangeTag; + MOZ_ASSERT(index < capacity_); + return (stack_[index] & TagMask) != SlotsOrElementsRangeTag; } /* static */ -void MarkStack::moveWork(MarkStack& dst, MarkStack& src) { +size_t MarkStack::moveWork(GCMarker* marker, MarkStack& dst, MarkStack& src, + bool allowDistribute) { // Move some work from |src| to |dst|. Assumes |dst| is empty. // // When this method runs during parallel marking, we are on the thread that // owns |src|, and the thread that owns |dst| is blocked waiting on the // ParallelMarkTask::resumed condition variable. + MOZ_ASSERT(dst.isEmpty()); + MOZ_ASSERT(src.elementsRangesAreValid == dst.elementsRangesAreValid); + // Limit the size of moves to stop threads with work spending too much time // donating. static const size_t MaxWordsToMove = 4096; @@ -1838,6 +1929,65 @@ void MarkStack::moveWork(MarkStack& dst, MarkStack& src) { size_t totalWords = src.position(); size_t wordsToMove = std::min(totalWords / 2, MaxWordsToMove); + // Mark stack entries do not represent uniform amounts of marking work (they + // are either single GC things or arbitrarily large arrays) and when the mark + // stack is small the situation often arises where one thread repeatedly takes + // what is in effect a small amount of marking work while leaving the other + // thread with a whole lot more. To split the work up more effectively we + // randomly distribute stack entries for small stack. + // + // This works by randomly choosing one of every pair of entries in |src| and + // moving it to |dst| (rather than moving half of the stack as a contiguous + // region). + // + // This has the effect of reducing the number of donations between threads. It + // does not decrease average marking time but it does decrease variance of + // marking time. + static constexpr size_t MaxWordsToDistribute = 30; + if (allowDistribute && totalWords <= MaxWordsToDistribute) { + if (!dst.ensureSpace(totalWords)) { + return 0; + } + + src.topIndex_ = 0; + + // We will use bits from a single 64-bit random number. + static_assert(HowMany(MaxWordsToDistribute, 2) <= 64); + uint64_t randomBits = marker->random.ref().next(); + DebugOnly randomBitCount = 64; + + size_t i = 0; // Entry index. + size_t pos = 0; // Source stack position. + uintptr_t* data = src.stack_; + while (pos < totalWords) { + MOZ_ASSERT(src.indexIsEntryBase(pos)); + + // Randomly chose which stack to copy the entry to, with each half of each + // pair of entries moving to different stacks. + MOZ_ASSERT(randomBitCount != 0); + bool whichStack = (randomBits & 1) ^ (i & 1); + randomBits <<= i & 1; + randomBitCount -= i & 1; + + MarkStack& stack = whichStack ? dst : src; + + bool isRange = + pos < totalWords - 1 && TagIsRangeTag(Tag(data[pos + 1] & TagMask)); + if (isRange) { + stack.infalliblePush( + SlotsOrElementsRange::fromBits(data[pos], data[pos + 1])); + pos += ValueRangeWords; + } else { + stack.infalliblePush(TaggedPtr::fromBits(data[pos])); + pos++; + } + + i++; + } + + return totalWords; + } + size_t targetPos = src.position() - wordsToMove; // Adjust the target position in case it points to the middle of a two word @@ -1852,7 +2002,7 @@ void MarkStack::moveWork(MarkStack& dst, MarkStack& src) { MOZ_ASSERT(wordsToMove == src.position() - targetPos); if (!dst.ensureSpace(wordsToMove)) { - return; + return 0; } // TODO: This doesn't have good cache behaviour when moving work between @@ -1860,7 +2010,7 @@ void MarkStack::moveWork(MarkStack& dst, MarkStack& src) { // part of the stack, in src words if this method stole from the bottom of // the stack rather than the top. - mozilla::PodCopy(dst.topPtr(), src.stack().begin() + targetPos, wordsToMove); + mozilla::PodCopy(dst.end(), src.stack_ + targetPos, wordsToMove); dst.topIndex_ += wordsToMove; dst.peekPtr().assertValid(); @@ -1869,24 +2019,24 @@ void MarkStack::moveWork(MarkStack& dst, MarkStack& src) { src.poisonUnused(); #endif src.peekPtr().assertValid(); + return wordsToMove; } void MarkStack::clearAndResetCapacity() { // Fall back to the smaller initial capacity so we don't hold on to excess // memory between GCs. - stack().clear(); topIndex_ = 0; (void)resetStackCapacity(); } void MarkStack::clearAndFreeStack() { // Free all stack memory so we don't hold on to excess memory between GCs. - stack().clearAndFree(); + js_free(stack_); + stack_ = nullptr; + capacity_ = 0; topIndex_ = 0; } -inline MarkStack::TaggedPtr* MarkStack::topPtr() { return &stack()[topIndex_]; } - template inline bool MarkStack::push(T* ptr) { return push(TaggedPtr(MapTypeToMarkStackTag::value, ptr)); @@ -1906,25 +2056,30 @@ inline bool MarkStack::push(const TaggedPtr& ptr) { } inline void MarkStack::infalliblePush(const TaggedPtr& ptr) { - *topPtr() = ptr; + MOZ_ASSERT(position() + 1 <= capacity()); + *end() = ptr.asBits(); topIndex_++; - MOZ_ASSERT(position() <= capacity()); } inline void MarkStack::infalliblePush(JSObject* obj, SlotsOrElementsKind kind, size_t start) { + SlotsOrElementsRange range(kind, obj, start); + infalliblePush(range); +} + +inline void MarkStack::infalliblePush(const SlotsOrElementsRange& range) { MOZ_ASSERT(position() + ValueRangeWords <= capacity()); - SlotsOrElementsRange array(kind, obj, start); - array.assertValid(); - *reinterpret_cast(topPtr()) = array; + range.assertValid(); + end()[0] = range.asBits0(); + end()[1] = range.asBits1(); topIndex_ += ValueRangeWords; MOZ_ASSERT(TagIsRangeTag(peekTag())); } -inline const MarkStack::TaggedPtr& MarkStack::peekPtr() const { +inline MarkStack::TaggedPtr MarkStack::peekPtr() const { MOZ_ASSERT(!isEmpty()); - return stack()[topIndex_ - 1]; + return TaggedPtr::fromBits(at(topIndex_ - 1)); } inline MarkStack::Tag MarkStack::peekTag() const { @@ -1937,7 +2092,7 @@ inline MarkStack::TaggedPtr MarkStack::popPtr() { MOZ_ASSERT(!TagIsRangeTag(peekTag())); peekPtr().assertValid(); topIndex_--; - return *topPtr(); + return TaggedPtr::fromBits(*end()); } inline MarkStack::SlotsOrElementsRange MarkStack::popSlotsOrElementsRange() { @@ -1946,9 +2101,7 @@ inline MarkStack::SlotsOrElementsRange MarkStack::popSlotsOrElementsRange() { MOZ_ASSERT(position() >= ValueRangeWords); topIndex_ -= ValueRangeWords; - const auto& array = *reinterpret_cast(topPtr()); - array.assertValid(); - return array; + return SlotsOrElementsRange::fromBits(end()[0], end()[1]); } inline bool MarkStack::ensureSpace(size_t count) { @@ -1977,11 +2130,20 @@ bool MarkStack::resize(size_t newCapacity) { MOZ_ASSERT(newCapacity != 0); MOZ_ASSERT(newCapacity >= position()); - if (!stack().resize(newCapacity)) { + auto poisonOnExit = mozilla::MakeScopeExit([this]() { poisonUnused(); }); + + if (newCapacity == capacity_) { + return true; + } + + uintptr_t* newStack = + js_pod_realloc(stack_, capacity_, newCapacity); + if (!newStack) { return false; } - poisonUnused(); + stack_ = newStack; + capacity_ = newCapacity; return true; } @@ -1990,13 +2152,14 @@ inline void MarkStack::poisonUnused() { "The mark stack poison pattern must not look like a valid " "tagged pointer"); - AlwaysPoison(stack().begin() + topIndex_, JS_FRESH_MARK_STACK_PATTERN, - stack().capacity() - topIndex_, MemCheckKind::MakeUndefined); + MOZ_ASSERT(topIndex_ <= capacity_); + AlwaysPoison(stack_ + topIndex_, JS_FRESH_MARK_STACK_PATTERN, + capacity_ - topIndex_, MemCheckKind::MakeUndefined); } size_t MarkStack::sizeOfExcludingThis( mozilla::MallocSizeOf mallocSizeOf) const { - return stack().sizeOfExcludingThis(mallocSizeOf); + return capacity_ * sizeof(uintptr_t); } MarkStackIter::MarkStackIter(MarkStack& stack) @@ -2025,17 +2188,25 @@ inline MarkStack::Tag MarkStackIter::peekTag() const { return peekPtr().tag(); } inline MarkStack::TaggedPtr MarkStackIter::peekPtr() const { MOZ_ASSERT(!done()); - return stack_.stack()[pos_ - 1]; + return MarkStack::TaggedPtr::fromBits(stack_.at(pos_ - 1)); } -inline MarkStack::SlotsOrElementsRange& MarkStackIter::slotsOrElementsRange() { +inline MarkStack::SlotsOrElementsRange MarkStackIter::slotsOrElementsRange() + const { MOZ_ASSERT(TagIsRangeTag(peekTag())); MOZ_ASSERT(position() >= ValueRangeWords); - MarkStack::TaggedPtr* ptr = &stack_.stack()[pos_ - ValueRangeWords]; - auto& range = *reinterpret_cast(ptr); - range.assertValid(); - return range; + uintptr_t* ptr = stack_.ptr(pos_ - ValueRangeWords); + return MarkStack::SlotsOrElementsRange::fromBits(ptr[0], ptr[1]); +} + +inline void MarkStackIter::setSlotsOrElementsRange( + const MarkStack::SlotsOrElementsRange& range) { + MOZ_ASSERT(isSlotsOrElementsRange()); + + uintptr_t* ptr = stack_.ptr(pos_ - ValueRangeWords); + ptr[0] = range.asBits0(); + ptr[1] = range.asBits1(); } /*** GCMarker ***************************************************************/ @@ -2053,7 +2224,8 @@ GCMarker::GCMarker(JSRuntime* rt) markColor_(MarkColor::Black), state(NotActive), incrementalWeakMapMarkingEnabled( - TuningDefaults::IncrementalWeakMapMarkingEnabled) + TuningDefaults::IncrementalWeakMapMarkingEnabled), + random(js::GenerateRandomSeed(), js::GenerateRandomSeed()) #ifdef DEBUG , checkAtomMarking(true), @@ -2073,14 +2245,9 @@ void GCMarker::start() { } static void ClearEphemeronEdges(JSRuntime* rt) { - AutoEnterOOMUnsafeRegion oomUnsafe; for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - if (!zone->gcEphemeronEdges().clear()) { - oomUnsafe.crash("clearing weak keys in GCMarker::stop()"); - } - if (!zone->gcNurseryEphemeronEdges().clear()) { - oomUnsafe.crash("clearing (nursery) weak keys in GCMarker::stop()"); - } + zone->gcEphemeronEdges().clearAndCompact(); + zone->gcNurseryEphemeronEdges().clearAndCompact(); } } @@ -2254,15 +2421,10 @@ IncrementalProgress JS::Zone::enterWeakMarkingMode(GCMarker* marker, MOZ_ASSERT(gcNurseryEphemeronEdges().count() == 0); - // An OrderedHashMap::MutableRange stays valid even when the underlying table - // (zone->gcEphemeronEdges) is mutated, which is useful here since we may add - // additional entries while iterating over the Range. - EphemeronEdgeTable::MutableRange r = gcEphemeronEdges().mutableAll(); - while (!r.empty()) { - Cell* src = r.front().key; + for (auto r = gcEphemeronEdges().all(); !r.empty(); r.popFront()) { + Cell* src = r.front().key(); CellColor srcColor = gc::detail::GetEffectiveColor(marker, src); - auto& edges = r.front().value; - r.popFront(); // Pop before any mutations happen. + auto& edges = r.front().value(); if (IsMarked(srcColor) && edges.length() > 0) { uint32_t steps = edges.length(); @@ -2605,7 +2767,7 @@ namespace js::gc { template JS_PUBLIC_API bool TraceWeakEdge(JSTracer* trc, JS::Heap* thingp) { - return TraceEdgeInternal(trc, gc::ConvertToBase(thingp->unsafeGet()), + return TraceEdgeInternal(trc, gc::ConvertToBase(thingp->unsafeAddress()), "JS::Heap edge"); } @@ -2796,7 +2958,6 @@ void UnmarkGrayTracer::unmark(JS::GCCellPtr cell) { bool js::gc::UnmarkGrayGCThingUnchecked(GCMarker* marker, JS::GCCellPtr thing) { MOZ_ASSERT(thing); - MOZ_ASSERT(thing.asCell()->isMarkedGray()); mozilla::Maybe profilingStackFrame; if (JSContext* cx = TlsContext.get()) { @@ -2819,6 +2980,7 @@ JS_PUBLIC_API bool JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr thing) { return false; } + MOZ_ASSERT(thing.asCell()->isMarkedGray()); return UnmarkGrayGCThingUnchecked(&rt->gc.marker(), thing); } @@ -2839,7 +3001,14 @@ namespace js::debug { MarkInfo GetMarkInfo(void* vp) { GCRuntime& gc = TlsGCContext.get()->runtime()->gc; if (gc.nursery().isInside(vp)) { - return MarkInfo::NURSERY; + ChunkBase* chunk = js::gc::detail::GetGCAddressChunkBase(vp); + return chunk->getKind() == js::gc::ChunkKind::NurseryFromSpace + ? MarkInfo::NURSERY_FROMSPACE + : MarkInfo::NURSERY_TOSPACE; + } + + if (gc.isPointerWithinBufferAlloc(vp)) { + return MarkInfo::BUFFER; } if (!gc.isPointerWithinTenuredCell(vp)) { @@ -2867,7 +3036,7 @@ uintptr_t* GetMarkWordAddress(Cell* cell) { MarkBitmapWord* wordp; uintptr_t mask; - TenuredChunkBase* chunk = gc::detail::GetCellChunkBase(&cell->asTenured()); + ArenaChunkBase* chunk = gc::detail::GetCellChunkBase(&cell->asTenured()); chunk->markBits.getMarkWordAndMask(&cell->asTenured(), ColorBit::BlackBit, &wordp, &mask); return reinterpret_cast(wordp); @@ -2883,7 +3052,7 @@ uintptr_t GetMarkMask(Cell* cell, uint32_t colorBit) { ColorBit bit = colorBit == 0 ? ColorBit::BlackBit : ColorBit::GrayOrBlackBit; MarkBitmapWord* wordp; uintptr_t mask; - TenuredChunkBase* chunk = gc::detail::GetCellChunkBase(&cell->asTenured()); + ArenaChunkBase* chunk = gc::detail::GetCellChunkBase(&cell->asTenured()); chunk->markBits.getMarkWordAndMask(&cell->asTenured(), bit, &wordp, &mask); return mask; } diff --git a/src/third_party/mozjs/extract/js/src/gc/Memory.cpp b/src/third_party/mozjs/extract/js/src/gc/Memory.cpp index 8f35f833ce4..fd15213c6aa 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Memory.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Memory.cpp @@ -6,7 +6,6 @@ #include "gc/Memory.h" -#include "mozilla/Atomics.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/RandomNum.h" #include "mozilla/TaggedAnonymousMemory.h" @@ -14,6 +13,11 @@ #include "jit/JitOptions.h" #include "js/HeapAPI.h" #include "js/Utility.h" + +#ifdef MOZ_MEMORY +# include "mozmemory_utils.h" +#endif + #include "util/Memory.h" #ifdef XP_WIN @@ -36,6 +40,19 @@ #endif // !XP_WIN +#if defined(XP_WIN) && !defined(MOZ_MEMORY) +namespace mozilla { +// On Windows platforms, mozjemalloc provides MozVirtualAlloc, a version of +// VirtualAlloc that will sleep and retry on failure. This is a shim for when +// that function is not available. +MOZ_ALWAYS_INLINE void* MozVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, + DWORD flAllocationType, + DWORD flProtect) { + return VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); +} +} // namespace mozilla +#endif // defined(XP_WIN) && !defined(MOZ_MEMORY) + namespace js::gc { /* @@ -53,6 +70,12 @@ static size_t numAddressBits = 0; /* An estimate of the number of bytes available for virtual memory. */ static size_t virtualMemoryLimit = size_t(-1); +/* Whether decommit is enabled. */ +static bool decommitEnabled = false; + +/* Whether DisableDecommit() has been called. */ +static bool disableDecommitRequested = false; + /* * System allocation functions may hand out regions of memory in increasing or * decreasing order. This ordering is used as a hint during chunk alignment to @@ -115,6 +138,10 @@ static size_t maxValidAddress = 0; static size_t hugeSplit = 0; #endif +/* Running totals to report to the profiler. */ +mozilla::Atomic gMappedMemorySizeBytes; +mozilla::Atomic gMappedMemoryOperations; + size_t SystemPageSize() { return pageSize; } size_t SystemAddressBits() { return numAddressBits; } @@ -170,30 +197,47 @@ static bool TryToAlignChunk(void** aRegion, void** aRetainedRegion, #ifndef __wasi__ static void* MapAlignedPagesSlow(size_t length, size_t alignment); #endif // wasi -static void* MapAlignedPagesLastDitch(size_t length, size_t alignment); +static void* MapAlignedPagesLastDitch(size_t length, size_t alignment, + StallAndRetry stallAndRetry); #ifdef JS_64BIT static void* MapAlignedPagesRandom(size_t length, size_t alignment); #endif void* TestMapAlignedPagesLastDitch(size_t length, size_t alignment) { - return MapAlignedPagesLastDitch(length, alignment); + void* region = MapAlignedPagesLastDitch(length, alignment, StallAndRetry::No); + if (region) { + RecordMemoryAlloc(length); + } + return region; } -bool DecommitEnabled() { return SystemPageSize() == PageSize; } +bool DecommitEnabled() { return decommitEnabled; } + +void DisableDecommit() { + MOZ_RELEASE_ASSERT( + pageSize == 0, + "DisableDecommit should be called before InitMemorySubsystem"); + disableDecommitRequested = true; +} /* Returns the offset from the nearest aligned address at or below |region|. */ static inline size_t OffsetFromAligned(void* region, size_t alignment) { return uintptr_t(region) % alignment; } -template +template static inline void* MapInternal(void* desired, size_t length) { void* region = nullptr; #ifdef XP_WIN DWORD flags = (commit == Commit::Yes ? MEM_RESERVE | MEM_COMMIT : MEM_RESERVE); - region = VirtualAlloc(desired, length, flags, DWORD(prot)); + if constexpr (retry == StallAndRetry::Yes) { + region = mozilla::MozVirtualAlloc(desired, length, flags, + DWORD(PageAccess::ReadWrite)); + } else { + region = VirtualAlloc(desired, length, flags, DWORD(PageAccess::ReadWrite)); + } #elif defined(__wasi__) if (int err = posix_memalign(®ion, gc::SystemPageSize(), length)) { MOZ_RELEASE_ASSERT(err == ENOMEM); @@ -204,8 +248,8 @@ static inline void* MapInternal(void* desired, size_t length) { } #else int flags = MAP_PRIVATE | MAP_ANON; - region = MozTaggedAnonymousMmap(desired, length, int(prot), flags, -1, 0, - "js-gc-heap"); + region = MozTaggedAnonymousMmap(desired, length, int(PageAccess::ReadWrite), + flags, -1, 0, "js-gc-heap"); if (region == MAP_FAILED) { return nullptr; } @@ -228,37 +272,37 @@ static inline void UnmapInternal(void* region, size_t length) { #endif } -template +template static inline void* MapMemory(size_t length) { MOZ_ASSERT(length > 0); - return MapInternal(nullptr, length); + return MapInternal(nullptr, length); } /* * Attempts to map memory at the given address, but allows the system * to return a different address that may still be suitable. */ -template +template static inline void* MapMemoryAtFuzzy(void* desired, size_t length) { MOZ_ASSERT(desired && OffsetFromAligned(desired, allocGranularity) == 0); MOZ_ASSERT(length > 0); // Note that some platforms treat the requested address as a hint, so the // returned address might not match the requested address. - return MapInternal(desired, length); + return MapInternal(desired, length); } /* * Attempts to map memory at the given address, returning nullptr if * the system returns any address other than the requested one. */ -template +template static inline void* MapMemoryAt(void* desired, size_t length) { MOZ_ASSERT(desired && OffsetFromAligned(desired, allocGranularity) == 0); MOZ_ASSERT(length > 0); - void* region = MapInternal(desired, length); + void* region = MapInternal(desired, length); if (!region) { return nullptr; } @@ -379,6 +423,11 @@ void InitMemorySubsystem() { pageSize = size_t(sysconf(_SC_PAGESIZE)); allocGranularity = pageSize; #endif + + // Decommit is supported if the system page size is the size as the + // compile time constant and has not been disabled. + decommitEnabled = pageSize == PageSize && !disableDecommitRequested; + #ifdef JS_64BIT # ifdef XP_WIN minValidAddress = size_t(sysinfo.lpMinimumApplicationAddress); @@ -411,6 +460,12 @@ void InitMemorySubsystem() { } #endif } + + MOZ_ASSERT(gMappedMemorySizeBytes == 0); +} + +void CheckMemorySubsystemOnShutDown() { + MOZ_ASSERT(gMappedMemorySizeBytes == 0); } #ifdef JS_64BIT @@ -421,7 +476,8 @@ static inline bool IsInvalidRegion(void* region, size_t length) { } #endif -void* MapAlignedPages(size_t length, size_t alignment) { +void* MapAlignedPages(size_t length, size_t alignment, + StallAndRetry stallAndRetry) { MOZ_RELEASE_ASSERT(length > 0 && alignment > 0); MOZ_RELEASE_ASSERT(length % pageSize == 0); MOZ_RELEASE_ASSERT(std::max(alignment, allocGranularity) % @@ -453,14 +509,20 @@ void* MapAlignedPages(size_t length, size_t alignment) { MOZ_RELEASE_ASSERT(!IsInvalidRegion(region, length)); MOZ_ASSERT(OffsetFromAligned(region, alignment) == 0); + RecordMemoryAlloc(length); return region; } # endif - // Try to allocate the region. If the returned address is aligned, - // either we OOMed (region is nullptr) or we're done. + // Try to allocate the region. void* region = MapMemory(length); + if (!region) { + return nullptr; + } + + // If the returned address is aligned, we're done. if (OffsetFromAligned(region, alignment) == 0) { + RecordMemoryAlloc(length); return region; } @@ -470,6 +532,7 @@ void* MapAlignedPages(size_t length, size_t alignment) { if (TryToAlignChunk(®ion, &retainedRegion, length, alignment)) { MOZ_ASSERT(region && OffsetFromAligned(region, alignment) == 0); MOZ_ASSERT(!retainedRegion); + RecordMemoryAlloc(length); return region; } @@ -492,11 +555,16 @@ void* MapAlignedPages(size_t length, size_t alignment) { if (!region) { // If there wasn't enough contiguous address space left for that, // try to find an alignable region using the last ditch allocator. - region = MapAlignedPagesLastDitch(length, alignment); + region = MapAlignedPagesLastDitch(length, alignment, stallAndRetry); + if (!region) { + return nullptr; + } } - // At this point we should either have an aligned region or nullptr. + // At this point we should have an aligned region. MOZ_ASSERT(OffsetFromAligned(region, alignment) == 0); + + RecordMemoryAlloc(length); return region; #endif // !__wasi__ } @@ -634,10 +702,18 @@ static void* MapAlignedPagesSlow(size_t length, size_t alignment) { * by temporarily holding onto the unaligned parts of each chunk until the * allocator gives us a chunk that either is, or can be aligned. */ -static void* MapAlignedPagesLastDitch(size_t length, size_t alignment) { +static void* MapAlignedPagesLastDitch(size_t length, size_t alignment, + StallAndRetry stallAndRetry) { void* tempMaps[MaxLastDitchAttempts]; int attempt = 0; - void* region = MapMemory(length); + void* region; + + if (stallAndRetry == StallAndRetry::Yes) { + region = MapMemory(length); + } else { + region = MapMemory(length); + } + if (OffsetFromAligned(region, alignment) == 0) { return region; } @@ -783,6 +859,10 @@ void UnmapPages(void* region, size_t length) { MOZ_MAKE_MEM_UNDEFINED(region, length); UnmapInternal(region, length); + +#ifndef __wasi__ + RecordMemoryFree(length); +#endif } static void CheckDecommit(void* region, size_t length) { @@ -941,9 +1021,14 @@ void* AllocateMappedContent(int fd, size_t offset, size_t length, map = static_cast( MapViewOfFileEx(hMap, FILE_MAP_COPY, offsetH, offsetL, alignedLength, reinterpret_cast(region))); + if (map) { + break; + } + + RecordMemoryFree(mappedLength); // Retry if another thread mapped the address we were trying to use. - if (map || GetLastError() != ERROR_INVALID_ADDRESS) { + if (GetLastError() != ERROR_INVALID_ADDRESS) { break; } } @@ -1009,14 +1094,24 @@ void DeallocateMappedContent(void* region, size_t length) { // that might be offset from the mapping, as the beginning of a // mapping must be aligned with the allocation granularity. uintptr_t map = uintptr_t(region) - (uintptr_t(region) % allocGranularity); + + size_t alignedLength = length + (uintptr_t(region) % allocGranularity); + + size_t mappedLength = alignedLength; + if (alignedLength % pageSize != 0) { + mappedLength += pageSize - alignedLength % pageSize; + } + # ifdef XP_WIN MOZ_RELEASE_ASSERT(UnmapViewOfFile(reinterpret_cast(map)) != 0); # else - size_t alignedLength = length + (uintptr_t(region) % allocGranularity); if (munmap(reinterpret_cast(map), alignedLength)) { MOZ_RELEASE_ASSERT(errno == ENOMEM); } # endif + + RecordMemoryFree(mappedLength); + #endif // __wasi__ } @@ -1046,4 +1141,30 @@ void UnprotectPages(void* region, size_t length) { ProtectMemory(region, length, PageAccess::ReadWrite); } +void RecordMemoryAlloc(size_t bytes) { + MOZ_ASSERT(bytes); + MOZ_ASSERT((bytes % pageSize) == 0); + + // MONGODB MODIFICATION: Check whether this allocation took us over a + // configured memory limit. This may trigger OOM in the background, but we + // allow the mozjs logic to proceed normally for now + mongo::sm::check_oom_on_mmap_allocation(bytes); + + gMappedMemorySizeBytes += bytes; + gMappedMemoryOperations++; +} + +void RecordMemoryFree(size_t bytes) { + MOZ_ASSERT(bytes); + MOZ_ASSERT((bytes % pageSize) == 0); + MOZ_ASSERT(bytes <= gMappedMemorySizeBytes); + + gMappedMemorySizeBytes -= bytes; + gMappedMemoryOperations++; +} + +JS_PUBLIC_API ProfilerMemoryCounts GetProfilerMemoryCounts() { + return {gc::gMappedMemorySizeBytes, gc::gMappedMemoryOperations}; +} + } // namespace js::gc diff --git a/src/third_party/mozjs/extract/js/src/gc/Memory.h b/src/third_party/mozjs/extract/js/src/gc/Memory.h index fece46171d5..2457d98be56 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Memory.h +++ b/src/third_party/mozjs/extract/js/src/gc/Memory.h @@ -7,15 +7,23 @@ #ifndef gc_Memory_h #define gc_Memory_h +#include "mozilla/Atomics.h" + #include namespace js { namespace gc { +extern mozilla::Atomic gMappedMemorySizeBytes; +extern mozilla::Atomic gMappedMemoryOperations; + // Sanity check that our compiled configuration matches the currently // running instance and initialize any runtime data needed for allocation. void InitMemorySubsystem(); +// Assert that memory use as recorded RecordMemoryAlloc/Free balances. +void CheckMemorySubsystemOnShutDown(); + // The page size as reported by the operating system. size_t SystemPageSize(); @@ -32,15 +40,27 @@ size_t VirtualMemoryLimit(); // range. On these platforms we allocate at random addresses. bool UsingScattershotAllocator(); +// Whether to stall and retry memory allocation on failure. Only supported on +// Windows when built with jemalloc. +enum class StallAndRetry : bool { + No = false, + Yes = true, +}; + // Allocate or deallocate pages from the system with the given alignment. // Pages will be read/write-able. -void* MapAlignedPages(size_t length, size_t alignment); +void* MapAlignedPages(size_t length, size_t alignment, + StallAndRetry stallAndRetry = StallAndRetry::No); void UnmapPages(void* region, size_t length); -// We can only decommit unused pages if the page size is less than or equal to -// the hardcoded Arena size for the running process. +// We only decommit unused pages if the system page size is the same as the +// hardcoded page size for the build. bool DecommitEnabled(); +// Disable decommit for testing purposes. This must be called before +// InitMemorySubsystem. +void DisableDecommit(); + // Tell the OS that the given pages are not in use, so they should not be // written to a paging file. This may be a no-op on some platforms. bool MarkPagesUnusedSoft(void* region, size_t length); @@ -78,6 +98,10 @@ void ProtectPages(void* region, size_t length); void MakePagesReadOnly(void* region, size_t length); void UnprotectPages(void* region, size_t length); +// Track mapped memory so we can report it to the profiler. +void RecordMemoryAlloc(size_t bytes); +void RecordMemoryFree(size_t bytes); + } // namespace gc } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/gc/Nursery-inl.h b/src/third_party/mozjs/extract/js/src/gc/Nursery-inl.h index 8579586ddc7..2ac5813659c 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Nursery-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/Nursery-inl.h @@ -15,6 +15,7 @@ #include "js/TracingAPI.h" #include "vm/JSContext.h" #include "vm/NativeObject.h" +#include "vm/StringType.h" namespace js { namespace gc { @@ -29,6 +30,74 @@ bool js::Nursery::isInside(const SharedMem& p) const { return isInside(p.unwrap(/*safe - used for value in comparison above*/)); } +inline void js::Nursery::addMallocedBufferBytes(size_t nbytes) { + MOZ_ASSERT(nbytes > 0); + toSpace.mallocedBufferBytes += nbytes; + if (MOZ_UNLIKELY(toSpace.mallocedBufferBytes > capacity() * 8)) { + requestMinorGC(JS::GCReason::NURSERY_MALLOC_BUFFERS); + } +} + +inline bool js::Nursery::addStringBuffer(JSLinearString* s) { + MOZ_ASSERT(IsInsideNursery(s)); + MOZ_ASSERT(isEnabled()); + MOZ_ASSERT(s->hasStringBuffer()); + + auto* buffer = s->stringBuffer(); + if (!stringBuffers_.emplaceBack(s, buffer)) { + return false; + } + + // Note: update mallocedBufferBytes only if the buffer has a refcount of 1, to + // avoid double counting when the same buffer is used by multiple nursery + // strings. + if (!buffer->HasMultipleReferences()) { + addMallocedBufferBytes(buffer->AllocationSize()); + } + return true; +} + +inline bool js::Nursery::addExtensibleStringBuffer( + JSLinearString* s, mozilla::StringBuffer* buffer, bool updateMallocBytes) { + MOZ_ASSERT(IsInsideNursery(s)); + MOZ_ASSERT(isEnabled()); + if (!extensibleStringBuffers_.putNew(s, buffer)) { + return false; + } + MOZ_ASSERT(!buffer->HasMultipleReferences()); + if (updateMallocBytes) { + addMallocedBufferBytes(buffer->AllocationSize()); + } + return true; +} + +inline void js::Nursery::removeMallocedBuffer(void* buffer, size_t nbytes) { + MOZ_ASSERT(!JS::RuntimeHeapIsMinorCollecting()); + MOZ_ASSERT(toSpace.mallocedBuffers.has(buffer)); + MOZ_ASSERT(nbytes > 0); + MOZ_ASSERT(toSpace.mallocedBufferBytes >= nbytes); + toSpace.mallocedBuffers.remove(buffer); + toSpace.mallocedBufferBytes -= nbytes; +} + +void js::Nursery::removeMallocedBufferDuringMinorGC(void* buffer) { + MOZ_ASSERT(JS::RuntimeHeapIsMinorCollecting()); + MOZ_ASSERT(fromSpace.mallocedBuffers.has(buffer)); + fromSpace.mallocedBuffers.remove(buffer); +} + +inline void js::Nursery::removeExtensibleStringBuffer(JSLinearString* s, + bool updateMallocBytes) { + MOZ_ASSERT(gc::IsInsideNursery(s)); + extensibleStringBuffers_.remove(s); + + if (updateMallocBytes) { + size_t nbytes = s->stringBuffer()->AllocationSize(); + MOZ_ASSERT(toSpace.mallocedBufferBytes >= nbytes); + toSpace.mallocedBufferBytes -= nbytes; + } +} + inline bool js::Nursery::shouldTenure(gc::Cell* cell) { MOZ_ASSERT(semispaceEnabled()); MOZ_ASSERT(inCollectedRegion(cell)); @@ -39,7 +108,7 @@ inline bool js::Nursery::shouldTenure(gc::Cell* cell) { return offset <= tenureThreshold_; } -inline bool js::Nursery::inCollectedRegion(gc::Cell* cell) const { +inline bool js::Nursery::inCollectedRegion(const gc::Cell* cell) const { return gc::InCollectedNurseryRegion(cell); } @@ -235,17 +304,38 @@ namespace js { // instead. template -static inline T* AllocateCellBuffer(Nursery& nursery, gc::Cell* cell, - uint32_t count) { +static inline T* AllocNurseryOrMallocBuffer(Nursery& nursery, gc::Cell* cell, + uint32_t count) { size_t nbytes = RoundUp(count * sizeof(T), sizeof(Value)); - return static_cast( - nursery.allocateBuffer(cell->zone(), cell, nbytes, js::MallocArena)); + return static_cast(nursery.allocNurseryOrMallocBuffer( + cell->zone(), cell, nbytes, js::MallocArena)); +} + +template +static inline T* AllocNurseryOrMallocBuffer(JSContext* cx, gc::Cell* cell, + uint32_t count) { + T* buffer = AllocNurseryOrMallocBuffer(cx->nursery(), cell, count); + if (!buffer) { + ReportOutOfMemory(cx); + return nullptr; + } + + return buffer; +} + +template +static inline T* AllocateCellBuffer(Nursery& nursery, JS::Zone* zone, + gc::Cell* cell, uint32_t count) { + MOZ_ASSERT(zone == cell->zone()); + + size_t nbytes = RoundUp(count * sizeof(T), sizeof(Value)); + return static_cast(nursery.allocateBuffer(zone, cell, nbytes)); } template static inline T* AllocateCellBuffer(JSContext* cx, gc::Cell* cell, uint32_t count) { - T* buffer = AllocateCellBuffer(cx->nursery(), cell, count); + T* buffer = AllocateCellBuffer(cx->nursery(), cx->zone(), cell, count); if (!buffer) { ReportOutOfMemory(cx); return nullptr; @@ -256,13 +346,14 @@ static inline T* AllocateCellBuffer(JSContext* cx, gc::Cell* cell, // If this returns null then the old buffer will be left alone. template -static inline T* ReallocateCellBuffer(JSContext* cx, gc::Cell* cell, - T* oldBuffer, uint32_t oldCount, - uint32_t newCount, arena_id_t arenaId) { +static inline T* ReallocNurseryOrMallocBuffer(JSContext* cx, gc::Cell* cell, + T* oldBuffer, uint32_t oldCount, + uint32_t newCount, + arena_id_t arenaId) { size_t oldBytes = RoundUp(oldCount * sizeof(T), sizeof(Value)); size_t newBytes = RoundUp(newCount * sizeof(T), sizeof(Value)); - T* buffer = static_cast(cx->nursery().reallocateBuffer( + T* buffer = static_cast(cx->nursery().reallocNurseryOrMallocBuffer( cell->zone(), cell, oldBuffer, oldBytes, newBytes, arenaId)); if (!buffer) { ReportOutOfMemory(cx); @@ -271,6 +362,34 @@ static inline T* ReallocateCellBuffer(JSContext* cx, gc::Cell* cell, return buffer; } +// If this returns null then the old buffer will be left alone. +template +static inline T* ReallocateCellBuffer(Nursery& nursery, JS::Zone* zone, + gc::Cell* cell, T* oldBuffer, + uint32_t oldCount, uint32_t newCount) { + MOZ_ASSERT(zone == cell->zone()); + + size_t oldBytes = RoundUp(oldCount * sizeof(T), sizeof(Value)); + size_t newBytes = RoundUp(newCount * sizeof(T), sizeof(Value)); + + return static_cast( + nursery.reallocateBuffer(zone, cell, oldBuffer, oldBytes, newBytes)); +} + +// If this returns null then the old buffer will be left alone. +template +static inline T* ReallocateCellBuffer(JSContext* cx, gc::Cell* cell, + T* oldBuffer, uint32_t oldCount, + uint32_t newCount) { + T* buffer = ReallocateCellBuffer(cx->nursery(), cx->zone(), cell, + oldBuffer, oldCount, newCount); + if (!buffer) { + ReportOutOfMemory(cx); + } + + return buffer; +} + } // namespace js #endif /* gc_Nursery_inl_h */ diff --git a/src/third_party/mozjs/extract/js/src/gc/Nursery.cpp b/src/third_party/mozjs/extract/js/src/gc/Nursery.cpp index 472911075b7..56f0ba6815e 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Nursery.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Nursery.cpp @@ -9,6 +9,7 @@ #include "mozilla/DebugOnly.h" #include "mozilla/IntegerPrintfMacros.h" +#include "mozilla/Maybe.h" #include "mozilla/ScopeExit.h" #include "mozilla/Sprintf.h" #include "mozilla/TimeStamp.h" @@ -19,6 +20,7 @@ #include "builtin/MapObject.h" #include "debugger/DebugAPI.h" +#include "gc/Allocator.h" #include "gc/GCInternals.h" #include "gc/GCLock.h" #include "gc/GCParallelTask.h" @@ -35,6 +37,7 @@ #include "vm/Realm.h" #include "vm/Time.h" +#include "gc/BufferAllocator-inl.h" #include "gc/Heap-inl.h" #include "gc/Marking-inl.h" #include "gc/StableCellHasher-inl.h" @@ -61,7 +64,7 @@ static constexpr size_t NurseryChunkUsableSize = struct NurseryChunk : public ChunkBase { alignas(CellAlignBytes) uint8_t data[NurseryChunkUsableSize]; - static NurseryChunk* fromChunk(TenuredChunk* chunk, ChunkKind kind, + static NurseryChunk* fromChunk(ArenaChunk* chunk, ChunkKind kind, uint8_t index); explicit NurseryChunk(JSRuntime* runtime, ChunkKind kind, uint8_t chunkIndex) @@ -87,6 +90,26 @@ static_assert(sizeof(NurseryChunk) == ChunkSize, "Nursery chunk size must match Chunk size."); static_assert(offsetof(NurseryChunk, data) == NurseryChunkHeaderSize); +class NurserySweepTask : public GCParallelTask { + SlimLinkedList allocatorsToSweep; + + public: + explicit NurserySweepTask(gc::GCRuntime* gc) + : GCParallelTask(gc, gcstats::PhaseKind::NONE) {} + + bool isEmpty(AutoLockHelperThreadState& lock) const { + return allocatorsToSweep.isEmpty(); + } + + void queueAllocatorToSweep(BufferAllocator& allocator) { + MOZ_ASSERT(isIdle()); + allocatorsToSweep.pushBack(&allocator); + } + + private: + void run(AutoLockHelperThreadState& lock) override; +}; + class NurseryDecommitTask : public GCParallelTask { public: explicit NurseryDecommitTask(gc::GCRuntime* gc); @@ -166,12 +189,23 @@ inline bool js::NurseryChunk::markPagesInUseHard(size_t endOffset) { } // static -inline js::NurseryChunk* js::NurseryChunk::fromChunk(TenuredChunk* chunk, +inline js::NurseryChunk* js::NurseryChunk::fromChunk(ArenaChunk* chunk, ChunkKind kind, uint8_t index) { return new (chunk) NurseryChunk(chunk->runtime, kind, index); } +void js::NurserySweepTask::run(AutoLockHelperThreadState& lock) { + SlimLinkedList allocators; + std::swap(allocators, allocatorsToSweep); + AutoUnlockHelperThreadState unlock(lock); + + while (!allocators.isEmpty()) { + BufferAllocator* allocator = allocators.popFirst(); + allocator->sweepForMinorCollection(); + } +} + js::NurseryDecommitTask::NurseryDecommitTask(gc::GCRuntime* gc) : GCParallelTask(gc, gcstats::PhaseKind::NONE) { // This can occur outside GCs so doesn't have a stats phase. @@ -210,8 +244,8 @@ void js::NurseryDecommitTask::run(AutoLockHelperThreadState& lock) { NurseryChunk* nurseryChunk = chunksToDecommit().popCopy(); AutoUnlockHelperThreadState unlock(lock); nurseryChunk->~NurseryChunk(); - TenuredChunk* tenuredChunk = TenuredChunk::emplace( - nurseryChunk, gc, /* allMemoryCommitted = */ false); + ArenaChunk* tenuredChunk = + ArenaChunk::emplace(nurseryChunk, gc, /* allMemoryCommitted = */ false); AutoLockGC lock(gc); gc->recycleChunk(tenuredChunk, lock); } @@ -297,6 +331,13 @@ bool js::Nursery::init(AutoLockGCBgAlloc& lock) { "JS_GC_REPORT_STATS=1\n" "\tAfter a minor GC, report how many strings were deduplicated.\n"); +#ifdef JS_GC_ZEAL + reportPromotion_ = GetBoolEnvVar( + "JS_GC_REPORT_PROMOTE", + "JS_GC_REPORT_PROMOTE=1\n" + "\tAfter a minor GC, report what kinds of things were promoted.\n"); +#endif + ReadReportPretenureEnv( "JS_GC_REPORT_PRETENURE", "JS_GC_REPORT_PRETENURE=FILTER\n" @@ -321,6 +362,11 @@ bool js::Nursery::init(AutoLockGCBgAlloc& lock) { "\twith AND. Prefixes of the keywords above are accepted.\n", &pretenuringReportFilter_); + sweepTask = MakeUnique(gc); + if (!sweepTask) { + return false; + } + decommitTask = MakeUnique(gc); if (!decommitTask) { return false; @@ -336,6 +382,8 @@ bool js::Nursery::init(AutoLockGCBgAlloc& lock) { js::Nursery::~Nursery() { disable(); } void js::Nursery::enable() { + MOZ_ASSERT(TlsContext.get()->generationalDisabled == 0); + if (isEnabled()) { return; } @@ -425,8 +473,11 @@ void js::Nursery::disable() { return; } - // Free all chunks. + // Wait for any background tasks. + sweepTask->join(); decommitTask->join(); + + // Free all chunks. freeChunksFrom(toSpace, 0); freeChunksFrom(fromSpace, 0); decommitTask->runFromMainThread(); @@ -710,8 +761,8 @@ bool Nursery::moveToNextChunk() { return true; } -std::tuple js::Nursery::allocateBuffer(Zone* zone, size_t nbytes, - arena_id_t arenaId) { +std::tuple js::Nursery::allocNurseryOrMallocBuffer( + Zone* zone, size_t nbytes, arena_id_t arenaId) { MOZ_ASSERT(nbytes > 0); MOZ_ASSERT(nbytes <= SIZE_MAX - gc::CellAlignBytes); nbytes = RoundUp(nbytes, gc::CellAlignBytes); @@ -727,8 +778,38 @@ std::tuple js::Nursery::allocateBuffer(Zone* zone, size_t nbytes, return {buffer, bool(buffer)}; } -void* js::Nursery::allocateBuffer(Zone* zone, Cell* owner, size_t nbytes, - arena_id_t arenaId) { +std::tuple js::Nursery::allocateBuffer(Zone* zone, size_t nbytes) { + MOZ_ASSERT(nbytes > 0); + MOZ_ASSERT(nbytes <= SIZE_MAX - gc::CellAlignBytes); + nbytes = RoundUp(nbytes, gc::CellAlignBytes); + + if (nbytes <= MaxNurseryBufferSize) { + void* buffer = allocate(nbytes); + if (buffer) { + return {buffer, false}; + } + } + + void* buffer = AllocBuffer(zone, nbytes, true); + return {buffer, bool(buffer)}; +} + +void* js::Nursery::tryAllocateNurseryBuffer(JS::Zone* zone, size_t nbytes, + arena_id_t arenaId) { + MOZ_ASSERT(nbytes > 0); + MOZ_ASSERT(nbytes <= SIZE_MAX - gc::CellAlignBytes); + nbytes = RoundUp(nbytes, gc::CellAlignBytes); + + if (nbytes <= MaxNurseryBufferSize) { + return allocate(nbytes); + } + + return nullptr; +} + +void* js::Nursery::allocNurseryOrMallocBuffer(Zone* zone, Cell* owner, + size_t nbytes, + arena_id_t arenaId) { MOZ_ASSERT(owner); MOZ_ASSERT(nbytes > 0); @@ -736,7 +817,7 @@ void* js::Nursery::allocateBuffer(Zone* zone, Cell* owner, size_t nbytes, return zone->pod_arena_malloc(arenaId, nbytes); } - auto [buffer, isMalloced] = allocateBuffer(zone, nbytes, arenaId); + auto [buffer, isMalloced] = allocNurseryOrMallocBuffer(zone, nbytes, arenaId); if (isMalloced && !registerMallocedBuffer(buffer, nbytes)) { js_free(buffer); return nullptr; @@ -744,18 +825,20 @@ void* js::Nursery::allocateBuffer(Zone* zone, Cell* owner, size_t nbytes, return buffer; } -void* js::Nursery::allocateBufferSameLocation(Cell* owner, size_t nbytes, - arena_id_t arenaId) { +void* js::Nursery::allocateBuffer(Zone* zone, Cell* owner, size_t nbytes) { MOZ_ASSERT(owner); + MOZ_ASSERT(zone == owner->zone()); MOZ_ASSERT(nbytes > 0); - MOZ_ASSERT(nbytes <= MaxNurseryBufferSize); if (!IsInsideNursery(owner)) { - return owner->asTenured().zone()->pod_arena_malloc(arenaId, - nbytes); + return AllocBuffer(zone, nbytes, false); } - return allocate(nbytes); + auto [buffer, isExternal] = allocateBuffer(zone, nbytes); + if (isExternal) { + registerBuffer(buffer, nbytes); + } + return buffer; } std::tuple js::Nursery::allocateZeroedBuffer(Zone* zone, @@ -792,9 +875,11 @@ void* js::Nursery::allocateZeroedBuffer(Cell* owner, size_t nbytes, return buffer; } -void* js::Nursery::reallocateBuffer(Zone* zone, Cell* cell, void* oldBuffer, - size_t oldBytes, size_t newBytes, - arena_id_t arena) { +void* js::Nursery::reallocNurseryOrMallocBuffer(Zone* zone, Cell* cell, + void* oldBuffer, + size_t oldBytes, + size_t newBytes, + arena_id_t arena) { if (!IsInsideNursery(cell)) { MOZ_ASSERT(!isInside(oldBuffer)); return zone->pod_realloc((uint8_t*)oldBuffer, oldBytes, newBytes); @@ -820,7 +905,42 @@ void* js::Nursery::reallocateBuffer(Zone* zone, Cell* cell, void* oldBuffer, return oldBuffer; } - auto newBuffer = allocateBuffer(zone, cell, newBytes, js::MallocArena); + auto newBuffer = + allocNurseryOrMallocBuffer(zone, cell, newBytes, js::MallocArena); + if (newBuffer) { + PodCopy((uint8_t*)newBuffer, (uint8_t*)oldBuffer, oldBytes); + } + return newBuffer; +} + +void* js::Nursery::reallocateBuffer(Zone* zone, Cell* cell, void* oldBuffer, + size_t oldBytes, size_t newBytes) { + if (!IsInsideNursery(cell)) { + MOZ_ASSERT(IsBufferAlloc(oldBuffer)); + MOZ_ASSERT(!IsNurseryOwned(zone, oldBuffer)); + return ReallocBuffer(zone, oldBuffer, newBytes, false); + } + + if (IsBufferAlloc(oldBuffer)) { + MOZ_ASSERT(IsNurseryOwned(zone, oldBuffer)); + MOZ_ASSERT(toSpace.mallocedBufferBytes >= oldBytes); + + void* newBuffer = ReallocBuffer(zone, oldBuffer, newBytes, true); + if (!newBuffer) { + return nullptr; + } + + toSpace.mallocedBufferBytes -= oldBytes; + toSpace.mallocedBufferBytes += newBytes; + return newBuffer; + } + + // The nursery cannot make use of the returned slots data. + if (newBytes < oldBytes) { + return oldBuffer; + } + + auto newBuffer = allocateBuffer(zone, cell, newBytes); if (newBuffer) { PodCopy((uint8_t*)newBuffer, (uint8_t*)oldBuffer, oldBytes); } @@ -942,6 +1062,10 @@ void js::Nursery::renderProfileJSON(JSONPrinter& json) const { return; } + // The profiler data uses the term 'tenured' for compatibility with the + // existing data format, although 'promoted' would be more accurate given + // support for semispace nursery. + json.beginObject(); json.property("status", "complete"); @@ -950,11 +1074,11 @@ void js::Nursery::renderProfileJSON(JSONPrinter& json) const { json.property("bytes_tenured", previousGC.tenuredBytes); json.property("cells_tenured", previousGC.tenuredCells); json.property("strings_tenured", - stats().getStat(gcstats::STAT_STRINGS_TENURED)); + stats().getStat(gcstats::STAT_STRINGS_PROMOTED)); json.property("strings_deduplicated", stats().getStat(gcstats::STAT_STRINGS_DEDUPLICATED)); json.property("bigints_tenured", - stats().getStat(gcstats::STAT_BIGINTS_TENURED)); + stats().getStat(gcstats::STAT_BIGINTS_PROMOTED)); json.property("bytes_used", previousGC.nurseryUsedBytes); json.property("cur_capacity", previousGC.nurseryCapacity); const size_t newCapacity = capacity(); @@ -968,6 +1092,14 @@ void js::Nursery::renderProfileJSON(JSONPrinter& json) const { json.property("chunk_alloc_us", timeInChunkAlloc_, json.MICROSECONDS); } + // This calculation includes the whole collection time, not just the time + // spent promoting. + double totalTime = profileDurations_[ProfileKey::Total].ToSeconds(); + if (totalTime > 0.0) { + double tenuredAllocRate = double(previousGC.tenuredBytes) / totalTime; + json.property("tenured_allocation_rate", size_t(tenuredAllocRate)); + } + // These counters only contain consistent data if the profiler is enabled, // and then there's no guarentee. if (runtime()->geckoProfiler().enabled()) { @@ -1260,6 +1392,12 @@ void js::Nursery::collect(JS::GCOptions options, JS::GCReason reason) { stats().beginNurseryCollection(); gcprobes::MinorGCStart(); + if (stats().bufferAllocStatsEnabled() && runtime()->isMainRuntime()) { + stats().maybePrintProfileHeaders(); + BufferAllocator::printStats(gc, gc->stats().creationTime(), false, + gc->stats().profileFile()); + } + gc->callNurseryCollectionCallbacks( JS::GCNurseryProgress::GC_NURSERY_COLLECTION_START, reason); @@ -1275,6 +1413,12 @@ void js::Nursery::collect(JS::GCOptions options, JS::GCReason reason) { previousGC.tenuredCells = 0; tenuredEverything = true; + // Wait for any previous buffer sweeping to finish. This happens even if the + // nursery is empty because we track whether this has happened by checking the + // minor GC number, which is incremented regardless. See the call to + // joinSweepTask in GCRuntime::endSweepingSweepGroup. + joinSweepTask(); + // If it isn't empty, it will call doCollection, and possibly after that // isEmpty() will become true, so use another variable to keep track of the // old empty state. @@ -1495,6 +1639,12 @@ js::Nursery::CollectionResult js::Nursery::doCollection(AutoGCSession& session, AutoDisableProxyCheck disableStrictProxyChecking; mozilla::DebugOnly oomUnsafeRegion; +#ifdef JS_GC_ZEAL + if (gc->hasZealMode(ZealMode::CheckHeapBeforeMinorGC)) { + gc->checkHeapBeforeMinorGC(session); + } +#endif + // Swap nursery spaces. swapSpaces(); MOZ_ASSERT(toSpace.isEmpty()); @@ -1503,11 +1653,24 @@ js::Nursery::CollectionResult js::Nursery::doCollection(AutoGCSession& session, poisonAndInitCurrentChunk(); } - clearMapAndSetNurseryRanges(); + clearMapAndSetNurseryIterators(); + + MOZ_ASSERT(sweepTask->isIdle()); + { + BufferAllocator::MaybeLock lock; + for (ZonesIter zone(runtime(), WithAtoms); !zone.done(); zone.next()) { + zone->bufferAllocator.startMinorCollection(lock); + } + } // Move objects pointed to by roots from the nursery to the major heap. tenuredEverything = shouldTenureEverything(reason); TenuringTracer mover(rt, this, tenuredEverything); +#ifdef JS_GC_ZEAL + if (reportPromotion_) { + mover.initPromotionReport(); + } +#endif // Trace everything considered as a root by a minor GC. traceRoots(session, mover); @@ -1528,6 +1691,14 @@ js::Nursery::CollectionResult js::Nursery::doCollection(AutoGCSession& session, mover.collectToStringFixedPoint(); endProfile(ProfileKey::CollectToStrFP); +#ifdef JS_GC_ZEAL + if (reportPromotion_ && options != JS::GCOptions::Shutdown) { + JSContext* cx = runtime()->mainContextFromOwnThread(); + JS::AutoAssertNoGC nogc(cx); + mover.printPromotionReport(cx, reason, nogc); + } +#endif + // Sweep to update any pointers to nursery objects that have now been // tenured. startProfile(ProfileKey::Sweep); @@ -1544,9 +1715,10 @@ js::Nursery::CollectionResult js::Nursery::doCollection(AutoGCSession& session, gc->callObjectsTenuredCallback(); endProfile(ProfileKey::ObjectsTenuredCallback); - // Sweep. + // Sweep malloced buffers. startProfile(ProfileKey::FreeMallocedBuffers); - gc->queueBuffersForFreeAfterMinorGC(fromSpace.mallocedBuffers); + gc->queueBuffersForFreeAfterMinorGC(fromSpace.mallocedBuffers, + stringBuffersToReleaseAfterMinorGC_); fromSpace.mallocedBufferBytes = 0; endProfile(ProfileKey::FreeMallocedBuffers); @@ -1566,16 +1738,21 @@ js::Nursery::CollectionResult js::Nursery::doCollection(AutoGCSession& session, runtime()->caches().stringToAtomCache.purge(); endProfile(ProfileKey::PurgeStringToAtomCache); +#ifdef JS_GC_ZEAL // Make sure hashtables have been updated after the collection. startProfile(ProfileKey::CheckHashTables); -#ifdef JS_GC_ZEAL if (gc->hasZealMode(ZealMode::CheckHashTablesOnMinorGC)) { runtime()->caches().checkEvalCacheAfterMinorGC(); gc->checkHashTablesAfterMovingGC(); } -#endif endProfile(ProfileKey::CheckHashTables); + // Check for missing post barriers. + if (gc->hasZealMode(ZealMode::VerifierPost)) { + gc->verifyPostBarriers(session); + } +#endif + if (semispaceEnabled_) { // On the next collection, tenure everything before |tenureThreshold_|. tenureThreshold_ = toSpace.offsetFromExclusiveAddress(position()); @@ -1625,8 +1802,6 @@ void js::Nursery::traceRoots(AutoGCSession& session, TenuringTracer& mover) { sb.traceWholeCells(mover); endProfile(ProfileKey::TraceWholeCells); - cellsToSweep = sb.releaseCellSweepSet(); - startProfile(ProfileKey::TraceValues); sb.traceValues(mover); endProfile(ProfileKey::TraceValues); @@ -1678,8 +1853,8 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason, size_t zonesWhereStringsDisabled = 0; size_t zonesWhereBigIntsDisabled = 0; - uint32_t numStringsTenured = 0; - uint32_t numBigIntsTenured = 0; + uint32_t numStringsPromoted = 0; + uint32_t numBigIntsPromoted = 0; for (ZonesIter zone(gc, SkipAtoms); !zone.done(); zone.next()) { bool disableNurseryStrings = zone->allocNurseryStrings() && @@ -1702,10 +1877,13 @@ size_t js::Nursery::doPretenuring(JSRuntime* rt, JS::GCReason reason, } updateAllocFlagsForZone(zone); } + + numStringsPromoted += zone->nurseryPromotedCount(JS::TraceKind::String); + numBigIntsPromoted += zone->nurseryPromotedCount(JS::TraceKind::BigInt); } - stats().setStat(gcstats::STAT_STRINGS_TENURED, numStringsTenured); - stats().setStat(gcstats::STAT_BIGINTS_TENURED, numBigIntsTenured); + stats().setStat(gcstats::STAT_STRINGS_PROMOTED, numStringsPromoted); + stats().setStat(gcstats::STAT_BIGINTS_PROMOTED, numBigIntsPromoted); if (reportPretenuring() && zonesWhereStringsDisabled) { fprintf(stderr, @@ -1730,14 +1908,18 @@ bool js::Nursery::registerMallocedBuffer(void* buffer, size_t nbytes) { return false; } - toSpace.mallocedBufferBytes += nbytes; - if (MOZ_UNLIKELY(toSpace.mallocedBufferBytes > capacity() * 8)) { - requestMinorGC(JS::GCReason::NURSERY_MALLOC_BUFFERS); - } - + addMallocedBufferBytes(nbytes); return true; } +void js::Nursery::registerBuffer(void* buffer, size_t nbytes) { + MOZ_ASSERT(buffer); + MOZ_ASSERT(nbytes > 0); + MOZ_ASSERT(!isInside(buffer)); + + addMallocedBufferBytes(nbytes); +} + /* * Several things may need to happen when a nursery allocated cell with an * external buffer is promoted: @@ -1747,14 +1929,16 @@ bool js::Nursery::registerMallocedBuffer(void* buffer, size_t nbytes) { * - memory accounting for the buffer needs to be updated */ Nursery::WasBufferMoved js::Nursery::maybeMoveRawBufferOnPromotion( - void** bufferp, gc::Cell* owner, size_t nbytes, MemoryUse use, - arena_id_t arena) { + void** bufferp, gc::Cell* owner, size_t bytesUsed, size_t bytesCapacity, + MemoryUse use, arena_id_t arena) { + MOZ_ASSERT(bytesUsed <= bytesCapacity); + void* buffer = *bufferp; if (!isInside(buffer)) { // This is a malloced buffer. Remove it from the nursery's previous list of // buffers so we don't free it. removeMallocedBufferDuringMinorGC(buffer); - trackMallocedBufferOnPromotion(buffer, owner, nbytes, use); + trackMallocedBufferOnPromotion(buffer, owner, bytesCapacity, use); return BufferNotMoved; } @@ -1762,14 +1946,14 @@ Nursery::WasBufferMoved js::Nursery::maybeMoveRawBufferOnPromotion( AutoEnterOOMUnsafeRegion oomUnsafe; Zone* zone = owner->zone(); - void* movedBuffer = zone->pod_arena_malloc(arena, nbytes); + void* movedBuffer = zone->pod_arena_malloc(arena, bytesCapacity); if (!movedBuffer) { - oomUnsafe.crash("Nursery::updateBufferOnPromotion"); + oomUnsafe.crash("Nursery::maybeMoveRawNurseryOrMallocBufferOnPromotion"); } - memcpy(movedBuffer, buffer, nbytes); + memcpy(movedBuffer, buffer, bytesUsed); - trackMallocedBufferOnPromotion(movedBuffer, owner, nbytes, use); + trackMallocedBufferOnPromotion(movedBuffer, owner, bytesCapacity, use); *bufferp = movedBuffer; return BufferMoved; @@ -1811,6 +1995,58 @@ void js::Nursery::trackTrailerOnPromotion(void* buffer, gc::Cell* owner, } } +Nursery::WasBufferMoved js::Nursery::maybeMoveRawBufferOnPromotion( + void** bufferp, gc::Cell* owner, size_t nbytes) { + bool nurseryOwned = IsInsideNursery(owner); + + void* buffer = *bufferp; + if (IsBufferAlloc(buffer)) { + // This is an external buffer allocation owned by a nursery GC thing. + Zone* zone = owner->zone(); + MOZ_ASSERT(IsNurseryOwned(zone, buffer)); + bool ownerWasTenured = !nurseryOwned; + zone->bufferAllocator.markNurseryOwnedAlloc(buffer, ownerWasTenured); + if (nurseryOwned) { + registerBuffer(buffer, nbytes); + } + return BufferNotMoved; + } + + // Copy the nursery-allocated buffer into a new allocation. + + // todo: only necessary for copying inline elements data where we didn't + // calculate this on allocation. + size_t dstBytes = GetGoodAllocSize(nbytes); + + AutoEnterOOMUnsafeRegion oomUnsafe; + void* movedBuffer = AllocBufferInGC(owner->zone(), dstBytes, nurseryOwned); + if (!movedBuffer) { + oomUnsafe.crash("Nursery::maybeMoveRawBufferOnPromotion"); + } + + memcpy(movedBuffer, buffer, nbytes); + + if (nurseryOwned) { + registerBuffer(movedBuffer, nbytes); + } + + *bufferp = movedBuffer; + return BufferMoved; +} + +void js::Nursery::sweepBuffers() { + for (ZonesIter zone(runtime(), WithAtoms); !zone.done(); zone.next()) { + if (zone->bufferAllocator.startMinorSweeping()) { + sweepTask->queueAllocatorToSweep(zone->bufferAllocator); + } + } + + AutoLockHelperThreadState lock; + if (!sweepTask->isEmpty(lock)) { + sweepTask->startOrRunIfIdle(lock); + } +} + void Nursery::requestMinorGC(JS::GCReason reason) { JS::HeapState heapState = runtime()->heapState(); #ifdef DEBUG @@ -1874,15 +2110,86 @@ size_t Nursery::sizeOfMallocedBuffers( total += mallocSizeOf(r.front()); } total += toSpace.mallocedBuffers.shallowSizeOfExcludingThis(mallocSizeOf); + + for (AllZonesIter zone(runtime()); !zone.done(); zone.next()) { + total += zone->bufferAllocator.getSizeOfNurseryBuffers(); + } + return total; } +void js::Nursery::sweepStringsWithBuffer() { + // Add StringBuffers to stringBuffersToReleaseAfterMinorGC_. Strings we + // tenured must have an additional refcount at this point. + + MOZ_ASSERT(stringBuffersToReleaseAfterMinorGC_.empty()); + + auto sweep = [&](JSLinearString* str, + mozilla::StringBuffer* buffer) -> JSLinearString* { + MOZ_ASSERT(inCollectedRegion(str)); + + if (!IsForwarded(str)) { + MOZ_ASSERT(str->hasStringBuffer() || str->isAtomRef()); + MOZ_ASSERT_IF(str->hasStringBuffer(), str->stringBuffer() == buffer); + if (!stringBuffersToReleaseAfterMinorGC_.append(buffer)) { + // Release on the main thread on OOM. + buffer->Release(); + } + return nullptr; + } + + JSLinearString* dst = Forwarded(str); + if (!IsInsideNursery(dst)) { + MOZ_ASSERT_IF(dst->hasStringBuffer() && dst->stringBuffer() == buffer, + buffer->RefCount() > 1); + if (!stringBuffersToReleaseAfterMinorGC_.append(buffer)) { + // Release on the main thread on OOM. + buffer->Release(); + } + return nullptr; + } + + return dst; + }; + + stringBuffers_.mutableEraseIf([&](StringAndBuffer& entry) { + if (JSLinearString* dst = sweep(entry.first, entry.second)) { + entry.first = dst; + // See comment in Nursery::addStringBuffer. + if (!entry.second->HasMultipleReferences()) { + addMallocedBufferBytes(entry.second->AllocationSize()); + } + return false; + } + return true; + }); + + AutoEnterOOMUnsafeRegion oomUnsafe; + + ExtensibleStringBuffers buffers(std::move(extensibleStringBuffers_)); + MOZ_ASSERT(extensibleStringBuffers_.empty()); + + for (ExtensibleStringBuffers::Enum e(buffers); !e.empty(); e.popFront()) { + if (JSLinearString* dst = sweep(e.front().key(), e.front().value())) { + if (!extensibleStringBuffers_.putNew(dst, e.front().value())) { + oomUnsafe.crash("sweepStringsWithBuffer"); + } + // Ensure mallocedBufferBytes includes the buffer size for + // removeExtensibleStringBuffer. + addMallocedBufferBytes(e.front().value()->AllocationSize()); + } + } +} + void js::Nursery::sweep() { // It's important that the context's GCUse is not Finalizing at this point, // otherwise we will miscount memory attached to nursery objects with // CellAllocPolicy. AutoSetThreadIsSweeping setThreadSweeping(runtime()->gcContext()); + // Start sweeping buffers off-thread as soon as possible. + sweepBuffers(); + MinorSweepingTracer trc(runtime()); // Sweep unique IDs first before we sweep any tables that may be keyed based @@ -1905,28 +2212,17 @@ void js::Nursery::sweep() { return false; }); + sweepStringsWithBuffer(); + for (ZonesIter zone(runtime(), SkipAtoms); !zone.done(); zone.next()) { zone->sweepAfterMinorGC(&trc); } sweepMapAndSetObjects(); - cellsToSweep.sweep(); - CellSweepSet empty; - std::swap(cellsToSweep, empty); runtime()->caches().sweepAfterMinorGC(&trc); } -void gc::CellSweepSet::sweep() { - if (head_) { - head_->sweepDependentStrings(); - head_ = nullptr; - } - if (storage_) { - storage_->freeAll(); - } -} - void js::Nursery::clear() { fromSpace.clear(this); MOZ_ASSERT(fromSpace.isEmpty()); @@ -2018,13 +2314,14 @@ bool js::Nursery::allocateNextChunk(AutoLockGCBgAlloc& lock) { return false; } - TenuredChunk* toSpaceChunk = gc->getOrAllocChunk(lock); + ArenaChunk* toSpaceChunk = gc->takeOrAllocChunk(StallAndRetry::No, lock); if (!toSpaceChunk) { return false; } - TenuredChunk* fromSpaceChunk = nullptr; - if (semispaceEnabled_ && !(fromSpaceChunk = gc->getOrAllocChunk(lock))) { + ArenaChunk* fromSpaceChunk = nullptr; + if (semispaceEnabled_ && + !(fromSpaceChunk = gc->takeOrAllocChunk(StallAndRetry::No, lock))) { gc->recycleChunk(toSpaceChunk, lock); return false; } @@ -2065,8 +2362,8 @@ void js::Nursery::maybeResizeNursery(JS::GCOptions options, decommitTask->join(); - size_t newCapacity = mozilla::Clamp(targetSize(options, reason), - minSpaceSize(), maxSpaceSize()); + size_t newCapacity = + std::clamp(targetSize(options, reason), minSpaceSize(), maxSpaceSize()); MOZ_ASSERT(roundSize(newCapacity) == newCapacity); MOZ_ASSERT(newCapacity >= SystemPageSize()); @@ -2161,9 +2458,10 @@ size_t js::Nursery::targetSize(JS::GCOptions options, JS::GCReason reason) { // Debug builds are so much slower and more unpredictable that doing this // would cause very different nursery behaviour to an equivalent release // build. - static const double MaxTimeGoalMs = 4.0; - if (!gc->isInPageLoad() && !js::SupportDifferentialTesting()) { - double timeGrowth = MaxTimeGoalMs / collectorTime.ToMilliseconds(); + double maxTimeGoalMS = tunables().nurseryMaxTimeGoalMS().ToMilliseconds(); + if (!gc->isInPageLoad() && maxTimeGoalMS != 0.0 && + !js::SupportDifferentialTesting()) { + double timeGrowth = maxTimeGoalMS / collectorTime.ToMilliseconds(); growthFactor = std::min(growthFactor, timeGrowth); } #endif @@ -2394,79 +2692,59 @@ bool js::Nursery::isSubChunkMode() const { return capacity() <= NurseryChunkUsableSize; } -void js::Nursery::clearMapAndSetNurseryRanges() { - // Clears the lists of nursery ranges used by map and set iterators. These - // lists are cleared at the start of minor GC and rebuilt when iterators are +void js::Nursery::clearMapAndSetNurseryIterators() { + // Clears the lists of nursery iterators for all Map/Set objects. These lists + // are cleared at the start of minor GC and rebuilt when iterators are // promoted during minor GC. - for (auto* map : mapsWithNurseryMemory_) { - map->clearNurseryRangesBeforeMinorGC(); + for (auto* map : mapsWithNurseryIterators_) { + map->clearNurseryIteratorsBeforeMinorGC(); } - for (auto* set : setsWithNurseryMemory_) { - set->clearNurseryRangesBeforeMinorGC(); + for (auto* set : setsWithNurseryIterators_) { + set->clearNurseryIteratorsBeforeMinorGC(); } } void js::Nursery::sweepMapAndSetObjects() { // This processes all Map and Set objects that are known to have associated - // nursery memory (either they are nursery allocated themselves or they have - // iterator objects that are nursery allocated). + // iterator objects that are nursery allocated. // // These objects may die and be finalized or if not their internal state and // memory tracking are updated. // // Finally the lists themselves are rebuilt so as to remove objects that are - // no longer associated with nursery memory (either because they died or - // because the nursery object was promoted to the tenured heap). + // no longer associated with nursery iterators (because all iterators died or + // were promoted to the tenured heap). auto* gcx = runtime()->gcContext(); AutoEnterOOMUnsafeRegion oomUnsafe; MapObjectVector maps; - std::swap(mapsWithNurseryMemory_, maps); + std::swap(mapsWithNurseryIterators_, maps); for (auto* mapobj : maps) { mapobj = MapObject::sweepAfterMinorGC(gcx, mapobj); if (mapobj) { - if (!mapsWithNurseryMemory_.append(mapobj)) { + if (!mapsWithNurseryIterators_.append(mapobj)) { oomUnsafe.crash("sweepAfterMinorGC"); } } } SetObjectVector sets; - std::swap(setsWithNurseryMemory_, sets); + std::swap(setsWithNurseryIterators_, sets); for (auto* setobj : sets) { setobj = SetObject::sweepAfterMinorGC(gcx, setobj); if (setobj) { - if (!setsWithNurseryMemory_.append(setobj)) { + if (!setsWithNurseryIterators_.append(setobj)) { oomUnsafe.crash("sweepAfterMinorGC"); } } } } +void js::Nursery::joinSweepTask() { sweepTask->join(); } void js::Nursery::joinDecommitTask() { decommitTask->join(); } -JS_PUBLIC_API void JS::EnableNurseryStrings(JSContext* cx) { - AutoEmptyNursery empty(cx); - ReleaseAllJITCode(cx->gcContext()); - cx->runtime()->gc.nursery().enableStrings(); -} - -JS_PUBLIC_API void JS::DisableNurseryStrings(JSContext* cx) { - AutoEmptyNursery empty(cx); - ReleaseAllJITCode(cx->gcContext()); - cx->runtime()->gc.nursery().disableStrings(); -} - -JS_PUBLIC_API void JS::EnableNurseryBigInts(JSContext* cx) { - AutoEmptyNursery empty(cx); - ReleaseAllJITCode(cx->gcContext()); - cx->runtime()->gc.nursery().enableBigInts(); -} - -JS_PUBLIC_API void JS::DisableNurseryBigInts(JSContext* cx) { - AutoEmptyNursery empty(cx); - ReleaseAllJITCode(cx->gcContext()); - cx->runtime()->gc.nursery().disableBigInts(); -} +#ifdef DEBUG +bool js::Nursery::sweepTaskIsIdle() { return sweepTask->isIdle(); } +#endif diff --git a/src/third_party/mozjs/extract/js/src/gc/Nursery.h b/src/third_party/mozjs/extract/js/src/gc/Nursery.h index 89cdd8f86b1..beb8b9a3e08 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Nursery.h +++ b/src/third_party/mozjs/extract/js/src/gc/Nursery.h @@ -14,6 +14,8 @@ #include #include "ds/LifoAlloc.h" +#include "ds/SlimLinkedList.h" +#include "gc/Allocator.h" #include "gc/GCEnum.h" #include "gc/GCProbes.h" #include "gc/Heap.h" @@ -56,6 +58,10 @@ template class SharedMem; +namespace mozilla { +class StringBuffer; +}; + namespace js { struct StringStats; @@ -65,27 +71,20 @@ struct NurseryChunk; class HeapSlot; class JSONPrinter; class MapObject; +class NurseryDecommitTask; +class NurserySweepTask; class SetObject; class JS_PUBLIC_API Sprinter; namespace gc { + class AutoGCSession; struct Cell; class GCSchedulingTunables; +struct LargeBuffer; class StoreBuffer; class TenuringTracer; -// A set of cells that need to be swept at the end of a minor GC, -// represented as a linked list of ArenaCellSet structs extracted from a -// WholeCellBuffer. -struct CellSweepSet { - UniquePtr storage_; - ArenaCellSet* head_ = nullptr; - - // Fixup the tenured dependent strings stored in the ArenaCellSet list. - void sweep(); -}; - } // namespace gc class Nursery { @@ -144,19 +143,21 @@ class Nursery { // needed. Returns false in |isMalloced| if the allocation fails. // // Use the following API if the owning Cell is already known. - std::tuple allocateBuffer(JS::Zone* zone, size_t nbytes, - arena_id_t arenaId); + std::tuple allocNurseryOrMallocBuffer(JS::Zone* zone, + size_t nbytes, + arena_id_t arenaId); + std::tuple allocateBuffer(JS::Zone* zone, size_t nbytes); + + // Like allocNurseryOrMallocBuffer, but returns nullptr if the buffer can't + // be allocated in the nursery. + void* tryAllocateNurseryBuffer(JS::Zone* zone, size_t nbytes, + arena_id_t arenaId); // Allocate a buffer for a given Cell, using the nursery if possible and // owner is in the nursery. - void* allocateBuffer(JS::Zone* zone, gc::Cell* owner, size_t nbytes, - arena_id_t arenaId); - - // Allocate a buffer for a given Cell, always using the nursery if |owner| is - // in the nursery. The requested size must be less than or equal to - // MaxNurseryBufferSize. - void* allocateBufferSameLocation(gc::Cell* owner, size_t nbytes, - arena_id_t arenaId); + void* allocNurseryOrMallocBuffer(JS::Zone* zone, gc::Cell* owner, + size_t nbytes, arena_id_t arenaId); + void* allocateBuffer(JS::Zone* zone, gc::Cell* owner, size_t nbytes); // Allocate a zero-initialized buffer for a given zone, using the nursery if // possible. If the buffer isn't allocated in the nursery, the given arena is @@ -170,9 +171,14 @@ class Nursery { // the nursery, the given arena is used. void* allocateZeroedBuffer(gc::Cell* owner, size_t nbytes, arena_id_t arena); + // Resize an existing buffer. + void* reallocNurseryOrMallocBuffer(JS::Zone* zone, gc::Cell* cell, + void* oldBuffer, size_t oldBytes, + size_t newBytes, arena_id_t arena); + // Resize an existing buffer. void* reallocateBuffer(JS::Zone* zone, gc::Cell* cell, void* oldBuffer, - size_t oldBytes, size_t newBytes, arena_id_t arena); + size_t oldBytes, size_t newBytes); // Free an object buffer. void freeBuffer(void* buffer, size_t nbytes); @@ -199,46 +205,53 @@ class Nursery { // Handle an external buffer when a cell is promoted. Updates the pointer to // the (possibly moved) buffer and returns whether it was moved. + // bytesUsed can be less than bytesCapacity if not all bytes need to be copied + // when the buffer is moved. enum WasBufferMoved : bool { BufferNotMoved = false, BufferMoved = true }; WasBufferMoved maybeMoveRawBufferOnPromotion(void** bufferp, gc::Cell* owner, - size_t nbytes, MemoryUse use, - arena_id_t arena); + size_t bytesUsed, + size_t bytesCapacity, + MemoryUse use, arena_id_t arena); template WasBufferMoved maybeMoveBufferOnPromotion(T** bufferp, gc::Cell* owner, - size_t nbytes, MemoryUse use, + size_t bytesUsed, + size_t bytesCapacity, MemoryUse use, arena_id_t arena) { return maybeMoveRawBufferOnPromotion(reinterpret_cast(bufferp), - owner, nbytes, use, arena); + owner, bytesUsed, bytesCapacity, use, + arena); } template + WasBufferMoved maybeMoveNurseryOrMallocBufferOnPromotion(T** bufferp, + gc::Cell* owner, + size_t nbytes, + MemoryUse use) { + return maybeMoveBufferOnPromotion(bufferp, owner, nbytes, nbytes, use, + MallocArena); + } + + WasBufferMoved maybeMoveRawBufferOnPromotion(void** bufferp, gc::Cell* owner, + size_t nbytes); + template WasBufferMoved maybeMoveBufferOnPromotion(T** bufferp, gc::Cell* owner, - size_t nbytes, MemoryUse use) { - return maybeMoveBufferOnPromotion(bufferp, owner, nbytes, use, MallocArena); + size_t nbytes) { + return maybeMoveRawBufferOnPromotion(reinterpret_cast(bufferp), + owner, nbytes); } // Register a malloced buffer that is held by a nursery object, which // should be freed at the end of a minor GC. Buffers are unregistered when // their owning objects are tenured. [[nodiscard]] bool registerMallocedBuffer(void* buffer, size_t nbytes); + void registerBuffer(void* buffer, size_t nbytes); // Mark a malloced buffer as no longer needing to be freed. - void removeMallocedBuffer(void* buffer, size_t nbytes) { - MOZ_ASSERT(!JS::RuntimeHeapIsMinorCollecting()); - MOZ_ASSERT(toSpace.mallocedBuffers.has(buffer)); - MOZ_ASSERT(nbytes > 0); - MOZ_ASSERT(toSpace.mallocedBufferBytes >= nbytes); - toSpace.mallocedBuffers.remove(buffer); - toSpace.mallocedBufferBytes -= nbytes; - } + inline void removeMallocedBuffer(void* buffer, size_t nbytes); // Mark a malloced buffer as no longer needing to be freed during minor // GC. There's no need to account for the size here since all remaining // buffers will soon be freed. - void removeMallocedBufferDuringMinorGC(void* buffer) { - MOZ_ASSERT(JS::RuntimeHeapIsMinorCollecting()); - MOZ_ASSERT(fromSpace.mallocedBuffers.has(buffer)); - fromSpace.mallocedBuffers.remove(buffer); - } + inline void removeMallocedBufferDuringMinorGC(void* buffer); [[nodiscard]] bool addedUniqueIdToCell(gc::Cell* cell) { MOZ_ASSERT(IsInsideNursery(cell)); @@ -246,6 +259,14 @@ class Nursery { return cellsWithUid_.append(cell); } + [[nodiscard]] inline bool addStringBuffer(JSLinearString* s); + + [[nodiscard]] inline bool addExtensibleStringBuffer( + JSLinearString* s, mozilla::StringBuffer* buffer, + bool updateMallocBytes = true); + inline void removeExtensibleStringBuffer(JSLinearString* s, + bool updateMallocBytes = true); + size_t sizeOfMallocedBuffers(mozilla::MallocSizeOf mallocSizeOf) const; // Wasm "trailer" (C++-heap-allocated) blocks. @@ -316,19 +337,24 @@ class Nursery { bool enableProfiling() const { return enableProfiling_; } - bool addMapWithNurseryMemory(MapObject* obj) { - MOZ_ASSERT_IF(!mapsWithNurseryMemory_.empty(), - mapsWithNurseryMemory_.back() != obj); - return mapsWithNurseryMemory_.append(obj); + bool addMapWithNurseryIterators(MapObject* obj) { + MOZ_ASSERT_IF(!mapsWithNurseryIterators_.empty(), + mapsWithNurseryIterators_.back() != obj); + return mapsWithNurseryIterators_.append(obj); } - bool addSetWithNurseryMemory(SetObject* obj) { - MOZ_ASSERT_IF(!setsWithNurseryMemory_.empty(), - setsWithNurseryMemory_.back() != obj); - return setsWithNurseryMemory_.append(obj); + bool addSetWithNurseryIterators(SetObject* obj) { + MOZ_ASSERT_IF(!setsWithNurseryIterators_.empty(), + setsWithNurseryIterators_.back() != obj); + return setsWithNurseryIterators_.append(obj); } + void joinSweepTask(); void joinDecommitTask(); +#ifdef DEBUG + bool sweepTaskIsIdle(); +#endif + mozilla::TimeStamp collectionStartTime() { return startTimes_[ProfileKey::Total]; } @@ -344,11 +370,12 @@ class Nursery { bool shouldTenureEverything(JS::GCReason reason); - inline bool inCollectedRegion(gc::Cell* cell) const; + inline bool inCollectedRegion(const gc::Cell* cell) const; inline bool inCollectedRegion(void* ptr) const; void trackMallocedBufferOnPromotion(void* buffer, gc::Cell* owner, size_t nbytes, MemoryUse use); + void trackBufferOnPromotion(void* buffer, gc::Cell* owner, size_t nbytes); void trackTrailerOnPromotion(void* buffer, gc::Cell* owner, size_t nbytes, size_t overhead, MemoryUse use); @@ -361,6 +388,8 @@ class Nursery { return mallocedBlockCache_.sizeOfExcludingThis(mallocSizeOf); } + inline void addMallocedBufferBytes(size_t nbytes); + mozilla::TimeStamp lastCollectionEndTime() const; private: @@ -491,8 +520,7 @@ class Nursery { bool checkForwardingPointerInsideNursery(void* ptr); #endif - // Updates pointers to nursery objects that have been tenured and discards - // pointers to objects that have been freed. + // Discard pointers to objects that have been freed. void sweep(); // In a minor GC, resets the start and end positions, the current chunk and @@ -502,11 +530,12 @@ class Nursery { // the nursery on debug & nightly builds. void clear(); - void clearMapAndSetNurseryRanges(); + void clearMapAndSetNurseryIterators(); void sweepMapAndSetObjects(); - // Allocate a buffer for a given zone, using the nursery if possible. - void* allocateBuffer(JS::Zone* zone, size_t nbytes); + void sweepStringsWithBuffer(); + + void sweepBuffers(); // Get per-space size limits. size_t maxSpaceSize() const; @@ -524,6 +553,9 @@ class Nursery { // vector. Shrinks the vector but does not update maxChunkCount(). void freeChunksFrom(Space& space, unsigned firstFreeChunk); + // During a semispace nursery collection, return whether a cell in fromspace + // was in the tospace of the previous collection, meaning that it should be + // tenured in this collection. inline bool shouldTenure(gc::Cell* cell); void sendTelemetry(JS::GCReason reason, mozilla::TimeDuration totalTime, @@ -570,7 +602,7 @@ class Nursery { uint32_t startChunk_ = 0; uintptr_t startPosition_ = 0; - // The set of malloced-allocated buffers owned by nursery objects. Any + // The set of malloc-allocated buffers owned by nursery objects. Any // buffers that do not belong to a promoted thing at the end of a minor GC // must be freed. BufferSet mallocedBuffers; @@ -646,6 +678,11 @@ class Nursery { // Report how many strings were deduplicated. bool reportDeduplications_; +#ifdef JS_GC_ZEAL + // Report on the kinds of things promoted. + bool reportPromotion_; +#endif + // Whether to report information on pretenuring, and if so the allocation // threshold at which to report details of each allocation site. gc::AllocSiteFilter pretenuringReportFilter_; @@ -687,8 +724,6 @@ class Nursery { HashMap, SystemAllocPolicy>; ForwardedBufferMap forwardedBuffers; - gc::CellSweepSet cellsToSweep; - // When we assign a unique id to cell in the nursery, that almost always // means that the cell will be in a hash table, and thus, held live, // automatically moving the uid from the nursery to its new home in @@ -702,13 +737,36 @@ class Nursery { using CellsWithUniqueIdVector = JS::GCVector; CellsWithUniqueIdVector cellsWithUid_; - // Lists of map and set objects allocated in the nursery or with iterators - // allocated there. Such objects need to be swept after minor GC. + // Lists of map and set objects with iterators allocated in the nursery. Such + // objects need to be swept after minor GC. using MapObjectVector = Vector; - MapObjectVector mapsWithNurseryMemory_; + MapObjectVector mapsWithNurseryIterators_; using SetObjectVector = Vector; - SetObjectVector setsWithNurseryMemory_; + SetObjectVector setsWithNurseryIterators_; + // List of strings with StringBuffers allocated in the nursery. References + // to the buffers are dropped after minor GC. The list stores both the JS + // string and the StringBuffer to simplify interaction with AtomRefs and + // string deduplication. + using StringAndBuffer = std::pair; + using StringAndBufferVector = + JS::GCVector; + StringAndBufferVector stringBuffers_; + + // Like stringBuffers_, but for extensible strings for flattened ropes. This + // requires a HashMap instead of a Vector because we need to remove the entry + // when transferring the buffer to a new extensible string during flattening. + using ExtensibleStringBuffers = + HashMap, js::SystemAllocPolicy>; + ExtensibleStringBuffers extensibleStringBuffers_; + + // List of StringBuffers to release off-thread. + using StringBufferVector = + Vector; + StringBufferVector stringBuffersToReleaseAfterMinorGC_; + + UniquePtr sweepTask; UniquePtr decommitTask; // A cache of small C++-heap allocated blocks associated with this Nursery. diff --git a/src/third_party/mozjs/extract/js/src/gc/NurseryAwareHashMap.h b/src/third_party/mozjs/extract/js/src/gc/NurseryAwareHashMap.h index 4df50c16272..23cc154a446 100644 --- a/src/third_party/mozjs/extract/js/src/gc/NurseryAwareHashMap.h +++ b/src/third_party/mozjs/extract/js/src/gc/NurseryAwareHashMap.h @@ -109,8 +109,7 @@ class NurseryAwareHashMap { nurseryEntries.sizeOfExcludingThis(mallocSizeOf); } size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return map.shallowSizeOfIncludingThis(mallocSizeOf) + - nurseryEntries.sizeOfIncludingThis(mallocSizeOf); + return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); } [[nodiscard]] bool put(const Key& key, const Value& value) { diff --git a/src/third_party/mozjs/extract/js/src/gc/ObjectKind-inl.h b/src/third_party/mozjs/extract/js/src/gc/ObjectKind-inl.h index d01680a5cfc..ec8890d91d4 100644 --- a/src/third_party/mozjs/extract/js/src/gc/ObjectKind-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/ObjectKind-inl.h @@ -18,14 +18,23 @@ namespace js { namespace gc { -/* Capacity for slotsToThingKind */ -const size_t SLOTS_TO_THING_KIND_LIMIT = 17; -extern const AllocKind slotsToThingKind[]; +inline constexpr AllocKind slotsToThingKind[] = { + // clang-format off + /* 0 */ AllocKind::OBJECT0, AllocKind::OBJECT2, AllocKind::OBJECT2, AllocKind::OBJECT4, + /* 4 */ AllocKind::OBJECT4, AllocKind::OBJECT8, AllocKind::OBJECT8, AllocKind::OBJECT8, + /* 8 */ AllocKind::OBJECT8, AllocKind::OBJECT12, AllocKind::OBJECT12, AllocKind::OBJECT12, + /* 12 */ AllocKind::OBJECT12, AllocKind::OBJECT16, AllocKind::OBJECT16, AllocKind::OBJECT16, + /* 16 */ AllocKind::OBJECT16 + // clang-format on +}; + extern const uint32_t slotsToAllocKindBytes[]; +static constexpr uint32_t MaxGCObjectFixedSlots = std::size(slotsToThingKind); + /* Get the best kind to use when making an object with the given slot count. */ -static inline AllocKind GetGCObjectKind(size_t numSlots) { - if (numSlots >= SLOTS_TO_THING_KIND_LIMIT) { +static constexpr AllocKind GetGCObjectKind(size_t numSlots) { + if (numSlots >= std::size(slotsToThingKind)) { return AllocKind::OBJECT16; } return slotsToThingKind[numSlots]; @@ -45,11 +54,11 @@ static constexpr bool CanUseFixedElementsForArray(size_t numElements) { return false; } size_t numSlots = numElements + ObjectElements::VALUES_PER_HEADER; - return numSlots < SLOTS_TO_THING_KIND_LIMIT; + return numSlots < std::size(slotsToThingKind); } /* As for GetGCObjectKind, but for dense array allocation. */ -static inline AllocKind GetGCArrayKind(size_t numElements) { +static constexpr AllocKind GetGCArrayKind(size_t numElements) { /* * Dense arrays can use their fixed slots to hold their elements array * (less two Values worth of ObjectElements header), but if more than the @@ -64,7 +73,7 @@ static inline AllocKind GetGCArrayKind(size_t numElements) { } static inline AllocKind GetGCObjectFixedSlotsKind(size_t numFixedSlots) { - MOZ_ASSERT(numFixedSlots < SLOTS_TO_THING_KIND_LIMIT); + MOZ_ASSERT(numFixedSlots < std::size(slotsToThingKind)); return slotsToThingKind[numFixedSlots]; } @@ -84,29 +93,35 @@ static inline AllocKind GetGCObjectKindForBytes(size_t nbytes) { } /* Get the number of fixed slots and initial capacity associated with a kind. */ -static constexpr inline size_t GetGCKindSlots(AllocKind thingKind) { +static constexpr size_t GetGCKindSlots(AllocKind thingKind) { // Using a switch in hopes that thingKind will usually be a compile-time // constant. switch (thingKind) { case AllocKind::OBJECT0: + case AllocKind::OBJECT0_FOREGROUND: case AllocKind::OBJECT0_BACKGROUND: return 0; case AllocKind::OBJECT2: + case AllocKind::OBJECT2_FOREGROUND: case AllocKind::OBJECT2_BACKGROUND: return 2; case AllocKind::FUNCTION: case AllocKind::OBJECT4: + case AllocKind::OBJECT4_FOREGROUND: case AllocKind::OBJECT4_BACKGROUND: return 4; case AllocKind::FUNCTION_EXTENDED: return 7; case AllocKind::OBJECT8: + case AllocKind::OBJECT8_FOREGROUND: case AllocKind::OBJECT8_BACKGROUND: return 8; case AllocKind::OBJECT12: + case AllocKind::OBJECT12_FOREGROUND: case AllocKind::OBJECT12_BACKGROUND: return 12; case AllocKind::OBJECT16: + case AllocKind::OBJECT16_FOREGROUND: case AllocKind::OBJECT16_BACKGROUND: return 16; default: @@ -118,42 +133,44 @@ static inline size_t GetGCKindBytes(AllocKind thingKind) { return sizeof(JSObject_Slots0) + GetGCKindSlots(thingKind) * sizeof(Value); } -static inline bool CanUseBackgroundAllocKind(const JSClass* clasp) { - return !clasp->hasFinalize() || (clasp->flags & JSCLASS_BACKGROUND_FINALIZE); -} - -static inline bool CanChangeToBackgroundAllocKind(AllocKind kind, - const JSClass* clasp) { - // If a foreground alloc kind is specified but the class has no finalizer or a - // finalizer that is safe to call on a different thread, we can change the - // alloc kind to one which is finalized on a background thread. - // - // For example, AllocKind::OBJECT0 calls the finalizer on the main thread, and - // AllocKind::OBJECT0_BACKGROUND calls the finalizer on the a helper thread. - - MOZ_ASSERT(IsObjectAllocKind(kind)); - - if (IsBackgroundFinalized(kind)) { - return false; // This kind is already a background finalized kind. +static inline FinalizeKind GetObjectFinalizeKind(const JSClass* clasp) { + if (!clasp->hasFinalize()) { + MOZ_ASSERT((clasp->flags & JSCLASS_FOREGROUND_FINALIZE) == 0); + MOZ_ASSERT((clasp->flags & JSCLASS_BACKGROUND_FINALIZE) == 0); + return FinalizeKind::None; } - return CanUseBackgroundAllocKind(clasp); + if (clasp->flags & JSCLASS_BACKGROUND_FINALIZE) { + MOZ_ASSERT((clasp->flags & JSCLASS_FOREGROUND_FINALIZE) == 0); + return FinalizeKind::Background; + } + + MOZ_ASSERT(clasp->flags & JSCLASS_FOREGROUND_FINALIZE); + return FinalizeKind::Foreground; } -static inline AllocKind ForegroundToBackgroundAllocKind(AllocKind fgKind) { - MOZ_ASSERT(IsObjectAllocKind(fgKind)); - MOZ_ASSERT(IsForegroundFinalized(fgKind)); +static inline AllocKind GetFinalizedAllocKind(AllocKind kind, + FinalizeKind finalizeKind) { + MOZ_ASSERT(kind != AllocKind::FUNCTION && + kind != AllocKind::FUNCTION_EXTENDED); + MOZ_ASSERT(IsObjectAllocKind(kind)); + MOZ_ASSERT(!IsFinalizedKind(kind)); - // For objects, each background alloc kind is defined just after the - // corresponding foreground alloc kind so we can convert between them by - // incrementing or decrementing as appropriate. - AllocKind bgKind = AllocKind(size_t(fgKind) + 1); + AllocKind newKind = AllocKind(size_t(kind) + size_t(finalizeKind)); + MOZ_ASSERT(IsObjectAllocKind(newKind)); + MOZ_ASSERT(GetGCKindSlots(newKind) == GetGCKindSlots(kind)); + MOZ_ASSERT_IF(finalizeKind == FinalizeKind::None, !IsFinalizedKind(newKind)); + MOZ_ASSERT_IF(finalizeKind == FinalizeKind::Foreground, + IsForegroundFinalized(newKind)); + MOZ_ASSERT_IF(finalizeKind == FinalizeKind::Background, + IsBackgroundFinalized(newKind)); - MOZ_ASSERT(IsObjectAllocKind(bgKind)); - MOZ_ASSERT(IsBackgroundFinalized(bgKind)); - MOZ_ASSERT(GetGCKindSlots(bgKind) == GetGCKindSlots(fgKind)); + return newKind; +} - return bgKind; +static inline AllocKind GetFinalizedAllocKindForClass(AllocKind kind, + const JSClass* clasp) { + return GetFinalizedAllocKind(kind, GetObjectFinalizeKind(clasp)); } } // namespace gc diff --git a/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.cpp b/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.cpp index 2d77b12e474..146f0c284fe 100644 --- a/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.cpp @@ -6,6 +6,7 @@ #include "gc/ParallelMarking.h" +#include "gc/GCInternals.h" #include "gc/GCLock.h" #include "gc/ParallelWork.h" #include "vm/GeckoProfiler.h" @@ -15,25 +16,27 @@ using namespace js; using namespace js::gc; -using mozilla::Maybe; using mozilla::TimeDuration; using mozilla::TimeStamp; +using JS::SliceBudget; + class AutoAddTimeDuration { - TimeStamp start; - TimeDuration& result; + TimeStamp start_; + TimeDuration& result_; public: explicit AutoAddTimeDuration(TimeDuration& result) - : start(TimeStamp::Now()), result(result) {} - ~AutoAddTimeDuration() { result += TimeSince(start); } + : start_(TimeStamp::Now()), result_(result) {} + TimeStamp start() const { return start_; } + ~AutoAddTimeDuration() { result_ += TimeSince(start_); } }; ParallelMarker::ParallelMarker(GCRuntime* gc) : gc(gc) {} size_t ParallelMarker::workerCount() const { return gc->markers.length(); } -bool ParallelMarker::mark(SliceBudget& sliceBudget) { +bool ParallelMarker::mark(const SliceBudget& sliceBudget) { MOZ_ASSERT(workerCount() <= gc->getMaxParallelThreads()); if (markOneColor(MarkColor::Black, sliceBudget) == NotFinished) { @@ -54,7 +57,8 @@ bool ParallelMarker::mark(SliceBudget& sliceBudget) { return true; } -bool ParallelMarker::markOneColor(MarkColor color, SliceBudget& sliceBudget) { +bool ParallelMarker::markOneColor(MarkColor color, + const SliceBudget& sliceBudget) { // Run a marking slice and return whether the stack is now empty. if (!hasWork(color)) { @@ -75,7 +79,7 @@ bool ParallelMarker::markOneColor(MarkColor color, SliceBudget& sliceBudget) { // TODO: When tuning for more than two markers we may need to adopt a more // sophisticated approach. if (!marker->hasEntriesForCurrentColor() && gc->marker().canDonateWork()) { - GCMarker::moveWork(marker, &gc->marker()); + GCMarker::moveWork(marker, &gc->marker(), false); } } @@ -156,6 +160,8 @@ void ParallelMarkTask::recordDuration() { } void ParallelMarkTask::run(AutoLockHelperThreadState& lock) { + AutoUpdateMarkStackRanges updateRanges(*marker); + for (;;) { if (hasWork()) { if (!tryMarking(lock)) { @@ -182,6 +188,12 @@ bool ParallelMarkTask::tryMarking(AutoLockHelperThreadState& lock) { AutoAddTimeDuration time(markTime.ref()); finished = marker->markCurrentColorInParallel(budget); + + GeckoProfilerRuntime& profiler = gc->rt->geckoProfiler(); + if (profiler.enabled()) { + profiler.markInterval("Parallel marking ran", time.start(), nullptr, + JS::ProfilingCategoryPair::GCCC); + } } MOZ_ASSERT_IF(finished, !hasWork()); @@ -210,10 +222,7 @@ bool ParallelMarkTask::requestWork(AutoLockHelperThreadState& lock) { } void ParallelMarkTask::waitUntilResumed(AutoLockHelperThreadState& lock) { - GeckoProfilerRuntime& profiler = gc->rt->geckoProfiler(); - if (profiler.enabled()) { - profiler.markEvent("Parallel marking wait start", ""); - } + AutoAddTimeDuration time(waitTime.ref()); pm->addTaskToWaitingList(this, lock); @@ -221,8 +230,6 @@ void ParallelMarkTask::waitUntilResumed(AutoLockHelperThreadState& lock) { MOZ_ASSERT(!isWaiting); isWaiting = true; - AutoAddTimeDuration time(waitTime.ref()); - do { MOZ_ASSERT(pm->hasActiveTasks(lock)); resumed.wait(lock); @@ -230,8 +237,12 @@ void ParallelMarkTask::waitUntilResumed(AutoLockHelperThreadState& lock) { MOZ_ASSERT(!pm->isTaskInWaitingList(this, lock)); + GeckoProfilerRuntime& profiler = gc->rt->geckoProfiler(); if (profiler.enabled()) { - profiler.markEvent("Parallel marking wait end", ""); + char details[32]; + SprintfLiteral(details, "markers=%zu", pm->workerCount()); + profiler.markInterval("Parallel marking wait", time.start(), details, + JS::ProfilingCategoryPair::GCCC); } } @@ -305,13 +316,21 @@ void ParallelMarker::decActiveTasks(ParallelMarkTask* task, } void ParallelMarker::donateWorkFrom(GCMarker* src) { + GeckoProfilerRuntime& profiler = gc->rt->geckoProfiler(); + if (!gHelperThreadLock.tryLock()) { + if (profiler.enabled()) { + profiler.markEvent("Parallel marking donate failed", "lock already held"); + } return; } // Check there are tasks waiting for work while holding the lock. if (waitingTaskCount == 0) { gHelperThreadLock.unlock(); + if (profiler.enabled()) { + profiler.markEvent("Parallel marking donate failed", "no tasks waiting"); + } return; } @@ -326,13 +345,15 @@ void ParallelMarker::donateWorkFrom(GCMarker* src) { // Move some work from this thread's mark stack to the waiting task. MOZ_ASSERT(!waitingTask->hasWork()); - GCMarker::moveWork(waitingTask->marker, src); + size_t wordsMoved = GCMarker::moveWork(waitingTask->marker, src, true); gc->stats().count(gcstats::COUNT_PARALLEL_MARK_INTERRUPTIONS); - GeckoProfilerRuntime& profiler = gc->rt->geckoProfiler(); if (profiler.enabled()) { - profiler.markEvent("Parallel marking donated work", ""); + char details[32]; + SprintfLiteral(details, "words=%zu", wordsMoved); + profiler.markEvent("Parallel marking donated work", details, + JS::ProfilingCategoryPair::GCCC); } // Resume waiting task. diff --git a/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.h b/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.h index 4c39328de1a..87b3aeef7dd 100644 --- a/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.h +++ b/src/third_party/mozjs/extract/js/src/gc/ParallelMarking.h @@ -38,7 +38,7 @@ class MOZ_STACK_CLASS ParallelMarker { public: explicit ParallelMarker(GCRuntime* gc); - bool mark(SliceBudget& sliceBudget); + bool mark(const JS::SliceBudget& sliceBudget); using AtomicCount = mozilla::Atomic; AtomicCount& waitingTaskCountRef() { return waitingTaskCount; } @@ -46,7 +46,7 @@ class MOZ_STACK_CLASS ParallelMarker { void donateWorkFrom(GCMarker* src); private: - bool markOneColor(MarkColor color, SliceBudget& sliceBudget); + bool markOneColor(MarkColor color, const JS::SliceBudget& sliceBudget); bool hasWork(MarkColor color) const; @@ -88,7 +88,7 @@ class alignas(TypicalCacheLineSize) ParallelMarkTask friend class ParallelMarker; ParallelMarkTask(ParallelMarker* pm, GCMarker* marker, MarkColor color, - const SliceBudget& budget); + const JS::SliceBudget& budget); ~ParallelMarkTask(); void run(AutoLockHelperThreadState& lock) override; @@ -109,7 +109,7 @@ class alignas(TypicalCacheLineSize) ParallelMarkTask ParallelMarker* const pm; GCMarker* const marker; AutoSetMarkColor color; - SliceBudget budget; + JS::SliceBudget budget; ConditionVariable resumed; HelperThreadLockData isWaiting; diff --git a/src/third_party/mozjs/extract/js/src/gc/ParallelWork.h b/src/third_party/mozjs/extract/js/src/gc/ParallelWork.h index db97c750094..1c747b56dad 100644 --- a/src/third_party/mozjs/extract/js/src/gc/ParallelWork.h +++ b/src/third_party/mozjs/extract/js/src/gc/ParallelWork.h @@ -38,7 +38,7 @@ class ParallelWorker : public GCParallelTask { ParallelWorker(GCRuntime* gc, gcstats::PhaseKind phaseKind, GCUse use, WorkFunc func, WorkItemIterator& work, - const SliceBudget& budget, AutoLockHelperThreadState& lock) + const JS::SliceBudget& budget, AutoLockHelperThreadState& lock) : GCParallelTask(gc, phaseKind, use), func_(func), work_(work), @@ -79,7 +79,7 @@ class ParallelWorker : public GCParallelTask { HelperThreadLockData work_; // The budget that determines how long to run for. - SliceBudget budget_; + JS::SliceBudget budget_; // The next work item to process. WorkItem item_; @@ -97,7 +97,7 @@ class MOZ_RAII AutoRunParallelWork { AutoRunParallelWork(GCRuntime* gc, WorkFunc func, gcstats::PhaseKind phaseKind, GCUse use, - WorkItemIterator& work, const SliceBudget& budget, + WorkItemIterator& work, const JS::SliceBudget& budget, AutoLockHelperThreadState& lock) : gc(gc), phaseKind(phaseKind), lock(lock), tasksStarted(0) { size_t workerCount = gc->parallelWorkerCount(); diff --git a/src/third_party/mozjs/extract/js/src/gc/Pretenuring.cpp b/src/third_party/mozjs/extract/js/src/gc/Pretenuring.cpp index bd5b0717a9b..e90297f8b60 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Pretenuring.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Pretenuring.cpp @@ -84,7 +84,7 @@ size_t PretenuringNursery::doPretenuring(GCRuntime* gc, JS::GCReason reason, // Zero allocation counts. totalAllocCount_ = 0; for (ZonesIter zone(gc, SkipAtoms); !zone.done(); zone.next()) { - for (auto& count : zone->pretenuring.nurseryAllocCounts) { + for (auto& count : zone->pretenuring.nurseryPromotedCounts) { count = 0; } } @@ -261,7 +261,9 @@ void PretenuringNursery::updateTotalAllocCounts(AllocSite* site) { JS::TraceKind kind = site->traceKind(); totalAllocCount_ += site->nurseryAllocCount; PretenuringZone& zone = site->zone()->pretenuring; - zone.nurseryAllocCount(kind) += site->nurseryAllocCount; + size_t i = size_t(kind); + MOZ_ASSERT(i < std::size(zone.nurseryPromotedCounts)); + zone.nurseryPromotedCounts[i] += site->nurseryPromotedCount; } bool AllocSite::invalidateScript(GCRuntime* gc) { diff --git a/src/third_party/mozjs/extract/js/src/gc/Pretenuring.h b/src/third_party/mozjs/extract/js/src/gc/Pretenuring.h index 19bfebe0ae5..ed825cde306 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Pretenuring.h +++ b/src/third_party/mozjs/extract/js/src/gc/Pretenuring.h @@ -61,15 +61,19 @@ class AllocSite { Normal = 0, Unknown = 1, Optimized = 2, - Missing = 3 + Missing = 3, + Tenuring = 4, }; - enum class State : uint32_t { ShortLived = 0, Unknown = 1, LongLived = 2 }; + enum class State : uint32_t { Unknown = 0, LongLived = 1, ShortLived = 2 }; - // The JIT depends on being able to tell the states apart by checking a single - // bit. - static constexpr int32_t LONG_LIVED_BIT = int32_t(State::LongLived); - static_assert((LONG_LIVED_BIT & int32_t(State::Unknown)) == 0); - static_assert((AllocSite::LONG_LIVED_BIT & int32_t(State::ShortLived)) == 0); + // We can convert between state and heap by extracting a single bit. + static constexpr int32_t LONG_LIVED_BIT = 1; + static_assert((uint32_t(State::Unknown) & LONG_LIVED_BIT) == + uint32_t(Heap::Default)); + static_assert((uint32_t(State::LongLived) & LONG_LIVED_BIT) == + uint32_t(Heap::Tenured)); + static_assert((uint32_t(State::ShortLived) & LONG_LIVED_BIT) == + uint32_t(Heap::Default)); private: JS::Zone* zone_ = nullptr; @@ -91,16 +95,16 @@ class AllocSite { // Note that the offset does not need to correspond with the script stored in // this AllocSite, because if we're doing trial-inlining, the script will be // the outer script and the pc offset can be in an inlined script. - uint32_t pcOffset_ : 30; - static constexpr uint32_t InvalidPCOffset = Bit(30) - 1; + uint32_t pcOffset_ : 29; + static constexpr uint32_t InvalidPCOffset = Bit(29) - 1; - uint32_t kind_ : 2; + uint32_t kind_ : 3; // Number of nursery allocations at this site since it was last processed by // processSite(). uint32_t nurseryAllocCount = 0; - // Number of nursery allocations at this site that were tenured since it was + // Number of nursery allocations at this site that were promoted since it was // last processed by processSite(). uint32_t nurseryPromotedCount : 24; @@ -122,7 +126,8 @@ class AllocSite { uintptr_t rawScript() const { return scriptAndState & ~STATE_MASK; } public: - static constexpr uint32_t MaxValidPCOffset = InvalidPCOffset - 1; + static constexpr uint32_t EnvSitePCOffset = InvalidPCOffset - 1; + static constexpr uint32_t MaxValidPCOffset = EnvSitePCOffset - 1; // Default constructor. Clients must call one of the init methods afterwards. AllocSite() @@ -141,7 +146,7 @@ class AllocSite { nurseryPromotedCount(0), invalidationCount(0), traceKind_(uint32_t(traceKind)) { - MOZ_ASSERT(pcOffset <= MaxValidPCOffset); + MOZ_ASSERT(pcOffset <= MaxValidPCOffset || pcOffset == EnvSitePCOffset); MOZ_ASSERT(pcOffset_ == pcOffset); setScript(script); } @@ -165,6 +170,13 @@ class AllocSite { kind_ = uint32_t(Kind::Optimized); } + void initTenuringSite(JS::Zone* zone) { + assertUninitialized(); + zone_ = zone; + scriptAndState = uintptr_t(State::LongLived); + kind_ = uint32_t(Kind::Tenuring); + } + // Initialize a site to be a wasm site. void initWasm(JS::Zone* zone) { assertUninitialized(); @@ -212,6 +224,7 @@ class AllocSite { bool isUnknown() const { return kind() == Kind::Unknown; } bool isOptimized() const { return kind() == Kind::Optimized; } bool isMissing() const { return kind() == Kind::Missing; } + bool isTenuring() const { return kind() == Kind::Tenuring; } Kind kind() const { MOZ_ASSERT((Kind(kind_) == Kind::Normal || Kind(kind_) == Kind::Missing) == @@ -224,10 +237,10 @@ class AllocSite { // Whether allocations at this site should be allocated in the nursery or the // tenured heap. Heap initialHeap() const { - if (!isNormal()) { - return Heap::Default; - } - return state() == State::LongLived ? Heap::Tenured : Heap::Default; + Heap heap = Heap(uint32_t(state()) & LONG_LIVED_BIT); + MOZ_ASSERT_IF(isTenuring(), heap == Heap::Tenured); + MOZ_ASSERT_IF(!isTenuring() && !isNormal(), heap == Heap::Default); + return heap; } bool hasNurseryAllocations() const { @@ -315,6 +328,10 @@ class PretenuringZone { // not recorded by optimized JIT code. AllocSite optimizedAllocSite; + // Alloc Site which always tenure allocates. Used to avoid type punning + // when JIT-compiling for the Realm local allocation site. + AllocSite tenuringAllocSite; + // Allocation sites used for nursery cells promoted to the next nursery // generation that didn't come from optimized alloc sites. AllocSite promotedAllocSites[NurseryTraceKinds]; @@ -334,9 +351,8 @@ class PretenuringZone { // get the pretenuring decision wrong. uint32_t highNurserySurvivalCount = 0; - // Total allocation count by trace kind (ignoring optimized - // allocations). Calculated during nursery collection. - uint32_t nurseryAllocCounts[NurseryTraceKinds] = {0}; + // Total promotion count by trace kind. Calculated during nursery collection. + uint32_t nurseryPromotedCounts[NurseryTraceKinds] = {0}; explicit PretenuringZone(JS::Zone* zone) { for (uint32_t i = 0; i < NurseryTraceKinds; i++) { @@ -344,6 +360,7 @@ class PretenuringZone { promotedAllocSites[i].initUnknownSite(zone, JS::TraceKind(i)); } optimizedAllocSite.initOptimizedSite(zone); + tenuringAllocSite.initTenuringSite(zone); } AllocSite& unknownAllocSite(JS::TraceKind kind) { @@ -378,13 +395,10 @@ class PretenuringZone { bool shouldResetNurseryAllocSites(); bool shouldResetPretenuredAllocSites(); - uint32_t& nurseryAllocCount(JS::TraceKind kind) { + uint32_t nurseryPromotedCount(JS::TraceKind kind) const { size_t i = size_t(kind); - MOZ_ASSERT(i < NurseryTraceKinds); - return nurseryAllocCounts[i]; - } - uint32_t nurseryAllocCount(JS::TraceKind kind) const { - return const_cast(this)->nurseryAllocCount(kind); + MOZ_ASSERT(i < std::size(nurseryPromotedCounts)); + return nurseryPromotedCounts[i]; } }; diff --git a/src/third_party/mozjs/extract/js/src/gc/PublicIterators.h b/src/third_party/mozjs/extract/js/src/gc/PublicIterators.h index 7ef6271f638..d4325204bba 100644 --- a/src/third_party/mozjs/extract/js/src/gc/PublicIterators.h +++ b/src/third_party/mozjs/extract/js/src/gc/PublicIterators.h @@ -35,9 +35,10 @@ class ZonesIter { public: ZonesIter(gc::GCRuntime* gc, ZoneSelector selector) : iterMarker(gc), it(gc->zones().begin()), end(gc->zones().end()) { - if (selector == SkipAtoms && !done()) { - MOZ_ASSERT(get()->isAtomsZone()); - next(); + if (selector == SkipAtoms) { + while (!done() && get()->isAtomsZone()) { + next(); + } } } ZonesIter(JSRuntime* rt, ZoneSelector selector) diff --git a/src/third_party/mozjs/extract/js/src/gc/RootMarking.cpp b/src/third_party/mozjs/extract/js/src/gc/RootMarking.cpp index d1aa46d7edb..10909a9b83e 100644 --- a/src/third_party/mozjs/extract/js/src/gc/RootMarking.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/RootMarking.cpp @@ -28,6 +28,7 @@ using namespace js::gc; using mozilla::LinkedList; using JS::AutoGCRooter; +using JS::SliceBudget; using RootRange = RootedValueMap::Range; using RootEntry = RootedValueMap::Entry; @@ -276,7 +277,7 @@ void js::TraceRuntimeWithoutEviction(JSTracer* trc) { rt->gc.traceRuntime(trc, session); } -void js::gc::GCRuntime::traceRuntime(JSTracer* trc, AutoTraceSession& session) { +void js::gc::GCRuntime::traceRuntime(JSTracer* trc, AutoHeapSession& session) { MOZ_ASSERT(!rt->isBeingDestroyed()); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_ROOTS); diff --git a/src/third_party/mozjs/extract/js/src/gc/Scheduling.cpp b/src/third_party/mozjs/extract/js/src/gc/Scheduling.cpp index 2870e0a97b5..a4ef84a2f92 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Scheduling.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Scheduling.cpp @@ -295,23 +295,26 @@ void GCSchedulingTunables::checkInvariants() { MOZ_ASSERT(smallHeapIncrementalLimit_ >= largeHeapIncrementalLimit_); } -void GCSchedulingState::updateHighFrequencyMode( - const mozilla::TimeStamp& lastGCTime, const mozilla::TimeStamp& currentTime, +void GCSchedulingState::updateHighFrequencyModeOnGCStart( + JS::GCOptions options, const mozilla::TimeStamp& lastGCTime, + const mozilla::TimeStamp& currentTime, const GCSchedulingTunables& tunables) { - if (js::SupportDifferentialTesting()) { - return; - } - - inHighFrequencyGCMode_ = - !lastGCTime.IsNull() && - lastGCTime + tunables.highFrequencyThreshold() > currentTime; + // Set high frequency mode based on the time between collections. + TimeDuration timeSinceLastGC = currentTime - lastGCTime; + inHighFrequencyGCMode_ = !js::SupportDifferentialTesting() && + options == JS::GCOptions::Normal && + timeSinceLastGC < tunables.highFrequencyThreshold(); } -void GCSchedulingState::updateHighFrequencyModeForReason(JS::GCReason reason) { - // These reason indicate that the embedding isn't triggering GC slices often - // enough and allocation rate is high. - if (reason == JS::GCReason::ALLOC_TRIGGER || - reason == JS::GCReason::TOO_MUCH_MALLOC) { +void GCSchedulingState::updateHighFrequencyModeOnSliceStart( + JS::GCOptions options, JS::GCReason reason) { + MOZ_ASSERT_IF(options != JS::GCOptions::Normal, !inHighFrequencyGCMode_); + + // Additionally set high frequency mode for reasons that indicate that slices + // aren't being triggered often enough and the allocation rate is high. + if (options == JS::GCOptions::Normal && + (reason == JS::GCReason::ALLOC_TRIGGER || + reason == JS::GCReason::TOO_MUCH_MALLOC)) { inHighFrequencyGCMode_ = true; } } diff --git a/src/third_party/mozjs/extract/js/src/gc/Scheduling.h b/src/third_party/mozjs/extract/js/src/gc/Scheduling.h index fec3dca5dca..7c1a9156111 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Scheduling.h +++ b/src/third_party/mozjs/extract/js/src/gc/Scheduling.h @@ -321,6 +321,8 @@ #include "js/GCAPI.h" #include "js/HashTable.h" #include "js/HeapAPI.h" +#include "threading/LockGuard.h" +#include "threading/Mutex.h" #include "threading/ProtectedData.h" // Macro to define scheduling tunables for GC parameters. Expands its argument @@ -382,11 +384,11 @@ * \ * Multiple of threshold.bytes() which triggers a non-incremental GC. \ * \ - * The small heap limit must be greater than 1.3 to maintain performance on \ + * The small heap limit must be at least 1.7 to maintain performance on \ * splay-latency. \ */ \ _(JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, double, smallHeapIncrementalLimit, \ - ConvertTimes100, CheckIncrementalLimit, 1.50) \ + ConvertTimes100, CheckIncrementalLimit, 1.70) \ _(JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, double, largeHeapIncrementalLimit, \ ConvertTimes100, CheckIncrementalLimit, 1.10) \ \ @@ -498,7 +500,14 @@ * JSGC_GENERATE_MISSING_ALLOC_SITES \ */ \ _(JSGC_GENERATE_MISSING_ALLOC_SITES, bool, generateMissingAllocSites, \ - ConvertBool, NoCheck, false) + ConvertBool, NoCheck, false) \ + \ + /* \ + * JSGC_NURSERY_MAX_TIME_GOAL_MS \ + */ \ + _(JSGC_NURSERY_MAX_TIME_GOAL_MS, mozilla::TimeDuration, \ + nurseryMaxTimeGoalMS, ConvertMillis, NoCheck, \ + mozilla::TimeDuration::FromMilliseconds(4)) namespace js { @@ -521,9 +530,6 @@ namespace TuningDefaults { /* JSGC_MIN_EMPTY_CHUNK_COUNT */ static const uint32_t MinEmptyChunkCount = 1; -/* JSGC_MAX_EMPTY_CHUNK_COUNT */ -static const uint32_t MaxEmptyChunkCount = 30; - /* JSGC_SLICE_TIME_BUDGET_MS */ static const int64_t DefaultTimeBudgetMS = 0; // Unlimited by default. @@ -536,6 +542,9 @@ static const bool PerZoneGCEnabled = false; /* JSGC_COMPACTING_ENABLED */ static const bool CompactingEnabled = true; +/* JSGC_NURSERY_ENABLED */ +static const bool NurseryEnabled = true; + /* JSGC_PARALLEL_MARKING_ENABLED */ static const bool ParallelMarkingEnabled = false; @@ -590,17 +599,19 @@ class GCSchedulingState { * growth factor is a measure of how large (as a percentage of the last GC) * the heap is allowed to grow before we try to schedule another GC. */ - mozilla::Atomic inHighFrequencyGCMode_; + mozilla::Atomic inHighFrequencyGCMode_; public: GCSchedulingState() : inHighFrequencyGCMode_(false) {} bool inHighFrequencyGCMode() const { return inHighFrequencyGCMode_; } - void updateHighFrequencyMode(const mozilla::TimeStamp& lastGCTime, - const mozilla::TimeStamp& currentTime, - const GCSchedulingTunables& tunables); - void updateHighFrequencyModeForReason(JS::GCReason reason); + void updateHighFrequencyModeOnGCStart(JS::GCOptions options, + const mozilla::TimeStamp& lastGCTime, + const mozilla::TimeStamp& currentTime, + const GCSchedulingTunables& tunables); + void updateHighFrequencyModeOnSliceStart(JS::GCOptions options, + JS::GCReason reason); }; struct TriggerResult { @@ -609,7 +620,7 @@ struct TriggerResult { size_t thresholdBytes; }; -using AtomicByteCount = mozilla::Atomic; +using AtomicByteCount = mozilla::Atomic; /* * Tracks the size of allocated data. This is used for both GC and malloc data. @@ -655,10 +666,13 @@ class HeapSize { MOZ_ASSERT(retainedBytes_ <= bytes_); } - void addBytes(size_t nbytes) { + void addBytes(size_t nbytes, bool updateRetainedSize = false) { mozilla::DebugOnly initialBytes(bytes_); MOZ_ASSERT(initialBytes + nbytes > initialBytes); bytes_ += nbytes; + if (updateRetainedSize) { + retainedBytes_ += nbytes; + } } void removeBytes(size_t nbytes, bool updateRetainedSize) { if (updateRetainedSize) { diff --git a/src/third_party/mozjs/extract/js/src/gc/Statistics.cpp b/src/third_party/mozjs/extract/js/src/gc/Statistics.cpp index c12d44db976..01a5f680212 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Statistics.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Statistics.cpp @@ -37,6 +37,8 @@ using mozilla::Maybe; using mozilla::TimeDuration; using mozilla::TimeStamp; +using JS::SliceBudget; + static const size_t BYTES_PER_MB = 1024 * 1024; /* @@ -84,6 +86,11 @@ JS_PUBLIC_API const char* JS::ExplainGCReason(JS::GCReason reason) { } } +JS_PUBLIC_API const char* JS::ExplainGCAbortReason(uint32_t val) { + GCAbortReason reason = static_cast(val); + return js::gcstats::ExplainAbortReason(reason); +} + JS_PUBLIC_API bool JS::InternalGCReason(JS::GCReason reason) { return reason < JS::GCReason::FIRST_FIREFOX_REASON; } @@ -174,6 +181,12 @@ class PhaseIter { operator Phase() const { return phase; } }; +JS_PUBLIC_API const char* JS::GetGCPhaseName(uint32_t val) { + PhaseKind kind = static_cast(val); + MOZ_RELEASE_ASSERT(kind < PhaseKind::LIMIT); + return phaseKinds[kind].name; +} + static double t(TimeDuration duration) { return duration.ToMilliseconds(); } static TimeDuration TimeBetween(TimeStamp start, TimeStamp end) { @@ -386,7 +399,7 @@ UniqueChars Statistics::formatCompactSummaryMessage() const { zoneStats.collectedZoneCount, zoneStats.zoneCount, zoneStats.sweptZoneCount, zoneStats.collectedCompartmentCount, zoneStats.compartmentCount, zoneStats.sweptCompartmentCount, - double(preTotalHeapBytes) / BYTES_PER_MB, + double(preTotalGCHeapBytes) / BYTES_PER_MB, int32_t(counts[COUNT_NEW_CHUNK] - counts[COUNT_DESTROY_CHUNK]), counts[COUNT_NEW_CHUNK] + counts[COUNT_DESTROY_CHUNK]); if (!fragments.append(DuplicateString(buffer))) { @@ -498,7 +511,7 @@ UniqueChars Statistics::formatDetailedDescription() const { zoneStats.compartmentCount, zoneStats.sweptCompartmentCount, getCount(COUNT_MINOR_GC), getCount(COUNT_STOREBUFFER_OVERFLOW), mmu20 * 100., mmu50 * 100., t(sccTotal), t(sccLongest), - double(preTotalHeapBytes) / BYTES_PER_MB, + double(preTotalGCHeapBytes) / BYTES_PER_MB, getCount(COUNT_NEW_CHUNK) - getCount(COUNT_DESTROY_CHUNK), getCount(COUNT_NEW_CHUNK) + getCount(COUNT_DESTROY_CHUNK), double(ArenaSize * getCount(COUNT_ARENA_RELOCATED)) / BYTES_PER_MB); @@ -714,8 +727,11 @@ void Statistics::formatJsonDescription(JSONPrinter& json) const { json.property("nonincremental_reason", ExplainAbortReason(nonincrementalReason_)); } - json.property("allocated_bytes", preTotalHeapBytes); - json.property("post_heap_size", postTotalHeapBytes); + json.property("allocated_bytes", preTotalGCHeapBytes); + json.property("post_heap_size", postTotalGCHeapBytes); + + json.property("pre_malloc_heap_size", preTotalMallocHeapBytes); + json.property("post_malloc_heap_size", postTotalMallocHeapBytes); uint32_t addedChunks = getCount(COUNT_NEW_CHUNK); if (addedChunks) { @@ -778,9 +794,11 @@ Statistics::Statistics(GCRuntime* gc) nonincrementalReason_(GCAbortReason::None), creationTime_(TimeStamp::Now()), tenuredAllocsSinceMinorGC(0), - preTotalHeapBytes(0), - postTotalHeapBytes(0), - preCollectedHeapBytes(0), + preTotalGCHeapBytes(0), + postTotalGCHeapBytes(0), + preCollectedGCHeapBytes(0), + preTotalMallocHeapBytes(0), + postTotalMallocHeapBytes(0), startingMinorGCNumber(0), startingMajorGCNumber(0), startingSliceNumber(0), @@ -820,6 +838,9 @@ Statistics::Statistics(GCRuntime* gc) "Report major GCs taking more than N milliseconds for " "all or just the main runtime\n", &enableProfiling_, &profileWorkers_, &profileThreshold_); + + const char* env = getenv("JS_GC_BUFFER_STATS"); + enableBufferAllocStats_ = env && atoi(env); } Statistics::~Statistics() { @@ -986,10 +1007,6 @@ void Statistics::beginGC(JS::GCOptions options, const TimeStamp& currentTime) { gcOptions = options; nonincrementalReason_ = GCAbortReason::None; - preTotalHeapBytes = gc->heapSize.bytes(); - - preCollectedHeapBytes = 0; - startingMajorGCNumber = gc->majorGCCount(); startingSliceNumber = gc->gcNumber(); @@ -998,17 +1015,37 @@ void Statistics::beginGC(JS::GCOptions options, const TimeStamp& currentTime) { } totalGCTime_ = TimeDuration::Zero(); + + preTotalGCHeapBytes = 0; + postTotalGCHeapBytes = 0; + preCollectedGCHeapBytes = 0; + preTotalMallocHeapBytes = 0; + postTotalMallocHeapBytes = 0; } -void Statistics::measureInitialHeapSize() { - MOZ_ASSERT(preCollectedHeapBytes == 0); - for (GCZonesIter zone(gc); !zone.done(); zone.next()) { - preCollectedHeapBytes += zone->gcHeapSize.bytes(); +void Statistics::measureInitialHeapSizes() { + MOZ_ASSERT(preTotalGCHeapBytes == 0); + MOZ_ASSERT(preCollectedGCHeapBytes == 0); + MOZ_ASSERT(preTotalMallocHeapBytes == 0); + + preTotalGCHeapBytes = gc->heapSize.bytes(); + + for (AllZonesIter zone(gc); !zone.done(); zone.next()) { + preTotalMallocHeapBytes += zone->mallocHeapSize.bytes(); + if (zone->wasGCStarted()) { + preCollectedGCHeapBytes += zone->gcHeapSize.bytes(); + } } } void Statistics::endGC() { - postTotalHeapBytes = gc->heapSize.bytes(); + MOZ_ASSERT(postTotalGCHeapBytes == 0); + MOZ_ASSERT(postTotalMallocHeapBytes == 0); + + postTotalGCHeapBytes = gc->heapSize.bytes(); + for (AllZonesIter zone(gc); !zone.done(); zone.next()) { + postTotalMallocHeapBytes += zone->mallocHeapSize.bytes(); + } sendGCTelemetry(); } @@ -1097,7 +1134,7 @@ void Statistics::sendGCTelemetry() { } } - if (!lastSlice.wasReset() && preCollectedHeapBytes != 0) { + if (!lastSlice.wasReset() && preCollectedGCHeapBytes != 0) { size_t bytesSurvived = 0; for (ZonesIter zone(runtime, WithAtoms); !zone.done(); zone.next()) { if (zone->wasCollected()) { @@ -1105,14 +1142,14 @@ void Statistics::sendGCTelemetry() { } } - MOZ_ASSERT(preCollectedHeapBytes >= bytesSurvived); + MOZ_ASSERT(preCollectedGCHeapBytes >= bytesSurvived); double survivalRate = - 100.0 * double(bytesSurvived) / double(preCollectedHeapBytes); + 100.0 * double(bytesSurvived) / double(preCollectedGCHeapBytes); runtime->metrics().GC_TENURED_SURVIVAL_RATE(survivalRate); // Calculate 'effectiveness' in MB / second, on main thread only for now. if (!runtime->parentRuntime) { - size_t bytesFreed = preCollectedHeapBytes - bytesSurvived; + size_t bytesFreed = preCollectedGCHeapBytes - bytesSurvived; TimeDuration clampedTotal = TimeDuration::Max(total, TimeDuration::FromMilliseconds(1)); double effectiveness = @@ -1244,14 +1281,18 @@ void Statistics::endSlice() { } } - if (!aborted && - ShouldPrintProfile(gc->rt, enableProfiling_, profileWorkers_, - profileThreshold_, slices_.back().duration())) { - printSliceProfile(); - } - - // Slice callbacks should only fire for the outermost level. if (!aborted) { + if (ShouldPrintProfile(gc->rt, enableProfiling_, profileWorkers_, + profileThreshold_, slices_.back().duration())) { + printSliceProfile(); + } + + if (enableBufferAllocStats_ && gc->rt->isMainRuntime()) { + maybePrintProfileHeaders(); + BufferAllocator::printStats(gc, creationTime(), true, profileFile()); + } + + // Slice callbacks should only fire for the outermost level. if (sliceCallback) { JSContext* cx = context(); JS::GCDescription desc(!gc->fullGCRequested, last, gcOptions, @@ -1313,18 +1354,28 @@ void Statistics::sendSliceTelemetry(const SliceData& slice) { // Record the longest phase in any long slice. if (wasLongSlice) { PhaseKind longest = LongestPhaseSelfTimeInMajorGC(slice.phaseTimes); - reportLongestPhaseInMajorGC(longest, [runtime](auto sample) { - runtime->metrics().GC_SLOW_PHASE(sample); - }); + reportLongestPhaseInMajorGC( + longest, + [runtime](auto sample) { + runtime->metrics().GC_SLOW_PHASE(sample); + }, + [runtime](auto sample) { + runtime->metrics().GC_GLEAN_SLOW_PHASE(sample); + }); // If the longest phase was waiting for parallel tasks then record the // longest task. if (longest == PhaseKind::JOIN_PARALLEL_TASKS) { PhaseKind longestParallel = FindLongestPhaseKind(slice.maxParallelTimes); - reportLongestPhaseInMajorGC(longestParallel, [runtime](auto sample) { - runtime->metrics().GC_SLOW_TASK(sample); - }); + reportLongestPhaseInMajorGC( + longestParallel, + [runtime](auto sample) { + runtime->metrics().GC_SLOW_TASK(sample); + }, + [runtime](auto sample) { + runtime->metrics().GC_GLEAN_SLOW_TASK(sample); + }); } } } @@ -1334,11 +1385,14 @@ void Statistics::sendSliceTelemetry(const SliceData& slice) { } } -template -void Statistics::reportLongestPhaseInMajorGC(PhaseKind longest, Fn reportFn) { +template +void Statistics::reportLongestPhaseInMajorGC(PhaseKind longest, + LegacyFn legacyReportFn, + GleanFn gleanReportFn) { if (longest != PhaseKind::NONE) { uint8_t bucket = phaseKinds[longest].telemetryBucket; - reportFn(bucket); + legacyReportFn(bucket); + gleanReportFn(static_cast(longest)); } } @@ -1518,7 +1572,7 @@ void Statistics::recordParallelPhase(PhaseKind phaseKind, TimeDuration duration) { MOZ_ASSERT(CurrentThreadCanAccessRuntime(gc->rt)); - if (aborted) { + if (slices_.empty()) { return; } @@ -1607,10 +1661,15 @@ double Statistics::computeMMU(TimeDuration window) const { void Statistics::maybePrintProfileHeaders() { static int printedHeader = 0; if ((printedHeader++ % 200) == 0) { - printProfileHeader(); + if (enableProfiling_) { + printProfileHeader(); + } if (gc->nursery().enableProfiling()) { gc->nursery().printProfileHeader(); } + if (enableBufferAllocStats_) { + BufferAllocator::printStatsHeader(profileFile()); + } } } @@ -1626,7 +1685,8 @@ void Statistics::maybePrintProfileHeaders() { _("Reason", 20, "%-20.20s", reason) \ _("States", 6, "%6s", formatGCStates(slice)) \ _("FSNR", 4, "%4s", formatGCFlags(slice)) \ - _("SizeKB", 8, "%8zu", sizeKB) \ + _("SizeKB", 8, "%8zu", gcSizeKB) \ + _("MllcKB", 8, "%8zu", mallocSizeKB) \ _("Zs", 3, "%3zu", zoneCount) \ _("Cs", 3, "%3zu", compartmentCount) \ _("Rs", 3, "%3zu", realmCount) \ @@ -1637,10 +1697,6 @@ void Statistics::maybePrintProfileHeaders() { FOR_EACH_GC_PROFILE_SLICE_METADATA(_) void Statistics::printProfileHeader() { - if (!enableProfiling_) { - return; - } - Sprinter sprinter; if (!sprinter.init()) { return; @@ -1692,7 +1748,8 @@ void Statistics::printSliceProfile() { JSRuntime* runtime = gc->rt; TimeDuration timestamp = TimeBetween(creationTime(), slice.end); const char* reason = ExplainGCReason(slice.reason); - size_t sizeKB = gc->heapSize.bytes() / 1024; + size_t gcSizeKB = gc->heapSize.bytes() / 1024; + size_t mallocSizeKB = getMallocHeapSize() / 1024; size_t zoneCount = zoneStats.zoneCount; size_t compartmentCount = zoneStats.compartmentCount; size_t realmCount = zoneStats.realmCount; @@ -1712,6 +1769,14 @@ void Statistics::printSliceProfile() { fputs(str.get(), profileFile()); } +size_t Statistics::getMallocHeapSize() { + size_t bytes = 0; + for (AllZonesIter zone(gc); !zone.done(); zone.next()) { + bytes += zone->mallocHeapSize.bytes(); + } + return bytes; +} + Statistics::ProfileDurations Statistics::getProfileTimes( const SliceData& slice) const { ProfileDurations times; diff --git a/src/third_party/mozjs/extract/js/src/gc/Statistics.h b/src/third_party/mozjs/extract/js/src/gc/Statistics.h index bc6d7bf5ddc..f6b2b03857f 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Statistics.h +++ b/src/third_party/mozjs/extract/js/src/gc/Statistics.h @@ -61,14 +61,14 @@ enum Count { // Stats can be set with Statistics::setStat(). They're not reset automatically. enum Stat { - // Number of strings tenured. - STAT_STRINGS_TENURED, + // Number of strings promoted. + STAT_STRINGS_PROMOTED, // Number of strings deduplicated. STAT_STRINGS_DEDUPLICATED, - // Number of BigInts tenured. - STAT_BIGINTS_TENURED, + // Number of BigInts promoted. + STAT_BIGINTS_PROMOTED, STAT_LIMIT }; @@ -178,7 +178,7 @@ struct Statistics { void resumePhases(); void beginSlice(const ZoneGCStats& zoneStats, JS::GCOptions options, - const SliceBudget& budget, JS::GCReason reason, + const JS::SliceBudget& budget, JS::GCReason reason, bool budgetWasIncreased); void endSlice(); @@ -196,7 +196,7 @@ struct Statistics { } } - void measureInitialHeapSize(); + void measureInitialHeapSizes(); void nonincremental(GCAbortReason reason) { MOZ_ASSERT(reason != GCAbortReason::None); @@ -253,11 +253,11 @@ struct Statistics { static const size_t MAX_SUSPENDED_PHASES = MAX_PHASE_NESTING * 3; struct SliceData { - SliceData(const SliceBudget& budget, mozilla::Maybe trigger, + SliceData(const JS::SliceBudget& budget, mozilla::Maybe trigger, JS::GCReason reason, TimeStamp start, size_t startFaults, gc::State initialState); - SliceBudget budget; + JS::SliceBudget budget; JS::GCReason reason = JS::GCReason::NO_REASON; mozilla::Maybe trigger; gc::State initialState = gc::State::NotActive; @@ -295,7 +295,7 @@ struct Statistics { TimeStamp creationTime() const { return creationTime_; } TimeDuration totalGCTime() const { return totalGCTime_; } - size_t initialCollectedBytes() const { return preCollectedHeapBytes; } + size_t initialCollectedBytes() const { return preCollectedGCHeapBytes; } // File to write profiling information to, either stderr or file specified // with JS_GC_PROFILE_FILE. @@ -322,11 +322,13 @@ struct Statistics { // Return JSON for the previous nursery collection. UniqueChars renderNurseryJson() const; + bool bufferAllocStatsEnabled() const { return enableBufferAllocStats_; } + #ifdef DEBUG // Print a logging message. void log(const char* fmt, ...); #else - void log(const char* fmt, ...){}; + void log(const char* fmt, ...) {}; #endif private: @@ -384,11 +386,15 @@ struct Statistics { uint32_t tenuredAllocsSinceMinorGC; /* Total GC heap size before and after the GC ran. */ - size_t preTotalHeapBytes; - size_t postTotalHeapBytes; + size_t preTotalGCHeapBytes; + size_t postTotalGCHeapBytes; /* GC heap size for collected zones before GC ran. */ - size_t preCollectedHeapBytes; + size_t preCollectedGCHeapBytes; + + /* Total malloc heap size before and after the GC ran. */ + size_t preTotalMallocHeapBytes; + size_t postTotalMallocHeapBytes; /* * If a GC slice was triggered by exceeding some threshold, record the @@ -444,6 +450,7 @@ struct Statistics { bool enableProfiling_ = false; bool profileWorkers_ = false; + bool enableBufferAllocStats_ = false; TimeDuration profileThreshold_; ProfileDurations totalTimes_; uint64_t sliceCount_; @@ -471,8 +478,9 @@ struct Statistics { void sccDurations(TimeDuration* total, TimeDuration* maxPause) const; void printStats(); - template - void reportLongestPhaseInMajorGC(PhaseKind longest, Fn reportFn); + template + void reportLongestPhaseInMajorGC(PhaseKind longest, LegacyFn legacyReportFn, + GleanFn gleanReportFn); UniqueChars formatCompactSlicePhaseTimes(const PhaseTimes& phaseTimes) const; @@ -497,13 +505,21 @@ struct Statistics { const char* formatGCFlags(const SliceData& slice); const char* formatBudget(const SliceData& slice); const char* formatTotalSlices(); + + size_t getMallocHeapSize(); + + void getBufferedAllocatorStats(Zone* zone, size_t& mediumChunks, + size_t& mediumTenuredChunks, + size_t& largeNurseryAllocs, + size_t& largeTenuredAllocs); + static void printProfileTimes(const ProfileDurations& times, Sprinter& sprinter); }; struct MOZ_RAII AutoGCSlice { AutoGCSlice(Statistics& stats, const ZoneGCStats& zoneStats, - JS::GCOptions options, const SliceBudget& budget, + JS::GCOptions options, const JS::SliceBudget& budget, JS::GCReason reason, bool budgetWasIncreased) : stats(stats) { stats.beginSlice(zoneStats, options, budget, reason, budgetWasIncreased); diff --git a/src/third_party/mozjs/extract/js/src/gc/StatsPhasesGenerated.inc b/src/third_party/mozjs/extract/js/src/gc/StatsPhasesGenerated.inc index 96fb89a85b9..43746a11810 100644 --- a/src/third_party/mozjs/extract/js/src/gc/StatsPhasesGenerated.inc +++ b/src/third_party/mozjs/extract/js/src/gc/StatsPhasesGenerated.inc @@ -32,7 +32,7 @@ static constexpr PhaseKindTable phaseKinds = { /* PhaseKind::FINALIZE_START */ PhaseKindInfo { Phase::FINALIZE_START, 17, "FINALIZE_START" }, /* PhaseKind::UPDATE_ATOMS_BITMAP */ PhaseKindInfo { Phase::UPDATE_ATOMS_BITMAP, 68, "UPDATE_ATOMS_BITMAP" }, /* PhaseKind::SWEEP_ATOMS_TABLE */ PhaseKindInfo { Phase::SWEEP_ATOMS_TABLE, 18, "SWEEP_ATOMS_TABLE" }, - /* PhaseKind::SWEEP_DISCARD_CODE */ PhaseKindInfo { Phase::SWEEP_DISCARD_CODE, 21, "SWEEP_DISCARD_CODE" }, + /* PhaseKind::SWEEP_JIT_SCRIPTS */ PhaseKindInfo { Phase::SWEEP_JIT_SCRIPTS, 21, "SWEEP_JIT_SCRIPTS" }, /* PhaseKind::SWEEP_INNER_VIEWS */ PhaseKindInfo { Phase::SWEEP_INNER_VIEWS, 22, "SWEEP_INNER_VIEWS" }, /* PhaseKind::SWEEP_CC_WRAPPER */ PhaseKindInfo { Phase::SWEEP_CC_WRAPPER, 23, "SWEEP_CC_WRAPPER" }, /* PhaseKind::SWEEP_BASE_SHAPE */ PhaseKindInfo { Phase::SWEEP_BASE_SHAPE, 24, "SWEEP_BASE_SHAPE" }, @@ -47,8 +47,6 @@ static constexpr PhaseKindTable phaseKinds = { /* PhaseKind::SWEEP_WEAK_CACHES */ PhaseKindInfo { Phase::SWEEP_WEAK_CACHES, 66, "SWEEP_WEAK_CACHES" }, /* PhaseKind::SWEEP_MISC */ PhaseKindInfo { Phase::SWEEP_MISC, 29, "SWEEP_MISC" }, /* PhaseKind::SWEEP_COMPARTMENTS */ PhaseKindInfo { Phase::SWEEP_COMPARTMENTS, 20, "SWEEP_COMPARTMENTS" }, - /* PhaseKind::FINALIZE_OBJECT */ PhaseKindInfo { Phase::FINALIZE_OBJECT, 33, "FINALIZE_OBJECT" }, - /* PhaseKind::FINALIZE_NON_OBJECT */ PhaseKindInfo { Phase::FINALIZE_NON_OBJECT, 34, "FINALIZE_NON_OBJECT" }, /* PhaseKind::SWEEP_PROP_MAP */ PhaseKindInfo { Phase::SWEEP_PROP_MAP, 77, "SWEEP_PROP_MAP" }, /* PhaseKind::FINALIZE_END */ PhaseKindInfo { Phase::FINALIZE_END, 38, "FINALIZE_END" }, /* PhaseKind::DESTROY */ PhaseKindInfo { Phase::DESTROY, 39, "DESTROY" }, @@ -124,8 +122,8 @@ static constexpr PhaseTable phases = { /* Phase::WEAK_COMPARTMENT_CALLBACK */ PhaseInfo { Phase::FINALIZE_START, Phase::NONE, Phase::NONE, Phase::NONE, PhaseKind::WEAK_COMPARTMENT_CALLBACK, 2, "Per-Compartment Weak Callback", "sweep.finalize_start.weak_compartment_callback" }, /* Phase::UPDATE_ATOMS_BITMAP */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::SWEEP_ATOMS_TABLE, Phase::NONE, PhaseKind::UPDATE_ATOMS_BITMAP, 1, "Sweep Atoms Bitmap", "sweep.update_atoms_bitmap" }, /* Phase::SWEEP_ATOMS_TABLE */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::SWEEP_COMPARTMENTS, Phase::NONE, PhaseKind::SWEEP_ATOMS_TABLE, 1, "Sweep Atoms Table", "sweep.sweep_atoms_table" }, - /* Phase::SWEEP_COMPARTMENTS */ PhaseInfo { Phase::SWEEP, Phase::SWEEP_DISCARD_CODE, Phase::FINALIZE_OBJECT, Phase::NONE, PhaseKind::SWEEP_COMPARTMENTS, 1, "Sweep Compartments", "sweep.sweep_compartments" }, - /* Phase::SWEEP_DISCARD_CODE */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::SWEEP_INNER_VIEWS, Phase::NONE, PhaseKind::SWEEP_DISCARD_CODE, 2, "Sweep Discard Code", "sweep.sweep_compartments.sweep_discard_code" }, + /* Phase::SWEEP_COMPARTMENTS */ PhaseInfo { Phase::SWEEP, Phase::SWEEP_JIT_SCRIPTS, Phase::SWEEP_PROP_MAP, Phase::NONE, PhaseKind::SWEEP_COMPARTMENTS, 1, "Sweep Compartments", "sweep.sweep_compartments" }, + /* Phase::SWEEP_JIT_SCRIPTS */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::SWEEP_INNER_VIEWS, Phase::NONE, PhaseKind::SWEEP_JIT_SCRIPTS, 2, "Sweep JitScripts", "sweep.sweep_compartments.sweep_jit_scripts" }, /* Phase::SWEEP_INNER_VIEWS */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::SWEEP_CC_WRAPPER, Phase::NONE, PhaseKind::SWEEP_INNER_VIEWS, 2, "Sweep Inner Views", "sweep.sweep_compartments.sweep_inner_views" }, /* Phase::SWEEP_CC_WRAPPER */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::SWEEP_BASE_SHAPE, Phase::NONE, PhaseKind::SWEEP_CC_WRAPPER, 2, "Sweep Cross Compartment Wrappers", "sweep.sweep_compartments.sweep_cc_wrapper" }, /* Phase::SWEEP_BASE_SHAPE */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::SWEEP_INITIAL_SHAPE, Phase::NONE, PhaseKind::SWEEP_BASE_SHAPE, 2, "Sweep Base Shapes", "sweep.sweep_compartments.sweep_base_shape" }, @@ -140,8 +138,6 @@ static constexpr PhaseTable phases = { /* Phase::SWEEP_WEAK_CACHES */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::SWEEP_MISC, Phase::NONE, PhaseKind::SWEEP_WEAK_CACHES, 2, "Sweep Weak Caches", "sweep.sweep_compartments.sweep_weak_caches" }, /* Phase::SWEEP_MISC */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::JOIN_PARALLEL_TASKS_4, Phase::NONE, PhaseKind::SWEEP_MISC, 2, "Sweep Miscellaneous", "sweep.sweep_compartments.sweep_misc" }, /* Phase::JOIN_PARALLEL_TASKS_4 */ PhaseInfo { Phase::SWEEP_COMPARTMENTS, Phase::NONE, Phase::NONE, Phase::JOIN_PARALLEL_TASKS_5, PhaseKind::JOIN_PARALLEL_TASKS, 2, "Join Parallel Tasks", "sweep.sweep_compartments.join_parallel_tasks" }, - /* Phase::FINALIZE_OBJECT */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::FINALIZE_NON_OBJECT, Phase::NONE, PhaseKind::FINALIZE_OBJECT, 1, "Finalize Objects", "sweep.finalize_object" }, - /* Phase::FINALIZE_NON_OBJECT */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::SWEEP_PROP_MAP, Phase::NONE, PhaseKind::FINALIZE_NON_OBJECT, 1, "Finalize Non-objects", "sweep.finalize_non_object" }, /* Phase::SWEEP_PROP_MAP */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::FINALIZE_END, Phase::NONE, PhaseKind::SWEEP_PROP_MAP, 1, "Sweep PropMap Tree", "sweep.sweep_prop_map" }, /* Phase::FINALIZE_END */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::DESTROY, Phase::NONE, PhaseKind::FINALIZE_END, 1, "Finalize End Callback", "sweep.finalize_end" }, /* Phase::DESTROY */ PhaseInfo { Phase::SWEEP, Phase::NONE, Phase::JOIN_PARALLEL_TASKS_5, Phase::NONE, PhaseKind::DESTROY, 1, "Deallocate", "sweep.destroy" }, diff --git a/src/third_party/mozjs/extract/js/src/gc/StoreBuffer-inl.h b/src/third_party/mozjs/extract/js/src/gc/StoreBuffer-inl.h index 343b953e3a7..3b5e6f95a28 100644 --- a/src/third_party/mozjs/extract/js/src/gc/StoreBuffer-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/StoreBuffer-inl.h @@ -49,7 +49,7 @@ inline void ArenaCellSet::check() const { MOZ_ASSERT(isEmpty() == !arena); if (!isEmpty()) { MOZ_ASSERT(IsCellPointerValid(arena)); - JSRuntime* runtime = arena->zone->runtimeFromMainThread(); + JSRuntime* runtime = arena->zone()->runtimeFromMainThread(); uint64_t minorGCCount = runtime->gc.minorGCCount(); MOZ_ASSERT(minorGCCount == minorGCNumberAtCreation || minorGCCount == minorGCNumberAtCreation + 1); @@ -87,6 +87,13 @@ inline void StoreBuffer::WholeCellBuffer::putDontCheckLast(const Cell* cell) { last_ = cell; } +/* static */ +inline bool StoreBuffer::isInWholeCellBuffer(Cell* cell) { + TenuredCell* tenured = &cell->asTenured(); + gc::ArenaCellSet* cells = tenured->arena()->bufferedCells(); + return cells && cells->hasCell(tenured); +} + inline void StoreBuffer::putWholeCell(Cell* cell) { bufferWholeCell.put(cell); } inline void StoreBuffer::putWholeCellDontCheckLast(Cell* cell) { bufferWholeCell.putDontCheckLast(cell); diff --git a/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.cpp b/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.cpp index 1f8023bc62b..357d63be852 100644 --- a/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.cpp @@ -31,23 +31,26 @@ void StoreBuffer::checkAccess() const { #endif bool StoreBuffer::WholeCellBuffer::init() { - MOZ_ASSERT(!head_); + MOZ_ASSERT(!sweepHead_); if (!storage_) { - storage_ = MakeUnique(LifoAllocBlockSize); - // This prevents LifoAlloc::Enum from crashing with a release - // assertion if we ever allocate one entry larger than - // LifoAllocBlockSize. - if (storage_) { - storage_->disableOversize(); + storage_ = MakeUnique(LifoAllocBlockSize, js::MallocArena); + if (!storage_) { + return false; } } + + // This prevents LifoAlloc::Enum from crashing with a release + // assertion if we ever allocate one entry larger than + // LifoAllocBlockSize. + storage_->disableOversize(); + clear(); - return bool(storage_); + return true; } bool StoreBuffer::GenericBuffer::init() { if (!storage_) { - storage_ = MakeUnique(LifoAllocBlockSize); + storage_ = MakeUnique(LifoAllocBlockSize, js::MallocArena); } clear(); return bool(storage_); @@ -190,13 +193,12 @@ void StoreBuffer::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, ArenaCellSet ArenaCellSet::Empty; -ArenaCellSet::ArenaCellSet(Arena* arena, ArenaCellSet* next) - : arena(arena), - next(next) +ArenaCellSet::ArenaCellSet(Arena* arena) + : arena(arena) #ifdef DEBUG , minorGCNumberAtCreation( - arena->zone->runtimeFromMainThread()->gc.minorGCCount()) + arena->zone()->runtimeFromMainThread()->gc.minorGCCount()) #endif { MOZ_ASSERT(arena); @@ -204,20 +206,21 @@ ArenaCellSet::ArenaCellSet(Arena* arena, ArenaCellSet* next) } ArenaCellSet* StoreBuffer::WholeCellBuffer::allocateCellSet(Arena* arena) { - Zone* zone = arena->zone; + MOZ_ASSERT(arena->bufferedCells() == &ArenaCellSet::Empty); + + Zone* zone = arena->zone(); JSRuntime* rt = zone->runtimeFromMainThread(); if (!rt->gc.nursery().isEnabled()) { return nullptr; } AutoEnterOOMUnsafeRegion oomUnsafe; - auto* cells = storage_->new_(arena, head_); + auto* cells = storage_->new_(arena); if (!cells) { oomUnsafe.crash("Failed to allocate ArenaCellSet"); } arena->bufferedCells() = cells; - head_ = cells; if (isAboutToOverflow()) { rt->gc.storeBuffer().setAboutToOverflow( @@ -233,10 +236,11 @@ void gc::CellHeaderPostWriteBarrier(JSObject** ptr, JSObject* prev, } void StoreBuffer::WholeCellBuffer::clear() { - for (auto* set = head_; set; set = set->next) { - set->arena->bufferedCells() = &ArenaCellSet::Empty; + for (LifoAlloc::Enum e(*storage_); !e.empty();) { + ArenaCellSet* cellSet = e.read(); + cellSet->arena->bufferedCells() = &ArenaCellSet::Empty; } - head_ = nullptr; + sweepHead_ = nullptr; if (storage_) { storage_->used() ? storage_->releaseAll() : storage_->freeAll(); diff --git a/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.h b/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.h index 0b1ca8af9b0..bcde3ccc873 100644 --- a/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.h +++ b/src/third_party/mozjs/extract/js/src/gc/StoreBuffer.h @@ -169,7 +169,7 @@ class StoreBuffer { struct WholeCellBuffer { UniquePtr storage_; - ArenaCellSet* head_ = nullptr; + ArenaCellSet* sweepHead_ = nullptr; const Cell* last_ = nullptr; WholeCellBuffer() = default; @@ -179,9 +179,9 @@ class StoreBuffer { WholeCellBuffer(WholeCellBuffer&& other) : storage_(std::move(other.storage_)), - head_(other.head_), + sweepHead_(other.sweepHead_), last_(other.last_) { - other.head_ = nullptr; + other.sweepHead_ = nullptr; other.last_ = nullptr; } WholeCellBuffer& operator=(WholeCellBuffer&& other) { @@ -210,21 +210,10 @@ class StoreBuffer { return storage_ ? storage_->sizeOfIncludingThis(mallocSizeOf) : 0; } - bool isEmpty() const { - MOZ_ASSERT_IF(!head_, !storage_ || storage_->isEmpty()); - return !head_; - } + bool isEmpty() const { return !storage_ || storage_->isEmpty(); } const Cell** lastBufferedPtr() { return &last_; } - CellSweepSet releaseCellSweepSet() { - CellSweepSet set; - std::swap(storage_, set.storage_); - std::swap(head_, set.head_); - last_ = nullptr; - return set; - } - private: ArenaCellSet* allocateCellSet(Arena* arena); }; @@ -393,33 +382,31 @@ class StoreBuffer { bool operator!=(const SlotsEdge& other) const { return !(*this == other); } - // True if this SlotsEdge range overlaps with the other SlotsEdge range, - // false if they do not overlap. - bool overlaps(const SlotsEdge& other) const { + // True if this SlotsEdge range is adjacent to or overlaps with the other + // SlotsEdge range. The adjacency case will coalesce a series of increasing + // or decreasing single index writes 0, 1, 2, ..., N into a SlotsEdge range + // of elements [0, N]. + bool touches(const SlotsEdge& other) const { if (objectAndKind_ != other.objectAndKind_) { return false; } - // Widen our range by one on each side so that we consider - // adjacent-but-not-actually-overlapping ranges as overlapping. This - // is particularly useful for coalescing a series of increasing or - // decreasing single index writes 0, 1, 2, ..., N into a SlotsEdge - // range of elements [0, N]. - uint32_t end = start_ + count_ + 1; - uint32_t start = start_ > 0 ? start_ - 1 : 0; - MOZ_ASSERT(start < end); + if (other.start_ < start_) { + // If the other range starts before this one, then it touches if its + // (exclusive) end is at or after this range. + return other.start_ + other.count_ >= start_; + } - uint32_t otherEnd = other.start_ + other.count_; - MOZ_ASSERT(other.start_ <= otherEnd); - return (start <= other.start_ && other.start_ <= end) || - (start <= otherEnd && otherEnd <= end); + // Otherwise, the other range touches if it starts before or at + // the exclusive end of this range. + return other.start_ <= start_ + count_; } // Destructively make this SlotsEdge range the union of the other // SlotsEdge range and this one. A precondition is that the ranges must // overlap. void merge(const SlotsEdge& other) { - MOZ_ASSERT(overlaps(other)); + MOZ_ASSERT(touches(other)); uint32_t end = std::max(start_ + count_, other.start_ + other.count_); start_ = std::min(start_, other.start_); count_ = end - start_; @@ -585,7 +572,7 @@ class StoreBuffer { void putSlot(NativeObject* obj, int kind, uint32_t start, uint32_t count) { SlotsEdge edge(obj, kind, start, count); - if (bufferSlot.last_.overlaps(edge)) { + if (bufferSlot.last_.touches(edge)) { bufferSlot.last_.merge(edge); } else { put(bufferSlot, edge, JS::GCReason::FULL_SLOT_BUFFER); @@ -600,6 +587,7 @@ class StoreBuffer { unput(bufferWasmAnyRef, WasmAnyRefEdge(vp)); } + static inline bool isInWholeCellBuffer(Cell* cell); inline void putWholeCell(Cell* cell); inline void putWholeCellDontCheckLast(Cell* cell); const void* addressOfLastBufferedWholeCell() { @@ -630,10 +618,6 @@ class StoreBuffer { } void traceGenericEntries(JSTracer* trc) { bufferGeneric.trace(trc, this); } - gc::CellSweepSet releaseCellSweepSet() { - return bufferWholeCell.releaseCellSweepSet(); - } - /* For use by our owned buffers and for testing. */ void setAboutToOverflow(JS::GCReason); @@ -651,10 +635,11 @@ class ArenaCellSet { using ArenaCellBits = BitArray; // The arena this relates to. - Arena* arena; + Arena* arena = nullptr; - // Pointer to next set forming a linked list. - ArenaCellSet* next; + // Pointer to next set forming a linked list. Used to form the list of cell + // sets to sweep. + ArenaCellSet* next = nullptr; // Bit vector for each possible cell start position. ArenaCellBits bits; @@ -662,26 +647,18 @@ class ArenaCellSet { #ifdef DEBUG // The minor GC number when this was created. This object should not survive // past the next minor collection. - const uint64_t minorGCNumberAtCreation; + const uint64_t minorGCNumberAtCreation = 0; #endif // Construct the empty sentinel object. - constexpr ArenaCellSet() - : arena(nullptr), - next(nullptr) -#ifdef DEBUG - , - minorGCNumberAtCreation(0) -#endif - { - } + constexpr ArenaCellSet() = default; public: using WordT = ArenaCellBits::WordT; - const size_t BitsPerWord = ArenaCellBits::bitsPerElement; - const size_t NumWords = ArenaCellBits::numSlots; + static constexpr size_t BitsPerWord = ArenaCellBits::bitsPerElement; + static constexpr size_t NumWords = ArenaCellBits::numSlots; - ArenaCellSet(Arena* arena, ArenaCellSet* next); + explicit ArenaCellSet(Arena* arena); bool hasCell(const TenuredCell* cell) const { return hasCell(getCellIndex(cell)); @@ -703,13 +680,8 @@ class ArenaCellSet { bits.setWord(wordIndex, value); } - // Returns the list of ArenaCellSets that need to be swept. - ArenaCellSet* trace(TenuringTracer& mover); - - // At the end of a minor GC, sweep through all tenured dependent strings that - // may point to nursery-allocated chars to update their pointers in case the - // base string moved its chars. - void sweepDependentStrings(); + // Sweep this set, returning whether it also needs to be swept later. + bool trace(TenuringTracer& mover); // Sentinel object used for all empty sets. // diff --git a/src/third_party/mozjs/extract/js/src/gc/Sweeping.cpp b/src/third_party/mozjs/extract/js/src/gc/Sweeping.cpp index 1738a93c90b..c6387aa6b20 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Sweeping.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Sweeping.cpp @@ -16,6 +16,7 @@ * sweep phase. This is also implemented in this file. */ +#include "mozilla/DebugOnly.h" #include "mozilla/Maybe.h" #include "mozilla/ScopeExit.h" #include "mozilla/TimeStamp.h" @@ -24,6 +25,7 @@ #include "builtin/WeakRefObject.h" #include "debugger/DebugAPI.h" #include "gc/AllocKind.h" +#include "gc/BufferAllocator.h" #include "gc/FinalizationObservers.h" #include "gc/GCInternals.h" #include "gc/GCLock.h" @@ -41,6 +43,7 @@ #include "vm/BigIntType.h" #include "vm/HelperThreads.h" #include "vm/JSContext.h" +#include "vm/Probes.h" #include "vm/Time.h" #include "vm/WrapperObject.h" @@ -54,48 +57,80 @@ using namespace js; using namespace js::gc; +using mozilla::DebugOnly; using mozilla::TimeStamp; -struct js::gc::FinalizePhase { - gcstats::PhaseKind statsPhase; - AllocKinds kinds; -}; +using JS::SliceBudget; /* - * Finalization order for objects swept incrementally on the main thread. + * Sweeping of arenas and possible finalization of dead cells proceeds in a + * sequence of phases. + * + * 1. ForegroundObjectFinalizePhase + * JSObjects with finalizers. Swept incrementally on the main thread. + * + * 2. ForegroundNonObjectFinalizePhase + * Non-JSObjects with finalizers. Swept incrementally on the main thread. + * + * 3. BackgroundObjectFinalizePhase + * JSObjects with finalizers that can run off main thread. Swept + * non-incrementally on a helper thread. + * + * 4. BackgroundTrivialFinalizePhase + * Everything else. These may or may not have finalizers. Any finalizers + * must not delete HeapPtrs. Swept non-incrementally on a helper thread. */ -static constexpr FinalizePhase ForegroundObjectFinalizePhase = { - gcstats::PhaseKind::FINALIZE_OBJECT, - {AllocKind::OBJECT0, AllocKind::OBJECT2, AllocKind::OBJECT4, - AllocKind::OBJECT8, AllocKind::OBJECT12, AllocKind::OBJECT16}}; -/* - * Finalization order for GC things swept incrementally on the main thread. - */ -static constexpr FinalizePhase ForegroundNonObjectFinalizePhase = { - gcstats::PhaseKind::FINALIZE_NON_OBJECT, - {AllocKind::SCRIPT, AllocKind::JITCODE}}; +static constexpr AllocKinds ForegroundObjectFinalizePhase = { + AllocKind::OBJECT0_FOREGROUND, AllocKind::OBJECT2_FOREGROUND, + AllocKind::OBJECT4_FOREGROUND, AllocKind::OBJECT8_FOREGROUND, + AllocKind::OBJECT12_FOREGROUND, AllocKind::OBJECT16_FOREGROUND}; -/* - * Finalization order for GC things swept on the background thread. - */ -static constexpr FinalizePhase BackgroundFinalizePhases[] = { - {gcstats::PhaseKind::FINALIZE_OBJECT, - {AllocKind::FUNCTION, AllocKind::FUNCTION_EXTENDED, - AllocKind::OBJECT0_BACKGROUND, AllocKind::OBJECT2_BACKGROUND, - AllocKind::ARRAYBUFFER4, AllocKind::OBJECT4_BACKGROUND, - AllocKind::ARRAYBUFFER8, AllocKind::OBJECT8_BACKGROUND, - AllocKind::ARRAYBUFFER12, AllocKind::OBJECT12_BACKGROUND, - AllocKind::ARRAYBUFFER16, AllocKind::OBJECT16_BACKGROUND}}, - {gcstats::PhaseKind::FINALIZE_NON_OBJECT, - {AllocKind::SCOPE, AllocKind::REGEXP_SHARED, AllocKind::FAT_INLINE_STRING, - AllocKind::STRING, AllocKind::EXTERNAL_STRING, AllocKind::FAT_INLINE_ATOM, - AllocKind::ATOM, AllocKind::SYMBOL, AllocKind::BIGINT, AllocKind::SHAPE, - AllocKind::BASE_SHAPE, AllocKind::GETTER_SETTER, - AllocKind::COMPACT_PROP_MAP, AllocKind::NORMAL_PROP_MAP, - AllocKind::DICT_PROP_MAP}}}; +static constexpr AllocKinds ForegroundNonObjectFinalizePhase = { + AllocKind::SCRIPT, AllocKind::JITCODE}; -template +static constexpr AllocKinds BackgroundObjectFinalizePhase = { + AllocKind::OBJECT0_BACKGROUND, AllocKind::OBJECT2_BACKGROUND, + AllocKind::ARRAYBUFFER4, AllocKind::OBJECT4_BACKGROUND, + AllocKind::ARRAYBUFFER8, AllocKind::OBJECT8_BACKGROUND, + AllocKind::ARRAYBUFFER12, AllocKind::OBJECT12_BACKGROUND, + AllocKind::ARRAYBUFFER16, AllocKind::OBJECT16_BACKGROUND}; + +static constexpr AllocKinds BackgroundTrivialFinalizePhase = { + AllocKind::FUNCTION, + AllocKind::FUNCTION_EXTENDED, + AllocKind::OBJECT0, + AllocKind::OBJECT2, + AllocKind::OBJECT4, + AllocKind::OBJECT8, + AllocKind::OBJECT12, + AllocKind::OBJECT16, + AllocKind::BUFFER16, + AllocKind::BUFFER32, + AllocKind::BUFFER64, + AllocKind::BUFFER128, + AllocKind::SCOPE, + AllocKind::REGEXP_SHARED, + AllocKind::FAT_INLINE_STRING, + AllocKind::STRING, + AllocKind::EXTERNAL_STRING, + AllocKind::FAT_INLINE_ATOM, + AllocKind::ATOM, + AllocKind::SYMBOL, + AllocKind::BIGINT, + AllocKind::SHAPE, + AllocKind::BASE_SHAPE, + AllocKind::GETTER_SETTER, + AllocKind::COMPACT_PROP_MAP, + AllocKind::NORMAL_PROP_MAP, + AllocKind::DICT_PROP_MAP}; + +static constexpr AllocKinds AllBackgroundSweptKinds = + BackgroundObjectFinalizePhase + BackgroundTrivialFinalizePhase; + +static constexpr size_t ArenaReleaseBatchSize = 32; + +template inline size_t Arena::finalize(JS::GCContext* gcx, AllocKind thingKind, size_t thingSize) { /* Enforce requirements on size of T. */ @@ -108,29 +143,37 @@ inline size_t Arena::finalize(JS::GCContext* gcx, AllocKind thingKind, MOZ_ASSERT(thingSize == getThingSize()); MOZ_ASSERT(!onDelayedMarkingList_); - uint_fast16_t firstThing = firstThingOffset(thingKind); - uint_fast16_t firstThingOrSuccessorOfLastMarkedThing = firstThing; - uint_fast16_t lastThing = ArenaSize - thingSize; + MOZ_ASSERT(finalizeKind == GetFinalizeKind(thingKind)); - FreeSpan newListHead; - FreeSpan* newListTail = &newListHead; - size_t nmarked = 0, nfinalized = 0; + uint_fast16_t freeStart = firstThingOffset(thingKind); + + // Update the free list as we go along. The cell iterator will always be ahead + // of this pointer when it is written through, so the write will not interfere + // with the iteration. + FreeSpan* newListTail = &firstFreeSpan; + + size_t nmarked = 0; + size_t nfinalized = 0; for (ArenaCellIterUnderFinalize cell(this); !cell.done(); cell.next()) { T* t = cell.as(); if (TenuredThingIsMarkedAny(t)) { uint_fast16_t thing = uintptr_t(t) & ArenaMask; - if (thing != firstThingOrSuccessorOfLastMarkedThing) { + if (thing != freeStart) { // We just finished passing over one or more free things, // so record a new FreeSpan. - newListTail->initBounds(firstThingOrSuccessorOfLastMarkedThing, - thing - thingSize, this); + newListTail->initBounds(freeStart, thing - thingSize, this); newListTail = newListTail->nextSpanUnchecked(this); } - firstThingOrSuccessorOfLastMarkedThing = thing + thingSize; + freeStart = thing + thingSize; nmarked++; } else { - t->finalize(gcx); + if constexpr (std::is_same_v) { + js::probes::FinalizeObject(t); + } + if constexpr (finalizeKind != FinalizeKind::None) { + t->finalize(gcx); + } AlwaysPoison(t, JS_SWEPT_TENURED_PATTERN, thingSize, MemCheckKind::MakeUndefined); gcprobes::TenuredFinalize(t); @@ -141,46 +184,34 @@ inline size_t Arena::finalize(JS::GCContext* gcx, AllocKind thingKind, if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) { if (isNewlyCreated_) { - zone->pretenuring.updateCellCountsInNewlyCreatedArenas( + zone()->pretenuring.updateCellCountsInNewlyCreatedArenas( nmarked + nfinalized, nmarked); } } isNewlyCreated_ = 0; - if (nmarked == 0) { - // Do nothing. The caller will update the arena appropriately. - MOZ_ASSERT(newListTail == &newListHead); - DebugOnlyPoison(data, JS_SWEPT_TENURED_PATTERN, sizeof(data), - MemCheckKind::MakeUndefined); - return nmarked; - } - - MOZ_ASSERT(firstThingOrSuccessorOfLastMarkedThing != firstThing); - uint_fast16_t lastMarkedThing = - firstThingOrSuccessorOfLastMarkedThing - thingSize; - if (lastThing == lastMarkedThing) { + if (freeStart == ArenaSize) { // If the last thing was marked, we will have already set the bounds of // the final span, and we just need to terminate the list. newListTail->initAsEmpty(); } else { // Otherwise, end the list with a span that covers the final stretch of free // things. - newListTail->initFinal(firstThingOrSuccessorOfLastMarkedThing, lastThing, - this); + newListTail->initFinal(freeStart, ArenaSize - thingSize, this); } - firstFreeSpan = newListHead; #ifdef DEBUG size_t nfree = numFreeThings(thingSize); MOZ_ASSERT(nfree + nmarked == thingsPerArena(thingKind)); #endif + return nmarked; } // Finalize arenas from src list, releasing empty arenas if keepArenas wasn't // specified and inserting the others into the appropriate destination size // bins. -template +template static inline bool FinalizeTypedArenas(JS::GCContext* gcx, ArenaList& src, SortedArenaList& dest, AllocKind thingKind, @@ -190,22 +221,35 @@ static inline bool FinalizeTypedArenas(JS::GCContext* gcx, ArenaList& src, size_t thingSize = Arena::thingSize(thingKind); size_t thingsPerArena = Arena::thingsPerArena(thingKind); size_t markCount = 0; + size_t emptyCount = 0; - auto updateMarkCount = mozilla::MakeScopeExit([&] { - GCRuntime* gc = &gcx->runtimeFromAnyThread()->gc; - gc->stats().addCount(gcstats::COUNT_CELLS_MARKED, markCount); - }); + GCRuntime* gc = &gcx->runtimeFromAnyThread()->gc; + auto updateMarkCount = mozilla::MakeScopeExit( + [&] { gc->stats().addCount(gcstats::COUNT_CELLS_MARKED, markCount); }); - while (Arena* arena = src.takeFirstArena()) { - size_t nmarked = arena->finalize(gcx, thingKind, thingSize); + while (!src.isEmpty()) { + Arena* arena = src.popFront(); + size_t nmarked = + arena->finalize(gcx, thingKind, thingSize); size_t nfree = thingsPerArena - nmarked; markCount += nmarked; - if (nmarked) { - dest.insertAt(arena, nfree); - } else { - arena->chunk()->recycleArena(arena, dest, thingsPerArena); + dest.insertAt(arena, nfree); + + if constexpr (bool(releaseEmpty)) { + if (nmarked == 0) { + emptyCount++; + MOZ_ASSERT(emptyCount <= ArenaReleaseBatchSize); + if (emptyCount == ArenaReleaseBatchSize) { + Arena* emptyArenas = nullptr; + dest.extractEmptyTo(&emptyArenas); + emptyArenas = + gc->releaseSomeEmptyArenas(emptyArenas->zone(), emptyArenas); + MOZ_ASSERT(!emptyArenas); + emptyCount = 0; + } + } } budget.step(thingsPerArena); @@ -214,20 +258,32 @@ static inline bool FinalizeTypedArenas(JS::GCContext* gcx, ArenaList& src, } } + if constexpr (bool(releaseEmpty)) { + if (emptyCount) { + Arena* emptyArenas = nullptr; + dest.extractEmptyTo(&emptyArenas); + emptyArenas = + gc->releaseSomeEmptyArenas(emptyArenas->zone(), emptyArenas); + MOZ_ASSERT(!emptyArenas); + } + } + return true; } /* * Finalize the list of areans. */ +template static bool FinalizeArenas(JS::GCContext* gcx, ArenaList& src, SortedArenaList& dest, AllocKind thingKind, SliceBudget& budget) { switch (thingKind) { -#define EXPAND_CASE(allocKind, traceKind, type, sizedType, bgFinal, nursery, \ - compact) \ - case AllocKind::allocKind: \ - return FinalizeTypedArenas(gcx, src, dest, thingKind, budget); +#define EXPAND_CASE(allocKind, _1, type, _2, finalizeKind, _3, _4) \ + case AllocKind::allocKind: \ + return FinalizeTypedArenas(gcx, src, dest, thingKind, \ + budget); FOR_EACH_ALLOCKIND(EXPAND_CASE) #undef EXPAND_CASE @@ -237,15 +293,14 @@ static bool FinalizeArenas(JS::GCContext* gcx, ArenaList& src, } void GCRuntime::initBackgroundSweep(Zone* zone, JS::GCContext* gcx, - const FinalizePhase& phase) { - gcstats::AutoPhase ap(stats(), phase.statsPhase); - for (auto kind : phase.kinds) { + const AllocKinds& kinds) { + for (AllocKind kind : kinds) { zone->arenas.initBackgroundSweep(kind); } } void ArenaLists::initBackgroundSweep(AllocKind thingKind) { - MOZ_ASSERT(IsBackgroundFinalized(thingKind)); + MOZ_ASSERT(IsBackgroundSwept(thingKind)); MOZ_ASSERT(concurrentUse(thingKind) == ConcurrentUse::None); if (!collectingArenaList(thingKind).isEmpty()) { @@ -253,74 +308,78 @@ void ArenaLists::initBackgroundSweep(AllocKind thingKind) { } } -void GCRuntime::backgroundFinalize(JS::GCContext* gcx, Zone* zone, - AllocKind kind, Arena** empty) { - MOZ_ASSERT(empty); +template +void ArenaLists::backgroundFinalize(JS::GCContext* gcx, AllocKind kind, + Arena** empty) { + MOZ_ASSERT(IsBackgroundSwept(kind)); + MOZ_ASSERT(bool(empty) != bool(releaseEmpty)); - ArenaLists* lists = &zone->arenas; - ArenaList& arenas = lists->collectingArenaList(kind); + ArenaList& arenas = collectingArenaList(kind); if (arenas.isEmpty()) { - MOZ_ASSERT(lists->concurrentUse(kind) == ArenaLists::ConcurrentUse::None); + MOZ_ASSERT(concurrentUse(kind) == ConcurrentUse::None); return; } + MOZ_ASSERT(concurrentUse(kind) == ConcurrentUse::BackgroundFinalize); SortedArenaList finalizedSorted(kind); auto unlimited = SliceBudget::unlimited(); - FinalizeArenas(gcx, arenas, finalizedSorted, kind, unlimited); + FinalizeArenas(gcx, arenas, finalizedSorted, kind, unlimited); MOZ_ASSERT(arenas.isEmpty()); - finalizedSorted.extractEmptyTo(empty); - - // When marking begins, all arenas are moved from arenaLists to - // collectingArenaLists. When the mutator runs, new arenas are allocated in - // arenaLists. Now that finalization is complete, we want to merge these lists - // back together. - - // We must take the GC lock to be able to safely modify the ArenaList; - // however, this does not by itself make the changes visible to all threads, - // as not all threads take the GC lock to read the ArenaLists. - // That safety is provided by the ReleaseAcquire memory ordering of the - // background finalize state, which we explicitly set as the final step. - { - AutoLockGC lock(rt); - MOZ_ASSERT(lists->concurrentUse(kind) == - ArenaLists::ConcurrentUse::BackgroundFinalize); - lists->mergeFinalizedArenas(kind, finalizedSorted); + if constexpr (!bool(releaseEmpty)) { + finalizedSorted.extractEmptyTo(empty); } + MOZ_ASSERT(!finalizedSorted.hasEmptyArenas()); - lists->concurrentUse(kind) = ArenaLists::ConcurrentUse::None; + // Set the collectingArenaList to the possibly empty list of swept arenas + // while holding the GC lock. Set concurrentUse to indicate to the main thread + // that sweeping has finished. + ArenaList sweptArenas = finalizedSorted.convertToArenaList(); + + AutoLockGC lock(gcx->runtimeFromAnyThread()); + collectingArenaList(kind) = std::move(sweptArenas); + concurrentUse(kind) = ConcurrentUse::BackgroundFinalizeFinished; } -// After finalizing arenas, merge the following to get the final state of an -// arena list: +void ArenaLists::mergeBackgroundSweptArenas() { + // Merge swept arenas into main arena lists on the main thread. + MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime())); + + for (AllocKind kind : AllBackgroundSweptKinds) { + maybeMergeSweptArenas(kind); + } +} + +void ArenaLists::maybeMergeSweptArenas(AllocKind kind) { + MOZ_ASSERT(zone_->isGCFinished()); + MOZ_ASSERT(concurrentUse(kind) != ConcurrentUse::BackgroundFinalize); + + if (concurrentUse(kind) == ConcurrentUse::BackgroundFinalizeFinished) { + concurrentUse(kind) = ConcurrentUse::None; + mergeSweptArenas(kind, collectingArenaList(kind)); + } + + MOZ_ASSERT(collectingArenaList(kind).isEmpty()); +} + +// This methods merges the following to get the final state of an arena +// list: +// - swept arenas // - arenas allocated during marking // - arenas allocated during sweeping -// - finalized arenas -void ArenaLists::mergeFinalizedArenas(AllocKind kind, - SortedArenaList& finalizedArenas) { -#ifdef DEBUG - // Updating arena lists off-thread requires taking the GC lock because the - // main thread uses these when allocating. - if (IsBackgroundFinalized(kind)) { - runtimeFromAnyThread()->gc.assertCurrentThreadHasLockedGC(); - } -#endif +void ArenaLists::mergeSweptArenas(AllocKind kind, ArenaList& sweptArenas) { + MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime())); + MOZ_ASSERT(concurrentUse(kind) == ConcurrentUse::None); - ArenaList& arenas = arenaList(kind); - - ArenaList allocatedDuringCollection = std::move(arenas); - arenas = finalizedArenas.convertToArenaList(); - arenas.insertListWithCursorAtEnd(allocatedDuringCollection); - - collectingArenaList(kind).clear(); + arenaList(kind).prepend(std::move(sweptArenas)); } void ArenaLists::queueForegroundThingsForSweep() { gcCompactPropMapArenasToUpdate = - collectingArenaList(AllocKind::COMPACT_PROP_MAP).head(); + collectingArenaList(AllocKind::COMPACT_PROP_MAP).first(); gcNormalPropMapArenasToUpdate = - collectingArenaList(AllocKind::NORMAL_PROP_MAP).head(); + collectingArenaList(AllocKind::NORMAL_PROP_MAP).first(); } void GCRuntime::sweepBackgroundThings(ZoneList& zones) { @@ -339,35 +398,44 @@ void GCRuntime::sweepBackgroundThings(ZoneList& zones) { TimeStamp startTime = TimeStamp::Now(); - Arena* emptyArenas = zone->arenas.takeSweptEmptyArenas(); + ArenaLists& arenaLists = zone->arenas; + Arena* emptyArenas = arenaLists.takeSweptEmptyArenas(); - // We must finalize thing kinds in the order specified by - // BackgroundFinalizePhases. - for (const auto& phase : BackgroundFinalizePhases) { - for (auto kind : phase.kinds) { - backgroundFinalize(gcx, zone, kind, &emptyArenas); - } + // We must finalize kinds in the order specified at the top of this file. + + for (auto kind : BackgroundObjectFinalizePhase) { + MOZ_ASSERT(IsBackgroundFinalized(kind)); + arenaLists.backgroundFinalize(gcx, kind, &emptyArenas); } // Release any arenas that are now empty. // - // Empty arenas are only released after everything has been finalized so - // that it's still possible to get a thing's zone after the thing has been - // finalized. The HeapPtr destructor depends on this, and this allows - // HeapPtrs between things of different alloc kind regardless of - // finalization order. + // Finalizers can still access the zone pointer in now-empty arenas because + // of the write barrier in the HeapPtr destructor. This means we can't + // release any empty arenas until all such finalizers have been run. // - // Periodically drop and reaquire the GC lock every so often to avoid - // blocking the main thread from allocating chunks. - static const size_t LockReleasePeriod = 32; + // At this point this has happened and we can release empty arenas + // immediately from now on. + + AutoDisallowPreWriteBarrier disallowBarrier(gcx); while (emptyArenas) { - AutoLockGC lock(this); - for (size_t i = 0; i < LockReleasePeriod && emptyArenas; i++) { - Arena* arena = emptyArenas; - emptyArenas = emptyArenas->next; - releaseArena(arena, lock); - } + emptyArenas = releaseSomeEmptyArenas(zone, emptyArenas); + } + + // Now everything with a non-trivial finalizer has been finalized we can + // sweep buffer memory. + // + // Note we depend on this happening before the BUFFER alloc kinds in + // BackgroundTrivialFinalizePhase are swept! + bool decommit = shouldDecommit() && DecommitEnabled(); + zone->bufferAllocator.sweepForMajorCollection(decommit); + + // TODO: The remaining sweeping work can be parallelised between multiple + // threads. + for (AllocKind kind : BackgroundTrivialFinalizePhase) { + MOZ_ASSERT(IsBackgroundSwept(kind)); + arenaLists.backgroundFinalize(gcx, kind); } // Record time spent sweeping this zone. @@ -376,6 +444,60 @@ void GCRuntime::sweepBackgroundThings(ZoneList& zones) { } } +Arena* GCRuntime::releaseSomeEmptyArenas(Zone* zone, Arena* emptyArenas) { + // Batch releases so as to periodically drop and reaquire the GC lock to + // avoid blocking the main thread from allocating arenas. This is important + // for allocation-heavy workloads such as the splay benchmark. + // + // This block is equivalent to calling GCRuntime::releaseArena on each arena + // individually. + bool isAtomsZone = zone->isAtomsZone(); + + Arena* arenasToRelease[ArenaReleaseBatchSize]; + size_t atomsBitmapIndexes[ArenaReleaseBatchSize]; + size_t count = 0; + + size_t gcHeapBytesFreed = 0; + size_t mallocHeapBytesFreed = 0; + + // Take up to ArenaReleaseBatchSize arenas from emptyArenas list. + for (size_t i = 0; emptyArenas && i < ArenaReleaseBatchSize; i++) { + Arena* arena = emptyArenas; + emptyArenas = arena->next; + + if (IsBufferAllocKind(arena->getAllocKind())) { + mallocHeapBytesFreed += ArenaSize - arena->getFirstThingOffset(); + } else { + gcHeapBytesFreed += ArenaSize; + } + + if (isAtomsZone) { + atomsBitmapIndexes[i] = arena->atomBitmapStart(); +#ifdef DEBUG + arena->atomBitmapStart() = 0; +#endif + } + + arena->release(); + arenasToRelease[i] = arena; + count++; + } + + zone->mallocHeapSize.removeBytes(mallocHeapBytesFreed, true); + zone->gcHeapSize.removeBytes(gcHeapBytesFreed, true, heapSize); + + AutoLockGC lock(this); + for (size_t i = 0; i < count; i++) { + Arena* arena = arenasToRelease[i]; + if (isAtomsZone) { + atomMarking.freeIndex(atomsBitmapIndexes[i], lock); + } + arena->chunk()->releaseArena(this, arena, lock); + } + + return emptyArenas; +} + void GCRuntime::assertBackgroundSweepingFinished() { #ifdef DEBUG { @@ -385,8 +507,7 @@ void GCRuntime::assertBackgroundSweepingFinished() { for (ZonesIter zone(this, WithAtoms); !zone.done(); zone.next()) { for (auto kind : AllAllocKinds()) { - MOZ_ASSERT_IF(state() != State::Prepare && state() != State::Mark && - state() != State::Sweep, + MOZ_ASSERT_IF(state() == State::NotActive || state() >= State::Compact, zone->arenas.collectingArenaList(kind).isEmpty()); MOZ_ASSERT(zone->arenas.doneBackgroundFinalize(kind)); } @@ -434,16 +555,22 @@ void GCRuntime::sweepFromBackgroundThread(AutoLockHelperThreadState& lock) { void GCRuntime::waitBackgroundSweepEnd() { sweepTask.join(); + for (AllZonesIter zone(this); !zone.done(); zone.next()) { + if (zone->isGCFinished()) { + zone->arenas.mergeBackgroundSweptArenas(); + } + } if (state() != State::Sweep) { assertBackgroundSweepingFinished(); } } +void GCRuntime::waitBackgroundDecommitEnd() { decommitTask.join(); } + void GCRuntime::startBackgroundFree() { AutoLockHelperThreadState lock; - if (lifoBlocksToFree.ref().isEmpty() && - buffersToFreeAfterMinorGC.ref().empty()) { + if (!hasBuffersForBackgroundFree()) { return; } @@ -461,12 +588,16 @@ void BackgroundFreeTask::run(AutoLockHelperThreadState& lock) { void GCRuntime::freeFromBackgroundThread(AutoLockHelperThreadState& lock) { do { - LifoAlloc lifoBlocks(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE); + LifoAlloc lifoBlocks(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE, + js::BackgroundMallocArena); lifoBlocks.transferFrom(&lifoBlocksToFree.ref()); Nursery::BufferSet buffers; std::swap(buffers, buffersToFreeAfterMinorGC.ref()); + Nursery::StringBufferVector stringBuffers; + std::swap(stringBuffers, stringBuffersToReleaseAfterMinorGC.ref()); + AutoUnlockHelperThreadState unlock(lock); lifoBlocks.freeAll(); @@ -478,8 +609,11 @@ void GCRuntime::freeFromBackgroundThread(AutoLockHelperThreadState& lock) { // are assumed to be short lived. gcx->freeUntracked(r.front()); } - } while (!lifoBlocksToFree.ref().isEmpty() || - !buffersToFreeAfterMinorGC.ref().empty()); + + for (auto* buffer : stringBuffers) { + buffer->Release(); + } + } while (hasBuffersForBackgroundFree()); } void GCRuntime::waitBackgroundFreeEnd() { freeTask.join(); } @@ -514,10 +648,7 @@ IncrementalProgress GCRuntime::markWeakReferences( // needs to be cleared first, then populated. if (!marker().incrementalWeakMapMarkingEnabled) { for (ZoneIterT zone(this); !zone.done(); zone.next()) { - AutoEnterOOMUnsafeRegion oomUnsafe; - if (!zone->gcEphemeronEdges().clear()) { - oomUnsafe.crash("clearing weak keys when entering weak marking mode"); - } + zone->gcEphemeronEdges().clearAndCompact(); } } @@ -556,7 +687,6 @@ IncrementalProgress GCRuntime::markWeakReferencesInCurrentGroup( return markWeakReferences(budget); } -template IncrementalProgress GCRuntime::markGrayRoots(SliceBudget& budget, gcstats::PhaseKind phase) { MOZ_ASSERT(marker().markColor() == MarkColor::Black); @@ -595,8 +725,15 @@ IncrementalProgress GCRuntime::markAllWeakReferences() { } void GCRuntime::markAllGrayReferences(gcstats::PhaseKind phase) { +#ifdef DEBUG + // Check zones are in the correct state to be marked. + for (GCZonesIter zone(this); !zone.done(); zone.next()) { + MOZ_ASSERT(zone->isGCMarkingBlackAndGray()); + } +#endif + SliceBudget budget = SliceBudget::unlimited(); - markGrayRoots(budget, phase); + markGrayRoots(budget, phase); drainMarkStack(); } @@ -684,7 +821,7 @@ bool Zone::findSweepGroupEdges(Zone* atomsZone) { } } - return WeakMapBase::findSweepGroupEdgesForZone(this); + return WeakMapBase::findSweepGroupEdgesForZone(atomsZone, this); } bool GCRuntime::addEdgesForMarkQueue() { @@ -779,7 +916,7 @@ void GCRuntime::groupZonesForSweeping(JS::GCReason reason) { #endif } -void GCRuntime::getNextSweepGroup() { +void GCRuntime::moveToNextSweepGroup() { currentSweepGroup = currentSweepGroup->nextGroup(); ++sweepGroupIndex; if (!currentSweepGroup) { @@ -792,7 +929,7 @@ void GCRuntime::getNextSweepGroup() { ZoneComponentFinder::mergeGroups(currentSweepGroup); } - for (Zone* zone = currentSweepGroup; zone; zone = zone->nextNodeInGroup()) { + for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { MOZ_ASSERT(zone->gcState() == zone->initialMarkingState()); MOZ_ASSERT(!zone->isQueuedForBackgroundSweep()); } @@ -803,7 +940,7 @@ void GCRuntime::getNextSweepGroup() { // Abort collection of subsequent sweep groups. for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { MOZ_ASSERT(!zone->gcNextGraphComponent); - zone->changeGCState(zone->initialMarkingState(), Zone::NoGC); + zone->changeGCState(zone->initialMarkingState(), Zone::Finished); zone->arenas.unmarkPreMarkedFreeCells(); zone->arenas.mergeArenasFromCollectingLists(); zone->clearGCSliceThresholds(); @@ -1127,12 +1264,28 @@ IncrementalProgress GCRuntime::beginMarkingSweepGroup(JS::GCContext* gcx, return Finished; } +#ifdef DEBUG +bool GCRuntime::zoneInCurrentSweepGroup(Zone* zone) const { + MOZ_ASSERT_IF(!zone->wasGCStarted(), !zone->gcNextGraphComponent); + return zone->wasGCStarted() && + zone->gcNextGraphComponent == currentSweepGroup->nextGroup(); +} +#endif + IncrementalProgress GCRuntime::markGrayRootsInCurrentGroup( JS::GCContext* gcx, SliceBudget& budget) { gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK); - return markGrayRoots(budget, - gcstats::PhaseKind::MARK_GRAY); + // Check that the zone state is set correctly for the current sweep group as + // that determines what gets marked. + MOZ_ASSERT(atomsZone()->wasGCStarted() == + atomsZone()->isGCMarkingBlackAndGray()); + for (NonAtomZonesIter zone(this); !zone.done(); zone.next()) { + MOZ_ASSERT(zone->isGCMarkingBlackAndGray() == + zoneInCurrentSweepGroup(zone)); + } + + return markGrayRoots(budget, gcstats::PhaseKind::MARK_GRAY); } IncrementalProgress GCRuntime::markGray(JS::GCContext* gcx, @@ -1268,10 +1421,7 @@ void GCRuntime::sweepWeakMaps() { SweepingTracer trc(rt); for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { /* No need to look up any more weakmap keys from this sweep group. */ - AutoEnterOOMUnsafeRegion oomUnsafe; - if (!zone->gcEphemeronEdges().clear()) { - oomUnsafe.crash("clearing weak keys in beginSweepingSweepGroup()"); - } + zone->gcEphemeronEdges().clearAndCompact(); // Lock the storebuffer since this may access it when rehashing or resizing // the tables. @@ -1365,24 +1515,16 @@ void GCRuntime::sweepJitDataOnMainThread(JS::GCContext* gcx) { jit::JitRuntime::TraceWeakJitcodeGlobalTable(rt, &trc); } - // Discard JIT code and trace weak edges in JitScripts to remove edges to - // dying GC things. The latter is carried out as part of discardJitCode if - // possible to avoid iterating all scripts in the zone twice. + // Trace weak edges in JitScripts to remove edges to dying GC things. { - gcstats::AutoPhase apdc(stats(), gcstats::PhaseKind::SWEEP_DISCARD_CODE); - Zone::DiscardOptions options; - options.traceWeakJitScripts = &trc; + gcstats::AutoPhase apdc(stats(), gcstats::PhaseKind::SWEEP_JIT_SCRIPTS); for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { - if (!haveDiscardedJITCodeThisSlice && !zone->isPreservingCode()) { - zone->forceDiscardJitCode(gcx, options); - } else { - zone->traceWeakJitScripts(&trc); - } + zone->traceWeakJitScripts(&trc); } } - // JitZone must be swept *after* discarding JIT code, because - // Zone::discardJitCode might access CacheIRStubInfos deleted here. + // JitZone must be swept *after* sweeping JitScripts, because + // Zone::traceWeakJitScripts might access CacheIRStubInfos deleted here. { gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_JIT_DATA); @@ -1541,12 +1683,6 @@ IncrementalProgress GCRuntime::beginSweepingSweepGroup(JS::GCContext* gcx, cellsToAssertNotGray.ref().clearAndFree(); #endif - // Cancel off thread compilation as soon as possible, unless this already - // happened in GCRuntime::discardJITCodeForGC. - if (!haveDiscardedJITCodeThisSlice) { - js::CancelOffThreadIonCompile(rt, JS::Zone::Sweep); - } - // Updating the atom marking bitmaps. This marks atoms referenced by // uncollected zones so cannot be done in parallel with the other sweeping // work below. @@ -1631,11 +1767,10 @@ IncrementalProgress GCRuntime::beginSweepingSweepGroup(JS::GCContext* gcx, // or on the background thread. for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { - for (const auto& phase : BackgroundFinalizePhases) { - initBackgroundSweep(zone, gcx, phase); - } - zone->arenas.queueForegroundThingsForSweep(); + constexpr AllocKinds backgroundKinds = + BackgroundObjectFinalizePhase + BackgroundTrivialFinalizePhase; + initBackgroundSweep(zone, gcx, backgroundKinds); } MOZ_ASSERT(!sweepZone); @@ -1696,19 +1831,29 @@ IncrementalProgress GCRuntime::endSweepingSweepGroup(JS::GCContext* gcx, zone->pretenuring.clearCellCountsInNewlyCreatedArenas(); } + /* Ensure the initial minor GC has finished sweeping. */ + MOZ_ASSERT(minorGCNumber >= initialMinorGCNumber); + if (minorGCNumber == initialMinorGCNumber) { + nursery().joinSweepTask(); + } + /* * Start background thread to sweep zones if required, sweeping any atoms * zones last if present. */ ZoneList zones; - for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { - if (zone->isAtomsZone()) { - zones.append(zone); - } else { - zones.prepend(zone); + { + BufferAllocator::MaybeLock lock; + for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) { + if (zone->isAtomsZone()) { + zones.append(zone); + } else { + zones.prepend(zone); + } + + zone->bufferAllocator.startMajorSweeping(lock); } } - queueZonesAndStartBackgroundSweep(std::move(zones)); return Finished; @@ -1763,25 +1908,24 @@ void GCRuntime::beginSweepPhase(JS::GCReason reason, AutoGCSession& session) { sweepActions->assertFinished(); } -bool GCRuntime::foregroundFinalize(JS::GCContext* gcx, Zone* zone, - AllocKind thingKind, - SliceBudget& sliceBudget, - SortedArenaList& sweepList) { - ArenaLists& lists = zone->arenas; - lists.checkNoArenasToUpdateForKind(thingKind); +bool ArenaLists::foregroundFinalize(JS::GCContext* gcx, AllocKind thingKind, + SliceBudget& sliceBudget, + SortedArenaList& sweepList) { + checkNoArenasToUpdateForKind(thingKind); // Non-empty arenas are reused for use for new allocations as soon as the // finalizers for that allocation kind have run. Empty arenas are only // released when everything in the zone has been swept (see // GCRuntime::sweepBackgroundThings for more details). - if (!FinalizeArenas(gcx, lists.collectingArenaList(thingKind), sweepList, - thingKind, sliceBudget)) { + ArenaList& arenas = collectingArenaList(thingKind); + if (!FinalizeArenas(gcx, arenas, sweepList, thingKind, + sliceBudget)) { return false; } - sweepList.extractEmptyTo(&lists.savedEmptyArenas.ref()); - lists.mergeFinalizedArenas(thingKind, sweepList); - + sweepList.extractEmptyTo(&savedEmptyArenas.ref()); + ArenaList sweptArenas = sweepList.convertToArenaList(); + mergeSweptArenas(thingKind, sweptArenas); return true; } @@ -1818,26 +1962,36 @@ static void SweepThing(JS::GCContext* gcx, T* thing) { } template -static bool SweepArenaList(JS::GCContext* gcx, Arena** arenasToSweep, - SliceBudget& sliceBudget) { - while (Arena* arena = *arenasToSweep) { - MOZ_ASSERT(arena->zone->isGCSweeping()); +static bool SweepArenaList(JS::GCContext* gcx, ArenaList& arenaList, + Arena** arenasToSweep, SliceBudget& sliceBudget) { + if (!*arenasToSweep) { + return true; + } - for (ArenaCellIterUnderGC cell(arena); !cell.done(); cell.next()) { + DebugOnly zone = (*arenasToSweep)->zone(); + MOZ_ASSERT(zone->isGCSweeping()); + + AllocKind kind = MapTypeToAllocKind::kind; + size_t steps = Arena::thingsPerArena(kind); + + for (auto arena = arenaList.iterFrom(*arenasToSweep); !arena.done(); + arena.next()) { + MOZ_ASSERT(arena->zone() == zone); + MOZ_ASSERT(arena->getAllocKind() == kind); + + if (sliceBudget.isOverBudget()) { + *arenasToSweep = arena.get(); + return false; + } + + for (ArenaCellIterUnderGC cell(arena.get()); !cell.done(); cell.next()) { SweepThing(gcx, cell.as()); } - Arena* next = arena->next; - MOZ_ASSERT_IF(next, next->zone == arena->zone); - *arenasToSweep = next; - - AllocKind kind = MapTypeToAllocKind::kind; - sliceBudget.step(Arena::thingsPerArena(kind)); - if (sliceBudget.isOverBudget()) { - return false; - } + sliceBudget.step(steps); } + *arenasToSweep = nullptr; return true; } @@ -1978,8 +2132,9 @@ IncrementalProgress GCRuntime::finalizeAllocKind(JS::GCContext* gcx, } AutoSetThreadIsFinalizing threadIsFinalizing(gcx); - if (!foregroundFinalize(gcx, sweepZone, sweepAllocKind, budget, - finalizedArenas.ref())) { + ArenaLists& arenaLists = sweepZone->arenas; + if (!arenaLists.foregroundFinalize(gcx, sweepAllocKind, budget, + finalizedArenas.ref())) { return NotFinished; } @@ -2017,11 +2172,13 @@ IncrementalProgress GCRuntime::sweepPropMapTree(JS::GCContext* gcx, ArenaLists& al = sweepZone->arenas; if (!SweepArenaList( - gcx, &al.gcCompactPropMapArenasToUpdate.ref(), budget)) { + gcx, al.collectingArenaList(AllocKind::COMPACT_PROP_MAP), + &al.gcCompactPropMapArenasToUpdate.ref(), budget)) { return NotFinished; } if (!SweepArenaList( - gcx, &al.gcNormalPropMapArenasToUpdate.ref(), budget)) { + gcx, al.collectingArenaList(AllocKind::NORMAL_PROP_MAP), + &al.gcNormalPropMapArenasToUpdate.ref(), budget)) { return NotFinished; } @@ -2102,7 +2259,7 @@ class js::gc::SweepGroupsIter { void next() { MOZ_ASSERT(!done()); - gc->getNextSweepGroup(); + gc->moveToNextSweepGroup(); } }; @@ -2285,7 +2442,7 @@ static UniquePtr ForEachZoneInSweepGroup( return js::MakeUnique(rt, zoneOut, std::move(action)); } -static UniquePtr ForEachAllocKind(AllocKinds kinds, +static UniquePtr ForEachAllocKind(const AllocKinds& kinds, AllocKind* kindOut, UniquePtr action) { if (!action) { @@ -2318,11 +2475,11 @@ bool GCRuntime::initSweepActions() { ForEachZoneInSweepGroup( rt, &sweepZone.ref(), Sequence(MaybeYield(ZealMode::YieldBeforeSweepingObjects), - ForEachAllocKind(ForegroundObjectFinalizePhase.kinds, + ForEachAllocKind(ForegroundObjectFinalizePhase, &sweepAllocKind.ref(), Call(&GCRuntime::finalizeAllocKind)), MaybeYield(ZealMode::YieldBeforeSweepingNonObjects), - ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds, + ForEachAllocKind(ForegroundNonObjectFinalizePhase, &sweepAllocKind.ref(), Call(&GCRuntime::finalizeAllocKind)), MaybeYield(ZealMode::YieldBeforeSweepingPropMapTrees), @@ -2350,7 +2507,8 @@ void GCRuntime::prepareForSweepSlice(JS::GCReason reason) { } IncrementalProgress GCRuntime::performSweepActions(SliceBudget& budget) { - MOZ_ASSERT(!storeBuffer().mayHavePointersToDeadCells()); + MOZ_ASSERT_IF(storeBuffer().isEnabled(), + !storeBuffer().mayHavePointersToDeadCells()); AutoMajorGCProfilerEntry s(this); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP); @@ -2459,14 +2617,5 @@ void GCRuntime::endSweepPhase(bool destroyingRuntime) { finishMarkingValidation(); #endif -#ifdef DEBUG - for (ZonesIter zone(this, WithAtoms); !zone.done(); zone.next()) { - for (auto i : AllAllocKinds()) { - MOZ_ASSERT_IF(!IsBackgroundFinalized(i) || !useBackgroundThreads, - zone->arenas.collectingArenaList(i).isEmpty()); - } - } -#endif - AssertNoWrappersInGrayList(rt); } diff --git a/src/third_party/mozjs/extract/js/src/gc/Tenuring.cpp b/src/third_party/mozjs/extract/js/src/gc/Tenuring.cpp index bcd2bd33044..c73958b9c5d 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Tenuring.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Tenuring.cpp @@ -10,8 +10,6 @@ #include "gc/Tenuring.h" -#include "mozilla/PodOperations.h" - #include "gc/Cell.h" #include "gc/GCInternals.h" #include "gc/GCProbes.h" @@ -34,17 +32,55 @@ #include "vm/JSObject-inl.h" #include "vm/PlainObject-inl.h" #include "vm/StringType-inl.h" -#ifdef ENABLE_RECORD_TUPLE -# include "vm/TupleType.h" -#endif - using namespace js; using namespace js::gc; -using mozilla::PodCopy; - constexpr size_t MAX_DEDUPLICATABLE_STRING_LENGTH = 500; +#ifdef JS_GC_ZEAL +class js::gc::PromotionStats { + static constexpr size_t AttentionThreshold = 100; + + size_t objectCount = 0; + size_t stringCount = 0; + size_t bigIntCount = 0; + + using BaseShapeCountMap = + HashMap, SystemAllocPolicy>; + BaseShapeCountMap objectCountByBaseShape; + + using AllocKindCountArray = + mozilla::EnumeratedArray; + AllocKindCountArray stringCountByKind; + + bool hadOOM = false; + + struct LabelAndCount { + char label[32] = {'\0'}; + size_t count = 0; + }; + using CountsVector = Vector; + + public: + void notePromotedObject(JSObject* obj); + void notePromotedString(JSString* str); + void notePromotedBigInt(JS::BigInt* bi); + + bool shouldPrintReport() const; + void printReport(JSContext* cx, const JS::AutoRequireNoGC& nogc); + + private: + void printObjectCounts(JSContext* cx, const JS::AutoRequireNoGC& nogc); + void printStringCounts(); + + void printCounts(CountsVector& counts, size_t total); + void printLine(const char* name, size_t count, size_t total); + + UniqueChars getConstructorName(JSContext* cx, BaseShape* baseShape, + const JS::AutoRequireNoGC& nogc); +}; +#endif // JS_GC_ZEAL + TenuringTracer::TenuringTracer(JSRuntime* rt, Nursery* nursery, bool tenureEverything) : JSTracer(rt, JS::TracerKind::Tenuring, @@ -54,6 +90,8 @@ TenuringTracer::TenuringTracer(JSRuntime* rt, Nursery* nursery, stringDeDupSet.emplace(); } +TenuringTracer::~TenuringTracer() = default; + size_t TenuringTracer::getPromotedSize() const { return promotedSize + promotedCells * sizeof(NurseryCellHeader); } @@ -83,13 +121,19 @@ JSObject* TenuringTracer::promoteOrForward(JSObject* obj) { return obj; } - return onNonForwardedNurseryObject(obj); + return promoteObject(obj); } -JSObject* TenuringTracer::onNonForwardedNurseryObject(JSObject* obj) { +JSObject* TenuringTracer::promoteObject(JSObject* obj) { MOZ_ASSERT(IsInsideNursery(obj)); MOZ_ASSERT(!obj->isForwarded()); +#ifdef JS_GC_ZEAL + if (promotionStats) { + promotionStats->notePromotedObject(obj); + } +#endif + // Take a fast path for promoting a plain object as this is by far the most // common case. if (obj->is()) { @@ -120,13 +164,6 @@ JSString* TenuringTracer::promoteOrForward(JSString* str) { return str; } - return onNonForwardedNurseryString(str); -} - -JSString* TenuringTracer::onNonForwardedNurseryString(JSString* str) { - MOZ_ASSERT(IsInsideNursery(str)); - MOZ_ASSERT(!str->isForwarded()); - return promoteString(str); } @@ -151,16 +188,10 @@ JS::BigInt* TenuringTracer::promoteOrForward(JS::BigInt* bi) { return bi; } - return onNonForwardedNurseryBigInt(bi); -} - -JS::BigInt* TenuringTracer::onNonForwardedNurseryBigInt(JS::BigInt* bi) { - MOZ_ASSERT(IsInsideNursery(bi)); - MOZ_ASSERT(!bi->isForwarded()); - return promoteBigInt(bi); } +// Ignore edges to cell kinds that are not allocated in the nursery. void TenuringTracer::onSymbolEdge(JS::Symbol** symp, const char* name) {} void TenuringTracer::onScriptEdge(BaseScript** scriptp, const char* name) {} void TenuringTracer::onShapeEdge(Shape** shapep, const char* name) {} @@ -171,6 +202,8 @@ void TenuringTracer::onGetterSetterEdge(GetterSetter** gsp, const char* name) {} void TenuringTracer::onPropMapEdge(PropMap** mapp, const char* name) {} void TenuringTracer::onJitCodeEdge(jit::JitCode** codep, const char* name) {} void TenuringTracer::onScopeEdge(Scope** scopep, const char* name) {} +void TenuringTracer::onSmallBufferEdge(SmallBuffer** sizedp, const char* name) { +} void TenuringTracer::traverse(JS::Value* thingp) { MOZ_ASSERT(!nursery().inCollectedRegion(thingp)); @@ -201,27 +234,19 @@ void TenuringTracer::traverse(JS::Value* thingp) { // We only care about a few kinds of GC thing here and this generates much // tighter code than using MapGCThingTyped. if (value.isObject()) { - JSObject* obj = onNonForwardedNurseryObject(&value.toObject()); + JSObject* obj = promoteObject(&value.toObject()); MOZ_ASSERT(obj != &value.toObject()); *thingp = JS::ObjectValue(*obj); return; } -#ifdef ENABLE_RECORD_TUPLE - if (value.isExtendedPrimitive()) { - JSObject* obj = onNonForwardedNurseryObject(&value.toExtendedPrimitive()); - MOZ_ASSERT(obj != &value.toExtendedPrimitive()); - *thingp = JS::ExtendedPrimitiveValue(*obj); - return; - } -#endif if (value.isString()) { - JSString* str = onNonForwardedNurseryString(value.toString()); + JSString* str = promoteString(value.toString()); MOZ_ASSERT(str != value.toString()); *thingp = JS::StringValue(str); return; } MOZ_ASSERT(value.isBigInt()); - JS::BigInt* bi = onNonForwardedNurseryBigInt(value.toBigInt()); + JS::BigInt* bi = promoteBigInt(value.toBigInt()); MOZ_ASSERT(bi != value.toBigInt()); *thingp = JS::BigIntValue(bi); } @@ -342,40 +367,41 @@ static inline void TraceWholeCell(TenuringTracer& mover, JSObject* object) { mover.traceObject(object); } -// Return whether the string needs to be swept. -// -// We can break down the relevant dependency chains as follows: -// -// T -> T2 : will not be swept, but safe because T2.chars is fixed. -// T -> N1 -> ... -> T2 : safe because T2.chars is fixed -// T -> N1 -> ... -> N2 : update T.chars += tenured(N2).chars - N2.chars -// -// Collapse the base chain down to simply T -> T2 or T -> N2. The pointer update -// will happen during sweeping. -// -// Note that in cases like T -> N1 -> T2 -> T3 -> N2, both T -> N1 and T3 -> N2 -// will be processed by the whole cell buffer (or rather, only T and T3 will -// be in the store buffer). The order that these strings are -// visited does not matter because the nursery bases are left alone until -// sweeping. -static inline bool TraceWholeCell(TenuringTracer& mover, JSString* str) { - if (str->hasBase()) { - // For tenured dependent strings -> nursery string edges, sweep the - // (tenured) strings at the end of nursery marking to update chars pointers - // that were in the nursery. Rather than updating the base pointer to point - // directly to the tenured version of itself, we will leave it pointing at - // the nursery Cell (which will become a StringRelocationOverlay during the - // minor GC.) - JSLinearString* base = str->nurseryBaseOrRelocOverlay(); - if (IsInsideNursery(base)) { - str->traceBaseFromStoreBuffer(&mover); - return IsInsideNursery(str->nurseryBaseOrRelocOverlay()); +void JSDependentString::setBase(JSLinearString* newBase) { + // This compiles down to a single assignment, with no type test. + if (isAtomRef()) { + MOZ_ASSERT(newBase->isAtom()); + d.s.u3.atom = &newBase->asAtom(); + } else { + MOZ_ASSERT(newBase->canOwnDependentChars()); + d.s.u3.base = newBase; + } + + if (isTenured() && !newBase->isTenured()) { + MOZ_ASSERT(!InCollectedNurseryRegion(newBase)); + newBase->storeBuffer()->putWholeCell(this); + } +} + +static void TraceWholeCell(TenuringTracer& mover, JSString* str) { + if (str->isDependent() && !str->isAtomRef()) { + // For tenured dependent strings -> nursery base string edges, promote the + // base immediately and then use its old chars pointer to find the offset + // needed to update the dependent string's pointer if the base string moves + // its chars. + JSDependentString* dep = &str->asDependent(); + JSLinearString* base = dep->rootBaseDuringMinorGC(); + if (InCollectedNurseryRegion(base)) { + mover.promoteOrForward(base); + dep->updateToPromotedBase(base); + } else { + // Set base to (promoted) root base. + dep->setBase(base); } + return; } str->traceChildren(&mover); - - return false; } static inline void TraceWholeCell(TenuringTracer& mover, BaseScript* script) { @@ -411,98 +437,250 @@ bool TenuringTracer::traceBufferedCells(Arena* arena, ArenaCellSet* cells) { return false; } -template <> -bool TenuringTracer::traceBufferedCells(Arena* arena, - ArenaCellSet* cells) { - bool needsSweep = false; - for (size_t i = 0; i < MaxArenaCellIndex; i += cells->BitsPerWord) { - ArenaCellSet::WordT bitset = cells->getWord(i / cells->BitsPerWord); - ArenaCellSet::WordT tosweep = bitset; - while (bitset) { - size_t bit = i + js::detail::CountTrailingZeroes(bitset); - auto* cell = reinterpret_cast(uintptr_t(arena) + - ArenaCellIndexBytes * bit); - TenuringTracer::AutoPromotedAnyToNursery promotedToNursery(*this); - bool needsSweep = TraceWholeCell(*this, cell); - if (promotedToNursery) { - runtime()->gc.storeBuffer().putWholeCell(cell); - } - ArenaCellSet::WordT mask = bitset - 1; - bitset &= mask; - if (!needsSweep) { - tosweep &= mask; - } - } +bool ArenaCellSet::trace(TenuringTracer& mover) { + check(); - cells->setWord(i / cells->BitsPerWord, tosweep); - if (tosweep) { - needsSweep = true; - } + arena->bufferedCells() = &ArenaCellSet::Empty; + + JS::TraceKind kind = MapAllocToTraceKind(arena->getAllocKind()); + switch (kind) { + case JS::TraceKind::Object: + return mover.traceBufferedCells(arena, this); + break; + case JS::TraceKind::String: + return mover.traceBufferedCells(arena, this); + break; + case JS::TraceKind::Script: + return mover.traceBufferedCells(arena, this); + break; + case JS::TraceKind::JitCode: + return mover.traceBufferedCells(arena, this); + break; + default: + MOZ_CRASH("Unexpected trace kind"); } - - return needsSweep; -} - -ArenaCellSet* ArenaCellSet::trace(TenuringTracer& mover) { - ArenaCellSet* head = nullptr; - - ArenaCellSet* cells = this; - while (cells) { - cells->check(); - - Arena* arena = cells->arena; - arena->bufferedCells() = &ArenaCellSet::Empty; - - JS::TraceKind kind = MapAllocToTraceKind(arena->getAllocKind()); - bool needsSweep; - switch (kind) { - case JS::TraceKind::Object: - needsSweep = mover.traceBufferedCells(arena, cells); - break; - case JS::TraceKind::String: - needsSweep = mover.traceBufferedCells(arena, cells); - break; - case JS::TraceKind::Script: - needsSweep = mover.traceBufferedCells(arena, cells); - break; - case JS::TraceKind::JitCode: - needsSweep = mover.traceBufferedCells(arena, cells); - break; - default: - MOZ_CRASH("Unexpected trace kind"); - } - - ArenaCellSet* next = cells->next; - if (needsSweep) { - cells->next = head; - head = cells; - } - - cells = next; - } - - return head; } void js::gc::StoreBuffer::WholeCellBuffer::trace(TenuringTracer& mover, StoreBuffer* owner) { MOZ_ASSERT(owner->isEnabled()); - if (head_) { - head_ = head_->trace(mover); + ArenaCellSet** sweepListTail = &sweepHead_; + + for (LifoAlloc::Enum e(*storage_); !e.empty();) { + ArenaCellSet* cellSet = e.read(); + bool needsSweep = cellSet->trace(mover); + if (needsSweep) { + MOZ_ASSERT(!*sweepListTail); + *sweepListTail = cellSet; + sweepListTail = &cellSet->next; + } } } -// Sweep a tenured dependent string with a nursery base. The base chain will -// have been collapsed to a single link before this string was added to the -// sweep set, so only the simple case of a tenured dependent string with a -// nursery base needs to be considered. -template -void JSDependentString::sweepTypedAfterMinorGC() { - MOZ_ASSERT(isTenured()); - MOZ_ASSERT(IsInsideNursery(nurseryBaseOrRelocOverlay())); +namespace js::gc { +// StringRelocationOverlay assists with updating the string chars +// pointers of dependent strings when their base strings are +// deduplicated. It stores: +// - nursery chars of potential root base strings +// - the original pointer to the original root base (still in the nursery if it +// was originally in the nursery, even if it has been forwarded to a promoted +// string now). +// +// StringRelocationOverlay exploits the fact that the 3rd word of a JSString's +// RelocationOverlay is not utilized and can be used to store extra information. +class StringRelocationOverlay : public RelocationOverlay { + union { + // nursery chars of a root base + const JS::Latin1Char* nurseryCharsLatin1; + const char16_t* nurseryCharsTwoByte; - JSLinearString* base = nurseryBaseOrRelocOverlay(); + // The nursery base can be forwarded, which becomes a string relocation + // overlay, or it is not yet forwarded and is simply the (nursery) base + // string. + JSLinearString* nurseryBaseOrRelocOverlay; + + // For ropes. Present only to simplify the generated code. + JSString* unusedLeftChild; + }; + + public: + StringRelocationOverlay(Cell* dst, const JS::Latin1Char* chars) + : RelocationOverlay(dst), nurseryCharsLatin1(chars) {} + + StringRelocationOverlay(Cell* dst, const char16_t* chars) + : RelocationOverlay(dst), nurseryCharsTwoByte(chars) {} + + StringRelocationOverlay(Cell* dst, JSLinearString* origBase) + : RelocationOverlay(dst), nurseryBaseOrRelocOverlay(origBase) {} + + StringRelocationOverlay(Cell* dst, JSString* origLeftChild) + : RelocationOverlay(dst), unusedLeftChild(origLeftChild) {} + + static const StringRelocationOverlay* fromCell(const Cell* cell) { + return static_cast(cell); + } + + static StringRelocationOverlay* fromCell(Cell* cell) { + return static_cast(cell); + } + + void setNext(StringRelocationOverlay* next) { + RelocationOverlay::setNext(next); + } + + StringRelocationOverlay* next() const { + MOZ_ASSERT(isForwarded()); + return (StringRelocationOverlay*)next_; + } + + template + MOZ_ALWAYS_INLINE const CharT* savedNurseryChars() const { + if constexpr (std::is_same_v) { + return savedNurseryCharsLatin1(); + } else { + return savedNurseryCharsTwoByte(); + } + } + + const MOZ_ALWAYS_INLINE JS::Latin1Char* savedNurseryCharsLatin1() const { + MOZ_ASSERT(!forwardingAddress()->as()->hasBase()); + return nurseryCharsLatin1; + } + + const MOZ_ALWAYS_INLINE char16_t* savedNurseryCharsTwoByte() const { + MOZ_ASSERT(!forwardingAddress()->as()->hasBase()); + return nurseryCharsTwoByte; + } + + JSLinearString* savedNurseryBaseOrRelocOverlay() const { + MOZ_ASSERT(forwardingAddress()->as()->hasBase()); + return nurseryBaseOrRelocOverlay; + } + + // Transform a nursery string to a StringRelocationOverlay that is forwarded + // to a promoted string. + inline static StringRelocationOverlay* forwardDependentString(JSString* src, + Cell* dst); + + // Usually only called on non-dependent strings, except for the case where a + // dependent string is converted to a linear string. + static StringRelocationOverlay* forwardString(JSString* src, Cell* dst) { + MOZ_ASSERT(!src->isForwarded()); + MOZ_ASSERT(!dst->isForwarded()); + + JS::AutoCheckCannotGC nogc; + + // Initialize the overlay for a non-dependent string (that could be the root + // base of other strings), remember nursery non-inlined chars. + // + // Note that this will store the chars pointer even when it is known that it + // will never be used (!canOwnDependentChar()), or a left child pointer of + // a rope that will never get used, in order to simplify the generated code + // to do an unconditional store. + // + // All of these compile down to + // header_.value_ = dst | 1; /* offset 0 */ + // StringRelocationOverlay.union = d.s.u2; /* offset 16 <- offset 8 */ + if (src->isLinear()) { + if (src->hasTwoByteChars()) { + auto* nurseryCharsTwoByte = src->asLinear().twoByteChars(nogc); + return new (src) StringRelocationOverlay(dst, nurseryCharsTwoByte); + } + auto* nurseryCharsLatin1 = src->asLinear().latin1Chars(nogc); + return new (src) StringRelocationOverlay(dst, nurseryCharsLatin1); + } else { + return new (src) StringRelocationOverlay( + dst, dst->as()->asRope().leftChild()); + } + } +}; + +/* static */ +StringRelocationOverlay* StringRelocationOverlay::forwardDependentString( + JSString* src, Cell* dst) { + MOZ_ASSERT(src->isDependent()); + MOZ_ASSERT(!src->isForwarded()); + MOZ_ASSERT(!dst->isForwarded()); + JSLinearString* origBase = src->asDependent().rootBaseDuringMinorGC(); + return new (src) StringRelocationOverlay(dst, origBase); +} + +} // namespace js::gc + +JSLinearString* JSDependentString::rootBaseDuringMinorGC() { + JSLinearString* root = this; + while (MaybeForwarded(root)->hasBase()) { + if (root->isForwarded()) { + root = js::gc::StringRelocationOverlay::fromCell(root) + ->savedNurseryBaseOrRelocOverlay(); + } else { + // Possibly nursery or tenured string (not an overlay). + root = root->nurseryBaseOrRelocOverlay(); + } + } + return root; +} + +template +static bool PtrIsWithinRange(const CharT* ptr, + const mozilla::Range& valid) { + return size_t(ptr - valid.begin().get()) <= valid.length(); +} + +/* static */ +template +void JSLinearString::maybeCloneCharsOnPromotionTyped(JSLinearString* str) { + MOZ_ASSERT(!InCollectedNurseryRegion(str), "str should have been promoted"); + MOZ_ASSERT(str->isDependent()); + JSLinearString* root = str->asDependent().rootBaseDuringMinorGC(); + if (InCollectedNurseryRegion(root)) { + // Can still fixup the original chars pointer. + return; + } + + // If the base has not moved its chars, continue using them. + JS::AutoCheckCannotGC nogc; + const CharT* chars = str->chars(nogc); + if (PtrIsWithinRange(chars, root->range(nogc))) { + return; + } + + // Clone the chars. + js::AutoEnterOOMUnsafeRegion oomUnsafe; + size_t len = str->length(); + size_t nbytes = len * sizeof(CharT); + CharT* data = + str->zone()->pod_arena_malloc(js::StringBufferArena, len); + if (!data) { + oomUnsafe.crash("cloning at-risk dependent string"); + } + js_memcpy(data, chars, nbytes); + + // Overwrite the dest string with a new linear string. + new (str) JSLinearString(data, len, false /* hasBuffer */); + if (str->isTenured()) { + str->zone()->addCellMemory(str, nbytes, js::MemoryUse::StringContents); + } else { + AutoEnterOOMUnsafeRegion oomUnsafe; + JSRuntime* rt = str->runtimeFromAnyThread(); + if (!rt->gc.nursery().registerMallocedBuffer(data, nbytes)) { + oomUnsafe.crash("maybeCloneCharsOnPromotionTyped"); + } + } +} + +template void JSLinearString::maybeCloneCharsOnPromotionTyped( + JSLinearString* str); +template void JSLinearString::maybeCloneCharsOnPromotionTyped( + JSLinearString* str); + +// Update a promoted dependent string with a nursery base. The base chain will +// have been collapsed to a single link, so only the simple case of a promoted +// dependent string with a nursery base needs to be considered. +template +void JSDependentString::updateToPromotedBaseImpl(JSLinearString* base) { + MOZ_ASSERT(!InCollectedNurseryRegion(this)); MOZ_ASSERT(IsInsideNursery(base)); MOZ_ASSERT(!Forwarded(base)->hasBase(), "base chain should be collapsed"); MOZ_ASSERT(base->isForwarded(), "root base should be kept alive"); @@ -516,44 +694,22 @@ void JSDependentString::sweepTypedAfterMinorGC() { // effect.) const CharT* oldChars = JSString::nonInlineCharsRaw(); size_t offset = oldChars - oldBaseChars; - JSLinearString* tenuredBase = Forwarded(base); - MOZ_ASSERT(offset < tenuredBase->length()); + JSLinearString* promotedBase = Forwarded(base); + MOZ_ASSERT(offset < promotedBase->length()); - const CharT* newBaseChars = tenuredBase->JSString::nonInlineCharsRaw(); - relocateNonInlineChars(newBaseChars, offset); - MOZ_ASSERT(tenuredBase->assertIsValidBase()); - d.s.u3.base = tenuredBase; + const CharT* newBaseChars = + promotedBase->JSString::nonInlineCharsRaw(); + relocateBaseAndChars(promotedBase, newBaseChars, offset); } -inline void JSDependentString::sweepAfterMinorGC() { +inline void JSDependentString::updateToPromotedBase(JSLinearString* base) { + // The base should have been traced. + MOZ_ASSERT(base->isForwarded() || !InCollectedNurseryRegion(base)); + if (hasTwoByteChars()) { - sweepTypedAfterMinorGC(); + updateToPromotedBaseImpl(base); } else { - sweepTypedAfterMinorGC(); - } -} - -static void SweepDependentStrings(Arena* arena, ArenaCellSet* cells) { - for (size_t i = 0; i < MaxArenaCellIndex; i += cells->BitsPerWord) { - ArenaCellSet::WordT bitset = cells->getWord(i / cells->BitsPerWord); - while (bitset) { - size_t bit = i + js::detail::CountTrailingZeroes(bitset); - auto* str = reinterpret_cast(uintptr_t(arena) + - ArenaCellIndexBytes * bit); - MOZ_ASSERT(str->isTenured()); - str->asDependent().sweepAfterMinorGC(); - bitset &= bitset - 1; // Clear the low bit. - } - } -} - -void ArenaCellSet::sweepDependentStrings() { - for (ArenaCellSet* cells = this; cells; cells = cells->next) { - Arena* arena = cells->arena; - arena->bufferedCells() = &ArenaCellSet::Empty; - MOZ_ASSERT(MapAllocToTraceKind(arena->getAllocKind()) == - JS::TraceKind::String); - SweepDependentStrings(arena, cells); + updateToPromotedBaseImpl(base); } } @@ -660,11 +816,11 @@ void js::gc::TenuringTracer::traceSlots(Value* vp, Value* end) { } void js::gc::TenuringTracer::traceString(JSString* str) { + AutoPromotedAnyToNursery promotedToNursery(*this); str->traceChildren(this); -} - -void js::gc::TenuringTracer::traceBigInt(JS::BigInt* bi) { - bi->traceChildren(this); + if (str->isTenured() && promotedToNursery) { + runtime()->gc.storeBuffer().putWholeCell(str); + } } #ifdef DEBUG @@ -857,8 +1013,8 @@ size_t js::gc::TenuringTracer::moveSlots(NativeObject* dst, NativeObject* src) { size_t allocSize = ObjectSlots::allocSize(count); ObjectSlots* header = src->getSlotsHeader(); - Nursery::WasBufferMoved result = nursery().maybeMoveBufferOnPromotion( - &header, dst, allocSize, MemoryUse::ObjectSlots); + Nursery::WasBufferMoved result = + nursery().maybeMoveBufferOnPromotion(&header, dst, allocSize); if (result == Nursery::BufferNotMoved) { return 0; } @@ -899,8 +1055,8 @@ size_t js::gc::TenuringTracer::moveElements(NativeObject* dst, /* TODO Bug 874151: Prefer to put element data inline if we have space. */ - Nursery::WasBufferMoved result = nursery().maybeMoveBufferOnPromotion( - &unshiftedHeader, dst, allocSize, MemoryUse::ObjectElements); + Nursery::WasBufferMoved result = + nursery().maybeMoveBufferOnPromotion(&unshiftedHeader, dst, allocSize); if (result == Nursery::BufferNotMoved) { return 0; } @@ -921,8 +1077,15 @@ inline void js::gc::TenuringTracer::insertIntoStringFixupList( JSString* js::gc::TenuringTracer::promoteString(JSString* src) { MOZ_ASSERT(IsInsideNursery(src)); + MOZ_ASSERT(!src->isForwarded()); MOZ_ASSERT(!src->isExternal()); +#ifdef JS_GC_ZEAL + if (promotionStats) { + promotionStats->notePromotedString(src); + } +#endif + AllocKind dstKind = src->getAllocKind(); Zone* zone = src->nurseryZone(); @@ -952,7 +1115,7 @@ JSString* js::gc::TenuringTracer::promoteString(JSString* src) { MOZ_ASSERT(src->canOwnDependentChars()); MOZ_ASSERT(atom->canOwnDependentChars()); - StringRelocationOverlay::forwardCell(src, atom); + StringRelocationOverlay::forwardString(src, atom); gcprobes::PromoteToTenured(src, atom); return atom; } @@ -979,22 +1142,35 @@ JSString* js::gc::TenuringTracer::promoteString(JSString* src) { if (p) { // Deduplicate to the looked-up string! dst = *p; + MOZ_ASSERT(dst->isTenured()); // Never deduplicate to a from-space cell. zone->stringStats.ref().noteDeduplicated(src->length(), src->allocSize()); - StringRelocationOverlay::forwardCell(src, dst); + if (src->isDependent()) { + StringRelocationOverlay::forwardDependentString(&src->asDependent(), + dst); + } else { + StringRelocationOverlay::forwardString(src, dst); + } gcprobes::PromoteToTenured(src, dst); return dst; } dst = allocString(src, zone, dstKind); - using DedupHasher [[maybe_unused]] = DeduplicationStringHasher; - MOZ_ASSERT(DedupHasher::hash(src) == DedupHasher::hash(dst), - "src and dst must have the same hash for lookupForAdd"); + // In some situations, a string may be converted to a different type when + // tenured. Currently, this only happens when a dependent string's chain of + // base strings makes it impossible to recover its data, in which case it + // will get converted to a regular linear string. In order to avoid + // rehashing and some complexity, do not deduplicate to such strings. + if (dst->flags() == src->flags()) { + using DedupHasher [[maybe_unused]] = DeduplicationStringHasher; + MOZ_ASSERT(DedupHasher::hash(src) == DedupHasher::hash(dst), + "src and dst must have the same hash for lookupForAdd"); - if (!stringDeDupSet->add(p, dst)) { - // When there is oom caused by the stringDeDupSet, stop deduplicating - // strings. - stringDeDupSet.reset(); + if (!stringDeDupSet->add(p, dst)) { + // When there is oom caused by the stringDeDupSet, stop deduplicating + // strings. + stringDeDupSet.reset(); + } } } else { dst = allocString(src, zone, dstKind); @@ -1004,93 +1180,57 @@ JSString* js::gc::TenuringTracer::promoteString(JSString* src) { } } + gcprobes::PromoteToTenured(src, dst); zone->stringStats.ref().noteTenured(src->allocSize()); - auto* overlay = StringRelocationOverlay::forwardCell(src, dst); - MOZ_ASSERT_IF(dst->isTenured() && dst->isLinear(), dst->isDeduplicatable()); + if (dst->isDependent()) { + // Dependent string: + // - root base was tenured => done + // - otherwise => promote the root base if it has not already been + // promoted, then update the dependent string's chars pointer based on + // the root base's original chars pointer (stored in its + // StringRelocationOverlay during promotion) - if (dst->hasBase() || dst->isRope()) { - // dst or one of its leaves might have a base that will be deduplicated. - // Insert the overlay into the fixup list to relocate it later. - insertIntoStringFixupList(overlay); - } + JSLinearString* base = src->asDependent().rootBaseDuringMinorGC(); - gcprobes::PromoteToTenured(src, dst); - return dst; -} + // Limited recursion: the root base cannot be dependent, so this will not + // recurse again. + JSString* promotedBase = + InCollectedNurseryRegion(base) ? promoteOrForward(base) : base; + MOZ_ASSERT(!promotedBase->isDependent()); -template -void js::gc::TenuringTracer::relocateDependentStringChars( - JSDependentString* tenuredDependentStr, JSLinearString* baseOrRelocOverlay, - size_t* offset, bool* rootBaseNotYetForwarded, JSLinearString** rootBase) { - MOZ_ASSERT(*offset == 0); - MOZ_ASSERT(*rootBaseNotYetForwarded == false); - MOZ_ASSERT(*rootBase == nullptr); + dst->asDependent().setBase(&promotedBase->asLinear()); + if (InCollectedNurseryRegion(base)) { + dst->asDependent().updateToPromotedBase(base); + } - JS::AutoCheckCannotGC nogc; + StringRelocationOverlay::forwardDependentString(src, dst); + } else { + // Non-dependent string: store the original chars pointer in the nursery + // cell (for future promotions of any dependent strings that use this string + // as a base), then forward to the promoted cell. - const CharT* dependentStrChars = - tenuredDependentStr->nonInlineChars(nogc); - - // Traverse the dependent string nursery base chain to find the base that - // it's using chars from. - while (true) { - if (baseOrRelocOverlay->isForwarded()) { - JSLinearString* tenuredBase = Forwarded(baseOrRelocOverlay); - StringRelocationOverlay* relocOverlay = - StringRelocationOverlay::fromCell(baseOrRelocOverlay); - - if (!tenuredBase->hasBase()) { - // The nursery root base is relocOverlay, it is tenured to tenuredBase. - // Relocate tenuredDependentStr chars and reassign the tenured root base - // as its base. - JSLinearString* tenuredRootBase = tenuredBase; - const CharT* rootBaseChars = relocOverlay->savedNurseryChars(); - *offset = dependentStrChars - rootBaseChars; - MOZ_ASSERT(*offset < tenuredRootBase->length()); - tenuredDependentStr->relocateNonInlineChars( - tenuredRootBase->nonInlineChars(nogc), *offset); - tenuredDependentStr->setBase(tenuredRootBase); - MOZ_ASSERT(tenuredRootBase->assertIsValidBase()); - - if (tenuredDependentStr->isTenured() && !tenuredRootBase->isTenured()) { - runtime()->gc.storeBuffer().putWholeCell(tenuredDependentStr); - } - return; - } - - baseOrRelocOverlay = relocOverlay->savedNurseryBaseOrRelocOverlay(); - - } else { - JSLinearString* base = baseOrRelocOverlay; - - if (!base->hasBase()) { - // The root base is not forwarded yet, it is simply base. - *rootBase = base; - - // The root base can be in either the nursery or the tenured heap. - // dependentStr chars needs to be relocated after traceString if the - // root base is in the nursery. - if (nursery().inCollectedRegion(*rootBase)) { - *rootBaseNotYetForwarded = true; - const CharT* rootBaseChars = (*rootBase)->nonInlineChars(nogc); - *offset = dependentStrChars - rootBaseChars; - MOZ_ASSERT(*offset < base->length(), "Tenured root base"); - } - - tenuredDependentStr->setBase(*rootBase); - MOZ_ASSERT((*rootBase)->assertIsValidBase()); - - return; - } - - baseOrRelocOverlay = base->nurseryBaseOrRelocOverlay(); + StringRelocationOverlay::forwardString(src, dst); + if (dst->isRope()) { + // Enqueue for recursion through the children. + insertIntoStringFixupList(StringRelocationOverlay::fromCell(src)); } } + + MOZ_ASSERT_IF(dst->isTenured() && dst->isLinear(), dst->isDeduplicatable()); + + return dst; } JS::BigInt* js::gc::TenuringTracer::promoteBigInt(JS::BigInt* src) { MOZ_ASSERT(IsInsideNursery(src)); + MOZ_ASSERT(!src->isForwarded()); + +#ifdef JS_GC_ZEAL + if (promotionStats) { + promotionStats->notePromotedBigInt(src); + } +#endif AllocKind dstKind = src->getAllocKind(); Zone* zone = src->nurseryZone(); @@ -1122,71 +1262,23 @@ void js::gc::TenuringTracer::collectToObjectFixedPoint() { } void js::gc::TenuringTracer::collectToStringFixedPoint() { + // Recurse through ropes. + while (StringRelocationOverlay* p = stringHead) { MOZ_ASSERT(nursery().inCollectedRegion(p)); stringHead = stringHead->next(); - auto* str = static_cast(p->forwardingAddress()); - MOZ_ASSERT_IF(IsInsideNursery(str), !nursery().inCollectedRegion(str)); + auto* promotedStr = static_cast(p->forwardingAddress()); + MOZ_ASSERT_IF(IsInsideNursery(promotedStr), + !nursery().inCollectedRegion(promotedStr)); // To ensure the NON_DEDUP_BIT was reset properly. - MOZ_ASSERT(!str->isAtom()); - MOZ_ASSERT_IF(str->isTenured() && str->isLinear(), str->isDeduplicatable()); + MOZ_ASSERT(!promotedStr->isAtom()); + MOZ_ASSERT_IF(promotedStr->isTenured() && promotedStr->isLinear(), + promotedStr->isDeduplicatable()); - // The nursery root base might not be forwarded before - // traceString(str). traceString(str) will forward the root - // base if that's the case. Dependent string chars needs to be relocated - // after traceString if root base was not forwarded. - size_t offset = 0; - bool rootBaseNotYetForwarded = false; - JSLinearString* rootBase = nullptr; - - if (str->isDependent() && !str->isAtomRef()) { - if (str->hasTwoByteChars()) { - relocateDependentStringChars( - &str->asDependent(), p->savedNurseryBaseOrRelocOverlay(), &offset, - &rootBaseNotYetForwarded, &rootBase); - } else { - relocateDependentStringChars( - &str->asDependent(), p->savedNurseryBaseOrRelocOverlay(), &offset, - &rootBaseNotYetForwarded, &rootBase); - } - } - - AutoPromotedAnyToNursery promotedAnyToNursery(*this); - traceString(str); - if (str->isTenured() && promotedAnyToNursery) { - runtime()->gc.storeBuffer().putWholeCell(str); - } - - if (rootBaseNotYetForwarded) { - MOZ_ASSERT(rootBase->isForwarded(), - "traceString() should make it forwarded"); - JS::AutoCheckCannotGC nogc; - - JSLinearString* tenuredRootBase = Forwarded(rootBase); - MOZ_ASSERT(offset < tenuredRootBase->length()); - - if (str->hasTwoByteChars()) { - str->asDependent().relocateNonInlineChars( - tenuredRootBase->twoByteChars(nogc), offset); - } else { - str->asDependent().relocateNonInlineChars( - tenuredRootBase->latin1Chars(nogc), offset); - } - - str->setBase(tenuredRootBase); - MOZ_ASSERT(tenuredRootBase->assertIsValidBase()); - if (str->isTenured() && !tenuredRootBase->isTenured()) { - runtime()->gc.storeBuffer().putWholeCell(str); - } - } - - if (str->hasBase()) { - MOZ_ASSERT(!str->base()->isForwarded()); - MOZ_ASSERT_IF(!str->base()->isTenured(), - !nursery().inCollectedRegion(str->base())); - } + MOZ_ASSERT(promotedStr->isRope()); + traceString(promotedStr); } } @@ -1201,6 +1293,20 @@ size_t js::gc::TenuringTracer::moveString(JSString* dst, JSString* src, MOZ_ASSERT(OffsetToChunkEnd(src) >= size); js_memcpy(dst, src, size); + if (src->isDependent()) { + // Special case: if src is a dependent string whose base chain goes through + // tenured space, then it may point to dead chars -- either because its root + // base was deduplicated, or its root base's chars were allocated in the + // nursery. If src's chars pointer will no longer be valid once minor GC is + // complete, give it its own copy of the chars. + // + // Note that the size of any cloned data is *not* included in the "number + // of bytes tenured" return value here, since the donor owns them and may + // still be alive and we don't want to double-count. + JSLinearString::maybeCloneCharsOnPromotion(&dst->asDependent()); + return size; + } + if (!src->hasOutOfLineChars()) { return size; } @@ -1213,6 +1319,19 @@ size_t js::gc::TenuringTracer::moveString(JSString* dst, JSString* src, return size; } + if (src->asLinear().hasStringBuffer()) { + auto* buffer = src->asLinear().stringBuffer(); + if (dst->isTenured()) { + // Increment the buffer's refcount because the tenured string now has a + // reference to it. The nursery's reference will be released at the end of + // the minor GC in Nursery::sweep. + buffer->AddRef(); + AddCellMemory(dst, dst->asLinear().allocSize(), + MemoryUse::StringContents); + } + return size; + } + // String data is in the nursery and needs to be moved to the malloc heap. MOZ_ASSERT(nursery().isInside(src->asLinear().nonInlineCharsRaw())); @@ -1246,8 +1365,9 @@ size_t js::gc::TenuringTracer::moveBigInt(JS::BigInt* dst, JS::BigInt* src, size_t length = dst->digitLength(); size_t nbytes = length * sizeof(JS::BigInt::Digit); - Nursery::WasBufferMoved result = nursery().maybeMoveBufferOnPromotion( - &dst->heapDigits_, dst, nbytes, MemoryUse::BigIntDigits); + Nursery::WasBufferMoved result = + nursery().maybeMoveNurseryOrMallocBufferOnPromotion( + &dst->heapDigits_, dst, nbytes, MemoryUse::BigIntDigits); if (result == Nursery::BufferMoved) { nursery().setDirectForwardingPointer(src->heapDigits_, dst->heapDigits_); size += nbytes; @@ -1305,6 +1425,186 @@ MOZ_ALWAYS_INLINE bool DeduplicationStringHasher::match( lookup->asLinear().twoByteChars(nogc), lookup->length()); } +#ifdef JS_GC_ZEAL + +void TenuringTracer::initPromotionReport() { + MOZ_ASSERT(!promotionStats); + promotionStats = MakeUnique(); + // Ignore OOM. +} + +void TenuringTracer::printPromotionReport( + JSContext* cx, JS::GCReason reason, const JS::AutoRequireNoGC& nogc) const { + if (!promotionStats || !promotionStats->shouldPrintReport()) { + return; + } + + size_t minorGCCount = runtime()->gc.minorGCCount(); + double usedBytes = double(nursery_.previousGC.nurseryUsedBytes); + double capacityBytes = double(nursery_.previousGC.nurseryCapacity); + double fractionPromoted = double(getPromotedSize()) / usedBytes; + double usedMB = usedBytes / (1024 * 1024); + double capacityMB = capacityBytes / (1024 * 1024); + fprintf(stderr, "Promotion stats for minor GC %zu:\n", minorGCCount); + fprintf(stderr, " Reason: %s\n", ExplainGCReason(reason)); + fprintf(stderr, " Nursery size: %4.1f MB used of %4.1f MB\n", usedMB, + capacityMB); + fprintf(stderr, " Promotion rate: %5.1f%%\n", fractionPromoted); + + promotionStats->printReport(cx, nogc); +} + +void PromotionStats::notePromotedObject(JSObject* obj) { + objectCount++; + + BaseShape* baseShape = obj->shape()->base(); + auto ptr = objectCountByBaseShape.lookupForAdd(baseShape); + if (!ptr) { + if (!objectCountByBaseShape.add(ptr, baseShape, 0)) { + hadOOM = true; + return; + } + } + ptr->value()++; +} + +void PromotionStats::notePromotedString(JSString* str) { + stringCount++; + + AllocKind kind = str->getAllocKind(); + stringCountByKind[kind]++; +} + +void PromotionStats::notePromotedBigInt(JS::BigInt* bi) { bigIntCount++; } + +bool PromotionStats::shouldPrintReport() const { + if (hadOOM) { + return false; + } + + return objectCount || stringCount || bigIntCount; +} + +void PromotionStats::printReport(JSContext* cx, + const JS::AutoRequireNoGC& nogc) { + if (objectCount) { + fprintf(stderr, " Objects promoted: %zu\n", objectCount); + printObjectCounts(cx, nogc); + } + + if (stringCount) { + fprintf(stderr, " Strings promoted: %zu\n", stringCount); + printStringCounts(); + } + + if (bigIntCount) { + fprintf(stderr, " BigInts promoted: %zu\n", bigIntCount); + } +} + +void PromotionStats::printObjectCounts(JSContext* cx, + const JS::AutoRequireNoGC& nogc) { + CountsVector counts; + + for (auto r = objectCountByBaseShape.all(); !r.empty(); r.popFront()) { + size_t count = r.front().value(); + if (count < AttentionThreshold) { + continue; + } + + BaseShape* baseShape = r.front().key(); + + const char* className = baseShape->clasp()->name; + + UniqueChars constructorName = getConstructorName(cx, baseShape, nogc); + const char* constructorChars = constructorName ? constructorName.get() : ""; + + LabelAndCount entry; + snprintf(entry.label, sizeof(entry.label), "%s %s", className, + constructorChars); + entry.count = count; + if (!counts.append(entry)) { + return; + } + } + + printCounts(counts, objectCount); +} + +UniqueChars PromotionStats::getConstructorName( + JSContext* cx, BaseShape* baseShape, const JS::AutoRequireNoGC& nogc) { + TaggedProto taggedProto = baseShape->proto(); + if (taggedProto.isDynamic()) { + return nullptr; + } + + JSObject* proto = taggedProto.toObjectOrNull(); + if (!proto) { + return nullptr; + } + + MOZ_ASSERT(!proto->isForwarded()); + + AutoRealm ar(cx, proto); + bool found; + Value value; + if (!GetOwnPropertyPure(cx, proto, NameToId(cx->names().constructor), &value, + &found)) { + return nullptr; + } + + if (!found || !value.isObject()) { + return nullptr; + } + + JSFunction* constructor = &value.toObject().as(); + JSAtom* atom = constructor->maybePartialDisplayAtom(); + if (!atom) { + return nullptr; + } + + return EncodeAscii(cx, atom); +} + +void PromotionStats::printStringCounts() { + CountsVector counts; + for (AllocKind kind : AllAllocKinds()) { + size_t count = stringCountByKind[kind]; + if (count < AttentionThreshold) { + continue; + } + + const char* name = AllocKindName(kind); + LabelAndCount entry; + strncpy(entry.label, name, sizeof(entry.label)); + entry.label[sizeof(entry.label) - 1] = 0; + entry.count = count; + if (!counts.append(entry)) { + return; + } + } + + printCounts(counts, stringCount); +} + +void PromotionStats::printCounts(CountsVector& counts, size_t total) { + std::sort(counts.begin(), counts.end(), + [](const auto& a, const auto& b) { return a.count > b.count; }); + + size_t max = std::min(counts.length(), size_t(10)); + for (size_t i = 0; i < max; i++) { + const auto& entry = counts[i]; + printLine(entry.label, entry.count, total); + } +} + +void PromotionStats::printLine(const char* name, size_t count, size_t total) { + double percent = 100.0 * double(count) / double(total); + fprintf(stderr, " %5.1f%%: %s\n", percent, name); +} + +#endif + MinorSweepingTracer::MinorSweepingTracer(JSRuntime* rt) : GenericTracerImpl(rt, JS::TracerKind::MinorSweeping, JS::WeakMapTraceAction::TraceKeysAndValues) { @@ -1316,9 +1616,11 @@ template inline void MinorSweepingTracer::onEdge(T** thingp, const char* name) { T* thing = *thingp; if (thing->isTenured()) { + MOZ_ASSERT(!IsForwarded(thing)); return; } + MOZ_ASSERT(runtime()->gc.nursery().inCollectedRegion(thing)); if (IsForwarded(thing)) { *thingp = Forwarded(thing); return; diff --git a/src/third_party/mozjs/extract/js/src/gc/Tenuring.h b/src/third_party/mozjs/extract/js/src/gc/Tenuring.h index 8bb9efd4f82..12920351111 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Tenuring.h +++ b/src/third_party/mozjs/extract/js/src/gc/Tenuring.h @@ -7,11 +7,14 @@ #ifndef gc_Tenuring_h #define gc_Tenuring_h +#include "mozilla/EnumeratedArray.h" +#include "mozilla/HashTable.h" #include "mozilla/Maybe.h" #include "gc/AllocKind.h" #include "js/GCAPI.h" #include "js/TracingAPI.h" +#include "js/UniquePtr.h" #include "util/Text.h" namespace js { @@ -30,6 +33,9 @@ class AllocSite; class ArenaCellSet; class RelocationOverlay; class StringRelocationOverlay; +#ifdef JS_GC_ZEAL +class PromotionStats; +#endif template struct DeduplicationStringHasher { @@ -68,16 +74,22 @@ class TenuringTracer final : public JSTracer { // edge to the remembered set during nursery collection. bool promotedToNursery = false; -#define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ - void on##name##Edge(type** thingp, const char* name) override; - JS_FOR_EACH_TRACEKIND(DEFINE_ON_EDGE_METHOD) -#undef DEFINE_ON_EDGE_METHOD +#ifdef JS_GC_ZEAL + UniquePtr promotionStats; +#endif public: TenuringTracer(JSRuntime* rt, Nursery* nursery, bool tenureEverything); + ~TenuringTracer(); Nursery& nursery() { return nursery_; } +#ifdef JS_GC_ZEAL + void initPromotionReport(); + void printPromotionReport(JSContext* cx, JS::GCReason reason, + const JS::AutoRequireNoGC& nogc) const; +#endif + // Promote all live objects and everything they can reach. Called after all // roots have been traced. void collectToObjectFixedPoint(); @@ -98,7 +110,6 @@ class TenuringTracer final : public JSTracer { void traceObjectSlots(NativeObject* nobj, uint32_t start, uint32_t end); void traceObjectElements(JS::Value* vp, uint32_t count); void traceString(JSString* str); - void traceBigInt(JS::BigInt* bi); // Methods to promote a live cell or get the pointer to its new location if // that has already happened. The store buffers call these. @@ -113,18 +124,10 @@ class TenuringTracer final : public JSTracer { class AutoPromotedAnyToNursery; private: - MOZ_ALWAYS_INLINE JSObject* onNonForwardedNurseryObject(JSObject* obj); - MOZ_ALWAYS_INLINE JSString* onNonForwardedNurseryString(JSString* str); - MOZ_ALWAYS_INLINE JS::BigInt* onNonForwardedNurseryBigInt(JS::BigInt* bi); - - // The dependent string chars needs to be relocated if the base which it's - // using chars from has been deduplicated. - template - void relocateDependentStringChars(JSDependentString* tenuredDependentStr, - JSLinearString* baseOrRelocOverlay, - size_t* offset, - bool* rootBaseNotYetForwarded, - JSLinearString** rootBase); +#define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ + void on##name##Edge(type** thingp, const char* name) override; + JS_FOR_EACH_TRACEKIND(DEFINE_ON_EDGE_METHOD) +#undef DEFINE_ON_EDGE_METHOD inline void insertIntoObjectFixupList(gc::RelocationOverlay* entry); inline void insertIntoStringFixupList(gc::StringRelocationOverlay* entry); @@ -138,6 +141,7 @@ class TenuringTracer final : public JSTracer { bool shouldTenure(Zone* zone, JS::TraceKind traceKind, Cell* cell); + MOZ_ALWAYS_INLINE JSObject* promoteObject(JSObject* obj); inline JSObject* promotePlainObject(PlainObject* src); JSObject* promoteObjectSlow(JSObject* src); JSString* promoteString(JSString* src); diff --git a/src/third_party/mozjs/extract/js/src/gc/TraceMethods-inl.h b/src/third_party/mozjs/extract/js/src/gc/TraceMethods-inl.h index e7066c5ebce..b44aa393f80 100644 --- a/src/third_party/mozjs/extract/js/src/gc/TraceMethods-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/TraceMethods-inl.h @@ -79,20 +79,6 @@ inline void JSString::traceChildren(JSTracer* trc) { asRope().traceChildren(trc); } } -inline void JSString::traceBaseFromStoreBuffer(JSTracer* trc) { - MOZ_ASSERT(!d.s.u3.base->isTenured()); - - // Contract the base chain so that this tenured dependent string points - // directly at the root base that owns its chars. - JSLinearString* root = asDependent().rootBaseDuringMinorGC(); - d.s.u3.base = root; - if (!root->isTenured()) { - js::TraceManuallyBarrieredEdge(trc, &root, "base"); - // Do not update the actual base to the tenured string yet. This string will - // need to be swept in order to update its chars ptr to be relative to the - // root, and that update requires information from the overlay. - } -} template void js::GCMarker::eagerlyMarkChildren(JSString* str) { if (str->isLinear()) { diff --git a/src/third_party/mozjs/extract/js/src/gc/Tracer.cpp b/src/third_party/mozjs/extract/js/src/gc/Tracer.cpp index e7a9f83863c..071d24f454b 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Tracer.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Tracer.cpp @@ -29,7 +29,6 @@ using namespace js; using namespace js::gc; -using mozilla::DebugOnly; template void RuntimeScopeData::trace(JSTracer* trc); template void RuntimeScopeData::trace(JSTracer* trc); @@ -43,7 +42,7 @@ void JS::TracingContext::getEdgeName(const char* name, char* buffer, size_t bufferSize) { MOZ_ASSERT(bufferSize > 0); if (functor_) { - (*functor_)(this, buffer, bufferSize); + (*functor_)(this, name, buffer, bufferSize); return; } if (index_ != InvalidIndex) { diff --git a/src/third_party/mozjs/extract/js/src/gc/Tracer.h b/src/third_party/mozjs/extract/js/src/gc/Tracer.h index 85b1fdfcfdb..74b34acda77 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Tracer.h +++ b/src/third_party/mozjs/extract/js/src/gc/Tracer.h @@ -7,6 +7,7 @@ #ifndef js_Tracer_h #define js_Tracer_h +#include "gc/Allocator.h" #include "gc/Barrier.h" #include "gc/TraceKind.h" #include "js/HashTable.h" @@ -254,6 +255,14 @@ inline void TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp), name); } +template +inline void TraceManuallyBarrieredNullableEdge(JSTracer* trc, T* thingp, + const char* name) { + if (InternalBarrierMethods::isMarkable(*thingp)) { + gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp), name); + } +} + // Trace through a weak edge. If *thingp is not marked at the end of marking, // it is replaced by nullptr, and this method will return false to indicate that // the edge no longer exists. @@ -320,6 +329,15 @@ void TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name) { gc::TraceRangeInternal(trc, len, gc::ConvertToBase(vec), name); } +// Note that this doesn't trace the contents of the alloc. +// TODO: Unify this with other TraceEdge methods. +template +void TraceBufferEdge(JSTracer* trc, gc::Cell* owner, T** bufferp, + const char* name) { + void** ptrp = reinterpret_cast(bufferp); + gc::TraceBufferEdgeInternal(trc, owner, ptrp, name); +} + // As below but with manual barriers. template void TraceManuallyBarrieredCrossCompartmentEdge(JSTracer* trc, JSObject* src, diff --git a/src/third_party/mozjs/extract/js/src/gc/Verifier.cpp b/src/third_party/mozjs/extract/js/src/gc/Verifier.cpp index aa9de492b77..e66d774067e 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Verifier.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Verifier.cpp @@ -25,14 +25,13 @@ #include "gc/ArenaList-inl.h" #include "gc/GC-inl.h" +#include "gc/Heap-inl.h" #include "gc/Marking-inl.h" #include "gc/PrivateIterators-inl.h" using namespace js; using namespace js::gc; -using mozilla::DebugOnly; - #ifdef JS_GC_ZEAL /* @@ -120,6 +119,21 @@ class js::VerifyPreTracer final : public JS::CallbackTracer { ~VerifyPreTracer() { js_free(root); } }; +inline bool IgnoreForPreBarrierVerifier(JSRuntime* runtime, + JS::GCCellPtr thing) { + // Skip things in other runtimes. + if (thing.asCell()->asTenured().runtimeFromAnyThread() != runtime) { + return true; + } + + // Ignore buffers as these don't escape and are not barriered. + if (thing.kind() == JS::TraceKind::SmallBuffer) { + return true; + } + + return false; +} + /* * This function builds up the heap snapshot by adding edges to the current * node. @@ -127,8 +141,7 @@ class js::VerifyPreTracer final : public JS::CallbackTracer { void VerifyPreTracer::onChild(JS::GCCellPtr thing, const char* name) { MOZ_ASSERT(!IsInsideNursery(thing.asCell())); - // Skip things in other runtimes. - if (thing.asCell()->asTenured().runtimeFromAnyThread() != runtime()) { + if (IgnoreForPreBarrierVerifier(runtime(), thing)) { return; } @@ -197,10 +210,7 @@ void gc::GCRuntime::startVerifyPreBarriers() { } JSContext* cx = rt->mainContextFromOwnThread(); - - if (IsIncrementalGCUnsafe(rt) != GCAbortReason::None) { - return; - } + MOZ_ASSERT(!cx->suppressGC); number++; @@ -211,6 +221,12 @@ void gc::GCRuntime::startVerifyPreBarriers() { AutoPrepareForTracing prep(cx); +# ifdef DEBUG + for (AllZonesIter zone(this); !zone.done(); zone.next()) { + zone->bufferAllocator.checkGCStateNotInUse(); + } +# endif + ClearMarkBits(this); gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::TRACE_HEAP); @@ -294,8 +310,7 @@ static const uint32_t MAX_VERIFIER_EDGES = 1000; * been modified) must point to marked objects. */ void CheckEdgeTracer::onChild(JS::GCCellPtr thing, const char* name) { - // Skip things in other runtimes. - if (thing.asCell()->asTenured().runtimeFromAnyThread() != runtime()) { + if (IgnoreForPreBarrierVerifier(runtime(), thing)) { return; } @@ -362,7 +377,7 @@ void gc::GCRuntime::endVerifyPreBarriers() { MOZ_ASSERT(incrementalState == State::Mark); incrementalState = State::NotActive; - if (!compartmentCreated && IsIncrementalGCUnsafe(rt) == GCAbortReason::None) { + if (!compartmentCreated) { CheckEdgeTracer cetrc(rt); /* Start after the roots. */ @@ -395,11 +410,25 @@ void gc::GCRuntime::endVerifyPreBarriers() { marker().reset(); resetDelayedMarking(); + for (AllZonesIter zone(this); !zone.done(); zone.next()) { + zone->bufferAllocator.clearMarkStateAfterBarrierVerification(); + } + js_delete(trc); } /*** Barrier Verifier Scheduling ***/ +void gc::VerifyBarriers(JSRuntime* rt, VerifierType type) { + if (type == PreBarrierVerifier) { + rt->gc.verifyPreBarriers(); + } + + if (type == PostBarrierVerifier) { + rt->gc.verifyPostBarriers(); + } +} + void gc::GCRuntime::verifyPreBarriers() { if (verifyPreData) { endVerifyPreBarriers(); @@ -408,9 +437,11 @@ void gc::GCRuntime::verifyPreBarriers() { } } -void gc::VerifyBarriers(JSRuntime* rt, VerifierType type) { - if (type == PreBarrierVerifier) { - rt->gc.verifyPreBarriers(); +void gc::GCRuntime::verifyPostBarriers() { + if (hasZealMode(ZealMode::VerifierPost)) { + clearZealMode(ZealMode::VerifierPost); + } else { + setZeal(uint8_t(ZealMode::VerifierPost), JS::ShellDefaultGCZealFrequency); } } @@ -447,18 +478,18 @@ void js::gc::GCRuntime::finishVerifier() { } struct GCChunkHasher { - using Lookup = gc::TenuredChunk*; + using Lookup = gc::ArenaChunk*; /* * Strip zeros for better distribution after multiplying by the golden * ratio. */ - static HashNumber hash(gc::TenuredChunk* chunk) { + static HashNumber hash(gc::ArenaChunk* chunk) { MOZ_ASSERT(!(uintptr_t(chunk) & gc::ChunkMask)); return HashNumber(uintptr_t(chunk) >> gc::ChunkShift); } - static bool match(gc::TenuredChunk* k, gc::TenuredChunk* l) { + static bool match(gc::ArenaChunk* k, gc::ArenaChunk* l) { MOZ_ASSERT(!(uintptr_t(k) & gc::ChunkMask)); MOZ_ASSERT(!(uintptr_t(l) & gc::ChunkMask)); return k == l; @@ -475,8 +506,8 @@ class js::gc::MarkingValidator { GCRuntime* gc; bool initialized; - using BitmapMap = HashMap, GCChunkHasher, - SystemAllocPolicy>; + using BitmapMap = HashMap, + GCChunkHasher, SystemAllocPolicy>; BitmapMap map; }; @@ -487,11 +518,8 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) { /* * Perform a non-incremental mark for all collecting zones and record * the results for later comparison. - * - * Currently this does not validate gray marking. */ - JSRuntime* runtime = gc->rt; GCMarker* gcmarker = &gc->marker(); MOZ_ASSERT(!gcmarker->isWeakMarking()); @@ -512,16 +540,12 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) { chunk.next()) { // Bug 1842582: Allocate mark bit buffer in two stages to avoid alignment // restriction which we currently can't support. - void* buffer = js_malloc(sizeof(MarkBitmap)); + void* buffer = js_malloc(sizeof(ChunkMarkBitmap)); if (!buffer) { return; } - UniquePtr entry(new (buffer) MarkBitmap); - - MarkBitmap* bitmap = &chunk->markBits; - memcpy((void*)entry->bitmap, (void*)bitmap->bitmap, - sizeof(bitmap->bitmap)); - + UniquePtr entry(new (buffer) ChunkMarkBitmap); + entry->copyFrom(chunk->markBits); if (!map.putNew(chunk, std::move(entry))) { return; } @@ -539,11 +563,7 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) { * For saving, smush all of the keys into one big table and split them back * up into per-zone tables when restoring. */ - gc::EphemeronEdgeTable savedEphemeronEdges( - SystemAllocPolicy(), runtime->randomHashCodeScrambler()); - if (!savedEphemeronEdges.init()) { - return; - } + gc::EphemeronEdgeTable savedEphemeronEdges; for (GCZonesIter zone(gc); !zone.done(); zone.next()) { if (!WeakMapBase::saveZoneMarkedWeakMaps(zone, markedWeakMaps)) { @@ -551,23 +571,25 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) { } AutoEnterOOMUnsafeRegion oomUnsafe; - for (auto r = zone->gcEphemeronEdges().mutableAll(); !r.empty(); - r.popFront()) { - MOZ_ASSERT(r.front().key->asTenured().zone() == zone); - if (!savedEphemeronEdges.put(r.front().key, std::move(r.front().value))) { + for (auto r = zone->gcEphemeronEdges().all(); !r.empty(); r.popFront()) { + MOZ_ASSERT(r.front().key()->asTenured().zone() == zone); + if (!savedEphemeronEdges.putNew(r.front().key(), + std::move(r.front().value()))) { oomUnsafe.crash("saving weak keys table for validator"); } } - if (!zone->gcEphemeronEdges().clear()) { - oomUnsafe.crash("clearing weak keys table for validator"); - } + zone->gcEphemeronEdges().clearAndCompact(); } - /* Save and restore test mark queue state. */ # ifdef DEBUG - size_t savedQueuePos = gc->queuePos; - mozilla::Maybe savedQueueColor = gc->queueMarkColor; + // The test mark queue can cause spurious differences if the non-incremental + // marking for validation happens before the full queue has been processed, + // since the later part of the queue may mark things during sweeping. Disable + // validation if there is anything left in the queue at this point. + if (gc->testMarkQueueRemaining() > 0) { + return; + } # endif /* @@ -638,40 +660,36 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) { AutoLockGC lock(gc); for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next()) { - MarkBitmap* bitmap = &chunk->markBits; + ChunkMarkBitmap* bitmap = &chunk->markBits; auto ptr = map.lookup(chunk); MOZ_RELEASE_ASSERT(ptr, "Chunk not found in map"); - MarkBitmap* entry = ptr->value().get(); - for (size_t i = 0; i < MarkBitmap::WordCount; i++) { - uintptr_t v = entry->bitmap[i]; - entry->bitmap[i] = uintptr_t(bitmap->bitmap[i]); - bitmap->bitmap[i] = v; - } + ChunkMarkBitmap* entry = ptr->value().get(); + ChunkMarkBitmap temp; + temp.copyFrom(*entry); + entry->copyFrom(*bitmap); + bitmap->copyFrom(temp); } } for (GCZonesIter zone(gc); !zone.done(); zone.next()) { WeakMapBase::unmarkZone(zone); - AutoEnterOOMUnsafeRegion oomUnsafe; - if (!zone->gcEphemeronEdges().clear()) { - oomUnsafe.crash("clearing weak keys table for validator"); - } + MOZ_ASSERT(zone->gcEphemeronEdges().empty(), "unmarkZone clears the map"); } WeakMapBase::restoreMarkedWeakMaps(markedWeakMaps); - for (auto r = savedEphemeronEdges.mutableAll(); !r.empty(); r.popFront()) { + for (auto r = savedEphemeronEdges.all(); !r.empty(); r.popFront()) { AutoEnterOOMUnsafeRegion oomUnsafe; - Zone* zone = r.front().key->asTenured().zone(); - if (!zone->gcEphemeronEdges().put(r.front().key, - std::move(r.front().value))) { + Zone* zone = r.front().key()->asTenured().zone(); + if (!zone->gcEphemeronEdges().putNew(r.front().key(), + std::move(r.front().value()))) { oomUnsafe.crash("restoring weak keys table for validator"); } } # ifdef DEBUG - gc->queuePos = savedQueuePos; - gc->queueMarkColor = savedQueueColor; + MOZ_ASSERT(gc->testMarkQueueRemaining() == 0); + MOZ_ASSERT(gc->queueMarkColor.isNothing()); # endif gc->incrementalState = state; @@ -699,18 +717,19 @@ void js::gc::MarkingValidator::validate() { continue; /* Allocated after we did the non-incremental mark. */ } - MarkBitmap* bitmap = ptr->value().get(); - MarkBitmap* incBitmap = &chunk->markBits; + ChunkMarkBitmap* bitmap = ptr->value().get(); + ChunkMarkBitmap* incBitmap = &chunk->markBits; for (size_t i = 0; i < ArenasPerChunk; i++) { - if (chunk->decommittedPages[chunk->pageIndex(i)]) { + size_t pageIndex = ArenaChunk::arenaToPageIndex(i); + if (chunk->decommittedPages[pageIndex]) { continue; } Arena* arena = &chunk->arenas[i]; if (!arena->allocated()) { continue; } - if (!arena->zone->isGCSweeping()) { + if (!arena->zone()->isGCSweeping()) { continue; } @@ -721,44 +740,53 @@ void js::gc::MarkingValidator::validate() { auto* cell = reinterpret_cast(thing); /* - * If a non-incremental GC wouldn't have collected a cell, then - * an incremental GC won't collect it. + * If a non-incremental GC wouldn't have collected a cell, then an + * incremental GC should not collect it either. However incremental + * marking is conservative and is allowed to mark things that + * non-incremental marking would not have marked. + * + * Further, incremental marking should not result in a cell that is + * "less marked" than non-incremental marking. For example where + * non-incremental marking would have marked a cell black incremental + * marking is not allowed to mark it gray, since the cycle collector + * could then consider paths through it to be part of garbage + * cycles. It's OK for a cell that would have been marked gray by + * non-incremental marking to be marked black by incremental marking. + * + * It's OK for a cell that would not be marked by non-incremental + * marking to end up gray. Since the cell is unreachable according to + * the non-incremental marking then the cycle collector will not find + * it. This can happen when a barrier marks a weak map key black and the + * map is gray, resulting in the value being marked gray. + * + * In summary: + * + * Non-incremental Incremental: Outcome: + * result: result: + * + * White White OK + * Gray OK, conservative + * Black OK, conservative + * Gray White Fail + * Gray OK + * Black OK, conservative + * Black White Fail + * Gray Fail + * Black OK */ - if (bitmap->isMarkedAny(cell)) { - if (!incBitmap->isMarkedAny(cell)) { - ok = false; - const char* color = - CellColorName(TenuredCell::getColor(bitmap, cell)); - fprintf(stderr, - "%p: cell not marked, but would be marked %s by " - "non-incremental marking\n", - cell, color); -# ifdef DEBUG - cell->dump(); - fprintf(stderr, "\n"); -# endif - } - } - /* - * If the cycle collector isn't allowed to collect an object - * after a non-incremental GC has run, then it isn't allowed to - * collected it after an incremental GC. - */ - if (!bitmap->isMarkedGray(cell)) { - if (incBitmap->isMarkedGray(cell)) { - ok = false; - const char* color = - CellColorName(TenuredCell::getColor(bitmap, cell)); - fprintf(stderr, - "%p: cell marked gray, but would be marked %s by " - "non-incremental marking\n", - cell, color); + CellColor incColor = TenuredCell::getColor(incBitmap, cell); + CellColor nonIncColor = TenuredCell::getColor(bitmap, cell); + if (incColor < nonIncColor) { + ok = false; + fprintf(stderr, + "%p: cell was marked %s, but would be marked %s by " + "non-incremental marking\n", + cell, CellColorName(incColor), CellColorName(nonIncColor)); # ifdef DEBUG - cell->dump(); - fprintf(stderr, "\n"); + cell->dump(); + fprintf(stderr, "\n"); # endif - } } thing += Arena::thingSize(kind); @@ -798,8 +826,8 @@ void GCRuntime::finishMarkingValidation() { class HeapCheckTracerBase : public JS::CallbackTracer { public: explicit HeapCheckTracerBase(JSRuntime* rt, JS::TraceOptions options); - bool traceHeap(AutoTraceSession& session); - virtual void checkCell(Cell* cell, const char* name) = 0; + bool traceHeap(AutoHeapSession& session); + virtual bool checkCell(Cell* cell, const char* name) = 0; protected: void dumpCellInfo(Cell* cell); @@ -836,7 +864,7 @@ class HeapCheckTracerBase : public JS::CallbackTracer { HeapCheckTracerBase::HeapCheckTracerBase(JSRuntime* rt, JS::TraceOptions options) - : CallbackTracer(rt, JS::TracerKind::Callback, options), + : CallbackTracer(rt, JS::TracerKind::HeapCheck, options), failures(0), rt(rt), oom(false), @@ -844,8 +872,6 @@ HeapCheckTracerBase::HeapCheckTracerBase(JSRuntime* rt, void HeapCheckTracerBase::onChild(JS::GCCellPtr thing, const char* name) { Cell* cell = thing.asCell(); - checkCell(cell, name); - if (visited.lookup(cell)) { return; } @@ -855,6 +881,11 @@ void HeapCheckTracerBase::onChild(JS::GCCellPtr thing, const char* name) { return; } + if (!checkCell(cell, name)) { + // Don't trace through known bad cell. + return; + } + // Don't trace into GC things owned by another runtime. if (cell->runtimeFromAnyThread() != rt) { return; @@ -866,7 +897,7 @@ void HeapCheckTracerBase::onChild(JS::GCCellPtr thing, const char* name) { } } -bool HeapCheckTracerBase::traceHeap(AutoTraceSession& session) { +bool HeapCheckTracerBase::traceHeap(AutoHeapSession& session) { // The analysis thinks that traceRuntime might GC by calling a GC callback. JS::AutoSuppressGCAnalysis nogc; if (!rt->isBeingDestroyed()) { @@ -918,13 +949,14 @@ void HeapCheckTracerBase::dumpCellPath(const char* name) { class CheckHeapTracer final : public HeapCheckTracerBase { public: - enum GCType { Moving, NonMoving }; + enum GCType { Moving, NonMoving, VerifyPostBarriers }; explicit CheckHeapTracer(JSRuntime* rt, GCType type); - void check(AutoTraceSession& session); + void check(AutoHeapSession& session); private: - void checkCell(Cell* cell, const char* name) override; + bool checkCell(Cell* cell, const char* name) override; + bool cellIsValid(Cell* cell); GCType gcType; }; @@ -936,18 +968,48 @@ inline static bool IsValidGCThingPointer(Cell* cell) { return (uintptr_t(cell) & CellAlignMask) == 0; } -void CheckHeapTracer::checkCell(Cell* cell, const char* name) { - // Moving - if (!IsValidGCThingPointer(cell) || - ((gcType == GCType::Moving) && !IsGCThingValidAfterMovingGC(cell)) || - ((gcType == GCType::NonMoving) && cell->isForwarded())) { - failures++; - fprintf(stderr, "Bad pointer %p\n", cell); - dumpCellPath(name); +bool CheckHeapTracer::checkCell(Cell* cell, const char* name) { + if (cellIsValid(cell)) { + return true; } + + failures++; + fprintf(stderr, "Bad pointer %p\n", cell); + dumpCellPath(name); + return false; } -void CheckHeapTracer::check(AutoTraceSession& session) { +bool CheckHeapTracer::cellIsValid(Cell* cell) { + if (!IsValidGCThingPointer(cell)) { + return false; + } + + if (gcType == GCType::Moving) { + return IsGCThingValidAfterMovingGC(cell); + } + + if (gcType == GCType::NonMoving) { + return !cell->isForwarded(); + } + + MOZ_ASSERT(gcType == GCType::VerifyPostBarriers); + + // No reachable Cell* should be in the collected part of the nursery. + if (runtime()->gc.nursery().inCollectedRegion(cell)) { + return false; + } + + // String data should also not be in the collected part of nursery. + if (cell->is() && cell->as()->isLinear()) { + if (cell->as()->asLinear().hasCharsInCollectedNurseryRegion()) { + return false; + } + } + + return true; +} + +void CheckHeapTracer::check(AutoHeapSession& session) { if (!traceHeap(session)) { return; } @@ -959,6 +1021,8 @@ void CheckHeapTracer::check(AutoTraceSession& session) { } void js::gc::CheckHeapAfterGC(JSRuntime* rt) { + MOZ_ASSERT(!rt->gc.isBackgroundDecommitting()); + AutoTraceSession session(rt); CheckHeapTracer::GCType gcType; @@ -975,10 +1039,11 @@ void js::gc::CheckHeapAfterGC(JSRuntime* rt) { class CheckGrayMarkingTracer final : public HeapCheckTracerBase { public: explicit CheckGrayMarkingTracer(JSRuntime* rt); - bool check(AutoTraceSession& session); + bool check(AutoHeapSession& session); private: - void checkCell(Cell* cell, const char* name) override; + bool checkCell(Cell* cell, const char* name) override; + bool isBlackToGrayEdge(Cell* parent, Cell* child); }; CheckGrayMarkingTracer::CheckGrayMarkingTracer(JSRuntime* rt) @@ -987,34 +1052,42 @@ CheckGrayMarkingTracer::CheckGrayMarkingTracer(JSRuntime* rt) // Weak gray->black edges are allowed. } -void CheckGrayMarkingTracer::checkCell(Cell* cell, const char* name) { +bool CheckGrayMarkingTracer::checkCell(Cell* cell, const char* name) { Cell* parent = parentCell(); if (!parent) { - return; + return true; } - if (parent->isMarkedBlack() && cell->isMarkedGray()) { - failures++; + if (!isBlackToGrayEdge(parent, cell)) { + return true; + } - fprintf(stderr, "Found black to gray edge to "); - dumpCellInfo(cell); - fprintf(stderr, "\n"); - dumpCellPath(name); + failures++; + + fprintf(stderr, "Found black to gray edge to "); + dumpCellInfo(cell); + fprintf(stderr, "\n"); + dumpCellPath(name); # ifdef DEBUG - if (parent->is()) { - fprintf(stderr, "\nSource: "); - DumpObject(parent->as(), stderr); - } - if (cell->is()) { - fprintf(stderr, "\nTarget: "); - DumpObject(cell->as(), stderr); - } -# endif + if (parent->is()) { + fprintf(stderr, "\nSource: "); + DumpObject(parent->as(), stderr); } + if (cell->is()) { + fprintf(stderr, "\nTarget: "); + DumpObject(cell->as(), stderr); + } +# endif + + return false; } -bool CheckGrayMarkingTracer::check(AutoTraceSession& session) { +bool CheckGrayMarkingTracer::isBlackToGrayEdge(Cell* parent, Cell* child) { + return parent->isMarkedBlack() && child->isMarkedGray(); +} + +bool CheckGrayMarkingTracer::check(AutoHeapSession& session) { if (!traceHeap(session)) { return true; // Ignore failure. } @@ -1126,6 +1199,37 @@ bool js::gc::CheckWeakMapEntryMarking(const WeakMapBase* map, Cell* key, #endif // defined(JS_GC_ZEAL) || defined(DEBUG) +#ifdef JS_GC_ZEAL +void GCRuntime::verifyPostBarriers(AutoHeapSession& session) { + // Walk the entire heap to check for pointers into the nursery that should + // have been tracked by the store buffer. + CheckHeapTracer tracer(rt, CheckHeapTracer::GCType::VerifyPostBarriers); + tracer.check(session); +} + +void GCRuntime::checkHeapBeforeMinorGC(AutoHeapSession& session) { + // Similar to verifyPostBarriers but run before a minor GC. Checks for tenured + // dependent strings pointing to nursery chars but not in the store buffer. If + // a tenured string cell points to a nursery string cell, then it will be in + // the store buffer and is fine. So this looks for tenured strings that point + // to tenured strings but contain nursery data. + + for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { + for (ArenaIter aiter(zone, gc::AllocKind::STRING); !aiter.done(); + aiter.next()) { + for (ArenaCellIterUnderGC cell(aiter.get()); !cell.done(); cell.next()) { + if (cell->is() && cell->as()->isDependent()) { + JSDependentString* str = &cell->as()->asDependent(); + if (str->isTenured() && str->base()->isTenured()) { + MOZ_RELEASE_ASSERT(!str->hasCharsInCollectedNurseryRegion()); + } + } + } + } + } +} +#endif + // Return whether an arbitrary pointer is within a cell with the given // traceKind. Only for assertions and js::debug::* APIs. bool GCRuntime::isPointerWithinTenuredCell(void* ptr, JS::TraceKind traceKind) { @@ -1145,3 +1249,17 @@ bool GCRuntime::isPointerWithinTenuredCell(void* ptr, JS::TraceKind traceKind) { return false; } + +bool GCRuntime::isPointerWithinBufferAlloc(void* ptr) { + if (isPointerWithinTenuredCell(ptr, JS::TraceKind::SmallBuffer)) { + return true; + } + + for (AllZonesIter zone(this); !zone.done(); zone.next()) { + if (zone->bufferAllocator.isPointerWithinMediumOrLargeBuffer(ptr)) { + return true; + } + } + + return false; +} diff --git a/src/third_party/mozjs/extract/js/src/gc/WeakMap-inl.h b/src/third_party/mozjs/extract/js/src/gc/WeakMap-inl.h index b1e52aacc8b..fdcf187e604 100644 --- a/src/third_party/mozjs/extract/js/src/gc/WeakMap-inl.h +++ b/src/third_party/mozjs/extract/js/src/gc/WeakMap-inl.h @@ -45,6 +45,14 @@ static CellColor GetEffectiveColor(GCMarker* marker, const T& item) { return t.color(); } +// If a wrapper is used as a key in a weakmap, the garbage collector should +// keep that object around longer than it otherwise would. We want to avoid +// collecting the wrapper (and removing the weakmap entry) as long as the +// wrapped object is alive (because the object can be rewrapped and looked up +// again). As long as the wrapper is used as a weakmap key, it will not be +// collected (and remain in the weakmap) until the wrapped object is +// collected. + // Only objects have delegates, so default to returning nullptr. Note that some // compilation units will only ever use the object version. static MOZ_MAYBE_UNUSED JSObject* GetDelegateInternal(gc::Cell* key) { @@ -91,7 +99,7 @@ inline bool IsSymbol(const HeapPtr& key) { // collecting but the value zone is, and incorrectly free a value that is // reachable solely through weakmaps. template -void WeakMap::assertMapIsSameZoneWithValue(const V& v) { +void WeakMap::assertMapIsSameZoneWithValue(const BarrieredValue& v) { #ifdef DEBUG gc::Cell* cell = gc::ToMarkable(v); if (cell) { @@ -107,15 +115,16 @@ WeakMap::WeakMap(JSContext* cx, JSObject* memOf) template WeakMap::WeakMap(JS::Zone* zone, JSObject* memOf) - : Base(zone), WeakMapBase(memOf, zone) { - using ElemType = typename K::ElementType; + : WeakMapBase(memOf, zone), map_(zone) { + static_assert(std::is_same_v::Type, K>); + static_assert(std::is_same_v::Type, V>); // The object's TraceKind needs to be added to CC graph if this object is // used as a WeakMap key, otherwise the key is considered to be pointed from // somewhere unknown, and results in leaking the subgraph which contains the // key. See the comments in NoteWeakMapsTracer::trace for more details. - if constexpr (std::is_pointer_v) { - using NonPtrType = std::remove_pointer_t; + if constexpr (std::is_pointer_v) { + using NonPtrType = std::remove_pointer_t; static_assert(JS::IsCCTraceKind(NonPtrType::TraceKind), "Object's TraceKind should be added to CC graph."); } @@ -126,6 +135,32 @@ WeakMap::WeakMap(JS::Zone* zone, JSObject* memOf) } } +template +WeakMap::~WeakMap() { +#ifdef DEBUG + // Weak maps store their data in an unbarriered map (|map_|) meaning that no + // barriers are run on destruction. This is safe because: + + // 1. Weak maps have GC lifetime except on construction failure, therefore no + // prebarrier is required. + MOZ_ASSERT_IF(!empty(), + CurrentThreadIsGCSweeping() || CurrentThreadIsGCFinalizing()); + + // 2. If we're finalizing a weak map due to GC then it cannot contain nursery + // things, because we evicted the nursery at the start of collection and + // writing a nursery thing into the table would require the map to be + // live. Therefore no postbarrier is required. + size_t i = 0; + for (auto r = all(); !r.empty() && i < 1000; r.popFront(), i++) { + K key = r.front().key(); + MOZ_ASSERT_IF(gc::ToMarkable(key), !IsInsideNursery(gc::ToMarkable(key))); + V value = r.front().value(); + MOZ_ASSERT_IF(gc::ToMarkable(value), + !IsInsideNursery(gc::ToMarkable(value))); + } +#endif +} + // If the entry is live, ensure its key and value are marked. Also make sure the // key is at least as marked as min(map, delegate), so it cannot get discarded // and then recreated by rewrapping the delegate. @@ -134,8 +169,9 @@ WeakMap::WeakMap(JS::Zone* zone, JSObject* memOf) // delegates) where future changes to their mark color would require marking the // value (or the key). template -bool WeakMap::markEntry(GCMarker* marker, gc::CellColor mapColor, K& key, - V& value, bool populateWeakKeysTable) { +bool WeakMap::markEntry(GCMarker* marker, gc::CellColor mapColor, + BarrieredKey& key, BarrieredValue& value, + bool populateWeakKeysTable) { #ifdef DEBUG MOZ_ASSERT(IsMarked(mapColor)); if (marker->isParallelMarking()) { @@ -239,7 +275,7 @@ void WeakMap::trace(JSTracer* trc) { } // Always trace all values (unless weakMapAction() is Skip). - for (Range r = Base::all(); !r.empty(); r.popFront()) { + for (Range r = all(); !r.empty(); r.popFront()) { TraceEdge(trc, &r.front().value(), "WeakMap entry value"); } } @@ -281,9 +317,14 @@ bool WeakMap::markEntries(GCMarker* marker) { template void WeakMap::traceWeakEdges(JSTracer* trc) { - // Remove all entries whose keys remain unmarked. + // Scan the map, removing all entries whose keys remain unmarked. Rebuild + // cached key state at the same time. + mayHaveSymbolKeys = false; + mayHaveKeyDelegates = false; for (Enum e(*this); !e.empty(); e.popFront()) { - if (!TraceWeakEdge(trc, &e.front().mutableKey(), "WeakMap key")) { + if (TraceWeakEdge(trc, &e.front().mutableKey(), "WeakMap key")) { + keyWriteBarrier(e.front().key()); + } else { e.removeFront(); } } @@ -298,7 +339,7 @@ void WeakMap::traceWeakEdges(JSTracer* trc) { // memberOf can be nullptr, which means that the map is not part of a JSObject. template void WeakMap::traceMappings(WeakMapTracer* tracer) { - for (Range r = Base::all(); !r.empty(); r.popFront()) { + for (Range r = all(); !r.empty(); r.popFront()) { gc::Cell* key = gc::ToMarkable(r.front().key()); gc::Cell* value = gc::ToMarkable(r.front().value()); if (key && value) { @@ -309,50 +350,53 @@ void WeakMap::traceMappings(WeakMapTracer* tracer) { } template -bool WeakMap::findSweepGroupEdges() { +bool WeakMap::findSweepGroupEdges(Zone* atomsZone) { // For weakmap keys with delegates in a different zone, add a zone edge to // ensure that the delegate zone finishes marking before the key zone. - JS::AutoSuppressGCAnalysis nogc; - for (Range r = all(); !r.empty(); r.popFront()) { - const K& key = r.front().key(); - JSObject* delegate = gc::detail::GetDelegate(key); - if (delegate) { - // Marking a WeakMap key's delegate will mark the key, so process the - // delegate zone no later than the key zone. - Zone* delegateZone = delegate->zone(); - gc::Cell* keyCell = gc::ToMarkable(key); - MOZ_ASSERT(keyCell); - Zone* keyZone = keyCell->zone(); - if (delegateZone != keyZone && delegateZone->isGCMarking() && - keyZone->isGCMarking()) { - if (!delegateZone->addSweepGroupEdgeTo(keyZone)) { - return false; - } - } +#ifdef DEBUG + if (!mayHaveSymbolKeys || !mayHaveKeyDelegates) { + for (Range r = all(); !r.empty(); r.popFront()) { + const K& key = r.front().key(); + MOZ_ASSERT_IF(!mayHaveKeyDelegates, !gc::detail::GetDelegate(key)); + MOZ_ASSERT_IF(!mayHaveSymbolKeys, !gc::detail::IsSymbol(key)); } + } +#endif #ifdef NIGHTLY_BUILD - bool symbolsAsWeakMapKeysEnabled = - JS::Prefs::experimental_symbols_as_weakmap_keys(); - if (!symbolsAsWeakMapKeysEnabled) { - continue; + if (mayHaveSymbolKeys) { + MOZ_ASSERT(JS::Prefs::experimental_symbols_as_weakmap_keys()); + if (atomsZone->isGCMarking()) { + if (!atomsZone->addSweepGroupEdgeTo(zone())) { + return false; + } } + } +#endif - bool isSym = gc::detail::IsSymbol(key); - if (isSym) { - gc::Cell* keyCell = gc::ToMarkable(key); - Zone* keyZone = keyCell->zone(); - MOZ_ASSERT(keyZone->isAtomsZone()); + if (mayHaveKeyDelegates) { + for (Range r = all(); !r.empty(); r.popFront()) { + const K& key = r.front().key(); - if (zone()->isGCMarking() && keyZone->isGCMarking()) { - if (!keyZone->addSweepGroupEdgeTo(zone())) { - return false; + JSObject* delegate = gc::detail::GetDelegate(key); + if (delegate) { + // Marking a WeakMap key's delegate will mark the key, so process the + // delegate zone no later than the key zone. + Zone* delegateZone = delegate->zone(); + gc::Cell* keyCell = gc::ToMarkable(key); + MOZ_ASSERT(keyCell); + Zone* keyZone = keyCell->zone(); + if (delegateZone != keyZone && delegateZone->isGCMarking() && + keyZone->isGCMarking()) { + if (!delegateZone->addSweepGroupEdgeTo(keyZone)) { + return false; + } } } } -#endif } + return true; } @@ -364,8 +408,8 @@ size_t WeakMap::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { #if DEBUG template void WeakMap::assertEntriesNotAboutToBeFinalized() { - for (Range r = Base::all(); !r.empty(); r.popFront()) { - UnbarrieredKey k = r.front().key(); + for (Range r = all(); !r.empty(); r.popFront()) { + K k = r.front().key(); MOZ_ASSERT(!gc::IsAboutToBeFinalizedUnbarriered(k)); JSObject* delegate = gc::detail::GetDelegate(k); if (delegate) { @@ -381,7 +425,7 @@ void WeakMap::assertEntriesNotAboutToBeFinalized() { template bool WeakMap::checkMarking() const { bool ok = true; - for (Range r = Base::all(); !r.empty(); r.popFront()) { + for (Range r = all(); !r.empty(); r.popFront()) { gc::Cell* key = gc::ToMarkable(r.front().key()); gc::Cell* value = gc::ToMarkable(r.front().value()); if (key && value) { @@ -412,11 +456,7 @@ void WeakMap::checkAfterMovingGC() const { } #endif // JSGC_HASH_TABLE_CHECKS -inline HashNumber GetHash(JS::Symbol* sym) { return sym->hash(); } - -inline bool HashMatch(JS::Symbol* key, JS::Symbol* lookup) { - return key->hash() == lookup->hash(); -} +inline HashNumber GetSymbolHash(JS::Symbol* sym) { return sym->hash(); } } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/gc/WeakMap.cpp b/src/third_party/mozjs/extract/js/src/gc/WeakMap.cpp index 61d6b14e6d2..c552dcaff3c 100644 --- a/src/third_party/mozjs/extract/js/src/gc/WeakMap.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/WeakMap.cpp @@ -22,16 +22,8 @@ WeakMapBase::WeakMapBase(JSObject* memOf, Zone* zone) MOZ_ASSERT(!IsMarked(mapColor())); } -WeakMapBase::~WeakMapBase() { - MOZ_ASSERT(CurrentThreadIsGCFinalizing() || - CurrentThreadCanAccessZone(zone_)); -} - void WeakMapBase::unmarkZone(JS::Zone* zone) { - AutoEnterOOMUnsafeRegion oomUnsafe; - if (!zone->gcEphemeronEdges().clear()) { - oomUnsafe.crash("clearing ephemeron edges table"); - } + zone->gcEphemeronEdges().clearAndCompact(); MOZ_ASSERT(zone->gcNurseryEphemeronEdges().count() == 0); for (WeakMapBase* m : zone->gcWeakMapList()) { @@ -91,8 +83,13 @@ bool WeakMapBase::addEphemeronEdge(MarkColor color, gc::Cell* src, // Add an implicit edge from |src| to |dst|. auto& edgeTable = src->zone()->gcEphemeronEdges(src); - auto* ptr = edgeTable.getOrAdd(src); - return ptr && ptr->value.emplaceBack(color, dst); + auto p = edgeTable.lookupForAdd(src); + if (!p) { + if (!edgeTable.add(p, src, EphemeronEdgeVector())) { + return false; + } + } + return p->value().emplaceBack(color, dst); } #if defined(JS_GC_ZEAL) || defined(DEBUG) @@ -130,9 +127,10 @@ bool WeakMapBase::markZoneIteratively(JS::Zone* zone, GCMarker* marker) { return markedAny; } -bool WeakMapBase::findSweepGroupEdgesForZone(JS::Zone* zone) { - for (WeakMapBase* m : zone->gcWeakMapList()) { - if (!m->findSweepGroupEdges()) { +bool WeakMapBase::findSweepGroupEdgesForZone(JS::Zone* atomsZone, + JS::Zone* mapZone) { + for (WeakMapBase* m : mapZone->gcWeakMapList()) { + if (!m->findSweepGroupEdges(atomsZone)) { return false; } } @@ -189,36 +187,6 @@ void WeakMapBase::restoreMarkedWeakMaps(WeakMapColors& markedWeakMaps) { } } -ObjectWeakMap::ObjectWeakMap(JSContext* cx) : map(cx, nullptr) {} - -JSObject* ObjectWeakMap::lookup(const JSObject* obj) { - if (ObjectValueWeakMap::Ptr p = map.lookup(const_cast(obj))) { - return &p->value().toObject(); - } - return nullptr; -} - -bool ObjectWeakMap::add(JSContext* cx, JSObject* obj, JSObject* target) { - MOZ_ASSERT(obj && target); - - Value targetVal(ObjectValue(*target)); - if (!map.putNew(obj, targetVal)) { - ReportOutOfMemory(cx); - return false; - } - - return true; -} - -void ObjectWeakMap::remove(JSObject* key) { - MOZ_ASSERT(key); - map.remove(key); -} - -void ObjectWeakMap::clear() { map.clear(); } - -void ObjectWeakMap::trace(JSTracer* trc) { map.trace(trc); } - -size_t ObjectWeakMap::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) { - return map.shallowSizeOfExcludingThis(mallocSizeOf); -} +namespace js { +template class WeakMap; +} // namespace js diff --git a/src/third_party/mozjs/extract/js/src/gc/WeakMap.h b/src/third_party/mozjs/extract/js/src/gc/WeakMap.h index 76c40749d7a..6fbb3761dd3 100644 --- a/src/third_party/mozjs/extract/js/src/gc/WeakMap.h +++ b/src/third_party/mozjs/extract/js/src/gc/WeakMap.h @@ -13,10 +13,10 @@ #include "gc/Barrier.h" #include "gc/Marking.h" #include "gc/Tracer.h" -#include "gc/Zone.h" #include "gc/ZoneAllocator.h" #include "js/HashTable.h" #include "js/HeapAPI.h" +#include "vm/JSObject.h" namespace JS { class Zone; @@ -104,7 +104,7 @@ class WeakMapBase : public mozilla::LinkedListElement { using CellColor = js::gc::CellColor; WeakMapBase(JSObject* memOf, JS::Zone* zone); - virtual ~WeakMapBase(); + virtual ~WeakMapBase() {} JS::Zone* zone() const { return zone_; } @@ -120,8 +120,10 @@ class WeakMapBase : public mozilla::LinkedListElement { // marked members' mid-collection. static bool markZoneIteratively(JS::Zone* zone, GCMarker* marker); - // Add zone edges for weakmaps with key delegates in a different zone. - [[nodiscard]] static bool findSweepGroupEdgesForZone(JS::Zone* zone); + // Add zone edges for weakmaps in zone |mapZone| with key delegates in a + // different zone. + [[nodiscard]] static bool findSweepGroupEdgesForZone(JS::Zone* atomsZone, + JS::Zone* mapZone); // Sweep the marked weak maps in a zone, updating moved keys. static void sweepZoneAfterMinorGC(JS::Zone* zone); @@ -148,7 +150,7 @@ class WeakMapBase : public mozilla::LinkedListElement { // Instance member functions called by the above. Instantiations of WeakMap // override these with definitions appropriate for their Key and Value types. virtual void trace(JSTracer* tracer) = 0; - virtual bool findSweepGroupEdges() = 0; + virtual bool findSweepGroupEdges(Zone* atomsZone) = 0; virtual void traceWeakEdges(JSTracer* trc) = 0; virtual void traceMappings(WeakMapTracer* tracer) = 0; virtual void clearAndCompact() = 0; @@ -190,57 +192,80 @@ class WeakMapBase : public mozilla::LinkedListElement { // color it was marked. mozilla::Atomic mapColor_; + // Cached information about keys to speed up findSweepGroupEdges. + bool mayHaveKeyDelegates = false; + bool mayHaveSymbolKeys = false; + friend class JS::Zone; }; template -class WeakMap - : private HashMap, ZoneAllocPolicy>, - public WeakMapBase { +class WeakMap : public WeakMapBase { + using BarrieredKey = HeapPtr; + using BarrieredValue = HeapPtr; + + using Map = HashMap, HeapPtr, + StableCellHasher>, ZoneAllocPolicy>; + using UnbarrieredMap = + HashMap, ZoneAllocPolicy>; + + UnbarrieredMap map_; // Barriers are added by |map()| accessor. + public: - using Base = HashMap, ZoneAllocPolicy>; + using Lookup = typename Map::Lookup; + using Entry = typename Map::Entry; + using Range = typename Map::Range; + using Ptr = typename Map::Ptr; + using AddPtr = typename Map::AddPtr; - using Lookup = typename Base::Lookup; - using Entry = typename Base::Entry; - using Range = typename Base::Range; - using Ptr = typename Base::Ptr; - using AddPtr = typename Base::AddPtr; - - struct Enum : public Base::Enum { - explicit Enum(WeakMap& map) : Base::Enum(static_cast(map)) {} + struct Enum : public Map::Enum { + explicit Enum(WeakMap& map) : Map::Enum(map.map()) {} }; - using Base::all; - using Base::clear; - using Base::count; - using Base::empty; - using Base::has; - using Base::shallowSizeOfExcludingThis; - - // Resolve ambiguity with LinkedListElement<>::remove. - using Base::remove; - - using UnbarrieredKey = typename RemoveBarrier::Type; - explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr); explicit WeakMap(JS::Zone* zone, JSObject* memOf = nullptr); + ~WeakMap() override; - // Add a read barrier to prevent an incorrectly gray value from escaping the - // weak map. See the UnmarkGrayTracer::onChild comment in gc/Marking.cpp. + Range all() const { return map().all(); } + uint32_t count() const { return map().count(); } + bool empty() const { return map().empty(); } + bool has(const Lookup& lookup) const { return map().has(lookup); } + void remove(const Lookup& lookup) { return map().remove(lookup); } + void remove(Ptr ptr) { return map().remove(ptr); } + + size_t shallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { + return map().shallowSizeOfExcludingThis(aMallocSizeOf); + } + size_t shallowSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(this) + shallowSizeOfExcludingThis(aMallocSizeOf); + } + + // Get the value associated with a key, or a default constructed Value if the + // key is not present in the map. + Value get(const Lookup& l) { + Ptr ptr = lookup(l); + if (!ptr) { + return Value(); + } + return ptr->value(); + } + + // Add a read barrier to prevent a gray value from escaping the weak map. This + // is necessary because we don't unmark gray through weak maps. Ptr lookup(const Lookup& l) const { - Ptr p = Base::lookup(l); + Ptr p = map().lookup(l); if (p) { - exposeGCThingToActiveJS(p->value()); + valueReadBarrier(p->value()); } return p; } - Ptr lookupUnbarriered(const Lookup& l) const { return Base::lookup(l); } + Ptr lookupUnbarriered(const Lookup& l) const { return map().lookup(l); } AddPtr lookupForAdd(const Lookup& l) { - AddPtr p = Base::lookupForAdd(l); + AddPtr p = map().lookupForAdd(l); if (p) { - exposeGCThingToActiveJS(p->value()); + valueReadBarrier(p->value()); } return p; } @@ -248,88 +273,69 @@ class WeakMap template [[nodiscard]] bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) { MOZ_ASSERT(gc::ToMarkable(k)); - return Base::add(p, std::forward(k), std::forward(v)); + keyWriteBarrier(std::forward(k)); + return map().add(p, std::forward(k), std::forward(v)); } template [[nodiscard]] bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) { MOZ_ASSERT(gc::ToMarkable(k)); - return Base::relookupOrAdd(p, std::forward(k), + keyWriteBarrier(std::forward(k)); + return map().relookupOrAdd(p, std::forward(k), std::forward(v)); } template [[nodiscard]] bool put(KeyInput&& k, ValueInput&& v) { MOZ_ASSERT(gc::ToMarkable(k)); - return Base::put(std::forward(k), std::forward(v)); + keyWriteBarrier(std::forward(k)); + return map().put(std::forward(k), std::forward(v)); } template [[nodiscard]] bool putNew(KeyInput&& k, ValueInput&& v) { MOZ_ASSERT(gc::ToMarkable(k)); - return Base::putNew(std::forward(k), std::forward(v)); + keyWriteBarrier(std::forward(k)); + return map().putNew(std::forward(k), std::forward(v)); } template void putNewInfallible(KeyInput&& k, ValueInput&& v) { MOZ_ASSERT(gc::ToMarkable(k)); - Base::putNewInfallible(std::forward(k), std::forward(k)); + keyWriteBarrier(std::forward(k)); + map().putNewInfallible(std::forward(k), std::forward(k)); + } + + void clear() { + map().clear(); + mayHaveSymbolKeys = false; + mayHaveKeyDelegates = false; } #ifdef DEBUG template bool hasEntry(KeyInput&& key, ValueInput&& value) { - Ptr p = Base::lookup(std::forward(key)); + Ptr p = map().lookup(std::forward(key)); return p && p->value() == value; } #endif - bool markEntry(GCMarker* marker, gc::CellColor mapColor, Key& key, - Value& value, bool populateWeakKeysTable); + bool markEntry(GCMarker* marker, gc::CellColor mapColor, BarrieredKey& key, + BarrieredValue& value, bool populateWeakKeysTable); void trace(JSTracer* trc) override; size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); protected: - inline void assertMapIsSameZoneWithValue(const Value& v); + inline void assertMapIsSameZoneWithValue(const BarrieredValue& v); bool markEntries(GCMarker* marker) override; - protected: // Find sweep group edges for delegates, if the key type has delegates. (If // not, the optimizer should make this a nop.) - bool findSweepGroupEdges() override; + bool findSweepGroupEdges(Zone* atomsZone) override; - /** - * If a wrapper is used as a key in a weakmap, the garbage collector should - * keep that object around longer than it otherwise would. We want to avoid - * collecting the wrapper (and removing the weakmap entry) as long as the - * wrapped object is alive (because the object can be rewrapped and looked up - * again). As long as the wrapper is used as a weakmap key, it will not be - * collected (and remain in the weakmap) until the wrapped object is - * collected. - */ - private: - void exposeGCThingToActiveJS(const JS::Value& v) const { - JS::ExposeValueToActiveJS(v); - } - void exposeGCThingToActiveJS(JSObject* obj) const { - JS::ExposeObjectToActiveJS(obj); - } - - void traceWeakEdges(JSTracer* trc) override; - - void clearAndCompact() override { - Base::clear(); - Base::compact(); - } - - // memberOf can be nullptr, which means that the map is not part of a - // JSObject. - void traceMappings(WeakMapTracer* tracer) override; - - protected: #if DEBUG void assertEntriesNotAboutToBeFinalized(); #endif @@ -341,39 +347,55 @@ class WeakMap #ifdef JSGC_HASH_TABLE_CHECKS void checkAfterMovingGC() const override; #endif -}; -using ObjectValueWeakMap = WeakMap, HeapPtr>; -using ValueValueWeakMap = WeakMap, HeapPtr>; + private: + // Map accessor uses a cast to add barriers. + Map& map() { return reinterpret_cast(map_); } + const Map& map() const { return reinterpret_cast(map_); } -// Generic weak map for mapping objects to other objects. -class ObjectWeakMap { - ObjectValueWeakMap map; - - public: - explicit ObjectWeakMap(JSContext* cx); - - JS::Zone* zone() const { return map.zone(); } - - JSObject* lookup(const JSObject* obj); - bool add(JSContext* cx, JSObject* obj, JSObject* target); - void remove(JSObject* key); - void clear(); - - void trace(JSTracer* trc); - size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); - size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { - return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); + static void valueReadBarrier(const JS::Value& v) { + JS::ExposeValueToActiveJS(v); + } + static void valueReadBarrier(JSObject* obj) { + JS::ExposeObjectToActiveJS(obj); } - ObjectValueWeakMap& valueMap() { return map; } + void keyWriteBarrier(const JS::Value& v) { + if (v.isSymbol()) { + mayHaveSymbolKeys = true; + } + if (v.isObject()) { + keyWriteBarrier(&v.toObject()); + } + } + void keyWriteBarrier(JSObject* key) { + JSObject* delegate = UncheckedUnwrapWithoutExpose(key); + if (delegate != key || ObjectMayBeSwapped(key)) { + mayHaveKeyDelegates = true; + } + } + void keyWriteBarrier(BaseScript* key) {} + + void traceWeakEdges(JSTracer* trc) override; + + void clearAndCompact() override { + map().clear(); + map().compact(); + } + + // memberOf can be nullptr, which means that the map is not part of a + // JSObject. + void traceMappings(WeakMapTracer* tracer) override; }; -// Get the hash from the Symbol. -[[nodiscard]] HashNumber GetHash(JS::Symbol* sym); +using ObjectValueWeakMap = WeakMap; +using ValueValueWeakMap = WeakMap; -// Return true if the hashes of two Symbols match. -[[nodiscard]] bool HashMatch(JS::Symbol* key, JS::Symbol* lookup); +// Generic weak map for mapping objects to other objects. +using ObjectWeakMap = WeakMap; + +// Get the hash from the Symbol. +HashNumber GetSymbolHash(JS::Symbol* sym); // NB: The specialization works based on pointer equality and not on JS Value // semantics, and it will assert if the Value's isGCThing() is false. @@ -388,27 +410,27 @@ struct StableCellHasher> { static bool maybeGetHash(const Lookup& l, HashNumber* hashOut) { if (l.isSymbol()) { - *hashOut = GetHash(l.toSymbol()); + *hashOut = GetSymbolHash(l.toSymbol()); return true; } return StableCellHasher::maybeGetHash(l.toGCThing(), hashOut); } static bool ensureHash(const Lookup& l, HashNumber* hashOut) { if (l.isSymbol()) { - *hashOut = GetHash(l.toSymbol()); + *hashOut = GetSymbolHash(l.toSymbol()); return true; } return StableCellHasher::ensureHash(l.toGCThing(), hashOut); } static HashNumber hash(const Lookup& l) { if (l.isSymbol()) { - return GetHash(l.toSymbol()); + return GetSymbolHash(l.toSymbol()); } return StableCellHasher::hash(l.toGCThing()); } static bool match(const Key& k, const Lookup& l) { if (l.isSymbol()) { - return HashMatch(k.toSymbol(), l.toSymbol()); + return k.toSymbol() == l.toSymbol(); } return StableCellHasher::match(k.toGCThing(), l.toGCThing()); } diff --git a/src/third_party/mozjs/extract/js/src/gc/WeakMapPtr.cpp b/src/third_party/mozjs/extract/js/src/gc/WeakMapPtr.cpp index 0910e7d3be6..42cf10b7994 100644 --- a/src/third_party/mozjs/extract/js/src/gc/WeakMapPtr.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/WeakMapPtr.cpp @@ -22,21 +22,18 @@ struct DataType {}; template <> struct DataType { - using BarrieredType = HeapPtr; - using HasherType = StableCellHasher; static JSObject* NullValue() { return nullptr; } }; template <> struct DataType { - using BarrieredType = HeapPtr; static JS::Value NullValue() { return JS::UndefinedValue(); } }; template struct Utils { - using KeyType = typename DataType::BarrieredType; - using ValueType = typename DataType::BarrieredType; + using KeyType = K; + using ValueType = V; using Type = WeakMap; using PtrType = Type*; static PtrType cast(void* ptr) { return static_cast(ptr); } diff --git a/src/third_party/mozjs/extract/js/src/gc/Zone.cpp b/src/third_party/mozjs/extract/js/src/gc/Zone.cpp index e7c058dfd5e..7c1d922f03b 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Zone.cpp +++ b/src/third_party/mozjs/extract/js/src/gc/Zone.cpp @@ -159,6 +159,7 @@ template class TrackedAllocPolicy; JS::Zone::Zone(JSRuntime* rt, Kind kind) : ZoneAllocator(rt, kind), arenas(this), + bufferAllocator(this), data(nullptr), suppressAllocationMetadataBuilder(false), allocNurseryObjects_(true), @@ -166,9 +167,6 @@ JS::Zone::Zone(JSRuntime* rt, Kind kind) allocNurseryBigInts_(true), pretenuring(this), crossZoneStringWrappers_(this), - gcEphemeronEdges_(SystemAllocPolicy(), rt->randomHashCodeScrambler()), - gcNurseryEphemeronEdges_(SystemAllocPolicy(), - rt->randomHashCodeScrambler()), shapeZone_(this), gcScheduled_(false), gcScheduledSaved_(false), @@ -208,8 +206,7 @@ Zone::~Zone() { bool Zone::init() { regExps_.ref() = make_unique(this); - return regExps_.ref() && gcEphemeronEdges().init() && - gcNurseryEphemeronEdges().init(); + return !!regExps_.ref(); } void Zone::setNeedsIncrementalBarrier(bool needs) { @@ -267,8 +264,7 @@ void Zone::sweepAfterMinorGC(JSTracer* trc) { } void Zone::sweepEphemeronTablesAfterMinorGC() { - for (auto r = gcNurseryEphemeronEdges().mutableAll(); !r.empty(); - r.popFront()) { + for (auto r = gcNurseryEphemeronEdges().all(); !r.empty(); r.popFront()) { // Sweep gcNurseryEphemeronEdges to move live (forwarded) keys to // gcEphemeronEdges, scanning through all the entries for such keys to // update them. @@ -280,7 +276,7 @@ void Zone::sweepEphemeronTablesAfterMinorGC() { // tenured. Then it will be in its compartment's gcEphemeronEdges, but we // still need to update the key (which will be in the entries // associated with it.) - gc::Cell* key = r.front().key; + gc::Cell* key = r.front().key(); MOZ_ASSERT(!key->isTenured()); if (!Nursery::getForwardedPointer(&key)) { // Dead nursery cell => discard. @@ -289,18 +285,19 @@ void Zone::sweepEphemeronTablesAfterMinorGC() { // Key been moved. The value is an array of pairs; update all // cells in that array. - EphemeronEdgeVector& entries = r.front().value; + EphemeronEdgeVector& entries = r.front().value(); SweepEphemeronEdgesWhileMinorSweeping(entries); // Live (moved) nursery cell. Append entries to gcEphemeronEdges. EphemeronEdgeTable& tenuredEdges = gcEphemeronEdges(); AutoEnterOOMUnsafeRegion oomUnsafe; - auto* entry = tenuredEdges.getOrAdd(key); + auto entry = tenuredEdges.lookupForAdd(key); if (!entry) { - oomUnsafe.crash("Failed to tenure weak keys entry"); + if (!tenuredEdges.add(entry, key, EphemeronEdgeVector())) { + oomUnsafe.crash("Failed to tenure weak keys entry"); + } } - - if (!entry->value.appendAll(entries)) { + if (!entry->value().appendAll(entries)) { oomUnsafe.crash("Failed to tenure weak keys entry"); } @@ -319,16 +316,13 @@ void Zone::sweepEphemeronTablesAfterMinorGC() { // location it was stored in has already been updated. // // Otherwise, it will be in gcEphemeronEdges and we sweep it here. - auto* p = delegate->zone()->gcEphemeronEdges().get(delegate); + auto p = delegate->zone()->gcEphemeronEdges().lookup(delegate); if (p) { - SweepEphemeronEdgesWhileMinorSweeping(p->value); + SweepEphemeronEdgesWhileMinorSweeping(p->value()); } } - if (!gcNurseryEphemeronEdges().clear()) { - AutoEnterOOMUnsafeRegion oomUnsafe; - oomUnsafe.crash("OOM while clearing gcNurseryEphemeronEdges."); - } + gcNurseryEphemeronEdges().clearAndCompact(); } void Zone::traceWeakCCWEdges(JSTracer* trc) { @@ -377,14 +371,14 @@ void Zone::checkStringWrappersAfterMovingGC() { } #endif -void Zone::discardJitCode(JS::GCContext* gcx, const DiscardOptions& options) { +void Zone::maybeDiscardJitCode(JS::GCContext* gcx) { if (!isPreservingCode()) { - forceDiscardJitCode(gcx, options); + forceDiscardJitCode(gcx); } } void Zone::forceDiscardJitCode(JS::GCContext* gcx, - const DiscardOptions& options) { + const JitDiscardOptions& options) { if (!jitZone()) { return; } @@ -438,11 +432,13 @@ void Zone::forceDiscardJitCode(JS::GCContext* gcx, script->maybeReleaseJitScript(gcx); jitScript = script->maybeJitScript(); if (!jitScript) { - // Try to discard the ScriptCounts too. + // If we successfully discarded the JIT script, try to discard the + // ScriptCounts too. if (!script->realm()->collectCoverageForDebug() && !gcx->runtime()->profilingScripts) { script->destroyScriptCounts(); } + script->realm()->removeFromCompileQueue(script); return; // Continue script loop. } } @@ -461,11 +457,6 @@ void Zone::forceDiscardJitCode(JS::GCContext* gcx, // Reset the active flag of each ICScript. jitScript->resetAllActiveFlags(); - - // Optionally trace weak edges in remaining JitScripts. - if (options.traceWeakJitScripts) { - jitScript->traceWeak(options.traceWeakJitScripts); - } }); // Also clear references to jit code from RegExpShared cells at this point. @@ -569,7 +560,7 @@ js::jit::JitZone* Zone::createJitZone(JSContext* cx) { MOZ_ASSERT(cx->runtime()->hasJitRuntime()); #endif - auto jitZone = cx->make_unique(allocNurseryStrings()); + auto jitZone = cx->make_unique(cx, allocNurseryStrings()); if (!jitZone) { return nullptr; } @@ -611,9 +602,20 @@ Zone* Zone::nextZone() const { return listNext_; } +void Zone::prepareForMovingGC() { + JS::GCContext* gcx = runtimeFromMainThread()->gcContext(); + + MOZ_ASSERT(!isPreservingCode()); + forceDiscardJitCode(gcx); + + // We must always call fixupAfterMovingGC after this point. + bufferAllocator.prepareForMovingGC(); +} + void Zone::fixupAfterMovingGC() { ZoneAllocator::fixupAfterMovingGC(); shapeZone().fixupPropMapShapeTableAfterMovingGC(); + bufferAllocator.fixupAfterMovingGC(); } void Zone::purgeAtomCache() { @@ -906,7 +908,13 @@ void Zone::clearScriptCounts(Realm* realm) { // Clear all hasScriptCounts_ flags of BaseScript, in order to release all // ScriptCounts entries of the given realm. for (auto i = scriptCountsMap->modIter(); !i.done(); i.next()) { - BaseScript* script = i.get().key(); + const HeapPtr& script = i.get().key(); + if (IsAboutToBeFinalized(script)) { + // Dead scripts may be present during incremental GC until script + // finalizers have been run. + continue; + } + if (script->realm() != realm) { continue; } @@ -927,7 +935,13 @@ void Zone::clearScriptLCov(Realm* realm) { } for (auto i = scriptLCovMap->modIter(); !i.done(); i.next()) { - BaseScript* script = i.get().key(); + const HeapPtr& script = i.get().key(); + if (IsAboutToBeFinalized(script)) { + // Dead scripts may be present during incremental GC until script + // finalizers have been run. + continue; + } + if (script->realm() == realm) { i.remove(); } diff --git a/src/third_party/mozjs/extract/js/src/gc/Zone.h b/src/third_party/mozjs/extract/js/src/gc/Zone.h index 81e55e53aab..744ef43c1be 100644 --- a/src/third_party/mozjs/extract/js/src/gc/Zone.h +++ b/src/third_party/mozjs/extract/js/src/gc/Zone.h @@ -22,6 +22,7 @@ #include "ds/Bitmap.h" #include "gc/ArenaList.h" #include "gc/Barrier.h" +#include "gc/BufferAllocator.h" #include "gc/FindSCCs.h" #include "gc/GCMarker.h" #include "gc/NurseryAwareHashMap.h" @@ -95,12 +96,14 @@ using StringWrapperMap = NurseryAwareHashMap; -// Cache for NewMaybeExternalString. It has cache entries for both the -// Latin1 JSInlineString path and JSExternalString. +// Cache for NewMaybeExternalString and NewStringFromBuffer. It has separate +// cache entries for the Latin1 JSThinInlineString fast path and for the generic +// path where we allocate either a JSExternalString, an inline string, or a +// string with a StringBuffer. class MOZ_NON_TEMPORARY_CLASS ExternalStringCache { static const size_t NumEntries = 4; - mozilla::Array externalEntries_; - mozilla::Array inlineEntries_; + mozilla::Array inlineLatin1Entries_; + mozilla::Array entries_; public: ExternalStringCache() { purge(); } @@ -109,29 +112,29 @@ class MOZ_NON_TEMPORARY_CLASS ExternalStringCache { void operator=(const ExternalStringCache&) = delete; void purge() { - externalEntries_ = {}; - inlineEntries_ = {}; + inlineLatin1Entries_ = {}; + entries_ = {}; } - MOZ_ALWAYS_INLINE JSExternalString* lookupExternal( - const JS::Latin1Char* chars, size_t len) const; - MOZ_ALWAYS_INLINE JSExternalString* lookupExternal(const char16_t* chars, - size_t len) const; - MOZ_ALWAYS_INLINE void putExternal(JSExternalString* s); + MOZ_ALWAYS_INLINE JSLinearString* lookup(const JS::Latin1Char* chars, + size_t len) const; + MOZ_ALWAYS_INLINE JSLinearString* lookup(const char16_t* chars, + size_t len) const; + MOZ_ALWAYS_INLINE void put(JSLinearString* s); - MOZ_ALWAYS_INLINE JSInlineString* lookupInline(const JS::Latin1Char* chars, - size_t len) const; - MOZ_ALWAYS_INLINE JSInlineString* lookupInline(const char16_t* chars, - size_t len) const; - MOZ_ALWAYS_INLINE void putInline(JSInlineString* s); + MOZ_ALWAYS_INLINE JSInlineString* lookupInlineLatin1( + const JS::Latin1Char* chars, size_t len) const; + MOZ_ALWAYS_INLINE JSInlineString* lookupInlineLatin1(const char16_t* chars, + size_t len) const; + MOZ_ALWAYS_INLINE void putInlineLatin1(JSInlineString* s); private: template - MOZ_ALWAYS_INLINE JSExternalString* lookupExternalImpl(const CharT* chars, - size_t len) const; + MOZ_ALWAYS_INLINE JSLinearString* lookupImpl(const CharT* chars, + size_t len) const; template - MOZ_ALWAYS_INLINE JSInlineString* lookupInlineImpl(const CharT* chars, - size_t len) const; + MOZ_ALWAYS_INLINE JSInlineString* lookupInlineLatin1Impl(const CharT* chars, + size_t len) const; }; class MOZ_NON_TEMPORARY_CLASS FunctionToStringCache { @@ -395,6 +398,8 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase { public: js::gc::ArenaLists arenas; + js::gc::BufferAllocator bufferAllocator; + // Per-zone data for use by an embedder. js::MainThreadData data; @@ -560,20 +565,19 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase { [[nodiscard]] bool findSweepGroupEdges(Zone* atomsZone); - struct DiscardOptions { - DiscardOptions() {} + struct JitDiscardOptions { + JitDiscardOptions() {} bool discardJitScripts = false; bool resetNurseryAllocSites = false; bool resetPretenuredAllocSites = false; - JSTracer* traceWeakJitScripts = nullptr; }; - void discardJitCode(JS::GCContext* gcx, - const DiscardOptions& options = DiscardOptions()); + void maybeDiscardJitCode(JS::GCContext* gcx); // Discard JIT code regardless of isPreservingCode(). - void forceDiscardJitCode(JS::GCContext* gcx, - const DiscardOptions& options = DiscardOptions()); + void forceDiscardJitCode( + JS::GCContext* gcx, + const JitDiscardOptions& options = JitDiscardOptions()); void resetAllocSitesAndInvalidate(bool resetNurserySites, bool resetPretenuredSites); @@ -679,8 +683,6 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase { return numRealmsWithAllocMetadataBuilder_ > 0; } - void prepareForCompacting(); - void traceRootsInMajorGC(JSTracer* trc); void sweepAfterMinorGC(JSTracer* trc); @@ -727,7 +729,9 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase { void traceWeakCCWEdges(JSTracer* trc); static void fixupAllCrossCompartmentWrappersAfterMovingGC(JSTracer* trc); + void prepareForMovingGC(); void fixupAfterMovingGC(); + void fixupScriptMapsAfterMovingGC(JSTracer* trc); void setNurseryAllocFlags(bool allocObjects, bool allocStrings, @@ -794,7 +798,7 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase { // Perform all pending weakmap entry marking for this zone after // transitioning to weak marking mode. js::gc::IncrementalProgress enterWeakMarkingMode(js::GCMarker* marker, - js::SliceBudget& budget); + JS::SliceBudget& budget); // A set of edges from this zone to other zones used during GC to calculate // sweep groups. @@ -866,8 +870,11 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase { js::gc::AllocSite* optimizedAllocSite() { return &pretenuring.optimizedAllocSite; } - uint32_t nurseryAllocCount(JS::TraceKind kind) const { - return pretenuring.nurseryAllocCount(kind); + js::gc::AllocSite* tenuringAllocSite() { + return &pretenuring.tenuringAllocSite; + } + uint32_t nurseryPromotedCount(JS::TraceKind kind) const { + return pretenuring.nurseryPromotedCount(kind); } #ifdef JSGC_HASH_TABLE_CHECKS diff --git a/src/third_party/mozjs/extract/js/src/gc/moz.build b/src/third_party/mozjs/extract/js/src/gc/moz.build index 489b5a96aeb..5facaa7b63d 100644 --- a/src/third_party/mozjs/extract/js/src/gc/moz.build +++ b/src/third_party/mozjs/extract/js/src/gc/moz.build @@ -28,6 +28,7 @@ UNIFIED_SOURCES += [ "Allocator.cpp", "AtomMarking.cpp", "Barrier.cpp", + "BufferAllocator.cpp", "Compacting.cpp", "FinalizationObservers.cpp", "GC.cpp", @@ -36,7 +37,6 @@ UNIFIED_SOURCES += [ "Heap.cpp", "MallocedBlockCache.cpp", "Marking.cpp", - "Memory.cpp", "Nursery.cpp", "ParallelMarking.cpp", "Pretenuring.cpp", @@ -53,9 +53,12 @@ UNIFIED_SOURCES += [ "Zone.cpp", ] -# StoreBuffer.cpp cannot be built in unified mode because its template -# instantiations may or may not be needed depending on what it gets bundled -# with. SOURCES += [ + # Memory.cpp cannot be built in unified mode because it includes + # platform specific headers which conflict with our code on MinGW. + "Memory.cpp", + # StoreBuffer.cpp cannot be built in unified mode because its template + # instantiations may or may not be needed depending on what it gets + # bundled with. "StoreBuffer.cpp", ] diff --git a/src/third_party/mozjs/extract/js/src/ics/remove-duplicates.py b/src/third_party/mozjs/extract/js/src/ics/remove-duplicates.py new file mode 100755 index 00000000000..c669bc6bd00 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/ics/remove-duplicates.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import glob +import hashlib +import os + +have_hashes = set() + +for file in glob.glob("IC-*"): + with open(file, "rb") as f: + content = f.read() + h = hashlib.new("sha256") + h.update(content) + digest = h.hexdigest() + if digest in have_hashes: + print("Removing: %s" % file) + os.unlink(file) + have_hashes.add(digest) diff --git a/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.cpp b/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.cpp index 0e79ccad36b..5039e62dec6 100644 --- a/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.cpp +++ b/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.cpp @@ -10,21 +10,32 @@ #include "mozilla/CheckedInt.h" #include "mozilla/IntegerPrintfMacros.h" +#include "mozilla/TimeStamp.h" #include +#include "fmt/format.h" #include "js/ErrorReport.h" #include "js/HeapAPI.h" #include "vm/ArrayBufferObject.h" +#include "vm/GeckoProfiler.h" +#include "vm/JSContext.h" #include "wasm/WasmBuiltins.h" #include "wasm/WasmInstance.h" #include "wasm/WasmLog.h" #if defined(USE_AVX512BW) # if defined(USE_AVX512VNNI) -# define SUPPORTED_ARCHS \ - xsimd::arch_list, xsimd::avx512bw, \ - xsimd::avx2, xsimd::ssse3, xsimd::sse2> +# if defined(USE_AVXVNNI) +# define SUPPORTED_ARCHS \ + xsimd::arch_list, xsimd::avx512bw, \ + xsimd::avxvnni, xsimd::avx2, xsimd::ssse3, \ + xsimd::sse2> +# else +# define SUPPORTED_ARCHS \ + xsimd::arch_list, xsimd::avx512bw, \ + xsimd::avx2, xsimd::ssse3, xsimd::sse2> +# endif # elif defined(USE_AVXVNNI) # define SUPPORTED_ARCHS \ xsimd::arch_list::FUNC(args...); \ }) -struct JSContext; +template +struct AutoProfilerMarker { + AutoProfilerMarker(js::GeckoProfilerRuntime& profiler, const CharT* name) + : profiler(profiler), name(name) { + if (profiler.enabled()) { + startTime = mozilla::TimeStamp::Now(); + } + } + + template + AutoProfilerMarker(js::GeckoProfilerRuntime& profiler, const CharT* name, + fmt::format_string aFormatStr, Args&&... aArgs) + : profiler(profiler), name(name) { + if (profiler.enabled()) { + startTime = mozilla::TimeStamp::Now(); + auto [out, size] = fmt::vformat_to_n( + text, sizeof(text) - 1, aFormatStr, + fmt::make_format_args>(aArgs...)); + + MOZ_ASSERT(size > sizeof(text) - 1, + "Truncated marker, consider increasing the buffer"); + + *out = 0; + } + } + ~AutoProfilerMarker() { + if (profiler.enabled()) { + profiler.markInterval(name, startTime, text, + JS::ProfilingCategoryPair::JS); + } + } + js::GeckoProfilerRuntime& profiler; + const char* name; + char text[TextLength]{}; + mozilla::TimeStamp startTime; +}; static constexpr uint32_t ARRAY_ALIGNMENT = 64; static constexpr uint32_t ROWS_A_MULTIPLIER = 1; @@ -159,11 +205,15 @@ int32_t js::intgemm::IntrI8PrepareB(wasm::Instance* instance, } // Actual call to the 3rd party library (intgemm) for PrepareB - uint8_t* inputMatrixBPtr = &memBase[inputMatrixB]; - uint8_t* outputMatrixBPtr = &memBase[outputMatrixB]; + const float* inputMatrixBPtr = + reinterpret_cast(&memBase[inputMatrixB]); + int8_t* outputMatrixBPtr = reinterpret_cast(&memBase[outputMatrixB]); + AutoProfilerMarker marker(cx->runtime()->geckoProfiler(), "integemm::PreparB", + FMT_STRING("rowsB: {} colsB: {} sizeB: {}"), rowsB, + colsB, sizeB); GEMMOLOGY_DISPATCH(PrepareB) - ((const float*)inputMatrixBPtr, (int8_t*)outputMatrixBPtr, - (float)scale, // Quant Mult + (inputMatrixBPtr, outputMatrixBPtr, + scale, // Quant Mult rowsB, colsB); return 0; } @@ -201,11 +251,15 @@ int32_t js::intgemm::IntrI8PrepareBFromTransposed( } // Actual call to the 3rd party library (intgemm) for PrepareBTransposed - uint8_t* inputMatrixBTransposedPtr = &memBase[inputMatrixBTransposed]; - uint8_t* outputMatrixBPtr = &memBase[outputMatrixB]; + const float* inputMatrixBTransposedPtr = + reinterpret_cast(&memBase[inputMatrixBTransposed]); + int8_t* outputMatrixBPtr = reinterpret_cast(&memBase[outputMatrixB]); + AutoProfilerMarker marker( + cx->runtime()->geckoProfiler(), "intgemm::PreparBTransposed", + FMT_STRING("rowsB: {} colsB: {} sizeB: {}"), rowsB, colsB, sizeB); GEMMOLOGY_DISPATCH(PrepareBTransposed) - ((const float*)inputMatrixBTransposedPtr, (int8_t*)outputMatrixBPtr, - (float)scale, // Quant Mult + (inputMatrixBTransposedPtr, outputMatrixBPtr, + scale, // Quant Mult rowsB, colsB); return 0; } @@ -242,12 +296,15 @@ int32_t js::intgemm::IntrI8PrepareBFromQuantizedTransposed( } // Actual call to the 3rd party library (intgemm) - uint8_t* inputMatrixBQuantizedTransposedPtr = - &memBase[inputMatrixBQuantizedTransposed]; - uint8_t* outputMatrixBPtr = &memBase[outputMatrixB]; + const int8_t* inputMatrixBQuantizedTransposedPtr = + reinterpret_cast( + &memBase[inputMatrixBQuantizedTransposed]); + int8_t* outputMatrixBPtr = reinterpret_cast(&memBase[outputMatrixB]); + AutoProfilerMarker marker(cx->runtime()->geckoProfiler(), + "intgemm::PrepareBQuantizedTransposed", + FMT_STRING("rowsB: {}, colsB: {}"), rowsB, colsB); GEMMOLOGY_DISPATCH(PrepareBQuantizedTransposed) - ((const int8_t*)inputMatrixBQuantizedTransposedPtr, (int8_t*)outputMatrixBPtr, - rowsB, colsB); + (inputMatrixBQuantizedTransposedPtr, outputMatrixBPtr, rowsB, colsB); return 0; } @@ -259,7 +316,6 @@ int32_t js::intgemm::IntrI8PrepareA(wasm::Instance* instance, MOZ_ASSERT(wasm::SASigIntrI8PrepareA.failureMode == wasm::FailureMode::FailOnNegI32); JSContext* cx = instance->cx(); - // Size checks for matricies if (!CheckMatrixDimension(cx, rowsA, ROWS_A_MULTIPLIER) || !CheckMatrixDimension(cx, colsA, COLUMNS_A_MULTIPLIER)) { @@ -284,10 +340,13 @@ int32_t js::intgemm::IntrI8PrepareA(wasm::Instance* instance, } // Actual call to the 3rd party library (intgemm) - uint8_t* inputMatrixAPtr = &memBase[inputMatrixA]; + const float* inputMatrixAPtr = + reinterpret_cast(&memBase[inputMatrixA]); uint8_t* outputMatrixAPtr = &memBase[outputMatrixA]; + AutoProfilerMarker marker(cx->runtime()->geckoProfiler(), "intgemm::PrepareA", + FMT_STRING("rowsA: {}, colsA: {}"), rowsA, colsA); GEMMOLOGY_DISPATCH(Shift::PrepareA) - ((const float*)inputMatrixAPtr, outputMatrixAPtr, scale, rowsA, colsA); + (inputMatrixAPtr, outputMatrixAPtr, scale, rowsA, colsA); return 0; } @@ -308,34 +367,53 @@ int32_t js::intgemm::IntrI8PrepareBias( return -1; } - // Memory Bound checks for all matricies + // Memory Bound checks for all matrices uint64_t sizeB = (uint64_t)rowsB * (uint64_t)colsB; uint64_t sizeBias = colsB; size_t wasmBufferSize = GetWasmRawBufferLength(memBase); if (!CheckMatrixBoundAndAlignment(cx, inputMatrixBPrepared, sizeB, wasmBufferSize) || - !CheckMatrixBound(cx, inputBias, sizeBias, wasmBufferSize) || !CheckMatrixBound(cx, output, sizeBias, wasmBufferSize)) { wasm::Log(cx, "%s: preparedB:%x rowsB:%" PRIu32 " colsB:%" PRIu32 - " inputBias:%x outputBias:%x sizeB:%" PRIu64 - " wasmBufferSize:%zu", - __FUNCTION__, inputMatrixBPrepared, rowsB, colsB, inputBias, - output, sizeB, wasmBufferSize); + " outputBias:%x sizeB:%" PRIu64 " wasmBufferSize:%zu", + __FUNCTION__, inputMatrixBPrepared, rowsB, colsB, output, sizeB, + wasmBufferSize); ReportGemmError(cx, JSMSG_WASM_OUT_OF_BOUNDS); return -1; } // Actual call to the 3rd party library (intgemm) - uint8_t* inputMatrixBPreparedPtr = &memBase[inputMatrixBPrepared]; - uint8_t* inputBiasPtr = &memBase[inputBias]; - uint8_t* outputPtr = &memBase[output]; + const int8_t* inputMatrixBPreparedPtr = + (const int8_t*)&memBase[inputMatrixBPrepared]; + float* outputPtr = (float*)&memBase[output]; float unquantFactor = (-1) * ((127.0f / scaleA) * (127.0f / scaleB)) / (127.0f); - GEMMOLOGY_DISPATCH(Shift::PrepareBias) - ((const int8_t*)inputMatrixBPreparedPtr, rowsB, colsB, - gemmology::callbacks::UnquantizeAndAddBiasAndWrite( - unquantFactor, (const float*)inputBiasPtr, (float*)outputPtr)); + + if (inputBias) { + if (!CheckMatrixBound(cx, inputBias, sizeBias, wasmBufferSize)) { + wasm::Log(cx, "%s: inputBias:%x wasmBufferSize:%zu", __FUNCTION__, + inputBias, wasmBufferSize); + ReportGemmError(cx, JSMSG_WASM_OUT_OF_BOUNDS); + return -1; + } + const float* inputBiasPtr = reinterpret_cast(&memBase[inputBias]); + + AutoProfilerMarker marker( + cx->runtime()->geckoProfiler(), "intgemm::PrepareBias w/ input bias", + FMT_STRING("rowsB: {} colsB: {} sizeB: {}"), rowsB, colsB, sizeB); + GEMMOLOGY_DISPATCH(Shift::PrepareBias) + (inputMatrixBPreparedPtr, rowsB, colsB, + gemmology::callbacks::UnquantizeAndAddBiasAndWrite( + unquantFactor, inputBiasPtr, outputPtr)); + } else { + AutoProfilerMarker marker( + cx->runtime()->geckoProfiler(), "intgemm::PrepareBias", + FMT_STRING("rowsB: {} colsB: {} sizeB: {}"), rowsB, colsB, sizeB); + GEMMOLOGY_DISPATCH(Shift::PrepareBias) + (inputMatrixBPreparedPtr, rowsB, colsB, + gemmology::callbacks::UnquantizeAndWrite(unquantFactor, outputPtr)); + } return 0; } @@ -384,17 +462,21 @@ int32_t js::intgemm::IntrI8MultiplyAndAddBias( } // Actual call to the 3rd party library (intgemm) - uint8_t* inputMatrixAPreparedPtr = &memBase[inputMatrixAPrepared]; - uint8_t* inputMatrixBPreparedPtr = &memBase[inputMatrixBPrepared]; - uint8_t* inputBiasPreparedPtr = &memBase[inputBiasPrepared]; - uint8_t* outputPtr = &memBase[output]; + const uint8_t* inputMatrixAPreparedPtr = &memBase[inputMatrixAPrepared]; + const int8_t* inputMatrixBPreparedPtr = + reinterpret_cast(&memBase[inputMatrixBPrepared]); + const float* inputBiasPreparedPtr = + reinterpret_cast(&memBase[inputBiasPrepared]); + float* outputPtr = reinterpret_cast(&memBase[output]); float unquantFactor = unquantMultiplier / (scaleA * scaleB); + AutoProfilerMarker marker( + cx->runtime()->geckoProfiler(), "intgemm::Shift::Multiply", + FMT_STRING("rowsA: {}, width: {}, colsA: {}"), rowsA, width, colsB); GEMMOLOGY_DISPATCH(Shift::Multiply) - (inputMatrixAPreparedPtr, (const int8_t*)inputMatrixBPreparedPtr, rowsA, - width, colsB, + (inputMatrixAPreparedPtr, inputMatrixBPreparedPtr, rowsA, width, colsB, gemmology::callbacks::UnquantizeAndAddBiasAndWrite( - unquantFactor, (const float*)inputBiasPreparedPtr, (float*)outputPtr)); + unquantFactor, inputBiasPreparedPtr, outputPtr)); return 0; } @@ -440,13 +522,18 @@ int32_t js::intgemm::IntrI8SelectColumnsOfB(wasm::Instance* instance, } // Actual call to the 3rd party library (intgemm) - uint8_t* inputMatrixBPreparedPtr = &memBase[inputMatrixBPrepared]; - uint8_t* colIndexListPtr = &memBase[colIndexList]; - uint8_t* outputPtr = &memBase[output]; + const int8_t* inputMatrixBPreparedPtr = + reinterpret_cast(&memBase[inputMatrixBPrepared]); + const uint32_t* colIndexListPtr = + reinterpret_cast(&memBase[colIndexList]); + int8_t* outputPtr = reinterpret_cast(&memBase[output]); + AutoProfilerMarker marker( + cx->runtime()->geckoProfiler(), "integemm::SelectColumnsB", + FMT_STRING("rowsB: {} colsB: {} sizecolList: {}, sizeB: {}"), rowsB, + colsB, sizeColIndexList, sizeB); GEMMOLOGY_DISPATCH(SelectColumnsB) - ((const int8_t*)inputMatrixBPreparedPtr, (int8_t*)outputPtr, rowsB, - (const uint32_t*)colIndexListPtr, - (const uint32_t*)colIndexListPtr + sizeColIndexList); + (inputMatrixBPreparedPtr, outputPtr, rowsB, colIndexListPtr, + colIndexListPtr + sizeColIndexList); return 0; } diff --git a/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.h b/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.h index 2cbb70853f8..f2a6d5dfd73 100644 --- a/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.h +++ b/src/third_party/mozjs/extract/js/src/intgemm/IntegerGemmIntrinsic.h @@ -298,7 +298,7 @@ int32_t IntrI8PrepareBias(wasm::Instance* instance, * inputBiasPrepared: i32, unquantMultiplier: f32, * rowsA: i32, width: i32, colsB: i32, output: i32) * which implements the function: - * int8_multiply_and_add_bias(const int8_t* inputMatrixAPrepared, float + * int8_multiply_and_add_bias(const uint8_t* inputMatrixAPrepared, float * scaleA, float zeroPointA, const int8_t* inputMatrixBPrepared, float scaleB, * float zeroPointB, const float* inputBiasPrepared, float unquantMultiplier, * uint32_t rowsA, uint32_t width, uint32_t colsB, float* diff --git a/src/third_party/mozjs/extract/js/src/irregexp/RegExpAPI.cpp b/src/third_party/mozjs/extract/js/src/irregexp/RegExpAPI.cpp index d178f2001e3..3621375a9b8 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/RegExpAPI.cpp +++ b/src/third_party/mozjs/extract/js/src/irregexp/RegExpAPI.cpp @@ -32,7 +32,7 @@ #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin, JS::ColumnNumberOffset #include "js/friend/ErrorMessages.h" // JSMSG_* #include "js/friend/StackLimits.h" // js::ReportOverRecursed -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "vm/MatchPairs.h" #include "vm/PlainObject.h" #include "vm/RegExpShared.h" @@ -68,7 +68,7 @@ using v8::internal::Zone; using v8::internal::ZoneVector; using V8HandleString = v8::internal::Handle; -using V8HandleRegExp = v8::internal::Handle; +using V8HandleRegExp = v8::internal::Handle; using namespace v8::internal::regexp_compiler_constants; @@ -109,13 +109,12 @@ static uint32_t ErrorNumber(RegExpError err) { return JSMSG_INVALID_QUANTIFIER; case RegExpError::kInvalidGroup: return JSMSG_INVALID_GROUP; - case RegExpError::kMultipleFlagDashes: case RegExpError::kRepeatedFlag: + return JSMSG_REPEATED_FLAG; case RegExpError::kInvalidFlagGroup: - // V8 contains experimental support for turning regexp flags on - // and off in the middle of a regular expression. Unless it - // becomes standardized, SM does not support this feature. - MOZ_CRASH("Mode modifiers not supported"); + return JSMSG_INVALID_FLAG_GROUP; + case RegExpError::kMultipleFlagDashes: + return JSMSG_MULTIPLE_FLAG_DASHES; case RegExpError::kNotLinear: // V8 has an experimental non-backtracking engine. We do not // support it yet. @@ -130,8 +129,6 @@ static uint32_t ErrorNumber(RegExpError err) { return JSMSG_INVALID_NAMED_REF; case RegExpError::kInvalidNamedCaptureReference: return JSMSG_INVALID_NAMED_CAPTURE_REF; - case RegExpError::kInvalidClassEscape: - return JSMSG_RANGE_WITH_CLASS_ESCAPE; case RegExpError::kInvalidClassPropertyName: return JSMSG_INVALID_CLASS_PROPERTY_NAME; case RegExpError::kInvalidCharacterClass: @@ -260,12 +257,12 @@ static void ReportSyntaxError(TokenStreamAnyChars& ts, // Create the windowed string, not including the potential line // terminator. - StringBuffer windowBuf(ts.context()); + StringBuilder windowBuf(ts.context()); if (!windowBuf.append(windowStart, windowEnd)) { return; } - // The line of context must be null-terminated, and StringBuffer doesn't + // The line of context must be null-terminated, and StringBuilder doesn't // make that happen unless we force it to. if (!windowBuf.append('\0')) { return; @@ -656,7 +653,7 @@ struct RegExpNamedCaptureIndexLess { // lowest capture index. MOZ_ASSERT(!lhs.indices.empty()); MOZ_ASSERT(!rhs.indices.empty()); - MOZ_ASSERT(lhs.indices[0] != rhs.indices[0]); + MOZ_ASSERT_IF(&lhs != &rhs, lhs.indices[0] != rhs.indices[0]); return lhs.indices[0] < rhs.indices[0]; } }; @@ -846,6 +843,12 @@ bool CompilePattern(JSContext* cx, MutableHandleRegExpShared re, SampleCharacters(input, compiler); data.node = compiler.PreprocessRegExp(&data, isLatin1); + if (data.error != RegExpError::kNone) { + MOZ_ASSERT(data.error == RegExpError::kTooLarge); + JS_ReportErrorASCII(cx, "regexp too big"); + cx->reportResourceExhaustion(); + return false; + } data.error = AnalyzeRegExp(cx->isolate, isLatin1, flags, data.node); if (data.error != RegExpError::kNone) { MOZ_ASSERT(data.error == RegExpError::kAnalysisStackOverflow); @@ -884,7 +887,7 @@ RegExpRunStatus ExecuteRaw(jit::JitCode* code, const CharT* chars, static_assert(static_cast(RegExpRunStatus::Success_NotFound) == v8::internal::RegExp::kInternalRegExpFailure); - typedef int (*RegExpCodeSignature)(InputOutputData*); + using RegExpCodeSignature = int (*)(InputOutputData*); auto function = reinterpret_cast(code->raw()); { JS::AutoSuppressGCAnalysis nogc; @@ -898,7 +901,7 @@ RegExpRunStatus Interpret(JSContext* cx, MutableHandleRegExpShared re, MOZ_ASSERT(re->getByteCode(input->hasLatin1Chars())); HandleScope handleScope(cx->isolate); - V8HandleRegExp wrappedRegExp(v8::internal::JSRegExp(re), cx->isolate); + V8HandleRegExp wrappedRegExp(v8::internal::IrRegExpData(re), cx->isolate); V8HandleString wrappedInput(v8::internal::String(input), cx->isolate); static_assert(static_cast(RegExpRunStatus::Error) == diff --git a/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.cpp b/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.cpp index 99cfc31bfcf..dbc1522ff1b 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.cpp +++ b/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.cpp @@ -76,8 +76,8 @@ SMRegExpMacroAssembler::SMRegExpMacroAssembler(JSContext* cx, masm_.bind(&start_label_); // and continue from here. } -int SMRegExpMacroAssembler::stack_limit_slack() { - return RegExpStack::kStackLimitSlack; +int SMRegExpMacroAssembler::stack_limit_slack_slot_count() { + return RegExpStack::kStackLimitSlackSlotCount; } void SMRegExpMacroAssembler::AdvanceCurrentPosition(int by) { @@ -115,8 +115,11 @@ void SMRegExpMacroAssembler::Backtrack() { masm_.jump(&exit_label_); masm_.bind(&noInterrupt); - // Pop code location from backtrack stack and jump to location. + // Pop code offset from backtrack stack, add to code base address, and jump to + // location. Pop(temp0_); + PushBacktrackCodeOffsetPatch(masm_.movWithPatch(ImmPtr(nullptr), temp1_)); + masm_.addPtr(temp1_, temp0_); masm_.jump(temp0_); } @@ -217,9 +220,9 @@ void SMRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd( // stack, pops the backtrack stack and branches to the given label. void SMRegExpMacroAssembler::CheckGreedyLoop(Label* on_equal) { js::jit::Label fallthrough; - masm_.branchPtr(Assembler::NotEqual, Address(backtrack_stack_pointer_, 0), - current_position_, &fallthrough); - masm_.addPtr(Imm32(sizeof(void*)), backtrack_stack_pointer_); // Pop. + masm_.load32SignExtendToPtr(Address(backtrack_stack_pointer_, 0), temp0_); + masm_.branchPtr(Assembler::NotEqual, temp0_, current_position_, &fallthrough); + masm_.addPtr(Imm32(sizeof(int32_t)), backtrack_stack_pointer_); // Pop. JumpOrBacktrack(on_equal); masm_.bind(&fallthrough); } @@ -368,6 +371,52 @@ void SMRegExpMacroAssembler::CheckBitInTable(Handle table, AddTable(std::move(rawTable)); } +void SMRegExpMacroAssembler::SkipUntilBitInTable(int cp_offset, + Handle table, + Handle nibble_table, + int advance_by) { + // Claim ownership of the ByteArray from the current HandleScope. + // ByteArrays are allocated on the C++ heap and are (eventually) + // owned by the RegExpShared. + PseudoHandle rawTable = table->takeOwnership(isolate()); + + // TODO: SIMD support (bug 1928862). + MOZ_ASSERT(!SkipUntilBitInTableUseSimd(advance_by)); + + // Scalar version. + Register tableReg = temp0_; + masm_.movePtr(ImmPtr(rawTable->data()), tableReg); + + Label cont; + js::jit::Label scalarRepeat; + masm_.bind(&scalarRepeat); + CheckPosition(cp_offset, &cont); + LoadCurrentCharacterUnchecked(cp_offset, 1); + + Register index = current_character_; + if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { + index = temp1_; + masm_.and32(Imm32(kTableMask), current_character_, index); + } + + masm_.load8ZeroExtend(BaseIndex(tableReg, index, js::jit::TimesOne), index); + masm_.branchTest32(Assembler::NonZero, index, index, cont.inner()); + AdvanceCurrentPosition(advance_by); + masm_.jump(&scalarRepeat); + + masm_.bind(cont.inner()); + + // Transfer ownership of |rawTable| to the |tables_| vector. + AddTable(std::move(rawTable)); +} + +bool SMRegExpMacroAssembler::SkipUntilBitInTableUseSimd(int advance_by) { + // V8 found that using SIMD instead of the scalar version was only + // faster when we are advancing by 1 byte per iteration. + bool simdEnabled = false; + return simdEnabled && advance_by * char_size() == 1; +} + void SMRegExpMacroAssembler::CheckNotBackReferenceImpl(int start_reg, bool read_backward, bool unicode, @@ -668,8 +717,7 @@ bool SMRegExpMacroAssembler::CheckSpecialCharacterClass( // To test for 0x0a and 0x0d efficiently, we XOR the input with 1. // This converts 0x0a to 0x0b, and 0x0d to 0x0c, allowing us to // test for the contiguous range 0x0b..0x0c. - masm_.move32(current_character_, temp0_); - masm_.xor32(Imm32(0x01), temp0_); + masm_.xor32(Imm32(0x01), current_character_, temp0_); masm_.sub32(Imm32(0x0b), temp0_); masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x0c - 0x0b), no_match); @@ -723,8 +771,7 @@ bool SMRegExpMacroAssembler::CheckSpecialCharacterClass( return true; case StandardCharacterSet::kLineTerminator: // Match newlines. The opposite of '.'. See '.' above. - masm_.move32(current_character_, temp0_); - masm_.xor32(Imm32(0x01), temp0_); + masm_.xor32(Imm32(0x01), current_character_, temp0_); masm_.sub32(Imm32(0x0b), temp0_); if (mode_ == LATIN1) { masm_.branch32(Assembler::Above, temp0_, Imm32(0x0c - 0x0b), no_match); @@ -924,15 +971,15 @@ void SMRegExpMacroAssembler::ClearRegisters(int reg_from, int reg_to) { void SMRegExpMacroAssembler::Push(Register source) { MOZ_ASSERT(source != backtrack_stack_pointer_); - masm_.subPtr(Imm32(sizeof(void*)), backtrack_stack_pointer_); - masm_.storePtr(source, Address(backtrack_stack_pointer_, 0)); + masm_.subPtr(Imm32(sizeof(int32_t)), backtrack_stack_pointer_); + masm_.store32(source, Address(backtrack_stack_pointer_, 0)); } void SMRegExpMacroAssembler::Pop(Register target) { MOZ_ASSERT(target != backtrack_stack_pointer_); - masm_.loadPtr(Address(backtrack_stack_pointer_, 0), target); - masm_.addPtr(Imm32(sizeof(void*)), backtrack_stack_pointer_); + masm_.load32SignExtendToPtr(Address(backtrack_stack_pointer_, 0), target); + masm_.addPtr(Imm32(sizeof(int32_t)), backtrack_stack_pointer_); } void SMRegExpMacroAssembler::JumpOrBacktrack(Label* to) { @@ -948,7 +995,7 @@ void SMRegExpMacroAssembler::JumpOrBacktrack(Label* to) { void SMRegExpMacroAssembler::CheckBacktrackStackLimit() { js::jit::Label no_stack_overflow; masm_.branchPtr( - Assembler::BelowOrEqual, + Assembler::Below, AbsoluteAddress(isolate()->regexp_stack()->limit_address_address()), backtrack_stack_pointer_, &no_stack_overflow); @@ -968,7 +1015,8 @@ static Handle DummyCode() { // Finalize code. This is called last, so that we know how many // registers we need. -Handle SMRegExpMacroAssembler::GetCode(Handle source) { +Handle SMRegExpMacroAssembler::GetCode(Handle source, + RegExpFlags flags) { if (!cx_->zone()->ensureJitZoneExists(cx_)) { return DummyCode(); } @@ -993,10 +1041,15 @@ Handle SMRegExpMacroAssembler::GetCode(Handle source) { for (LabelPatch& lp : labelPatches_) { Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, lp.patchOffset_), - ImmPtr(code->raw() + lp.labelOffset_), + ImmPtr((void*)lp.labelOffset_), ImmPtr(nullptr)); } + for (js::jit::CodeOffset& offset : backtrackCodeOffsetPatches_) { + Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, offset), + ImmPtr(code->raw()), ImmPtr(nullptr)); + } + CollectPerfSpewerJitCodeProfile(code, "RegExp"); #ifdef MOZ_VTUNE @@ -1152,8 +1205,8 @@ void SMRegExpMacroAssembler::initFrameAndRegs() { masm_.storePtr(inputStartMinusOneReg, BaseIndex(masm_.getStackPointer(), temp1_, js::jit::TimesOne)); masm_.addPtr(ImmWord(sizeof(void*)), temp1_); - masm_.branchPtr(Assembler::LessThan, temp1_, - ImmWord(register_offset(num_capture_registers_)), + masm_.branchPtr(Assembler::LessThanOrEqual, temp1_, + ImmWord(register_offset(num_capture_registers_ - 1)), &init_loop); } else { // Unroll the loop @@ -1395,8 +1448,8 @@ bool SMRegExpMacroAssembler::GrowBacktrackStack(RegExpStack* regexp_stack) { bool SMRegExpMacroAssembler::CanReadUnaligned() const { #if defined(JS_CODEGEN_ARM) - return !js::jit::HasAlignmentFault(); -#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + return !js::jit::ARMFlags::HasAlignmentFault(); +#elif defined(JS_CODEGEN_MIPS64) return false; #else return true; diff --git a/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.h b/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.h index 3c3acf40d45..6b473571bf2 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/RegExpNativeMacroAssembler.h @@ -41,7 +41,7 @@ class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler { Zone* zone, Mode mode, uint32_t num_capture_registers); virtual ~SMRegExpMacroAssembler() = default; - virtual int stack_limit_slack(); + virtual int stack_limit_slack_slot_count(); virtual IrregexpImplementation Implementation(); virtual bool Succeed(); @@ -81,6 +81,10 @@ class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler { virtual void CheckNotAtStart(int cp_offset, Label* on_not_at_start); virtual void CheckPosition(int cp_offset, Label* on_outside_input); virtual void CheckBitInTable(Handle table, Label* on_bit_set); + virtual void SkipUntilBitInTable(int cp_offset, Handle table, + Handle nibble_table, + int advance_by); + virtual bool SkipUntilBitInTableUseSimd(int advance_by); virtual bool CheckSpecialCharacterClass(StandardCharacterSet type, Label* on_no_match); virtual void CheckNotBackReference(int start_reg, bool read_backward, @@ -107,7 +111,7 @@ class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler { virtual void SetRegister(int register_index, int to); virtual void ClearRegisters(int reg_from, int reg_to); - virtual Handle GetCode(Handle source); + virtual Handle GetCode(Handle source, RegExpFlags flags); virtual bool CanReadUnaligned() const; @@ -265,6 +269,9 @@ class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler { // // 3. While linking the code, we walk the list of label patches // and patch the code accordingly. + // + // 4. Finally, we patch in the code base address that is added to the + // label offset to calculate the actual address to jump to. class LabelPatch { public: LabelPatch(js::jit::CodeOffset patchOffset, size_t labelOffset) @@ -282,6 +289,15 @@ class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler { } } + js::Vector + backtrackCodeOffsetPatches_; + void PushBacktrackCodeOffsetPatch(js::jit::CodeOffset offset) { + js::AutoEnterOOMUnsafeRegion oomUnsafe; + if (!backtrackCodeOffsetPatches_.append(offset)) { + oomUnsafe.crash("Irregexp backtrack code offset patch"); + } + } + Mode mode_; int num_registers_; int num_capture_registers_; diff --git a/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.cpp b/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.cpp index da388e00573..a25cc9a2350 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.cpp +++ b/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.cpp @@ -81,8 +81,9 @@ Handle::Handle(T object, Isolate* isolate) : location_(isolate->getHandleLocation(object.value())) {} template Handle::Handle(ByteArray b, Isolate* isolate); +template Handle::Handle(TrustedByteArray b, Isolate* isolate); template Handle::Handle(const JS::Value& v, Isolate* isolate); -template Handle::Handle(JSRegExp re, Isolate* isolate); +template Handle::Handle(IrRegExpData re, Isolate* isolate); template Handle::Handle(String s, Isolate* isolate); template @@ -238,6 +239,23 @@ Handle Isolate::NewByteArray(int length, AllocationType alloc) { return Handle(JS::PrivateValue(data), this); } +Handle Isolate::NewTrustedByteArray(int length, + AllocationType alloc) { + MOZ_RELEASE_ASSERT(length >= 0); + + js::AutoEnterOOMUnsafeRegion oomUnsafe; + + size_t alloc_size = sizeof(ByteArrayData) + length; + ByteArrayData* data = + static_cast(allocatePseudoHandle(alloc_size)); + if (!data) { + oomUnsafe.crash("Irregexp NewTrustedByteArray"); + } + new (data) ByteArrayData(length); + + return Handle(JS::PrivateValue(data), this); +} + Handle Isolate::NewFixedArray(int length) { MOZ_RELEASE_ASSERT(length >= 0); js::AutoEnterOOMUnsafeRegion oomUnsafe; @@ -293,5 +311,37 @@ template Handle Isolate::InternalizeString( static_assert(JSRegExp::RegistersForCaptureCount(JSRegExp::kMaxCaptures) <= RegExpMacroAssembler::kMaxRegisterCount); +// This function implements AdvanceStringIndex and CodePointAt: +// - https://tc39.es/ecma262/#sec-advancestringindex +// - https://tc39.es/ecma262/#sec-codepointat +// The semantics are to advance 2 code units for properly paired +// surrogates in unicode mode, and 1 code unit otherwise +// (non-surrogates, unpaired surrogates, or non-unicode mode). +uint64_t RegExpUtils::AdvanceStringIndex(Tagged wrappedString, + uint64_t index, bool unicode) { + MOZ_ASSERT(index < kMaxSafeIntegerUint64); + MOZ_ASSERT(wrappedString->IsFlat()); + JSLinearString* string = &wrappedString->str()->asLinear(); + + if (unicode && index < string->length()) { + char16_t first = string->latin1OrTwoByteChar(index); + if (first >= 0xD800 && first <= 0xDBFF && index + 1 < string->length()) { + char16_t second = string->latin1OrTwoByteChar(index + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { + return index + 2; + } + } + } + + return index + 1; +} + +// RegexpMacroAssemblerTracer::GetCode dumps the flags by first converting to +// a String, then into a C string. To avoid allocating while assembling, +// we just return a handle to the well-known atom "flags". +Handle JSRegExp::StringFromFlags(Isolate* isolate, RegExpFlags flags) { + return Handle(String(isolate->cx()->names().flags), isolate); +} + } // namespace internal } // namespace v8 diff --git a/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.h b/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.h index ebd6b55a308..6fc13d8b0ee 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/RegExpShim.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "irregexp/RegExpTypes.h" #include "irregexp/util/FlagsShim.h" @@ -80,6 +81,7 @@ class Handle; #define CHECK_EQ(lhs, rhs) MOZ_RELEASE_ASSERT((lhs) == (rhs)) #define CHECK_LE(lhs, rhs) MOZ_RELEASE_ASSERT((lhs) <= (rhs)) #define CHECK_GE(lhs, rhs) MOZ_RELEASE_ASSERT((lhs) >= (rhs)) +#define CHECK_IMPLIES(lhs, rhs) MOZ_RELEASE_ASSERT(!(lhs) || (rhs)) #define CONSTEXPR_DCHECK MOZ_ASSERT // These assertions are necessary to preserve the soundness of the V8 @@ -181,7 +183,7 @@ struct Use { template inline Dst saturated_cast(Src value); -// This is the only specialization that is needed for regexp code. +// These are the only specializations that are needed for regexp code. // Instead of pulling in dozens of lines of template goo // to derive it, I used the implementation from uint8_clamped in // ArrayBufferObject.h. @@ -189,6 +191,10 @@ template <> inline uint8_t saturated_cast(int x) { return (x >= 0) ? ((x < 255) ? uint8_t(x) : 255) : 0; } +template <> +inline uint8_t saturated_cast(uint32_t x) { + return (x < 255) ? uint8_t(x) : 255; +} // Origin: // https://github.com/v8/v8/blob/fc088cdaccadede84886eee881e67af9db53669a/src/base/bounds.h#L14-L28 @@ -205,7 +211,8 @@ inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) { } #define LAZY_INSTANCE_INITIALIZER \ - {} + { \ + } template class LazyInstanceImpl { @@ -248,21 +255,6 @@ template return mozilla::AddToHash(aHash, aArgs...); } -template -class Optional { - mozilla::Maybe inner_; - - public: - Optional() = default; - Optional(T t) { inner_.emplace(t); } - - bool has_value() const { return inner_.isSome(); } - const T& value() const { return inner_.ref(); } - - T* operator->() { return &inner_.ref(); } - T& operator*() { return inner_.ref(); } -}; - namespace bits { inline uint64_t CountTrailingZeros(uint64_t value) { @@ -449,11 +441,13 @@ constexpr int kSystemPointerSize = sizeof(void*); // The largest integer n such that n and n + 1 are both exactly // representable as a Number value. ES6 section 20.1.2.6 -constexpr double kMaxSafeInteger = 9007199254740991.0; // 2^53-1 +constexpr uint64_t kMaxSafeIntegerUint64 = (uint64_t{1} << 53) - 1; +constexpr double kMaxSafeInteger = static_cast(kMaxSafeIntegerUint64); constexpr int kBitsPerByte = 8; constexpr int kBitsPerByteLog2 = 3; constexpr int kUInt16Size = sizeof(uint16_t); +constexpr int kInt32Size = sizeof(int32_t); constexpr int kUInt32Size = sizeof(uint32_t); constexpr int kInt64Size = sizeof(int64_t); @@ -665,6 +659,18 @@ class Tagged { T value_; }; +// Adapted from v8/src/objects/casting.h + +template +inline Tagged UncheckedCast(Tagged value) { + return Tagged(To::cast(value)); +} + +template +inline Tagged Cast(const From& value) { + return UncheckedCast(Tagged(value)); +} + // A fixed-size array with Objects (aka Values) as element types. // Implemented using the dense elements of an ArrayObject. // Used for named captures. @@ -744,6 +750,17 @@ class ByteArray : public HeapObject { friend class SMRegExpMacroAssembler; }; +// A byte array that can be trusted to not contain malicious data. +// See https://issues.chromium.org/issues/40069826. +class TrustedByteArray : public ByteArray { + public: + static TrustedByteArray cast(Object object) { + TrustedByteArray b; + b.setValue(object.value()); + return b; + } +}; + // This is only used in assertions. In debug builds, we put a magic value // in the header of each ByteArrayData, and assert here that it matches. inline bool IsByteArray(Object obj) { @@ -915,6 +932,21 @@ inline Handle handle(T object, Isolate* isolate) { return Handle(object, isolate); } +// V8 is migrating to a conservative stack scanning approach. When that +// is enabled, a DirectHandle points directly at the V8 heap, and an +// IndirectHandle is an unmigrated old-style Handle with a layer of +// indirection. When disabled (which matches our implementation) the two +// types are the same. See: +// https://github.com/v8/v8/blob/887ec63c43e23c4fefba1c52d4525654bdc71e5b/src/common/globals.h#L1000-L1012 +template +using DirectHandle = Handle; + +template +using IndirectHandle = Handle; + +template +using MaybeDirectHandle = MaybeHandle; + // RAII Guard classes using DisallowGarbageCollection = JS::AutoAssertNoGC; @@ -1009,6 +1041,8 @@ class String : public HeapObject { template base::Vector GetCharVector( const DisallowGarbageCollection& no_gc); + + friend class RegExpUtils; }; template <> @@ -1027,39 +1061,20 @@ inline base::Vector String::GetCharVector( return flat.ToUC16Vector(); } -class JSRegExp : public HeapObject { +using RegExpFlags = JS::RegExpFlags; +using RegExpFlag = JS::RegExpFlags::Flag; + +class JSRegExp { public: - JSRegExp() : HeapObject() {} - JSRegExp(js::RegExpShared* re) { setValue(JS::PrivateGCThingValue(re)); } - - // ****************************************************** - // Methods that are called from inside the implementation - // ****************************************************** - void TierUpTick() { inner()->tierUpTick(); } - - Object bytecode(bool is_latin1) const { - return Object(JS::PrivateValue(inner()->getByteCode(is_latin1))); - } - - // TODO: should we expose this? - uint32_t backtrack_limit() const { return 0; } - - static JSRegExp cast(Object object) { - JSRegExp regexp; - js::gc::Cell* regexpShared = object.value().toGCThing(); - MOZ_ASSERT(regexpShared->is()); - regexp.setValue(JS::PrivateGCThingValue(regexpShared)); - return regexp; - } - // Each capture (including the match itself) needs two registers. static constexpr int RegistersForCaptureCount(int count) { return (count + 1) * 2; } - inline uint32_t max_register_count() const { - return inner()->getMaxRegisters(); - } + static RegExpFlags AsRegExpFlags(RegExpFlags flags) { return flags; } + static RegExpFlags AsJSRegExpFlags(RegExpFlags flags) { return flags; } + + static Handle StringFromFlags(Isolate* isolate, RegExpFlags flags); // ****************************** // Static constants @@ -1068,6 +1083,44 @@ class JSRegExp : public HeapObject { static constexpr int kMaxCaptures = (1 << 15) - 1; static constexpr int kNoBacktrackLimit = 0; +}; + +class IrRegExpData : public HeapObject { + public: + IrRegExpData() : HeapObject() {} + IrRegExpData(js::RegExpShared* re) { setValue(JS::PrivateGCThingValue(re)); } + + // ****************************************************** + // Methods that are called from inside the implementation + // ****************************************************** + void TierUpTick() { inner()->tierUpTick(); } + + Tagged bytecode(bool is_latin1) const { + return TrustedByteArray::cast( + Object(JS::PrivateValue(inner()->getByteCode(is_latin1)))); + } + + // TODO: should we expose this? + uint32_t backtrack_limit() const { return 0; } + + static IrRegExpData cast(Object object) { + IrRegExpData regexp; + js::gc::Cell* regexpShared = object.value().toGCThing(); + MOZ_ASSERT(regexpShared->is()); + regexp.setValue(JS::PrivateGCThingValue(regexpShared)); + return regexp; + } + + inline uint32_t max_register_count() const { + return inner()->getMaxRegisters(); + } + + RegExpFlags flags() const { return inner()->getFlags(); } + + size_t capture_count() const { + // Subtract 1 because pairCount includes the implicit global capture. + return inner()->pairCount() - 1; + } private: js::RegExpShared* inner() const { @@ -1075,9 +1128,6 @@ class JSRegExp : public HeapObject { } }; -using RegExpFlags = JS::RegExpFlags; -using RegExpFlag = JS::RegExpFlags::Flag; - inline bool IsUnicode(RegExpFlags flags) { return flags.unicode(); } inline bool IsGlobal(RegExpFlags flags) { return flags.global(); } inline bool IsIgnoreCase(RegExpFlags flags) { return flags.ignoreCase(); } @@ -1089,13 +1139,15 @@ inline bool IsEitherUnicode(RegExpFlags flags) { return flags.unicode() || flags.unicodeSets(); } -inline base::Optional TryRegExpFlagFromChar(char c) { +inline std::optional TryRegExpFlagFromChar(char c) { RegExpFlag flag; // The parser only calls this after verifying that it's a supported flag. - MOZ_ALWAYS_TRUE(JS::MaybeParseRegExpFlag(c, &flag)); + if (JS::MaybeParseRegExpFlag(c, &flag)) { + return flag; + } - return base::Optional(flag); + return std::optional{}; } inline bool operator==(const RegExpFlags& lhs, const int& rhs) { @@ -1173,6 +1225,9 @@ class Isolate { Handle NewByteArray( int length, AllocationType allocation = AllocationType::kYoung); + Handle NewTrustedByteArray( + int length, AllocationType allocation = AllocationType::kYoung); + // Allocates a fixed array initialized with undefined values. Handle NewFixedArray(int length); @@ -1302,6 +1357,9 @@ class Code : public HeapObject { // (NativeRegExpMacroAssembler::CheckStackGuardState) class InstructionStream {}; +// Only used in the definition of RegExpGlobalExecRunner, which we don't use. +class RegExpResultVectorScope {}; + // Origin: https://github.com/v8/v8/blob/master/src/codegen/label.h class Label { public: @@ -1326,6 +1384,12 @@ class Label { friend class SMRegExpMacroAssembler; }; +class RegExpUtils { + public: + static uint64_t AdvanceStringIndex(Tagged string, uint64_t index, + bool unicode); +}; + #define v8_flags js::jit::JitOptions // MONGODB MODIFICATION: Fall back to switch-based interpreters in MSVC. diff --git a/src/third_party/mozjs/extract/js/src/irregexp/import-irregexp.py b/src/third_party/mozjs/extract/js/src/irregexp/import-irregexp.py index 523276e7b38..dd95a1fe7e4 100755 --- a/src/third_party/mozjs/extract/js/src/irregexp/import-irregexp.py +++ b/src/third_party/mozjs/extract/js/src/irregexp/import-irregexp.py @@ -48,12 +48,13 @@ def copy_and_update_includes(src_path, dst_path): "special-case.h", ] - src = open(str(src_path), "r") + src = open(str(src_path)) dst = open(str(dst_path), "w") # 1. Rewrite includes of V8 regexp headers: - # Note that we exclude regexp-flags.h and provide our own definition. - regexp_include = re.compile('#include "src/regexp(?!/regexp-flags.h)') + # Note that we exclude several headers and provide our own definitions. + excluded = "|".join(["flags", "utils", "result-vector"]) + regexp_include = re.compile(f'#include "src/regexp(?!/regexp-({excluded}).h)') regexp_include_new = '#include "irregexp/imported' # 2. Remove includes of other V8 headers @@ -91,6 +92,8 @@ def import_from(srcdir, dstdir): "OWNERS", "regexp.cc", "regexp-flags.h", + "regexp-result-vector.cc", + "regexp-result-vector.h", "regexp-utils.cc", "regexp-utils.h", "regexp-macro-assembler-arch.h", diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.cc index 34946bd80c7..0062912fade 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.cc @@ -418,8 +418,8 @@ RegExpClassSetExpression::RegExpClassSetExpression( max_match_ = 2; } else { max_match_ = 0; - for (auto op : *operands) { - max_match_ = std::max(max_match_, op->max_match()); + for (auto operand : *operands) { + max_match_ = std::max(max_match_, operand->max_match()); } } } diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.h index b2b88515d3a..75f19e82684 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-ast.h @@ -5,13 +5,15 @@ #ifndef V8_REGEXP_REGEXP_AST_H_ #define V8_REGEXP_REGEXP_AST_H_ +#include + +#include "irregexp/RegExpShim.h" + #ifdef V8_INTL_SUPPORT #include "unicode/uniset.h" #endif // V8_INTL_SUPPORT -#include "irregexp/RegExpShim.h" -namespace v8 { -namespace internal { +namespace v8::internal { #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ VISIT(Disjunction) \ @@ -209,7 +211,6 @@ class RegExpTree : public ZoneObject { #undef MAKE_ASTYPE }; - class RegExpDisjunction final : public RegExpTree { public: explicit RegExpDisjunction(ZoneList* alternatives); @@ -232,7 +233,6 @@ class RegExpDisjunction final : public RegExpTree { int max_match_; }; - class RegExpAlternative final : public RegExpTree { public: explicit RegExpAlternative(ZoneList* nodes); @@ -252,7 +252,6 @@ class RegExpAlternative final : public RegExpTree { int max_match_; }; - class RegExpAssertion final : public RegExpTree { public: enum class Type { @@ -296,7 +295,7 @@ class CharacterSet final { private: ZoneList* ranges_ = nullptr; - base::Optional standard_set_type_; + std::optional standard_set_type_; }; class RegExpClassRanges final : public RegExpTree { @@ -539,15 +538,16 @@ class RegExpText final : public RegExpTree { int length_ = 0; }; - class RegExpQuantifier final : public RegExpTree { public: enum QuantifierType { GREEDY, NON_GREEDY, POSSESSIVE }; - RegExpQuantifier(int min, int max, QuantifierType type, RegExpTree* body) + RegExpQuantifier(int min, int max, QuantifierType type, int index, + RegExpTree* body) : body_(body), min_(min), max_(max), - quantifier_type_(type) { + quantifier_type_(type), + index_(index) { if (min > 0 && body->min_match() > kInfinity / min) { min_match_ = kInfinity; } else { @@ -571,6 +571,7 @@ class RegExpQuantifier final : public RegExpTree { int min() const { return min_; } int max() const { return max_; } QuantifierType quantifier_type() const { return quantifier_type_; } + int index() const { return index_; } bool is_possessive() const { return quantifier_type_ == POSSESSIVE; } bool is_non_greedy() const { return quantifier_type_ == NON_GREEDY; } bool is_greedy() const { return quantifier_type_ == GREEDY; } @@ -583,9 +584,9 @@ class RegExpQuantifier final : public RegExpTree { int min_match_; int max_match_; QuantifierType quantifier_type_; + int index_; }; - class RegExpCapture final : public RegExpTree { public: explicit RegExpCapture(int index) @@ -700,7 +701,6 @@ class RegExpLookaround final : public RegExpTree { int index_; }; - class RegExpBackReference final : public RegExpTree { public: explicit RegExpBackReference(Zone* zone) : captures_(1, zone) {} @@ -727,7 +727,6 @@ class RegExpBackReference final : public RegExpTree { const ZoneVector* name_ = nullptr; }; - class RegExpEmpty final : public RegExpTree { public: DECL_BOILERPLATE(Empty); @@ -735,8 +734,7 @@ class RegExpEmpty final : public RegExpTree { int max_match() override { return 0; } }; -} // namespace internal -} // namespace v8 +} // namespace v8::internal #undef DECL_BOILERPLATE diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.cc index 251ed1cda55..66ad65d02d5 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.cc @@ -312,10 +312,7 @@ void RegExpBytecodeGenerator::CheckCharacterNotInRange(base::uc16 from, EmitOrLink(on_not_in_range); } -void RegExpBytecodeGenerator::CheckBitInTable(Handle table, - Label* on_bit_set) { - Emit(BC_CHECK_BIT_IN_TABLE, 0); - EmitOrLink(on_bit_set); +void RegExpBytecodeGenerator::EmitSkipTable(DirectHandle table) { for (int i = 0; i < kTableSize; i += kBitsPerByte) { int byte = 0; for (int j = 0; j < kBitsPerByte; j++) { @@ -325,6 +322,25 @@ void RegExpBytecodeGenerator::CheckBitInTable(Handle table, } } +void RegExpBytecodeGenerator::CheckBitInTable(Handle table, + Label* on_bit_set) { + Emit(BC_CHECK_BIT_IN_TABLE, 0); + EmitOrLink(on_bit_set); + EmitSkipTable(table); +} + +void RegExpBytecodeGenerator::SkipUntilBitInTable( + int cp_offset, Handle table, Handle nibble_table, + int advance_by) { + Label cont; + Emit(BC_SKIP_UNTIL_BIT_IN_TABLE, cp_offset); + Emit32(advance_by); + EmitSkipTable(table); + EmitOrLink(&cont); // goto_when_match + EmitOrLink(&cont); // goto_on_failure + Bind(&cont); +} + void RegExpBytecodeGenerator::CheckNotBackReference(int start_reg, bool read_backward, Label* on_not_equal) { @@ -373,16 +389,17 @@ void RegExpBytecodeGenerator::IfRegisterEqPos(int register_index, EmitOrLink(on_eq); } -Handle RegExpBytecodeGenerator::GetCode(Handle source) { +DirectHandle RegExpBytecodeGenerator::GetCode( + DirectHandle source, RegExpFlags flags) { Bind(&backtrack_); Backtrack(); - Handle array; + DirectHandle array; if (v8_flags.regexp_peephole_optimization) { array = RegExpBytecodePeepholeOptimization::OptimizeBytecode( isolate_, zone(), source, buffer_.data(), length(), jump_edges_); } else { - array = isolate_->factory()->NewByteArray(length()); + array = isolate_->factory()->NewTrustedByteArray(length()); Copy(array->begin()); } diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.h index 18ac22c8083..f18d7a98db6 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-generator.h @@ -24,7 +24,7 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGenerator : public RegExpMacroAssembler { RegExpBytecodeGenerator(Isolate* isolate, Zone* zone); ~RegExpBytecodeGenerator() override; // The byte-code interpreter checks on each push anyway. - int stack_limit_slack() override { return 1; } + int stack_limit_slack_slot_count() override { return 1; } bool CanReadUnaligned() const override { return false; } void Bind(Label* label) override; void AdvanceCurrentPosition(int by) override; // Signed cp change. @@ -83,6 +83,9 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGenerator : public RegExpMacroAssembler { return false; } void CheckBitInTable(Handle table, Label* on_bit_set) override; + void SkipUntilBitInTable(int cp_offset, Handle table, + Handle nibble_table, + int advance_by) override; void CheckNotBackReference(int start_reg, bool read_backward, Label* on_no_match) override; void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward, @@ -93,7 +96,8 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGenerator : public RegExpMacroAssembler { void IfRegisterEqPos(int register_index, Label* if_eq) override; IrregexpImplementation Implementation() override; - Handle GetCode(Handle source) override; + DirectHandle GetCode(DirectHandle source, + RegExpFlags flags) override; private: void ExpandBuffer(); @@ -105,6 +109,7 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGenerator : public RegExpMacroAssembler { inline void Emit8(uint32_t x); inline void Emit(uint32_t bc, uint32_t arg); inline void Emit(uint32_t bc, int32_t arg); + void EmitSkipTable(DirectHandle table); // Bytecode buffer. int length(); void Copy(uint8_t* a); diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.cc index 0ef0bab7022..f4ce6a5db85 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.cc @@ -1005,13 +1005,15 @@ Zone* RegExpBytecodePeephole::zone() const { return zone_; } } // namespace // static -Handle RegExpBytecodePeepholeOptimization::OptimizeBytecode( - Isolate* isolate, Zone* zone, Handle source, +DirectHandle +RegExpBytecodePeepholeOptimization::OptimizeBytecode( + Isolate* isolate, Zone* zone, DirectHandle source, const uint8_t* bytecode, int length, const ZoneUnorderedMap& jump_edges) { RegExpBytecodePeephole peephole(zone, length, jump_edges); bool did_optimize = peephole.OptimizeBytecode(bytecode, length); - Handle array = isolate->factory()->NewByteArray(peephole.Length()); + DirectHandle array = + isolate->factory()->NewTrustedByteArray(peephole.Length()); peephole.CopyOptimizedBytecode(array->begin()); if (did_optimize && v8_flags.trace_regexp_peephole_optimization) { diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.h index c1f0d66ccab..6c32cdfff37 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-bytecode-peephole.h @@ -10,7 +10,7 @@ namespace v8 { namespace internal { -class ByteArray; +class TrustedByteArray; // Peephole optimization for regexp interpreter bytecode. // Pre-defined bytecode sequences occuring in the bytecode generated by the @@ -19,8 +19,8 @@ class RegExpBytecodePeepholeOptimization : public AllStatic { public: // Performs peephole optimization on the given bytecode and returns the // optimized bytecode. - static Handle OptimizeBytecode( - Isolate* isolate, Zone* zone, Handle source, + static DirectHandle OptimizeBytecode( + Isolate* isolate, Zone* zone, DirectHandle source, const uint8_t* bytecode, int length, const ZoneUnorderedMap& jump_edges); }; diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler-tonode.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler-tonode.cc index 1f9b2a495a5..79a3be0b2d2 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler-tonode.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler-tonode.cc @@ -20,7 +20,6 @@ using namespace regexp_compiler_constants; // NOLINT(build/namespaces) constexpr base::uc32 kMaxCodePoint = 0x10ffff; constexpr int kMaxUtf16CodeUnit = 0xffff; constexpr uint32_t kMaxUtf16CodeUnitU = 0xffff; -constexpr int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar; // ------------------------------------------------------------------- // Tree to graph conversion @@ -418,6 +417,7 @@ RegExpNode* UnanchoredAdvance(RegExpCompiler* compiler, } // namespace // static +// Only for /ui and /vi, not for /i regexps. void CharacterRange::AddUnicodeCaseEquivalents(ZoneList* ranges, Zone* zone) { #ifdef V8_INTL_SUPPORT @@ -1087,16 +1087,17 @@ RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, newline_ranges, false, zone); RegExpClassRanges* newline_atom = zone->New(StandardCharacterSet::kLineTerminator); + ActionNode* submatch_success = ActionNode::PositiveSubmatchSuccess( + stack_pointer_register, position_register, + 0, // No captures inside. + -1, // Ignored if no captures. + on_success); TextNode* newline_matcher = - zone->New(newline_atom, false, - ActionNode::PositiveSubmatchSuccess( - stack_pointer_register, position_register, - 0, // No captures inside. - -1, // Ignored if no captures. - on_success)); + zone->New(newline_atom, false, submatch_success); // Create an end-of-input matcher. RegExpNode* end_of_line = ActionNode::BeginPositiveSubmatch( - stack_pointer_register, position_register, newline_matcher); + stack_pointer_register, position_register, newline_matcher, + submatch_success); // Add the two alternatives to the ChoiceNode. GuardedAlternative eol_alternative(end_of_line); result->AddAlternative(eol_alternative); @@ -1188,14 +1189,15 @@ RegExpLookaround::Builder::Builder(bool is_positive, RegExpNode* on_success, RegExpNode* RegExpLookaround::Builder::ForMatch(RegExpNode* match) { if (is_positive_) { - return ActionNode::BeginPositiveSubmatch(stack_pointer_register_, - position_register_, match); + ActionNode* on_match_success = on_match_success_->AsActionNode(); + return ActionNode::BeginPositiveSubmatch( + stack_pointer_register_, position_register_, match, on_match_success); } else { Zone* zone = on_success_->zone(); // We use a ChoiceNode to represent the negative lookaround. The first // alternative is the negative match. On success, the end node backtracks. // On failure, the second alternative is tried and leads to success. - // NegativeLookaheadChoiceNode is a special ChoiceNode that ignores the + // NegativeLookaroundChoiceNode is a special ChoiceNode that ignores the // first exit when calculating quick checks. ChoiceNode* choice_node = zone->New( GuardedAlternative(match), GuardedAlternative(on_success_), zone); @@ -1444,6 +1446,7 @@ void CharacterRange::AddClassEscape(StandardCharacterSet standard_character_set, } // static +// Only for /i, not for /ui or /vi. void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone, ZoneList* ranges, bool is_one_byte) { @@ -1459,8 +1462,8 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone, // Nothing to be done for surrogates. if (from >= kLeadSurrogateStart && to <= kTrailSurrogateEnd) continue; if (is_one_byte && !RangeContainsLatin1Equivalents(range)) { - if (from > kMaxOneByteCharCode) continue; - if (to > kMaxOneByteCharCode) to = kMaxOneByteCharCode; + if (from > String::kMaxOneByteCharCode) continue; + if (to > String::kMaxOneByteCharCode) to = String::kMaxOneByteCharCode; } others.add(from, to); } @@ -1502,17 +1505,17 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone, // Nothing to be done for surrogates. if (bottom >= kLeadSurrogateStart && top <= kTrailSurrogateEnd) continue; if (is_one_byte && !RangeContainsLatin1Equivalents(range)) { - if (bottom > kMaxOneByteCharCode) continue; - if (top > kMaxOneByteCharCode) top = kMaxOneByteCharCode; + if (bottom > String::kMaxOneByteCharCode) continue; + if (top > String::kMaxOneByteCharCode) top = String::kMaxOneByteCharCode; } unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; if (top == bottom) { // If this is a singleton we just expand the one character. int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); - for (int i = 0; i < length; i++) { - base::uc32 chr = chars[i]; + for (int j = 0; j < length; j++) { + base::uc32 chr = chars[j]; if (chr != bottom) { - ranges->Add(CharacterRange::Singleton(chars[i]), zone); + ranges->Add(CharacterRange::Singleton(chars[j]), zone); } } } else { @@ -1547,8 +1550,8 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone, int end = (block_end > top) ? top : block_end; length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', equivalents); - for (int i = 0; i < length; i++) { - base::uc32 c = equivalents[i]; + for (int j = 0; j < length; j++) { + base::uc32 c = equivalents[j]; base::uc32 range_from = c - (block_end - pos); base::uc32 range_to = c - (block_end - end); if (!(bottom <= range_from && range_to <= top)) { diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.cc index 5c3637ff7fa..dcba390db8c 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.cc @@ -4,6 +4,8 @@ #include "irregexp/imported/regexp-compiler.h" +#include + #include "irregexp/imported/regexp-macro-assembler-arch.h" #ifdef V8_INTL_SUPPORT @@ -13,8 +15,7 @@ #include "unicode/utypes.h" #endif // V8_INTL_SUPPORT -namespace v8 { -namespace internal { +namespace v8::internal { using namespace regexp_compiler_constants; // NOLINT(build/namespaces) @@ -255,7 +256,7 @@ RegExpCompiler::RegExpCompiler(Isolate* isolate, Zone* zone, int capture_count, RegExpCompiler::CompilationResult RegExpCompiler::Assemble( Isolate* isolate, RegExpMacroAssembler* macro_assembler, RegExpNode* start, - int capture_count, Handle pattern) { + int capture_count, DirectHandle pattern) { macro_assembler_ = macro_assembler; ZoneVector work_list(zone()); @@ -280,7 +281,7 @@ RegExpCompiler::CompilationResult RegExpCompiler::Assemble( return CompilationResult::RegExpTooBig(); } - Handle code = macro_assembler_->GetCode(pattern); + DirectHandle code = macro_assembler_->GetCode(pattern, flags_); isolate->IncreaseTotalRegexpCodeGenerated(code); work_list_ = nullptr; @@ -394,9 +395,6 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, DynamicBitSet* registers_to_pop, DynamicBitSet* registers_to_clear, Zone* zone) { - // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1. - const int push_limit = (assembler->stack_limit_slack() + 1) / 2; - // Count pushes performed to force a stack limit check occasionally. int pushes = 0; @@ -490,7 +488,8 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, pushes++; RegExpMacroAssembler::StackCheckFlag stack_check = RegExpMacroAssembler::kNoStackLimitCheck; - if (pushes == push_limit) { + DCHECK_GT(assembler->stack_limit_slack_slot_count(), 0); + if (pushes == assembler->stack_limit_slack_slot_count()) { stack_check = RegExpMacroAssembler::kCheckStackLimit; pushes = 0; } @@ -665,11 +664,13 @@ ActionNode* ActionNode::ClearCaptures(Interval range, RegExpNode* on_success) { } ActionNode* ActionNode::BeginPositiveSubmatch(int stack_reg, int position_reg, - RegExpNode* on_success) { + RegExpNode* body, + ActionNode* success_node) { ActionNode* result = - on_success->zone()->New(BEGIN_POSITIVE_SUBMATCH, on_success); + body->zone()->New(BEGIN_POSITIVE_SUBMATCH, body); result->data_.u_submatch.stack_pointer_register = stack_reg; result->data_.u_submatch.current_position_register = position_reg; + result->data_.u_submatch.success_node = success_node; return result; } @@ -751,12 +752,35 @@ bool ContainsOnlyUtf16CodeUnits(unibrow::uchar* chars, int length) { #endif // DEBUG // Returns the number of characters in the equivalence class, omitting those -// that cannot occur in the source string because it is Latin1. +// that cannot occur in the source string because it is Latin1. This is called +// both for unicode modes /ui and /vi, and also for legacy case independent +// mode /i. In the case of Unicode modes we handled surrogate pair expansions +// earlier so at this point it's all about single-code-unit expansions. int GetCaseIndependentLetters(Isolate* isolate, base::uc16 character, - bool one_byte_subject, unibrow::uchar* letters, + RegExpCompiler* compiler, unibrow::uchar* letters, int letter_length) { + bool one_byte_subject = compiler->one_byte(); + bool unicode = IsEitherUnicode(compiler->flags()); + static const base::uc16 kMaxAscii = 0x7f; + if (!unicode && character <= kMaxAscii) { + // Fast case for common characters. + base::uc16 upper = character & ~0x20; + if ('A' <= upper && upper <= 'Z') { + letters[0] = upper; + letters[1] = upper | 0x20; + return 2; + } + letters[0] = character; + return 1; + } #ifdef V8_INTL_SUPPORT - if (RegExpCaseFolding::IgnoreSet().contains(character)) { + + if (!unicode && RegExpCaseFolding::IgnoreSet().contains(character)) { + if (one_byte_subject && character > String::kMaxOneByteCharCode) { + // This function promises not to return a character that is impossible + // for the subject encoding. + return 0; + } letters[0] = character; DCHECK(ContainsOnlyUtf16CodeUnits(letters, 1)); return 1; @@ -766,10 +790,11 @@ int GetCaseIndependentLetters(Isolate* isolate, base::uc16 character, icu::UnicodeSet set; set.add(character); - set = set.closeOver(USET_CASE_INSENSITIVE); + set = set.closeOver(unicode ? USET_SIMPLE_CASE_INSENSITIVE + : USET_CASE_INSENSITIVE); UChar32 canon = 0; - if (in_special_add_set) { + if (in_special_add_set && !unicode) { canon = RegExpCaseFolding::Canonicalize(character); } @@ -780,8 +805,9 @@ int GetCaseIndependentLetters(Isolate* isolate, base::uc16 character, UChar32 end = set.getRangeEnd(i); CHECK(end - start + items <= letter_length); for (UChar32 cu = start; cu <= end; cu++) { - if (one_byte_subject && cu > String::kMaxOneByteCharCode) break; - if (in_special_add_set && RegExpCaseFolding::Canonicalize(cu) != canon) { + if (one_byte_subject && cu > String::kMaxOneByteCharCode) continue; + if (!unicode && in_special_add_set && + RegExpCaseFolding::Canonicalize(cu) != canon) { continue; } letters[items++] = static_cast(cu); @@ -835,25 +861,26 @@ inline bool EmitAtomNonLetter(Isolate* isolate, RegExpCompiler* compiler, RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); bool one_byte = compiler->one_byte(); unibrow::uchar chars[4]; - int length = GetCaseIndependentLetters(isolate, c, one_byte, chars, 4); + int length = GetCaseIndependentLetters(isolate, c, compiler, chars, 4); if (length < 1) { // This can't match. Must be an one-byte subject and a non-one-byte // character. We do not need to do anything since the one-byte pass // already handled this. + CHECK(one_byte); return false; // Bounds not checked. } bool checked = false; // We handle the length > 1 case in a later pass. if (length == 1) { - if (one_byte && c > String::kMaxOneByteCharCodeU) { - // Can't match - see above. - return false; // Bounds not checked. - } + // GetCaseIndependentLetters promises not to return characters that can't + // match because of the subject encoding. This case is already handled by + // the one-byte pass. + CHECK_IMPLIES(one_byte, chars[0] <= String::kMaxOneByteCharCodeU); if (!preloaded) { macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check); checked = check; } - macro_assembler->CheckNotCharacter(c, on_failure); + macro_assembler->CheckNotCharacter(chars[0], on_failure); } return checked; } @@ -895,7 +922,8 @@ inline bool EmitAtomLetter(Isolate* isolate, RegExpCompiler* compiler, RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); bool one_byte = compiler->one_byte(); unibrow::uchar chars[4]; - int length = GetCaseIndependentLetters(isolate, c, one_byte, chars, 4); + int length = GetCaseIndependentLetters(isolate, c, compiler, chars, 4); + // The 0 and 1 case are handled by earlier passes. if (length <= 1) return false; // We may not need to check against the end of the input string // if this character lies before a character that matched. @@ -1367,7 +1395,7 @@ bool RegExpNode::KeepRecursing(RegExpCompiler* compiler) { void ActionNode::FillInBMInfo(Isolate* isolate, int offset, int budget, BoyerMooreLookahead* bm, bool not_at_start) { - base::Optional old_flags; + std::optional old_flags; if (action_type_ == MODIFY_FLAGS) { // It is not guaranteed that we hit the resetting modify flags node, due to // recursion budget limitation for filling in BMInfo. Therefore we reset the @@ -1375,11 +1403,15 @@ void ActionNode::FillInBMInfo(Isolate* isolate, int offset, int budget, old_flags = bm->compiler()->flags(); bm->compiler()->set_flags(flags()); } - if (action_type_ == POSITIVE_SUBMATCH_SUCCESS) { - // Anything may follow a positive submatch success, thus we need to accept - // all characters from this position onwards. - bm->SetRest(offset); - } else { + if (action_type_ == BEGIN_POSITIVE_SUBMATCH) { + // We use the node after the lookaround to fill in the eats_at_least info + // so we have to use the same node to fill in the Boyer-Moore info. + success_node()->on_success()->FillInBMInfo(isolate, offset, budget - 1, bm, + not_at_start); + } else if (action_type_ != POSITIVE_SUBMATCH_SUCCESS) { + // We don't use the node after a positive submatch success because it + // rewinds the position. Since we returned 0 as the eats_at_least value for + // this node, we don't need to fill in any data. on_success()->FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start); } SaveBMInfo(bm, not_at_start, offset); @@ -1394,12 +1426,28 @@ void ActionNode::GetQuickCheckDetails(QuickCheckDetails* details, if (action_type_ == SET_REGISTER_FOR_LOOP) { on_success()->GetQuickCheckDetailsFromLoopEntry(details, compiler, filled_in, not_at_start); - } else { + } else if (action_type_ == BEGIN_POSITIVE_SUBMATCH) { + // We use the node after the lookaround to fill in the eats_at_least info + // so we have to use the same node to fill in the QuickCheck info. + success_node()->on_success()->GetQuickCheckDetails(details, compiler, + filled_in, not_at_start); + } else if (action_type() != POSITIVE_SUBMATCH_SUCCESS) { + // We don't use the node after a positive submatch success because it + // rewinds the position. Since we returned 0 as the eats_at_least value + // for this node, we don't need to fill in any data. + std::optional old_flags; if (action_type() == MODIFY_FLAGS) { + // It is not guaranteed that we hit the resetting modify flags node, as + // GetQuickCheckDetails doesn't travers the whole graph. Therefore we + // reset the flags manually to the previous state after recursing. + old_flags = compiler->flags(); compiler->set_flags(flags()); } on_success()->GetQuickCheckDetails(details, compiler, filled_in, not_at_start); + if (old_flags.has_value()) { + compiler->set_flags(*old_flags); + } } } @@ -1450,7 +1498,7 @@ bool QuickCheckDetails::Rationalize(bool asc) { return found_useful_op; } -int RegExpNode::EatsAtLeast(bool not_at_start) { +uint32_t RegExpNode::EatsAtLeast(bool not_at_start) { return not_at_start ? eats_at_least_.eats_at_least_from_not_start : eats_at_least_.eats_at_least_from_possibly_start; } @@ -1489,10 +1537,13 @@ EatsAtLeastInfo LoopChoiceNode::EatsAtLeastFromLoopEntry() { // successful match in the loop body must also include the continuation node. // However, in some cases involving positive lookaround, the loop body under- // reports its appetite, so use saturated math here to avoid negative numbers. + // For this to work correctly, we explicitly need to use signed integers here. uint8_t loop_body_from_not_start = base::saturated_cast( - loop_node_->EatsAtLeast(true) - continue_node_->EatsAtLeast(true)); + static_cast(loop_node_->EatsAtLeast(true)) - + static_cast(continue_node_->EatsAtLeast(true))); uint8_t loop_body_from_possibly_start = base::saturated_cast( - loop_node_->EatsAtLeast(false) - continue_node_->EatsAtLeast(true)); + static_cast(loop_node_->EatsAtLeast(false)) - + static_cast(continue_node_->EatsAtLeast(true))); // Limit the number of loop iterations to avoid overflow in subsequent steps. int loop_iterations = base::saturated_cast(min_loop_iterations()); @@ -1618,8 +1669,8 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, base::uc16 c = quarks[i]; if (IsIgnoreCase(compiler->flags())) { unibrow::uchar chars[4]; - int length = GetCaseIndependentLetters( - isolate, c, compiler->one_byte(), chars, 4); + int length = + GetCaseIndependentLetters(isolate, c, compiler, chars, 4); if (length == 0) { // This can happen because all case variants are non-Latin1, but we // know the input is Latin1. @@ -1848,16 +1899,17 @@ class IterationDecrementer { LoopChoiceNode* node_; }; -RegExpNode* SeqRegExpNode::FilterOneByte(int depth, RegExpFlags flags) { +RegExpNode* SeqRegExpNode::FilterOneByte(int depth, RegExpCompiler* compiler) { if (info()->replacement_calculated) return replacement(); if (depth < 0) return this; DCHECK(!info()->visited); VisitMarker marker(info()); - return FilterSuccessor(depth - 1, flags); + return FilterSuccessor(depth - 1, compiler); } -RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, RegExpFlags flags) { - RegExpNode* next = on_success_->FilterOneByte(depth - 1, flags); +RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, + RegExpCompiler* compiler) { + RegExpNode* next = on_success_->FilterOneByte(depth - 1, compiler); if (next == nullptr) return set_replacement(nullptr); on_success_ = next; return set_replacement(this); @@ -1882,7 +1934,8 @@ bool RangesContainLatin1Equivalents(ZoneList* ranges) { } // namespace -RegExpNode* TextNode::FilterOneByte(int depth, RegExpFlags flags) { +RegExpNode* TextNode::FilterOneByte(int depth, RegExpCompiler* compiler) { + RegExpFlags flags = compiler->flags(); if (info()->replacement_calculated) return replacement(); if (depth < 0) return this; DCHECK(!info()->visited); @@ -1894,46 +1947,56 @@ RegExpNode* TextNode::FilterOneByte(int depth, RegExpFlags flags) { base::Vector quarks = elm.atom()->data(); for (int j = 0; j < quarks.length(); j++) { base::uc16 c = quarks[j]; - if (IsIgnoreCase(flags)) { - c = unibrow::Latin1::TryConvertToLatin1(c); + if (!IsIgnoreCase(flags)) { + if (c > String::kMaxOneByteCharCode) return set_replacement(nullptr); + } else { + unibrow::uchar chars[4]; + int length = GetCaseIndependentLetters(compiler->isolate(), c, + compiler, chars, 4); + if (length == 0 || chars[0] > String::kMaxOneByteCharCode) { + return set_replacement(nullptr); + } } - if (c > unibrow::Latin1::kMaxChar) return set_replacement(nullptr); - // Replace quark in case we converted to Latin-1. - base::uc16* writable_quarks = const_cast(quarks.begin()); - writable_quarks[j] = c; } } else { + // A character class can also be impossible to match in one-byte mode. DCHECK(elm.text_type() == TextElement::CLASS_RANGES); RegExpClassRanges* cr = elm.class_ranges(); ZoneList* ranges = cr->ranges(zone()); CharacterRange::Canonicalize(ranges); // Now they are in order so we only need to look at the first. + // If we are in non-Unicode case independent mode then we need + // to be a bit careful here, because the character classes have + // not been case-desugared yet, but there are characters and ranges + // that can become Latin-1 when case is considered. int range_count = ranges->length(); if (cr->is_negated()) { if (range_count != 0 && ranges->at(0).from() == 0 && ranges->at(0).to() >= String::kMaxOneByteCharCode) { - // This will be handled in a later filter. - if (IsIgnoreCase(flags) && RangesContainLatin1Equivalents(ranges)) { - continue; + bool case_complications = !IsEitherUnicode(flags) && + IsIgnoreCase(flags) && + RangesContainLatin1Equivalents(ranges); + if (!case_complications) { + return set_replacement(nullptr); } - return set_replacement(nullptr); } } else { if (range_count == 0 || ranges->at(0).from() > String::kMaxOneByteCharCode) { - // This will be handled in a later filter. - if (IsIgnoreCase(flags) && RangesContainLatin1Equivalents(ranges)) { - continue; + bool case_complications = !IsEitherUnicode(flags) && + IsIgnoreCase(flags) && + RangesContainLatin1Equivalents(ranges); + if (!case_complications) { + return set_replacement(nullptr); } - return set_replacement(nullptr); } } } } - return FilterSuccessor(depth - 1, flags); + return FilterSuccessor(depth - 1, compiler); } -RegExpNode* LoopChoiceNode::FilterOneByte(int depth, RegExpFlags flags) { +RegExpNode* LoopChoiceNode::FilterOneByte(int depth, RegExpCompiler* compiler) { if (info()->replacement_calculated) return replacement(); if (depth < 0) return this; if (info()->visited) return this; @@ -1941,16 +2004,16 @@ RegExpNode* LoopChoiceNode::FilterOneByte(int depth, RegExpFlags flags) { VisitMarker marker(info()); RegExpNode* continue_replacement = - continue_node_->FilterOneByte(depth - 1, flags); + continue_node_->FilterOneByte(depth - 1, compiler); // If we can't continue after the loop then there is no sense in doing the // loop. if (continue_replacement == nullptr) return set_replacement(nullptr); } - return ChoiceNode::FilterOneByte(depth - 1, flags); + return ChoiceNode::FilterOneByte(depth - 1, compiler); } -RegExpNode* ChoiceNode::FilterOneByte(int depth, RegExpFlags flags) { +RegExpNode* ChoiceNode::FilterOneByte(int depth, RegExpCompiler* compiler) { if (info()->replacement_calculated) return replacement(); if (depth < 0) return this; if (info()->visited) return this; @@ -1971,7 +2034,7 @@ RegExpNode* ChoiceNode::FilterOneByte(int depth, RegExpFlags flags) { for (int i = 0; i < choice_count; i++) { GuardedAlternative alternative = alternatives_->at(i); RegExpNode* replacement = - alternative.node()->FilterOneByte(depth - 1, flags); + alternative.node()->FilterOneByte(depth - 1, compiler); DCHECK(replacement != this); // No missing EMPTY_MATCH_CHECK. if (replacement != nullptr) { alternatives_->at(i).set_node(replacement); @@ -1991,7 +2054,7 @@ RegExpNode* ChoiceNode::FilterOneByte(int depth, RegExpFlags flags) { zone()->New>(surviving, zone()); for (int i = 0; i < choice_count; i++) { RegExpNode* replacement = - alternatives_->at(i).node()->FilterOneByte(depth - 1, flags); + alternatives_->at(i).node()->FilterOneByte(depth - 1, compiler); if (replacement != nullptr) { alternatives_->at(i).set_node(replacement); new_alternatives->Add(alternatives_->at(i), zone()); @@ -2001,8 +2064,8 @@ RegExpNode* ChoiceNode::FilterOneByte(int depth, RegExpFlags flags) { return this; } -RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(int depth, - RegExpFlags flags) { +RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte( + int depth, RegExpCompiler* compiler) { if (info()->replacement_calculated) return replacement(); if (depth < 0) return this; if (info()->visited) return this; @@ -2010,12 +2073,12 @@ RegExpNode* NegativeLookaroundChoiceNode::FilterOneByte(int depth, // Alternative 0 is the negative lookahead, alternative 1 is what comes // afterwards. RegExpNode* node = continue_node(); - RegExpNode* replacement = node->FilterOneByte(depth - 1, flags); + RegExpNode* replacement = node->FilterOneByte(depth - 1, compiler); if (replacement == nullptr) return set_replacement(nullptr); alternatives_->at(kContinueIndex).set_node(replacement); RegExpNode* neg_node = lookaround_node(); - RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, flags); + RegExpNode* neg_replacement = neg_node->FilterOneByte(depth - 1, compiler); // If the negative lookahead is always going to fail then // we don't need to check it. if (neg_replacement == nullptr) return set_replacement(replacement); @@ -2360,29 +2423,38 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass, TextElement elm = elements()->at(i); int cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset; if (elm.text_type() == TextElement::ATOM) { - if (SkipPass(pass, IsIgnoreCase(compiler->flags()))) continue; base::Vector quarks = elm.atom()->data(); for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { if (first_element_checked && i == 0 && j == 0) continue; if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue; base::uc16 quark = quarks[j]; - if (IsIgnoreCase(compiler->flags())) { - // Everywhere else we assume that a non-Latin-1 character cannot match - // a Latin-1 character. Avoid the cases where this is assumption is - // invalid by using the Latin1 equivalent instead. - quark = unibrow::Latin1::TryConvertToLatin1(quark); - } bool needs_bounds_check = *checked_up_to < cp_offset + j || read_backward(); bool bounds_checked = false; switch (pass) { - case NON_LATIN1_MATCH: - DCHECK(one_byte); - if (quark > String::kMaxOneByteCharCode) { - assembler->GoTo(backtrack); - return; + case NON_LATIN1_MATCH: { + DCHECK(one_byte); // This pass is only done in one-byte mode. + if (IsIgnoreCase(compiler->flags())) { + // We are compiling for a one-byte subject, case independent mode. + // We have to check whether any of the case alternatives are in + // the one-byte range. + unibrow::uchar chars[4]; + // Only returns characters that are in the one-byte range. + int length = + GetCaseIndependentLetters(isolate, quark, compiler, chars, 4); + if (length == 0) { + assembler->GoTo(backtrack); + return; + } + } else { + // Case-dependent mode. + if (quark > String::kMaxOneByteCharCode) { + assembler->GoTo(backtrack); + return; + } } break; + } case NON_LETTER_CHARACTER_MATCH: bounds_checked = EmitAtomNonLetter(isolate, compiler, quark, backtrack, @@ -2424,14 +2496,6 @@ int TextNode::Length() { return elm.cp_offset() + elm.length(); } -bool TextNode::SkipPass(TextEmitPassType pass, bool ignore_case) { - if (ignore_case) { - return pass == SIMPLE_CHARACTER_MATCH; - } else { - return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH; - } -} - TextNode* TextNode::CreateForCharacterRanges(Zone* zone, ZoneList* ranges, bool read_backward, @@ -2446,11 +2510,18 @@ TextNode* TextNode::CreateForCharacterRanges(Zone* zone, TextNode* TextNode::CreateForSurrogatePair( Zone* zone, CharacterRange lead, ZoneList* trail_ranges, bool read_backward, RegExpNode* on_success) { - ZoneList* lead_ranges = CharacterRange::List(zone, lead); ZoneList* elms = zone->New>(2, zone); - elms->Add( - TextElement::ClassRanges(zone->New(zone, lead_ranges)), - zone); + if (lead.from() == lead.to()) { + ZoneList lead_surrogate(1, zone); + lead_surrogate.Add(lead.from(), zone); + RegExpAtom* atom = zone->New(lead_surrogate.ToConstVector()); + elms->Add(TextElement::Atom(atom), zone); + } else { + ZoneList* lead_ranges = CharacterRange::List(zone, lead); + elms->Add(TextElement::ClassRanges( + zone->New(zone, lead_ranges)), + zone); + } elms->Add(TextElement::ClassRanges( zone->New(zone, trail_ranges)), zone); @@ -2497,18 +2568,22 @@ void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) { bound_checked_to += trace->bound_checked_up_to(); // If a character is preloaded into the current character register then - // check that now. - if (trace->characters_preloaded() == 1) { - for (int pass = kFirstRealPass; pass <= kLastPass; pass++) { - TextEmitPass(compiler, static_cast(pass), true, trace, - false, &bound_checked_to); + // check that first to save reloading it. + for (int twice = 0; twice < 2; twice++) { + bool is_preloaded_pass = twice == 0; + if (is_preloaded_pass && trace->characters_preloaded() != 1) continue; + if (IsIgnoreCase(compiler->flags())) { + TextEmitPass(compiler, NON_LETTER_CHARACTER_MATCH, is_preloaded_pass, + trace, first_elt_done, &bound_checked_to); + TextEmitPass(compiler, CASE_CHARACTER_MATCH, is_preloaded_pass, trace, + first_elt_done, &bound_checked_to); + } else { + TextEmitPass(compiler, SIMPLE_CHARACTER_MATCH, is_preloaded_pass, trace, + first_elt_done, &bound_checked_to); } - first_elt_done = true; - } - - for (int pass = kFirstRealPass; pass <= kLastPass; pass++) { - TextEmitPass(compiler, static_cast(pass), false, trace, + TextEmitPass(compiler, CHARACTER_CLASS_MATCH, is_preloaded_pass, trace, first_elt_done, &bound_checked_to); + first_elt_done = true; } Trace successor_trace(*trace); @@ -2544,6 +2619,8 @@ void TextNode::MakeCaseIndependent(Isolate* isolate, bool is_one_byte, RegExpFlags flags) { if (!IsIgnoreCase(flags)) return; #ifdef V8_INTL_SUPPORT + // This is done in an earlier step when generating the nodes from the AST + // because we may have to split up into separate nodes. if (NeedsUnicodeCaseEquivalents(flags)) return; #endif @@ -2600,8 +2677,7 @@ int ChoiceNode::GreedyLoopTextLengthForAlternative( return kNodeIsTooComplexForGreedyLoops; } length += node_length; - SeqRegExpNode* seq_node = static_cast(node); - node = seq_node->on_success(); + node = node->AsSeqRegExpNode()->on_success(); } if (read_backward()) { length = -length; @@ -2883,13 +2959,24 @@ int BoyerMooreLookahead::FindBestInterval(int max_number_of_chars, // max_lookahead (inclusive) measured from the current position. If the // character at max_lookahead offset is not one of these characters, then we // can safely skip forwards by the number of characters in the range. -int BoyerMooreLookahead::GetSkipTable(int min_lookahead, int max_lookahead, - Handle boolean_skip_table) { +// nibble_table is only used for SIMD variants and encodes the same information +// as boolean_skip_table but in only 128 bits. It contains 16 bytes where the +// index into the table represent low nibbles of a character, and the stored +// byte is a bitset representing matching high nibbles. E.g. to store the +// character 'b' (0x62) in the nibble table, we set the 6th bit in row 2. +int BoyerMooreLookahead::GetSkipTable( + int min_lookahead, int max_lookahead, + DirectHandle boolean_skip_table, + DirectHandle nibble_table) { const int kSkipArrayEntry = 0; const int kDontSkipArrayEntry = 1; std::memset(boolean_skip_table->begin(), kSkipArrayEntry, boolean_skip_table->length()); + const bool fill_nibble_table = !nibble_table.is_null(); + if (fill_nibble_table) { + std::memset(nibble_table->begin(), 0, nibble_table->length()); + } for (int i = max_lookahead; i >= min_lookahead; i--) { BoyerMoorePositionInfo::Bitset bitset = bitmaps_->at(i)->raw_bitset(); @@ -2899,6 +2986,13 @@ int BoyerMooreLookahead::GetSkipTable(int min_lookahead, int max_lookahead, while ((j = BitsetFirstSetBit(bitset)) != -1) { DCHECK(bitset[j]); // Sanity check. boolean_skip_table->set(j, kDontSkipArrayEntry); + if (fill_nibble_table) { + int lo_nibble = j & 0x0f; + int hi_nibble = (j >> 4) & 0x07; + int row = nibble_table->get(lo_nibble); + row |= 1 << hi_nibble; + nibble_table->set(lo_nibble, row); + } bitset.reset(j); } } @@ -2946,6 +3040,7 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) { } if (found_single_character) { + // TODO(pthier): Add vectorized version. Label cont, again; masm->Bind(&again); masm->LoadCurrentCharacter(max_lookahead, &cont, true); @@ -2964,17 +3059,19 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) { Factory* factory = masm->isolate()->factory(); Handle boolean_skip_table = factory->NewByteArray(kSize, AllocationType::kOld); - int skip_distance = - GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table); + Handle nibble_table; + const int skip_distance = max_lookahead + 1 - min_lookahead; + if (masm->SkipUntilBitInTableUseSimd(skip_distance)) { + // The current implementation is tailored specifically for 128-bit tables. + static_assert(kSize == 128); + nibble_table = + factory->NewByteArray(kSize / kBitsPerByte, AllocationType::kOld); + } + GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table, nibble_table); DCHECK_NE(0, skip_distance); - Label cont, again; - masm->Bind(&again); - masm->LoadCurrentCharacter(max_lookahead, &cont, true); - masm->CheckBitInTable(boolean_skip_table, &cont); - masm->AdvanceCurrentPosition(skip_distance); - masm->GoTo(&again); - masm->Bind(&cont); + masm->SkipUntilBitInTable(max_lookahead, boolean_skip_table, nibble_table, + skip_distance); } /* Code generation for choice nodes. @@ -3119,11 +3216,6 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { trace = EmitGreedyLoop(compiler, trace, &alt_gens, &preload, &greedy_loop_state, text_length); } else { - // TODO(erikcorry): Delete this. We don't need this label, but it makes us - // match the traces produced pre-cleanup. - Label second_choice; - compiler->macro_assembler()->Bind(&second_choice); - preload.eats_at_least_ = EmitOptimizedUnanchoredSearch(compiler, trace); EmitChoices(compiler, &alt_gens, 0, trace, &preload); @@ -3272,7 +3364,7 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler, } alt_gen->expects_preload = preload->preload_is_current_; bool generate_full_check_inline = false; - if (compiler->optimize() && + if (v8_flags.regexp_optimization && try_to_emit_quick_check_for_alternative(i == 0) && alternative.node()->EmitQuickCheck( compiler, trace, &new_trace, preload->preload_has_checked_bounds_, @@ -3602,16 +3694,23 @@ class EatsAtLeastPropagator : public AllStatic { static void VisitAction(ActionNode* that) { switch (that->action_type()) { - case ActionNode::BEGIN_POSITIVE_SUBMATCH: + case ActionNode::BEGIN_POSITIVE_SUBMATCH: { + // For a begin positive submatch we propagate the eats_at_least + // data from the successor of the success node, ignoring the body of + // the lookahead, which eats nothing, since it is a zero-width + // assertion. + // TODO(chromium:42201836) This is better than discarding all + // information when there is a positive lookahead, but it loses some + // information that could be useful, since the body of the lookahead + // could tell us something about how close to the end of the string we + // are. + that->set_eats_at_least_info( + *that->success_node()->on_success()->eats_at_least_info()); + break; + } case ActionNode::POSITIVE_SUBMATCH_SUCCESS: - // We do not propagate eats_at_least data through positive lookarounds, - // because they rewind input. - // TODO(v8:11859) Potential approaches for fixing this include: - // 1. Add a dedicated choice node for positive lookaround, similar to - // NegativeLookaroundChoiceNode. - // 2. Add an eats_at_least_inside_loop field to EatsAtLeastInfo, which - // is <= eats_at_least_from_possibly_start, and use that value in - // EatsAtLeastFromLoopEntry. + // We do not propagate eats_at_least data through positive submatch + // success because it rewinds input. DCHECK(that->eats_at_least_info()->IsZero()); break; case ActionNode::SET_REGISTER_FOR_LOOP: @@ -3761,15 +3860,28 @@ class Analysis : public NodeVisitor { DCHECK_EQ(that->alternatives()->length(), 2); // Just loop and continue. // First propagate all information from the continuation node. + // Due to the unusual visitation order, we need to manage the flags manually + // as if we were visiting the loop node before visiting the continuation. + RegExpFlags orig_flags = flags(); + EnsureAnalyzed(that->continue_node()); if (has_failed()) return; + // Propagators don't access global state (including flags), so we don't need + // to reset them here. STATIC_FOR_EACH(Propagators::VisitLoopChoiceContinueNode(that)); + RegExpFlags continuation_flags = flags(); + // Check the loop last since it may need the value of this node // to get a correct result. + set_flags(orig_flags); EnsureAnalyzed(that->loop_node()); if (has_failed()) return; + // Propagators don't access global state (including flags), so we don't need + // to reset them here. STATIC_FOR_EACH(Propagators::VisitLoopChoiceLoopNode(that)); + + set_flags(continuation_flags); } void VisitNegativeLookaroundChoice( @@ -3854,6 +3966,7 @@ void ChoiceNode::FillInBMInfo(Isolate* isolate, int offset, int budget, void TextNode::FillInBMInfo(Isolate* isolate, int initial_offset, int budget, BoyerMooreLookahead* bm, bool not_at_start) { if (initial_offset >= bm->length()) return; + if (read_backward()) return; int offset = initial_offset; int max_char = bm->max_char(); for (int i = 0; i < elements()->length(); i++) { @@ -3872,9 +3985,8 @@ void TextNode::FillInBMInfo(Isolate* isolate, int initial_offset, int budget, base::uc16 character = atom->data()[j]; if (IsIgnoreCase(bm->compiler()->flags())) { unibrow::uchar chars[4]; - int length = GetCaseIndependentLetters( - isolate, character, bm->max_char() == String::kMaxOneByteCharCode, - chars, 4); + int length = GetCaseIndependentLetters(isolate, character, + bm->compiler(), chars, 4); for (int k = 0; k < length; k++) { bm->Set(offset, chars[k]); } @@ -3962,11 +4074,11 @@ RegExpNode* RegExpCompiler::PreprocessRegExp(RegExpCompileData* data, } } if (is_one_byte) { - node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, flags()); + node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, this); // Do it again to propagate the new nodes to places where they were not // put because they had not been calculated yet. if (node != nullptr) { - node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, flags()); + node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, this); } } else if (IsEitherUnicode(flags()) && (IsGlobal(flags()) || IsSticky(flags()))) { @@ -3974,6 +4086,11 @@ RegExpNode* RegExpCompiler::PreprocessRegExp(RegExpCompileData* data, } if (node == nullptr) node = zone()->New(EndNode::BACKTRACK, zone()); + // We can run out of registers during preprocessing. Indicate an error in case + // we do. + if (reg_exp_too_big_) { + data->error = RegExpError::kTooLarge; + } return node; } @@ -3983,5 +4100,4 @@ void RegExpCompiler::ToNodeCheckForStackOverflow() { } } -} // namespace internal -} // namespace v8 +} // namespace v8::internal diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.h index 7a369430bbb..e02d9f2eb5c 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-compiler.h @@ -40,10 +40,10 @@ constexpr int kLineTerminatorRanges[] = {0x000A, 0x000B, 0x000D, 0x000E, constexpr int kLineTerminatorRangeCount = arraysize(kLineTerminatorRanges); // More makes code generation slower, less makes V8 benchmark score lower. -constexpr int kMaxLookaheadForBoyerMoore = 8; +constexpr uint32_t kMaxLookaheadForBoyerMoore = 8; // In a 3-character pattern you can maximally step forwards 3 characters // at a time, which is not always enough to pay for the extra logic. -constexpr int kPatternTooShortForBoyerMoore = 2; +constexpr uint32_t kPatternTooShortForBoyerMoore = 2; } // namespace regexp_compiler_constants @@ -205,8 +205,10 @@ class BoyerMooreLookahead : public ZoneObject { int max_char_; ZoneList* bitmaps_; - int GetSkipTable(int min_lookahead, int max_lookahead, - Handle boolean_skip_table); + int GetSkipTable( + int min_lookahead, int max_lookahead, + DirectHandle boolean_skip_table, + DirectHandle nibble_table = DirectHandle{}); bool FindWorthwhileInterval(int* from, int* to); int FindBestInterval(int max_number_of_chars, int old_biggest_points, int* from, int* to); @@ -477,7 +479,7 @@ class RegExpCompiler { struct CompilationResult final { explicit CompilationResult(RegExpError err) : error(err) {} - CompilationResult(Handle code, int registers) + CompilationResult(DirectHandle code, int registers) : code(code), num_registers(registers) {} static CompilationResult RegExpTooBig() { @@ -487,13 +489,13 @@ class RegExpCompiler { bool Succeeded() const { return error == RegExpError::kNone; } const RegExpError error = RegExpError::kNone; - Handle code; + DirectHandle code; int num_registers = 0; }; CompilationResult Assemble(Isolate* isolate, RegExpMacroAssembler* assembler, RegExpNode* start, int capture_count, - Handle pattern); + DirectHandle pattern); // Preprocessing is the final step of node creation before analysis // and assembly. It includes: diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-dotprinter.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-dotprinter.cc index cd0ca5dea86..420cd5bfc7f 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-dotprinter.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-dotprinter.cc @@ -108,6 +108,7 @@ void DotPrinterImpl::VisitChoice(ChoiceNode* that) { GuardedAlternative alt = that->alternatives()->at(i); alt.node()->Accept(this); } + PrintAttributes(that); } void DotPrinterImpl::VisitLoopChoice(LoopChoiceNode* that) { diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-error.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-error.h index ff4fe41cd59..0e2f388b1eb 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-error.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-error.h @@ -37,7 +37,6 @@ namespace internal { T(DuplicateCaptureGroupName, "Duplicate capture group name") \ T(InvalidNamedReference, "Invalid named reference") \ T(InvalidNamedCaptureReference, "Invalid named capture referenced") \ - T(InvalidClassEscape, "Invalid class escape") \ T(InvalidClassPropertyName, "Invalid property name in character class") \ T(InvalidCharacterClass, "Invalid character class") \ T(UnterminatedCharacterClass, "Unterminated character class") \ diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.cc index f2349909847..17319a0ca2a 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.cc @@ -126,7 +126,7 @@ class BacktrackStack { return (static_cast(data_.size()) <= kMaxSize); } int peek() const { - DCHECK(!data_.empty()); + SBXCHECK(!data_.empty()); return data_.back(); } int pop() { @@ -137,7 +137,7 @@ class BacktrackStack { // The 'sp' is the index of the first empty element in the stack. int sp() const { return static_cast(data_.size()); } - void set_sp(int new_sp) { + void set_sp(uint32_t new_sp) { DCHECK_LE(new_sp, sp()); data_.resize_no_init(new_sp); } @@ -228,10 +228,10 @@ IrregexpInterpreter::Result MaybeThrowStackOverflow( template void UpdateCodeAndSubjectReferences( - Isolate* isolate, Handle code_array, - Handle subject_string, Tagged* code_array_out, - const uint8_t** code_base_out, const uint8_t** pc_out, - Tagged* subject_string_out, + Isolate* isolate, DirectHandle code_array, + DirectHandle subject_string, + Tagged* code_array_out, const uint8_t** code_base_out, + const uint8_t** pc_out, Tagged* subject_string_out, base::Vector* subject_string_vector_out) { DisallowGarbageCollection no_gc; @@ -253,8 +253,8 @@ void UpdateCodeAndSubjectReferences( template IrregexpInterpreter::Result HandleInterrupts( Isolate* isolate, RegExp::CallOrigin call_origin, - Tagged* code_array_out, Tagged* subject_string_out, - const uint8_t** code_base_out, + Tagged* code_array_out, + Tagged* subject_string_out, const uint8_t** code_base_out, base::Vector* subject_string_vector_out, const uint8_t** pc_out) { DisallowGarbageCollection no_gc; @@ -277,14 +277,14 @@ IrregexpInterpreter::Result HandleInterrupts( DCHECK(call_origin == RegExp::CallOrigin::kFromRuntime); // Prepare for possible GC. HandleScope handles(isolate); - Handle code_handle(*code_array_out, isolate); - Handle subject_handle(*subject_string_out, isolate); + DirectHandle code_handle(*code_array_out, isolate); + DirectHandle subject_handle(*subject_string_out, isolate); if (js_has_overflowed) { return ThrowStackOverflow(isolate, call_origin); } else if (check.InterruptRequested()) { const bool was_one_byte = - String::IsOneByteRepresentationUnderneath(*subject_string_out); + (*subject_string_out)->IsOneByteRepresentation(); Tagged result; { AllowGarbageCollection yes_gc; @@ -297,8 +297,7 @@ IrregexpInterpreter::Result HandleInterrupts( // If we changed between a LATIN1 and a UC16 string, we need to // restart regexp matching with the appropriate template instantiation of // RawMatch. - if (String::IsOneByteRepresentationUnderneath(*subject_handle) != - was_one_byte) { + if (subject_handle->IsOneByteRepresentation() != was_one_byte) { return IrregexpInterpreter::RETRY; } @@ -384,8 +383,8 @@ bool IndexIsInBounds(int index, int length) { template IrregexpInterpreter::Result RawMatch( - Isolate* isolate, Tagged code_array, - Tagged subject_string, base::Vector subject, + Isolate* isolate, Tagged* code_array, + Tagged* subject_string, base::Vector subject, int* output_registers, int output_register_count, int total_register_count, int current, uint32_t current_char, RegExp::CallOrigin call_origin, const uint32_t backtrack_limit) { @@ -439,7 +438,7 @@ IrregexpInterpreter::Result RawMatch( #endif // V8_USE_COMPUTED_GOTO - const uint8_t* pc = code_array->begin(); + const uint8_t* pc = (*code_array)->begin(); const uint8_t* code_base = pc; InterpreterRegisters registers(total_register_count, output_registers, @@ -531,7 +530,7 @@ IrregexpInterpreter::Result RawMatch( } IrregexpInterpreter::Result return_code = - HandleInterrupts(isolate, call_origin, &code_array, &subject_string, + HandleInterrupts(isolate, call_origin, code_array, subject_string, &code_base, &subject, &pc); if (return_code != IrregexpInterpreter::SUCCESS) return return_code; @@ -972,7 +971,7 @@ IrregexpInterpreter::Result RawMatch( } BYTECODE(SKIP_UNTIL_BIT_IN_TABLE) { int32_t load_offset = LoadPacked24Signed(insn); - int32_t advance = Load16AlignedSigned(pc + 4); + int32_t advance = Load32Aligned(pc + 4); const uint8_t* table = pc + 8; while (IndexIsInBounds(current + load_offset, subject.length())) { current_char = subject[current + load_offset]; @@ -1055,30 +1054,78 @@ IrregexpInterpreter::Result RawMatch( } // namespace // static -IrregexpInterpreter::Result IrregexpInterpreter::Match( - Isolate* isolate, Tagged regexp, Tagged subject_string, - int* output_registers, int output_register_count, int start_position, - RegExp::CallOrigin call_origin) { - if (v8_flags.regexp_tier_up) regexp->TierUpTick(); +int IrregexpInterpreter::Match(Isolate* isolate, + Tagged regexp_data, + Tagged subject_string, + int* output_registers, int output_register_count, + int start_position, + RegExp::CallOrigin call_origin) { + if (v8_flags.regexp_tier_up) regexp_data->TierUpTick(); - bool is_one_byte = String::IsOneByteRepresentationUnderneath(subject_string); - Tagged code_array = ByteArray::cast(regexp->bytecode(is_one_byte)); - int total_register_count = regexp->max_register_count(); + bool is_any_unicode = + IsEitherUnicode(JSRegExp::AsRegExpFlags(regexp_data->flags())); + bool is_one_byte = subject_string->IsOneByteRepresentation(); + Tagged code_array = regexp_data->bytecode(is_one_byte); + int total_register_count = regexp_data->max_register_count(); - return MatchInternal(isolate, code_array, subject_string, output_registers, - output_register_count, total_register_count, - start_position, call_origin, regexp->backtrack_limit()); + // MatchInternal only supports returning a single match per call. In global + // mode, i.e. when output_registers has space for more than one match, we + // need to keep running until all matches are filled in. + int registers_per_match = + JSRegExp::RegistersForCaptureCount(regexp_data->capture_count()); + DCHECK_LE(registers_per_match, output_register_count); + int number_of_matches_in_output_registers = + output_register_count / registers_per_match; + + int backtrack_limit = regexp_data->backtrack_limit(); + + int num_matches = 0; + int* current_output_registers = output_registers; + for (int i = 0; i < number_of_matches_in_output_registers; i++) { + auto current_result = MatchInternal( + isolate, &code_array, &subject_string, current_output_registers, + registers_per_match, total_register_count, start_position, call_origin, + backtrack_limit); + + if (current_result == SUCCESS) { + // Fall through. + } else if (current_result == FAILURE) { + break; + } else { + DCHECK(current_result == EXCEPTION || + current_result == FALLBACK_TO_EXPERIMENTAL || + current_result == RETRY); + return current_result; + } + + // Found a match. Advance the index. + + num_matches++; + + int next_start_position = current_output_registers[1]; + if (next_start_position == current_output_registers[0]) { + // Zero-length matches. + // TODO(jgruber): Use AdvanceStringIndex based on flat contents instead. + next_start_position = static_cast(RegExpUtils::AdvanceStringIndex( + subject_string, next_start_position, is_any_unicode)); + if (next_start_position > static_cast(subject_string->length())) { + break; + } + } + + start_position = next_start_position; + current_output_registers += registers_per_match; + } + + return num_matches; } IrregexpInterpreter::Result IrregexpInterpreter::MatchInternal( - Isolate* isolate, Tagged code_array, - Tagged subject_string, int* output_registers, + Isolate* isolate, Tagged* code_array, + Tagged* subject_string, int* output_registers, int output_register_count, int total_register_count, int start_position, RegExp::CallOrigin call_origin, uint32_t backtrack_limit) { - DCHECK(subject_string->IsFlat()); - - // TODO(chromium:1262676): Remove this CHECK once fixed. - CHECK(IsByteArray(code_array)); + DCHECK((*subject_string)->IsFlat()); // Note: Heap allocation *is* allowed in two situations if calling from // Runtime: @@ -1089,7 +1136,8 @@ IrregexpInterpreter::Result IrregexpInterpreter::MatchInternal( DisallowGarbageCollection no_gc; base::uc16 previous_char = '\n'; - String::FlatContent subject_content = subject_string->GetFlatContent(no_gc); + String::FlatContent subject_content = + (*subject_string)->GetFlatContent(no_gc); // Because interrupts can result in GC and string content relocation, the // checksum verification in FlatContent may fail even though this code is // safe. See (2) above. @@ -1118,10 +1166,10 @@ IrregexpInterpreter::Result IrregexpInterpreter::MatchInternal( // This method is called through an external reference from RegExpExecInternal // builtin. -IrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromJs( +int IrregexpInterpreter::MatchForCallFromJs( Address subject, int32_t start_position, Address, Address, int* output_registers, int32_t output_register_count, - RegExp::CallOrigin call_origin, Isolate* isolate, Address regexp) { + RegExp::CallOrigin call_origin, Isolate* isolate, Address regexp_data) { DCHECK_NOT_NULL(isolate); DCHECK_NOT_NULL(output_registers); DCHECK(call_origin == RegExp::CallOrigin::kFromJs); @@ -1131,25 +1179,27 @@ IrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromJs( DisallowHandleAllocation no_handles; DisallowHandleDereference no_deref; - Tagged subject_string = String::cast(Tagged(subject)); - Tagged regexp_obj = JSRegExp::cast(Tagged(regexp)); + Tagged subject_string = Cast(Tagged(subject)); + Tagged regexp_data_obj = + Cast(Tagged(regexp_data)); - if (regexp_obj->MarkedForTierUp()) { + if (regexp_data_obj->MarkedForTierUp()) { // Returning RETRY will re-enter through runtime, where actual recompilation // for tier-up takes place. return IrregexpInterpreter::RETRY; } - return Match(isolate, regexp_obj, subject_string, output_registers, + return Match(isolate, regexp_data_obj, subject_string, output_registers, output_register_count, start_position, call_origin); } #endif // !COMPILING_IRREGEXP_FOR_EXTERNAL_EMBEDDER -IrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromRuntime( - Isolate* isolate, Handle regexp, Handle subject_string, - int* output_registers, int output_register_count, int start_position) { - return Match(isolate, *regexp, *subject_string, output_registers, +int IrregexpInterpreter::MatchForCallFromRuntime( + Isolate* isolate, DirectHandle regexp_data, + DirectHandle subject_string, int* output_registers, + int output_register_count, int start_position) { + return Match(isolate, *regexp_data, *subject_string, output_registers, output_register_count, start_position, RegExp::CallOrigin::kFromRuntime); } diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.h index 825916291fe..3150cf9c082 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-interpreter.h @@ -12,7 +12,7 @@ namespace v8 { namespace internal { -class ByteArray; +class TrustedByteArray; class V8_EXPORT_PRIVATE IrregexpInterpreter : public AllStatic { public: @@ -26,9 +26,12 @@ class V8_EXPORT_PRIVATE IrregexpInterpreter : public AllStatic { // In case a StackOverflow occurs, a StackOverflowException is created and // EXCEPTION is returned. - static Result MatchForCallFromRuntime( - Isolate* isolate, Handle regexp, Handle subject_string, - int* output_registers, int output_register_count, int start_position); + static int MatchForCallFromRuntime(Isolate* isolate, + DirectHandle regexp_data, + DirectHandle subject_string, + int* output_registers, + int output_register_count, + int start_position); // In case a StackOverflow occurs, EXCEPTION is returned. The caller is // responsible for creating the exception. @@ -40,27 +43,29 @@ class V8_EXPORT_PRIVATE IrregexpInterpreter : public AllStatic { // match the signature of the native irregex code. // // Arguments output_registers and output_register_count describe the results - // array, which will contain register values of all captures if SUCCESS is - // returned. For all other return codes, the results array remains unmodified. - static Result MatchForCallFromJs(Address subject, int32_t start_position, - Address input_start, Address input_end, - int* output_registers, - int32_t output_register_count, - RegExp::CallOrigin call_origin, - Isolate* isolate, Address regexp); + // array, which will contain register values of all captures if one or more + // matches were found. In this case, the return value is the number of + // matches. For all other return codes, the results array remains unmodified. + static int MatchForCallFromJs(Address subject, int32_t start_position, + Address input_start, Address input_end, + int* output_registers, + int32_t output_register_count, + RegExp::CallOrigin call_origin, + Isolate* isolate, Address regexp_data); - static Result MatchInternal(Isolate* isolate, Tagged code_array, - Tagged subject_string, + static Result MatchInternal(Isolate* isolate, + Tagged* code_array, + Tagged* subject_string, int* output_registers, int output_register_count, int total_register_count, int start_position, RegExp::CallOrigin call_origin, uint32_t backtrack_limit); private: - static Result Match(Isolate* isolate, Tagged regexp, - Tagged subject_string, int* output_registers, - int output_register_count, int start_position, - RegExp::CallOrigin call_origin); + static int Match(Isolate* isolate, Tagged regexp_data, + Tagged subject_string, int* output_registers, + int output_register_count, int start_position, + RegExp::CallOrigin call_origin); }; } // namespace internal diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.cc index 6444ca3c605..94fa7231e11 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.cc @@ -344,12 +344,16 @@ bool RegExpMacroAssemblerTracer::CheckCharacterInRangeArray( bool RegExpMacroAssemblerTracer::CheckCharacterNotInRangeArray( const ZoneList* ranges, Label* on_not_in_range) { - PrintF( - " CheckCharacterNotInRangeArray(\n" - " label[%08x]);\n", - LabelToInt(on_not_in_range)); - PrintRangeArray(ranges); - return assembler_->CheckCharacterNotInRangeArray(ranges, on_not_in_range); + bool emitted = + assembler_->CheckCharacterNotInRangeArray(ranges, on_not_in_range); + if (emitted) { + PrintF( + " CheckCharacterNotInRangeArray(\n" + " label[%08x]);\n", + LabelToInt(on_not_in_range)); + PrintRangeArray(ranges); + } + return emitted; } void RegExpMacroAssemblerTracer::CheckBitInTable( @@ -365,6 +369,39 @@ void RegExpMacroAssemblerTracer::CheckBitInTable( assembler_->CheckBitInTable(table, on_bit_set); } +void RegExpMacroAssemblerTracer::SkipUntilBitInTable( + int cp_offset, Handle table, Handle nibble_table, + int advance_by) { + PrintF("SkipUntilBitInTable(cp_offset=%d, advance_by=%d\n ", cp_offset, + advance_by); + for (int i = 0; i < kTableSize; i++) { + PrintF("%c", table->get(i) != 0 ? 'X' : '.'); + if (i % 32 == 31 && i != kTableMask) { + PrintF("\n "); + } + } + static_assert(kTableSize == 128); + static constexpr int kRows = 16; + static_assert(kRows * kBitsPerByte == kTableSize); + if (!nibble_table.is_null()) { + PrintF("\n"); + PrintF(" +----------------\n"); + PrintF(" |"); + for (int j = 0; j < kBitsPerByte; j++) { + PrintF(" %x", j); + } + PrintF("\n--+----------------"); + for (int i = 0; i < kRows; i++) { + int r = nibble_table->get(i); + PrintF("\n%x |", i); + for (int j = 0; j < kBitsPerByte; j++) { + PrintF(" %c", (r & (1 << j)) == 0 ? '.' : 'X'); + } + } + } + PrintF(");\n"); + assembler_->SkipUntilBitInTable(cp_offset, table, nibble_table, advance_by); +} void RegExpMacroAssemblerTracer::CheckNotBackReference(int start_reg, bool read_backward, @@ -428,10 +465,13 @@ RegExpMacroAssembler::IrregexpImplementation return assembler_->Implementation(); } - -Handle RegExpMacroAssemblerTracer::GetCode(Handle source) { - PrintF(" GetCode(%s);\n", source->ToCString().get()); - return assembler_->GetCode(source); +DirectHandle RegExpMacroAssemblerTracer::GetCode( + DirectHandle source, RegExpFlags flags) { + DirectHandle flags_str = + JSRegExp::StringFromFlags(isolate(), JSRegExp::AsJSRegExpFlags(flags)); + PrintF(" GetCode('%s', '%s');\n", source->ToCString().get(), + flags_str->ToCString().get()); + return assembler_->GetCode(source, flags); } } // namespace internal diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.h index 3fadf1a8937..249e209e801 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler-tracer.h @@ -16,7 +16,9 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler { RegExpMacroAssemblerTracer(Isolate* isolate, RegExpMacroAssembler* assembler); ~RegExpMacroAssemblerTracer() override; void AbortedCodeGeneration() override; - int stack_limit_slack() override { return assembler_->stack_limit_slack(); } + int stack_limit_slack_slot_count() override { + return assembler_->stack_limit_slack_slot_count(); + } bool CanReadUnaligned() const override { return assembler_->CanReadUnaligned(); } @@ -52,11 +54,18 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler { bool CheckCharacterNotInRangeArray(const ZoneList* ranges, Label* on_not_in_range) override; void CheckBitInTable(Handle table, Label* on_bit_set) override; + bool SkipUntilBitInTableUseSimd(int advance_by) override { + return assembler_->SkipUntilBitInTableUseSimd(advance_by); + } + void SkipUntilBitInTable(int cp_offset, Handle table, + Handle nibble_table, + int advance_by) override; void CheckPosition(int cp_offset, Label* on_outside_input) override; bool CheckSpecialClassRanges(StandardCharacterSet type, Label* on_no_match) override; void Fail() override; - Handle GetCode(Handle source) override; + DirectHandle GetCode(DirectHandle source, + RegExpFlags flags) override; void GoTo(Label* label) override; void IfRegisterGE(int reg, int comparand, Label* if_ge) override; void IfRegisterLT(int reg, int comparand, Label* if_lt) override; diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.cc index b99c08424e1..1a250f38dfb 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.cc @@ -124,7 +124,7 @@ int RangeArrayLengthFor(const ZoneList* ranges) { } bool Equals(const ZoneList* lhs, - const Handle& rhs) { + const DirectHandle& rhs) { const int rhs_length = rhs->length(); if (rhs_length != RangeArrayLengthFor(lhs)) return false; for (int i = 0; i < lhs->length(); i++) { @@ -175,15 +175,14 @@ Handle NativeRegExpMacroAssembler::GetOrAddRangeArray( // static uint32_t RegExpMacroAssembler::IsCharacterInRangeArray(uint32_t current_char, - Address raw_byte_array, - Isolate* isolate) { + Address raw_byte_array) { // Use uint32_t to avoid complexity around bool return types (which may be // optimized to use only the least significant byte). static constexpr uint32_t kTrue = 1; static constexpr uint32_t kFalse = 0; Tagged ranges = - FixedUInt16Array::cast(Tagged(raw_byte_array)); + Cast(Tagged(raw_byte_array)); DCHECK_GE(ranges->length(), 1); // Shortcut for fully out of range chars. @@ -311,10 +310,10 @@ int NativeRegExpMacroAssembler::CheckStackGuardState( // Prepare for possible GC. HandleScope handles(isolate); - Handle code_handle(re_code, isolate); - Handle subject_handle(String::cast(Tagged(*subject)), - isolate); - bool is_one_byte = String::IsOneByteRepresentationUnderneath(*subject_handle); + DirectHandle code_handle(re_code, isolate); + DirectHandle subject_handle(Cast(Tagged(*subject)), + isolate); + bool is_one_byte = subject_handle->IsOneByteRepresentation(); int return_value = 0; { @@ -344,8 +343,7 @@ int NativeRegExpMacroAssembler::CheckStackGuardState( // If we continue, we need to update the subject string addresses. if (return_value == 0) { // String encoding might have changed. - if (String::IsOneByteRepresentationUnderneath(*subject_handle) != - is_one_byte) { + if (subject_handle->IsOneByteRepresentation() != is_one_byte) { // If we changed between an LATIN1 and an UC16 string, the specialized // code cannot be used, and we need to restart regexp matching from // scratch (including, potentially, compiling a new version of the code). @@ -361,8 +359,8 @@ int NativeRegExpMacroAssembler::CheckStackGuardState( } // Returns a {Result} sentinel, or the number of successful matches. -int NativeRegExpMacroAssembler::Match(Handle regexp, - Handle subject, +int NativeRegExpMacroAssembler::Match(DirectHandle regexp_data, + DirectHandle subject, int* offsets_vector, int offsets_vector_length, int previous_index, Isolate* isolate) { @@ -383,15 +381,15 @@ int NativeRegExpMacroAssembler::Match(Handle regexp, // The string has been flattened, so if it is a cons string it contains the // full string in the first part. if (StringShape(subject_ptr).IsCons()) { - DCHECK_EQ(0, ConsString::cast(subject_ptr)->second()->length()); - subject_ptr = ConsString::cast(subject_ptr)->first(); + DCHECK_EQ(0, Cast(subject_ptr)->second()->length()); + subject_ptr = Cast(subject_ptr)->first(); } else if (StringShape(subject_ptr).IsSliced()) { - Tagged slice = SlicedString::cast(subject_ptr); + Tagged slice = Cast(subject_ptr); subject_ptr = slice->parent(); slice_offset = slice->offset(); } if (StringShape(subject_ptr).IsThin()) { - subject_ptr = ThinString::cast(subject_ptr)->actual(); + subject_ptr = Cast(subject_ptr)->actual(); } // Ensure that an underlying string has the same representation. bool is_one_byte = subject_ptr->IsOneByteRepresentation(); @@ -405,7 +403,7 @@ int NativeRegExpMacroAssembler::Match(Handle regexp, int byte_length = char_length << char_size_shift; const uint8_t* input_end = input_start + byte_length; return Execute(*subject, start_offset, input_start, input_end, offsets_vector, - offsets_vector_length, isolate, *regexp); + offsets_vector_length, isolate, *regexp_data); } // static @@ -413,34 +411,33 @@ int NativeRegExpMacroAssembler::ExecuteForTesting( Tagged input, int start_offset, const uint8_t* input_start, const uint8_t* input_end, int* output, int output_size, Isolate* isolate, Tagged regexp) { + Tagged data = regexp->data(isolate); + SBXCHECK(Is(data)); return Execute(input, start_offset, input_start, input_end, output, - output_size, isolate, regexp); + output_size, isolate, Cast(data)); } // Returns a {Result} sentinel, or the number of successful matches. -// TODO(pthier): The JSRegExp object is passed to native irregexp code to match -// the signature of the interpreter. We should get rid of JS objects passed to -// internal methods. int NativeRegExpMacroAssembler::Execute( Tagged input, // This needs to be the unpacked (sliced, cons) string. int start_offset, const uint8_t* input_start, const uint8_t* input_end, - int* output, int output_size, Isolate* isolate, Tagged regexp) { - RegExpStackScope stack_scope(isolate); - - bool is_one_byte = String::IsOneByteRepresentationUnderneath(input); - Tagged code = Code::cast(regexp->code(isolate, is_one_byte)); + int* output, int output_size, Isolate* isolate, + Tagged regexp_data) { + bool is_one_byte = input->IsOneByteRepresentation(); + Tagged code = regexp_data->code(isolate, is_one_byte); RegExp::CallOrigin call_origin = RegExp::CallOrigin::kFromRuntime; using RegexpMatcherSig = // NOLINTNEXTLINE(readability/casting) int(Address input_string, int start_offset, const uint8_t* input_start, const uint8_t* input_end, int* output, int output_size, - int call_origin, Isolate* isolate, Address regexp); + int call_origin, Isolate* isolate, Address regexp_data); auto fn = GeneratedCode::FromCode(isolate, code); - int result = fn.Call(input.ptr(), start_offset, input_start, input_end, - output, output_size, call_origin, isolate, regexp.ptr()); + int result = + fn.Call(input.ptr(), start_offset, input_start, input_end, output, + output_size, call_origin, isolate, regexp_data.ptr()); DCHECK_GE(result, SMALLEST_REGEXP_RESULT); if (result == EXCEPTION && !isolate->has_exception()) { diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.h index 6863adbaffc..d299b871b56 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-macro-assembler.h @@ -42,7 +42,8 @@ class RegExpMacroAssembler { RegExpMacroAssembler(Isolate* isolate, Zone* zone); virtual ~RegExpMacroAssembler() = default; - virtual Handle GetCode(Handle source) = 0; + virtual DirectHandle GetCode(DirectHandle source, + RegExpFlags flags) = 0; // This function is called when code generation is aborted, so that // the assembler could clean up internal data structures. @@ -50,7 +51,7 @@ class RegExpMacroAssembler { // The maximal number of pushes between stack checks. Users must supply // kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck) // at least once for every stack_limit() pushes that are executed. - virtual int stack_limit_slack() = 0; + virtual int stack_limit_slack_slot_count() = 0; virtual bool CanReadUnaligned() const = 0; virtual void AdvanceCurrentPosition(int by) = 0; // Signed cp change. @@ -106,6 +107,11 @@ class RegExpMacroAssembler { // array, and if the found byte is non-zero, we jump to the on_bit_set label. virtual void CheckBitInTable(Handle table, Label* on_bit_set) = 0; + virtual void SkipUntilBitInTable(int cp_offset, Handle table, + Handle nibble_table, + int advance_by) = 0; + virtual bool SkipUntilBitInTableUseSimd(int advance_by) { return false; } + // Checks whether the given offset from the current position is before // the end of the string. May overwrite the current character. virtual void CheckPosition(int cp_offset, Label* on_outside_input); @@ -214,8 +220,7 @@ class RegExpMacroAssembler { // // Called from generated code. static uint32_t IsCharacterInRangeArray(uint32_t current_char, - Address raw_byte_array, - Isolate* isolate); + Address raw_byte_array); // Controls the generation of large inlined constants in the code. void set_slow_safe(bool ssc) { slow_safe_compiler_ = ssc; } @@ -297,9 +302,10 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler { ~NativeRegExpMacroAssembler() override = default; // Returns a {Result} sentinel, or the number of successful matches. - static int Match(Handle regexp, Handle subject, - int* offsets_vector, int offsets_vector_length, - int previous_index, Isolate* isolate); + static int Match(DirectHandle regexp_data, + DirectHandle subject, int* offsets_vector, + int offsets_vector_length, int previous_index, + Isolate* isolate); V8_EXPORT_PRIVATE static int ExecuteForTesting( Tagged input, int start_offset, const uint8_t* input_start, @@ -349,9 +355,10 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler { static int Execute(Tagged input, int start_offset, const uint8_t* input_start, const uint8_t* input_end, int* output, int output_size, Isolate* isolate, - Tagged regexp); + Tagged regexp_data); - ZoneUnorderedMap> range_array_cache_; + ZoneUnorderedMap> + range_array_cache_; }; } // namespace internal diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-nodes.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-nodes.h index e6fc2066215..8ae7b993e2c 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-nodes.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-nodes.h @@ -16,9 +16,9 @@ class GreedyLoopState; class NodeVisitor; class QuickCheckDetails; class RegExpCompiler; +class SeqRegExpNode; class Trace; struct PreloadState; -class ChoiceNode; #define FOR_EACH_NODE_TYPE(VISIT) \ VISIT(End) \ @@ -30,6 +30,10 @@ class ChoiceNode; VISIT(Assertion) \ VISIT(Text) +#define FORWARD_DECLARE(type) class type##Node; +FOR_EACH_NODE_TYPE(FORWARD_DECLARE) +#undef FORWARD_DECLARE + struct NodeInfo final { NodeInfo() : being_analyzed(false), @@ -142,7 +146,7 @@ class RegExpNode : public ZoneObject { // not at the start of the input. In this case anchored branches will always // fail and can be ignored when determining how many characters are consumed // on success. If this node has not been analyzed yet, EatsAtLeast returns 0. - int EatsAtLeast(bool not_at_start); + uint32_t EatsAtLeast(bool not_at_start); // Returns how many characters this node must consume in order to succeed, // given that this is a LoopChoiceNode whose counter register is in a // newly-initialized state at the current position in the generated code. For @@ -203,7 +207,7 @@ class RegExpNode : public ZoneObject { // If we know that the input is one-byte then there are some nodes that can // never match. This method returns a node that can be substituted for // itself, or nullptr if the node can never match. - virtual RegExpNode* FilterOneByte(int depth, RegExpFlags flags) { + virtual RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) { return this; } // Helper for FilterOneByte. @@ -255,6 +259,13 @@ class RegExpNode : public ZoneObject { return bm_info_[not_at_start ? 1 : 0]; } +#define DECLARE_CAST(type) \ + virtual type##Node* As##type##Node() { return nullptr; } + FOR_EACH_NODE_TYPE(DECLARE_CAST) +#undef DECLARE_CAST + + virtual SeqRegExpNode* AsSeqRegExpNode() { return nullptr; } + Zone* zone() const { return zone_; } protected: @@ -294,15 +305,16 @@ class SeqRegExpNode : public RegExpNode { : RegExpNode(on_success->zone()), on_success_(on_success) {} RegExpNode* on_success() { return on_success_; } void set_on_success(RegExpNode* node) { on_success_ = node; } - RegExpNode* FilterOneByte(int depth, RegExpFlags flags) override; + RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override; void FillInBMInfo(Isolate* isolate, int offset, int budget, BoyerMooreLookahead* bm, bool not_at_start) override { on_success_->FillInBMInfo(isolate, offset, budget - 1, bm, not_at_start); if (offset == 0) set_bm_info(not_at_start, bm); } + SeqRegExpNode* AsSeqRegExpNode() override { return this; } protected: - RegExpNode* FilterSuccessor(int depth, RegExpFlags flags); + RegExpNode* FilterSuccessor(int depth, RegExpCompiler* compiler); private: RegExpNode* on_success_; @@ -328,8 +340,8 @@ class ActionNode : public SeqRegExpNode { RegExpNode* on_success); static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success); static ActionNode* BeginPositiveSubmatch(int stack_pointer_reg, - int position_reg, - RegExpNode* on_success); + int position_reg, RegExpNode* body, + ActionNode* success_node); static ActionNode* BeginNegativeSubmatch(int stack_pointer_reg, int position_reg, RegExpNode* on_success); @@ -343,6 +355,7 @@ class ActionNode : public SeqRegExpNode { int repetition_limit, RegExpNode* on_success); static ActionNode* ModifyFlags(RegExpFlags flags, RegExpNode* on_success); + ActionNode* AsActionNode() override { return this; } void Accept(NodeVisitor* visitor) override; void Emit(RegExpCompiler* compiler, Trace* trace) override; void GetQuickCheckDetails(QuickCheckDetails* details, @@ -350,16 +363,24 @@ class ActionNode : public SeqRegExpNode { bool not_at_start) override; void FillInBMInfo(Isolate* isolate, int offset, int budget, BoyerMooreLookahead* bm, bool not_at_start) override; - ActionType action_type() { return action_type_; } + ActionType action_type() const { return action_type_; } // TODO(erikcorry): We should allow some action nodes in greedy loops. int GreedyLoopTextLength() override { return kNodeIsTooComplexForGreedyLoops; } - RegExpFlags flags() { + RegExpFlags flags() const { DCHECK_EQ(action_type(), MODIFY_FLAGS); // MONGODB MODIFICATION: Fix -Wc++11-narrowing error with explicit cast return RegExpFlags{static_cast(data_.u_modify_flags.flags)}; } + ActionNode* success_node() const { + DCHECK_EQ(action_type(), BEGIN_POSITIVE_SUBMATCH); + return data_.u_submatch.success_node; + } + + protected: + ActionNode(ActionType action_type, RegExpNode* on_success) + : SeqRegExpNode(on_success), action_type_(action_type) {} private: union { @@ -379,6 +400,7 @@ class ActionNode : public SeqRegExpNode { int current_position_register; int clear_register_count; int clear_register_from; + ActionNode* success_node; // Only used for positive submatch. } u_submatch; struct { int start_register; @@ -393,8 +415,6 @@ class ActionNode : public SeqRegExpNode { int flags; } u_modify_flags; } data_; - ActionNode(ActionType action_type, RegExpNode* on_success) - : SeqRegExpNode(on_success), action_type_(action_type) {} ActionType action_type_; friend class DotPrinterImpl; @@ -427,6 +447,7 @@ class TextNode : public SeqRegExpNode { CharacterRange trail, bool read_backward, RegExpNode* on_success); + TextNode* AsTextNode() override { return this; } void Accept(NodeVisitor* visitor) override; void Emit(RegExpCompiler* compiler, Trace* trace) override; void GetQuickCheckDetails(QuickCheckDetails* details, @@ -442,20 +463,17 @@ class TextNode : public SeqRegExpNode { void FillInBMInfo(Isolate* isolate, int offset, int budget, BoyerMooreLookahead* bm, bool not_at_start) override; void CalculateOffsets(); - RegExpNode* FilterOneByte(int depth, RegExpFlags flags) override; + RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override; int Length(); private: enum TextEmitPassType { - NON_LATIN1_MATCH, // Check for characters that can't match. + NON_LATIN1_MATCH, // Check for characters that can never match. SIMPLE_CHARACTER_MATCH, // Case-dependent single character check. NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs. CASE_CHARACTER_MATCH, // Case-independent single character check. CHARACTER_CLASS_MATCH // Character class. }; - static bool SkipPass(TextEmitPassType pass, bool ignore_case); - static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH; - static const int kLastPass = CHARACTER_CLASS_MATCH; void TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass, bool preloaded, Trace* trace, bool first_element_checked, int* checked_up_to); @@ -487,6 +505,7 @@ class AssertionNode : public SeqRegExpNode { static AssertionNode* AfterNewline(RegExpNode* on_success) { return on_success->zone()->New(AFTER_NEWLINE, on_success); } + AssertionNode* AsAssertionNode() override { return this; } void Accept(NodeVisitor* visitor) override; void Emit(RegExpCompiler* compiler, Trace* trace) override; void GetQuickCheckDetails(QuickCheckDetails* details, @@ -516,6 +535,7 @@ class BackReferenceNode : public SeqRegExpNode { start_reg_(start_reg), end_reg_(end_reg), read_backward_(read_backward) {} + BackReferenceNode* AsBackReferenceNode() override { return this; } void Accept(NodeVisitor* visitor) override; int start_register() { return start_reg_; } int end_register() { return end_reg_; } @@ -539,6 +559,7 @@ class EndNode : public RegExpNode { public: enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; EndNode(Action action, Zone* zone) : RegExpNode(zone), action_(action) {} + EndNode* AsEndNode() override { return this; } void Accept(NodeVisitor* visitor) override; void Emit(RegExpCompiler* compiler, Trace* trace) override; void GetQuickCheckDetails(QuickCheckDetails* details, @@ -614,6 +635,7 @@ class ChoiceNode : public RegExpNode { zone->New>(expected_size, zone)), not_at_start_(false), being_calculated_(false) {} + ChoiceNode* AsChoiceNode() override { return this; } void Accept(NodeVisitor* visitor) override; void AddAlternative(GuardedAlternative node) { alternatives()->Add(node, zone()); @@ -633,7 +655,7 @@ class ChoiceNode : public RegExpNode { virtual bool try_to_emit_quick_check_for_alternative(bool is_first) { return true; } - RegExpNode* FilterOneByte(int depth, RegExpFlags flags) override; + RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override; virtual bool read_backward() { return false; } protected: @@ -704,8 +726,11 @@ class NegativeLookaroundChoiceNode : public ChoiceNode { bool try_to_emit_quick_check_for_alternative(bool is_first) override { return !is_first; } + NegativeLookaroundChoiceNode* AsNegativeLookaroundChoiceNode() override { + return this; + } void Accept(NodeVisitor* visitor) override; - RegExpNode* FilterOneByte(int depth, RegExpFlags flags) override; + RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override; }; class LoopChoiceNode : public ChoiceNode { @@ -737,8 +762,9 @@ class LoopChoiceNode : public ChoiceNode { bool body_can_be_zero_length() { return body_can_be_zero_length_; } int min_loop_iterations() const { return min_loop_iterations_; } bool read_backward() override { return read_backward_; } + LoopChoiceNode* AsLoopChoiceNode() override { return this; } void Accept(NodeVisitor* visitor) override; - RegExpNode* FilterOneByte(int depth, RegExpFlags flags) override; + RegExpNode* FilterOneByte(int depth, RegExpCompiler* compiler) override; private: // AddAlternative is made private for loop nodes because alternatives diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.cc index f925baafbc1..b71c4b201fb 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.cc @@ -148,14 +148,10 @@ void RegExpTextBuilder::FlushText() { void RegExpTextBuilder::AddCharacter(base::uc16 c) { FlushPendingSurrogate(); - if (NeedsDesugaringForIgnoreCase(c)) { - AddClassRangesForDesugaring(c); - } else { - if (characters_ == nullptr) { - characters_ = zone()->New>(4, zone()); - } - characters_->Add(c, zone()); + if (characters_ == nullptr) { + characters_ = zone()->New>(4, zone()); } + characters_->Add(c, zone()); } void RegExpTextBuilder::AddUnicodeCharacter(base::uc32 c) { @@ -234,6 +230,9 @@ bool RegExpTextBuilder::NeedsDesugaringForUnicode(RegExpClassRanges* cc) { return false; } +// We only use this for characters made of surrogate pairs. All other +// characters outside of character classes are made case independent in the +// code generation. bool RegExpTextBuilder::NeedsDesugaringForIgnoreCase(base::uc32 c) { #ifdef V8_INTL_SUPPORT if (IsUnicodeMode() && ignore_case()) { @@ -300,7 +299,7 @@ class RegExpBuilder { void AddTerm(RegExpTree* tree); void AddAssertion(RegExpTree* tree); void NewAlternative(); // '|' - bool AddQuantifierToAtom(int min, int max, + bool AddQuantifierToAtom(int min, int max, int index, RegExpQuantifier::QuantifierType type); void FlushText(); RegExpTree* ToRegExp(); @@ -530,7 +529,13 @@ class RegExpParserImpl final { bool contains_anchor() const { return contains_anchor_; } void set_contains_anchor() { contains_anchor_ = true; } int captures_started() const { return captures_started_; } - int position() const { return next_pos_ - 1; } + int position() const { + const bool current_is_surrogate = + current() != kEndMarker && + current() > unibrow::Utf16::kMaxNonSurrogateCharCode; + const int rewind_bytes = current_is_surrogate ? 2 : 1; + return next_pos_ - rewind_bytes; + } bool failed() const { return failed_; } RegExpFlags flags() const { return flags_; } bool IsUnicodeMode() const { @@ -624,7 +629,6 @@ class RegExpParserImpl final { ZoneMap*, RegExpCaptureNameLess>* named_captures_; ZoneList* named_back_references_; - ZoneList* temp_ranges_; const CharT* const input_; const int input_length_; base::uc32 current_; @@ -633,6 +637,7 @@ class RegExpParserImpl final { int next_pos_; int captures_started_; int capture_count_; // Only valid after we have scanned for captures. + int quantifier_count_; int lookaround_count_; // Only valid after we have scanned for lookbehinds. bool has_more_; bool simple_; @@ -660,6 +665,7 @@ RegExpParserImpl::RegExpParserImpl( next_pos_(0), captures_started_(0), capture_count_(0), + quantifier_count_(0), lookaround_count_(0), has_more_(true), simple_(false), @@ -1267,9 +1273,11 @@ RegExpTree* RegExpParserImpl::ParseDisjunction() { quantifier_type = RegExpQuantifier::POSSESSIVE; Advance(); } - if (!builder->AddQuantifierToAtom(min, max, quantifier_type)) { + if (!builder->AddQuantifierToAtom(min, max, quantifier_count_, + quantifier_type)) { return ReportError(RegExpError::kInvalidQuantifier); } + ++quantifier_count_; } } @@ -1287,7 +1295,8 @@ RegExpParserState* RegExpParserImpl::ParseOpenParenthesis( Advance(); if (current() == '?') { do { - switch (Next()) { + base::uc32 next = Next(); + switch (next) { case '-': if (!v8_flags.js_regexp_modifiers) { ReportError(RegExpError::kInvalidGroup); @@ -1310,7 +1319,7 @@ RegExpParserState* RegExpParserImpl::ParseOpenParenthesis( } Advance(); parsing_modifiers = true; - RegExpFlag flag = TryRegExpFlagFromChar(current()).value(); + RegExpFlag flag = TryRegExpFlagFromChar(next).value(); if ((modifiers & flag) != 0) { ReportError(RegExpError::kRepeatedFlag); return nullptr; @@ -1724,7 +1733,7 @@ RegExpCapture* RegExpParserImpl::GetCapture(int index) { // zero-based. const int known_captures = is_scanned_for_captures_ ? capture_count_ : captures_started_; - DCHECK(index <= known_captures); + SBXCHECK(index >= 1 && index <= known_captures); if (captures_ == nullptr) { captures_ = zone()->template New>(known_captures, zone()); @@ -2372,7 +2381,7 @@ base::uc32 RegExpParserImpl::ParseCharacterEscape( if (IsUnicodeMode()) { // With /u or /v, decimal escape is not interpreted as octal character // code. - ReportError(RegExpError::kInvalidClassEscape); + ReportError(RegExpError::kInvalidDecimalEscape); return 0; } return ParseOctalLiteral(); @@ -3044,7 +3053,8 @@ RegExpTree* RegExpParserImpl::ParseCharacterClass( if (Next() == '-') { if (operand == nullptr) { if (operand_type == ClassSetOperandType::kClassSetCharacter) { - ranges->Add(CharacterRange::Singleton(character), zone()); + AddMaybeSimpleCaseFoldedRange( + ranges, CharacterRange::Singleton(character)); } operand = zone()->template New(ranges, strings); @@ -3058,7 +3068,8 @@ RegExpTree* RegExpParserImpl::ParseCharacterClass( if (Next() == '&') { if (operand == nullptr) { if (operand_type == ClassSetOperandType::kClassSetCharacter) { - ranges->Add(CharacterRange::Singleton(character), zone()); + AddMaybeSimpleCaseFoldedRange( + ranges, CharacterRange::Singleton(character)); } operand = zone()->template New(ranges, strings); @@ -3191,7 +3202,8 @@ RegExpTree* RegExpBuilder::ToRegExp() { } bool RegExpBuilder::AddQuantifierToAtom( - int min, int max, RegExpQuantifier::QuantifierType quantifier_type) { + int min, int max, int index, + RegExpQuantifier::QuantifierType quantifier_type) { if (pending_empty_) { pending_empty_ = false; return true; @@ -3223,7 +3235,7 @@ bool RegExpBuilder::AddQuantifierToAtom( UNREACHABLE(); } terms_.emplace_back( - zone()->New(min, max, quantifier_type, atom)); + zone()->New(min, max, quantifier_type, index, atom)); return true; } @@ -3234,7 +3246,7 @@ template class RegExpParserImpl; // static bool RegExpParser::ParseRegExpFromHeapString(Isolate* isolate, Zone* zone, - Handle input, + DirectHandle input, RegExpFlags flags, RegExpCompileData* result) { DisallowGarbageCollection no_gc; diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.h index 1e45d975323..f01c5bc6c8f 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-parser.h @@ -18,7 +18,8 @@ struct RegExpCompileData; class V8_EXPORT_PRIVATE RegExpParser : public AllStatic { public: static bool ParseRegExpFromHeapString(Isolate* isolate, Zone* zone, - Handle input, RegExpFlags flags, + DirectHandle input, + RegExpFlags flags, RegExpCompileData* result); template diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.cc b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.cc index 892ba3a069f..71fef6a65b0 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.cc +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.cc @@ -52,7 +52,7 @@ void RegExpStack::ThreadLocal::ResetToStaticStack(RegExpStack* regexp_stack) { memory_size_ = kStaticStackSize; stack_pointer_ = memory_top_; limit_ = reinterpret_cast
(regexp_stack->static_stack_) + - kStackLimitSlack * kSystemPointerSize; + kStackLimitSlackSize; owns_memory_ = false; } @@ -84,8 +84,8 @@ Address RegExpStack::EnsureCapacity(size_t size) { thread_local_.memory_top_ = new_memory + size; thread_local_.memory_size_ = size; thread_local_.stack_pointer_ = thread_local_.memory_top_ + delta; - thread_local_.limit_ = reinterpret_cast
(new_memory) + - kStackLimitSlack * kSystemPointerSize; + thread_local_.limit_ = + reinterpret_cast
(new_memory) + kStackLimitSlackSize; thread_local_.owns_memory_ = true; } return reinterpret_cast
(thread_local_.memory_top_); diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.h index fc8827116bd..ac70a602acf 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp-stack.h @@ -38,16 +38,27 @@ class RegExpStack final { RegExpStack(const RegExpStack&) = delete; RegExpStack& operator=(const RegExpStack&) = delete; +#if defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_S390X) + static constexpr int kSlotSize = kSystemPointerSize; +#else + static constexpr int kSlotSize = kInt32Size; +#endif // Number of allocated locations on the stack below the limit. No sequence of // pushes must be longer than this without doing a stack-limit check. - static constexpr int kStackLimitSlack = 32; + static constexpr int kStackLimitSlackSlotCount = 32; + static constexpr int kStackLimitSlackSize = + kStackLimitSlackSlotCount * kSlotSize; - Address memory_top() const { + Address begin() const { + return reinterpret_cast
(thread_local_.memory_); + } + Address end() const { DCHECK_NE(0, thread_local_.memory_size_); DCHECK_EQ(thread_local_.memory_top_, thread_local_.memory_ + thread_local_.memory_size_); return reinterpret_cast
(thread_local_.memory_top_); } + Address memory_top() const { return end(); } Address stack_pointer() const { return reinterpret_cast
(thread_local_.stack_pointer_); @@ -82,20 +93,21 @@ class RegExpStack final { static const Address kMemoryTop = static_cast
(static_cast(-1)); - // Minimal size of dynamically-allocated stack area. - static constexpr size_t kMinimumDynamicStackSize = 1 * KB; - // In addition to dynamically-allocated, variable-sized stacks, we also have // a statically allocated and sized area that is used whenever no dynamic // stack is allocated. This guarantees that a stack is always available and // we can skip availability-checks later on. - // It's double the slack size to ensure that we have a bit of breathing room - // before NativeRegExpMacroAssembler::GrowStack must be called. - static constexpr size_t kStaticStackSize = - 2 * kStackLimitSlack * kSystemPointerSize; + static constexpr size_t kStaticStackSize = 1 * KB; + // It's at least double the slack size to ensure that we have a bit of + // breathing room before NativeRegExpMacroAssembler::GrowStack must be + // called. + static_assert(kStaticStackSize >= 2 * kStackLimitSlackSize); + static_assert(kStaticStackSize <= kMaximumStackSize); uint8_t static_stack_[kStaticStackSize] = {0}; - static_assert(kStaticStackSize <= kMaximumStackSize); + // Minimal size of dynamically-allocated stack area. + static constexpr size_t kMinimumDynamicStackSize = 2 * KB; + static_assert(kMinimumDynamicStackSize == 2 * kStaticStackSize); // Structure holding the allocated memory, size and limit. Thread switching // archives and restores this struct. diff --git a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp.h b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp.h index 5dc9070ed94..262278f8a97 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp.h +++ b/src/third_party/mozjs/extract/js/src/irregexp/imported/regexp.h @@ -13,6 +13,9 @@ namespace internal { class JSRegExp; class RegExpCapture; +class RegExpData; +class IrRegExpData; +class AtomRegExpData; class RegExpMatchInfo; class RegExpNode; class RegExpTree; @@ -30,7 +33,7 @@ struct RegExpCompileData { // Either the generated code as produced by the compiler or a trampoline // to the interpreter. - Handle code; + DirectHandle code; // True, iff the pattern is a 'simple' atom with zero captures. In other // words, the pattern consists of a string with no metacharacters and special @@ -82,44 +85,46 @@ class RegExp final : public AllStatic { // generic data and choice of implementation - as well as what // the implementation wants to store in the data field. // Returns false if compilation fails. - V8_WARN_UNUSED_RESULT static MaybeHandle Compile( - Isolate* isolate, Handle re, Handle pattern, + V8_WARN_UNUSED_RESULT static MaybeDirectHandle Compile( + Isolate* isolate, DirectHandle re, DirectHandle pattern, RegExpFlags flags, uint32_t backtrack_limit); // Ensures that a regexp is fully compiled and ready to be executed on a // subject string. Returns true on success. Throw and return false on // failure. - V8_WARN_UNUSED_RESULT static bool EnsureFullyCompiled(Isolate* isolate, - Handle re, - Handle subject); + V8_WARN_UNUSED_RESULT static bool EnsureFullyCompiled( + Isolate* isolate, DirectHandle re_data, + DirectHandle subject); enum CallOrigin : int { kFromRuntime = 0, kFromJs = 1, }; - enum class ExecQuirks { - kNone, - // Used to work around an issue in the RegExpPrototypeSplit fast path, - // which diverges from the spec by not creating a sticky copy of the RegExp - // instance and calling `exec` in a loop. If called in this context, we - // must not update the last_match_info on a successful match at the subject - // string end. See crbug.com/1075514 for more information. - kTreatMatchAtEndAsFailure, - }; - // See ECMA-262 section 15.10.6.2. // This function calls the garbage collector if necessary. - V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle Exec( - Isolate* isolate, Handle regexp, Handle subject, - int index, Handle last_match_info, - ExecQuirks exec_quirks = ExecQuirks::kNone); + V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static std::optional Exec( + Isolate* isolate, DirectHandle regexp, + DirectHandle subject, int index, int32_t* result_offsets_vector, + uint32_t result_offsets_vector_length); + // As above, but passes the result through the old-style RegExpMatchInfo|Null + // interface. At most one match is returned. + V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeDirectHandle + Exec_Single(Isolate* isolate, DirectHandle regexp, + DirectHandle subject, int index, + DirectHandle last_match_info); - V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle - ExperimentalOneshotExec(Isolate* isolate, Handle regexp, - Handle subject, int index, - Handle last_match_info, - ExecQuirks exec_quirks = ExecQuirks::kNone); + V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static std::optional + ExperimentalOneshotExec(Isolate* isolate, DirectHandle regexp, + DirectHandle subject, int index, + int32_t* result_offsets_vector, + uint32_t result_offsets_vector_length); + + // Called directly from generated code through ExternalReference. + V8_EXPORT_PRIVATE static intptr_t AtomExecRaw( + Isolate* isolate, Address /* AtomRegExpData */ data_address, + Address /* String */ subject_address, int32_t index, + int32_t* result_offsets_vector, int32_t result_offsets_vector_length); // Integral return values used throughout regexp code layers. static constexpr int kInternalRegExpFailure = 0; @@ -139,13 +144,14 @@ class RegExp final : public AllStatic { // Set last match info. If match is nullptr, then setting captures is // omitted. - static Handle SetLastMatchInfo( - Isolate* isolate, Handle last_match_info, - Handle subject, int capture_count, int32_t* match); + static DirectHandle SetLastMatchInfo( + Isolate* isolate, DirectHandle last_match_info, + DirectHandle subject, int capture_count, int32_t* match); V8_EXPORT_PRIVATE static bool CompileForTesting( Isolate* isolate, Zone* zone, RegExpCompileData* input, RegExpFlags flags, - Handle pattern, Handle sample_subject, bool is_one_byte); + DirectHandle pattern, DirectHandle sample_subject, + bool is_one_byte); V8_EXPORT_PRIVATE static void DotPrintForTesting(const char* label, RegExpNode* node); @@ -153,29 +159,27 @@ class RegExp final : public AllStatic { static const int kRegExpTooLargeToOptimize = 20 * KB; V8_WARN_UNUSED_RESULT - static MaybeHandle ThrowRegExpException(Isolate* isolate, - Handle re, - RegExpFlags flags, - Handle pattern, - RegExpError error); - static void ThrowRegExpException(Isolate* isolate, Handle re, + static MaybeDirectHandle ThrowRegExpException( + Isolate* isolate, RegExpFlags flags, DirectHandle pattern, + RegExpError error); + static void ThrowRegExpException(Isolate* isolate, + DirectHandle re_data, RegExpError error_text); - static bool IsUnmodifiedRegExp(Isolate* isolate, Handle regexp); + static bool IsUnmodifiedRegExp(Isolate* isolate, + DirectHandle regexp); - static Handle CreateCaptureNameMap( + static DirectHandle CreateCaptureNameMap( Isolate* isolate, ZoneVector* named_captures); }; // Uses a special global mode of irregexp-generated code to perform a global // search and return multiple results at once. As such, this is essentially an // iterator over multiple results (retrieved batch-wise in advance). -class RegExpGlobalCache final { +class RegExpGlobalExecRunner final { public: - RegExpGlobalCache(Handle regexp, Handle subject, - Isolate* isolate); - - ~RegExpGlobalCache(); + RegExpGlobalExecRunner(DirectHandle regexp_data, + DirectHandle subject, Isolate* isolate); // Fetch the next entry in the cache for global regexp match results. // This does not set the last match info. Upon failure, nullptr is @@ -183,23 +187,28 @@ class RegExpGlobalCache final { // still in available in memory when a failure happens. int32_t* FetchNext(); - int32_t* LastSuccessfulMatch(); + int32_t* LastSuccessfulMatch() const; - bool HasException() { return num_matches_ < 0; } + bool HasException() const { return num_matches_ < 0; } private: - int AdvanceZeroLength(int last_index); + int AdvanceZeroLength(int last_index) const; - int num_matches_; - int max_matches_; - int current_match_index_; - int registers_per_match_; + int max_matches() const { + DCHECK_NE(register_array_size_, 0); + return register_array_size_ / registers_per_match_; + } + + RegExpResultVectorScope result_vector_scope_; + int num_matches_ = 0; + int current_match_index_ = 0; + int registers_per_match_ = 0; // Pointer to the last set of captures. - int32_t* register_array_; - int register_array_size_; - Handle regexp_; - Handle subject_; - Isolate* isolate_; + int32_t* register_array_ = nullptr; + int register_array_size_ = 0; + DirectHandle regexp_data_; + DirectHandle subject_; + Isolate* const isolate_; }; // Caches results for specific regexp queries on the isolate. At the time of @@ -217,9 +226,11 @@ class RegExpResultsCache final : public AllStatic { ResultsCacheType type); // Attempt to add value_array to the cache specified by type. On success, // value_array is turned into a COW-array. - static void Enter(Isolate* isolate, Handle key_string, - Handle key_pattern, Handle value_array, - Handle last_match_cache, ResultsCacheType type); + static void Enter(Isolate* isolate, DirectHandle key_string, + DirectHandle key_pattern, + DirectHandle value_array, + DirectHandle last_match_cache, + ResultsCacheType type); static void Clear(Tagged cache); static constexpr int kRegExpResultsCacheSize = 0x100; @@ -232,6 +243,43 @@ class RegExpResultsCache final : public AllStatic { static constexpr int kArrayEntriesPerCacheEntry = 4; }; +// Caches results of RegExpPrototypeMatch when: +// - the subject is a SlicedString +// - the pattern is an ATOM type regexp. +// +// This is intended for usage patterns where we search ever-growing slices of +// some large string. After a cache hit, RegExpMatchGlobalAtom only needs to +// process the trailing part of the subject string that was *not* part of the +// cached SlicedString. +// +// For example: +// +// long_string.substring(0, 100).match(pattern); +// long_string.substring(0, 200).match(pattern); +// +// The second call hits the cache for the slice [0, 100[ and only has to search +// the slice [100, 200]. +class RegExpResultsCache_MatchGlobalAtom final : public AllStatic { + public: + static void TryInsert(Isolate* isolate, Tagged subject, + Tagged pattern, int number_of_matches, + int last_match_index); + static bool TryGet(Isolate* isolate, Tagged subject, + Tagged pattern, int* number_of_matches_out, + int* last_match_index_out); + static void Clear(Heap* heap); + + private: + static constexpr int kSubjectIndex = 0; // SlicedString. + static constexpr int kPatternIndex = 1; // String. + static constexpr int kNumberOfMatchesIndex = 2; // Smi. + static constexpr int kLastMatchIndexIndex = 3; // Smi. + static constexpr int kEntrySize = 4; + + public: + static constexpr int kSize = kEntrySize; // Single-entry cache. +}; + } // namespace internal } // namespace v8 diff --git a/src/third_party/mozjs/extract/js/src/irregexp/moz.yaml b/src/third_party/mozjs/extract/js/src/irregexp/moz.yaml index 5bc60ae6231..c89c87970ae 100644 --- a/src/third_party/mozjs/extract/js/src/irregexp/moz.yaml +++ b/src/third_party/mozjs/extract/js/src/irregexp/moz.yaml @@ -9,8 +9,8 @@ origin: description: A fast regular expression engine from V8 url: https://v8.dev - release: 66c0bd3237b1577e6291de56003f8fddc6b65b16 (Thu May 09 09:52:08 2024). - revision: 66c0bd3237b1577e6291de56003f8fddc6b65b16 + release: 8903af1302dde030e26de0d3fa1202f8f28b4d70 (Sat Feb 22 16:43:26 2025). + revision: 8903af1302dde030e26de0d3fa1202f8f28b4d70 license: BSD-3-Clause license-file: LICENSE.v8 diff --git a/src/third_party/mozjs/extract/js/src/jit/ABIArgGenerator.h b/src/third_party/mozjs/extract/js/src/jit/ABIArgGenerator.h index bd6193782cf..803866c88c7 100644 --- a/src/third_party/mozjs/extract/js/src/jit/ABIArgGenerator.h +++ b/src/third_party/mozjs/extract/js/src/jit/ABIArgGenerator.h @@ -32,6 +32,8 @@ static inline MIRType ToMIRType(ABIType argType) { return MIRType::Int32; case ABIType::Int64: return MIRType::Int64; + case ABIType::Void: + return MIRType::None; default: break; } diff --git a/src/third_party/mozjs/extract/js/src/jit/ABIFunctionList-inl.h b/src/third_party/mozjs/extract/js/src/jit/ABIFunctionList-inl.h index a1a992e77cd..6f3e569294b 100644 --- a/src/third_party/mozjs/extract/js/src/jit/ABIFunctionList-inl.h +++ b/src/third_party/mozjs/extract/js/src/jit/ABIFunctionList-inl.h @@ -7,7 +7,8 @@ #ifndef jit_ABIFunctionList_inl_h #define jit_ABIFunctionList_inl_h -#include "mozilla/SIMD.h" // mozilla::SIMD::memchr{,2x}{8,16} +#include "mozilla/MacroArgs.h" // MOZ_CONCAT +#include "mozilla/SIMD.h" // mozilla::SIMD::memchr{,2x}{8,16} #include "jslibmath.h" // js::NumberMod #include "jsmath.h" // js::ecmaPow, js::ecmaHypot, js::hypot3, js::hypot4, @@ -42,7 +43,6 @@ #include "js/Conversions.h" // JS::ToInt32 // JSJitGetterOp, JSJitSetterOp, JSJitMethodOp #include "js/experimental/JitInfo.h" -#include "js/Utility.h" // js_free #include "proxy/Proxy.h" // js::ProxyGetProperty @@ -98,106 +98,108 @@ namespace jit { # define ABIFUNCTION_FUZZILLI_LIST(_) #endif -#define ABIFUNCTION_LIST(_) \ - ABIFUNCTION_JS_GC_PROBES_LIST(_) \ - ABIFUNCTION_JS_CODEGEN_ARM_LIST(_) \ - ABIFUNCTION_WASM_CODEGEN_DEBUG_LIST(_) \ - _(js::ArgumentsObject::finishForIonPure) \ - _(js::ArgumentsObject::finishInlineForIonPure) \ - _(js::ArrayShiftMoveElements) \ - _(js::ArraySortData::sortArrayWithComparator) \ - _(js::ArraySortData::sortTypedArrayWithComparator) \ - _(js::ArraySortFromJit) \ - _(js::ecmaAtan2) \ - _(js::ecmaHypot) \ - _(js::ecmaPow) \ - _(js::EmulatesUndefined) \ - _(js::EmulatesUndefinedCheckFuse) \ - _(js::ExecuteRegExpAtomRaw) \ - _(js_free) \ - _(js::hypot3) \ - _(js::hypot4) \ - _(js::Interpret) \ - _(js::Int32ToStringPure) \ - _(js::irregexp::CaseInsensitiveCompareNonUnicode) \ - _(js::irregexp::CaseInsensitiveCompareUnicode) \ - _(js::irregexp::GrowBacktrackStack) \ - _(js::irregexp::IsCharacterInRangeArray) \ - _(js::jit::AllocateAndInitTypedArrayBuffer) \ - _(js::jit::AllocateBigIntNoGC) \ - _(js::jit::AllocateFatInlineString) \ - _(js::jit::AllocateDependentString) \ - _(js::jit::AssertMapObjectHash) \ - _(js::jit::AssertPropertyLookup) \ - _(js::jit::AssertSetObjectHash) \ - _(js::jit::AssertValidBigIntPtr) \ - _(js::jit::AssertValidObjectPtr) \ - _(js::jit::AssertValidStringPtr) \ - _(js::jit::AssertValidSymbolPtr) \ - _(js::jit::AssertValidValue) \ - _(js::jit::AssumeUnreachable) \ - _(js::jit::AtomicsStore64) \ - _(js::jit::AtomizeStringNoGC) \ - _(js::jit::Bailout) \ - _(js::jit::BigIntNumberEqual) \ - _(js::jit::BigIntNumberEqual) \ - _(js::jit::BigIntNumberCompare) \ - _(js::jit::NumberBigIntCompare) \ - _(js::jit::NumberBigIntCompare) \ - _(js::jit::BigIntNumberCompare) \ - _(js::jit::EqualStringsHelperPure) \ - _(js::jit::FinishBailoutToBaseline) \ - _(js::jit::FrameIsDebuggeeCheck) \ - _(js::jit::GetContextSensitiveInterpreterStub) \ - _(js::jit::GetIndexFromString) \ - _(js::jit::GetInt32FromStringPure) \ - _(js::jit::GetNativeDataPropertyPure) \ - _(js::jit::GetNativeDataPropertyPureWithCacheLookup) \ - _(js::jit::GetNativeDataPropertyByValuePure) \ - _(js::jit::GlobalHasLiveOnDebuggerStatement) \ - _(js::jit::HandleCodeCoverageAtPC) \ - _(js::jit::HandleCodeCoverageAtPrologue) \ - _(js::jit::HandleException) \ - _(js::jit::HasNativeDataPropertyPure) \ - _(js::jit::HasNativeDataPropertyPure) \ - _(js::jit::HasNativeElementPure) \ - _(js::jit::InitBaselineFrameForOsr) \ - _(js::jit::InvalidationBailout) \ - _(js::jit::InvokeFromInterpreterStub) \ - _(js::jit::LazyLinkTopActivation) \ - _(js::jit::LinearizeForCharAccessPure) \ - _(js::jit::ObjectHasGetterSetterPure) \ - _(js::jit::ObjectIsCallable) \ - _(js::jit::ObjectIsConstructor) \ - _(js::jit::PostGlobalWriteBarrier) \ - _(js::jit::PostWriteBarrier) \ - _(js::jit::PostWriteElementBarrier) \ - _(js::jit::Printf0) \ - _(js::jit::Printf1) \ - _(js::jit::StringFromCharCodeNoGC) \ - _(js::jit::StringTrimEndIndex) \ - _(js::jit::StringTrimStartIndex) \ - _(js::jit::TypeOfNameObject) \ - _(js::jit::TypeOfEqObject) \ - _(js::jit::WrapObjectPure) \ - ABIFUNCTION_FUZZILLI_LIST(_) \ - _(js::MapIteratorObject::next) \ - _(js::NativeObject::addDenseElementPure) \ - _(js::NativeObject::growSlotsPure) \ - _(js::NumberMod) \ - _(js::NumberToStringPure) \ - _(js::ObjectClassToString) \ - _(js::powi) \ - _(js::ProxyGetProperty) \ - _(js::RegExpInstanceOptimizableRaw) \ - _(js::RegExpPrototypeOptimizableRaw) \ - _(js::SetIteratorObject::next) \ - _(js::StringToNumberPure) \ - _(js::TypedArraySortFromJit) \ - _(js::TypeOfObject) \ - _(mozilla::SIMD::memchr16) \ - _(mozilla::SIMD::memchr2x16) \ - _(mozilla::SIMD::memchr2x8) \ +#define ABIFUNCTION_LIST(_) \ + ABIFUNCTION_JS_GC_PROBES_LIST(_) \ + ABIFUNCTION_JS_CODEGEN_ARM_LIST(_) \ + ABIFUNCTION_WASM_CODEGEN_DEBUG_LIST(_) \ + _(js::ArgumentsObject::finishForIonPure) \ + _(js::ArgumentsObject::finishInlineForIonPure) \ + _(js::ArrayShiftMoveElements) \ + _(js::ArraySortData::sortArrayWithComparator) \ + _(js::ArraySortData::sortTypedArrayWithComparator) \ + _(js::ArraySortFromJit) \ + _(js::ecmaAtan2) \ + _(js::ecmaHypot) \ + _(js::ecmaPow) \ + _(js::EmulatesUndefined) \ + _(js::EmulatesUndefinedCheckFuse) \ + _(js::ExecuteRegExpAtomRaw) \ + _(js::hypot3) \ + _(js::hypot4) \ + _(js::Interpret) \ + _(js::Int32ToStringPure) \ + _(js::irregexp::CaseInsensitiveCompareNonUnicode) \ + _(js::irregexp::CaseInsensitiveCompareUnicode) \ + _(js::irregexp::GrowBacktrackStack) \ + _(js::irregexp::IsCharacterInRangeArray) \ + _(js::jit::AllocateAndInitTypedArrayBuffer) \ + _(js::jit::AllocateBigIntNoGC) \ + _(js::jit::AllocateFatInlineString) \ + _(js::jit::AllocateDependentString) \ + _(js::jit::AssertMapObjectHash) \ + _(js::jit::AssertPropertyLookup) \ + _(js::jit::AssertSetObjectHash) \ + _(js::jit::AssertValidBigIntPtr) \ + _(js::jit::AssertValidObjectPtr) \ + _(js::jit::AssertValidStringPtr) \ + _(js::jit::AssertValidSymbolPtr) \ + _(js::jit::AssertValidValue) \ + _(js::jit::AssumeUnreachable) \ + _(js::jit::AtomicsStore64) \ + _(js::jit::AtomizeStringNoGC) \ + _(js::jit::Bailout) \ + _(js::jit::BaselineScript::OSREntryForFrame) \ + _(js::jit::BigIntNumberEqual) \ + _(js::jit::BigIntNumberEqual) \ + _(js::jit::BigIntNumberCompare) \ + _(js::jit::NumberBigIntCompare) \ + _(js::jit::NumberBigIntCompare) \ + _(js::jit::BigIntNumberCompare) \ + _(js::jit::DateFillLocalTimeSlots) \ + _(js::jit::EqualStringsHelperPure) \ + _(js::jit::FinishBailoutToBaseline) \ + _(js::jit::Float16ToFloat32) \ + _(js::jit::Float32ToFloat16) \ + _(js::jit::FrameIsDebuggeeCheck) \ + _(js::jit::GetContextSensitiveInterpreterStub) \ + _(js::jit::GetIndexFromString) \ + _(js::jit::GetInt32FromStringPure) \ + _(js::jit::GetNativeDataPropertyPure) \ + _(js::jit::GetNativeDataPropertyPureWithCacheLookup) \ + _(js::jit::GetNativeDataPropertyByValuePure) \ + _(js::jit::GlobalHasLiveOnDebuggerStatement) \ + _(js::jit::HandleCodeCoverageAtPC) \ + _(js::jit::HandleCodeCoverageAtPrologue) \ + _(js::jit::HandleException) \ + _(js::jit::HasNativeDataPropertyPure) \ + _(js::jit::HasNativeDataPropertyPure) \ + _(js::jit::HasNativeElementPure) \ + _(js::jit::InitBaselineFrameForOsr) \ + _(js::jit::InvalidationBailout) \ + _(js::jit::InvokeFromInterpreterStub) \ + _(js::jit::LazyLinkTopActivation) \ + _(js::jit::LinearizeForCharAccessPure) \ + _(js::jit::ObjectHasGetterSetterPure) \ + _(js::jit::ObjectIsCallable) \ + _(js::jit::ObjectIsConstructor) \ + _(js::jit::PostGlobalWriteBarrier) \ + _(js::jit::PostWriteBarrier) \ + _(js::jit::PostWriteElementBarrier) \ + _(js::jit::Printf0) \ + _(js::jit::Printf1) \ + _(js::jit::StringFromCharCodeNoGC) \ + _(js::jit::StringTrimEndIndex) \ + _(js::jit::StringTrimStartIndex) \ + _(js::jit::TypeOfNameObject) \ + _(js::jit::TypeOfEqObject) \ + _(js::jit::WrapObjectPure) \ + ABIFUNCTION_FUZZILLI_LIST(_) \ + _(js::MapIteratorObject::next) \ + _(js::NativeObject::addDenseElementPure) \ + _(js::NativeObject::growSlotsPure) \ + _(js::NumberMod) \ + _(js::NumberToStringPure) \ + _(js::ObjectClassToString) \ + _(js::powi) \ + _(js::ProxyGetProperty) \ + _(js::RoundFloat16) \ + _(js::SetIteratorObject::next) \ + _(js::StringToNumberPure) \ + _(js::TypedArraySortFromJit) \ + _(js::TypeOfObject) \ + _(mozilla::SIMD::memchr16) \ + _(mozilla::SIMD::memchr2x16) \ + _(mozilla::SIMD::memchr2x8) \ _(mozilla::SIMD::memchr8) // List of all ABI functions to be used with callWithABI, which are @@ -206,7 +208,11 @@ namespace jit { // is not overloaded, you should prefer adding the function to // ABIFUNCTION_LIST instead. This list must be sorted with the name of the C++ // function. -#define ABIFUNCTION_AND_TYPE_LIST(_) _(JS::ToInt32, int32_t (*)(double)) +#define ABIFUNCTION_AND_TYPE_LIST(_) \ + _(JS::ToInt32, int32_t (*)(double)) \ + _(js::jit::RoundFloat16ToFloat32, float (*)(int32_t)) \ + _(js::jit::RoundFloat16ToFloat32, float (*)(float)) \ + _(js::jit::RoundFloat16ToFloat32, float (*)(double)) // List of all ABI function signature which are using a computed function // pointer instead of a statically known function pointer. @@ -236,20 +242,18 @@ namespace jit { # pragma GCC diagnostic ignored "-Wignored-attributes" #endif -// Note: the use of ::fp instead of fp is intentional to enforce use of -// fully-qualified names in the list above. -#define DEF_TEMPLATE(fp) \ - template <> \ - struct ABIFunctionData { \ - static constexpr bool registered = true; \ +#define DEF_TEMPLATE(fp) \ + template <> \ + struct ABIFunctionData { \ + static constexpr bool registered = true; \ }; ABIFUNCTION_LIST(DEF_TEMPLATE) #undef DEF_TEMPLATE -#define DEF_TEMPLATE(fp, ...) \ - template <> \ - struct ABIFunctionData<__VA_ARGS__, ::fp> { \ - static constexpr bool registered = true; \ +#define DEF_TEMPLATE(fp, ...) \ + template <> \ + struct ABIFunctionData<__VA_ARGS__, fp> { \ + static constexpr bool registered = true; \ }; ABIFUNCTION_AND_TYPE_LIST(DEF_TEMPLATE) #undef DEF_TEMPLATE @@ -270,4 +274,21 @@ ABIFUNCTIONSIG_LIST(DEF_TEMPLATE) } // namespace jit } // namespace js +// Make sure that all names are fully qualified (or at least, are resolvable +// within the toplevel namespace). +// +// Previously this was accomplished just by using `::fp` to force resolution +// within the toplevel namespace, but (1) that prevented using templated +// functions with more than one parameter (eg `void foo`) because the +// macro split on the comma and wrapping it in parens doesn't work because +// `::(foo)` is invalid; and (2) that would only check the function name itself, +// not eg template parameters. +namespace check_fully_qualified { +#define CHECK_NS_VISIBILITY(fp) \ + [[maybe_unused]] static constexpr decltype(&fp) MOZ_CONCAT( \ + fp_, __COUNTER__) = nullptr; +ABIFUNCTION_LIST(CHECK_NS_VISIBILITY) +#undef CHECK_NS_VISIBILITY +} // namespace check_fully_qualified + #endif // jit_VMFunctionList_inl_h diff --git a/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.h b/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.h index fe54aaf4a17..5ec37ae1524 100644 --- a/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.h +++ b/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.h @@ -25,7 +25,9 @@ enum class ABIType { // A 32-bit floating point number Float32 = 0x4, // A 64-bit floating point number - Float64 = 0x5 + Float64 = 0x5, + // No result + Void = 0x6, }; const size_t ABITypeArgShift = 0x3; diff --git a/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.yaml b/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.yaml index 4d115e05cb2..7e7886b27b9 100644 --- a/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.yaml +++ b/src/third_party/mozjs/extract/js/src/jit/ABIFunctionType.yaml @@ -55,10 +55,26 @@ ret: General args: [Float32] +# int32_t f(float32) +- ret: Int32 + args: [Float32] + # float f(float) - ret: Float32 args: [Float32] +# float f(double) +- ret: Float32 + args: [Float64] + +# float f(int) +- ret: Float32 + args: [General] + +# float f(int32_t) +- ret: Float32 + args: [Int32] + # float f(int, int) - name: Float32_IntInt ret: Float32 @@ -146,9 +162,15 @@ - ret: General args: [General, Int32, Int32] +- ret: General + args: [General, Int32, Int32, General] + - ret: General args: [General, Int32, Int32, General, Int32] +- ret: General + args: [General, Int32, Int32, Int32, General, Int32] + - name: General_GeneralGeneralInt32Int32 ret: General args: [General, General, Int32, Int32] @@ -163,6 +185,9 @@ - ret: Int32 args: [General, General, General] +- ret: Int32 + args: [General, General, General, General] + - ret: Int32 args: [General, General, General, Int32] @@ -178,6 +203,12 @@ - ret: Int32 args: [General, General, Int32, Int32] +- ret: Int32 + args: [General, General, Int32, Int32, Int32, Int32] + +- ret: Int32 + args: [General, General, Int32, Int32, Int32, Int32, Int32] + - ret: Int32 args: [General, General, Int32, Int32, Int32, General, Int32] @@ -278,3 +309,10 @@ - ret: Int64 args: [General, Int64, Int32] + +# void +- ret: Void + args: [General, Int32, General, Int32, Int32] + +- ret: Void + args: [General, Int32, General, Int32, Int32, Int32] diff --git a/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.cpp b/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.cpp index 00b7829e11f..548ce5e384a 100644 --- a/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.cpp @@ -9,6 +9,7 @@ #include "mozilla/DebugOnly.h" #include "jit/JitSpewer.h" +#include "jit/MIR-wasm.h" #include "jit/MIR.h" #include "jit/MIRGenerator.h" #include "jit/MIRGraph.h" diff --git a/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.h b/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.h index 49ddaee47c8..46a6cb66b9d 100644 --- a/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.h +++ b/src/third_party/mozjs/extract/js/src/jit/AliasAnalysis.h @@ -7,6 +7,7 @@ #ifndef jit_AliasAnalysis_h #define jit_AliasAnalysis_h +#include "jit/MIR-wasm.h" #include "jit/MIR.h" #include "jit/MIRGraph.h" @@ -16,7 +17,7 @@ namespace jit { class LoopAliasInfo; class AliasAnalysis { - MIRGenerator* mir; + const MIRGenerator* mir; MIRGraph& graph_; LoopAliasInfo* loop_; @@ -25,7 +26,7 @@ class AliasAnalysis { TempAllocator& alloc() const { return graph_.alloc(); } public: - AliasAnalysis(MIRGenerator* mir, MIRGraph& graph) + AliasAnalysis(const MIRGenerator* mir, MIRGraph& graph) : mir(mir), graph_(graph), loop_(nullptr) {} [[nodiscard]] bool analyze(); diff --git a/src/third_party/mozjs/extract/js/src/jit/AlignmentMaskAnalysis.cpp b/src/third_party/mozjs/extract/js/src/jit/AlignmentMaskAnalysis.cpp index 5b19b0861c2..c072dfa9e58 100644 --- a/src/third_party/mozjs/extract/js/src/jit/AlignmentMaskAnalysis.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/AlignmentMaskAnalysis.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jit/AlignmentMaskAnalysis.h" +#include "jit/MIR-wasm.h" #include "jit/MIR.h" #include "jit/MIRGraph.h" diff --git a/src/third_party/mozjs/extract/js/src/jit/Assembler.h b/src/third_party/mozjs/extract/js/src/jit/Assembler.h index 5003c351ac0..0dd45d74e89 100644 --- a/src/third_party/mozjs/extract/js/src/jit/Assembler.h +++ b/src/third_party/mozjs/extract/js/src/jit/Assembler.h @@ -15,8 +15,6 @@ # include "jit/arm/Assembler-arm.h" #elif defined(JS_CODEGEN_ARM64) # include "jit/arm64/Assembler-arm64.h" -#elif defined(JS_CODEGEN_MIPS32) -# include "jit/mips32/Assembler-mips32.h" #elif defined(JS_CODEGEN_MIPS64) # include "jit/mips64/Assembler-mips64.h" #elif defined(JS_CODEGEN_LOONG64) diff --git a/src/third_party/mozjs/extract/js/src/jit/AtomicOp.h b/src/third_party/mozjs/extract/js/src/jit/AtomicOp.h index ed9a6dd74c9..1a03d62223b 100644 --- a/src/third_party/mozjs/extract/js/src/jit/AtomicOp.h +++ b/src/third_party/mozjs/extract/js/src/jit/AtomicOp.h @@ -22,76 +22,97 @@ enum class AtomicOp { Xor, }; -// Memory barrier types, shared by MIR and LIR. -// -// MembarSynchronizing is here because some platforms can make the -// distinction (DSB vs DMB on ARM, SYNC vs parameterized SYNC on MIPS) -// but there's been no reason to use it yet. +// Memory barrier type, shared by MIR and LIR. +class MemoryBarrier { + enum MemoryBarrierBits : uint8_t { + MembarLoadLoad = 1, + MembarLoadStore = 2, + MembarStoreStore = 4, + MembarStoreLoad = 8, -enum MemoryBarrierBits : uint8_t { - MembarLoadLoad = 1, - MembarLoadStore = 2, - MembarStoreStore = 4, - MembarStoreLoad = 8, + // MembarSynchronizing is here because some platforms can make the + // distinction (DSB vs DMB on ARM, SYNC vs parameterized SYNC on MIPS) + // but there's been no reason to use it yet. + MembarSynchronizing = 16, - MembarSynchronizing = 16, + // For validity testing + MembarNobits = 0, + MembarAllbits = 31, + }; - // For validity testing - MembarNobits = 0, - MembarAllbits = 31, + MemoryBarrierBits bits_; + + template + constexpr explicit MemoryBarrier(MembarBits... bits) + : bits_(static_cast((bits | ...))) {} + + public: + // Accessors for currently used memory barrier types. + + constexpr bool isNone() const { return bits_ == MembarNobits; } + + constexpr bool isStoreStore() const { return bits_ == MembarStoreStore; } + + constexpr bool isSyncStoreStore() const { + return bits_ == static_cast(MembarStoreStore | + MembarSynchronizing); + } + + constexpr bool hasSync() const { return bits_ & MembarSynchronizing; } + + constexpr bool hasStoreLoad() const { return bits_ & MembarStoreLoad; } + + // No memory barrier. + static constexpr MemoryBarrier None() { return MemoryBarrier{MembarNobits}; } + + // Full memory barrier. + static constexpr MemoryBarrier Full() { + return MemoryBarrier{MembarLoadLoad, MembarLoadStore, MembarStoreLoad, + MembarStoreStore}; + } + + // Standard sets of barriers for atomic loads and stores. + // See http://gee.cs.oswego.edu/dl/jmm/cookbook.html for more. + static constexpr MemoryBarrier BeforeLoad() { + return MemoryBarrier{MembarNobits}; + } + static constexpr MemoryBarrier AfterLoad() { + return MemoryBarrier{MembarLoadLoad, MembarLoadStore}; + } + static constexpr MemoryBarrier BeforeStore() { + return MemoryBarrier{MembarStoreStore}; + } + static constexpr MemoryBarrier AfterStore() { + return MemoryBarrier{MembarStoreLoad}; + } }; -static inline constexpr MemoryBarrierBits operator|(MemoryBarrierBits a, - MemoryBarrierBits b) { - return MemoryBarrierBits(static_cast(a) | static_cast(b)); -} - -static inline constexpr MemoryBarrierBits operator&(MemoryBarrierBits a, - MemoryBarrierBits b) { - return MemoryBarrierBits(static_cast(a) & static_cast(b)); -} - -static inline constexpr MemoryBarrierBits operator~(MemoryBarrierBits a) { - return MemoryBarrierBits(~static_cast(a)); -} - -// Standard barrier bits for a full barrier. -static constexpr MemoryBarrierBits MembarFull = - MembarLoadLoad | MembarLoadStore | MembarStoreLoad | MembarStoreStore; - -// Standard sets of barrier bits for atomic loads and stores. -// See http://gee.cs.oswego.edu/dl/jmm/cookbook.html for more. -static constexpr MemoryBarrierBits MembarBeforeLoad = MembarNobits; -static constexpr MemoryBarrierBits MembarAfterLoad = - MembarLoadLoad | MembarLoadStore; -static constexpr MemoryBarrierBits MembarBeforeStore = MembarStoreStore; -static constexpr MemoryBarrierBits MembarAfterStore = MembarStoreLoad; - struct Synchronization { - const MemoryBarrierBits barrierBefore; - const MemoryBarrierBits barrierAfter; + const MemoryBarrier barrierBefore; + const MemoryBarrier barrierAfter; - constexpr Synchronization(MemoryBarrierBits before, MemoryBarrierBits after) + constexpr Synchronization(MemoryBarrier before, MemoryBarrier after) : barrierBefore(before), barrierAfter(after) {} - static Synchronization None() { - return Synchronization(MemoryBarrierBits(MembarNobits), - MemoryBarrierBits(MembarNobits)); + static constexpr Synchronization None() { + return {MemoryBarrier::None(), MemoryBarrier::None()}; } - static Synchronization Full() { - return Synchronization(MembarFull, MembarFull); + static constexpr Synchronization Full() { + return {MemoryBarrier::Full(), MemoryBarrier::Full()}; } - static Synchronization Load() { - return Synchronization(MembarBeforeLoad, MembarAfterLoad); + static constexpr Synchronization Load() { + return {MemoryBarrier::BeforeLoad(), MemoryBarrier::AfterLoad()}; } - static Synchronization Store() { - return Synchronization(MembarBeforeStore, MembarAfterStore); + static constexpr Synchronization Store() { + return {MemoryBarrier::BeforeStore(), MemoryBarrier::AfterStore()}; } - bool isNone() const { return (barrierBefore | barrierAfter) == MembarNobits; } + constexpr bool isNone() const { + return barrierBefore.isNone() && barrierAfter.isNone(); + } }; } // namespace jit diff --git a/src/third_party/mozjs/extract/js/src/jit/AtomicOperations.h b/src/third_party/mozjs/extract/js/src/jit/AtomicOperations.h index 8ad2839b36e..4fecacb7126 100644 --- a/src/third_party/mozjs/extract/js/src/jit/AtomicOperations.h +++ b/src/third_party/mozjs/extract/js/src/jit/AtomicOperations.h @@ -174,6 +174,9 @@ class AtomicOperations { // Execute a full memory barrier (LoadLoad+LoadStore+StoreLoad+StoreStore). static inline void fenceSeqCst(); + // Pause or yield instruction. + static inline void pause(); + // All clients should use the APIs that take SharedMem pointers. // See above for semantics and acceptable types. @@ -343,7 +346,7 @@ constexpr inline bool AtomicOperations::isLockfreeJS(int32_t size) { #ifdef JS_HAVE_GENERATED_ATOMIC_OPS # include "jit/shared/AtomicOperations-shared-jit.h" -#elif defined(JS_SIMULATOR_MIPS32) || defined(__mips__) +#elif defined(__mips__) # include "jit/mips-shared/AtomicOperations-mips-shared.h" #else # include "jit/shared/AtomicOperations-feeling-lucky.h" diff --git a/src/third_party/mozjs/extract/js/src/jit/AutoWritableJitCode.h b/src/third_party/mozjs/extract/js/src/jit/AutoWritableJitCode.h index e7a1632a1e8..57f7ed53190 100644 --- a/src/third_party/mozjs/extract/js/src/jit/AutoWritableJitCode.h +++ b/src/third_party/mozjs/extract/js/src/jit/AutoWritableJitCode.h @@ -37,18 +37,13 @@ class MOZ_RAII AutoWritableJitCodeFallible { AutoMarkJitCodeWritableForThread writableForThread_; public: - AutoWritableJitCodeFallible(JSRuntime* rt, void* addr, size_t size) - : rt_(rt), addr_(addr), size_(size) { + explicit AutoWritableJitCodeFallible(JitCode* code) + : rt_(code->runtimeFromMainThread()), + addr_(code->allocatedMemory()), + size_(code->allocatedSize()) { rt_->toggleAutoWritableJitCodeActive(true); } - AutoWritableJitCodeFallible(void* addr, size_t size) - : AutoWritableJitCodeFallible(TlsContext.get()->runtime(), addr, size) {} - - explicit AutoWritableJitCodeFallible(JitCode* code) - : AutoWritableJitCodeFallible(code->runtimeFromMainThread(), code->raw(), - code->bufferSize()) {} - [[nodiscard]] bool makeWritable() { return ExecutableAllocator::makeWritable(addr_, size_); } @@ -78,20 +73,13 @@ class MOZ_RAII AutoWritableJitCodeFallible { // construction class MOZ_RAII AutoWritableJitCode : private AutoWritableJitCodeFallible { public: - AutoWritableJitCode(JSRuntime* rt, void* addr, size_t size) - : AutoWritableJitCodeFallible(rt, addr, size) { + explicit AutoWritableJitCode(JitCode* code) + : AutoWritableJitCodeFallible(code) { AutoEnterOOMUnsafeRegion oomUnsafe; if (!makeWritable()) { oomUnsafe.crash("Failed to mmap. Likely no mappings available."); } } - - AutoWritableJitCode(void* addr, size_t size) - : AutoWritableJitCode(TlsContext.get()->runtime(), addr, size) {} - - explicit AutoWritableJitCode(JitCode* code) - : AutoWritableJitCode(code->runtimeFromMainThread(), code->raw(), - code->bufferSize()) {} }; } // namespace js::jit diff --git a/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.cpp b/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.cpp index b6d23becf1f..0da98476399 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.cpp @@ -226,14 +226,13 @@ // LiveBundles by contrast come and go; they are created, but may be split up // into new bundles, and old ones abandoned. // -// Each LiveRange is a member of two different linked lists, chained through -// fields registerLink and bundleLink. +// Each LiveRange is a member of two different lists. // -// A VirtualRegister (described in detail below) has a list of LiveRanges that -// it "owns". These are chained through LiveRange::registerLink. +// A VirtualRegister (described in detail below) has a vector of LiveRanges that +// it "owns". // -// A LiveBundle (also described below) also has a list LiveRanges that it -// "owns", chained through LiveRange::bundleLink. +// A LiveBundle (also described below) has a linked list of LiveRanges that it +// "owns". // // Hence each LiveRange is "owned" by one VirtualRegister and one LiveBundle. // LiveRanges may have their owning LiveBundle changed as a result of @@ -372,13 +371,16 @@ // --------------- // Each VirtualRegister is associated with an SSA value created by the LIR. // Fundamentally it is a container to hold all of the LiveRanges that together -// indicate where the value must be kept live. This is a linked list beginning -// at VirtualRegister::ranges_, and which, as described above, is chained -// through LiveRange::registerLink. The set of LiveRanges must logically form +// indicate where the value must be kept live. The live ranges are stored in a +// vector, VirtualRegister::ranges_. The set of LiveRanges must logically form // a tree, rooted at the LiveRange which defines the value. // -// For adminstrative convenience, the linked list must contain the LiveRanges -// in order of increasing start point. +// The live ranges are sorted in order of decreasing start point by construction +// after buildLivenessInfo until the main register allocation loops. At that +// point they can become unsorted and this is important for performance because +// it allows the core allocation code to add/remove ranges more efficiently. +// After all bundles are allocated, sortVirtualRegisterRanges is called to +// ensure the ranges are sorted again. // // There are various auxiliary fields, most importantly the LIR node and the // associated LDefinition that define the value. @@ -397,7 +399,7 @@ // ---------- // Similar to VirtualRegister, a LiveBundle is also, fundamentally, a container // for a set of LiveRanges. The set is stored as a linked list, rooted at -// LiveBundle::ranges_ and chained through LiveRange::bundleLink. +// LiveBundle::ranges_. // // However, the similarity ends there: // @@ -425,7 +427,7 @@ // // LB2(parent=none v3 8-21 { 16_v3:A } ## v3 24-25 { 25_v3:F:xmm0 }) // -// LB merely indicates "LiveBundle", and the 2 is the debugId_ value (see +// LB merely indicates "LiveBundle", and the 2 is the id_ value (see // below). This bundle has two LiveRanges // // v3 8-21 { 16_v3:A } @@ -513,9 +515,10 @@ // * else (it has a null spillParent_ field) it is a root node, and so other // LiveBundles may point at it. // -// When compiled with JS_JITSPEW, LiveBundle has a 32-bit `debugId_` field. -// This is used only for debug printing, and makes it easier to see -// parent-child relationships induced by the `spillParent_` pointers. +// LiveBundle has a 32-bit `id_` field. This is used for debug printing, and +// makes it easier to see parent-child relationships induced by the +// `spillParent_` pointers. It's also used for sorting live ranges in +// VirtualRegister::sortRanges. // // The "life cycle" of LiveBundles is described in Section 2 below. // @@ -578,13 +581,14 @@ // | | `->--(def)--> LDefinition // v ^ // | | -// (ranges) | +// (ranges vector) | +// | | // | (vreg) -// `--v->--. | ,-->--v-->-------------->--v-->--. ,--NULL -// \ | / \ / -// LiveRange LiveRange LiveRange -// / | \ / \. -// ,--b->--' / `-->--b-->--' `--NULL +// `--v->--. | +// \ | +// LiveRange -->--b-->-- LiveRange -->--b-->-- NULL +// / | +// ,--b->--' / // | (bundle) // ^ / // | v @@ -600,20 +604,19 @@ // \ | / // `--->---> SpillSet <--' // -// --b-- LiveRange::bundleLink: links in the list of LiveRanges that belong to +// --b-- LiveRange::next_: links in the list of LiveRanges that belong to // a LiveBundle // -// --v-- LiveRange::registerLink: links in the list of LiveRanges that belong -// to a VirtualRegister +// --v-- VirtualRegister::ranges_: vector of LiveRanges that belong to a +// VirtualRegister // // --s-- LiveBundle::spillParent: a possible link to my "spill parent bundle" // // -// * LiveRange is in the center. Each LiveRange is a member of two different -// linked lists, the --b-- list and the --v-- list. +// * LiveRange is in the center. Each LiveRange is a member of a linked list, +// the --b-- list, and is also stored in VirtualRegister's `ranges` vector. // -// * VirtualRegister has a pointer `ranges` that points to the start of its -// --v-- list of LiveRanges. +// * VirtualRegister has a `ranges` vector that contains its LiveRanges. // // * LiveBundle has a pointer `ranges` that points to the start of its --b-- // list of LiveRanges. @@ -676,6 +679,9 @@ #include "jit/BacktrackingAllocator.h" +#include "mozilla/BinarySearch.h" +#include "mozilla/Maybe.h" + #include #include "jit/BitSet.h" @@ -686,6 +692,7 @@ using namespace js; using namespace js::jit; using mozilla::DebugOnly; +using mozilla::Maybe; // This is a big, complex file. Code is grouped into various sections, each // preceded by a box comment. Sections not marked as "Misc helpers" are @@ -703,33 +710,46 @@ static inline bool SortBefore(UsePosition* a, UsePosition* b) { return a->pos <= b->pos; } -static inline bool SortBefore(LiveRange::BundleLink* a, - LiveRange::BundleLink* b) { - LiveRange* rangea = LiveRange::get(a); - LiveRange* rangeb = LiveRange::get(b); - MOZ_ASSERT(!rangea->intersects(rangeb)); - return rangea->from() < rangeb->from(); -} - -static inline bool SortBefore(LiveRange::RegisterLink* a, - LiveRange::RegisterLink* b) { - return LiveRange::get(a)->from() <= LiveRange::get(b)->from(); +static inline bool SortBefore(LiveRange* a, LiveRange* b) { + MOZ_ASSERT(!a->intersects(b)); + return a->from() < b->from(); } template -static inline void InsertSortedList(InlineForwardList& list, T* value) { +static void InsertSortedList(InlineForwardList& list, T* value, + T* startAt = nullptr) { if (list.empty()) { + MOZ_ASSERT(!startAt); list.pushFront(value); return; } +#ifdef DEBUG + if (startAt) { + // `startAt` must be an element in `list` that sorts before `value`. + MOZ_ASSERT(SortBefore(startAt, value)); + MOZ_ASSERT_IF(*list.begin() == list.back(), list.back() == startAt); + MOZ_ASSERT_IF(startAt != *list.begin(), SortBefore(*list.begin(), startAt)); + MOZ_ASSERT_IF(startAt != list.back(), SortBefore(startAt, list.back())); + } +#endif + if (SortBefore(list.back(), value)) { list.pushBack(value); return; } + // If `startAt` is non-nullptr, we can start iterating there. T* prev = nullptr; - for (InlineForwardListIterator iter = list.begin(); iter; iter++) { + InlineForwardListIterator iter = + startAt ? list.begin(startAt) : list.begin(); + if (startAt) { + // `value` must sort after `startAt` so skip to the next element. + MOZ_ASSERT(!SortBefore(value, *iter)); + ++iter; + prev = startAt; + } + for (; iter; iter++) { if (SortBefore(value, *iter)) { break; } @@ -808,24 +828,59 @@ void LiveRange::tryToMoveDefAndUsesInto(LiveRange* other) { MOZ_ASSERT(&other->vreg() == &vreg()); MOZ_ASSERT(this != other); - // Move over all uses which fit in |other|'s boundaries. - for (UsePositionIterator iter = usesBegin(); iter;) { - UsePosition* use = *iter; - if (other->covers(use->pos)) { - uses_.removeAndIncrement(iter); - noteRemovedUse(use); - other->addUse(use); - } else { - iter++; - } + // This method shouldn't be called for two non-intersecting live ranges + // because it's a no-op in that case. + MOZ_ASSERT(intersects(other)); + + CodePosition otherFrom = other->from(); + CodePosition otherTo = other->to(); + + // The uses are sorted by position, so first skip all uses before |other| + // starts. + UsePositionIterator iter = usesBegin(); + while (iter && iter->pos < otherFrom) { + iter++; } + // Move over all uses which fit in |other|'s boundaries. + while (iter && iter->pos < otherTo) { + UsePosition* use = *iter; + MOZ_ASSERT(other->covers(use->pos)); + uses_.removeAndIncrement(iter); + noteRemovedUse(use); + other->addUse(use); + } + + MOZ_ASSERT_IF(iter, !other->covers(iter->pos)); + // Distribute the definition to |other| as well, if possible. if (hasDefinition() && from() == other->from()) { other->setHasDefinition(); } } +void LiveRange::moveAllUsesToTheEndOf(LiveRange* other) { + MOZ_ASSERT(&other->vreg() == &vreg()); + MOZ_ASSERT(this != other); + MOZ_ASSERT(other->contains(this)); + + if (uses_.empty()) { + return; + } + + // Assert |other->uses_| remains sorted after adding our uses at the end. + MOZ_ASSERT_IF(!other->uses_.empty(), + SortBefore(other->uses_.back(), *uses_.begin())); + + other->uses_.extendBack(std::move(uses_)); + MOZ_ASSERT(!hasUses()); + + other->usesSpillWeight_ += usesSpillWeight_; + other->numFixedUses_ += numFixedUses_; + usesSpillWeight_ = 0; + numFixedUses_ = 0; +} + bool LiveRange::contains(LiveRange* other) const { return from() <= other->from() && to() >= other->to(); } @@ -874,7 +929,7 @@ bool LiveRange::intersects(LiveRange* other) const { #ifdef DEBUG size_t LiveBundle::numRanges() const { size_t count = 0; - for (LiveRange::BundleLinkIterator iter = rangesBegin(); iter; iter++) { + for (RangeIterator iter = rangesBegin(); iter; iter++) { count++; } return count; @@ -882,8 +937,8 @@ size_t LiveBundle::numRanges() const { #endif LiveRange* LiveBundle::rangeFor(CodePosition pos) const { - for (LiveRange::BundleLinkIterator iter = rangesBegin(); iter; iter++) { - LiveRange* range = LiveRange::get(*iter); + for (RangeIterator iter = rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (range->covers(pos)) { return range; } @@ -891,19 +946,32 @@ LiveRange* LiveBundle::rangeFor(CodePosition pos) const { return nullptr; } -void LiveBundle::addRange(LiveRange* range) { +void LiveBundle::addRange(LiveRange* range, + LiveRange* startAt /* = nullptr */) { MOZ_ASSERT(!range->bundle()); + MOZ_ASSERT(range->hasVreg()); + MOZ_ASSERT_IF(startAt, startAt->bundle() == this); range->setBundle(this); - InsertSortedList(ranges_, &range->bundleLink); + InsertSortedList(ranges_, range, startAt); } -bool LiveBundle::addRange(TempAllocator& alloc, VirtualRegister* vreg, - CodePosition from, CodePosition to) { +void LiveBundle::addRangeAtEnd(LiveRange* range) { + // Note: this method is functionally equivalent to `addRange`, but can be used + // when we know `range` must be added after all existing ranges in the bundle. + MOZ_ASSERT(!range->bundle()); + MOZ_ASSERT(range->hasVreg()); + MOZ_ASSERT_IF(!ranges_.empty(), SortBefore(ranges_.back(), range)); + range->setBundle(this); + ranges_.pushBack(range); +} + +bool LiveBundle::addRangeAtEnd(TempAllocator& alloc, VirtualRegister* vreg, + CodePosition from, CodePosition to) { LiveRange* range = LiveRange::FallibleNew(alloc, vreg, from, to); if (!range) { return false; } - addRange(range); + addRangeAtEnd(range); return true; } @@ -920,12 +988,12 @@ bool LiveBundle::addRangeAndDistributeUses(TempAllocator& alloc, } LiveRange* LiveBundle::popFirstRange() { - LiveRange::BundleLinkIterator iter = rangesBegin(); + RangeIterator iter = rangesBegin(); if (!iter) { return nullptr; } - LiveRange* range = LiveRange::get(*iter); + LiveRange* range = *iter; ranges_.removeAt(iter); range->setBundle(nullptr); @@ -933,8 +1001,8 @@ LiveRange* LiveBundle::popFirstRange() { } void LiveBundle::removeRange(LiveRange* range) { - for (LiveRange::BundleLinkIterator iter = rangesBegin(); iter; iter++) { - LiveRange* existing = LiveRange::get(*iter); + for (RangeIterator iter = rangesBegin(); iter; iter++) { + LiveRange* existing = *iter; if (existing == range) { ranges_.removeAt(iter); return; @@ -943,6 +1011,20 @@ void LiveBundle::removeRange(LiveRange* range) { MOZ_CRASH(); } +void LiveBundle::removeAllRangesFromVirtualRegisters() { + VirtualRegister* prevVreg = nullptr; + for (RangeIterator iter = rangesBegin(); iter; iter++) { + LiveRange* range = *iter; + MOZ_ASSERT(!range->hasUses()); + if (&range->vreg() != prevVreg) { + // As an optimization, remove all ranges owned by this bundle from the + // register's list, instead of a single range at a time. + range->vreg().removeRangesForBundle(this); + prevVreg = &range->vreg(); + } + } +} + /////////////////////////////////////////////////////////////////////////////// // // // Misc helpers: methods for class VirtualRegister // @@ -950,31 +1032,23 @@ void LiveBundle::removeRange(LiveRange* range) { /////////////////////////////////////////////////////////////////////////////// bool VirtualRegister::addInitialRange(TempAllocator& alloc, CodePosition from, - CodePosition to, size_t* numRanges) { + CodePosition to) { + MOZ_ASSERT(rangesSorted_, "ranges stay sorted during live range building"); + MOZ_ASSERT(from < to); + MOZ_ASSERT_IF(hasRanges(), from < ranges_.back()->to()); // Mark [from,to) as a live range for this register during the initial // liveness analysis, coalescing with any existing overlapping ranges. - // On some pathological graphs there might be a huge number of different - // live ranges. Allow non-overlapping live range to be merged if the - // number of ranges exceeds the cap below. - static const size_t CoalesceLimit = 100000; - - LiveRange* prev = nullptr; LiveRange* merged = nullptr; - for (LiveRange::RegisterLinkIterator iter(rangesBegin()); iter;) { - LiveRange* existing = LiveRange::get(*iter); + for (RangeIterator iter(*this); iter; iter++) { + LiveRange* existing = *iter; - if (from > existing->to() && *numRanges < CoalesceLimit) { - // The new range should go after this one. - prev = existing; - iter++; - continue; - } + MOZ_ASSERT(from < existing->to()); - if (to.next() < existing->from()) { - // The new range should go before this one. + if (to < existing->from()) { + // All other ranges start after |to| so can't overlap. break; } @@ -992,48 +1066,67 @@ bool VirtualRegister::addInitialRange(TempAllocator& alloc, CodePosition from, // Continue searching to see if any other old ranges can be // coalesced with the new merged range. - iter++; - continue; + } else { + // Coalesce this range into the previous range we merged into. + MOZ_ASSERT(existing->from() >= merged->from()); + if (existing->to() > merged->to()) { + merged->setTo(existing->to()); + } + + MOZ_ASSERT(!existing->hasDefinition()); + existing->moveAllUsesToTheEndOf(merged); + MOZ_ASSERT(!existing->hasUses()); } - // Coalesce this range into the previous range we merged into. - MOZ_ASSERT(existing->from() >= merged->from()); - if (existing->to() > merged->to()) { - merged->setTo(existing->to()); - } - - MOZ_ASSERT(!existing->hasDefinition()); - existing->tryToMoveDefAndUsesInto(merged); - MOZ_ASSERT(!existing->hasUses()); - - ranges_.removeAndIncrement(iter); + removeFirstRange(iter); } - if (!merged) { + if (merged) { + // Re-append the merged range. + if (!ranges_.append(merged)) { + return false; + } + } else { // The new range does not overlap any existing range for the vreg. + MOZ_ASSERT_IF(hasRanges(), to < ranges_.back()->from()); + LiveRange* range = LiveRange::FallibleNew(alloc, this, from, to); if (!range) { return false; } - if (prev) { - ranges_.insertAfter(&prev->registerLink, &range->registerLink); - } else { - ranges_.pushFront(&range->registerLink); + if (!ranges_.append(range)) { + return false; } - - (*numRanges)++; } + MOZ_ASSERT(rangesSorted_, "ranges are still sorted"); + +#ifdef DEBUG + // Check the last few ranges don't overlap and are in the correct order. + size_t len = ranges_.length(); + static constexpr size_t MaxIterations = 4; + size_t start = len > MaxIterations ? (len - MaxIterations) : 1; + + for (size_t i = start; i < len; i++) { + LiveRange* range = ranges_[i]; + LiveRange* prev = ranges_[i - 1]; + MOZ_ASSERT(range->from() < range->to()); + MOZ_ASSERT(range->to() < prev->from()); + } +#endif + return true; } void VirtualRegister::addInitialUse(UsePosition* use) { - LiveRange::get(*rangesBegin())->addUse(use); + MOZ_ASSERT(rangesSorted_, "ranges stay sorted during live range building"); + ranges_.back()->addUse(use); } void VirtualRegister::setInitialDefinition(CodePosition from) { - LiveRange* first = LiveRange::get(*rangesBegin()); + MOZ_ASSERT(rangesSorted_, "ranges stay sorted during live range building"); + LiveRange* first = ranges_.back(); MOZ_ASSERT(from >= first->from()); first->setFrom(from); first->setHasDefinition(); @@ -1041,34 +1134,168 @@ void VirtualRegister::setInitialDefinition(CodePosition from) { LiveRange* VirtualRegister::rangeFor(CodePosition pos, bool preferRegister /* = false */) const { + assertRangesSorted(); + + size_t len = ranges_.length(); + + // Because the ranges are sorted in order of descending start position, we use + // binary search to find the first range where |range->from <= pos|. All + // ranges before that definitely don't cover |pos|. + auto compare = [pos](LiveRange* other) { + if (pos < other->from()) { + return 1; + } + if (pos > other->from()) { + return -1; + } + return 0; + }; + size_t index; + mozilla::BinarySearchIf(ranges_, 0, len, compare, &index); + + if (index == len) { + // None of the ranges overlap. + MOZ_ASSERT(ranges_.back()->from() > pos); + return nullptr; + } + + // There can be multiple ranges with |range->from == pos|. We want to start at + // the first one. + while (index > 0 && ranges_[index - 1]->from() == pos) { + index--; + } + + // Verify the above code is correct: + // * The range at |index| starts before or at |pos| and needs to be searched. + // * All ranges before |index| start after |pos| and can be ignored. + MOZ_ASSERT(ranges_[index]->from() <= pos); + MOZ_ASSERT_IF(index > 0, ranges_[index - 1]->from() > pos); + LiveRange* found = nullptr; - for (LiveRange::RegisterLinkIterator iter = rangesBegin(); iter; iter++) { - LiveRange* range = LiveRange::get(*iter); + do { + LiveRange* range = ranges_[index]; if (range->covers(pos)) { - if (!preferRegister || range->bundle()->allocation().isRegister()) { + if (!preferRegister || range->bundle()->allocation().isAnyRegister()) { return range; } if (!found) { found = range; } } - } + index++; + } while (index < len); + return found; } -void VirtualRegister::addRange(LiveRange* range) { - InsertSortedList(ranges_, &range->registerLink); +void VirtualRegister::sortRanges() { + if (rangesSorted_) { + assertRangesSorted(); + return; + } + + // Sort ranges by start position in descending order. + // + // It would be correct to only compare the start position, but std::sort is + // not a stable sort and we don't want the order of ranges with the same start + // position to depend on the sort implementation. Use the end position and the + // bundle's id to ensure ranges are always sorted the same way. + auto compareRanges = [](LiveRange* a, LiveRange* b) -> bool { + if (a->from() != b->from()) { + return a->from() > b->from(); + } + if (a->to() != b->to()) { + return a->to() > b->to(); + } + // Overlapping live ranges must belong to different bundles. + MOZ_ASSERT_IF(a != b, a->bundle()->id() != b->bundle()->id()); + return a->bundle()->id() > b->bundle()->id(); + }; + std::sort(ranges_.begin(), ranges_.end(), compareRanges); + + rangesSorted_ = true; } -void VirtualRegister::removeRange(LiveRange* range) { - for (LiveRange::RegisterLinkIterator iter = rangesBegin(); iter; iter++) { - LiveRange* existing = LiveRange::get(*iter); - if (existing == range) { - ranges_.removeAt(iter); - return; - } +#ifdef DEBUG +void VirtualRegister::assertRangesSorted() const { + MOZ_ASSERT(rangesSorted_); + + // Assert the last N ranges in the vector are sorted correctly. We don't check + // the whole vector to not slow down debug builds too much. + + size_t len = ranges_.length(); + static constexpr size_t MaxIterations = 4; + size_t start = len > MaxIterations ? (len - MaxIterations) : 1; + + for (size_t i = start; i < len; i++) { + LiveRange* prev = ranges_[i - 1]; + LiveRange* range = ranges_[i]; + MOZ_ASSERT(range->from() <= prev->from()); + + // If two ranges have the same |from| position, neither must be defining. + // This ensures the defining range, if any, always comes first after + // sorting. + MOZ_ASSERT_IF(range->from() == prev->from(), + !range->hasDefinition() && !prev->hasDefinition()); } - MOZ_CRASH(); +} +#endif + +bool VirtualRegister::addRange(LiveRange* range) { + bool sorted = ranges_.empty() || + (rangesSorted_ && ranges_.back()->from() >= range->from()); + if (!ranges_.append(range)) { + return false; + } + rangesSorted_ = sorted; + return true; +} + +void VirtualRegister::removeFirstRange(RangeIterator& iter) { + MOZ_ASSERT(iter.index() == ranges_.length() - 1); + ranges_.popBack(); +} + +void VirtualRegister::removeRangesForBundle(LiveBundle* bundle) { + auto bundleMatches = [bundle](LiveRange* range) { + return range->bundle() == bundle; + }; + ranges_.eraseIf(bundleMatches); +} + +template +void VirtualRegister::removeRangesIf(Pred&& pred) { + assertRangesSorted(); + ranges_.eraseIf([&](LiveRange* range) { return pred(ranges_, range); }); +} + +// Helper for ::tryMergeReusedRegister. +bool VirtualRegister::replaceLastRangeLinear(LiveRange* old, LiveRange* newPre, + LiveRange* newPost) { + assertRangesSorted(); + + // |old| is currently the first range in the Vector (the range with the + // highest start position). This range is being replaced with two new ranges, + // |newPre| and |newPost|. The relative order of these ranges by start + // position is: + // + // old <= newPre <= newPost + // + // To keep the vector sorted by descending start position, |newPost| must + // become the new last range and |newPre| must be inserted after it. + + MOZ_ASSERT(ranges_[0] == old); + MOZ_ASSERT(old->from() <= newPre->from()); + MOZ_ASSERT(newPre->from() <= newPost->from()); + + ranges_[0] = newPost; + + if (!ranges_.insert(ranges_.begin() + 1, newPre)) { + return false; + } + + assertRangesSorted(); + return true; } /////////////////////////////////////////////////////////////////////////////// @@ -1139,7 +1366,7 @@ bool BacktrackingAllocator::isRegisterDefinition(LiveRange* range) { } if (reg.def()->policy() == LDefinition::FIXED && - !reg.def()->output()->isRegister()) { + !reg.def()->output()->isAnyRegister()) { return false; } @@ -1162,7 +1389,7 @@ bool BacktrackingAllocator::isRegisterDefinition(LiveRange* range) { // [Further group definitions and supporting code to come, pending rework // of the wasm atomic-group situation.] -CodePosition RegisterAllocator::minimalDefEnd(LNode* ins) const { +CodePosition BacktrackingAllocator::minimalDefEnd(LNode* ins) const { // Compute the shortest interval that captures vregs defined by ins. // Watch for instructions that are followed by an OSI point. // If moves are introduced between the instruction and the OSI point then @@ -1190,9 +1417,8 @@ size_t BacktrackingAllocator::computePriority(LiveBundle* bundle) { // have a low spill weight). See processBundle(). size_t lifetimeTotal = 0; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; lifetimeTotal += range->to() - range->from(); } @@ -1215,13 +1441,18 @@ bool BacktrackingAllocator::minimalUse(LiveRange* range, UsePosition* use) { } bool BacktrackingAllocator::minimalBundle(LiveBundle* bundle, bool* pfixed) { - LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); - LiveRange* range = LiveRange::get(*iter); + // Return true iff |bundle| is a minimal bundle. A minimal bundle is a bundle + // that can't be split further. Minimal bundles have a single (very short) + // range. + // + // If the bundle is minimal we also set the |*pfixed| outparam to indicate + // whether the bundle must be allocated to a fixed register. The value of + // |*pfixed| is undefined if this function returns false. - if (!range->hasVreg()) { - *pfixed = true; - return true; - } + LiveBundle::RangeIterator iter = bundle->rangesBegin(); + LiveRange* range = *iter; + + MOZ_ASSERT(range->hasVreg(), "Call ranges are not added to LiveBundles"); // If a bundle contains multiple ranges, splitAtAllRegisterUses will split // each range into a separate bundle. @@ -1231,11 +1462,25 @@ bool BacktrackingAllocator::minimalBundle(LiveBundle* bundle, bool* pfixed) { if (range->hasDefinition()) { VirtualRegister& reg = range->vreg(); + if (!minimalDef(range, reg.ins())) { + return false; + } if (pfixed) { *pfixed = reg.def()->policy() == LDefinition::FIXED && - reg.def()->output()->isRegister(); + reg.def()->output()->isAnyRegister(); } - return minimalDef(range, reg.ins()); + return true; + } + + // Performance optimization: |minimalUse| will only return true for length-1 + // or length-2 ranges so if this is a longer range it can't be minimal. + if (range->to() - range->from() > 2) { +#ifdef DEBUG + for (UsePositionIterator iter = range->usesBegin(); iter; iter++) { + MOZ_ASSERT(!minimalUse(range, *iter)); + } +#endif + return false; } bool fixed = false, minimal = false, multiple = false; @@ -1270,13 +1515,16 @@ bool BacktrackingAllocator::minimalBundle(LiveBundle* bundle, bool* pfixed) { // If a range contains a fixed use and at least one other use, // splitAtAllRegisterUses will split each use into a different bundle. if (multiple && fixed) { - minimal = false; + return false; } + if (!minimal) { + return false; + } if (pfixed) { *pfixed = fixed; } - return minimal; + return true; } size_t BacktrackingAllocator::computeSpillWeight(LiveBundle* bundle) { @@ -1290,14 +1538,13 @@ size_t BacktrackingAllocator::computeSpillWeight(LiveBundle* bundle) { size_t usesTotal = 0; fixed = false; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (range->hasDefinition()) { VirtualRegister& reg = range->vreg(); if (reg.def()->policy() == LDefinition::FIXED && - reg.def()->output()->isRegister()) { + reg.def()->output()->isAnyRegister()) { usesTotal += 2000; fixed = true; } else if (!reg.ins()->isPhi()) { @@ -1311,12 +1558,6 @@ size_t BacktrackingAllocator::computeSpillWeight(LiveBundle* bundle) { } } - // Bundles with fixed uses are given a higher spill weight, since they must - // be allocated to a specific register. - if (testbed && fixed) { - usesTotal *= 2; - } - // Compute spill weight as a use density, lowering the weight for long // lived bundles with relatively few uses. size_t lifetimeTotal = computePriority(bundle); @@ -1341,21 +1582,49 @@ size_t BacktrackingAllocator::maximumSpillWeight( // This function pre-allocates and initializes as much global state as possible // to avoid littering the algorithms with memory management cruft. bool BacktrackingAllocator::init() { - if (!RegisterAllocator::init()) { + if (!insData.init(mir, graph.numInstructions())) { return false; } - liveIn = mir->allocate(graph.numBlockIds()); - if (!liveIn) { + if (!entryPositions.reserve(graph.numBlocks()) || + !exitPositions.reserve(graph.numBlocks())) { + return false; + } + + for (size_t i = 0; i < graph.numBlocks(); i++) { + LBlock* block = graph.getBlock(i); + for (LInstructionIterator ins = block->begin(); ins != block->end(); + ins++) { + insData[ins->id()] = *ins; + } + for (size_t j = 0; j < block->numPhis(); j++) { + LPhi* phi = block->getPhi(j); + insData[phi->id()] = phi; + } + + CodePosition entry = + block->numPhis() != 0 + ? CodePosition(block->getPhi(0)->id(), CodePosition::INPUT) + : inputOf(block->firstInstructionWithId()); + CodePosition exit = outputOf(block->lastInstructionWithId()); + + MOZ_ASSERT(block->mir()->id() == i); + entryPositions.infallibleAppend(entry); + exitPositions.infallibleAppend(exit); + } + + uint32_t numBlocks = graph.numBlockIds(); + MOZ_ASSERT(liveIn.empty()); + if (!liveIn.growBy(numBlocks)) { return false; } size_t numVregs = graph.numVirtualRegisters(); - if (!vregs.init(mir->alloc(), numVregs)) { + if (!vregs.initCapacity(numVregs)) { return false; } for (uint32_t i = 0; i < numVregs; i++) { - new (&vregs[i]) VirtualRegister(); + vregs.infallibleEmplaceBack(); } // Build virtual register objects. @@ -1371,20 +1640,11 @@ bool BacktrackingAllocator::init() { return false; } - for (size_t j = 0; j < ins->numDefs(); j++) { - LDefinition* def = ins->getDef(j); - if (def->isBogusTemp()) { - continue; - } - vreg(def).init(*ins, def, /* isTemp = */ false); + for (LInstruction::OutputIter output(*ins); !output.done(); output++) { + vreg(*output).init(*ins, *output, /* isTemp = */ false); } - - for (size_t j = 0; j < ins->numTemps(); j++) { - LDefinition* def = ins->getTemp(j); - if (def->isBogusTemp()) { - continue; - } - vreg(def).init(*ins, def, /* isTemp = */ true); + for (LInstruction::TempIter temp(*ins); !temp.done(); temp++) { + vreg(*temp).init(*ins, *temp, /* isTemp = */ true); } } for (size_t j = 0; j < block->numPhis(); j++) { @@ -1412,7 +1672,6 @@ bool BacktrackingAllocator::init() { } hotcode.setAllocator(lifoAlloc); - callRanges.setAllocator(lifoAlloc); // Partition the graph into hot and cold sections, for helping to make // splitting decisions. Since we don't have any profiling data this is a @@ -1504,13 +1763,16 @@ static bool IsInputReused(LInstruction* ins, LUse* use) { bool BacktrackingAllocator::buildLivenessInfo() { JitSpew(JitSpew_RegAlloc, "Beginning liveness analysis"); - Vector loopWorkList; - BitSet loopDone(graph.numBlockIds()); - if (!loopDone.init(alloc())) { + // The callPositions vector and the safepoint vectors are initialized from + // index |length - 1| to 0, to ensure they are sorted. + if (!callPositions.growByUninitialized(graph.numCallInstructions()) || + !safepoints_.growByUninitialized(graph.numSafepoints()) || + !nonCallSafepoints_.growByUninitialized(graph.numNonCallSafepoints())) { return false; } - - size_t numRanges = 0; + size_t prevCallPositionIndex = callPositions.length(); + size_t prevSafepointIndex = safepoints_.length(); + size_t prevNonCallSafepointIndex = nonCallSafepoints_.length(); for (size_t i = graph.numBlocks(); i > 0; i--) { if (mir->shouldCancel("Build Liveness Info (main loop)")) { @@ -1520,18 +1782,16 @@ bool BacktrackingAllocator::buildLivenessInfo() { LBlock* block = graph.getBlock(i - 1); MBasicBlock* mblock = block->mir(); - BitSet& live = liveIn[mblock->id()]; - new (&live) BitSet(graph.numVirtualRegisters()); - if (!live.init(alloc())) { - return false; - } + VirtualRegBitSet& live = liveIn[mblock->id()]; // Propagate liveIn from our successors to us. for (size_t i = 0; i < mblock->lastIns()->numSuccessors(); i++) { MBasicBlock* successor = mblock->lastIns()->getSuccessor(i); // Skip backedges, as we fix them up at the loop header. if (mblock->id() < successor->id()) { - live.insertAll(liveIn[successor->id()]); + if (!live.insertAll(liveIn[successor->id()])) { + return false; + } } } @@ -1542,17 +1802,20 @@ bool BacktrackingAllocator::buildLivenessInfo() { LPhi* phi = phiSuccessor->getPhi(j); LAllocation* use = phi->getOperand(mblock->positionInPhiSuccessor()); uint32_t reg = use->toUse()->virtualRegister(); - live.insert(reg); + if (!live.insert(reg)) { + return false; + } vreg(use).setUsedByPhi(); } } // Registers are assumed alive for the entire block, a define shortens // the range to the point of definition. - for (BitSet::Iterator liveRegId(live); liveRegId; ++liveRegId) { + for (VirtualRegBitSet::Iterator liveRegId(live); liveRegId; ++liveRegId) { if (!vregs[*liveRegId].addInitialRange(alloc(), entryOf(block), - exitOf(block).next(), &numRanges)) + exitOf(block).next())) { return false; + } } // Shorten the front end of ranges for live variables to their point of @@ -1583,52 +1846,33 @@ bool BacktrackingAllocator::buildLivenessInfo() { } } - CallRange* callRange = new (alloc().fallible()) - CallRange(outputOf(*ins), outputOf(*ins).next()); - if (!callRange) { - return false; - } - - callRangesList.pushFront(callRange); - if (!callRanges.insert(callRange)) { - return false; - } + // Add the call position before the previous one to ensure the vector is + // sorted. + MOZ_ASSERT(prevCallPositionIndex > 0); + MOZ_ASSERT_IF(prevCallPositionIndex < callPositions.length(), + outputOf(*ins) < callPositions[prevCallPositionIndex]); + prevCallPositionIndex--; + callPositions[prevCallPositionIndex] = outputOf(*ins); } - for (size_t i = 0; i < ins->numDefs(); i++) { - LDefinition* def = ins->getDef(i); - if (def->isBogusTemp()) { - continue; - } - + for (LInstruction::OutputIter output(*ins); !output.done(); output++) { + LDefinition* def = *output; CodePosition from = outputOf(*ins); if (def->policy() == LDefinition::MUST_REUSE_INPUT) { - // MUST_REUSE_INPUT is implemented by allocating an output - // register and moving the input to it. Register hints are - // used to avoid unnecessary moves. We give the input an - // LUse::ANY policy to avoid allocating a register for the - // input. - LUse* inputUse = ins->getOperand(def->getReusedInput())->toUse(); - MOZ_ASSERT(inputUse->policy() == LUse::REGISTER); - MOZ_ASSERT(inputUse->usedAtStart()); - *inputUse = LUse(inputUse->virtualRegister(), LUse::ANY, - /* usedAtStart = */ true); + ins->changePolicyOfReusedInputToAny(def); } - if (!vreg(def).addInitialRange(alloc(), from, from.next(), - &numRanges)) { + if (!vreg(def).addInitialRange(alloc(), from, from.next())) { return false; } vreg(def).setInitialDefinition(from); live.remove(def->virtualRegister()); } - for (size_t i = 0; i < ins->numTemps(); i++) { - LDefinition* temp = ins->getTemp(i); - if (temp->isBogusTemp()) { - continue; - } + for (LInstruction::TempIter tempIter(*ins); !tempIter.done(); + tempIter++) { + LDefinition* temp = *tempIter; // Normally temps are considered to cover both the input // and output of the associated instruction. In some cases @@ -1637,8 +1881,8 @@ bool BacktrackingAllocator::buildLivenessInfo() { // this and shorten the temp to cover only the output. CodePosition from = inputOf(*ins); if (temp->policy() == LDefinition::FIXED) { - AnyRegister reg = temp->output()->toRegister(); - for (LInstruction::InputIterator alloc(**ins); alloc.more(); + AnyRegister reg = temp->output()->toAnyRegister(); + for (LInstruction::NonSnapshotInputIter alloc(**ins); alloc.more(); alloc.next()) { if (alloc->isUse()) { LUse* use = alloc->toUse(); @@ -1662,7 +1906,7 @@ bool BacktrackingAllocator::buildLivenessInfo() { CodePosition to = ins->isCall() ? outputOf(*ins) : outputOf(*ins).next(); - if (!vreg(temp).addInitialRange(alloc(), from, to, &numRanges)) { + if (!vreg(temp).addInitialRange(alloc(), from, to)) { return false; } vreg(temp).setInitialDefinition(from); @@ -1671,7 +1915,7 @@ bool BacktrackingAllocator::buildLivenessInfo() { DebugOnly hasUseRegister = false; DebugOnly hasUseRegisterAtStart = false; - for (LInstruction::InputIterator inputAlloc(**ins); inputAlloc.more(); + for (LInstruction::InputIter inputAlloc(**ins); inputAlloc.more(); inputAlloc.next()) { if (inputAlloc->isUse()) { LUse* use = inputAlloc->toUse(); @@ -1714,8 +1958,7 @@ bool BacktrackingAllocator::buildLivenessInfo() { } } - if (!vreg(use).addInitialRange(alloc(), entryOf(block), to.next(), - &numRanges)) { + if (!vreg(use).addInitialRange(alloc(), entryOf(block), to.next())) { return false; } UsePosition* usePosition = @@ -1724,7 +1967,20 @@ bool BacktrackingAllocator::buildLivenessInfo() { return false; } vreg(use).addInitialUse(usePosition); - live.insert(use->virtualRegister()); + if (!live.insert(use->virtualRegister())) { + return false; + } + } + } + + if (ins->safepoint()) { + MOZ_ASSERT(prevSafepointIndex > 0); + prevSafepointIndex--; + safepoints_[prevSafepointIndex] = *ins; + if (!ins->isCall()) { + MOZ_ASSERT(prevNonCallSafepointIndex > 0); + prevNonCallSafepointIndex--; + nonCallSafepoints_[prevNonCallSafepointIndex] = *ins; } } } @@ -1740,89 +1996,89 @@ bool BacktrackingAllocator::buildLivenessInfo() { // This is a dead phi, so add a dummy range over all phis. This // can go away if we have an earlier dead code elimination pass. CodePosition entryPos = entryOf(block); - if (!vreg(def).addInitialRange(alloc(), entryPos, entryPos.next(), - &numRanges)) { + if (!vreg(def).addInitialRange(alloc(), entryPos, entryPos.next())) { return false; } } } if (mblock->isLoopHeader()) { - // A divergence from the published algorithm is required here, as - // our block order does not guarantee that blocks of a loop are - // contiguous. As a result, a single live range spanning the - // loop is not possible. Additionally, we require liveIn in a later - // pass for resolution, so that must also be fixed up here. - MBasicBlock* loopBlock = mblock->backedge(); - while (true) { - // Blocks must already have been visited to have a liveIn set. - MOZ_ASSERT(loopBlock->id() >= mblock->id()); + // MakeLoopsContiguous ensures blocks of a loop are contiguous, so add a + // single live range spanning the loop. Because we require liveIn in a + // later pass for resolution, we also have to fix that up for all loop + // blocks. - // Add a range for this entire loop block - CodePosition from = entryOf(loopBlock->lir()); - CodePosition to = exitOf(loopBlock->lir()).next(); + MBasicBlock* backedge = mblock->backedge(); - for (BitSet::Iterator liveRegId(live); liveRegId; ++liveRegId) { - if (!vregs[*liveRegId].addInitialRange(alloc(), from, to, - &numRanges)) { - return false; - } - } + // Add a range for this entire loop + CodePosition from = entryOf(mblock->lir()); + CodePosition to = exitOf(backedge->lir()).next(); - // Fix up the liveIn set. - liveIn[loopBlock->id()].insertAll(live); - - // Make sure we don't visit this node again - loopDone.insert(loopBlock->id()); - - // If this is the loop header, any predecessors are either the - // backedge or out of the loop, so skip any predecessors of - // this block - if (loopBlock != mblock) { - for (size_t i = 0; i < loopBlock->numPredecessors(); i++) { - MBasicBlock* pred = loopBlock->getPredecessor(i); - if (loopDone.contains(pred->id())) { - continue; - } - if (!loopWorkList.append(pred)) { - return false; - } - } - } - - // Terminate loop if out of work. - if (loopWorkList.empty()) { - break; - } - - // Grab the next block off the work list, skipping any OSR block. - MBasicBlock* osrBlock = graph.mir().osrBlock(); - while (!loopWorkList.empty()) { - loopBlock = loopWorkList.popCopy(); - if (loopBlock != osrBlock) { - break; - } - } - - // If end is reached without finding a non-OSR block, then no more work - // items were found. - if (loopBlock == osrBlock) { - MOZ_ASSERT(loopWorkList.empty()); - break; + for (VirtualRegBitSet::Iterator liveRegId(live); liveRegId; ++liveRegId) { + if (!vregs[*liveRegId].addInitialRange(alloc(), from, to)) { + return false; } } - // Clear the done set for other loops - loopDone.clear(); + if (mblock != backedge) { + // Start at the block after |mblock|. + MOZ_ASSERT(graph.getBlock(i - 1) == mblock->lir()); + size_t j = i; + while (true) { + MBasicBlock* loopBlock = graph.getBlock(j)->mir(); + + // Fix up the liveIn set. + if (!liveIn[loopBlock->id()].insertAll(live)) { + return false; + } + + if (loopBlock == backedge) { + break; + } + j++; + } + } } MOZ_ASSERT_IF(!mblock->numPredecessors(), live.empty()); } + MOZ_RELEASE_ASSERT(prevCallPositionIndex == 0, + "Must have initialized all call positions"); + MOZ_RELEASE_ASSERT(prevSafepointIndex == 0, + "Must have initialized all safepoints"); + MOZ_RELEASE_ASSERT(prevNonCallSafepointIndex == 0, + "Must have initialized all safepoints"); + JitSpew(JitSpew_RegAlloc, "Completed liveness analysis"); return true; } +Maybe BacktrackingAllocator::lookupFirstCallPositionInRange( + CodePosition from, CodePosition to) { + MOZ_ASSERT(from < to); + + // Use binary search to find the first call position in range [from, to). + size_t len = callPositions.length(); + size_t index; + mozilla::BinarySearch(callPositions, 0, len, from, &index); + MOZ_ASSERT(index <= len); + + if (index == len) { + // Last call position in the vector is before this range. + MOZ_ASSERT_IF(len > 0, callPositions.back() < from); + return {}; + } + + if (callPositions[index] >= to) { + // The next call position comes after this range. + return {}; + } + + MOZ_ASSERT(callPositions[index] >= from && callPositions[index] < to); + return mozilla::Some(index); +} + /////////////////////////////////////////////////////////////////////////////// // // // Merging and queueing of LiveRange groups // @@ -1855,15 +2111,15 @@ static bool CanMergeTypesInBundle(LDefinition::Type a, LDefinition::Type b) { // Only merge if the sizes match, so that we don't get confused about the // width of spill slots. - return StackSlotAllocator::width(a) == StackSlotAllocator::width(b); + return LStackSlot::width(a) == LStackSlot::width(b); } // Helper for ::tryMergeReusedRegister -bool BacktrackingAllocator::tryMergeBundles(LiveBundle* bundle0, +void BacktrackingAllocator::tryMergeBundles(LiveBundle* bundle0, LiveBundle* bundle1) { // See if bundle0 and bundle1 can be merged together. if (bundle0 == bundle1) { - return true; + return; } // Get a representative virtual register from each bundle. @@ -1873,30 +2129,41 @@ bool BacktrackingAllocator::tryMergeBundles(LiveBundle* bundle0, MOZ_ASSERT(CanMergeTypesInBundle(reg0.type(), reg1.type())); MOZ_ASSERT(reg0.isCompatible(reg1)); - // Registers which might spill to the frame's |this| slot can only be - // grouped with other such registers. The frame's |this| slot must always - // hold the |this| value, as required by JitFrame tracing and by the Ion - // constructor calling convention. - if (IsThisSlotDefinition(reg0.def()) || IsThisSlotDefinition(reg1.def())) { - if (*reg0.def()->output() != *reg1.def()->output()) { - return true; - } - } - - // Registers which might spill to the frame's argument slots can only be - // grouped with other such registers if the frame might access those - // arguments through a lazy arguments object or rest parameter. - if (IsArgumentSlotDefinition(reg0.def()) || - IsArgumentSlotDefinition(reg1.def())) { -#ifdef JS_PUNBOX64 - bool canSpillToArgSlots = - !graph.mir().entryBlock()->info().mayReadFrameArgsDirectly(); -#else - bool canSpillToArgSlots = false; -#endif - if (!canSpillToArgSlots) { + if (!compilingWasm()) { + // Registers which might spill to the frame's |this| slot can only be + // grouped with other such registers. The frame's |this| slot must always + // hold the |this| value, as required by JitFrame tracing and by the Ion + // constructor calling convention. + if (IsThisSlotDefinition(reg0.def()) || IsThisSlotDefinition(reg1.def())) { if (*reg0.def()->output() != *reg1.def()->output()) { - return true; + return; + } + } + + // Registers which might spill to the frame's argument slots can only be + // grouped with other such registers in the following cases: + // + // * If the frame might access those arguments through a lazy arguments + // object or rest parameter. + // + // * On 32-bit platforms, to prevent creating garbage Values in the formal + // argument slots when spilling just the type or payload of a different + // Value. GC tracing of ArraySortData relies on the argument slots holding + // valid JS values. See bug 1911858. + if (IsArgumentSlotDefinition(reg0.def()) || + IsArgumentSlotDefinition(reg1.def())) { +#ifdef JS_PUNBOX64 + MOZ_ASSERT(reg0.type() == LDefinition::Type::BOX); + MOZ_ASSERT(reg1.type() == LDefinition::Type::BOX); + bool canSpillToArgSlots = + !graph.mir().entryBlock()->info().mayReadFrameArgsDirectly(); +#else + bool canSpillToArgSlots = false; +#endif + if (!canSpillToArgSlots) { + if (*reg0.def()->output() != *reg1.def()->output()) { + return; + } } } } @@ -1909,7 +2176,7 @@ bool BacktrackingAllocator::tryMergeBundles(LiveBundle* bundle0, // policy LDefinition::STACK. This aliasing between allocations makes it // unsound to merge anything with a LDefinition::STACK policy. if (HasStackPolicy(reg0.def()) || HasStackPolicy(reg1.def())) { - return true; + return; } // Limit the number of times we compare ranges if there are many ranges in @@ -1917,32 +2184,39 @@ bool BacktrackingAllocator::tryMergeBundles(LiveBundle* bundle0, static const size_t MAX_RANGES = 200; // Make sure that ranges in the bundles do not overlap. - LiveRange::BundleLinkIterator iter0 = bundle0->rangesBegin(), - iter1 = bundle1->rangesBegin(); + LiveBundle::RangeIterator iter0 = bundle0->rangesBegin(), + iter1 = bundle1->rangesBegin(); size_t count = 0; while (iter0 && iter1) { if (++count >= MAX_RANGES) { - return true; + return; } - LiveRange* range0 = LiveRange::get(*iter0); - LiveRange* range1 = LiveRange::get(*iter1); + LiveRange* range0 = *iter0; + LiveRange* range1 = *iter1; if (range0->from() >= range1->to()) { iter1++; } else if (range1->from() >= range0->to()) { iter0++; } else { - return true; + return; } } - // Move all ranges from bundle1 into bundle0. - while (LiveRange* range = bundle1->popFirstRange()) { - bundle0->addRange(range); + // Move all ranges from bundle1 into bundle0. Use a fast path for the case + // where we can add all ranges from bundle1 at the end of bundle0. + if (SortBefore(bundle0->lastRange(), bundle1->firstRange())) { + while (LiveRange* range = bundle1->popFirstRange()) { + bundle0->addRangeAtEnd(range); + } + } else { + LiveRange* prevRange = nullptr; + while (LiveRange* range = bundle1->popFirstRange()) { + bundle0->addRange(range, prevRange); + prevRange = range; + } } - - return true; } // Helper for ::mergeAndQueueRegisters @@ -1970,11 +2244,14 @@ bool BacktrackingAllocator::tryMergeReusedRegister(VirtualRegister& def, // copies before def's instruction is crucial for generated code quality // (MUST_REUSE_INPUT is used for all arithmetic on x86/x64). - if (def.rangeFor(inputOf(def.ins()))) { + // Don't try to merge if the definition starts at the input point of the + // instruction. + if (def.firstRange()->from() == inputOf(def.ins())) { MOZ_ASSERT(def.isTemp()); def.setMustCopyInput(); return true; } + MOZ_ASSERT(def.firstRange()->from() == outputOf(def.ins())); if (!CanMergeTypesInBundle(def.type(), input.type())) { def.setMustCopyInput(); @@ -1986,14 +2263,20 @@ bool BacktrackingAllocator::tryMergeReusedRegister(VirtualRegister& def, // The input is not live after the instruction, either in a safepoint // for the instruction or in subsequent code. The input and output // can thus be in the same group. - return tryMergeBundles(def.firstBundle(), input.firstBundle()); + tryMergeBundles(def.firstBundle(), input.firstBundle()); + return true; } // Avoid merging in very large live ranges as merging has non-linear // complexity. The cutoff value is hard to gauge. 1M was chosen because it // is "large" and yet usefully caps compile time on AutoCad-for-the-web to - // something reasonable on a 2017-era desktop system. - const uint32_t RANGE_SIZE_CUTOFF = 1000000; + // something reasonable on a 2017-era desktop system. See bug 1728781. + // + // Subsequently -- bug 1897427 comment 9 -- even this threshold seems too + // high, resulting in delays of around 10 seconds. Setting it to 500000 + // "fixes" that one, but it seems prudent to reduce it to 250000 so as to + // avoid having to change it yet again at some future point. + const uint32_t RANGE_SIZE_CUTOFF = 250000; if (inputRange->to() - inputRange->from() > RANGE_SIZE_CUTOFF) { def.setMustCopyInput(); return true; @@ -2026,7 +2309,7 @@ bool BacktrackingAllocator::tryMergeReusedRegister(VirtualRegister& def, // If the input will start out in memory then adding a separate bundle for // memory uses after the def won't help. - if (input.def()->isFixed() && !input.def()->output()->isRegister()) { + if (input.def()->isFixed() && !input.def()->output()->isAnyRegister()) { def.setMustCopyInput(); return true; } @@ -2073,22 +2356,28 @@ bool BacktrackingAllocator::tryMergeReusedRegister(VirtualRegister& def, inputOf(def.ins()).bits()); LiveBundle* firstBundle = inputRange->bundle(); - input.removeRange(inputRange); - input.addRange(preRange); - input.addRange(postRange); + + // Note: this inserts an item at the beginning of the ranges vector. That's + // okay in this case because the checks above ensure this happens at most once + // for the |input| virtual register. + if (!input.replaceLastRangeLinear(inputRange, preRange, postRange)) { + return false; + } firstBundle->removeRange(inputRange); firstBundle->addRange(preRange); // The new range goes in a separate bundle, where it will be spilled during // allocation. - LiveBundle* secondBundle = LiveBundle::FallibleNew(alloc(), nullptr, nullptr); + LiveBundle* secondBundle = + LiveBundle::FallibleNew(alloc(), nullptr, nullptr, getNextBundleId()); if (!secondBundle) { return false; } - secondBundle->addRange(postRange); + secondBundle->addRangeAtEnd(postRange); - return tryMergeBundles(def.firstBundle(), input.firstBundle()); + tryMergeBundles(def.firstBundle(), input.firstBundle()); + return true; } bool BacktrackingAllocator::mergeAndQueueRegisters() { @@ -2101,14 +2390,13 @@ bool BacktrackingAllocator::mergeAndQueueRegisters() { continue; } - LiveBundle* bundle = LiveBundle::FallibleNew(alloc(), nullptr, nullptr); + LiveBundle* bundle = + LiveBundle::FallibleNew(alloc(), nullptr, nullptr, getNextBundleId()); if (!bundle) { return false; } - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); - bundle->addRange(range); + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + bundle->addRangeAtEnd(*iter); } } @@ -2126,10 +2414,8 @@ bool BacktrackingAllocator::mergeAndQueueRegisters() { VirtualRegister& originalVreg = vregs[original]; if (*originalVreg.def()->output() == *iter->getDef(i)->output()) { MOZ_ASSERT(originalVreg.ins()->isParameter()); - if (!tryMergeBundles(originalVreg.firstBundle(), - paramVreg.firstBundle())) { - return false; - } + tryMergeBundles(originalVreg.firstBundle(), + paramVreg.firstBundle()); found = true; break; } @@ -2166,10 +2452,7 @@ bool BacktrackingAllocator::mergeAndQueueRegisters() { VirtualRegister& outputVreg = vreg(phi->getDef(0)); for (size_t k = 0, kend = phi->numOperands(); k < kend; k++) { VirtualRegister& inputVreg = vreg(phi->getOperand(k)->toUse()); - if (!tryMergeBundles(inputVreg.firstBundle(), - outputVreg.firstBundle())) { - return false; - } + tryMergeBundles(inputVreg.firstBundle(), outputVreg.firstBundle()); } } } @@ -2183,9 +2466,8 @@ bool BacktrackingAllocator::mergeAndQueueRegisters() { allocateStackDefinition(reg); } - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + LiveRange* range = *iter; LiveBundle* bundle = range->bundle(); if (range == bundle->firstRange()) { if (!alloc().ensureBallast()) { @@ -2241,11 +2523,11 @@ bool BacktrackingAllocator::updateVirtualRegisterListsThenRequeueBundles( if (newBundle->numRanges() == bundle->numRanges() && computePriority(newBundle) == computePriority(bundle)) { bool different = false; - LiveRange::BundleLinkIterator oldRanges = bundle->rangesBegin(); - LiveRange::BundleLinkIterator newRanges = newBundle->rangesBegin(); + LiveBundle::RangeIterator oldRanges = bundle->rangesBegin(); + LiveBundle::RangeIterator newRanges = newBundle->rangesBegin(); while (oldRanges) { - LiveRange* oldRange = LiveRange::get(*oldRanges); - LiveRange* newRange = LiveRange::get(*newRanges); + LiveRange* oldRange = *oldRanges; + LiveRange* newRange = *newRanges; if (oldRange->from() != newRange->from() || oldRange->to() != newRange->to()) { different = true; @@ -2272,19 +2554,17 @@ bool BacktrackingAllocator::updateVirtualRegisterListsThenRequeueBundles( } // Remove all ranges in the old bundle from their register's list. - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); - range->vreg().removeRange(range); - } + bundle->removeAllRangesFromVirtualRegisters(); // Add all ranges in the new bundles to their register's list. for (size_t i = 0; i < newBundles.length(); i++) { LiveBundle* newBundle = newBundles[i]; - for (LiveRange::BundleLinkIterator iter = newBundle->rangesBegin(); iter; + for (LiveBundle::RangeIterator iter = newBundle->rangesBegin(); iter; iter++) { - LiveRange* range = LiveRange::get(*iter); - range->vreg().addRange(range); + LiveRange* range = *iter; + if (!range->vreg().addRange(range)) { + return false; + } } } @@ -2334,9 +2614,8 @@ static bool UseNewBundle(const SplitPositionVector& splitPositions, static bool HasPrecedingRangeSharingVreg(LiveBundle* bundle, LiveRange* range) { MOZ_ASSERT(range->bundle() == bundle); - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* prevRange = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* prevRange = *iter; if (prevRange == range) { return false; } @@ -2352,19 +2631,17 @@ static bool HasPrecedingRangeSharingVreg(LiveBundle* bundle, LiveRange* range) { static bool HasFollowingRangeSharingVreg(LiveBundle* bundle, LiveRange* range) { MOZ_ASSERT(range->bundle() == bundle); - bool foundRange = false; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* prevRange = LiveRange::get(*iter); - if (foundRange && &prevRange->vreg() == &range->vreg()) { + LiveBundle::RangeIterator iter = bundle->rangesBegin(range); + MOZ_ASSERT(*iter == range); + iter++; + + for (; iter; iter++) { + LiveRange* nextRange = *iter; + if (&nextRange->vreg() == &range->vreg()) { return true; } - if (prevRange == range) { - foundRange = true; - } } - MOZ_ASSERT(foundRange); return false; } @@ -2508,15 +2785,15 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, bool spillBundleIsNew = false; LiveBundle* spillBundle = bundle->spillParent(); if (!spillBundle) { - spillBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), nullptr); + spillBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), nullptr, + getNextBundleId()); if (!spillBundle) { return false; } spillBundleIsNew = true; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; CodePosition from = range->from(); if (isRegisterDefinition(range)) { @@ -2524,8 +2801,8 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, } if (from < range->to()) { - if (!spillBundle->addRange(alloc(), &range->vreg(), from, - range->to())) { + if (!spillBundle->addRangeAtEnd(alloc(), &range->vreg(), from, + range->to())) { return false; } @@ -2539,8 +2816,8 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, LiveBundleVector newBundles; // The bundle which ranges are currently being added to. - LiveBundle* activeBundle = - LiveBundle::FallibleNew(alloc(), bundle->spillSet(), spillBundle); + LiveBundle* activeBundle = LiveBundle::FallibleNew( + alloc(), bundle->spillSet(), spillBundle, getNextBundleId()); if (!activeBundle || !newBundles.append(activeBundle)) { return false; } @@ -2550,13 +2827,12 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, // Make new bundles according to the split positions, and distribute ranges // and uses to them. - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (UseNewBundle(splitPositions, range->from(), &activeSplitPosition)) { - activeBundle = - LiveBundle::FallibleNew(alloc(), bundle->spillSet(), spillBundle); + activeBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), + spillBundle, getNextBundleId()); if (!activeBundle || !newBundles.append(activeBundle)) { return false; } @@ -2567,7 +2843,7 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, if (!activeRange) { return false; } - activeBundle->addRange(activeRange); + activeBundle->addRangeAtEnd(activeRange); if (isRegisterDefinition(range)) { activeRange->setHasDefinition(); @@ -2595,8 +2871,8 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, activeRange->usesBegin()->pos != use->pos || activeRange->usesBegin()->usePolicy() == LUse::FIXED || use->usePolicy() == LUse::FIXED)) { - activeBundle = - LiveBundle::FallibleNew(alloc(), bundle->spillSet(), spillBundle); + activeBundle = LiveBundle::FallibleNew( + alloc(), bundle->spillSet(), spillBundle, getNextBundleId()); if (!activeBundle || !newBundles.append(activeBundle)) { return false; } @@ -2605,7 +2881,7 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, if (!activeRange) { return false; } - activeBundle->addRange(activeRange); + activeBundle->addRangeAtEnd(activeRange); } activeRange->addUse(use); @@ -2623,8 +2899,8 @@ bool BacktrackingAllocator::splitAt(LiveBundle* bundle, for (size_t i = 0; i < newBundles.length(); i++) { LiveBundle* bundle = newBundles[i]; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter;) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter;) { + LiveRange* range = *iter; if (!range->hasDefinition()) { if (!HasPrecedingRangeSharingVreg(bundle, range)) { @@ -2679,62 +2955,81 @@ bool BacktrackingAllocator::splitAcrossCalls(LiveBundle* bundle) { // Split the bundle to separate register uses and non-register uses and // allow the vreg to be spilled across its range. - // Find the locations of all calls in the bundle's range. - SplitPositionVector callPositions; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); - CallRange searchRange(range->from(), range->to()); - CallRange* callRange; - if (!callRanges.contains(&searchRange, &callRange)) { + // Locations of all calls in the bundle's range. This vector is sorted in + // ascending order because ranges in the bundle are sorted by start position + // and don't overlap + SplitPositionVector bundleCallPositions; + + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; + + // Append call positions in range [from+1, to) to bundleCallPositions. + // Calls at the beginning of the range are ignored because there is no + // splitting to do in this case. + + CodePosition from = range->from().next(); + if (from == range->to()) { + // Empty range can't contain any calls. + continue; + } + + // Use binary search to find the first call position. + Maybe index = lookupFirstCallPositionInRange(from, range->to()); + if (!index.isSome()) { // There are no calls inside this range. continue; } - MOZ_ASSERT(range->covers(callRange->range.from)); - // The search above returns an arbitrary call within the range. Walk - // backwards to find the first call in the range. - for (CallRangeList::reverse_iterator riter = - callRangesList.rbegin(callRange); - riter != callRangesList.rend(); ++riter) { - CodePosition pos = riter->range.from; - if (range->covers(pos)) { - callRange = *riter; - } else { + // Find the index of the last call within this range. + size_t startIndex = *index; + size_t endIndex = startIndex; + while (endIndex < callPositions.length() - 1) { + if (callPositions[endIndex + 1] >= range->to()) { break; } + endIndex++; } - // Add all call positions within the range, by walking forwards. - for (CallRangeList::iterator iter = callRangesList.begin(callRange); - iter != callRangesList.end(); ++iter) { - CodePosition pos = iter->range.from; - if (!range->covers(pos)) { - break; - } + MOZ_ASSERT(startIndex <= endIndex); - // Calls at the beginning of the range are ignored; there is no splitting - // to do. - if (range->covers(pos.previous())) { - MOZ_ASSERT_IF(callPositions.length(), pos > callPositions.back()); - if (!callPositions.append(pos)) { - return false; - } - } +#ifdef DEBUG + auto inRange = [range](CodePosition pos) { + return range->covers(pos) && pos != range->from(); + }; + + // Assert startIndex is the first call position in this range. + MOZ_ASSERT(inRange(callPositions[startIndex])); + MOZ_ASSERT_IF(startIndex > 0, !inRange(callPositions[startIndex - 1])); + + // Assert endIndex is the last call position in this range. + MOZ_ASSERT(inRange(callPositions[endIndex])); + MOZ_ASSERT_IF(endIndex + 1 < callPositions.length(), + !inRange(callPositions[endIndex + 1])); + + // Assert bundleCallPositions stays sorted. + MOZ_ASSERT_IF(!bundleCallPositions.empty(), + bundleCallPositions.back() < callPositions[startIndex]); +#endif + + const CodePosition* start = &callPositions[startIndex]; + size_t count = endIndex - startIndex + 1; + if (!bundleCallPositions.append(start, start + count)) { + return false; } } - MOZ_ASSERT(callPositions.length()); + + MOZ_ASSERT(!bundleCallPositions.empty()); #ifdef JS_JITSPEW JitSpewStart(JitSpew_RegAlloc, " .. split across calls at "); - for (size_t i = 0; i < callPositions.length(); ++i) { + for (size_t i = 0; i < bundleCallPositions.length(); ++i) { JitSpewCont(JitSpew_RegAlloc, "%s%u", i != 0 ? ", " : "", - callPositions[i].bits()); + bundleCallPositions[i].bits()); } JitSpewFin(JitSpew_RegAlloc); #endif - return splitAt(bundle, callPositions); + return splitAt(bundle, bundleCallPositions); } bool BacktrackingAllocator::trySplitAcrossHotcode(LiveBundle* bundle, @@ -2744,9 +3039,8 @@ bool BacktrackingAllocator::trySplitAcrossHotcode(LiveBundle* bundle, LiveRange* hotRange = nullptr; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (hotcode.contains(range, &hotRange)) { break; } @@ -2760,9 +3054,8 @@ bool BacktrackingAllocator::trySplitAcrossHotcode(LiveBundle* bundle, // Don't split if there is no cold code in the bundle. bool coldCode = false; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (!hotRange->contains(range)) { coldCode = true; break; @@ -2790,29 +3083,19 @@ bool BacktrackingAllocator::trySplitAcrossHotcode(LiveBundle* bundle, return splitAt(bundle, splitPositions); } - LiveBundle* hotBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), - bundle->spillParent()); + LiveBundle* hotBundle = LiveBundle::FallibleNew( + alloc(), bundle->spillSet(), bundle->spillParent(), getNextBundleId()); if (!hotBundle) { return false; } LiveBundle* preBundle = nullptr; LiveBundle* postBundle = nullptr; - LiveBundle* coldBundle = nullptr; - - if (testbed) { - coldBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), - bundle->spillParent()); - if (!coldBundle) { - return false; - } - } // Accumulate the ranges of hot and cold code in the bundle. Note that // we are only comparing with the single hot range found, so the cold code // may contain separate hot ranges. - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; LiveRange::Range hot, coldPre, coldPost; range->intersect(hotRange, &coldPre, &hot, &coldPost); @@ -2824,45 +3107,33 @@ bool BacktrackingAllocator::trySplitAcrossHotcode(LiveBundle* bundle, } if (!coldPre.empty()) { - if (testbed) { - if (!coldBundle->addRangeAndDistributeUses(alloc(), range, coldPre.from, - coldPre.to)) { - return false; - } - } else { + if (!preBundle) { + preBundle = + LiveBundle::FallibleNew(alloc(), bundle->spillSet(), + bundle->spillParent(), getNextBundleId()); if (!preBundle) { - preBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), - bundle->spillParent()); - if (!preBundle) { - return false; - } - } - if (!preBundle->addRangeAndDistributeUses(alloc(), range, coldPre.from, - coldPre.to)) { return false; } } + if (!preBundle->addRangeAndDistributeUses(alloc(), range, coldPre.from, + coldPre.to)) { + return false; + } } if (!coldPost.empty()) { - if (testbed) { - if (!coldBundle->addRangeAndDistributeUses( - alloc(), range, coldPost.from, coldPost.to)) { - return false; - } - } else { + if (!postBundle) { + postBundle = + LiveBundle::FallibleNew(alloc(), bundle->spillSet(), + bundle->spillParent(), getNextBundleId()); if (!postBundle) { - postBundle = LiveBundle::FallibleNew(alloc(), bundle->spillSet(), - bundle->spillParent()); - if (!postBundle) { - return false; - } - } - if (!postBundle->addRangeAndDistributeUses( - alloc(), range, coldPost.from, coldPost.to)) { return false; } } + if (!postBundle->addRangeAndDistributeUses(alloc(), range, coldPost.from, + coldPost.to)) { + return false; + } } } @@ -2873,19 +3144,12 @@ bool BacktrackingAllocator::trySplitAcrossHotcode(LiveBundle* bundle, return false; } - if (testbed) { - MOZ_ASSERT(coldBundle->numRanges() != 0); - if (!newBundles.append(coldBundle)) { - return false; - } - } else { - MOZ_ASSERT(preBundle || postBundle); - if (preBundle && !newBundles.append(preBundle)) { - return false; - } - if (postBundle && !newBundles.append(postBundle)) { - return false; - } + MOZ_ASSERT(preBundle || postBundle); + if (preBundle && !newBundles.append(preBundle)) { + return false; + } + if (postBundle && !newBundles.append(postBundle)) { + return false; } *success = true; @@ -2901,9 +3165,8 @@ bool BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveBundle* bundle, CodePosition lastRegisterFrom, lastRegisterTo, lastUse; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; // If the range defines a register, consider that a register use for // our purposes here. @@ -2972,18 +3235,17 @@ bool BacktrackingAllocator::trySplitBeforeFirstRegisterUse(LiveBundle* bundle, CodePosition conflictEnd; if (conflict) { - for (LiveRange::BundleLinkIterator iter = conflict->rangesBegin(); iter; + for (LiveBundle::RangeIterator iter = conflict->rangesBegin(); iter; iter++) { - LiveRange* range = LiveRange::get(*iter); + LiveRange* range = *iter; if (range->to() > conflictEnd) { conflictEnd = range->to(); } } } - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (!conflict || range->from() > conflictEnd) { if (range->hasDefinition() && isRegisterDefinition(range)) { @@ -3059,7 +3321,7 @@ bool BacktrackingAllocator::trySplitBeforeFirstRegisterUse(LiveBundle* bundle, // register uses". When combined with how ::splitAt works, the effect is to // spill the bundle. -bool BacktrackingAllocator::chooseBundleSplit(LiveBundle* bundle, bool fixed, +bool BacktrackingAllocator::chooseBundleSplit(LiveBundle* bundle, bool hasCall, LiveBundle* conflict) { bool success = false; @@ -3073,7 +3335,7 @@ bool BacktrackingAllocator::chooseBundleSplit(LiveBundle* bundle, bool fixed, return true; } - if (fixed) { + if (hasCall) { return splitAcrossCalls(bundle); } @@ -3111,9 +3373,8 @@ bool BacktrackingAllocator::computeRequirement(LiveBundle* bundle, // uses. Return false if there are conflicting requirements which will // require the bundle to be split. - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; VirtualRegister& reg = range->vreg(); if (range->hasDefinition()) { @@ -3181,19 +3442,22 @@ bool BacktrackingAllocator::computeRequirement(LiveBundle* bundle, bool BacktrackingAllocator::tryAllocateRegister(PhysicalRegister& r, LiveBundle* bundle, - bool* success, bool* pfixed, + bool* success, bool* hasCall, LiveBundleVector& conflicting) { *success = false; + // If we know this bundle contains a call (where all registers are spilled) we + // shouldn't try again to allocate a register. + MOZ_ASSERT(!*hasCall); + if (!r.allocatable) { return true; } LiveBundleVector aliasedConflicting; - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; LiveRangePlus rangePlus(range); // All ranges in the bundle must be compatible with the physical register. @@ -3208,7 +3472,8 @@ bool BacktrackingAllocator::tryAllocateRegister(PhysicalRegister& r, } const LiveRange* existing = existingPlus.liveRange(); if (existing->hasVreg()) { - MOZ_ASSERT(existing->bundle()->allocation().toRegister() == rAlias.reg); + MOZ_ASSERT(existing->bundle()->allocation().toAnyRegister() == + rAlias.reg); bool duplicate = false; for (size_t i = 0; i < aliasedConflicting.length(); i++) { if (aliasedConflicting[i] == existing->bundle()) { @@ -3220,9 +3485,11 @@ bool BacktrackingAllocator::tryAllocateRegister(PhysicalRegister& r, return false; } } else { + // This bundle contains a call instruction. + MOZ_ASSERT(lookupFirstCallPositionInRange(range->from(), range->to())); JitSpewIfEnabled(JitSpew_RegAlloc, " %s collides with fixed use %s", rAlias.reg.name(), existing->toString().get()); - *pfixed = true; + *hasCall = true; return true; } MOZ_ASSERT(r.reg.numAliased() == numAliased); @@ -3268,9 +3535,8 @@ bool BacktrackingAllocator::tryAllocateRegister(PhysicalRegister& r, JitSpewIfEnabled(JitSpew_RegAlloc, " allocated to %s", r.reg.name()); - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (!alloc().ensureBallast()) { return false; } @@ -3286,7 +3552,7 @@ bool BacktrackingAllocator::tryAllocateRegister(PhysicalRegister& r, } bool BacktrackingAllocator::tryAllocateAnyRegister( - LiveBundle* bundle, bool* success, bool* pfixed, + LiveBundle* bundle, bool* success, bool* hasCall, LiveBundleVector& conflicting) { // Search for any available register which the bundle can be allocated to. @@ -3297,25 +3563,35 @@ bool BacktrackingAllocator::tryAllocateAnyRegister( if (!LDefinition::isFloatRegCompatible(type, registers[i].reg.fpu())) { continue; } - if (!tryAllocateRegister(registers[i], bundle, success, pfixed, + if (!tryAllocateRegister(registers[i], bundle, success, hasCall, conflicting)) { return false; } if (*success) { break; } + if (*hasCall) { + // This bundle contains a call instruction. Calls require spilling all + // registers, so we have to split or spill this bundle. + break; + } } return true; } for (size_t i = 0; i < AnyRegister::FirstFloatReg; i++) { - if (!tryAllocateRegister(registers[i], bundle, success, pfixed, + if (!tryAllocateRegister(registers[i], bundle, success, hasCall, conflicting)) { return false; } if (*success) { break; } + if (*hasCall) { + // This bundle contains a call instruction. Calls require spilling all + // registers, so we have to split or spill this bundle. + break; + } } return true; } @@ -3326,13 +3602,12 @@ bool BacktrackingAllocator::evictBundle(LiveBundle* bundle) { bundle->toString().get(), computePriority(bundle), computeSpillWeight(bundle)); - AnyRegister reg(bundle->allocation().toRegister()); + AnyRegister reg(bundle->allocation().toAnyRegister()); PhysicalRegister& physical = registers[reg.code()]; MOZ_ASSERT(physical.reg == reg && physical.allocatable); - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; LiveRangePlus rangePlus(range); physical.allocations.remove(rangePlus); } @@ -3345,45 +3620,32 @@ bool BacktrackingAllocator::evictBundle(LiveBundle* bundle) { bool BacktrackingAllocator::tryAllocateFixed(LiveBundle* bundle, Requirement requirement, - bool* success, bool* pfixed, + bool* success, bool* hasCall, LiveBundleVector& conflicting) { // Spill bundles which are required to be in a certain stack slot. - if (!requirement.allocation().isRegister()) { + if (!requirement.allocation().isAnyRegister()) { JitSpew(JitSpew_RegAlloc, " stack allocation requirement"); bundle->setAllocation(requirement.allocation()); *success = true; return true; } - AnyRegister reg = requirement.allocation().toRegister(); - return tryAllocateRegister(registers[reg.code()], bundle, success, pfixed, + AnyRegister reg = requirement.allocation().toAnyRegister(); + return tryAllocateRegister(registers[reg.code()], bundle, success, hasCall, conflicting); } bool BacktrackingAllocator::tryAllocateNonFixed(LiveBundle* bundle, Requirement requirement, Requirement hint, bool* success, - bool* pfixed, + bool* hasCall, LiveBundleVector& conflicting) { - // If we want, but do not require a bundle to be in a specific register, - // only look at that register for allocating and evict or spill if it is - // not available. Picking a separate register may be even worse than - // spilling, as it will still necessitate moves and will tie up more - // registers than if we spilled. - if (hint.kind() == Requirement::FIXED) { - AnyRegister reg = hint.allocation().toRegister(); - if (!tryAllocateRegister(registers[reg.code()], bundle, success, pfixed, - conflicting)) { - return false; - } - if (*success) { - return true; - } - } + MOZ_ASSERT(hint.kind() != Requirement::FIXED); + MOZ_ASSERT(conflicting.empty()); // Spill bundles which have no hint or register requirement. if (requirement.kind() == Requirement::NONE && - hint.kind() != Requirement::REGISTER) { + hint.kind() == Requirement::NONE) { JitSpew(JitSpew_RegAlloc, " postponed spill (no hint or register requirement)"); if (!spilledBundles.append(bundle)) { @@ -3393,13 +3655,11 @@ bool BacktrackingAllocator::tryAllocateNonFixed(LiveBundle* bundle, return true; } - if (conflicting.empty() || minimalBundle(bundle)) { - if (!tryAllocateAnyRegister(bundle, success, pfixed, conflicting)) { - return false; - } - if (*success) { - return true; - } + if (!tryAllocateAnyRegister(bundle, success, hasCall, conflicting)) { + return false; + } + if (*success) { + return true; } // Spill bundles which have no register requirement if they didn't get @@ -3418,7 +3678,7 @@ bool BacktrackingAllocator::tryAllocateNonFixed(LiveBundle* bundle, return true; } -bool BacktrackingAllocator::processBundle(MIRGenerator* mir, +bool BacktrackingAllocator::processBundle(const MIRGenerator* mir, LiveBundle* bundle) { JitSpewIfEnabled(JitSpew_RegAlloc, "Allocating %s [priority %zu] [weight %zu]", @@ -3448,28 +3708,30 @@ bool BacktrackingAllocator::processBundle(MIRGenerator* mir, // for higher weight bundles. Requirement requirement, hint; - bool canAllocate = computeRequirement(bundle, &requirement, &hint); + bool doesNotHaveFixedConflict = + computeRequirement(bundle, &requirement, &hint); - bool fixed; + bool hasCall = false; LiveBundleVector conflicting; - for (size_t attempt = 0;; attempt++) { - if (mir->shouldCancel("Backtracking Allocation (processBundle loop)")) { - return false; - } - if (canAllocate) { + if (doesNotHaveFixedConflict) { + for (size_t attempt = 0;; attempt++) { + if (mir->shouldCancel("Backtracking Allocation (processBundle loop)")) { + return false; + } + bool success = false; - fixed = false; + hasCall = false; conflicting.clear(); // Ok, let's try allocating for this bundle. if (requirement.kind() == Requirement::FIXED) { - if (!tryAllocateFixed(bundle, requirement, &success, &fixed, + if (!tryAllocateFixed(bundle, requirement, &success, &hasCall, conflicting)) { return false; } } else { - if (!tryAllocateNonFixed(bundle, requirement, hint, &success, &fixed, + if (!tryAllocateNonFixed(bundle, requirement, hint, &success, &hasCall, conflicting)) { return false; } @@ -3480,9 +3742,9 @@ bool BacktrackingAllocator::processBundle(MIRGenerator* mir, return true; } - // If that didn't work, but we have one or more non-fixed bundles - // known to be conflicting, maybe we can evict them and try again. - if ((attempt < MAX_ATTEMPTS || minimalBundle(bundle)) && !fixed && + // If that didn't work, but we have one or more non-call bundles known to + // be conflicting, maybe we can evict them and try again. + if ((attempt < MAX_ATTEMPTS || minimalBundle(bundle)) && !hasCall && !conflicting.empty() && maximumSpillWeight(conflicting) < computeSpillWeight(bundle)) { for (size_t i = 0; i < conflicting.length(); i++) { @@ -3492,17 +3754,20 @@ bool BacktrackingAllocator::processBundle(MIRGenerator* mir, } continue; } + + // We have to split this bundle. + break; } - - // A minimal bundle cannot be split any further. If we try to split it - // it at this point we will just end up with the same bundle and will - // enter an infinite loop. Weights and the initial live ranges must - // be constructed so that any minimal bundle is allocatable. - MOZ_ASSERT(!minimalBundle(bundle)); - - LiveBundle* conflict = conflicting.empty() ? nullptr : conflicting[0]; - return chooseBundleSplit(bundle, canAllocate && fixed, conflict); } + + // A minimal bundle cannot be split any further. If we try to split it + // it at this point we will just end up with the same bundle and will + // enter an infinite loop. Weights and the initial live ranges must + // be constructed so that any minimal bundle is allocatable. + MOZ_ASSERT(!minimalBundle(bundle)); + + LiveBundle* conflict = conflicting.empty() ? nullptr : conflicting[0]; + return chooseBundleSplit(bundle, hasCall, conflict); } // Helper for ::tryAllocatingRegistersForSpillBundles @@ -3512,16 +3777,14 @@ bool BacktrackingAllocator::spill(LiveBundle* bundle) { if (LiveBundle* spillParent = bundle->spillParent()) { JitSpew(JitSpew_RegAlloc, " Using existing spill bundle"); - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; LiveRange* parentRange = spillParent->rangeFor(range->from()); MOZ_ASSERT(parentRange->contains(range)); MOZ_ASSERT(&range->vreg() == &parentRange->vreg()); range->tryToMoveDefAndUsesInto(parentRange); - MOZ_ASSERT(!range->hasUses()); - range->vreg().removeRange(range); } + bundle->removeAllRangesFromVirtualRegisters(); return true; } @@ -3532,7 +3795,7 @@ bool BacktrackingAllocator::tryAllocatingRegistersForSpillBundles() { for (auto it = spilledBundles.begin(); it != spilledBundles.end(); it++) { LiveBundle* bundle = *it; LiveBundleVector conflicting; - bool fixed = false; + bool hasCall = false; bool success = false; if (mir->shouldCancel("Backtracking Try Allocating Spilled Bundles")) { @@ -3542,7 +3805,7 @@ bool BacktrackingAllocator::tryAllocatingRegistersForSpillBundles() { JitSpewIfEnabled(JitSpew_RegAlloc, "Spill or allocate %s", bundle->toString().get()); - if (!tryAllocateAnyRegister(bundle, &success, &fixed, conflicting)) { + if (!tryAllocateAnyRegister(bundle, &success, &hasCall, conflicting)) { return false; } @@ -3569,9 +3832,8 @@ bool BacktrackingAllocator::tryAllocatingRegistersForSpillBundles() { // Helper for ::pickStackSlot bool BacktrackingAllocator::insertAllRanges(LiveRangePlusSet& set, LiveBundle* bundle) { - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (!alloc().ensureBallast()) { return false; } @@ -3583,6 +3845,13 @@ bool BacktrackingAllocator::insertAllRanges(LiveRangePlusSet& set, return true; } +void BacktrackingAllocator::sortVirtualRegisterRanges() { + for (size_t i = 1; i < graph.numVirtualRegisters(); i++) { + VirtualRegister& reg = vregs[i]; + reg.sortRanges(); + } +} + // Helper for ::pickStackSlots bool BacktrackingAllocator::pickStackSlot(SpillSet* spillSet) { // Look through all ranges that have been spilled in this set for a @@ -3592,13 +3861,12 @@ bool BacktrackingAllocator::pickStackSlot(SpillSet* spillSet) { // from multiple virtual registers. for (size_t i = 0; i < spillSet->numSpilledBundles(); i++) { LiveBundle* bundle = spillSet->spilledBundle(i); - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { + LiveRange* range = *iter; if (range->hasDefinition()) { LDefinition* def = range->vreg().def(); if (def->policy() == LDefinition::FIXED) { - MOZ_ASSERT(!def->output()->isRegister()); + MOZ_ASSERT(!def->output()->isAnyRegister()); MOZ_ASSERT(!def->output()->isStackSlot()); spillSet->setAllocation(*def->output()); return true; @@ -3611,14 +3879,14 @@ bool BacktrackingAllocator::pickStackSlot(SpillSet* spillSet) { spillSet->spilledBundle(0)->firstRange()->vreg().type(); SpillSlotList* slotList; - switch (StackSlotAllocator::width(type)) { - case 4: + switch (LStackSlot::width(type)) { + case LStackSlot::Word: slotList = &normalSlots; break; - case 8: + case LStackSlot::DoubleWord: slotList = &doubleSlots; break; - case 16: + case LStackSlot::QuadWord: slotList = &quadSlots; break; default: @@ -3643,9 +3911,9 @@ bool BacktrackingAllocator::pickStackSlot(SpillSet* spillSet) { bool success = true; for (size_t i = 0; i < spillSet->numSpilledBundles(); i++) { LiveBundle* bundle = spillSet->spilledBundle(i); - for (LiveRange::BundleLinkIterator iter = bundle->rangesBegin(); iter; + for (LiveBundle::RangeIterator iter = bundle->rangesBegin(); iter; iter++) { - LiveRange* range = LiveRange::get(*iter); + LiveRange* range = *iter; LiveRangePlus rangePlus(range); LiveRangePlus existingPlus; if (spillSlot->allocated.contains(rangePlus, &existingPlus)) { @@ -3682,10 +3950,11 @@ bool BacktrackingAllocator::pickStackSlot(SpillSet* spillSet) { } // We need a new physical stack slot. - uint32_t stackSlot = stackSlotAllocator.allocateSlot(type); + LStackSlot::Width width = LStackSlot::width(type); + uint32_t stackSlot = stackSlotAllocator.allocateSlot(width); SpillSlot* spillSlot = - new (alloc().fallible()) SpillSlot(stackSlot, alloc().lifoAlloc()); + new (alloc().fallible()) SpillSlot(stackSlot, width, alloc().lifoAlloc()); if (!spillSlot) { return false; } @@ -3711,10 +3980,8 @@ bool BacktrackingAllocator::pickStackSlots() { return false; } - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); - LiveBundle* bundle = range->bundle(); + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + LiveBundle* bundle = iter->bundle(); if (bundle->allocation().isBogus()) { if (!pickStackSlot(bundle->spillSet())) { @@ -3741,39 +4008,132 @@ bool BacktrackingAllocator::moveAtEdge(LBlock* predecessor, LBlock* successor, } // Helper for ::createMoveGroupsFromLiveRangeTransitions -bool BacktrackingAllocator::deadRange(LiveRange* range) { - // Check for direct uses of this range. - if (range->hasUses() || range->hasDefinition()) { - return false; - } - - CodePosition start = range->from(); - LNode* ins = insData[start]; - if (start == entryOf(ins->block())) { - return false; - } - - VirtualRegister& reg = range->vreg(); - - // Check if there are later ranges for this vreg. - LiveRange::RegisterLinkIterator iter = reg.rangesBegin(range); - for (iter++; iter; iter++) { - LiveRange* laterRange = LiveRange::get(*iter); - if (laterRange->from() > range->from()) { +void BacktrackingAllocator::removeDeadRanges(VirtualRegister& reg) { + auto isDeadRange = [&](VirtualRegister::RangeVector& ranges, + LiveRange* range) { + // Check for direct uses of this range. + if (range->hasUses() || range->hasDefinition()) { return false; } - } - // Check if this range ends at a loop backedge. - LNode* last = insData[range->to().previous()]; - if (last->isGoto() && - last->toGoto()->target()->id() < last->block()->mir()->id()) { - return false; - } + // Check if there are later ranges for this vreg. The first item in the list + // must have the highest start position so we compare against that one. + CodePosition start = range->from(); + CodePosition maxFrom = ranges[0]->from(); + if (maxFrom > start) { + return false; + } - // Check if there are phis which this vreg flows to. - if (reg.usedByPhi()) { - return false; + LNode* ins = insData[start]; + if (start == entryOf(ins->block())) { + return false; + } + + // Check if this range ends at a loop backedge. + LNode* last = insData[range->to().previous()]; + if (last->isGoto() && + last->toGoto()->target()->id() < last->block()->mir()->id()) { + return false; + } + + // Check if there are phis which this vreg flows to. + if (reg.usedByPhi()) { + return false; + } + + return true; + }; + + reg.removeRangesIf(isDeadRange); +} + +static void AssertCorrectRangeForPosition(const VirtualRegister& reg, + CodePosition pos, + const LiveRange* range) { + MOZ_ASSERT(range->covers(pos)); +#ifdef DEBUG + // Assert the result is consistent with rangeFor. The ranges can be different + // but must be equivalent (both register or both non-register ranges). + LiveRange* expected = reg.rangeFor(pos, /* preferRegister = */ true); + MOZ_ASSERT(range->bundle()->allocation().isAnyRegister() == + expected->bundle()->allocation().isAnyRegister()); +#endif +} + +// Helper for ::createMoveGroupsFromLiveRangeTransitions +bool BacktrackingAllocator::createMoveGroupsForControlFlowEdges( + const VirtualRegister& reg, const ControlFlowEdgeVector& edges) { + // Iterate over both the virtual register ranges (sorted by start position) + // and the control flow edges (sorted by predecessorExit). When we find the + // predecessor range for the next edge, add a move from predecessor range to + // successor range. + + VirtualRegister::RangeIterator iter(reg); + LiveRange* nonRegisterRange = nullptr; + + for (const ControlFlowEdge& edge : edges) { + CodePosition pos = edge.predecessorExit; + LAllocation successorAllocation = + edge.successorRange->bundle()->allocation(); + + // We don't need to insert a move if nonRegisterRange covers the predecessor + // block exit and has the same allocation as the successor block. This check + // is not required for correctness but it reduces the number of generated + // moves. + if (nonRegisterRange && pos < nonRegisterRange->to() && + nonRegisterRange->bundle()->allocation() == successorAllocation) { + MOZ_ASSERT(nonRegisterRange->covers(pos)); + continue; + } + + // Search for a matching range. Prefer a register range. + LiveRange* predecessorRange = nullptr; + bool foundSameAllocation = false; + while (true) { + if (iter.done() || iter->from() > pos) { + // No register range covers this edge. + predecessorRange = nonRegisterRange; + break; + } + if (iter->to() <= pos) { + // Skip ranges that end before this edge (and later edges). + iter++; + continue; + } + MOZ_ASSERT(iter->covers(pos)); + if (iter->bundle()->allocation() == successorAllocation) { + // There's a range covering the predecessor block exit that has the same + // allocation, so we don't need to insert a move. This check is not + // required for correctness but it reduces the number of generated + // moves. + foundSameAllocation = true; + break; + } + if (iter->bundle()->allocation().isAnyRegister()) { + predecessorRange = *iter; + break; + } + if (!nonRegisterRange || iter->to() > nonRegisterRange->to()) { + nonRegisterRange = *iter; + } + iter++; + } + + if (foundSameAllocation) { + continue; + } + + MOZ_ASSERT(predecessorRange); + AssertCorrectRangeForPosition(reg, pos, predecessorRange); + + if (!alloc().ensureBallast()) { + return false; + } + JitSpew(JitSpew_RegAlloc, " (moveAtEdge#2)"); + if (!moveAtEdge(edge.predecessor, edge.successor, predecessorRange, + edge.successorRange, reg.type())) { + return false; + } } return true; @@ -3797,24 +4157,43 @@ bool BacktrackingAllocator::createMoveGroupsFromLiveRangeTransitions() { return false; } - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter;) { - LiveRange* range = LiveRange::get(*iter); + // Remove ranges which will never be used. + removeDeadRanges(reg); + + LiveRange* registerRange = nullptr; + LiveRange* nonRegisterRange = nullptr; + VirtualRegister::RangeIterator iter(reg); + + // Keep track of the register and non-register ranges with the highest end + // position before advancing the iterator. These are predecessor ranges for + // later ranges. + auto moveToNextRange = [&](LiveRange* range) { + MOZ_ASSERT(*iter == range); + if (range->bundle()->allocation().isAnyRegister()) { + if (!registerRange || range->to() > registerRange->to()) { + registerRange = range; + } + } else { + if (!nonRegisterRange || range->to() > nonRegisterRange->to()) { + nonRegisterRange = range; + } + } + iter++; + }; + + // Iterate over all ranges. + while (!iter.done()) { + LiveRange* range = *iter; if (mir->shouldCancel( "Backtracking Resolve Control Flow (vreg inner loop)")) { return false; } - // Remove ranges which will never be used. - if (deadRange(range)) { - reg.removeRangeAndIncrement(iter); - continue; - } - // The range which defines the register does not have a predecessor // to add moves from. if (range->hasDefinition()) { - iter++; + moveToNextRange(range); continue; } @@ -3823,51 +4202,60 @@ bool BacktrackingAllocator::createMoveGroupsFromLiveRangeTransitions() { CodePosition start = range->from(); LNode* ins = insData[start]; if (start == entryOf(ins->block())) { - iter++; + moveToNextRange(range); continue; } - // If we already saw a range which covers the start of this range - // and has the same allocation, we don't need an explicit move at - // the start of this range. - bool skip = false; - for (LiveRange::RegisterLinkIterator prevIter = reg.rangesBegin(); - prevIter != iter; prevIter++) { - LiveRange* prevRange = LiveRange::get(*prevIter); - if (prevRange->covers(start) && prevRange->bundle()->allocation() == - range->bundle()->allocation()) { - skip = true; - break; - } - } - if (skip) { - iter++; - continue; - } - - if (!alloc().ensureBallast()) { - return false; - } - - LiveRange* predecessorRange = - reg.rangeFor(start.previous(), /* preferRegister = */ true); - if (start.subpos() == CodePosition::INPUT) { - JitSpewIfEnabled(JitSpew_RegAlloc, " moveInput (%s) <- (%s)", - range->toString().get(), - predecessorRange->toString().get()); - if (!moveInput(ins->toInstruction(), predecessorRange, range, - reg.type())) { - return false; - } + // Determine the predecessor range to use for this range and other ranges + // starting at the same position. Prefer a register range. + LiveRange* predecessorRange = nullptr; + if (registerRange && start.previous() < registerRange->to()) { + predecessorRange = registerRange; } else { - JitSpew(JitSpew_RegAlloc, " (moveAfter)"); - if (!moveAfter(ins->toInstruction(), predecessorRange, range, - reg.type())) { + MOZ_ASSERT(nonRegisterRange); + MOZ_ASSERT(start.previous() < nonRegisterRange->to()); + predecessorRange = nonRegisterRange; + } + AssertCorrectRangeForPosition(reg, start.previous(), predecessorRange); + + // Add moves from predecessorRange to all ranges that start here. + do { + range = *iter; + MOZ_ASSERT(!range->hasDefinition()); + + if (!alloc().ensureBallast()) { return false; } - } - iter++; +#ifdef DEBUG + // If we already saw a range which covers the start of this range, it + // must have a different allocation. + for (VirtualRegister::RangeIterator prevIter(reg); *prevIter != range; + prevIter++) { + MOZ_ASSERT_IF(prevIter->covers(start), + prevIter->bundle()->allocation() != + range->bundle()->allocation()); + } +#endif + + if (start.subpos() == CodePosition::INPUT) { + JitSpewIfEnabled(JitSpew_RegAlloc, " moveInput (%s) <- (%s)", + range->toString().get(), + predecessorRange->toString().get()); + if (!moveInput(ins->toInstruction(), predecessorRange, range, + reg.type())) { + return false; + } + } else { + JitSpew(JitSpew_RegAlloc, " (moveAfter)"); + if (!moveAfter(ins->toInstruction(), predecessorRange, range, + reg.type())) { + return false; + } + } + + moveToNextRange(range); + } while (!iter.done() && iter->from() == start); } } @@ -3891,8 +4279,8 @@ bool BacktrackingAllocator::createMoveGroupsFromLiveRangeTransitions() { MOZ_ASSERT(phi->numDefs() == 1); LDefinition* def = phi->getDef(0); VirtualRegister& reg = vreg(def); - LiveRange* to = reg.rangeFor(entryOf(successor)); - MOZ_ASSERT(to); + LiveRange* to = reg.firstRange(); + MOZ_ASSERT(to->from() == entryOf(successor)); for (size_t k = 0; k < mSuccessor->numPredecessors(); k++) { LBlock* predecessor = mSuccessor->getPredecessor(k)->lir(); @@ -3922,11 +4310,17 @@ bool BacktrackingAllocator::createMoveGroupsFromLiveRangeTransitions() { // Add moves to resolve graph edges with different allocations at their // source and target. + ControlFlowEdgeVector edges; for (size_t i = 1; i < graph.numVirtualRegisters(); i++) { VirtualRegister& reg = vregs[i]; - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - LiveRange* targetRange = LiveRange::get(*iter); + + // First collect all control flow edges we need to resolve. This loop knows + // the range on the successor side, but looking up the corresponding + // predecessor range with rangeFor is quadratic so we handle that + // differently. + edges.clear(); + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + LiveRange* targetRange = *iter; size_t firstBlockId = insData[targetRange->from()]->block()->mir()->id(); if (!targetRange->covers(entryOf(graph.getBlock(firstBlockId)))) { @@ -3938,29 +4332,41 @@ bool BacktrackingAllocator::createMoveGroupsFromLiveRangeTransitions() { break; } - BitSet& live = liveIn[id]; + VirtualRegBitSet& live = liveIn[id]; if (!live.contains(i)) { continue; } for (size_t j = 0; j < successor->mir()->numPredecessors(); j++) { LBlock* predecessor = successor->mir()->getPredecessor(j)->lir(); - if (targetRange->covers(exitOf(predecessor))) { + CodePosition predecessorExit = exitOf(predecessor); + if (targetRange->covers(predecessorExit)) { continue; } - - if (!alloc().ensureBallast()) { - return false; - } - JitSpew(JitSpew_RegAlloc, " (moveAtEdge#2)"); - LiveRange* from = reg.rangeFor(exitOf(predecessor), true); - if (!moveAtEdge(predecessor, successor, from, targetRange, - reg.type())) { + if (!edges.emplaceBack(predecessor, successor, targetRange, + predecessorExit)) { return false; } } } } + + if (edges.empty()) { + continue; + } + + // Sort edges by predecessor position. This doesn't need to be a stable sort + // because createMoveGroupsForControlFlowEdges will use the same predecessor + // range if there are multiple edges with the same predecessor position. + auto compareEdges = [](const ControlFlowEdge& a, const ControlFlowEdge& b) { + return a.predecessorExit < b.predecessorExit; + }; + std::sort(edges.begin(), edges.end(), compareEdges); + + // Resolve edges and add move groups. + if (!createMoveGroupsForControlFlowEdges(reg, edges)) { + return false; + } } JitSpew(JitSpew_RegAlloc, "ResolveControlFlow: end"); @@ -3968,11 +4374,16 @@ bool BacktrackingAllocator::createMoveGroupsFromLiveRangeTransitions() { } // Helper for ::addLiveRegistersForRange -size_t BacktrackingAllocator::findFirstNonCallSafepoint(CodePosition from) { - size_t i = 0; - for (; i < graph.numNonCallSafepoints(); i++) { - const LInstruction* ins = graph.getNonCallSafepoint(i); - if (from <= inputOf(ins)) { +size_t BacktrackingAllocator::findFirstNonCallSafepoint(CodePosition pos, + size_t startFrom) { + // Assert startFrom is valid. + MOZ_ASSERT_IF(startFrom > 0, + inputOf(nonCallSafepoints_[startFrom - 1]) < pos); + + size_t i = startFrom; + for (; i < nonCallSafepoints_.length(); i++) { + const LInstruction* ins = nonCallSafepoints_[i]; + if (pos <= inputOf(ins)) { break; } } @@ -3980,33 +4391,39 @@ size_t BacktrackingAllocator::findFirstNonCallSafepoint(CodePosition from) { } // Helper for ::installAllocationsInLIR -void BacktrackingAllocator::addLiveRegistersForRange(VirtualRegister& reg, - LiveRange* range) { +void BacktrackingAllocator::addLiveRegistersForRange( + VirtualRegister& reg, LiveRange* range, size_t* firstNonCallSafepoint) { // Fill in the live register sets for all non-call safepoints. LAllocation a = range->bundle()->allocation(); - if (!a.isRegister()) { + if (!a.isAnyRegister()) { return; } // Don't add output registers to the safepoint. CodePosition start = range->from(); - if (range->hasDefinition() && !reg.isTemp()) { + if (range->hasDefinition()) { #ifdef CHECK_OSIPOINT_REGISTERS - // We don't add the output register to the safepoint, - // but it still might get added as one of the inputs. - // So eagerly add this reg to the safepoint clobbered registers. - if (reg.ins()->isInstruction()) { + // Add output and temp registers to the safepoint's clobberedRegs. + // Note: the outputs aren't added to the safepoint's liveRegs here, but the + // same register might still be added to liveRegs for one of the inputs, so + // we have to add outputs to clobberedRegs here. + if (reg.ins()->isInstruction() && !reg.ins()->isCall()) { if (LSafepoint* safepoint = reg.ins()->toInstruction()->safepoint()) { - safepoint->addClobberedRegister(a.toRegister()); + safepoint->addClobberedRegister(a.toAnyRegister()); } } #endif - start = start.next(); + if (!reg.isTemp()) { + start = start.next(); + } } - size_t i = findFirstNonCallSafepoint(start); - for (; i < graph.numNonCallSafepoints(); i++) { - LInstruction* ins = graph.getNonCallSafepoint(i); + *firstNonCallSafepoint = + findFirstNonCallSafepoint(start, *firstNonCallSafepoint); + + for (size_t i = *firstNonCallSafepoint; i < nonCallSafepoints_.length(); + i++) { + LInstruction* ins = nonCallSafepoints_[i]; CodePosition pos = inputOf(ins); // Safepoints are sorted, so we can shortcut out of this loop @@ -4018,13 +4435,7 @@ void BacktrackingAllocator::addLiveRegistersForRange(VirtualRegister& reg, MOZ_ASSERT(range->covers(pos)); LSafepoint* safepoint = ins->safepoint(); - safepoint->addLiveRegister(a.toRegister()); - -#ifdef CHECK_OSIPOINT_REGISTERS - if (reg.isTemp()) { - safepoint->addClobberedRegister(a.toRegister()); - } -#endif + safepoint->addLiveRegister(a.toAnyRegister()); } } @@ -4043,6 +4454,12 @@ static inline size_t NumReusingDefs(LInstruction* ins) { bool BacktrackingAllocator::installAllocationsInLIR() { JitSpew(JitSpew_RegAlloc, "Installing Allocations"); + // The virtual registers and safepoints are both ordered by position. To avoid + // quadratic behavior in findFirstNonCallSafepoint, we use + // firstNonCallSafepoint as cursor to start the search at the safepoint + // returned by the previous call. + size_t firstNonCallSafepoint = 0; + MOZ_ASSERT(!vregs[0u].hasRanges()); for (size_t i = 1; i < graph.numVirtualRegisters(); i++) { VirtualRegister& reg = vregs[i]; @@ -4051,9 +4468,15 @@ bool BacktrackingAllocator::installAllocationsInLIR() { return false; } - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + firstNonCallSafepoint = + findFirstNonCallSafepoint(inputOf(reg.ins()), firstNonCallSafepoint); + + // The ranges are sorted by start position, so we can use the same + // findFirstNonCallSafepoint optimization here. + size_t firstNonCallSafepointForRange = firstNonCallSafepoint; + + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + LiveRange* range = *iter; if (range->hasDefinition()) { reg.def()->setOutput(range->bundle()->allocation()); @@ -4077,7 +4500,8 @@ bool BacktrackingAllocator::installAllocationsInLIR() { // add copies if the use and def have different allocations. LNode* ins = insData[iter->pos]; if (LDefinition* def = FindReusingDefOrTemp(ins, alloc)) { - LiveRange* outputRange = vreg(def).rangeFor(outputOf(ins)); + LiveRange* outputRange = vreg(def).firstRange(); + MOZ_ASSERT(outputRange->covers(outputOf(ins))); LAllocation res = outputRange->bundle()->allocation(); LAllocation sourceAlloc = range->bundle()->allocation(); @@ -4101,7 +4525,7 @@ bool BacktrackingAllocator::installAllocationsInLIR() { } } - addLiveRegistersForRange(reg, range); + addLiveRegistersForRange(reg, range, &firstNonCallSafepointForRange); } } @@ -4112,9 +4536,12 @@ bool BacktrackingAllocator::installAllocationsInLIR() { // Helper for ::populateSafepoints size_t BacktrackingAllocator::findFirstSafepoint(CodePosition pos, size_t startFrom) { + // Assert startFrom is valid. + MOZ_ASSERT_IF(startFrom > 0, inputOf(safepoints_[startFrom - 1]) < pos); + size_t i = startFrom; - for (; i < graph.numSafepoints(); i++) { - LInstruction* ins = graph.getSafepoint(i); + for (; i < safepoints_.length(); i++) { + LInstruction* ins = safepoints_[i]; if (pos <= inputOf(ins)) { break; } @@ -4122,54 +4549,19 @@ size_t BacktrackingAllocator::findFirstSafepoint(CodePosition pos, return i; } -// Helper for ::populateSafepoints -static inline bool IsNunbox(VirtualRegister& reg) { -#ifdef JS_NUNBOX32 - return reg.type() == LDefinition::TYPE || reg.type() == LDefinition::PAYLOAD; -#else - return false; -#endif -} - -// Helper for ::populateSafepoints -static inline bool IsSlotsOrElements(VirtualRegister& reg) { - return reg.type() == LDefinition::SLOTS; -} - -// Helper for ::populateSafepoints -static inline bool IsTraceable(VirtualRegister& reg) { - if (reg.type() == LDefinition::OBJECT || - reg.type() == LDefinition::WASM_ANYREF) { - return true; - } -#ifdef JS_PUNBOX64 - if (reg.type() == LDefinition::BOX) { - return true; - } -#endif - if (reg.type() == LDefinition::STACKRESULTS) { - MOZ_ASSERT(reg.def()); - const LStackArea* alloc = reg.def()->output()->toStackArea(); - for (auto iter = alloc->results(); iter; iter.next()) { - if (iter.isWasmAnyRef()) { - return true; - } - } - } - return false; -} - bool BacktrackingAllocator::populateSafepoints() { JitSpew(JitSpew_RegAlloc, "Populating Safepoints"); + // The virtual registers and safepoints are both ordered by position. To avoid + // quadratic behavior in findFirstSafepoint, we use firstSafepoint as cursor + // to start the search at the safepoint returned by the previous call. size_t firstSafepoint = 0; MOZ_ASSERT(!vregs[0u].def()); for (uint32_t i = 1; i < graph.numVirtualRegisters(); i++) { VirtualRegister& reg = vregs[i]; - if (!reg.def() || - (!IsTraceable(reg) && !IsSlotsOrElements(reg) && !IsNunbox(reg))) { + if (!reg.def() || !reg.def()->isSafepointGCType(reg.ins())) { continue; } @@ -4178,20 +4570,25 @@ bool BacktrackingAllocator::populateSafepoints() { break; } - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - LiveRange* range = LiveRange::get(*iter); + // The ranges are sorted by start position, so we can use the same + // findFirstSafepoint optimization here. + size_t firstSafepointForRange = firstSafepoint; - for (size_t j = firstSafepoint; j < graph.numSafepoints(); j++) { - LInstruction* ins = graph.getSafepoint(j); + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + LiveRange* range = *iter; - if (!range->covers(inputOf(ins))) { - if (inputOf(ins) >= range->to()) { - break; - } - continue; + firstSafepointForRange = + findFirstSafepoint(range->from(), firstSafepointForRange); + + for (size_t j = firstSafepointForRange; j < graph.numSafepoints(); j++) { + LInstruction* ins = safepoints_[j]; + + if (inputOf(ins) >= range->to()) { + break; } + MOZ_ASSERT(range->covers(inputOf(ins))); + // Include temps but not instruction outputs. Also make sure // MUST_REUSE_INPUT is not used with gcthings or nunboxes, or // we would have to add the input reg to this safepoint. @@ -4213,53 +4610,8 @@ bool BacktrackingAllocator::populateSafepoints() { continue; } - switch (reg.type()) { - case LDefinition::OBJECT: - if (!safepoint->addGcPointer(a)) { - return false; - } - break; - case LDefinition::SLOTS: - if (!safepoint->addSlotsOrElementsPointer(a)) { - return false; - } - break; - case LDefinition::WASM_ANYREF: - if (!safepoint->addWasmAnyRef(a)) { - return false; - } - break; - case LDefinition::STACKRESULTS: { - MOZ_ASSERT(a.isStackArea()); - for (auto iter = a.toStackArea()->results(); iter; iter.next()) { - if (iter.isWasmAnyRef()) { - if (!safepoint->addWasmAnyRef(iter.alloc())) { - return false; - } - } - } - break; - } -#ifdef JS_NUNBOX32 - case LDefinition::TYPE: - if (!safepoint->addNunboxType(i, a)) { - return false; - } - break; - case LDefinition::PAYLOAD: - if (!safepoint->addNunboxPayload(i, a)) { - return false; - } - break; -#else - case LDefinition::BOX: - if (!safepoint->addBoxedValue(a)) { - return false; - } - break; -#endif - default: - MOZ_CRASH("Bad register type"); + if (!safepoint->addGCAllocation(i, reg.def(), a)) { + return false; } } } @@ -4413,23 +4765,22 @@ UniqueChars LiveRange::toString() const { UniqueChars LiveBundle::toString() const { AutoEnterOOMUnsafeRegion oomUnsafe; - UniqueChars buf = JS_smprintf("LB%u(", debugId()); + UniqueChars buf = JS_smprintf("LB%u(", id()); if (buf) { if (spillParent()) { - buf = JS_sprintf_append(std::move(buf), "parent=LB%u", - spillParent()->debugId()); + buf = + JS_sprintf_append(std::move(buf), "parent=LB%u", spillParent()->id()); } else { buf = JS_sprintf_append(std::move(buf), "parent=none"); } } - for (LiveRange::BundleLinkIterator iter = rangesBegin(); buf && iter; - iter++) { + for (LiveBundle::RangeIterator iter = rangesBegin(); buf && iter; iter++) { if (buf) { buf = JS_sprintf_append(std::move(buf), "%s %s", (iter == rangesBegin()) ? "" : " ##", - LiveRange::get(*iter)->toString().get()); + iter->toString().get()); } } @@ -4454,13 +4805,11 @@ void BacktrackingAllocator::dumpLiveRangesByVReg(const char* who) { JitSpewHeader(JitSpew_RegAlloc); JitSpewCont(JitSpew_RegAlloc, " "); VirtualRegister& reg = vregs[i]; - for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; - iter++) { - if (iter != reg.rangesBegin()) { + for (VirtualRegister::RangeIterator iter(reg); iter; iter++) { + if (*iter != reg.firstRange()) { JitSpewCont(JitSpew_RegAlloc, " ## "); } - JitSpewCont(JitSpew_RegAlloc, "%s", - LiveRange::get(*iter)->toString().get()); + JitSpewCont(JitSpew_RegAlloc, "%s", iter->toString().get()); } JitSpewCont(JitSpew_RegAlloc, "\n"); } @@ -4474,9 +4823,8 @@ void BacktrackingAllocator::dumpLiveRangesByBundle(const char* who) { for (uint32_t i = 1; i < graph.numVirtualRegisters(); i++) { VirtualRegister& reg = vregs[i]; - for (LiveRange::RegisterLinkIterator baseIter = reg.rangesBegin(); baseIter; - baseIter++) { - LiveRange* range = LiveRange::get(*baseIter); + for (VirtualRegister::RangeIterator baseIter(reg); baseIter; baseIter++) { + LiveRange* range = *baseIter; LiveBundle* bundle = range->bundle(); if (range == bundle->firstRange()) { JitSpew(JitSpew_RegAlloc, " %s", bundle->toString().get()); @@ -4649,6 +4997,10 @@ bool BacktrackingAllocator::go() { JitSpew(JitSpew_RegAlloc, "Spill-bundle allocation loop complete"); JitSpewCont(JitSpew_RegAlloc, "\n"); + // After this point, the VirtualRegister ranges are sorted and must stay + // sorted. + sortVirtualRegisterRanges(); + if (!pickStackSlots()) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.h b/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.h index 366aa0d16c0..b7a24bf0ef2 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.h +++ b/src/third_party/mozjs/extract/js/src/jit/BacktrackingAllocator.h @@ -10,10 +10,12 @@ #include "mozilla/Array.h" #include "mozilla/Atomics.h" #include "mozilla/Attributes.h" +#include "mozilla/Maybe.h" #include "ds/AvlTree.h" #include "ds/PriorityQueue.h" #include "jit/RegisterAllocator.h" +#include "jit/SparseBitSet.h" #include "jit/StackSlotAllocator.h" // Gives better traces in Nightly/debug builds (could be EARLY_BETA_OR_EARLIER) @@ -67,7 +69,7 @@ class Requirement { MOZ_ASSERT(newRequirement.kind() == Requirement::REGISTER); if (kind() == Requirement::FIXED) { - return allocation().isRegister(); + return allocation().isAnyRegister(); } *this = newRequirement; @@ -177,30 +179,8 @@ using UsePositionIterator = InlineForwardListIterator; class LiveBundle; class VirtualRegister; -class LiveRange : public TempObject { +class LiveRange : public TempObject, public InlineForwardListNode { public: - // Linked lists are used to keep track of the ranges in each LiveBundle and - // VirtualRegister. Since a LiveRange may be in two lists simultaneously, use - // these auxiliary classes to keep things straight. - class BundleLink : public InlineForwardListNode {}; - class RegisterLink : public InlineForwardListNode {}; - - using BundleLinkIterator = InlineForwardListIterator; - using RegisterLinkIterator = InlineForwardListIterator; - - // Links in the lists in LiveBundle and VirtualRegister. - BundleLink bundleLink; - RegisterLink registerLink; - - static LiveRange* get(BundleLink* link) { - return reinterpret_cast(reinterpret_cast(link) - - offsetof(LiveRange, bundleLink)); - } - static LiveRange* get(RegisterLink* link) { - return reinterpret_cast(reinterpret_cast(link) - - offsetof(LiveRange, registerLink)); - } - struct Range { // The beginning of this range, inclusive. CodePosition from; @@ -311,7 +291,9 @@ class LiveRange : public TempObject { void setBundle(LiveBundle* bundle) { bundle_ = bundle; } void addUse(UsePosition* use); + void tryToMoveDefAndUsesInto(LiveRange* other); + void moveAllUsesToTheEndOf(LiveRange* other); void setHasDefinition() { MOZ_ASSERT(!hasDefinition_); @@ -407,14 +389,6 @@ class SpillSet : public TempObject { void setAllocation(LAllocation alloc); }; -#ifdef JS_JITSPEW -// See comment on LiveBundle::debugId_ just below. This needs to be atomic -// because TSan automation runs on debug builds will otherwise (correctly) -// report a race. -static mozilla::Atomic LiveBundle_debugIdCounter = - mozilla::Atomic{0}; -#endif - // A set of live ranges which are all pairwise disjoint. The register allocator // attempts to find allocations for an entire bundle, and if it fails the // bundle will be broken into smaller ones which are allocated independently. @@ -423,7 +397,7 @@ class LiveBundle : public TempObject { SpillSet* spill_; // All the ranges in this set, ordered by location. - InlineForwardList ranges_; + InlineForwardList ranges_; // Allocation to use for ranges in this set, bogus if unallocated or spilled // and not yet given a physical stack slot. @@ -434,41 +408,43 @@ class LiveBundle : public TempObject { // will not be split. LiveBundle* spillParent_; -#ifdef JS_JITSPEW - // This is used only for debug-printing bundles. It gives them an + // This is used for debug-printing bundles. It gives them an // identifiable identity in the debug output, which they otherwise wouldn't - // have. - uint32_t debugId_; -#endif + // have. It's also used for sorting VirtualRegister's live ranges; see the + // comment in VirtualRegister::sortRanges. + const uint32_t id_; - LiveBundle(SpillSet* spill, LiveBundle* spillParent) - : spill_(spill), spillParent_(spillParent) { -#ifdef JS_JITSPEW - debugId_ = LiveBundle_debugIdCounter++; -#endif - } + LiveBundle(SpillSet* spill, LiveBundle* spillParent, uint32_t id) + : spill_(spill), spillParent_(spillParent), id_(id) {} public: static LiveBundle* FallibleNew(TempAllocator& alloc, SpillSet* spill, - LiveBundle* spillParent) { - return new (alloc.fallible()) LiveBundle(spill, spillParent); + LiveBundle* spillParent, uint32_t id) { + return new (alloc.fallible()) LiveBundle(spill, spillParent, id); } + using RangeIterator = InlineForwardListIterator; + SpillSet* spillSet() const { return spill_; } void setSpillSet(SpillSet* spill) { spill_ = spill; } - LiveRange::BundleLinkIterator rangesBegin() const { return ranges_.begin(); } + RangeIterator rangesBegin() const { return ranges_.begin(); } + RangeIterator rangesBegin(LiveRange* range) const { + return ranges_.begin(range); + } bool hasRanges() const { return !!rangesBegin(); } - LiveRange* firstRange() const { return LiveRange::get(*rangesBegin()); } - LiveRange* lastRange() const { return LiveRange::get(ranges_.back()); } + LiveRange* firstRange() const { return *rangesBegin(); } + LiveRange* lastRange() const { return ranges_.back(); } LiveRange* rangeFor(CodePosition pos) const; void removeRange(LiveRange* range); - void removeRangeAndIncrementIterator(LiveRange::BundleLinkIterator& iter) { + void removeRangeAndIncrementIterator(RangeIterator& iter) { ranges_.removeAndIncrement(iter); } - void addRange(LiveRange* range); - [[nodiscard]] bool addRange(TempAllocator& alloc, VirtualRegister* vreg, - CodePosition from, CodePosition to); + void removeAllRangesFromVirtualRegisters(); + void addRange(LiveRange* range, LiveRange* startAt = nullptr); + void addRangeAtEnd(LiveRange* range); + [[nodiscard]] bool addRangeAtEnd(TempAllocator& alloc, VirtualRegister* vreg, + CodePosition from, CodePosition to); [[nodiscard]] bool addRangeAndDistributeUses(TempAllocator& alloc, LiveRange* oldRange, CodePosition from, @@ -483,25 +459,59 @@ class LiveBundle : public TempObject { LiveBundle* spillParent() const { return spillParent_; } -#ifdef JS_JITSPEW - uint32_t debugId() const { return debugId_; } + uint32_t id() const { return id_; } +#ifdef JS_JITSPEW // Return a string describing this bundle. UniqueChars toString() const; #endif }; +// Information about a control flow edge to resolve (by inserting a move from +// predecessor range to successor range) in createMoveGroupsForControlFlowEdges. +struct ControlFlowEdge { + // The predecessor and successor sides of this edge. + LBlock* predecessor; + LBlock* successor; + + // Live range that covers the successor block. + LiveRange* successorRange; + + // Exit position of the predecessor block. This is |exitOf(predecessor)| but + // cached here. + CodePosition predecessorExit; + + ControlFlowEdge(LBlock* predecessor, LBlock* successor, + LiveRange* successorRange, CodePosition predecessorExit) + : predecessor(predecessor), + successor(successor), + successorRange(successorRange), + predecessorExit(predecessorExit) { + MOZ_ASSERT(predecessor != successor); + } +}; +using ControlFlowEdgeVector = + Vector; + // Information about the allocation for a virtual register. class VirtualRegister { + public: + // Note: most virtual registers have <= 4 live ranges (at least 95% on x64 for + // a few very large Wasm modules). + using RangeVector = Vector; + class RangeIterator; + + private: // Instruction which defines this register. LNode* ins_ = nullptr; // Definition in the instruction for this register. LDefinition* def_ = nullptr; - // All live ranges for this register. These may overlap each other, and are - // ordered by their start position. - InlineForwardList ranges_; + // All live ranges for this register. These may overlap each other. + // If |rangesSorted_| is true, then these are ordered by their start position + // in descending order. + RangeVector ranges_; // Whether def_ is a temp or an output. bool isTemp_ = false; @@ -514,9 +524,23 @@ class VirtualRegister { // be introduced before the definition that relaxes the policy. bool mustCopyInput_ = false; + // If true, the |ranges_| vector is guaranteed to be sorted. + bool rangesSorted_ = true; + void operator=(const VirtualRegister&) = delete; VirtualRegister(const VirtualRegister&) = delete; +#ifdef DEBUG + void assertRangesSorted() const; +#else + void assertRangesSorted() const {} +#endif + + const RangeVector& sortedRanges() const { + assertRangesSorted(); + return ranges_; + } + public: VirtualRegister() = default; @@ -545,47 +569,124 @@ class VirtualRegister { void setMustCopyInput() { mustCopyInput_ = true; } bool mustCopyInput() { return mustCopyInput_; } - LiveRange::RegisterLinkIterator rangesBegin() const { - return ranges_.begin(); + bool hasRanges() const { return !ranges_.empty(); } + LiveRange* firstRange() const { + assertRangesSorted(); + return ranges_.back(); } - LiveRange::RegisterLinkIterator rangesBegin(LiveRange* range) const { - return ranges_.begin(&range->registerLink); + LiveRange* lastRange() const { + assertRangesSorted(); + return ranges_[0]; } - bool hasRanges() const { return !!rangesBegin(); } - LiveRange* firstRange() const { return LiveRange::get(*rangesBegin()); } - LiveRange* lastRange() const { return LiveRange::get(ranges_.back()); } LiveRange* rangeFor(CodePosition pos, bool preferRegister = false) const; - void removeRange(LiveRange* range); - void addRange(LiveRange* range); + void sortRanges(); - void removeRangeAndIncrement(LiveRange::RegisterLinkIterator& iter) { - ranges_.removeAndIncrement(iter); - } + void removeFirstRange(RangeIterator& iter); + void removeRangesForBundle(LiveBundle* bundle); + template + void removeRangesIf(Pred&& pred); + + [[nodiscard]] bool replaceLastRangeLinear(LiveRange* old, LiveRange* newPre, + LiveRange* newPost); + + [[nodiscard]] bool addRange(LiveRange* range); LiveBundle* firstBundle() const { return firstRange()->bundle(); } [[nodiscard]] bool addInitialRange(TempAllocator& alloc, CodePosition from, - CodePosition to, size_t* numRanges); + CodePosition to); void addInitialUse(UsePosition* use); void setInitialDefinition(CodePosition from); + + // Iterator visiting a VirtualRegister's live ranges in order of increasing + // start position. Because the ranges are sorted in descending order, this + // iterates over the vector from index |length - 1| to 0. + class MOZ_RAII RangeIterator { + const RangeVector& ranges_; +#ifdef DEBUG + const VirtualRegister& reg_; +#endif + // if |pos_| is 0, the iterator is done. Else, |pos_ - 1| is the index of + // the range that will be returned by |*iter|. + size_t pos_; + + public: + explicit RangeIterator(const VirtualRegister& reg) + : ranges_(reg.sortedRanges()), +#ifdef DEBUG + reg_(reg), +#endif + pos_(ranges_.length()) { + } + RangeIterator(const VirtualRegister& reg, size_t index) + : ranges_(reg.sortedRanges()), +#ifdef DEBUG + reg_(reg), +#endif + pos_(index + 1) { + MOZ_ASSERT(index < ranges_.length()); + } + +#ifdef DEBUG + ~RangeIterator() { + // Ranges should stay sorted during iteration. + reg_.assertRangesSorted(); + } +#endif + + RangeIterator(RangeIterator&) = delete; + void operator=(RangeIterator&) = delete; + + bool done() const { return pos_ == 0; } + + explicit operator bool() const { return !done(); } + + LiveRange* operator*() const { + MOZ_ASSERT(!done()); + return ranges_[pos_ - 1]; + } + LiveRange* operator->() { return operator*(); } + + size_t index() const { + MOZ_ASSERT(!done()); + return pos_ - 1; + } + + void operator++(int) { + MOZ_ASSERT(!done()); + pos_--; + } + }; }; // A sequence of code positions, for tellings BacktrackingAllocator::splitAt // where to split. -using SplitPositionVector = js::Vector; +using SplitPositionVector = + js::Vector; class BacktrackingAllocator : protected RegisterAllocator { friend class JSONSpewer; - // This flag is set when testing new allocator modifications. - bool testbed; + // Computed data + InstructionDataMap insData; + Vector entryPositions; + Vector exitPositions; - BitSet* liveIn; - FixedList vregs; + using VirtualRegBitSet = SparseBitSet; + Vector liveIn; + Vector vregs; // Allocation state. StackSlotAllocator stackSlotAllocator; + // List of all instructions with a safepoint. The order is the same as the + // order of the instructions in the LIR graph. + Vector safepoints_; + + // List of all non-call instructions with a safepoint. The order is the same + // as the order of the instructions in the LIR graph. + Vector nonCallSafepoints_; + // Priority queue element: a bundle and the associated priority. struct QueueItem { LiveBundle* bundle; @@ -593,13 +694,16 @@ class BacktrackingAllocator : protected RegisterAllocator { QueueItem(LiveBundle* bundle, size_t priority) : bundle(bundle), priority_(priority) {} - static size_t priority(const QueueItem& v) { return v.priority_; } + static bool higherPriority(const QueueItem& a, const QueueItem& b) { + return a.priority_ > b.priority_; + } private: size_t priority_; }; - PriorityQueue allocationQueue; + PriorityQueue + allocationQueue; // This is a set of LiveRange. They must be non-overlapping. Attempts // to add an overlapping range will cause AvlTree::insert to MOZ_CRASH(). @@ -623,27 +727,10 @@ class BacktrackingAllocator : protected RegisterAllocator { // should be prioritized. LiveRangeSet hotcode; - struct CallRange : public TempObject, public InlineListNode { - LiveRange::Range range; - - CallRange(CodePosition from, CodePosition to) : range(from, to) {} - - // Comparator for use in AVL trees. - static int compare(CallRange* v0, CallRange* v1) { - if (v0->range.to <= v1->range.from) { - return -1; - } - if (v0->range.from >= v1->range.to) { - return 1; - } - return 0; - } - }; - - // Ranges where all registers must be spilled due to call instructions. - using CallRangeList = InlineList; - CallRangeList callRangesList; - AvlTree callRanges; + // Output positions of all call instructions (where all registers must be + // spilled). This vector is sorted in ascending order and doesn't contain + // duplicate values. + Vector callPositions; // Information about an allocated stack slot. struct SpillSlot : public TempObject, @@ -651,17 +738,20 @@ class BacktrackingAllocator : protected RegisterAllocator { LStackSlot alloc; LiveRangePlusSet allocated; - SpillSlot(uint32_t slot, LifoAlloc* alloc) - : alloc(slot), allocated(alloc) {} + SpillSlot(uint32_t slot, LStackSlot::Width width, LifoAlloc* alloc) + : alloc(slot, width), allocated(alloc) {} }; using SpillSlotList = InlineForwardList; // All allocated slots of each width. SpillSlotList normalSlots, doubleSlots, quadSlots; - Vector spilledBundles; + Vector spilledBundles; - using LiveBundleVector = Vector; + // The bundle id that will be used for the next LiveBundle that's allocated. + uint32_t nextBundleId_ = 0; + + using LiveBundleVector = Vector; // Misc accessors bool compilingWasm() { return mir->outerInfo().compilingWasm(); } @@ -673,6 +763,18 @@ class BacktrackingAllocator : protected RegisterAllocator { return vregs[alloc->toUse()->virtualRegister()]; } + uint32_t getNextBundleId() { return nextBundleId_++; } + + CodePosition entryOf(const LBlock* block) { + return entryPositions[block->mir()->id()]; + } + CodePosition exitOf(const LBlock* block) { + return exitPositions[block->mir()->id()]; + } + + // Atomic group helper. See comments in BacktrackingAllocator.cpp. + CodePosition minimalDefEnd(LNode* ins) const; + // Helpers for creating and adding MoveGroups [[nodiscard]] bool addMove(LMoveGroup* moves, LiveRange* from, LiveRange* to, LDefinition::Type type) { @@ -744,8 +846,12 @@ class BacktrackingAllocator : protected RegisterAllocator { CodePosition to); [[nodiscard]] bool buildLivenessInfo(); + // Call positions. + mozilla::Maybe lookupFirstCallPositionInRange(CodePosition from, + CodePosition to); + // Merging and queueing of LiveRange groups - [[nodiscard]] bool tryMergeBundles(LiveBundle* bundle0, LiveBundle* bundle1); + void tryMergeBundles(LiveBundle* bundle0, LiveBundle* bundle1); void allocateStackDefinition(VirtualRegister& reg); [[nodiscard]] bool tryMergeReusedRegister(VirtualRegister& def, VirtualRegister& input); @@ -772,7 +878,7 @@ class BacktrackingAllocator : protected RegisterAllocator { bool* success); // The top level driver for the splitting machinery - [[nodiscard]] bool chooseBundleSplit(LiveBundle* bundle, bool fixed, + [[nodiscard]] bool chooseBundleSplit(LiveBundle* bundle, bool hasCall, LiveBundle* conflict); // Bundle allocation @@ -781,38 +887,42 @@ class BacktrackingAllocator : protected RegisterAllocator { Requirement* phint); [[nodiscard]] bool tryAllocateRegister(PhysicalRegister& r, LiveBundle* bundle, bool* success, - bool* pfixed, + bool* hasCall, LiveBundleVector& conflicting); [[nodiscard]] bool tryAllocateAnyRegister(LiveBundle* bundle, bool* success, - bool* pfixed, + bool* hasCall, LiveBundleVector& conflicting); [[nodiscard]] bool evictBundle(LiveBundle* bundle); [[nodiscard]] bool tryAllocateFixed(LiveBundle* bundle, Requirement requirement, bool* success, - bool* pfixed, + bool* hasCall, LiveBundleVector& conflicting); [[nodiscard]] bool tryAllocateNonFixed(LiveBundle* bundle, Requirement requirement, Requirement hint, bool* success, - bool* pfixed, + bool* hasCall, LiveBundleVector& conflicting); - [[nodiscard]] bool processBundle(MIRGenerator* mir, LiveBundle* bundle); + [[nodiscard]] bool processBundle(const MIRGenerator* mir, LiveBundle* bundle); [[nodiscard]] bool spill(LiveBundle* bundle); [[nodiscard]] AVOID_INLINE_FOR_DEBUGGING bool tryAllocatingRegistersForSpillBundles(); // Rewriting of the LIR after bundle processing is done [[nodiscard]] bool insertAllRanges(LiveRangePlusSet& set, LiveBundle* bundle); + void sortVirtualRegisterRanges(); [[nodiscard]] bool pickStackSlot(SpillSet* spill); [[nodiscard]] AVOID_INLINE_FOR_DEBUGGING bool pickStackSlots(); [[nodiscard]] bool moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from, LiveRange* to, LDefinition::Type type); - [[nodiscard]] AVOID_INLINE_FOR_DEBUGGING bool deadRange(LiveRange* range); + void removeDeadRanges(VirtualRegister& reg); + [[nodiscard]] bool createMoveGroupsForControlFlowEdges( + const VirtualRegister& reg, const ControlFlowEdgeVector& edges); [[nodiscard]] AVOID_INLINE_FOR_DEBUGGING bool createMoveGroupsFromLiveRangeTransitions(); - size_t findFirstNonCallSafepoint(CodePosition from); - void addLiveRegistersForRange(VirtualRegister& reg, LiveRange* range); + size_t findFirstNonCallSafepoint(CodePosition pos, size_t startFrom); + void addLiveRegistersForRange(VirtualRegister& reg, LiveRange* range, + size_t* firstNonCallSafepoint); [[nodiscard]] AVOID_INLINE_FOR_DEBUGGING bool installAllocationsInLIR(); size_t findFirstSafepoint(CodePosition pos, size_t startFrom); [[nodiscard]] AVOID_INLINE_FOR_DEBUGGING bool populateSafepoints(); @@ -828,12 +938,12 @@ class BacktrackingAllocator : protected RegisterAllocator { // Top level of the register allocation machinery, and the only externally // visible bit. public: - BacktrackingAllocator(MIRGenerator* mir, LIRGenerator* lir, LIRGraph& graph, - bool testbed) + BacktrackingAllocator(MIRGenerator* mir, LIRGenerator* lir, LIRGraph& graph) : RegisterAllocator(mir, lir, graph), - testbed(testbed), - liveIn(nullptr), - callRanges(nullptr) {} + liveIn(mir->alloc()), + vregs(mir->alloc()), + safepoints_(mir->alloc()), + nonCallSafepoints_(mir->alloc()) {} [[nodiscard]] bool go(); }; diff --git a/src/third_party/mozjs/extract/js/src/jit/Bailouts.cpp b/src/third_party/mozjs/extract/js/src/jit/Bailouts.cpp index 1d2657c3998..cfb68ace1ae 100644 --- a/src/third_party/mozjs/extract/js/src/jit/Bailouts.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/Bailouts.cpp @@ -313,10 +313,12 @@ bool jit::ExceptionHandlerBailout(JSContext* cx, rfe->bailoutInfo = bailoutInfo; } else { // Drop the exception that triggered the bailout and instead propagate the - // failure caused by processing the bailout (eg. OOM). + // failure caused by processing the bailout (eg. OOM). Note that recover + // instructions can do an interrupt check and throw an uncatchable + // exception. savedExc.drop(); MOZ_ASSERT(!bailoutInfo); - MOZ_ASSERT(cx->isExceptionPending()); + MOZ_ASSERT(cx->isExceptionPending() || cx->hadUncatchableException()); } // Make the frame being bailed out the top profiled frame. diff --git a/src/third_party/mozjs/extract/js/src/jit/BaselineBailouts.cpp b/src/third_party/mozjs/extract/js/src/jit/BaselineBailouts.cpp index 150e16b618b..4bc345ad6f9 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BaselineBailouts.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/BaselineBailouts.cpp @@ -832,17 +832,28 @@ bool BaselineStackBuilder::buildExpressionStack() { for (uint32_t i = 0; i < exprStackSlots(); i++) { Value v; - // If we are in the middle of propagating an exception from Ion by - // bailing to baseline due to debug mode, we might not have all - // the stack if we are at the newest frame. + // If we're at the newest frame and in the middle of throwing an exception, + // some expression stack slots might not be available. // - // For instance, if calling |f()| pushed an Ion frame which threw, - // the snapshot expects the return value to be pushed, but it's - // possible nothing was pushed before we threw. + // For example, if we call a function that throws, and then catch the + // exception, the return value won't be available. This isn't usually a + // problem, because the expression stack is generally empty when we enter a + // catch block. However, if a catch is inside a for-of, there are + // iterator-related values on the stack. If one of those values is defined + // by the function that threw, then its value will be unavailable. This is + // not possible for a user-written catch, but can happen for synthetic + // catches generated via desugaring. See bug 1934425 for a case involving + // `for (await using ...)`. + // + // Similar issues of trying to recover the result of a throwing function can + // also occur when bailing out while propagating an exception due to debug + // mode. // // We therefore use a fallible read here. if (!iter_.tryRead(&v)) { - MOZ_ASSERT(propagatingIonExceptionForDebugMode() && !iter_.moreFrames()); + MOZ_ASSERT( + !iter_.moreFrames() && + (catchingException() || propagatingIonExceptionForDebugMode())); v = MagicValue(JS_OPTIMIZED_OUT); } if (!writeValue(v, "StackValue")) { diff --git a/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.cpp b/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.cpp index 4e574dd3e2b..b06c02f9fa7 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.cpp @@ -6,9 +6,13 @@ #include "jit/BaselineCacheIRCompiler.h" +#include "mozilla/RandomNum.h" + #include "gc/GC.h" #include "jit/CacheIR.h" +#include "jit/CacheIRAOT.h" #include "jit/CacheIRCloner.h" +#include "jit/CacheIRSpewer.h" #include "jit/CacheIRWriter.h" #include "jit/JitFrames.h" #include "jit/JitRuntime.h" @@ -22,7 +26,9 @@ #include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration #include "proxy/DeadObjectProxy.h" #include "proxy/Proxy.h" +#include "util/DifferentialTesting.h" #include "util/Unicode.h" +#include "vm/PortableBaselineInterpret.h" #include "vm/StaticStrings.h" #include "jit/JitScript-inl.h" @@ -448,8 +454,7 @@ bool BaselineCacheIRCompiler::emitGuardSpecificAtom(StringOperandId strId, // We have a non-atomized string with the same length. Call a helper // function to do the comparison. - LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), - liveVolatileFloatRegs()); + LiveRegisterSet volatileRegs = liveVolatileRegs(); masm.PushRegsInMask(volatileRegs); using Fn = bool (*)(JSString* str1, JSString* str2); @@ -484,6 +489,21 @@ bool BaselineCacheIRCompiler::emitGuardSpecificSymbol(SymbolOperandId symId, return true; } +bool BaselineCacheIRCompiler::emitGuardSpecificValue(ValOperandId valId, + uint32_t expectedOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + ValueOperand val = allocator.useValueRegister(masm, valId); + + FailurePath* failure; + if (!addFailurePath(&failure)) { + return false; + } + + Address addr(stubAddress(expectedOffset)); + masm.branchTestValue(Assembler::NotEqual, addr, val, failure->label()); + return true; +} + bool BaselineCacheIRCompiler::emitLoadValueResult(uint32_t valOffset) { JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); AutoOutputRegister output(*this); @@ -899,8 +919,7 @@ bool BaselineCacheIRCompiler::emitAddAndStoreSlotShared( return false; } - LiveRegisterSet save(GeneralRegisterSet::Volatile(), - liveVolatileFloatRegs()); + LiveRegisterSet save = liveVolatileRegs(); masm.PushRegsInMask(save); using Fn = bool (*)(JSContext* cx, NativeObject* obj, uint32_t newCount); @@ -1178,7 +1197,7 @@ bool BaselineCacheIRCompiler::emitIsTypedArrayResult(ObjOperandId objId, allocator.discardStack(masm); - Label notTypedArray, isProxy, done; + Label notTypedArray, isWrapper, done; masm.loadObjClassUnsafe(obj, scratch); masm.branchIfClassIsNotTypedArray(scratch, ¬TypedArray); masm.moveValue(BooleanValue(true), output.valueReg()); @@ -1186,14 +1205,18 @@ bool BaselineCacheIRCompiler::emitIsTypedArrayResult(ObjOperandId objId, masm.bind(¬TypedArray); if (isPossiblyWrapped) { - masm.branchTestClassIsProxy(true, scratch, &isProxy); + Label notProxy; + masm.branchTestClassIsProxy(false, scratch, ¬Proxy); + masm.branchTestProxyHandlerFamily(Assembler::Equal, obj, scratch, + &Wrapper::family, &isWrapper); + masm.bind(¬Proxy); } masm.moveValue(BooleanValue(false), output.valueReg()); if (isPossiblyWrapped) { masm.jump(&done); - masm.bind(&isProxy); + masm.bind(&isWrapper); AutoStubFrame stubFrame(*this); stubFrame.enter(masm, scratch); @@ -1467,6 +1490,23 @@ bool BaselineCacheIRCompiler::emitHasClassResult(ObjOperandId objId, return true; } +bool BaselineCacheIRCompiler::emitHasShapeResult(ObjOperandId objId, + uint32_t shapeOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + + AutoOutputRegister output(*this); + Register obj = allocator.useRegister(masm, objId); + AutoScratchRegisterMaybeOutput scratch(allocator, masm, output); + + // Note: no Spectre mitigations are needed here because this shape check only + // affects correctness. + Address shapeAddr(stubAddress(shapeOffset)); + masm.loadObjShapeUnsafe(obj, scratch); + masm.cmpPtrSet(Assembler::Equal, shapeAddr, scratch.get(), scratch); + masm.tagValue(JSVAL_TYPE_BOOLEAN, scratch, output.valueReg()); + return true; +} + void BaselineCacheIRCompiler::emitAtomizeString(Register str, Register temp, Label* failure) { Label isAtom, notCachedAtom; @@ -1477,8 +1517,7 @@ void BaselineCacheIRCompiler::emitAtomizeString(Register str, Register temp, masm.bind(¬CachedAtom); { - LiveRegisterSet save(GeneralRegisterSet::Volatile(), - liveVolatileFloatRegs()); + LiveRegisterSet save = liveVolatileRegs(); masm.PushRegsInMask(save); using Fn = JSAtom* (*)(JSContext* cx, JSString* str); @@ -2035,7 +2074,9 @@ bool BaselineCacheIRCompiler::init(CacheKind kind) { switch (kind) { case CacheKind::NewArray: case CacheKind::NewObject: - case CacheKind::GetIntrinsic: + case CacheKind::Lambda: + case CacheKind::LazyConstant: + case CacheKind::GetImport: MOZ_ASSERT(numInputs == 0); outputUnchecked_.emplace(R0); break; @@ -2139,7 +2180,11 @@ static void ResetEnteredCounts(const ICEntry* icEntry) { static const uint32_t MaxFoldedShapes = 16; -const JSClass ShapeListObject::class_ = {"JIT ShapeList", 0, &classOps_}; +const JSClass ShapeListObject::class_ = { + "JIT ShapeList", + 0, + &classOps_, +}; const JSClassOps ShapeListObject::classOps_ = { nullptr, // addProperty @@ -2162,6 +2207,7 @@ const JSClassOps ShapeListObject::classOps_ = { // Register this object so the GC can sweep its weak pointers. if (!cx->zone()->registerObjectWithWeakPointers(obj)) { + ReportOutOfMemory(cx); return nullptr; } @@ -2199,8 +2245,13 @@ bool ShapeListObject::traceWeak(JSTracer* trc) { } MOZ_ASSERT(dst <= end); - length = dst - elements_; - setDenseInitializedLength(length); + uint32_t newLength = dst - elements_; + setDenseInitializedLength(newLength); + + if (length != newLength) { + JitSpew(JitSpew_StubFolding, "Cleared %u/%u shapes from %p", + length - newLength, length, this); + } return length != 0; } @@ -2392,6 +2443,12 @@ bool js::jit::TryFoldingStubs(JSContext* cx, ICFallbackStub* fallback, } MOZ_ASSERT(result == ICAttachResult::Attached); + JitSpew(JitSpew_StubFolding, + "Folded stub at offset %u (icScript: %p) with %zu shapes (%s:%u:%u)", + fallback->pcOffset(), icScript, shapeList.length(), + script->filename(), script->lineno(), + script->column().oneOriginValue()); + fallback->setMayHaveFoldedStub(); return true; } @@ -2511,57 +2568,78 @@ static bool AddToFoldedStub(JSContext* cx, const CacheIRWriter& writer, return false; } + JitSpew(JitSpew_StubFolding, "ShapeListObject %p: new length: %u", + foldedShapes.get(), foldedShapes->length()); + return true; } -ICAttachResult js::jit::AttachBaselineCacheIRStub( - JSContext* cx, const CacheIRWriter& writer, CacheKind kind, - JSScript* outerScript, ICScript* icScript, ICFallbackStub* stub, - const char* name) { - // We shouldn't GC or report OOM (or any other exception) here. - AutoAssertNoPendingException aanpe(cx); - JS::AutoCheckCannotGC nogc; +#ifdef ENABLE_JS_AOT_ICS +void DumpNonAOTICStubAndQuit(CacheKind kind, const CacheIRWriter& writer) { + // Generate a random filename (unlikely to conflict with others). + char filename[64]; + snprintf(filename, sizeof(filename), "IC-%" PRIu64, + mozilla::RandomUint64OrDie()); + FILE* f = fopen(filename, "w"); + MOZ_RELEASE_ASSERT(f); - if (writer.tooLarge()) { - return ICAttachResult::TooLarge; + // Generate the CacheIR text to dump to a file. + { + Fprinter printer(f); + SpewCacheIROpsAsAOT(printer, kind, writer); } - if (writer.oom()) { - return ICAttachResult::OOM; - } - MOZ_ASSERT(!writer.failed()); + fflush(f); + fclose(f); + fprintf(stderr, "UNEXPECTED NEW IC BODY\n"); - // Just a sanity check: the caller should ensure we don't attach an - // unlimited number of stubs. -#ifdef DEBUG - static const size_t MaxOptimizedCacheIRStubs = 16; - MOZ_ASSERT(stub->numOptimizedStubs() < MaxOptimizedCacheIRStubs); + fprintf(stderr, + "Please add the file '%s' to the ahead-of-time known IC bodies in " + "js/src/ics/.\n" + "\n" + "To keep running and dump all new ICs (useful for updating with " + "test-suites),\n" + "set the environment variable AOT_ICS_KEEP_GOING=1 and rerun.\n", + filename); + + if (!getenv("AOT_ICS_KEEP_GOING")) { + abort(); + } +} #endif - constexpr uint32_t stubDataOffset = sizeof(ICCacheIRStub); - static_assert(stubDataOffset % sizeof(uint64_t) == 0, - "Stub fields must be aligned"); +static constexpr uint32_t StubDataOffset = sizeof(ICCacheIRStub); +static_assert(StubDataOffset % sizeof(uint64_t) == 0, + "Stub fields must be aligned"); - JitZone* jitZone = cx->zone()->jitZone(); - - // Check if we already have JitCode for this stub. - CacheIRStubInfo* stubInfo; +static bool LookupOrCompileStub(JSContext* cx, CacheKind kind, + const CacheIRWriter& writer, + CacheIRStubInfo*& stubInfo, JitCode*& code, + const char* name, bool isAOTFill, + JitZone* jitZone) { CacheIRStubKey::Lookup lookup(kind, ICStubEngine::Baseline, writer.codeStart(), writer.codeLength()); - JitCode* code = jitZone->getBaselineCacheIRStubCode(lookup, &stubInfo); + code = jitZone->getBaselineCacheIRStubCode(lookup, &stubInfo); + +#ifdef ENABLE_JS_AOT_ICS + if (JitOptions.enableAOTICEnforce && !stubInfo && !isAOTFill && + !jitZone->isIncompleteAOTICs()) { + DumpNonAOTICStubAndQuit(kind, writer); + } +#endif if (!code && !IsPortableBaselineInterpreterEnabled()) { // We have to generate stub code. TempAllocator temp(&cx->tempLifoAlloc()); JitContext jctx(cx); - BaselineCacheIRCompiler comp(cx, temp, writer, stubDataOffset); + BaselineCacheIRCompiler comp(cx, temp, writer, StubDataOffset); if (!comp.init(kind)) { - return ICAttachResult::OOM; + return false; } code = comp.compile(); if (!code) { - return ICAttachResult::OOM; + return false; } comp.perfSpewer().saveProfile(code, name); @@ -2573,14 +2651,14 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( MOZ_ASSERT(!stubInfo); stubInfo = CacheIRStubInfo::New(kind, ICStubEngine::Baseline, comp.makesGCCalls(), - stubDataOffset, writer); + StubDataOffset, writer); if (!stubInfo) { - return ICAttachResult::OOM; + return false; } CacheIRStubKey key(stubInfo); if (!jitZone->putBaselineCacheIRStubCode(lookup, key, code)) { - return ICAttachResult::OOM; + return false; } } else if (!stubInfo) { MOZ_ASSERT(IsPortableBaselineInterpreterEnabled()); @@ -2593,21 +2671,76 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( // we don't invoke the BaselineCacheIRCompiler so we otherwise // don't know for sure. stubInfo = CacheIRStubInfo::New(kind, ICStubEngine::Baseline, - /* makes GC calls = */ true, stubDataOffset, + /* makes GC calls = */ true, StubDataOffset, writer); if (!stubInfo) { - return ICAttachResult::OOM; + return false; } CacheIRStubKey key(stubInfo); if (!jitZone->putBaselineCacheIRStubCode(lookup, key, /* stubCode = */ nullptr)) { - return ICAttachResult::OOM; + return false; } } MOZ_ASSERT_IF(IsBaselineInterpreterEnabled(), code); MOZ_ASSERT(stubInfo); - MOZ_ASSERT(stubInfo->stubDataSize() == writer.stubDataSize()); + // Assert that the StubInfo recomputing its stub-data size exactly + // matches the writer's stub-data size, but only if we're not + // loading an AOT IC -- otherwise, trust the recomputation from + // field types. + // + // Why ignore if AOT? Because the AOT corpus might have been dumped + // on a machine with a different word size than our machine (e.g., + // 64 to 32 bits). The field types are serialized and deserialized, + // and they are authoritative; the CacheIRWriter's stubDataSize is + // computed during build and used only for this assert, so it is + // strictly a redundant check. + // + // (This cross-machine movement of the corpus is acceptable/correct + // because the CacheIR itself, and our encoding of it in the corpus + // source code, is platform-independent. The worst that happens is + // that some platforms may not generate all possible ICs for another + // platform (e.g. due to limited registers on x86-32) but it is always + // fine not to have an IC preloaded in the corpus. + MOZ_ASSERT_IF(!isAOTFill, stubInfo->stubDataSize() == writer.stubDataSize()); + + return true; +} + +ICAttachResult js::jit::AttachBaselineCacheIRStub( + JSContext* cx, const CacheIRWriter& writer, CacheKind kind, + JSScript* outerScript, ICScript* icScript, ICFallbackStub* stub, + const char* name) { + // We shouldn't GC or report OOM (or any other exception) here. + AutoAssertNoPendingException aanpe(cx); + JS::AutoCheckCannotGC nogc; + + if (writer.tooLarge()) { + cx->runtime()->setUseCounter(cx->global(), JSUseCounter::IC_STUB_TOO_LARGE); + return ICAttachResult::TooLarge; + } + if (writer.oom()) { + cx->runtime()->setUseCounter(cx->global(), JSUseCounter::IC_STUB_OOM); + return ICAttachResult::OOM; + } + MOZ_ASSERT(!writer.failed()); + + // Just a sanity check: the caller should ensure we don't attach an + // unlimited number of stubs. +#ifdef DEBUG + static const size_t MaxOptimizedCacheIRStubs = 16; + MOZ_ASSERT(stub->numOptimizedStubs() < MaxOptimizedCacheIRStubs); +#endif + + // Check if we already have JitCode for this stub. + CacheIRStubInfo* stubInfo; + JitCode* code; + + if (!LookupOrCompileStub(cx, kind, writer, stubInfo, code, name, + /* isAOTFill = */ false, cx->zone()->jitZone())) { + return ICAttachResult::OOM; + } ICEntry* icEntry = icScript->icEntryForStub(stub); @@ -2637,6 +2770,11 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( // Try including this case in an existing folded stub. if (stub->mayHaveFoldedStub() && AddToFoldedStub(cx, writer, icScript, stub)) { + JitSpew(JitSpew_StubFolding, + "Added to folded stub at offset %u (icScript: %p) (%s:%u:%u)", + stub->pcOffset(), icScript, outerScript->filename(), + outerScript->lineno(), outerScript->column().oneOriginValue()); + // Instead of adding a new stub, we have added a new case to an existing // folded stub. We do not have to invalidate Warp, because the // ShapeListObject that stores the cases is shared between baseline and @@ -2647,14 +2785,22 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( JSScript* owningScript = nullptr; if (cx->zone()->jitZone()->hasStubFoldingBailoutData(outerScript)) { owningScript = cx->zone()->jitZone()->stubFoldingBailoutParent(); + JitSpew(JitSpew_StubFolding, + "Found stub folding bailout parent: %s:%u:%u", + owningScript->filename(), owningScript->lineno(), + owningScript->column().oneOriginValue()); } else { owningScript = icScript->isInlined() ? icScript->inliningRoot()->owningScript() : outerScript; } cx->zone()->jitZone()->clearStubFoldingBailoutData(); - if (stub->usedByTranspiler() && owningScript->hasIonScript()) { - owningScript->ionScript()->resetNumFixableBailouts(); + if (stub->usedByTranspiler()) { + if (owningScript->hasIonScript()) { + owningScript->ionScript()->resetNumFixableBailouts(); + } else if (owningScript->hasJitScript()) { + owningScript->jitScript()->clearFailedICHash(); + } } else { // Update the last IC counter if this is not a bailout from Ion. owningScript->updateLastICStubCounter(); @@ -2666,7 +2812,7 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( size_t bytesNeeded = stubInfo->stubDataOffset() + stubInfo->stubDataSize(); - void* newStubMem = jitZone->stubSpace()->alloc(bytesNeeded); + void* newStubMem = cx->zone()->jitZone()->stubSpace()->alloc(bytesNeeded); if (!newStubMem) { return ICAttachResult::OOM; } @@ -2694,6 +2840,11 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( auto newStub = new (newStubMem) ICCacheIRStub(code, stubInfo); writer.copyStubData(newStub->stubDataStart()); newStub->setTypeData(writer.typeData()); + +#ifdef ENABLE_PORTABLE_BASELINE_INTERP + newStub->updateRawJitCode(pbl::GetICInterpreter()); +#endif + stub->addNewStub(icEntry, newStub); JSScript* owningScript = icScript->isInlined() @@ -2703,6 +2854,35 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub( return ICAttachResult::Attached; } +#ifdef ENABLE_JS_AOT_ICS + +# ifndef ENABLE_PORTABLE_BASELINE_INTERP +// The AOT loading of ICs doesn't work (yet) in modes with a native +// JIT enabled because compilation tries to access state that doesn't +// exist yet (trampolines?) when we create the JitZone. +# error AOT ICs are only supported (for now) in PBL builds. +# endif + +void js::jit::FillAOTICs(JSContext* cx, JitZone* zone) { + if (JitOptions.enableAOTICs) { + for (auto& stub : GetAOTStubs()) { + CacheIRWriter writer(cx, stub); + if (writer.failed()) { + zone->setIncompleteAOTICs(); + break; + } + CacheIRStubInfo* stubInfo; + JitCode* code; + (void)LookupOrCompileStub(cx, stub.kind, writer, stubInfo, code, + "aot stub", + /* isAOTFill = */ true, zone); + (void)stubInfo; + (void)code; + } + } +} +#endif + uint8_t* ICCacheIRStub::stubDataStart() { return reinterpret_cast(this) + stubInfo_->stubDataOffset(); } @@ -2872,8 +3052,7 @@ void BaselineCacheIRCompiler::pushStandardArguments( // We use a scratch register to avoid clobbering argc, which is an input // reg. Register countReg = scratch; - masm.move32(argcReg, countReg); - masm.add32(Imm32(additionalArgc), countReg); + masm.add32(Imm32(additionalArgc), argcReg, countReg); // Align the stack such that the JitFrameLayout is aligned on the // JitStackAlignment. @@ -3193,7 +3372,7 @@ void BaselineCacheIRCompiler::pushBoundFunctionArguments( bool BaselineCacheIRCompiler::emitCallNativeShared( NativeCallType callType, ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, Maybe ignoresReturnValue, - Maybe targetOffset) { + Maybe targetOffset, ClearLocalAllocSite clearLocalAllocSite) { AutoOutputRegister output(*this); AutoScratchRegisterMaybeOutput scratch(allocator, masm, output); AutoScratchRegister scratch2(allocator, masm); @@ -3291,9 +3470,24 @@ bool BaselineCacheIRCompiler::emitCallNativeShared( masm.switchToBaselineFrameRealm(scratch2); } + // We will also unilaterally clear this on exception handling. + if (clearLocalAllocSite == ClearLocalAllocSite::Yes) { + masm.storeLocalAllocSite(ImmPtr(nullptr), scratch2); + } + return true; } +void BaselineCacheIRCompiler::loadAllocSiteIntoContext(uint32_t siteOffset) { + AutoScratchRegister scratch(allocator, masm); + AutoScratchRegister site(allocator, masm); + + StubFieldOffset siteField(siteOffset, StubField::Type::AllocSite); + emitLoadStubField(siteField, site); + + masm.storeLocalAllocSite(site.get(), scratch); +} + #ifdef JS_SIMULATOR bool BaselineCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, @@ -3316,6 +3510,19 @@ bool BaselineCacheIRCompiler::emitCallDOMFunction( return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags, argcFixed, ignoresReturnValue, targetOffset_); } + +bool BaselineCacheIRCompiler::emitCallDOMFunctionWithAllocSite( + ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, + CallFlags flags, uint32_t argcFixed, uint32_t siteOffset, + uint32_t targetOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + loadAllocSiteIntoContext(siteOffset); + Maybe ignoresReturnValue; + Maybe targetOffset_ = mozilla::Some(targetOffset); + return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags, + argcFixed, ignoresReturnValue, targetOffset_, + ClearLocalAllocSite::Yes); +} #else bool BaselineCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, @@ -3340,6 +3547,18 @@ bool BaselineCacheIRCompiler::emitCallDOMFunction(ObjOperandId calleeId, return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags, argcFixed, ignoresReturnValue, targetOffset); } + +bool BaselineCacheIRCompiler::emitCallDOMFunctionWithAllocSite( + ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, + CallFlags flags, uint32_t argcFixed, uint32_t siteOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + loadAllocSiteIntoContext(siteOffset); + Maybe ignoresReturnValue = mozilla::Some(false); + Maybe targetOffset; + return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags, + argcFixed, ignoresReturnValue, targetOffset, + ClearLocalAllocSite::Yes); +} #endif bool BaselineCacheIRCompiler::emitCallClassHook(ObjOperandId calleeId, @@ -3886,8 +4105,9 @@ bool BaselineCacheIRCompiler::emitNewArrayObjectResult(uint32_t arrayLength, JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); gc::AllocKind allocKind = GuessArrayGCKind(arrayLength); - MOZ_ASSERT(CanChangeToBackgroundAllocKind(allocKind, &ArrayObject::class_)); - allocKind = ForegroundToBackgroundAllocKind(allocKind); + MOZ_ASSERT(gc::GetObjectFinalizeKind(&ArrayObject::class_) == + gc::FinalizeKind::None); + MOZ_ASSERT(!IsFinalizedKind(allocKind)); uint32_t slotCount = GetGCKindSlots(allocKind); MOZ_ASSERT(slotCount >= ObjectElements::VALUES_PER_HEADER); @@ -3999,6 +4219,59 @@ bool BaselineCacheIRCompiler::emitNewPlainObjectResult(uint32_t numFixedSlots, return true; } +bool BaselineCacheIRCompiler::emitNewFunctionCloneResult( + uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + + AutoOutputRegister output(*this); + AutoScratchRegisterMaybeOutput result(allocator, masm, output); + AutoScratchRegisterMaybeOutputType site(allocator, masm, output); + AutoScratchRegister canonical(allocator, masm); + AutoScratchRegister envChain(allocator, masm); + AutoScratchRegister scratch(allocator, masm); + MOZ_ASSERT(result.get() != site.get()); + + // Load the canonical function and the frame's environment chain. + masm.loadPtr(stubAddress(canonicalOffset), canonical); + Address envAddr(baselineFrameReg_, + BaselineFrame::reverseOffsetOfEnvironmentChain()); + masm.loadPtr(envAddr, envChain); + + Address siteAddr(stubAddress(siteOffset)); + masm.loadPtr(siteAddr, site); + + allocator.discardStack(masm); + + // Try to allocate a new function object in JIT code. + Label done, fail; + + masm.createFunctionClone(result, canonical, envChain, scratch, allocKind, + &fail, AllocSiteInput(site)); + masm.jump(&done); + + { + masm.bind(&fail); + + AutoStubFrame stubFrame(*this); + stubFrame.enter(masm, scratch); + + masm.Push(site); + masm.Push(envChain); + masm.Push(canonical); + + using Fn = + JSObject* (*)(JSContext*, HandleFunction, HandleObject, gc::AllocSite*); + callVM(masm); + + stubFrame.leave(masm); + masm.storeCallPointerResult(result); + } + + masm.bind(&done); + masm.tagValue(JSVAL_TYPE_OBJECT, result, output.valueReg()); + return true; +} + bool BaselineCacheIRCompiler::emitBindFunctionResult( ObjOperandId targetId, uint32_t argc, uint32_t templateObjectOffset) { JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); diff --git a/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.h b/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.h index cf025bdb3bd..c8f46562292 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.h +++ b/src/third_party/mozjs/extract/js/src/jit/BaselineCacheIRCompiler.h @@ -99,11 +99,14 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler { void updateReturnValue(); enum class NativeCallType { Native, ClassHook }; - bool emitCallNativeShared(NativeCallType callType, ObjOperandId calleeId, - Int32OperandId argcId, CallFlags flags, - uint32_t argcFixed, - mozilla::Maybe ignoresReturnValue, - mozilla::Maybe targetOffset); + enum class ClearLocalAllocSite { No, Yes }; + bool emitCallNativeShared( + NativeCallType callType, ObjOperandId calleeId, Int32OperandId argcId, + CallFlags flags, uint32_t argcFixed, + mozilla::Maybe ignoresReturnValue, + mozilla::Maybe targetOffset, + ClearLocalAllocSite clearLocalAllocSite = ClearLocalAllocSite::No); + void loadAllocSiteIntoContext(uint32_t siteOffset); enum class StringCode { CodeUnit, CodePoint }; bool emitStringFromCodeResult(Int32OperandId codeId, StringCode stringCode); diff --git a/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.cpp b/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.cpp index 54c262c59af..0bacc29533e 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.cpp +++ b/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.cpp @@ -9,6 +9,8 @@ #include "mozilla/Casting.h" #include "gc/GC.h" +#include "jit/BaselineCompileQueue.h" +#include "jit/BaselineCompileTask.h" #include "jit/BaselineIC.h" #include "jit/BaselineJIT.h" #include "jit/CacheIRCompiler.h" @@ -31,10 +33,12 @@ #include "vm/AsyncFunction.h" #include "vm/AsyncIteration.h" #include "vm/BuiltinObjectKind.h" +#include "vm/ConstantCompareOperand.h" #include "vm/EnvironmentObject.h" #include "vm/FunctionFlags.h" // js::FunctionFlags #include "vm/Interpreter.h" #include "vm/JSFunction.h" +#include "vm/Logging.h" #include "vm/Time.h" #ifdef MOZ_VTUNE # include "vtune/VTuneWrapper.h" @@ -65,49 +69,57 @@ class PlainObject; namespace jit { -BaselineCompilerHandler::BaselineCompilerHandler(JSContext* cx, - MacroAssembler& masm, +BaselineCompilerHandler::BaselineCompilerHandler(MacroAssembler& masm, TempAllocator& alloc, - JSScript* script) - : frame_(script, masm), + BaselineSnapshot* snapshot) + : frame_(snapshot->script(), masm), alloc_(alloc), - analysis_(alloc, script), + analysis_(alloc, snapshot->script()), #ifdef DEBUG masm_(masm), #endif - script_(script), - pc_(script->code()), + script_(snapshot->script()), + pc_(snapshot->script()->code()), + globalLexicalEnvironment_(snapshot->globalLexical()), + globalThis_(snapshot->globalThis()), icEntryIndex_(0), - compileDebugInstrumentation_(script->isDebuggee()), - ionCompileable_(IsIonEnabled(cx) && CanIonCompileScript(cx, script)) { + baseWarmUpThreshold_(snapshot->baseWarmUpThreshold()), + compileDebugInstrumentation_(snapshot->compileDebugInstrumentation()), + ionCompileable_(snapshot->isIonCompileable()) { } -BaselineInterpreterHandler::BaselineInterpreterHandler(JSContext* cx, - MacroAssembler& masm) +BaselineInterpreterHandler::BaselineInterpreterHandler(MacroAssembler& masm) : frame_(masm) {} template template -BaselineCodeGen::BaselineCodeGen(JSContext* cx, TempAllocator& alloc, +BaselineCodeGen::BaselineCodeGen(TempAllocator& alloc, + MacroAssembler& masmArg, + CompileRuntime* runtimeArg, HandlerArgs&&... args) - : handler(cx, masm, std::forward(args)...), - cx(cx), - masm(cx, alloc), + : handler(masmArg, std::forward(args)...), + runtime(runtimeArg), + masm(masmArg), frame(handler.frame()) {} -BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, - JSScript* script) - : BaselineCodeGen(cx, alloc, /* HandlerArgs = */ alloc, script) { +BaselineCompiler::BaselineCompiler(TempAllocator& alloc, + CompileRuntime* runtime, + MacroAssembler& masm, + BaselineSnapshot* snapshot) + : BaselineCodeGen(alloc, masm, runtime, + /* HandlerArgs = */ alloc, snapshot) { #ifdef JS_CODEGEN_NONE MOZ_CRASH(); #endif } BaselineInterpreterGenerator::BaselineInterpreterGenerator(JSContext* cx, - TempAllocator& alloc) - : BaselineCodeGen(cx, alloc /* no handlerArgs */) {} + TempAllocator& alloc, + MacroAssembler& masm) + : BaselineCodeGen(alloc, masm, CompileRuntime::get(cx->runtime()) + /* no handlerArgs */) {} -bool BaselineCompilerHandler::init(JSContext* cx) { +bool BaselineCompilerHandler::init() { if (!analysis_.init(alloc_)) { return false; } @@ -130,15 +142,14 @@ bool BaselineCompilerHandler::init(JSContext* cx) { } bool BaselineCompiler::init() { - if (!handler.init(cx)) { + if (!handler.init()) { return false; } return true; } -bool BaselineCompilerHandler::recordCallRetAddr(JSContext* cx, - RetAddrEntry::Kind kind, +bool BaselineCompilerHandler::recordCallRetAddr(RetAddrEntry::Kind kind, uint32_t retOffset) { uint32_t pcOffset = script_->pcToOffset(pc_); @@ -153,15 +164,13 @@ bool BaselineCompilerHandler::recordCallRetAddr(JSContext* cx, retAddrEntries_.back().returnOffset().offset() < retOffset); if (!retAddrEntries_.emplaceBack(pcOffset, kind, CodeOffset(retOffset))) { - ReportOutOfMemory(cx); return false; } return true; } -bool BaselineInterpreterHandler::recordCallRetAddr(JSContext* cx, - RetAddrEntry::Kind kind, +bool BaselineInterpreterHandler::recordCallRetAddr(RetAddrEntry::Kind kind, uint32_t retOffset) { switch (kind) { case RetAddrEntry::Kind::DebugPrologue: @@ -187,38 +196,27 @@ bool BaselineInterpreterHandler::recordCallRetAddr(JSContext* cx, } bool BaselineInterpreterHandler::addDebugInstrumentationOffset( - JSContext* cx, CodeOffset offset) { - if (!debugInstrumentationOffsets_.append(offset.offset())) { - ReportOutOfMemory(cx); - return false; - } - return true; + CodeOffset offset) { + return debugInstrumentationOffsets_.append(offset.offset()); } -MethodStatus BaselineCompiler::compile() { - AutoCreatedBy acb(masm, "BaselineCompiler::compile"); - - Rooted script(cx, handler.script()); +/*static*/ +bool BaselineCompiler::PrepareToCompile(JSContext* cx, Handle script, + bool compileDebugInstrumentation) { JitSpew(JitSpew_BaselineScripts, "Baseline compiling script %s:%u:%u (%p)", script->filename(), script->lineno(), script->column().oneOriginValue(), script.get()); - JitSpew(JitSpew_Codegen, "# Emitting baseline code for script %s:%u:%u", - script->filename(), script->lineno(), - script->column().oneOriginValue()); - - AutoIncrementalTimer timer(cx->realm()->timers.baselineCompileTime); - AutoKeepJitScripts keepJitScript(cx); if (!script->ensureHasJitScript(cx, keepJitScript)) { - return Method_Error; + return false; } // When code coverage is enabled, we have to create the ScriptCounts if they // do not exist. if (!script->hasScriptCounts() && cx->realm()->collectCoverageForDebug()) { if (!script->initScriptCounts(cx)) { - return Method_Error; + return false; } } @@ -228,76 +226,126 @@ MethodStatus BaselineCompiler::compile() { jitHints->setEagerBaselineHint(script); } - // Suppress GC during compilation. - gc::AutoSuppressGC suppressGC(cx); - if (!script->jitScript()->ensureHasCachedBaselineJitData(cx, script)) { - return Method_Error; + return false; } + if (MOZ_UNLIKELY(compileDebugInstrumentation) && + !cx->runtime()->jitRuntime()->ensureDebugTrapHandler( + cx, DebugTrapHandlerKind::Compiler)) { + return false; + } + + return true; +} + +MethodStatus BaselineCompiler::compile(JSContext* cx) { + Rooted script(cx, handler.script()); + + JitSpew(JitSpew_Codegen, "# Emitting baseline code for script %s:%u:%u", + script->filename(), script->lineno(), + script->column().oneOriginValue()); + + AutoIncrementalTimer timer(cx->realm()->timers.baselineCompileTime); + MOZ_ASSERT(!script->hasBaselineScript()); - perfSpewer_.recordOffset(masm, "Prologue"); - if (!emitPrologue()) { - return Method_Error; - } - - MethodStatus status = emitBody(); - if (status != Method_Compiled) { - return status; - } - - perfSpewer_.recordOffset(masm, "Epilogue"); - if (!emitEpilogue()) { - return Method_Error; - } - - perfSpewer_.recordOffset(masm, "OOLPostBarrierSlot"); - if (!emitOutOfLinePostBarrierSlot()) { - return Method_Error; - } - - AutoCreatedBy acb2(masm, "exception_tail"); - Linker linker(masm); - if (masm.oom()) { + if (!compileImpl()) { ReportOutOfMemory(cx); return Method_Error; } - JitCode* code = linker.newCode(cx, CodeKind::Baseline); - if (!code) { + if (!finishCompile(cx)) { return Method_Error; } + return Method_Compiled; +} + +MethodStatus BaselineCompiler::compileOffThread() { + handler.setCompilingOffThread(); + if (!compileImpl()) { + return Method_Error; + } + return Method_Compiled; +} + +bool BaselineCompiler::compileImpl() { + AutoCreatedBy acb(masm, "BaselineCompiler::compile"); + + perfSpewer_.recordOffset(masm, "Prologue"); + if (!emitPrologue()) { + return false; + } + + if (!emitBody()) { + return false; + } + + perfSpewer_.recordOffset(masm, "Epilogue"); + if (!emitEpilogue()) { + return false; + } + + perfSpewer_.recordOffset(masm, "OOLPostBarrierSlot"); + emitOutOfLinePostBarrierSlot(); + + return true; +} + +bool BaselineCompiler::finishCompile(JSContext* cx) { + Rooted script(cx, handler.script()); + bool isSelfHostedJitCodeShared = + JS::Prefs::experimental_self_hosted_cache() && script->selfHosted(); + UniquePtr baselineScript( - BaselineScript::New( - cx, warmUpCheckPrologueOffset_.offset(), - profilerEnterFrameToggleOffset_.offset(), - profilerExitFrameToggleOffset_.offset(), - handler.retAddrEntries().length(), handler.osrEntries().length(), - debugTrapEntries_.length(), script->resumeOffsets().size()), - JS::DeletePolicy(cx->runtime())); - if (!baselineScript) { - return Method_Error; + nullptr, JS::DeletePolicy(cx->runtime())); + JitCode* code = nullptr; + { + mozilla::Maybe ar; + if (isSelfHostedJitCodeShared) { + ar.emplace(cx); + } + + AutoCreatedBy acb2(masm, "exception_tail"); + Linker linker(masm); + if (masm.oom()) { + ReportOutOfMemory(cx); + return false; + } + + code = linker.newCode(cx, CodeKind::Baseline); + if (!code) { + return false; + } + + baselineScript.reset(BaselineScript::New( + cx, warmUpCheckPrologueOffset_.offset(), + profilerEnterFrameToggleOffset_.offset(), + profilerExitFrameToggleOffset_.offset(), + handler.retAddrEntries().length(), handler.osrEntries().length(), + debugTrapEntries_.length(), script->resumeOffsets().size())); + if (!baselineScript) { + return false; + } + + baselineScript->setMethod(code); + + JitSpew(JitSpew_BaselineScripts, + "Created BaselineScript %p (raw %p) for %s:%u:%u", + (void*)baselineScript.get(), (void*)code->raw(), script->filename(), + script->lineno(), script->column().oneOriginValue()); + + // If profiler instrumentation is enabled, toggle instrumentation on. + if (cx->runtime()->jitRuntime()->isProfilerInstrumentationEnabled( + cx->runtime())) { + baselineScript->toggleProfilerInstrumentation(true); + } } - - baselineScript->setMethod(code); - - JitSpew(JitSpew_BaselineScripts, - "Created BaselineScript %p (raw %p) for %s:%u:%u", - (void*)baselineScript.get(), (void*)code->raw(), script->filename(), - script->lineno(), script->column().oneOriginValue()); - baselineScript->copyRetAddrEntries(handler.retAddrEntries().begin()); baselineScript->copyOSREntries(handler.osrEntries().begin()); baselineScript->copyDebugTrapEntries(debugTrapEntries_.begin()); - // If profiler instrumentation is enabled, toggle instrumentation on. - if (cx->runtime()->jitRuntime()->isProfilerInstrumentationEnabled( - cx->runtime())) { - baselineScript->toggleProfilerInstrumentation(true); - } - // Compute native resume addresses for the script's resume offsets. baselineScript->computeResumeNativeOffsets(script, resumeOffsetEntries_); @@ -305,32 +353,46 @@ MethodStatus BaselineCompiler::compile() { baselineScript->setHasDebugInstrumentation(); } + // If BytecodeAnalysis indicated that we should disable Ion or inlining, + // update the script now. + handler.maybeDisableIon(); + + // AllocSites must be allocated on the main thread. + handler.createAllocSites(); + // Always register a native => bytecode mapping entry, since profiler can be // turned on with baseline jitcode on stack, and baseline jitcode cannot be // invalidated. { + UniqueJitcodeGlobalEntry entry; JitSpew(JitSpew_Profiling, - "Added JitcodeGlobalEntry for baseline script %s:%u:%u (%p)", + "Added JitcodeGlobalEntry for baseline %sscript %s:%u:%u (%p)", + isSelfHostedJitCodeShared ? "shared self-hosted " : "", script->filename(), script->lineno(), script->column().oneOriginValue(), baselineScript.get()); // Generate profiling string. UniqueChars str = GeckoProfilerRuntime::allocProfileString(cx, script); if (!str) { - return Method_Error; + return false; } - auto entry = MakeJitcodeGlobalEntry( - cx, code, code->raw(), code->rawEnd(), script, std::move(str)); + if (isSelfHostedJitCodeShared) { + entry = MakeJitcodeGlobalEntry( + cx, code, code->raw(), code->rawEnd(), std::move(str)); + } else { + entry = MakeJitcodeGlobalEntry( + cx, code, code->raw(), code->rawEnd(), script, std::move(str)); + } if (!entry) { - return Method_Error; + return false; } JitcodeGlobalTable* globalTable = cx->runtime()->jitRuntime()->getJitcodeGlobalTable(); if (!globalTable->addEntry(std::move(entry))) { ReportOutOfMemory(cx); - return Method_Error; + return false; } // Mark the jitcode as having a bytecode map. @@ -345,7 +407,16 @@ MethodStatus BaselineCompiler::compile() { vtune::MarkScript(code, script, "baseline"); #endif - return Method_Compiled; + return true; +} + +void BaselineCompilerHandler::maybeDisableIon() { + if (analysis_.isIonDisabled()) { + script()->disableIon(); + } + if (analysis_.isInliningDisabled()) { + script()->setUninlineable(); + } } // On most platforms we use a dedicated bytecode PC register to avoid many @@ -383,6 +454,20 @@ static void LoadUint16Operand(MacroAssembler& masm, Register dest) { masm.load16ZeroExtend(Address(pc, sizeof(jsbytecode)), dest); } +static void LoadConstantCompareOperand(MacroAssembler& masm, + Register constantType, + Register payload) { + // Note: In baseline interpreter on 32-bit we dont + // have a separate pc register see HasInterpreterPCReg() + // so we use the payload reg as scratch first and then rewrite the + // actual payload on to it after loading the type + Register pc = LoadBytecodePC(masm, payload); + masm.load8ZeroExtend(Address(pc, ConstantCompareOperand::OFFSET_OF_TYPE), + constantType); + masm.load8SignExtend(Address(pc, ConstantCompareOperand::OFFSET_OF_VALUE), + payload); +} + static void LoadInt32Operand(MacroAssembler& masm, Register dest) { Register pc = LoadBytecodePC(masm, dest); masm.load32(Address(pc, sizeof(jsbytecode)), dest); @@ -409,14 +494,23 @@ static void LoadInlineValueOperand(MacroAssembler& masm, ValueOperand dest) { masm.loadUnalignedValue(Address(pc, sizeof(jsbytecode)), dest); } -template <> -void BaselineCompilerCodeGen::loadScript(Register dest) { - masm.movePtr(ImmGCPtr(handler.script()), dest); +template +void BaselineCodeGen::loadScript(Register dest) { + if (handler.realmIndependentJitcode()) { + masm.loadPtr(frame.addressOfInterpreterScript(), dest); + } else { + masm.movePtr(ImmGCPtr(handler.maybeScript()), dest); + } } -template <> -void BaselineInterpreterCodeGen::loadScript(Register dest) { - masm.loadPtr(frame.addressOfInterpreterScript(), dest); +template +void BaselineCodeGen::loadJitScript(Register dest) { + if (handler.realmIndependentJitcode()) { + loadScript(dest); + masm.loadPtr(Address(dest, JSScript::offsetOfWarmUpData()), dest); + } else { + masm.movePtr(ImmPtr(handler.maybeScript()->jitScript()), dest); + } } template <> @@ -507,12 +601,12 @@ void BaselineInterpreterCodeGen::emitInitializeLocals() { // This calls: // void PostWriteBarrier(JSRuntime* rt, JSObject* obj); template -bool BaselineCodeGen::emitOutOfLinePostBarrierSlot() { +void BaselineCodeGen::emitOutOfLinePostBarrierSlot() { AutoCreatedBy acb(masm, "BaselineCodeGen::emitOutOfLinePostBarrierSlot"); if (!postBarrierSlot_.used()) { - return true; + return; } masm.bind(&postBarrierSlot_); @@ -525,7 +619,7 @@ bool BaselineCodeGen::emitOutOfLinePostBarrierSlot() { // Check one element cache to avoid VM call. Label skipBarrier; - auto* lastCellAddr = cx->runtime()->gc.addressOfLastBufferedWholeCell(); + auto* lastCellAddr = runtime->addressOfLastBufferedWholeCell(); masm.branchPtr(Assembler::Equal, AbsoluteAddress(lastCellAddr), objReg, &skipBarrier); @@ -541,7 +635,7 @@ bool BaselineCodeGen::emitOutOfLinePostBarrierSlot() { using Fn = void (*)(JSRuntime* rt, js::gc::Cell* cell); masm.setupUnalignedABICall(scratch); - masm.movePtr(ImmPtr(cx->runtime()), scratch); + masm.movePtr(ImmPtr(runtime), scratch); masm.passABIArg(scratch); masm.passABIArg(objReg); masm.callWithABI(); @@ -552,7 +646,6 @@ bool BaselineCodeGen::emitOutOfLinePostBarrierSlot() { masm.bind(&skipBarrier); masm.ret(); - return true; } // Scan the a cache IR stub's fields and create an allocation site for any that @@ -596,10 +689,10 @@ static bool CreateAllocSitesForCacheIRStub(JSScript* script, uint32_t pcOffset, return true; } -static void CreateAllocSitesForICChain(JSScript* script, uint32_t pcOffset, - uint32_t entryIndex) { +static void CreateAllocSitesForICChain(JSScript* script, uint32_t entryIndex) { JitScript* jitScript = script->jitScript(); ICStub* stub = jitScript->icEntry(entryIndex).firstStub(); + uint32_t pcOffset = jitScript->fallbackStub(entryIndex)->pcOffset(); while (!stub->isFallback()) { if (!CreateAllocSitesForCacheIRStub(script, pcOffset, @@ -612,6 +705,16 @@ static void CreateAllocSitesForICChain(JSScript* script, uint32_t pcOffset, } } +void BaselineCompilerHandler::createAllocSites() { + for (uint32_t allocSiteIndex : allocSiteIndices_) { + CreateAllocSitesForICChain(script(), allocSiteIndex); + } + + if (needsEnvAllocSite_) { + script()->jitScript()->icScript()->ensureEnvAllocSite(script()); + } +} + template <> bool BaselineCompilerCodeGen::emitNextIC() { AutoCreatedBy acb(masm, "emitNextIC"); @@ -636,8 +739,9 @@ bool BaselineCompilerCodeGen::emitNextIC() { MOZ_ASSERT(stub->pcOffset() == pcOffset); MOZ_ASSERT(BytecodeOpHasIC(JSOp(*handler.pc()))); - if (BytecodeOpCanHaveAllocSite(JSOp(*handler.pc()))) { - CreateAllocSitesForICChain(script, pcOffset, entryIndex); + if (BytecodeOpCanHaveAllocSite(JSOp(*handler.pc())) && + !handler.addAllocSiteIndex(entryIndex)) { + return false; } // Load stub pointer into ICStubReg. @@ -650,7 +754,6 @@ bool BaselineCompilerCodeGen::emitNextIC() { RetAddrEntry::Kind kind = RetAddrEntry::Kind::IC; if (!handler.retAddrEntries().emplaceBack(pcOffset, kind, returnOffset)) { - ReportOutOfMemory(cx); return false; } @@ -745,7 +848,7 @@ bool BaselineCodeGen::callVMInternal(VMFunctionId id, inCall_ = false; #endif - TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id); + TrampolinePtr code = runtime->jitRuntime()->getVMWrapper(id); const VMFunctionData& fun = GetVMFunction(id); uint32_t argSize = GetVMFunctionArgSize(fun); @@ -774,7 +877,7 @@ bool BaselineCodeGen::callVMInternal(VMFunctionId id, restoreInterpreterPCReg(); - return handler.recordCallRetAddr(cx, kind, callOffset); + return handler.recordCallRetAddr(kind, callOffset); } template @@ -794,11 +897,11 @@ bool BaselineCodeGen::emitStackCheck() { masm.moveStackPtrTo(scratch); subtractScriptSlotsSize(scratch, R2.scratchReg()); masm.branchPtr(Assembler::BelowOrEqual, - AbsoluteAddress(cx->addressOfJitStackLimit()), scratch, + AbsoluteAddress(runtime->addressOfJitStackLimit()), scratch, &skipCall); } else { masm.branchStackPtrRhs(Assembler::BelowOrEqual, - AbsoluteAddress(cx->addressOfJitStackLimit()), + AbsoluteAddress(runtime->addressOfJitStackLimit()), &skipCall); } @@ -850,7 +953,7 @@ bool BaselineInterpreterCodeGen::emitIsDebuggeeCheck() { restoreInterpreterPCReg(); } masm.bind(&skipCheck); - return handler.addDebugInstrumentationOffset(cx, toggleOffset); + return handler.addDebugInstrumentationOffset(toggleOffset); } static void MaybeIncrementCodeCoverageCounter(MacroAssembler& masm, @@ -866,6 +969,12 @@ static void MaybeIncrementCodeCoverageCounter(MacroAssembler& masm, template <> bool BaselineCompilerCodeGen::emitHandleCodeCoverageAtPrologue() { + // TSAN disapproves of accessing scriptCounts off-thread. + // We don't compile off-thread if the script has scriptCounts. + if (handler.compilingOffThread()) { + return true; + } + // If the main instruction is not a jump target, then we emit the // corresponding code coverage counter. JSScript* script = handler.script(); @@ -908,36 +1017,33 @@ void BaselineInterpreterCodeGen::subtractScriptSlotsSize(Register reg, masm.subPtr(scratch, reg); } -template <> -void BaselineCompilerCodeGen::loadGlobalLexicalEnvironment(Register dest) { - MOZ_ASSERT(!handler.script()->hasNonSyntacticScope()); - masm.movePtr(ImmGCPtr(&cx->global()->lexicalEnvironment()), dest); +template +void BaselineCodeGen::loadGlobalLexicalEnvironment(Register dest) { + if (handler.realmIndependentJitcode()) { + masm.loadGlobalObjectData(dest); + masm.loadPtr(Address(dest, GlobalObjectData::offsetOfLexicalEnvironment()), + dest); + } else { + MOZ_ASSERT(!handler.maybeScript()->hasNonSyntacticScope()); + masm.movePtr(ImmGCPtr(handler.maybeGlobalLexicalEnvironment()), dest); + } } -template <> -void BaselineInterpreterCodeGen::loadGlobalLexicalEnvironment(Register dest) { - masm.loadGlobalObjectData(dest); - masm.loadPtr(Address(dest, GlobalObjectData::offsetOfLexicalEnvironment()), - dest); -} - -template <> -void BaselineCompilerCodeGen::pushGlobalLexicalEnvironmentValue( +template +void BaselineCodeGen::pushGlobalLexicalEnvironmentValue( ValueOperand scratch) { - frame.push(ObjectValue(cx->global()->lexicalEnvironment())); -} - -template <> -void BaselineInterpreterCodeGen::pushGlobalLexicalEnvironmentValue( - ValueOperand scratch) { - loadGlobalLexicalEnvironment(scratch.scratchReg()); - masm.tagValue(JSVAL_TYPE_OBJECT, scratch.scratchReg(), scratch); - frame.push(scratch); + if (handler.realmIndependentJitcode()) { + loadGlobalLexicalEnvironment(scratch.scratchReg()); + masm.tagValue(JSVAL_TYPE_OBJECT, scratch.scratchReg(), scratch); + frame.push(scratch); + } else { + frame.push(ObjectValue(*handler.maybeGlobalLexicalEnvironment())); + } } template <> void BaselineCompilerCodeGen::loadGlobalThisValue(ValueOperand dest) { - JSObject* thisObj = cx->global()->lexicalEnvironment().thisObject(); + JSObject* thisObj = handler.globalThis(); masm.moveValue(ObjectValue(*thisObj), dest); } @@ -950,14 +1056,13 @@ void BaselineInterpreterCodeGen::loadGlobalThisValue(ValueOperand dest) { masm.loadValue(Address(scratch, SlotOffset), dest); } -template <> -void BaselineCompilerCodeGen::pushScriptArg() { - pushArg(ImmGCPtr(handler.script())); -} - -template <> -void BaselineInterpreterCodeGen::pushScriptArg() { - pushArg(frame.addressOfInterpreterScript()); +template +void BaselineCodeGen::pushScriptArg() { + if (handler.realmIndependentJitcode()) { + pushArg(frame.addressOfInterpreterScript()); + } else { + pushArg(ImmGCPtr(handler.maybeScript())); + } } template <> @@ -995,23 +1100,10 @@ static gc::Cell* GetScriptGCThing(JSScript* script, jsbytecode* pc, MOZ_CRASH("Unexpected GCThing type"); } -template <> -void BaselineCompilerCodeGen::loadScriptGCThing(ScriptGCThingType type, - Register dest, - Register scratch) { - gc::Cell* thing = GetScriptGCThing(handler.script(), handler.pc(), type); - masm.movePtr(ImmGCPtr(thing), dest); -} - -template <> -void BaselineInterpreterCodeGen::loadScriptGCThing(ScriptGCThingType type, - Register dest, - Register scratch) { - MOZ_ASSERT(dest != scratch); - - // Load the index in |scratch|. - LoadInt32Operand(masm, scratch); - +template +void BaselineCodeGen::loadScriptGCThingInternal(ScriptGCThingType type, + Register dest, + Register scratch) { // Load the GCCellPtr. loadScript(dest); masm.loadPtr(Address(dest, JSScript::offsetOfPrivateData()), dest); @@ -1051,6 +1143,31 @@ void BaselineInterpreterCodeGen::loadScriptGCThing(ScriptGCThingType type, masm.xorPtr(Imm32(JS::OutOfLineTraceKindMask), dest); break; } +} + +template <> +void BaselineCompilerCodeGen::loadScriptGCThing(ScriptGCThingType type, + Register dest, + Register scratch) { + if (handler.realmIndependentJitcode()) { + masm.move32(Imm32(GET_GCTHING_INDEX(handler.pc())), scratch); + loadScriptGCThingInternal(type, dest, scratch); + } else { + gc::Cell* thing = GetScriptGCThing(handler.script(), handler.pc(), type); + masm.movePtr(ImmGCPtr(thing), dest); + } +} + +template <> +void BaselineInterpreterCodeGen::loadScriptGCThing(ScriptGCThingType type, + Register dest, + Register scratch) { + MOZ_ASSERT(dest != scratch); + + // Load the index in |scratch|. + LoadInt32Operand(masm, scratch); + + loadScriptGCThingInternal(type, dest, scratch); #ifdef DEBUG // Assert low bits are not set. @@ -1061,20 +1178,18 @@ void BaselineInterpreterCodeGen::loadScriptGCThing(ScriptGCThingType type, #endif } -template <> -void BaselineCompilerCodeGen::pushScriptGCThingArg(ScriptGCThingType type, - Register scratch1, - Register scratch2) { - gc::Cell* thing = GetScriptGCThing(handler.script(), handler.pc(), type); - pushArg(ImmGCPtr(thing)); -} - -template <> -void BaselineInterpreterCodeGen::pushScriptGCThingArg(ScriptGCThingType type, - Register scratch1, - Register scratch2) { - loadScriptGCThing(type, scratch1, scratch2); - pushArg(scratch1); +template +void BaselineCodeGen::pushScriptGCThingArg(ScriptGCThingType type, + Register scratch1, + Register scratch2) { + if (handler.realmIndependentJitcode()) { + loadScriptGCThing(type, scratch1, scratch2); + pushArg(scratch1); + } else { + gc::Cell* thing = + GetScriptGCThing(handler.maybeScript(), handler.maybePC(), type); + pushArg(ImmGCPtr(thing)); + } } template @@ -1149,13 +1264,26 @@ void BaselineCompilerCodeGen::emitInitFrameFields(Register nonFunctionEnv) { Register scratch2 = R2.scratchReg(); MOZ_ASSERT(nonFunctionEnv != scratch && nonFunctionEnv != scratch2); - masm.store32(Imm32(0), frame.addressOfFlags()); + uint32_t flags = + handler.realmIndependentJitcode() ? BaselineFrame::REALM_INDEPENDENT : 0; + masm.store32(Imm32(flags), frame.addressOfFlags()); + if (handler.function()) { masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), scratch); masm.unboxObject(Address(scratch, JSFunction::offsetOfEnvironment()), - scratch); - masm.storePtr(scratch, frame.addressOfEnvironmentChain()); + scratch2); + masm.storePtr(scratch2, frame.addressOfEnvironmentChain()); + if (handler.realmIndependentJitcode()) { + masm.loadPrivate(Address(scratch, JSFunction::offsetOfJitInfoOrScript()), + scratch); + masm.storePtr(scratch, frame.addressOfInterpreterScript()); + } } else { + if (handler.realmIndependentJitcode()) { + masm.loadPtr(frame.addressOfCalleeToken(), scratch); + masm.andPtr(Imm32(uint32_t(CalleeTokenMask)), scratch); + masm.storePtr(scratch, frame.addressOfInterpreterScript()); + } masm.storePtr(nonFunctionEnv, frame.addressOfEnvironmentChain()); } @@ -1163,7 +1291,7 @@ void BaselineCompilerCodeGen::emitInitFrameFields(Register nonFunctionEnv) { // the caller), take that ICScript and store it in the frame, then // overwrite cx->inlinedICScript with nullptr. Label notInlined, done; - masm.movePtr(ImmPtr(cx->addressOfInlinedICScript()), scratch); + masm.movePtr(ImmPtr(runtime->addressOfInlinedICScript()), scratch); Address inlinedAddr(scratch, 0); masm.branchPtr(Assembler::Equal, inlinedAddr, ImmWord(0), ¬Inlined); masm.loadPtr(inlinedAddr, scratch2); @@ -1173,8 +1301,18 @@ void BaselineCompilerCodeGen::emitInitFrameFields(Register nonFunctionEnv) { // Otherwise, store this script's default ICSCript in the frame. masm.bind(¬Inlined); - masm.storePtr(ImmPtr(handler.script()->jitScript()->icScript()), - frame.addressOfICScript()); + if (handler.realmIndependentJitcode()) { + // When JitCode is reused in a new realm, the frames baked into + // the native bytecode need to refer to the IC list for the new JitScript or + // they will execute the IC scripts using the IC stub fields from the wrong + // script. + loadJitScript(scratch); + masm.addPtr(Imm32(JitScript::offsetOfICScript()), scratch); + masm.storePtr(scratch, frame.addressOfICScript()); + } else { + masm.storePtr(ImmPtr(handler.script()->jitScript()->icScript()), + frame.addressOfICScript()); + } masm.bind(&done); } @@ -1262,82 +1400,83 @@ bool BaselineCompilerCodeGen::initEnvironmentChain() { return true; } - // Allocate a NamedLambdaObject and/or a CallObject. If the function needs - // both, the NamedLambdaObject must enclose the CallObject. If one of the - // allocations fails, we perform the whole operation in C++. - - JSObject* templateEnv = handler.script()->jitScript()->templateEnvironment(); - MOZ_ASSERT(templateEnv); - - CallObject* callObjectTemplate = nullptr; - if (handler.function()->needsCallObject()) { - callObjectTemplate = &templateEnv->as(); - } - - NamedLambdaObject* namedLambdaTemplate = nullptr; - if (handler.function()->needsNamedLambdaEnvironment()) { - if (callObjectTemplate) { - templateEnv = templateEnv->enclosingEnvironment(); - } - namedLambdaTemplate = &templateEnv->as(); - } - - MOZ_ASSERT(namedLambdaTemplate || callObjectTemplate); - AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All()); - Register newEnv = regs.takeAny(); - Register enclosingEnv = regs.takeAny(); - Register callee = regs.takeAny(); Register temp = regs.takeAny(); - - Label fail; - masm.loadPtr(frame.addressOfEnvironmentChain(), enclosingEnv); - masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), callee); - - // Allocate a NamedLambdaObject if needed. - if (namedLambdaTemplate) { - TemplateObject templateObject(namedLambdaTemplate); - masm.createGCObject(newEnv, temp, templateObject, gc::Heap::Default, &fail); - - // Store enclosing environment. - Address enclosingSlot(newEnv, - NamedLambdaObject::offsetOfEnclosingEnvironment()); - masm.storeValue(JSVAL_TYPE_OBJECT, enclosingEnv, enclosingSlot); - AssertCanElidePostWriteBarrier(masm, newEnv, enclosingEnv, temp); - - // Store callee. - Address lambdaSlot(newEnv, NamedLambdaObject::offsetOfLambdaSlot()); - masm.storeValue(JSVAL_TYPE_OBJECT, callee, lambdaSlot); - AssertCanElidePostWriteBarrier(masm, newEnv, callee, temp); - - if (callObjectTemplate) { - masm.movePtr(newEnv, enclosingEnv); - } - } - - // Allocate a CallObject if needed. - if (callObjectTemplate) { - TemplateObject templateObject(callObjectTemplate); - masm.createGCObject(newEnv, temp, templateObject, gc::Heap::Default, &fail); - - // Store enclosing environment. - Address enclosingSlot(newEnv, CallObject::offsetOfEnclosingEnvironment()); - masm.storeValue(JSVAL_TYPE_OBJECT, enclosingEnv, enclosingSlot); - AssertCanElidePostWriteBarrier(masm, newEnv, enclosingEnv, temp); - - // Store callee. - Address calleeSlot(newEnv, CallObject::offsetOfCallee()); - masm.storeValue(JSVAL_TYPE_OBJECT, callee, calleeSlot); - AssertCanElidePostWriteBarrier(masm, newEnv, callee, temp); - } - - // Update the frame's environment chain and mark it initialized. Label done; - masm.storePtr(newEnv, frame.addressOfEnvironmentChain()); - masm.or32(Imm32(BaselineFrame::HAS_INITIAL_ENV), frame.addressOfFlags()); - masm.jump(&done); + if (!handler.realmIndependentJitcode()) { + // Allocate a NamedLambdaObject and/or a CallObject. If the function needs + // both, the NamedLambdaObject must enclose the CallObject. If one of the + // allocations fails, we perform the whole operation in C++. - masm.bind(&fail); + auto [callObjectTemplate, namedLambdaTemplate] = + handler.script()->jitScript()->functionEnvironmentTemplates( + handler.function()); + MOZ_ASSERT(namedLambdaTemplate || callObjectTemplate); + + Register newEnv = regs.takeAny(); + Register enclosingEnv = regs.takeAny(); + Register callee = regs.takeAny(); + Register siteRegister; + + Label fail; + masm.loadPtr(frame.addressOfEnvironmentChain(), enclosingEnv); + masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), callee); + + AllocSiteInput site; + if (handler.addEnvAllocSite()) { + siteRegister = regs.takeAny(); + masm.loadPtr(frame.addressOfICScript(), temp); + masm.loadPtr(Address(temp, ICScript::offsetOfEnvAllocSite()), + siteRegister); + site = AllocSiteInput(siteRegister); + } + + // Allocate a NamedLambdaObject if needed. + if (namedLambdaTemplate) { + TemplateObject templateObject(namedLambdaTemplate); + masm.createGCObject(newEnv, temp, templateObject, gc::Heap::Default, + &fail, true, site); + + // Store enclosing environment. + Address enclosingSlot(newEnv, + NamedLambdaObject::offsetOfEnclosingEnvironment()); + masm.storeValue(JSVAL_TYPE_OBJECT, enclosingEnv, enclosingSlot); + AssertCanElidePostWriteBarrier(masm, newEnv, enclosingEnv, temp); + + // Store callee. + Address lambdaSlot(newEnv, NamedLambdaObject::offsetOfLambdaSlot()); + masm.storeValue(JSVAL_TYPE_OBJECT, callee, lambdaSlot); + AssertCanElidePostWriteBarrier(masm, newEnv, callee, temp); + + if (callObjectTemplate) { + masm.movePtr(newEnv, enclosingEnv); + } + } + + // Allocate a CallObject if needed. + if (callObjectTemplate) { + TemplateObject templateObject(callObjectTemplate); + masm.createGCObject(newEnv, temp, templateObject, gc::Heap::Default, + &fail, true, site); + + // Store enclosing environment. + Address enclosingSlot(newEnv, CallObject::offsetOfEnclosingEnvironment()); + masm.storeValue(JSVAL_TYPE_OBJECT, enclosingEnv, enclosingSlot); + AssertCanElidePostWriteBarrier(masm, newEnv, enclosingEnv, temp); + + // Store callee. + Address calleeSlot(newEnv, CallObject::offsetOfCallee()); + masm.storeValue(JSVAL_TYPE_OBJECT, callee, calleeSlot); + AssertCanElidePostWriteBarrier(masm, newEnv, callee, temp); + } + + // Update the frame's environment chain and mark it initialized. + masm.storePtr(newEnv, frame.addressOfEnvironmentChain()); + masm.or32(Imm32(BaselineFrame::HAS_INITIAL_ENV), frame.addressOfFlags()); + masm.jump(&done); + + masm.bind(&fail); + } prepareVMCall(); @@ -1392,8 +1531,9 @@ bool BaselineCodeGen::emitInterruptCheck() { frame.syncStack(0); Label done; - masm.branch32(Assembler::Equal, AbsoluteAddress(cx->addressOfInterruptBits()), - Imm32(0), &done); + masm.branch32(Assembler::Equal, + AbsoluteAddress(runtime->addressOfInterruptBits()), Imm32(0), + &done); prepareVMCall(); @@ -1424,7 +1564,6 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() { uint32_t pcOffset = script->pcToOffset(pc); uint32_t nativeOffset = masm.currentOffset(); if (!handler.osrEntries().emplaceBack(pcOffset, nativeOffset)) { - ReportOutOfMemory(cx); return false; } } @@ -1481,9 +1620,8 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() { Label done; - const OptimizationInfo* info = - IonOptimizations.get(OptimizationLevel::Normal); - uint32_t warmUpThreshold = info->compilerWarmUpThreshold(cx, script, pc); + uint32_t warmUpThreshold = OptimizationInfo::warmUpThresholdForPC( + script, pc, handler.baseWarmUpThreshold()); masm.branch32(Assembler::LessThan, countReg, Imm32(warmUpThreshold), &done); // Don't trigger Warp compilations from trial-inlined scripts. @@ -1498,10 +1636,8 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() { // Do nothing if Ion is already compiling this script off-thread or if Ion has // been disabled for this script. - masm.branchPtr(Assembler::Equal, scriptReg, ImmPtr(IonCompilingScriptPtr), - &done); - masm.branchPtr(Assembler::Equal, scriptReg, ImmPtr(IonDisabledScriptPtr), - &done); + masm.branchTestPtr(Assembler::NonZero, scriptReg, Imm32(SpecialScriptBit), + &done); // Try to compile and/or finish a compilation. if (JSOp(*pc) == JSOp::LoopHead) { @@ -1552,9 +1688,10 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() { { Label checkOk; AbsoluteAddress addressOfEnabled( - cx->runtime()->geckoProfiler().addressOfEnabled()); + runtime->geckoProfiler().addressOfEnabled()); masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &checkOk); - masm.loadPtr(AbsoluteAddress((void*)&cx->jitActivation), scratchReg); + masm.loadPtr(AbsoluteAddress(runtime->addressOfJitActivation()), + scratchReg); masm.loadPtr( Address(scratchReg, JitActivation::offsetOfLastProfilingFrame()), scratchReg); @@ -1610,14 +1747,114 @@ bool BaselineInterpreterCodeGen::emitWarmUpCounterIncrement() { masm.add32(Imm32(1), countReg); masm.store32(countReg, warmUpCounterAddr); + if (JitOptions.baselineBatching) { + Register scratch = R1.scratchReg(); + Label done, compileBatch; + Address baselineScriptAddr(scriptReg, JitScript::offsetOfBaselineScript()); + + // If the script is not warm enough to compile, we're done. + masm.branch32(Assembler::BelowOrEqual, countReg, + Imm32(JitOptions.baselineJitWarmUpThreshold), &done); + + // Decide what to do based on the state of the baseline script field. + Label notSpecial; + masm.loadPtr(baselineScriptAddr, scratch); + masm.branchTestPtr(Assembler::Zero, scratch, Imm32(SpecialScriptBit), + ¬Special); + + // The baseline script is a special tagged value: disabled, queued, or + // compiling. If it's queued and the warmup count is high enough, + // trigger a batch compilation with whatever is currently queued. + // Otherwise, we're done. + uint32_t eagerWarmUpThreshold = JitOptions.baselineJitWarmUpThreshold * 2; + masm.branchPtr(Assembler::NotEqual, scratch, + ImmPtr(BaselineQueuedScriptPtr), &done); + + masm.branch32(Assembler::Below, countReg, Imm32(eagerWarmUpThreshold), + &done); + + masm.jump(&compileBatch); + + masm.bind(¬Special); + + // If we already have a valid BaselineScript, tier up now. + Label notCompiled; + masm.branchPtr(Assembler::BelowOrEqual, scratch, + ImmPtr(BaselineCompilingScriptPtr), ¬Compiled); + + // We just need to update our frame, find the OSR address, and jump to it. + saveInterpreterPCReg(); + + using Fn = uint8_t* (*)(BaselineFrame*); + masm.setupUnalignedABICall(R0.scratchReg()); + masm.loadBaselineFramePtr(FramePointer, R0.scratchReg()); + masm.passABIArg(R0.scratchReg()); + masm.callWithABI(); + + // If we are a debuggee frame, and our baseline script was compiled + // without debug instrumentation, and recompilation failed, we may + // not have an OSR entry available. + masm.branchTestPtr(Assembler::Zero, ReturnReg, ReturnReg, &done); + + // Otherwise: OSR! + masm.jump(ReturnReg); + + masm.bind(¬Compiled); + + // Otherwise, add this script to the queue. + // First, mark the jitscript as queued. + masm.storePtr(ImmPtr(BaselineQueuedScriptPtr), baselineScriptAddr); + + Register queueReg = scratch; + masm.loadBaselineCompileQueue(queueReg); + + Address numQueuedAddr(queueReg, BaselineCompileQueue::offsetOfNumQueued()); + masm.load32(numQueuedAddr, countReg); + + BaseIndex queueSlot(queueReg, countReg, ScalePointer, + BaselineCompileQueue::offsetOfQueue()); + + // Store the JSScript in the compilation queue. Note that we don't need + // a prebarrier here because we will always be overwriting a nullptr, + // and we don't need a postbarrier because the script is always tenured. +#ifdef DEBUG + Label queueSlotIsEmpty; + masm.branchPtr(Assembler::Equal, queueSlot, ImmWord(0), &queueSlotIsEmpty); + masm.assumeUnreachable( + "Overwriting non-null slot in baseline compile queue"); + masm.bind(&queueSlotIsEmpty); +#endif + loadScript(scriptReg); + masm.storePtr(scriptReg, queueSlot); + + // Update `numQueued`. + masm.add32(Imm32(1), countReg); + masm.store32(countReg, numQueuedAddr); + + // If the queue is now full, trigger a batch compilation. + masm.branch32(Assembler::Below, countReg, + Imm32(JitOptions.baselineQueueCapacity), &done); + + masm.bind(&compileBatch); + prepareVMCall(); + + using Fn2 = bool (*)(JSContext*); + if (!callVM()) { + return false; + } + masm.bind(&done); + return true; + } + // If the script is warm enough for Baseline compilation, call into the VM to // compile it. Label done; masm.branch32(Assembler::BelowOrEqual, countReg, Imm32(JitOptions.baselineJitWarmUpThreshold), &done); - masm.branchPtr(Assembler::Equal, - Address(scriptReg, JitScript::offsetOfBaselineScript()), - ImmPtr(BaselineDisabledScriptPtr), &done); + + masm.branchTestPtr(Assembler::NonZero, + Address(scriptReg, JitScript::offsetOfBaselineScript()), + Imm32(SpecialScriptBit), &done); { prepareVMCall(); @@ -1655,22 +1892,17 @@ bool BaselineCompiler::emitDebugTrap() { DebugAPI::hasBreakpointsAt(script, handler.pc()); // Emit patchable call to debug trap handler. - JitCode* handlerCode = cx->runtime()->jitRuntime()->debugTrapHandler( - cx, DebugTrapHandlerKind::Compiler); - if (!handlerCode) { - return false; - } - + JitCode* handlerCode = + runtime->jitRuntime()->debugTrapHandler(DebugTrapHandlerKind::Compiler); CodeOffset nativeOffset = masm.toggledCall(handlerCode, enabled); uint32_t pcOffset = script->pcToOffset(handler.pc()); if (!debugTrapEntries_.emplaceBack(pcOffset, nativeOffset.offset())) { - ReportOutOfMemory(cx); return false; } // Add a RetAddrEntry for the return offset -> pc mapping. - return handler.recordCallRetAddr(cx, RetAddrEntry::Kind::DebugTrap, + return handler.recordCallRetAddr(RetAddrEntry::Kind::DebugTrap, masm.currentOffset()); } @@ -2469,43 +2701,42 @@ bool BaselineInterpreterCodeGen::emit_Double() { return true; } -template <> -bool BaselineCompilerCodeGen::emit_BigInt() { - BigInt* bi = handler.script()->getBigInt(handler.pc()); - frame.push(BigIntValue(bi)); +template +bool BaselineCodeGen::emit_BigInt() { + if (handler.realmIndependentJitcode()) { + frame.syncStack(0); + Register scratch1 = R0.scratchReg(); + Register scratch2 = R1.scratchReg(); + loadScriptGCThing(ScriptGCThingType::BigInt, scratch1, scratch2); + masm.tagValue(JSVAL_TYPE_BIGINT, scratch1, R0); + frame.push(R0); + } else { + BigInt* bi = handler.maybeScript()->getBigInt(handler.maybePC()); + frame.push(BigIntValue(bi)); + } return true; } -template <> -bool BaselineInterpreterCodeGen::emit_BigInt() { - Register scratch1 = R0.scratchReg(); - Register scratch2 = R1.scratchReg(); - loadScriptGCThing(ScriptGCThingType::BigInt, scratch1, scratch2); - masm.tagValue(JSVAL_TYPE_BIGINT, scratch1, R0); - frame.push(R0); - return true; -} - -template <> -bool BaselineCompilerCodeGen::emit_String() { - frame.push(StringValue(handler.script()->getString(handler.pc()))); - return true; -} - -template <> -bool BaselineInterpreterCodeGen::emit_String() { - Register scratch1 = R0.scratchReg(); - Register scratch2 = R1.scratchReg(); - loadScriptGCThing(ScriptGCThingType::String, scratch1, scratch2); - masm.tagValue(JSVAL_TYPE_STRING, scratch1, R0); - frame.push(R0); +template +bool BaselineCodeGen::emit_String() { + if (handler.realmIndependentJitcode()) { + frame.syncStack(0); + Register scratch1 = R0.scratchReg(); + Register scratch2 = R1.scratchReg(); + loadScriptGCThing(ScriptGCThingType::String, scratch1, scratch2); + masm.tagValue(JSVAL_TYPE_STRING, scratch1, R0); + frame.push(R0); + } else { + frame.push( + StringValue(handler.maybeScript()->getString(handler.maybePC()))); + } return true; } template <> bool BaselineCompilerCodeGen::emit_Symbol() { unsigned which = GET_UINT8(handler.pc()); - JS::Symbol* sym = cx->runtime()->wellKnownSymbols->get(which); + JS::Symbol* sym = runtime->wellKnownSymbols().get(which); frame.push(SymbolValue(sym)); return true; } @@ -2516,7 +2747,7 @@ bool BaselineInterpreterCodeGen::emit_Symbol() { Register scratch2 = R1.scratchReg(); LoadUint8Operand(masm, scratch1); - masm.movePtr(ImmPtr(cx->runtime()->wellKnownSymbols), scratch2); + masm.movePtr(ImmPtr(&runtime->wellKnownSymbols()), scratch2); masm.loadPtr(BaseIndex(scratch2, scratch1, ScalePointer), scratch1); masm.tagValue(JSVAL_TYPE_SYMBOL, scratch1, R0); @@ -2524,19 +2755,18 @@ bool BaselineInterpreterCodeGen::emit_Symbol() { return true; } -template <> -bool BaselineCompilerCodeGen::emit_Object() { - frame.push(ObjectValue(*handler.script()->getObject(handler.pc()))); - return true; -} - -template <> -bool BaselineInterpreterCodeGen::emit_Object() { - Register scratch1 = R0.scratchReg(); - Register scratch2 = R1.scratchReg(); - loadScriptGCThing(ScriptGCThingType::Object, scratch1, scratch2); - masm.tagValue(JSVAL_TYPE_OBJECT, scratch1, R0); - frame.push(R0); +template +bool BaselineCodeGen::emit_Object() { + if (handler.realmIndependentJitcode()) { + Register scratch1 = R0.scratchReg(); + Register scratch2 = R1.scratchReg(); + loadScriptGCThing(ScriptGCThingType::Object, scratch1, scratch2); + masm.tagValue(JSVAL_TYPE_OBJECT, scratch1, R0); + frame.push(R0); + } else { + frame.push( + ObjectValue(*handler.maybeScript()->getObject(handler.maybePC()))); + } return true; } @@ -2562,41 +2792,14 @@ bool BaselineCodeGen::emit_RegExp() { return true; } -#ifdef ENABLE_RECORD_TUPLE -# define UNSUPPORTED_OPCODE(OP) \ - template \ - bool BaselineCodeGen::emit_##OP() { \ - MOZ_CRASH("Record and Tuple are not supported by jit"); \ - return false; \ - } - -UNSUPPORTED_OPCODE(InitRecord) -UNSUPPORTED_OPCODE(AddRecordProperty) -UNSUPPORTED_OPCODE(AddRecordSpread) -UNSUPPORTED_OPCODE(FinishRecord) -UNSUPPORTED_OPCODE(InitTuple) -UNSUPPORTED_OPCODE(AddTupleElement) -UNSUPPORTED_OPCODE(FinishTuple) - -# undef UNSUPPORTED_OPCODE -#endif - template bool BaselineCodeGen::emit_Lambda() { - prepareVMCall(); - masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg()); + frame.syncStack(0); - pushArg(R0.scratchReg()); - pushScriptGCThingArg(ScriptGCThingType::Function, R0.scratchReg(), - R1.scratchReg()); - - using Fn = JSObject* (*)(JSContext*, HandleFunction, HandleObject); - if (!callVM()) { + if (!emitNextIC()) { return false; } - // Box and push return value. - masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); frame.push(R0); return true; } @@ -2786,6 +2989,195 @@ bool BaselineCodeGen::emit_StrictNe() { return emitCompare(); } +template <> +bool BaselineCompilerCodeGen::emitConstantStrictEq(JSOp op) { + ConstantCompareOperand data = + ConstantCompareOperand::fromRawValue(GET_UINT16(handler.pc())); + + frame.popRegsAndSync(1); + + ValueOperand value = R0; + Label fail, pass, done; + + switch (data.type()) { + case ConstantCompareOperand::EncodedType::Int32: { + int32_t constantVal = data.toInt32(); + + Label maybeDouble; + masm.branchTestInt32(Assembler::NotEqual, value, &maybeDouble); + masm.branch32(JSOpToCondition(op, true), value.payloadOrValueReg(), + Imm32(constantVal), &pass, + MacroAssembler::LhsHighBitsAreClean::No); + masm.jump(&fail); + + masm.bind(&maybeDouble); + { + FloatRegister unboxedValue = FloatReg0; + FloatRegister floatPayload = FloatReg1; + + masm.branchTestDouble(Assembler::NotEqual, value, + op == JSOp::StrictEq ? &fail : &pass); + + masm.unboxDouble(value, unboxedValue); + masm.loadConstantDouble(double(constantVal), floatPayload); + masm.branchDouble(JSOpToDoubleCondition(op), unboxedValue, floatPayload, + &pass); + } + break; + } + + case ConstantCompareOperand::EncodedType::Boolean: { + bool constantVal = data.toBoolean(); + Register boolUnboxed = R1.scratchReg(); + masm.fallibleUnboxBoolean(value, boolUnboxed, + op == JSOp::StrictEq ? &fail : &pass); + masm.branch32(JSOpToCondition(op, true), boolUnboxed, Imm32(constantVal), + &pass); + break; + } + + case ConstantCompareOperand::EncodedType::Null: { + masm.branchTestNull(Assembler::NotEqual, value, + op == JSOp::StrictEq ? &fail : &pass); + if (op == JSOp::StrictEq) { + masm.jump(&pass); + } + break; + } + + case ConstantCompareOperand::EncodedType::Undefined: { + masm.branchTestUndefined(Assembler::NotEqual, value, + op == JSOp::StrictEq ? &fail : &pass); + if (op == JSOp::StrictEq) { + masm.jump(&pass); + } + break; + } + } + + masm.bind(&fail); + { + masm.moveValue(BooleanValue(false), R0); + masm.jump(&done); + } + + masm.bind(&pass); + { + masm.moveValue(BooleanValue(true), R0); + } + + masm.bind(&done); + frame.push(R0, JSVAL_TYPE_BOOLEAN); + return true; +} + +template <> +bool BaselineCompilerCodeGen::emit_StrictConstantEq() { + return emitConstantStrictEq(JSOp::StrictEq); +} + +template <> +bool BaselineCompilerCodeGen::emit_StrictConstantNe() { + return emitConstantStrictEq(JSOp::StrictNe); +} + +template <> +bool BaselineInterpreterCodeGen::emitConstantStrictEq(JSOp op) { + frame.popRegsAndSync(1); + + ValueOperand value = R0; + Register constantType = R1.scratchReg(); + Register payload = R2.scratchReg(); + + LoadConstantCompareOperand(masm, constantType, payload); + Label isInt32, isBool, isNull, isUndefined; + Label pass, fail, done; + + masm.branch32(Assembler::Equal, constantType, + Imm32(int32_t(ConstantCompareOperand::EncodedType::Int32)), + &isInt32); + masm.branch32(Assembler::Equal, constantType, + Imm32(int32_t(ConstantCompareOperand::EncodedType::Boolean)), + &isBool); + masm.branch32(Assembler::Equal, constantType, + Imm32(int32_t(ConstantCompareOperand::EncodedType::Null)), + &isNull); + masm.branch32(Assembler::Equal, constantType, + Imm32(int32_t(ConstantCompareOperand::EncodedType::Undefined)), + &isUndefined); + masm.assumeUnreachable("Unexpected constant compare type"); + + masm.bind(&isInt32); + { + Label maybeDouble; + masm.branchTestInt32(Assembler::NotEqual, value, &maybeDouble); + masm.branch32(JSOpToCondition(op, true), value.payloadOrValueReg(), payload, + &pass, MacroAssembler::LhsHighBitsAreClean::No); + masm.jump(&fail); + + masm.bind(&maybeDouble); + { + FloatRegister unboxedValue = FloatReg0; + FloatRegister floatPayload = FloatReg1; + masm.branchTestDouble(Assembler::NotEqual, value, + op == JSOp::StrictEq ? &fail : &pass); + masm.unboxDouble(value, unboxedValue); + masm.convertInt32ToDouble(payload, floatPayload); + masm.branchDouble(JSOpToDoubleCondition(op), unboxedValue, floatPayload, + &pass); + masm.jump(&fail); + } + } + + masm.bind(&isBool); + { + Register boolUnboxed = R1.scratchReg(); + masm.fallibleUnboxBoolean(value, boolUnboxed, + op == JSOp::StrictEq ? &fail : &pass); + masm.branch32(JSOpToCondition(op, true), boolUnboxed, payload, &pass); + masm.jump(&fail); + } + + masm.bind(&isNull); + { + masm.branchTestNull(Assembler::NotEqual, value, + op == JSOp::StrictEq ? &fail : &pass); + masm.jump(op == JSOp::StrictEq ? &pass : &fail); + } + + masm.bind(&isUndefined); + { + masm.branchTestUndefined(Assembler::NotEqual, value, + op == JSOp::StrictEq ? &fail : &pass); + masm.jump(op == JSOp::StrictEq ? &pass : &fail); + } + + masm.bind(&pass); + { + masm.moveValue(BooleanValue(true), value); + masm.jump(&done); + } + + masm.bind(&fail); + { + masm.moveValue(BooleanValue(false), value); + } + + masm.bind(&done); + frame.push(R0, JSVAL_TYPE_BOOLEAN); + return true; +} + +template <> +bool BaselineInterpreterCodeGen::emit_StrictConstantEq() { + return emitConstantStrictEq(JSOp::StrictEq); +} + +template <> +bool BaselineInterpreterCodeGen::emit_StrictConstantNe() { + return emitConstantStrictEq(JSOp::StrictNe); +} + template bool BaselineCodeGen::emit_Case() { frame.popRegsAndSync(1); @@ -3254,13 +3646,21 @@ bool BaselineCodeGen::emit_GetGName() { } template <> -bool BaselineCompilerCodeGen::tryOptimizeBindGlobalName() { +bool BaselineCompilerCodeGen::tryOptimizeBindUnqualifiedGlobalName() { + if (handler.realmIndependentJitcode()) { + return false; + } JSScript* script = handler.script(); MOZ_ASSERT(!script->hasNonSyntacticScope()); - Rooted global(cx, &script->global()); - Rooted name(cx, script->getName(handler.pc())); - if (JSObject* binding = MaybeOptimizeBindGlobalName(cx, global, name)) { + if (handler.compilingOffThread()) { + return false; + } + + GlobalObject* global = &script->global(); + PropertyName* name = script->getName(handler.pc()); + if (JSObject* binding = + MaybeOptimizeBindUnqualifiedGlobalName(global, name)) { frame.push(ObjectValue(*binding)); return true; } @@ -3268,14 +3668,14 @@ bool BaselineCompilerCodeGen::tryOptimizeBindGlobalName() { } template <> -bool BaselineInterpreterCodeGen::tryOptimizeBindGlobalName() { - // Interpreter doesn't optimize simple BindGNames. +bool BaselineInterpreterCodeGen::tryOptimizeBindUnqualifiedGlobalName() { + // Interpreter doesn't optimize simple BindUnqualifiedGNames. return false; } template -bool BaselineCodeGen::emit_BindGName() { - if (tryOptimizeBindGlobalName()) { +bool BaselineCodeGen::emit_BindUnqualifiedGName() { + if (tryOptimizeBindUnqualifiedGlobalName()) { return true; } @@ -3715,6 +4115,21 @@ bool BaselineCodeGen::emit_GetName() { return true; } +template +bool BaselineCodeGen::emit_BindUnqualifiedName() { + frame.syncStack(0); + masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg()); + + // Call IC. + if (!emitNextIC()) { + return false; + } + + // Mark R0 as pushed stack value. + frame.push(R0); + return true; +} + template bool BaselineCodeGen::emit_BindName() { frame.syncStack(0); @@ -3750,59 +4165,11 @@ bool BaselineCodeGen::emit_DelName() { return true; } -template <> -bool BaselineCompilerCodeGen::emit_GetImport() { - JSScript* script = handler.script(); - ModuleEnvironmentObject* env = GetModuleEnvironmentForScript(script); - MOZ_ASSERT(env); - - jsid id = NameToId(script->getName(handler.pc())); - ModuleEnvironmentObject* targetEnv; - Maybe prop; - MOZ_ALWAYS_TRUE(env->lookupImport(id, &targetEnv, &prop)); - +template +bool BaselineCodeGen::emit_GetImport() { frame.syncStack(0); - uint32_t slot = prop->slot(); - Register scratch = R0.scratchReg(); - masm.movePtr(ImmGCPtr(targetEnv), scratch); - if (slot < targetEnv->numFixedSlots()) { - masm.loadValue(Address(scratch, NativeObject::getFixedSlotOffset(slot)), - R0); - } else { - masm.loadPtr(Address(scratch, NativeObject::offsetOfSlots()), scratch); - masm.loadValue( - Address(scratch, (slot - targetEnv->numFixedSlots()) * sizeof(Value)), - R0); - } - - // Imports are initialized by this point except in rare circumstances, so - // don't emit a check unless we have to. - if (targetEnv->getSlot(slot).isMagic(JS_UNINITIALIZED_LEXICAL)) { - if (!emitUninitializedLexicalCheck(R0)) { - return false; - } - } - - frame.push(R0); - return true; -} - -template <> -bool BaselineInterpreterCodeGen::emit_GetImport() { - frame.syncStack(0); - - masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg()); - - prepareVMCall(); - - pushBytecodePCArg(); - pushScriptArg(); - pushArg(R0.scratchReg()); - - using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*, - MutableHandleValue); - if (!callVM()) { + if (!emitNextIC()) { return false; } @@ -4496,20 +4863,28 @@ bool BaselineCodeGen::emit_OptimizeSpreadCall() { template bool BaselineCodeGen::emit_ImplicitThis() { - frame.syncStack(0); - masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg()); + frame.popRegsAndSync(1); - prepareVMCall(); + Register env = R1.scratchReg(); + masm.unboxObject(R0, env); - pushScriptNameArg(R1.scratchReg(), R2.scratchReg()); - pushArg(R0.scratchReg()); + Label slowPath, skipCall; + masm.computeImplicitThis(env, R0, &slowPath); + masm.jump(&skipCall); - using Fn = bool (*)(JSContext*, HandleObject, Handle, - MutableHandleValue); - if (!callVM()) { - return false; + masm.bind(&slowPath); + { + prepareVMCall(); + + pushArg(env); + + using Fn = void (*)(JSContext*, HandleObject, MutableHandleValue); + if (!callVM()) { + return false; + } } + masm.bind(&skipCall); frame.push(R0); return true; } @@ -4601,12 +4976,12 @@ bool BaselineCodeGen::emit_Finally() { return emitInterruptCheck(); } -static void LoadBaselineScriptResumeEntries(MacroAssembler& masm, - JSScript* script, Register dest, - Register scratch) { +template +void BaselineCodeGen::loadBaselineScriptResumeEntries( + Register dest, Register scratch) { MOZ_ASSERT(dest != scratch); - masm.movePtr(ImmPtr(script->jitScript()), dest); + loadJitScript(dest); masm.loadPtr(Address(dest, JitScript::offsetOfBaselineScript()), dest); masm.load32(Address(dest, BaselineScript::offsetOfResumeEntriesOffset()), scratch); @@ -4643,7 +5018,7 @@ template <> void BaselineCompilerCodeGen::jumpToResumeEntry(Register resumeIndex, Register scratch1, Register scratch2) { - LoadBaselineScriptResumeEntries(masm, handler.script(), scratch1, scratch2); + loadBaselineScriptResumeEntries(scratch1, scratch2); masm.loadPtr( BaseIndex(scratch1, resumeIndex, ScaleFromElemWidth(sizeof(uintptr_t))), scratch1); @@ -4687,7 +5062,7 @@ template Label isNotDebuggee, done; CodeOffset toggleOffset = masm.toggledJump(&isNotDebuggee); - if (!handler.addDebugInstrumentationOffset(cx, toggleOffset)) { + if (!handler.addDebugInstrumentationOffset(toggleOffset)) { return false; } @@ -4877,14 +5252,65 @@ bool BaselineCodeGen::emit_LeaveWith() { #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT template bool BaselineCodeGen::emit_AddDisposable() { - // TODO: AddDisposable to be implemented for Baseline (Bug 1899500) - MOZ_CRASH("AddDisposable has not been implemented for baseline"); + frame.syncStack(0); + prepareVMCall(); + + pushUint8BytecodeOperandArg(R0.scratchReg()); // hint + + masm.unboxBoolean(frame.addressOfStackValue(-1), R0.scratchReg()); + pushArg(R0.scratchReg()); // needsClosure + + masm.loadValue(frame.addressOfStackValue(-2), R1); + pushArg(R1); // method + + masm.loadValue(frame.addressOfStackValue(-3), R2); + pushArg(R2); // object + + masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg()); + pushArg(R0.scratchReg()); + + using Fn = bool (*)(JSContext*, JS::Handle, JS::Handle, + JS::Handle, bool, UsingHint); + if (!callVM()) { + return false; + } + frame.popn(3); + return true; } template -bool BaselineCodeGen::emit_DisposeDisposables() { - // TODO: DisposeDisposables to be implemented for Baseline (Bug 1899500) - MOZ_CRASH("DisposeDisposables has not been implemented for baseline"); +bool BaselineCodeGen::emit_TakeDisposeCapability() { + frame.syncStack(0); + + masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg()); + Address capAddr(R0.scratchReg(), + DisposableEnvironmentObject::offsetOfDisposeCapability()); + masm.guardedCallPreBarrierAnyZone(capAddr, MIRType::Value, R2.scratchReg()); + masm.loadValue(capAddr, R1); + masm.storeValue(UndefinedValue(), capAddr); + + frame.push(R1); + return true; +} + +template +bool BaselineCodeGen::emit_CreateSuppressedError() { + frame.popRegsAndSync(2); + prepareVMCall(); + + pushArg(R1); // suppressed + pushArg(R0); // error + + using Fn = ErrorObject* (*)(JSContext*, JS::Handle, + JS::Handle); + + if (!callVM()) { + return false; + } + + masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + frame.push(R0); + return true; } #endif @@ -5303,7 +5729,7 @@ void BaselineCompilerCodeGen::emitTableSwitchJump(Register key, // |firstResumeIndex * sizeof(uintptr_t)| fits in int32_t. uint32_t firstResumeIndex = GET_RESUMEINDEX(handler.pc() + TableSwitchOpFirstResumeIndexOffset); - LoadBaselineScriptResumeEntries(masm, handler.script(), scratch1, scratch2); + loadBaselineScriptResumeEntries(scratch1, scratch2); masm.loadPtr(BaseIndex(scratch1, key, ScaleFromElemWidth(sizeof(uintptr_t)), firstResumeIndex * sizeof(uintptr_t)), scratch1); @@ -5331,7 +5757,7 @@ bool BaselineCodeGen::emit_TableSwitch() { // Call a stub to convert R0 from double to int32 if needed. // Note: this stub may clobber scratch1. - masm.call(cx->runtime()->jitRuntime()->getDoubleToInt32ValueStub()); + masm.call(runtime->jitRuntime()->getDoubleToInt32ValueStub()); // Load the index in the jump table in |key|, or branch to default pc if not // int32 or out-of-range. @@ -5792,10 +6218,10 @@ bool BaselineInterpreterCodeGen::emitAfterYieldDebugInstrumentation( // If the current Realm is not a debuggee we're done. Label done; CodeOffset toggleOffset = masm.toggledJump(&done); - if (!handler.addDebugInstrumentationOffset(cx, toggleOffset)) { + if (!handler.addDebugInstrumentationOffset(toggleOffset)) { return false; } - masm.loadPtr(AbsoluteAddress(cx->addressOfRealm()), scratch); + masm.loadPtr(AbsoluteAddress(runtime->addressOfRealm()), scratch); masm.branchTest32(Assembler::Zero, Address(scratch, Realm::offsetOfDebugModeBits()), Imm32(Realm::debugModeIsDebuggeeBit()), &done); @@ -5854,7 +6280,7 @@ bool BaselineCodeGen::emit_FinalYieldRval() { template <> void BaselineCompilerCodeGen::emitJumpToInterpretOpLabel() { TrampolinePtr code = - cx->runtime()->jitRuntime()->baselineInterpreter().interpretOpAddr(); + runtime->jitRuntime()->baselineInterpreter().interpretOpAddr(); masm.jump(code); } @@ -5869,7 +6295,7 @@ bool BaselineCodeGen::emitEnterGeneratorCode(Register script, Register scratch) { // Resume in either the BaselineScript (if present) or Baseline Interpreter. - static_assert(BaselineDisabledScript == 0x1, + static_assert(CompilingScript == 0x5, "Comparison below requires specific sentinel encoding"); // Initialize the icScript slot in the baseline frame. @@ -5880,10 +6306,14 @@ bool BaselineCodeGen::emitEnterGeneratorCode(Register script, masm.storePtr(scratch, icScriptAddr); Label noBaselineScript; + // Frames with shared bytecode need the interpreterScript pointer + if (handler.realmIndependentJitcode()) { + masm.storePtr(script, frame.addressOfInterpreterScript()); + } masm.loadJitScript(script, scratch); masm.loadPtr(Address(scratch, JitScript::offsetOfBaselineScript()), scratch); masm.branchPtr(Assembler::BelowOrEqual, scratch, - ImmPtr(BaselineDisabledScriptPtr), &noBaselineScript); + ImmPtr(BaselineCompilingScriptPtr), &noBaselineScript); masm.load32(Address(scratch, BaselineScript::offsetOfResumeEntriesOffset()), script); @@ -6015,7 +6445,7 @@ bool BaselineCodeGen::emit_Resume() { #endif // Record the return address so the return offset -> pc mapping works. - if (!handler.recordCallRetAddr(cx, RetAddrEntry::Kind::IC, + if (!handler.recordCallRetAddr(RetAddrEntry::Kind::IC, masm.currentOffset())) { return false; } @@ -6036,7 +6466,7 @@ bool BaselineCodeGen::emit_Resume() { Register scratchReg = scratch2; Label skip; AbsoluteAddress addressOfEnabled( - cx->runtime()->geckoProfiler().addressOfEnabled()); + runtime->geckoProfiler().addressOfEnabled()); masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skip); masm.loadJSContext(scratchReg); masm.loadPtr(Address(scratchReg, JSContext::offsetOfProfilingActivation()), @@ -6143,8 +6573,8 @@ bool BaselineCodeGen::emit_Resume() { // After the generator returns, we restore the stack pointer, switch back to // the current realm, push the return value, and we're done. - if (JSScript* script = handler.maybeScript()) { - masm.switchToRealm(script->realm(), R2.scratchReg()); + if (!handler.realmIndependentJitcode()) { + masm.switchToRealm(handler.maybeScript()->realm(), R2.scratchReg()); } else { masm.switchToBaselineFrameRealm(R2.scratchReg()); } @@ -6236,7 +6666,9 @@ bool BaselineCodeGen::emit_IsConstructing() { template <> bool BaselineCompilerCodeGen::emit_JumpTarget() { - MaybeIncrementCodeCoverageCounter(masm, handler.script(), handler.pc()); + if (!handler.compilingOffThread()) { + MaybeIncrementCodeCoverageCounter(masm, handler.script(), handler.pc()); + } return true; } @@ -6306,30 +6738,15 @@ bool BaselineCodeGen::emit_InitHomeObject() { return true; } -template <> -bool BaselineCompilerCodeGen::emit_BuiltinObject() { - // Built-in objects are constants for a given global. - auto kind = BuiltinObjectKind(GET_UINT8(handler.pc())); - JSObject* builtin = BuiltinObjectOperation(cx, kind); - if (!builtin) { - return false; - } - frame.push(ObjectValue(*builtin)); - return true; -} +template +bool BaselineCodeGen::emit_BuiltinObject() { + frame.syncStack(0); -template <> -bool BaselineInterpreterCodeGen::emit_BuiltinObject() { - prepareVMCall(); - - pushUint8BytecodeOperandArg(R0.scratchReg()); - - using Fn = JSObject* (*)(JSContext*, BuiltinObjectKind); - if (!callVM()) { + if (!emitNextIC()) { return false; } - masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + // Mark R0 as pushed stack value. frame.push(R0); return true; } @@ -6379,40 +6796,15 @@ bool BaselineCodeGen::emit_FunWithProto() { return true; } -template <> -bool BaselineCompilerCodeGen::emit_ImportMeta() { - // Note: this is like the interpreter implementation, but optimized a bit by - // calling GetModuleObjectForScript at compile-time. - - Rooted module(cx, GetModuleObjectForScript(handler.script())); - +template +bool BaselineCodeGen::emit_ImportMeta() { frame.syncStack(0); - prepareVMCall(); - pushArg(ImmGCPtr(module)); - - using Fn = JSObject* (*)(JSContext*, HandleObject); - if (!callVM()) { + if (!emitNextIC()) { return false; } - masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); - frame.push(R0); - return true; -} - -template <> -bool BaselineInterpreterCodeGen::emit_ImportMeta() { - prepareVMCall(); - - pushScriptArg(); - - using Fn = JSObject* (*)(JSContext*, HandleScript); - if (!callVM()) { - return false; - } - - masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + // Mark R0 as pushed stack value. frame.push(R0); return true; } @@ -6496,8 +6888,9 @@ bool BaselineCodeGen::emitPrologue() { frame.assertSyncedStack(); - if (JSScript* script = handler.maybeScript()) { - masm.debugAssertContextRealm(script->realm(), R1.scratchReg()); + if (!handler.realmIndependentJitcode()) { + masm.debugAssertContextRealm(handler.maybeScript()->realm(), + R1.scratchReg()); } if (!emitDebugPrologue()) { @@ -6538,7 +6931,7 @@ bool BaselineCodeGen::emitEpilogue() { return true; } -MethodStatus BaselineCompiler::emitBody() { +bool BaselineCompiler::emitBody() { AutoCreatedBy acb(masm, "BaselineCompiler::emitBody"); JSScript* script = handler.script(); @@ -6590,22 +6983,21 @@ MethodStatus BaselineCompiler::emitBody() { uint32_t pcOffset = script->pcToOffset(handler.pc()); uint32_t nativeOffset = masm.currentOffset(); if (!resumeOffsetEntries_.emplaceBack(pcOffset, nativeOffset)) { - ReportOutOfMemory(cx); - return Method_Error; + return false; } } // Emit traps for breakpoints and step mode. if (MOZ_UNLIKELY(compileDebugInstrumentation()) && !emitDebugTrap()) { - return Method_Error; + return false; } - perfSpewer_.recordInstruction(cx, masm, handler.pc(), frame); + perfSpewer_.recordInstruction(masm, handler.pc(), frame); -#define EMIT_OP(OP, ...) \ - case JSOp::OP: { \ - AutoCreatedBy acb(masm, "op=" #OP); \ - if (MOZ_UNLIKELY(!this->emit_##OP())) return Method_Error; \ +#define EMIT_OP(OP, ...) \ + case JSOp::OP: { \ + AutoCreatedBy acb(masm, "op=" #OP); \ + if (MOZ_UNLIKELY(!this->emit_##OP())) return false; \ } break; switch (op) { @@ -6630,13 +7022,12 @@ MethodStatus BaselineCompiler::emitBody() { } MOZ_ASSERT(JSOp(*prevpc) == JSOp::RetRval || JSOp(*prevpc) == JSOp::Return); - return Method_Compiled; + return true; } bool BaselineInterpreterGenerator::emitDebugTrap() { CodeOffset offset = masm.nopPatchableToCall(); if (!debugTrapOffsets_.append(offset.offset())) { - ReportOutOfMemory(cx); return false; } @@ -6762,13 +7153,8 @@ bool BaselineInterpreterGenerator::emitInterpreterLoop() { // Emit debug trap handler code (target of patchable call instructions). This // is just a tail call to the debug trap handler trampoline code. { - JitRuntime* jrt = cx->runtime()->jitRuntime(); - JitCode* handlerCode = - jrt->debugTrapHandler(cx, DebugTrapHandlerKind::Interpreter); - if (!handlerCode) { - return false; - } - + JitCode* handlerCode = runtime->jitRuntime()->debugTrapHandler( + DebugTrapHandlerKind::Interpreter); debugTrapHandlerOffset_ = masm.currentOffset(); masm.jump(handlerCode); } @@ -6835,28 +7221,35 @@ void BaselineInterpreterGenerator::emitOutOfLineCodeCoverageInstrumentation() { masm.ret(); } -bool BaselineInterpreterGenerator::generate(BaselineInterpreter& interpreter) { +bool BaselineInterpreterGenerator::generate(JSContext* cx, + BaselineInterpreter& interpreter) { AutoCreatedBy acb(masm, "BaselineInterpreterGenerator::generate"); + if (!cx->runtime()->jitRuntime()->ensureDebugTrapHandler( + cx, DebugTrapHandlerKind::Interpreter)) { + return false; + } + perfSpewer_.recordOffset(masm, "Prologue"); if (!emitPrologue()) { + ReportOutOfMemory(cx); return false; } perfSpewer_.recordOffset(masm, "InterpreterLoop"); if (!emitInterpreterLoop()) { + ReportOutOfMemory(cx); return false; } perfSpewer_.recordOffset(masm, "Epilogue"); if (!emitEpilogue()) { + ReportOutOfMemory(cx); return false; } perfSpewer_.recordOffset(masm, "OOLPostBarrierSlot"); - if (!emitOutOfLinePostBarrierSlot()) { - return false; - } + emitOutOfLinePostBarrierSlot(); perfSpewer_.recordOffset(masm, "OOLCodeCoverageInstrumentation"); emitOutOfLineCodeCoverageInstrumentation(); diff --git a/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.h b/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.h index 16df7d39577..4376c7a9776 100644 --- a/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.h +++ b/src/third_party/mozjs/extract/js/src/jit/BaselineCodeGen.h @@ -9,6 +9,7 @@ #include "jit/BaselineFrameInfo.h" #include "jit/BytecodeAnalysis.h" +#include "jit/CompileWrappers.h" #include "jit/FixedList.h" #include "jit/MacroAssembler.h" #include "jit/PerfSpewer.h" @@ -17,6 +18,8 @@ namespace js { namespace jit { +class BaselineSnapshot; + enum class ScriptGCThingType { Atom, String, @@ -36,8 +39,8 @@ class BaselineCodeGen { protected: Handler handler; - JSContext* cx; - StackMacroAssembler masm; + CompileRuntime* runtime; + MacroAssembler& masm; typename Handler::FrameInfoT& frame; @@ -66,8 +69,8 @@ class BaselineCodeGen { #endif template - explicit BaselineCodeGen(JSContext* cx, TempAllocator& alloc, - HandlerArgs&&... args); + explicit BaselineCodeGen(TempAllocator& alloc, MacroAssembler& masmArg, + CompileRuntime* runtimeArg, HandlerArgs&&... args); template void pushArg(const T& t) { @@ -84,6 +87,8 @@ class BaselineCodeGen { // stored in the script) as argument for a VM function. void loadScriptGCThing(ScriptGCThingType type, Register dest, Register scratch); + void loadScriptGCThingInternal(ScriptGCThingType type, Register dest, + Register scratch); void pushScriptGCThingArg(ScriptGCThingType type, Register scratch1, Register scratch2); void pushScriptNameArg(Register scratch1, Register scratch2); @@ -97,6 +102,8 @@ class BaselineCodeGen { // Loads the current JSScript* in dest. void loadScript(Register dest); + // Loads the current JitScript* in dest + void loadJitScript(Register dest); void saveInterpreterPCReg(); void restoreInterpreterPCReg(); @@ -104,6 +111,9 @@ class BaselineCodeGen { // Subtracts |script->nslots() * sizeof(Value)| from reg. void subtractScriptSlotsSize(Register reg, Register scratch); + // Loads the resume entries of the current BaselineScript* in dest + void loadBaselineScriptResumeEntries(Register dest, Register scratch); + // Jump to the script's resume entry indicated by resumeIndex. void jumpToResumeEntry(Register resumeIndex, Register scratch1, Register scratch2); @@ -198,6 +208,8 @@ class BaselineCodeGen { // Handles JSOp::Lt, JSOp::Gt, and friends [[nodiscard]] bool emitCompare(); + [[nodiscard]] bool emitConstantStrictEq(JSOp op); + // Handles JSOp::NewObject and JSOp::NewInit. [[nodiscard]] bool emitNewObject(); @@ -231,9 +243,9 @@ class BaselineCodeGen { [[nodiscard]] bool emitSetElemSuper(bool strict); [[nodiscard]] bool emitSetPropSuper(bool strict); - // Try to bake in the result of BindGName instead of using an IC. + // Try to bake in the result of BindUnqualifiedGName instead of using an IC. // Return true if we managed to optimize the op. - bool tryOptimizeBindGlobalName(); + bool tryOptimizeBindUnqualifiedGlobalName(); [[nodiscard]] bool emitInitPropGetterSetter(); [[nodiscard]] bool emitInitElemGetterSetter(); @@ -251,7 +263,6 @@ class BaselineCodeGen { [[nodiscard]] bool emitPrologue(); [[nodiscard]] bool emitEpilogue(); - [[nodiscard]] bool emitOutOfLinePostBarrierSlot(); [[nodiscard]] bool emitStackCheck(); [[nodiscard]] bool emitDebugPrologue(); [[nodiscard]] bool emitDebugEpilogue(); @@ -266,9 +277,12 @@ class BaselineCodeGen { void emitProfilerEnterFrame(); void emitProfilerExitFrame(); + + void emitOutOfLinePostBarrierSlot(); }; using RetAddrEntryVector = js::Vector; +using AllocSiteIndexVector = js::Vector; // Interface used by BaselineCodeGen for BaselineCompiler. class BaselineCompilerHandler { @@ -280,6 +294,7 @@ class BaselineCompilerHandler { #endif FixedList
* seenTables, size_t* code, size_t* data) const; @@ -519,11 +570,11 @@ class alignas(16) Instance { uint64_t byteLen, uint8_t* memBase); static int32_t memDiscardShared_m64(Instance* instance, uint64_t byteOffset, uint64_t byteLen, uint8_t* memBase); - static void* tableGet(Instance* instance, uint32_t index, + static void* tableGet(Instance* instance, uint32_t address, uint32_t tableIndex); static uint32_t tableGrow(Instance* instance, void* initValue, uint32_t delta, uint32_t tableIndex); - static int32_t tableSet(Instance* instance, uint32_t index, void* value, + static int32_t tableSet(Instance* instance, uint32_t address, void* value, uint32_t tableIndex); static uint32_t tableSize(Instance* instance, uint32_t tableIndex); static int32_t tableInit(Instance* instance, uint32_t dstOffset, @@ -547,38 +598,33 @@ class alignas(16) Instance { static int32_t wake_m64(Instance* instance, uint64_t byteOffset, int32_t count, uint32_t memoryIndex); static void* refFunc(Instance* instance, uint32_t funcIndex); - static void postBarrier(Instance* instance, void** location); - static void postBarrierPrecise(Instance* instance, void** location, - void* prev); - static void postBarrierPreciseWithOffset(Instance* instance, void** base, - uint32_t offset, void* prev); + static void postBarrierEdge(Instance* instance, AnyRef* location); + static void postBarrierEdgePrecise(Instance* instance, AnyRef* location, + void* prev); + static void postBarrierWholeCell(Instance* instance, gc::Cell* object); static void* exceptionNew(Instance* instance, void* exceptionArg); static int32_t throwException(Instance* instance, void* exceptionArg); template - static void* structNewIL(Instance* instance, - TypeDefInstanceData* typeDefData); + static void* structNewIL(Instance* instance, uint32_t typeDefIndex, + gc::AllocSite* allocSite); template - static void* structNewOOL(Instance* instance, - TypeDefInstanceData* typeDefData); + static void* structNewOOL(Instance* instance, uint32_t typeDefIndex, + gc::AllocSite* allocSite); template static void* arrayNew(Instance* instance, uint32_t numElements, - TypeDefInstanceData* typeDefData); + uint32_t typeDefIndex, gc::AllocSite* allocSite); static void* arrayNewData(Instance* instance, uint32_t segByteOffset, - uint32_t numElements, - TypeDefInstanceData* typeDefData, - uint32_t segIndex); + uint32_t numElements, uint32_t typeDefIndex, + gc::AllocSite* allocSite, uint32_t segIndex); static void* arrayNewElem(Instance* instance, uint32_t srcOffset, - uint32_t numElements, - TypeDefInstanceData* typeDefData, - uint32_t segIndex); + uint32_t numElements, uint32_t typeDefIndex, + gc::AllocSite* allocSite, uint32_t segIndex); static int32_t arrayInitData(Instance* instance, void* array, uint32_t index, uint32_t segByteOffset, uint32_t numElements, - TypeDefInstanceData* typeDefData, uint32_t segIndex); static int32_t arrayInitElem(Instance* instance, void* array, uint32_t index, uint32_t segOffset, uint32_t numElements, - TypeDefInstanceData* typeDefData, - uint32_t segIndex); + uint32_t typeDefIndex, uint32_t segIndex); static int32_t arrayCopy(Instance* instance, void* dstArray, uint32_t dstIndex, void* srcArray, uint32_t srcIndex, uint32_t numElements, uint32_t elementSize); @@ -589,11 +635,11 @@ class alignas(16) Instance { static int32_t intrI8VecMul(Instance* instance, uint32_t dest, uint32_t src1, uint32_t src2, uint32_t len, uint8_t* memBase); +#ifdef ENABLE_WASM_JS_STRING_BUILTINS static int32_t stringTest(Instance* instance, void* stringArg); static void* stringCast(Instance* instance, void* stringArg); static void* stringFromCharCodeArray(Instance* instance, void* arrayArg, - uint32_t arrayStart, - uint32_t arrayCount); + uint32_t arrayStart, uint32_t arrayEnd); static int32_t stringIntoCharCodeArray(Instance* instance, void* stringArg, void* arrayArg, uint32_t arrayStart); static void* stringFromCharCode(Instance* instance, uint32_t charCode); @@ -606,21 +652,27 @@ class alignas(16) Instance { static void* stringConcat(Instance* instance, void* firstStringArg, void* secondStringArg); static void* stringSubstring(Instance* instance, void* stringArg, - int32_t startIndex, int32_t endIndex); + uint32_t startIndex, uint32_t endIndex); static int32_t stringEquals(Instance* instance, void* firstStringArg, void* secondStringArg); static int32_t stringCompare(Instance* instance, void* firstStringArg, void* secondStringArg); +#endif // ENABLE_WASM_JS_STRING_BUILTINS }; bool ResultsToJSValue(JSContext* cx, ResultType type, void* registerResultLoc, - Maybe stackResultsLoc, MutableHandleValue rval, + mozilla::Maybe stackResultsLoc, + MutableHandleValue rval, CoercionLevel level = CoercionLevel::Spec); // Report an error to `cx` and mark it as a 'trap' so that it cannot be caught // by wasm exception handlers. void ReportTrapError(JSContext* cx, unsigned errorNumber); +// Mark an already reported error as a 'trap' so that it cannot be caught by +// wasm exception handlers. +void MarkPendingExceptionAsTrap(JSContext* cx); + // Instance is not a GC thing itself but contains GC thing pointers. Ensure they // are traced appropriately. void TraceInstanceEdge(JSTracer* trc, Instance* instance, const char* name); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmInstanceData.h b/src/third_party/mozjs/extract/js/src/wasm/WasmInstanceData.h index 98aa097deee..2709fe4076f 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmInstanceData.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmInstanceData.h @@ -25,6 +25,7 @@ #include "gc/Pretenuring.h" #include "js/Utility.h" +#include "vm/JSFunction.h" #include "wasm/WasmInstance.h" #include "wasm/WasmMemory.h" #include "wasm/WasmTypeDecls.h" @@ -68,8 +69,6 @@ struct TypeDefInstanceData { // arrays. GCPtr shape; const JSClass* clasp; - // The allocation site for GC types. This is used for pre-tenuring. - alignas(8) gc::AllocSite allocSite; // Only valid for structs. gc::AllocKind allocKind; @@ -96,14 +95,27 @@ struct TypeDefInstanceData { static constexpr size_t offsetOfSuperTypeVector() { return offsetof(TypeDefInstanceData, superTypeVector); } - static constexpr size_t offsetOfAllocSite() { - return offsetof(TypeDefInstanceData, allocSite); - } static constexpr size_t offsetOfArrayElemSize() { return offsetof(TypeDefInstanceData, arrayElemSize); } }; +// FuncDefInstanceData maintains the per-instance hotness state for a locally +// defined wasm function. This is a signed-int32 value that counts downwards +// from an initially non-negative value. At the point where the value +// transitions below zero (not *to* zero), we deem the owning function to +// have become hot. Transitions from one negative value to any other (even +// more) negative value are meaningless and should not happen. +struct FuncDefInstanceData { + int32_t hotnessCounter; +}; + +// FuncExportInstanceData maintains the exported function JS wrapper for an +// exported function. +struct FuncExportInstanceData { + GCPtr func; +}; + // FuncImportInstanceData describes the region of wasm global memory allocated // in the instance's thread-local storage for a function import. This is // accessed directly from JIT code and mutated by Instance as exits become @@ -128,7 +140,7 @@ struct FuncImportInstanceData { }; struct MemoryInstanceData { - // Pointer the memory object. + // Pointer to the memory object. GCPtr memory; // Pointer to the base of the memory. @@ -181,6 +193,150 @@ struct FunctionTableElem { Instance* instance; }; +// A collection of metrics for a `call_ref` instruction. This is tracked by +// baseline when we are using lazy tiering to perform speculative inlining. +// +// See MacroAssembler::updateCallRefMetrics for how this is written into. +// +// Because it contains thread-local data and is written into without +// synchronization, we cannot access this directly from our function compilers +// and so we use CallRefHints for that (see WasmModuleTypes.h). +struct CallRefMetrics { + // We track up to NUM_SLOTS targets with associated count, plus a count for + // "all other" targets, including cross-instance calls. This facilitates + // knowing the total number of calls made by the instruction, which is + // required in order to know whether the hottest tracked function is more + // than some percentage (eg, 50%) of all calls. + // + // In order to keep search costs low (in the baseline code), we rely on the + // fact that most call sites have distributions which are heavily skewed + // towards one target. This struct is updated by the code generated in + // GenerateUpdateCallRefMetricsStub. That tries to make + // `targets[0]`/`counts[0]` be the hottest target, so that for most calls, + // the monitoring code will only check `targets[0]` for a match. + // + // For NUM_SLOTS <= 2, GenerateUpdateCallRefMetricsStub's incremental-sort + // heuristic maintains the `counts` array in strictly non-decreasing order. + // For NUM_SLOTS > 2, in the worst case we will have counts[N+1] at most + // (NUM_SLOTS - 2) larger than counts[N]. In practice the incremental + // sorting heuristic is very effective and so counts are in decreasing order, + // as we desire. + // + // Once NUM_SLOTS targets are being tracked, all new targets will be lumped + // together in the `countOther` bucket. This can lead to the unfortunate + // case of having NUM_SLOTS different cold targets show up first, after which + // follows a different target that is hot, but cannot be inlined because it + // goes in the `countOther` bucket, so its identity is unknown. This is + // unlikely but could happen. The only known fix is to increase NUM_SLOTS. + // + // The `targets` values may be nullptr only to indicate that the slot is not + // in use. No legitimate target can be nullptr. Given that the state is + // updated by generated code and that code isn't entirely simple, we place + // emphasis on checking invariants carefully. + // + // Stores of funcrefs in `targets[]`: These CallRefMetrics structs logically + // belong to the Instance data, and do not require any GC barriers for two + // reasons: + // + // 1. The pre-write barrier protects against an unmarked object being stored + // into a marked object during an incremental GC. However this funcref is + // from the Instance we're storing it into (see above) and so if the + // instance has already been traced, this function will already have been + // traced (all exported functions are kept alive by an instance cache). + // + // 2. The post-write barrier tracks edges from tenured objects to nursery + // objects. However wasm exported functions are not nursery allocated and + // so no new edge can be created. + // + // Overflows in `counts[]` and `countOther`: increments of these values are + // not checked for overflow and so could wrap around from 2^32-1 to zero. + // We ignore but tolerate this, because: + // + // 1. This is extremely unlikely to happen in practice, since the function + // containing the call site is almost certain to get tiered up long before + // any of these counters gets anywhere near the limit. + // + // 2. Performing saturating increments is possible, but has a minimum extra + // cost of two instructions, and given (1.) it is pointless. + // + // This does however require that interpretation of the `counts[]` and + // `countOther` values needs to be aware that zeroes could mean 2^32 or any + // multiple of it. Hence a zero in `counts[]` does not necessarily mean that + // the corresponding `target[]` was never called, nor is it the case that a + // `countsOther` of zero means no "other" targets were observed. + + static constexpr size_t NUM_SLOTS = 3; + static_assert(NUM_SLOTS >= 1); // 1 slot + others is the minimal config + + // An array of pairs of (target, count) .. + GCPtr targets[NUM_SLOTS]; + uint32_t counts[NUM_SLOTS]; + // .. and a count for all other targets. + uint32_t countOther; + + // Generated code assumes this + static_assert(sizeof(GCPtr) == sizeof(void*)); + static_assert(sizeof(uint32_t) == 4); + + CallRefMetrics() { + for (size_t i = 0; i < NUM_SLOTS; i++) { + targets[i] = nullptr; + counts[i] = 0; + } + countOther = 0; + MOZ_ASSERT(checkInvariants()); + } + + [[nodiscard]] bool checkInvariants() const { + // If targets[N] is null, then this slot is not in use and so counts[N] + // must be zero. Per comments above about overflow, the implication in the + // other direction does not hold. + size_t i; + for (i = 0; i < NUM_SLOTS; i++) { + if (targets[i] == nullptr && counts[i] != 0) { + return false; + } + } + // The targets/counts slots must be filled in in sequence. + for (i = 0; i < NUM_SLOTS; i++) { + if (targets[i] == nullptr) { + break; + } + } + size_t numUsed = i; + for (/*keepgoing*/; i < NUM_SLOTS; i++) { + if (targets[i] != nullptr) { + return false; + } + } + // For the slots in use, the target values must be different + for (i = 0; i < numUsed; i++) { + for (size_t j = i + 1; j < numUsed; j++) { + if (targets[j] == targets[i]) { + return false; + } + } + } + // Note we don't say anything about `countOther`. This gets incremented in + // the cases when we (1) see a new target when all slots are already in + // use, or (2) have a cross-instance call. The effect of (2) is that + // `countOther` can be non-zero regardless of how many slots are in use. + return true; + } + + static size_t offsetOfTarget(size_t n) { + MOZ_ASSERT(n < NUM_SLOTS); + return offsetof(CallRefMetrics, targets) + n * sizeof(GCPtr); + } + static size_t offsetOfCount(size_t n) { + MOZ_ASSERT(n < NUM_SLOTS); + return offsetof(CallRefMetrics, counts) + n * sizeof(uint32_t); + } + static size_t offsetOfCountOther() { + return offsetof(CallRefMetrics, countOther); + } +}; + } // namespace wasm } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.cpp index 4474835d71c..0cdd4256cdf 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.cpp @@ -28,9 +28,12 @@ #include "jit/CompileInfo.h" #include "jit/Ion.h" #include "jit/IonOptimizationLevels.h" +#include "jit/MIR-wasm.h" #include "jit/MIR.h" #include "jit/ShuffleAnalysis.h" +#include "js/GCAPI.h" // JS::AutoSuppressGCAnalysis #include "js/ScalarType.h" // js::Scalar::Type +#include "util/DifferentialTesting.h" #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmBuiltinModule.h" #include "wasm/WasmBuiltins.h" @@ -48,50 +51,18 @@ using namespace js::jit; using namespace js::wasm; using mozilla::IsPowerOfTwo; -using mozilla::Maybe; using mozilla::Nothing; -using mozilla::Some; namespace { +using UniqueCompileInfo = UniquePtr; +using UniqueCompileInfoVector = Vector; + using BlockVector = Vector; using DefVector = Vector; - -// To compile try-catch blocks, we extend the IonCompilePolicy's ControlItem -// from being just an MBasicBlock* to a Control structure collecting additional -// information. using ControlInstructionVector = Vector; -struct TryControl { - // Branches to bind to the try's landing pad. - ControlInstructionVector landingPadPatches; - // For `try_table`, the list of tagged catches and labels to branch to. - TryTableCatchVector catches; - // Whether this try is in the body and should catch any thrown exception. - bool inBody; - - TryControl() : inBody(false) {} - - // Reset the try control for when it is cached in FunctionCompiler. - void reset() { - landingPadPatches.clearAndFree(); - catches.clearAndFree(); - inBody = false; - } -}; -using UniqueTryControl = UniquePtr; -using VectorUniqueTryControl = Vector; - -struct Control { - MBasicBlock* block; - UniqueTryControl tryControl; - - Control() : block(nullptr), tryControl(nullptr) {} - Control(Control&&) = default; - Control(const Control&) = delete; -}; - // [SMDOC] WebAssembly Exception Handling in Ion // ======================================================= // @@ -184,6 +155,106 @@ struct Control { // block will either be a rethrow, if there is no catch_all, or else a // jump to a catch_all block. +struct TryControl { + // Branches to bind to the try's landing pad. + ControlInstructionVector landingPadPatches; + // For `try_table`, the list of tagged catches and labels to branch to. + TryTableCatchVector catches; + // The pending exception for the try's landing pad. + MDefinition* pendingException; + // The pending exception's tag for the try's landing pad. + MDefinition* pendingExceptionTag; + // Whether this try is in the body and should catch any thrown exception. + bool inBody; + + TryControl() + : pendingException(nullptr), + pendingExceptionTag(nullptr), + inBody(false) {} + + // Reset the try control for when it is cached in FunctionCompiler. + void reset() { + landingPadPatches.clearAndFree(); + catches.clearAndFree(); + inBody = false; + } +}; +using UniqueTryControl = UniquePtr; +using VectorUniqueTryControl = Vector; + +struct ControlFlowPatch { + MControlInstruction* ins; + uint32_t index; + ControlFlowPatch(MControlInstruction* ins, uint32_t index) + : ins(ins), index(index) {} +}; + +using ControlFlowPatchVector = Vector; + +struct PendingBlockTarget { + ControlFlowPatchVector patches; + BranchHint hint = BranchHint::Invalid; +}; + +using PendingBlockTargetVector = + Vector; + +// Inlined functions accumulate all returns to be bound to a caller function +// after compilation is finished. +struct PendingInlineReturn { + PendingInlineReturn(MGoto* jump, DefVector&& results) + : jump(jump), results(std::move(results)) {} + + MGoto* jump; + DefVector results; +}; + +using PendingInlineReturnVector = + Vector; + +// CallCompileState describes a call that is being compiled. +struct CallCompileState { + // A generator object that is passed each argument as it is compiled. + WasmABIArgGenerator abi; + + // Accumulates the register arguments while compiling arguments. + MWasmCallBase::Args regArgs; + + // Reserved argument for passing Instance* to builtin instance method calls. + ABIArg instanceArg; + + // The stack area in which the callee will write stack return values, or + // nullptr if no stack results. + MWasmStackResultArea* stackResultArea = nullptr; + + // Indicates that the call is a return/tail call. + bool returnCall = false; + + // The landing pad patches for the nearest enclosing try-catch. This is + // non-null iff the call is catchable. + ControlInstructionVector* tryLandingPadPatches = nullptr; + + // The index of the try note for a catchable call. + uint32_t tryNoteIndex = UINT32_MAX; + + // The block to take for fallthrough execution for a catchable call. + MBasicBlock* fallthroughBlock = nullptr; + + // The block to take for exceptional execution for a catchable call. + MBasicBlock* prePadBlock = nullptr; + + bool isCatchable() const { return tryLandingPadPatches != nullptr; } +}; + +struct Control { + MBasicBlock* block; + UniqueTryControl tryControl; + + Control() : block(nullptr), tryControl(nullptr) {} + Control(Control&&) = default; + Control(const Control&) = delete; +}; + struct IonCompilePolicy { // We store SSA definitions in the value stack. using Value = MDefinition*; @@ -198,126 +269,130 @@ struct IonCompilePolicy { using IonOpIter = OpIter; -class FunctionCompiler; - -// CallCompileState describes a call that is being compiled. - -class CallCompileState { - // A generator object that is passed each argument as it is compiled. - WasmABIArgGenerator abi_; - - // Accumulates the register arguments while compiling arguments. - MWasmCallBase::Args regArgs_; - - // Reserved argument for passing Instance* to builtin instance method calls. - ABIArg instanceArg_; - - // The stack area in which the callee will write stack return values, or - // nullptr if no stack results. - MWasmStackResultArea* stackResultArea_ = nullptr; - - // Indicates that the call is a return/tail call. - bool returnCall = false; - - // Only FunctionCompiler should be directly manipulating CallCompileState. - friend class FunctionCompiler; +// Statistics for inlining (at all depths) into the root function. +struct InliningStats { + size_t inlinedDirectBytecodeSize = 0; // sum of sizes of inlinees + size_t inlinedDirectFunctions = 0; // number of inlinees + size_t inlinedCallRefBytecodeSize = 0; // sum of sizes of inlinees + size_t inlinedCallRefFunctions = 0; // number of inlinees + bool largeFunctionBackoff = false; // did large function backoff happen? }; -// Encapsulates the compilation of a single function in an asm.js module. The -// function compiler handles the creation and final backend compilation of the -// MIR graph. -class FunctionCompiler { - struct ControlFlowPatch { - MControlInstruction* ins; - uint32_t index; - ControlFlowPatch(MControlInstruction* ins, uint32_t index) - : ins(ins), index(index) {} - }; +// Encapsulates the generation of MIR for a wasm function and any functions +// that become inlined into it. +class RootCompiler { + const CompilerEnvironment& compilerEnv_; + const CodeMetadata& codeMeta_; + const CodeTailMetadata* codeTailMeta_; - using ControlFlowPatchVector = Vector; - - struct PendingBlockTarget { - ControlFlowPatchVector patches; - BranchHint hint = BranchHint::Invalid; - }; - - using PendingBlockTargetVector = - Vector; - - const ModuleEnvironment& moduleEnv_; - IonOpIter iter_; - uint32_t functionBodyOffset_; - const FuncCompileInput& func_; const ValTypeVector& locals_; - size_t lastReadCallSite_; + const FuncCompileInput& func_; + Decoder& decoder_; + FeatureUsage observedFeatures_; + CompileInfo compileInfo_; + const JitCompileOptions options_; TempAllocator& alloc_; - MIRGraph& graph_; - const CompileInfo& info_; - MIRGenerator& mirGen_; - - MBasicBlock* curBlock_; - uint32_t maxStackArgBytes_; + MIRGraph mirGraph_; + MIRGenerator mirGen_; + // The current loop depth we're generating inside of. This includes all + // callee functions when we're generating an inlined function, and so it + // lives here on the root compiler. uint32_t loopDepth_; - uint32_t blockDepth_; - PendingBlockTargetVector pendingBlocks_; - // Control flow patches created by `delegate` instructions that target the - // outermost label of this function. These will be bound to a pad that will - // do a rethrow in `emitBodyDelegateThrowPad`. - ControlInstructionVector bodyDelegatePadPatches_; - // Instance pointer argument to the current function. - MWasmParameter* instancePointer_; - MWasmParameter* stackResultPointer_; + // The current stack of bytecode offsets of the caller functions of the + // function currently being inlined. + BytecodeOffsetVector inlinedCallerOffsets_; + InlinedCallerOffsetIndex inlinedCallerOffsetsIndex_; - // Reference to masm.tryNotes_ - wasm::TryNoteVector& tryNotes_; + // Compilation statistics for this function. + CompileStats funcStats_; - // Cache of TryControl to minimize heap allocations + // Accumulated inlining statistics for this function. + InliningStats inliningStats_; + // The remaining inlining budget, in terms of bytecode bytes. This may go + // negative and so is signed. + int64_t localInliningBudget_; + + // All jit::CompileInfo objects created during this compilation. This must + // be kept alive for as long as the MIR graph is alive. + UniqueCompileInfoVector compileInfos_; + + // Cache of TryControl to minimize heap allocations. VectorUniqueTryControl tryControlCache_; + // Reference to masm.tryNotes() + wasm::TryNoteVector& tryNotes_; + + // Reference to masm.inliningContext() + wasm::InliningContext& inliningContext_; + public: - FunctionCompiler(const ModuleEnvironment& moduleEnv, Decoder& decoder, - const FuncCompileInput& func, const ValTypeVector& locals, - MIRGenerator& mirGen, TryNoteVector& tryNotes) - : moduleEnv_(moduleEnv), - iter_(moduleEnv, decoder), - functionBodyOffset_(decoder.beginOffset()), - func_(func), + RootCompiler(const CompilerEnvironment& compilerEnv, + const CodeMetadata& codeMeta, + const CodeTailMetadata* codeTailMeta, TempAllocator& alloc, + const ValTypeVector& locals, const FuncCompileInput& func, + Decoder& decoder, wasm::TryNoteVector& tryNotes, + wasm::InliningContext& inliningContext) + : compilerEnv_(compilerEnv), + codeMeta_(codeMeta), + codeTailMeta_(codeTailMeta), locals_(locals), - lastReadCallSite_(0), - alloc_(mirGen.alloc()), - graph_(mirGen.graph()), - info_(mirGen.outerInfo()), - mirGen_(mirGen), - curBlock_(nullptr), - maxStackArgBytes_(0), + func_(func), + decoder_(decoder), + observedFeatures_(FeatureUsage::None), + compileInfo_(locals.length()), + alloc_(alloc), + mirGraph_(&alloc), + mirGen_(nullptr, options_, &alloc_, &mirGraph_, &compileInfo_, + IonOptimizations.get(OptimizationLevel::Wasm), &codeMeta), loopDepth_(0), - blockDepth_(0), - instancePointer_(nullptr), - stackResultPointer_(nullptr), - tryNotes_(tryNotes) {} + localInliningBudget_(0), + tryNotes_(tryNotes), + inliningContext_(inliningContext) {} - const ModuleEnvironment& moduleEnv() const { return moduleEnv_; } - - IonOpIter& iter() { return iter_; } - uint32_t relativeBytecodeOffset() { - return readBytecodeOffset() - functionBodyOffset_; - } - TempAllocator& alloc() const { return alloc_; } - // FIXME(1401675): Replace with BlockType. - uint32_t funcIndex() const { return func_.index; } - const FuncType& funcType() const { - return *moduleEnv_.funcs[func_.index].type; + const CompilerEnvironment& compilerEnv() const { return compilerEnv_; } + const CodeMetadata& codeMeta() const { return codeMeta_; } + const CodeTailMetadata* codeTailMeta() const { return codeTailMeta_; } + const FuncCompileInput& func() const { return func_; } + TempAllocator& alloc() { return alloc_; } + MIRGraph& mirGraph() { return mirGraph_; } + MIRGenerator& mirGen() { return mirGen_; } + int64_t inliningBudget() const { return localInliningBudget_; } + FeatureUsage observedFeatures() const { return observedFeatures_; } + const CompileStats& funcStats() const { return funcStats_; } + void noteLargeFunctionBackoffWasApplied() { + inliningStats_.largeFunctionBackoff = true; } - MBasicBlock* getCurBlock() const { return curBlock_; } - BytecodeOffset bytecodeOffset() const { return iter_.bytecodeOffset(); } - BytecodeOffset bytecodeIfNotAsmJS() const { - return moduleEnv_.isAsmJS() ? BytecodeOffset() : iter_.bytecodeOffset(); + uint32_t loopDepth() const { return loopDepth_; } + void startLoop() { loopDepth_++; } + void closeLoop() { loopDepth_--; } + + [[nodiscard]] bool generate(); + + InlinedCallerOffsetIndex inlinedCallerOffsetsIndex() const { + return inlinedCallerOffsetsIndex_; + } + + // Add a compile info for an inlined function. This keeps the inlined + // function's compile info alive for the outermost function's + // compilation. + [[nodiscard]] CompileInfo* startInlineCall( + uint32_t callerFuncIndex, BytecodeOffset callerOffset, + uint32_t calleeFuncIndex, uint32_t numLocals, size_t inlineeBytecodeSize, + InliningHeuristics::CallKind callKind); + void finishInlineCall(); + + // Add a try note and return the index. + [[nodiscard]] bool addTryNote(uint32_t* tryNoteIndex) { + if (!tryNotes_.append(wasm::TryNote())) { + return false; + } + *tryNoteIndex = tryNotes_.length() - 1; + return true; } - FeatureUsage featureUsage() const { return iter_.featureUsage(); } // Try to get a free TryControl from the cache, or allocate a new one. [[nodiscard]] UniqueTryControl newTryControl() { @@ -336,13 +411,155 @@ class FunctionCompiler { // Ignore any OOM, as we'll fail later (void)tryControlCache_.append(std::move(tryControl)); } +}; + +// Encapsulates the generation of MIR for a single function in a wasm module. +class FunctionCompiler { + // The root function compiler we are being compiled within. + RootCompiler& rootCompiler_; + + // The caller function compiler, if any, that we are being inlined into. + // Note that `inliningDepth_` is zero for the first inlinee, one for the + // second inlinee, etc. + const FunctionCompiler* callerCompiler_; + const uint32_t inliningDepth_; + + // Information about this function's bytecode and parsing state + IonOpIter iter_; + uint32_t functionBodyOffset_; + const FuncCompileInput& func_; + const ValTypeVector& locals_; + size_t lastReadCallSite_; + size_t numCallRefs_; + size_t numAllocSites_; + + // CompileInfo for compiling the MIR for this function. Allocated inside of + // RootCompiler::compileInfos, and kept alive for the duration of the + // total compilation. + const jit::CompileInfo& info_; + + MBasicBlock* curBlock_; + uint32_t maxStackArgBytes_; + + // When generating a forward branch we haven't created the basic block that + // the branch needs to target. We handle this by accumulating all the branch + // instructions that want to target a block we have not yet created into + // `pendingBlocks_` and then patching them in `bindBranches`. + // + // For performance reasons we only grow `pendingBlocks_` as needed, never + // shrink it. So the length of the vector has no relation to the current + // nesting depth of wasm blocks. We use `pendingBlockDepth_` to track the + // current wasm block depth. We assert that all entries beyond the current + // block depth are empty. + uint32_t pendingBlockDepth_; + PendingBlockTargetVector pendingBlocks_; + // Control flow patches for exceptions that are caught without a landing + // pad they can directly jump to. This happens when either: + // (1) `delegate` targets the function body label. + // (2) A `try` ends without any cases, and there is no enclosing `try`. + // (3) There is no `try` in this function, but a caller function (when + // inlining) has a `try`. + // + // These exceptions will be rethrown using `emitBodyRethrowPad`. + ControlInstructionVector bodyRethrowPadPatches_; + // A vector of the returns in this function for use when we're being inlined + // into another function. + PendingInlineReturnVector pendingInlineReturns_; + // A block that all uncaught exceptions in this function will jump to. The + // inline caller will link this to the nearest enclosing catch handler. + MBasicBlock* pendingInlineCatchBlock_; + + // Instance pointer argument to the current function. + MWasmParameter* instancePointer_; + MWasmParameter* stackResultPointer_; + + public: + // Construct a FunctionCompiler for the root function of a compilation + FunctionCompiler(RootCompiler& rootCompiler, Decoder& decoder, + const FuncCompileInput& func, const ValTypeVector& locals, + const CompileInfo& compileInfo) + : rootCompiler_(rootCompiler), + callerCompiler_(nullptr), + inliningDepth_(0), + iter_(rootCompiler.codeMeta(), decoder, locals), + functionBodyOffset_(decoder.beginOffset()), + func_(func), + locals_(locals), + lastReadCallSite_(0), + numCallRefs_(0), + numAllocSites_(0), + info_(compileInfo), + curBlock_(nullptr), + maxStackArgBytes_(0), + pendingBlockDepth_(0), + pendingInlineCatchBlock_(nullptr), + instancePointer_(nullptr), + stackResultPointer_(nullptr) {} + + // Construct a FunctionCompiler for an inlined callee of a compilation + FunctionCompiler(const FunctionCompiler* callerCompiler, Decoder& decoder, + const FuncCompileInput& func, const ValTypeVector& locals, + const CompileInfo& compileInfo) + : rootCompiler_(callerCompiler->rootCompiler_), + callerCompiler_(callerCompiler), + inliningDepth_(callerCompiler_->inliningDepth() + 1), + iter_(rootCompiler_.codeMeta(), decoder, locals), + functionBodyOffset_(decoder.beginOffset()), + func_(func), + locals_(locals), + lastReadCallSite_(0), + numCallRefs_(0), + numAllocSites_(0), + info_(compileInfo), + curBlock_(nullptr), + maxStackArgBytes_(0), + pendingBlockDepth_(0), + pendingInlineCatchBlock_(nullptr), + instancePointer_(callerCompiler_->instancePointer_), + stackResultPointer_(nullptr) {} + + RootCompiler& rootCompiler() { return rootCompiler_; } + const CodeMetadata& codeMeta() const { return rootCompiler_.codeMeta(); } + const CodeTailMetadata* codeTailMeta() const { + return rootCompiler_.codeTailMeta(); + } + + IonOpIter& iter() { return iter_; } + uint32_t relativeBytecodeOffset() { + return readBytecodeOffset() - functionBodyOffset_; + } + TempAllocator& alloc() const { return rootCompiler_.alloc(); } + // FIXME(1401675): Replace with BlockType. + uint32_t funcIndex() const { return func_.index; } + const FuncType& funcType() const { + return codeMeta().getFuncType(func_.index); + } + + bool isInlined() const { return callerCompiler_ != nullptr; } + uint32_t inliningDepth() const { return inliningDepth_; } + + MBasicBlock* getCurBlock() const { return curBlock_; } + BytecodeOffset bytecodeOffset() const { return iter_.bytecodeOffset(); } + TrapSiteDesc trapSiteDesc() { + return TrapSiteDesc(wasm::BytecodeOffset(bytecodeOffset()), + rootCompiler_.inlinedCallerOffsetsIndex()); + } + TrapSiteDesc trapSiteDescWithCallSiteLineNumber() { + return TrapSiteDesc(wasm::BytecodeOffset(readCallSiteLineOrBytecode()), + rootCompiler_.inlinedCallerOffsetsIndex()); + } + FeatureUsage featureUsage() const { return iter_.featureUsage(); } + + [[nodiscard]] bool initRoot() { + // We are not being inlined into something + MOZ_ASSERT(!callerCompiler_); - [[nodiscard]] bool init() { // Prepare the entry block for MIR generation: - const ArgTypeVector args(funcType()); + const FuncType& ft = funcType(); + const ArgTypeVector args(ft); - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } if (!newBlock(/* prev */ nullptr, &curBlock_)) { @@ -350,7 +567,15 @@ class FunctionCompiler { } for (WasmABIArgIter i(args); !i.done(); i++) { - MWasmParameter* ins = MWasmParameter::New(alloc(), *i, i.mirType()); + MaybeRefType argRefType; + if (!args.isSyntheticStackResultPointerArg(i.index())) { + ValType argType = ft.arg(i.index()); + argRefType = argType.isRefType() ? MaybeRefType(argType.refType()) + : MaybeRefType(); + } + + MWasmParameter* ins = + MWasmParameter::New(alloc(), *i, i.mirType(), argRefType); curBlock_->add(ins); if (args.isSyntheticStackResultPointerArg(i.index())) { MOZ_ASSERT(stackResultPointer_ == nullptr); @@ -359,7 +584,7 @@ class FunctionCompiler { curBlock_->initSlot(info().localSlot(args.naturalIndex(i.index())), ins); } - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } } @@ -368,7 +593,7 @@ class FunctionCompiler { instancePointer_ = MWasmParameter::New(alloc(), ABIArg(InstanceReg), MIRType::Pointer); curBlock_->add(instancePointer_); - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } @@ -382,7 +607,52 @@ class FunctionCompiler { #endif MDefinition* zero = constantZeroOfValType(slotValType); curBlock_->initSlot(info().localSlot(i), zero); - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { + return false; + } + } + + return true; + } + + [[nodiscard]] bool initInline(const DefVector& argValues) { + // "This is an inlined-callee FunctionCompiler" + MOZ_ASSERT(callerCompiler_); + + // Prepare the entry block for MIR generation: + if (!mirGen().ensureBallast()) { + return false; + } + if (!newBlock(nullptr, &curBlock_)) { + return false; + } + + MBasicBlock* pred = callerCompiler_->curBlock_; + pred->end(MGoto::New(alloc(), curBlock_)); + if (!curBlock_->addPredecessorWithoutPhis(pred)) { + return false; + } + + // Set up args slots to point to passed argument values + const FuncType& type = funcType(); + for (uint32_t argIndex = 0; argIndex < type.args().length(); argIndex++) { + curBlock_->initSlot(info().localSlot(argIndex), argValues[argIndex]); + } + + // Set up a parameter that receives the hidden instance pointer argument. + instancePointer_ = callerCompiler_->instancePointer_; + + // Initialize all local slots to zero value + for (size_t i = type.args().length(); i < locals_.length(); i++) { + ValType slotValType = locals_[i]; +#ifndef ENABLE_WASM_SIMD + if (slotValType == ValType::V128) { + return iter().fail("Ion has no SIMD support yet"); + } +#endif + MDefinition* zero = constantZeroOfValType(slotValType); + curBlock_->initSlot(info().localSlot(i), zero); + if (!mirGen().ensureBallast()) { return false; } } @@ -391,25 +661,36 @@ class FunctionCompiler { } void finish() { - mirGen().initWasmMaxStackArgBytes(maxStackArgBytes_); + mirGen().accumulateWasmMaxStackArgBytes(maxStackArgBytes_); - MOZ_ASSERT(loopDepth_ == 0); - MOZ_ASSERT(blockDepth_ == 0); + MOZ_ASSERT(pendingBlockDepth_ == 0); #ifdef DEBUG for (PendingBlockTarget& targets : pendingBlocks_) { MOZ_ASSERT(targets.patches.empty()); } #endif MOZ_ASSERT(inDeadCode()); - MOZ_ASSERT(done(), "all bytes must be consumed"); + MOZ_ASSERT(done()); MOZ_ASSERT(func_.callSiteLineNums.length() == lastReadCallSite_); + MOZ_ASSERT_IF( + compilerEnv().mode() == CompileMode::LazyTiering, + codeTailMeta()->getFuncDefCallRefs(funcIndex()).length == numCallRefs_); + MOZ_ASSERT_IF(codeTailMeta(), + codeTailMeta()->getFuncDefAllocSites(funcIndex()).length == + numAllocSites_); + MOZ_ASSERT_IF(!isInlined(), + pendingInlineReturns_.empty() && !pendingInlineCatchBlock_); + MOZ_ASSERT(bodyRethrowPadPatches_.empty()); } /************************* Read-only interface (after local scope setup) */ - MIRGenerator& mirGen() const { return mirGen_; } - MIRGraph& mirGraph() const { return graph_; } + MIRGenerator& mirGen() const { return rootCompiler_.mirGen(); } + MIRGraph& mirGraph() const { return rootCompiler_.mirGraph(); } const CompileInfo& info() const { return info_; } + const CompilerEnvironment& compilerEnv() const { + return rootCompiler_.compilerEnv(); + } MDefinition* getLocalDef(unsigned slot) { if (inDeadCode()) { @@ -489,12 +770,12 @@ class FunctionCompiler { MDefinition* constantV128(T) = delete; #endif - MDefinition* constantNullRef() { + MDefinition* constantNullRef(MaybeRefType type) { if (inDeadCode()) { return nullptr; } // MConstant has a lot of baggage so we don't use that here. - MWasmNullConstant* constant = MWasmNullConstant::New(alloc()); + MWasmNullConstant* constant = MWasmNullConstant::New(alloc(), type); curBlock_->add(constant); return constant; } @@ -515,7 +796,7 @@ class FunctionCompiler { case ValType::F64: return constantF64(0.0); case ValType::Ref: - return constantNullRef(); + return constantNullRef(MaybeRefType(valType.refType())); default: MOZ_CRASH(); } @@ -601,7 +882,7 @@ class FunctionCompiler { } bool mustPreserveNaN(MIRType type) { - return IsFloatingPointType(type) && !moduleEnv().isAsmJS(); + return IsFloatingPointType(type) && !codeMeta().isAsmJS(); } MDefinition* sub(MDefinition* lhs, MDefinition* rhs, MIRType type) { @@ -661,7 +942,7 @@ class FunctionCompiler { if (inDeadCode()) { return nullptr; } - bool trapOnError = !moduleEnv().isAsmJS(); + bool trapOnError = !codeMeta().isAsmJS(); if (!unsignd && type == MIRType::Int32) { // Enforce the signedness of the operation by coercing the operands // to signed. Otherwise, operands that "look" unsigned to Ion but @@ -686,16 +967,15 @@ class FunctionCompiler { // A call to c++ builtin requires instance pointer. #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) if (type == MIRType::Int64) { - auto* ins = - MWasmBuiltinDivI64::New(alloc(), lhs, rhs, instancePointer_, unsignd, - trapOnError, bytecodeOffset()); + auto* ins = MWasmBuiltinDivI64::New(alloc(), lhs, rhs, instancePointer_, + unsignd, trapOnError, trapSiteDesc()); curBlock_->add(ins); return ins; } #endif auto* ins = MDiv::New(alloc(), lhs, rhs, type, unsignd, trapOnError, - bytecodeOffset(), mustPreserveNaN(type)); + trapSiteDesc(), mustPreserveNaN(type)); curBlock_->add(ins); return ins; } @@ -713,7 +993,7 @@ class FunctionCompiler { if (inDeadCode()) { return nullptr; } - bool trapOnError = !moduleEnv().isAsmJS(); + bool trapOnError = !codeMeta().isAsmJS(); if (!unsignd && type == MIRType::Int32) { // See block comment in div(). auto* lhs2 = createTruncateToInt32(lhs); @@ -728,9 +1008,8 @@ class FunctionCompiler { // A call to c++ builtin requires instance pointer. #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) if (type == MIRType::Int64) { - auto* ins = - MWasmBuiltinModI64::New(alloc(), lhs, rhs, instancePointer_, unsignd, - trapOnError, bytecodeOffset()); + auto* ins = MWasmBuiltinModI64::New(alloc(), lhs, rhs, instancePointer_, + unsignd, trapOnError, trapSiteDesc()); curBlock_->add(ins); return ins; } @@ -746,16 +1025,16 @@ class FunctionCompiler { } auto* ins = MMod::New(alloc(), lhs, rhs, type, unsignd, trapOnError, - bytecodeOffset()); + trapSiteDesc()); curBlock_->add(ins); return ins; } - MDefinition* bitnot(MDefinition* op) { + MDefinition* bitnot(MDefinition* op, MIRType type) { if (inDeadCode()) { return nullptr; } - auto* ins = MBitNot::New(alloc(), op); + auto* ins = MBitNot::New(alloc(), op, type); curBlock_->add(ins); return ins; } @@ -858,7 +1137,7 @@ class FunctionCompiler { if (inDeadCode()) { return nullptr; } - auto* ins = T::New(alloc(), op, flags, bytecodeOffset()); + auto* ins = T::New(alloc(), op, flags, trapSiteDesc()); curBlock_->add(ins); return ins; } @@ -869,7 +1148,7 @@ class FunctionCompiler { return nullptr; } auto* ins = MWasmBuiltinTruncateToInt64::New(alloc(), op, instancePointer_, - flags, bytecodeOffset()); + flags, trapSiteDesc()); curBlock_->add(ins); return ins; } @@ -893,26 +1172,23 @@ class FunctionCompiler { } MDefinition* compareIsNull(MDefinition* ref, JSOp compareOp) { - MDefinition* nullVal = constantNullRef(); + MDefinition* nullVal = constantNullRef(MaybeRefType()); if (!nullVal) { return nullptr; } return compare(ref, nullVal, compareOp, MCompare::Compare_WasmAnyRef); } - [[nodiscard]] bool refAsNonNull(MDefinition* ref) { - if (inDeadCode()) { - return true; + [[nodiscard]] MDefinition* refAsNonNull(MDefinition* ref) { + MOZ_ASSERT(!inDeadCode()); + auto* ins = MWasmRefAsNonNull::New(alloc(), ref, trapSiteDesc()); + if (!ins) { + return nullptr; } - - auto* ins = MWasmTrapIfNull::New( - alloc(), ref, wasm::Trap::NullPointerDereference, bytecodeOffset()); - curBlock_->add(ins); - return true; + return ins; } -#ifdef ENABLE_WASM_GC [[nodiscard]] bool brOnNull(uint32_t relativeDepth, const DefVector& values, const ResultType& type, MDefinition* condition) { if (inDeadCode()) { @@ -975,9 +1251,6 @@ class FunctionCompiler { return true; } -#endif // ENABLE_WASM_GC - -#ifdef ENABLE_WASM_GC MDefinition* refI31(MDefinition* input) { auto* ins = MWasmNewI31Ref::New(alloc(), input); curBlock_->add(ins); @@ -989,7 +1262,6 @@ class FunctionCompiler { curBlock_->add(ins); return ins; } -#endif // ENABLE_WASM_GC #ifdef ENABLE_WASM_SIMD // About Wasm SIMD as supported by Ion: @@ -1154,7 +1426,7 @@ class FunctionCompiler { // A value holding the memory base, whether that's HeapReg or some other // register. MDefinition* memoryBase(uint32_t memoryIndex) { - AliasSet aliases = !moduleEnv_.memories[memoryIndex].canMovingGrow() + AliasSet aliases = !codeMeta().memories[memoryIndex].canMovingGrow() ? AliasSet::None() : AliasSet::Load(AliasSet::WasmHeapMeta); #ifdef WASM_HAS_HEAPREG @@ -1168,7 +1440,7 @@ class FunctionCompiler { memoryIndex == 0 ? Instance::offsetOfMemory0Base() : (Instance::offsetInData( - moduleEnv_.offsetOfMemoryInstanceData(memoryIndex) + + codeMeta().offsetOfMemoryInstanceData(memoryIndex) + offsetof(MemoryInstanceData, base))); MWasmLoadInstance* base = MWasmLoadInstance::New( alloc(), instancePointer_, offset, MIRType::Pointer, aliases); @@ -1182,16 +1454,16 @@ class FunctionCompiler { MWasmLoadInstance* maybeLoadBoundsCheckLimit(uint32_t memoryIndex, MIRType type) { MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Int64); - if (moduleEnv_.hugeMemoryEnabled(memoryIndex)) { + if (codeMeta().hugeMemoryEnabled(memoryIndex)) { return nullptr; } uint32_t offset = memoryIndex == 0 ? Instance::offsetOfMemory0BoundsCheckLimit() : (Instance::offsetInData( - moduleEnv_.offsetOfMemoryInstanceData(memoryIndex) + + codeMeta().offsetOfMemoryInstanceData(memoryIndex) + offsetof(MemoryInstanceData, boundsCheckLimit))); - AliasSet aliases = !moduleEnv_.memories[memoryIndex].canMovingGrow() + AliasSet aliases = !codeMeta().memories[memoryIndex].canMovingGrow() ? AliasSet::None() : AliasSet::Load(AliasSet::WasmHeapMeta); auto* load = MWasmLoadInstance::New(alloc(), instancePointer_, offset, type, @@ -1200,6 +1472,20 @@ class FunctionCompiler { return load; } + MDefinition* maybeCanonicalizeNaN(Scalar::Type accessType, + MDefinition* value) { + MOZ_ASSERT(codeMeta().isAsmJS()); + + // Canonicalize floating point values for differential testing. + if (Scalar::isFloatingType(accessType) && + js::SupportDifferentialTesting()) { + auto* canonicalize = MCanonicalizeNaN::New(alloc(), value); + curBlock_->add(canonicalize); + return canonicalize; + } + return value; + } + // Return true if the access requires an alignment check. If so, sets // *mustAdd to true if the offset must be added to the pointer before // checking. @@ -1208,7 +1494,7 @@ class FunctionCompiler { MOZ_ASSERT(!*mustAdd); // asm.js accesses are always aligned and need no checks. - if (moduleEnv_.isAsmJS() || !access->isAtomic()) { + if (codeMeta().isAsmJS() || !access->isAtomic()) { return false; } @@ -1238,8 +1524,8 @@ class FunctionCompiler { // the offset rather than vice versa is that a small offset can be ignored // by both explicit bounds checking and bounds check elimination. void foldConstantPointer(MemoryAccessDesc* access, MDefinition** base) { - uint32_t offsetGuardLimit = GetMaxOffsetGuardLimit( - moduleEnv_.hugeMemoryEnabled(access->memoryIndex())); + uint64_t offsetGuardLimit = GetMaxOffsetGuardLimit( + codeMeta().hugeMemoryEnabled(access->memoryIndex())); if ((*base)->isConstant()) { uint64_t basePtr = 0; @@ -1250,9 +1536,8 @@ class FunctionCompiler { } uint64_t offset = access->offset64(); - if (offset < offsetGuardLimit && basePtr < offsetGuardLimit - offset) { - offset += uint32_t(basePtr); + offset += basePtr; access->setOffset32(uint32_t(offset)); *base = isMem64(access->memoryIndex()) ? constantI64(int64_t(0)) : constantI32(0); @@ -1264,8 +1549,8 @@ class FunctionCompiler { // be checked, compute the effective address, trapping on overflow. void maybeComputeEffectiveAddress(MemoryAccessDesc* access, MDefinition** base, bool mustAddOffset) { - uint32_t offsetGuardLimit = GetMaxOffsetGuardLimit( - moduleEnv_.hugeMemoryEnabled(access->memoryIndex())); + uint64_t offsetGuardLimit = GetMaxOffsetGuardLimit( + codeMeta().hugeMemoryEnabled(access->memoryIndex())); if (access->offset64() >= offsetGuardLimit || access->offset64() > UINT32_MAX || mustAddOffset || @@ -1288,8 +1573,8 @@ class FunctionCompiler { static_assert(0x100000000 % PageSize == 0); bool mem32LimitIs64Bits = isMem32(memoryIndex) && - !moduleEnv_.memories[memoryIndex].boundsCheckLimitIs32Bits() && - MaxMemoryPages(moduleEnv_.memories[memoryIndex].indexType()) >= + !codeMeta().memories[memoryIndex].boundsCheckLimitIs32Bits() && + MaxMemoryPages(codeMeta().memories[memoryIndex].addressType()) >= Pages(0x100000000 / PageSize); #else // On 32-bit platforms we have no more than 2GB memory and the limit for a @@ -1323,7 +1608,7 @@ class FunctionCompiler { auto target = memoryIndex == 0 ? MWasmBoundsCheck::Memory0 : MWasmBoundsCheck::Unknown; auto* ins = MWasmBoundsCheck::New(alloc(), actualBase, boundsCheckLimit, - bytecodeOffset(), target); + trapSiteDesc(), target); curBlock_->add(ins); actualBase = ins; @@ -1351,10 +1636,10 @@ class FunctionCompiler { void checkOffsetAndAlignmentAndBounds(MemoryAccessDesc* access, MDefinition** base) { MOZ_ASSERT(!inDeadCode()); - MOZ_ASSERT(!moduleEnv_.isAsmJS()); + MOZ_ASSERT(!codeMeta().isAsmJS()); - // Attempt to fold an offset into a constant base pointer so as to simplify - // the addressing expression. This may update *base. + // Attempt to fold a constant base pointer into the offset so as to simplify + // the addressing expression. This may update *base. foldConstantPointer(access, base); // Determine whether an alignment check is needed and whether the offset @@ -1371,7 +1656,7 @@ class FunctionCompiler { // Emit the alignment check if necessary; it traps if it fails. if (alignmentCheck) { curBlock_->add(MWasmAlignmentCheck::New( - alloc(), *base, access->byteSize(), bytecodeOffset())); + alloc(), *base, access->byteSize(), trapSiteDesc())); } // Emit the bounds check if necessary; it traps if it fails. This may @@ -1389,7 +1674,7 @@ class FunctionCompiler { // 32 bits: the max memory is 2GB. So chop the index down to 32-bit to // simplify the back-end. MOZ_ASSERT((*base)->type() == MIRType::Int64); - MOZ_ASSERT(!moduleEnv_.hugeMemoryEnabled(access->memoryIndex())); + MOZ_ASSERT(!codeMeta().hugeMemoryEnabled(access->memoryIndex())); auto* chopped = MWasmWrapU32Index::New(alloc(), *base); MOZ_ASSERT(chopped->type() == MIRType::Int32); curBlock_->add(chopped); @@ -1409,16 +1694,17 @@ class FunctionCompiler { public: bool isMem32(uint32_t memoryIndex) { - return moduleEnv_.memories[memoryIndex].indexType() == IndexType::I32; + return codeMeta().memories[memoryIndex].addressType() == AddressType::I32; } bool isMem64(uint32_t memoryIndex) { - return moduleEnv_.memories[memoryIndex].indexType() == IndexType::I64; + return codeMeta().memories[memoryIndex].addressType() == AddressType::I64; } bool hugeMemoryEnabled(uint32_t memoryIndex) { - return moduleEnv_.hugeMemoryEnabled(memoryIndex); + return codeMeta().hugeMemoryEnabled(memoryIndex); } - // Add the offset into the pointer to yield the EA; trap on overflow. + // Add the offset into the pointer to yield the EA; trap on overflow. Clears + // the offset on the memory access as a result. MDefinition* computeEffectiveAddress(MDefinition* base, MemoryAccessDesc* access) { if (inDeadCode()) { @@ -1428,7 +1714,7 @@ class FunctionCompiler { if (offset == 0) { return base; } - auto* ins = MWasmAddOffset::New(alloc(), base, offset, bytecodeOffset()); + auto* ins = MWasmAddOffset::New(alloc(), base, offset, trapSiteDesc()); curBlock_->add(ins); access->clearOffset(); return ins; @@ -1442,7 +1728,7 @@ class FunctionCompiler { MDefinition* memoryBase = maybeLoadMemoryBase(access->memoryIndex()); MInstruction* load = nullptr; - if (moduleEnv_.isAsmJS()) { + if (codeMeta().isAsmJS()) { MOZ_ASSERT(access->offset64() == 0); MWasmLoadInstance* boundsCheckLimit = maybeLoadBoundsCheckLimit(access->memoryIndex(), MIRType::Int32); @@ -1470,10 +1756,11 @@ class FunctionCompiler { MDefinition* memoryBase = maybeLoadMemoryBase(access->memoryIndex()); MInstruction* store = nullptr; - if (moduleEnv_.isAsmJS()) { + if (codeMeta().isAsmJS()) { MOZ_ASSERT(access->offset64() == 0); MWasmLoadInstance* boundsCheckLimit = maybeLoadBoundsCheckLimit(access->memoryIndex(), MIRType::Int32); + v = maybeCanonicalizeNaN(access->type(), v); store = MAsmJSStoreHeap::New(alloc(), memoryBase, base, boundsCheckLimit, access->type(), v); } else { @@ -1611,7 +1898,7 @@ class FunctionCompiler { } MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, - bytecodeIfNotAsmJS(), + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); // Generate better code (on x86) @@ -1648,7 +1935,7 @@ class FunctionCompiler { // Generate better code (on x86) by loading as a double with an // operation that sign extends directly. MemoryAccessDesc access(addr.memoryIndex, Scalar::Float64, addr.align, - addr.offset, bytecodeIfNotAsmJS(), + addr.offset, trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); access.setWidenSimd128Load(op); return load(addr.base, &access, ValType::V128); @@ -1661,7 +1948,7 @@ class FunctionCompiler { } MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, - bytecodeIfNotAsmJS(), + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); access.setZeroExtendSimd128Load(); return load(addr.base, &access, ValType::V128); @@ -1675,11 +1962,11 @@ class FunctionCompiler { } MemoryAccessDesc access(addr.memoryIndex, Scalar::Simd128, addr.align, - addr.offset, bytecodeIfNotAsmJS(), + addr.offset, trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); MDefinition* memoryBase = maybeLoadMemoryBase(access.memoryIndex()); MDefinition* base = addr.base; - MOZ_ASSERT(!moduleEnv_.isAsmJS()); + MOZ_ASSERT(!codeMeta().isAsmJS()); checkOffsetAndAlignmentAndBounds(&access, &base); # ifndef JS_64BIT MOZ_ASSERT(base->type() == MIRType::Int32); @@ -1700,11 +1987,11 @@ class FunctionCompiler { return; } MemoryAccessDesc access(addr.memoryIndex, Scalar::Simd128, addr.align, - addr.offset, bytecodeIfNotAsmJS(), + addr.offset, trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); MDefinition* memoryBase = maybeLoadMemoryBase(access.memoryIndex()); MDefinition* base = addr.base; - MOZ_ASSERT(!moduleEnv_.isAsmJS()); + MOZ_ASSERT(!codeMeta().isAsmJS()); checkOffsetAndAlignmentAndBounds(&access, &base); # ifndef JS_64BIT MOZ_ASSERT(base->type() == MIRType::Int32); @@ -1720,14 +2007,13 @@ class FunctionCompiler { /************************************************ Global variable accesses */ - MDefinition* loadGlobalVar(unsigned instanceDataOffset, bool isConst, - bool isIndirect, MIRType type) { + MDefinition* loadGlobalVar(const GlobalDesc& global) { if (inDeadCode()) { return nullptr; } MInstruction* load; - if (isIndirect) { + if (global.isIndirect()) { // Pull a pointer to the value out of Instance::globalArea, then // load from that pointer. Note that the pointer is immutable // even though the value it points at may change, hence the use of @@ -1735,39 +2021,42 @@ class FunctionCompiler { // the |isConst| formal parameter to this method. The latter // applies to the denoted value as a whole. auto* cellPtr = MWasmLoadInstanceDataField::New( - alloc(), MIRType::Pointer, instanceDataOffset, + alloc(), MIRType::Pointer, global.offset(), /*isConst=*/true, instancePointer_); curBlock_->add(cellPtr); - load = MWasmLoadGlobalCell::New(alloc(), type, cellPtr); + load = MWasmLoadGlobalCell::New(alloc(), global.type().toMIRType(), + cellPtr, global.type()); } else { // Pull the value directly out of Instance::globalArea. - load = MWasmLoadInstanceDataField::New(alloc(), type, instanceDataOffset, - isConst, instancePointer_); + load = MWasmLoadInstanceDataField::New( + alloc(), global.type().toMIRType(), global.offset(), + !global.isMutable(), instancePointer_, + global.type().toMaybeRefType()); } curBlock_->add(load); return load; } [[nodiscard]] bool storeGlobalVar(uint32_t lineOrBytecode, - uint32_t instanceDataOffset, - bool isIndirect, MDefinition* v) { + const GlobalDesc& global, MDefinition* v) { if (inDeadCode()) { return true; } - if (isIndirect) { + if (global.isIndirect()) { // Pull a pointer to the value out of Instance::globalArea, then // store through that pointer. auto* valueAddr = MWasmLoadInstanceDataField::New( - alloc(), MIRType::Pointer, instanceDataOffset, - /*isConst=*/true, instancePointer_); + alloc(), MIRType::Pointer, global.offset(), + /*isConstant=*/true, instancePointer_); curBlock_->add(valueAddr); // Handle a store to a ref-typed field specially - if (v->type() == MIRType::WasmAnyRef) { + if (global.type().toMIRType() == MIRType::WasmAnyRef) { // Load the previous value for the post-write barrier - auto* prevValue = - MWasmLoadGlobalCell::New(alloc(), MIRType::WasmAnyRef, valueAddr); + MOZ_ASSERT(v->type() == MIRType::WasmAnyRef); + auto* prevValue = MWasmLoadGlobalCell::New(alloc(), MIRType::WasmAnyRef, + valueAddr, global.type()); curBlock_->add(prevValue); // Store the new value @@ -1778,7 +2067,7 @@ class FunctionCompiler { curBlock_->add(store); // Call the post-write barrier - return postBarrierPrecise(lineOrBytecode, valueAddr, prevValue); + return postBarrierEdgePrecise(lineOrBytecode, valueAddr, prevValue); } auto* store = MWasmStoreGlobalCell::New(alloc(), v, valueAddr); @@ -1788,16 +2077,17 @@ class FunctionCompiler { // Or else store the value directly in Instance::globalArea. // Handle a store to a ref-typed field specially - if (v->type() == MIRType::WasmAnyRef) { + if (global.type().toMIRType() == MIRType::WasmAnyRef) { // Compute the address of the ref-typed global auto* valueAddr = MWasmDerivedPointer::New( alloc(), instancePointer_, - wasm::Instance::offsetInData(instanceDataOffset)); + wasm::Instance::offsetInData(global.offset())); curBlock_->add(valueAddr); // Load the previous value for the post-write barrier - auto* prevValue = - MWasmLoadGlobalCell::New(alloc(), MIRType::WasmAnyRef, valueAddr); + MOZ_ASSERT(v->type() == MIRType::WasmAnyRef); + auto* prevValue = MWasmLoadGlobalCell::New(alloc(), MIRType::WasmAnyRef, + valueAddr, global.type()); curBlock_->add(prevValue); // Store the new value @@ -1808,19 +2098,33 @@ class FunctionCompiler { curBlock_->add(store); // Call the post-write barrier - return postBarrierPrecise(lineOrBytecode, valueAddr, prevValue); + return postBarrierEdgePrecise(lineOrBytecode, valueAddr, prevValue); } - auto* store = MWasmStoreInstanceDataField::New(alloc(), instanceDataOffset, - v, instancePointer_); + auto* store = MWasmStoreInstanceDataField::New(alloc(), global.offset(), v, + instancePointer_); curBlock_->add(store); return true; } + // Load the slot on the instance where the result of `ref.func` is cached. + // This may be null if a function reference for this function has not been + // asked for yet. + MDefinition* loadCachedRefFunc(uint32_t funcIndex) { + uint32_t exportedFuncIndex = codeMeta().findFuncExportIndex(funcIndex); + MWasmLoadInstanceDataField* refFunc = MWasmLoadInstanceDataField::New( + alloc(), MIRType::WasmAnyRef, + codeMeta().offsetOfFuncExportInstanceData(exportedFuncIndex) + + offsetof(FuncExportInstanceData, func), + true, instancePointer_); + curBlock_->add(refFunc); + return refFunc; + } + MDefinition* loadTableField(uint32_t tableIndex, unsigned fieldOffset, MIRType type) { uint32_t instanceDataOffset = wasm::Instance::offsetInData( - moduleEnv_.offsetOfTableInstanceData(tableIndex) + fieldOffset); + codeMeta().offsetOfTableInstanceData(tableIndex) + fieldOffset); auto* load = MWasmLoadInstance::New(alloc(), instancePointer_, instanceDataOffset, type, AliasSet::Load(AliasSet::WasmTableMeta)); @@ -1838,47 +2142,69 @@ class FunctionCompiler { MIRType::Pointer); } - MDefinition* tableGetAnyRef(uint32_t tableIndex, MDefinition* index) { + MDefinition* tableAddressToI32(AddressType addressType, + MDefinition* address) { + switch (addressType) { + case AddressType::I32: + return address; + case AddressType::I64: + auto* clamp = MWasmClampTable64Address::New(alloc(), address); + if (!clamp) { + return nullptr; + } + curBlock_->add(clamp); + return clamp; + } + MOZ_CRASH("unknown address type"); + } + + MDefinition* tableGetAnyRef(uint32_t tableIndex, MDefinition* address) { + const TableDesc& table = codeMeta().tables[tableIndex]; + // Load the table length and perform a bounds check with spectre index // masking auto* length = loadTableLength(tableIndex); auto* check = MWasmBoundsCheck::New( - alloc(), index, length, bytecodeOffset(), MWasmBoundsCheck::Unknown); + alloc(), address, length, trapSiteDesc(), MWasmBoundsCheck::Unknown); curBlock_->add(check); if (JitOptions.spectreIndexMasking) { - index = check; + address = check; } // Load the table elements and load the element auto* elements = loadTableElements(tableIndex); - auto* element = MWasmLoadTableElement::New(alloc(), elements, index); + auto* element = + MWasmLoadTableElement::New(alloc(), elements, address, table.elemType); curBlock_->add(element); return element; } - [[nodiscard]] bool tableSetAnyRef(uint32_t tableIndex, MDefinition* index, + [[nodiscard]] bool tableSetAnyRef(uint32_t tableIndex, MDefinition* address, MDefinition* value, uint32_t lineOrBytecode) { + const TableDesc& table = codeMeta().tables[tableIndex]; + // Load the table length and perform a bounds check with spectre index // masking auto* length = loadTableLength(tableIndex); auto* check = MWasmBoundsCheck::New( - alloc(), index, length, bytecodeOffset(), MWasmBoundsCheck::Unknown); + alloc(), address, length, trapSiteDesc(), MWasmBoundsCheck::Unknown); curBlock_->add(check); if (JitOptions.spectreIndexMasking) { - index = check; + address = check; } // Load the table elements auto* elements = loadTableElements(tableIndex); // Load the previous value - auto* prevValue = MWasmLoadTableElement::New(alloc(), elements, index); + auto* prevValue = + MWasmLoadTableElement::New(alloc(), elements, address, table.elemType); curBlock_->add(prevValue); // Compute the value's location for the post barrier auto* loc = - MWasmDerivedIndexPointer::New(alloc(), elements, index, ScalePointer); + MWasmDerivedIndexPointer::New(alloc(), elements, address, ScalePointer); curBlock_->add(loc); // Store the new value @@ -1888,7 +2214,7 @@ class FunctionCompiler { curBlock_->add(store); // Perform the post barrier - return postBarrierPrecise(lineOrBytecode, loc, prevValue); + return postBarrierEdgePrecise(lineOrBytecode, loc, prevValue); } void addInterruptCheck() { @@ -1896,46 +2222,17 @@ class FunctionCompiler { return; } curBlock_->add( - MWasmInterruptCheck::New(alloc(), instancePointer_, bytecodeOffset())); + MWasmInterruptCheck::New(alloc(), instancePointer_, trapSiteDesc())); } // Perform a post-write barrier to update the generational store buffer. This - // version will remove a previous store buffer entry if it is no longer - // needed. - [[nodiscard]] bool postBarrierPrecise(uint32_t lineOrBytecode, - MDefinition* valueAddr, - MDefinition* value) { - return emitInstanceCall2(lineOrBytecode, SASigPostBarrierPrecise, valueAddr, - value); - } - - // Perform a post-write barrier to update the generational store buffer. This - // version will remove a previous store buffer entry if it is no longer - // needed. - [[nodiscard]] bool postBarrierPreciseWithOffset(uint32_t lineOrBytecode, - MDefinition* valueBase, - uint32_t valueOffset, - MDefinition* value) { - MDefinition* valueOffsetDef = constantI32(int32_t(valueOffset)); - if (!valueOffsetDef) { - return false; - } - return emitInstanceCall3(lineOrBytecode, SASigPostBarrierPreciseWithOffset, - valueBase, valueOffsetDef, value); - } - - // Perform a post-write barrier to update the generational store buffer. This - // version is the most efficient and only requires the address to store the - // value and the new value. It does not remove a previous store buffer entry - // if it is no longer needed, you must use a precise post-write barrier for - // that. - [[nodiscard]] bool postBarrierImmediate(uint32_t lineOrBytecode, + // version stores the entire containing object (e.g. a struct) rather than a + // single edge. + [[nodiscard]] bool postBarrierWholeCell(uint32_t lineOrBytecode, MDefinition* object, - MDefinition* valueBase, - uint32_t valueOffset, MDefinition* newValue) { - auto* barrier = MWasmPostWriteBarrierImmediate::New( - alloc(), instancePointer_, object, valueBase, valueOffset, newValue); + auto* barrier = MWasmPostWriteBarrierWholeCell::New( + alloc(), instancePointer_, object, newValue); if (!barrier) { return false; } @@ -1943,12 +2240,25 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool postBarrierIndex(uint32_t lineOrBytecode, - MDefinition* object, - MDefinition* valueBase, - MDefinition* index, uint32_t scale, - MDefinition* newValue) { - auto* barrier = MWasmPostWriteBarrierIndex::New( + // Perform a post-write barrier to update the generational store buffer. This + // version tracks a single tenured -> nursery edge, and will remove a previous + // store buffer entry if it is no longer needed. + [[nodiscard]] bool postBarrierEdgePrecise(uint32_t lineOrBytecode, + MDefinition* valueAddr, + MDefinition* value) { + return emitInstanceCall2(lineOrBytecode, SASigPostBarrierEdgePrecise, + valueAddr, value); + } + + // Perform a post-write barrier to update the generational store buffer. This + // version does not remove a previous store buffer entry if it is no longer + // needed. + [[nodiscard]] bool postBarrierEdgeAtIndex(uint32_t lineOrBytecode, + MDefinition* object, + MDefinition* valueBase, + MDefinition* index, uint32_t scale, + MDefinition* newValue) { + auto* barrier = MWasmPostWriteBarrierEdgeAtIndex::New( alloc(), instancePointer_, object, valueBase, index, scale, newValue); if (!barrier) { return false; @@ -1969,25 +2279,26 @@ class FunctionCompiler { // stack space required for each individual call (as determined by the call // ABI). - // Operations that modify a CallCompileState. - - [[nodiscard]] bool passInstance(MIRType instanceType, - CallCompileState* args) { + [[nodiscard]] + bool passInstanceCallArg(MIRType instanceType, CallCompileState* callState) { if (inDeadCode()) { return true; } // Should only pass an instance once. And it must be a non-GC pointer. - MOZ_ASSERT(args->instanceArg_ == ABIArg()); + MOZ_ASSERT(callState->instanceArg == ABIArg()); MOZ_ASSERT(instanceType == MIRType::Pointer); - args->instanceArg_ = args->abi_.next(MIRType::Pointer); + callState->instanceArg = callState->abi.next(MIRType::Pointer); return true; } - // Do not call this directly. Call one of the passArg() variants instead. - [[nodiscard]] bool passArgWorker(MDefinition* argDef, MIRType type, - CallCompileState* call) { - ABIArg arg = call->abi_.next(type); + // Do not call this directly. Call one of the passCallArg() variants instead. + [[nodiscard]] + bool passCallArgWorker(MDefinition* argDef, MIRType type, + CallCompileState* callState) { + MOZ_ASSERT(argDef->type() == type); + + ABIArg arg = callState->abi.next(type); switch (arg.kind()) { #ifdef JS_CODEGEN_REGISTER_PAIR case ABIArg::GPR_PAIR: { @@ -1997,15 +2308,15 @@ class FunctionCompiler { auto mirHigh = MWrapInt64ToInt32::New(alloc(), argDef, /* bottomHalf = */ false); curBlock_->add(mirHigh); - return call->regArgs_.append( + return callState->regArgs.append( MWasmCallBase::Arg(AnyRegister(arg.gpr64().low), mirLow)) && - call->regArgs_.append( + callState->regArgs.append( MWasmCallBase::Arg(AnyRegister(arg.gpr64().high), mirHigh)); } #endif case ABIArg::GPR: case ABIArg::FPU: - return call->regArgs_.append(MWasmCallBase::Arg(arg.reg(), argDef)); + return callState->regArgs.append(MWasmCallBase::Arg(arg.reg(), argDef)); case ABIArg::Stack: { auto* mir = MWasmStackArg::New(alloc(), arg.offsetFromArgBase(), argDef); @@ -2019,42 +2330,44 @@ class FunctionCompiler { } template - [[nodiscard]] bool passArgs(const DefVector& argDefs, const VecT& types, - CallCompileState* call) { + [[nodiscard]] + bool passCallArgs(const DefVector& argDefs, const VecT& types, + CallCompileState* callState) { MOZ_ASSERT(argDefs.length() == types.length()); for (uint32_t i = 0; i < argDefs.length(); i++) { MDefinition* def = argDefs[i]; ValType type = types[i]; - if (!passArg(def, type, call)) { + if (!passCallArg(def, type, callState)) { return false; } } return true; } - [[nodiscard]] bool passArg(MDefinition* argDef, MIRType type, - CallCompileState* call) { + [[nodiscard]] + bool passCallArg(MDefinition* argDef, MIRType type, + CallCompileState* callState) { if (inDeadCode()) { return true; } - return passArgWorker(argDef, type, call); + return passCallArgWorker(argDef, type, callState); } - [[nodiscard]] bool passArg(MDefinition* argDef, ValType type, - CallCompileState* call) { + [[nodiscard]] + bool passCallArg(MDefinition* argDef, ValType type, + CallCompileState* callState) { if (inDeadCode()) { return true; } - return passArgWorker(argDef, type.toMIRType(), call); + return passCallArgWorker(argDef, type.toMIRType(), callState); } - void markReturnCall(CallCompileState* call) { call->returnCall = true; } - // If the call returns results on the stack, prepare a stack area to receive // them, and pass the address of the stack area to the callee as an additional // argument. - [[nodiscard]] bool passStackResultAreaCallArg(const ResultType& resultType, - CallCompileState* call) { + [[nodiscard]] + bool passStackResultAreaCallArg(const ResultType& resultType, + CallCompileState* callState) { if (inDeadCode()) { return true; } @@ -2080,35 +2393,54 @@ class FunctionCompiler { stackResultArea->initResult(iter.index() - base, loc); } curBlock_->add(stackResultArea); - MDefinition* def = call->returnCall ? (MDefinition*)stackResultPointer_ - : (MDefinition*)stackResultArea; - if (!passArg(def, MIRType::Pointer, call)) { + MDefinition* def = callState->returnCall ? (MDefinition*)stackResultPointer_ + : (MDefinition*)stackResultArea; + if (!passCallArg(def, MIRType::StackResults, callState)) { return false; } - call->stackResultArea_ = stackResultArea; + callState->stackResultArea = stackResultArea; return true; } - [[nodiscard]] bool finishCall(CallCompileState* call) { + [[nodiscard]] + bool finishCallArgs(CallCompileState* callState) { if (inDeadCode()) { return true; } - if (!call->regArgs_.append( + if (!callState->regArgs.append( MWasmCallBase::Arg(AnyRegister(InstanceReg), instancePointer_))) { return false; } - uint32_t stackBytes = call->abi_.stackBytesConsumedSoFar(); + uint32_t stackBytes = callState->abi.stackBytesConsumedSoFar(); maxStackArgBytes_ = std::max(maxStackArgBytes_, stackBytes); return true; } - // Wrappers for creating various kinds of calls. + [[nodiscard]] + bool emitCallArgs(const FuncType& funcType, const DefVector& args, + CallCompileState* callState) { + for (size_t i = 0, n = funcType.args().length(); i < n; ++i) { + if (!mirGen().ensureBallast()) { + return false; + } + if (!passCallArg(args[i], funcType.args()[i], callState)) { + return false; + } + } - [[nodiscard]] bool collectUnaryCallResult(MIRType type, - MDefinition** result) { + ResultType resultType = ResultType::Vector(funcType.results()); + if (!passStackResultAreaCallArg(resultType, callState)) { + return false; + } + + return finishCallArgs(callState); + } + + [[nodiscard]] + bool collectUnaryCallResult(MIRType type, MDefinition** result) { MInstruction* def; switch (type) { case MIRType::Int32: @@ -2131,6 +2463,9 @@ class FunctionCompiler { case MIRType::WasmAnyRef: def = MWasmRegisterResult::New(alloc(), MIRType::WasmAnyRef, ReturnReg); break; + case MIRType::None: + MOZ_ASSERT(result == nullptr, "Not expecting any results created"); + return true; default: MOZ_CRASH("unexpected MIRType result for builtin call"); } @@ -2145,9 +2480,10 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool collectCallResults(const ResultType& type, - MWasmStackResultArea* stackResultArea, - DefVector* results) { + [[nodiscard]] + bool collectCallResults(const ResultType& type, + MWasmStackResultArea* stackResultArea, + DefVector* results) { if (!results->reserve(type.length())) { return false; } @@ -2188,7 +2524,8 @@ class FunctionCompiler { break; case wasm::ValType::Ref: def = MWasmRegisterResult::New(alloc(), MIRType::WasmAnyRef, - result.gpr()); + result.gpr(), + result.type().toMaybeRefType()); break; case wasm::ValType::V128: #ifdef ENABLE_WASM_SIMD @@ -2217,64 +2554,265 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool catchableCall(const CallSiteDesc& desc, - const CalleeDesc& callee, - const MWasmCallBase::Args& args, - const ArgTypeVector& argTypes, - MDefinition* indexOrRef = nullptr) { - MWasmCallTryDesc tryDesc; - if (!beginTryCall(&tryDesc)) { + [[nodiscard]] + bool call(CallCompileState* callState, const CallSiteDesc& desc, + const CalleeDesc& callee, const ArgTypeVector& argTypes, + MDefinition* addressOrRef = nullptr) { + if (!beginCatchableCall(callState)) { return false; } MInstruction* ins; - if (tryDesc.inTry) { - ins = MWasmCallCatchable::New(alloc(), desc, callee, args, - StackArgAreaSizeUnaligned(argTypes), - tryDesc, indexOrRef); + if (callState->isCatchable()) { + ins = MWasmCallCatchable::New( + alloc(), desc, callee, callState->regArgs, + StackArgAreaSizeUnaligned(argTypes), callState->tryNoteIndex, + callState->fallthroughBlock, callState->prePadBlock, addressOrRef); } else { - ins = MWasmCallUncatchable::New(alloc(), desc, callee, args, + ins = MWasmCallUncatchable::New(alloc(), desc, callee, callState->regArgs, StackArgAreaSizeUnaligned(argTypes), - indexOrRef); + addressOrRef); } if (!ins) { return false; } curBlock_->add(ins); - return finishTryCall(&tryDesc); + return finishCatchableCall(callState); } - [[nodiscard]] bool callDirect(const FuncType& funcType, uint32_t funcIndex, - uint32_t lineOrBytecode, - const CallCompileState& call, - DefVector* results) { + [[nodiscard]] + CallRefHint auditInlineableCallees(InliningHeuristics::CallKind kind, + CallRefHint hints) { + // Takes candidates for inlining as provided in `hints`, and returns a + // subset (or all) of them for which inlining is approved. To indicate + // that they are all disallowed, return an empty CallRefHint. + + MOZ_ASSERT_IF(kind == InliningHeuristics::CallKind::Direct, + hints.length() == 1); + + // We only support inlining when lazy tiering. This is currently a + // requirement because we need the full module bytecode and function + // definition ranges, which are not available in other modes. + if (compilerEnv().mode() != CompileMode::LazyTiering) { + return CallRefHint(); + } + + // We don't support asm.js and inlining. asm.js also doesn't support + // baseline, which is required for lazy tiering, so we should never get + // here. The biggest complication for asm.js is getting correct stack + // traces with inlining. + MOZ_ASSERT(!codeMeta().isAsmJS()); + + // If we were given no candidates, give up now. + if (hints.empty()) { + return CallRefHint(); + } + + // We can't inline if we've exceeded our per-root-function inlining + // budget. + // + // This logic will cause `availableBudget` to be driven slightly negative + // if a budget overshoot happens, so we will have performed slightly more + // inlining than allowed by the initial setting of `availableBudget`. The + // size of this overshoot is however very limited -- it can't exceed the + // size of three function bodies that are inlined (3 because that's what + // CallRefHint can hold). And the max size of an inlineable function body + // is limited by InliningHeuristics::isSmallEnoughToInline. + if (rootCompiler_.inliningBudget() < 0) { + return CallRefHint(); + } + + // Check each candidate in turn, and add all acceptable ones to `filtered`. + // It is important that `filtered` retains the same ordering as `hints`. + CallRefHint filtered; + for (uint32_t i = 0; i < hints.length(); i++) { + uint32_t funcIndex = hints.get(i); + + // We can't inline an imported function. + if (codeMeta().funcIsImport(funcIndex)) { + continue; + } + + // We do not support inlining a callee which uses tail calls + FeatureUsage funcFeatureUsage = + codeTailMeta()->funcDefFeatureUsage(funcIndex); + if (funcFeatureUsage & FeatureUsage::ReturnCall) { + continue; + } + + // Ask the heuristics system if we're allowed to inline a function of + // this size and kind at the current inlining depth. + uint32_t inlineeBodySize = codeTailMeta()->funcDefRange(funcIndex).size(); + uint32_t rootFunctionBodySize = rootCompiler_.func().bytecodeSize(); + bool largeFunctionBackoff; + bool smallEnough = InliningHeuristics::isSmallEnoughToInline( + kind, inliningDepth(), inlineeBodySize, rootFunctionBodySize, + &largeFunctionBackoff); + if (largeFunctionBackoff) { + rootCompiler_.noteLargeFunctionBackoffWasApplied(); + } + if (!smallEnough) { + continue; + } + + filtered.append(funcIndex); + } + + // Whatever ends up in `filtered` is approved for inlining. + return filtered; + } + + [[nodiscard]] + bool finishInlinedCallDirect(FunctionCompiler& calleeCompiler, + DefVector* results) { + const PendingInlineReturnVector& calleeReturns = + calleeCompiler.pendingInlineReturns_; + MBasicBlock* calleeCatchBlock = calleeCompiler.pendingInlineCatchBlock_; + const FuncType& calleeFuncType = calleeCompiler.funcType(); + MBasicBlock* lastBlockBeforeCall = curBlock_; + + // Add the observed features from the inlined function to this function + iter_.addFeatureUsage(calleeCompiler.featureUsage()); + + // Create a block, if needed, to handle exceptions from the callee function + if (calleeCatchBlock) { + ControlInstructionVector* tryLandingPadPatches; + bool inTryCode = inTryBlock(&tryLandingPadPatches); + + // The callee compiler should never create a catch block unless we have + // a landing pad for it + MOZ_RELEASE_ASSERT(inTryCode); + + // Create a block in our function to jump to the nearest try block. We + // cannot just use the callee's catch block for this, as the slots on it + // are set up for all the locals from that function. We need to create a + // new block in our function with the slots for this function, that then + // does the jump to the landing pad. Ion should be able to optimize this + // away using jump threading. + MBasicBlock* callerCatchBlock = nullptr; + if (!newBlock(nullptr, &callerCatchBlock)) { + return false; + } + + // Our catch block inherits all of the locals state from immediately + // before the inlined call + callerCatchBlock->inheritSlots(lastBlockBeforeCall); + + // The callee catch block jumps to our catch block + calleeCatchBlock->end(MGoto::New(alloc(), callerCatchBlock)); + + // Our catch block has the callee rethrow block as a predecessor, but + // ignores all phi's, because we use our own locals state. + if (!callerCatchBlock->addPredecessorWithoutPhis(calleeCatchBlock)) { + return false; + } + + // Our catch block ends with a patch to jump to the enclosing try block. + MBasicBlock* prevBlock = curBlock_; + curBlock_ = callerCatchBlock; + if (!endWithPadPatch(tryLandingPadPatches)) { + return false; + } + curBlock_ = prevBlock; + } + + // If there were no returns, then we are now in dead code + if (calleeReturns.empty()) { + curBlock_ = nullptr; + return true; + } + + // Create a block to join all of the returns from the inlined function + MBasicBlock* joinAfterCall = nullptr; + if (!newBlock(nullptr, &joinAfterCall)) { + return false; + } + + // The join block inherits all of the locals state from immediately before + // the inlined call + joinAfterCall->inheritSlots(lastBlockBeforeCall); + + // The join block has a phi node for every result of the inlined function + // type. Each phi node has an operand for each of the returns of the + // inlined function. + for (uint32_t i = 0; i < calleeFuncType.results().length(); i++) { + MPhi* phi = MPhi::New(alloc(), calleeFuncType.results()[i].toMIRType()); + if (!phi || !phi->reserveLength(calleeReturns.length())) { + return false; + } + joinAfterCall->addPhi(phi); + if (!results->append(phi)) { + return false; + } + } + + // Bind every return from the inlined function to go to the join block, and + // add the results for the return to the phi nodes. + for (size_t i = 0; i < calleeReturns.length(); i++) { + const PendingInlineReturn& calleeReturn = calleeReturns[i]; + + // Setup the predecessor and successor relationship + MBasicBlock* pred = calleeReturn.jump->block(); + if (!joinAfterCall->addPredecessorWithoutPhis(pred)) { + return false; + } + calleeReturn.jump->replaceSuccessor(MGoto::TargetIndex, joinAfterCall); + + // For each result in this return, add it to the corresponding phi node + for (uint32_t resultIndex = 0; + resultIndex < calleeFuncType.results().length(); resultIndex++) { + MDefinition* result = (*results)[resultIndex]; + ((MPhi*)(result))->addInput(calleeReturn.results[resultIndex]); + } + } + + // Continue MIR generation starting in the join block + curBlock_ = joinAfterCall; + + return true; + } + + [[nodiscard]] + bool callDirect(const FuncType& funcType, uint32_t funcIndex, + uint32_t lineOrBytecode, const DefVector& args, + DefVector* results) { MOZ_ASSERT(!inDeadCode()); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Func); + CallCompileState callState; + CallSiteDesc desc(lineOrBytecode, rootCompiler_.inlinedCallerOffsetsIndex(), + CallSiteKind::Func); ResultType resultType = ResultType::Vector(funcType.results()); auto callee = CalleeDesc::function(funcIndex); - ArgTypeVector args(funcType); + ArgTypeVector argTypes(funcType); - if (!catchableCall(desc, callee, call.regArgs_, args)) { - return false; - } - return collectCallResults(resultType, call.stackResultArea_, results); + return emitCallArgs(funcType, args, &callState) && + call(&callState, desc, callee, argTypes) && + collectCallResults(resultType, callState.stackResultArea, results); } - [[nodiscard]] bool returnCallDirect(const FuncType& funcType, - uint32_t funcIndex, - uint32_t lineOrBytecode, - const CallCompileState& call, - DefVector* results) { + [[nodiscard]] + bool returnCallDirect(const FuncType& funcType, uint32_t funcIndex, + uint32_t lineOrBytecode, const DefVector& args, + DefVector* results) { MOZ_ASSERT(!inDeadCode()); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::ReturnFunc); + // We do not support tail calls in inlined functions. + MOZ_RELEASE_ASSERT(!isInlined()); + + CallCompileState callState; + callState.returnCall = true; + CallSiteDesc desc(lineOrBytecode, CallSiteKind::ReturnFunc); auto callee = CalleeDesc::function(funcIndex); - ArgTypeVector args(funcType); + ArgTypeVector argTypes(funcType); - auto ins = MWasmReturnCall::New(alloc(), desc, callee, call.regArgs_, - StackArgAreaSizeUnaligned(args), nullptr); + if (!emitCallArgs(funcType, args, &callState)) { + return false; + } + + auto ins = + MWasmReturnCall::New(alloc(), desc, callee, callState.regArgs, + StackArgAreaSizeUnaligned(argTypes), nullptr); if (!ins) { return false; } @@ -2283,19 +2821,28 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool returnCallImport(unsigned globalDataOffset, - uint32_t lineOrBytecode, - const CallCompileState& call, - const FuncType& funcType, - DefVector* results) { + [[nodiscard]] + bool returnCallImport(unsigned globalDataOffset, uint32_t lineOrBytecode, + const FuncType& funcType, const DefVector& args, + DefVector* results) { MOZ_ASSERT(!inDeadCode()); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Import); + // We do not support tail calls in inlined functions. + MOZ_RELEASE_ASSERT(!isInlined()); + + CallCompileState callState; + callState.returnCall = true; + CallSiteDesc desc(lineOrBytecode, CallSiteKind::Import); auto callee = CalleeDesc::import(globalDataOffset); - ArgTypeVector args(funcType); + ArgTypeVector argTypes(funcType); - auto* ins = MWasmReturnCall::New(alloc(), desc, callee, call.regArgs_, - StackArgAreaSizeUnaligned(args), nullptr); + if (!emitCallArgs(funcType, args, &callState)) { + return false; + } + + auto* ins = + MWasmReturnCall::New(alloc(), desc, callee, callState.regArgs, + StackArgAreaSizeUnaligned(argTypes), nullptr); if (!ins) { return false; } @@ -2304,28 +2851,42 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool returnCallIndirect(uint32_t funcTypeIndex, - uint32_t tableIndex, MDefinition* index, - uint32_t lineOrBytecode, - const CallCompileState& call, - DefVector* results) { + [[nodiscard]] + bool returnCallIndirect(uint32_t funcTypeIndex, uint32_t tableIndex, + MDefinition* address, uint32_t lineOrBytecode, + const DefVector& args, DefVector* results) { MOZ_ASSERT(!inDeadCode()); - const FuncType& funcType = (*moduleEnv_.types)[funcTypeIndex].funcType(); - CallIndirectId callIndirectId = - CallIndirectId::forFuncType(moduleEnv_, funcTypeIndex); + // We do not support tail calls in inlined functions. + MOZ_RELEASE_ASSERT(!isInlined()); + const FuncType& funcType = (*codeMeta().types)[funcTypeIndex].funcType(); + CallIndirectId callIndirectId = + CallIndirectId::forFuncType(codeMeta(), funcTypeIndex); + + CallCompileState callState; + callState.returnCall = true; CalleeDesc callee; MOZ_ASSERT(callIndirectId.kind() != CallIndirectIdKind::AsmJS); - const TableDesc& table = moduleEnv_.tables[tableIndex]; + const TableDesc& table = codeMeta().tables[tableIndex]; callee = - CalleeDesc::wasmTable(moduleEnv_, table, tableIndex, callIndirectId); + CalleeDesc::wasmTable(codeMeta(), table, tableIndex, callIndirectId); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Indirect); - ArgTypeVector args(funcType); + CallSiteDesc desc(lineOrBytecode, CallSiteKind::Indirect); + ArgTypeVector argTypes(funcType); - auto* ins = MWasmReturnCall::New(alloc(), desc, callee, call.regArgs_, - StackArgAreaSizeUnaligned(args), index); + if (!emitCallArgs(funcType, args, &callState)) { + return false; + } + + MDefinition* address32 = tableAddressToI32(table.addressType(), address); + if (!address32) { + return false; + } + + auto* ins = + MWasmReturnCall::New(alloc(), desc, callee, callState.regArgs, + StackArgAreaSizeUnaligned(argTypes), address32); if (!ins) { return false; } @@ -2334,133 +2895,324 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool callIndirect(uint32_t funcTypeIndex, uint32_t tableIndex, - MDefinition* index, uint32_t lineOrBytecode, - const CallCompileState& call, - DefVector* results) { + [[nodiscard]] + bool callIndirect(uint32_t funcTypeIndex, uint32_t tableIndex, + MDefinition* address, uint32_t lineOrBytecode, + const DefVector& args, DefVector* results) { MOZ_ASSERT(!inDeadCode()); - const FuncType& funcType = (*moduleEnv_.types)[funcTypeIndex].funcType(); + CallCompileState callState; + const FuncType& funcType = (*codeMeta().types)[funcTypeIndex].funcType(); CallIndirectId callIndirectId = - CallIndirectId::forFuncType(moduleEnv_, funcTypeIndex); + CallIndirectId::forFuncType(codeMeta(), funcTypeIndex); CalleeDesc callee; - if (moduleEnv_.isAsmJS()) { + if (codeMeta().isAsmJS()) { MOZ_ASSERT(tableIndex == 0); MOZ_ASSERT(callIndirectId.kind() == CallIndirectIdKind::AsmJS); - uint32_t tableIndex = moduleEnv_.asmJSSigToTableIndex[funcTypeIndex]; - const TableDesc& table = moduleEnv_.tables[tableIndex]; - MOZ_ASSERT(IsPowerOfTwo(table.initialLength)); + uint32_t tableIndex = codeMeta().asmJSSigToTableIndex[funcTypeIndex]; + const TableDesc& table = codeMeta().tables[tableIndex]; + // ensured by asm.js validation + MOZ_ASSERT(table.initialLength() <= UINT32_MAX); + MOZ_ASSERT(IsPowerOfTwo(table.initialLength())); - MDefinition* mask = constantI32(int32_t(table.initialLength - 1)); - MBitAnd* maskedIndex = MBitAnd::New(alloc(), index, mask, MIRType::Int32); - curBlock_->add(maskedIndex); + MDefinition* mask = constantI32(int32_t(table.initialLength() - 1)); + MBitAnd* maskedAddress = + MBitAnd::New(alloc(), address, mask, MIRType::Int32); + curBlock_->add(maskedAddress); - index = maskedIndex; - callee = CalleeDesc::asmJSTable(moduleEnv_, tableIndex); + address = maskedAddress; + callee = CalleeDesc::asmJSTable(codeMeta(), tableIndex); } else { MOZ_ASSERT(callIndirectId.kind() != CallIndirectIdKind::AsmJS); - const TableDesc& table = moduleEnv_.tables[tableIndex]; + const TableDesc& table = codeMeta().tables[tableIndex]; callee = - CalleeDesc::wasmTable(moduleEnv_, table, tableIndex, callIndirectId); + CalleeDesc::wasmTable(codeMeta(), table, tableIndex, callIndirectId); + address = tableAddressToI32(table.addressType(), address); + if (!address) { + return false; + } } - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Indirect); - ArgTypeVector args(funcType); + CallSiteDesc desc(lineOrBytecode, rootCompiler_.inlinedCallerOffsetsIndex(), + CallSiteKind::Indirect); + ArgTypeVector argTypes(funcType); ResultType resultType = ResultType::Vector(funcType.results()); - if (!catchableCall(desc, callee, call.regArgs_, args, index)) { - return false; - } - return collectCallResults(resultType, call.stackResultArea_, results); + return emitCallArgs(funcType, args, &callState) && + call(&callState, desc, callee, argTypes, address) && + collectCallResults(resultType, callState.stackResultArea, results); } - [[nodiscard]] bool callImport(unsigned instanceDataOffset, - uint32_t lineOrBytecode, - const CallCompileState& call, - const FuncType& funcType, DefVector* results) { + [[nodiscard]] + bool callImport(unsigned instanceDataOffset, uint32_t lineOrBytecode, + const FuncType& funcType, const DefVector& args, + DefVector* results) { MOZ_ASSERT(!inDeadCode()); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Import); + CallCompileState callState; + CallSiteDesc desc(lineOrBytecode, rootCompiler_.inlinedCallerOffsetsIndex(), + CallSiteKind::Import); auto callee = CalleeDesc::import(instanceDataOffset); - ArgTypeVector args(funcType); + ArgTypeVector argTypes(funcType); ResultType resultType = ResultType::Vector(funcType.results()); - if (!catchableCall(desc, callee, call.regArgs_, args)) { - return false; - } - return collectCallResults(resultType, call.stackResultArea_, results); + return emitCallArgs(funcType, args, &callState) && + call(&callState, desc, callee, argTypes) && + collectCallResults(resultType, callState.stackResultArea, results); } - [[nodiscard]] bool builtinCall(const SymbolicAddressSignature& builtin, - uint32_t lineOrBytecode, - const CallCompileState& call, - MDefinition** def) { + [[nodiscard]] + bool builtinCall(CallCompileState* callState, + const SymbolicAddressSignature& builtin, + uint32_t lineOrBytecode, MDefinition** result) { if (inDeadCode()) { - *def = nullptr; + *result = nullptr; return true; } MOZ_ASSERT(builtin.failureMode == FailureMode::Infallible); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Symbolic); + CallSiteDesc desc(lineOrBytecode, rootCompiler_.inlinedCallerOffsetsIndex(), + CallSiteKind::Symbolic); auto callee = CalleeDesc::builtin(builtin.identity); - auto* ins = MWasmCallUncatchable::New(alloc(), desc, callee, call.regArgs_, - StackArgAreaSizeUnaligned(builtin)); + + auto* ins = + MWasmCallUncatchable::New(alloc(), desc, callee, callState->regArgs, + StackArgAreaSizeUnaligned(builtin)); if (!ins) { return false; } - curBlock_->add(ins); - return collectUnaryCallResult(builtin.retType, def); + return collectUnaryCallResult(builtin.retType, result); } - [[nodiscard]] bool builtinInstanceMethodCall( - const SymbolicAddressSignature& builtin, uint32_t lineOrBytecode, - const CallCompileState& call, MDefinition** def = nullptr) { - MOZ_ASSERT_IF(!def, builtin.retType == MIRType::None); + [[nodiscard]] + bool builtinCall1(const SymbolicAddressSignature& builtin, + uint32_t lineOrBytecode, MDefinition* arg, + MDefinition** result) { + CallCompileState callState; + return passCallArg(arg, builtin.argTypes[0], &callState) && + finishCallArgs(&callState) && + builtinCall(&callState, builtin, lineOrBytecode, result); + } + + [[nodiscard]] + bool builtinCall2(const SymbolicAddressSignature& builtin, + uint32_t lineOrBytecode, MDefinition* arg1, + MDefinition* arg2, MDefinition** result) { + CallCompileState callState; + return passCallArg(arg1, builtin.argTypes[0], &callState) && + passCallArg(arg2, builtin.argTypes[1], &callState) && + finishCallArgs(&callState) && + builtinCall(&callState, builtin, lineOrBytecode, result); + } + + [[nodiscard]] + bool builtinCall5(const SymbolicAddressSignature& builtin, + uint32_t lineOrBytecode, MDefinition* arg1, + MDefinition* arg2, MDefinition* arg3, MDefinition* arg4, + MDefinition* arg5, MDefinition** result) { + CallCompileState callState; + return passCallArg(arg1, builtin.argTypes[0], &callState) && + passCallArg(arg2, builtin.argTypes[1], &callState) && + passCallArg(arg3, builtin.argTypes[2], &callState) && + passCallArg(arg4, builtin.argTypes[3], &callState) && + passCallArg(arg5, builtin.argTypes[4], &callState) && + finishCallArgs(&callState) && + builtinCall(&callState, builtin, lineOrBytecode, result); + } + + [[nodiscard]] + bool builtinCall6(const SymbolicAddressSignature& builtin, + uint32_t lineOrBytecode, MDefinition* arg1, + MDefinition* arg2, MDefinition* arg3, MDefinition* arg4, + MDefinition* arg5, MDefinition* arg6, + MDefinition** result) { + CallCompileState callState; + return passCallArg(arg1, builtin.argTypes[0], &callState) && + passCallArg(arg2, builtin.argTypes[1], &callState) && + passCallArg(arg3, builtin.argTypes[2], &callState) && + passCallArg(arg4, builtin.argTypes[3], &callState) && + passCallArg(arg5, builtin.argTypes[4], &callState) && + passCallArg(arg6, builtin.argTypes[5], &callState) && + finishCallArgs(&callState) && + builtinCall(&callState, builtin, lineOrBytecode, result); + } + + [[nodiscard]] + bool instanceCall(CallCompileState* callState, + const SymbolicAddressSignature& builtin, + uint32_t lineOrBytecode, MDefinition** result = nullptr) { + MOZ_ASSERT_IF(!result, builtin.retType == MIRType::None); if (inDeadCode()) { - if (def) { - *def = nullptr; + if (result) { + *result = nullptr; } return true; } - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Symbolic); - MWasmCallTryDesc tryDesc; - if (!beginTryCall(&tryDesc)) { + CallSiteDesc desc(lineOrBytecode, rootCompiler_.inlinedCallerOffsetsIndex(), + CallSiteKind::Symbolic); + if (builtin.failureMode != FailureMode::Infallible && + !beginCatchableCall(callState)) { return false; } MInstruction* ins; - if (tryDesc.inTry) { + if (callState->isCatchable()) { ins = MWasmCallCatchable::NewBuiltinInstanceMethodCall( alloc(), desc, builtin.identity, builtin.failureMode, - call.instanceArg_, call.regArgs_, StackArgAreaSizeUnaligned(builtin), - tryDesc); + callState->instanceArg, callState->regArgs, + StackArgAreaSizeUnaligned(builtin), callState->tryNoteIndex, + callState->fallthroughBlock, callState->prePadBlock); } else { ins = MWasmCallUncatchable::NewBuiltinInstanceMethodCall( alloc(), desc, builtin.identity, builtin.failureMode, - call.instanceArg_, call.regArgs_, StackArgAreaSizeUnaligned(builtin)); + callState->instanceArg, callState->regArgs, + StackArgAreaSizeUnaligned(builtin)); } if (!ins) { return false; } curBlock_->add(ins); - if (!finishTryCall(&tryDesc)) { + if (!finishCatchableCall(callState)) { return false; } - if (!def) { + if (!result) { return true; } - return collectUnaryCallResult(builtin.retType, def); + return collectUnaryCallResult(builtin.retType, result); } - [[nodiscard]] bool stackSwitch(MDefinition* suspender, MDefinition* fn, - MDefinition* data, StackSwitchKind kind) { + /*********************************************** Instance call helpers ***/ + + // Do not call this function directly -- it offers no protection against + // mis-counting of arguments. Instead call one of + // ::emitInstanceCall{0,1,2,3,4,5,6}. + // + // Emits a call to the Instance function indicated by `callee`. This is + // assumed to take an Instance pointer as its first argument. The remaining + // args are taken from `args`, which is assumed to hold `numArgs` entries. + // If `result` is non-null, the MDefinition* holding the return value is + // written to `*result`. + [[nodiscard]] + bool emitInstanceCallN(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition** args, size_t numArgs, + MDefinition** result = nullptr) { + // Check that the first formal parameter is plausibly an Instance pointer. + MOZ_ASSERT(callee.numArgs > 0); + MOZ_ASSERT(callee.argTypes[0] == MIRType::Pointer); + // Check we agree on the number of args. + MOZ_ASSERT(numArgs + 1 /* the instance pointer */ == callee.numArgs); + // Check we agree on whether a value is returned. + MOZ_ASSERT((result == nullptr) == (callee.retType == MIRType::None)); + + // If we are in dead code, it can happen that some of the `args` entries + // are nullptr, which will look like an OOM to the logic below. So exit + // at this point. `passInstanceCallArg`, `passCallArg`, `finishCall` and + // `instanceCall` all do nothing in dead code, so it's valid + // to exit here. + if (inDeadCode()) { + if (result) { + *result = nullptr; + } + return true; + } + + // Check all args for signs of OOMness before attempting to allocating any + // more memory. + for (size_t i = 0; i < numArgs; i++) { + if (!args[i]) { + if (result) { + *result = nullptr; + } + return false; + } + } + + // Finally, construct the call. + CallCompileState callState; + if (!passInstanceCallArg(callee.argTypes[0], &callState)) { + return false; + } + for (size_t i = 0; i < numArgs; i++) { + if (!passCallArg(args[i], callee.argTypes[i + 1], &callState)) { + return false; + } + } + if (!finishCallArgs(&callState)) { + return false; + } + return instanceCall(&callState, callee, lineOrBytecode, result); + } + + [[nodiscard]] + bool emitInstanceCall0(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition** result = nullptr) { + MDefinition** args = nullptr; + return emitInstanceCallN(lineOrBytecode, callee, args, 0, result); + } + [[nodiscard]] + bool emitInstanceCall1(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition* arg1, MDefinition** result = nullptr) { + MDefinition* args[1] = {arg1}; + return emitInstanceCallN(lineOrBytecode, callee, args, 1, result); + } + [[nodiscard]] + bool emitInstanceCall2(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition* arg1, MDefinition* arg2, + MDefinition** result = nullptr) { + MDefinition* args[2] = {arg1, arg2}; + return emitInstanceCallN(lineOrBytecode, callee, args, 2, result); + } + [[nodiscard]] + bool emitInstanceCall3(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition* arg1, MDefinition* arg2, + MDefinition* arg3, MDefinition** result = nullptr) { + MDefinition* args[3] = {arg1, arg2, arg3}; + return emitInstanceCallN(lineOrBytecode, callee, args, 3, result); + } + [[nodiscard]] + bool emitInstanceCall4(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition* arg1, MDefinition* arg2, + MDefinition* arg3, MDefinition* arg4, + MDefinition** result = nullptr) { + MDefinition* args[4] = {arg1, arg2, arg3, arg4}; + return emitInstanceCallN(lineOrBytecode, callee, args, 4, result); + } + [[nodiscard]] + bool emitInstanceCall5(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition* arg1, MDefinition* arg2, + MDefinition* arg3, MDefinition* arg4, + MDefinition* arg5, MDefinition** result = nullptr) { + MDefinition* args[5] = {arg1, arg2, arg3, arg4, arg5}; + return emitInstanceCallN(lineOrBytecode, callee, args, 5, result); + } + [[nodiscard]] + bool emitInstanceCall6(uint32_t lineOrBytecode, + const SymbolicAddressSignature& callee, + MDefinition* arg1, MDefinition* arg2, + MDefinition* arg3, MDefinition* arg4, + MDefinition* arg5, MDefinition* arg6, + MDefinition** result = nullptr) { + MDefinition* args[6] = {arg1, arg2, arg3, arg4, arg5, arg6}; + return emitInstanceCallN(lineOrBytecode, callee, args, 6, result); + } + + [[nodiscard]] MDefinition* stackSwitch(MDefinition* suspender, + MDefinition* fn, MDefinition* data, + StackSwitchKind kind) { MOZ_ASSERT(!inDeadCode()); MInstruction* ins; @@ -2472,50 +3224,55 @@ class FunctionCompiler { ins = MWasmStackSwitchToSuspendable::New(alloc(), suspender, fn, data); break; case StackSwitchKind::ContinueOnSuspendable: - ins = MWasmStackContinueOnSuspendable::New(alloc(), suspender); + ins = MWasmStackContinueOnSuspendable::New(alloc(), suspender, data); break; } if (!ins) { - return false; + return nullptr; } curBlock_->add(ins); - return true; + return ins; } -#ifdef ENABLE_WASM_GC - [[nodiscard]] bool callRef(const FuncType& funcType, MDefinition* ref, - uint32_t lineOrBytecode, - const CallCompileState& call, DefVector* results) { + [[nodiscard]] + bool callRef(const FuncType& funcType, MDefinition* ref, + uint32_t lineOrBytecode, const DefVector& args, + DefVector* results) { MOZ_ASSERT(!inDeadCode()); + CallCompileState callState; CalleeDesc callee = CalleeDesc::wasmFuncRef(); - - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::FuncRef); - ArgTypeVector args(funcType); + CallSiteDesc desc(lineOrBytecode, rootCompiler_.inlinedCallerOffsetsIndex(), + CallSiteKind::FuncRef); + ArgTypeVector argTypes(funcType); ResultType resultType = ResultType::Vector(funcType.results()); - if (!catchableCall(desc, callee, call.regArgs_, args, ref)) { - return false; - } - return collectCallResults(resultType, call.stackResultArea_, results); + return emitCallArgs(funcType, args, &callState) && + call(&callState, desc, callee, argTypes, ref) && + collectCallResults(resultType, callState.stackResultArea, results); } -# ifdef ENABLE_WASM_TAIL_CALLS - [[nodiscard]] bool returnCallRef(const FuncType& funcType, MDefinition* ref, - uint32_t lineOrBytecode, - const CallCompileState& call, - DefVector* results) { + [[nodiscard]] + bool returnCallRef(const FuncType& funcType, MDefinition* ref, + uint32_t lineOrBytecode, const DefVector& args, + DefVector* results) { MOZ_ASSERT(!inDeadCode()); + MOZ_ASSERT(!isInlined()); + CallCompileState callState; + callState.returnCall = true; CalleeDesc callee = CalleeDesc::wasmFuncRef(); + CallSiteDesc desc(lineOrBytecode, CallSiteKind::FuncRef); + ArgTypeVector argTypes(funcType); - CallSiteDesc desc(lineOrBytecode, CallSiteDesc::FuncRef); - ArgTypeVector args(funcType); + if (!emitCallArgs(funcType, args, &callState)) { + return false; + } - auto* ins = MWasmReturnCall::New(alloc(), desc, callee, call.regArgs_, - StackArgAreaSizeUnaligned(args), ref); + auto* ins = MWasmReturnCall::New(alloc(), desc, callee, callState.regArgs, + StackArgAreaSizeUnaligned(argTypes), ref); if (!ins) { return false; } @@ -2524,19 +3281,147 @@ class FunctionCompiler { return true; } -# endif // ENABLE_WASM_TAIL_CALLS + [[nodiscard]] MDefinition* stringCast(MDefinition* string) { + auto* ins = MWasmTrapIfAnyRefIsNotJSString::New( + alloc(), string, wasm::Trap::BadCast, trapSiteDesc()); + if (!ins) { + return ins; + } + curBlock_->add(ins); + return ins; + } -#endif // ENABLE_WASM_GC + [[nodiscard]] MDefinition* stringTest(MDefinition* string) { + auto* ins = MWasmAnyRefIsJSString::New(alloc(), string); + if (!ins) { + return nullptr; + } + curBlock_->add(ins); + return ins; + } + + [[nodiscard]] MDefinition* stringLength(MDefinition* string) { + auto* ins = MWasmAnyRefJSStringLength::New( + alloc(), string, wasm::Trap::BadCast, trapSiteDesc()); + if (!ins) { + return nullptr; + } + curBlock_->add(ins); + return ins; + } + + [[nodiscard]] bool dispatchInlineBuiltinModuleFunc( + const BuiltinModuleFunc& builtinModuleFunc, const DefVector& params) { + BuiltinInlineOp inlineOp = builtinModuleFunc.inlineOp(); + MOZ_ASSERT(inlineOp != BuiltinInlineOp::None); + switch (inlineOp) { + case BuiltinInlineOp::StringCast: { + MOZ_ASSERT(params.length() == 1); + MDefinition* string = params[0]; + MDefinition* cast = stringCast(string); + if (!cast) { + return false; + } + iter().setResult(string); + return true; + } + case BuiltinInlineOp::StringTest: { + MOZ_ASSERT(params.length() == 1); + MDefinition* string = params[0]; + MDefinition* test = stringTest(string); + if (!test) { + return false; + } + iter().setResult(test); + return true; + } + case BuiltinInlineOp::StringLength: { + MOZ_ASSERT(params.length() == 1); + MDefinition* string = params[0]; + MDefinition* length = stringLength(string); + if (!length) { + return false; + } + iter().setResult(length); + return true; + } + case BuiltinInlineOp::None: + case BuiltinInlineOp::Limit: + break; + } + MOZ_CRASH(); + } + + [[nodiscard]] bool callBuiltinModuleFunc( + const BuiltinModuleFunc& builtinModuleFunc, const DefVector& params) { + MOZ_ASSERT(!inDeadCode()); + + BuiltinInlineOp inlineOp = builtinModuleFunc.inlineOp(); + if (inlineOp != BuiltinInlineOp::None) { + return dispatchInlineBuiltinModuleFunc(builtinModuleFunc, params); + } + + // It's almost possible to use FunctionCompiler::emitInstanceCallN here. + // Unfortunately not currently possible though, since ::emitInstanceCallN + // expects an array of arguments along with a size, and that's not what is + // available here. It would be possible if we were prepared to copy + // `builtinModuleFunc->params` into a fixed-sized (16 element?) array, add + // `memoryBase`, and make the call. + const SymbolicAddressSignature& callee = *builtinModuleFunc.sig(); + + CallCompileState callState; + if (!passInstanceCallArg(callee.argTypes[0], &callState) || + !passCallArgs(params, builtinModuleFunc.funcType()->args(), + &callState)) { + return false; + } + + if (builtinModuleFunc.usesMemory()) { + if (!passCallArg(memoryBase(0), MIRType::Pointer, &callState)) { + return false; + } + } + + if (!finishCallArgs(&callState)) { + return false; + } + + bool hasResult = !builtinModuleFunc.funcType()->results().empty(); + MDefinition* result = nullptr; + MDefinition** resultOutParam = hasResult ? &result : nullptr; + if (!instanceCall(&callState, callee, readBytecodeOffset(), + resultOutParam)) { + return false; + } + + if (hasResult) { + iter().setResult(result); + } + return true; + } /*********************************************** Control flow generation */ inline bool inDeadCode() const { return curBlock_ == nullptr; } - [[nodiscard]] bool returnValues(const DefVector& values) { + [[nodiscard]] bool returnValues(DefVector&& values) { if (inDeadCode()) { return true; } + // If we're inlined into another function, we must accumulate the returns + // so that they can be patched into the caller function. + if (isInlined()) { + MGoto* jump = MGoto::New(alloc()); + if (!jump) { + return false; + } + curBlock_->end(jump); + curBlock_ = nullptr; + return pendingInlineReturns_.emplaceBack( + PendingInlineReturn(jump, std::move(values))); + } + if (values.empty()) { curBlock_->end(MWasmReturnVoid::New(alloc(), instancePointer_)); } else { @@ -2554,17 +3439,9 @@ class FunctionCompiler { const ABIResult& result = iter.cur(); if (result.onStack()) { MOZ_ASSERT(iter.remaining() > 1); - if (result.type().isRefRepr()) { - auto* store = MWasmStoreRef::New( - alloc(), instancePointer_, stackResultPointer_, - result.stackOffset(), values[i], AliasSet::WasmStackResult, - WasmPreBarrierKind::None); - curBlock_->add(store); - } else { - auto* store = MWasmStoreStackResult::New( - alloc(), stackResultPointer_, result.stackOffset(), values[i]); - curBlock_->add(store); - } + auto* store = MWasmStoreStackResult::New( + alloc(), stackResultPointer_, result.stackOffset(), values[i]); + curBlock_->add(store); } else { MOZ_ASSERT(iter.remaining() == 1); MOZ_ASSERT(i + 1 == values.length()); @@ -2583,7 +3460,7 @@ class FunctionCompiler { } auto* ins = - MWasmTrap::New(alloc(), wasm::Trap::Unreachable, bytecodeOffset()); + MWasmTrap::New(alloc(), wasm::Trap::Unreachable, trapSiteDesc()); curBlock_->end(ins); curBlock_ = nullptr; } @@ -2719,37 +3596,37 @@ class FunctionCompiler { } [[nodiscard]] bool startBlock() { - MOZ_ASSERT_IF(blockDepth_ < pendingBlocks_.length(), - pendingBlocks_[blockDepth_].patches.empty()); - blockDepth_++; + MOZ_ASSERT_IF(pendingBlockDepth_ < pendingBlocks_.length(), + pendingBlocks_[pendingBlockDepth_].patches.empty()); + pendingBlockDepth_++; return true; } [[nodiscard]] bool finishBlock(DefVector* defs) { - MOZ_ASSERT(blockDepth_); - uint32_t topLabel = --blockDepth_; + MOZ_ASSERT(pendingBlockDepth_); + uint32_t topLabel = --pendingBlockDepth_; return bindBranches(topLabel, defs); } [[nodiscard]] bool startLoop(MBasicBlock** loopHeader, size_t paramCount) { *loopHeader = nullptr; - blockDepth_++; - loopDepth_++; + pendingBlockDepth_++; + rootCompiler_.startLoop(); if (inDeadCode()) { return true; } // Create the loop header. - MOZ_ASSERT(curBlock_->loopDepth() == loopDepth_ - 1); + MOZ_ASSERT(curBlock_->loopDepth() == rootCompiler_.loopDepth() - 1); *loopHeader = MBasicBlock::New(mirGraph(), info(), curBlock_, MBasicBlock::PENDING_LOOP_HEADER); if (!*loopHeader) { return false; } - (*loopHeader)->setLoopDepth(loopDepth_); + (*loopHeader)->setLoopDepth(rootCompiler_.loopDepth()); mirGraph().addBlock(*loopHeader); curBlock_->end(MGoto::New(alloc(), *loopHeader)); @@ -2757,6 +3634,9 @@ class FunctionCompiler { if (!iter().getResults(paramCount, &loopParams)) { return false; } + + // Eagerly create a phi for all loop params. setLoopBackedge will remove + // any that were not necessary. for (size_t i = 0; i < paramCount; i++) { MPhi* phi = MPhi::New(alloc(), loopParams[i]->type()); if (!phi) { @@ -2796,7 +3676,16 @@ class FunctionCompiler { return false; } - // Flag all redundant phis as unused. + // Entering a loop will eagerly create a phi node for all locals and loop + // params. Now that we've closed the loop we can check which phi nodes + // were actually needed by checking if the SSA definition flowing into the + // loop header (operand 0) is different than the SSA definition coming from + // the loop backedge (operand 1). If they are the same definition, the phi + // is redundant and can be removed. + // + // To do this we mark all redundant phis as 'unused', then remove the phi's + // from places in ourself the phis may have flowed into, then replace all + // uses of the phi's in the MIR graph with the original SSA definition. for (MPhiIterator phi = loopEntry->phisBegin(); phi != loopEntry->phisEnd(); phi++) { MOZ_ASSERT(phi->numOperands() == 2); @@ -2840,13 +3729,26 @@ class FunctionCompiler { } } } - for (MControlInstruction* patch : bodyDelegatePadPatches_) { + for (MControlInstruction* patch : bodyRethrowPadPatches_) { MBasicBlock* block = patch->block(); if (block->loopDepth() >= loopEntry->loopDepth()) { fixupRedundantPhis(block); } } + // If we're inlined into another function we are accumulating return values + // in a vector, search through the results to see if any refer to a + // redundant phi. + for (PendingInlineReturn& pendingReturn : pendingInlineReturns_) { + for (uint32_t resultIndex = 0; + resultIndex < pendingReturn.results.length(); resultIndex++) { + MDefinition** pendingResult = &pendingReturn.results[resultIndex]; + if ((*pendingResult)->isUnused()) { + *pendingResult = (*pendingResult)->toPhi()->getOperand(0); + } + } + } + // Discard redundant phis and add to the free list. for (MPhiIterator phi = loopEntry->phisBegin(); phi != loopEntry->phisEnd();) { @@ -2866,17 +3768,17 @@ class FunctionCompiler { public: [[nodiscard]] bool closeLoop(MBasicBlock* loopHeader, DefVector* loopResults) { - MOZ_ASSERT(blockDepth_ >= 1); - MOZ_ASSERT(loopDepth_); + MOZ_ASSERT(pendingBlockDepth_ >= 1); + MOZ_ASSERT(rootCompiler_.loopDepth()); - uint32_t headerLabel = blockDepth_ - 1; + uint32_t headerLabel = pendingBlockDepth_ - 1; if (!loopHeader) { MOZ_ASSERT(inDeadCode()); MOZ_ASSERT(headerLabel >= pendingBlocks_.length() || pendingBlocks_[headerLabel].patches.empty()); - blockDepth_--; - loopDepth_--; + pendingBlockDepth_--; + rootCompiler_.closeLoop(); return true; } @@ -2896,7 +3798,7 @@ class FunctionCompiler { return false; } - MOZ_ASSERT(loopHeader->loopDepth() == loopDepth_); + MOZ_ASSERT(loopHeader->loopDepth() == rootCompiler_.loopDepth()); if (curBlock_) { // We're on the loop backedge block, created by bindBranches. @@ -2908,7 +3810,7 @@ class FunctionCompiler { return false; } - MOZ_ASSERT(curBlock_->loopDepth() == loopDepth_); + MOZ_ASSERT(curBlock_->loopDepth() == rootCompiler_.loopDepth()); curBlock_->end(MGoto::New(alloc(), loopHeader)); if (!setLoopBackedge(loopHeader, loopBody, curBlock_, backedgeValues.length())) { @@ -2918,10 +3820,10 @@ class FunctionCompiler { curBlock_ = loopBody; - loopDepth_--; + rootCompiler_.closeLoop(); // If the loop depth still at the inner loop body, correct it. - if (curBlock_ && curBlock_->loopDepth() != loopDepth_) { + if (curBlock_ && curBlock_->loopDepth() != rootCompiler_.loopDepth()) { MBasicBlock* out; if (!goToNewBlock(curBlock_, &out)) { return false; @@ -2929,15 +3831,15 @@ class FunctionCompiler { curBlock_ = out; } - blockDepth_ -= 1; + pendingBlockDepth_ -= 1; return inDeadCode() || popPushedDefs(loopResults); } [[nodiscard]] bool addControlFlowPatch( MControlInstruction* ins, uint32_t relative, uint32_t index, BranchHint branchHint = BranchHint::Invalid) { - MOZ_ASSERT(relative < blockDepth_); - uint32_t absolute = blockDepth_ - 1 - relative; + MOZ_ASSERT(relative < pendingBlockDepth_); + uint32_t absolute = pendingBlockDepth_ - 1 - relative; if (absolute >= pendingBlocks_.length() && !pendingBlocks_.resize(absolute + 1)) { @@ -3026,7 +3928,7 @@ class FunctionCompiler { } for (size_t i = 0; i < numCases; i++) { - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } @@ -3065,42 +3967,74 @@ class FunctionCompiler { /********************************************************** Exceptions ***/ - bool inTryBlockFrom(uint32_t fromRelativeDepth, uint32_t* relativeDepth) { - return iter().controlFindInnermostFrom( - [](LabelKind kind, const Control& control) { - return control.tryControl != nullptr && control.tryControl->inBody; - }, - fromRelativeDepth, relativeDepth); - } - - bool inTryBlock(uint32_t* relativeDepth) { - return inTryBlockFrom(0, relativeDepth); - } - - bool inTryCode() { + bool inTryBlockFrom(uint32_t fromRelativeDepth, + uint32_t* tryRelativeDepth) const { uint32_t relativeDepth; - return inTryBlock(&relativeDepth); + if (iter_.controlFindInnermostFrom( + [](LabelKind kind, const Control& control) { + return control.tryControl != nullptr && + control.tryControl->inBody; + }, + fromRelativeDepth, &relativeDepth)) { + *tryRelativeDepth = relativeDepth; + return true; + } + + if (callerCompiler_ && callerCompiler_->inTryCode()) { + *tryRelativeDepth = iter_.controlStackDepth() - 1; + return true; + } + + return false; + } + + bool inTryBlockFrom(uint32_t fromRelativeDepth, + ControlInstructionVector** landingPadPatches) { + uint32_t tryRelativeDepth; + if (!inTryBlockFrom(fromRelativeDepth, &tryRelativeDepth)) { + return false; + } + + if (tryRelativeDepth == iter().controlStackDepth() - 1) { + *landingPadPatches = &bodyRethrowPadPatches_; + } else { + *landingPadPatches = + &iter().controlItem(tryRelativeDepth).tryControl->landingPadPatches; + } + return true; + } + + bool inTryBlock(ControlInstructionVector** landingPadPatches) { + return inTryBlockFrom(0, landingPadPatches); + } + + bool inTryCode() const { + uint32_t tryRelativeDepth; + return inTryBlockFrom(0, &tryRelativeDepth); } MDefinition* loadTag(uint32_t tagIndex) { MWasmLoadInstanceDataField* tag = MWasmLoadInstanceDataField::New( alloc(), MIRType::WasmAnyRef, - moduleEnv_.offsetOfTagInstanceData(tagIndex), true, instancePointer_); + codeMeta().offsetOfTagInstanceData(tagIndex), true, instancePointer_); curBlock_->add(tag); return tag; } - void loadPendingExceptionState(MInstruction** exception, MInstruction** tag) { - *exception = MWasmLoadInstance::New( + void loadPendingExceptionState(MDefinition** pendingException, + MDefinition** pendingExceptionTag) { + auto* exception = MWasmLoadInstance::New( alloc(), instancePointer_, wasm::Instance::offsetOfPendingException(), MIRType::WasmAnyRef, AliasSet::Load(AliasSet::WasmPendingException)); - curBlock_->add(*exception); + curBlock_->add(exception); + *pendingException = exception; - *tag = MWasmLoadInstance::New( + auto* tag = MWasmLoadInstance::New( alloc(), instancePointer_, wasm::Instance::offsetOfPendingExceptionTag(), MIRType::WasmAnyRef, AliasSet::Load(AliasSet::WasmPendingException)); - curBlock_->add(*tag); + curBlock_->add(tag); + *pendingExceptionTag = tag; } [[nodiscard]] bool setPendingExceptionState(MDefinition* exception, @@ -3113,7 +4047,8 @@ class FunctionCompiler { alloc(), instancePointer_, exceptionAddr, /*valueOffset=*/0, exception, AliasSet::WasmPendingException, WasmPreBarrierKind::Normal); curBlock_->add(setException); - if (!postBarrierPrecise(/*lineOrBytecode=*/0, exceptionAddr, exception)) { + if (!postBarrierEdgePrecise(/*lineOrBytecode=*/0, exceptionAddr, + exception)) { return false; } @@ -3125,19 +4060,14 @@ class FunctionCompiler { alloc(), instancePointer_, exceptionTagAddr, /*valueOffset=*/0, tag, AliasSet::WasmPendingException, WasmPreBarrierKind::Normal); curBlock_->add(setExceptionTag); - return postBarrierPrecise(/*lineOrBytecode=*/0, exceptionTagAddr, tag); + return postBarrierEdgePrecise(/*lineOrBytecode=*/0, exceptionTagAddr, tag); } - [[nodiscard]] bool addPadPatch(MControlInstruction* ins, - size_t relativeTryDepth) { - Control& control = iter().controlItem(relativeTryDepth); - return control.tryControl->landingPadPatches.emplaceBack(ins); - } - - [[nodiscard]] bool endWithPadPatch(uint32_t relativeTryDepth) { + [[nodiscard]] bool endWithPadPatch( + ControlInstructionVector* tryLandingPadPatches) { MGoto* jumpToLandingPad = MGoto::New(alloc()); curBlock_->end(jumpToLandingPad); - return addPadPatch(jumpToLandingPad, relativeTryDepth); + return tryLandingPadPatches->emplaceBack(jumpToLandingPad); } [[nodiscard]] bool delegatePadPatches(const ControlInstructionVector& patches, @@ -3148,14 +4078,9 @@ class FunctionCompiler { // Find where we are delegating the pad patches to. ControlInstructionVector* targetPatches; - uint32_t targetRelativeDepth; - if (inTryBlockFrom(relativeDepth, &targetRelativeDepth)) { - targetPatches = &iter() - .controlItem(targetRelativeDepth) - .tryControl->landingPadPatches; - } else { - MOZ_ASSERT(relativeDepth <= blockDepth_ - 1); - targetPatches = &bodyDelegatePadPatches_; + if (!inTryBlockFrom(relativeDepth, &targetPatches)) { + MOZ_ASSERT(relativeDepth <= pendingBlockDepth_ - 1); + targetPatches = &bodyRethrowPadPatches_; } // Append the delegate's pad patches to the target's. @@ -3167,79 +4092,71 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool beginTryCall(MWasmCallTryDesc* call) { - call->inTry = inTryBlock(&call->relativeTryDepth); - if (!call->inTry) { + [[nodiscard]] + bool beginCatchableCall(CallCompileState* callState) { + if (!inTryBlock(&callState->tryLandingPadPatches)) { + MOZ_ASSERT(!callState->isCatchable()); return true; } + MOZ_ASSERT(callState->isCatchable()); + // Allocate a try note - if (!tryNotes_.append(wasm::TryNote())) { + if (!rootCompiler_.addTryNote(&callState->tryNoteIndex)) { return false; } - call->tryNoteIndex = tryNotes_.length() - 1; + // Allocate blocks for fallthrough and exceptions - return newBlock(curBlock_, &call->fallthroughBlock) && - newBlock(curBlock_, &call->prePadBlock); + return newBlock(curBlock_, &callState->fallthroughBlock) && + newBlock(curBlock_, &callState->prePadBlock); } - [[nodiscard]] bool finishTryCall(MWasmCallTryDesc* call) { - if (!call->inTry) { + [[nodiscard]] + bool finishCatchableCall(CallCompileState* callState) { + if (!callState->tryLandingPadPatches) { return true; } // Switch to the prePadBlock MBasicBlock* callBlock = curBlock_; - curBlock_ = call->prePadBlock; + curBlock_ = callState->prePadBlock; // Mark this as the landing pad for the call - curBlock_->add( - MWasmCallLandingPrePad::New(alloc(), callBlock, call->tryNoteIndex)); + curBlock_->add(MWasmCallLandingPrePad::New(alloc(), callBlock, + callState->tryNoteIndex)); // End with a pending jump to the landing pad - if (!endWithPadPatch(call->relativeTryDepth)) { + if (!endWithPadPatch(callState->tryLandingPadPatches)) { return false; } // Compilation continues in the fallthroughBlock. - curBlock_ = call->fallthroughBlock; + curBlock_ = callState->fallthroughBlock; return true; } - // Create a landing pad for a try block if there are any throwing - // instructions. This is also used for the implicit rethrow landing pad used - // for delegate instructions that target the outermost label. - [[nodiscard]] bool createTryLandingPadIfNeeded( - ControlInstructionVector& landingPadPatches, MBasicBlock** landingPad) { - // If there are no pad-patches for this try control, it means there are no - // instructions in the try code that could throw an exception. In this - // case, all the catches are dead code, and the try code ends up equivalent - // to a plain wasm block. - if (landingPadPatches.empty()) { - *landingPad = nullptr; - return true; - } + // Create a landing pad for a try block. This is also used for the implicit + // rethrow landing pad used for delegate instructions that target the + // outermost label. + [[nodiscard]] + bool createTryLandingPad(ControlInstructionVector& landingPadPatches, + MBasicBlock** landingPad) { + MOZ_ASSERT(!landingPadPatches.empty()); - // Otherwise, if there are (pad-) branches from places in the try code that - // may throw an exception, bind these branches to a new landing pad + // Bind the branches from exception throwing code to a new landing pad // block. This is done similarly to what is done in bindBranches. MControlInstruction* ins = landingPadPatches[0]; MBasicBlock* pred = ins->block(); if (!newBlock(pred, landingPad)) { return false; } - ins->replaceSuccessor(0, *landingPad); + ins->replaceSuccessor(MGoto::TargetIndex, *landingPad); for (size_t i = 1; i < landingPadPatches.length(); i++) { ins = landingPadPatches[i]; pred = ins->block(); if (!(*landingPad)->addPredecessor(alloc(), pred)) { return false; } - ins->replaceSuccessor(0, *landingPad); - } - - // Set up the slots in the landing pad block. - if (!setupLandingPadSlots(landingPad)) { - return false; + ins->replaceSuccessor(MGoto::TargetIndex, *landingPad); } // Clear the now bound pad patches. @@ -3247,17 +4164,26 @@ class FunctionCompiler { return true; } - [[nodiscard]] bool createTryTableLandingPad(TryControl* tryControl) { + [[nodiscard]] + bool createTryTableLandingPad(TryControl* tryControl) { + // If there were no patches, then there were no throwing instructions and + // we don't need to do anything. + if (tryControl->landingPadPatches.empty()) { + return true; + } + + // Create the landing pad block and bind all the throwing instructions MBasicBlock* landingPad; - if (!createTryLandingPadIfNeeded(tryControl->landingPadPatches, - &landingPad)) { + if (!createTryLandingPad(tryControl->landingPadPatches, &landingPad)) { return false; } - // If there is no landing pad created, no exceptions were possibly thrown - // and we don't need to do anything here. - if (!landingPad) { - return true; + // Get the pending exception from the instance + MDefinition* pendingException; + MDefinition* pendingExceptionTag; + if (!consumePendingException(&landingPad, &pendingException, + &pendingExceptionTag)) { + return false; } MBasicBlock* originalBlock = curBlock_; @@ -3265,18 +4191,11 @@ class FunctionCompiler { bool hadCatchAll = false; for (const TryTableCatch& tryTableCatch : tryControl->catches) { - MOZ_ASSERT(numPushed(curBlock_) == 2); - // Handle a catch_all by jumping to the target block if (tryTableCatch.tagIndex == CatchAllIndex) { - // Get the exception from the slots we pushed when adding - // control flow patches. - curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - // Capture the exnref value if we need to DefVector values; - if (tryTableCatch.captureExnRef && !values.append(exception)) { + if (tryTableCatch.captureExnRef && !values.append(pendingException)) { return false; } @@ -3301,16 +4220,12 @@ class FunctionCompiler { return false; } - // Get the exception and its tag from the slots we pushed when adding - // control flow patches. - MDefinition* exceptionTag = curBlock_->pop(); - curBlock_->pop(); - // Branch to the catch block if the exception's tag matches this catch // block's tag. MDefinition* catchTag = loadTag(tryTableCatch.tagIndex); - MDefinition* matchesCatchTag = compare(exceptionTag, catchTag, JSOp::Eq, - MCompare::Compare_WasmAnyRef); + MDefinition* matchesCatchTag = + compare(pendingExceptionTag, catchTag, JSOp::Eq, + MCompare::Compare_WasmAnyRef); curBlock_->end( MTest::New(alloc(), matchesCatchTag, catchBlock, fallthroughBlock)); @@ -3318,18 +4233,13 @@ class FunctionCompiler { // object. curBlock_ = catchBlock; - // Remove the tag and exception slots from the block, they are no - // longer necessary. - curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - MOZ_ASSERT(numPushed(curBlock_) == 0); - // Extract the exception values for the catch block DefVector values; - if (!loadExceptionValues(exception, tryTableCatch.tagIndex, &values)) { + if (!loadExceptionValues(pendingException, tryTableCatch.tagIndex, + &values)) { return false; } - if (tryTableCatch.captureExnRef && !values.append(exception)) { + if (tryTableCatch.captureExnRef && !values.append(pendingException)) { return false; } @@ -3342,12 +4252,7 @@ class FunctionCompiler { // If there was no catch_all, we must rethrow this exception. if (!hadCatchAll) { - MOZ_ASSERT(numPushed(curBlock_) == 2); - MDefinition* tag = curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - MOZ_ASSERT(numPushed(curBlock_) == 0); - - if (!throwFrom(exception, tag)) { + if (!throwFrom(pendingException, pendingExceptionTag)) { return false; } } @@ -3356,30 +4261,26 @@ class FunctionCompiler { return true; } - // Consume the pending exception state from instance, and set up the slots - // of the landing pad with the exception state. - [[nodiscard]] bool setupLandingPadSlots(MBasicBlock** landingPad) { + // Consume the pending exception state from instance. This will clear out the + // previous value. + [[nodiscard]] + bool consumePendingException(MBasicBlock** landingPad, + MDefinition** pendingException, + MDefinition** pendingExceptionTag) { MBasicBlock* prevBlock = curBlock_; curBlock_ = *landingPad; // Load the pending exception and tag - MInstruction* exception; - MInstruction* tag; - loadPendingExceptionState(&exception, &tag); + loadPendingExceptionState(pendingException, pendingExceptionTag); // Clear the pending exception and tag - auto* null = constantNullRef(); + auto* null = constantNullRef(MaybeRefType()); if (!setPendingExceptionState(null, null)) { return false; } - // Push the exception and its tag on the stack to make them available - // to the landing pad blocks. - if (!curBlock_->ensureHasSlots(2)) { - return false; - } - curBlock_->push(exception); - curBlock_->push(tag); + // The landing pad may have changed from loading and clearing the pending + // exception state. *landingPad = curBlock_; curBlock_ = prevBlock; @@ -3389,7 +4290,7 @@ class FunctionCompiler { [[nodiscard]] bool startTry() { Control& control = iter().controlItem(); control.block = curBlock_; - control.tryControl = newTryControl(); + control.tryControl = rootCompiler_.newTryControl(); if (!control.tryControl) { return false; } @@ -3400,7 +4301,7 @@ class FunctionCompiler { [[nodiscard]] bool startTryTable(TryTableCatchVector&& catches) { Control& control = iter().controlItem(); control.block = curBlock_; - control.tryControl = newTryControl(); + control.tryControl = rootCompiler_.newTryControl(); if (!control.tryControl) { return false; } @@ -3454,13 +4355,27 @@ class FunctionCompiler { // If we are switching from the try block, create the landing pad. This is // guaranteed to happen once and only once before processing catch blocks. if (fromKind == LabelKind::Try) { - MBasicBlock* padBlock = nullptr; - if (!createTryLandingPadIfNeeded(control.tryControl->landingPadPatches, - &padBlock)) { - return false; + if (!control.tryControl->landingPadPatches.empty()) { + // Create the landing pad block and bind all the throwing instructions + MBasicBlock* padBlock = nullptr; + if (!createTryLandingPad(control.tryControl->landingPadPatches, + &padBlock)) { + return false; + } + + // Store the pending exception and tag on the control item for future + // use in catch handlers. + if (!consumePendingException( + &padBlock, &control.tryControl->pendingException, + &control.tryControl->pendingExceptionTag)) { + return false; + } + + // Set the control block for this try-catch to the landing pad. + control.block = padBlock; + } else { + control.block = nullptr; } - // Set the control block for this try-catch to the landing pad. - control.block = padBlock; } // If there is no landing pad, then this and following catches are dead @@ -3473,6 +4388,11 @@ class FunctionCompiler { // Switch to the landing pad. curBlock_ = control.block; + // We should have a pending exception and tag if we were able to create a + // landing pad. + MOZ_ASSERT(control.tryControl->pendingException); + MOZ_ASSERT(control.tryControl->pendingExceptionTag); + // Handle a catch_all by immediately jumping to a new block. We require a // new block (as opposed to just emitting the catch_all code in the current // block) because rethrow requires the exception/tag to be present in the @@ -3485,10 +4405,6 @@ class FunctionCompiler { } // Compilation will continue in the catch_all block. curBlock_ = catchAllBlock; - // Remove the tag and exception slots from the block, they are no - // longer necessary. - curBlock_->pop(); - curBlock_->pop(); return true; } @@ -3502,16 +4418,12 @@ class FunctionCompiler { return false; } - // Get the exception and its tag from the slots we pushed when adding - // control flow patches. - MDefinition* exceptionTag = curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - // Branch to the catch block if the exception's tag matches this catch // block's tag. MDefinition* catchTag = loadTag(tagIndex); MDefinition* matchesCatchTag = - compare(exceptionTag, catchTag, JSOp::Eq, MCompare::Compare_WasmAnyRef); + compare(control.tryControl->pendingExceptionTag, catchTag, JSOp::Eq, + MCompare::Compare_WasmAnyRef); curBlock_->end( MTest::New(alloc(), matchesCatchTag, catchBlock, fallthroughBlock)); @@ -3522,14 +4434,10 @@ class FunctionCompiler { // object. curBlock_ = catchBlock; - // Remove the tag and exception slots from the block, they are no - // longer necessary. - curBlock_->pop(); - exception = curBlock_->pop(); - // Extract the exception values for the catch block DefVector values; - if (!loadExceptionValues(exception, tagIndex, &values)) { + if (!loadExceptionValues(control.tryControl->pendingException, tagIndex, + &values)) { return false; } iter().setResults(values.length(), values); @@ -3538,14 +4446,15 @@ class FunctionCompiler { [[nodiscard]] bool loadExceptionValues(MDefinition* exception, uint32_t tagIndex, DefVector* values) { - SharedTagType tagType = moduleEnv().tags[tagIndex].type; + SharedTagType tagType = codeMeta().tags[tagIndex].type; const ValTypeVector& params = tagType->argTypes(); const TagOffsetVector& offsets = tagType->argOffsets(); // Get the data pointer from the exception object auto* data = MWasmLoadField::New( - alloc(), exception, WasmExceptionObject::offsetOfData(), - MIRType::Pointer, MWideningOp::None, AliasSet::Load(AliasSet::Any)); + alloc(), exception, nullptr, WasmExceptionObject::offsetOfData(), + mozilla::Nothing(), MIRType::Pointer, MWideningOp::None, + AliasSet::Load(AliasSet::Any)); if (!data) { return false; } @@ -3558,12 +4467,14 @@ class FunctionCompiler { // Load each value from the data pointer for (size_t i = 0; i < params.length(); i++) { - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } - auto* load = MWasmLoadFieldKA::New( - alloc(), exception, data, offsets[i], params[i].toMIRType(), - MWideningOp::None, AliasSet::Load(AliasSet::Any)); + auto* load = + MWasmLoadField::New(alloc(), data, exception, offsets[i], + mozilla::Nothing(), params[i].toMIRType(), + MWideningOp::None, AliasSet::Load(AliasSet::Any), + mozilla::Nothing(), params[i].toMaybeRefType()); if (!load || !values->append(load)) { return false; } @@ -3578,7 +4489,7 @@ class FunctionCompiler { case LabelKind::Try: { // This is a catchless try, we must delegate all throwing instructions // to the nearest enclosing try block if one exists, or else to the - // body block which will handle it in emitBodyDelegateThrowPad. We + // body block which will handle it in emitBodyRethrowPad. We // specify a relativeDepth of '1' to delegate outside of the still // active try block. uint32_t relativeDepth = 1; @@ -3596,9 +4507,8 @@ class FunctionCompiler { if (padBlock) { MBasicBlock* prevBlock = curBlock_; curBlock_ = padBlock; - MDefinition* tag = curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - if (!throwFrom(exception, tag)) { + if (!throwFrom(control.tryControl->pendingException, + control.tryControl->pendingExceptionTag)) { return false; } curBlock_ = prevBlock; @@ -3629,27 +4539,44 @@ class FunctionCompiler { return finishBlock(defs); } - [[nodiscard]] bool emitBodyDelegateThrowPad(Control& control) { + [[nodiscard]] bool emitBodyRethrowPad(Control& control) { + // If there are no throwing instructions pending, we don't need to do + // anything + if (bodyRethrowPadPatches_.empty()) { + return true; + } + // Create a landing pad for any throwing instructions MBasicBlock* padBlock; - if (!createTryLandingPadIfNeeded(bodyDelegatePadPatches_, &padBlock)) { + if (!createTryLandingPad(bodyRethrowPadPatches_, &padBlock)) { return false; } - // If no landing pad was necessary, then we don't need to do anything here - if (!padBlock) { + // If we're inlined into another function, we save the landing pad to be + // linked later directly to our caller's landing pad. See + // `finishedInlinedCallDirect`. + if (callerCompiler_ && callerCompiler_->inTryCode()) { + pendingInlineCatchBlock_ = padBlock; return true; } + // Otherwise we need to grab the pending exception and rethrow it. + MDefinition* pendingException; + MDefinition* pendingExceptionTag; + if (!consumePendingException(&padBlock, &pendingException, + &pendingExceptionTag)) { + return false; + } + // Switch to the landing pad and rethrow the exception MBasicBlock* prevBlock = curBlock_; curBlock_ = padBlock; - MDefinition* tag = curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - if (!throwFrom(exception, tag)) { + if (!throwFrom(pendingException, pendingExceptionTag)) { return false; } curBlock_ = prevBlock; + + MOZ_ASSERT(bodyRethrowPadPatches_.empty()); return true; } @@ -3679,26 +4606,27 @@ class FunctionCompiler { // Load the data pointer from the object auto* data = MWasmLoadField::New( - alloc(), exception, WasmExceptionObject::offsetOfData(), - MIRType::Pointer, MWideningOp::None, AliasSet::Load(AliasSet::Any)); + alloc(), exception, nullptr, WasmExceptionObject::offsetOfData(), + mozilla::Nothing(), MIRType::Pointer, MWideningOp::None, + AliasSet::Load(AliasSet::Any)); if (!data) { return false; } curBlock_->add(data); // Store the params into the data pointer - SharedTagType tagType = moduleEnv_.tags[tagIndex].type; + SharedTagType tagType = codeMeta().tags[tagIndex].type; for (size_t i = 0; i < tagType->argOffsets().length(); i++) { - if (!mirGen_.ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } ValType type = tagType->argTypes()[i]; uint32_t offset = tagType->argOffsets()[i]; if (!type.isRefRepr()) { - auto* store = MWasmStoreFieldKA::New(alloc(), exception, data, offset, - argValues[i], MNarrowingOp::None, - AliasSet::Store(AliasSet::Any)); + auto* store = MWasmStoreField::New( + alloc(), data, exception, offset, mozilla::Nothing(), argValues[i], + MNarrowingOp::None, AliasSet::Store(AliasSet::Any)); if (!store) { return false; } @@ -3707,17 +4635,17 @@ class FunctionCompiler { } // Store the new value - auto* store = MWasmStoreFieldRefKA::New( - alloc(), instancePointer_, exception, data, offset, argValues[i], - AliasSet::Store(AliasSet::Any), Nothing(), WasmPreBarrierKind::None); + auto* store = MWasmStoreFieldRef::New( + alloc(), instancePointer_, data, exception, offset, + mozilla::Nothing(), argValues[i], AliasSet::Store(AliasSet::Any), + Nothing(), WasmPreBarrierKind::None); if (!store) { return false; } curBlock_->add(store); // Call the post-write barrier - if (!postBarrierImmediate(bytecodeOffset, exception, data, offset, - argValues[i])) { + if (!postBarrierWholeCell(bytecodeOffset, exception, argValues[i])) { return false; } } @@ -3732,7 +4660,8 @@ class FunctionCompiler { } // The exception must be non-null - if (!refAsNonNull(exnRef)) { + exnRef = refAsNonNull(exnRef); + if (!exnRef) { return false; } @@ -3754,15 +4683,15 @@ class FunctionCompiler { // Check if there is a local catching try control, and if so, then add a // pad-patch to its tryPadPatches. - uint32_t relativeTryDepth; - if (inTryBlock(&relativeTryDepth)) { + ControlInstructionVector* tryLandingPadPatches; + if (inTryBlock(&tryLandingPadPatches)) { // Set the pending exception state, the landing pad will read from this if (!setPendingExceptionState(exn, tag)) { return false; } // End with a pending jump to the landing pad - if (!endWithPadPatch(relativeTryDepth)) { + if (!endWithPadPatch(tryLandingPadPatches)) { return false; } curBlock_ = nullptr; @@ -3786,136 +4715,10 @@ class FunctionCompiler { } Control& control = iter().controlItem(relativeDepth); - MBasicBlock* pad = control.block; - MOZ_ASSERT(pad); - MOZ_ASSERT(pad->nslots() > 1); MOZ_ASSERT(iter().controlKind(relativeDepth) == LabelKind::Catch || iter().controlKind(relativeDepth) == LabelKind::CatchAll); - - // The exception will always be the last slot in the landing pad. - size_t exnSlotPosition = pad->nslots() - 2; - MDefinition* tag = pad->getSlot(exnSlotPosition + 1); - MDefinition* exception = pad->getSlot(exnSlotPosition); - MOZ_ASSERT(exception->type() == MIRType::WasmAnyRef && - tag->type() == MIRType::WasmAnyRef); - return throwFrom(exception, tag); - } - - /*********************************************** Instance call helpers ***/ - - // Do not call this function directly -- it offers no protection against - // mis-counting of arguments. Instead call one of - // ::emitInstanceCall{0,1,2,3,4,5,6}. - // - // Emits a call to the Instance function indicated by `callee`. This is - // assumed to take an Instance pointer as its first argument. The remaining - // args are taken from `args`, which is assumed to hold `numArgs` entries. - // If `result` is non-null, the MDefinition* holding the return value is - // written to `*result`. - [[nodiscard]] bool emitInstanceCallN(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition** args, size_t numArgs, - MDefinition** result = nullptr) { - // Check that the first formal parameter is plausibly an Instance pointer. - MOZ_ASSERT(callee.numArgs > 0); - MOZ_ASSERT(callee.argTypes[0] == MIRType::Pointer); - // Check we agree on the number of args. - MOZ_ASSERT(numArgs + 1 /* the instance pointer */ == callee.numArgs); - // Check we agree on whether a value is returned. - MOZ_ASSERT((result == nullptr) == (callee.retType == MIRType::None)); - - // If we are in dead code, it can happen that some of the `args` entries - // are nullptr, which will look like an OOM to the logic below. So exit - // at this point. `passInstance`, `passArg`, `finishCall` and - // `builtinInstanceMethodCall` all do nothing in dead code, so it's valid - // to exit here. - if (inDeadCode()) { - if (result) { - *result = nullptr; - } - return true; - } - - // Check all args for signs of OOMness before attempting to allocating any - // more memory. - for (size_t i = 0; i < numArgs; i++) { - if (!args[i]) { - if (result) { - *result = nullptr; - } - return false; - } - } - - // Finally, construct the call. - CallCompileState ccsArgs; - if (!passInstance(callee.argTypes[0], &ccsArgs)) { - return false; - } - for (size_t i = 0; i < numArgs; i++) { - if (!passArg(args[i], callee.argTypes[i + 1], &ccsArgs)) { - return false; - } - } - if (!finishCall(&ccsArgs)) { - return false; - } - return builtinInstanceMethodCall(callee, lineOrBytecode, ccsArgs, result); - } - - [[nodiscard]] bool emitInstanceCall0(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition** result = nullptr) { - MDefinition** args = nullptr; - return emitInstanceCallN(lineOrBytecode, callee, args, 0, result); - } - [[nodiscard]] bool emitInstanceCall1(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition* arg1, - MDefinition** result = nullptr) { - MDefinition* args[1] = {arg1}; - return emitInstanceCallN(lineOrBytecode, callee, args, 1, result); - } - [[nodiscard]] bool emitInstanceCall2(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition* arg1, MDefinition* arg2, - MDefinition** result = nullptr) { - MDefinition* args[2] = {arg1, arg2}; - return emitInstanceCallN(lineOrBytecode, callee, args, 2, result); - } - [[nodiscard]] bool emitInstanceCall3(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition* arg1, MDefinition* arg2, - MDefinition* arg3, - MDefinition** result = nullptr) { - MDefinition* args[3] = {arg1, arg2, arg3}; - return emitInstanceCallN(lineOrBytecode, callee, args, 3, result); - } - [[nodiscard]] bool emitInstanceCall4(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition* arg1, MDefinition* arg2, - MDefinition* arg3, MDefinition* arg4, - MDefinition** result = nullptr) { - MDefinition* args[4] = {arg1, arg2, arg3, arg4}; - return emitInstanceCallN(lineOrBytecode, callee, args, 4, result); - } - [[nodiscard]] bool emitInstanceCall5(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition* arg1, MDefinition* arg2, - MDefinition* arg3, MDefinition* arg4, - MDefinition* arg5, - MDefinition** result = nullptr) { - MDefinition* args[5] = {arg1, arg2, arg3, arg4, arg5}; - return emitInstanceCallN(lineOrBytecode, callee, args, 5, result); - } - [[nodiscard]] bool emitInstanceCall6(uint32_t lineOrBytecode, - const SymbolicAddressSignature& callee, - MDefinition* arg1, MDefinition* arg2, - MDefinition* arg3, MDefinition* arg4, - MDefinition* arg5, MDefinition* arg6, - MDefinition** result = nullptr) { - MDefinition* args[6] = {arg1, arg2, arg3, arg4, arg5, arg6}; - return emitInstanceCallN(lineOrBytecode, callee, args, 6, result); + return throwFrom(control.tryControl->pendingException, + control.tryControl->pendingExceptionTag); } /******************************** WasmGC: low level load/store helpers ***/ @@ -3998,20 +4801,22 @@ class FunctionCompiler { [[nodiscard]] bool writeGcValueAtBasePlusOffset( uint32_t lineOrBytecode, StorageType type, MDefinition* keepAlive, AliasSet::Flag aliasBitset, MDefinition* value, MDefinition* base, - uint32_t offset, bool needsTrapInfo, WasmPreBarrierKind preBarrierKind) { + uint32_t offset, uint32_t fieldIndex, bool needsTrapInfo, + WasmPreBarrierKind preBarrierKind) { MOZ_ASSERT(aliasBitset != 0); MOZ_ASSERT(keepAlive->type() == MIRType::WasmAnyRef); MOZ_ASSERT(type.widenToValType().toMIRType() == value->type()); MNarrowingOp narrowingOp = fieldStoreInfoToMIR(type); if (!type.isRefRepr()) { - MaybeTrapSiteInfo maybeTrap; + MaybeTrapSiteDesc maybeTrap; if (needsTrapInfo) { - maybeTrap.emplace(getTrapSiteInfo()); + maybeTrap.emplace(trapSiteDesc()); } - auto* store = MWasmStoreFieldKA::New( - alloc(), keepAlive, base, offset, value, narrowingOp, - AliasSet::Store(aliasBitset), maybeTrap); + + auto* store = MWasmStoreField::New( + alloc(), base, keepAlive, offset, mozilla::Some(fieldIndex), value, + narrowingOp, AliasSet::Store(aliasBitset), maybeTrap); if (!store) { return false; } @@ -4030,17 +4835,17 @@ class FunctionCompiler { MOZ_ASSERT(type.widenToValType() == type.valType()); // Store the new value - auto* store = MWasmStoreFieldRefKA::New( - alloc(), instancePointer_, keepAlive, base, offset, value, - AliasSet::Store(aliasBitset), mozilla::Some(getTrapSiteInfo()), - preBarrierKind); + auto* store = MWasmStoreFieldRef::New( + alloc(), instancePointer_, base, keepAlive, offset, + mozilla::Some(fieldIndex), value, AliasSet::Store(aliasBitset), + mozilla::Some(trapSiteDesc()), preBarrierKind); if (!store) { return false; } curBlock_->add(store); // Call the post-write barrier - return postBarrierImmediate(lineOrBytecode, keepAlive, base, offset, value); + return postBarrierWholeCell(lineOrBytecode, keepAlive, value); } // Generate a write of `value` at address `base + index * scale`, where @@ -4061,10 +4866,10 @@ class FunctionCompiler { MNarrowingOp narrowingOp = fieldStoreInfoToMIR(type); if (!type.isRefRepr()) { - MaybeTrapSiteInfo maybeTrap; + MaybeTrapSiteDesc maybeTrap; Scale scale = scaleFromFieldType(type); - auto* store = MWasmStoreElementKA::New( - alloc(), keepAlive, base, index, value, narrowingOp, scale, + auto* store = MWasmStoreElement::New( + alloc(), base, index, value, keepAlive, narrowingOp, scale, AliasSet::Store(aliasBitset), maybeTrap); if (!store) { return false; @@ -4078,17 +4883,17 @@ class FunctionCompiler { MOZ_ASSERT(type.widenToValType() == type.valType()); // Store the new value - auto* store = MWasmStoreElementRefKA::New( - alloc(), instancePointer_, keepAlive, base, index, value, - AliasSet::Store(aliasBitset), mozilla::Some(getTrapSiteInfo()), + auto* store = MWasmStoreElementRef::New( + alloc(), instancePointer_, base, index, value, keepAlive, + AliasSet::Store(aliasBitset), mozilla::Some(trapSiteDesc()), preBarrierKind); if (!store) { return false; } curBlock_->add(store); - return postBarrierIndex(lineOrBytecode, keepAlive, base, index, - sizeof(void*), value); + return postBarrierEdgeAtIndex(lineOrBytecode, keepAlive, base, index, + sizeof(void*), value); } // Generate a read from address `base + offset`, where `offset` is known at @@ -4098,19 +4903,21 @@ class FunctionCompiler { [[nodiscard]] MDefinition* readGcValueAtBasePlusOffset( StorageType type, FieldWideningOp fieldWideningOp, MDefinition* keepAlive, AliasSet::Flag aliasBitset, MDefinition* base, uint32_t offset, - bool needsTrapInfo) { + uint32_t fieldIndex, bool needsTrapInfo) { MOZ_ASSERT(aliasBitset != 0); MOZ_ASSERT(keepAlive->type() == MIRType::WasmAnyRef); MIRType mirType; MWideningOp mirWideningOp; fieldLoadInfoToMIR(type, fieldWideningOp, &mirType, &mirWideningOp); - MaybeTrapSiteInfo maybeTrap; + MaybeTrapSiteDesc maybeTrap; if (needsTrapInfo) { - maybeTrap.emplace(getTrapSiteInfo()); + maybeTrap.emplace(trapSiteDesc()); } - auto* load = MWasmLoadFieldKA::New(alloc(), keepAlive, base, offset, - mirType, mirWideningOp, - AliasSet::Load(aliasBitset), maybeTrap); + + auto* load = MWasmLoadField::New(alloc(), base, keepAlive, offset, + mozilla::Some(fieldIndex), mirType, + mirWideningOp, AliasSet::Load(aliasBitset), + maybeTrap, type.toMaybeRefType()); if (!load) { return nullptr; } @@ -4132,9 +4939,10 @@ class FunctionCompiler { MWideningOp mirWideningOp; fieldLoadInfoToMIR(type, fieldWideningOp, &mirType, &mirWideningOp); Scale scale = scaleFromFieldType(type); - auto* load = MWasmLoadElementKA::New( - alloc(), keepAlive, base, index, mirType, mirWideningOp, scale, - AliasSet::Load(aliasBitset), mozilla::Some(getTrapSiteInfo())); + auto* load = MWasmLoadElement::New( + alloc(), base, keepAlive, index, mirType, mirWideningOp, scale, + AliasSet::Load(aliasBitset), mozilla::Some(trapSiteDesc()), + type.toMaybeRefType()); if (!load) { return nullptr; } @@ -4146,7 +4954,7 @@ class FunctionCompiler { // Returns an MDefinition holding the supertype vector for `typeIndex`. [[nodiscard]] MDefinition* loadSuperTypeVector(uint32_t typeIndex) { - uint32_t stvOffset = moduleEnv().offsetOfSuperTypeVector(typeIndex); + uint32_t stvOffset = codeMeta().offsetOfSuperTypeVector(typeIndex); auto* load = MWasmLoadInstanceDataField::New(alloc(), MIRType::Pointer, stvOffset, @@ -4158,10 +4966,31 @@ class FunctionCompiler { return load; } - [[nodiscard]] MDefinition* loadTypeDefInstanceData(uint32_t typeIndex) { - size_t offset = Instance::offsetInData( - moduleEnv_.offsetOfTypeDefInstanceData(typeIndex)); - auto* result = MWasmDerivedPointer::New(alloc(), instancePointer_, offset); + uint32_t readAllocSiteIndex(uint32_t typeIndex) { + if (!codeTailMeta() || !codeTailMeta()->hasFuncDefAllocSites()) { + // For single tier of optimized compilation, there are no assigned alloc + // sites, using type index as alloc site. + return typeIndex; + } + AllocSitesRange rangeInModule = + codeTailMeta()->getFuncDefAllocSites(funcIndex()); + uint32_t localIndex = numAllocSites_++; + MOZ_RELEASE_ASSERT(localIndex < rangeInModule.length); + return rangeInModule.begin + localIndex; + } + + [[nodiscard]] MDefinition* loadAllocSiteInstanceData( + uint32_t allocSiteIndex) { + auto* allocSites = MWasmLoadInstance::New( + alloc(), instancePointer_, Instance::offsetOfAllocSites(), + MIRType::Pointer, AliasSet::None()); + if (!allocSites) { + return nullptr; + } + curBlock_->add(allocSites); + + auto* result = MWasmDerivedPointer::New( + alloc(), allocSites, allocSiteIndex * sizeof(gc::AllocSite)); if (!result) { return nullptr; } @@ -4172,22 +5001,18 @@ class FunctionCompiler { /********************************************** WasmGC: struct helpers ***/ [[nodiscard]] MDefinition* createStructObject(uint32_t typeIndex, + uint32_t allocSiteIndex, bool zeroFields) { - const TypeDef& typeDef = (*moduleEnv().types)[typeIndex]; - gc::AllocKind allocKind = WasmStructObject::allocKindForTypeDef(&typeDef); - bool isOutline = - WasmStructObject::requiresOutlineBytes(typeDef.structType().size_); - - // Allocate an uninitialized struct. This requires the type definition - // for the struct. - MDefinition* typeDefData = loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { + // Allocate an uninitialized struct. + MDefinition* allocSite = loadAllocSiteInstanceData(allocSiteIndex); + if (!allocSite) { return nullptr; } + const TypeDef* typeDef = &(*codeMeta().types)[typeIndex]; auto* structObject = - MWasmNewStructObject::New(alloc(), instancePointer_, typeDefData, - isOutline, zeroFields, allocKind); + MWasmNewStructObject::New(alloc(), instancePointer_, allocSite, typeDef, + zeroFields, trapSiteDesc()); if (!structObject) { return nullptr; } @@ -4217,16 +5042,17 @@ class FunctionCompiler { MDefinition* base; bool needsTrapInfo; if (areaIsOutline) { - auto* load = MWasmLoadField::New( - alloc(), structObject, WasmStructObject::offsetOfOutlineData(), + auto* loadDataPointer = MWasmLoadField::New( + alloc(), structObject, nullptr, + WasmStructObject::offsetOfOutlineData(), mozilla::Nothing(), MIRType::Pointer, MWideningOp::None, AliasSet::Load(AliasSet::WasmStructOutlineDataPointer), - mozilla::Some(getTrapSiteInfo())); - if (!load) { + mozilla::Some(trapSiteDesc())); + if (!loadDataPointer) { return false; } - curBlock_->add(load); - base = load; + curBlock_->add(loadDataPointer); + base = loadDataPointer; needsTrapInfo = false; } else { base = structObject; @@ -4242,9 +5068,9 @@ class FunctionCompiler { ? AliasSet::WasmStructOutlineDataArea : AliasSet::WasmStructInlineDataArea; - return writeGcValueAtBasePlusOffset(lineOrBytecode, fieldType, structObject, - fieldAliasSet, value, base, areaOffset, - needsTrapInfo, preBarrierKind); + return writeGcValueAtBasePlusOffset( + lineOrBytecode, fieldType, structObject, fieldAliasSet, value, base, + areaOffset, fieldIndex, needsTrapInfo, preBarrierKind); } // Helper function for EmitStructGet: given a MIR pointer to a @@ -4267,16 +5093,17 @@ class FunctionCompiler { MDefinition* base; bool needsTrapInfo; if (areaIsOutline) { - auto* loadOOLptr = MWasmLoadField::New( - alloc(), structObject, WasmStructObject::offsetOfOutlineData(), + auto* loadDataPointer = MWasmLoadField::New( + alloc(), structObject, nullptr, + WasmStructObject::offsetOfOutlineData(), mozilla::Nothing(), MIRType::Pointer, MWideningOp::None, AliasSet::Load(AliasSet::WasmStructOutlineDataPointer), - mozilla::Some(getTrapSiteInfo())); - if (!loadOOLptr) { + mozilla::Some(trapSiteDesc())); + if (!loadDataPointer) { return nullptr; } - curBlock_->add(loadOOLptr); - base = loadOOLptr; + curBlock_->add(loadDataPointer); + base = loadDataPointer; needsTrapInfo = false; } else { base = structObject; @@ -4294,7 +5121,7 @@ class FunctionCompiler { return readGcValueAtBasePlusOffset(fieldType, wideningOp, structObject, fieldAliasSet, base, areaOffset, - needsTrapInfo); + fieldIndex, needsTrapInfo); } /********************************* WasmGC: address-arithmetic helpers ***/ @@ -4338,10 +5165,10 @@ class FunctionCompiler { MOZ_ASSERT(arrayObject->type() == MIRType::WasmAnyRef); auto* numElements = MWasmLoadField::New( - alloc(), arrayObject, WasmArrayObject::offsetOfNumElements(), - MIRType::Int32, MWideningOp::None, + alloc(), arrayObject, nullptr, WasmArrayObject::offsetOfNumElements(), + mozilla::Nothing(), MIRType::Int32, MWideningOp::None, AliasSet::Load(AliasSet::WasmArrayNumElements), - mozilla::Some(getTrapSiteInfo())); + mozilla::Some(trapSiteDesc())); if (!numElements) { return nullptr; } @@ -4356,10 +5183,10 @@ class FunctionCompiler { MOZ_ASSERT(arrayObject->type() == MIRType::WasmAnyRef); auto* data = MWasmLoadField::New( - alloc(), arrayObject, WasmArrayObject::offsetOfData(), - MIRType::WasmArrayData, MWideningOp::None, + alloc(), arrayObject, nullptr, WasmArrayObject::offsetOfData(), + mozilla::Nothing(), MIRType::WasmArrayData, MWideningOp::None, AliasSet::Load(AliasSet::WasmArrayDataPointer), - mozilla::Some(getTrapSiteInfo())); + mozilla::Some(trapSiteDesc())); if (!data) { return nullptr; } @@ -4371,20 +5198,19 @@ class FunctionCompiler { // Given a JIT-time-known type index `typeIndex` and a run-time known number // of elements `numElements`, create MIR to allocate a new wasm array, // possibly initialized with `typeIndex`s default value. - [[nodiscard]] MDefinition* createArrayObject(uint32_t lineOrBytecode, - uint32_t typeIndex, + [[nodiscard]] MDefinition* createArrayObject(uint32_t typeIndex, + uint32_t allocSiteIndex, MDefinition* numElements, - uint32_t elemSize, bool zeroFields) { - // Get the type definition for the array as a whole. - MDefinition* typeDefData = loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { + MDefinition* allocSite = loadAllocSiteInstanceData(allocSiteIndex); + if (!allocSite) { return nullptr; } + const TypeDef* typeDef = &(*codeMeta().types)[typeIndex]; auto* arrayObject = MWasmNewArrayObject::New( - alloc(), instancePointer_, numElements, typeDefData, elemSize, - zeroFields, bytecodeOffset()); + alloc(), instancePointer_, numElements, allocSite, typeDef, zeroFields, + trapSiteDesc()); if (!arrayObject) { return nullptr; } @@ -4419,7 +5245,7 @@ class FunctionCompiler { // Create a bounds check. auto* boundsCheck = - MWasmBoundsCheck::New(alloc(), index, numElements, bytecodeOffset(), + MWasmBoundsCheck::New(alloc(), index, numElements, trapSiteDesc(), MWasmBoundsCheck::Target::Unknown); if (!boundsCheck) { return nullptr; @@ -4487,9 +5313,9 @@ class FunctionCompiler { } curBlock_->add(limit); - // Use JSOp::StrictEq, not ::Eq, so that the comparison (and eventually - // the entire initialisation loop) will be folded out in the case where - // the number of elements is zero. See MCompare::tryFoldEqualOperands. + // Note: the comparison (and eventually the entire initialisation loop) will + // be folded out in the case where the number of elements is zero. + // See MCompare::tryFoldEqualOperands. MDefinition* limitEqualsBase = compare(limit, index, JSOp::StrictEq, MCompare::Compare_UInt32); if (!limitEqualsBase) { @@ -4516,7 +5342,7 @@ class FunctionCompiler { } indexPhi->addInput(index); curBlock_->addPhi(indexPhi); - curBlock_->setLoopDepth(loopDepth_ + 1); + curBlock_->setLoopDepth(rootCompiler_.loopDepth() + 1); if (!writeGcValueAtBasePlusScaledIndex( lineOrBytecode, elemType, arrayObject, AliasSet::WasmArrayDataArea, @@ -4556,14 +5382,13 @@ class FunctionCompiler { // value is for the newly created array. [[nodiscard]] MDefinition* createArrayNewCallAndLoop(uint32_t lineOrBytecode, uint32_t typeIndex, + uint32_t allocSiteIndex, MDefinition* numElements, MDefinition* fillValue) { - const ArrayType& arrayType = (*moduleEnv_.types)[typeIndex].arrayType(); - // Create the array object, uninitialized. MDefinition* arrayObject = - createArrayObject(lineOrBytecode, typeIndex, numElements, - arrayType.elementType().size(), /*zeroFields=*/false); + createArrayObject(typeIndex, allocSiteIndex, numElements, + /*zeroFields=*/false); if (!arrayObject) { return nullptr; } @@ -4574,6 +5399,7 @@ class FunctionCompiler { // reftyped case, that would be a big win since each iteration requires a // call to the post-write barrier routine. + const ArrayType& arrayType = (*codeMeta().types)[typeIndex].arrayType(); if (!fillArray(lineOrBytecode, arrayType, arrayObject, constantI32(0), numElements, fillValue, WasmPreBarrierKind::None)) { return nullptr; @@ -4582,6 +5408,113 @@ class FunctionCompiler { return arrayObject; } + [[nodiscard]] bool createArrayCopy(uint32_t lineOrBytecode, + MDefinition* dstArrayObject, + MDefinition* dstArrayIndex, + MDefinition* srcArrayObject, + MDefinition* srcArrayIndex, + MDefinition* numElements, int32_t elemSize, + bool elemsAreRefTyped) { + // Check for null is done in getWasmArrayObjectNumElements. + + // Get the arrays' actual sizes. + MDefinition* dstNumElements = getWasmArrayObjectNumElements(dstArrayObject); + if (!dstNumElements) { + return false; + } + MDefinition* srcNumElements = getWasmArrayObjectNumElements(srcArrayObject); + if (!srcNumElements) { + return false; + } + + // Create the bounds checks. + MInstruction* dstBoundsCheck = MWasmBoundsCheckRange32::New( + alloc(), dstArrayIndex, numElements, dstNumElements, trapSiteDesc()); + if (!dstBoundsCheck) { + return false; + } + curBlock_->add(dstBoundsCheck); + + MInstruction* srcBoundsCheck = MWasmBoundsCheckRange32::New( + alloc(), srcArrayIndex, numElements, srcNumElements, trapSiteDesc()); + if (!srcBoundsCheck) { + return false; + } + curBlock_->add(srcBoundsCheck); + + // Check if numElements != 0 -- optimization to not invoke builtins. + MBasicBlock* copyBlock = nullptr; + if (!newBlock(curBlock_, ©Block)) { + return false; + } + MBasicBlock* joinBlock = nullptr; + if (!newBlock(curBlock_, &joinBlock)) { + return false; + } + + MInstruction* condition = + MCompare::NewWasm(alloc(), numElements, constantI32(0), JSOp::StrictEq, + MCompare::Compare_UInt32); + curBlock_->add(condition); + + MTest* test = MTest::New(alloc(), condition, joinBlock, copyBlock); + if (!test) { + return false; + } + curBlock_->end(test); + curBlock_ = copyBlock; + + MInstruction* dstData = MWasmLoadField::New( + alloc(), dstArrayObject, nullptr, WasmArrayObject::offsetOfData(), + mozilla::Nothing(), MIRType::WasmArrayData, MWideningOp::None, + AliasSet::Load(AliasSet::WasmArrayDataPointer)); + if (!dstData) { + return false; + } + curBlock_->add(dstData); + + MInstruction* srcData = MWasmLoadField::New( + alloc(), srcArrayObject, nullptr, WasmArrayObject::offsetOfData(), + mozilla::Nothing(), MIRType::WasmArrayData, MWideningOp::None, + AliasSet::Load(AliasSet::WasmArrayDataPointer)); + if (!srcData) { + return false; + } + curBlock_->add(srcData); + + if (elemsAreRefTyped) { + MOZ_RELEASE_ASSERT(elemSize == sizeof(void*)); + + if (!builtinCall5(SASigArrayRefsMove, lineOrBytecode, dstData, + dstArrayIndex, srcData, srcArrayIndex, numElements, + nullptr)) { + return false; + } + } else { + MDefinition* elemSizeDef = constantI32(elemSize); + if (!elemSizeDef) { + return false; + } + + if (!builtinCall6(SASigArrayMemMove, lineOrBytecode, dstData, + dstArrayIndex, srcData, srcArrayIndex, elemSizeDef, + numElements, nullptr)) { + return false; + } + } + + MGoto* fallthrough = MGoto::New(alloc(), joinBlock); + if (!fallthrough) { + return false; + } + curBlock_->end(fallthrough); + if (!joinBlock->addPredecessor(alloc(), curBlock_)) { + return false; + } + curBlock_ = joinBlock; + return true; + } + [[nodiscard]] bool createArrayFill(uint32_t lineOrBytecode, uint32_t typeIndex, MDefinition* arrayObject, @@ -4591,7 +5524,7 @@ class FunctionCompiler { MOZ_ASSERT(index->type() == MIRType::Int32); MOZ_ASSERT(numElements->type() == MIRType::Int32); - const ArrayType& arrayType = (*moduleEnv_.types)[typeIndex].arrayType(); + const ArrayType& arrayType = (*codeMeta().types)[typeIndex].arrayType(); // Check for null is done in getWasmArrayObjectNumElements. @@ -4603,7 +5536,7 @@ class FunctionCompiler { // Create a bounds check. auto* boundsCheck = MWasmBoundsCheckRange32::New( - alloc(), index, numElements, actualNumElements, bytecodeOffset()); + alloc(), index, numElements, actualNumElements, trapSiteDesc()); if (!boundsCheck) { return false; } @@ -4626,7 +5559,7 @@ class FunctionCompiler { return false; } - auto* trap = MWasmTrap::New(alloc(), trapKind, bytecodeOffset()); + auto* trap = MWasmTrap::New(alloc(), trapKind, trapSiteDesc()); if (!trap) { return false; } @@ -4646,18 +5579,44 @@ class FunctionCompiler { return true; } - [[nodiscard]] MDefinition* isRefSubtypeOf(MDefinition* ref, - RefType sourceType, - RefType destType) { + // Generate MIR that attempts to cast `ref` to `castToTypeDef`. If the + // cast fails, we trap. If it succeeds, then `ref` can be assumed to + // have a type that is a subtype of (or the same as) `castToTypeDef` after + // this point. + [[nodiscard]] MDefinition* refCast(MDefinition* ref, RefType destType) { + MInstruction* cast = nullptr; + if (destType.isTypeRef()) { + uint32_t typeIndex = codeMeta().types->indexOf(*destType.typeDef()); + MDefinition* superSTV = loadSuperTypeVector(typeIndex); + if (!superSTV) { + return nullptr; + } + cast = MWasmRefCastConcrete::New(alloc(), ref, superSTV, destType, + trapSiteDesc()); + } else { + cast = MWasmRefCastAbstract::New(alloc(), ref, destType, trapSiteDesc()); + } + + if (!cast) { + return nullptr; + } + curBlock_->add(cast); + return cast; + } + + // Generate MIR that computes a boolean value indicating whether or not it + // is possible to cast `ref` to `destType`. + [[nodiscard]] MDefinition* refTest(MDefinition* ref, RefType destType) { MInstruction* isSubTypeOf = nullptr; if (destType.isTypeRef()) { - uint32_t typeIndex = moduleEnv_.types->indexOf(*destType.typeDef()); + uint32_t typeIndex = codeMeta().types->indexOf(*destType.typeDef()); MDefinition* superSTV = loadSuperTypeVector(typeIndex); - isSubTypeOf = MWasmRefIsSubtypeOfConcrete::New(alloc(), ref, superSTV, - sourceType, destType); + if (!superSTV) { + return nullptr; + } + isSubTypeOf = MWasmRefTestConcrete::New(alloc(), ref, superSTV, destType); } else { - isSubTypeOf = - MWasmRefIsSubtypeOfAbstract::New(alloc(), ref, sourceType, destType); + isSubTypeOf = MWasmRefTestAbstract::New(alloc(), ref, destType); } MOZ_ASSERT(isSubTypeOf); @@ -4665,29 +5624,6 @@ class FunctionCompiler { return isSubTypeOf; } - // Generate MIR that attempts to downcast `ref` to `castToTypeDef`. If the - // downcast fails, we trap. If it succeeds, then `ref` can be assumed to - // have a type that is a subtype of (or the same as) `castToTypeDef` after - // this point. - [[nodiscard]] bool refCast(MDefinition* ref, RefType sourceType, - RefType destType) { - MDefinition* success = isRefSubtypeOf(ref, sourceType, destType); - if (!success) { - return false; - } - - // Trap if `success` is zero. If it's nonzero, we have established that - // `ref <: castToTypeDef`. - return trapIfZero(wasm::Trap::BadCast, success); - } - - // Generate MIR that computes a boolean value indicating whether or not it - // is possible to downcast `ref` to `destType`. - [[nodiscard]] MDefinition* refTest(MDefinition* ref, RefType sourceType, - RefType destType) { - return isRefSubtypeOf(ref, sourceType, destType); - } - // Generates MIR for br_on_cast and br_on_cast_fail. [[nodiscard]] bool brOnCastCommon(bool onSuccess, uint32_t labelRelativeDepth, RefType sourceType, RefType destType, @@ -4714,7 +5650,7 @@ class FunctionCompiler { MDefinition* ref = values.back(); MOZ_ASSERT(ref->type() == MIRType::WasmAnyRef); - MDefinition* success = isRefSubtypeOf(ref, sourceType, destType); + MDefinition* success = refTest(ref, destType); if (!success) { return false; } @@ -4769,6 +5705,16 @@ class FunctionCompiler { return true; } + [[nodiscard]] MDefinition* convertAnyExtern(MDefinition* ref, + wasm::RefType::Kind kind) { + auto* converted = MWasmRefConvertAnyExtern::New(alloc(), ref, kind); + if (!converted) { + return nullptr; + } + curBlock_->add(converted); + return converted; + } + /************************************************************ DECODING ***/ // AsmJS adds a line number to `callSiteLineNums` for certain operations that @@ -4790,8 +5736,18 @@ class FunctionCompiler { // Return the current bytecode offset. uint32_t readBytecodeOffset() { return iter_.lastOpcodeOffset(); } - TrapSiteInfo getTrapSiteInfo() { - return TrapSiteInfo(wasm::BytecodeOffset(readBytecodeOffset())); + CallRefHint readCallRefHint() { + // We don't track anything if we're not using lazy tiering + if (compilerEnv().mode() != CompileMode::LazyTiering) { + return CallRefHint(); + } + + CallRefMetricsRange rangeInModule = + codeTailMeta()->getFuncDefCallRefs(funcIndex()); + uint32_t localIndex = numCallRefs_++; + MOZ_RELEASE_ASSERT(localIndex < rangeInModule.length); + uint32_t moduleIndex = rangeInModule.begin + localIndex; + return codeTailMeta()->getCallRefHint(moduleIndex); } #if DEBUG @@ -4807,7 +5763,7 @@ class FunctionCompiler { return false; } mirGraph().addBlock(*block); - (*block)->setLoopDepth(loopDepth_); + (*block)->setLoopDepth(rootCompiler_.loopDepth()); return true; } @@ -4881,6 +5837,169 @@ class FunctionCompiler { patches.clear(); return true; } + + bool emitI32Const(); + bool emitI64Const(); + bool emitF32Const(); + bool emitF64Const(); + bool emitBlock(); + bool emitLoop(); + bool emitIf(); + bool emitElse(); + bool emitEnd(); + bool emitBr(); + bool emitBrIf(); + bool emitBrTable(); + bool emitReturn(); + bool emitUnreachable(); + bool emitTry(); + bool emitCatch(); + bool emitCatchAll(); + bool emitTryTable(); + bool emitDelegate(); + bool emitThrow(); + bool emitThrowRef(); + bool emitRethrow(); + bool emitInlineCall(const FuncType& funcType, uint32_t funcIndex, + InliningHeuristics::CallKind callKind, + const DefVector& args, DefVector* results); + bool emitCall(bool asmJSFuncDef); + bool emitCallIndirect(bool oldStyle); + bool emitStackSwitch(); + bool emitReturnCall(); + bool emitReturnCallIndirect(); + bool emitReturnCallRef(); + bool emitGetLocal(); + bool emitSetLocal(); + bool emitTeeLocal(); + bool emitGetGlobal(); + bool emitSetGlobal(); + bool emitTeeGlobal(); + template + bool emitUnary(ValType operandType); + template + bool emitConversion(ValType operandType, ValType resultType); + template + bool emitUnaryWithType(ValType operandType, MIRType mirType); + template + bool emitConversionWithType(ValType operandType, ValType resultType, + MIRType mirType); + bool emitTruncate(ValType operandType, ValType resultType, bool isUnsigned, + bool isSaturating); + bool emitSignExtend(uint32_t srcSize, uint32_t targetSize); + bool emitExtendI32(bool isUnsigned); + bool emitConvertI64ToFloatingPoint(ValType resultType, MIRType mirType, + bool isUnsigned); + bool emitReinterpret(ValType resultType, ValType operandType, + MIRType mirType); + bool emitAdd(ValType type, MIRType mirType); + bool emitSub(ValType type, MIRType mirType); + bool emitRotate(ValType type, bool isLeftRotation); + bool emitBitNot(ValType operandType, MIRType mirType); + bool emitBitwiseAndOrXor(ValType operandType, MIRType mirType, + MWasmBinaryBitwise::SubOpcode subOpc); + template + bool emitShift(ValType operandType, MIRType mirType); + bool emitUrsh(ValType operandType, MIRType mirType); + bool emitMul(ValType operandType, MIRType mirType); + bool emitDiv(ValType operandType, MIRType mirType, bool isUnsigned); + bool emitRem(ValType operandType, MIRType mirType, bool isUnsigned); + bool emitMinMax(ValType operandType, MIRType mirType, bool isMax); + bool emitCopySign(ValType operandType); + bool emitComparison(ValType operandType, JSOp compareOp, + MCompare::CompareType compareType); + bool emitSelect(bool typed); + bool emitLoad(ValType type, Scalar::Type viewType); + bool emitStore(ValType resultType, Scalar::Type viewType); + bool emitTeeStore(ValType resultType, Scalar::Type viewType); + bool emitTeeStoreWithCoercion(ValType resultType, Scalar::Type viewType); + bool tryInlineUnaryBuiltin(SymbolicAddress callee, MDefinition* input); + bool emitUnaryMathBuiltinCall(const SymbolicAddressSignature& callee); + bool emitBinaryMathBuiltinCall(const SymbolicAddressSignature& callee); + bool emitMemoryGrow(); + bool emitMemorySize(); + bool emitAtomicCmpXchg(ValType type, Scalar::Type viewType); + bool emitAtomicLoad(ValType type, Scalar::Type viewType); + bool emitAtomicRMW(ValType type, Scalar::Type viewType, jit::AtomicOp op); + bool emitAtomicStore(ValType type, Scalar::Type viewType); + bool emitWait(ValType type, uint32_t byteSize); + bool emitFence(); + bool emitNotify(); + bool emitAtomicXchg(ValType type, Scalar::Type viewType); + bool emitMemCopyCall(uint32_t dstMemIndex, uint32_t srcMemIndex, + MDefinition* dst, MDefinition* src, MDefinition* len); + bool emitMemCopyInline(uint32_t memoryIndex, MDefinition* dst, + MDefinition* src, uint32_t length); + bool emitMemCopy(); + bool emitTableCopy(); + bool emitDataOrElemDrop(bool isData); + bool emitMemFillCall(uint32_t memoryIndex, MDefinition* start, + MDefinition* val, MDefinition* len); + bool emitMemFillInline(uint32_t memoryIndex, MDefinition* start, + MDefinition* val, uint32_t length); + bool emitMemFill(); + bool emitMemInit(); + bool emitTableInit(); + bool emitTableFill(); + bool emitMemDiscard(); + bool emitTableGet(); + bool emitTableGrow(); + bool emitTableSet(); + bool emitTableSize(); + bool emitRefFunc(); + bool emitRefNull(); + bool emitRefIsNull(); + bool emitConstSimd128(); + bool emitBinarySimd128(bool commutative, SimdOp op); + bool emitTernarySimd128(wasm::SimdOp op); + bool emitShiftSimd128(SimdOp op); + bool emitSplatSimd128(ValType inType, SimdOp op); + bool emitUnarySimd128(SimdOp op); + bool emitReduceSimd128(SimdOp op); + bool emitExtractLaneSimd128(ValType outType, uint32_t laneLimit, SimdOp op); + bool emitReplaceLaneSimd128(ValType laneType, uint32_t laneLimit, SimdOp op); + bool emitShuffleSimd128(); + bool emitLoadSplatSimd128(Scalar::Type viewType, wasm::SimdOp splatOp); + bool emitLoadExtendSimd128(wasm::SimdOp op); + bool emitLoadZeroSimd128(Scalar::Type viewType, size_t numBytes); + bool emitLoadLaneSimd128(uint32_t laneSize); + bool emitStoreLaneSimd128(uint32_t laneSize); + bool emitRefAsNonNull(); + bool emitBrOnNull(); + bool emitBrOnNonNull(); + bool emitSpeculativeInlineCallRef(uint32_t bytecodeOffset, + const FuncType& funcType, + CallRefHint expectedFuncIndices, + MDefinition* actualCalleeFunc, + const DefVector& args, DefVector* results); + bool emitCallRef(); + bool emitStructNew(); + bool emitStructNewDefault(); + bool emitStructSet(); + bool emitStructGet(FieldWideningOp wideningOp); + bool emitArrayNew(); + bool emitArrayNewDefault(); + bool emitArrayNewFixed(); + bool emitArrayNewData(); + bool emitArrayNewElem(); + bool emitArrayInitData(); + bool emitArrayInitElem(); + bool emitArraySet(); + bool emitArrayGet(FieldWideningOp wideningOp); + bool emitArrayLen(); + bool emitArrayCopy(); + bool emitArrayFill(); + bool emitRefI31(); + bool emitI31Get(FieldWideningOp wideningOp); + bool emitRefTest(bool nullable); + bool emitRefCast(bool nullable); + bool emitBrOnCast(bool onSuccess); + bool emitAnyConvertExtern(); + bool emitExternConvertAny(); + bool emitCallBuiltinModuleFunc(); + + public: + bool emitBodyExprs(); }; template <> @@ -4899,8 +6018,8 @@ MDefinition* FunctionCompiler::unary( if (inDeadCode()) { return nullptr; } - auto* ins = MWasmBuiltinTruncateToInt32::New(alloc(), op, instancePointer_, - bytecodeOffset()); + auto* ins = MWasmBuiltinTruncateToInt32::New( + alloc(), op, instancePointer_, trapSiteDescWithCallSiteLineNumber()); curBlock_->add(ins); return ins; } @@ -4925,123 +6044,121 @@ MDefinition* FunctionCompiler::unary(MDefinition* op, MIRType type) { return ins; } -} // end anonymous namespace - -static bool EmitI32Const(FunctionCompiler& f) { +bool FunctionCompiler::emitI32Const() { int32_t i32; - if (!f.iter().readI32Const(&i32)) { + if (!iter().readI32Const(&i32)) { return false; } - f.iter().setResult(f.constantI32(i32)); + iter().setResult(constantI32(i32)); return true; } -static bool EmitI64Const(FunctionCompiler& f) { +bool FunctionCompiler::emitI64Const() { int64_t i64; - if (!f.iter().readI64Const(&i64)) { + if (!iter().readI64Const(&i64)) { return false; } - f.iter().setResult(f.constantI64(i64)); + iter().setResult(constantI64(i64)); return true; } -static bool EmitF32Const(FunctionCompiler& f) { +bool FunctionCompiler::emitF32Const() { float f32; - if (!f.iter().readF32Const(&f32)) { + if (!iter().readF32Const(&f32)) { return false; } - f.iter().setResult(f.constantF32(f32)); + iter().setResult(constantF32(f32)); return true; } -static bool EmitF64Const(FunctionCompiler& f) { +bool FunctionCompiler::emitF64Const() { double f64; - if (!f.iter().readF64Const(&f64)) { + if (!iter().readF64Const(&f64)) { return false; } - f.iter().setResult(f.constantF64(f64)); + iter().setResult(constantF64(f64)); return true; } -static bool EmitBlock(FunctionCompiler& f) { - ResultType params; - return f.iter().readBlock(¶ms) && f.startBlock(); +bool FunctionCompiler::emitBlock() { + BlockType type; + return iter().readBlock(&type) && startBlock(); } -static bool EmitLoop(FunctionCompiler& f) { - ResultType params; - if (!f.iter().readLoop(¶ms)) { +bool FunctionCompiler::emitLoop() { + BlockType type; + if (!iter().readLoop(&type)) { return false; } MBasicBlock* loopHeader; - if (!f.startLoop(&loopHeader, params.length())) { + if (!startLoop(&loopHeader, type.params().length())) { return false; } - f.addInterruptCheck(); + addInterruptCheck(); - f.iter().controlItem().block = loopHeader; + iter().controlItem().block = loopHeader; return true; } -static bool EmitIf(FunctionCompiler& f) { +bool FunctionCompiler::emitIf() { BranchHint branchHint = - f.iter().getBranchHint(f.funcIndex(), f.relativeBytecodeOffset()); + iter().getBranchHint(funcIndex(), relativeBytecodeOffset()); - ResultType params; + BlockType type; MDefinition* condition = nullptr; - if (!f.iter().readIf(¶ms, &condition)) { + if (!iter().readIf(&type, &condition)) { return false; } MBasicBlock* elseBlock; - if (!f.branchAndStartThen(condition, &elseBlock)) { + if (!branchAndStartThen(condition, &elseBlock)) { return false; } // Store the branch hint in the basic block. - if (!f.inDeadCode() && branchHint != BranchHint::Invalid) { - f.getCurBlock()->setBranchHinting(branchHint); + if (!inDeadCode() && branchHint != BranchHint::Invalid) { + getCurBlock()->setBranchHinting(branchHint); } - f.iter().controlItem().block = elseBlock; + iter().controlItem().block = elseBlock; return true; } -static bool EmitElse(FunctionCompiler& f) { +bool FunctionCompiler::emitElse() { ResultType paramType; ResultType resultType; DefVector thenValues; - if (!f.iter().readElse(¶mType, &resultType, &thenValues)) { + if (!iter().readElse(¶mType, &resultType, &thenValues)) { return false; } - if (!f.pushDefs(thenValues)) { + if (!pushDefs(thenValues)) { return false; } - Control& control = f.iter().controlItem(); - return f.switchToElse(control.block, &control.block); + Control& control = iter().controlItem(); + return switchToElse(control.block, &control.block); } -static bool EmitEnd(FunctionCompiler& f) { +bool FunctionCompiler::emitEnd() { LabelKind kind; ResultType type; DefVector preJoinDefs; DefVector resultsForEmptyElse; - if (!f.iter().readEnd(&kind, &type, &preJoinDefs, &resultsForEmptyElse)) { + if (!iter().readEnd(&kind, &type, &preJoinDefs, &resultsForEmptyElse)) { return false; } - Control& control = f.iter().controlItem(); + Control& control = iter().controlItem(); MBasicBlock* block = control.block; - if (!f.pushDefs(preJoinDefs)) { + if (!pushDefs(preJoinDefs)) { return false; } @@ -5049,120 +6166,121 @@ static bool EmitEnd(FunctionCompiler& f) { // time for the label case DefVector postJoinDefs; switch (kind) { - case LabelKind::Body: + case LabelKind::Body: { MOZ_ASSERT(!control.tryControl); - if (!f.emitBodyDelegateThrowPad(control)) { + if (!emitBodyRethrowPad(control)) { return false; } - if (!f.finishBlock(&postJoinDefs)) { + if (!finishBlock(&postJoinDefs)) { return false; } - if (!f.returnValues(postJoinDefs)) { + if (!returnValues(std::move(postJoinDefs))) { return false; } - f.iter().popEnd(); - MOZ_ASSERT(f.iter().controlStackEmpty()); - return f.iter().endFunction(f.iter().end()); + iter().popEnd(); + MOZ_ASSERT(iter().controlStackEmpty()); + return iter().endFunction(iter().end()); + } case LabelKind::Block: MOZ_ASSERT(!control.tryControl); - if (!f.finishBlock(&postJoinDefs)) { + if (!finishBlock(&postJoinDefs)) { return false; } - f.iter().popEnd(); + iter().popEnd(); break; case LabelKind::Loop: MOZ_ASSERT(!control.tryControl); - if (!f.closeLoop(block, &postJoinDefs)) { + if (!closeLoop(block, &postJoinDefs)) { return false; } - f.iter().popEnd(); + iter().popEnd(); break; case LabelKind::Then: { MOZ_ASSERT(!control.tryControl); // If we didn't see an Else, create a trivial else block so that we create // a diamond anyway, to preserve Ion invariants. - if (!f.switchToElse(block, &block)) { + if (!switchToElse(block, &block)) { return false; } - if (!f.pushDefs(resultsForEmptyElse)) { + if (!pushDefs(resultsForEmptyElse)) { return false; } - if (!f.joinIfElse(block, &postJoinDefs)) { + if (!joinIfElse(block, &postJoinDefs)) { return false; } - f.iter().popEnd(); + iter().popEnd(); break; } case LabelKind::Else: MOZ_ASSERT(!control.tryControl); - if (!f.joinIfElse(block, &postJoinDefs)) { + if (!joinIfElse(block, &postJoinDefs)) { return false; } - f.iter().popEnd(); + iter().popEnd(); break; case LabelKind::Try: case LabelKind::Catch: case LabelKind::CatchAll: MOZ_ASSERT(control.tryControl); - if (!f.finishTryCatch(kind, control, &postJoinDefs)) { + if (!finishTryCatch(kind, control, &postJoinDefs)) { return false; } - f.freeTryControl(std::move(control.tryControl)); - f.iter().popEnd(); + rootCompiler().freeTryControl(std::move(control.tryControl)); + iter().popEnd(); break; case LabelKind::TryTable: MOZ_ASSERT(control.tryControl); - if (!f.finishTryTable(control, &postJoinDefs)) { + if (!finishTryTable(control, &postJoinDefs)) { return false; } - f.freeTryControl(std::move(control.tryControl)); - f.iter().popEnd(); + rootCompiler().freeTryControl(std::move(control.tryControl)); + iter().popEnd(); break; } - MOZ_ASSERT_IF(!f.inDeadCode(), postJoinDefs.length() == type.length()); - f.iter().setResults(postJoinDefs.length(), postJoinDefs); + MOZ_ASSERT_IF(!inDeadCode(), postJoinDefs.length() == type.length()); + iter().setResults(postJoinDefs.length(), postJoinDefs); return true; } -static bool EmitBr(FunctionCompiler& f) { +bool FunctionCompiler::emitBr() { uint32_t relativeDepth; ResultType type; DefVector values; - if (!f.iter().readBr(&relativeDepth, &type, &values)) { + if (!iter().readBr(&relativeDepth, &type, &values)) { return false; } - return f.br(relativeDepth, values); + return br(relativeDepth, values); } -static bool EmitBrIf(FunctionCompiler& f) { +bool FunctionCompiler::emitBrIf() { uint32_t relativeDepth; ResultType type; DefVector values; MDefinition* condition; BranchHint branchHint = - f.iter().getBranchHint(f.funcIndex(), f.relativeBytecodeOffset()); + iter().getBranchHint(funcIndex(), relativeBytecodeOffset()); - if (!f.iter().readBrIf(&relativeDepth, &type, &values, &condition)) { + if (!iter().readBrIf(&relativeDepth, &type, &values, &condition)) { return false; } - return f.brIf(relativeDepth, values, condition, branchHint); + return brIf(relativeDepth, values, condition, branchHint); } -static bool EmitBrTable(FunctionCompiler& f) { +bool FunctionCompiler::emitBrTable() { Uint32Vector depths; uint32_t defaultDepth; ResultType branchValueType; DefVector branchValues; MDefinition* index; - if (!f.iter().readBrTable(&depths, &defaultDepth, &branchValueType, - &branchValues, &index)) { + if (!iter().readBrTable(&depths, &defaultDepth, &branchValueType, + &branchValues, &index)) { return false; } @@ -5178,46 +6296,46 @@ static bool EmitBrTable(FunctionCompiler& f) { } if (allSameDepth) { - return f.br(defaultDepth, branchValues); + return br(defaultDepth, branchValues); } - return f.brTable(index, defaultDepth, depths, branchValues); + return brTable(index, defaultDepth, depths, branchValues); } -static bool EmitReturn(FunctionCompiler& f) { +bool FunctionCompiler::emitReturn() { DefVector values; - if (!f.iter().readReturn(&values)) { + if (!iter().readReturn(&values)) { return false; } - return f.returnValues(values); + return returnValues(std::move(values)); } -static bool EmitUnreachable(FunctionCompiler& f) { - if (!f.iter().readUnreachable()) { +bool FunctionCompiler::emitUnreachable() { + if (!iter().readUnreachable()) { return false; } - f.unreachableTrap(); + unreachableTrap(); return true; } -static bool EmitTry(FunctionCompiler& f) { - ResultType params; - if (!f.iter().readTry(¶ms)) { +bool FunctionCompiler::emitTry() { + BlockType type; + if (!iter().readTry(&type)) { return false; } - return f.startTry(); + return startTry(); } -static bool EmitCatch(FunctionCompiler& f) { +bool FunctionCompiler::emitCatch() { LabelKind kind; uint32_t tagIndex; ResultType paramType, resultType; DefVector tryValues; - if (!f.iter().readCatch(&kind, &tagIndex, ¶mType, &resultType, - &tryValues)) { + if (!iter().readCatch(&kind, &tagIndex, ¶mType, &resultType, + &tryValues)) { return false; } @@ -5225,175 +6343,217 @@ static bool EmitCatch(FunctionCompiler& f) { // after the try and after each handler, as well as potential control flow // patches from other instrunctions. This is similar to what is done for // if-then-else control flow and for most other control control flow joins. - if (!f.pushDefs(tryValues)) { + if (!pushDefs(tryValues)) { return false; } - return f.switchToCatch(f.iter().controlItem(), kind, tagIndex); + return switchToCatch(iter().controlItem(), kind, tagIndex); } -static bool EmitCatchAll(FunctionCompiler& f) { +bool FunctionCompiler::emitCatchAll() { LabelKind kind; ResultType paramType, resultType; DefVector tryValues; - if (!f.iter().readCatchAll(&kind, ¶mType, &resultType, &tryValues)) { + if (!iter().readCatchAll(&kind, ¶mType, &resultType, &tryValues)) { return false; } // Pushing the results of the previous block, to properly join control flow // after the try and after each handler, as well as potential control flow // patches from other instrunctions. - if (!f.pushDefs(tryValues)) { + if (!pushDefs(tryValues)) { return false; } - return f.switchToCatch(f.iter().controlItem(), kind, CatchAllIndex); + return switchToCatch(iter().controlItem(), kind, CatchAllIndex); } -static bool EmitTryTable(FunctionCompiler& f) { - ResultType params; +bool FunctionCompiler::emitTryTable() { + BlockType type; TryTableCatchVector catches; - if (!f.iter().readTryTable(¶ms, &catches)) { + if (!iter().readTryTable(&type, &catches)) { return false; } - return f.startTryTable(std::move(catches)); + return startTryTable(std::move(catches)); } -static bool EmitDelegate(FunctionCompiler& f) { +bool FunctionCompiler::emitDelegate() { uint32_t relativeDepth; ResultType resultType; DefVector tryValues; - if (!f.iter().readDelegate(&relativeDepth, &resultType, &tryValues)) { + if (!iter().readDelegate(&relativeDepth, &resultType, &tryValues)) { return false; } - Control& control = f.iter().controlItem(); + Control& control = iter().controlItem(); MBasicBlock* block = control.block; MOZ_ASSERT(control.tryControl); // Unless the entire try-delegate is dead code, delegate any pad-patches from // this try to the next try-block above relativeDepth. if (block) { - ControlInstructionVector& delegatePadPatches = + ControlInstructionVector& padPatches = control.tryControl->landingPadPatches; - if (!f.delegatePadPatches(delegatePadPatches, relativeDepth)) { + if (!delegatePadPatches(padPatches, relativeDepth)) { return false; } } - f.freeTryControl(std::move(control.tryControl)); - f.iter().popDelegate(); + rootCompiler().freeTryControl(std::move(control.tryControl)); + iter().popDelegate(); // Push the results of the previous block, and join control flow with // potential control flow patches from other instrunctions in the try code. // This is similar to what is done for EmitEnd. - if (!f.pushDefs(tryValues)) { + if (!pushDefs(tryValues)) { return false; } DefVector postJoinDefs; - if (!f.finishBlock(&postJoinDefs)) { + if (!finishBlock(&postJoinDefs)) { return false; } - MOZ_ASSERT_IF(!f.inDeadCode(), postJoinDefs.length() == resultType.length()); - f.iter().setResults(postJoinDefs.length(), postJoinDefs); + MOZ_ASSERT_IF(!inDeadCode(), postJoinDefs.length() == resultType.length()); + iter().setResults(postJoinDefs.length(), postJoinDefs); return true; } -static bool EmitThrow(FunctionCompiler& f) { +bool FunctionCompiler::emitThrow() { uint32_t tagIndex; DefVector argValues; - if (!f.iter().readThrow(&tagIndex, &argValues)) { + if (!iter().readThrow(&tagIndex, &argValues)) { return false; } - return f.emitThrow(tagIndex, argValues); + return emitThrow(tagIndex, argValues); } -static bool EmitThrowRef(FunctionCompiler& f) { +bool FunctionCompiler::emitThrowRef() { MDefinition* exnRef; - if (!f.iter().readThrowRef(&exnRef)) { + if (!iter().readThrowRef(&exnRef)) { return false; } - return f.emitThrowRef(exnRef); + return emitThrowRef(exnRef); } -static bool EmitRethrow(FunctionCompiler& f) { +bool FunctionCompiler::emitRethrow() { uint32_t relativeDepth; - if (!f.iter().readRethrow(&relativeDepth)) { + if (!iter().readRethrow(&relativeDepth)) { return false; } - return f.emitRethrow(relativeDepth); + return emitRethrow(relativeDepth); } -static bool EmitCallArgs(FunctionCompiler& f, const FuncType& funcType, - const DefVector& args, CallCompileState* call) { - for (size_t i = 0, n = funcType.args().length(); i < n; ++i) { - if (!f.mirGen().ensureBallast()) { - return false; - } - if (!f.passArg(args[i], funcType.args()[i], call)) { - return false; - } - } +bool FunctionCompiler::emitInlineCall(const FuncType& funcType, + uint32_t funcIndex, + InliningHeuristics::CallKind callKind, + const DefVector& args, + DefVector* results) { + UniqueChars error; + const BytecodeRange& funcRange = codeTailMeta()->funcDefRange(funcIndex); + BytecodeSpan funcBytecode = codeTailMeta()->funcDefBody(funcIndex); + FuncCompileInput func(funcIndex, funcRange.start, funcBytecode.data(), + funcBytecode.data() + funcBytecode.size(), + Uint32Vector()); + Decoder d(func.begin, func.end, func.lineOrBytecode, &error); - ResultType resultType = ResultType::Vector(funcType.results()); - if (!f.passStackResultAreaCallArg(resultType, call)) { + ValTypeVector locals; + if (!DecodeLocalEntriesWithParams(d, codeMeta(), funcIndex, &locals)) { return false; } - return f.finishCall(call); + CompileInfo* compileInfo = rootCompiler().startInlineCall( + this->funcIndex(), bytecodeOffset(), funcIndex, locals.length(), + funcRange.size(), callKind); + if (!compileInfo) { + return false; + } + + FunctionCompiler calleeCompiler(this, d, func, locals, *compileInfo); + if (!calleeCompiler.initInline(args)) { + MOZ_ASSERT(!error); + return false; + } + + if (!calleeCompiler.startBlock()) { + MOZ_ASSERT(!error); + return false; + } + + if (!calleeCompiler.emitBodyExprs()) { + MOZ_ASSERT(!error); + return false; + } + + calleeCompiler.finish(); + rootCompiler_.finishInlineCall(); + + return finishInlinedCallDirect(calleeCompiler, results); } -static bool EmitCall(FunctionCompiler& f, bool asmJSFuncDef) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitCall(bool asmJSFuncDef) { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t funcIndex; DefVector args; if (asmJSFuncDef) { - if (!f.iter().readOldCallDirect(f.moduleEnv().numFuncImports, &funcIndex, - &args)) { + if (!iter().readOldCallDirect(codeMeta().numFuncImports, &funcIndex, + &args)) { return false; } } else { - if (!f.iter().readCall(&funcIndex, &args)) { + if (!iter().readCall(&funcIndex, &args)) { return false; } } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - const FuncType& funcType = *f.moduleEnv().funcs[funcIndex].type; - - CallCompileState call; - if (!EmitCallArgs(f, funcType, args, &call)) { - return false; - } + const FuncType& funcType = codeMeta().getFuncType(funcIndex); DefVector results; - if (f.moduleEnv().funcIsImport(funcIndex)) { + if (codeMeta().funcIsImport(funcIndex)) { + BuiltinModuleFuncId knownFuncImport = codeMeta().knownFuncImport(funcIndex); + if (knownFuncImport != BuiltinModuleFuncId::None) { + const BuiltinModuleFunc& builtinModuleFunc = + BuiltinModuleFuncs::getFromId(knownFuncImport); + return callBuiltinModuleFunc(builtinModuleFunc, args); + } + uint32_t instanceDataOffset = - f.moduleEnv().offsetOfFuncImportInstanceData(funcIndex); - if (!f.callImport(instanceDataOffset, lineOrBytecode, call, funcType, - &results)) { + codeMeta().offsetOfFuncImportInstanceData(funcIndex); + if (!callImport(instanceDataOffset, lineOrBytecode, funcType, args, + &results)) { return false; } } else { - if (!f.callDirect(funcType, funcIndex, lineOrBytecode, call, &results)) { - return false; + const auto callKind = InliningHeuristics::CallKind::Direct; + // Make up a single-entry CallRefHint and enquire about its inlineability. + CallRefHint hints; + hints.append(funcIndex); + hints = auditInlineableCallees(callKind, hints); + if (!hints.empty()) { + // Inlining of `funcIndex` was approved. + if (!emitInlineCall(funcType, funcIndex, callKind, args, &results)) { + return false; + } + } else { + if (!callDirect(funcType, funcIndex, lineOrBytecode, args, &results)) { + return false; + } } } - f.iter().setResults(results.length(), results); + iter().setResults(results.length(), results); return true; } -static bool EmitCallIndirect(FunctionCompiler& f, bool oldStyle) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitCallIndirect(bool oldStyle) { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t funcTypeIndex; uint32_t tableIndex; @@ -5401,192 +6561,164 @@ static bool EmitCallIndirect(FunctionCompiler& f, bool oldStyle) { DefVector args; if (oldStyle) { tableIndex = 0; - if (!f.iter().readOldCallIndirect(&funcTypeIndex, &callee, &args)) { + if (!iter().readOldCallIndirect(&funcTypeIndex, &callee, &args)) { return false; } } else { - if (!f.iter().readCallIndirect(&funcTypeIndex, &tableIndex, &callee, - &args)) { + if (!iter().readCallIndirect(&funcTypeIndex, &tableIndex, &callee, &args)) { return false; } } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - const FuncType& funcType = (*f.moduleEnv().types)[funcTypeIndex].funcType(); - - CallCompileState call; - if (!EmitCallArgs(f, funcType, args, &call)) { - return false; - } - DefVector results; - if (!f.callIndirect(funcTypeIndex, tableIndex, callee, lineOrBytecode, call, - &results)) { + if (!callIndirect(funcTypeIndex, tableIndex, callee, lineOrBytecode, args, + &results)) { return false; } - f.iter().setResults(results.length(), results); + iter().setResults(results.length(), results); return true; } #ifdef ENABLE_WASM_JSPI -static bool EmitStackSwitch(FunctionCompiler& f) { +bool FunctionCompiler::emitStackSwitch() { StackSwitchKind kind; MDefinition* suspender; MDefinition* fn; MDefinition* data; - if (!f.iter().readStackSwitch(&kind, &suspender, &fn, &data)) { + if (!iter().readStackSwitch(&kind, &suspender, &fn, &data)) { return false; } - if (!f.stackSwitch(suspender, fn, data, kind)) { + MDefinition* result = stackSwitch(suspender, fn, data, kind); + if (!result) { return false; } + + if (kind == StackSwitchKind::SwitchToMain) { + iter().setResult(result); + } return true; } #endif -#ifdef ENABLE_WASM_TAIL_CALLS -static bool EmitReturnCall(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitReturnCall() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t funcIndex; DefVector args; - if (!f.iter().readReturnCall(&funcIndex, &args)) { + if (!iter().readReturnCall(&funcIndex, &args)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - const FuncType& funcType = *f.moduleEnv().funcs[funcIndex].type; - - CallCompileState call; - f.markReturnCall(&call); - if (!EmitCallArgs(f, funcType, args, &call)) { - return false; - } + const FuncType& funcType = codeMeta().getFuncType(funcIndex); DefVector results; - if (f.moduleEnv().funcIsImport(funcIndex)) { + if (codeMeta().funcIsImport(funcIndex)) { uint32_t globalDataOffset = - f.moduleEnv().offsetOfFuncImportInstanceData(funcIndex); - if (!f.returnCallImport(globalDataOffset, lineOrBytecode, call, funcType, - &results)) { + codeMeta().offsetOfFuncImportInstanceData(funcIndex); + if (!returnCallImport(globalDataOffset, lineOrBytecode, funcType, args, + &results)) { return false; } } else { - if (!f.returnCallDirect(funcType, funcIndex, lineOrBytecode, call, - &results)) { + if (!returnCallDirect(funcType, funcIndex, lineOrBytecode, args, + &results)) { return false; } } return true; } -static bool EmitReturnCallIndirect(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitReturnCallIndirect() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t funcTypeIndex; uint32_t tableIndex; MDefinition* callee; DefVector args; - if (!f.iter().readReturnCallIndirect(&funcTypeIndex, &tableIndex, &callee, - &args)) { + if (!iter().readReturnCallIndirect(&funcTypeIndex, &tableIndex, &callee, + &args)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - const FuncType& funcType = (*f.moduleEnv().types)[funcTypeIndex].funcType(); - - CallCompileState call; - f.markReturnCall(&call); - if (!EmitCallArgs(f, funcType, args, &call)) { - return false; - } - DefVector results; - return f.returnCallIndirect(funcTypeIndex, tableIndex, callee, lineOrBytecode, - call, &results); + return returnCallIndirect(funcTypeIndex, tableIndex, callee, lineOrBytecode, + args, &results); } -#endif -#if defined(ENABLE_WASM_TAIL_CALLS) && defined(ENABLE_WASM_GC) -static bool EmitReturnCallRef(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitReturnCallRef() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); - const FuncType* funcType; + uint32_t funcTypeIndex; MDefinition* callee; DefVector args; - if (!f.iter().readReturnCallRef(&funcType, &callee, &args)) { + if (!iter().readReturnCallRef(&funcTypeIndex, &callee, &args)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - CallCompileState call; - f.markReturnCall(&call); - if (!EmitCallArgs(f, *funcType, args, &call)) { - return false; - } - + const FuncType& funcType = codeMeta().types->type(funcTypeIndex).funcType(); DefVector results; - return f.returnCallRef(*funcType, callee, lineOrBytecode, call, &results); + return returnCallRef(funcType, callee, lineOrBytecode, args, &results); } -#endif -static bool EmitGetLocal(FunctionCompiler& f) { +bool FunctionCompiler::emitGetLocal() { uint32_t id; - if (!f.iter().readGetLocal(f.locals(), &id)) { + if (!iter().readGetLocal(&id)) { return false; } - f.iter().setResult(f.getLocalDef(id)); + iter().setResult(getLocalDef(id)); return true; } -static bool EmitSetLocal(FunctionCompiler& f) { +bool FunctionCompiler::emitSetLocal() { uint32_t id; MDefinition* value; - if (!f.iter().readSetLocal(f.locals(), &id, &value)) { + if (!iter().readSetLocal(&id, &value)) { return false; } - f.assign(id, value); + assign(id, value); return true; } -static bool EmitTeeLocal(FunctionCompiler& f) { +bool FunctionCompiler::emitTeeLocal() { uint32_t id; MDefinition* value; - if (!f.iter().readTeeLocal(f.locals(), &id, &value)) { + if (!iter().readTeeLocal(&id, &value)) { return false; } - f.assign(id, value); + assign(id, value); return true; } -static bool EmitGetGlobal(FunctionCompiler& f) { +bool FunctionCompiler::emitGetGlobal() { uint32_t id; - if (!f.iter().readGetGlobal(&id)) { + if (!iter().readGetGlobal(&id)) { return false; } - const GlobalDesc& global = f.moduleEnv().globals[id]; + const GlobalDesc& global = codeMeta().globals[id]; if (!global.isConstant()) { - f.iter().setResult(f.loadGlobalVar(global.offset(), !global.isMutable(), - global.isIndirect(), - global.type().toMIRType())); + iter().setResult(loadGlobalVar(global)); return true; } @@ -5595,119 +6727,115 @@ static bool EmitGetGlobal(FunctionCompiler& f) { MDefinition* result; switch (value.type().kind()) { case ValType::I32: - result = f.constantI32(int32_t(value.i32())); + result = constantI32(int32_t(value.i32())); break; case ValType::I64: - result = f.constantI64(int64_t(value.i64())); + result = constantI64(int64_t(value.i64())); break; case ValType::F32: - result = f.constantF32(value.f32()); + result = constantF32(value.f32()); break; case ValType::F64: - result = f.constantF64(value.f64()); + result = constantF64(value.f64()); break; case ValType::V128: #ifdef ENABLE_WASM_SIMD - result = f.constantV128(value.v128()); + result = constantV128(value.v128()); break; #else - return f.iter().fail("Ion has no SIMD support yet"); + return iter().fail("Ion has no SIMD support yet"); #endif case ValType::Ref: MOZ_ASSERT(value.ref().isNull()); - result = f.constantNullRef(); + result = constantNullRef(MaybeRefType(value.type().refType())); break; default: MOZ_CRASH("unexpected type in EmitGetGlobal"); } - f.iter().setResult(result); + iter().setResult(result); return true; } -static bool EmitSetGlobal(FunctionCompiler& f) { - uint32_t bytecodeOffset = f.readBytecodeOffset(); +bool FunctionCompiler::emitSetGlobal() { + uint32_t bytecodeOffset = readBytecodeOffset(); uint32_t id; MDefinition* value; - if (!f.iter().readSetGlobal(&id, &value)) { + if (!iter().readSetGlobal(&id, &value)) { return false; } - const GlobalDesc& global = f.moduleEnv().globals[id]; + const GlobalDesc& global = codeMeta().globals[id]; MOZ_ASSERT(global.isMutable()); - return f.storeGlobalVar(bytecodeOffset, global.offset(), global.isIndirect(), - value); + return storeGlobalVar(bytecodeOffset, global, value); } -static bool EmitTeeGlobal(FunctionCompiler& f) { - uint32_t bytecodeOffset = f.readBytecodeOffset(); +bool FunctionCompiler::emitTeeGlobal() { + uint32_t bytecodeOffset = readBytecodeOffset(); uint32_t id; MDefinition* value; - if (!f.iter().readTeeGlobal(&id, &value)) { + if (!iter().readTeeGlobal(&id, &value)) { return false; } - const GlobalDesc& global = f.moduleEnv().globals[id]; + const GlobalDesc& global = codeMeta().globals[id]; MOZ_ASSERT(global.isMutable()); - return f.storeGlobalVar(bytecodeOffset, global.offset(), global.isIndirect(), - value); + return storeGlobalVar(bytecodeOffset, global, value); } template -static bool EmitUnary(FunctionCompiler& f, ValType operandType) { +bool FunctionCompiler::emitUnary(ValType operandType) { MDefinition* input; - if (!f.iter().readUnary(operandType, &input)) { + if (!iter().readUnary(operandType, &input)) { return false; } - f.iter().setResult(f.unary(input)); + iter().setResult(unary(input)); return true; } template -static bool EmitConversion(FunctionCompiler& f, ValType operandType, - ValType resultType) { +bool FunctionCompiler::emitConversion(ValType operandType, ValType resultType) { MDefinition* input; - if (!f.iter().readConversion(operandType, resultType, &input)) { + if (!iter().readConversion(operandType, resultType, &input)) { return false; } - f.iter().setResult(f.unary(input)); + iter().setResult(unary(input)); return true; } template -static bool EmitUnaryWithType(FunctionCompiler& f, ValType operandType, - MIRType mirType) { +bool FunctionCompiler::emitUnaryWithType(ValType operandType, MIRType mirType) { MDefinition* input; - if (!f.iter().readUnary(operandType, &input)) { + if (!iter().readUnary(operandType, &input)) { return false; } - f.iter().setResult(f.unary(input, mirType)); + iter().setResult(unary(input, mirType)); return true; } template -static bool EmitConversionWithType(FunctionCompiler& f, ValType operandType, - ValType resultType, MIRType mirType) { +bool FunctionCompiler::emitConversionWithType(ValType operandType, + ValType resultType, + MIRType mirType) { MDefinition* input; - if (!f.iter().readConversion(operandType, resultType, &input)) { + if (!iter().readConversion(operandType, resultType, &input)) { return false; } - f.iter().setResult(f.unary(input, mirType)); + iter().setResult(unary(input, mirType)); return true; } -static bool EmitTruncate(FunctionCompiler& f, ValType operandType, - ValType resultType, bool isUnsigned, - bool isSaturating) { +bool FunctionCompiler::emitTruncate(ValType operandType, ValType resultType, + bool isUnsigned, bool isSaturating) { MDefinition* input = nullptr; - if (!f.iter().readConversion(operandType, resultType, &input)) { + if (!iter().readConversion(operandType, resultType, &input)) { return false; } @@ -5719,321 +6847,318 @@ static bool EmitTruncate(FunctionCompiler& f, ValType operandType, flags |= TRUNC_SATURATING; } if (resultType == ValType::I32) { - if (f.moduleEnv().isAsmJS()) { - if (input && (input->type() == MIRType::Double || - input->type() == MIRType::Float32)) { - f.iter().setResult(f.unary(input)); + if (codeMeta().isAsmJS()) { + if (inDeadCode()) { + // The read callsite line, produced by prepareCall, has to be + // consumed -- the MWasmBuiltinTruncateToInt32 and MTruncateToInt32 + // will not create MIR node. + (void)readCallSiteLineOrBytecode(); + iter().setResult(nullptr); + } else if (input && (input->type() == MIRType::Double || + input->type() == MIRType::Float32)) { + iter().setResult(unary(input)); } else { - f.iter().setResult(f.unary(input)); + iter().setResult(unary(input)); } } else { - f.iter().setResult(f.truncate(input, flags)); + iter().setResult(truncate(input, flags)); } } else { MOZ_ASSERT(resultType == ValType::I64); - MOZ_ASSERT(!f.moduleEnv().isAsmJS()); + MOZ_ASSERT(!codeMeta().isAsmJS()); #if defined(JS_CODEGEN_ARM) - f.iter().setResult(f.truncateWithInstance(input, flags)); + iter().setResult(truncateWithInstance(input, flags)); #else - f.iter().setResult(f.truncate(input, flags)); + iter().setResult(truncate(input, flags)); #endif } return true; } -static bool EmitSignExtend(FunctionCompiler& f, uint32_t srcSize, - uint32_t targetSize) { +bool FunctionCompiler::emitSignExtend(uint32_t srcSize, uint32_t targetSize) { MDefinition* input; ValType type = targetSize == 4 ? ValType::I32 : ValType::I64; - if (!f.iter().readConversion(type, type, &input)) { + if (!iter().readConversion(type, type, &input)) { return false; } - f.iter().setResult(f.signExtend(input, srcSize, targetSize)); + iter().setResult(signExtend(input, srcSize, targetSize)); return true; } -static bool EmitExtendI32(FunctionCompiler& f, bool isUnsigned) { +bool FunctionCompiler::emitExtendI32(bool isUnsigned) { MDefinition* input; - if (!f.iter().readConversion(ValType::I32, ValType::I64, &input)) { + if (!iter().readConversion(ValType::I32, ValType::I64, &input)) { return false; } - f.iter().setResult(f.extendI32(input, isUnsigned)); + iter().setResult(extendI32(input, isUnsigned)); return true; } -static bool EmitConvertI64ToFloatingPoint(FunctionCompiler& f, - ValType resultType, MIRType mirType, - bool isUnsigned) { +bool FunctionCompiler::emitConvertI64ToFloatingPoint(ValType resultType, + MIRType mirType, + bool isUnsigned) { MDefinition* input; - if (!f.iter().readConversion(ValType::I64, resultType, &input)) { + if (!iter().readConversion(ValType::I64, resultType, &input)) { return false; } - f.iter().setResult(f.convertI64ToFloatingPoint(input, mirType, isUnsigned)); + iter().setResult(convertI64ToFloatingPoint(input, mirType, isUnsigned)); return true; } -static bool EmitReinterpret(FunctionCompiler& f, ValType resultType, - ValType operandType, MIRType mirType) { +bool FunctionCompiler::emitReinterpret(ValType resultType, ValType operandType, + MIRType mirType) { MDefinition* input; - if (!f.iter().readConversion(operandType, resultType, &input)) { + if (!iter().readConversion(operandType, resultType, &input)) { return false; } - f.iter().setResult(f.unary(input, mirType)); + iter().setResult(unary(input, mirType)); return true; } -static bool EmitAdd(FunctionCompiler& f, ValType type, MIRType mirType) { +bool FunctionCompiler::emitAdd(ValType type, MIRType mirType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(type, &lhs, &rhs)) { + if (!iter().readBinary(type, &lhs, &rhs)) { return false; } - f.iter().setResult(f.add(lhs, rhs, mirType)); + iter().setResult(add(lhs, rhs, mirType)); return true; } -static bool EmitSub(FunctionCompiler& f, ValType type, MIRType mirType) { +bool FunctionCompiler::emitSub(ValType type, MIRType mirType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(type, &lhs, &rhs)) { + if (!iter().readBinary(type, &lhs, &rhs)) { return false; } - f.iter().setResult(f.sub(lhs, rhs, mirType)); + iter().setResult(sub(lhs, rhs, mirType)); return true; } -static bool EmitRotate(FunctionCompiler& f, ValType type, bool isLeftRotation) { +bool FunctionCompiler::emitRotate(ValType type, bool isLeftRotation) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(type, &lhs, &rhs)) { + if (!iter().readBinary(type, &lhs, &rhs)) { return false; } - MDefinition* result = f.rotate(lhs, rhs, type.toMIRType(), isLeftRotation); - f.iter().setResult(result); + MDefinition* result = rotate(lhs, rhs, type.toMIRType(), isLeftRotation); + iter().setResult(result); return true; } -static bool EmitBitNot(FunctionCompiler& f, ValType operandType) { +bool FunctionCompiler::emitBitNot(ValType operandType, MIRType mirType) { MDefinition* input; - if (!f.iter().readUnary(operandType, &input)) { + if (!iter().readUnary(operandType, &input)) { return false; } - f.iter().setResult(f.bitnot(input)); + iter().setResult(bitnot(input, mirType)); return true; } -static bool EmitBitwiseAndOrXor(FunctionCompiler& f, ValType operandType, - MIRType mirType, - MWasmBinaryBitwise::SubOpcode subOpc) { +bool FunctionCompiler::emitBitwiseAndOrXor( + ValType operandType, MIRType mirType, + MWasmBinaryBitwise::SubOpcode subOpc) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.binary(lhs, rhs, mirType, subOpc)); + iter().setResult(binary(lhs, rhs, mirType, subOpc)); return true; } template -static bool EmitShift(FunctionCompiler& f, ValType operandType, - MIRType mirType) { +bool FunctionCompiler::emitShift(ValType operandType, MIRType mirType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.binary(lhs, rhs, mirType)); + iter().setResult(binary(lhs, rhs, mirType)); return true; } -static bool EmitUrsh(FunctionCompiler& f, ValType operandType, - MIRType mirType) { +bool FunctionCompiler::emitUrsh(ValType operandType, MIRType mirType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.ursh(lhs, rhs, mirType)); + iter().setResult(ursh(lhs, rhs, mirType)); return true; } -static bool EmitMul(FunctionCompiler& f, ValType operandType, MIRType mirType) { +bool FunctionCompiler::emitMul(ValType operandType, MIRType mirType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult( - f.mul(lhs, rhs, mirType, - mirType == MIRType::Int32 ? MMul::Integer : MMul::Normal)); + iter().setResult( + mul(lhs, rhs, mirType, + mirType == MIRType::Int32 ? MMul::Integer : MMul::Normal)); return true; } -static bool EmitDiv(FunctionCompiler& f, ValType operandType, MIRType mirType, - bool isUnsigned) { +bool FunctionCompiler::emitDiv(ValType operandType, MIRType mirType, + bool isUnsigned) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.div(lhs, rhs, mirType, isUnsigned)); + iter().setResult(div(lhs, rhs, mirType, isUnsigned)); return true; } -static bool EmitRem(FunctionCompiler& f, ValType operandType, MIRType mirType, - bool isUnsigned) { +bool FunctionCompiler::emitRem(ValType operandType, MIRType mirType, + bool isUnsigned) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.mod(lhs, rhs, mirType, isUnsigned)); + iter().setResult(mod(lhs, rhs, mirType, isUnsigned)); return true; } -static bool EmitMinMax(FunctionCompiler& f, ValType operandType, - MIRType mirType, bool isMax) { +bool FunctionCompiler::emitMinMax(ValType operandType, MIRType mirType, + bool isMax) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.minMax(lhs, rhs, mirType, isMax)); + iter().setResult(minMax(lhs, rhs, mirType, isMax)); return true; } -static bool EmitCopySign(FunctionCompiler& f, ValType operandType) { +bool FunctionCompiler::emitCopySign(ValType operandType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(operandType, &lhs, &rhs)) { + if (!iter().readBinary(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.binary(lhs, rhs, operandType.toMIRType())); + iter().setResult(binary(lhs, rhs, operandType.toMIRType())); return true; } -static bool EmitComparison(FunctionCompiler& f, ValType operandType, - JSOp compareOp, MCompare::CompareType compareType) { +bool FunctionCompiler::emitComparison(ValType operandType, JSOp compareOp, + MCompare::CompareType compareType) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readComparison(operandType, &lhs, &rhs)) { + if (!iter().readComparison(operandType, &lhs, &rhs)) { return false; } - f.iter().setResult(f.compare(lhs, rhs, compareOp, compareType)); + iter().setResult(compare(lhs, rhs, compareOp, compareType)); return true; } -static bool EmitSelect(FunctionCompiler& f, bool typed) { +bool FunctionCompiler::emitSelect(bool typed) { StackType type; MDefinition* trueValue; MDefinition* falseValue; MDefinition* condition; - if (!f.iter().readSelect(typed, &type, &trueValue, &falseValue, &condition)) { + if (!iter().readSelect(typed, &type, &trueValue, &falseValue, &condition)) { return false; } - f.iter().setResult(f.select(trueValue, falseValue, condition)); + iter().setResult(select(trueValue, falseValue, condition)); return true; } -static bool EmitLoad(FunctionCompiler& f, ValType type, Scalar::Type viewType) { +bool FunctionCompiler::emitLoad(ValType type, Scalar::Type viewType) { LinearMemoryAddress addr; - if (!f.iter().readLoad(type, Scalar::byteSize(viewType), &addr)) { + if (!iter().readLoad(type, Scalar::byteSize(viewType), &addr)) { return false; } MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, - f.bytecodeIfNotAsmJS(), - f.hugeMemoryEnabled(addr.memoryIndex)); - auto* ins = f.load(addr.base, &access, type); - if (!f.inDeadCode() && !ins) { + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); + auto* ins = load(addr.base, &access, type); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitStore(FunctionCompiler& f, ValType resultType, - Scalar::Type viewType) { +bool FunctionCompiler::emitStore(ValType resultType, Scalar::Type viewType) { LinearMemoryAddress addr; MDefinition* value; - if (!f.iter().readStore(resultType, Scalar::byteSize(viewType), &addr, - &value)) { + if (!iter().readStore(resultType, Scalar::byteSize(viewType), &addr, + &value)) { return false; } MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, - f.bytecodeIfNotAsmJS(), - f.hugeMemoryEnabled(addr.memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); - f.store(addr.base, &access, value); + store(addr.base, &access, value); return true; } -static bool EmitTeeStore(FunctionCompiler& f, ValType resultType, - Scalar::Type viewType) { +bool FunctionCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType) { LinearMemoryAddress addr; MDefinition* value; - if (!f.iter().readTeeStore(resultType, Scalar::byteSize(viewType), &addr, - &value)) { + if (!iter().readTeeStore(resultType, Scalar::byteSize(viewType), &addr, + &value)) { return false; } - MOZ_ASSERT(f.isMem32(addr.memoryIndex)); // asm.js opcode + MOZ_ASSERT(isMem32(addr.memoryIndex)); // asm.js opcode MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, - f.bytecodeIfNotAsmJS(), - f.hugeMemoryEnabled(addr.memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); - f.store(addr.base, &access, value); + store(addr.base, &access, value); return true; } -static bool EmitTeeStoreWithCoercion(FunctionCompiler& f, ValType resultType, - Scalar::Type viewType) { +bool FunctionCompiler::emitTeeStoreWithCoercion(ValType resultType, + Scalar::Type viewType) { LinearMemoryAddress addr; MDefinition* value; - if (!f.iter().readTeeStore(resultType, Scalar::byteSize(viewType), &addr, - &value)) { + if (!iter().readTeeStore(resultType, Scalar::byteSize(viewType), &addr, + &value)) { return false; } if (resultType == ValType::F32 && viewType == Scalar::Float64) { - value = f.unary(value); + value = unary(value); } else if (resultType == ValType::F64 && viewType == Scalar::Float32) { - value = f.unary(value); + value = unary(value); } else { MOZ_CRASH("unexpected coerced store"); } - MOZ_ASSERT(f.isMem32(addr.memoryIndex)); // asm.js opcode + MOZ_ASSERT(isMem32(addr.memoryIndex)); // asm.js opcode MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, - f.bytecodeIfNotAsmJS(), - f.hugeMemoryEnabled(addr.memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex)); - f.store(addr.base, &access, value); + store(addr.base, &access, value); return true; } -static bool TryInlineUnaryBuiltin(FunctionCompiler& f, SymbolicAddress callee, - MDefinition* input) { +bool FunctionCompiler::tryInlineUnaryBuiltin(SymbolicAddress callee, + MDefinition* input) { if (!input) { return false; } @@ -6049,389 +7174,361 @@ static bool TryInlineUnaryBuiltin(FunctionCompiler& f, SymbolicAddress callee, return false; } - f.iter().setResult(f.nearbyInt(input, mode)); + iter().setResult(nearbyInt(input, mode)); return true; } -static bool EmitUnaryMathBuiltinCall(FunctionCompiler& f, - const SymbolicAddressSignature& callee) { +bool FunctionCompiler::emitUnaryMathBuiltinCall( + const SymbolicAddressSignature& callee) { MOZ_ASSERT(callee.numArgs == 1); - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); MDefinition* input; - if (!f.iter().readUnary(ValType::fromMIRType(callee.argTypes[0]), &input)) { + if (!iter().readUnary(ValType::fromMIRType(callee.argTypes[0]), &input)) { return false; } - if (TryInlineUnaryBuiltin(f, callee.identity, input)) { + if (tryInlineUnaryBuiltin(callee.identity, input)) { return true; } - CallCompileState call; - if (!f.passArg(input, callee.argTypes[0], &call)) { - return false; - } - - if (!f.finishCall(&call)) { - return false; - } - MDefinition* def; - if (!f.builtinCall(callee, lineOrBytecode, call, &def)) { + if (!builtinCall1(callee, lineOrBytecode, input, &def)) { return false; } - f.iter().setResult(def); + iter().setResult(def); return true; } -static bool EmitBinaryMathBuiltinCall(FunctionCompiler& f, - const SymbolicAddressSignature& callee) { +bool FunctionCompiler::emitBinaryMathBuiltinCall( + const SymbolicAddressSignature& callee) { MOZ_ASSERT(callee.numArgs == 2); MOZ_ASSERT(callee.argTypes[0] == callee.argTypes[1]); - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); - CallCompileState call; MDefinition* lhs; MDefinition* rhs; // This call to readBinary assumes both operands have the same type. - if (!f.iter().readBinary(ValType::fromMIRType(callee.argTypes[0]), &lhs, - &rhs)) { - return false; - } - - if (!f.passArg(lhs, callee.argTypes[0], &call)) { - return false; - } - - if (!f.passArg(rhs, callee.argTypes[1], &call)) { - return false; - } - - if (!f.finishCall(&call)) { + if (!iter().readBinary(ValType::fromMIRType(callee.argTypes[0]), &lhs, + &rhs)) { return false; } MDefinition* def; - if (!f.builtinCall(callee, lineOrBytecode, call, &def)) { + if (!builtinCall2(callee, lineOrBytecode, lhs, rhs, &def)) { return false; } - f.iter().setResult(def); + iter().setResult(def); return true; } -static bool EmitMemoryGrow(FunctionCompiler& f) { - uint32_t bytecodeOffset = f.readBytecodeOffset(); +bool FunctionCompiler::emitMemoryGrow() { + uint32_t bytecodeOffset = readBytecodeOffset(); MDefinition* delta; uint32_t memoryIndex; - if (!f.iter().readMemoryGrow(&memoryIndex, &delta)) { + if (!iter().readMemoryGrow(&memoryIndex, &delta)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* memoryIndexValue = f.constantI32(int32_t(memoryIndex)); + MDefinition* memoryIndexValue = constantI32(int32_t(memoryIndex)); if (!memoryIndexValue) { return false; } const SymbolicAddressSignature& callee = - f.isMem32(memoryIndex) ? SASigMemoryGrowM32 : SASigMemoryGrowM64; + isMem32(memoryIndex) ? SASigMemoryGrowM32 : SASigMemoryGrowM64; MDefinition* ret; - if (!f.emitInstanceCall2(bytecodeOffset, callee, delta, memoryIndexValue, - &ret)) { + if (!emitInstanceCall2(bytecodeOffset, callee, delta, memoryIndexValue, + &ret)) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } -static bool EmitMemorySize(FunctionCompiler& f) { - uint32_t bytecodeOffset = f.readBytecodeOffset(); +bool FunctionCompiler::emitMemorySize() { + uint32_t bytecodeOffset = readBytecodeOffset(); uint32_t memoryIndex; - if (!f.iter().readMemorySize(&memoryIndex)) { + if (!iter().readMemorySize(&memoryIndex)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* memoryIndexValue = f.constantI32(int32_t(memoryIndex)); + MDefinition* memoryIndexValue = constantI32(int32_t(memoryIndex)); if (!memoryIndexValue) { return false; } const SymbolicAddressSignature& callee = - f.isMem32(memoryIndex) ? SASigMemorySizeM32 : SASigMemorySizeM64; + isMem32(memoryIndex) ? SASigMemorySizeM32 : SASigMemorySizeM64; MDefinition* ret; - if (!f.emitInstanceCall1(bytecodeOffset, callee, memoryIndexValue, &ret)) { + if (!emitInstanceCall1(bytecodeOffset, callee, memoryIndexValue, &ret)) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } -static bool EmitAtomicCmpXchg(FunctionCompiler& f, ValType type, - Scalar::Type viewType) { +bool FunctionCompiler::emitAtomicCmpXchg(ValType type, Scalar::Type viewType) { LinearMemoryAddress addr; MDefinition* oldValue; MDefinition* newValue; - if (!f.iter().readAtomicCmpXchg(&addr, type, byteSize(viewType), &oldValue, - &newValue)) { + if (!iter().readAtomicCmpXchg(&addr, type, byteSize(viewType), &oldValue, + &newValue)) { return false; } - MemoryAccessDesc access( - addr.memoryIndex, viewType, addr.align, addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex), Synchronization::Full()); + MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex), + Synchronization::Full()); auto* ins = - f.atomicCompareExchangeHeap(addr.base, &access, type, oldValue, newValue); - if (!f.inDeadCode() && !ins) { + atomicCompareExchangeHeap(addr.base, &access, type, oldValue, newValue); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitAtomicLoad(FunctionCompiler& f, ValType type, - Scalar::Type viewType) { +bool FunctionCompiler::emitAtomicLoad(ValType type, Scalar::Type viewType) { LinearMemoryAddress addr; - if (!f.iter().readAtomicLoad(&addr, type, byteSize(viewType))) { + if (!iter().readAtomicLoad(&addr, type, byteSize(viewType))) { return false; } - MemoryAccessDesc access( - addr.memoryIndex, viewType, addr.align, addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex), Synchronization::Load()); - auto* ins = f.load(addr.base, &access, type); - if (!f.inDeadCode() && !ins) { + MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex), + Synchronization::Load()); + auto* ins = load(addr.base, &access, type); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitAtomicRMW(FunctionCompiler& f, ValType type, - Scalar::Type viewType, jit::AtomicOp op) { +bool FunctionCompiler::emitAtomicRMW(ValType type, Scalar::Type viewType, + jit::AtomicOp op) { LinearMemoryAddress addr; MDefinition* value; - if (!f.iter().readAtomicRMW(&addr, type, byteSize(viewType), &value)) { + if (!iter().readAtomicRMW(&addr, type, byteSize(viewType), &value)) { return false; } - MemoryAccessDesc access( - addr.memoryIndex, viewType, addr.align, addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex), Synchronization::Full()); - auto* ins = f.atomicBinopHeap(op, addr.base, &access, type, value); - if (!f.inDeadCode() && !ins) { + MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex), + Synchronization::Full()); + auto* ins = atomicBinopHeap(op, addr.base, &access, type, value); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitAtomicStore(FunctionCompiler& f, ValType type, - Scalar::Type viewType) { +bool FunctionCompiler::emitAtomicStore(ValType type, Scalar::Type viewType) { LinearMemoryAddress addr; MDefinition* value; - if (!f.iter().readAtomicStore(&addr, type, byteSize(viewType), &value)) { + if (!iter().readAtomicStore(&addr, type, byteSize(viewType), &value)) { return false; } - MemoryAccessDesc access( - addr.memoryIndex, viewType, addr.align, addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex), Synchronization::Store()); - f.store(addr.base, &access, value); + MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex), + Synchronization::Store()); + store(addr.base, &access, value); return true; } -static bool EmitWait(FunctionCompiler& f, ValType type, uint32_t byteSize) { +bool FunctionCompiler::emitWait(ValType type, uint32_t byteSize) { MOZ_ASSERT(type == ValType::I32 || type == ValType::I64); MOZ_ASSERT(type.size() == byteSize); - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); LinearMemoryAddress addr; MDefinition* expected; MDefinition* timeout; - if (!f.iter().readWait(&addr, type, byteSize, &expected, &timeout)) { + if (!iter().readWait(&addr, type, byteSize, &expected, &timeout)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } MemoryAccessDesc access(addr.memoryIndex, type == ValType::I32 ? Scalar::Int32 : Scalar::Int64, - addr.align, addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex)); - MDefinition* ptr = f.computeEffectiveAddress(addr.base, &access); + addr.align, addr.offset, trapSiteDesc(), + hugeMemoryEnabled(addr.memoryIndex)); + MDefinition* ptr = computeEffectiveAddress(addr.base, &access); if (!ptr) { return false; } - MDefinition* memoryIndex = f.constantI32(int32_t(addr.memoryIndex)); + MDefinition* memoryIndex = constantI32(int32_t(addr.memoryIndex)); if (!memoryIndex) { return false; } const SymbolicAddressSignature& callee = - f.isMem32(addr.memoryIndex) + isMem32(addr.memoryIndex) ? (type == ValType::I32 ? SASigWaitI32M32 : SASigWaitI64M32) : (type == ValType::I32 ? SASigWaitI32M64 : SASigWaitI64M64); MDefinition* ret; - if (!f.emitInstanceCall4(bytecodeOffset, callee, ptr, expected, timeout, - memoryIndex, &ret)) { + if (!emitInstanceCall4(bytecodeOffset, callee, ptr, expected, timeout, + memoryIndex, &ret)) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } -static bool EmitFence(FunctionCompiler& f) { - if (!f.iter().readFence()) { +bool FunctionCompiler::emitFence() { + if (!iter().readFence()) { return false; } - f.fence(); + fence(); return true; } -static bool EmitWake(FunctionCompiler& f) { - uint32_t bytecodeOffset = f.readBytecodeOffset(); +bool FunctionCompiler::emitNotify() { + uint32_t bytecodeOffset = readBytecodeOffset(); LinearMemoryAddress addr; MDefinition* count; - if (!f.iter().readWake(&addr, &count)) { + if (!iter().readNotify(&addr, &count)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } MemoryAccessDesc access(addr.memoryIndex, Scalar::Int32, addr.align, - addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex)); - MDefinition* ptr = f.computeEffectiveAddress(addr.base, &access); + addr.offset, trapSiteDesc(), + hugeMemoryEnabled(addr.memoryIndex)); + MDefinition* ptr = computeEffectiveAddress(addr.base, &access); if (!ptr) { return false; } - MDefinition* memoryIndex = f.constantI32(int32_t(addr.memoryIndex)); + MDefinition* memoryIndex = constantI32(int32_t(addr.memoryIndex)); if (!memoryIndex) { return false; } const SymbolicAddressSignature& callee = - f.isMem32(addr.memoryIndex) ? SASigWakeM32 : SASigWakeM64; + isMem32(addr.memoryIndex) ? SASigWakeM32 : SASigWakeM64; MDefinition* ret; - if (!f.emitInstanceCall3(bytecodeOffset, callee, ptr, count, memoryIndex, - &ret)) { + if (!emitInstanceCall3(bytecodeOffset, callee, ptr, count, memoryIndex, + &ret)) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } -static bool EmitAtomicXchg(FunctionCompiler& f, ValType type, - Scalar::Type viewType) { +bool FunctionCompiler::emitAtomicXchg(ValType type, Scalar::Type viewType) { LinearMemoryAddress addr; MDefinition* value; - if (!f.iter().readAtomicRMW(&addr, type, byteSize(viewType), &value)) { + if (!iter().readAtomicRMW(&addr, type, byteSize(viewType), &value)) { return false; } - MemoryAccessDesc access( - addr.memoryIndex, viewType, addr.align, addr.offset, f.bytecodeOffset(), - f.hugeMemoryEnabled(addr.memoryIndex), Synchronization::Full()); - MDefinition* ins = f.atomicExchangeHeap(addr.base, &access, type, value); - if (!f.inDeadCode() && !ins) { + MemoryAccessDesc access(addr.memoryIndex, viewType, addr.align, addr.offset, + trapSiteDesc(), hugeMemoryEnabled(addr.memoryIndex), + Synchronization::Full()); + MDefinition* ins = atomicExchangeHeap(addr.base, &access, type, value); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitMemCopyCall(FunctionCompiler& f, uint32_t dstMemIndex, - uint32_t srcMemIndex, MDefinition* dst, - MDefinition* src, MDefinition* len) { - uint32_t bytecodeOffset = f.readBytecodeOffset(); +bool FunctionCompiler::emitMemCopyCall(uint32_t dstMemIndex, + uint32_t srcMemIndex, MDefinition* dst, + MDefinition* src, MDefinition* len) { + uint32_t bytecodeOffset = readBytecodeOffset(); if (dstMemIndex == srcMemIndex) { const SymbolicAddressSignature& callee = - (f.moduleEnv().usesSharedMemory(dstMemIndex) - ? (f.isMem32(dstMemIndex) ? SASigMemCopySharedM32 - : SASigMemCopySharedM64) - : (f.isMem32(dstMemIndex) ? SASigMemCopyM32 : SASigMemCopyM64)); - MDefinition* memoryBase = f.memoryBase(dstMemIndex); - if (!memoryBase) { + (codeMeta().usesSharedMemory(dstMemIndex) + ? (isMem32(dstMemIndex) ? SASigMemCopySharedM32 + : SASigMemCopySharedM64) + : (isMem32(dstMemIndex) ? SASigMemCopyM32 : SASigMemCopyM64)); + MDefinition* base = memoryBase(dstMemIndex); + if (!base) { return false; } - return f.emitInstanceCall4(bytecodeOffset, callee, dst, src, len, - memoryBase); + return emitInstanceCall4(bytecodeOffset, callee, dst, src, len, base); } - IndexType dstIndexType = f.moduleEnv().memories[dstMemIndex].indexType(); - IndexType srcIndexType = f.moduleEnv().memories[srcMemIndex].indexType(); + AddressType dstIndexType = codeMeta().memories[dstMemIndex].addressType(); + AddressType srcIndexType = codeMeta().memories[srcMemIndex].addressType(); - if (dstIndexType == IndexType::I32) { - dst = f.extendI32(dst, /*isUnsigned=*/true); + if (dstIndexType == AddressType::I32) { + dst = extendI32(dst, /*isUnsigned=*/true); if (!dst) { return false; } } - if (srcIndexType == IndexType::I32) { - src = f.extendI32(src, /*isUnsigned=*/true); + if (srcIndexType == AddressType::I32) { + src = extendI32(src, /*isUnsigned=*/true); if (!src) { return false; } } - if (dstIndexType == IndexType::I32 || srcIndexType == IndexType::I32) { - len = f.extendI32(len, /*isUnsigned=*/true); + if (dstIndexType == AddressType::I32 || srcIndexType == AddressType::I32) { + len = extendI32(len, /*isUnsigned=*/true); if (!len) { return false; } } - MDefinition* dstMemIndexValue = f.constantI32(int32_t(dstMemIndex)); + MDefinition* dstMemIndexValue = constantI32(int32_t(dstMemIndex)); if (!dstMemIndexValue) { return false; } - MDefinition* srcMemIndexValue = f.constantI32(int32_t(srcMemIndex)); + MDefinition* srcMemIndexValue = constantI32(int32_t(srcMemIndex)); if (!srcMemIndexValue) { return false; } - return f.emitInstanceCall5(bytecodeOffset, SASigMemCopyAny, dst, src, len, - dstMemIndexValue, srcMemIndexValue); + return emitInstanceCall5(bytecodeOffset, SASigMemCopyAny, dst, src, len, + dstMemIndexValue, srcMemIndexValue); } -static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, - MDefinition* dst, MDefinition* src, - uint32_t length) { +bool FunctionCompiler::emitMemCopyInline(uint32_t memoryIndex, MDefinition* dst, + MDefinition* src, uint32_t length) { MOZ_ASSERT(length != 0 && length <= MaxInlineMemoryCopyLength); // Compute the number of copies of each width we will need to do @@ -6462,10 +7559,9 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, #ifdef ENABLE_WASM_SIMD for (uint32_t i = 0; i < numCopies16; i++) { MemoryAccessDesc access(memoryIndex, Scalar::Simd128, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - auto* load = f.load(src, &access, ValType::V128); - if (!load || !loadedValues.append(load)) { + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + auto* loadValue = load(src, &access, ValType::V128); + if (!loadValue || !loadedValues.append(loadValue)) { return false; } @@ -6476,10 +7572,9 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, #ifdef JS_64BIT for (uint32_t i = 0; i < numCopies8; i++) { MemoryAccessDesc access(memoryIndex, Scalar::Int64, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - auto* load = f.load(src, &access, ValType::I64); - if (!load || !loadedValues.append(load)) { + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + auto* loadValue = load(src, &access, ValType::I64); + if (!loadValue || !loadedValues.append(loadValue)) { return false; } @@ -6489,10 +7584,9 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, for (uint32_t i = 0; i < numCopies4; i++) { MemoryAccessDesc access(memoryIndex, Scalar::Uint32, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - auto* load = f.load(src, &access, ValType::I32); - if (!load || !loadedValues.append(load)) { + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + auto* loadValue = load(src, &access, ValType::I32); + if (!loadValue || !loadedValues.append(loadValue)) { return false; } @@ -6501,10 +7595,9 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, if (numCopies2) { MemoryAccessDesc access(memoryIndex, Scalar::Uint16, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - auto* load = f.load(src, &access, ValType::I32); - if (!load || !loadedValues.append(load)) { + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + auto* loadValue = load(src, &access, ValType::I32); + if (!loadValue || !loadedValues.append(loadValue)) { return false; } @@ -6513,10 +7606,9 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, if (numCopies1) { MemoryAccessDesc access(memoryIndex, Scalar::Uint8, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - auto* load = f.load(src, &access, ValType::I32); - if (!load || !loadedValues.append(load)) { + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + auto* loadValue = load(src, &access, ValType::I32); + if (!loadValue || !loadedValues.append(loadValue)) { return false; } } @@ -6530,30 +7622,27 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, offset -= sizeof(uint8_t); MemoryAccessDesc access(memoryIndex, Scalar::Uint8, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); auto* value = loadedValues.popCopy(); - f.store(dst, &access, value); + store(dst, &access, value); } if (numCopies2) { offset -= sizeof(uint16_t); MemoryAccessDesc access(memoryIndex, Scalar::Uint16, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); auto* value = loadedValues.popCopy(); - f.store(dst, &access, value); + store(dst, &access, value); } for (uint32_t i = 0; i < numCopies4; i++) { offset -= sizeof(uint32_t); MemoryAccessDesc access(memoryIndex, Scalar::Uint32, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); auto* value = loadedValues.popCopy(); - f.store(dst, &access, value); + store(dst, &access, value); } #ifdef JS_64BIT @@ -6561,10 +7650,9 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, offset -= sizeof(uint64_t); MemoryAccessDesc access(memoryIndex, Scalar::Int64, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); auto* value = loadedValues.popCopy(); - f.store(dst, &access, value); + store(dst, &access, value); } #endif @@ -6573,99 +7661,121 @@ static bool EmitMemCopyInline(FunctionCompiler& f, uint32_t memoryIndex, offset -= sizeof(V128); MemoryAccessDesc access(memoryIndex, Scalar::Simd128, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); auto* value = loadedValues.popCopy(); - f.store(dst, &access, value); + store(dst, &access, value); } #endif return true; } -static bool EmitMemCopy(FunctionCompiler& f) { +bool FunctionCompiler::emitMemCopy() { MDefinition *dst, *src, *len; uint32_t dstMemIndex; uint32_t srcMemIndex; - if (!f.iter().readMemOrTableCopy(true, &dstMemIndex, &dst, &srcMemIndex, &src, - &len)) { + if (!iter().readMemOrTableCopy(true, &dstMemIndex, &dst, &srcMemIndex, &src, + &len)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } if (dstMemIndex == srcMemIndex && len->isConstant()) { - uint64_t length = f.isMem32(dstMemIndex) ? len->toConstant()->toInt32() - : len->toConstant()->toInt64(); + uint64_t length = isMem32(dstMemIndex) ? len->toConstant()->toInt32() + : len->toConstant()->toInt64(); static_assert(MaxInlineMemoryCopyLength <= UINT32_MAX); if (length != 0 && length <= MaxInlineMemoryCopyLength) { - return EmitMemCopyInline(f, dstMemIndex, dst, src, uint32_t(length)); + return emitMemCopyInline(dstMemIndex, dst, src, uint32_t(length)); } } - return EmitMemCopyCall(f, dstMemIndex, srcMemIndex, dst, src, len); + return emitMemCopyCall(dstMemIndex, srcMemIndex, dst, src, len); } -static bool EmitTableCopy(FunctionCompiler& f) { +bool FunctionCompiler::emitTableCopy() { MDefinition *dst, *src, *len; uint32_t dstTableIndex; uint32_t srcTableIndex; - if (!f.iter().readMemOrTableCopy(false, &dstTableIndex, &dst, &srcTableIndex, - &src, &len)) { + if (!iter().readMemOrTableCopy(false, &dstTableIndex, &dst, &srcTableIndex, + &src, &len)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); - MDefinition* dti = f.constantI32(int32_t(dstTableIndex)); - MDefinition* sti = f.constantI32(int32_t(srcTableIndex)); + uint32_t bytecodeOffset = readBytecodeOffset(); + const TableDesc& dstTable = codeMeta().tables[dstTableIndex]; + const TableDesc& srcTable = codeMeta().tables[srcTableIndex]; - return f.emitInstanceCall5(bytecodeOffset, SASigTableCopy, dst, src, len, dti, - sti); + AddressType dstAddressType = dstTable.addressType(); + AddressType srcAddressType = srcTable.addressType(); + AddressType lenAddressType = + dstAddressType == AddressType::I64 && srcAddressType == AddressType::I64 + ? AddressType::I64 + : AddressType::I32; + + MDefinition* dst32 = tableAddressToI32(dstAddressType, dst); + if (!dst32) { + return false; + } + + MDefinition* src32 = tableAddressToI32(srcAddressType, src); + if (!src32) { + return false; + } + + MDefinition* len32 = tableAddressToI32(lenAddressType, len); + if (!len32) { + return false; + } + + MDefinition* dti = constantI32(int32_t(dstTableIndex)); + MDefinition* sti = constantI32(int32_t(srcTableIndex)); + + return emitInstanceCall5(bytecodeOffset, SASigTableCopy, dst32, src32, len32, + dti, sti); } -static bool EmitDataOrElemDrop(FunctionCompiler& f, bool isData) { +bool FunctionCompiler::emitDataOrElemDrop(bool isData) { uint32_t segIndexVal = 0; - if (!f.iter().readDataOrElemDrop(isData, &segIndexVal)) { + if (!iter().readDataOrElemDrop(isData, &segIndexVal)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); - MDefinition* segIndex = f.constantI32(int32_t(segIndexVal)); + MDefinition* segIndex = constantI32(int32_t(segIndexVal)); const SymbolicAddressSignature& callee = isData ? SASigDataDrop : SASigElemDrop; - return f.emitInstanceCall1(bytecodeOffset, callee, segIndex); + return emitInstanceCall1(bytecodeOffset, callee, segIndex); } -static bool EmitMemFillCall(FunctionCompiler& f, uint32_t memoryIndex, - MDefinition* start, MDefinition* val, - MDefinition* len) { - MDefinition* memoryBase = f.memoryBase(memoryIndex); +bool FunctionCompiler::emitMemFillCall(uint32_t memoryIndex, MDefinition* start, + MDefinition* val, MDefinition* len) { + MDefinition* base = memoryBase(memoryIndex); - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); const SymbolicAddressSignature& callee = - (f.moduleEnv().usesSharedMemory(memoryIndex) - ? (f.isMem32(memoryIndex) ? SASigMemFillSharedM32 - : SASigMemFillSharedM64) - : (f.isMem32(memoryIndex) ? SASigMemFillM32 : SASigMemFillM64)); - return f.emitInstanceCall4(bytecodeOffset, callee, start, val, len, - memoryBase); + (codeMeta().usesSharedMemory(memoryIndex) + ? (isMem32(memoryIndex) ? SASigMemFillSharedM32 + : SASigMemFillSharedM64) + : (isMem32(memoryIndex) ? SASigMemFillM32 : SASigMemFillM64)); + return emitInstanceCall4(bytecodeOffset, callee, start, val, len, base); } -static bool EmitMemFillInline(FunctionCompiler& f, uint32_t memoryIndex, - MDefinition* start, MDefinition* val, - uint32_t length) { +bool FunctionCompiler::emitMemFillInline(uint32_t memoryIndex, + MDefinition* start, MDefinition* val, + uint32_t length) { MOZ_ASSERT(length != 0 && length <= MaxInlineMemoryFillLength); uint32_t value = val->toConstant()->toInt32(); @@ -6690,18 +7800,18 @@ static bool EmitMemFillInline(FunctionCompiler& f, uint32_t memoryIndex, // Generate splatted definitions for wider fills as needed #ifdef ENABLE_WASM_SIMD - MDefinition* val16 = numCopies16 ? f.constantV128(V128(value)) : nullptr; + MDefinition* val16 = numCopies16 ? constantV128(V128(value)) : nullptr; #endif #ifdef JS_64BIT MDefinition* val8 = - numCopies8 ? f.constantI64(int64_t(SplatByteToUInt(value, 8))) + numCopies8 ? constantI64(int64_t(SplatByteToUInt(value, 8))) : nullptr; #endif MDefinition* val4 = - numCopies4 ? f.constantI32(int32_t(SplatByteToUInt(value, 4))) + numCopies4 ? constantI32(int32_t(SplatByteToUInt(value, 4))) : nullptr; MDefinition* val2 = - numCopies2 ? f.constantI32(int32_t(SplatByteToUInt(value, 2))) + numCopies2 ? constantI32(int32_t(SplatByteToUInt(value, 2))) : nullptr; // Store the fill value to the destination from high to low. We will trap @@ -6713,27 +7823,24 @@ static bool EmitMemFillInline(FunctionCompiler& f, uint32_t memoryIndex, offset -= sizeof(uint8_t); MemoryAccessDesc access(memoryIndex, Scalar::Uint8, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - f.store(start, &access, val); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + store(start, &access, val); } if (numCopies2) { offset -= sizeof(uint16_t); MemoryAccessDesc access(memoryIndex, Scalar::Uint16, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - f.store(start, &access, val2); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + store(start, &access, val2); } for (uint32_t i = 0; i < numCopies4; i++) { offset -= sizeof(uint32_t); MemoryAccessDesc access(memoryIndex, Scalar::Uint32, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - f.store(start, &access, val4); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + store(start, &access, val4); } #ifdef JS_64BIT @@ -6741,9 +7848,8 @@ static bool EmitMemFillInline(FunctionCompiler& f, uint32_t memoryIndex, offset -= sizeof(uint64_t); MemoryAccessDesc access(memoryIndex, Scalar::Int64, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - f.store(start, &access, val8); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + store(start, &access, val8); } #endif @@ -6752,144 +7858,189 @@ static bool EmitMemFillInline(FunctionCompiler& f, uint32_t memoryIndex, offset -= sizeof(V128); MemoryAccessDesc access(memoryIndex, Scalar::Simd128, 1, offset, - f.bytecodeOffset(), - f.hugeMemoryEnabled(memoryIndex)); - f.store(start, &access, val16); + trapSiteDesc(), hugeMemoryEnabled(memoryIndex)); + store(start, &access, val16); } #endif return true; } -static bool EmitMemFill(FunctionCompiler& f) { +bool FunctionCompiler::emitMemFill() { uint32_t memoryIndex; MDefinition *start, *val, *len; - if (!f.iter().readMemFill(&memoryIndex, &start, &val, &len)) { + if (!iter().readMemFill(&memoryIndex, &start, &val, &len)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } if (len->isConstant() && val->isConstant()) { - uint64_t length = f.isMem32(memoryIndex) ? len->toConstant()->toInt32() - : len->toConstant()->toInt64(); + uint64_t length = isMem32(memoryIndex) ? len->toConstant()->toInt32() + : len->toConstant()->toInt64(); static_assert(MaxInlineMemoryFillLength <= UINT32_MAX); if (length != 0 && length <= MaxInlineMemoryFillLength) { - return EmitMemFillInline(f, memoryIndex, start, val, uint32_t(length)); + return emitMemFillInline(memoryIndex, start, val, uint32_t(length)); } } - return EmitMemFillCall(f, memoryIndex, start, val, len); + return emitMemFillCall(memoryIndex, start, val, len); } -static bool EmitMemOrTableInit(FunctionCompiler& f, bool isMem) { - uint32_t segIndexVal = 0, dstMemOrTableIndex = 0; +bool FunctionCompiler::emitMemInit() { + uint32_t segIndexVal = 0, dstMemIndex = 0; MDefinition *dstOff, *srcOff, *len; - if (!f.iter().readMemOrTableInit(isMem, &segIndexVal, &dstMemOrTableIndex, - &dstOff, &srcOff, &len)) { + if (!iter().readMemOrTableInit(true, &segIndexVal, &dstMemIndex, &dstOff, + &srcOff, &len)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); const SymbolicAddressSignature& callee = - isMem - ? (f.isMem32(dstMemOrTableIndex) ? SASigMemInitM32 : SASigMemInitM64) - : SASigTableInit; + (isMem32(dstMemIndex) ? SASigMemInitM32 : SASigMemInitM64); - MDefinition* segIndex = f.constantI32(int32_t(segIndexVal)); + MDefinition* segIndex = constantI32(int32_t(segIndexVal)); if (!segIndex) { return false; } - MDefinition* dti = f.constantI32(int32_t(dstMemOrTableIndex)); + MDefinition* dti = constantI32(int32_t(dstMemIndex)); if (!dti) { return false; } - return f.emitInstanceCall5(bytecodeOffset, callee, dstOff, srcOff, len, - segIndex, dti); + return emitInstanceCall5(bytecodeOffset, callee, dstOff, srcOff, len, + segIndex, dti); } -// Note, table.{get,grow,set} on table(funcref) are currently rejected by the -// verifier. - -static bool EmitTableFill(FunctionCompiler& f) { - uint32_t tableIndex; - MDefinition *start, *val, *len; - if (!f.iter().readTableFill(&tableIndex, &start, &val, &len)) { +bool FunctionCompiler::emitTableInit() { + uint32_t segIndexVal = 0, dstTableIndex = 0; + MDefinition *dstOff, *srcOff, *len; + if (!iter().readMemOrTableInit(false, &segIndexVal, &dstTableIndex, &dstOff, + &srcOff, &len)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); + const TableDesc& table = codeMeta().tables[dstTableIndex]; - MDefinition* tableIndexArg = f.constantI32(int32_t(tableIndex)); + MDefinition* dstOff32 = tableAddressToI32(table.addressType(), dstOff); + if (!dstOff32) { + return false; + } + + MDefinition* segIndex = constantI32(int32_t(segIndexVal)); + if (!segIndex) { + return false; + } + + MDefinition* dti = constantI32(int32_t(dstTableIndex)); + if (!dti) { + return false; + } + + return emitInstanceCall5(bytecodeOffset, SASigTableInit, dstOff32, srcOff, + len, segIndex, dti); +} + +bool FunctionCompiler::emitTableFill() { + uint32_t tableIndex; + MDefinition *start, *val, *len; + if (!iter().readTableFill(&tableIndex, &start, &val, &len)) { + return false; + } + + if (inDeadCode()) { + return true; + } + + uint32_t bytecodeOffset = readBytecodeOffset(); + const TableDesc& table = codeMeta().tables[tableIndex]; + + MDefinition* start32 = tableAddressToI32(table.addressType(), start); + if (!start32) { + return false; + } + + MDefinition* len32 = tableAddressToI32(table.addressType(), len); + if (!len32) { + return false; + } + + MDefinition* tableIndexArg = constantI32(int32_t(tableIndex)); if (!tableIndexArg) { return false; } - return f.emitInstanceCall4(bytecodeOffset, SASigTableFill, start, val, len, - tableIndexArg); + return emitInstanceCall4(bytecodeOffset, SASigTableFill, start32, val, len32, + tableIndexArg); } #if ENABLE_WASM_MEMORY_CONTROL -static bool EmitMemDiscard(FunctionCompiler& f) { +bool FunctionCompiler::emitMemDiscard() { uint32_t memoryIndex; MDefinition *start, *len; - if (!f.iter().readMemDiscard(&memoryIndex, &start, &len)) { + if (!iter().readMemDiscard(&memoryIndex, &start, &len)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); - MDefinition* memoryBase = f.memoryBase(memoryIndex); - bool isMem32 = f.isMem32(memoryIndex); + MDefinition* base = memoryBase(memoryIndex); + bool mem32 = isMem32(memoryIndex); const SymbolicAddressSignature& callee = - (f.moduleEnv().usesSharedMemory(memoryIndex) - ? (isMem32 ? SASigMemDiscardSharedM32 : SASigMemDiscardSharedM64) - : (isMem32 ? SASigMemDiscardM32 : SASigMemDiscardM64)); - return f.emitInstanceCall3(bytecodeOffset, callee, start, len, memoryBase); + (codeMeta().usesSharedMemory(memoryIndex) + ? (mem32 ? SASigMemDiscardSharedM32 : SASigMemDiscardSharedM64) + : (mem32 ? SASigMemDiscardM32 : SASigMemDiscardM64)); + return emitInstanceCall3(bytecodeOffset, callee, start, len, base); } #endif -static bool EmitTableGet(FunctionCompiler& f) { +bool FunctionCompiler::emitTableGet() { uint32_t tableIndex; - MDefinition* index; - if (!f.iter().readTableGet(&tableIndex, &index)) { + MDefinition* address; + if (!iter().readTableGet(&tableIndex, &address)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - const TableDesc& table = f.moduleEnv().tables[tableIndex]; + const TableDesc& table = codeMeta().tables[tableIndex]; + + MDefinition* address32 = tableAddressToI32(table.addressType(), address); + if (!address32) { + return false; + } + if (table.elemType.tableRepr() == TableRepr::Ref) { - MDefinition* ret = f.tableGetAnyRef(tableIndex, index); + MDefinition* ret = tableGetAnyRef(tableIndex, address32); if (!ret) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); - MDefinition* tableIndexArg = f.constantI32(int32_t(tableIndex)); + MDefinition* tableIndexArg = constantI32(int32_t(tableIndex)); if (!tableIndexArg) { return false; } @@ -6897,104 +8048,130 @@ static bool EmitTableGet(FunctionCompiler& f) { // The return value here is either null, denoting an error, or a short-lived // pointer to a location containing a possibly-null ref. MDefinition* ret; - if (!f.emitInstanceCall2(bytecodeOffset, SASigTableGet, index, tableIndexArg, - &ret)) { + if (!emitInstanceCall2(bytecodeOffset, SASigTableGet, address32, + tableIndexArg, &ret)) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } -static bool EmitTableGrow(FunctionCompiler& f) { +bool FunctionCompiler::emitTableGrow() { uint32_t tableIndex; MDefinition* initValue; MDefinition* delta; - if (!f.iter().readTableGrow(&tableIndex, &initValue, &delta)) { + if (!iter().readTableGrow(&tableIndex, &initValue, &delta)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); + const TableDesc& table = codeMeta().tables[tableIndex]; - MDefinition* tableIndexArg = f.constantI32(int32_t(tableIndex)); + MDefinition* delta32 = tableAddressToI32(table.addressType(), delta); + if (!delta32) { + return false; + } + + MDefinition* tableIndexArg = constantI32(int32_t(tableIndex)); if (!tableIndexArg) { return false; } MDefinition* ret; - if (!f.emitInstanceCall3(bytecodeOffset, SASigTableGrow, initValue, delta, - tableIndexArg, &ret)) { + if (!emitInstanceCall3(bytecodeOffset, SASigTableGrow, initValue, delta32, + tableIndexArg, &ret)) { return false; } - f.iter().setResult(ret); + if (table.addressType() == AddressType::I64) { + ret = extendI32(ret, false); + if (!ret) { + return false; + } + } + + iter().setResult(ret); return true; } -static bool EmitTableSet(FunctionCompiler& f) { +bool FunctionCompiler::emitTableSet() { uint32_t tableIndex; - MDefinition* index; + MDefinition* address; MDefinition* value; - if (!f.iter().readTableSet(&tableIndex, &index, &value)) { + if (!iter().readTableSet(&tableIndex, &address, &value)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); - const TableDesc& table = f.moduleEnv().tables[tableIndex]; - if (table.elemType.tableRepr() == TableRepr::Ref) { - return f.tableSetAnyRef(tableIndex, index, value, bytecodeOffset); + const TableDesc& table = codeMeta().tables[tableIndex]; + + MDefinition* address32 = tableAddressToI32(table.addressType(), address); + if (!address32) { + return false; } - MDefinition* tableIndexArg = f.constantI32(int32_t(tableIndex)); + if (table.elemType.tableRepr() == TableRepr::Ref) { + return tableSetAnyRef(tableIndex, address32, value, bytecodeOffset); + } + + MDefinition* tableIndexArg = constantI32(int32_t(tableIndex)); if (!tableIndexArg) { return false; } - return f.emitInstanceCall3(bytecodeOffset, SASigTableSet, index, value, - tableIndexArg); + return emitInstanceCall3(bytecodeOffset, SASigTableSet, address32, value, + tableIndexArg); } -static bool EmitTableSize(FunctionCompiler& f) { +bool FunctionCompiler::emitTableSize() { uint32_t tableIndex; - if (!f.iter().readTableSize(&tableIndex)) { + if (!iter().readTableSize(&tableIndex)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* length = f.loadTableLength(tableIndex); + MDefinition* length = loadTableLength(tableIndex); if (!length) { return false; } - f.iter().setResult(length); + if (codeMeta().tables[tableIndex].addressType() == AddressType::I64) { + length = extendI32(length, true); + if (!length) { + return false; + } + } + + iter().setResult(length); return true; } -static bool EmitRefFunc(FunctionCompiler& f) { +bool FunctionCompiler::emitRefFunc() { uint32_t funcIndex; - if (!f.iter().readRefFunc(&funcIndex)) { + if (!iter().readRefFunc(&funcIndex)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); + uint32_t bytecodeOffset = readBytecodeOffset(); - MDefinition* funcIndexArg = f.constantI32(int32_t(funcIndex)); + MDefinition* funcIndexArg = constantI32(int32_t(funcIndex)); if (!funcIndexArg) { return false; } @@ -7002,323 +8179,455 @@ static bool EmitRefFunc(FunctionCompiler& f) { // The return value here is either null, denoting an error, or a short-lived // pointer to a location containing a possibly-null ref. MDefinition* ret; - if (!f.emitInstanceCall1(bytecodeOffset, SASigRefFunc, funcIndexArg, &ret)) { + if (!emitInstanceCall1(bytecodeOffset, SASigRefFunc, funcIndexArg, &ret)) { return false; } - f.iter().setResult(ret); + iter().setResult(ret); return true; } -static bool EmitRefNull(FunctionCompiler& f) { +bool FunctionCompiler::emitRefNull() { RefType type; - if (!f.iter().readRefNull(&type)) { + if (!iter().readRefNull(&type)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* nullVal = f.constantNullRef(); + MDefinition* nullVal = constantNullRef(MaybeRefType(type)); if (!nullVal) { return false; } - f.iter().setResult(nullVal); + iter().setResult(nullVal); return true; } -static bool EmitRefIsNull(FunctionCompiler& f) { +bool FunctionCompiler::emitRefIsNull() { MDefinition* input; - if (!f.iter().readRefIsNull(&input)) { + if (!iter().readRefIsNull(&input)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* nullVal = f.constantNullRef(); + MDefinition* nullVal = constantNullRef(MaybeRefType()); if (!nullVal) { return false; } - f.iter().setResult( - f.compare(input, nullVal, JSOp::Eq, MCompare::Compare_WasmAnyRef)); + iter().setResult( + compare(input, nullVal, JSOp::Eq, MCompare::Compare_WasmAnyRef)); return true; } #ifdef ENABLE_WASM_SIMD -static bool EmitConstSimd128(FunctionCompiler& f) { +bool FunctionCompiler::emitConstSimd128() { V128 v128; - if (!f.iter().readV128Const(&v128)) { + if (!iter().readV128Const(&v128)) { return false; } - f.iter().setResult(f.constantV128(v128)); + iter().setResult(constantV128(v128)); return true; } -static bool EmitBinarySimd128(FunctionCompiler& f, bool commutative, - SimdOp op) { +bool FunctionCompiler::emitBinarySimd128(bool commutative, SimdOp op) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readBinary(ValType::V128, &lhs, &rhs)) { + if (!iter().readBinary(ValType::V128, &lhs, &rhs)) { return false; } - f.iter().setResult(f.binarySimd128(lhs, rhs, commutative, op)); + iter().setResult(binarySimd128(lhs, rhs, commutative, op)); return true; } -static bool EmitTernarySimd128(FunctionCompiler& f, wasm::SimdOp op) { +bool FunctionCompiler::emitTernarySimd128(wasm::SimdOp op) { MDefinition* v0; MDefinition* v1; MDefinition* v2; - if (!f.iter().readTernary(ValType::V128, &v0, &v1, &v2)) { + if (!iter().readTernary(ValType::V128, &v0, &v1, &v2)) { return false; } - f.iter().setResult(f.ternarySimd128(v0, v1, v2, op)); + iter().setResult(ternarySimd128(v0, v1, v2, op)); return true; } -static bool EmitShiftSimd128(FunctionCompiler& f, SimdOp op) { +bool FunctionCompiler::emitShiftSimd128(SimdOp op) { MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readVectorShift(&lhs, &rhs)) { + if (!iter().readVectorShift(&lhs, &rhs)) { return false; } - f.iter().setResult(f.shiftSimd128(lhs, rhs, op)); + iter().setResult(shiftSimd128(lhs, rhs, op)); return true; } -static bool EmitSplatSimd128(FunctionCompiler& f, ValType inType, SimdOp op) { +bool FunctionCompiler::emitSplatSimd128(ValType inType, SimdOp op) { MDefinition* src; - if (!f.iter().readConversion(inType, ValType::V128, &src)) { + if (!iter().readConversion(inType, ValType::V128, &src)) { return false; } - f.iter().setResult(f.scalarToSimd128(src, op)); + iter().setResult(scalarToSimd128(src, op)); return true; } -static bool EmitUnarySimd128(FunctionCompiler& f, SimdOp op) { +bool FunctionCompiler::emitUnarySimd128(SimdOp op) { MDefinition* src; - if (!f.iter().readUnary(ValType::V128, &src)) { + if (!iter().readUnary(ValType::V128, &src)) { return false; } - f.iter().setResult(f.unarySimd128(src, op)); + iter().setResult(unarySimd128(src, op)); return true; } -static bool EmitReduceSimd128(FunctionCompiler& f, SimdOp op) { +bool FunctionCompiler::emitReduceSimd128(SimdOp op) { MDefinition* src; - if (!f.iter().readConversion(ValType::V128, ValType::I32, &src)) { + if (!iter().readConversion(ValType::V128, ValType::I32, &src)) { return false; } - f.iter().setResult(f.reduceSimd128(src, op, ValType::I32)); + iter().setResult(reduceSimd128(src, op, ValType::I32)); return true; } -static bool EmitExtractLaneSimd128(FunctionCompiler& f, ValType outType, - uint32_t laneLimit, SimdOp op) { +bool FunctionCompiler::emitExtractLaneSimd128(ValType outType, + uint32_t laneLimit, SimdOp op) { uint32_t laneIndex; MDefinition* src; - if (!f.iter().readExtractLane(outType, laneLimit, &laneIndex, &src)) { + if (!iter().readExtractLane(outType, laneLimit, &laneIndex, &src)) { return false; } - f.iter().setResult(f.reduceSimd128(src, op, outType, laneIndex)); + iter().setResult(reduceSimd128(src, op, outType, laneIndex)); return true; } -static bool EmitReplaceLaneSimd128(FunctionCompiler& f, ValType laneType, - uint32_t laneLimit, SimdOp op) { +bool FunctionCompiler::emitReplaceLaneSimd128(ValType laneType, + uint32_t laneLimit, SimdOp op) { uint32_t laneIndex; MDefinition* lhs; MDefinition* rhs; - if (!f.iter().readReplaceLane(laneType, laneLimit, &laneIndex, &lhs, &rhs)) { + if (!iter().readReplaceLane(laneType, laneLimit, &laneIndex, &lhs, &rhs)) { return false; } - f.iter().setResult(f.replaceLaneSimd128(lhs, rhs, laneIndex, op)); + iter().setResult(replaceLaneSimd128(lhs, rhs, laneIndex, op)); return true; } -static bool EmitShuffleSimd128(FunctionCompiler& f) { +bool FunctionCompiler::emitShuffleSimd128() { MDefinition* v1; MDefinition* v2; V128 control; - if (!f.iter().readVectorShuffle(&v1, &v2, &control)) { + if (!iter().readVectorShuffle(&v1, &v2, &control)) { return false; } - f.iter().setResult(f.shuffleSimd128(v1, v2, control)); + iter().setResult(shuffleSimd128(v1, v2, control)); return true; } -static bool EmitLoadSplatSimd128(FunctionCompiler& f, Scalar::Type viewType, - wasm::SimdOp splatOp) { +bool FunctionCompiler::emitLoadSplatSimd128(Scalar::Type viewType, + wasm::SimdOp splatOp) { LinearMemoryAddress addr; - if (!f.iter().readLoadSplat(Scalar::byteSize(viewType), &addr)) { + if (!iter().readLoadSplat(Scalar::byteSize(viewType), &addr)) { return false; } - auto* ins = f.loadSplatSimd128(viewType, addr, splatOp); - if (!f.inDeadCode() && !ins) { + auto* ins = loadSplatSimd128(viewType, addr, splatOp); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitLoadExtendSimd128(FunctionCompiler& f, wasm::SimdOp op) { +bool FunctionCompiler::emitLoadExtendSimd128(wasm::SimdOp op) { LinearMemoryAddress addr; - if (!f.iter().readLoadExtend(&addr)) { + if (!iter().readLoadExtend(&addr)) { return false; } - auto* ins = f.loadExtendSimd128(addr, op); - if (!f.inDeadCode() && !ins) { + auto* ins = loadExtendSimd128(addr, op); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitLoadZeroSimd128(FunctionCompiler& f, Scalar::Type viewType, - size_t numBytes) { +bool FunctionCompiler::emitLoadZeroSimd128(Scalar::Type viewType, + size_t numBytes) { LinearMemoryAddress addr; - if (!f.iter().readLoadSplat(numBytes, &addr)) { + if (!iter().readLoadSplat(numBytes, &addr)) { return false; } - auto* ins = f.loadZeroSimd128(viewType, numBytes, addr); - if (!f.inDeadCode() && !ins) { + auto* ins = loadZeroSimd128(viewType, numBytes, addr); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitLoadLaneSimd128(FunctionCompiler& f, uint32_t laneSize) { +bool FunctionCompiler::emitLoadLaneSimd128(uint32_t laneSize) { uint32_t laneIndex; MDefinition* src; LinearMemoryAddress addr; - if (!f.iter().readLoadLane(laneSize, &addr, &laneIndex, &src)) { + if (!iter().readLoadLane(laneSize, &addr, &laneIndex, &src)) { return false; } - auto* ins = f.loadLaneSimd128(laneSize, addr, laneIndex, src); - if (!f.inDeadCode() && !ins) { + auto* ins = loadLaneSimd128(laneSize, addr, laneIndex, src); + if (!inDeadCode() && !ins) { return false; } - f.iter().setResult(ins); + iter().setResult(ins); return true; } -static bool EmitStoreLaneSimd128(FunctionCompiler& f, uint32_t laneSize) { +bool FunctionCompiler::emitStoreLaneSimd128(uint32_t laneSize) { uint32_t laneIndex; MDefinition* src; LinearMemoryAddress addr; - if (!f.iter().readStoreLane(laneSize, &addr, &laneIndex, &src)) { + if (!iter().readStoreLane(laneSize, &addr, &laneIndex, &src)) { return false; } - f.storeLaneSimd128(laneSize, addr, laneIndex, src); + storeLaneSimd128(laneSize, addr, laneIndex, src); return true; } #endif // ENABLE_WASM_SIMD -#ifdef ENABLE_WASM_GC -static bool EmitRefAsNonNull(FunctionCompiler& f) { +bool FunctionCompiler::emitRefAsNonNull() { MDefinition* ref; - if (!f.iter().readRefAsNonNull(&ref)) { + if (!iter().readRefAsNonNull(&ref)) { return false; } - return f.refAsNonNull(ref); -} - -static bool EmitBrOnNull(FunctionCompiler& f) { - uint32_t relativeDepth; - ResultType type; - DefVector values; - MDefinition* condition; - if (!f.iter().readBrOnNull(&relativeDepth, &type, &values, &condition)) { - return false; - } - - return f.brOnNull(relativeDepth, values, type, condition); -} - -static bool EmitBrOnNonNull(FunctionCompiler& f) { - uint32_t relativeDepth; - ResultType type; - DefVector values; - MDefinition* condition; - if (!f.iter().readBrOnNonNull(&relativeDepth, &type, &values, &condition)) { - return false; - } - - return f.brOnNonNull(relativeDepth, values, type, condition); -} - -static bool EmitCallRef(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); - - const FuncType* funcType; - MDefinition* callee; - DefVector args; - - if (!f.iter().readCallRef(&funcType, &callee, &args)) { - return false; - } - - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - CallCompileState call; - if (!EmitCallArgs(f, *funcType, args, &call)) { + MDefinition* ins = refAsNonNull(ref); + if (!ins) { return false; } - DefVector results; - if (!f.callRef(*funcType, callee, lineOrBytecode, call, &results)) { - return false; - } - - f.iter().setResults(results.length(), results); + iter().setResult(ins); return true; } -#endif // ENABLE_WASM_GC - -#ifdef ENABLE_WASM_GC - -static bool EmitStructNew(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); - - uint32_t typeIndex; - DefVector args; - if (!f.iter().readStructNew(&typeIndex, &args)) { +bool FunctionCompiler::emitBrOnNull() { + uint32_t relativeDepth; + ResultType type; + DefVector values; + MDefinition* condition; + if (!iter().readBrOnNull(&relativeDepth, &type, &values, &condition)) { return false; } - if (f.inDeadCode()) { + return brOnNull(relativeDepth, values, type, condition); +} + +bool FunctionCompiler::emitBrOnNonNull() { + uint32_t relativeDepth; + ResultType type; + DefVector values; + MDefinition* condition; + if (!iter().readBrOnNonNull(&relativeDepth, &type, &values, &condition)) { + return false; + } + + return brOnNonNull(relativeDepth, values, type, condition); +} + +// Speculatively inline a call_refs that are likely to target the expected +// function index in this module. A fallback for if the actual callee is not +// any of the speculated expected callees is always generated. This leads to a +// control flow chain that is roughly: +// +// if (ref.func $expectedFuncIndex_1) == actualCalleeFunc: +// (call_inline $expectedFuncIndex1) +// else if (ref.func $expectedFuncIndex_2) == actualCalleeFunc: +// (call_inline $expectedFuncIndex2) +// ... +// else: +// (call_ref actualCalleeFunc) +// +bool FunctionCompiler::emitSpeculativeInlineCallRef( + uint32_t bytecodeOffset, const FuncType& funcType, + CallRefHint expectedFuncIndices, MDefinition* actualCalleeFunc, + const DefVector& args, DefVector* results) { + // There must be at least one speculative target. + MOZ_ASSERT(!expectedFuncIndices.empty()); + + // Perform an up front null check on the callee function reference. + actualCalleeFunc = refAsNonNull(actualCalleeFunc); + if (!actualCalleeFunc) { + return false; + } + + constexpr size_t numElseBlocks = CallRefHint::NUM_ENTRIES + 1; + Vector elseBlocks; + if (!elseBlocks.reserve(numElseBlocks)) { + return false; + } + + for (uint32_t i = 0; i < expectedFuncIndices.length(); i++) { + uint32_t funcIndex = expectedFuncIndices.get(i); + + // Load the cached value of `ref.func $expectedFuncIndex` for comparing + // against `actualCalleeFunc`. This cached value may be null if the + // `ref.func` for the expected function has not been executed in this + // runtime session. + // + // This is okay because we have done a null check on the `actualCalleeFunc` + // already and so comparing it against a null expected callee func will + // return false and fall back to the general case. This can only happen if + // we've deserialized a cached module in a different session, and then run + // the code without ever acquiring a reference to the expected function. In + // that case, the expected callee could never be the target of this + // call_ref, so performing the fallback path is the right thing to do + // anyways. + MDefinition* expectedCalleeFunc = loadCachedRefFunc(funcIndex); + if (!expectedCalleeFunc) { + return false; + } + + // Check if the callee funcref we have is equals to the expected callee + // funcref we're inlining. + MDefinition* isExpectedCallee = + compare(actualCalleeFunc, expectedCalleeFunc, JSOp::Eq, + MCompare::Compare_WasmAnyRef); + if (!isExpectedCallee) { + return false; + } + + // Start a 'then' block, which will have the inlined code + MBasicBlock* elseBlock; + if (!branchAndStartThen(isExpectedCallee, &elseBlock)) { + return false; + } + + // Inline the expected callee as we do with direct calls + DefVector inlineResults; + if (!emitInlineCall(funcType, funcIndex, + InliningHeuristics::CallKind::CallRef, args, + &inlineResults)) { + return false; + } + + // Push the results for joining with the 'else' block + if (!pushDefs(inlineResults)) { + return false; + } + + // Switch to the 'else' block which will have, either the check for the + // next target, or the fallback `call_ref` if we're out of targets. + if (!switchToElse(elseBlock, &elseBlock)) { + return false; + } + + elseBlocks.infallibleAppend(elseBlock); + } + + DefVector callResults; + if (!callRef(funcType, actualCalleeFunc, bytecodeOffset, args, + &callResults)) { + return false; + } + + // Push the results for joining with the 'then' block + if (!pushDefs(callResults)) { + return false; + } + + // Join the various branches together + for (uint32_t i = elseBlocks.length() - 1; i != 0; i--) { + DefVector results; + if (!joinIfElse(elseBlocks[i], &results) || !pushDefs(results)) { + return false; + } + } + return joinIfElse(elseBlocks[0], results); +} + +bool FunctionCompiler::emitCallRef() { + uint32_t bytecodeOffset = readBytecodeOffset(); + uint32_t funcTypeIndex; + MDefinition* callee; + DefVector args; + + if (!iter().readCallRef(&funcTypeIndex, &callee, &args)) { + return false; + } + + // We must unconditionally read a call_ref hint so that we stay in sync with + // how baseline generates them. + CallRefHint hint = readCallRefHint(); + + if (inDeadCode()) { return true; } - const TypeDef& typeDef = (*f.moduleEnv().types)[typeIndex]; + const FuncType& funcType = codeMeta().types->type(funcTypeIndex).funcType(); + + // Ask the inlining heuristics which entries in `hint` we are allowed to + // inline. + CallRefHint approved = + auditInlineableCallees(InliningHeuristics::CallKind::CallRef, hint); + if (!approved.empty()) { + DefVector results; + if (!emitSpeculativeInlineCallRef(bytecodeOffset, funcType, approved, + callee, args, &results)) { + return false; + } + iter().setResults(results.length(), results); + return true; + } + + DefVector results; + if (!callRef(funcType, callee, bytecodeOffset, args, &results)) { + return false; + } + + iter().setResults(results.length(), results); + return true; +} + +bool FunctionCompiler::emitStructNew() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); + + uint32_t typeIndex; + DefVector args; + if (!iter().readStructNew(&typeIndex, &args)) { + return false; + } + + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { + return true; + } + + const TypeDef& typeDef = (*codeMeta().types)[typeIndex]; const StructType& structType = typeDef.structType(); MOZ_ASSERT(args.length() == structType.fields_.length()); - MDefinition* structObject = f.createStructObject(typeIndex, false); + MDefinition* structObject = + createStructObject(typeIndex, allocSiteIndex, false); if (!structObject) { return false; } @@ -7326,197 +8635,183 @@ static bool EmitStructNew(FunctionCompiler& f) { // And fill in the fields. for (uint32_t fieldIndex = 0; fieldIndex < structType.fields_.length(); fieldIndex++) { - if (!f.mirGen().ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } - if (!f.writeValueToStructField(lineOrBytecode, structType, fieldIndex, - structObject, args[fieldIndex], - WasmPreBarrierKind::None)) { + if (!writeValueToStructField(lineOrBytecode, structType, fieldIndex, + structObject, args[fieldIndex], + WasmPreBarrierKind::None)) { return false; } } - f.iter().setResult(structObject); + iter().setResult(structObject); return true; } -static bool EmitStructNewDefault(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); - +bool FunctionCompiler::emitStructNewDefault() { uint32_t typeIndex; - if (!f.iter().readStructNewDefault(&typeIndex)) { + if (!iter().readStructNewDefault(&typeIndex)) { return false; } - if (f.inDeadCode()) { + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { return true; } - const StructType& structType = (*f.moduleEnv().types)[typeIndex].structType(); - - // Allocate a default initialized struct. This requires the type definition - // for the struct. - MDefinition* typeDefData = f.loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { + MDefinition* structObject = + createStructObject(typeIndex, allocSiteIndex, true); + if (!structObject) { return false; } - // Figure out whether we need an OOL storage area, and hence which routine - // to call. - SymbolicAddressSignature calleeSASig = - WasmStructObject::requiresOutlineBytes(structType.size_) - ? SASigStructNewOOL_true - : SASigStructNewIL_true; - - // Create call: structObject = Instance::structNew{IL,OOL}(typeDefData) - MDefinition* structObject; - if (!f.emitInstanceCall1(lineOrBytecode, calleeSASig, typeDefData, - &structObject)) { - return false; - } - - f.iter().setResult(structObject); + iter().setResult(structObject); return true; } -static bool EmitStructSet(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitStructSet() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex; uint32_t fieldIndex; MDefinition* structObject; MDefinition* value; - if (!f.iter().readStructSet(&typeIndex, &fieldIndex, &structObject, &value)) { + if (!iter().readStructSet(&typeIndex, &fieldIndex, &structObject, &value)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } // Check for null is done at writeValueToStructField. // And fill in the field. - const StructType& structType = (*f.moduleEnv().types)[typeIndex].structType(); - return f.writeValueToStructField(lineOrBytecode, structType, fieldIndex, - structObject, value, - WasmPreBarrierKind::Normal); + const StructType& structType = (*codeMeta().types)[typeIndex].structType(); + return writeValueToStructField(lineOrBytecode, structType, fieldIndex, + structObject, value, + WasmPreBarrierKind::Normal); } -static bool EmitStructGet(FunctionCompiler& f, FieldWideningOp wideningOp) { +bool FunctionCompiler::emitStructGet(FieldWideningOp wideningOp) { uint32_t typeIndex; uint32_t fieldIndex; MDefinition* structObject; - if (!f.iter().readStructGet(&typeIndex, &fieldIndex, wideningOp, - &structObject)) { + if (!iter().readStructGet(&typeIndex, &fieldIndex, wideningOp, + &structObject)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } // Check for null is done at readValueFromStructField. // And fetch the data. - const StructType& structType = (*f.moduleEnv().types)[typeIndex].structType(); - MDefinition* load = f.readValueFromStructField(structType, fieldIndex, - wideningOp, structObject); + const StructType& structType = (*codeMeta().types)[typeIndex].structType(); + MDefinition* load = readValueFromStructField(structType, fieldIndex, + wideningOp, structObject); if (!load) { return false; } - f.iter().setResult(load); + iter().setResult(load); return true; } -static bool EmitArrayNew(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayNew() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex; MDefinition* numElements; MDefinition* fillValue; - if (!f.iter().readArrayNew(&typeIndex, &numElements, &fillValue)) { + if (!iter().readArrayNew(&typeIndex, &numElements, &fillValue)) { return false; } - if (f.inDeadCode()) { + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { return true; } // If the requested size exceeds MaxArrayPayloadBytes, the MIR generated by // this helper will trap. - MDefinition* arrayObject = f.createArrayNewCallAndLoop( - lineOrBytecode, typeIndex, numElements, fillValue); + MDefinition* arrayObject = createArrayNewCallAndLoop( + lineOrBytecode, typeIndex, allocSiteIndex, numElements, fillValue); if (!arrayObject) { return false; } - f.iter().setResult(arrayObject); + iter().setResult(arrayObject); return true; } -static bool EmitArrayNewDefault(FunctionCompiler& f) { +bool FunctionCompiler::emitArrayNewDefault() { // This is almost identical to EmitArrayNew, except we skip the // initialisation loop. - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); - uint32_t typeIndex; MDefinition* numElements; - if (!f.iter().readArrayNewDefault(&typeIndex, &numElements)) { + if (!iter().readArrayNewDefault(&typeIndex, &numElements)) { return false; } - if (f.inDeadCode()) { + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { return true; } // Create the array object, default-initialized. - const ArrayType& arrayType = (*f.moduleEnv().types)[typeIndex].arrayType(); MDefinition* arrayObject = - f.createArrayObject(lineOrBytecode, typeIndex, numElements, - arrayType.elementType().size(), /*zeroFields=*/true); + createArrayObject(typeIndex, allocSiteIndex, numElements, + /*zeroFields=*/true); if (!arrayObject) { return false; } - f.iter().setResult(arrayObject); + iter().setResult(arrayObject); return true; } -static bool EmitArrayNewFixed(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayNewFixed() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex, numElements; DefVector values; - if (!f.iter().readArrayNewFixed(&typeIndex, &numElements, &values)) { + if (!iter().readArrayNewFixed(&typeIndex, &numElements, &values)) { return false; } MOZ_ASSERT(values.length() == numElements); - if (f.inDeadCode()) { + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { return true; } - MDefinition* numElementsDef = f.constantI32(int32_t(numElements)); + MDefinition* numElementsDef = constantI32(int32_t(numElements)); if (!numElementsDef) { return false; } // Create the array object, uninitialized. - const ArrayType& arrayType = (*f.moduleEnv().types)[typeIndex].arrayType(); + const ArrayType& arrayType = (*codeMeta().types)[typeIndex].arrayType(); StorageType elemType = arrayType.elementType(); uint32_t elemSize = elemType.size(); MDefinition* arrayObject = - f.createArrayObject(lineOrBytecode, typeIndex, numElementsDef, elemSize, - /*zeroFields=*/false); + createArrayObject(typeIndex, allocSiteIndex, numElementsDef, + /*zeroFields=*/false); if (!arrayObject) { return false; } // Make `base` point at the first byte of the (OOL) data area. - MDefinition* base = f.getWasmArrayObjectData(arrayObject); + MDefinition* base = getWasmArrayObjectData(arrayObject); if (!base) { return false; } @@ -7534,45 +8829,51 @@ static bool EmitArrayNewFixed(FunctionCompiler& f) { MOZ_RELEASE_ASSERT(numElements <= MaxFunctionBytes); for (uint32_t i = 0; i < numElements; i++) { - if (!f.mirGen().ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } // `i * elemSize` is made safe by the assertions above. - if (!f.writeGcValueAtBasePlusOffset( + if (!writeGcValueAtBasePlusOffset( lineOrBytecode, elemType, arrayObject, AliasSet::WasmArrayDataArea, - values[numElements - 1 - i], base, i * elemSize, false, + values[numElements - 1 - i], base, i * elemSize, i, false, WasmPreBarrierKind::None)) { return false; } } - f.iter().setResult(arrayObject); + iter().setResult(arrayObject); return true; } -static bool EmitArrayNewData(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayNewData() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex, segIndex; MDefinition* segByteOffset; MDefinition* numElements; - if (!f.iter().readArrayNewData(&typeIndex, &segIndex, &segByteOffset, - &numElements)) { + if (!iter().readArrayNewData(&typeIndex, &segIndex, &segByteOffset, + &numElements)) { return false; } - if (f.inDeadCode()) { + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { return true; } - // Get the type definition data for the array as a whole. - MDefinition* typeDefData = f.loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { + MDefinition* typeIndexValue = constantI32(int32_t(typeIndex)); + if (!typeIndexValue) { + return false; + } + + MDefinition* allocSite = loadAllocSiteInstanceData(allocSiteIndex); + if (!allocSite) { return false; } // Other values we need to pass to the instance call: - MDefinition* segIndexM = f.constantI32(int32_t(segIndex)); + MDefinition* segIndexM = constantI32(int32_t(segIndex)); if (!segIndexM) { return false; } @@ -7583,39 +8884,45 @@ static bool EmitArrayNewData(FunctionCompiler& f) { // If the requested size exceeds MaxArrayPayloadBytes, the MIR generated by // this call will trap. MDefinition* arrayObject; - if (!f.emitInstanceCall4(lineOrBytecode, SASigArrayNewData, segByteOffset, - numElements, typeDefData, segIndexM, &arrayObject)) { + if (!emitInstanceCall5(lineOrBytecode, SASigArrayNewData, segByteOffset, + numElements, typeIndexValue, allocSite, segIndexM, + &arrayObject)) { return false; } - f.iter().setResult(arrayObject); + iter().setResult(arrayObject); return true; } -static bool EmitArrayNewElem(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayNewElem() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex, segIndex; MDefinition* segElemIndex; MDefinition* numElements; - if (!f.iter().readArrayNewElem(&typeIndex, &segIndex, &segElemIndex, - &numElements)) { + if (!iter().readArrayNewElem(&typeIndex, &segIndex, &segElemIndex, + &numElements)) { return false; } - if (f.inDeadCode()) { + uint32_t allocSiteIndex = readAllocSiteIndex(typeIndex); + + if (inDeadCode()) { return true; } - // Get the type definition for the array as a whole. - // Get the type definition data for the array as a whole. - MDefinition* typeDefData = f.loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { + MDefinition* typeIndexValue = constantI32(int32_t(typeIndex)); + if (!typeIndexValue) { + return false; + } + + MDefinition* allocSite = loadAllocSiteInstanceData(allocSiteIndex); + if (!allocSite) { return false; } // Other values we need to pass to the instance call: - MDefinition* segIndexM = f.constantI32(int32_t(segIndex)); + MDefinition* segIndexM = constantI32(int32_t(segIndex)); if (!segIndexM) { return false; } @@ -7626,78 +8933,71 @@ static bool EmitArrayNewElem(FunctionCompiler& f) { // If the requested size exceeds MaxArrayPayloadBytes, the MIR generated by // this call will trap. MDefinition* arrayObject; - if (!f.emitInstanceCall4(lineOrBytecode, SASigArrayNewElem, segElemIndex, - numElements, typeDefData, segIndexM, &arrayObject)) { + if (!emitInstanceCall5(lineOrBytecode, SASigArrayNewElem, segElemIndex, + numElements, typeIndexValue, allocSite, segIndexM, + &arrayObject)) { return false; } - f.iter().setResult(arrayObject); + iter().setResult(arrayObject); return true; } -static bool EmitArrayInitData(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayInitData() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); - uint32_t typeIndex, segIndex; + uint32_t unusedTypeIndex, segIndex; MDefinition* array; MDefinition* arrayIndex; MDefinition* segOffset; MDefinition* length; - if (!f.iter().readArrayInitData(&typeIndex, &segIndex, &array, &arrayIndex, - &segOffset, &length)) { + if (!iter().readArrayInitData(&unusedTypeIndex, &segIndex, &array, + &arrayIndex, &segOffset, &length)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - // Get the type definition data for the array as a whole. - MDefinition* typeDefData = f.loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { - return false; - } - // Other values we need to pass to the instance call: - MDefinition* segIndexM = f.constantI32(int32_t(segIndex)); + MDefinition* segIndexM = constantI32(int32_t(segIndex)); if (!segIndexM) { return false; } // Create call: // Instance::arrayInitData(array:word, index:u32, segByteOffset:u32, - // numElements:u32, typeDefData:word, segIndex:u32) If the requested size - // exceeds MaxArrayPayloadBytes, the MIR generated by this call will trap. - return f.emitInstanceCall6(lineOrBytecode, SASigArrayInitData, array, - arrayIndex, segOffset, length, typeDefData, - segIndexM); + // numElements:u32, segIndex:u32) If the requested size exceeds + // MaxArrayPayloadBytes, the MIR generated by this call will trap. + return emitInstanceCall5(lineOrBytecode, SASigArrayInitData, array, + arrayIndex, segOffset, length, segIndexM); } -static bool EmitArrayInitElem(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayInitElem() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex, segIndex; MDefinition* array; MDefinition* arrayIndex; MDefinition* segOffset; MDefinition* length; - if (!f.iter().readArrayInitElem(&typeIndex, &segIndex, &array, &arrayIndex, - &segOffset, &length)) { + if (!iter().readArrayInitElem(&typeIndex, &segIndex, &array, &arrayIndex, + &segOffset, &length)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - // Get the type definition data for the array as a whole. - MDefinition* typeDefData = f.loadTypeDefInstanceData(typeIndex); - if (!typeDefData) { + MDefinition* typeIndexValue = constantI32(int32_t(typeIndex)); + if (!typeIndexValue) { return false; } // Other values we need to pass to the instance call: - MDefinition* segIndexM = f.constantI32(int32_t(segIndex)); + MDefinition* segIndexM = constantI32(int32_t(segIndex)); if (!segIndexM) { return false; } @@ -7706,23 +9006,23 @@ static bool EmitArrayInitElem(FunctionCompiler& f) { // Instance::arrayInitElem(array:word, index:u32, segByteOffset:u32, // numElements:u32, typeDefData:word, segIndex:u32) If the requested size // exceeds MaxArrayPayloadBytes, the MIR generated by this call will trap. - return f.emitInstanceCall6(lineOrBytecode, SASigArrayInitElem, array, - arrayIndex, segOffset, length, typeDefData, - segIndexM); + return emitInstanceCall6(lineOrBytecode, SASigArrayInitElem, array, + arrayIndex, segOffset, length, typeIndexValue, + segIndexM); } -static bool EmitArraySet(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArraySet() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex; MDefinition* value; MDefinition* index; MDefinition* arrayObject; - if (!f.iter().readArraySet(&typeIndex, &value, &index, &arrayObject)) { + if (!iter().readArraySet(&typeIndex, &value, &index, &arrayObject)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } @@ -7730,31 +9030,31 @@ static bool EmitArraySet(FunctionCompiler& f) { // Create the object null check and the array bounds check and get the OOL // data pointer. - MDefinition* base = f.setupForArrayAccess(arrayObject, index); + MDefinition* base = setupForArrayAccess(arrayObject, index); if (!base) { return false; } // And do the store. - const ArrayType& arrayType = (*f.moduleEnv().types)[typeIndex].arrayType(); + const ArrayType& arrayType = (*codeMeta().types)[typeIndex].arrayType(); StorageType elemType = arrayType.elementType(); uint32_t elemSize = elemType.size(); MOZ_ASSERT(elemSize >= 1 && elemSize <= 16); - return f.writeGcValueAtBasePlusScaledIndex( + return writeGcValueAtBasePlusScaledIndex( lineOrBytecode, elemType, arrayObject, AliasSet::WasmArrayDataArea, value, base, elemSize, index, WasmPreBarrierKind::Normal); } -static bool EmitArrayGet(FunctionCompiler& f, FieldWideningOp wideningOp) { +bool FunctionCompiler::emitArrayGet(FieldWideningOp wideningOp) { uint32_t typeIndex; MDefinition* index; MDefinition* arrayObject; - if (!f.iter().readArrayGet(&typeIndex, wideningOp, &index, &arrayObject)) { + if (!iter().readArrayGet(&typeIndex, wideningOp, &index, &arrayObject)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } @@ -7762,290 +9062,250 @@ static bool EmitArrayGet(FunctionCompiler& f, FieldWideningOp wideningOp) { // Create the object null check and the array bounds check and get the data // pointer. - MDefinition* base = f.setupForArrayAccess(arrayObject, index); + MDefinition* base = setupForArrayAccess(arrayObject, index); if (!base) { return false; } // And do the load. - const ArrayType& arrayType = (*f.moduleEnv().types)[typeIndex].arrayType(); + const ArrayType& arrayType = (*codeMeta().types)[typeIndex].arrayType(); StorageType elemType = arrayType.elementType(); MDefinition* load = - f.readGcArrayValueAtIndex(elemType, wideningOp, arrayObject, - AliasSet::WasmArrayDataArea, base, index); + readGcArrayValueAtIndex(elemType, wideningOp, arrayObject, + AliasSet::WasmArrayDataArea, base, index); if (!load) { return false; } - f.iter().setResult(load); + iter().setResult(load); return true; } -static bool EmitArrayLen(FunctionCompiler& f) { +bool FunctionCompiler::emitArrayLen() { MDefinition* arrayObject; - if (!f.iter().readArrayLen(&arrayObject)) { + if (!iter().readArrayLen(&arrayObject)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } // Check for null is done at getWasmArrayObjectNumElements. // Get the size value for the array - MDefinition* numElements = f.getWasmArrayObjectNumElements(arrayObject); + MDefinition* numElements = getWasmArrayObjectNumElements(arrayObject); if (!numElements) { return false; } - f.iter().setResult(numElements); + iter().setResult(numElements); return true; } -static bool EmitArrayCopy(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayCopy() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); - int32_t elemSize; - bool elemsAreRefTyped; + uint32_t dstArrayTypeIndex; + uint32_t srcArrayTypeIndex; MDefinition* dstArrayObject; MDefinition* dstArrayIndex; MDefinition* srcArrayObject; MDefinition* srcArrayIndex; MDefinition* numElements; - if (!f.iter().readArrayCopy(&elemSize, &elemsAreRefTyped, &dstArrayObject, - &dstArrayIndex, &srcArrayObject, &srcArrayIndex, - &numElements)) { + if (!iter().readArrayCopy(&dstArrayTypeIndex, &srcArrayTypeIndex, + &dstArrayObject, &dstArrayIndex, &srcArrayObject, + &srcArrayIndex, &numElements)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MOZ_ASSERT_IF(elemsAreRefTyped, - size_t(elemSize) == MIRTypeToSize(TargetWordMIRType())); - MOZ_ASSERT_IF(!elemsAreRefTyped, elemSize == 1 || elemSize == 2 || - elemSize == 4 || elemSize == 8 || - elemSize == 16); + const ArrayType& dstArrayType = + codeMeta().types->type(dstArrayTypeIndex).arrayType(); + StorageType dstElemType = dstArrayType.elementType(); + int32_t elemSize = int32_t(dstElemType.size()); + bool elemsAreRefTyped = dstElemType.isRefType(); - // A negative element size is used to inform Instance::arrayCopy that the - // values are reftyped. This avoids having to pass it an extra boolean - // argument. - MDefinition* elemSizeDef = - f.constantI32(elemsAreRefTyped ? -elemSize : elemSize); - if (!elemSizeDef) { - return false; - } - - // Create call: - // Instance::arrayCopy(dstArrayObject:word, dstArrayIndex:u32, - // srcArrayObject:word, srcArrayIndex:u32, - // numElements:u32, - // (elemsAreRefTyped ? -elemSize : elemSize):u32)) - return f.emitInstanceCall6(lineOrBytecode, SASigArrayCopy, dstArrayObject, - dstArrayIndex, srcArrayObject, srcArrayIndex, - numElements, elemSizeDef); + return createArrayCopy(lineOrBytecode, dstArrayObject, dstArrayIndex, + srcArrayObject, srcArrayIndex, numElements, elemSize, + elemsAreRefTyped); } -static bool EmitArrayFill(FunctionCompiler& f) { - uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode(); +bool FunctionCompiler::emitArrayFill() { + uint32_t lineOrBytecode = readCallSiteLineOrBytecode(); uint32_t typeIndex; MDefinition* array; MDefinition* index; MDefinition* val; MDefinition* numElements; - if (!f.iter().readArrayFill(&typeIndex, &array, &index, &val, &numElements)) { + if (!iter().readArrayFill(&typeIndex, &array, &index, &val, &numElements)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - return f.createArrayFill(lineOrBytecode, typeIndex, array, index, val, - numElements); + return createArrayFill(lineOrBytecode, typeIndex, array, index, val, + numElements); } -static bool EmitRefI31(FunctionCompiler& f) { +bool FunctionCompiler::emitRefI31() { MDefinition* input; - if (!f.iter().readConversion( - ValType::I32, ValType(RefType::i31().asNonNullable()), &input)) { + if (!iter().readConversion(ValType::I32, + ValType(RefType::i31().asNonNullable()), &input)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* output = f.refI31(input); + MDefinition* output = refI31(input); if (!output) { return false; } - f.iter().setResult(output); + iter().setResult(output); return true; } -static bool EmitI31Get(FunctionCompiler& f, FieldWideningOp wideningOp) { +bool FunctionCompiler::emitI31Get(FieldWideningOp wideningOp) { MOZ_ASSERT(wideningOp != FieldWideningOp::None); MDefinition* input; - if (!f.iter().readConversion(ValType(RefType::i31()), ValType::I32, &input)) { + if (!iter().readConversion(ValType(RefType::i31()), ValType::I32, &input)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - if (!f.refAsNonNull(input)) { + input = refAsNonNull(input); + if (!input) { return false; } - MDefinition* output = f.i31Get(input, wideningOp); + MDefinition* output = i31Get(input, wideningOp); if (!output) { return false; } - f.iter().setResult(output); + iter().setResult(output); return true; } -static bool EmitRefTest(FunctionCompiler& f, bool nullable) { +bool FunctionCompiler::emitRefTest(bool nullable) { MDefinition* ref; RefType sourceType; RefType destType; - if (!f.iter().readRefTest(nullable, &sourceType, &destType, &ref)) { + if (!iter().readRefTest(nullable, &sourceType, &destType, &ref)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - MDefinition* success = f.refTest(ref, sourceType, destType); + MDefinition* success = refTest(ref, destType); if (!success) { return false; } - f.iter().setResult(success); + iter().setResult(success); return true; } -static bool EmitRefCast(FunctionCompiler& f, bool nullable) { +bool FunctionCompiler::emitRefCast(bool nullable) { MDefinition* ref; RefType sourceType; RefType destType; - if (!f.iter().readRefCast(nullable, &sourceType, &destType, &ref)) { + if (!iter().readRefCast(nullable, &sourceType, &destType, &ref)) { return false; } - if (f.inDeadCode()) { + if (inDeadCode()) { return true; } - if (!f.refCast(ref, sourceType, destType)) { + MDefinition* castedRef = refCast(ref, destType); + if (!castedRef) { return false; } - f.iter().setResult(ref); + iter().setResult(castedRef); return true; } -static bool EmitBrOnCast(FunctionCompiler& f, bool onSuccess) { +bool FunctionCompiler::emitBrOnCast(bool onSuccess) { uint32_t labelRelativeDepth; RefType sourceType; RefType destType; ResultType labelType; DefVector values; - if (!f.iter().readBrOnCast(onSuccess, &labelRelativeDepth, &sourceType, - &destType, &labelType, &values)) { + if (!iter().readBrOnCast(onSuccess, &labelRelativeDepth, &sourceType, + &destType, &labelType, &values)) { return false; } - return f.brOnCastCommon(onSuccess, labelRelativeDepth, sourceType, destType, - labelType, values); + return brOnCastCommon(onSuccess, labelRelativeDepth, sourceType, destType, + labelType, values); } -static bool EmitAnyConvertExtern(FunctionCompiler& f) { - // any.convert_extern is a no-op because anyref and extern share the same - // representation +bool FunctionCompiler::emitAnyConvertExtern() { MDefinition* ref; - if (!f.iter().readRefConversion(RefType::extern_(), RefType::any(), &ref)) { + if (!iter().readRefConversion(RefType::extern_(), RefType::any(), &ref)) { return false; } - f.iter().setResult(ref); + if (inDeadCode()) { + return true; + } + + MDefinition* conversion = convertAnyExtern(ref, wasm::RefType::Kind::Any); + if (!conversion) { + return false; + } + + iter().setResult(conversion); return true; } -static bool EmitExternConvertAny(FunctionCompiler& f) { - // extern.convert_any is a no-op because anyref and extern share the same - // representation +bool FunctionCompiler::emitExternConvertAny() { MDefinition* ref; - if (!f.iter().readRefConversion(RefType::any(), RefType::extern_(), &ref)) { + if (!iter().readRefConversion(RefType::any(), RefType::extern_(), &ref)) { return false; } - f.iter().setResult(ref); + if (inDeadCode()) { + return true; + } + + MDefinition* conversion = convertAnyExtern(ref, wasm::RefType::Kind::Extern); + if (!conversion) { + return false; + } + + iter().setResult(conversion); return true; } -#endif // ENABLE_WASM_GC - -static bool EmitCallBuiltinModuleFunc(FunctionCompiler& f) { - // It's almost possible to use FunctionCompiler::emitInstanceCallN here. - // Unfortunately not currently possible though, since ::emitInstanceCallN - // expects an array of arguments along with a size, and that's not what is - // available here. It would be possible if we were prepared to copy - // `builtinModuleFunc->params` into a fixed-sized (16 element?) array, add - // `memoryBase`, and make the call. +bool FunctionCompiler::emitCallBuiltinModuleFunc() { const BuiltinModuleFunc* builtinModuleFunc; DefVector params; - if (!f.iter().readCallBuiltinModuleFunc(&builtinModuleFunc, ¶ms)) { + if (!iter().readCallBuiltinModuleFunc(&builtinModuleFunc, ¶ms)) { return false; } - uint32_t bytecodeOffset = f.readBytecodeOffset(); - const SymbolicAddressSignature& callee = *builtinModuleFunc->sig(); - - CallCompileState args; - if (!f.passInstance(callee.argTypes[0], &args)) { - return false; - } - - if (!f.passArgs(params, builtinModuleFunc->funcType()->args(), &args)) { - return false; - } - - if (builtinModuleFunc->usesMemory()) { - MDefinition* memoryBase = f.memoryBase(0); - if (!f.passArg(memoryBase, MIRType::Pointer, &args)) { - return false; - } - } - - if (!f.finishCall(&args)) { - return false; - } - - bool hasResult = !builtinModuleFunc->funcType()->results().empty(); - MDefinition* result = nullptr; - MDefinition** resultOutParam = hasResult ? &result : nullptr; - if (!f.builtinInstanceMethodCall(callee, bytecodeOffset, args, - resultOutParam)) { - return false; - } - - if (hasResult) { - f.iter().setResult(result); - } - return true; + return callBuiltinModuleFunc(*builtinModuleFunc, params); } -static bool EmitBodyExprs(FunctionCompiler& f) { - if (!f.iter().startFunction(f.funcIndex(), f.locals())) { +bool FunctionCompiler::emitBodyExprs() { + if (!iter().startFunction(funcIndex())) { return false; } @@ -8054,623 +9314,553 @@ static bool EmitBodyExprs(FunctionCompiler& f) { break while (true) { - if (!f.mirGen().ensureBallast()) { + if (!mirGen().ensureBallast()) { return false; } OpBytes op; - if (!f.iter().readOp(&op)) { + if (!iter().readOp(&op)) { return false; } switch (op.b0) { case uint16_t(Op::End): - if (!EmitEnd(f)) { + if (!emitEnd()) { return false; } - if (f.iter().controlStackEmpty()) { + if (iter().controlStackEmpty()) { return true; } break; // Control opcodes case uint16_t(Op::Unreachable): - CHECK(EmitUnreachable(f)); + CHECK(emitUnreachable()); case uint16_t(Op::Nop): - CHECK(f.iter().readNop()); + CHECK(iter().readNop()); case uint16_t(Op::Block): - CHECK(EmitBlock(f)); + CHECK(emitBlock()); case uint16_t(Op::Loop): - CHECK(EmitLoop(f)); + CHECK(emitLoop()); case uint16_t(Op::If): - CHECK(EmitIf(f)); + CHECK(emitIf()); case uint16_t(Op::Else): - CHECK(EmitElse(f)); + CHECK(emitElse()); case uint16_t(Op::Try): - CHECK(EmitTry(f)); + CHECK(emitTry()); case uint16_t(Op::Catch): - CHECK(EmitCatch(f)); + CHECK(emitCatch()); case uint16_t(Op::CatchAll): - CHECK(EmitCatchAll(f)); + CHECK(emitCatchAll()); case uint16_t(Op::Delegate): - if (!EmitDelegate(f)) { - return false; - } - break; + CHECK(emitDelegate()); case uint16_t(Op::Throw): - CHECK(EmitThrow(f)); + CHECK(emitThrow()); case uint16_t(Op::Rethrow): - CHECK(EmitRethrow(f)); + CHECK(emitRethrow()); case uint16_t(Op::ThrowRef): - if (!f.moduleEnv().exnrefEnabled()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().exnrefEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitThrowRef(f)); + CHECK(emitThrowRef()); case uint16_t(Op::TryTable): - if (!f.moduleEnv().exnrefEnabled()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().exnrefEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitTryTable(f)); + CHECK(emitTryTable()); case uint16_t(Op::Br): - CHECK(EmitBr(f)); + CHECK(emitBr()); case uint16_t(Op::BrIf): - CHECK(EmitBrIf(f)); + CHECK(emitBrIf()); case uint16_t(Op::BrTable): - CHECK(EmitBrTable(f)); + CHECK(emitBrTable()); case uint16_t(Op::Return): - CHECK(EmitReturn(f)); + CHECK(emitReturn()); // Calls case uint16_t(Op::Call): - CHECK(EmitCall(f, /* asmJSFuncDef = */ false)); + CHECK(emitCall(/* asmJSFuncDef = */ false)); case uint16_t(Op::CallIndirect): - CHECK(EmitCallIndirect(f, /* oldStyle = */ false)); + CHECK(emitCallIndirect(/* oldStyle = */ false)); // Parametric operators case uint16_t(Op::Drop): - CHECK(f.iter().readDrop()); + CHECK(iter().readDrop()); case uint16_t(Op::SelectNumeric): - CHECK(EmitSelect(f, /*typed*/ false)); + CHECK(emitSelect(/*typed*/ false)); case uint16_t(Op::SelectTyped): - CHECK(EmitSelect(f, /*typed*/ true)); + CHECK(emitSelect(/*typed*/ true)); // Locals and globals case uint16_t(Op::LocalGet): - CHECK(EmitGetLocal(f)); + CHECK(emitGetLocal()); case uint16_t(Op::LocalSet): - CHECK(EmitSetLocal(f)); + CHECK(emitSetLocal()); case uint16_t(Op::LocalTee): - CHECK(EmitTeeLocal(f)); + CHECK(emitTeeLocal()); case uint16_t(Op::GlobalGet): - CHECK(EmitGetGlobal(f)); + CHECK(emitGetGlobal()); case uint16_t(Op::GlobalSet): - CHECK(EmitSetGlobal(f)); + CHECK(emitSetGlobal()); case uint16_t(Op::TableGet): - CHECK(EmitTableGet(f)); + CHECK(emitTableGet()); case uint16_t(Op::TableSet): - CHECK(EmitTableSet(f)); + CHECK(emitTableSet()); // Memory-related operators case uint16_t(Op::I32Load): - CHECK(EmitLoad(f, ValType::I32, Scalar::Int32)); + CHECK(emitLoad(ValType::I32, Scalar::Int32)); case uint16_t(Op::I64Load): - CHECK(EmitLoad(f, ValType::I64, Scalar::Int64)); + CHECK(emitLoad(ValType::I64, Scalar::Int64)); case uint16_t(Op::F32Load): - CHECK(EmitLoad(f, ValType::F32, Scalar::Float32)); + CHECK(emitLoad(ValType::F32, Scalar::Float32)); case uint16_t(Op::F64Load): - CHECK(EmitLoad(f, ValType::F64, Scalar::Float64)); + CHECK(emitLoad(ValType::F64, Scalar::Float64)); case uint16_t(Op::I32Load8S): - CHECK(EmitLoad(f, ValType::I32, Scalar::Int8)); + CHECK(emitLoad(ValType::I32, Scalar::Int8)); case uint16_t(Op::I32Load8U): - CHECK(EmitLoad(f, ValType::I32, Scalar::Uint8)); + CHECK(emitLoad(ValType::I32, Scalar::Uint8)); case uint16_t(Op::I32Load16S): - CHECK(EmitLoad(f, ValType::I32, Scalar::Int16)); + CHECK(emitLoad(ValType::I32, Scalar::Int16)); case uint16_t(Op::I32Load16U): - CHECK(EmitLoad(f, ValType::I32, Scalar::Uint16)); + CHECK(emitLoad(ValType::I32, Scalar::Uint16)); case uint16_t(Op::I64Load8S): - CHECK(EmitLoad(f, ValType::I64, Scalar::Int8)); + CHECK(emitLoad(ValType::I64, Scalar::Int8)); case uint16_t(Op::I64Load8U): - CHECK(EmitLoad(f, ValType::I64, Scalar::Uint8)); + CHECK(emitLoad(ValType::I64, Scalar::Uint8)); case uint16_t(Op::I64Load16S): - CHECK(EmitLoad(f, ValType::I64, Scalar::Int16)); + CHECK(emitLoad(ValType::I64, Scalar::Int16)); case uint16_t(Op::I64Load16U): - CHECK(EmitLoad(f, ValType::I64, Scalar::Uint16)); + CHECK(emitLoad(ValType::I64, Scalar::Uint16)); case uint16_t(Op::I64Load32S): - CHECK(EmitLoad(f, ValType::I64, Scalar::Int32)); + CHECK(emitLoad(ValType::I64, Scalar::Int32)); case uint16_t(Op::I64Load32U): - CHECK(EmitLoad(f, ValType::I64, Scalar::Uint32)); + CHECK(emitLoad(ValType::I64, Scalar::Uint32)); case uint16_t(Op::I32Store): - CHECK(EmitStore(f, ValType::I32, Scalar::Int32)); + CHECK(emitStore(ValType::I32, Scalar::Int32)); case uint16_t(Op::I64Store): - CHECK(EmitStore(f, ValType::I64, Scalar::Int64)); + CHECK(emitStore(ValType::I64, Scalar::Int64)); case uint16_t(Op::F32Store): - CHECK(EmitStore(f, ValType::F32, Scalar::Float32)); + CHECK(emitStore(ValType::F32, Scalar::Float32)); case uint16_t(Op::F64Store): - CHECK(EmitStore(f, ValType::F64, Scalar::Float64)); + CHECK(emitStore(ValType::F64, Scalar::Float64)); case uint16_t(Op::I32Store8): - CHECK(EmitStore(f, ValType::I32, Scalar::Int8)); + CHECK(emitStore(ValType::I32, Scalar::Int8)); case uint16_t(Op::I32Store16): - CHECK(EmitStore(f, ValType::I32, Scalar::Int16)); + CHECK(emitStore(ValType::I32, Scalar::Int16)); case uint16_t(Op::I64Store8): - CHECK(EmitStore(f, ValType::I64, Scalar::Int8)); + CHECK(emitStore(ValType::I64, Scalar::Int8)); case uint16_t(Op::I64Store16): - CHECK(EmitStore(f, ValType::I64, Scalar::Int16)); + CHECK(emitStore(ValType::I64, Scalar::Int16)); case uint16_t(Op::I64Store32): - CHECK(EmitStore(f, ValType::I64, Scalar::Int32)); + CHECK(emitStore(ValType::I64, Scalar::Int32)); case uint16_t(Op::MemorySize): - CHECK(EmitMemorySize(f)); + CHECK(emitMemorySize()); case uint16_t(Op::MemoryGrow): - CHECK(EmitMemoryGrow(f)); + CHECK(emitMemoryGrow()); // Constants case uint16_t(Op::I32Const): - CHECK(EmitI32Const(f)); + CHECK(emitI32Const()); case uint16_t(Op::I64Const): - CHECK(EmitI64Const(f)); + CHECK(emitI64Const()); case uint16_t(Op::F32Const): - CHECK(EmitF32Const(f)); + CHECK(emitF32Const()); case uint16_t(Op::F64Const): - CHECK(EmitF64Const(f)); + CHECK(emitF64Const()); // Comparison operators case uint16_t(Op::I32Eqz): - CHECK(EmitConversion(f, ValType::I32, ValType::I32)); + CHECK(emitConversion(ValType::I32, ValType::I32)); case uint16_t(Op::I32Eq): - CHECK( - EmitComparison(f, ValType::I32, JSOp::Eq, MCompare::Compare_Int32)); + CHECK(emitComparison(ValType::I32, JSOp::Eq, MCompare::Compare_Int32)); case uint16_t(Op::I32Ne): - CHECK( - EmitComparison(f, ValType::I32, JSOp::Ne, MCompare::Compare_Int32)); + CHECK(emitComparison(ValType::I32, JSOp::Ne, MCompare::Compare_Int32)); case uint16_t(Op::I32LtS): - CHECK( - EmitComparison(f, ValType::I32, JSOp::Lt, MCompare::Compare_Int32)); + CHECK(emitComparison(ValType::I32, JSOp::Lt, MCompare::Compare_Int32)); case uint16_t(Op::I32LtU): - CHECK(EmitComparison(f, ValType::I32, JSOp::Lt, - MCompare::Compare_UInt32)); + CHECK(emitComparison(ValType::I32, JSOp::Lt, MCompare::Compare_UInt32)); case uint16_t(Op::I32GtS): - CHECK( - EmitComparison(f, ValType::I32, JSOp::Gt, MCompare::Compare_Int32)); + CHECK(emitComparison(ValType::I32, JSOp::Gt, MCompare::Compare_Int32)); case uint16_t(Op::I32GtU): - CHECK(EmitComparison(f, ValType::I32, JSOp::Gt, - MCompare::Compare_UInt32)); + CHECK(emitComparison(ValType::I32, JSOp::Gt, MCompare::Compare_UInt32)); case uint16_t(Op::I32LeS): - CHECK( - EmitComparison(f, ValType::I32, JSOp::Le, MCompare::Compare_Int32)); + CHECK(emitComparison(ValType::I32, JSOp::Le, MCompare::Compare_Int32)); case uint16_t(Op::I32LeU): - CHECK(EmitComparison(f, ValType::I32, JSOp::Le, - MCompare::Compare_UInt32)); + CHECK(emitComparison(ValType::I32, JSOp::Le, MCompare::Compare_UInt32)); case uint16_t(Op::I32GeS): - CHECK( - EmitComparison(f, ValType::I32, JSOp::Ge, MCompare::Compare_Int32)); + CHECK(emitComparison(ValType::I32, JSOp::Ge, MCompare::Compare_Int32)); case uint16_t(Op::I32GeU): - CHECK(EmitComparison(f, ValType::I32, JSOp::Ge, - MCompare::Compare_UInt32)); + CHECK(emitComparison(ValType::I32, JSOp::Ge, MCompare::Compare_UInt32)); case uint16_t(Op::I64Eqz): - CHECK(EmitConversion(f, ValType::I64, ValType::I32)); + CHECK(emitConversion(ValType::I64, ValType::I32)); case uint16_t(Op::I64Eq): - CHECK( - EmitComparison(f, ValType::I64, JSOp::Eq, MCompare::Compare_Int64)); + CHECK(emitComparison(ValType::I64, JSOp::Eq, MCompare::Compare_Int64)); case uint16_t(Op::I64Ne): - CHECK( - EmitComparison(f, ValType::I64, JSOp::Ne, MCompare::Compare_Int64)); + CHECK(emitComparison(ValType::I64, JSOp::Ne, MCompare::Compare_Int64)); case uint16_t(Op::I64LtS): - CHECK( - EmitComparison(f, ValType::I64, JSOp::Lt, MCompare::Compare_Int64)); + CHECK(emitComparison(ValType::I64, JSOp::Lt, MCompare::Compare_Int64)); case uint16_t(Op::I64LtU): - CHECK(EmitComparison(f, ValType::I64, JSOp::Lt, - MCompare::Compare_UInt64)); + CHECK(emitComparison(ValType::I64, JSOp::Lt, MCompare::Compare_UInt64)); case uint16_t(Op::I64GtS): - CHECK( - EmitComparison(f, ValType::I64, JSOp::Gt, MCompare::Compare_Int64)); + CHECK(emitComparison(ValType::I64, JSOp::Gt, MCompare::Compare_Int64)); case uint16_t(Op::I64GtU): - CHECK(EmitComparison(f, ValType::I64, JSOp::Gt, - MCompare::Compare_UInt64)); + CHECK(emitComparison(ValType::I64, JSOp::Gt, MCompare::Compare_UInt64)); case uint16_t(Op::I64LeS): - CHECK( - EmitComparison(f, ValType::I64, JSOp::Le, MCompare::Compare_Int64)); + CHECK(emitComparison(ValType::I64, JSOp::Le, MCompare::Compare_Int64)); case uint16_t(Op::I64LeU): - CHECK(EmitComparison(f, ValType::I64, JSOp::Le, - MCompare::Compare_UInt64)); + CHECK(emitComparison(ValType::I64, JSOp::Le, MCompare::Compare_UInt64)); case uint16_t(Op::I64GeS): - CHECK( - EmitComparison(f, ValType::I64, JSOp::Ge, MCompare::Compare_Int64)); + CHECK(emitComparison(ValType::I64, JSOp::Ge, MCompare::Compare_Int64)); case uint16_t(Op::I64GeU): - CHECK(EmitComparison(f, ValType::I64, JSOp::Ge, - MCompare::Compare_UInt64)); + CHECK(emitComparison(ValType::I64, JSOp::Ge, MCompare::Compare_UInt64)); case uint16_t(Op::F32Eq): - CHECK(EmitComparison(f, ValType::F32, JSOp::Eq, - MCompare::Compare_Float32)); + CHECK( + emitComparison(ValType::F32, JSOp::Eq, MCompare::Compare_Float32)); case uint16_t(Op::F32Ne): - CHECK(EmitComparison(f, ValType::F32, JSOp::Ne, - MCompare::Compare_Float32)); + CHECK( + emitComparison(ValType::F32, JSOp::Ne, MCompare::Compare_Float32)); case uint16_t(Op::F32Lt): - CHECK(EmitComparison(f, ValType::F32, JSOp::Lt, - MCompare::Compare_Float32)); + CHECK( + emitComparison(ValType::F32, JSOp::Lt, MCompare::Compare_Float32)); case uint16_t(Op::F32Gt): - CHECK(EmitComparison(f, ValType::F32, JSOp::Gt, - MCompare::Compare_Float32)); + CHECK( + emitComparison(ValType::F32, JSOp::Gt, MCompare::Compare_Float32)); case uint16_t(Op::F32Le): - CHECK(EmitComparison(f, ValType::F32, JSOp::Le, - MCompare::Compare_Float32)); + CHECK( + emitComparison(ValType::F32, JSOp::Le, MCompare::Compare_Float32)); case uint16_t(Op::F32Ge): - CHECK(EmitComparison(f, ValType::F32, JSOp::Ge, - MCompare::Compare_Float32)); + CHECK( + emitComparison(ValType::F32, JSOp::Ge, MCompare::Compare_Float32)); case uint16_t(Op::F64Eq): - CHECK(EmitComparison(f, ValType::F64, JSOp::Eq, - MCompare::Compare_Double)); + CHECK(emitComparison(ValType::F64, JSOp::Eq, MCompare::Compare_Double)); case uint16_t(Op::F64Ne): - CHECK(EmitComparison(f, ValType::F64, JSOp::Ne, - MCompare::Compare_Double)); + CHECK(emitComparison(ValType::F64, JSOp::Ne, MCompare::Compare_Double)); case uint16_t(Op::F64Lt): - CHECK(EmitComparison(f, ValType::F64, JSOp::Lt, - MCompare::Compare_Double)); + CHECK(emitComparison(ValType::F64, JSOp::Lt, MCompare::Compare_Double)); case uint16_t(Op::F64Gt): - CHECK(EmitComparison(f, ValType::F64, JSOp::Gt, - MCompare::Compare_Double)); + CHECK(emitComparison(ValType::F64, JSOp::Gt, MCompare::Compare_Double)); case uint16_t(Op::F64Le): - CHECK(EmitComparison(f, ValType::F64, JSOp::Le, - MCompare::Compare_Double)); + CHECK(emitComparison(ValType::F64, JSOp::Le, MCompare::Compare_Double)); case uint16_t(Op::F64Ge): - CHECK(EmitComparison(f, ValType::F64, JSOp::Ge, - MCompare::Compare_Double)); + CHECK(emitComparison(ValType::F64, JSOp::Ge, MCompare::Compare_Double)); // Numeric operators case uint16_t(Op::I32Clz): - CHECK(EmitUnaryWithType(f, ValType::I32, MIRType::Int32)); + CHECK(emitUnaryWithType(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32Ctz): - CHECK(EmitUnaryWithType(f, ValType::I32, MIRType::Int32)); + CHECK(emitUnaryWithType(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32Popcnt): - CHECK(EmitUnaryWithType(f, ValType::I32, MIRType::Int32)); + CHECK(emitUnaryWithType(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32Add): - CHECK(EmitAdd(f, ValType::I32, MIRType::Int32)); + CHECK(emitAdd(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32Sub): - CHECK(EmitSub(f, ValType::I32, MIRType::Int32)); + CHECK(emitSub(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32Mul): - CHECK(EmitMul(f, ValType::I32, MIRType::Int32)); + CHECK(emitMul(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32DivS): case uint16_t(Op::I32DivU): - CHECK( - EmitDiv(f, ValType::I32, MIRType::Int32, Op(op.b0) == Op::I32DivU)); + CHECK(emitDiv(ValType::I32, MIRType::Int32, Op(op.b0) == Op::I32DivU)); case uint16_t(Op::I32RemS): case uint16_t(Op::I32RemU): - CHECK( - EmitRem(f, ValType::I32, MIRType::Int32, Op(op.b0) == Op::I32RemU)); + CHECK(emitRem(ValType::I32, MIRType::Int32, Op(op.b0) == Op::I32RemU)); case uint16_t(Op::I32And): - CHECK(EmitBitwiseAndOrXor(f, ValType::I32, MIRType::Int32, + CHECK(emitBitwiseAndOrXor(ValType::I32, MIRType::Int32, MWasmBinaryBitwise::SubOpcode::And)); case uint16_t(Op::I32Or): - CHECK(EmitBitwiseAndOrXor(f, ValType::I32, MIRType::Int32, + CHECK(emitBitwiseAndOrXor(ValType::I32, MIRType::Int32, MWasmBinaryBitwise::SubOpcode::Or)); case uint16_t(Op::I32Xor): - CHECK(EmitBitwiseAndOrXor(f, ValType::I32, MIRType::Int32, + CHECK(emitBitwiseAndOrXor(ValType::I32, MIRType::Int32, MWasmBinaryBitwise::SubOpcode::Xor)); case uint16_t(Op::I32Shl): - CHECK(EmitShift(f, ValType::I32, MIRType::Int32)); + CHECK(emitShift(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32ShrS): - CHECK(EmitShift(f, ValType::I32, MIRType::Int32)); + CHECK(emitShift(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32ShrU): - CHECK(EmitUrsh(f, ValType::I32, MIRType::Int32)); + CHECK(emitUrsh(ValType::I32, MIRType::Int32)); case uint16_t(Op::I32Rotl): case uint16_t(Op::I32Rotr): - CHECK(EmitRotate(f, ValType::I32, Op(op.b0) == Op::I32Rotl)); + CHECK(emitRotate(ValType::I32, Op(op.b0) == Op::I32Rotl)); case uint16_t(Op::I64Clz): - CHECK(EmitUnaryWithType(f, ValType::I64, MIRType::Int64)); + CHECK(emitUnaryWithType(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64Ctz): - CHECK(EmitUnaryWithType(f, ValType::I64, MIRType::Int64)); + CHECK(emitUnaryWithType(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64Popcnt): - CHECK(EmitUnaryWithType(f, ValType::I64, MIRType::Int64)); + CHECK(emitUnaryWithType(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64Add): - CHECK(EmitAdd(f, ValType::I64, MIRType::Int64)); + CHECK(emitAdd(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64Sub): - CHECK(EmitSub(f, ValType::I64, MIRType::Int64)); + CHECK(emitSub(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64Mul): - CHECK(EmitMul(f, ValType::I64, MIRType::Int64)); + CHECK(emitMul(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64DivS): case uint16_t(Op::I64DivU): - CHECK( - EmitDiv(f, ValType::I64, MIRType::Int64, Op(op.b0) == Op::I64DivU)); + CHECK(emitDiv(ValType::I64, MIRType::Int64, Op(op.b0) == Op::I64DivU)); case uint16_t(Op::I64RemS): case uint16_t(Op::I64RemU): - CHECK( - EmitRem(f, ValType::I64, MIRType::Int64, Op(op.b0) == Op::I64RemU)); + CHECK(emitRem(ValType::I64, MIRType::Int64, Op(op.b0) == Op::I64RemU)); case uint16_t(Op::I64And): - CHECK(EmitBitwiseAndOrXor(f, ValType::I64, MIRType::Int64, + CHECK(emitBitwiseAndOrXor(ValType::I64, MIRType::Int64, MWasmBinaryBitwise::SubOpcode::And)); case uint16_t(Op::I64Or): - CHECK(EmitBitwiseAndOrXor(f, ValType::I64, MIRType::Int64, + CHECK(emitBitwiseAndOrXor(ValType::I64, MIRType::Int64, MWasmBinaryBitwise::SubOpcode::Or)); case uint16_t(Op::I64Xor): - CHECK(EmitBitwiseAndOrXor(f, ValType::I64, MIRType::Int64, + CHECK(emitBitwiseAndOrXor(ValType::I64, MIRType::Int64, MWasmBinaryBitwise::SubOpcode::Xor)); case uint16_t(Op::I64Shl): - CHECK(EmitShift(f, ValType::I64, MIRType::Int64)); + CHECK(emitShift(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64ShrS): - CHECK(EmitShift(f, ValType::I64, MIRType::Int64)); + CHECK(emitShift(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64ShrU): - CHECK(EmitUrsh(f, ValType::I64, MIRType::Int64)); + CHECK(emitUrsh(ValType::I64, MIRType::Int64)); case uint16_t(Op::I64Rotl): case uint16_t(Op::I64Rotr): - CHECK(EmitRotate(f, ValType::I64, Op(op.b0) == Op::I64Rotl)); + CHECK(emitRotate(ValType::I64, Op(op.b0) == Op::I64Rotl)); case uint16_t(Op::F32Abs): - CHECK(EmitUnaryWithType(f, ValType::F32, MIRType::Float32)); + CHECK(emitUnaryWithType(ValType::F32, MIRType::Float32)); case uint16_t(Op::F32Neg): - CHECK(EmitUnaryWithType(f, ValType::F32, MIRType::Float32)); + CHECK(emitUnaryWithType(ValType::F32, MIRType::Float32)); case uint16_t(Op::F32Ceil): - CHECK(EmitUnaryMathBuiltinCall(f, SASigCeilF)); + CHECK(emitUnaryMathBuiltinCall(SASigCeilF)); case uint16_t(Op::F32Floor): - CHECK(EmitUnaryMathBuiltinCall(f, SASigFloorF)); + CHECK(emitUnaryMathBuiltinCall(SASigFloorF)); case uint16_t(Op::F32Trunc): - CHECK(EmitUnaryMathBuiltinCall(f, SASigTruncF)); + CHECK(emitUnaryMathBuiltinCall(SASigTruncF)); case uint16_t(Op::F32Nearest): - CHECK(EmitUnaryMathBuiltinCall(f, SASigNearbyIntF)); + CHECK(emitUnaryMathBuiltinCall(SASigNearbyIntF)); case uint16_t(Op::F32Sqrt): - CHECK(EmitUnaryWithType(f, ValType::F32, MIRType::Float32)); + CHECK(emitUnaryWithType(ValType::F32, MIRType::Float32)); case uint16_t(Op::F32Add): - CHECK(EmitAdd(f, ValType::F32, MIRType::Float32)); + CHECK(emitAdd(ValType::F32, MIRType::Float32)); case uint16_t(Op::F32Sub): - CHECK(EmitSub(f, ValType::F32, MIRType::Float32)); + CHECK(emitSub(ValType::F32, MIRType::Float32)); case uint16_t(Op::F32Mul): - CHECK(EmitMul(f, ValType::F32, MIRType::Float32)); + CHECK(emitMul(ValType::F32, MIRType::Float32)); case uint16_t(Op::F32Div): - CHECK(EmitDiv(f, ValType::F32, MIRType::Float32, + CHECK(emitDiv(ValType::F32, MIRType::Float32, /* isUnsigned = */ false)); case uint16_t(Op::F32Min): case uint16_t(Op::F32Max): - CHECK(EmitMinMax(f, ValType::F32, MIRType::Float32, + CHECK(emitMinMax(ValType::F32, MIRType::Float32, Op(op.b0) == Op::F32Max)); case uint16_t(Op::F32CopySign): - CHECK(EmitCopySign(f, ValType::F32)); + CHECK(emitCopySign(ValType::F32)); case uint16_t(Op::F64Abs): - CHECK(EmitUnaryWithType(f, ValType::F64, MIRType::Double)); + CHECK(emitUnaryWithType(ValType::F64, MIRType::Double)); case uint16_t(Op::F64Neg): - CHECK(EmitUnaryWithType(f, ValType::F64, MIRType::Double)); + CHECK(emitUnaryWithType(ValType::F64, MIRType::Double)); case uint16_t(Op::F64Ceil): - CHECK(EmitUnaryMathBuiltinCall(f, SASigCeilD)); + CHECK(emitUnaryMathBuiltinCall(SASigCeilD)); case uint16_t(Op::F64Floor): - CHECK(EmitUnaryMathBuiltinCall(f, SASigFloorD)); + CHECK(emitUnaryMathBuiltinCall(SASigFloorD)); case uint16_t(Op::F64Trunc): - CHECK(EmitUnaryMathBuiltinCall(f, SASigTruncD)); + CHECK(emitUnaryMathBuiltinCall(SASigTruncD)); case uint16_t(Op::F64Nearest): - CHECK(EmitUnaryMathBuiltinCall(f, SASigNearbyIntD)); + CHECK(emitUnaryMathBuiltinCall(SASigNearbyIntD)); case uint16_t(Op::F64Sqrt): - CHECK(EmitUnaryWithType(f, ValType::F64, MIRType::Double)); + CHECK(emitUnaryWithType(ValType::F64, MIRType::Double)); case uint16_t(Op::F64Add): - CHECK(EmitAdd(f, ValType::F64, MIRType::Double)); + CHECK(emitAdd(ValType::F64, MIRType::Double)); case uint16_t(Op::F64Sub): - CHECK(EmitSub(f, ValType::F64, MIRType::Double)); + CHECK(emitSub(ValType::F64, MIRType::Double)); case uint16_t(Op::F64Mul): - CHECK(EmitMul(f, ValType::F64, MIRType::Double)); + CHECK(emitMul(ValType::F64, MIRType::Double)); case uint16_t(Op::F64Div): - CHECK(EmitDiv(f, ValType::F64, MIRType::Double, + CHECK(emitDiv(ValType::F64, MIRType::Double, /* isUnsigned = */ false)); case uint16_t(Op::F64Min): case uint16_t(Op::F64Max): - CHECK(EmitMinMax(f, ValType::F64, MIRType::Double, - Op(op.b0) == Op::F64Max)); + CHECK( + emitMinMax(ValType::F64, MIRType::Double, Op(op.b0) == Op::F64Max)); case uint16_t(Op::F64CopySign): - CHECK(EmitCopySign(f, ValType::F64)); + CHECK(emitCopySign(ValType::F64)); // Conversions case uint16_t(Op::I32WrapI64): - CHECK(EmitConversion(f, ValType::I64, ValType::I32)); + CHECK(emitConversion(ValType::I64, ValType::I32)); case uint16_t(Op::I32TruncF32S): case uint16_t(Op::I32TruncF32U): - CHECK(EmitTruncate(f, ValType::F32, ValType::I32, + CHECK(emitTruncate(ValType::F32, ValType::I32, Op(op.b0) == Op::I32TruncF32U, false)); case uint16_t(Op::I32TruncF64S): case uint16_t(Op::I32TruncF64U): - CHECK(EmitTruncate(f, ValType::F64, ValType::I32, + CHECK(emitTruncate(ValType::F64, ValType::I32, Op(op.b0) == Op::I32TruncF64U, false)); case uint16_t(Op::I64ExtendI32S): case uint16_t(Op::I64ExtendI32U): - CHECK(EmitExtendI32(f, Op(op.b0) == Op::I64ExtendI32U)); + CHECK(emitExtendI32(Op(op.b0) == Op::I64ExtendI32U)); case uint16_t(Op::I64TruncF32S): case uint16_t(Op::I64TruncF32U): - CHECK(EmitTruncate(f, ValType::F32, ValType::I64, + CHECK(emitTruncate(ValType::F32, ValType::I64, Op(op.b0) == Op::I64TruncF32U, false)); case uint16_t(Op::I64TruncF64S): case uint16_t(Op::I64TruncF64U): - CHECK(EmitTruncate(f, ValType::F64, ValType::I64, + CHECK(emitTruncate(ValType::F64, ValType::I64, Op(op.b0) == Op::I64TruncF64U, false)); case uint16_t(Op::F32ConvertI32S): - CHECK(EmitConversion(f, ValType::I32, ValType::F32)); + CHECK(emitConversion(ValType::I32, ValType::F32)); case uint16_t(Op::F32ConvertI32U): - CHECK(EmitConversion(f, ValType::I32, - ValType::F32)); + CHECK( + emitConversion(ValType::I32, ValType::F32)); case uint16_t(Op::F32ConvertI64S): case uint16_t(Op::F32ConvertI64U): - CHECK(EmitConvertI64ToFloatingPoint(f, ValType::F32, MIRType::Float32, + CHECK(emitConvertI64ToFloatingPoint(ValType::F32, MIRType::Float32, Op(op.b0) == Op::F32ConvertI64U)); case uint16_t(Op::F32DemoteF64): - CHECK(EmitConversion(f, ValType::F64, ValType::F32)); + CHECK(emitConversion(ValType::F64, ValType::F32)); case uint16_t(Op::F64ConvertI32S): - CHECK(EmitConversion(f, ValType::I32, ValType::F64)); + CHECK(emitConversion(ValType::I32, ValType::F64)); case uint16_t(Op::F64ConvertI32U): - CHECK(EmitConversion(f, ValType::I32, - ValType::F64)); + CHECK( + emitConversion(ValType::I32, ValType::F64)); case uint16_t(Op::F64ConvertI64S): case uint16_t(Op::F64ConvertI64U): - CHECK(EmitConvertI64ToFloatingPoint(f, ValType::F64, MIRType::Double, + CHECK(emitConvertI64ToFloatingPoint(ValType::F64, MIRType::Double, Op(op.b0) == Op::F64ConvertI64U)); case uint16_t(Op::F64PromoteF32): - CHECK(EmitConversion(f, ValType::F32, ValType::F64)); + CHECK(emitConversion(ValType::F32, ValType::F64)); // Reinterpretations case uint16_t(Op::I32ReinterpretF32): - CHECK(EmitReinterpret(f, ValType::I32, ValType::F32, MIRType::Int32)); + CHECK(emitReinterpret(ValType::I32, ValType::F32, MIRType::Int32)); case uint16_t(Op::I64ReinterpretF64): - CHECK(EmitReinterpret(f, ValType::I64, ValType::F64, MIRType::Int64)); + CHECK(emitReinterpret(ValType::I64, ValType::F64, MIRType::Int64)); case uint16_t(Op::F32ReinterpretI32): - CHECK(EmitReinterpret(f, ValType::F32, ValType::I32, MIRType::Float32)); + CHECK(emitReinterpret(ValType::F32, ValType::I32, MIRType::Float32)); case uint16_t(Op::F64ReinterpretI64): - CHECK(EmitReinterpret(f, ValType::F64, ValType::I64, MIRType::Double)); + CHECK(emitReinterpret(ValType::F64, ValType::I64, MIRType::Double)); -#ifdef ENABLE_WASM_GC case uint16_t(Op::RefEq): - if (!f.moduleEnv().gcEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitComparison(f, RefType::eq(), JSOp::Eq, + CHECK(emitComparison(RefType::eq(), JSOp::Eq, MCompare::Compare_WasmAnyRef)); -#endif case uint16_t(Op::RefFunc): - CHECK(EmitRefFunc(f)); + CHECK(emitRefFunc()); case uint16_t(Op::RefNull): - CHECK(EmitRefNull(f)); + CHECK(emitRefNull()); case uint16_t(Op::RefIsNull): - CHECK(EmitRefIsNull(f)); + CHECK(emitRefIsNull()); // Sign extensions case uint16_t(Op::I32Extend8S): - CHECK(EmitSignExtend(f, 1, 4)); + CHECK(emitSignExtend(1, 4)); case uint16_t(Op::I32Extend16S): - CHECK(EmitSignExtend(f, 2, 4)); + CHECK(emitSignExtend(2, 4)); case uint16_t(Op::I64Extend8S): - CHECK(EmitSignExtend(f, 1, 8)); + CHECK(emitSignExtend(1, 8)); case uint16_t(Op::I64Extend16S): - CHECK(EmitSignExtend(f, 2, 8)); + CHECK(emitSignExtend(2, 8)); case uint16_t(Op::I64Extend32S): - CHECK(EmitSignExtend(f, 4, 8)); + CHECK(emitSignExtend(4, 8)); -#ifdef ENABLE_WASM_TAIL_CALLS case uint16_t(Op::ReturnCall): { - if (!f.moduleEnv().tailCallsEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitReturnCall(f)); + CHECK(emitReturnCall()); } case uint16_t(Op::ReturnCallIndirect): { - if (!f.moduleEnv().tailCallsEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitReturnCallIndirect(f)); + CHECK(emitReturnCallIndirect()); } -#endif -#ifdef ENABLE_WASM_GC case uint16_t(Op::RefAsNonNull): - if (!f.moduleEnv().gcEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitRefAsNonNull(f)); + CHECK(emitRefAsNonNull()); case uint16_t(Op::BrOnNull): { - if (!f.moduleEnv().gcEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitBrOnNull(f)); + CHECK(emitBrOnNull()); } case uint16_t(Op::BrOnNonNull): { - if (!f.moduleEnv().gcEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitBrOnNonNull(f)); + CHECK(emitBrOnNonNull()); } case uint16_t(Op::CallRef): { - if (!f.moduleEnv().gcEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitCallRef(f)); + CHECK(emitCallRef()); } -#endif -#if defined(ENABLE_WASM_TAIL_CALLS) && defined(ENABLE_WASM_GC) case uint16_t(Op::ReturnCallRef): { - if (!f.moduleEnv().gcEnabled() || !f.moduleEnv().tailCallsEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitReturnCallRef(f)); + CHECK(emitReturnCallRef()); } -#endif // Gc operations -#ifdef ENABLE_WASM_GC case uint16_t(Op::GcPrefix): { - if (!f.moduleEnv().gcEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } switch (op.b1) { case uint32_t(GcOp::StructNew): - CHECK(EmitStructNew(f)); + CHECK(emitStructNew()); case uint32_t(GcOp::StructNewDefault): - CHECK(EmitStructNewDefault(f)); + CHECK(emitStructNewDefault()); case uint32_t(GcOp::StructSet): - CHECK(EmitStructSet(f)); + CHECK(emitStructSet()); case uint32_t(GcOp::StructGet): - CHECK(EmitStructGet(f, FieldWideningOp::None)); + CHECK(emitStructGet(FieldWideningOp::None)); case uint32_t(GcOp::StructGetS): - CHECK(EmitStructGet(f, FieldWideningOp::Signed)); + CHECK(emitStructGet(FieldWideningOp::Signed)); case uint32_t(GcOp::StructGetU): - CHECK(EmitStructGet(f, FieldWideningOp::Unsigned)); + CHECK(emitStructGet(FieldWideningOp::Unsigned)); case uint32_t(GcOp::ArrayNew): - CHECK(EmitArrayNew(f)); + CHECK(emitArrayNew()); case uint32_t(GcOp::ArrayNewDefault): - CHECK(EmitArrayNewDefault(f)); + CHECK(emitArrayNewDefault()); case uint32_t(GcOp::ArrayNewFixed): - CHECK(EmitArrayNewFixed(f)); + CHECK(emitArrayNewFixed()); case uint32_t(GcOp::ArrayNewData): - CHECK(EmitArrayNewData(f)); + CHECK(emitArrayNewData()); case uint32_t(GcOp::ArrayNewElem): - CHECK(EmitArrayNewElem(f)); + CHECK(emitArrayNewElem()); case uint32_t(GcOp::ArrayInitData): - CHECK(EmitArrayInitData(f)); + CHECK(emitArrayInitData()); case uint32_t(GcOp::ArrayInitElem): - CHECK(EmitArrayInitElem(f)); + CHECK(emitArrayInitElem()); case uint32_t(GcOp::ArraySet): - CHECK(EmitArraySet(f)); + CHECK(emitArraySet()); case uint32_t(GcOp::ArrayGet): - CHECK(EmitArrayGet(f, FieldWideningOp::None)); + CHECK(emitArrayGet(FieldWideningOp::None)); case uint32_t(GcOp::ArrayGetS): - CHECK(EmitArrayGet(f, FieldWideningOp::Signed)); + CHECK(emitArrayGet(FieldWideningOp::Signed)); case uint32_t(GcOp::ArrayGetU): - CHECK(EmitArrayGet(f, FieldWideningOp::Unsigned)); + CHECK(emitArrayGet(FieldWideningOp::Unsigned)); case uint32_t(GcOp::ArrayLen): - CHECK(EmitArrayLen(f)); + CHECK(emitArrayLen()); case uint32_t(GcOp::ArrayCopy): - CHECK(EmitArrayCopy(f)); + CHECK(emitArrayCopy()); case uint32_t(GcOp::ArrayFill): - CHECK(EmitArrayFill(f)); + CHECK(emitArrayFill()); case uint32_t(GcOp::RefI31): - CHECK(EmitRefI31(f)); + CHECK(emitRefI31()); case uint32_t(GcOp::I31GetS): - CHECK(EmitI31Get(f, FieldWideningOp::Signed)); + CHECK(emitI31Get(FieldWideningOp::Signed)); case uint32_t(GcOp::I31GetU): - CHECK(EmitI31Get(f, FieldWideningOp::Unsigned)); + CHECK(emitI31Get(FieldWideningOp::Unsigned)); case uint32_t(GcOp::BrOnCast): - CHECK(EmitBrOnCast(f, /*onSuccess=*/true)); + CHECK(emitBrOnCast(/*onSuccess=*/true)); case uint32_t(GcOp::BrOnCastFail): - CHECK(EmitBrOnCast(f, /*onSuccess=*/false)); + CHECK(emitBrOnCast(/*onSuccess=*/false)); case uint32_t(GcOp::RefTest): - CHECK(EmitRefTest(f, /*nullable=*/false)); + CHECK(emitRefTest(/*nullable=*/false)); case uint32_t(GcOp::RefTestNull): - CHECK(EmitRefTest(f, /*nullable=*/true)); + CHECK(emitRefTest(/*nullable=*/true)); case uint32_t(GcOp::RefCast): - CHECK(EmitRefCast(f, /*nullable=*/false)); + CHECK(emitRefCast(/*nullable=*/false)); case uint32_t(GcOp::RefCastNull): - CHECK(EmitRefCast(f, /*nullable=*/true)); + CHECK(emitRefCast(/*nullable=*/true)); case uint16_t(GcOp::AnyConvertExtern): - CHECK(EmitAnyConvertExtern(f)); + CHECK(emitAnyConvertExtern()); case uint16_t(GcOp::ExternConvertAny): - CHECK(EmitExternConvertAny(f)); + CHECK(emitExternConvertAny()); default: - return f.iter().unrecognizedOpcode(&op); + return iter().unrecognizedOpcode(&op); } // switch (op.b1) break; } -#endif // SIMD operations #ifdef ENABLE_WASM_SIMD case uint16_t(Op::SimdPrefix): { - if (!f.moduleEnv().simdAvailable()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().simdAvailable()) { + return iter().unrecognizedOpcode(&op); } switch (op.b1) { case uint32_t(SimdOp::V128Const): - CHECK(EmitConstSimd128(f)); + CHECK(emitConstSimd128()); case uint32_t(SimdOp::V128Load): - CHECK(EmitLoad(f, ValType::V128, Scalar::Simd128)); + CHECK(emitLoad(ValType::V128, Scalar::Simd128)); case uint32_t(SimdOp::V128Store): - CHECK(EmitStore(f, ValType::V128, Scalar::Simd128)); + CHECK(emitStore(ValType::V128, Scalar::Simd128)); case uint32_t(SimdOp::V128And): case uint32_t(SimdOp::V128Or): case uint32_t(SimdOp::V128Xor): @@ -8733,7 +9923,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::I64x2ExtmulLowI32x4U): case uint32_t(SimdOp::I64x2ExtmulHighI32x4U): case uint32_t(SimdOp::I16x8Q15MulrSatS): - CHECK(EmitBinarySimd128(f, /* commutative= */ true, SimdOp(op.b1))); + CHECK(emitBinarySimd128(/* commutative= */ true, SimdOp(op.b1))); case uint32_t(SimdOp::V128AndNot): case uint32_t(SimdOp::I8x16Sub): case uint32_t(SimdOp::I8x16SubSatS): @@ -8792,18 +9982,17 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::F32x4PMin): case uint32_t(SimdOp::F64x2PMax): case uint32_t(SimdOp::F64x2PMin): - CHECK( - EmitBinarySimd128(f, /* commutative= */ false, SimdOp(op.b1))); + CHECK(emitBinarySimd128(/* commutative= */ false, SimdOp(op.b1))); case uint32_t(SimdOp::I8x16Splat): case uint32_t(SimdOp::I16x8Splat): case uint32_t(SimdOp::I32x4Splat): - CHECK(EmitSplatSimd128(f, ValType::I32, SimdOp(op.b1))); + CHECK(emitSplatSimd128(ValType::I32, SimdOp(op.b1))); case uint32_t(SimdOp::I64x2Splat): - CHECK(EmitSplatSimd128(f, ValType::I64, SimdOp(op.b1))); + CHECK(emitSplatSimd128(ValType::I64, SimdOp(op.b1))); case uint32_t(SimdOp::F32x4Splat): - CHECK(EmitSplatSimd128(f, ValType::F32, SimdOp(op.b1))); + CHECK(emitSplatSimd128(ValType::F32, SimdOp(op.b1))); case uint32_t(SimdOp::F64x2Splat): - CHECK(EmitSplatSimd128(f, ValType::F64, SimdOp(op.b1))); + CHECK(emitSplatSimd128(ValType::F64, SimdOp(op.b1))); case uint32_t(SimdOp::I8x16Neg): case uint32_t(SimdOp::I16x8Neg): case uint32_t(SimdOp::I16x8ExtendLowI8x16S): @@ -8854,7 +10043,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::I16x8ExtaddPairwiseI8x16U): case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8S): case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8U): - CHECK(EmitUnarySimd128(f, SimdOp(op.b1))); + CHECK(emitUnarySimd128(SimdOp(op.b1))); case uint32_t(SimdOp::V128AnyTrue): case uint32_t(SimdOp::I8x16AllTrue): case uint32_t(SimdOp::I16x8AllTrue): @@ -8864,7 +10053,7 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::I16x8Bitmask): case uint32_t(SimdOp::I32x4Bitmask): case uint32_t(SimdOp::I64x2Bitmask): - CHECK(EmitReduceSimd128(f, SimdOp(op.b1))); + CHECK(emitReduceSimd128(SimdOp(op.b1))); case uint32_t(SimdOp::I8x16Shl): case uint32_t(SimdOp::I8x16ShrS): case uint32_t(SimdOp::I8x16ShrU): @@ -8877,72 +10066,72 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::I64x2Shl): case uint32_t(SimdOp::I64x2ShrS): case uint32_t(SimdOp::I64x2ShrU): - CHECK(EmitShiftSimd128(f, SimdOp(op.b1))); + CHECK(emitShiftSimd128(SimdOp(op.b1))); case uint32_t(SimdOp::I8x16ExtractLaneS): case uint32_t(SimdOp::I8x16ExtractLaneU): - CHECK(EmitExtractLaneSimd128(f, ValType::I32, 16, SimdOp(op.b1))); + CHECK(emitExtractLaneSimd128(ValType::I32, 16, SimdOp(op.b1))); case uint32_t(SimdOp::I16x8ExtractLaneS): case uint32_t(SimdOp::I16x8ExtractLaneU): - CHECK(EmitExtractLaneSimd128(f, ValType::I32, 8, SimdOp(op.b1))); + CHECK(emitExtractLaneSimd128(ValType::I32, 8, SimdOp(op.b1))); case uint32_t(SimdOp::I32x4ExtractLane): - CHECK(EmitExtractLaneSimd128(f, ValType::I32, 4, SimdOp(op.b1))); + CHECK(emitExtractLaneSimd128(ValType::I32, 4, SimdOp(op.b1))); case uint32_t(SimdOp::I64x2ExtractLane): - CHECK(EmitExtractLaneSimd128(f, ValType::I64, 2, SimdOp(op.b1))); + CHECK(emitExtractLaneSimd128(ValType::I64, 2, SimdOp(op.b1))); case uint32_t(SimdOp::F32x4ExtractLane): - CHECK(EmitExtractLaneSimd128(f, ValType::F32, 4, SimdOp(op.b1))); + CHECK(emitExtractLaneSimd128(ValType::F32, 4, SimdOp(op.b1))); case uint32_t(SimdOp::F64x2ExtractLane): - CHECK(EmitExtractLaneSimd128(f, ValType::F64, 2, SimdOp(op.b1))); + CHECK(emitExtractLaneSimd128(ValType::F64, 2, SimdOp(op.b1))); case uint32_t(SimdOp::I8x16ReplaceLane): - CHECK(EmitReplaceLaneSimd128(f, ValType::I32, 16, SimdOp(op.b1))); + CHECK(emitReplaceLaneSimd128(ValType::I32, 16, SimdOp(op.b1))); case uint32_t(SimdOp::I16x8ReplaceLane): - CHECK(EmitReplaceLaneSimd128(f, ValType::I32, 8, SimdOp(op.b1))); + CHECK(emitReplaceLaneSimd128(ValType::I32, 8, SimdOp(op.b1))); case uint32_t(SimdOp::I32x4ReplaceLane): - CHECK(EmitReplaceLaneSimd128(f, ValType::I32, 4, SimdOp(op.b1))); + CHECK(emitReplaceLaneSimd128(ValType::I32, 4, SimdOp(op.b1))); case uint32_t(SimdOp::I64x2ReplaceLane): - CHECK(EmitReplaceLaneSimd128(f, ValType::I64, 2, SimdOp(op.b1))); + CHECK(emitReplaceLaneSimd128(ValType::I64, 2, SimdOp(op.b1))); case uint32_t(SimdOp::F32x4ReplaceLane): - CHECK(EmitReplaceLaneSimd128(f, ValType::F32, 4, SimdOp(op.b1))); + CHECK(emitReplaceLaneSimd128(ValType::F32, 4, SimdOp(op.b1))); case uint32_t(SimdOp::F64x2ReplaceLane): - CHECK(EmitReplaceLaneSimd128(f, ValType::F64, 2, SimdOp(op.b1))); + CHECK(emitReplaceLaneSimd128(ValType::F64, 2, SimdOp(op.b1))); case uint32_t(SimdOp::V128Bitselect): - CHECK(EmitTernarySimd128(f, SimdOp(op.b1))); + CHECK(emitTernarySimd128(SimdOp(op.b1))); case uint32_t(SimdOp::I8x16Shuffle): - CHECK(EmitShuffleSimd128(f)); + CHECK(emitShuffleSimd128()); case uint32_t(SimdOp::V128Load8Splat): - CHECK(EmitLoadSplatSimd128(f, Scalar::Uint8, SimdOp::I8x16Splat)); + CHECK(emitLoadSplatSimd128(Scalar::Uint8, SimdOp::I8x16Splat)); case uint32_t(SimdOp::V128Load16Splat): - CHECK(EmitLoadSplatSimd128(f, Scalar::Uint16, SimdOp::I16x8Splat)); + CHECK(emitLoadSplatSimd128(Scalar::Uint16, SimdOp::I16x8Splat)); case uint32_t(SimdOp::V128Load32Splat): - CHECK(EmitLoadSplatSimd128(f, Scalar::Float32, SimdOp::I32x4Splat)); + CHECK(emitLoadSplatSimd128(Scalar::Float32, SimdOp::I32x4Splat)); case uint32_t(SimdOp::V128Load64Splat): - CHECK(EmitLoadSplatSimd128(f, Scalar::Float64, SimdOp::I64x2Splat)); + CHECK(emitLoadSplatSimd128(Scalar::Float64, SimdOp::I64x2Splat)); case uint32_t(SimdOp::V128Load8x8S): case uint32_t(SimdOp::V128Load8x8U): case uint32_t(SimdOp::V128Load16x4S): case uint32_t(SimdOp::V128Load16x4U): case uint32_t(SimdOp::V128Load32x2S): case uint32_t(SimdOp::V128Load32x2U): - CHECK(EmitLoadExtendSimd128(f, SimdOp(op.b1))); + CHECK(emitLoadExtendSimd128(SimdOp(op.b1))); case uint32_t(SimdOp::V128Load32Zero): - CHECK(EmitLoadZeroSimd128(f, Scalar::Float32, 4)); + CHECK(emitLoadZeroSimd128(Scalar::Float32, 4)); case uint32_t(SimdOp::V128Load64Zero): - CHECK(EmitLoadZeroSimd128(f, Scalar::Float64, 8)); + CHECK(emitLoadZeroSimd128(Scalar::Float64, 8)); case uint32_t(SimdOp::V128Load8Lane): - CHECK(EmitLoadLaneSimd128(f, 1)); + CHECK(emitLoadLaneSimd128(1)); case uint32_t(SimdOp::V128Load16Lane): - CHECK(EmitLoadLaneSimd128(f, 2)); + CHECK(emitLoadLaneSimd128(2)); case uint32_t(SimdOp::V128Load32Lane): - CHECK(EmitLoadLaneSimd128(f, 4)); + CHECK(emitLoadLaneSimd128(4)); case uint32_t(SimdOp::V128Load64Lane): - CHECK(EmitLoadLaneSimd128(f, 8)); + CHECK(emitLoadLaneSimd128(8)); case uint32_t(SimdOp::V128Store8Lane): - CHECK(EmitStoreLaneSimd128(f, 1)); + CHECK(emitStoreLaneSimd128(1)); case uint32_t(SimdOp::V128Store16Lane): - CHECK(EmitStoreLaneSimd128(f, 2)); + CHECK(emitStoreLaneSimd128(2)); case uint32_t(SimdOp::V128Store32Lane): - CHECK(EmitStoreLaneSimd128(f, 4)); + CHECK(emitStoreLaneSimd128(4)); case uint32_t(SimdOp::V128Store64Lane): - CHECK(EmitStoreLaneSimd128(f, 8)); + CHECK(emitStoreLaneSimd128(8)); # ifdef ENABLE_WASM_RELAXED_SIMD case uint32_t(SimdOp::F32x4RelaxedMadd): case uint32_t(SimdOp::F32x4RelaxedNmadd): @@ -8952,43 +10141,51 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::I16x8RelaxedLaneSelect): case uint32_t(SimdOp::I32x4RelaxedLaneSelect): case uint32_t(SimdOp::I64x2RelaxedLaneSelect): - case uint32_t(SimdOp::I32x4DotI8x16I7x16AddS): { - if (!f.moduleEnv().v128RelaxedEnabled()) { - return f.iter().unrecognizedOpcode(&op); + case uint32_t(SimdOp::I32x4RelaxedDotI8x16I7x16AddS): { + if (!codeMeta().v128RelaxedEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitTernarySimd128(f, SimdOp(op.b1))); + CHECK(emitTernarySimd128(SimdOp(op.b1))); } case uint32_t(SimdOp::F32x4RelaxedMin): case uint32_t(SimdOp::F32x4RelaxedMax): case uint32_t(SimdOp::F64x2RelaxedMin): - case uint32_t(SimdOp::F64x2RelaxedMax): - case uint32_t(SimdOp::I16x8RelaxedQ15MulrS): { - if (!f.moduleEnv().v128RelaxedEnabled()) { - return f.iter().unrecognizedOpcode(&op); + case uint32_t(SimdOp::F64x2RelaxedMax): { + if (!codeMeta().v128RelaxedEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitBinarySimd128(f, /* commutative= */ true, SimdOp(op.b1))); + // These aren't really commutative, because at least on Intel, the + // behaviour in the presence of NaNs depends on the order of the + // operands. And we need to have that ordering fixed, so that we + // can produce the same results as baseline. See bug 1946618. + CHECK(emitBinarySimd128(/* commutative= */ false, SimdOp(op.b1))); + } + case uint32_t(SimdOp::I16x8RelaxedQ15MulrS): { + if (!codeMeta().v128RelaxedEnabled()) { + return iter().unrecognizedOpcode(&op); + } + CHECK(emitBinarySimd128(/* commutative= */ true, SimdOp(op.b1))); } case uint32_t(SimdOp::I32x4RelaxedTruncF32x4S): case uint32_t(SimdOp::I32x4RelaxedTruncF32x4U): case uint32_t(SimdOp::I32x4RelaxedTruncF64x2SZero): case uint32_t(SimdOp::I32x4RelaxedTruncF64x2UZero): { - if (!f.moduleEnv().v128RelaxedEnabled()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().v128RelaxedEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitUnarySimd128(f, SimdOp(op.b1))); + CHECK(emitUnarySimd128(SimdOp(op.b1))); } case uint32_t(SimdOp::I8x16RelaxedSwizzle): - case uint32_t(SimdOp::I16x8DotI8x16I7x16S): { - if (!f.moduleEnv().v128RelaxedEnabled()) { - return f.iter().unrecognizedOpcode(&op); + case uint32_t(SimdOp::I16x8RelaxedDotI8x16I7x16S): { + if (!codeMeta().v128RelaxedEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK( - EmitBinarySimd128(f, /* commutative= */ false, SimdOp(op.b1))); + CHECK(emitBinarySimd128(/* commutative= */ false, SimdOp(op.b1))); } # endif default: - return f.iter().unrecognizedOpcode(&op); + return iter().unrecognizedOpcode(&op); } // switch (op.b1) break; } @@ -8999,50 +10196,50 @@ static bool EmitBodyExprs(FunctionCompiler& f) { switch (op.b1) { case uint32_t(MiscOp::I32TruncSatF32S): case uint32_t(MiscOp::I32TruncSatF32U): - CHECK(EmitTruncate(f, ValType::F32, ValType::I32, + CHECK(emitTruncate(ValType::F32, ValType::I32, MiscOp(op.b1) == MiscOp::I32TruncSatF32U, true)); case uint32_t(MiscOp::I32TruncSatF64S): case uint32_t(MiscOp::I32TruncSatF64U): - CHECK(EmitTruncate(f, ValType::F64, ValType::I32, + CHECK(emitTruncate(ValType::F64, ValType::I32, MiscOp(op.b1) == MiscOp::I32TruncSatF64U, true)); case uint32_t(MiscOp::I64TruncSatF32S): case uint32_t(MiscOp::I64TruncSatF32U): - CHECK(EmitTruncate(f, ValType::F32, ValType::I64, + CHECK(emitTruncate(ValType::F32, ValType::I64, MiscOp(op.b1) == MiscOp::I64TruncSatF32U, true)); case uint32_t(MiscOp::I64TruncSatF64S): case uint32_t(MiscOp::I64TruncSatF64U): - CHECK(EmitTruncate(f, ValType::F64, ValType::I64, + CHECK(emitTruncate(ValType::F64, ValType::I64, MiscOp(op.b1) == MiscOp::I64TruncSatF64U, true)); case uint32_t(MiscOp::MemoryCopy): - CHECK(EmitMemCopy(f)); + CHECK(emitMemCopy()); case uint32_t(MiscOp::DataDrop): - CHECK(EmitDataOrElemDrop(f, /*isData=*/true)); + CHECK(emitDataOrElemDrop(/*isData=*/true)); case uint32_t(MiscOp::MemoryFill): - CHECK(EmitMemFill(f)); + CHECK(emitMemFill()); case uint32_t(MiscOp::MemoryInit): - CHECK(EmitMemOrTableInit(f, /*isMem=*/true)); + CHECK(emitMemInit()); case uint32_t(MiscOp::TableCopy): - CHECK(EmitTableCopy(f)); + CHECK(emitTableCopy()); case uint32_t(MiscOp::ElemDrop): - CHECK(EmitDataOrElemDrop(f, /*isData=*/false)); + CHECK(emitDataOrElemDrop(/*isData=*/false)); case uint32_t(MiscOp::TableInit): - CHECK(EmitMemOrTableInit(f, /*isMem=*/false)); + CHECK(emitTableInit()); case uint32_t(MiscOp::TableFill): - CHECK(EmitTableFill(f)); + CHECK(emitTableFill()); #if ENABLE_WASM_MEMORY_CONTROL case uint32_t(MiscOp::MemoryDiscard): { - if (!f.moduleEnv().memoryControlEnabled()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().memoryControlEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitMemDiscard(f)); + CHECK(emitMemDiscard()); } #endif case uint32_t(MiscOp::TableGrow): - CHECK(EmitTableGrow(f)); + CHECK(emitTableGrow()); case uint32_t(MiscOp::TableSize): - CHECK(EmitTableSize(f)); + CHECK(emitTableSize()); default: - return f.iter().unrecognizedOpcode(&op); + return iter().unrecognizedOpcode(&op); } break; } @@ -9052,169 +10249,157 @@ static bool EmitBodyExprs(FunctionCompiler& f) { // Though thread ops can be used on nonshared memories, we make them // unavailable if shared memory has been disabled in the prefs, for // maximum predictability and safety and consistency with JS. - if (f.moduleEnv().sharedMemoryEnabled() == Shareable::False) { - return f.iter().unrecognizedOpcode(&op); + if (codeMeta().sharedMemoryEnabled() == Shareable::False) { + return iter().unrecognizedOpcode(&op); } switch (op.b1) { - case uint32_t(ThreadOp::Wake): - CHECK(EmitWake(f)); + case uint32_t(ThreadOp::Notify): + CHECK(emitNotify()); case uint32_t(ThreadOp::I32Wait): - CHECK(EmitWait(f, ValType::I32, 4)); + CHECK(emitWait(ValType::I32, 4)); case uint32_t(ThreadOp::I64Wait): - CHECK(EmitWait(f, ValType::I64, 8)); + CHECK(emitWait(ValType::I64, 8)); case uint32_t(ThreadOp::Fence): - CHECK(EmitFence(f)); + CHECK(emitFence()); case uint32_t(ThreadOp::I32AtomicLoad): - CHECK(EmitAtomicLoad(f, ValType::I32, Scalar::Int32)); + CHECK(emitAtomicLoad(ValType::I32, Scalar::Int32)); case uint32_t(ThreadOp::I64AtomicLoad): - CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Int64)); + CHECK(emitAtomicLoad(ValType::I64, Scalar::Int64)); case uint32_t(ThreadOp::I32AtomicLoad8U): - CHECK(EmitAtomicLoad(f, ValType::I32, Scalar::Uint8)); + CHECK(emitAtomicLoad(ValType::I32, Scalar::Uint8)); case uint32_t(ThreadOp::I32AtomicLoad16U): - CHECK(EmitAtomicLoad(f, ValType::I32, Scalar::Uint16)); + CHECK(emitAtomicLoad(ValType::I32, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicLoad8U): - CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Uint8)); + CHECK(emitAtomicLoad(ValType::I64, Scalar::Uint8)); case uint32_t(ThreadOp::I64AtomicLoad16U): - CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Uint16)); + CHECK(emitAtomicLoad(ValType::I64, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicLoad32U): - CHECK(EmitAtomicLoad(f, ValType::I64, Scalar::Uint32)); + CHECK(emitAtomicLoad(ValType::I64, Scalar::Uint32)); case uint32_t(ThreadOp::I32AtomicStore): - CHECK(EmitAtomicStore(f, ValType::I32, Scalar::Int32)); + CHECK(emitAtomicStore(ValType::I32, Scalar::Int32)); case uint32_t(ThreadOp::I64AtomicStore): - CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Int64)); + CHECK(emitAtomicStore(ValType::I64, Scalar::Int64)); case uint32_t(ThreadOp::I32AtomicStore8U): - CHECK(EmitAtomicStore(f, ValType::I32, Scalar::Uint8)); + CHECK(emitAtomicStore(ValType::I32, Scalar::Uint8)); case uint32_t(ThreadOp::I32AtomicStore16U): - CHECK(EmitAtomicStore(f, ValType::I32, Scalar::Uint16)); + CHECK(emitAtomicStore(ValType::I32, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicStore8U): - CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Uint8)); + CHECK(emitAtomicStore(ValType::I64, Scalar::Uint8)); case uint32_t(ThreadOp::I64AtomicStore16U): - CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Uint16)); + CHECK(emitAtomicStore(ValType::I64, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicStore32U): - CHECK(EmitAtomicStore(f, ValType::I64, Scalar::Uint32)); + CHECK(emitAtomicStore(ValType::I64, Scalar::Uint32)); case uint32_t(ThreadOp::I32AtomicAdd): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicOp::Add)); case uint32_t(ThreadOp::I64AtomicAdd): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicOp::Add)); case uint32_t(ThreadOp::I32AtomicAdd8U): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicOp::Add)); case uint32_t(ThreadOp::I32AtomicAdd16U): - CHECK( - EmitAtomicRMW(f, ValType::I32, Scalar::Uint16, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicOp::Add)); case uint32_t(ThreadOp::I64AtomicAdd8U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicOp::Add)); case uint32_t(ThreadOp::I64AtomicAdd16U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint16, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicOp::Add)); case uint32_t(ThreadOp::I64AtomicAdd32U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint32, AtomicOp::Add)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicOp::Add)); case uint32_t(ThreadOp::I32AtomicSub): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicOp::Sub)); case uint32_t(ThreadOp::I64AtomicSub): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicOp::Sub)); case uint32_t(ThreadOp::I32AtomicSub8U): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicOp::Sub)); case uint32_t(ThreadOp::I32AtomicSub16U): - CHECK( - EmitAtomicRMW(f, ValType::I32, Scalar::Uint16, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicOp::Sub)); case uint32_t(ThreadOp::I64AtomicSub8U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicOp::Sub)); case uint32_t(ThreadOp::I64AtomicSub16U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint16, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicOp::Sub)); case uint32_t(ThreadOp::I64AtomicSub32U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint32, AtomicOp::Sub)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicOp::Sub)); case uint32_t(ThreadOp::I32AtomicAnd): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicOp::And)); case uint32_t(ThreadOp::I64AtomicAnd): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicOp::And)); case uint32_t(ThreadOp::I32AtomicAnd8U): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicOp::And)); case uint32_t(ThreadOp::I32AtomicAnd16U): - CHECK( - EmitAtomicRMW(f, ValType::I32, Scalar::Uint16, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicOp::And)); case uint32_t(ThreadOp::I64AtomicAnd8U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicOp::And)); case uint32_t(ThreadOp::I64AtomicAnd16U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint16, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicOp::And)); case uint32_t(ThreadOp::I64AtomicAnd32U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint32, AtomicOp::And)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicOp::And)); case uint32_t(ThreadOp::I32AtomicOr): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicOp::Or)); case uint32_t(ThreadOp::I64AtomicOr): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicOp::Or)); case uint32_t(ThreadOp::I32AtomicOr8U): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicOp::Or)); case uint32_t(ThreadOp::I32AtomicOr16U): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint16, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicOp::Or)); case uint32_t(ThreadOp::I64AtomicOr8U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicOp::Or)); case uint32_t(ThreadOp::I64AtomicOr16U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint16, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicOp::Or)); case uint32_t(ThreadOp::I64AtomicOr32U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint32, AtomicOp::Or)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicOp::Or)); case uint32_t(ThreadOp::I32AtomicXor): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Int32, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Int32, AtomicOp::Xor)); case uint32_t(ThreadOp::I64AtomicXor): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Int64, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Int64, AtomicOp::Xor)); case uint32_t(ThreadOp::I32AtomicXor8U): - CHECK(EmitAtomicRMW(f, ValType::I32, Scalar::Uint8, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint8, AtomicOp::Xor)); case uint32_t(ThreadOp::I32AtomicXor16U): - CHECK( - EmitAtomicRMW(f, ValType::I32, Scalar::Uint16, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I32, Scalar::Uint16, AtomicOp::Xor)); case uint32_t(ThreadOp::I64AtomicXor8U): - CHECK(EmitAtomicRMW(f, ValType::I64, Scalar::Uint8, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint8, AtomicOp::Xor)); case uint32_t(ThreadOp::I64AtomicXor16U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint16, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint16, AtomicOp::Xor)); case uint32_t(ThreadOp::I64AtomicXor32U): - CHECK( - EmitAtomicRMW(f, ValType::I64, Scalar::Uint32, AtomicOp::Xor)); + CHECK(emitAtomicRMW(ValType::I64, Scalar::Uint32, AtomicOp::Xor)); case uint32_t(ThreadOp::I32AtomicXchg): - CHECK(EmitAtomicXchg(f, ValType::I32, Scalar::Int32)); + CHECK(emitAtomicXchg(ValType::I32, Scalar::Int32)); case uint32_t(ThreadOp::I64AtomicXchg): - CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Int64)); + CHECK(emitAtomicXchg(ValType::I64, Scalar::Int64)); case uint32_t(ThreadOp::I32AtomicXchg8U): - CHECK(EmitAtomicXchg(f, ValType::I32, Scalar::Uint8)); + CHECK(emitAtomicXchg(ValType::I32, Scalar::Uint8)); case uint32_t(ThreadOp::I32AtomicXchg16U): - CHECK(EmitAtomicXchg(f, ValType::I32, Scalar::Uint16)); + CHECK(emitAtomicXchg(ValType::I32, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicXchg8U): - CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Uint8)); + CHECK(emitAtomicXchg(ValType::I64, Scalar::Uint8)); case uint32_t(ThreadOp::I64AtomicXchg16U): - CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Uint16)); + CHECK(emitAtomicXchg(ValType::I64, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicXchg32U): - CHECK(EmitAtomicXchg(f, ValType::I64, Scalar::Uint32)); + CHECK(emitAtomicXchg(ValType::I64, Scalar::Uint32)); case uint32_t(ThreadOp::I32AtomicCmpXchg): - CHECK(EmitAtomicCmpXchg(f, ValType::I32, Scalar::Int32)); + CHECK(emitAtomicCmpXchg(ValType::I32, Scalar::Int32)); case uint32_t(ThreadOp::I64AtomicCmpXchg): - CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Int64)); + CHECK(emitAtomicCmpXchg(ValType::I64, Scalar::Int64)); case uint32_t(ThreadOp::I32AtomicCmpXchg8U): - CHECK(EmitAtomicCmpXchg(f, ValType::I32, Scalar::Uint8)); + CHECK(emitAtomicCmpXchg(ValType::I32, Scalar::Uint8)); case uint32_t(ThreadOp::I32AtomicCmpXchg16U): - CHECK(EmitAtomicCmpXchg(f, ValType::I32, Scalar::Uint16)); + CHECK(emitAtomicCmpXchg(ValType::I32, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicCmpXchg8U): - CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Uint8)); + CHECK(emitAtomicCmpXchg(ValType::I64, Scalar::Uint8)); case uint32_t(ThreadOp::I64AtomicCmpXchg16U): - CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Uint16)); + CHECK(emitAtomicCmpXchg(ValType::I64, Scalar::Uint16)); case uint32_t(ThreadOp::I64AtomicCmpXchg32U): - CHECK(EmitAtomicCmpXchg(f, ValType::I64, Scalar::Uint32)); + CHECK(emitAtomicCmpXchg(ValType::I64, Scalar::Uint32)); default: - return f.iter().unrecognizedOpcode(&op); + return iter().unrecognizedOpcode(&op); } break; } @@ -9222,101 +10407,101 @@ static bool EmitBodyExprs(FunctionCompiler& f) { // asm.js-specific operators case uint16_t(Op::MozPrefix): { if (op.b1 == uint32_t(MozOp::CallBuiltinModuleFunc)) { - if (!f.moduleEnv().isBuiltinModule()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().isBuiltinModule()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitCallBuiltinModuleFunc(f)); + CHECK(emitCallBuiltinModuleFunc()); } #ifdef ENABLE_WASM_JSPI if (op.b1 == uint32_t(MozOp::StackSwitch)) { - if (!f.moduleEnv().isBuiltinModule() || - !f.moduleEnv().jsPromiseIntegrationEnabled()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().isBuiltinModule() || + !codeMeta().jsPromiseIntegrationEnabled()) { + return iter().unrecognizedOpcode(&op); } - CHECK(EmitStackSwitch(f)); + CHECK(emitStackSwitch()); } #endif - if (!f.moduleEnv().isAsmJS()) { - return f.iter().unrecognizedOpcode(&op); + if (!codeMeta().isAsmJS()) { + return iter().unrecognizedOpcode(&op); } switch (op.b1) { case uint32_t(MozOp::TeeGlobal): - CHECK(EmitTeeGlobal(f)); + CHECK(emitTeeGlobal()); case uint32_t(MozOp::I32Min): case uint32_t(MozOp::I32Max): - CHECK(EmitMinMax(f, ValType::I32, MIRType::Int32, + CHECK(emitMinMax(ValType::I32, MIRType::Int32, MozOp(op.b1) == MozOp::I32Max)); case uint32_t(MozOp::I32Neg): - CHECK(EmitUnaryWithType(f, ValType::I32, MIRType::Int32)); + CHECK(emitUnaryWithType(ValType::I32, MIRType::Int32)); case uint32_t(MozOp::I32BitNot): - CHECK(EmitBitNot(f, ValType::I32)); + CHECK(emitBitNot(ValType::I32, MIRType::Int32)); case uint32_t(MozOp::I32Abs): - CHECK(EmitUnaryWithType(f, ValType::I32, MIRType::Int32)); + CHECK(emitUnaryWithType(ValType::I32, MIRType::Int32)); case uint32_t(MozOp::F32TeeStoreF64): - CHECK(EmitTeeStoreWithCoercion(f, ValType::F32, Scalar::Float64)); + CHECK(emitTeeStoreWithCoercion(ValType::F32, Scalar::Float64)); case uint32_t(MozOp::F64TeeStoreF32): - CHECK(EmitTeeStoreWithCoercion(f, ValType::F64, Scalar::Float32)); + CHECK(emitTeeStoreWithCoercion(ValType::F64, Scalar::Float32)); case uint32_t(MozOp::I32TeeStore8): - CHECK(EmitTeeStore(f, ValType::I32, Scalar::Int8)); + CHECK(emitTeeStore(ValType::I32, Scalar::Int8)); case uint32_t(MozOp::I32TeeStore16): - CHECK(EmitTeeStore(f, ValType::I32, Scalar::Int16)); + CHECK(emitTeeStore(ValType::I32, Scalar::Int16)); case uint32_t(MozOp::I64TeeStore8): - CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int8)); + CHECK(emitTeeStore(ValType::I64, Scalar::Int8)); case uint32_t(MozOp::I64TeeStore16): - CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int16)); + CHECK(emitTeeStore(ValType::I64, Scalar::Int16)); case uint32_t(MozOp::I64TeeStore32): - CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int32)); + CHECK(emitTeeStore(ValType::I64, Scalar::Int32)); case uint32_t(MozOp::I32TeeStore): - CHECK(EmitTeeStore(f, ValType::I32, Scalar::Int32)); + CHECK(emitTeeStore(ValType::I32, Scalar::Int32)); case uint32_t(MozOp::I64TeeStore): - CHECK(EmitTeeStore(f, ValType::I64, Scalar::Int64)); + CHECK(emitTeeStore(ValType::I64, Scalar::Int64)); case uint32_t(MozOp::F32TeeStore): - CHECK(EmitTeeStore(f, ValType::F32, Scalar::Float32)); + CHECK(emitTeeStore(ValType::F32, Scalar::Float32)); case uint32_t(MozOp::F64TeeStore): - CHECK(EmitTeeStore(f, ValType::F64, Scalar::Float64)); + CHECK(emitTeeStore(ValType::F64, Scalar::Float64)); case uint32_t(MozOp::F64Mod): - CHECK(EmitRem(f, ValType::F64, MIRType::Double, + CHECK(emitRem(ValType::F64, MIRType::Double, /* isUnsigned = */ false)); case uint32_t(MozOp::F64SinNative): - CHECK(EmitUnaryMathBuiltinCall(f, SASigSinNativeD)); + CHECK(emitUnaryMathBuiltinCall(SASigSinNativeD)); case uint32_t(MozOp::F64SinFdlibm): - CHECK(EmitUnaryMathBuiltinCall(f, SASigSinFdlibmD)); + CHECK(emitUnaryMathBuiltinCall(SASigSinFdlibmD)); case uint32_t(MozOp::F64CosNative): - CHECK(EmitUnaryMathBuiltinCall(f, SASigCosNativeD)); + CHECK(emitUnaryMathBuiltinCall(SASigCosNativeD)); case uint32_t(MozOp::F64CosFdlibm): - CHECK(EmitUnaryMathBuiltinCall(f, SASigCosFdlibmD)); + CHECK(emitUnaryMathBuiltinCall(SASigCosFdlibmD)); case uint32_t(MozOp::F64TanNative): - CHECK(EmitUnaryMathBuiltinCall(f, SASigTanNativeD)); + CHECK(emitUnaryMathBuiltinCall(SASigTanNativeD)); case uint32_t(MozOp::F64TanFdlibm): - CHECK(EmitUnaryMathBuiltinCall(f, SASigTanFdlibmD)); + CHECK(emitUnaryMathBuiltinCall(SASigTanFdlibmD)); case uint32_t(MozOp::F64Asin): - CHECK(EmitUnaryMathBuiltinCall(f, SASigASinD)); + CHECK(emitUnaryMathBuiltinCall(SASigASinD)); case uint32_t(MozOp::F64Acos): - CHECK(EmitUnaryMathBuiltinCall(f, SASigACosD)); + CHECK(emitUnaryMathBuiltinCall(SASigACosD)); case uint32_t(MozOp::F64Atan): - CHECK(EmitUnaryMathBuiltinCall(f, SASigATanD)); + CHECK(emitUnaryMathBuiltinCall(SASigATanD)); case uint32_t(MozOp::F64Exp): - CHECK(EmitUnaryMathBuiltinCall(f, SASigExpD)); + CHECK(emitUnaryMathBuiltinCall(SASigExpD)); case uint32_t(MozOp::F64Log): - CHECK(EmitUnaryMathBuiltinCall(f, SASigLogD)); + CHECK(emitUnaryMathBuiltinCall(SASigLogD)); case uint32_t(MozOp::F64Pow): - CHECK(EmitBinaryMathBuiltinCall(f, SASigPowD)); + CHECK(emitBinaryMathBuiltinCall(SASigPowD)); case uint32_t(MozOp::F64Atan2): - CHECK(EmitBinaryMathBuiltinCall(f, SASigATan2D)); + CHECK(emitBinaryMathBuiltinCall(SASigATan2D)); case uint32_t(MozOp::OldCallDirect): - CHECK(EmitCall(f, /* asmJSFuncDef = */ true)); + CHECK(emitCall(/* asmJSFuncDef = */ true)); case uint32_t(MozOp::OldCallIndirect): - CHECK(EmitCallIndirect(f, /* oldStyle = */ true)); + CHECK(emitCallIndirect(/* oldStyle = */ true)); default: - return f.iter().unrecognizedOpcode(&op); + return iter().unrecognizedOpcode(&op); } break; } default: - return f.iter().unrecognizedOpcode(&op); + return iter().unrecognizedOpcode(&op); } } @@ -9325,53 +10510,164 @@ static bool EmitBodyExprs(FunctionCompiler& f) { #undef CHECK } -static bool IonBuildMIR(Decoder& d, const ModuleEnvironment& moduleEnv, - const FuncCompileInput& func, - const ValTypeVector& locals, MIRGenerator& mir, - TryNoteVector& tryNotes, FeatureUsage* observedFeatures, - UniqueChars* error) { - // Initialize MIR global information used for optimization - if (moduleEnv.numMemories() > 0) { - if (moduleEnv.memories[0].indexType() == IndexType::I32) { - mir.initMinWasmMemory0Length(moduleEnv.memories[0].initialLength32()); +} // end anonymous namespace + +bool RootCompiler::generate() { + // Initialize global information used for optimization + if (codeMeta_.numMemories() > 0) { + if (codeMeta_.memories[0].addressType() == AddressType::I32) { + mirGen_.initMinWasmMemory0Length(codeMeta_.memories[0].initialLength32()); } else { - mir.initMinWasmMemory0Length(moduleEnv.memories[0].initialLength64()); + mirGen_.initMinWasmMemory0Length(codeMeta_.memories[0].initialLength64()); } } - // Build MIR graph - FunctionCompiler f(moduleEnv, d, func, locals, mir, tryNotes); - if (!f.init()) { - return false; + // Only activate branch hinting if the option is enabled and some hints were + // parsed. + if (codeMeta_.branchHintingEnabled() && !codeMeta_.branchHints.isEmpty()) { + compileInfo_.setBranchHinting(true); } - if (!f.startBlock()) { - return false; + // Figure out what the inlining budget for this function is. If we've + // already exceeded the module-level limit, the budget is zero. See + // "[SMDOC] Per-function and per-module inlining limits" (WasmHeuristics.h) + if (codeTailMeta_) { + auto guard = codeTailMeta_->inliningBudget.lock(); + + if (guard.get() > 0) { + localInliningBudget_ = + int64_t(codeMeta_.codeSectionSize()) * PerFunctionMaxInliningRatio; + localInliningBudget_ = + std::min(localInliningBudget_, guard.get()); + } else { + localInliningBudget_ = 0; + } + MOZ_ASSERT(localInliningBudget_ >= 0); + } else { + localInliningBudget_ = 0; } - if (!EmitBodyExprs(f)) { + // Build the MIR graph + FunctionCompiler funcCompiler(*this, decoder_, func_, locals_, compileInfo_); + if (!funcCompiler.initRoot() || !funcCompiler.startBlock() || + !funcCompiler.emitBodyExprs()) { return false; } + funcCompiler.finish(); + observedFeatures_ = funcCompiler.featureUsage(); - f.finish(); + MOZ_ASSERT(loopDepth_ == 0); - *observedFeatures = f.featureUsage(); + funcStats_.numFuncs += 1; + funcStats_.bytecodeSize += func_.bytecodeSize(); + funcStats_.inlinedDirectCallCount += inliningStats_.inlinedDirectFunctions; + funcStats_.inlinedCallRefCount += inliningStats_.inlinedCallRefFunctions; + funcStats_.inlinedDirectCallBytecodeSize += + inliningStats_.inlinedDirectBytecodeSize; + funcStats_.inlinedCallRefBytecodeSize += + inliningStats_.inlinedCallRefBytecodeSize; + funcStats_.numLargeFunctionBackoffs += + inliningStats_.largeFunctionBackoff ? 1 : 0; + + if (codeTailMeta_) { + auto guard = codeTailMeta_->inliningBudget.lock(); + // Update the module's inlining budget accordingly. If it is already + // negative, no more inlining for the module can happen, so there's no + // point in updating it further. + if (guard.get() >= 0) { + guard.get() -= int64_t(inliningStats_.inlinedDirectBytecodeSize); + guard.get() -= int64_t(inliningStats_.inlinedCallRefBytecodeSize); + if (guard.get() < 0) { + JS_LOG(wasmPerf, Info, + "CM=..%06lx RC::generate " + "Inlining budget for entire module exceeded", + 0xFFFFFF & (unsigned long)uintptr_t(&codeMeta_)); + } + } + // If this particular root function overran the function-level + // limit, note that in the module too. + if (localInliningBudget_ < 0) { + funcStats_.numInliningBudgetOverruns += 1; + } + } return true; } -bool wasm::IonCompileFunctions(const ModuleEnvironment& moduleEnv, +CompileInfo* RootCompiler::startInlineCall( + uint32_t callerFuncIndex, BytecodeOffset callerOffset, + uint32_t calleeFuncIndex, uint32_t numLocals, size_t inlineeBytecodeSize, + InliningHeuristics::CallKind callKind) { + if (callKind == InliningHeuristics::CallKind::Direct) { + inliningStats_.inlinedDirectBytecodeSize += inlineeBytecodeSize; + inliningStats_.inlinedDirectFunctions += 1; + } else { + MOZ_ASSERT(callKind == InliningHeuristics::CallKind::CallRef); + inliningStats_.inlinedCallRefBytecodeSize += inlineeBytecodeSize; + inliningStats_.inlinedCallRefFunctions += 1; + } + + // Update the inlining budget accordingly. If it is already negative, no + // more inlining within this root function can happen, so there's no + // point in updating it further. + if (localInliningBudget_ >= 0) { + localInliningBudget_ -= int64_t(inlineeBytecodeSize); +#ifdef JS_JITSPEW + if (localInliningBudget_ <= 0) { + JS_LOG(wasmPerf, Info, + "CM=..%06lx RC::startInlineCall " + "Inlining budget for fI=%u exceeded", + 0xFFFFFF & (unsigned long)uintptr_t(&codeMeta_), callerFuncIndex); + } +#endif + } + + // Add the callers offset to the stack of inlined caller offsets + if (!inlinedCallerOffsets_.append(callerOffset)) { + return nullptr; + } + + // Cache a copy of the current stack of inlined caller offsets that can be + // shared across all call sites + InlinedCallerOffsets inlinedCallerOffsets; + if (!inlinedCallerOffsets.appendAll(inlinedCallerOffsets_)) { + return nullptr; + } + + if (!inliningContext_.append(std::move(inlinedCallerOffsets), + &inlinedCallerOffsetsIndex_)) { + return nullptr; + } + + UniqueCompileInfo compileInfo = MakeUnique(numLocals); + if (!compileInfo || !compileInfos_.append(std::move(compileInfo))) { + return nullptr; + } + return compileInfos_[compileInfos_.length() - 1].get(); +} + +void RootCompiler::finishInlineCall() { inlinedCallerOffsets_.popBack(); } + +bool wasm::IonCompileFunctions(const CodeMetadata& codeMeta, + const CodeTailMetadata* codeTailMeta, const CompilerEnvironment& compilerEnv, LifoAlloc& lifo, const FuncCompileInputVector& inputs, CompiledCode* code, UniqueChars* error) { MOZ_ASSERT(compilerEnv.tier() == Tier::Optimized); MOZ_ASSERT(compilerEnv.debug() == DebugEnabled::False); + MOZ_ASSERT_IF(compilerEnv.mode() == CompileMode::LazyTiering, !!codeTailMeta); + + // We should not interact with the GC heap, nor allocate from it when we are + // compiling wasm code. Ion data structures have some fields for GC objects + // that we do not use, yet can confuse the static analysis here. Disable it + // for this function. + JS::AutoSuppressGCAnalysis nogc; TempAllocator alloc(&lifo); JitContext jitContext; MOZ_ASSERT(IsCompilingWasm()); - WasmMacroAssembler masm(alloc, moduleEnv); + WasmMacroAssembler masm(alloc); #if defined(JS_CODEGEN_ARM64) masm.SetStackPointer64(PseudoStackPointer64); #endif @@ -9401,67 +10697,73 @@ bool wasm::IonCompileFunctions(const ModuleEnvironment& moduleEnv, // Build the local types vector. ValTypeVector locals; - if (!DecodeLocalEntriesWithParams(d, moduleEnv, func.index, &locals)) { + if (!DecodeLocalEntriesWithParams(d, codeMeta, func.index, &locals)) { return false; } // Set up for Ion compilation. - const JitCompileOptions options; - MIRGraph graph(&alloc); - CompileInfo compileInfo(locals.length()); - // Only activate branch hinting if the option is enabled and some hints were - // parsed. - if (moduleEnv.branchHintingEnabled() && !moduleEnv.branchHints.isEmpty()) { - compileInfo.setBranchHinting(true); - } - - MIRGenerator mir(nullptr, options, &alloc, &graph, &compileInfo, - IonOptimizations.get(OptimizationLevel::Wasm)); - - // Build MIR graph - FeatureUsage observedFeatures; - if (!IonBuildMIR(d, moduleEnv, func, locals, mir, masm.tryNotes(), - &observedFeatures, error)) { + RootCompiler rootCompiler(compilerEnv, codeMeta, codeTailMeta, alloc, + locals, func, d, masm.tryNotes(), + masm.inliningContext()); + if (!rootCompiler.generate()) { return false; } // Record observed feature usage + FeatureUsage observedFeatures = rootCompiler.observedFeatures(); code->featureUsage |= observedFeatures; // Compile MIR graph { - jit::SpewBeginWasmFunction(&mir, func.index); - jit::AutoSpewEndFunction spewEndFunction(&mir); + jit::SpewBeginWasmFunction(&rootCompiler.mirGen(), func.index); + jit::AutoSpewEndFunction spewEndFunction(&rootCompiler.mirGen()); - if (!OptimizeMIR(&mir)) { + if (!OptimizeMIR(&rootCompiler.mirGen())) { return false; } - LIRGraph* lir = GenerateLIR(&mir); + LIRGraph* lir = GenerateLIR(&rootCompiler.mirGen()); if (!lir) { return false; } size_t unwindInfoBefore = masm.codeRangeUnwindInfos().length(); - CodeGenerator codegen(&mir, lir, &masm); + CodeGenerator codegen(&rootCompiler.mirGen(), lir, &masm, &codeMeta); - BytecodeOffset prologueTrapOffset(func.lineOrBytecode); + TrapSiteDesc prologueTrapSiteDesc( + wasm::BytecodeOffset(func.lineOrBytecode)); FuncOffsets offsets; - ArgTypeVector args(*moduleEnv.funcs[func.index].type); - if (!codegen.generateWasm(CallIndirectId::forFunc(moduleEnv, func.index), - prologueTrapOffset, args, trapExitLayout, + ArgTypeVector args(codeMeta.getFuncType(func.index)); + IonPerfSpewer spewer; + if (!codegen.generateWasm(CallIndirectId::forFunc(codeMeta, func.index), + prologueTrapSiteDesc, args, trapExitLayout, trapExitLayoutNumWords, &offsets, - &code->stackMaps, &d)) { + &code->stackMaps, &d, &spewer)) { return false; } bool hasUnwindInfo = unwindInfoBefore != masm.codeRangeUnwindInfos().length(); - if (!code->codeRanges.emplaceBack(func.index, func.lineOrBytecode, - offsets, hasUnwindInfo)) { + + // Record this function's code range + if (!code->codeRanges.emplaceBack(func.index, offsets, hasUnwindInfo)) { return false; } + + if (PerfEnabled()) { + if (!code->funcIonSpewers.emplaceBack(func.index, std::move(spewer))) { + return false; + } + } + } + + // Record this function's compilation stats + code->compileStats.merge(rootCompiler.funcStats()); + + // Record this function's specific feature usage + if (!code->funcs.emplaceBack(func.index, observedFeatures)) { + return false; } JitSpew(JitSpew_Codegen, @@ -9482,54 +10784,49 @@ bool wasm::IonCompileFunctions(const ModuleEnvironment& moduleEnv, return code->swap(masm); } -bool wasm::IonDumpFunction(const ModuleEnvironment& moduleEnv, +bool wasm::IonDumpFunction(const CompilerEnvironment& compilerEnv, + const CodeMetadata& codeMeta, const FuncCompileInput& func, IonDumpContents contents, GenericPrinter& out, UniqueChars* error) { - LifoAlloc lifo(TempAllocator::PreferredLifoChunkSize); + LifoAlloc lifo(TempAllocator::PreferredLifoChunkSize, + js::BackgroundMallocArena); TempAllocator alloc(&lifo); JitContext jitContext; Decoder d(func.begin, func.end, func.lineOrBytecode, error); // Decode the locals. ValTypeVector locals; - if (!DecodeLocalEntriesWithParams(d, moduleEnv, func.index, &locals)) { + if (!DecodeLocalEntriesWithParams(d, codeMeta, func.index, &locals)) { return false; } - // Set up for Ion compilation. - const JitCompileOptions options; - MIRGraph graph(&alloc); - CompileInfo compileInfo(locals.length()); - MIRGenerator mir(nullptr, options, &alloc, &graph, &compileInfo, - IonOptimizations.get(OptimizationLevel::Wasm)); - - // Build MIR graph TryNoteVector tryNotes; - FeatureUsage observedFeatures; - if (!IonBuildMIR(d, moduleEnv, func, locals, mir, tryNotes, &observedFeatures, - error)) { + InliningContext inliningContext; + RootCompiler rootCompiler(compilerEnv, codeMeta, nullptr, alloc, locals, func, + d, tryNotes, inliningContext); + if (!rootCompiler.generate()) { return false; } if (contents == IonDumpContents::UnoptimizedMIR) { - graph.dump(out); + rootCompiler.mirGraph().dump(out); return true; } // Optimize the MIR graph - if (!OptimizeMIR(&mir)) { + if (!OptimizeMIR(&rootCompiler.mirGen())) { return false; } if (contents == IonDumpContents::OptimizedMIR) { - graph.dump(out); + rootCompiler.mirGraph().dump(out); return true; } #ifdef JS_JITSPEW // Generate the LIR graph - LIRGraph* lir = GenerateLIR(&mir); + LIRGraph* lir = GenerateLIR(&rootCompiler.mirGen()); if (!lir) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.h b/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.h index 4597c08be1c..fb1b40f8df4 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmIonCompile.h @@ -32,13 +32,15 @@ namespace wasm { [[nodiscard]] bool IonPlatformSupport(); // Generates very fast code at the expense of compilation time. -[[nodiscard]] bool IonCompileFunctions(const ModuleEnvironment& moduleEnv, +[[nodiscard]] bool IonCompileFunctions(const CodeMetadata& codeMeta, + const CodeTailMetadata* codeTailMeta, const CompilerEnvironment& compilerEnv, LifoAlloc& lifo, const FuncCompileInputVector& inputs, CompiledCode* code, UniqueChars* error); -[[nodiscard]] bool IonDumpFunction(const ModuleEnvironment& moduleEnv, +[[nodiscard]] bool IonDumpFunction(const CompilerEnvironment& compilerEnv, + const CodeMetadata& codeMeta, const FuncCompileInput& func, IonDumpContents contents, GenericPrinter& out, UniqueChars* error); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmJS.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmJS.cpp index 1ba7067d078..fe361d3cc7e 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmJS.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmJS.cpp @@ -18,10 +18,8 @@ #include "wasm/WasmJS.h" -#include "mozilla/CheckedInt.h" #include "mozilla/EndianUtils.h" #include "mozilla/Maybe.h" -#include "mozilla/RangedPtr.h" #include #include @@ -45,7 +43,7 @@ #include "js/PropertySpec.h" // JS_{PS,FN}{,_END} #include "js/Stack.h" // BuildStackString #include "js/StreamConsumer.h" -#include "util/StringBuffer.h" +#include "util/StringBuilder.h" #include "util/Text.h" #include "vm/ErrorObject.h" #include "vm/FunctionFlags.h" // js::FunctionFlags @@ -99,9 +97,9 @@ using namespace js; using namespace js::jit; using namespace js::wasm; -using mozilla::CheckedInt; +using mozilla::Maybe; using mozilla::Nothing; -using mozilla::RangedPtr; +using mozilla::Some; using mozilla::Span; static bool ThrowCompileOutOfMemory(JSContext* cx) { @@ -146,34 +144,43 @@ static bool IsWasmSuspendingWrapper(const Value& v) { bool js::wasm::GetImports(JSContext* cx, const Module& module, HandleObject importObj, ImportValues* imports) { - if (!module.imports().empty() && !importObj) { + const ModuleMetadata& moduleMeta = module.moduleMeta(); + const CodeMetadata& codeMeta = module.codeMeta(); + const BuiltinModuleIds& builtinModules = codeMeta.features().builtinModules; + + if (!moduleMeta.imports.empty() && !importObj) { return ThrowBadImportArg(cx); } - const Metadata& metadata = module.metadata(); - BuiltinModuleInstances builtinInstances(cx); RootedValue importModuleValue(cx); RootedObject importModuleObject(cx); + bool isImportedStringModule = false; RootedValue importFieldValue(cx); uint32_t tagIndex = 0; - const TagDescVector& tags = metadata.tags; + const TagDescVector& tags = codeMeta.tags; uint32_t globalIndex = 0; - const GlobalDescVector& globals = metadata.globals; + const GlobalDescVector& globals = codeMeta.globals; uint32_t tableIndex = 0; - const TableDescVector& tables = metadata.tables; - for (const Import& import : module.imports()) { - Maybe builtinModule = ImportMatchesBuiltinModule( - import.module.utf8Bytes(), metadata.builtinModules); + const TableDescVector& tables = codeMeta.tables; + for (const Import& import : moduleMeta.imports) { + Maybe builtinModule = + ImportMatchesBuiltinModule(import.module.utf8Bytes(), builtinModules); if (builtinModule) { - MutableHandle builtinInstance = - builtinInstances[*builtinModule]; - if (!builtinInstance && !wasm::InstantiateBuiltinModule( - cx, *builtinModule, builtinInstance)) { - return false; + if (*builtinModule == BuiltinModuleId::JSStringConstants) { + isImportedStringModule = true; + importModuleObject = nullptr; + } else { + MutableHandle builtinInstance = + builtinInstances[*builtinModule]; + if (!builtinInstance && !wasm::InstantiateBuiltinModule( + cx, *builtinModule, builtinInstance)) { + return false; + } + isImportedStringModule = false; + importModuleObject = builtinInstance; } - importModuleObject = builtinInstance; } else { RootedId moduleName(cx); if (!import.module.toPropertyKey(cx, &moduleName)) { @@ -197,17 +204,28 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, return false; } + isImportedStringModule = false; importModuleObject = &importModuleValue.toObject(); } + MOZ_RELEASE_ASSERT(!isImportedStringModule || + import.kind == DefinitionKind::Global); - RootedId fieldName(cx); - if (!import.field.toPropertyKey(cx, &fieldName)) { - return false; - } - - if (!GetProperty(cx, importModuleObject, importModuleObject, fieldName, - &importFieldValue)) { - return false; + if (isImportedStringModule) { + RootedString stringConstant(cx, import.field.toJSString(cx)); + if (!stringConstant) { + ReportOutOfMemory(cx); + return false; + } + importFieldValue = StringValue(stringConstant); + } else { + RootedId fieldName(cx); + if (!import.field.toPropertyKey(cx, &fieldName)) { + return false; + } + if (!GetProperty(cx, importModuleObject, importModuleObject, fieldName, + &importFieldValue)) { + return false; + } } switch (import.kind) { @@ -218,6 +236,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, } if (!imports->funcs.append(&importFieldValue.toObject())) { + ReportOutOfMemory(cx); return false; } @@ -239,6 +258,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, } if (!imports->tables.append(obj)) { + ReportOutOfMemory(cx); return false; } break; @@ -251,6 +271,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, if (!imports->memories.append( &importFieldValue.toObject().as())) { + ReportOutOfMemory(cx); return false; } break; @@ -267,7 +288,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, // Checks whether the signature of the imported exception object matches // the signature declared in the exception import's TagDesc. - if (obj->resultType() != tags[index].type->resultType()) { + if (!TagType::matches(*obj->tagType(), *tags[index].type)) { UniqueChars fieldQuoted = import.field.toQuotedString(cx); UniqueChars moduleQuoted = import.module.toQuotedString(cx); if (!fieldQuoted || !moduleQuoted) { @@ -341,6 +362,7 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, } if (!imports->globalValues.append(val)) { + ReportOutOfMemory(cx); return false; } @@ -362,7 +384,7 @@ static bool DescribeScriptedCaller(JSContext* cx, ScriptedCaller* caller, // back to the more ordinary false-if-error form. JS::AutoFilename af; - if (JS::DescribeScriptedCaller(cx, &af, &caller->line)) { + if (JS::DescribeScriptedCaller(&af, cx, &caller->line)) { caller->filename = FormatIntroducedFilename(af.get(), caller->line, introducer); if (!caller->filename) { @@ -394,27 +416,18 @@ bool wasm::Eval(JSContext* cx, Handle code, return false; } - MutableBytes bytecode = cx->new_(); - if (!bytecode) { - return false; - } - - if (!bytecode->append((uint8_t*)code->dataPointerEither().unwrap(), - code->byteLength().valueOr(0))) { - ReportOutOfMemory(cx); - return false; - } - FeatureOptions options; SharedCompileArgs compileArgs = InitCompileArgs(cx, options, "wasm_eval"); if (!compileArgs) { return false; } + BytecodeSource source((uint8_t*)code->dataPointerEither().unwrap(), + code->byteLength().valueOr(0)); UniqueChars error; UniqueCharsVector warnings; - SharedModule module = - CompileBuffer(*compileArgs, *bytecode, &error, &warnings, nullptr); + SharedModule module = CompileBuffer( + *compileArgs, BytecodeBufferOrSource(source), &error, &warnings, nullptr); if (!module) { if (error) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, @@ -437,7 +450,7 @@ struct MOZ_STACK_CLASS SerializeListener : JS::OptimizedEncodingListener { MozExternalRefCountType MOZ_XPCOM_ABI AddRef() override { return 0; } MozExternalRefCountType MOZ_XPCOM_ABI Release() override { return 0; } - DebugOnly called = false; + mozilla::DebugOnly called = false; Bytes* serialized; explicit SerializeListener(Bytes* serialized) : serialized(serialized) {} @@ -450,13 +463,14 @@ struct MOZ_STACK_CLASS SerializeListener : JS::OptimizedEncodingListener { } }; -bool wasm::CompileAndSerialize(JSContext* cx, const ShareableBytes& bytecode, +bool wasm::CompileAndSerialize(JSContext* cx, + const BytecodeSource& bytecodeSource, Bytes* serialized) { // The caller must check that code caching is available MOZ_ASSERT(CodeCachingAvailable(cx)); // Create and manually fill in compile args for code caching - MutableCompileArgs compileArgs = js_new(ScriptedCaller()); + MutableCompileArgs compileArgs = js_new(); if (!compileArgs) { return false; } @@ -484,13 +498,14 @@ bool wasm::CompileAndSerialize(JSContext* cx, const ShareableBytes& bytecode, UniqueChars error; UniqueCharsVector warnings; SharedModule module = - CompileBuffer(*compileArgs, bytecode, &error, &warnings, &listener); + CompileBuffer(*compileArgs, BytecodeBufferOrSource(bytecodeSource), + &error, &warnings, &listener); if (!module) { fprintf(stderr, "Compilation error: %s\n", error ? error.get() : "oom"); return false; } - MOZ_ASSERT(module->code().hasTier(Tier::Serialized)); + MOZ_ASSERT(module->code().hasCompleteTier(Tier::Serialized)); MOZ_ASSERT(listener.called); return !listener.serialized->empty(); } @@ -569,9 +584,71 @@ static bool EnforceRangeU64(JSContext* cx, HandleValue v, const char* kind, return EnforceRange(cx, v, kind, noun, (1LL << 53) - 1, u64); } -static bool GetLimit(JSContext* cx, HandleObject obj, const char* name, - const char* noun, const char* msg, uint32_t range, - bool* found, uint64_t* value) { +static bool EnforceRangeBigInt64(JSContext* cx, HandleValue v, const char* kind, + const char* noun, uint64_t* u64) { + RootedBigInt bi(cx, ToBigInt(cx, v)); + if (!bi) { + return false; + } + if (!BigInt::isUint64(bi, u64)) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_BAD_ENFORCE_RANGE, kind, noun); + return false; + } + return true; +} + +static bool EnforceAddressValue(JSContext* cx, HandleValue v, + AddressType addressType, const char* kind, + const char* noun, uint64_t* result) { + switch (addressType) { + case AddressType::I32: { + uint32_t result32; + if (!EnforceRangeU32(cx, v, kind, noun, &result32)) { + return false; + } + *result = uint64_t(result32); + return true; + } + case AddressType::I64: + return EnforceRangeBigInt64(cx, v, kind, noun, result); + default: + MOZ_CRASH("unknown address type"); + } +} + +// The AddressValue typedef, a union of number and bigint, is used in the JS API +// spec for memory and table arguments, where number is used for memory32 and +// bigint is used for memory64. +[[nodiscard]] static bool CreateAddressValue(JSContext* cx, uint64_t value, + AddressType addressType, + MutableHandleValue addressValue) { + switch (addressType) { + case AddressType::I32: + MOZ_ASSERT(value <= UINT32_MAX); + addressValue.set(NumberValue(value)); + return true; + case AddressType::I64: { + BigInt* bi = BigInt::createFromUint64(cx, value); + if (!bi) { + return false; + } + addressValue.set(BigIntValue(bi)); + return true; + } + default: + MOZ_CRASH("unknown address type"); + } +} + +// Gets an AddressValue property ("initial" or "maximum") from a +// MemoryDescriptor or TableDescriptor. The values returned by this should be +// run through CheckLimits to enforce the validation limits prescribed by the +// spec. +static bool GetDescriptorAddressValue(JSContext* cx, HandleObject obj, + const char* name, const char* noun, + const char* msg, AddressType addressType, + bool* found, uint64_t* value) { JSAtom* atom = Atomize(cx, name, strlen(name)); if (!atom) { return false; @@ -588,56 +665,48 @@ static bool GetLimit(JSContext* cx, HandleObject obj, const char* name, return true; } *found = true; - // The range can be greater than 53, but then the logic in EnforceRange has to - // change to avoid precision loss. - MOZ_ASSERT(range < 54); - return EnforceRange(cx, val, noun, msg, (uint64_t(1) << range) - 1, value); + + return EnforceAddressValue(cx, val, addressType, noun, msg, value); } static bool GetLimits(JSContext* cx, HandleObject obj, LimitsKind kind, Limits* limits) { - limits->indexType = IndexType::I32; + limits->addressType = AddressType::I32; - // Memory limits may specify an alternate index type, and we need this to - // check the ranges for initial and maximum, so look for the index type first. - if (kind == LimitsKind::Memory) { + // Limits may specify an alternate address type, and we need this to check the + // ranges for initial and maximum, so look for the address type first. #ifdef ENABLE_WASM_MEMORY64 - // Get the index type field - JSAtom* indexTypeAtom = Atomize(cx, "index", strlen("index")); - if (!indexTypeAtom) { - return false; - } - RootedId indexTypeId(cx, AtomToId(indexTypeAtom)); - - RootedValue indexTypeVal(cx); - if (!GetProperty(cx, obj, obj, indexTypeId, &indexTypeVal)) { - return false; - } - - // The index type has a default value - if (!indexTypeVal.isUndefined()) { - if (!ToIndexType(cx, indexTypeVal, &limits->indexType)) { - return false; - } - - if (limits->indexType == IndexType::I64 && !Memory64Available(cx)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_WASM_NO_MEM64_LINK); - return false; - } - } -#endif + // Get the address type field + JSAtom* addressTypeAtom = Atomize(cx, "address", strlen("address")); + if (!addressTypeAtom) { + return false; + } + RootedId addressTypeId(cx, AtomToId(addressTypeAtom)); + RootedValue addressTypeVal(cx); + if (!GetProperty(cx, obj, obj, addressTypeId, &addressTypeVal)) { + return false; } - const char* noun = (kind == LimitsKind::Memory ? "Memory" : "Table"); - // 2^48 is a valid value, so the range goes to 49 bits. Values above 2^48 are - // filtered later, just as values above 2^16 are filtered for mem32. - const uint32_t range = limits->indexType == IndexType::I32 ? 32 : 49; + // The address type has a default value + if (!addressTypeVal.isUndefined()) { + if (!ToAddressType(cx, addressTypeVal, &limits->addressType)) { + return false; + } + + if (limits->addressType == AddressType::I64 && !Memory64Available(cx)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_WASM_NO_MEM64_LINK); + return false; + } + } +#endif + + const char* noun = ToString(kind); uint64_t limit = 0; bool haveInitial = false; - if (!GetLimit(cx, obj, "initial", noun, "initial size", range, &haveInitial, - &limit)) { + if (!GetDescriptorAddressValue(cx, obj, "initial", noun, "initial size", + limits->addressType, &haveInitial, &limit)) { return false; } if (haveInitial) { @@ -646,8 +715,8 @@ static bool GetLimits(JSContext* cx, HandleObject obj, LimitsKind kind, bool haveMinimum = false; #ifdef ENABLE_WASM_TYPE_REFLECTIONS - if (!GetLimit(cx, obj, "minimum", noun, "initial size", range, &haveMinimum, - &limit)) { + if (!GetDescriptorAddressValue(cx, obj, "minimum", noun, "initial size", + limits->addressType, &haveMinimum, &limit)) { return false; } if (haveMinimum) { @@ -667,8 +736,8 @@ static bool GetLimits(JSContext* cx, HandleObject obj, LimitsKind kind, } bool haveMaximum = false; - if (!GetLimit(cx, obj, "maximum", noun, "maximum size", range, &haveMaximum, - &limit)) { + if (!GetDescriptorAddressValue(cx, obj, "maximum", noun, "maximum size", + limits->addressType, &haveMaximum, &limit)) { return false; } if (haveMaximum) { @@ -717,22 +786,45 @@ static bool GetLimits(JSContext* cx, HandleObject obj, LimitsKind kind, return true; } -static bool CheckLimits(JSContext* cx, uint64_t maximumField, LimitsKind kind, +static bool CheckLimits(JSContext* cx, uint64_t validationMax, LimitsKind kind, Limits* limits) { - const char* noun = (kind == LimitsKind::Memory ? "Memory" : "Table"); + const char* noun = ToString(kind); - if (limits->initial > maximumField) { + // There are several layers of validation and error-throwing here, including + // one which is currently not defined by the JS API spec: + // + // - [EnforceRange] on parameters (must be TypeError) + // - A check that initial <= maximum (must be RangeError) + // - Either a mem_alloc or table_alloc operation, which has two components: + // - A pre-condition that the given memory or table type is valid + // (not specified, RangeError in practice) + // - The actual allocation (should report OOM if it fails) + // + // There are two questions currently left open by the spec: when is the memory + // or table type validated, and if it is invalid, what type of exception does + // it throw? In practice, all browsers throw RangeError, and by the time you + // read this the spec will hopefully have been updated to reflect this. See + // the following issue: https://github.com/WebAssembly/spec/issues/1792 + + // Check that initial <= maximum + if (limits->maximum.isSome() && *limits->maximum < limits->initial) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_MAX_LT_INITIAL, noun); + return false; + } + + // Check wasm validation limits + if (limits->initial > validationMax) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_RANGE, noun, "initial size"); return false; } - - if (limits->maximum.isSome() && - (*limits->maximum > maximumField || limits->initial > *limits->maximum)) { + if (limits->maximum.isSome() && *limits->maximum > validationMax) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_RANGE, noun, "maximum size"); return false; } + return true; } @@ -796,6 +888,12 @@ static JSString* TypeToString(JSContext* cx, T type) { cx, JS::ConstUTF8CharsZ(chars.get(), strlen(chars.get()))); } +# ifdef ENABLE_WASM_MEMORY64 +static JSString* AddressTypeToString(JSContext* cx, AddressType type) { + return JS_NewStringCopyZ(cx, ToString(type)); +} +# endif + [[nodiscard]] static JSObject* ValTypesToArray(JSContext* cx, const ValTypeVector& valTypes) { Rooted arrayObj(cx, NewDenseEmptyArray(cx)); @@ -835,8 +933,9 @@ static JSObject* FuncTypeToObject(JSContext* cx, const FuncType& type) { return NewPlainObjectWithUniqueNames(cx, props); } -static JSObject* TableTypeToObject(JSContext* cx, RefType type, - uint32_t initial, Maybe maximum) { +static JSObject* TableTypeToObject(JSContext* cx, AddressType addressType, + RefType type, uint64_t initial, + Maybe maximum) { Rooted props(cx, IdValueVector(cx)); RootedString elementType(cx, TypeToString(cx, type)); @@ -847,62 +946,81 @@ static JSObject* TableTypeToObject(JSContext* cx, RefType type, } if (maximum.isSome()) { - if (!props.append(IdValuePair(NameToId(cx->names().maximum), - NumberValue(maximum.value())))) { + RootedId maximumId(cx, NameToId(cx->names().maximum)); + RootedValue maximumValue(cx); + if (!CreateAddressValue(cx, maximum.value(), addressType, &maximumValue)) { + ReportOutOfMemory(cx); + return nullptr; + } + if (!props.append(IdValuePair(maximumId, maximumValue))) { ReportOutOfMemory(cx); return nullptr; } } - if (!props.append( - IdValuePair(NameToId(cx->names().minimum), NumberValue(initial)))) { + RootedId minimumId(cx, NameToId(cx->names().minimum)); + RootedValue minimumValue(cx); + if (!CreateAddressValue(cx, initial, addressType, &minimumValue)) { ReportOutOfMemory(cx); return nullptr; } - - return NewPlainObjectWithUniqueNames(cx, props); -} - -static JSObject* MemoryTypeToObject(JSContext* cx, bool shared, - wasm::IndexType indexType, - wasm::Pages minPages, - Maybe maxPages) { - Rooted props(cx, IdValueVector(cx)); - if (maxPages) { - double maxPagesNum; - if (indexType == IndexType::I32) { - maxPagesNum = double(mozilla::AssertedCast(maxPages->value())); - } else { - // The maximum number of pages is 2^48. - maxPagesNum = double(maxPages->value()); - } - if (!props.append(IdValuePair(NameToId(cx->names().maximum), - NumberValue(maxPagesNum)))) { - ReportOutOfMemory(cx); - return nullptr; - } - } - - double minPagesNum; - if (indexType == IndexType::I32) { - minPagesNum = double(mozilla::AssertedCast(minPages.value())); - } else { - minPagesNum = double(minPages.value()); - } - if (!props.append(IdValuePair(NameToId(cx->names().minimum), - NumberValue(minPagesNum)))) { + if (!props.append(IdValuePair(minimumId, minimumValue))) { ReportOutOfMemory(cx); return nullptr; } # ifdef ENABLE_WASM_MEMORY64 - RootedString it( - cx, JS_NewStringCopyZ(cx, indexType == IndexType::I32 ? "i32" : "i64")); - if (!it) { + RootedString at(cx, AddressTypeToString(cx, addressType)); + if (!at) { return nullptr; } if (!props.append( - IdValuePair(NameToId(cx->names().index), StringValue(it)))) { + IdValuePair(NameToId(cx->names().address), StringValue(at)))) { + ReportOutOfMemory(cx); + return nullptr; + } +# endif + + return NewPlainObjectWithUniqueNames(cx, props); +} + +static JSObject* MemoryTypeToObject(JSContext* cx, bool shared, + wasm::AddressType addressType, + wasm::Pages minPages, + Maybe maxPages) { + Rooted props(cx, IdValueVector(cx)); + if (maxPages) { + RootedId maximumId(cx, NameToId(cx->names().maximum)); + RootedValue maximumValue(cx); + if (!CreateAddressValue(cx, maxPages.value().value(), addressType, + &maximumValue)) { + ReportOutOfMemory(cx); + return nullptr; + } + if (!props.append(IdValuePair(maximumId, maximumValue))) { + ReportOutOfMemory(cx); + return nullptr; + } + } + + RootedId minimumId(cx, NameToId(cx->names().minimum)); + RootedValue minimumValue(cx); + if (!CreateAddressValue(cx, minPages.value(), addressType, &minimumValue)) { + ReportOutOfMemory(cx); + return nullptr; + } + if (!props.append(IdValuePair(minimumId, minimumValue))) { + ReportOutOfMemory(cx); + return nullptr; + } + +# ifdef ENABLE_WASM_MEMORY64 + RootedString at(cx, AddressTypeToString(cx, addressType)); + if (!at) { + return nullptr; + } + if (!props.append( + IdValuePair(NameToId(cx->names().address), StringValue(at)))) { ReportOutOfMemory(cx); return nullptr; } @@ -990,25 +1108,33 @@ const ClassSpec WasmModuleObject::classSpec_ = { WasmModuleObject::methods, WasmModuleObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; const JSPropertySpec WasmModuleObject::properties[] = { JS_STRING_SYM_PS(toStringTag, "WebAssembly.Module", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; -const JSFunctionSpec WasmModuleObject::methods[] = {JS_FS_END}; +const JSFunctionSpec WasmModuleObject::methods[] = { + JS_FS_END, +}; const JSFunctionSpec WasmModuleObject::static_methods[] = { JS_FN("imports", WasmModuleObject::imports, 1, JSPROP_ENUMERATE), JS_FN("exports", WasmModuleObject::exports, 1, JSPROP_ENUMERATE), JS_FN("customSections", WasmModuleObject::customSections, 2, JSPROP_ENUMERATE), - JS_FS_END}; + JS_FS_END, +}; /* static */ void WasmModuleObject::finalize(JS::GCContext* gcx, JSObject* obj) { const Module& module = obj->as().module(); - obj->zone()->decJitMemory(module.codeLength(module.code().stableTier())); + size_t codeMemory = module.tier1CodeMemoryUsed(); + if (codeMemory) { + obj->zone()->decJitMemory(codeMemory); + } gcx->release(obj, &module, module.gcMallocBytesExcludingCode(), MemoryUse::WasmModule); } @@ -1116,16 +1242,19 @@ bool WasmModuleObject::imports(JSContext* cx, unsigned argc, Value* vp) { return false; } + const ModuleMetadata& moduleMeta = module->moduleMeta(); + RootedValueVector elems(cx); - if (!elems.reserve(module->imports().length())) { + if (!elems.reserve(moduleMeta.imports.length())) { return false; } -#ifdef ENABLE_WASM_TYPE_REFLECTIONS - const Metadata& metadata = module->metadata(); - const MetadataTier& metadataTier = - module->metadata(module->code().stableTier()); +#if defined(ENABLE_WASM_JS_STRING_BUILTINS) || \ + defined(ENABLE_WASM_TYPE_REFLECTIONS) + const CodeMetadata& codeMeta = module->codeMeta(); +#endif +#if defined(ENABLE_WASM_TYPE_REFLECTIONS) size_t numFuncImport = 0; size_t numMemoryImport = 0; size_t numGlobalImport = 0; @@ -1133,7 +1262,15 @@ bool WasmModuleObject::imports(JSContext* cx, unsigned argc, Value* vp) { size_t numTagImport = 0; #endif // ENABLE_WASM_TYPE_REFLECTIONS - for (const Import& import : module->imports()) { + for (const Import& import : moduleMeta.imports) { +#ifdef ENABLE_WASM_JS_STRING_BUILTINS + Maybe builtinModule = ImportMatchesBuiltinModule( + import.module.utf8Bytes(), codeMeta.features().builtinModules); + if (builtinModule) { + continue; + } +#endif + Rooted props(cx, IdValueVector(cx)); if (!props.reserve(3)) { return false; @@ -1165,35 +1302,35 @@ bool WasmModuleObject::imports(JSContext* cx, unsigned argc, Value* vp) { switch (import.kind) { case DefinitionKind::Function: { size_t funcIndex = numFuncImport++; - const FuncType& funcType = - metadata.getFuncImportType(metadataTier.funcImports[funcIndex]); + const FuncType& funcType = codeMeta.getFuncType(funcIndex); typeObj = FuncTypeToObject(cx, funcType); break; } case DefinitionKind::Table: { size_t tableIndex = numTableImport++; - const TableDesc& table = metadata.tables[tableIndex]; - typeObj = TableTypeToObject(cx, table.elemType, table.initialLength, - table.maximumLength); + const TableDesc& table = codeMeta.tables[tableIndex]; + typeObj = + TableTypeToObject(cx, table.addressType(), table.elemType, + table.initialLength(), table.maximumLength()); break; } case DefinitionKind::Memory: { size_t memoryIndex = numMemoryImport++; - const MemoryDesc& memory = metadata.memories[memoryIndex]; + const MemoryDesc& memory = codeMeta.memories[memoryIndex]; typeObj = - MemoryTypeToObject(cx, memory.isShared(), memory.indexType(), + MemoryTypeToObject(cx, memory.isShared(), memory.addressType(), memory.initialPages(), memory.maximumPages()); break; } case DefinitionKind::Global: { size_t globalIndex = numGlobalImport++; - const GlobalDesc& global = metadata.globals[globalIndex]; + const GlobalDesc& global = codeMeta.globals[globalIndex]; typeObj = GlobalTypeToObject(cx, global.type(), global.isMutable()); break; } case DefinitionKind::Tag: { size_t tagIndex = numTagImport++; - const TagDesc& tag = metadata.tags[tagIndex]; + const TagDesc& tag = codeMeta.tags[tagIndex]; typeObj = TagTypeToObject(cx, tag.type->argTypes()); break; } @@ -1237,18 +1374,18 @@ bool WasmModuleObject::exports(JSContext* cx, unsigned argc, Value* vp) { return false; } + const ModuleMetadata& moduleMeta = module->moduleMeta(); + RootedValueVector elems(cx); - if (!elems.reserve(module->exports().length())) { + if (!elems.reserve(moduleMeta.exports.length())) { return false; } #ifdef ENABLE_WASM_TYPE_REFLECTIONS - const Metadata& metadata = module->metadata(); - const MetadataTier& metadataTier = - module->metadata(module->code().stableTier()); + const CodeMetadata& codeMeta = module->codeMeta(); #endif // ENABLE_WASM_TYPE_REFLECTIONS - for (const Export& exp : module->exports()) { + for (const Export& exp : moduleMeta.exports) { Rooted props(cx, IdValueVector(cx)); if (!props.reserve(2)) { return false; @@ -1272,31 +1409,32 @@ bool WasmModuleObject::exports(JSContext* cx, unsigned argc, Value* vp) { RootedObject typeObj(cx); switch (exp.kind()) { case DefinitionKind::Function: { - const FuncExport& fe = metadataTier.lookupFuncExport(exp.funcIndex()); - const FuncType& funcType = metadata.getFuncExportType(fe); + const FuncType& funcType = + module->codeMeta().getFuncType(exp.funcIndex()); typeObj = FuncTypeToObject(cx, funcType); break; } case DefinitionKind::Table: { - const TableDesc& table = metadata.tables[exp.tableIndex()]; - typeObj = TableTypeToObject(cx, table.elemType, table.initialLength, - table.maximumLength); + const TableDesc& table = codeMeta.tables[exp.tableIndex()]; + typeObj = + TableTypeToObject(cx, table.addressType(), table.elemType, + table.initialLength(), table.maximumLength()); break; } case DefinitionKind::Memory: { - const MemoryDesc& memory = metadata.memories[exp.memoryIndex()]; + const MemoryDesc& memory = codeMeta.memories[exp.memoryIndex()]; typeObj = - MemoryTypeToObject(cx, memory.isShared(), memory.indexType(), + MemoryTypeToObject(cx, memory.isShared(), memory.addressType(), memory.initialPages(), memory.maximumPages()); break; } case DefinitionKind::Global: { - const GlobalDesc& global = metadata.globals[exp.globalIndex()]; + const GlobalDesc& global = codeMeta.globals[exp.globalIndex()]; typeObj = GlobalTypeToObject(cx, global.type(), global.isMutable()); break; } case DefinitionKind::Tag: { - const TagDesc& tag = metadata.tags[exp.tagIndex()]; + const TagDesc& tag = codeMeta.tags[exp.tagIndex()]; typeObj = TagTypeToObject(cx, tag.type->argTypes()); break; } @@ -1359,7 +1497,7 @@ bool WasmModuleObject::customSections(JSContext* cx, unsigned argc, Value* vp) { RootedValueVector elems(cx); Rooted buf(cx); - for (const CustomSection& cs : module->customSections()) { + for (const CustomSection& cs : module->moduleMeta().customSections) { if (name.length() != cs.name.length()) { continue; } @@ -1416,31 +1554,27 @@ WasmModuleObject* WasmModuleObject::create(JSContext* cx, const Module& module, // Bug 1569888: We account for the first tier here; the second tier, if // different, also needs to be accounted for. - cx->zone()->incJitMemory(module.codeLength(module.code().stableTier())); + size_t codeMemory = module.tier1CodeMemoryUsed(); + if (codeMemory) { + cx->zone()->incJitMemory(codeMemory); + } return obj; } static bool GetBufferSource(JSContext* cx, JSObject* obj, unsigned errorNumber, - MutableBytes* bytecode) { - *bytecode = cx->new_(); - if (!*bytecode) { - return false; - } - + BytecodeSource* bytecode) { JSObject* unwrapped = CheckedUnwrapStatic(obj); SharedMem dataPointer; size_t byteLength; - if (!unwrapped || !IsBufferSource(unwrapped, &dataPointer, &byteLength)) { + if (!unwrapped || + !IsBufferSource(cx, unwrapped, /*allowShared*/ false, + /*allowResizable*/ false, &dataPointer, &byteLength)) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, errorNumber); return false; } - if (!(*bytecode)->append(dataPointer.unwrap(), byteLength)) { - ReportOutOfMemory(cx); - return false; - } - + *bytecode = BytecodeSource(dataPointer.unwrap(), byteLength); return true; } @@ -1475,7 +1609,16 @@ bool WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return false; + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_WASM, "WebAssembly.Module"); return false; @@ -1491,9 +1634,9 @@ bool WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - MutableBytes bytecode; + BytecodeSource source; if (!GetBufferSource(cx, &callArgs[0].toObject(), JSMSG_WASM_BAD_BUF_ARG, - &bytecode)) { + &source)) { return false; } @@ -1510,8 +1653,8 @@ bool WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp) { UniqueChars error; UniqueCharsVector warnings; - SharedModule module = - CompileBuffer(*compileArgs, *bytecode, &error, &warnings, nullptr); + SharedModule module = CompileBuffer( + *compileArgs, BytecodeBufferOrSource(source), &error, &warnings, nullptr); if (!ReportCompileWarnings(cx, warnings)) { return false; @@ -1585,7 +1728,8 @@ const ClassSpec WasmInstanceObject::classSpec_ = { WasmInstanceObject::methods, WasmInstanceObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; static bool IsInstance(HandleValue v) { return v.isObject() && v.toObject().is(); @@ -1609,11 +1753,16 @@ bool WasmInstanceObject::exportsGetter(JSContext* cx, unsigned argc, const JSPropertySpec WasmInstanceObject::properties[] = { JS_PSG("exports", WasmInstanceObject::exportsGetter, JSPROP_ENUMERATE), JS_STRING_SYM_PS(toStringTag, "WebAssembly.Instance", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; -const JSFunctionSpec WasmInstanceObject::methods[] = {JS_FS_END}; +const JSFunctionSpec WasmInstanceObject::methods[] = { + JS_FS_END, +}; -const JSFunctionSpec WasmInstanceObject::static_methods[] = {JS_FS_END}; +const JSFunctionSpec WasmInstanceObject::static_methods[] = { + JS_FS_END, +}; bool WasmInstanceObject::isNewborn() const { MOZ_ASSERT(is()); @@ -1639,7 +1788,6 @@ class WasmInstanceObject::UnspecifiedScopeMap { /* static */ void WasmInstanceObject::finalize(JS::GCContext* gcx, JSObject* obj) { WasmInstanceObject& instance = obj->as(); - gcx->delete_(obj, &instance.exports(), MemoryUse::WasmInstanceExports); gcx->delete_(obj, &instance.scopes().asWasmFunctionScopeMap(), MemoryUse::WasmInstanceScopes); gcx->delete_(obj, &instance.indirectGlobals(), @@ -1657,7 +1805,6 @@ void WasmInstanceObject::finalize(JS::GCContext* gcx, JSObject* obj) { /* static */ void WasmInstanceObject::trace(JSTracer* trc, JSObject* obj) { WasmInstanceObject& instanceObj = obj->as(); - instanceObj.exports().trace(trc); instanceObj.indirectGlobals().trace(trc); if (!instanceObj.isNewborn()) { instanceObj.instance().tracePrivate(trc); @@ -1675,13 +1822,6 @@ WasmInstanceObject* WasmInstanceObject::create( const WasmGlobalObjectVector& globalObjs, const WasmTagObjectVector& tagObjs, HandleObject proto, UniqueDebugState maybeDebug) { - Rooted> exports(cx, - js::MakeUnique(cx->zone())); - if (!exports) { - ReportOutOfMemory(cx); - return nullptr; - } - UniquePtr scopes = js::MakeUnique(cx->zone(), cx->zone()); if (!scopes) { @@ -1730,10 +1870,6 @@ WasmInstanceObject* WasmInstanceObject::create( MOZ_ASSERT(obj->isTenured(), "assumed by WasmTableObject write barriers"); - // Finalization assumes these slots are always initialized: - InitReservedSlot(obj, EXPORTS_SLOT, exports.release(), - MemoryUse::WasmInstanceExports); - InitReservedSlot(obj, SCOPES_SLOT, scopes.release(), MemoryUse::WasmInstanceScopes); @@ -1840,10 +1976,6 @@ JSObject& WasmInstanceObject::exportsObj() const { return getReservedSlot(EXPORTS_OBJ_SLOT).toObject(); } -WasmInstanceObject::ExportMap& WasmInstanceObject::exports() const { - return *(ExportMap*)getReservedSlot(EXPORTS_SLOT).toPrivate(); -} - WasmInstanceObject::UnspecifiedScopeMap& WasmInstanceObject::scopes() const { return *(UnspecifiedScopeMap*)(getReservedSlot(SCOPES_SLOT).toPrivate()); } @@ -1853,359 +1985,12 @@ WasmInstanceObject::GlobalObjectVector& WasmInstanceObject::indirectGlobals() return *(GlobalObjectVector*)getReservedSlot(GLOBALS_SLOT).toPrivate(); } -static bool WasmCall(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - RootedFunction callee(cx, &args.callee().as()); - - Instance& instance = ExportedFunctionToInstance(callee); - uint32_t funcIndex = ExportedFunctionToFuncIndex(callee); - return instance.callExport(cx, funcIndex, args); -} - -/* - * [SMDOC] Exported wasm functions and the jit-entry stubs - * - * ## The kinds of exported functions - * - * There are several kinds of exported wasm functions. /Explicitly/ exported - * functions are: - * - * - any wasm function exported via the export section - * - any asm.js export - * - the module start function - * - * There are also /implicitly/ exported functions, these are the functions whose - * indices in the module are referenced outside the code segment, eg, in element - * segments and in global initializers. - * - * ## Wasm functions as JSFunctions - * - * Any exported function can be manipulated by JS and wasm code, and to both the - * exported function is represented as a JSFunction. To JS, that means that the - * function can be called in the same way as any other JSFunction. To Wasm, it - * means that the function is a reference with the same representation as - * externref. - * - * However, the JSFunction object is created only when the function value is - * actually exposed to JS the first time. The creation is performed by - * getExportedFunction(), below, as follows: - * - * - A function exported via the export section (or from asm.js) is created - * when the export object is created, which happens at instantiation time. - * - * - A function implicitly exported via a table is created when the table - * element is read (by JS or wasm) and a function value is needed to - * represent that value. Functions stored in tables by initializers have a - * special representation that does not require the function object to be - * created, as long as the initializing element segment uses the more - * efficient index encoding instead of the more general expression encoding. - * - * - A function implicitly exported via a global initializer is created when - * the global is initialized. - * - * - A function referenced from a ref.func instruction in code is created when - * that instruction is executed the first time. - * - * The JSFunction representing a wasm function never changes: every reference to - * the wasm function that exposes the JSFunction gets the same JSFunction. In - * particular, imported functions already have a JSFunction representation (from - * JS or from their home module), and will be exposed using that representation. - * - * The mapping from a wasm function to its JSFunction is instance-specific, and - * held in a hashmap in the instance. If a module is shared across multiple - * instances, possibly in multiple threads, each instance will have its own - * JSFunction representing the wasm function. - * - * ## Stubs -- interpreter, eager, lazy, provisional, and absent - * - * While a Wasm exported function is just a JSFunction, the internal wasm ABI is - * neither the C++ ABI nor the JS JIT ABI, so there needs to be an extra step - * when C++ or JS JIT code calls wasm code. For this, execution passes through - * a stub that is adapted to both the JS caller and the wasm callee. - * - * ### Interpreter stubs and jit-entry stubs - * - * When JS interpreted code calls a wasm function, we end up in - * Instance::callExport() to execute the call. This function must enter wasm, - * and to do this it uses a stub that is specific to the wasm function (see - * GenerateInterpEntry) that is callable with the C++ interpreter ABI and which - * will convert arguments as necessary and enter compiled wasm code. - * - * The interpreter stub is created eagerly, when the module is compiled. - * - * However, the interpreter call path is slow, and when JS jitted code calls - * wasm we want to do better. In this case, there is a different, optimized - * stub that is to be invoked, and it uses the JIT ABI. This is the jit-entry - * stub for the function. Jitted code will call a wasm function's jit-entry - * stub to invoke the function with the JIT ABI. The stub will adapt the call - * to the wasm ABI. - * - * Some jit-entry stubs are created eagerly and some are created lazily. - * - * ### Eager jit-entry stubs - * - * The explicitly exported functions have stubs created for them eagerly. Eager - * stubs are created with their tier when the module is compiled, see - * ModuleGenerator::finishCodeTier(), which calls wasm::GenerateStubs(), which - * generates stubs for functions with eager stubs. - * - * An eager stub for tier-1 is upgraded to tier-2 if the module tiers up, see - * below. - * - * ### Lazy jit-entry stubs - * - * Stubs are created lazily for all implicitly exported functions. These - * functions may flow out to JS, but will only need a stub if they are ever - * called from jitted code. (That's true for explicitly exported functions too, - * but for them the presumption is that they will be called.) - * - * Lazy stubs are created only when they are needed, and they are /doubly/ lazy, - * see getExportedFunction(), below: A function implicitly exported via a table - * or global may be manipulated eagerly by host code without actually being - * called (maybe ever), so we do not generate a lazy stub when the function - * object escapes to JS, but instead delay stub generation until the function is - * actually called. - * - * ### The provisional lazy jit-entry stub - * - * However, JS baseline compilation needs to have a stub to start with in order - * to allow it to attach CacheIR data to the call (or it deoptimizes the call as - * a C++ call). Thus when the JSFunction for the wasm export is retrieved by JS - * code, a /provisional/ lazy jit-entry stub is associated with the function. - * The stub will invoke the wasm function on the slow interpreter path via - * callExport - if the function is ever called - and will cause a fast jit-entry - * stub to be created at the time of the call. The provisional lazy stub is - * shared globally, it contains no function-specific or context-specific data. - * - * Thus, the final lazy jit-entry stubs are eventually created by - * Instance::callExport, when a call is routed through it on the slow path for - * any of the reasons given above. - * - * ### Absent jit-entry stubs - * - * Some functions never get jit-entry stubs. The predicate canHaveJitEntry() - * determines if a wasm function gets a stub, and it will deny this if the - * function's signature exposes non-JS-compatible types (such as v128) or if - * stub optimization has been disabled by a jit option. Calls to these - * functions will continue to go via callExport and use the slow interpreter - * stub. - * - * ## The jit-entry jump table - * - * The mapping from the exported function to its jit-entry stub is implemented - * by the jit-entry jump table in the JumpTables object (see WasmCode.h). The - * jit-entry jump table entry for a function holds a stub that the jit can call - * to perform fast calls. - * - * While there is a single contiguous jump table, it has two logical sections: - * one for eager stubs, and one for lazy stubs. These sections are initialized - * and updated separately, using logic that is specific to each section. - * - * The value of the table element for an eager stub is a pointer to the stub - * code in the current tier. The pointer is installed just after the creation - * of the stub, before any code in the module is executed. If the module later - * tiers up, the eager jit-entry stub for tier-1 code is replaced by one for - * tier-2 code, see the next section. - * - * Initially the value of the jump table element for a lazy stub is null. - * - * If the function is retrieved by JS (by getExportedFunction()) and is not - * barred from having a jit-entry, then the stub is upgraded to the shared - * provisional lazy jit-entry stub. This upgrade happens to be racy if the - * module is shared, and so the update is atomic and only happens if the entry - * is already null. Since the provisional lazy stub is shared, this is fine; if - * several threads try to upgrade at the same time, it is to the same shared - * value. - * - * If the retrieved function is later invoked (via callExport()), the stub is - * upgraded to an actual jit-entry stub for the current code tier, again if the - * function is allowed to have a jit-entry. This is not racy -- though multiple - * threads can be trying to create a jit-entry stub at the same time, they do so - * under a lock and only the first to take the lock will be allowed to create a - * stub, the others will reuse the first-installed stub. - * - * If the module later tiers up, the lazy jit-entry stub for tier-1 code (if it - * exists) is replaced by one for tier-2 code, see the next section. - * - * (Note, the InterpEntry stub is never stored in the jit-entry table, as it - * uses the C++ ABI, not the JIT ABI. It is accessible through the - * FunctionEntry.) - * - * ### Interaction of the jit-entry jump table and tiering - * - * (For general info about tiering, see the comment in WasmCompile.cpp.) - * - * The jit-entry stub, whether eager or lazy, is specific to a code tier - a - * stub will invoke the code for its function for the tier. When we tier up, - * new jit-entry stubs must be created that reference tier-2 code, and must then - * be patched into the jit-entry table. The complication here is that, since - * the jump table is shared with its code between instances on multiple threads, - * tier-1 code is running on other threads and new tier-1 specific jit-entry - * stubs may be created concurrently with trying to create the tier-2 stubs on - * the thread that performs the tiering-up. Indeed, there may also be - * concurrent attempts to upgrade null jit-entries to the provisional lazy stub. - * - * Eager stubs: - * - * - Eager stubs for tier-2 code are patched in racily by Module::finishTier2() - * along with code pointers for tiering; nothing conflicts with these writes. - * - * Lazy stubs: - * - * - An upgrade from a null entry to a lazy provisional stub is atomic and can - * only happen if the entry is null, and it only happens in - * getExportedFunction(). No lazy provisional stub will be installed if - * there's another stub present. - * - * - The lazy tier-appropriate stub is installed by callExport() (really by - * EnsureEntryStubs()) during the first invocation of the exported function - * that reaches callExport(). That invocation must be from within JS, and so - * the jit-entry element can't be null, because a prior getExportedFunction() - * will have ensured that it is not: the lazy provisional stub will have been - * installed. Hence the installing of the lazy tier-appropriate stub does - * not race with the installing of the lazy provisional stub. - * - * - A lazy tier-1 stub is upgraded to a lazy tier-2 stub by - * Module::finishTier2(). The upgrade needs to ensure that all tier-1 stubs - * are upgraded, and that once the upgrade is finished, callExport() will - * only create tier-2 lazy stubs. (This upgrading does not upgrade lazy - * provisional stubs or absent stubs.) - * - * The locking protocol ensuring that all stubs are upgraded properly and - * that the system switches to creating tier-2 stubs is implemented in - * Module::finishTier2() and EnsureEntryStubs(): - * - * There are two locks, one per code tier. - * - * EnsureEntryStubs() is attempting to create a tier-appropriate lazy stub, - * so it takes the lock for the current best tier, checks to see if there is - * a stub, and exits if there is. If the tier changed racily it takes the - * other lock too, since that is now the lock for the best tier. Then it - * creates the stub, installs it, and releases the locks. Thus at most one - * stub per tier can be created at a time. - * - * Module::finishTier2() takes both locks (tier-1 before tier-2), thus - * preventing EnsureEntryStubs() from creating stubs while stub upgrading is - * going on, and itself waiting until EnsureEntryStubs() is not active. Once - * it has both locks, it upgrades all lazy stubs and makes tier-2 the new - * best tier. Should EnsureEntryStubs subsequently enter, it will find that - * a stub already exists at tier-2 and will exit early. - * - * (It would seem that the locking protocol could be simplified a little by - * having only one lock, hanging off the Code object, or by unconditionally - * taking both locks in EnsureEntryStubs(). However, in some cases where we - * acquire a lock the Code object is not readily available, so plumbing would - * have to be added, and in EnsureEntryStubs(), there are sometimes not two code - * tiers.) - * - * ## Stub lifetimes and serialization - * - * Eager jit-entry stub code, along with stub code for import functions, is - * serialized along with the tier-2 code for the module. - * - * Lazy stub code and thunks for builtin functions (including the provisional - * lazy jit-entry stub) are never serialized. - */ - /* static */ bool WasmInstanceObject::getExportedFunction( JSContext* cx, Handle instanceObj, uint32_t funcIndex, MutableHandleFunction fun) { - if (ExportMap::Ptr p = instanceObj->exports().lookup(funcIndex)) { - fun.set(p->value()); - return true; - } - - const Instance& instance = instanceObj->instance(); - const FuncExport& funcExport = - instance.metadata(instance.code().bestTier()).lookupFuncExport(funcIndex); - const TypeDef& funcTypeDef = - instance.metadata().getFuncExportTypeDef(funcExport); - unsigned numArgs = funcTypeDef.funcType().args().length(); - - if (instance.isAsmJS()) { - // asm.js needs to act like a normal JS function which means having the - // name from the original source and being callable as a constructor. - Rooted name(cx, instance.getFuncDisplayAtom(cx, funcIndex)); - if (!name) { - return false; - } - fun.set(NewNativeConstructor(cx, WasmCall, numArgs, name, - gc::AllocKind::FUNCTION_EXTENDED, - TenuredObject, FunctionFlags::ASMJS_CTOR)); - if (!fun) { - return false; - } - - // asm.js does not support jit entries. - fun->setWasmFuncIndex(funcIndex); - } else { - Rooted name(cx, NumberToAtom(cx, funcIndex)); - if (!name) { - return false; - } - RootedObject proto(cx); -#ifdef ENABLE_WASM_TYPE_REFLECTIONS - proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmFunction); - if (!proto) { - return false; - } -#endif - fun.set(NewFunctionWithProto( - cx, WasmCall, numArgs, FunctionFlags::WASM, nullptr, name, proto, - gc::AllocKind::FUNCTION_EXTENDED, TenuredObject)); - if (!fun) { - return false; - } - - // Some applications eagerly access all table elements which currently - // triggers worst-case behavior for lazy stubs, since each will allocate a - // separate 4kb code page. Most eagerly-accessed functions are not called, - // so use a shared, provisional (and slow) lazy stub as JitEntry and wait - // until Instance::callExport() to create the fast entry stubs. - if (funcTypeDef.funcType().canHaveJitEntry()) { - if (!funcExport.hasEagerStubs()) { - if (!EnsureBuiltinThunksInitialized()) { - return false; - } - void* provisionalLazyJitEntryStub = ProvisionalLazyJitEntryStub(); - MOZ_ASSERT(provisionalLazyJitEntryStub); - instance.code().setJitEntryIfNull(funcIndex, - provisionalLazyJitEntryStub); - } - fun->setWasmJitEntry(instance.code().getAddressOfJitEntry(funcIndex)); - } else { - fun->setWasmFuncIndex(funcIndex); - } - } - - fun->setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT, - PrivateValue(const_cast(&instance))); - fun->setExtendedSlot(FunctionExtended::WASM_STV_SLOT, - PrivateValue((void*)funcTypeDef.superTypeVector())); - - const CodeTier& codeTier = - instance.code().codeTier(instance.code().bestTier()); - const CodeRange& codeRange = codeTier.metadata().codeRange(funcExport); - - fun->setExtendedSlot(FunctionExtended::WASM_FUNC_UNCHECKED_ENTRY_SLOT, - PrivateValue(codeTier.segment().base() + - codeRange.funcUncheckedCallEntry())); - - if (!instanceObj->exports().putNew(funcIndex, fun)) { - ReportOutOfMemory(cx); - return false; - } - - return true; -} - -const CodeRange& WasmInstanceObject::getExportedFunctionCodeRange( - JSFunction* fun, Tier tier) { - uint32_t funcIndex = ExportedFunctionToFuncIndex(fun); - MOZ_ASSERT(exports().lookup(funcIndex)->value() == fun); - const MetadataTier& metadata = instance().metadata(tier); - return metadata.codeRange(metadata.lookupFuncExport(funcIndex)); + Instance& instance = instanceObj->instance(); + return instance.getExportedFunction(cx, funcIndex, fun); } /* static */ @@ -2258,22 +2043,6 @@ WasmFunctionScope* WasmInstanceObject::getFunctionScope( return funcScope; } -bool wasm::IsWasmExportedFunction(JSFunction* fun) { - return fun->kind() == FunctionFlags::Wasm; -} - -Instance& wasm::ExportedFunctionToInstance(JSFunction* fun) { - return fun->wasmInstance(); -} - -WasmInstanceObject* wasm::ExportedFunctionToInstanceObject(JSFunction* fun) { - return fun->wasmInstance().object(); -} - -uint32_t wasm::ExportedFunctionToFuncIndex(JSFunction* fun) { - return fun->wasmInstance().code().getFuncIndex(fun); -} - // ============================================================================ // WebAssembly.Memory class and methods @@ -2295,7 +2064,9 @@ const JSClass WasmMemoryObject::class_ = { JSCLASS_DELAY_METADATA_BUILDER | JSCLASS_HAS_RESERVED_SLOTS(WasmMemoryObject::RESERVED_SLOTS) | JSCLASS_FOREGROUND_FINALIZE, - &WasmMemoryObject::classOps_, &WasmMemoryObject::classSpec_}; + &WasmMemoryObject::classOps_, + &WasmMemoryObject::classSpec_, +}; const JSClass& WasmMemoryObject::protoClass_ = PlainObject::class_; @@ -2324,7 +2095,8 @@ const ClassSpec WasmMemoryObject::classSpec_ = { WasmMemoryObject::methods, WasmMemoryObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /* static */ void WasmMemoryObject::finalize(JS::GCContext* gcx, JSObject* obj) { @@ -2372,12 +2144,12 @@ bool WasmMemoryObject::construct(JSContext* cx, unsigned argc, Value* vp) { RootedObject obj(cx, &args[0].toObject()); Limits limits; if (!GetLimits(cx, obj, LimitsKind::Memory, &limits) || - !CheckLimits(cx, MaxMemoryLimitField(limits.indexType), + !CheckLimits(cx, MaxMemoryPagesValidation(limits.addressType), LimitsKind::Memory, &limits)) { return false; } - if (Pages(limits.initial) > MaxMemoryPages(limits.indexType)) { + if (Pages(limits.initial) > MaxMemoryPages(limits.addressType)) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_MEM_IMP_LIMIT); return false; @@ -2399,7 +2171,7 @@ bool WasmMemoryObject::construct(JSContext* cx, unsigned argc, Value* vp) { Rooted memoryObj( cx, WasmMemoryObject::create( - cx, buffer, IsHugeMemoryEnabled(limits.indexType), proto)); + cx, buffer, IsHugeMemoryEnabled(limits.addressType), proto)); if (!memoryObj) { return false; } @@ -2413,35 +2185,57 @@ static bool IsMemory(HandleValue v) { } /* static */ -bool WasmMemoryObject::bufferGetterImpl(JSContext* cx, const CallArgs& args) { - Rooted memoryObj( - cx, &args.thisv().toObject().as()); - Rooted buffer(cx, &memoryObj->buffer()); - +ArrayBufferObjectMaybeShared* WasmMemoryObject::refreshBuffer( + JSContext* cx, Handle memoryObj, + Handle buffer) { if (memoryObj->isShared()) { size_t memoryLength = memoryObj->volatileMemoryLength(); - MOZ_ASSERT(memoryLength >= buffer->byteLength()); + MOZ_ASSERT_IF(!buffer->is(), + memoryLength >= buffer->byteLength()); - if (memoryLength > buffer->byteLength()) { + // The `length` field on a fixed length SAB cannot change even if + // the underlying memory has grown. The spec therefore requires that + // accessing the buffer property will create a new fixed length SAB + // with the current length if the underlying raw buffer's length has + // changed. We don't need to do this for growable SAB. + if (!buffer->is() && + memoryLength > buffer->byteLength()) { Rooted newBuffer( cx, SharedArrayBufferObject::New( cx, memoryObj->sharedArrayRawBuffer(), memoryLength)); + MOZ_ASSERT(newBuffer->is()); if (!newBuffer) { - return false; + return nullptr; } // OK to addReference after we try to allocate because the memoryObj // keeps the rawBuffer alive. if (!memoryObj->sharedArrayRawBuffer()->addReference()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SAB_REFCNT_OFLO); - return false; + return nullptr; } - buffer = newBuffer; memoryObj->setReservedSlot(BUFFER_SLOT, ObjectValue(*newBuffer)); + return newBuffer; } } + return buffer; +} - args.rval().setObject(*buffer); +/* static */ +bool WasmMemoryObject::bufferGetterImpl(JSContext* cx, const CallArgs& args) { + Rooted memoryObj( + cx, &args.thisv().toObject().as()); + + Rooted buffer(cx, &memoryObj->buffer()); + MOZ_RELEASE_ASSERT(buffer->isWasm() && !buffer->isPreparedForAsmJS()); + + ArrayBufferObjectMaybeShared* refreshedBuffer = + WasmMemoryObject::refreshBuffer(cx, memoryObj, buffer); + if (!refreshedBuffer) { + return false; + } + + args.rval().setObject(*refreshedBuffer); return true; } @@ -2454,7 +2248,8 @@ bool WasmMemoryObject::bufferGetter(JSContext* cx, unsigned argc, Value* vp) { const JSPropertySpec WasmMemoryObject::properties[] = { JS_PSG("buffer", WasmMemoryObject::bufferGetter, JSPROP_ENUMERATE), JS_STRING_SYM_PS(toStringTag, "WebAssembly.Memory", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; /* static */ bool WasmMemoryObject::growImpl(JSContext* cx, const CallArgs& args) { @@ -2465,8 +2260,9 @@ bool WasmMemoryObject::growImpl(JSContext* cx, const CallArgs& args) { return false; } - uint32_t delta; - if (!EnforceRangeU32(cx, args.get(0), "Memory", "grow delta", &delta)) { + uint64_t delta; + if (!EnforceAddressValue(cx, args.get(0), memory->addressType(), "Memory", + "grow delta", &delta)) { return false; } @@ -2478,7 +2274,12 @@ bool WasmMemoryObject::growImpl(JSContext* cx, const CallArgs& args) { return false; } - args.rval().setInt32(int32_t(ret)); + RootedValue result(cx); + if (!CreateAddressValue(cx, ret, memory->addressType(), &result)) { + ReportOutOfMemory(cx); + return false; + } + args.rval().set(result); return true; } @@ -2532,17 +2333,121 @@ bool WasmMemoryObject::discard(JSContext* cx, unsigned argc, Value* vp) { return CallNonGenericMethod(cx, args); } +#ifdef ENABLE_WASM_RESIZABLE_ARRAYBUFFER +/* static */ +bool WasmMemoryObject::toFixedLengthBufferImpl(JSContext* cx, + const CallArgs& args) { + Rooted memory( + cx, &args.thisv().toObject().as()); + + Rooted buffer(cx, &memory->buffer()); + MOZ_RELEASE_ASSERT(buffer->isWasm() && !buffer->isPreparedForAsmJS()); + // If IsFixedLengthArrayBuffer(buffer) is true, return buffer. + if (!buffer->isResizable()) { + ArrayBufferObjectMaybeShared* refreshedBuffer = + refreshBuffer(cx, memory, buffer); + args.rval().set(ObjectValue(*refreshedBuffer)); + return true; + } + + Rooted fixedBuffer(cx); + if (memory->isShared()) { + Rooted oldBuffer( + cx, &buffer->as()); + fixedBuffer.set(SharedArrayBufferObject::createFromWasmObject< + FixedLengthSharedArrayBufferObject>(cx, oldBuffer)); + } else { + Rooted oldBuffer(cx, &buffer->as()); + fixedBuffer.set( + ArrayBufferObject::createFromWasmObject( + cx, oldBuffer)); + } + + if (!fixedBuffer) { + return false; + } + memory->setReservedSlot(BUFFER_SLOT, ObjectValue(*fixedBuffer)); + args.rval().set(ObjectValue(*fixedBuffer)); + return true; +} + +/* static */ +bool WasmMemoryObject::toFixedLengthBuffer(JSContext* cx, unsigned argc, + Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + +/* static */ +bool WasmMemoryObject::toResizableBufferImpl(JSContext* cx, + const CallArgs& args) { + Rooted memory( + cx, &args.thisv().toObject().as()); + + Rooted buffer(cx, &memory->buffer()); + // If IsFixedLengthArrayBuffer(buffer) is false, return buffer. + if (buffer->isResizable()) { + args.rval().set(ObjectValue(*buffer)); + return true; + } + + if (buffer->wasmSourceMaxPages().isNothing()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_WASM_MEMORY_NOT_RESIZABLE); + return false; + } + + Rooted resizableBuffer(cx); + if (memory->isShared()) { + Rooted oldBuffer( + cx, &buffer->as()); + resizableBuffer.set(SharedArrayBufferObject::createFromWasmObject< + GrowableSharedArrayBufferObject>(cx, oldBuffer)); + } else { + Rooted oldBuffer(cx, &buffer->as()); + resizableBuffer.set( + ArrayBufferObject::createFromWasmObject( + cx, oldBuffer)); + } + + if (!resizableBuffer) { + return false; + } + memory->setReservedSlot(BUFFER_SLOT, ObjectValue(*resizableBuffer)); + args.rval().set(ObjectValue(*resizableBuffer)); + return true; +} + +/* static */ +bool WasmMemoryObject::toResizableBuffer(JSContext* cx, unsigned argc, + Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} +#endif // ENABLE_WASM_RESIZABLE_ARRAYBUFFER + const JSFunctionSpec WasmMemoryObject::methods[] = { #ifdef ENABLE_WASM_TYPE_REFLECTIONS JS_FN("type", WasmMemoryObject::type, 0, JSPROP_ENUMERATE), #endif - JS_FN("grow", WasmMemoryObject::grow, 1, JSPROP_ENUMERATE), JS_FS_END}; + JS_FN("grow", WasmMemoryObject::grow, 1, JSPROP_ENUMERATE), +#ifdef ENABLE_WASM_RESIZABLE_ARRAYBUFFER + JS_FN("toFixedLengthBuffer", WasmMemoryObject::toFixedLengthBuffer, 0, + JSPROP_ENUMERATE), + JS_FN("toResizableBuffer", WasmMemoryObject::toResizableBuffer, 0, + JSPROP_ENUMERATE), +#endif + JS_FS_END, +}; const JSFunctionSpec WasmMemoryObject::memoryControlMethods[] = { JS_FN("discard", WasmMemoryObject::discard, 2, JSPROP_ENUMERATE), - JS_FS_END}; + JS_FS_END, +}; -const JSFunctionSpec WasmMemoryObject::static_methods[] = {JS_FS_END}; +const JSFunctionSpec WasmMemoryObject::static_methods[] = { + JS_FS_END, +}; ArrayBufferObjectMaybeShared& WasmMemoryObject::buffer() const { return getReservedSlot(BUFFER_SLOT) @@ -2559,10 +2464,10 @@ WasmSharedArrayRawBuffer* WasmMemoryObject::sharedArrayRawBuffer() const { bool WasmMemoryObject::typeImpl(JSContext* cx, const CallArgs& args) { Rooted memoryObj( cx, &args.thisv().toObject().as()); - RootedObject typeObj( - cx, MemoryTypeToObject(cx, memoryObj->isShared(), memoryObj->indexType(), - memoryObj->volatilePages(), - memoryObj->sourceMaxPages())); + RootedObject typeObj(cx, MemoryTypeToObject(cx, memoryObj->isShared(), + memoryObj->addressType(), + memoryObj->volatilePages(), + memoryObj->sourceMaxPages())); if (!typeObj) { return false; } @@ -2604,11 +2509,11 @@ Maybe WasmMemoryObject::sourceMaxPages() const { return buffer().wasmSourceMaxPages(); } -wasm::IndexType WasmMemoryObject::indexType() const { +wasm::AddressType WasmMemoryObject::addressType() const { if (isShared()) { - return sharedArrayRawBuffer()->wasmIndexType(); + return sharedArrayRawBuffer()->wasmAddressType(); } - return buffer().wasmIndexType(); + return buffer().wasmAddressType(); } bool WasmMemoryObject::isShared() const { @@ -2665,7 +2570,7 @@ size_t WasmMemoryObject::boundsCheckLimit() const { MOZ_ASSERT(mappedSize >= wasm::GuardSize); MOZ_ASSERT(wasm::IsValidBoundsCheckImmediate(mappedSize - wasm::GuardSize)); size_t limit = mappedSize - wasm::GuardSize; - MOZ_ASSERT(limit <= MaxMemoryBoundsCheckLimit(indexType())); + MOZ_ASSERT(limit <= MaxMemoryBoundsCheckLimit(addressType())); return limit; } @@ -2700,7 +2605,7 @@ uint64_t WasmMemoryObject::growShared(Handle memory, return uint64_t(int64_t(-1)); } - if (!rawBuf->wasmGrowToPagesInPlace(lock, memory->indexType(), newPages)) { + if (!rawBuf->wasmGrowToPagesInPlace(lock, memory->addressType(), newPages)) { return uint64_t(int64_t(-1)); } // New buffer objects will be created lazily in all agents (including in @@ -2722,7 +2627,7 @@ uint64_t WasmMemoryObject::grow(Handle memory, #if !defined(JS_64BIT) // TODO (large ArrayBuffer): See more information at the definition of // MaxMemoryBytes(). - MOZ_ASSERT(MaxMemoryBytes(memory->indexType()) <= UINT32_MAX, + MOZ_ASSERT(MaxMemoryBytes(memory->addressType()) <= UINT32_MAX, "Avoid 32-bit overflows"); #endif @@ -2735,10 +2640,10 @@ uint64_t WasmMemoryObject::grow(Handle memory, ArrayBufferObject* newBuf; if (memory->movingGrowable()) { MOZ_ASSERT(!memory->isHuge()); - newBuf = ArrayBufferObject::wasmMovingGrowToPages(memory->indexType(), + newBuf = ArrayBufferObject::wasmMovingGrowToPages(memory->addressType(), newPages, oldBuf, cx); } else { - newBuf = ArrayBufferObject::wasmGrowToPagesInPlace(memory->indexType(), + newBuf = ArrayBufferObject::wasmGrowToPagesInPlace(memory->addressType(), newPages, oldBuf, cx); } if (!newBuf) { @@ -2800,7 +2705,9 @@ const JSClass WasmTableObject::class_ = { JSCLASS_DELAY_METADATA_BUILDER | JSCLASS_HAS_RESERVED_SLOTS(WasmTableObject::RESERVED_SLOTS) | JSCLASS_FOREGROUND_FINALIZE, - &WasmTableObject::classOps_, &WasmTableObject::classSpec_}; + &WasmTableObject::classOps_, + &WasmTableObject::classSpec_, +}; const JSClass& WasmTableObject::protoClass_ = PlainObject::class_; @@ -2814,7 +2721,8 @@ const ClassSpec WasmTableObject::classSpec_ = { WasmTableObject::methods, WasmTableObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; bool WasmTableObject::isNewborn() const { MOZ_ASSERT(is()); @@ -2842,22 +2750,13 @@ void WasmTableObject::trace(JSTracer* trc, JSObject* obj) { // value is omitted. An implementation of [1]. // // [1] -// https://webassembly.github.io/reference-types/js-api/index.html#defaultvalue -static Value RefTypeDefautValue(wasm::RefType tableType) { +// https://webassembly.github.io/spec/js-api/#defaultvalue +static Value RefTypeDefaultValue(wasm::RefType tableType) { return tableType.isExtern() ? UndefinedValue() : NullValue(); } -static bool CheckRefTypeValue(JSContext* cx, wasm::RefType type, - HandleValue value) { - RootedFunction fun(cx); - RootedAnyRef any(cx, AnyRef::null()); - - return CheckRefType(cx, type, value, &fun, &any); -} - /* static */ -WasmTableObject* WasmTableObject::create(JSContext* cx, uint32_t initialLength, - Maybe maximumLength, +WasmTableObject* WasmTableObject::create(JSContext* cx, Limits limits, wasm::RefType tableType, HandleObject proto) { AutoSetNewObjectMetadata metadata(cx); @@ -2869,7 +2768,7 @@ WasmTableObject* WasmTableObject::create(JSContext* cx, uint32_t initialLength, MOZ_ASSERT(obj->isNewborn()); - TableDesc td(tableType, initialLength, maximumLength, Nothing(), + TableDesc td(limits, tableType, Nothing(), /*isAsmJS*/ false, /*isImported=*/true, /*isExported=*/true); @@ -2924,14 +2823,12 @@ bool WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp) { Limits limits; if (!GetLimits(cx, obj, LimitsKind::Table, &limits) || - !CheckLimits(cx, MaxTableLimitField, LimitsKind::Table, &limits)) { + !CheckLimits(cx, MaxTableElemsValidation(limits.addressType), + LimitsKind::Table, &limits)) { return false; } - // Converting limits for a table only supports i32 - MOZ_ASSERT(limits.indexType == IndexType::I32); - - if (limits.initial > MaxTableLength) { + if (limits.initial > MaxTableElemsRuntime) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_TABLE_IMP_LIMIT); return false; @@ -2944,41 +2841,32 @@ bool WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - // The rest of the runtime expects table limits to be within a 32-bit range. - static_assert(MaxTableLimitField <= UINT32_MAX, "invariant"); - uint32_t initialLength = uint32_t(limits.initial); - Maybe maximumLength; - if (limits.maximum) { - maximumLength = Some(uint32_t(*limits.maximum)); - } - Rooted table( - cx, WasmTableObject::create(cx, initialLength, maximumLength, tableType, - proto)); + cx, WasmTableObject::create(cx, limits, tableType, proto)); if (!table) { return false; } // Initialize the table to a default value RootedValue initValue( - cx, args.length() < 2 ? RefTypeDefautValue(tableType) : args[1]); - if (!CheckRefTypeValue(cx, tableType, initValue)) { + cx, args.length() < 2 ? RefTypeDefaultValue(tableType) : args[1]); + if (!CheckRefType(cx, tableType, initValue)) { return false; } // Skip initializing the table if the fill value is null, as that is the // default value. if (!initValue.isNull() && - !table->fillRange(cx, 0, initialLength, initValue)) { + !table->fillRange(cx, 0, limits.initial, initValue)) { return false; } #ifdef DEBUG // Assert that null is the default value of a new table. if (initValue.isNull()) { - table->table().assertRangeNull(0, initialLength); + table->table().assertRangeNull(0, limits.initial); } if (!tableType.isNullable()) { - table->table().assertRangeNotNull(0, initialLength); + table->table().assertRangeNotNull(0, limits.initial); } #endif @@ -2992,8 +2880,15 @@ static bool IsTable(HandleValue v) { /* static */ bool WasmTableObject::lengthGetterImpl(JSContext* cx, const CallArgs& args) { - args.rval().setNumber( - args.thisv().toObject().as().table().length()); + const WasmTableObject& tableObj = + args.thisv().toObject().as(); + RootedValue length(cx); + if (!CreateAddressValue(cx, tableObj.table().length(), + tableObj.table().addressType(), &length)) { + ReportOutOfMemory(cx); + return false; + } + args.rval().set(length); return true; } @@ -3006,15 +2901,31 @@ bool WasmTableObject::lengthGetter(JSContext* cx, unsigned argc, Value* vp) { const JSPropertySpec WasmTableObject::properties[] = { JS_PSG("length", WasmTableObject::lengthGetter, JSPROP_ENUMERATE), JS_STRING_SYM_PS(toStringTag, "WebAssembly.Table", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; -static bool ToTableIndex(JSContext* cx, HandleValue v, const Table& table, - const char* noun, uint32_t* index) { - if (!EnforceRangeU32(cx, v, "Table", noun, index)) { +// Gets an AddressValue parameter for a table. This differs from our general +// EnforceAddressValue because our table implementation still uses 32-bit sizes +// internally, and this function therefore returns a uint32_t. Values outside +// the 32-bit range will be clamped to UINT32_MAX, which will always trigger +// bounds checks for all Table uses of AddressValue. See +// MacroAssembler::wasmClampTable64Address and its uses. +// +// isAddress should be true if the value is an actual address, and false if it +// is a different quantity (e.g. a grow delta). +static bool EnforceTableAddressValue(JSContext* cx, HandleValue v, + const Table& table, const char* noun, + uint32_t* result, bool isAddress) { + uint64_t result64; + if (!EnforceAddressValue(cx, v, table.addressType(), "Table", noun, + &result64)) { return false; } - if (*index >= table.length()) { + static_assert(MaxTableElemsRuntime < UINT32_MAX); + *result = result64 > UINT32_MAX ? UINT32_MAX : uint32_t(result64); + + if (isAddress && *result >= table.length()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_RANGE, "Table", noun); return false; @@ -3027,8 +2938,9 @@ static bool ToTableIndex(JSContext* cx, HandleValue v, const Table& table, /* static */ bool WasmTableObject::typeImpl(JSContext* cx, const CallArgs& args) { Table& table = args.thisv().toObject().as().table(); - RootedObject typeObj(cx, TableTypeToObject(cx, table.elemType(), - table.length(), table.maximum())); + RootedObject typeObj( + cx, TableTypeToObject(cx, table.addressType(), table.elemType(), + table.length(), table.maximum())); if (!typeObj) { return false; } @@ -3053,12 +2965,13 @@ bool WasmTableObject::getImpl(JSContext* cx, const CallArgs& args) { return false; } - uint32_t index; - if (!ToTableIndex(cx, args.get(0), table, "get index", &index)) { + uint32_t address; + if (!EnforceTableAddressValue(cx, args.get(0), table, "get address", &address, + /*isAddress=*/true)) { return false; } - return table.getValue(cx, index, args.rval()); + return table.getValue(cx, address, args.rval()); } /* static */ @@ -3077,14 +2990,15 @@ bool WasmTableObject::setImpl(JSContext* cx, const CallArgs& args) { return false; } - uint32_t index; - if (!ToTableIndex(cx, args.get(0), table, "set index", &index)) { + uint32_t address; + if (!EnforceTableAddressValue(cx, args.get(0), table, "set address", &address, + /*isAddress=*/true)) { return false; } RootedValue fillValue( - cx, args.length() < 2 ? RefTypeDefautValue(table.elemType()) : args[1]); - if (!tableObj->fillRange(cx, index, 1, fillValue)) { + cx, args.length() < 2 ? RefTypeDefaultValue(table.elemType()) : args[1]); + if (!tableObj->fillRange(cx, address, 1, fillValue)) { return false; } @@ -3109,13 +3023,14 @@ bool WasmTableObject::growImpl(JSContext* cx, const CallArgs& args) { } uint32_t delta; - if (!EnforceRangeU32(cx, args.get(0), "Table", "grow delta", &delta)) { + if (!EnforceTableAddressValue(cx, args.get(0), table, "grow delta", &delta, + /*isAddress=*/false)) { return false; } RootedValue fillValue( - cx, args.length() < 2 ? RefTypeDefautValue(table.elemType()) : args[1]); - if (!CheckRefTypeValue(cx, table.elemType(), fillValue)) { + cx, args.length() < 2 ? RefTypeDefaultValue(table.elemType()) : args[1]); + if (!CheckRefType(cx, table.elemType(), fillValue)) { return false; } @@ -3143,7 +3058,12 @@ bool WasmTableObject::growImpl(JSContext* cx, const CallArgs& args) { } #endif - args.rval().setInt32(int32_t(oldLength)); + RootedValue result(cx); + if (!CreateAddressValue(cx, oldLength, table.addressType(), &result)) { + ReportOutOfMemory(cx); + return false; + } + args.rval().set(result); return true; } @@ -3159,9 +3079,13 @@ const JSFunctionSpec WasmTableObject::methods[] = { #endif JS_FN("get", WasmTableObject::get, 1, JSPROP_ENUMERATE), JS_FN("set", WasmTableObject::set, 2, JSPROP_ENUMERATE), - JS_FN("grow", WasmTableObject::grow, 1, JSPROP_ENUMERATE), JS_FS_END}; + JS_FN("grow", WasmTableObject::grow, 1, JSPROP_ENUMERATE), + JS_FS_END, +}; -const JSFunctionSpec WasmTableObject::static_methods[] = {JS_FS_END}; +const JSFunctionSpec WasmTableObject::static_methods[] = { + JS_FS_END, +}; Table& WasmTableObject::table() const { return *(Table*)getReservedSlot(TABLE_SLOT).toPrivate(); @@ -3175,15 +3099,15 @@ bool WasmTableObject::fillRange(JSContext* cx, uint32_t index, uint32_t length, // bounds MOZ_ASSERT(uint64_t(index) + uint64_t(length) <= tab.length()); - RootedFunction fun(cx); RootedAnyRef any(cx, AnyRef::null()); - if (!CheckRefType(cx, tab.elemType(), value, &fun, &any)) { + if (!wasm::CheckRefType(cx, tab.elemType(), value, &any)) { return false; } switch (tab.repr()) { case TableRepr::Func: MOZ_RELEASE_ASSERT(!tab.isAsmJS()); - tab.fillFuncRef(index, length, FuncRef::fromJSFunction(fun), cx); + tab.fillFuncRef(index, length, FuncRef::fromAnyRefUnchecked(any.get()), + cx); break; case TableRepr::Ref: tab.fillAnyRef(index, length, any); @@ -3212,7 +3136,9 @@ const JSClass WasmGlobalObject::class_ = { "WebAssembly.Global", JSCLASS_HAS_RESERVED_SLOTS(WasmGlobalObject::RESERVED_SLOTS) | JSCLASS_BACKGROUND_FINALIZE, - &WasmGlobalObject::classOps_, &WasmGlobalObject::classSpec_}; + &WasmGlobalObject::classOps_, + &WasmGlobalObject::classSpec_, +}; const JSClass& WasmGlobalObject::protoClass_ = PlainObject::class_; @@ -3226,7 +3152,8 @@ const ClassSpec WasmGlobalObject::classSpec_ = { WasmGlobalObject::methods, WasmGlobalObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /* static */ void WasmGlobalObject::trace(JSTracer* trc, JSObject* obj) { @@ -3336,7 +3263,7 @@ bool WasmGlobalObject::construct(JSContext* cx, unsigned argc, Value* vp) { // Override with non-undefined value, if provided. RootedValue valueVal(cx); if (globalType.isRefType()) { - valueVal.set(args.length() < 2 ? RefTypeDefautValue(globalType.refType()) + valueVal.set(args.length() < 2 ? RefTypeDefaultValue(globalType.refType()) : args[1]); if (!Val::fromJSValue(cx, globalType, valueVal, &globalVal)) { return false; @@ -3422,16 +3349,20 @@ const JSPropertySpec WasmGlobalObject::properties[] = { JS_PSGS("value", WasmGlobalObject::valueGetter, WasmGlobalObject::valueSetter, JSPROP_ENUMERATE), JS_STRING_SYM_PS(toStringTag, "WebAssembly.Global", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; const JSFunctionSpec WasmGlobalObject::methods[] = { #ifdef ENABLE_WASM_TYPE_REFLECTIONS JS_FN("type", WasmGlobalObject::type, 0, JSPROP_ENUMERATE), #endif JS_FN("valueOf", WasmGlobalObject::valueGetter, 0, JSPROP_ENUMERATE), - JS_FS_END}; + JS_FS_END, +}; -const JSFunctionSpec WasmGlobalObject::static_methods[] = {JS_FS_END}; +const JSFunctionSpec WasmGlobalObject::static_methods[] = { + JS_FS_END, +}; bool WasmGlobalObject::isMutable() const { return getReservedSlot(MUTABLE_SLOT).toBoolean(); @@ -3497,7 +3428,9 @@ const JSClass WasmTagObject::class_ = { "WebAssembly.Tag", JSCLASS_HAS_RESERVED_SLOTS(WasmTagObject::RESERVED_SLOTS) | JSCLASS_FOREGROUND_FINALIZE, - &WasmTagObject::classOps_, &WasmTagObject::classSpec_}; + &WasmTagObject::classOps_, + &WasmTagObject::classSpec_, +}; const JSClass& WasmTagObject::protoClass_ = PlainObject::class_; @@ -3511,7 +3444,8 @@ const ClassSpec WasmTagObject::classSpec_ = { WasmTagObject::methods, WasmTagObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /* static */ void WasmTagObject::finalize(JS::GCContext* gcx, JSObject* obj) { @@ -3550,8 +3484,22 @@ bool WasmTagObject::construct(JSContext* cx, unsigned argc, Value* vp) { if (!ParseValTypes(cx, paramsVal, params)) { return false; } + + RefPtr types = js_new(); + if (!types) { + ReportOutOfMemory(cx); + return false; + } + const TypeDef* tagTypeDef = + types->addType(FuncType(std::move(params), ValTypeVector())); + if (!tagTypeDef) { + ReportOutOfMemory(cx); + return false; + } + wasm::MutableTagType tagType = js_new(); - if (!tagType || !tagType->initialize(std::move(params))) { + if (!tagType || !tagType->initialize(tagTypeDef)) { + ReportOutOfMemory(cx); return false; } @@ -3589,7 +3537,8 @@ WasmTagObject* WasmTagObject::create(JSContext* cx, const JSPropertySpec WasmTagObject::properties[] = { JS_STRING_SYM_PS(toStringTag, "WebAssembly.Tag", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; #ifdef ENABLE_WASM_TYPE_REFLECTIONS /* static */ @@ -3614,9 +3563,12 @@ const JSFunctionSpec WasmTagObject::methods[] = { #ifdef ENABLE_WASM_TYPE_REFLECTIONS JS_FN("type", WasmTagObject::type, 0, JSPROP_ENUMERATE), #endif - JS_FS_END}; + JS_FS_END, +}; -const JSFunctionSpec WasmTagObject::static_methods[] = {JS_FS_END}; +const JSFunctionSpec WasmTagObject::static_methods[] = { + JS_FS_END, +}; const TagType* WasmTagObject::tagType() const { return (const TagType*)getFixedSlot(TYPE_SLOT).toPrivate(); @@ -3626,10 +3578,6 @@ const wasm::ValTypeVector& WasmTagObject::valueTypes() const { return tagType()->argTypes(); }; -wasm::ResultType WasmTagObject::resultType() const { - return wasm::ResultType::Vector(valueTypes()); -} - // ============================================================================ // WebAssembly.Exception class and methods @@ -3650,7 +3598,9 @@ const JSClass WasmExceptionObject::class_ = { "WebAssembly.Exception", JSCLASS_HAS_RESERVED_SLOTS(WasmExceptionObject::RESERVED_SLOTS) | JSCLASS_FOREGROUND_FINALIZE, - &WasmExceptionObject::classOps_, &WasmExceptionObject::classSpec_}; + &WasmExceptionObject::classOps_, + &WasmExceptionObject::classSpec_, +}; const JSClass& WasmExceptionObject::protoClass_ = PlainObject::class_; @@ -3664,7 +3614,8 @@ const ClassSpec WasmExceptionObject::classSpec_ = { WasmExceptionObject::methods, WasmExceptionObject::properties, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; /* static */ void WasmExceptionObject::finalize(JS::GCContext* gcx, JSObject* obj) { @@ -3893,7 +3844,8 @@ Value WasmExceptionObject::wrappedJSValue() const { const JSPropertySpec WasmExceptionObject::properties[] = { JS_PSG("stack", WasmExceptionObject::getStack, 0), JS_STRING_SYM_PS(toStringTag, "WebAssembly.Exception", JSPROP_READONLY), - JS_PS_END}; + JS_PS_END, +}; /* static */ bool WasmExceptionObject::isImpl(JSContext* cx, const CallArgs& args) { @@ -4048,9 +4000,12 @@ wasm::AnyRef WasmExceptionObject::loadRefArg(size_t offset) const { const JSFunctionSpec WasmExceptionObject::methods[] = { JS_FN("is", WasmExceptionObject::isMethod, 1, JSPROP_ENUMERATE), JS_FN("getArg", WasmExceptionObject::getArg, 2, JSPROP_ENUMERATE), - JS_FS_END}; + JS_FS_END, +}; -const JSFunctionSpec WasmExceptionObject::static_methods[] = {JS_FS_END}; +const JSFunctionSpec WasmExceptionObject::static_methods[] = { + JS_FS_END, +}; const TagType* WasmExceptionObject::tagType() const { return (const TagType*)getReservedSlot(TYPE_SLOT).toPrivate(); @@ -4062,14 +4017,7 @@ WasmTagObject& WasmExceptionObject::tag() const { // ============================================================================ // WebAssembly.Function and methods -#ifdef ENABLE_WASM_TYPE_REFLECTIONS -static JSObject* CreateWasmFunctionPrototype(JSContext* cx, JSProtoKey key) { - // WasmFunction's prototype should inherit from JSFunction's prototype. - RootedObject jsProto(cx, &cx->global()->getFunctionPrototype()); - return GlobalObject::createBlankPrototypeInheriting(cx, &PlainObject::class_, - jsProto); -} - +#if defined(ENABLE_WASM_TYPE_REFLECTIONS) || defined(ENABLE_WASM_JSPI) [[nodiscard]] static bool IsWasmFunction(HandleValue v) { if (!v.isObject()) { return false; @@ -4079,16 +4027,19 @@ static JSObject* CreateWasmFunctionPrototype(JSContext* cx, JSProtoKey key) { } return v.toObject().as().isWasm(); } +#endif // ENABLE_WASM_TYPE_REFLECTIONS || ENABLE_WASM_JSPI + +#ifdef ENABLE_WASM_TYPE_REFLECTIONS +static JSObject* CreateWasmFunctionPrototype(JSContext* cx, JSProtoKey key) { + // WasmFunction's prototype should inherit from JSFunction's prototype. + RootedObject jsProto(cx, &cx->global()->getFunctionPrototype()); + return GlobalObject::createBlankPrototypeInheriting(cx, &PlainObject::class_, + jsProto); +} bool WasmFunctionTypeImpl(JSContext* cx, const CallArgs& args) { RootedFunction function(cx, &args.thisv().toObject().as()); - Rooted instanceObj( - cx, ExportedFunctionToInstanceObject(function)); - uint32_t funcIndex = ExportedFunctionToFuncIndex(function); - Instance& instance = instanceObj->instance(); - const FuncExport& fe = - instance.metadata(instance.code().bestTier()).lookupFuncExport(funcIndex); - const FuncType& funcType = instance.metadata().getFuncExportType(fe); + const FuncType& funcType = function->wasmTypeDef()->funcType(); RootedObject typeObj(cx, FuncTypeToObject(cx, funcType)); if (!typeObj) { return false; @@ -4107,8 +4058,6 @@ static JSFunction* WasmFunctionCreate(JSContext* cx, HandleObject func, wasm::ValTypeVector&& results, HandleObject proto) { MOZ_ASSERT(IsCallableNonCCW(ObjectValue(*func))); - MOZ_RELEASE_ASSERT(!func->is() || - !IsWasmExportedFunction(&func->as())); // We want to import the function to a wasm module and then export it again so // that it behaves exactly like a normal wasm function and can be used like @@ -4122,52 +4071,55 @@ static JSFunction* WasmFunctionCreate(JSContext* cx, HandleObject func, return nullptr; } - ModuleEnvironment moduleEnv(compileArgs->features); + MutableModuleMetadata moduleMeta = js_new(); + if (!moduleMeta || !moduleMeta->init(*compileArgs)) { + return nullptr; + } + MutableCodeMetadata codeMeta = moduleMeta->codeMeta; CompilerEnvironment compilerEnv(CompileMode::Once, Tier::Optimized, DebugEnabled::False); compilerEnv.computeParameters(); - if (!moduleEnv.init()) { - return nullptr; - } - FuncType funcType = FuncType(std::move(params), std::move(results)); - if (!moduleEnv.types->addType(std::move(funcType))) { + if (!codeMeta->types->addType(std::move(funcType))) { return nullptr; } // Add an (import (func ...)) - FuncDesc funcDesc = FuncDesc(&(*moduleEnv.types)[0].funcType(), 0); - if (!moduleEnv.funcs.append(funcDesc)) { + FuncDesc funcDesc = FuncDesc(0); + if (!codeMeta->funcs.append(funcDesc)) { return nullptr; } - moduleEnv.numFuncImports = 1; + codeMeta->numFuncImports = 1; + codeMeta->funcImportsAreJS = true; // Add an (export (func 0)) - moduleEnv.declareFuncExported(0, /* eager */ true, /* canRefFunc */ true); + codeMeta->funcs[0].declareFuncExported(/* eager */ true, + /* canRefFunc */ true); // We will be looking up and using the function in the future by index so the // name doesn't matter. CacheableName fieldName; - if (!moduleEnv.exports.emplaceBack(std::move(fieldName), 0, - DefinitionKind::Function)) { + if (!moduleMeta->exports.emplaceBack(std::move(fieldName), 0, + DefinitionKind::Function)) { return nullptr; } - ModuleGenerator mg(*compileArgs, &moduleEnv, &compilerEnv, nullptr, nullptr, - nullptr); - if (!mg.init(nullptr)) { + if (!moduleMeta->prepareForCompile(compilerEnv.mode())) { + return nullptr; + } + + ModuleGenerator mg(*codeMeta, compilerEnv, compilerEnv.initialState(), + nullptr, nullptr, nullptr); + if (!mg.initializeCompleteTier()) { return nullptr; } // We're not compiling any function definitions. if (!mg.finishFuncDefs()) { return nullptr; } - SharedBytes shareableBytes = js_new(); - if (!shareableBytes) { - return nullptr; - } - SharedModule module = mg.finishModule(*shareableBytes); + SharedModule module = mg.finishModule(BytecodeBufferOrSource(), *moduleMeta, + /*maybeCompleteTier2Listener=*/nullptr); if (!module) { return nullptr; } @@ -4220,6 +4172,11 @@ bool WasmFunctionConstruct(JSContext* cx, unsigned argc, Value* vp) { if (!ParseValTypes(cx, parametersVal, params)) { return false; } + if (params.length() > MaxParams) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_BAD_FUNCTION_TYPE, "parameters"); + return false; + } RootedValue resultsVal(cx); if (!JS_GetProperty(cx, typeObj, "results", &resultsVal)) { @@ -4230,70 +4187,15 @@ bool WasmFunctionConstruct(JSContext* cx, unsigned argc, Value* vp) { if (!ParseValTypes(cx, resultsVal, results)) { return false; } - -# ifdef ENABLE_WASM_JSPI - // Check suspeding and promising - SuspenderArgPosition suspending = SuspenderArgPosition::None; - SuspenderArgPosition promising = SuspenderArgPosition::None; - if (wasm::JSPromiseIntegrationAvailable(cx) && args.length() > 2 && - args[2].isObject()) { - RootedObject usageObj(cx, &args[2].toObject()); - RootedValue val(cx); - if (!JS_GetProperty(cx, usageObj, "suspending", &val)) { - return false; - } - if (!ParseSuspendingPromisingString(cx, val, suspending)) { - return false; - } - if (!JS_GetProperty(cx, usageObj, "promising", &val)) { - return false; - } - if (!ParseSuspendingPromisingString(cx, val, promising)) { - return false; - } + if (results.length() > MaxResults) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_BAD_FUNCTION_TYPE, "results"); + return false; } - if (suspending > SuspenderArgPosition::None) { - if (!IsCallableNonCCW(args[1])) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_FUNCTION_VALUE); - return false; - } - - RootedObject func(cx, &args[1].toObject()); - RootedFunction suspend( - cx, WasmSuspendingFunctionCreate(cx, func, std::move(params), - std::move(results), suspending)); - if (!suspend) { - return false; - } - args.rval().setObject(*suspend); - - return true; - } - if (promising > SuspenderArgPosition::None) { - if (!IsWasmFunction(args[1])) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_FUNCTION_VALUE); - return false; - } - - RootedObject func(cx, &args[1].toObject()); - RootedFunction promise( - cx, WasmPromisingFunctionCreate(cx, func, std::move(params), - std::move(results), promising)); - if (!promise) { - return false; - } - args.rval().setObject(*promise); - - return true; - } -# endif // ENABLE_WASM_JSPI - // Get the target function - if (!IsCallableNonCCW(args[1]) || IsWasmFunction(args[1])) { + if (!IsCallableNonCCW(args[1])) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_FUNCTION_VALUE); return false; @@ -4334,19 +4236,27 @@ static JSObject* CreateWasmFunctionConstructor(JSContext* cx, JSProtoKey key) { } const JSFunctionSpec WasmFunctionMethods[] = { - JS_FN("type", WasmFunctionType, 0, 0), JS_FS_END}; + JS_FN("type", WasmFunctionType, 0, 0), + JS_FS_END, +}; -const ClassSpec WasmFunctionClassSpec = {CreateWasmFunctionConstructor, - CreateWasmFunctionPrototype, - nullptr, - nullptr, - WasmFunctionMethods, - nullptr, - nullptr, - ClassSpec::DontDefineConstructor}; +const ClassSpec WasmFunctionClassSpec = { + CreateWasmFunctionConstructor, + CreateWasmFunctionPrototype, + nullptr, + nullptr, + WasmFunctionMethods, + nullptr, + nullptr, + ClassSpec::DontDefineConstructor, +}; const JSClass js::WasmFunctionClass = { - "WebAssembly.Function", 0, JS_NULL_CLASS_OPS, &WasmFunctionClassSpec}; + "WebAssembly.Function", + 0, + JS_NULL_CLASS_OPS, + &WasmFunctionClassSpec, +}; #endif @@ -4508,7 +4418,7 @@ static bool AsyncInstantiate(JSContext* cx, const Module& module, return RejectWithPendingException(cx, promise); } - task.release()->dispatchResolveAndDestroy(); + OffThreadPromiseTask::DispatchResolveAndDestroy(std::move(task)); return true; } @@ -4530,7 +4440,7 @@ static bool ResolveCompile(JSContext* cx, const Module& module, } struct CompileBufferTask : PromiseHelperTask { - MutableBytes bytecode; + BytecodeBuffer bytecode; SharedCompileArgs compileArgs; UniqueChars error; UniqueCharsVector warnings; @@ -4556,7 +4466,8 @@ struct CompileBufferTask : PromiseHelperTask { } void execute() override { - module = CompileBuffer(*compileArgs, *bytecode, &error, &warnings, nullptr); + module = CompileBuffer(*compileArgs, BytecodeBufferOrSource(bytecode), + &error, &warnings, nullptr); } bool resolve(JSContext* cx, Handle promise) override { @@ -4594,7 +4505,7 @@ static bool EnsurePromiseSupport(JSContext* cx) { } static bool GetBufferSource(JSContext* cx, const CallArgs& callArgs, - const char* name, MutableBytes* bytecode) { + const char* name, BytecodeSource* bytecode) { if (!callArgs.requireAtLeast(cx, name, 1)) { return false; } @@ -4623,7 +4534,16 @@ static bool WebAssembly_compile(JSContext* cx, unsigned argc, Value* vp) { CallArgs callArgs = CallArgsFromVp(argc, vp); - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return RejectWithPendingException(cx, promise, callArgs); + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_WASM, "WebAssembly.compile"); return RejectWithPendingException(cx, promise, callArgs); @@ -4634,9 +4554,14 @@ static bool WebAssembly_compile(JSContext* cx, unsigned argc, Value* vp) { return false; } - if (!GetBufferSource(cx, callArgs, "WebAssembly.compile", &task->bytecode)) { + BytecodeSource source; + if (!GetBufferSource(cx, callArgs, "WebAssembly.compile", &source)) { return RejectWithPendingException(cx, promise, callArgs); } + if (!BytecodeBuffer::fromSource(source, &task->bytecode)) { + ReportOutOfMemory(cx); + return false; + } FeatureOptions options; if (!options.init(cx, callArgs.get(1))) { @@ -4707,7 +4632,16 @@ static bool WebAssembly_instantiate(JSContext* cx, unsigned argc, Value* vp) { return false; } } else { - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return RejectWithPendingException(cx, promise, callArgs); + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_WASM, "WebAssembly.instantiate"); @@ -4724,10 +4658,14 @@ static bool WebAssembly_instantiate(JSContext* cx, unsigned argc, Value* vp) { return false; } - if (!GetBufferSource(cx, firstArg, JSMSG_WASM_BAD_BUF_MOD_ARG, - &task->bytecode)) { + BytecodeSource source; + if (!GetBufferSource(cx, firstArg, JSMSG_WASM_BAD_BUF_MOD_ARG, &source)) { return RejectWithPendingException(cx, promise, callArgs); } + if (!BytecodeBuffer::fromSource(source, &task->bytecode)) { + ReportOutOfMemory(cx); + return false; + } if (!StartOffThreadPromiseHelperTask(cx, std::move(task))) { return false; @@ -4741,8 +4679,8 @@ static bool WebAssembly_instantiate(JSContext* cx, unsigned argc, Value* vp) { static bool WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp) { CallArgs callArgs = CallArgsFromVp(argc, vp); - MutableBytes bytecode; - if (!GetBufferSource(cx, callArgs, "WebAssembly.validate", &bytecode)) { + BytecodeSource source; + if (!GetBufferSource(cx, callArgs, "WebAssembly.validate", &source)) { return false; } @@ -4752,7 +4690,7 @@ static bool WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp) { } UniqueChars error; - bool validated = Validate(cx, *bytecode, options, &error); + bool validated = Validate(cx, source, options, &error); // If the reason for validation failure was OOM (signalled by null error // message), report out-of-memory so that validate's return is always @@ -4822,18 +4760,18 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { const MutableCompileArgs compileArgs_; // Immutable after Env state: - Bytes envBytes_; - SectionRange codeSection_; + MutableBytes envBytes_; + BytecodeRange codeSection_; // The code section vector is resized once during the Env state and filled // in chunk by chunk during the Code state, updating the end-pointer after // each chunk: - Bytes codeBytes_; + MutableBytes codeBytes_; uint8_t* codeBytesEnd_; ExclusiveBytesPtr exclusiveCodeBytesEnd_; // Immutable after Tail state: - Bytes tailBytes_; + MutableBytes tailBytes_; ExclusiveStreamEndData exclusiveStreamEnd_; // Written once before Closed state and read in Closed state on main thread: @@ -4843,7 +4781,7 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { UniqueCharsVector warnings_; // Set on stream thread and read racily on helper thread to abort compilation: - Atomic streamFailed_; + mozilla::Atomic streamFailed_; // Called on some thread before consumeChunk(), streamEnd(), streamError()): @@ -4905,29 +4843,29 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { bool consumeChunk(const uint8_t* begin, size_t length) override { switch (streamState_.lock().get()) { case Env: { - if (!envBytes_.append(begin, length)) { + if (!envBytes_->append(begin, length)) { return rejectAndDestroyBeforeHelperThreadStarted(StreamOOMCode); } - if (!StartsCodeSection(envBytes_.begin(), envBytes_.end(), + if (!StartsCodeSection(envBytes_->begin(), envBytes_->end(), &codeSection_)) { return true; } - uint32_t extraBytes = envBytes_.length() - codeSection_.start; + uint32_t extraBytes = envBytes_->length() - codeSection_.start; if (extraBytes) { - envBytes_.shrinkTo(codeSection_.start); + envBytes_->shrinkTo(codeSection_.start); } - if (codeSection_.size > MaxCodeSectionBytes) { + if (codeSection_.size() > MaxCodeSectionBytes) { return rejectAndDestroyBeforeHelperThreadStarted(StreamOOMCode); } - if (!codeBytes_.resize(codeSection_.size)) { + if (!codeBytes_->vector.resize(codeSection_.size())) { return rejectAndDestroyBeforeHelperThreadStarted(StreamOOMCode); } - codeBytesEnd_ = codeBytes_.begin(); + codeBytesEnd_ = codeBytes_->begin(); exclusiveCodeBytesEnd_.lock().get() = codeBytesEnd_; if (!StartOffThreadPromiseHelperTask(this)) { @@ -4947,7 +4885,7 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { } case Code: { size_t copyLength = - std::min(length, codeBytes_.end() - codeBytesEnd_); + std::min(length, codeBytes_->end() - codeBytesEnd_); memcpy(codeBytesEnd_, begin, copyLength); codeBytesEnd_ += copyLength; @@ -4957,7 +4895,7 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { codeStreamEnd.notify_one(); } - if (codeBytesEnd_ != codeBytes_.end()) { + if (codeBytesEnd_ != codeBytes_->end()) { return true; } @@ -4970,7 +4908,7 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { return true; } case Tail: { - if (!tailBytes_.append(begin, length)) { + if (!tailBytes_->append(begin, length)) { return rejectAndDestroyAfterHelperThreadStarted(StreamOOMCode); } @@ -4982,16 +4920,13 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { MOZ_CRASH("unreachable"); } - void streamEnd(JS::OptimizedEncodingListener* tier2Listener) override { + void streamEnd( + JS::OptimizedEncodingListener* completeTier2Listener) override { switch (streamState_.lock().get()) { case Env: { - SharedBytes bytecode = js_new(std::move(envBytes_)); - if (!bytecode) { - rejectAndDestroyBeforeHelperThreadStarted(StreamOOMCode); - return; - } - module_ = CompileBuffer(*compileArgs_, *bytecode, &compileError_, - &warnings_, nullptr); + BytecodeBuffer bytecode(envBytes_, nullptr, nullptr); + module_ = CompileBuffer(*compileArgs_, BytecodeBufferOrSource(bytecode), + &compileError_, &warnings_, nullptr); setClosedAndDestroyBeforeHelperThreadStarted(); return; } @@ -5002,8 +4937,8 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { auto streamEnd = exclusiveStreamEnd_.lock(); MOZ_ASSERT(!streamEnd->reached); streamEnd->reached = true; - streamEnd->tailBytes = &tailBytes_; - streamEnd->tier2Listener = tier2Listener; + streamEnd->tailBytes = tailBytes_; + streamEnd->completeTier2Listener = completeTier2Listener; streamEnd.notify_one(); } setClosedAndDestroyAfterHelperThreadStarted(); @@ -5038,7 +4973,7 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { // Called on a helper thread: void execute() override { - module_ = CompileStreaming(*compileArgs_, envBytes_, codeBytes_, + module_ = CompileStreaming(*compileArgs_, *envBytes_, *codeBytes_, exclusiveCodeBytesEnd_, exclusiveStreamEnd_, streamFailed_, &compileError_, &warnings_); @@ -5091,6 +5026,25 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer { streamFailed_(false) { MOZ_ASSERT_IF(importObj_, instantiate_); } + + [[nodiscard]] bool init(JSContext* cx) { + envBytes_ = cx->new_(); + if (!envBytes_) { + return false; + } + + codeBytes_ = js_new(); + if (!codeBytes_) { + return false; + } + + tailBytes_ = js_new(); + if (!tailBytes_) { + return false; + } + + return PromiseHelperTask::init(cx); + } }; // A short-lived object that captures the arguments of a @@ -5299,7 +5253,16 @@ static bool WebAssembly_compileStreaming(JSContext* cx, unsigned argc, CallArgs callArgs = CallArgsFromVp(argc, vp); - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return RejectWithPendingException(cx, resultPromise, callArgs); + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_WASM, "WebAssembly.compileStreaming"); @@ -5332,7 +5295,16 @@ static bool WebAssembly_instantiateStreaming(JSContext* cx, unsigned argc, CallArgs callArgs = CallArgsFromVp(argc, vp); - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return RejectWithPendingException(cx, resultPromise, callArgs); + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_WASM, "WebAssembly.instantiateStreaming"); @@ -5366,12 +5338,15 @@ const ClassSpec WasmSuspendingObject::classSpec_ = { nullptr, nullptr, nullptr, - ClassSpec::DontDefineConstructor}; + ClassSpec::DontDefineConstructor, +}; const JSClass WasmSuspendingObject::class_ = { "Suspending", JSCLASS_HAS_RESERVED_SLOTS(WasmSuspendingObject::RESERVED_SLOTS), - JS_NULL_CLASS_OPS, &classSpec_}; + JS_NULL_CLASS_OPS, + &classSpec_, +}; const JSClass& WasmSuspendingObject::protoClass_ = PlainObject::class_; @@ -5379,6 +5354,10 @@ const JSClass& WasmSuspendingObject::protoClass_ = PlainObject::class_; bool WasmSuspendingObject::construct(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); + if (!ThrowIfNotConstructing(cx, args, "WebAssembly.Suspending")) { + return false; + } + if (!args.requireAtLeast(cx, "WebAssembly.Suspending", 1)) { return false; } @@ -5416,8 +5395,7 @@ static bool WebAssembly_promising(JSContext* cx, unsigned argc, Value* vp) { RootedObject func(cx, &args[0].toObject()); RootedFunction promise( cx, WasmPromisingFunctionCreate(cx, func, wasm::ValTypeVector(), - wasm::ValTypeVector(), - SuspenderArgPosition::None)); + wasm::ValTypeVector())); if (!promise) { return false; } @@ -5426,7 +5404,9 @@ static bool WebAssembly_promising(JSContext* cx, unsigned argc, Value* vp) { } static const JSFunctionSpec WebAssembly_jspi_methods[] = { - JS_FN("promising", WebAssembly_promising, 1, JSPROP_ENUMERATE), JS_FS_END}; + JS_FN("promising", WebAssembly_promising, 1, JSPROP_ENUMERATE), + JS_FS_END, +}; bool js::IsWasmSuspendingObject(JSObject* obj) { return obj->is(); @@ -5459,7 +5439,8 @@ static bool WebAssembly_mozIntGemm(JSContext* cx, unsigned argc, Value* vp) { static const JSFunctionSpec WebAssembly_mozIntGemm_methods[] = { JS_FN("mozIntGemm", WebAssembly_mozIntGemm, 0, JSPROP_ENUMERATE), - JS_FS_END}; + JS_FS_END, +}; #endif // ENABLE_WASM_MOZ_INTGEMM @@ -5472,10 +5453,13 @@ static const JSFunctionSpec WebAssembly_static_methods[] = { JSPROP_ENUMERATE), JS_FN("instantiateStreaming", WebAssembly_instantiateStreaming, 1, JSPROP_ENUMERATE), - JS_FS_END}; + JS_FS_END, +}; static const JSPropertySpec WebAssembly_static_properties[] = { - JS_STRING_SYM_PS(toStringTag, "WebAssembly", JSPROP_READONLY), JS_PS_END}; + JS_STRING_SYM_PS(toStringTag, "WebAssembly", JSPROP_READONLY), + JS_PS_END, +}; static JSObject* CreateWebAssemblyObject(JSContext* cx, JSProtoKey key) { MOZ_RELEASE_ASSERT(HasSupport(cx)); @@ -5573,6 +5557,7 @@ static bool WebAssemblyClassFinish(JSContext* cx, HandleObject object, #ifdef ENABLE_WASM_JSPI constexpr NameAndProtoKey jspiEntries[] = { {"Suspending", JSProto_WasmSuspending}, + {"SuspendError", GetExceptionProtoKey(JSEXN_WASMSUSPENDERROR)}, }; if (JSPromiseIntegrationAvailable(cx)) { if (!JS_DefineFunctions(cx, wasm, WebAssembly_jspi_methods)) { @@ -5608,12 +5593,15 @@ WasmNamespaceObject* WasmNamespaceObject::getOrCreate(JSContext* cx) { static const ClassSpec WebAssemblyClassSpec = { CreateWebAssemblyObject, nullptr, WebAssembly_static_methods, WebAssembly_static_properties, nullptr, nullptr, - WebAssemblyClassFinish}; + WebAssemblyClassFinish, +}; const JSClass js::WasmNamespaceObject::class_ = { "WebAssembly", JSCLASS_HAS_CACHED_PROTO(JSProto_WebAssembly) | JSCLASS_HAS_RESERVED_SLOTS(WasmNamespaceObject::RESERVED_SLOTS), - JS_NULL_CLASS_OPS, &WebAssemblyClassSpec}; + JS_NULL_CLASS_OPS, + &WebAssemblyClassSpec, +}; // Sundry diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmJS.h b/src/third_party/mozjs/extract/js/src/wasm/WasmJS.h index 230922f9e70..3a529787f25 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmJS.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmJS.h @@ -103,25 +103,12 @@ struct ImportValues; // WebAssembly.Module object. [[nodiscard]] bool CompileAndSerialize(JSContext* cx, - const ShareableBytes& bytecode, + const BytecodeSource& source, Bytes* serialized); [[nodiscard]] bool DeserializeModule(JSContext* cx, const Bytes& serialized, MutableHandleObject module); -// A WebAssembly "Exported Function" is the spec name for the JS function -// objects created to wrap wasm functions. This predicate returns false -// for asm.js functions which are semantically just normal JS functions -// (even if they are implemented via wasm under the hood). The accessor -// functions for extracting the instance and func-index of a wasm function -// can be used for both wasm and asm.js, however. - -bool IsWasmExportedFunction(JSFunction* fun); - -Instance& ExportedFunctionToInstance(JSFunction* fun); -WasmInstanceObject* ExportedFunctionToInstanceObject(JSFunction* fun); -uint32_t ExportedFunctionToFuncIndex(JSFunction* fun); - bool IsSharedWasmMemoryObject(JSObject* obj); } // namespace wasm @@ -206,10 +193,9 @@ class WasmGlobalObject : public NativeObject { class WasmInstanceObject : public NativeObject { static const unsigned INSTANCE_SLOT = 0; static const unsigned EXPORTS_OBJ_SLOT = 1; - static const unsigned EXPORTS_SLOT = 2; - static const unsigned SCOPES_SLOT = 3; - static const unsigned INSTANCE_SCOPE_SLOT = 4; - static const unsigned GLOBALS_SLOT = 5; + static const unsigned SCOPES_SLOT = 2; + static const unsigned INSTANCE_SCOPE_SLOT = 3; + static const unsigned GLOBALS_SLOT = 4; static const JSClassOps classOps_; static const ClassSpec classSpec_; @@ -219,20 +205,12 @@ class WasmInstanceObject : public NativeObject { static void finalize(JS::GCContext* gcx, JSObject* obj); static void trace(JSTracer* trc, JSObject* obj); - // ExportMap maps from function index to exported function object. - // This allows the instance to lazily create exported function - // objects on demand (instead up-front for all table elements) while - // correctly preserving observable function object identity. - using ExportMap = GCHashMap, - DefaultHasher, CellAllocPolicy>; - ExportMap& exports() const; - // See the definition inside WasmJS.cpp. class UnspecifiedScopeMap; UnspecifiedScopeMap& scopes() const; public: - static const unsigned RESERVED_SLOTS = 6; + static const unsigned RESERVED_SLOTS = 5; static const JSClass class_; static const JSClass& protoClass_; static const JSPropertySpec properties[]; @@ -260,9 +238,6 @@ class WasmInstanceObject : public NativeObject { JSContext* cx, Handle instanceObj, uint32_t funcIndex, MutableHandleFunction fun); - const wasm::CodeRange& getExportedFunctionCodeRange(JSFunction* fun, - wasm::Tier tier); - static WasmInstanceScope* getScope(JSContext* cx, Handle instanceObj); static WasmFunctionScope* getFunctionScope( @@ -293,6 +268,10 @@ class WasmMemoryObject : public NativeObject { static bool discardImpl(JSContext* cx, const CallArgs& args); static bool discard(JSContext* cx, unsigned argc, Value* vp); static uint64_t growShared(Handle memory, uint64_t delta); + static bool toFixedLengthBufferImpl(JSContext* cx, const CallArgs& args); + static bool toFixedLengthBuffer(JSContext* cx, unsigned argc, Value* vp); + static bool toResizableBufferImpl(JSContext* cx, const CallArgs& args); + static bool toResizableBuffer(JSContext* cx, unsigned argc, Value* vp); using InstanceSet = JS::WeakCache, @@ -301,6 +280,13 @@ class WasmMemoryObject : public NativeObject { InstanceSet& observers() const; InstanceSet* getOrCreateObservers(JSContext* cx); + // The spec requires that the buffer property will create a new fixed length + // SAB if the underlying raw buffer's length has changed. The method creates + // new objects and updates the BUFFER_SLOT slot. + static ArrayBufferObjectMaybeShared* refreshBuffer( + JSContext* cx, Handle memoryObj, + Handle buffer); + public: static const unsigned RESERVED_SLOTS = 3; static const JSClass class_; @@ -338,7 +324,7 @@ class WasmMemoryObject : public NativeObject { wasm::Pages clampedMaxPages() const; mozilla::Maybe sourceMaxPages() const; - wasm::IndexType indexType() const; + wasm::AddressType addressType() const; bool isShared() const; bool isHuge() const; bool movingGrowable() const; @@ -388,8 +374,7 @@ class WasmTableObject : public NativeObject { // Note that, after creation, a WasmTableObject's table() is not initialized // and must be initialized before use. - static WasmTableObject* create(JSContext* cx, uint32_t initialLength, - mozilla::Maybe maximumLength, + static WasmTableObject* create(JSContext* cx, wasm::Limits limits, wasm::RefType tableType, HandleObject proto); wasm::Table& table() const; @@ -427,7 +412,6 @@ class WasmTagObject : public NativeObject { const wasm::TagType* tagType() const; const wasm::ValTypeVector& valueTypes() const; - wasm::ResultType resultType() const; }; // The class of WebAssembly.Exception. This class is used for diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmLog.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmLog.cpp index 34ef219ce15..8dc59dc1c7d 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmLog.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmLog.cpp @@ -24,15 +24,19 @@ #include "js/Printf.h" #include "js/Utility.h" #include "vm/JSContext.h" +#include "vm/Logging.h" #include "vm/Warnings.h" using namespace js; using namespace js::wasm; void wasm::Log(JSContext* cx, const char* fmt, ...) { - MOZ_ASSERT(!cx->isExceptionPending()); + MOZ_ASSERT(!cx->isExceptionPending() || cx->isThrowingOutOfMemory()); - if (!cx->options().wasmVerbose()) { + bool shouldWarn = JS::Prefs::wasm_trace_api(); + bool shouldLog = wasmApiModule.shouldLog(LogLevel::Info); + + if (cx->isThrowingOutOfMemory() || (!shouldWarn && !shouldLog)) { return; } @@ -40,9 +44,15 @@ void wasm::Log(JSContext* cx, const char* fmt, ...) { va_start(args, fmt); if (UniqueChars chars = JS_vsmprintf(fmt, args)) { - WarnNumberASCII(cx, JSMSG_WASM_VERBOSE, chars.get()); - if (cx->isExceptionPending()) { - cx->clearPendingException(); + if (shouldWarn) { + WarnNumberASCII(cx, JSMSG_WASM_VERBOSE, chars.get()); + if (cx->isExceptionPending()) { + cx->clearPendingException(); + } + } + if (shouldLog) { + wasmApiModule.interface.logPrint(wasmApiModule.logger, LogLevel::Info, + "%s", chars.get()); } } @@ -50,10 +60,17 @@ void wasm::Log(JSContext* cx, const char* fmt, ...) { } void wasm::LogOffThread(const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); + if (!wasmApiModule.shouldLog(LogLevel::Info)) { + return; + } + + va_list args; + va_start(args, fmt); + if (UniqueChars chars = JS_vsmprintf(fmt, args)) { + wasmApiModule.interface.logPrint(wasmApiModule.logger, LogLevel::Info, "%s", + chars.get()); + } + va_end(args); } #ifdef WASM_CODEGEN_DEBUG diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.cpp index 01ef36e8a36..937d1f893dd 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.cpp @@ -31,18 +31,19 @@ using mozilla::IsPowerOfTwo; using namespace js; using namespace js::wasm; -const char* wasm::ToString(IndexType indexType) { - switch (indexType) { - case IndexType::I32: +const char* wasm::ToString(AddressType addressType) { + switch (addressType) { + case AddressType::I32: return "i32"; - case IndexType::I64: + case AddressType::I64: return "i64"; default: MOZ_CRASH(); } } -bool wasm::ToIndexType(JSContext* cx, HandleValue value, IndexType* indexType) { +bool wasm::ToAddressType(JSContext* cx, HandleValue value, + AddressType* addressType) { RootedString typeStr(cx, ToString(cx, value)); if (!typeStr) { return false; @@ -54,12 +55,12 @@ bool wasm::ToIndexType(JSContext* cx, HandleValue value, IndexType* indexType) { } if (StringEqualsLiteral(typeLinearStr, "i32")) { - *indexType = IndexType::I32; + *addressType = AddressType::I32; } else if (StringEqualsLiteral(typeLinearStr, "i64")) { - *indexType = IndexType::I64; + *addressType = AddressType::I64; } else { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_STRING_IDX_TYPE); + JSMSG_WASM_BAD_STRING_ADDR_TYPE); return false; } return true; @@ -71,116 +72,181 @@ bool wasm::ToIndexType(JSContext* cx, HandleValue value, IndexType* indexType) { * (Also see "WASM Linear Memory structure" in vm/ArrayBufferObject.cpp) * * - * Memory addresses, bounds check avoidance, and the huge memory trick. + * ## Memory addresses * * A memory address in an access instruction has three components, the "memory - * base", the "pointer", and the "offset". The "memory base" - the HeapReg on - * most platforms and a value loaded from the instance on x86 - is a native - * pointer that points to the start of the linear memory array; we'll ignore the - * memory base in the following. The "pointer" is the i32 or i64 index supplied - * by the program as a separate value argument to the access instruction; it is - * usually variable but can be constant. The "offset" is a constant encoded in - * the access instruction. + * base", the "address", and the "offset". The "memory base" (the HeapReg on + * most platforms and a value loaded from the instance on x86) is a native + * pointer to the start of the linear memory array; we'll ignore the memory base + * in the following. The "address" is the i32 or i64 address into linear memory + * from the WebAssembly program; it is usually variable but can be constant. The + * "offset" is a constant immediate to the access instruction. For example, + * consider the following instructions: * - * The "effective address" (EA) is the non-overflowed sum of the pointer and the - * offset (if the sum overflows the program traps); the pointer, offset, and EA - * all have the same type, i32 or i64. + * i32.const 128 + * f32.load offset=8 + * + * The address is 128; the offset is 8. The memory base is not observable to + * wasm. Note that the address comes from wasm value stack, but the offset is an + * immediate. + * + * The "effective address" (EA) is the non-overflowed sum of the address and the + * offset. (If the sum overflows, the program traps.) For the above, the + * effective address is 136. * * An access has an "access size", which is the number of bytes that are - * accessed - currently up to 16 (for V128). The highest-addressed byte to be - * accessed by an access is thus the byte at (pointer+offset+access_size-1), - * where offset+access_size-1 is compile-time evaluable. + * accessed - currently up to 16 (for V128). The highest-addressed byte to be + * accessed is thus the byte at (address + offset + access_size - 1). Note that + * (offset + access_size - 1) can be evaluated at compile time. * - * Bounds checking ensures that the entire access is in bounds, ie, that the - * highest-addressed byte is at an offset in the linear memory below that of the - * memory's current byteLength. + * Bounds checking ensures that the entire access is in bounds, i.e. that the + * highest-addressed byte is within the memory's current byteLength. + * + * + * ## Bounds check avoidance * * To avoid performing an addition with overflow check and a compare-and-branch * bounds check for every memory access, we use some tricks: * - * - An access-protected guard region of size R at the end of each memory is - * used to trap accesses to out-of-bounds offsets in the range - * 0..R-access_size. Thus the offset and the access size need not be added - * into the pointer before the bounds check, saving the add and overflow - * check. The offset is added into the pointer without an overflow check - * either directly before the access or in the access instruction itself - * (depending on the ISA). The pointer must still be explicitly - * bounds-checked. + * - We allocate an access-protected guard region of size R at the end of each + * memory to trap out-of-bounds offsets in the range 0..R-access_size. Thus, + * the offset and the access size can be omitted from the bounds check, saving + * the add and overflow check. For example, given the following module: * - * - On 64-bit systems where we determine there is plenty of virtual memory - * space (and ideally we determine that the VM system uses overcommit), a - * 32-bit memory is implemented as a 4GB + R reservation, where the memory - * from the current heap length through the end of the reservation is - * access-protected. The protected area R allows offsets up to R-access_size - * to be encoded in the access instruction. The pointer need not be bounds - * checked explicitly, since it has only a 4GB range and thus points into the - * 4GB part of the reservation. The offset can be added into the pointer - * (using 64-bit arithmetic) either directly before the access or in the - * access instruction. + * (memory 1) ;; 1 page, 65536 bytes + * (func + * (f64.load offset=8 (i32.const 65528)) + * ) * - * The value of R differs in the two situations; in the first case it tends to - * be small, currently 64KB; in the second case it is large, currently 2GB+64KB. - * The difference is due to explicit bounds checking tending to be used on - * 32-bit systems where memory and address space are scarce, while the implicit - * bounds check is used only on 64-bit systems after ensuring that sufficient - * address space is available in the process. (2GB is really overkill, and - * there's nothing magic about it; we could use something much smaller.) + * As long as the address itself is bounds checked, the offset will at worst + * cause the access to land in the guard region and trap via signal handling: * - * The implicit bounds checking strategy with the large reservation is known - * below and elsewhere as the "huge memory trick" or just "huge memory". + * Memory │ Guard Region + * ─ ─ ──────────┼────────┬──────── ─ ─ + * │ access │ + * ─ ─ ─┬────────┼────────┴──────── ─ ─ + * 65528 65536 + * + * Therefore, after bounds checking the address, the offset can be added into + * the address without an overflow check, either directly before the access or + * in the access instruction itself (depending on the ISA). + * + * This is the second part of the "SLOP" region as defined in "WASM Linear + * Memory structure" in ArrayBufferObject.cpp. + * + * - For 32-bit memories on 64-bit systems where we determine there is plenty of + * virtual memory space, we use "huge memories", in which we reserve 4GiB + R + * bytes of memory regardless of the memory's byteLength. Since the address + * itself has a 4GiB range, this allows us to skip bounds checks on the + * address as well. The extra R bytes of guard pages protect against + * out-of-bounds offsets as above. + * + * The offset can be added into the pointer (using 64-bit arithmetic) either + * directly before the access or in the access instruction. + * + * In both cases, accesses with offsets greater than R-access_size must be + * explicitly bounds checked in full, with an overflow check, since we cannot + * rely on the guard region. + * + * The value of R may vary depending on the memory allocation strategy and the + * amount of address space we can freely reserve. We do not document it here + * lest it be absurdly out of date. Search for "OffsetGuardLimit" if you wish. * * All memories in a process use the same strategy, selected at process startup. - * The immediate reason for that is that the machine code embeds the strategy - * it's been compiled with, and may later be exposed to memories originating - * from different modules or directly from JS. If the memories did not all use - * the same strategy, and the same strategy as the code, linking would fail or - * we would have to recompile the code. + * This is because the machine code embeds the strategy it's been compiled with, + * and may later be exposed to memories originating from different modules or + * directly from JS. If the memories did not all use the same strategy, we would + * have to recompile the code for each case. * * - * The boundsCheckLimit. + * ## The boundsCheckLimit and the byteLength * - * The bounds check limit that is stored in the instance is always valid and is - * always a 64-bit datum, and it is always correct to load it and use it as a - * 64-bit value. However, in situations when the 32 upper bits are known to be - * zero, it is also correct to load just the low 32 bits from the address of the - * limit (which is always little-endian when a JIT is enabled), and use that - * value as the limit. + * One would expect the boundsCheckLimit to always equal the memory's current + * byteLength. However, because the memory can grow, this means each bounds + * check must first load the boundsCheckLimit from the instance. + * + * We can sometimes avoid this load by observing that, even for non-huge + * memories, the signal handler is the final source of truth. In any case where + * we make a single memory reservation up front, we can set the boundsCheckLimit + * to the maximum possible byteLength. (For example, huge memories and memories + * with a max - anything that will NOT move on grow.) + * + * + * b.c. pass b.c. pass b.c. fail + * s.h. pass s.h. fail s.h. n/a + * ─ ─ ─────────────────┼─────────────────┼────────────── ─ ─ + * + * ─ ─ ─────────────────────────────────────────────────────┐ + * ─ ─ ─────────────────│─────────────────│─────────────────│ + * byteLength boundsCheckLimit mappedSize + * + * ─ ─ ─────────────────┘ + * COMMITTED + * └─────────────────┴─────────────────┘ + * SLOP + * + * + * Note that this works even if byteLength later grows: + * + * + * b.c. pass b.c. fail + * s.h. pass s.h. n/a + * ─ ─ ───────────────────────────────────┼────────────── ─ ─ + * + * ─ ─ ─────────────────────────────────────────────────────┐ + * ─ ─ ───────────────────────────────────│─────────────────│ + * byteLength mappedSize + * boundsCheckLimit + * + * ─ ─ ───────────────────────────────────┘ + * COMMITTED + * └─────────────────┘ + * SLOP + * + * + * Therefore, the boundsCheckLimit need only be greater than byteLength, not + * equal to byteLength, and the boundsCheckLimit need only be loaded once. This + * is the first part of the "SLOP" region as defined in "WASM Linear Memory + * structure" in ArrayBufferObject.cpp. + * + * + * ## Size of the boundsCheckLimit + * + * The boundsCheckLimit that is stored in the instance is always valid and is + * always a 64-bit value, and it is always correct to load it and use it as a + * 64-bit value. However, in situations when the 32 upper bits are known to be + * zero, it is also correct to load just the low 32 bits, and use that value as + * the limit. (This does not require a different address, since the limit is + * always little-endian when a JIT is enabled) * * On x86 and arm32 (and on any other 32-bit platform, should there ever be - * one), there is explicit bounds checking and the heap, whether memory32 or - * memory64, is limited to 2GB; the bounds check limit can be treated as a - * 32-bit quantity. + * one), we always use explicit bounds checks, and the boundsCheckLimit can + * always be treated as a 32-bit quantity. * - * On all 64-bit platforms, we may use explicit bounds checking or the huge - * memory trick for memory32, but must always use explicit bounds checking for - * memory64. If the heap does not have a known maximum size or the known - * maximum is greater than or equal to 4GB, then the bounds check limit must be - * treated as a 64-bit quantity; otherwise it can be treated as a 32-bit - * quantity. - * - * On x64 and arm64 with Baseline and Ion, we allow 32-bit memories up to 4GB, - * and 64-bit memories can be larger. - * - * On mips64, memories are limited to 2GB, for now. + * On all 64-bit platforms, we may use explicit bounds checking or huge memories + * for memory32, but must always use explicit bounds checking for memory64. If + * the heap has a known maximum size that is less than 4GiB, then the + * boundsCheckLimit can be treated as a 32-bit quantity; otherwise it must be + * treated as a 64-bit quantity. * * Asm.js memories are limited to 2GB even on 64-bit platforms, and we can - * always assume a 32-bit bounds check limit for asm.js. + * therefore always assume a 32-bit bounds check limit for asm.js. * * - * Constant pointers. + * ## Constant pointers * * If the pointer is constant then the EA can be computed at compile time, and - * if the EA is below the initial memory size then the bounds check can be - * elided. + * if (EA + access_size) is below the initial memory size, then the bounds check + * can always be elided. * * - * Alignment checks. + * ## Alignment checks * * On all platforms, some accesses (currently atomics) require an alignment * check: the EA must be naturally aligned for the datum being accessed. * However, we do not need to compute the EA properly, we care only about the - * low bits - a cheap, overflowing add is fine, and if the offset is known - * to be aligned, only the pointer need be checked. + * low bits - a cheap, overflowing add is fine, and if the offset is known to be + * aligned, only the address need be checked. */ // Bounds checks always compare the base of the memory access with the bounds @@ -232,7 +298,7 @@ static_assert(MaxMemoryAccessSize < GuardSize, static_assert(OffsetGuardLimit < UINT32_MAX, "checking for overflow against OffsetGuardLimit is enough."); -size_t wasm::GetMaxOffsetGuardLimit(bool hugeMemory) { +uint64_t wasm::GetMaxOffsetGuardLimit(bool hugeMemory) { #ifdef WASM_SUPPORTS_HUGE_MEMORY return hugeMemory ? HugeOffsetGuardLimit : OffsetGuardLimit; #else @@ -247,14 +313,14 @@ static_assert(MaxInlineMemoryCopyLength < MinOffsetGuardLimit, "precondition"); static_assert(MaxInlineMemoryFillLength < MinOffsetGuardLimit, "precondition"); #ifdef JS_64BIT -wasm::Pages wasm::MaxMemoryPages(IndexType t) { - MOZ_ASSERT_IF(t == IndexType::I64, !IsHugeMemoryEnabled(t)); - size_t desired = MaxMemoryLimitField(t); +wasm::Pages wasm::MaxMemoryPages(AddressType t) { + MOZ_ASSERT_IF(t == AddressType::I64, !IsHugeMemoryEnabled(t)); + size_t desired = MaxMemoryPagesValidation(t); constexpr size_t actual = ArrayBufferObject::ByteLengthLimit / PageSize; return wasm::Pages(std::min(desired, actual)); } -size_t wasm::MaxMemoryBoundsCheckLimit(IndexType t) { +size_t wasm::MaxMemoryBoundsCheckLimit(AddressType t) { return MaxMemoryPages(t).byteLength(); } @@ -262,7 +328,7 @@ size_t wasm::MaxMemoryBoundsCheckLimit(IndexType t) { // On 32-bit systems, the heap limit must be representable in the nonnegative // range of an int32_t, which means the maximum heap size as observed by wasm // code is one wasm page less than 2GB. -wasm::Pages wasm::MaxMemoryPages(IndexType t) { +wasm::Pages wasm::MaxMemoryPages(AddressType t) { static_assert(ArrayBufferObject::ByteLengthLimit >= INT32_MAX / PageSize); return wasm::Pages(INT32_MAX / PageSize); } @@ -270,7 +336,7 @@ wasm::Pages wasm::MaxMemoryPages(IndexType t) { // The max bounds check limit can be larger than the MaxMemoryPages because it // is really MaxMemoryPages rounded up to the next valid bounds check immediate, // see ComputeMappedSize(). -size_t wasm::MaxMemoryBoundsCheckLimit(IndexType t) { +size_t wasm::MaxMemoryBoundsCheckLimit(AddressType t) { size_t boundsCheckLimit = size_t(INT32_MAX) + 1; MOZ_ASSERT(IsValidBoundsCheckImmediate(boundsCheckLimit)); return boundsCheckLimit; @@ -311,8 +377,8 @@ uint64_t wasm::RoundUpToNextValidARMImmediate(uint64_t i) { return i; } -Pages wasm::ClampedMaxPages(IndexType t, Pages initialPages, - const Maybe& sourceMaxPages, +Pages wasm::ClampedMaxPages(AddressType t, Pages initialPages, + const mozilla::Maybe& sourceMaxPages, bool useHugeMemory) { Pages clampedMaxPages; diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.h b/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.h index ea2c61aa382..641a7102d59 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmMemory.h @@ -32,19 +32,25 @@ namespace js { namespace wasm { -// Limits are parameterized by an IndexType which is used to index the +// Limits are parameterized by an AddressType which is used to index the // underlying resource (either a Memory or a Table). Tables are restricted to // I32, while memories may use I64 when memory64 is enabled. -enum class IndexType : uint8_t { I32, I64 }; +enum class AddressType : uint8_t { I32, I64 }; -inline ValType ToValType(IndexType it) { - return it == IndexType::I64 ? ValType::I64 : ValType::I32; +inline ValType ToValType(AddressType at) { + return at == AddressType::I64 ? ValType::I64 : ValType::I32; } -extern bool ToIndexType(JSContext* cx, HandleValue value, IndexType* indexType); +inline AddressType MinAddressType(AddressType a, AddressType b) { + return (a == AddressType::I32 || b == AddressType::I32) ? AddressType::I32 + : AddressType::I64; +} -extern const char* ToString(IndexType indexType); +extern bool ToAddressType(JSContext* cx, HandleValue value, + AddressType* addressType); + +extern const char* ToString(AddressType addressType); // Pages is a typed unit representing a multiple of wasm::PageSize. We // generally use pages as the unit of length when representing linear memory @@ -120,10 +126,10 @@ struct Pages { }; // The largest number of pages the application can request. -extern Pages MaxMemoryPages(IndexType t); +extern Pages MaxMemoryPages(AddressType t); // The byte value of MaxMemoryPages(t). -static inline size_t MaxMemoryBytes(IndexType t) { +static inline size_t MaxMemoryBytes(AddressType t) { return MaxMemoryPages(t).byteLength(); } @@ -131,16 +137,21 @@ static inline size_t MaxMemoryBytes(IndexType t) { // bounds check limit on the system. (It can be larger than MaxMemoryBytes() // because bounds check limits are rounded up to fit formal requirements on some // platforms. Also see ComputeMappedSize().) -extern size_t MaxMemoryBoundsCheckLimit(IndexType t); +extern size_t MaxMemoryBoundsCheckLimit(AddressType t); -static inline uint64_t MaxMemoryLimitField(IndexType indexType) { - return indexType == IndexType::I32 ? MaxMemory32LimitField - : MaxMemory64LimitField; +static inline uint64_t MaxMemoryPagesValidation(AddressType addressType) { + return addressType == AddressType::I32 ? MaxMemory32PagesValidation + : MaxMemory64PagesValidation; +} + +static inline uint64_t MaxTableElemsValidation(AddressType addressType) { + return addressType == AddressType::I32 ? MaxTable32ElemsValidation + : MaxTable64ElemsValidation; } // Compute the 'clamped' maximum size of a memory. See // 'WASM Linear Memory structure' in ArrayBufferObject.cpp for background. -extern Pages ClampedMaxPages(IndexType t, Pages initialPages, +extern Pages ClampedMaxPages(AddressType t, Pages initialPages, const mozilla::Maybe& sourceMaxPages, bool useHugeMemory); @@ -150,7 +161,7 @@ extern Pages ClampedMaxPages(IndexType t, Pages initialPages, // vm/ArrayBufferObject.cpp. extern size_t ComputeMappedSize(Pages clampedMaxPages); -extern size_t GetMaxOffsetGuardLimit(bool hugeMemory); +extern uint64_t GetMaxOffsetGuardLimit(bool hugeMemory); // Return whether the given immediate satisfies the constraints of the platform. extern bool IsValidBoundsCheckImmediate(uint32_t i); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.cpp new file mode 100644 index 00000000000..fa7d52a3797 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.cpp @@ -0,0 +1,335 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "wasm/WasmMetadata.h" + +#include "mozilla/BinarySearch.h" +#include "mozilla/CheckedInt.h" + +#include "jsnum.h" // Int32ToCStringBuf + +#include "vm/Logging.h" + +using mozilla::CheckedInt; + +using namespace js; +using namespace js::wasm; + +// CodeMetadata helpers -- computing the Instance layout. + +bool CodeMetadata::allocateInstanceDataBytes(uint32_t bytes, uint32_t align, + uint32_t* assignedOffset) { + // Assert that this offset hasn't already been computed. + MOZ_ASSERT(*assignedOffset == UINT32_MAX); + + CheckedInt newInstanceDataLength(instanceDataLength); + + // Adjust the current global data length so that it's aligned to `align` + newInstanceDataLength += + ComputeByteAlignment(newInstanceDataLength.value(), align); + if (!newInstanceDataLength.isValid()) { + return false; + } + + // The allocated data is given by the aligned length + *assignedOffset = newInstanceDataLength.value(); + + // Advance the length for `bytes` being allocated + newInstanceDataLength += bytes; + if (!newInstanceDataLength.isValid()) { + return false; + } + + // This is the highest offset into Instance::globalArea that will not + // overflow a signed 32-bit integer. + const uint32_t maxInstanceDataOffset = + uint32_t(INT32_MAX) - uint32_t(Instance::offsetOfData()); + + // Check that the highest offset into this allocated space would not overflow + // a signed 32-bit integer. + if (newInstanceDataLength.value() > maxInstanceDataOffset + 1) { + return false; + } + + instanceDataLength = newInstanceDataLength.value(); + return true; +} + +bool CodeMetadata::allocateInstanceDataBytesN(uint32_t bytes, uint32_t align, + uint32_t count, + uint32_t* assignedOffset) { + // The size of each allocation should be a multiple of alignment so that a + // contiguous array of allocations will be aligned + MOZ_ASSERT(bytes % align == 0); + + // Compute the total bytes being allocated + CheckedInt totalBytes = bytes; + totalBytes *= count; + if (!totalBytes.isValid()) { + return false; + } + + // Allocate the bytes + return allocateInstanceDataBytes(totalBytes.value(), align, assignedOffset); +} + +bool CodeMetadata::prepareForCompile(CompileMode mode) { + MOZ_ASSERT(!isPreparedForCompile()); + + // Find every function that is exported from this module and give it an + // implicit index + uint32_t exportedFuncCount = 0; + for (uint32_t funcIndex = 0; funcIndex < funcs.length(); funcIndex++) { + const FuncDesc& func = funcs[funcIndex]; + if (func.isExported()) { + exportedFuncCount++; + } + } + + if (!exportedFuncIndices.reserve(exportedFuncCount)) { + return false; + } + for (uint32_t funcIndex = 0; funcIndex < funcs.length(); funcIndex++) { + const FuncDesc& func = funcs[funcIndex]; + if (!func.isExported()) { + continue; + } + exportedFuncIndices.infallibleEmplaceBack(funcIndex); + } + + // Allocate the layout for instance data + instanceDataLength = 0; + + // Allocate space for function counters, if we have them + if (mode == CompileMode::LazyTiering) { + if (!allocateInstanceDataBytesN(sizeof(FuncDefInstanceData), + alignof(FuncDefInstanceData), numFuncDefs(), + &funcDefsOffsetStart)) { + return false; + } + } + + // Allocate space for type definitions + if (!allocateInstanceDataBytesN(sizeof(TypeDefInstanceData), + alignof(TypeDefInstanceData), types->length(), + &typeDefsOffsetStart)) { + return false; + } + + // Allocate space for every function import + if (!allocateInstanceDataBytesN(sizeof(FuncImportInstanceData), + alignof(FuncImportInstanceData), + numFuncImports, &funcImportsOffsetStart)) { + return false; + } + + // Allocate space for every function export + if (!allocateInstanceDataBytesN( + sizeof(FuncExportInstanceData), alignof(FuncExportInstanceData), + numExportedFuncs(), &funcExportsOffsetStart)) { + return false; + } + + // Allocate space for every memory + if (!allocateInstanceDataBytesN(sizeof(MemoryInstanceData), + alignof(MemoryInstanceData), + memories.length(), &memoriesOffsetStart)) { + return false; + } + + // Allocate space for every table + if (!allocateInstanceDataBytesN(sizeof(TableInstanceData), + alignof(TableInstanceData), tables.length(), + &tablesOffsetStart)) { + return false; + } + + // Allocate space for every tag + if (!allocateInstanceDataBytesN(sizeof(TagInstanceData), + alignof(TagInstanceData), tags.length(), + &tagsOffsetStart)) { + return false; + } + + // Allocate space for every global that requires it + for (GlobalDesc& global : globals) { + if (global.isConstant()) { + continue; + } + + uint32_t width = global.isIndirect() ? sizeof(void*) : global.type().size(); + + uint32_t assignedOffset = UINT32_MAX; + if (!allocateInstanceDataBytes(width, width, &assignedOffset)) { + return false; + } + + global.setOffset(assignedOffset); + } + + return true; +} + +uint32_t CodeMetadata::findFuncExportIndex(uint32_t funcIndex) const { + MOZ_ASSERT(funcs[funcIndex].isExported()); + + size_t match; + if (!mozilla::BinarySearch(exportedFuncIndices, 0, + exportedFuncIndices.length(), funcIndex, &match)) { + MOZ_CRASH("missing function export"); + } + return (uint32_t)match; +} + +uint32_t CodeTailMetadata::findFuncIndex(uint32_t bytecodeOffset) const { + size_t funcDefIndex; + if (!mozilla::BinarySearchIf( + funcDefRanges, 0, funcDefRanges.length(), + [bytecodeOffset](const BytecodeRange& range) { + return range.compareOffset(bytecodeOffset); + }, + &funcDefIndex)) { + MOZ_CRASH("missing function definition"); + } + return codeMeta->numFuncImports + funcDefIndex; +} + +// CodeMetadata helpers -- getting function names. + +static bool AppendName(const Bytes& namePayload, const Name& name, + UTF8Bytes* bytes) { + MOZ_RELEASE_ASSERT(name.offsetInNamePayload <= namePayload.length()); + MOZ_RELEASE_ASSERT(name.length <= + namePayload.length() - name.offsetInNamePayload); + return bytes->append( + (const char*)namePayload.begin() + name.offsetInNamePayload, name.length); +} + +static bool AppendFunctionIndexName(uint32_t funcIndex, UTF8Bytes* bytes) { + const char beforeFuncIndex[] = "wasm-function["; + const char afterFuncIndex[] = "]"; + + Int32ToCStringBuf cbuf; + size_t funcIndexStrLen; + const char* funcIndexStr = + Uint32ToCString(&cbuf, funcIndex, &funcIndexStrLen); + MOZ_ASSERT(funcIndexStr); + + return bytes->append(beforeFuncIndex, strlen(beforeFuncIndex)) && + bytes->append(funcIndexStr, funcIndexStrLen) && + bytes->append(afterFuncIndex, strlen(afterFuncIndex)); +} + +bool CodeMetadata::getFuncNameForWasm(NameContext ctx, uint32_t funcIndex, + const ShareableBytes* nameSectionPayload, + UTF8Bytes* name) const { + if (nameSection && nameSection->moduleName.length != 0) { + if (!AppendName(nameSectionPayload->vector, nameSection->moduleName, + name)) { + return false; + } + if (!name->append('.')) { + return false; + } + } + + if (nameSection && funcIndex < nameSection->funcNames.length() && + nameSection->funcNames[funcIndex].length != 0) { + return AppendName(nameSectionPayload->vector, + nameSection->funcNames[funcIndex], name); + } + + if (ctx == NameContext::BeforeLocation) { + return true; + } + + return AppendFunctionIndexName(funcIndex, name); +} + +// CodeMetadata helpers -- memory accounting. + +size_t CodeMetadata::sizeOfExcludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + return memories.sizeOfExcludingThis(mallocSizeOf) + + types->sizeOfExcludingThis(mallocSizeOf) + + globals.sizeOfExcludingThis(mallocSizeOf) + + tags.sizeOfExcludingThis(mallocSizeOf) + + tables.sizeOfExcludingThis(mallocSizeOf) + + SizeOfMaybeExcludingThis(nameSection, mallocSizeOf) + + funcs.sizeOfExcludingThis(mallocSizeOf) + + elemSegmentTypes.sizeOfExcludingThis(mallocSizeOf) + + asmJSSigToTableIndex.sizeOfExcludingThis(mallocSizeOf) + + customSectionRanges.sizeOfExcludingThis(mallocSizeOf); +} + +CodeTailMetadata::CodeTailMetadata() + : codeMeta(nullptr), + debugEnabled(false), + debugHash(), + inliningBudget(mutexid::WasmInliningBudget, 0), + callRefHints(nullptr), + numCallRefMetrics(UINT32_MAX), + numAllocSites(UINT32_MAX) {} + +CodeTailMetadata::CodeTailMetadata(const CodeMetadata& codeMeta) + : js::wasm::CodeTailMetadata() { + this->codeMeta = &codeMeta; + inliningBudget.lock().get() = + InliningHeuristics::moduleInliningBudget(codeMeta.codeSectionSize()); +} + +// ModuleMetadata helpers -- memory accounting. + +size_t ModuleMetadata::sizeOfExcludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + return imports.sizeOfExcludingThis(mallocSizeOf) + + exports.sizeOfExcludingThis(mallocSizeOf) + + elemSegments.sizeOfExcludingThis(mallocSizeOf) + + dataSegmentRanges.sizeOfExcludingThis(mallocSizeOf) + + dataSegments.sizeOfExcludingThis(mallocSizeOf) + + customSections.sizeOfExcludingThis(mallocSizeOf); +} + +bool ModuleMetadata::addDefinedFunc( + ValTypeVector&& params, ValTypeVector&& results, bool declareForRef, + mozilla::Maybe&& optionalExportedName) { + uint32_t typeIndex = codeMeta->types->length(); + FuncType funcType(std::move(params), std::move(results)); + if (!codeMeta->types->addType(std::move(funcType))) { + return false; + } + + FuncDesc funcDesc = FuncDesc(typeIndex); + uint32_t funcIndex = codeMeta->funcs.length(); + if (!codeMeta->funcs.append(funcDesc)) { + return false; + } + if (declareForRef) { + codeMeta->funcs[funcIndex].declareFuncExported(true, true); + } + if (optionalExportedName.isSome()) { + if (!exports.emplaceBack(std::move(optionalExportedName.ref()), funcIndex, + DefinitionKind::Function)) { + return false; + } + } + return true; +} + +bool ModuleMetadata::addImportedFunc(ValTypeVector&& params, + ValTypeVector&& results, + CacheableName&& importModName, + CacheableName&& importFieldName) { + MOZ_ASSERT(codeMeta->numFuncImports == codeMeta->funcs.length()); + if (!addDefinedFunc(std::move(params), std::move(results), false, + mozilla::Nothing())) { + return false; + } + codeMeta->numFuncImports++; + return imports.emplaceBack(std::move(importModName), + std::move(importFieldName), + DefinitionKind::Function); +} diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.h b/src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.h new file mode 100644 index 00000000000..33aea8e0350 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmMetadata.h @@ -0,0 +1,494 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef wasm_WasmMetadata_h +#define wasm_WasmMetadata_h + +#include "mozilla/Atomics.h" + +#include "wasm/WasmBinaryTypes.h" +#include "wasm/WasmHeuristics.h" +#include "wasm/WasmInstanceData.h" // various of *InstanceData +#include "wasm/WasmModuleTypes.h" +#include "wasm/WasmProcess.h" // IsHugeMemoryEnabled + +namespace js { +namespace wasm { + +using BuiltinModuleFuncIdVector = + Vector; + +// ==== Printing of names +// +// The Developer-Facing Display Conventions section of the WebAssembly Web +// API spec defines two cases for displaying a wasm function name: +// 1. the function name stands alone +// 2. the function name precedes the location + +enum class NameContext { Standalone, BeforeLocation }; + +// wasm::CodeMetadata contains metadata whose lifetime ends at the same time +// that the lifetime of wasm::Code ends. This encompasses a wide variety of +// uses. In practice that means metadata needed for any and all aspects of +// compilation or execution of wasm code. Hence this metadata conceptually +// belongs to, and is kept alive by, wasm::Code. Note also that wasm::Code is +// in turn kept alive by wasm::Instance(s), hence this metadata will be kept +// alive as long as any instance for it exists. + +using ModuleHash = uint8_t[8]; + +struct CodeMetadata : public ShareableBase { + // NOTE: if you add, remove, rename or reorder fields here, be sure to + // update CodeCodeMetadata() to keep it in sync. + + // Constant parameters for the entire compilation. These are not marked + // `const` only because it breaks constructor delegation in + // CodeMetadata::CodeMetadata, which is a shame. + ModuleKind kind; + + // The compile arguments that were used for this module. + SharedCompileArgs compileArgs; + + // The number of imported functions in the module. + uint32_t numFuncImports; + // A vector of the builtin func id (or 'none') for all imported functions. + // This may be empty for internally constructed modules which don't care + // about this information. + BuiltinModuleFuncIdVector knownFuncImports; + // Treat imported wasm functions as if they were JS functions. This is used + // when compiling the module for new WebAssembly.Function. + bool funcImportsAreJS; + // The number of imported globals in the module. + uint32_t numGlobalImports; + + // Info about all types in the module. + MutableTypeContext types; + // Info about all functions in the module. + FuncDescVector funcs; + // Info about all tables in the module. + TableDescVector tables; + // Info about all memories in the module. + MemoryDescVector memories; + // Info about all tags in the module. + TagDescVector tags; + // Info about all globals in the module. + GlobalDescVector globals; + + // The start function for the module, if any + mozilla::Maybe startFuncIndex; + + // Info about elem segments needed only for validation and compilation. + // Should have the same length as ModuleMetadata::elemSegments, and each + // entry here should be identical the corresponding .elemType field in + // ModuleMetadata::elemSegments. + RefTypeVector elemSegmentTypes; + + // The number of data segments this module will have. Pre-declared before the + // code section so that we can validate instructions that reference data + // segments. + mozilla::Maybe dataCount; + + // A sorted vector of the index of every function that is exported from this + // module. An index into this vector is a 'exported function index' and can + // be used to lookup exported functions on an instance. + Uint32Vector exportedFuncIndices; + + // asm.js tables are homogenous and only store functions of the same type. + // This maps from a function type to the table index to use for an indirect + // call. + Uint32Vector asmJSSigToTableIndex; + + // Branch hints to apply to functions + BranchHintCollection branchHints; + + // Name section information + mozilla::Maybe nameSection; + + // Bytecode ranges for custom sections. + CustomSectionRangeVector customSectionRanges; + + // Bytecode range for the code section. + MaybeBytecodeRange codeSectionRange; + + // ==== Instance layout fields + // + // The start offset of the FuncDefInstanceData[] section of the instance + // data. There is one entry for every function definition. + uint32_t funcDefsOffsetStart; + // The start offset of the FuncImportInstanceData[] section of the instance + // data. There is one entry for every imported function. + uint32_t funcImportsOffsetStart; + // The start offset of the FuncExportInstanceData[] section of the instance + // data. There is one entry for every exported function. + uint32_t funcExportsOffsetStart; + // The start offset of the TypeDefInstanceData[] section of the instance + // data. There is one entry for every type. + uint32_t typeDefsOffsetStart; + // The start offset of the MemoryInstanceData[] section of the instance data. + // There is one entry for every memory. + uint32_t memoriesOffsetStart; + // The start offset of the TableInstanceData[] section of the instance data. + // There is one entry for every table. + uint32_t tablesOffsetStart; + // The start offset of the tag section of the instance data. There is one + // entry for every tag. + uint32_t tagsOffsetStart; + // The total size of the instance data. + uint32_t instanceDataLength; + + explicit CodeMetadata(const CompileArgs* compileArgs = nullptr, + ModuleKind kind = ModuleKind::Wasm) + : kind(kind), + compileArgs(compileArgs), + numFuncImports(0), + funcImportsAreJS(false), + numGlobalImports(0), + funcDefsOffsetStart(UINT32_MAX), + funcImportsOffsetStart(UINT32_MAX), + funcExportsOffsetStart(UINT32_MAX), + typeDefsOffsetStart(UINT32_MAX), + memoriesOffsetStart(UINT32_MAX), + tablesOffsetStart(UINT32_MAX), + tagsOffsetStart(UINT32_MAX), + instanceDataLength(UINT32_MAX) {} + + [[nodiscard]] bool init() { + MOZ_ASSERT(!types); + types = js_new(); + return types; + } + + // Generates any new metadata necessary to compile this module. This must be + // called after the 'module environment' (everything before the code section) + // has been decoded. + [[nodiscard]] bool prepareForCompile(CompileMode mode); + bool isPreparedForCompile() const { return instanceDataLength != UINT32_MAX; } + + bool isAsmJS() const { return kind == ModuleKind::AsmJS; } + // A builtin module is a host constructed wasm module that exports host + // functionality, using special opcodes. Otherwise, it has the same rules + // as wasm modules and so it does not get a new ModuleKind. + bool isBuiltinModule() const { return features().isBuiltinModule; } + +#define WASM_FEATURE(NAME, SHORT_NAME, ...) \ + bool SHORT_NAME##Enabled() const { return features().SHORT_NAME; } + JS_FOR_WASM_FEATURES(WASM_FEATURE) +#undef WASM_FEATURE + Shareable sharedMemoryEnabled() const { return features().sharedMemory; } + bool simdAvailable() const { return features().simd; } + + bool hugeMemoryEnabled(uint32_t memoryIndex) const { + return !isAsmJS() && memoryIndex < memories.length() && + IsHugeMemoryEnabled(memories[memoryIndex].addressType()); + } + bool usesSharedMemory(uint32_t memoryIndex) const { + return memoryIndex < memories.length() && memories[memoryIndex].isShared(); + } + + const FeatureArgs& features() const { return compileArgs->features; } + const ScriptedCaller& scriptedCaller() const { + return compileArgs->scriptedCaller; + } + const UniqueChars& sourceMapURL() const { return compileArgs->sourceMapURL; } + + size_t numTypes() const { return types->length(); } + size_t numFuncs() const { return funcs.length(); } + size_t numFuncDefs() const { return funcs.length() - numFuncImports; } + size_t numTables() const { return tables.length(); } + size_t numMemories() const { return memories.length(); } + + bool funcIsImport(uint32_t funcIndex) const { + return funcIndex < numFuncImports; + } + const TypeDef& getFuncTypeDef(uint32_t funcIndex) const { + return types->type(funcs[funcIndex].typeIndex); + } + const FuncType& getFuncType(uint32_t funcIndex) const { + return getFuncTypeDef(funcIndex).funcType(); + } + + BuiltinModuleFuncId knownFuncImport(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex < numFuncImports); + if (knownFuncImports.empty()) { + return BuiltinModuleFuncId::None; + } + return knownFuncImports[funcIndex]; + } + + // Find the exported function index for a function index + uint32_t findFuncExportIndex(uint32_t funcIndex) const; + + // The number of functions that are exported in this module + uint32_t numExportedFuncs() const { return exportedFuncIndices.length(); } + + size_t codeSectionSize() const { + if (codeSectionRange) { + return codeSectionRange->size(); + } + return 0; + } + + // This gets names for wasm only. + // For asm.js, see CodeMetadataForAsmJS::getFuncNameForAsmJS. + bool getFuncNameForWasm(NameContext ctx, uint32_t funcIndex, + const ShareableBytes* nameSectionPayload, + UTF8Bytes* name) const; + + uint32_t offsetOfFuncDefInstanceData(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex >= numFuncImports && funcIndex < numFuncs()); + return funcDefsOffsetStart + + (funcIndex - numFuncImports) * sizeof(FuncDefInstanceData); + } + + uint32_t offsetOfFuncImportInstanceData(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex < numFuncImports); + return funcImportsOffsetStart + funcIndex * sizeof(FuncImportInstanceData); + } + + uint32_t offsetOfFuncExportInstanceData(uint32_t funcExportIndex) const { + MOZ_ASSERT(funcExportIndex < exportedFuncIndices.length()); + return funcExportsOffsetStart + + funcExportIndex * sizeof(FuncExportInstanceData); + } + + uint32_t offsetOfTypeDefInstanceData(uint32_t typeIndex) const { + MOZ_ASSERT(typeIndex < types->length()); + return typeDefsOffsetStart + typeIndex * sizeof(TypeDefInstanceData); + } + + uint32_t offsetOfTypeDef(uint32_t typeIndex) const { + return offsetOfTypeDefInstanceData(typeIndex) + + offsetof(TypeDefInstanceData, typeDef); + } + uint32_t offsetOfSuperTypeVector(uint32_t typeIndex) const { + return offsetOfTypeDefInstanceData(typeIndex) + + offsetof(TypeDefInstanceData, superTypeVector); + } + + uint32_t offsetOfMemoryInstanceData(uint32_t memoryIndex) const { + MOZ_ASSERT(memoryIndex < memories.length()); + return memoriesOffsetStart + memoryIndex * sizeof(MemoryInstanceData); + } + uint32_t offsetOfTableInstanceData(uint32_t tableIndex) const { + MOZ_ASSERT(tableIndex < tables.length()); + return tablesOffsetStart + tableIndex * sizeof(TableInstanceData); + } + + uint32_t offsetOfTagInstanceData(uint32_t tagIndex) const { + MOZ_ASSERT(tagIndex < tags.length()); + return tagsOffsetStart + tagIndex * sizeof(TagInstanceData); + } + + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + + private: + // Allocate space for `bytes`@`align` in the instance, updating + // `instanceDataLength` and returning the offset in in `assignedOffset`. + [[nodiscard]] bool allocateInstanceDataBytes(uint32_t bytes, uint32_t align, + uint32_t* assignedOffset); + // The same for an array of allocations. + [[nodiscard]] bool allocateInstanceDataBytesN(uint32_t bytes, uint32_t align, + uint32_t count, + uint32_t* assignedOffset); +}; + +using MutableCodeMetadata = RefPtr; +using SharedCodeMetadata = RefPtr; + +using InliningBudget = ExclusiveData; + +// wasm::CodeTailMetadata contains all metadata needed by wasm::Code that is +// only after the whole module has been downloaded. It is sometimes available +// for Ion compilation, and never available for baseline compilation. +struct CodeTailMetadata : public ShareableBase { + // Default initializer only used for serialization. + CodeTailMetadata(); + + // Initialize the metadata with a given wasm::CodeMetadata. + explicit CodeTailMetadata(const CodeMetadata& codeMeta); + + // The code metadata for this module. + SharedCodeMetadata codeMeta; + + // The bytes for the code section. + SharedBytes codeSectionBytecode; + + // Whether this module was compiled with debugging support. + bool debugEnabled; + + // A SHA-1 hash of the module bytecode for use in display urls. Only + // available if we're debugging. + ModuleHash debugHash; + + // The full bytecode for this module. Only available for debuggable modules. + BytecodeBuffer debugBytecode; + + // Shared and mutable inlining budget for this module. + mutable InliningBudget inliningBudget; + + // The ranges of every function defined in this module. + BytecodeRangeVector funcDefRanges; + + // The feature usage for every function defined in this module. + FeatureUsageVector funcDefFeatureUsages; + + // Tracks the range of CallRefMetrics created for each function definition in + // this module. + CallRefMetricsRangeVector funcDefCallRefs; + + // Tracks the range of AllocSites created for each function definition in + // this module. If we are compiling with a 'once' compilation and using just + // ion, this will be empty and ion will instead use per-typedef alloc sites. + AllocSitesRangeVector funcDefAllocSites; + + // An array of hints to use when compiling a call_ref. + // + // This is written into when an instance requests a function to be tiered up, + // and read from our function compilers. + MutableCallRefHints callRefHints; + + // nameSectionPayload points at the name section's CustomSection::payload so + // that the Names (which are use payload-relative offsets) can be used + // independently of the Module without duplicating the name section. + SharedBytes nameSectionPayload; + + // The number of call ref metrics in Instance::callRefs_ + uint32_t numCallRefMetrics; + + // The number of AllocSites in Instance::allocSites_. + uint32_t numAllocSites; + + // Given a bytecode offset inside a function definition, find the function + // index. + uint32_t findFuncIndex(uint32_t bytecodeOffset) const; + uint32_t funcBytecodeOffset(uint32_t funcIndex) const { + if (funcIndex < codeMeta->numFuncImports) { + return 0; + } + uint32_t funcDefIndex = funcIndex - codeMeta->numFuncImports; + return funcDefRanges[funcDefIndex].start; + } + const BytecodeRange& funcDefRange(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex >= codeMeta->numFuncImports); + uint32_t funcDefIndex = funcIndex - codeMeta->numFuncImports; + return funcDefRanges[funcDefIndex]; + } + BytecodeSpan funcDefBody(uint32_t funcIndex) const { + return funcDefRange(funcIndex) + .relativeTo(*codeMeta->codeSectionRange) + .toSpan(*codeSectionBytecode); + } + FeatureUsage funcDefFeatureUsage(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex >= codeMeta->numFuncImports); + uint32_t funcDefIndex = funcIndex - codeMeta->numFuncImports; + return funcDefFeatureUsages[funcDefIndex]; + } + + CallRefMetricsRange getFuncDefCallRefs(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex >= codeMeta->numFuncImports); + uint32_t funcDefIndex = funcIndex - codeMeta->numFuncImports; + return funcDefCallRefs[funcDefIndex]; + } + + AllocSitesRange getFuncDefAllocSites(uint32_t funcIndex) const { + MOZ_ASSERT(funcIndex >= codeMeta->numFuncImports); + uint32_t funcDefIndex = funcIndex - codeMeta->numFuncImports; + return funcDefAllocSites[funcDefIndex]; + } + + bool hasFuncDefAllocSites() const { return !funcDefAllocSites.empty(); } + + CallRefHint getCallRefHint(uint32_t callRefIndex) const { + if (!callRefHints) { + return CallRefHint(); + } + return CallRefHint::fromRepr(callRefHints[callRefIndex]); + } + void setCallRefHint(uint32_t callRefIndex, CallRefHint hint) const { + callRefHints[callRefIndex] = hint.toRepr(); + } +}; + +using MutableCodeTailMetadata = RefPtr; +using SharedCodeTailMetadata = RefPtr; + +// wasm::ModuleMetadata contains metadata whose lifetime ends at the same time +// that the lifetime of wasm::Module ends. In practice that means metadata +// that is needed only for creating wasm::Instances. Hence this metadata +// conceptually belongs to, and is held alive by, wasm::Module. + +struct ModuleMetadata : public ShareableBase { + // NOTE: if you add, remove, rename or reorder fields here, be sure to + // update CodeModuleMetadata() to keep it in sync. + + // The subset of module metadata that is shared between a module and + // instance (i.e. wasm::Code), and is available for all compilation. It + // does not contain any data that is only available after the whole module + // has been downloaded. + MutableCodeMetadata codeMeta; + + // The subset of module metadata that is shared between a module and + // instance (i.e. wasm::Code), and is only available after the whole module + // has been downloaded. + MutableCodeTailMetadata codeTailMeta; + + // Module fields decoded from the module environment (or initialized while + // validating an asm.js module) and immutable during compilation: + ImportVector imports; + ExportVector exports; + + // Info about elem segments needed for instantiation. Should have the same + // length as CodeMetadata::elemSegmentTypes. + ModuleElemSegmentVector elemSegments; + + // Info about data segments needed for instantiation. These wind up having + // the same length. Initially both are empty. `dataSegmentRanges` is + // filled in during validation, and `dataSegments` remains empty. Later, at + // module-generation time, `dataSegments` is filled in, by copying the + // underlying data blocks, and so the two vectors have the same length after + // that. + DataSegmentRangeVector dataSegmentRanges; + DataSegmentVector dataSegments; + + CustomSectionVector customSections; + + // Which features were observed when compiling this module. + FeatureUsage featureUsage = FeatureUsage::None; + + explicit ModuleMetadata() = default; + + [[nodiscard]] bool init(const CompileArgs& compileArgs, + ModuleKind kind = ModuleKind::Wasm) { + codeMeta = js_new(&compileArgs, kind); + return !!codeMeta && codeMeta->init(); + } + + bool addDefinedFunc(ValTypeVector&& params, ValTypeVector&& results, + bool declareForRef = false, + mozilla::Maybe&& optionalExportedName = + mozilla::Nothing()); + bool addImportedFunc(ValTypeVector&& params, ValTypeVector&& results, + CacheableName&& importModName, + CacheableName&& importFieldName); + + // Generates any new metadata necessary to compile this module. This must be + // called after the 'module environment' (everything before the code section) + // has been decoded. + [[nodiscard]] bool prepareForCompile(CompileMode mode) { + return codeMeta->prepareForCompile(mode); + } + bool isPreparedForCompile() const { return codeMeta->isPreparedForCompile(); } + + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; +}; + +using MutableModuleMetadata = RefPtr; +using SharedModuleMetadata = RefPtr; + +} // namespace wasm +} // namespace js + +#endif /* wasm_WasmMetadata_h */ diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmModule.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmModule.cpp index 3609eeaf6e1..470e00af4d0 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmModule.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmModule.cpp @@ -20,8 +20,7 @@ #include -#include "jit/FlushICache.h" // for FlushExecutionContextForAllThreads -#include "js/BuildId.h" // JS::BuildIdCharVector +#include "js/BuildId.h" // JS::BuildIdCharVector #include "js/experimental/TypedData.h" // JS_NewUint8Array #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/Printf.h" // JS_smprintf @@ -29,8 +28,10 @@ #include "js/StreamConsumer.h" #include "threading/LockGuard.h" #include "threading/Thread.h" +#include "util/DifferentialTesting.h" #include "vm/HelperThreadState.h" // Tier2GeneratorTask #include "vm/PlainObject.h" // js::PlainObject +#include "vm/Warnings.h" // WarnNumberASCII #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmCompile.h" #include "wasm/WasmDebug.h" @@ -58,26 +59,36 @@ static UniqueChars Tier2ResultsContext(const ScriptedCaller& scriptedCaller) { : UniqueChars(); } -static void ReportTier2ResultsOffThread(bool success, - const ScriptedCaller& scriptedCaller, - const UniqueChars& error, - const UniqueCharsVector& warnings) { +void js::wasm::ReportTier2ResultsOffThread(bool cancelled, bool success, + Maybe maybeFuncIndex, + const ScriptedCaller& scriptedCaller, + const UniqueChars& error, + const UniqueCharsVector& warnings) { // Get context to describe this tier-2 task. UniqueChars context = Tier2ResultsContext(scriptedCaller); const char* contextString = context ? context.get() : "unknown"; // Display the main error, if any. - if (!success) { - const char* errorString = error ? error.get() : "out of memory"; - LogOffThread("'%s': wasm tier-2 failed with '%s'.\n", contextString, - errorString); + if (!success || cancelled) { + const char* errorString = error ? error.get() + : cancelled ? "compilation cancelled" + : "out of memory"; + if (maybeFuncIndex.isSome()) { + LogOffThread( + "'%s': wasm partial tier-2 (func index %u) failed with '%s'.\n", + contextString, maybeFuncIndex.value(), errorString); + } else { + LogOffThread("'%s': wasm complete tier-2 failed with '%s'.\n", + contextString, errorString); + } } // Display warnings as a follow-up, avoiding spamming the console. size_t numWarnings = std::min(warnings.length(), 3); for (size_t i = 0; i < numWarnings; i++) { - LogOffThread("'%s': wasm tier-2 warning: '%s'.\n'.", contextString, + // Per the assertion above, we won't get warnings for partial tier-2. + LogOffThread("'%s': wasm complete tier-2 warning: '%s'.\n'.", contextString, warnings[i].get()); } if (warnings.length() > numWarnings) { @@ -85,22 +96,19 @@ static void ReportTier2ResultsOffThread(bool success, } } -class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask { - SharedCompileArgs compileArgs_; - SharedBytes bytecode_; +class Module::CompleteTier2GeneratorTaskImpl + : public CompleteTier2GeneratorTask { + SharedBytes codeSection_; SharedModule module_; - Atomic cancelled_; + mozilla::Atomic cancelled_; public: - Tier2GeneratorTaskImpl(const CompileArgs& compileArgs, - const ShareableBytes& bytecode, Module& module) - : compileArgs_(&compileArgs), - bytecode_(&bytecode), - module_(&module), - cancelled_(false) {} + CompleteTier2GeneratorTaskImpl(const ShareableBytes* codeSection, + Module& module) + : codeSection_(codeSection), module_(&module), cancelled_(false) {} - ~Tier2GeneratorTaskImpl() override { - module_->tier2Listener_ = nullptr; + ~CompleteTier2GeneratorTaskImpl() override { + module_->completeTier2Listener_ = nullptr; module_->testingTier2Active_ = false; } @@ -110,156 +118,83 @@ class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask { { AutoUnlockHelperThreadState unlock(locked); - // Compile tier-2 and report any warning/errors as long as it's not a - // cancellation. Encountering a warning/error during compilation and - // being cancelled may race with each other, but the only observable race - // should be being cancelled after a warning/error is set, and that's - // okay. + // Compile complete tier-2 and report any warning/errors as long as it's + // not a cancellation. Encountering a warning/error during compilation + // and being cancelled may race with each other, but the only observable + // race should be being cancelled after a warning/error is set, and + // that's okay. UniqueChars error; UniqueCharsVector warnings; - bool success = CompileTier2(*compileArgs_, bytecode_->bytes, *module_, - &error, &warnings, &cancelled_); + bool success = CompileCompleteTier2(codeSection_, *module_, &error, + &warnings, &cancelled_); if (!cancelled_) { // We could try to dispatch a runnable to the thread that started this // compilation, so as to report the warning/error using a JSContext*. // For now we just report to stderr. - ReportTier2ResultsOffThread(success, compileArgs_->scriptedCaller, - error, warnings); + ReportTier2ResultsOffThread(cancelled_, success, mozilla::Nothing(), + module_->codeMeta().scriptedCaller(), error, + warnings); } } // During shutdown the main thread will wait for any ongoing (cancelled) - // tier-2 generation to shut down normally. To do so, it waits on the - // HelperThreadState's condition variable for the count of finished + // complete tier-2 generation to shut down normally. To do so, it waits on + // the HelperThreadState's condition variable for the count of finished // generators to rise. - HelperThreadState().incWasmTier2GeneratorsFinished(locked); + HelperThreadState().incWasmCompleteTier2GeneratorsFinished(locked); // The task is finished, release it. js_delete(this); } ThreadType threadType() override { - return ThreadType::THREAD_TYPE_WASM_GENERATOR_TIER2; + return ThreadType::THREAD_TYPE_WASM_GENERATOR_COMPLETE_TIER2; } }; Module::~Module() { // Note: Modules can be destroyed on any thread. - MOZ_ASSERT(!tier2Listener_); + MOZ_ASSERT(!completeTier2Listener_); MOZ_ASSERT(!testingTier2Active_); } -void Module::startTier2(const CompileArgs& args, const ShareableBytes& bytecode, +void Module::startTier2(const ShareableBytes* codeSection, JS::OptimizedEncodingListener* listener) { MOZ_ASSERT(!testingTier2Active_); + MOZ_ASSERT_IF(codeMeta().codeSectionRange.isSome(), codeSection); - auto task = MakeUnique(args, bytecode, *this); + auto task = MakeUnique(codeSection, *this); if (!task) { return; } - // These will be cleared asynchronously by ~Tier2GeneratorTaskImpl() if not - // sooner by finishTier2(). - tier2Listener_ = listener; + // These will be cleared asynchronously by ~CompleteTier2GeneratorTaskImpl() + // if not sooner by finishTier2(). + completeTier2Listener_ = listener; testingTier2Active_ = true; - StartOffThreadWasmTier2Generator(std::move(task)); + StartOffThreadWasmCompleteTier2Generator(std::move(task)); } -bool Module::finishTier2(const LinkData& linkData2, - UniqueCodeTier code2) const { - MOZ_ASSERT(code().bestTier() == Tier::Baseline && - code2->tier() == Tier::Optimized); - - // Install the data in the data structures. They will not be visible - // until commitTier2(). - - const CodeTier* borrowedTier2; - if (!code().setAndBorrowTier2(std::move(code2), linkData2, &borrowedTier2)) { +bool Module::finishTier2(UniqueCodeBlock tier2CodeBlock, + UniqueLinkData tier2LinkData, + const CompileAndLinkStats& tier2Stats) const { + if (!code_->finishTier2(std::move(tier2CodeBlock), std::move(tier2LinkData), + tier2Stats)) { return false; } - // Before we can make tier-2 live, we need to compile tier2 versions of any - // extant tier1 lazy stubs (otherwise, tiering would break the assumption - // that any extant exported wasm function has had a lazy entry stub already - // compiled for it). - // - // Also see doc block for stubs in WasmJS.cpp. - { - // We need to prevent new tier1 stubs generation until we've committed - // the newer tier2 stubs, otherwise we might not generate one tier2 - // stub that has been generated for tier1 before we committed. - - const MetadataTier& metadataTier1 = metadata(Tier::Baseline); - - auto stubs1 = code().codeTier(Tier::Baseline).lazyStubs().readLock(); - auto stubs2 = borrowedTier2->lazyStubs().writeLock(); - - MOZ_ASSERT(stubs2->entryStubsEmpty()); - - Uint32Vector funcExportIndices; - for (size_t i = 0; i < metadataTier1.funcExports.length(); i++) { - const FuncExport& fe = metadataTier1.funcExports[i]; - if (fe.hasEagerStubs()) { - continue; - } - if (!stubs1->hasEntryStub(fe.funcIndex())) { - continue; - } - if (!funcExportIndices.emplaceBack(i)) { - return false; - } - } - - Maybe stub2Index; - if (!stubs2->createTier2(funcExportIndices, metadata(), *borrowedTier2, - &stub2Index)) { - return false; - } - - // Initializing the code above will have flushed the icache for all cores. - // However, there could still be stale data in the execution pipeline of - // other cores on some platforms. Force an execution context flush on all - // threads to fix this before we commit the code. - // - // This is safe due to the check in `PlatformCanTier` in WasmCompile.cpp - jit::FlushExecutionContextForAllThreads(); - - // Now that we can't fail or otherwise abort tier2, make it live. - - MOZ_ASSERT(!code().hasTier2()); - code().commitTier2(); - - stubs2->setJitEntries(stub2Index, code()); - } - - // And we update the jump vectors with pointers to tier-2 functions and eager - // stubs. Callers will continue to invoke tier-1 code until, suddenly, they - // will invoke tier-2 code. This is benign. - - uint8_t* base = code().segment(Tier::Optimized).base(); - for (const CodeRange& cr : metadata(Tier::Optimized).codeRanges) { - // These are racy writes that we just want to be visible, atomically, - // eventually. All hardware we care about will do this right. But - // we depend on the compiler not splitting the stores hidden inside the - // set*Entry functions. - if (cr.isFunction()) { - code().setTieringEntry(cr.funcIndex(), base + cr.funcTierEntry()); - } else if (cr.isJitEntry()) { - code().setJitEntry(cr.funcIndex(), base + cr.begin()); - } - } - // Tier-2 is done; let everyone know. Mark tier-2 active for testing // purposes so that wasmHasTier2CompilationCompleted() only returns true // after tier-2 has been fully cached. - if (tier2Listener_) { + if (completeTier2Listener_ && canSerialize()) { Bytes bytes; - if (serialize(linkData2, &bytes)) { - tier2Listener_->storeOptimizedEncoding(bytes.begin(), bytes.length()); + if (serialize(&bytes)) { + completeTier2Listener_->storeOptimizedEncoding(bytes.begin(), + bytes.length()); } - tier2Listener_ = nullptr; + completeTier2Listener_ = nullptr; } testingTier2Active_ = false; @@ -278,7 +213,16 @@ JSObject* Module::createObject(JSContext* cx) const { return nullptr; } - if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr)) { + JS::RootedVector parameterStrings(cx); + JS::RootedVector parameterArgs(cx); + bool canCompileStrings = false; + if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::WASM, nullptr, + JS::CompilationType::Undefined, + parameterStrings, nullptr, parameterArgs, + NullHandleValue, &canCompileStrings)) { + return nullptr; + } + if (!canCompileStrings) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_WASM, "WebAssembly.Module"); return nullptr; @@ -319,27 +263,23 @@ bool wasm::GetOptimizedEncodingBuildId(JS::BuildIdCharVector* buildId) { buildId->infallibleAppend(')'); buildId->infallibleAppend('m'); - buildId->infallibleAppend(wasm::IsHugeMemoryEnabled(IndexType::I32) ? '+' - : '-'); - buildId->infallibleAppend(wasm::IsHugeMemoryEnabled(IndexType::I64) ? '+' - : '-'); + buildId->infallibleAppend(wasm::IsHugeMemoryEnabled(AddressType::I32) ? '+' + : '-'); + buildId->infallibleAppend(wasm::IsHugeMemoryEnabled(AddressType::I64) ? '+' + : '-'); return true; } /* virtual */ -void Module::addSizeOfMisc(MallocSizeOf mallocSizeOf, - Metadata::SeenSet* seenMetadata, +void Module::addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, + CodeMetadata::SeenSet* seenCodeMeta, + CodeMetadataForAsmJS::SeenSet* seenCodeMetaForAsmJS, Code::SeenSet* seenCode, size_t* code, size_t* data) const { - code_->addSizeOfMiscIfNotSeen(mallocSizeOf, seenMetadata, seenCode, code, - data); - *data += mallocSizeOf(this) + - SizeOfVectorExcludingThis(imports_, mallocSizeOf) + - SizeOfVectorExcludingThis(exports_, mallocSizeOf) + - SizeOfVectorExcludingThis(dataSegments_, mallocSizeOf) + - SizeOfVectorExcludingThis(elemSegments_, mallocSizeOf) + - SizeOfVectorExcludingThis(customSections_, mallocSizeOf); + code_->addSizeOfMiscIfNotSeen(mallocSizeOf, seenCodeMeta, + seenCodeMetaForAsmJS, seenCode, code, data); + *data += mallocSizeOf(this); } // Extracting machine code as JS object. The result has the "code" property, as @@ -357,21 +297,22 @@ bool Module::extractCode(JSContext* cx, Tier tier, // block on tiered compilation to complete. testingBlockOnTier2Complete(); - if (!code_->hasTier(tier)) { + if (!code_->hasCompleteTier(tier)) { vp.setNull(); return true; } - const ModuleSegment& moduleSegment = code_->segment(tier); - RootedObject code(cx, JS_NewUint8Array(cx, moduleSegment.length())); - if (!code) { + const CodeBlock& codeBlock = code_->completeTierCodeBlock(tier); + const CodeSegment& codeSegment = *codeBlock.segment; + RootedObject codeObj(cx, JS_NewUint8Array(cx, codeSegment.lengthBytes())); + if (!codeObj) { return false; } - memcpy(code->as().dataPointerUnshared(), - moduleSegment.base(), moduleSegment.length()); + memcpy(codeObj->as().dataPointerUnshared(), + codeSegment.base(), codeSegment.lengthBytes()); - RootedValue value(cx, ObjectValue(*code)); + RootedValue value(cx, ObjectValue(*codeObj)); if (!JS_DefineProperty(cx, result, "code", value, JSPROP_ENUMERATE)) { return false; } @@ -381,7 +322,7 @@ bool Module::extractCode(JSContext* cx, Tier tier, return false; } - for (const CodeRange& p : metadata(tier).codeRanges) { + for (const CodeRange& p : codeBlock.codeRanges) { RootedObject segment(cx, NewPlainObjectWithProto(cx, nullptr)); if (!segment) { return false; @@ -453,38 +394,28 @@ static const Import& FindImportFunction(const ImportVector& imports, bool Module::instantiateFunctions(JSContext* cx, const JSObjectVector& funcImports) const { #ifdef DEBUG - for (auto t : code().tiers()) { - MOZ_ASSERT(funcImports.length() == metadata(t).funcImports.length()); - } + MOZ_ASSERT(funcImports.length() == code().funcImports().length()); #endif - if (metadata().isAsmJS()) { + if (codeMeta().isAsmJS()) { return true; } - Tier tier = code().stableTier(); - - for (size_t i = 0; i < metadata(tier).funcImports.length(); i++) { + for (size_t i = 0; i < code().funcImports().length(); i++) { if (!funcImports[i]->is()) { continue; } JSFunction* f = &funcImports[i]->as(); - if (!IsWasmExportedFunction(f)) { + if (!f->isWasm() || codeMeta().funcImportsAreJS) { continue; } - uint32_t funcIndex = ExportedFunctionToFuncIndex(f); - Instance& instance = ExportedFunctionToInstance(f); - Tier otherTier = instance.code().stableTier(); - - const TypeDef& exportFuncType = instance.metadata().getFuncExportTypeDef( - instance.metadata(otherTier).lookupFuncExport(funcIndex)); - const TypeDef& importFuncType = - metadata().getFuncImportTypeDef(metadata(tier).funcImports[i]); + const TypeDef& exportFuncType = *f->wasmTypeDef(); + const TypeDef& importFuncType = code().codeMeta().getFuncTypeDef(i); if (!TypeDef::isSubTypeOf(&exportFuncType, &importFuncType)) { - const Import& import = FindImportFunction(imports_, i); + const Import& import = FindImportFunction(moduleMeta().imports, i); UniqueChars importModuleName = import.module.toQuotedString(cx); UniqueChars importFieldName = import.field.toQuotedString(cx); if (!importFieldName || !importModuleName) { @@ -503,9 +434,9 @@ bool Module::instantiateFunctions(JSContext* cx, template static bool CheckLimits(JSContext* cx, T declaredMin, - const Maybe& declaredMax, T defaultMax, - T actualLength, const Maybe& actualMax, bool isAsmJS, - const char* kind) { + const mozilla::Maybe& declaredMax, T defaultMax, + T actualLength, const mozilla::Maybe& actualMax, + bool isAsmJS, const char* kind) { if (isAsmJS) { MOZ_ASSERT(actualLength >= declaredMin); MOZ_ASSERT(!declaredMax); @@ -559,29 +490,29 @@ static bool CheckSharing(JSContext* cx, bool declaredShared, bool isShared) { bool Module::instantiateMemories( JSContext* cx, const WasmMemoryObjectVector& memoryImports, MutableHandle memoryObjs) const { - for (uint32_t memoryIndex = 0; memoryIndex < metadata().memories.length(); + for (uint32_t memoryIndex = 0; memoryIndex < codeMeta().memories.length(); memoryIndex++) { - const MemoryDesc& desc = metadata().memories[memoryIndex]; + const MemoryDesc& desc = codeMeta().memories[memoryIndex]; Rooted memory(cx); if (memoryIndex < memoryImports.length()) { memory = memoryImports[memoryIndex]; - MOZ_ASSERT_IF(metadata().isAsmJS(), + MOZ_ASSERT_IF(codeMeta().isAsmJS(), memory->buffer().isPreparedForAsmJS()); - MOZ_ASSERT_IF(!metadata().isAsmJS(), memory->buffer().isWasm()); + MOZ_ASSERT_IF(!codeMeta().isAsmJS(), memory->buffer().isWasm()); - if (memory->indexType() != desc.indexType()) { + if (memory->addressType() != desc.addressType()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_IMP_INDEX, - ToString(memory->indexType())); + JSMSG_WASM_BAD_IMP_ADDRESS, "memory", + ToString(memory->addressType())); return false; } if (!CheckLimits(cx, desc.initialPages(), desc.maximumPages(), - /* defaultMax */ MaxMemoryPages(desc.indexType()), + /* defaultMax */ MaxMemoryPages(desc.addressType()), /* actualLength */ memory->volatilePages(), memory->sourceMaxPages(), - metadata().isAsmJS(), "Memory")) { + codeMeta().isAsmJS(), "Memory")) { return false; } @@ -589,9 +520,9 @@ bool Module::instantiateMemories( return false; } } else { - MOZ_ASSERT(!metadata().isAsmJS()); + MOZ_ASSERT(!codeMeta().isAsmJS()); - if (desc.initialPages() > MaxMemoryPages(desc.indexType())) { + if (desc.initialPages() > MaxMemoryPages(desc.addressType())) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_MEM_IMP_LIMIT); return false; @@ -605,17 +536,18 @@ bool Module::instantiateMemories( RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory)); memory = WasmMemoryObject::create( - cx, buffer, IsHugeMemoryEnabled(desc.indexType()), proto); + cx, buffer, IsHugeMemoryEnabled(desc.addressType()), proto); if (!memory) { return false; } } - MOZ_RELEASE_ASSERT(metadata().isAsmJS() || + MOZ_RELEASE_ASSERT(codeMeta().isAsmJS() || memory->isHuge() == - IsHugeMemoryEnabled(desc.indexType())); + IsHugeMemoryEnabled(desc.addressType())); if (!memoryObjs.get().append(memory)) { + ReportOutOfMemory(cx); return false; } } @@ -624,7 +556,7 @@ bool Module::instantiateMemories( bool Module::instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs) const { - size_t tagLength = metadata().tags.length(); + size_t tagLength = codeMeta().tags.length(); if (tagLength == 0) { return true; } @@ -636,7 +568,7 @@ bool Module::instantiateTags(JSContext* cx, uint32_t tagIndex = 0; RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTag)); - for (const TagDesc& desc : metadata().tags) { + for (const TagDesc& desc : codeMeta().tags) { if (tagIndex >= importedTagsLength) { Rooted tagObj( cx, WasmTagObject::create(cx, desc.type, proto)); @@ -655,13 +587,21 @@ bool Module::instantiateImportedTable(JSContext* cx, const TableDesc& td, WasmTableObjectVector* tableObjs, SharedTableVector* tables) const { MOZ_ASSERT(tableObj); - MOZ_ASSERT(!metadata().isAsmJS()); + MOZ_ASSERT(!codeMeta().isAsmJS()); Table& table = tableObj->table(); - if (!CheckLimits(cx, td.initialLength, td.maximumLength, - /* declaredMin */ MaxTableLimitField, - /* actualLength */ table.length(), table.maximum(), - metadata().isAsmJS(), "Table")) { + if (table.addressType() != td.addressType()) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_BAD_IMP_ADDRESS, "table", + ToString(tableObj->table().addressType())); + return false; + } + if (!CheckLimits(cx, /*declaredMin=*/td.initialLength(), + /*declaredMax=*/td.maximumLength(), + /*defaultMax=*/MaxTableElemsValidation(td.addressType()), + /*actualLength=*/uint64_t(table.length()), + /*actualMax=*/table.maximum(), codeMeta().isAsmJS(), + "Table")) { return false; } @@ -681,7 +621,7 @@ bool Module::instantiateImportedTable(JSContext* cx, const TableDesc& td, bool Module::instantiateLocalTable(JSContext* cx, const TableDesc& td, WasmTableObjectVector* tableObjs, SharedTableVector* tables) const { - if (td.initialLength > MaxTableLength) { + if (td.initialLength() > MaxTableElemsRuntime) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_TABLE_IMP_LIMIT); return false; @@ -691,8 +631,7 @@ bool Module::instantiateLocalTable(JSContext* cx, const TableDesc& td, Rooted tableObj(cx); if (td.isExported) { RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTable)); - tableObj.set(WasmTableObject::create(cx, td.initialLength, td.maximumLength, - td.elemType, proto)); + tableObj.set(WasmTableObject::create(cx, td.limits, td.elemType, proto)); if (!tableObj) { return false; } @@ -723,9 +662,10 @@ bool Module::instantiateTables(JSContext* cx, MutableHandle tableObjs, SharedTableVector* tables) const { uint32_t tableIndex = 0; - for (const TableDesc& td : metadata().tables) { + for (const TableDesc& td : codeMeta().tables) { if (tableIndex < tableImports.length()) { Rooted tableObj(cx, tableImports[tableIndex]); + if (!instantiateImportedTable(cx, td, tableObj, &tableObjs.get(), tables)) { return false; @@ -789,9 +729,9 @@ bool Module::instantiateGlobals(JSContext* cx, // them here, as WasmInstanceObject::create() and CreateExportObject() will // need the cells to exist. - const GlobalDescVector& globals = metadata().globals; + const GlobalDescVector& globals = codeMeta().globals; - for (const Export& exp : exports_) { + for (const Export& exp : moduleMeta().exports) { if (exp.kind() != DefinitionKind::Global) { continue; } @@ -809,7 +749,7 @@ bool Module::instantiateGlobals(JSContext* cx, #ifdef DEBUG size_t numGlobalImports = 0; - for (const Import& import : imports_) { + for (const Import& import : moduleMeta().imports) { if (import.kind != DefinitionKind::Global) { continue; } @@ -819,29 +759,13 @@ bool Module::instantiateGlobals(JSContext* cx, MOZ_ASSERT_IF(global.isIndirect(), globalIndex < globalObjs.length() || globalObjs[globalIndex]); } - MOZ_ASSERT_IF(!metadata().isAsmJS(), + MOZ_ASSERT_IF(!codeMeta().isAsmJS(), numGlobalImports == globals.length() || !globals[numGlobalImports].isImport()); #endif return true; } -static bool GetFunctionExport(JSContext* cx, - Handle instanceObj, - const JSObjectVector& funcImports, - uint32_t funcIndex, MutableHandleFunction func) { - if (funcIndex < funcImports.length() && - funcImports[funcIndex]->is()) { - JSFunction* f = &funcImports[funcIndex]->as(); - if (IsWasmExportedFunction(f)) { - func.set(f); - return true; - } - } - - return instanceObj->getExportedFunction(cx, instanceObj, funcIndex, func); -} - static bool GetGlobalExport(JSContext* cx, Handle instanceObj, const JSObjectVector& funcImports, @@ -882,15 +806,14 @@ static bool CreateExportObject( const WasmMemoryObjectVector& memoryObjs, const WasmTagObjectVector& tagObjs, const ValVector& globalImportValues, const WasmGlobalObjectVector& globalObjs, const ExportVector& exports) { - const Instance& instance = instanceObj->instance(); - const Metadata& metadata = instance.metadata(); - const GlobalDescVector& globals = metadata.globals; + Instance& instance = instanceObj->instance(); + const CodeMetadata& codeMeta = instance.codeMeta(); + const GlobalDescVector& globals = codeMeta.globals; - if (metadata.isAsmJS() && exports.length() == 1 && + if (codeMeta.isAsmJS() && exports.length() == 1 && exports[0].fieldName().isEmpty()) { RootedFunction func(cx); - if (!GetFunctionExport(cx, instanceObj, funcImports, exports[0].funcIndex(), - &func)) { + if (!instance.getExportedFunction(cx, exports[0].funcIndex(), &func)) { return false; } instanceObj->initExportsObj(*func.get()); @@ -900,7 +823,7 @@ static bool CreateExportObject( RootedObject exportObj(cx); uint8_t propertyAttr = JSPROP_ENUMERATE; - if (metadata.isAsmJS()) { + if (codeMeta.isAsmJS()) { exportObj = NewPlainObject(cx); } else { exportObj = NewPlainObjectWithProto(cx, nullptr); @@ -921,8 +844,7 @@ static bool CreateExportObject( switch (exp.kind()) { case DefinitionKind::Function: { RootedFunction func(cx); - if (!GetFunctionExport(cx, instanceObj, funcImports, exp.funcIndex(), - &func)) { + if (!instance.getExportedFunction(cx, exp.funcIndex(), &func)) { return false; } val = ObjectValue(*func); @@ -956,7 +878,7 @@ static bool CreateExportObject( } } - if (!metadata.isAsmJS()) { + if (!codeMeta.isAsmJS()) { if (!PreventExtensions(cx, exportObj)) { return false; } @@ -1005,7 +927,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports, } UniqueDebugState maybeDebug; - if (metadata().debugEnabled) { + if (code().debugEnabled()) { maybeDebug = cx->make_unique(*code_, *this); if (!maybeDebug) { ReportOutOfMemory(cx); @@ -1014,17 +936,17 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports, } instance.set(WasmInstanceObject::create( - cx, code_, dataSegments_, elemSegments_, metadata().instanceDataLength, - memories, std::move(tables), imports.funcs, metadata().globals, - imports.globalValues, imports.globalObjs, imports.tagObjs, instanceProto, - std::move(maybeDebug))); + cx, code_, moduleMeta().dataSegments, moduleMeta().elemSegments, + codeMeta().instanceDataLength, memories, std::move(tables), imports.funcs, + codeMeta().globals, imports.globalValues, imports.globalObjs, + imports.tagObjs, instanceProto, std::move(maybeDebug))); if (!instance) { return false; } if (!CreateExportObject(cx, instance, imports.funcs, tableObjs.get(), memories.get(), imports.tagObjs, imports.globalValues, - imports.globalObjs, exports_)) { + imports.globalObjs, moduleMeta().exports)) { return false; } @@ -1042,7 +964,8 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports, // constructed since this can make the instance live to content (even if the // start function fails). - if (!instance->instance().initSegments(cx, dataSegments_, elemSegments_)) { + if (!instance->instance().initSegments(cx, moduleMeta().dataSegments, + moduleMeta().elemSegments)) { return false; } @@ -1050,20 +973,43 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports, // Note that failure may cause instantiation to throw, but the instance may // still be live via edges created by initSegments or the start function. - if (metadata().startFuncIndex) { + if (codeMeta().startFuncIndex) { FixedInvokeArgs<0> args(cx); - if (!instance->instance().callExport(cx, *metadata().startFuncIndex, + if (!instance->instance().callExport(cx, *codeMeta().startFuncIndex, args)) { return false; } } JSUseCounter useCounter = - metadata().isAsmJS() ? JSUseCounter::ASMJS : JSUseCounter::WASM; + codeMeta().isAsmJS() ? JSUseCounter::ASMJS : JSUseCounter::WASM; cx->runtime()->setUseCounter(instance, useCounter); - SetUseCountersForFeatureUsage(cx, instance, metadata().featureUsage); + SetUseCountersForFeatureUsage(cx, instance, moduleMeta().featureUsage); - if (cx->options().testWasmAwaitTier2()) { + // Warn for deprecated features. Don't do this with differential testing as + // that will think these warnings are significant. + if (!js::SupportDifferentialTesting()) { + // Warn if the user is using the legacy exceptions proposal. + if (moduleMeta().featureUsage & FeatureUsage::LegacyExceptions) { + if (!js::WarnNumberASCII(cx, JSMSG_WASM_LEGACY_EXCEPTIONS_DEPRECATED)) { + if (cx->isExceptionPending()) { + cx->clearPendingException(); + } + } + } + + // Warn if the user is using asm.js still. + if (JS::Prefs::warn_asmjs_deprecation() && codeMeta().isAsmJS()) { + if (!js::WarnNumberASCII(cx, JSMSG_USE_ASM_DEPRECATED)) { + if (cx->isExceptionPending()) { + cx->clearPendingException(); + } + } + } + } + + if (cx->options().testWasmAwaitTier2() && + code().mode() != CompileMode::LazyTiering) { testingBlockOnTier2Complete(); } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmModule.h b/src/third_party/mozjs/extract/js/src/wasm/WasmModule.h index 6fe24212b0f..ad963c0cf89 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmModule.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmModule.h @@ -28,6 +28,8 @@ #include "wasm/WasmSerialize.h" #include "wasm/WasmTable.h" +using mozilla::Maybe; + namespace JS { class OptimizedEncodingListener; } @@ -38,9 +40,19 @@ namespace wasm { struct CompileArgs; // In the context of wasm, the OptimizedEncodingListener specifically is -// listening for the completion of tier-2. +// listening for the completion of complete tier-2. -using Tier2Listener = RefPtr; +using CompleteTier2Listener = RefPtr; + +// Report tier-2 compilation results off-thread. If `maybeFuncIndex` is +// `Some`, this report is for a partial tier-2 compilation of the specified +// function. Otherwise it's for a complete tier-2 compilation. + +void ReportTier2ResultsOffThread(bool cancelled, bool success, + Maybe maybeFuncIndex, + const ScriptedCaller& scriptedCaller, + const UniqueChars& error, + const UniqueCharsVector& warnings); // A struct containing the typed, imported values that are harvested from the // import object and passed to Module::instantiate(). This struct must be @@ -75,26 +87,22 @@ struct ImportValues { // where the LinkData is also available, which is primarily (1) at the end of // module generation, (2) at the end of tier-2 compilation. // -// Fully linked-and-instantiated code (represented by SharedCode and its owned -// ModuleSegment) can be shared between instances. +// Fully linked-and-instantiated code (represented by SharedCode) can be shared +// between instances. class Module : public JS::WasmModule { + // This has the same lifetime end as Module itself -- it can be dropped when + // Module itself is dropped. + const SharedModuleMetadata moduleMeta_; + + // This contains all compilation artifacts for the module. const SharedCode code_; - const ImportVector imports_; - const ExportVector exports_; - const DataSegmentVector dataSegments_; - const ModuleElemSegmentVector elemSegments_; - const CustomSectionVector customSections_; - // This field is only meaningful when code_->metadata().debugEnabled. + // This field is set during complete tier-2 compilation and cleared on + // success or failure. These happen on different threads and are serialized + // by the control flow of helper tasks. - const SharedBytes debugBytecode_; - - // This field is set during tier-2 compilation and cleared on success or - // failure. These happen on different threads and are serialized by the - // control flow of helper tasks. - - mutable Tier2Listener tier2Listener_; + mutable CompleteTier2Listener completeTier2Listener_; // This flag is used for logging (and testing) purposes to indicate // whether the module was deserialized (from a cache). @@ -104,7 +112,7 @@ class Module : public JS::WasmModule { // This flag is only used for testing purposes and is cleared on success or // failure. The field is racily polled from various threads. - mutable Atomic testingTier2Active_; + mutable mozilla::Atomic testingTier2Active_; // Cached malloc allocation size for GC memory tracking. @@ -130,22 +138,15 @@ class Module : public JS::WasmModule { bool instantiateGlobals(JSContext* cx, const ValVector& globalImportValues, WasmGlobalObjectVector& globalObjs) const; - class Tier2GeneratorTaskImpl; + class CompleteTier2GeneratorTaskImpl; public: - Module(const Code& code, ImportVector&& imports, ExportVector&& exports, - DataSegmentVector&& dataSegments, - ModuleElemSegmentVector&& elemSegments, - CustomSectionVector&& customSections, - const ShareableBytes* debugBytecode = nullptr, + class PartialTier2CompileTaskImpl; + + Module(const ModuleMetadata& moduleMeta, const Code& code, bool loggingDeserialized = false) - : code_(&code), - imports_(std::move(imports)), - exports_(std::move(exports)), - dataSegments_(std::move(dataSegments)), - elemSegments_(std::move(elemSegments)), - customSections_(std::move(customSections)), - debugBytecode_(debugBytecode), + : moduleMeta_(&moduleMeta), + code_(&code), loggingDeserialized_(loggingDeserialized), testingTier2Active_(false) { initGCMallocBytesExcludingCode(); @@ -153,14 +154,16 @@ class Module : public JS::WasmModule { ~Module() override; const Code& code() const { return *code_; } - const ModuleSegment& moduleSegment(Tier t) const { return code_->segment(t); } - const Metadata& metadata() const { return code_->metadata(); } - const MetadataTier& metadata(Tier t) const { return code_->metadata(t); } - const ImportVector& imports() const { return imports_; } - const ExportVector& exports() const { return exports_; } - const CustomSectionVector& customSections() const { return customSections_; } - const Bytes& debugBytecode() const { return debugBytecode_->bytes; } - uint32_t codeLength(Tier t) const { return code_->segment(t).length(); } + const ModuleMetadata& moduleMeta() const { return *moduleMeta_; } + const CodeMetadata& codeMeta() const { return code_->codeMeta(); } + const CodeTailMetadata& codeTailMeta() const { return code_->codeTailMeta(); } + const CodeMetadataForAsmJS* codeMetaForAsmJS() const { + return code_->codeMetaForAsmJS(); + } + const BytecodeSource& debugBytecode() const { + return codeTailMeta().debugBytecode.source(); + } + uint32_t tier1CodeMemoryUsed() const { return code_->tier1CodeMemoryUsed(); } // Instantiate this module with the given imports: @@ -173,16 +176,18 @@ class Module : public JS::WasmModule { // finishTier2() from a helper thread, passing tier-variant data which will // be installed and made visible. - void startTier2(const CompileArgs& args, const ShareableBytes& bytecode, + void startTier2(const ShareableBytes* codeSection, JS::OptimizedEncodingListener* listener); - bool finishTier2(const LinkData& linkData2, UniqueCodeTier code2) const; + bool finishTier2(UniqueCodeBlock tier2CodeBlock, UniqueLinkData tier2LinkData, + const CompileAndLinkStats& tier2Stats) const; void testingBlockOnTier2Complete() const; bool testingTier2Active() const { return testingTier2Active_; } // Code caching support. - [[nodiscard]] bool serialize(const LinkData& linkData, Bytes* bytes) const; + bool canSerialize() const; + [[nodiscard]] bool serialize(Bytes* bytes) const; static RefPtr deserialize(const uint8_t* begin, size_t size); bool loggingDeserialized() const { return loggingDeserialized_; } @@ -193,7 +198,9 @@ class Module : public JS::WasmModule { // about:memory reporting: - void addSizeOfMisc(MallocSizeOf mallocSizeOf, Metadata::SeenSet* seenMetadata, + void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, + CodeMetadata::SeenSet* seenCodeMeta, + CodeMetadataForAsmJS::SeenSet* seenCodeMetaForAsmJS, Code::SeenSet* seenCode, size_t* code, size_t* data) const; // GC malloc memory tracking: @@ -207,7 +214,7 @@ class Module : public JS::WasmModule { bool extractCode(JSContext* cx, Tier tier, MutableHandleValue vp) const; - WASM_DECLARE_FRIEND_SERIALIZE_ARGS(Module, const wasm::LinkData& linkData); + WASM_DECLARE_FRIEND_SERIALIZE(Module); }; using MutableModule = RefPtr; diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.cpp index 8fc4effb5f4..fcced7ab750 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.cpp @@ -29,6 +29,9 @@ using namespace js; using namespace js::wasm; +using mozilla::CheckedInt32; +using mozilla::MallocSizeOf; + /* static */ CacheableName CacheableName::fromUTF8Chars(UniqueChars&& utf8Chars) { size_t length = strlen(utf8Chars.get()); @@ -49,7 +52,11 @@ bool CacheableName::fromUTF8Chars(const char* utf8Chars, CacheableName* name) { return true; } -BranchHintVector BranchHintCollection::invalidVector; +MOZ_RUNINIT BranchHintVector BranchHintCollection::invalidVector_; + +JSString* CacheableName::toJSString(JSContext* cx) const { + return NewStringCopyUTF8N(cx, JS::UTF8Chars(begin(), length())); +} JSAtom* CacheableName::toAtom(JSContext* cx) const { return AtomizeUTF8Chars(cx, begin(), length()); @@ -121,33 +128,19 @@ size_t GlobalDesc::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { return initial_.sizeOfExcludingThis(mallocSizeOf); } -TagType::~TagType() { - // Release strong references to any type definitions this tag could - // be referencing. - for (const ValType& argType : argTypes_) { - argType.Release(); - } -} - -bool TagType::initialize(ValTypeVector&& argTypes) { - MOZ_ASSERT(argTypes_.empty() && argOffsets_.empty() && size_ == 0); - - argTypes_ = std::move(argTypes); - - // Acquire a strong reference to any type definitions this tag could - // be referencing. - for (const ValType& argType : argTypes_) { - argType.AddRef(); - } +bool TagType::initialize(const SharedTypeDef& funcType) { + MOZ_ASSERT(funcType->isFuncType()); + type_ = funcType; + const ValTypeVector& args = argTypes(); // Compute the byte offsets for arguments when we layout an exception. - if (!argOffsets_.resize(argTypes_.length())) { + if (!argOffsets_.resize(args.length())) { return false; } StructLayout layout; - for (size_t i = 0; i < argTypes_.length(); i++) { - CheckedInt32 offset = layout.addField(StorageType(argTypes_[i].packed())); + for (size_t i = 0; i < args.length(); i++) { + CheckedInt32 offset = layout.addField(StorageType(args[i].packed())); if (!offset.isValid()) { return false; } @@ -165,8 +158,7 @@ bool TagType::initialize(ValTypeVector&& argTypes) { } size_t TagType::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { - return argTypes_.sizeOfExcludingThis(mallocSizeOf) + - argOffsets_.sizeOfExcludingThis(mallocSizeOf); + return argOffsets_.sizeOfExcludingThis(mallocSizeOf); } size_t TagDesc::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { @@ -192,3 +184,18 @@ size_t CustomSection::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { return name.sizeOfExcludingThis(mallocSizeOf) + sizeof(*payload) + payload->sizeOfExcludingThis(mallocSizeOf); } + +size_t NameSection::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { + return funcNames.sizeOfExcludingThis(mallocSizeOf); +} + +const char* wasm::ToString(LimitsKind kind) { + switch (kind) { + case LimitsKind::Memory: + return "Memory"; + case LimitsKind::Table: + return "Table"; + default: + MOZ_CRASH(); + } +} diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.h b/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.h index c6cfabaca53..75785e637c5 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmModuleTypes.h @@ -42,10 +42,6 @@ namespace js { namespace wasm { -using mozilla::Maybe; -using mozilla::Nothing; -using mozilla::Span; - class FuncType; // A Module can either be asm.js or wasm. @@ -80,13 +76,16 @@ struct CacheableName { bool isEmpty() const { return bytes_.length() == 0; } - Span utf8Bytes() { return Span(bytes_); } - Span utf8Bytes() const { return Span(bytes_); } + mozilla::Span utf8Bytes() { return mozilla::Span(bytes_); } + mozilla::Span utf8Bytes() const { + return mozilla::Span(bytes_); + } static CacheableName fromUTF8Chars(UniqueChars&& utf8Chars); [[nodiscard]] static bool fromUTF8Chars(const char* utf8Chars, CacheableName* name); + [[nodiscard]] JSString* toJSString(JSContext* cx) const; [[nodiscard]] JSAtom* toAtom(JSContext* cx) const; [[nodiscard]] bool toPropertyKey(JSContext* cx, MutableHandleId propertyKey) const; @@ -100,8 +99,8 @@ using CacheableNameVector = Vector; // A hash policy for names. struct NameHasher { - using Key = Span; - using Lookup = Span; + using Key = mozilla::Span; + using Lookup = mozilla::Span; static HashNumber hash(const Lookup& aLookup) { return mozilla::HashString(aLookup.data(), aLookup.Length()); @@ -197,18 +196,33 @@ enum class FuncFlags : uint8_t { // A FuncDesc describes a single function definition. struct FuncDesc { - const FuncType* type; // Bit pack to keep this struct small on 32-bit systems uint32_t typeIndex : 24; FuncFlags flags : 8; + WASM_CHECK_CACHEABLE_POD(typeIndex, flags); + // Assert that the bit packing scheme is viable static_assert(MaxTypes <= (1 << 24) - 1); static_assert(sizeof(FuncFlags) == sizeof(uint8_t)); FuncDesc() = default; - FuncDesc(const FuncType* type, uint32_t typeIndex) - : type(type), typeIndex(typeIndex), flags(FuncFlags::None) {} + explicit FuncDesc(uint32_t typeIndex) + : typeIndex(typeIndex), flags(FuncFlags::None) {} + + void declareFuncExported(bool eager, bool canRefFunc) { + // Set the `Exported` flag, if not set. + flags = FuncFlags(uint8_t(flags) | uint8_t(FuncFlags::Exported)); + + // Merge in the `Eager` and `CanRefFunc` flags, if they're set. Be sure + // to not unset them if they've already been set. + if (eager) { + flags = FuncFlags(uint8_t(flags) | uint8_t(FuncFlags::Eager)); + } + if (canRefFunc) { + flags = FuncFlags(uint8_t(flags) | uint8_t(FuncFlags::CanRefFunc)); + } + } bool isExported() const { return uint8_t(flags) & uint8_t(FuncFlags::Exported); @@ -219,8 +233,143 @@ struct FuncDesc { } }; +WASM_DECLARE_CACHEABLE_POD(FuncDesc); + using FuncDescVector = Vector; +struct CallRefMetricsRange { + explicit CallRefMetricsRange() {} + explicit CallRefMetricsRange(uint32_t begin, uint32_t length) + : begin(begin), length(length) {} + + uint32_t begin = 0; + uint32_t length = 0; + + void offsetBy(uint32_t offset) { begin += offset; } + + WASM_CHECK_CACHEABLE_POD(begin, length); +}; + +struct AllocSitesRange { + explicit AllocSitesRange() {} + explicit AllocSitesRange(uint32_t begin, uint32_t length) + : begin(begin), length(length) {} + + uint32_t begin = 0; + uint32_t length = 0; + + void offsetBy(uint32_t offset) { begin += offset; } + + WASM_CHECK_CACHEABLE_POD(begin, length); +}; + +// A compact plain data summary of CallRefMetrics for use by our function +// compilers. See CallRefMetrics in WasmInstanceData.h for more information. +// +// We cannot allow the metrics collected by an instance to directly be read +// from our function compilers because they contain thread-local data and are +// written into without any synchronization. +// +// Instead, CodeMetadata contains an array of CallRefHint that every instance +// writes into when it has a function that requests a tier-up. This array is +// 1:1 with the non-threadsafe CallRefMetrics that is stored on the instance. +// +// This class must be thread safe, as it's read and written from different +// threads. It is an array of up to 3 function indices, and the entire array +// can be read/written atomically. Each function index is represented in 20 +// bits, and 2 of the remaining 4 bits are used to indicate the array's current +// size. +// +// Although unstated and unenforced here, it is expected that -- in the case +// where more than one function index is stored -- the func index at `.get(0)` +// is the "most important" in terms of inlining, that at `.get(1)` is the +// second most important, etc. +// +// Note that the fact that this array has 3 elements is unrelated to the value +// of CallRefMetrics::NUM_TRACKED. The target-collection mechanism will work +// properly even if CallRefMetrics::NUM_TRACKED is greater than 3, in which +// case at most only 3 targets (probably the hottest ones) will get baked into +// the CallRefHint. +class CallRefHint { + public: + using Repr = uint64_t; + static constexpr size_t NUM_ENTRIES = 3; + + private: + // Representation is: + // + // 63 61 42 41 22 21 2 1 0 + // | | | | | | | | | + // 00 index#2 index#1 index#0 length + static constexpr uint32_t ElemBits = 20; + static constexpr uint32_t LengthBits = 2; + static constexpr uint64_t Mask = (uint64_t(1) << ElemBits) - 1; + static_assert(js::wasm::MaxFuncs <= Mask); + static_assert(3 * ElemBits + LengthBits <= 8 * sizeof(Repr)); + + Repr state_ = 0; + + bool valid() const { + // Shift out the length field and all of the entries that the length field + // implies are occupied. What remains should be all zeroes. + return (state_ >> (length() * ElemBits + LengthBits)) == 0; + } + + public: + // We omit the obvious single-argument constructor that takes a `Repr`, + // because that is too easily confused with one that takes a function index, + // and in any case it is not necessary. + + uint32_t length() const { return state_ & 3; } + bool empty() const { return length() == 0; } + bool full() const { return length() == 3; } + + uint32_t get(uint32_t index) const { + MOZ_ASSERT(index < length()); + uint64_t res = (state_ >> (index * ElemBits + LengthBits)) & Mask; + return uint32_t(res); + } + void set(uint32_t index, uint32_t funcIndex) { + MOZ_ASSERT(index < length()); + MOZ_ASSERT(funcIndex <= Mask); + uint32_t shift = index * ElemBits + LengthBits; + uint64_t c = uint64_t(Mask) << shift; + uint64_t s = uint64_t(funcIndex) << shift; + state_ = (state_ & ~c) | s; + } + + void append(uint32_t funcIndex) { + MOZ_RELEASE_ASSERT(!full()); + // We know the lowest two bits of `state_` are not 0b11, so we can + // increment the length field by incrementing `state_` as a whole. + state_++; + set(length() - 1, funcIndex); + } + + static CallRefHint fromRepr(Repr repr) { + CallRefHint res; + res.state_ = repr; + MOZ_ASSERT(res.valid()); + return res; + } + Repr toRepr() const { return state_; } +}; + +static_assert(sizeof(CallRefHint) == sizeof(CallRefHint::Repr)); + +using MutableCallRefHint = mozilla::Atomic; +using MutableCallRefHints = + mozilla::UniquePtr; + +WASM_DECLARE_CACHEABLE_POD(CallRefMetricsRange); + +using CallRefMetricsRangeVector = + Vector; + +WASM_DECLARE_CACHEABLE_POD(AllocSitesRange); + +using AllocSitesRangeVector = Vector; + enum class BranchHint : uint8_t { Unlikely = 0, Likely = 1, Invalid = 2 }; // Stores pairs of @@ -236,37 +385,47 @@ struct BranchHintEntry { // Branch hint sorted vector for a function, // stores tuples of using BranchHintVector = Vector; +using BranchHintFuncMap = HashMap, SystemAllocPolicy>; struct BranchHintCollection { private: - // Map from function index to their collection of branch hints - HashMap, - SystemAllocPolicy> - branchHintsMap; - - public: // Used for lookups into the collection if a function // doesn't contain any hints. - static BranchHintVector invalidVector; + static BranchHintVector invalidVector_; + // Map from function index to their collection of branch hints + BranchHintFuncMap branchHintsMap_; + // Whether the module had branch hints, but we failed to parse them. This + // is not semantically visible to user code, but used for internal testing. + bool failedParse_ = false; + + public: // Add all the branch hints for a function [[nodiscard]] bool addHintsForFunc(uint32_t functionIndex, BranchHintVector&& branchHints) { - return branchHintsMap.put(functionIndex, std::move(branchHints)); + return branchHintsMap_.put(functionIndex, std::move(branchHints)); } // Return the vector with branch hints for a funcIndex. // If this function doesn't contain any hints, return an empty vector. BranchHintVector& getHintVector(uint32_t funcIndex) const { - if (auto hintsVector = branchHintsMap.readonlyThreadsafeLookup(funcIndex)) { + if (auto hintsVector = + branchHintsMap_.readonlyThreadsafeLookup(funcIndex)) { return hintsVector->value(); } // If not found, return the empty invalid Vector - return invalidVector; + return invalidVector_; } - bool isEmpty() const { return branchHintsMap.empty(); } + bool isEmpty() const { return branchHintsMap_.empty(); } + + void setFailedAndClear() { + failedParse_ = true; + branchHintsMap_.clearAndCompact(); + } + bool failedParse() const { return failedParse_; } }; enum class GlobalKind { Import, Constant, Variable }; @@ -388,23 +547,29 @@ using GlobalDescVector = Vector; using TagOffsetVector = Vector; class TagType : public AtomicRefCounted { - ValTypeVector argTypes_; + SharedTypeDef type_; TagOffsetVector argOffsets_; uint32_t size_; public: TagType() : size_(0) {} - ~TagType(); - const ValTypeVector& argTypes() const { return argTypes_; } + [[nodiscard]] bool initialize(const SharedTypeDef& funcType); + + const TypeDef& type() const { return *type_; } + const ValTypeVector& argTypes() const { return type_->funcType().args(); } const TagOffsetVector& argOffsets() const { return argOffsets_; } - ResultType resultType() const { return ResultType::Vector(argTypes_); } + ResultType resultType() const { return ResultType::Vector(argTypes()); } uint32_t tagSize() const { return size_; } - [[nodiscard]] bool initialize(ValTypeVector&& argTypes); + static bool matches(const TagType& a, const TagType& b) { + // Note that this does NOT use subtyping. This is deliberate per the spec. + return a.type_ == b.type_; + } size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + WASM_DECLARE_FRIEND_SERIALIZE(TagType); }; using MutableTagType = RefPtr; @@ -425,6 +590,8 @@ struct TagDesc { using TagDescVector = Vector; using ElemExprOffsetVector = Vector; +// This holds info about elem segments that is needed for instantiation. It +// can be dropped when the associated wasm::Module is dropped. struct ModuleElemSegment { enum class Kind { Active, @@ -450,7 +617,7 @@ struct ModuleElemSegment { Kind kind; uint32_t tableIndex; RefType elemType; - Maybe offsetIfActive; + mozilla::Maybe offsetIfActive; // We store either an array of indices or the full bytecode of the element // expressions, depending on the encoding used for the element segment. @@ -482,32 +649,37 @@ using InstanceElemSegment = GCVector, 0, SystemAllocPolicy>; using InstanceElemSegmentVector = GCVector; -// DataSegmentEnv holds the initial results of decoding a data segment from the -// bytecode and is stored in the ModuleEnvironment during compilation. When -// compilation completes, (non-Env) DataSegments are created and stored in -// the wasm::Module which contain copies of the data segment payload. This -// allows non-compilation uses of wasm validation to avoid expensive copies. +// DataSegmentRange holds the initial results of decoding a data segment from +// the bytecode and is stored in the ModuleMetadata. It contains the bytecode +// bounds of the data segment, and some auxiliary information, but not the +// segment contents itself. // -// When a DataSegment is "passive" it is shared between a wasm::Module and its -// wasm::Instances. To allow each segment to be released as soon as the last -// Instance mem.drops it and the Module is destroyed, each DataSegment is -// individually atomically ref-counted. +// When compilation completes, each DataSegmentRange is transformed into a +// DataSegment, which are also stored in the ModuleMetadata. DataSegment +// contains the same information as DataSegmentRange but additionally contains +// the segment contents itself. This allows non-compilation uses of wasm +// validation to avoid expensive copies. +// +// A DataSegment that is "passive" is shared between a ModuleMetadata and its +// wasm::Instances. To allow each segment to be released as soon as the last +// Instance mem.drops it and the Module (hence, also the ModuleMetadata) is +// destroyed, each DataSegment is individually atomically ref-counted. constexpr uint32_t InvalidMemoryIndex = UINT32_MAX; static_assert(InvalidMemoryIndex > MaxMemories, "Invariant"); -struct DataSegmentEnv { +struct DataSegmentRange { uint32_t memoryIndex; - Maybe offsetIfActive; + mozilla::Maybe offsetIfActive; uint32_t bytecodeOffset; uint32_t length; }; -using DataSegmentEnvVector = Vector; +using DataSegmentRangeVector = Vector; struct DataSegment : AtomicRefCounted { uint32_t memoryIndex; - Maybe offsetIfActive; + mozilla::Maybe offsetIfActive; Bytes bytes; DataSegment() = default; @@ -516,8 +688,8 @@ struct DataSegment : AtomicRefCounted { const InitExpr& offset() const { return *offsetIfActive; } - [[nodiscard]] bool init(const ShareableBytes& bytecode, - const DataSegmentEnv& src) { + [[nodiscard]] bool init(const BytecodeSource& bytecode, + const DataSegmentRange& src) { memoryIndex = src.memoryIndex; if (src.offsetIfActive) { offsetIfActive.emplace(); @@ -525,7 +697,10 @@ struct DataSegment : AtomicRefCounted { return false; } } - return bytes.append(bytecode.begin() + src.bytecodeOffset, src.length); + MOZ_ASSERT(bytes.length() == 0); + BytecodeSpan span = + bytecode.getSpan(BytecodeRange(src.bytecodeOffset, src.length)); + return bytes.append(span.data(), span.size()); } size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; @@ -535,18 +710,22 @@ using MutableDataSegment = RefPtr; using SharedDataSegment = RefPtr; using DataSegmentVector = Vector; -// The CustomSection(Env) structs are like DataSegment(Env): CustomSectionEnv is -// stored in the ModuleEnvironment and CustomSection holds a copy of the payload -// and is stored in the wasm::Module. +// CustomSectionRange and CustomSection are related in the same way that +// DataSegmentRange and DataSegment are: the CustomSectionRanges are stored in +// the ModuleMetadata, and are transformed into CustomSections at the end of +// compilation and stored in wasm::Module. -struct CustomSectionEnv { - uint32_t nameOffset; - uint32_t nameLength; - uint32_t payloadOffset; - uint32_t payloadLength; +struct CustomSectionRange { + BytecodeRange name; + BytecodeRange payload; + + WASM_CHECK_CACHEABLE_POD(name, payload); }; -using CustomSectionEnvVector = Vector; +WASM_DECLARE_CACHEABLE_POD(CustomSectionRange); + +using CustomSectionRangeVector = + Vector; struct CustomSection { Bytes name; @@ -576,6 +755,14 @@ WASM_DECLARE_CACHEABLE_POD(Name); using NameVector = Vector; +struct NameSection { + Name moduleName; + NameVector funcNames; + uint32_t customSectionIndex; + + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; +}; + // The kind of limits to decode or convert from JS. enum class LimitsKind { @@ -583,28 +770,30 @@ enum class LimitsKind { Table, }; +extern const char* ToString(LimitsKind kind); + // Represents the resizable limits of memories and tables. struct Limits { - // `indexType` will always be I32 for tables, but may be I64 for memories - // when memory64 is enabled. - IndexType indexType; + // `addressType` may be I64 when memory64 is enabled. + AddressType addressType; // The initial and maximum limit. The unit is pages for memories and elements // for tables. uint64_t initial; - Maybe maximum; + mozilla::Maybe maximum; // `shared` is Shareable::False for tables but may be Shareable::True for // memories. Shareable shared; - WASM_CHECK_CACHEABLE_POD(indexType, initial, maximum, shared); + WASM_CHECK_CACHEABLE_POD(addressType, initial, maximum, shared); Limits() = default; - explicit Limits(uint64_t initial, const Maybe& maximum = Nothing(), + explicit Limits(uint64_t initial, + const mozilla::Maybe& maximum = mozilla::Nothing(), Shareable shared = Shareable::False) - : indexType(IndexType::I32), + : addressType(AddressType::I32), initial(initial), maximum(maximum), shared(shared) {} @@ -632,25 +821,25 @@ struct MemoryDesc { limits.maximum.value() < (0x100000000 / PageSize); } - IndexType indexType() const { return limits.indexType; } + AddressType addressType() const { return limits.addressType; } // The initial length of this memory in pages. Pages initialPages() const { return Pages(limits.initial); } // The maximum length of this memory in pages. - Maybe maximumPages() const { + mozilla::Maybe maximumPages() const { return limits.maximum.map([](uint64_t x) { return Pages(x); }); } // The initial length of this memory in bytes. Only valid for memory32. uint64_t initialLength32() const { - MOZ_ASSERT(indexType() == IndexType::I32); + MOZ_ASSERT(addressType() == AddressType::I32); // See static_assert after MemoryDesc for why this is safe. return limits.initial * PageSize; } uint64_t initialLength64() const { - MOZ_ASSERT(indexType() == IndexType::I64); + MOZ_ASSERT(addressType() == AddressType::I64); return limits.initial * PageSize; } @@ -664,38 +853,32 @@ using MemoryDescVector = Vector; // We don't need to worry about overflow with a Memory32 field when // using a uint64_t. -static_assert(MaxMemory32LimitField <= UINT64_MAX / PageSize); - -// TableDesc describes a table as well as the offset of the table's base pointer -// in global memory. -// -// A TableDesc contains the element type and whether the table is for asm.js, -// which determines the table representation. -// - ExternRef: a wasm anyref word (wasm::AnyRef) -// - FuncRef: a two-word FunctionTableElem (wasm indirect call ABI) -// - FuncRef (if `isAsmJS`): a two-word FunctionTableElem (asm.js ABI) -// Eventually there should be a single unified AnyRef representation. +static_assert(MaxMemory32PagesValidation <= UINT64_MAX / PageSize); struct TableDesc { + Limits limits; RefType elemType; bool isImported; bool isExported; bool isAsmJS; - uint32_t initialLength; - Maybe maximumLength; - Maybe initExpr; + mozilla::Maybe initExpr; TableDesc() = default; - TableDesc(RefType elemType, uint32_t initialLength, - Maybe maximumLength, Maybe&& initExpr, - bool isAsmJS, bool isImported = false, bool isExported = false) - : elemType(elemType), + TableDesc(Limits limits, RefType elemType, + mozilla::Maybe&& initExpr, bool isAsmJS, + bool isImported = false, bool isExported = false) + : limits(limits), + elemType(elemType), isImported(isImported), isExported(isExported), isAsmJS(isAsmJS), - initialLength(initialLength), - maximumLength(maximumLength), initExpr(std::move(initExpr)) {} + + AddressType addressType() const { return limits.addressType; } + + uint64_t initialLength() const { return limits.initial; } + + mozilla::Maybe maximumLength() const { return limits.maximum; } }; using TableDescVector = Vector; diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.cpp index e35c6ce5788..90d4d3505e8 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.cpp @@ -24,30 +24,13 @@ using namespace js; using namespace js::jit; using namespace js::wasm; -#ifdef ENABLE_WASM_GC -# ifndef ENABLE_WASM_GC -# error "GC types require the function-references feature" -# endif +#ifdef ENABLE_WASM_SIMD +# define WASM_SIMD_OP(code) return code +#else +# define WASM_SIMD_OP(code) break #endif #ifdef DEBUG - -# ifdef ENABLE_WASM_GC -# define WASM_FUNCTION_REFERENCES_OP(code) return code -# else -# define WASM_FUNCTION_REFERENCES_OP(code) break -# endif -# ifdef ENABLE_WASM_GC -# define WASM_GC_OP(code) return code -# else -# define WASM_GC_OP(code) break -# endif -# ifdef ENABLE_WASM_SIMD -# define WASM_SIMD_OP(code) return code -# else -# define WASM_SIMD_OP(code) break -# endif - OpKind wasm::Classify(OpBytes op) { switch (Op(op.b0)) { case Op::Block: @@ -59,13 +42,13 @@ OpKind wasm::Classify(OpBytes op) { case Op::Drop: return OpKind::Drop; case Op::I32Const: - return OpKind::I32; + return OpKind::I32Const; case Op::I64Const: - return OpKind::I64; + return OpKind::I64Const; case Op::F32Const: - return OpKind::F32; + return OpKind::F32Const; case Op::F64Const: - return OpKind::F64; + return OpKind::F64Const; case Op::Br: return OpKind::Br; case Op::BrIf: @@ -257,9 +240,9 @@ OpKind wasm::Classify(OpBytes op) { case Op::ReturnCallIndirect: return OpKind::ReturnCallIndirect; case Op::CallRef: - WASM_FUNCTION_REFERENCES_OP(OpKind::CallRef); + return OpKind::CallRef; case Op::ReturnCallRef: - WASM_FUNCTION_REFERENCES_OP(OpKind::ReturnCallRef); + return OpKind::ReturnCallRef; case Op::Return: case Op::Limit: // Accept Limit, for use in decoding the end of a function after the body. @@ -292,76 +275,76 @@ OpKind wasm::Classify(OpBytes op) { return OpKind::MemoryGrow; case Op::RefNull: return OpKind::RefNull; - case Op::RefIsNull: - return OpKind::Conversion; case Op::RefFunc: return OpKind::RefFunc; + case Op::RefIsNull: + return OpKind::RefIsNull; case Op::RefAsNonNull: - WASM_FUNCTION_REFERENCES_OP(OpKind::RefAsNonNull); + return OpKind::RefAsNonNull; case Op::BrOnNull: - WASM_FUNCTION_REFERENCES_OP(OpKind::BrOnNull); + return OpKind::BrOnNull; case Op::BrOnNonNull: - WASM_FUNCTION_REFERENCES_OP(OpKind::BrOnNonNull); + return OpKind::BrOnNonNull; case Op::RefEq: - WASM_GC_OP(OpKind::Comparison); + return OpKind::Comparison; case Op::GcPrefix: { switch (GcOp(op.b1)) { case GcOp::Limit: // Reject Limit for GcPrefix encoding break; case GcOp::StructNew: - WASM_GC_OP(OpKind::StructNew); + return OpKind::StructNew; case GcOp::StructNewDefault: - WASM_GC_OP(OpKind::StructNewDefault); + return OpKind::StructNewDefault; case GcOp::StructGet: case GcOp::StructGetS: case GcOp::StructGetU: - WASM_GC_OP(OpKind::StructGet); + return OpKind::StructGet; case GcOp::StructSet: - WASM_GC_OP(OpKind::StructSet); + return OpKind::StructSet; case GcOp::ArrayNew: - WASM_GC_OP(OpKind::ArrayNew); + return OpKind::ArrayNew; case GcOp::ArrayNewFixed: - WASM_GC_OP(OpKind::ArrayNewFixed); + return OpKind::ArrayNewFixed; case GcOp::ArrayNewDefault: - WASM_GC_OP(OpKind::ArrayNewDefault); + return OpKind::ArrayNewDefault; case GcOp::ArrayNewData: - WASM_GC_OP(OpKind::ArrayNewData); + return OpKind::ArrayNewData; case GcOp::ArrayNewElem: - WASM_GC_OP(OpKind::ArrayNewElem); + return OpKind::ArrayNewElem; case GcOp::ArrayInitData: - WASM_GC_OP(OpKind::ArrayInitData); + return OpKind::ArrayInitData; case GcOp::ArrayInitElem: - WASM_GC_OP(OpKind::ArrayInitElem); + return OpKind::ArrayInitElem; case GcOp::ArrayGet: case GcOp::ArrayGetS: case GcOp::ArrayGetU: - WASM_GC_OP(OpKind::ArrayGet); + return OpKind::ArrayGet; case GcOp::ArraySet: - WASM_GC_OP(OpKind::ArraySet); + return OpKind::ArraySet; case GcOp::ArrayLen: - WASM_GC_OP(OpKind::ArrayLen); + return OpKind::ArrayLen; case GcOp::ArrayCopy: - WASM_GC_OP(OpKind::ArrayCopy); + return OpKind::ArrayCopy; case GcOp::ArrayFill: - WASM_GC_OP(OpKind::ArrayFill); + return OpKind::ArrayFill; case GcOp::RefI31: case GcOp::I31GetS: case GcOp::I31GetU: - WASM_GC_OP(OpKind::Conversion); + return OpKind::Conversion; case GcOp::RefTest: case GcOp::RefTestNull: - WASM_GC_OP(OpKind::RefTest); + return OpKind::RefTest; case GcOp::RefCast: case GcOp::RefCastNull: - WASM_GC_OP(OpKind::RefCast); + return OpKind::RefCast; case GcOp::BrOnCast: case GcOp::BrOnCastFail: - WASM_GC_OP(OpKind::BrOnCast); + return OpKind::BrOnCast; case GcOp::AnyConvertExtern: - WASM_GC_OP(OpKind::RefConversion); + return OpKind::RefConversion; case GcOp::ExternConvertAny: - WASM_GC_OP(OpKind::RefConversion); + return OpKind::RefConversion; } break; } @@ -529,7 +512,7 @@ OpKind wasm::Classify(OpBytes op) { case SimdOp::F64x2RelaxedMax: case SimdOp::I8x16RelaxedSwizzle: case SimdOp::I16x8RelaxedQ15MulrS: - case SimdOp::I16x8DotI8x16I7x16S: + case SimdOp::I16x8RelaxedDotI8x16I7x16S: WASM_SIMD_OP(OpKind::Binary); case SimdOp::I8x16Neg: case SimdOp::I16x8Neg: @@ -604,7 +587,7 @@ OpKind wasm::Classify(OpBytes op) { case SimdOp::I8x16Shuffle: WASM_SIMD_OP(OpKind::VectorShuffle); case SimdOp::V128Const: - WASM_SIMD_OP(OpKind::V128); + WASM_SIMD_OP(OpKind::V128Const); case SimdOp::V128Load: case SimdOp::V128Load8Splat: case SimdOp::V128Load16Splat: @@ -639,7 +622,7 @@ OpKind wasm::Classify(OpBytes op) { case SimdOp::I16x8RelaxedLaneSelect: case SimdOp::I32x4RelaxedLaneSelect: case SimdOp::I64x2RelaxedLaneSelect: - case SimdOp::I32x4DotI8x16I7x16AddS: + case SimdOp::I32x4RelaxedDotI8x16I7x16AddS: WASM_SIMD_OP(OpKind::Ternary); } break; @@ -685,8 +668,8 @@ OpKind wasm::Classify(OpBytes op) { case ThreadOp::Limit: // Reject Limit for ThreadPrefix encoding break; - case ThreadOp::Wake: - return OpKind::Wake; + case ThreadOp::Notify: + return OpKind::Notify; case ThreadOp::I32Wait: case ThreadOp::I64Wait: return OpKind::Wait; @@ -750,7 +733,7 @@ OpKind wasm::Classify(OpBytes op) { case ThreadOp::I64AtomicXchg8U: case ThreadOp::I64AtomicXchg16U: case ThreadOp::I64AtomicXchg32U: - return OpKind::AtomicBinOp; + return OpKind::AtomicRMW; case ThreadOp::I32AtomicCmpXchg: case ThreadOp::I64AtomicCmpXchg: case ThreadOp::I32AtomicCmpXchg8U: @@ -758,7 +741,7 @@ OpKind wasm::Classify(OpBytes op) { case ThreadOp::I64AtomicCmpXchg8U: case ThreadOp::I64AtomicCmpXchg16U: case ThreadOp::I64AtomicCmpXchg32U: - return OpKind::AtomicCompareExchange; + return OpKind::AtomicCmpXchg; default: break; } @@ -821,12 +804,1183 @@ OpKind wasm::Classify(OpBytes op) { } MOZ_CRASH("unimplemented opcode"); } - -# undef WASM_GC_OP -# undef WASM_REF_OP - #endif // DEBUG +const char* OpBytes::toString() const { + switch (Op(b0)) { + case Op::Unreachable: + return "unreachable"; + case Op::Nop: + return "nop"; + case Op::Block: + return "block"; + case Op::Loop: + return "loop"; + case Op::If: + return "if"; + case Op::Else: + return "else"; + case Op::Try: + return "try"; + case Op::Catch: + return "catch"; + case Op::Throw: + return "throw"; + case Op::Rethrow: + return "rethrow"; + case Op::ThrowRef: + return "throw_ref"; + case Op::End: + return "end"; + case Op::Br: + return "br"; + case Op::BrIf: + return "br_if"; + case Op::BrTable: + return "br_table"; + case Op::Return: + return "return"; + case Op::Call: + return "call"; + case Op::CallIndirect: + return "call_indirect"; + case Op::ReturnCall: + return "return_call"; + case Op::ReturnCallIndirect: + return "return_call_indirect"; + case Op::CallRef: + return "call_ref"; + case Op::ReturnCallRef: + return "return_call_ref"; + case Op::Delegate: + return "delegate"; + case Op::CatchAll: + return "catch_all"; + case Op::Drop: + return "drop"; + case Op::SelectNumeric: + return "select"; + case Op::SelectTyped: + return "select"; + case Op::TryTable: + return "try_table"; + case Op::LocalGet: + return "local.get"; + case Op::LocalSet: + return "local.set"; + case Op::LocalTee: + return "local.tee"; + case Op::GlobalGet: + return "global.get"; + case Op::GlobalSet: + return "global.set"; + case Op::TableGet: + return "table.get"; + case Op::TableSet: + return "table.set"; + case Op::I32Load: + return "i32.load"; + case Op::I64Load: + return "i64.load"; + case Op::F32Load: + return "f32.load"; + case Op::F64Load: + return "f64.load"; + case Op::I32Load8S: + return "i32.load8_s"; + case Op::I32Load8U: + return "i32.load8_u"; + case Op::I32Load16S: + return "i32.load16_s"; + case Op::I32Load16U: + return "i32.load16_u"; + case Op::I64Load8S: + return "i64.load8_s"; + case Op::I64Load8U: + return "i64.load8_u"; + case Op::I64Load16S: + return "i64.load16_s"; + case Op::I64Load16U: + return "i64.load16_u"; + case Op::I64Load32S: + return "i64.load32_s"; + case Op::I64Load32U: + return "i64.load32_u"; + case Op::I32Store: + return "i32.store"; + case Op::I64Store: + return "i64.store"; + case Op::F32Store: + return "f32.store"; + case Op::F64Store: + return "f64.store"; + case Op::I32Store8: + return "i32.store8"; + case Op::I32Store16: + return "i32.store16"; + case Op::I64Store8: + return "i64.store8"; + case Op::I64Store16: + return "i64.store16"; + case Op::I64Store32: + return "i64.store32"; + case Op::MemorySize: + return "memory.size"; + case Op::MemoryGrow: + return "memory.grow"; + case Op::I32Const: + return "i32.const"; + case Op::I64Const: + return "i64.const"; + case Op::F32Const: + return "f32.const"; + case Op::F64Const: + return "f64.const"; + case Op::I32Eqz: + return "i32.eqz"; + case Op::I32Eq: + return "i32.eq"; + case Op::I32Ne: + return "i32.ne"; + case Op::I32LtS: + return "i32.lt_s"; + case Op::I32LtU: + return "i32.lt_u"; + case Op::I32GtS: + return "i32.gt_s"; + case Op::I32GtU: + return "i32.gt_u"; + case Op::I32LeS: + return "i32.le_s"; + case Op::I32LeU: + return "i32.le_u"; + case Op::I32GeS: + return "i32.ge_s"; + case Op::I32GeU: + return "i32.ge_u"; + case Op::I64Eqz: + return "i64.eqz"; + case Op::I64Eq: + return "i64.eq"; + case Op::I64Ne: + return "i64.ne"; + case Op::I64LtS: + return "i64.lt_s"; + case Op::I64LtU: + return "i64.lt_u"; + case Op::I64GtS: + return "i64.gt_s"; + case Op::I64GtU: + return "i64.gt_u"; + case Op::I64LeS: + return "i64.le_s"; + case Op::I64LeU: + return "i64.le_u"; + case Op::I64GeS: + return "i64.ge_s"; + case Op::I64GeU: + return "i64.ge_u"; + case Op::F32Eq: + return "f32.eq"; + case Op::F32Ne: + return "f32.ne"; + case Op::F32Lt: + return "f32.lt"; + case Op::F32Gt: + return "f32.gt"; + case Op::F32Le: + return "f32.le"; + case Op::F32Ge: + return "f32.ge"; + case Op::F64Eq: + return "f64.eq"; + case Op::F64Ne: + return "f64.ne"; + case Op::F64Lt: + return "f64.lt"; + case Op::F64Gt: + return "f64.gt"; + case Op::F64Le: + return "f64.le"; + case Op::F64Ge: + return "f64.ge"; + case Op::I32Clz: + return "i32.clz"; + case Op::I32Ctz: + return "i32.ctz"; + case Op::I32Popcnt: + return "i32.popcnt"; + case Op::I32Add: + return "i32.add"; + case Op::I32Sub: + return "i32.sub"; + case Op::I32Mul: + return "i32.mul"; + case Op::I32DivS: + return "i32.div_s"; + case Op::I32DivU: + return "i32.div_u"; + case Op::I32RemS: + return "i32.rem_s"; + case Op::I32RemU: + return "i32.rem_u"; + case Op::I32And: + return "i32.and"; + case Op::I32Or: + return "i32.or"; + case Op::I32Xor: + return "i32.xor"; + case Op::I32Shl: + return "i32.shl"; + case Op::I32ShrS: + return "i32.shr_s"; + case Op::I32ShrU: + return "i32.shr_u"; + case Op::I32Rotl: + return "i32.rotl"; + case Op::I32Rotr: + return "i32.rotr"; + case Op::I64Clz: + return "i64.clz"; + case Op::I64Ctz: + return "i64.ctz"; + case Op::I64Popcnt: + return "i64.popcnt"; + case Op::I64Add: + return "i64.add"; + case Op::I64Sub: + return "i64.sub"; + case Op::I64Mul: + return "i64.mul"; + case Op::I64DivS: + return "i64.div_s"; + case Op::I64DivU: + return "i64.div_u"; + case Op::I64RemS: + return "i64.rem_s"; + case Op::I64RemU: + return "i64.rem_u"; + case Op::I64And: + return "i64.and"; + case Op::I64Or: + return "i64.or"; + case Op::I64Xor: + return "i64.xor"; + case Op::I64Shl: + return "i64.shl"; + case Op::I64ShrS: + return "i64.shr_s"; + case Op::I64ShrU: + return "i64.shr_u"; + case Op::I64Rotl: + return "i64.rotl"; + case Op::I64Rotr: + return "i64.rotr"; + case Op::F32Abs: + return "f32.abs"; + case Op::F32Neg: + return "f32.neg"; + case Op::F32Ceil: + return "f32.ceil"; + case Op::F32Floor: + return "f32.floor"; + case Op::F32Trunc: + return "f32.trunc"; + case Op::F32Nearest: + return "f32.nearest"; + case Op::F32Sqrt: + return "f32.sqrt"; + case Op::F32Add: + return "f32.add"; + case Op::F32Sub: + return "f32.sub"; + case Op::F32Mul: + return "f32.mul"; + case Op::F32Div: + return "f32.div"; + case Op::F32Min: + return "f32.min"; + case Op::F32Max: + return "f32.max"; + case Op::F32CopySign: + return "f32.copysign"; + case Op::F64Abs: + return "f64.abs"; + case Op::F64Neg: + return "f64.neg"; + case Op::F64Ceil: + return "f64.ceil"; + case Op::F64Floor: + return "f64.floor"; + case Op::F64Trunc: + return "f64.trunc"; + case Op::F64Nearest: + return "f64.nearest"; + case Op::F64Sqrt: + return "f64.sqrt"; + case Op::F64Add: + return "f64.add"; + case Op::F64Sub: + return "f64.sub"; + case Op::F64Mul: + return "f64.mul"; + case Op::F64Div: + return "f64.div"; + case Op::F64Min: + return "f64.min"; + case Op::F64Max: + return "f64.max"; + case Op::F64CopySign: + return "f64.copysign"; + case Op::I32WrapI64: + return "i32.wrap_i64"; + case Op::I32TruncF32S: + return "i32.trunc_f32_s"; + case Op::I32TruncF32U: + return "i32.trunc_f32_u"; + case Op::I32TruncF64S: + return "i32.trunc_f64_s"; + case Op::I32TruncF64U: + return "i32.trunc_f64_u"; + case Op::I64ExtendI32S: + return "i64.extend_i32_s"; + case Op::I64ExtendI32U: + return "i64.extend_i32_u"; + case Op::I64TruncF32S: + return "i64.trunc_f32_s"; + case Op::I64TruncF32U: + return "i64.trunc_f32_u"; + case Op::I64TruncF64S: + return "i64.trunc_f64_s"; + case Op::I64TruncF64U: + return "i64.trunc_f64_u"; + case Op::F32ConvertI32S: + return "f32.convert_i32_s"; + case Op::F32ConvertI32U: + return "f32.convert_i32_u"; + case Op::F32ConvertI64S: + return "f32.convert_i64_s"; + case Op::F32ConvertI64U: + return "f32.convert_i64_u"; + case Op::F32DemoteF64: + return "f32.demote_f64"; + case Op::F64ConvertI32S: + return "f64.convert_i32_s"; + case Op::F64ConvertI32U: + return "f64.convert_i32_u"; + case Op::F64ConvertI64S: + return "f64.convert_i64_s"; + case Op::F64ConvertI64U: + return "f64.convert_i64_u"; + case Op::F64PromoteF32: + return "f64.promote_f32"; + case Op::I32ReinterpretF32: + return "i32.reinterpret_f32"; + case Op::I64ReinterpretF64: + return "i64.reinterpret_f64"; + case Op::F32ReinterpretI32: + return "f32.reinterpret_i32"; + case Op::F64ReinterpretI64: + return "f64.reinterpret_i64"; + case Op::I32Extend8S: + return "i32.extend8_s"; + case Op::I32Extend16S: + return "i32.extend16_s"; + case Op::I64Extend8S: + return "i64.extend8_s"; + case Op::I64Extend16S: + return "i64.extend16_s"; + case Op::I64Extend32S: + return "i64.extend32_s"; + case Op::RefNull: + return "ref.null"; + case Op::RefIsNull: + return "ref.is_null"; + case Op::RefFunc: + return "ref.func"; + case Op::RefAsNonNull: + return "ref.as_non_null"; + case Op::BrOnNull: + return "br_on_null"; + case Op::RefEq: + return "ref.eq"; + case Op::BrOnNonNull: + return "br_on_non_null"; + case Op::GcPrefix: { + switch (GcOp(b1)) { + case GcOp::StructNew: + return "struct.new"; + case GcOp::StructNewDefault: + return "struct.new_default"; + case GcOp::StructGet: + return "struct.get"; + case GcOp::StructGetS: + return "struct.get_s"; + case GcOp::StructGetU: + return "struct.get_u"; + case GcOp::StructSet: + return "struct.set"; + case GcOp::ArrayNew: + return "array.new"; + case GcOp::ArrayNewDefault: + return "array.new_default"; + case GcOp::ArrayNewFixed: + return "array.new_fixed"; + case GcOp::ArrayNewData: + return "array.new_data"; + case GcOp::ArrayNewElem: + return "array.new_elem"; + case GcOp::ArrayGet: + return "array.get"; + case GcOp::ArrayGetS: + return "array.get_s"; + case GcOp::ArrayGetU: + return "array.get_u"; + case GcOp::ArraySet: + return "array.set"; + case GcOp::ArrayLen: + return "array.len"; + case GcOp::ArrayFill: + return "array.fill"; + case GcOp::ArrayCopy: + return "array.copy"; + case GcOp::ArrayInitData: + return "array.init_data"; + case GcOp::ArrayInitElem: + return "array.init_elem"; + case GcOp::RefTest: + return "ref.test"; + case GcOp::RefTestNull: + return "ref.test"; + case GcOp::RefCast: + return "ref.cast"; + case GcOp::RefCastNull: + return "ref.cast"; + case GcOp::BrOnCast: + return "br_on_cast"; + case GcOp::BrOnCastFail: + return "br_on_cast_fail"; + case GcOp::AnyConvertExtern: + return "any.convert_extern"; + case GcOp::ExternConvertAny: + return "extern.convert_any"; + case GcOp::RefI31: + return "ref.i31"; + case GcOp::I31GetS: + return "i31.get_s"; + case GcOp::I31GetU: + return "i31.get_u"; + default: + return "unknown"; + } + } + case Op::MiscPrefix: { + switch (MiscOp(b1)) { + case MiscOp::I32TruncSatF32S: + return "i32.trunc_sat_f32_s"; + case MiscOp::I32TruncSatF32U: + return "i32.trunc_sat_f32_u"; + case MiscOp::I32TruncSatF64S: + return "i32.trunc_sat_f64_s"; + case MiscOp::I32TruncSatF64U: + return "i32.trunc_sat_f64_u"; + case MiscOp::I64TruncSatF32S: + return "i64.trunc_sat_f32_s"; + case MiscOp::I64TruncSatF32U: + return "i64.trunc_sat_f32_u"; + case MiscOp::I64TruncSatF64S: + return "i64.trunc_sat_f64_s"; + case MiscOp::I64TruncSatF64U: + return "i64.trunc_sat_f64_u"; + case MiscOp::MemoryInit: + return "memory.init"; + case MiscOp::DataDrop: + return "data.drop"; + case MiscOp::MemoryCopy: + return "memory.copy"; + case MiscOp::MemoryFill: + return "memory.fill"; + case MiscOp::TableInit: + return "table.init"; + case MiscOp::ElemDrop: + return "elem.drop"; + case MiscOp::TableCopy: + return "table.copy"; + case MiscOp::TableGrow: + return "table.grow"; + case MiscOp::TableSize: + return "table.size"; + case MiscOp::TableFill: + return "table.fill"; + case MiscOp::MemoryDiscard: + return "memory.discard"; + default: + return "unknown"; + } + } + case Op::SimdPrefix: { + switch (SimdOp(b1)) { + case SimdOp::V128Load: + return "v128.load"; + case SimdOp::V128Load8x8S: + return "v128.load8x8_s"; + case SimdOp::V128Load8x8U: + return "v128.load8x8_u"; + case SimdOp::V128Load16x4S: + return "v128.load16x4_s"; + case SimdOp::V128Load16x4U: + return "v128.load16x4_u"; + case SimdOp::V128Load32x2S: + return "v128.load32x2_s"; + case SimdOp::V128Load32x2U: + return "v128.load32x2_u"; + case SimdOp::V128Load8Splat: + return "v128.load8_splat"; + case SimdOp::V128Load16Splat: + return "v128.load16_splat"; + case SimdOp::V128Load32Splat: + return "v128.load32_splat"; + case SimdOp::V128Load64Splat: + return "v128.load64_splat"; + case SimdOp::V128Store: + return "v128.store"; + case SimdOp::V128Const: + return "v128.const"; + case SimdOp::I8x16Shuffle: + return "i8x16.shuffle"; + case SimdOp::I8x16Swizzle: + return "i8x16.swizzle"; + case SimdOp::I8x16Splat: + return "i8x16.splat"; + case SimdOp::I16x8Splat: + return "i16x8.splat"; + case SimdOp::I32x4Splat: + return "i32x4.splat"; + case SimdOp::I64x2Splat: + return "i64x2.splat"; + case SimdOp::F32x4Splat: + return "f32x4.splat"; + case SimdOp::F64x2Splat: + return "f64x2.splat"; + case SimdOp::I8x16ExtractLaneS: + return "i8x16.extract_lane_s"; + case SimdOp::I8x16ExtractLaneU: + return "i8x16.extract_lane_u"; + case SimdOp::I8x16ReplaceLane: + return "i8x16.replace_lane"; + case SimdOp::I16x8ExtractLaneS: + return "i16x8.extract_lane_s"; + case SimdOp::I16x8ExtractLaneU: + return "i16x8.extract_lane_u"; + case SimdOp::I16x8ReplaceLane: + return "i16x8.replace_lane"; + case SimdOp::I32x4ExtractLane: + return "i32x4.extract_lane"; + case SimdOp::I32x4ReplaceLane: + return "i32x4.replace_lane"; + case SimdOp::I64x2ExtractLane: + return "i64x2.extract_lane"; + case SimdOp::I64x2ReplaceLane: + return "i64x2.replace_lane"; + case SimdOp::F32x4ExtractLane: + return "f32x4.extract_lane"; + case SimdOp::F32x4ReplaceLane: + return "f32x4.replace_lane"; + case SimdOp::F64x2ExtractLane: + return "f64x2.extract_lane"; + case SimdOp::F64x2ReplaceLane: + return "f64x2.replace_lane"; + case SimdOp::I8x16Eq: + return "i8x16.eq"; + case SimdOp::I8x16Ne: + return "i8x16.ne"; + case SimdOp::I8x16LtS: + return "i8x16.lt_s"; + case SimdOp::I8x16LtU: + return "i8x16.lt_u"; + case SimdOp::I8x16GtS: + return "i8x16.gt_s"; + case SimdOp::I8x16GtU: + return "i8x16.gt_u"; + case SimdOp::I8x16LeS: + return "i8x16.le_s"; + case SimdOp::I8x16LeU: + return "i8x16.le_u"; + case SimdOp::I8x16GeS: + return "i8x16.ge_s"; + case SimdOp::I8x16GeU: + return "i8x16.ge_u"; + case SimdOp::I16x8Eq: + return "i16x8.eq"; + case SimdOp::I16x8Ne: + return "i16x8.ne"; + case SimdOp::I16x8LtS: + return "i16x8.lt_s"; + case SimdOp::I16x8LtU: + return "i16x8.lt_u"; + case SimdOp::I16x8GtS: + return "i16x8.gt_s"; + case SimdOp::I16x8GtU: + return "i16x8.gt_u"; + case SimdOp::I16x8LeS: + return "i16x8.le_s"; + case SimdOp::I16x8LeU: + return "i16x8.le_u"; + case SimdOp::I16x8GeS: + return "i16x8.ge_s"; + case SimdOp::I16x8GeU: + return "i16x8.ge_u"; + case SimdOp::I32x4Eq: + return "i32x4.eq"; + case SimdOp::I32x4Ne: + return "i32x4.ne"; + case SimdOp::I32x4LtS: + return "i32x4.lt_s"; + case SimdOp::I32x4LtU: + return "i32x4.lt_u"; + case SimdOp::I32x4GtS: + return "i32x4.gt_s"; + case SimdOp::I32x4GtU: + return "i32x4.gt_u"; + case SimdOp::I32x4LeS: + return "i32x4.le_s"; + case SimdOp::I32x4LeU: + return "i32x4.le_u"; + case SimdOp::I32x4GeS: + return "i32x4.ge_s"; + case SimdOp::I32x4GeU: + return "i32x4.ge_u"; + case SimdOp::F32x4Eq: + return "f32x4.eq"; + case SimdOp::F32x4Ne: + return "f32x4.ne"; + case SimdOp::F32x4Lt: + return "f32x4.lt"; + case SimdOp::F32x4Gt: + return "f32x4.gt"; + case SimdOp::F32x4Le: + return "f32x4.le"; + case SimdOp::F32x4Ge: + return "f32x4.ge"; + case SimdOp::F64x2Eq: + return "f64x2.eq"; + case SimdOp::F64x2Ne: + return "f64x2.ne"; + case SimdOp::F64x2Lt: + return "f64x2.lt"; + case SimdOp::F64x2Gt: + return "f64x2.gt"; + case SimdOp::F64x2Le: + return "f64x2.le"; + case SimdOp::F64x2Ge: + return "f64x2.ge"; + case SimdOp::V128Not: + return "v128.not"; + case SimdOp::V128And: + return "v128.and"; + case SimdOp::V128AndNot: + return "v128.andnot"; + case SimdOp::V128Or: + return "v128.or"; + case SimdOp::V128Xor: + return "v128.xor"; + case SimdOp::V128Bitselect: + return "v128.bit_select"; + case SimdOp::V128AnyTrue: + return "v128.any_true"; + case SimdOp::V128Load8Lane: + return "v128.load8_lane"; + case SimdOp::V128Load16Lane: + return "v128.load16_lane"; + case SimdOp::V128Load32Lane: + return "v128.load32_lane"; + case SimdOp::V128Load64Lane: + return "v128.load64_lane"; + case SimdOp::V128Store8Lane: + return "v128.store8_lane"; + case SimdOp::V128Store16Lane: + return "v128.store16_lane"; + case SimdOp::V128Store32Lane: + return "v128.store32_lane"; + case SimdOp::V128Store64Lane: + return "v128.store64_lane"; + case SimdOp::V128Load32Zero: + return "v128.load32_zero"; + case SimdOp::V128Load64Zero: + return "v128.load64_zero"; + case SimdOp::F32x4DemoteF64x2Zero: + return "f32x4.demote_f64x2_zero"; + case SimdOp::F64x2PromoteLowF32x4: + return "f64x2.promote_low_f32x4"; + case SimdOp::I8x16Abs: + return "i8x16.abs"; + case SimdOp::I8x16Neg: + return "i8x16.neg"; + case SimdOp::I8x16Popcnt: + return "i8x16.popcnt"; + case SimdOp::I8x16AllTrue: + return "i8x16.all_true"; + case SimdOp::I8x16Bitmask: + return "i8x16.bitmask"; + case SimdOp::I8x16NarrowI16x8S: + return "i8x16.narrow_i16x8_s"; + case SimdOp::I8x16NarrowI16x8U: + return "i8x16.narrow_i16x8_u"; + case SimdOp::F32x4Ceil: + return "f32x4.ceil"; + case SimdOp::F32x4Floor: + return "f32x4.floor"; + case SimdOp::F32x4Trunc: + return "f32x4.trunc"; + case SimdOp::F32x4Nearest: + return "f32x4.nearest"; + case SimdOp::I8x16Shl: + return "i8x16.shl"; + case SimdOp::I8x16ShrS: + return "i8x16.shr_s"; + case SimdOp::I8x16ShrU: + return "i8x16.shr_u"; + case SimdOp::I8x16Add: + return "i8x16.add"; + case SimdOp::I8x16AddSatS: + return "i8x16.add_sat_s"; + case SimdOp::I8x16AddSatU: + return "i8x16.add_sat_u"; + case SimdOp::I8x16Sub: + return "i8x16.sub"; + case SimdOp::I8x16SubSatS: + return "i8x16.sub_sat_s"; + case SimdOp::I8x16SubSatU: + return "i8x16.sub_sat_u"; + case SimdOp::F64x2Ceil: + return "f64x2.ceil"; + case SimdOp::F64x2Floor: + return "f64x2.floor"; + case SimdOp::I8x16MinS: + return "i8x16.min_s"; + case SimdOp::I8x16MinU: + return "i8x16.min_u"; + case SimdOp::I8x16MaxS: + return "i8x16.max_s"; + case SimdOp::I8x16MaxU: + return "i8x16.max_u"; + case SimdOp::F64x2Trunc: + return "f64x2.trunc"; + case SimdOp::I8x16AvgrU: + return "i8x16.avgr_u"; + case SimdOp::I16x8ExtaddPairwiseI8x16S: + return "i16x8.extadd_pairwise_i8x16_s"; + case SimdOp::I16x8ExtaddPairwiseI8x16U: + return "i16x8.extadd_pairwise_i8x16_u"; + case SimdOp::I32x4ExtaddPairwiseI16x8S: + return "i32x4.extadd_pairwise_i16x8_s"; + case SimdOp::I32x4ExtaddPairwiseI16x8U: + return "i32x4.extadd_pairwise_i16x8_u"; + case SimdOp::I16x8Abs: + return "i16x8.abs"; + case SimdOp::I16x8Neg: + return "i16x8.neg"; + case SimdOp::I16x8Q15MulrSatS: + return "i16x8.q15mulr_sat_s"; + case SimdOp::I16x8AllTrue: + return "i16x8.all_true"; + case SimdOp::I16x8Bitmask: + return "i16x8.bitmask"; + case SimdOp::I16x8NarrowI32x4S: + return "i16x8.narrow_i32x4_s"; + case SimdOp::I16x8NarrowI32x4U: + return "i16x8.narrow_i32x4_u"; + case SimdOp::I16x8ExtendLowI8x16S: + return "i16x8.extend_low_i8x16_s"; + case SimdOp::I16x8ExtendHighI8x16S: + return "i16x8.extend_high_i8x16_s"; + case SimdOp::I16x8ExtendLowI8x16U: + return "i16x8.extend_low_i8x16_u"; + case SimdOp::I16x8ExtendHighI8x16U: + return "i16x8.extend_high_i8x16_u"; + case SimdOp::I16x8Shl: + return "i16x8.shl"; + case SimdOp::I16x8ShrS: + return "i16x8.shr_s"; + case SimdOp::I16x8ShrU: + return "i16x8.shr_u"; + case SimdOp::I16x8Add: + return "i16x8.add"; + case SimdOp::I16x8AddSatS: + return "i16x8.add_sat_s"; + case SimdOp::I16x8AddSatU: + return "i16x8.add_sat_u"; + case SimdOp::I16x8Sub: + return "i16x8.sub"; + case SimdOp::I16x8SubSatS: + return "i16x8.sub_sat_s"; + case SimdOp::I16x8SubSatU: + return "i16x8.sub_sat_u"; + case SimdOp::F64x2Nearest: + return "f64x2.nearest"; + case SimdOp::I16x8Mul: + return "i16x8.mul"; + case SimdOp::I16x8MinS: + return "i16x8.min_s"; + case SimdOp::I16x8MinU: + return "i16x8.min_u"; + case SimdOp::I16x8MaxS: + return "i16x8.max_s"; + case SimdOp::I16x8MaxU: + return "i16x8.max_u"; + case SimdOp::I16x8AvgrU: + return "i16x8.avgr_u"; + case SimdOp::I16x8ExtmulLowI8x16S: + return "i16x8.extmul_low_i8x16_s"; + case SimdOp::I16x8ExtmulHighI8x16S: + return "i16x8.extmul_high_i8x16_s"; + case SimdOp::I16x8ExtmulLowI8x16U: + return "i16x8.extmul_low_i8x16_u"; + case SimdOp::I16x8ExtmulHighI8x16U: + return "i16x8.extmul_high_i8x16_u"; + case SimdOp::I32x4Abs: + return "i32x4.abs"; + case SimdOp::I32x4Neg: + return "i32x4.neg"; + case SimdOp::I32x4AllTrue: + return "i32x4.all_true"; + case SimdOp::I32x4Bitmask: + return "i32x4.bitmask"; + case SimdOp::I32x4ExtendLowI16x8S: + return "i32x4.extend_low_i16x8_s"; + case SimdOp::I32x4ExtendHighI16x8S: + return "i32x4.extend_high_i16x8_s"; + case SimdOp::I32x4ExtendLowI16x8U: + return "i32x4.extend_low_i16x8_u"; + case SimdOp::I32x4ExtendHighI16x8U: + return "i32x4.extend_high_i16x8_u"; + case SimdOp::I32x4Shl: + return "i32x4.shl"; + case SimdOp::I32x4ShrS: + return "i32x4.shr_s"; + case SimdOp::I32x4ShrU: + return "i32x4.shr_u"; + case SimdOp::I32x4Add: + return "i32x4.add"; + case SimdOp::I32x4Sub: + return "i32x4.sub"; + case SimdOp::I32x4Mul: + return "i32x4.mul"; + case SimdOp::I32x4MinS: + return "i32x4.min_s"; + case SimdOp::I32x4MinU: + return "i32x4.min_u"; + case SimdOp::I32x4MaxS: + return "i32x4.max_s"; + case SimdOp::I32x4MaxU: + return "i32x4.max_u"; + case SimdOp::I32x4DotI16x8S: + return "i32x4.dot_i16x8_s"; + case SimdOp::I32x4ExtmulLowI16x8S: + return "i32x4.extmul_low_i16x8_s"; + case SimdOp::I32x4ExtmulHighI16x8S: + return "i32x4.extmul_high_i16x8_s"; + case SimdOp::I32x4ExtmulLowI16x8U: + return "i32x4.extmul_low_i16x8_u"; + case SimdOp::I32x4ExtmulHighI16x8U: + return "i32x4.extmul_high_i16x8_u"; + case SimdOp::I64x2Abs: + return "i64x2.abs"; + case SimdOp::I64x2Neg: + return "i64x2.neg"; + case SimdOp::I64x2AllTrue: + return "i64x2.all_true"; + case SimdOp::I64x2Bitmask: + return "i64x2.bitmask"; + case SimdOp::I64x2ExtendLowI32x4S: + return "i64x2.extend_low_i32x4_s"; + case SimdOp::I64x2ExtendHighI32x4S: + return "i64x2.extend_high_i32x4_s"; + case SimdOp::I64x2ExtendLowI32x4U: + return "i64x2.extend_low_i32x4_u"; + case SimdOp::I64x2ExtendHighI32x4U: + return "i64x2.extend_high_i32x4_u"; + case SimdOp::I64x2Shl: + return "i64x2.shl"; + case SimdOp::I64x2ShrS: + return "i64x2.shr_s"; + case SimdOp::I64x2ShrU: + return "i64x2.shr_u"; + case SimdOp::I64x2Add: + return "i64x2.add"; + case SimdOp::I64x2Sub: + return "i64x2.sub"; + case SimdOp::I64x2Mul: + return "i64x2.mul"; + case SimdOp::I64x2Eq: + return "i64x2.eq"; + case SimdOp::I64x2Ne: + return "i64x2.ne"; + case SimdOp::I64x2LtS: + return "i64x2.lt_s"; + case SimdOp::I64x2GtS: + return "i64x2.gt_s"; + case SimdOp::I64x2LeS: + return "i64x2.le_s"; + case SimdOp::I64x2GeS: + return "i64x2.ge_s"; + case SimdOp::I64x2ExtmulLowI32x4S: + return "i64x2.extmul_low_i32x4_s"; + case SimdOp::I64x2ExtmulHighI32x4S: + return "i64x2.extmul_high_i32x4_s"; + case SimdOp::I64x2ExtmulLowI32x4U: + return "i64x2.extmul_low_i32x4_u"; + case SimdOp::I64x2ExtmulHighI32x4U: + return "i64x2.extmul_high_i32x4_u"; + case SimdOp::F32x4Abs: + return "f32x4.abs"; + case SimdOp::F32x4Neg: + return "f32x4.neg"; + case SimdOp::F32x4Sqrt: + return "f32x4.sqrt"; + case SimdOp::F32x4Add: + return "f32x4.add"; + case SimdOp::F32x4Sub: + return "f32x4.sub"; + case SimdOp::F32x4Mul: + return "f32x4.mul"; + case SimdOp::F32x4Div: + return "f32x4.div"; + case SimdOp::F32x4Min: + return "f32x4.min"; + case SimdOp::F32x4Max: + return "f32x4.max"; + case SimdOp::F32x4PMin: + return "f32x4.pmin"; + case SimdOp::F32x4PMax: + return "f32x4.pmax"; + case SimdOp::F64x2Abs: + return "f64x2.abs"; + case SimdOp::F64x2Neg: + return "f64x2.neg"; + case SimdOp::F64x2Sqrt: + return "f64x2.sqrt"; + case SimdOp::F64x2Add: + return "f64x2.add"; + case SimdOp::F64x2Sub: + return "f64x2.sub"; + case SimdOp::F64x2Mul: + return "f64x2.mul"; + case SimdOp::F64x2Div: + return "f64x2.div"; + case SimdOp::F64x2Min: + return "f64x2.min"; + case SimdOp::F64x2Max: + return "f64x2.max"; + case SimdOp::F64x2PMin: + return "f64x2.pmin"; + case SimdOp::F64x2PMax: + return "f64x2.pmax"; + case SimdOp::I32x4TruncSatF32x4S: + return "i32x4.trunc_sat_f32x4_s"; + case SimdOp::I32x4TruncSatF32x4U: + return "i32x4.trunc_sat_f32x4_u"; + case SimdOp::F32x4ConvertI32x4S: + return "f32x4.convert_i32x4_s"; + case SimdOp::F32x4ConvertI32x4U: + return "f32x4.convert_i32x4_u"; + case SimdOp::I32x4TruncSatF64x2SZero: + return "i32x4.trunc_sat_f64x2_s_zero"; + case SimdOp::I32x4TruncSatF64x2UZero: + return "i32x4.trunc_sat_f64x2_u_zero"; + case SimdOp::F64x2ConvertLowI32x4S: + return "f64x2.convert_low_i32x4_s"; + case SimdOp::F64x2ConvertLowI32x4U: + return "f64x2.convert_low_i32x4_u"; + case SimdOp::I8x16RelaxedSwizzle: + return "i8x16.relaxed_swizzle"; + case SimdOp::I32x4RelaxedTruncF32x4S: + return "i32x4.relaxed_trunc_f32x4_s"; + case SimdOp::I32x4RelaxedTruncF32x4U: + return "i32x4.relaxed_trunc_f32x4_u"; + case SimdOp::I32x4RelaxedTruncF64x2SZero: + return "i32x4.relaxed_trunc_f64x2_s_zero"; + case SimdOp::I32x4RelaxedTruncF64x2UZero: + return "i32x4.relaxed_trunc_f64x2_u_zero"; + case SimdOp::F32x4RelaxedMadd: + return "f32x4.relaxed_madd"; + case SimdOp::F32x4RelaxedNmadd: + return "f32x4.relaxed_nmadd"; + case SimdOp::F64x2RelaxedMadd: + return "f64x2.relaxed_madd"; + case SimdOp::F64x2RelaxedNmadd: + return "f64x2.relaxed_nmadd"; + case SimdOp::I8x16RelaxedLaneSelect: + return "i8x16.relaxed_laneselect"; + case SimdOp::I16x8RelaxedLaneSelect: + return "i16x8.relaxed_laneselect"; + case SimdOp::I32x4RelaxedLaneSelect: + return "i32x4.relaxed_laneselect"; + case SimdOp::I64x2RelaxedLaneSelect: + return "i64x2.relaxed_laneselect"; + case SimdOp::F32x4RelaxedMin: + return "f32x4.relaxed_min"; + case SimdOp::F32x4RelaxedMax: + return "f32x4.relaxed_max"; + case SimdOp::F64x2RelaxedMin: + return "f64x2.relaxed_min"; + case SimdOp::F64x2RelaxedMax: + return "f64x2.relaxed_max"; + case SimdOp::I16x8RelaxedQ15MulrS: + return "i16x8.relaxed_q15mulr_s"; + case SimdOp::I16x8RelaxedDotI8x16I7x16S: + return "i16x8.relaxed_dot_i8x16_i7x16_s"; + case SimdOp::I32x4RelaxedDotI8x16I7x16AddS: + return "i32x4.relaxed_dot_i8x16_i7x16_add_s"; + default: + return "unknown"; + } + } + case Op::ThreadPrefix: { + switch (ThreadOp(b1)) { + case ThreadOp::Notify: + return "memory.atomic.notify"; + case ThreadOp::I32Wait: + return "memory.atomic.wait32"; + case ThreadOp::I64Wait: + return "memory.atomic.wait64"; + case ThreadOp::Fence: + return "atomic.fence"; + case ThreadOp::I32AtomicLoad: + return "i32.atomic.load"; + case ThreadOp::I64AtomicLoad: + return "i64.atomic.load"; + case ThreadOp::I32AtomicLoad8U: + return "i32.atomic.load8u"; + case ThreadOp::I32AtomicLoad16U: + return "i32.atomic.load16_u"; + case ThreadOp::I64AtomicLoad8U: + return "i64.atomic.load8u"; + case ThreadOp::I64AtomicLoad16U: + return "i64.atomic.load16_u"; + case ThreadOp::I64AtomicLoad32U: + return "i64.atomic.load32_u"; + case ThreadOp::I32AtomicStore: + return "i32.atomic.store"; + case ThreadOp::I64AtomicStore: + return "i64.atomic.store"; + case ThreadOp::I32AtomicStore8U: + return "i32.atomic.store8_u"; + case ThreadOp::I32AtomicStore16U: + return "i32.atomic.store16_u"; + case ThreadOp::I64AtomicStore8U: + return "i64.atomic.store8_u"; + case ThreadOp::I64AtomicStore16U: + return "i64.atomic.store16_u"; + case ThreadOp::I64AtomicStore32U: + return "i64.atomic.store32_u"; + case ThreadOp::I32AtomicAdd: + return "i32.atomic.rmw.add"; + case ThreadOp::I64AtomicAdd: + return "i64.atomic.rmw.add"; + case ThreadOp::I32AtomicAdd8U: + return "i32.atomic.rmw8.add_u"; + case ThreadOp::I32AtomicAdd16U: + return "i32.atomic.rmw16.add_u"; + case ThreadOp::I64AtomicAdd8U: + return "i64.atomic.rmw8.add_u"; + case ThreadOp::I64AtomicAdd16U: + return "i64.atomic.rmw16.add_u"; + case ThreadOp::I64AtomicAdd32U: + return "i64.atomic.rmw32.add_u"; + case ThreadOp::I32AtomicSub: + return "i32.atomic.rmw.sub"; + case ThreadOp::I64AtomicSub: + return "i64.atomic.rmw.sub"; + case ThreadOp::I32AtomicSub8U: + return "i32.atomic.rmw8.sub_u"; + case ThreadOp::I32AtomicSub16U: + return "i32.atomic.rmw16.sub_u"; + case ThreadOp::I64AtomicSub8U: + return "i64.atomic.rmw8.sub_u"; + case ThreadOp::I64AtomicSub16U: + return "i64.atomic.rmw16.sub_u"; + case ThreadOp::I64AtomicSub32U: + return "i64.atomic.rmw32.sub_u"; + case ThreadOp::I32AtomicAnd: + return "i32.atomic.rmw.and"; + case ThreadOp::I64AtomicAnd: + return "i64.atomic.rmw.and"; + case ThreadOp::I32AtomicAnd8U: + return "i32.atomic.rmw.and8_u"; + case ThreadOp::I32AtomicAnd16U: + return "i32.atomic.rmw16.and_u"; + case ThreadOp::I64AtomicAnd8U: + return "i64.atomic.rmw8.and_u"; + case ThreadOp::I64AtomicAnd16U: + return "i64.atomic.rmw16.and_u"; + case ThreadOp::I64AtomicAnd32U: + return "i64.atomic.rmw32.and_u"; + case ThreadOp::I32AtomicOr: + return "i32.atomic.rmw.or"; + case ThreadOp::I64AtomicOr: + return "i64.atomic.rmw.or"; + case ThreadOp::I32AtomicOr8U: + return "i32.atomic.rmw8.or_u"; + case ThreadOp::I32AtomicOr16U: + return "i32.atomic.rmw16.or_u"; + case ThreadOp::I64AtomicOr8U: + return "i64.atomic.rmw8.or_u"; + case ThreadOp::I64AtomicOr16U: + return "i64.atomic.rmw16.or_u"; + case ThreadOp::I64AtomicOr32U: + return "i64.atomic.rmw32.or_u"; + case ThreadOp::I32AtomicXor: + return "i32.atomic.rmw.xor"; + case ThreadOp::I64AtomicXor: + return "i64.atomic.rmw.xor"; + case ThreadOp::I32AtomicXor8U: + return "i32.atomic.rmw8.xor_u"; + case ThreadOp::I32AtomicXor16U: + return "i32.atomic.rmw16.xor_u"; + case ThreadOp::I64AtomicXor8U: + return "i64.atomic.rmw8.xor_u"; + case ThreadOp::I64AtomicXor16U: + return "i64.atomic.rmw16.xor_u"; + case ThreadOp::I64AtomicXor32U: + return "i64.atomic.rmw32.xor_u"; + case ThreadOp::I32AtomicXchg: + return "i32.atomic.rmw.xchg"; + case ThreadOp::I64AtomicXchg: + return "i64.atomic.rmw.xchg"; + case ThreadOp::I32AtomicXchg8U: + return "i32.atomic.rmw8.xchg_u"; + case ThreadOp::I32AtomicXchg16U: + return "i32.atomic.rmw16.xchg_u"; + case ThreadOp::I64AtomicXchg8U: + return "i64.atomic.rmw8.xchg_u"; + case ThreadOp::I64AtomicXchg16U: + return "i64.atomic.rmw16.xchg_u"; + case ThreadOp::I64AtomicXchg32U: + return "i64.atomic.rmw32.xchg_u"; + case ThreadOp::I32AtomicCmpXchg: + return "i32.atomic.rmw.cmpxchg"; + case ThreadOp::I64AtomicCmpXchg: + return "i64.atomic.rmw.cmpxchg"; + case ThreadOp::I32AtomicCmpXchg8U: + return "i32.atomic.rmw8.cmpxchg_u"; + case ThreadOp::I32AtomicCmpXchg16U: + return "i32.atomic.rmw16.cmpxchg_u"; + case ThreadOp::I64AtomicCmpXchg8U: + return "i64.atomic.rmw8.cmpxchg_u"; + case ThreadOp::I64AtomicCmpXchg16U: + return "i64.atomic.rmw16.cmpxchg_u"; + case ThreadOp::I64AtomicCmpXchg32U: + return "i64.atomic.rmw32.cmpxchg_u"; + default: + return "unknown"; + } + } + default: + return "unknown"; + } +} + bool UnsetLocalsState::init(const ValTypeVector& locals, size_t numParams) { MOZ_ASSERT(setLocalsStack_.empty()); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.h b/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.h index 0805fb1b37c..c9157112abd 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmOpIter.h @@ -25,9 +25,10 @@ #include #include "js/Printf.h" +#include "wasm/WasmBinary.h" #include "wasm/WasmBuiltinModule.h" +#include "wasm/WasmMetadata.h" #include "wasm/WasmUtility.h" -#include "wasm/WasmValidate.h" namespace js { namespace wasm { @@ -135,11 +136,11 @@ enum class OpKind { Loop, Unreachable, Drop, - I32, - I64, - F32, - F64, - V128, + I32Const, + I64Const, + F32Const, + F64Const, + V128Const, Br, BrIf, BrTable, @@ -165,10 +166,8 @@ enum class OpKind { ReturnCall, CallIndirect, ReturnCallIndirect, -# ifdef ENABLE_WASM_GC CallRef, ReturnCallRef, -# endif OldCallDirect, OldCallIndirect, Return, @@ -176,12 +175,12 @@ enum class OpKind { Else, End, Wait, - Wake, + Notify, Fence, AtomicLoad, AtomicStore, - AtomicBinOp, - AtomicCompareExchange, + AtomicRMW, + AtomicCmpXchg, MemOrTableCopy, DataOrElemDrop, MemFill, @@ -194,6 +193,7 @@ enum class OpKind { TableSize, RefNull, RefFunc, + RefIsNull, RefAsNonNull, BrOnNull, BrOnNonNull, @@ -286,6 +286,7 @@ class ControlStackEntry { } uint32_t valueStackBase() const { return valueStackBase_; } ControlItem& controlItem() { return typeAndItem_.second(); } + const ControlItem& controlItem() const { return typeAndItem_.second(); } void setPolymorphicBase() { polymorphicBase_ = true; } bool polymorphicBase() const { return polymorphicBase_; } @@ -420,17 +421,13 @@ class MOZ_STACK_CLASS OpIter : private Policy { private: Kind kind_; Decoder& d_; - const ModuleEnvironment& env_; + const CodeMetadata& codeMeta_; + const ValTypeVector& locals_; TypeAndValueStack valueStack_; TypeAndValueStack elseParamStack_; ControlStack controlStack_; UnsetLocalsState unsetLocals_; - // The exclusive max index of a global that can be accessed by global.get in - // this expression. When GC is enabled, this is any previously defined - // immutable global. Otherwise this is always set to zero, and only imported - // immutable globals are allowed. - uint32_t maxInitializedGlobalsIndexPlus1_; FeatureUsage featureUsage_; uint32_t lastBranchHintIndex_; BranchHintVector* branchHintVector_; @@ -537,35 +534,28 @@ class MOZ_STACK_CLASS OpIter : private Policy { inline bool checkIsSubtypeOf(ResultType params, ResultType results); -#ifdef ENABLE_WASM_GC inline bool checkIsSubtypeOf(uint32_t actualTypeIndex, uint32_t expectedTypeIndex); -#endif public: -#ifdef DEBUG - explicit OpIter(const ModuleEnvironment& env, Decoder& decoder, - Kind kind = OpIter::Func) + explicit OpIter(const CodeMetadata& codeMeta, Decoder& decoder, + const ValTypeVector& locals, Kind kind = OpIter::Func) : kind_(kind), d_(decoder), - env_(env), - maxInitializedGlobalsIndexPlus1_(0), + codeMeta_(codeMeta), + locals_(locals), featureUsage_(FeatureUsage::None), branchHintVector_(nullptr), +#ifdef DEBUG op_(OpBytes(Op::Limit)), - offsetOfLastReadOp_(0) {} -#else - explicit OpIter(const ModuleEnvironment& env, Decoder& decoder, - Kind kind = OpIter::Func) - : kind_(kind), - d_(decoder), - env_(env), - maxInitializedGlobalsIndexPlus1_(0), - featureUsage_(FeatureUsage::None), - offsetOfLastReadOp_(0) {} #endif + offsetOfLastReadOp_(0) { + } FeatureUsage featureUsage() const { return featureUsage_; } + void addFeatureUsage(FeatureUsage featureUsage) { + featureUsage_ |= featureUsage; + } // Return the decoding byte offset. uint32_t currentOffset() const { return d_.currentOffset(); } @@ -608,7 +598,7 @@ class MOZ_STACK_CLASS OpIter : private Policy { // order, we keep track of the most recently accessed index. // Retrieving branch hints is also done in order inside a function. BranchHint getBranchHint(uint32_t funcIndex, uint32_t branchOffset) { - if (!env_.branchHintingEnabled()) { + if (!codeMeta_.branchHintingEnabled()) { return BranchHint::Invalid; } @@ -633,8 +623,7 @@ class MOZ_STACK_CLASS OpIter : private Policy { // Initialization and termination - [[nodiscard]] bool startFunction(uint32_t funcIndex, - const ValTypeVector& locals); + [[nodiscard]] bool startFunction(uint32_t funcIndex); [[nodiscard]] bool endFunction(const uint8_t* bodyEnd); [[nodiscard]] bool startInitExpr(ValType expected); @@ -649,9 +638,9 @@ class MOZ_STACK_CLASS OpIter : private Policy { [[nodiscard]] bool readOp(OpBytes* op); [[nodiscard]] bool readReturn(ValueVector* values); - [[nodiscard]] bool readBlock(ResultType* paramType); - [[nodiscard]] bool readLoop(ResultType* paramType); - [[nodiscard]] bool readIf(ResultType* paramType, Value* condition); + [[nodiscard]] bool readBlock(BlockType* type); + [[nodiscard]] bool readLoop(BlockType* type); + [[nodiscard]] bool readIf(BlockType* type, Value* condition); [[nodiscard]] bool readElse(ResultType* paramType, ResultType* resultType, ValueVector* thenResults); [[nodiscard]] bool readEnd(LabelKind* kind, ResultType* type, @@ -665,8 +654,8 @@ class MOZ_STACK_CLASS OpIter : private Policy { [[nodiscard]] bool readBrTable(Uint32Vector* depths, uint32_t* defaultDepth, ResultType* defaultBranchType, ValueVector* branchValues, Value* index); - [[nodiscard]] bool readTry(ResultType* type); - [[nodiscard]] bool readTryTable(ResultType* type, + [[nodiscard]] bool readTry(BlockType* type); + [[nodiscard]] bool readTryTable(BlockType* type, TryTableCatchVector* catches); [[nodiscard]] bool readCatch(LabelKind* kind, uint32_t* tagIndex, ResultType* paramType, ResultType* resultType, @@ -703,11 +692,9 @@ class MOZ_STACK_CLASS OpIter : private Policy { [[nodiscard]] bool readMemoryGrow(uint32_t* memoryIndex, Value* input); [[nodiscard]] bool readSelect(bool typed, StackType* type, Value* trueValue, Value* falseValue, Value* condition); - [[nodiscard]] bool readGetLocal(const ValTypeVector& locals, uint32_t* id); - [[nodiscard]] bool readSetLocal(const ValTypeVector& locals, uint32_t* id, - Value* value); - [[nodiscard]] bool readTeeLocal(const ValTypeVector& locals, uint32_t* id, - Value* value); + [[nodiscard]] bool readGetLocal(uint32_t* id); + [[nodiscard]] bool readSetLocal(uint32_t* id, Value* value); + [[nodiscard]] bool readTeeLocal(uint32_t* id, Value* value); [[nodiscard]] bool readGetGlobal(uint32_t* id); [[nodiscard]] bool readSetGlobal(uint32_t* id, Value* value); [[nodiscard]] bool readTeeGlobal(uint32_t* id, Value* value); @@ -723,32 +710,25 @@ class MOZ_STACK_CLASS OpIter : private Policy { ValueVector* values, Value* condition); [[nodiscard]] bool readBrOnNonNull(uint32_t* relativeDepth, ResultType* type, ValueVector* values, Value* condition); - [[nodiscard]] bool readCall(uint32_t* funcTypeIndex, ValueVector* argValues); + [[nodiscard]] bool readCall(uint32_t* funcIndex, ValueVector* argValues); [[nodiscard]] bool readCallIndirect(uint32_t* funcTypeIndex, uint32_t* tableIndex, Value* callee, ValueVector* argValues); -#ifdef ENABLE_WASM_TAIL_CALLS - [[nodiscard]] bool readReturnCall(uint32_t* funcTypeIndex, + [[nodiscard]] bool readReturnCall(uint32_t* funcIndex, ValueVector* argValues); [[nodiscard]] bool readReturnCallIndirect(uint32_t* funcTypeIndex, uint32_t* tableIndex, Value* callee, ValueVector* argValues); -#endif -#ifdef ENABLE_WASM_GC - [[nodiscard]] bool readCallRef(const FuncType** funcType, Value* callee, + [[nodiscard]] bool readCallRef(uint32_t* funcTypeIndex, Value* callee, ValueVector* argValues); - -# ifdef ENABLE_WASM_TAIL_CALLS - [[nodiscard]] bool readReturnCallRef(const FuncType** funcType, Value* callee, + [[nodiscard]] bool readReturnCallRef(uint32_t* funcTypeIndex, Value* callee, ValueVector* argValues); -# endif -#endif [[nodiscard]] bool readOldCallDirect(uint32_t numFuncImports, - uint32_t* funcTypeIndex, + uint32_t* funcIndex, ValueVector* argValues); [[nodiscard]] bool readOldCallIndirect(uint32_t* funcTypeIndex, Value* callee, ValueVector* argValues); - [[nodiscard]] bool readWake(LinearMemoryAddress* addr, Value* count); + [[nodiscard]] bool readNotify(LinearMemoryAddress* addr, Value* count); [[nodiscard]] bool readWait(LinearMemoryAddress* addr, ValType valueType, uint32_t byteSize, Value* value, Value* timeout); @@ -779,15 +759,14 @@ class MOZ_STACK_CLASS OpIter : private Policy { Value* val, Value* len); [[nodiscard]] bool readMemDiscard(uint32_t* memoryIndex, Value* start, Value* len); - [[nodiscard]] bool readTableGet(uint32_t* tableIndex, Value* index); + [[nodiscard]] bool readTableGet(uint32_t* tableIndex, Value* address); [[nodiscard]] bool readTableGrow(uint32_t* tableIndex, Value* initValue, Value* delta); - [[nodiscard]] bool readTableSet(uint32_t* tableIndex, Value* index, + [[nodiscard]] bool readTableSet(uint32_t* tableIndex, Value* address, Value* value); [[nodiscard]] bool readTableSize(uint32_t* tableIndex); -#ifdef ENABLE_WASM_GC [[nodiscard]] bool readStructNew(uint32_t* typeIndex, ValueVector* argValues); [[nodiscard]] bool readStructNewDefault(uint32_t* typeIndex); [[nodiscard]] bool readStructGet(uint32_t* typeIndex, uint32_t* fieldIndex, @@ -817,10 +796,10 @@ class MOZ_STACK_CLASS OpIter : private Policy { [[nodiscard]] bool readArraySet(uint32_t* typeIndex, Value* val, Value* index, Value* ptr); [[nodiscard]] bool readArrayLen(Value* ptr); - [[nodiscard]] bool readArrayCopy(int32_t* elemSize, bool* elemsAreRefTyped, - Value* dstArray, Value* dstIndex, - Value* srcArray, Value* srcIndex, - Value* numElements); + [[nodiscard]] bool readArrayCopy(uint32_t* dstArrayTypeIndex, + uint32_t* srcArrayTypeIndex, Value* dstArray, + Value* dstIndex, Value* srcArray, + Value* srcIndex, Value* numElements); [[nodiscard]] bool readArrayFill(uint32_t* typeIndex, Value* array, Value* index, Value* val, Value* length); [[nodiscard]] bool readRefTest(bool nullable, RefType* sourceType, @@ -832,7 +811,6 @@ class MOZ_STACK_CLASS OpIter : private Policy { ResultType* labelType, ValueVector* values); [[nodiscard]] bool readRefConversion(RefType operandType, RefType resultType, Value* operandValue); -#endif #ifdef ENABLE_WASM_SIMD [[nodiscard]] bool readLaneIndex(uint32_t inputLanes, uint32_t* laneIndex); @@ -928,7 +906,7 @@ class MOZ_STACK_CLASS OpIter : private Policy { // via a parameter. template bool controlFindInnermostFrom(Predicate predicate, uint32_t fromRelativeDepth, - uint32_t* foundRelativeDepth) { + uint32_t* foundRelativeDepth) const { int32_t fromAbsoluteDepth = controlStack_.length() - fromRelativeDepth - 1; for (int32_t i = fromAbsoluteDepth; i >= 0; i--) { if (predicate(controlStack_[i].kind(), controlStack_[i].controlItem())) { @@ -943,43 +921,26 @@ class MOZ_STACK_CLASS OpIter : private Policy { template inline bool OpIter::checkIsSubtypeOf(StorageType subType, StorageType superType) { - return CheckIsSubtypeOf(d_, env_, lastOpcodeOffset(), subType, superType); + return CheckIsSubtypeOf(d_, codeMeta_, lastOpcodeOffset(), subType, + superType); } template inline bool OpIter::checkIsSubtypeOf(ResultType params, ResultType results) { - if (params.length() != results.length()) { - UniqueChars error( - JS_smprintf("type mismatch: expected %zu values, got %zu values", - results.length(), params.length())); - if (!error) { - return false; - } - return fail(error.get()); - } - for (uint32_t i = 0; i < params.length(); i++) { - ValType param = params[i]; - ValType result = results[i]; - if (!checkIsSubtypeOf(param, result)) { - return false; - } - } - return true; + return CheckIsSubtypeOf(d_, codeMeta_, lastOpcodeOffset(), params, results); } -#ifdef ENABLE_WASM_GC template inline bool OpIter::checkIsSubtypeOf(uint32_t actualTypeIndex, uint32_t expectedTypeIndex) { - const TypeDef& actualTypeDef = env_.types->type(actualTypeIndex); - const TypeDef& expectedTypeDef = env_.types->type(expectedTypeIndex); + const TypeDef& actualTypeDef = codeMeta_.types->type(actualTypeIndex); + const TypeDef& expectedTypeDef = codeMeta_.types->type(expectedTypeIndex); return CheckIsSubtypeOf( - d_, env_, lastOpcodeOffset(), + d_, codeMeta_, lastOpcodeOffset(), ValType(RefType::fromTypeDef(&actualTypeDef, true)), ValType(RefType::fromTypeDef(&expectedTypeDef, true))); } -#endif template inline bool OpIter::unrecognizedOpcode(const OpBytes* expr) { @@ -1104,7 +1065,7 @@ inline bool OpIter::popWithRefType(Value* value, StackType* type) { return true; } - UniqueChars actualText = ToString(type->valType(), env_.types); + UniqueChars actualText = ToString(type->valType(), codeMeta_.types); if (!actualText) { return false; } @@ -1252,11 +1213,11 @@ inline bool OpIter::readBlockType(BlockType* type) { } int32_t x; - if (!d_.readVarS32(&x) || x < 0 || uint32_t(x) >= env_.types->length()) { + if (!d_.readVarS32(&x) || x < 0 || uint32_t(x) >= codeMeta_.types->length()) { return fail("invalid block type type index"); } - const TypeDef* typeDef = &env_.types->type(x); + const TypeDef* typeDef = &codeMeta_.types->type(x); if (!typeDef->isFuncType()) { return fail("block type type index must be func type"); } @@ -1295,24 +1256,22 @@ inline void OpIter::peekOp(OpBytes* op) { } template -inline bool OpIter::startFunction(uint32_t funcIndex, - const ValTypeVector& locals) { +inline bool OpIter::startFunction(uint32_t funcIndex) { MOZ_ASSERT(kind_ == OpIter::Func); MOZ_ASSERT(elseParamStack_.empty()); MOZ_ASSERT(valueStack_.empty()); MOZ_ASSERT(controlStack_.empty()); MOZ_ASSERT(op_.b0 == uint16_t(Op::Limit)); - MOZ_ASSERT(maxInitializedGlobalsIndexPlus1_ == 0); - BlockType type = BlockType::FuncResults(*env_.funcs[funcIndex].type); + BlockType type = BlockType::FuncResults(codeMeta_.getFuncType(funcIndex)); // Initialize information related to branch hinting. lastBranchHintIndex_ = 0; - if (env_.branchHintingEnabled()) { - branchHintVector_ = &env_.branchHints.getHintVector(funcIndex); + if (codeMeta_.branchHintingEnabled()) { + branchHintVector_ = &codeMeta_.branchHints.getHintVector(funcIndex); } - size_t numArgs = env_.funcs[funcIndex].type->args().length(); - if (!unsetLocals_.init(locals, numArgs)) { + size_t numArgs = codeMeta_.getFuncType(funcIndex).args().length(); + if (!unsetLocals_.init(locals_, numArgs)) { return false; } @@ -1341,20 +1300,13 @@ inline bool OpIter::endFunction(const uint8_t* bodyEnd) { template inline bool OpIter::startInitExpr(ValType expected) { MOZ_ASSERT(kind_ == OpIter::InitExpr); + MOZ_ASSERT(locals_.length() == 0); MOZ_ASSERT(elseParamStack_.empty()); MOZ_ASSERT(valueStack_.empty()); MOZ_ASSERT(controlStack_.empty()); MOZ_ASSERT(op_.b0 == uint16_t(Op::Limit)); lastBranchHintIndex_ = 0; - // GC allows accessing any previously defined global, not just those that are - // imported and immutable. - if (env_.features.gc) { - maxInitializedGlobalsIndexPlus1_ = env_.globals.length(); - } else { - maxInitializedGlobalsIndexPlus1_ = env_.numGlobalImports; - } - BlockType type = BlockType::VoidToSingle(expected); return pushControl(LabelKind::Body, type); } @@ -1373,12 +1325,13 @@ inline bool OpIter::endInitExpr() { template inline bool OpIter::readValType(ValType* type) { - return d_.readValType(*env_.types, env_.features, type); + return d_.readValType(*codeMeta_.types, codeMeta_.features(), type); } template inline bool OpIter::readHeapType(bool nullable, RefType* type) { - return d_.readHeapType(*env_.types, env_.features, nullable, type); + return d_.readHeapType(*codeMeta_.types, codeMeta_.features(), nullable, + type); } template @@ -1397,37 +1350,32 @@ inline bool OpIter::readReturn(ValueVector* values) { } template -inline bool OpIter::readBlock(ResultType* paramType) { +inline bool OpIter::readBlock(BlockType* type) { MOZ_ASSERT(Classify(op_) == OpKind::Block); - BlockType type; - if (!readBlockType(&type)) { + if (!readBlockType(type)) { return false; } - *paramType = type.params(); - return pushControl(LabelKind::Block, type); + return pushControl(LabelKind::Block, *type); } template -inline bool OpIter::readLoop(ResultType* paramType) { +inline bool OpIter::readLoop(BlockType* type) { MOZ_ASSERT(Classify(op_) == OpKind::Loop); - BlockType type; - if (!readBlockType(&type)) { + if (!readBlockType(type)) { return false; } - *paramType = type.params(); - return pushControl(LabelKind::Loop, type); + return pushControl(LabelKind::Loop, *type); } template -inline bool OpIter::readIf(ResultType* paramType, Value* condition) { +inline bool OpIter::readIf(BlockType* type, Value* condition) { MOZ_ASSERT(Classify(op_) == OpKind::If); - BlockType type; - if (!readBlockType(&type)) { + if (!readBlockType(type)) { return false; } @@ -1435,12 +1383,11 @@ inline bool OpIter::readIf(ResultType* paramType, Value* condition) { return false; } - if (!pushControl(LabelKind::Then, type)) { + if (!pushControl(LabelKind::Then, *type)) { return false; } - *paramType = type.params(); - size_t paramsLength = type.params().length(); + size_t paramsLength = type->params().length(); return elseParamStack_.append(valueStack_.end() - paramsLength, paramsLength); } @@ -1492,8 +1439,10 @@ inline bool OpIter::readEnd(LabelKind* kind, ResultType* type, // If an `if` block ends with `end` instead of `else`, then the `else` block // implicitly passes the `if` parameters as the `else` results. In that // case, assert that the `if`'s param type matches the result type. - if (params != block.type().results()) { - return fail("if without else with a result value"); + if (!checkIsSubtypeOf(params, block.type().results())) { + return fail( + "the parameters to an if without an else must be compatible with the " + "if's result type"); } size_t nparams = params.length(); @@ -1647,17 +1596,15 @@ inline bool OpIter::readBrTable(Uint32Vector* depths, #undef UNKNOWN_ARITY template -inline bool OpIter::readTry(ResultType* paramType) { +inline bool OpIter::readTry(BlockType* type) { MOZ_ASSERT(Classify(op_) == OpKind::Try); featureUsage_ |= FeatureUsage::LegacyExceptions; - BlockType type; - if (!readBlockType(&type)) { + if (!readBlockType(type)) { return false; } - *paramType = type.params(); - return pushControl(LabelKind::Try, type); + return pushControl(LabelKind::Try, *type); } enum class TryTableCatchFlags : uint8_t { @@ -1667,17 +1614,15 @@ enum class TryTableCatchFlags : uint8_t { }; template -inline bool OpIter::readTryTable(ResultType* paramType, +inline bool OpIter::readTryTable(BlockType* type, TryTableCatchVector* catches) { MOZ_ASSERT(Classify(op_) == OpKind::TryTable); - BlockType type; - if (!readBlockType(&type)) { + if (!readBlockType(type)) { return false; } - *paramType = type.params(); - if (!pushControl(LabelKind::TryTable, type)) { + if (!pushControl(LabelKind::TryTable, *type)) { return false; } @@ -1717,7 +1662,7 @@ inline bool OpIter::readTryTable(ResultType* paramType, if (!readVarU32(&tryTableCatch.tagIndex)) { return fail("expected tag index"); } - if (tryTableCatch.tagIndex >= env_.tags.length()) { + if (tryTableCatch.tagIndex >= codeMeta_.tags.length()) { return fail("tag index out of range"); } } @@ -1742,7 +1687,7 @@ inline bool OpIter::readTryTable(ResultType* paramType, // Tagged catches will unpack the exception package and pass it to the // branch if (tryTableCatch.tagIndex != CatchAllIndex) { - const TagType& tagType = *env_.tags[tryTableCatch.tagIndex].type; + const TagType& tagType = *codeMeta_.tags[tryTableCatch.tagIndex].type; ResultType tagResult = tagType.resultType(); if (!tagResult.cloneToVector(&tryTableCatch.labelType)) { return false; @@ -1751,7 +1696,7 @@ inline bool OpIter::readTryTable(ResultType* paramType, // Any captured exnref is the final parameter if (tryTableCatch.captureExnRef && - !tryTableCatch.labelType.append(ValType(RefType::exn()))) { + !tryTableCatch.labelType.append(ValType(RefType::exn().asNonNullable()))) { return false; } @@ -1782,7 +1727,7 @@ inline bool OpIter::readCatch(LabelKind* kind, uint32_t* tagIndex, if (!readVarU32(tagIndex)) { return fail("expected tag index"); } - if (*tagIndex >= env_.tags.length()) { + if (*tagIndex >= codeMeta_.tags.length()) { return fail("tag index out of range"); } @@ -1805,7 +1750,7 @@ inline bool OpIter::readCatch(LabelKind* kind, uint32_t* tagIndex, // Reset local state to the beginning of the 'try' block. unsetLocals_.resetToBlock(controlStack_.length() - 1); - return push(env_.tags[*tagIndex].type->resultType()); + return push(codeMeta_.tags[*tagIndex].type->resultType()); } template @@ -1877,11 +1822,11 @@ inline bool OpIter::readThrow(uint32_t* tagIndex, if (!readVarU32(tagIndex)) { return fail("expected tag index"); } - if (*tagIndex >= env_.tags.length()) { + if (*tagIndex >= codeMeta_.tags.length()) { return fail("tag index out of range"); } - if (!popWithType(env_.tags[*tagIndex].type->resultType(), argValues)) { + if (!popWithType(codeMeta_.tags[*tagIndex].type->resultType(), argValues)) { return false; } @@ -2046,7 +1991,7 @@ inline bool OpIter::readLinearMemoryAddress( addr->memoryIndex = 0; } - if (addr->memoryIndex >= env_.numMemories()) { + if (addr->memoryIndex >= codeMeta_.numMemories()) { return fail("memory index out of range"); } @@ -2054,8 +1999,8 @@ inline bool OpIter::readLinearMemoryAddress( return fail("unable to read load offset"); } - IndexType it = env_.memories[addr->memoryIndex].indexType(); - if (it == IndexType::I32 && addr->offset > UINT32_MAX) { + AddressType at = codeMeta_.memories[addr->memoryIndex].addressType(); + if (at == AddressType::I32 && addr->offset > UINT32_MAX) { return fail("offset too large for memory type"); } @@ -2063,7 +2008,7 @@ inline bool OpIter::readLinearMemoryAddress( return fail("greater than natural alignment"); } - if (!popWithType(ToValType(it), &addr->base)) { + if (!popWithType(ToValType(at), &addr->base)) { return false; } @@ -2145,11 +2090,11 @@ inline bool OpIter::readMemorySize(uint32_t* memoryIndex) { return fail("failed to read memory flags"); } - if (*memoryIndex >= env_.numMemories()) { + if (*memoryIndex >= codeMeta_.numMemories()) { return fail("memory index out of range for memory.size"); } - ValType ptrType = ToValType(env_.memories[*memoryIndex].indexType()); + ValType ptrType = ToValType(codeMeta_.memories[*memoryIndex].addressType()); return push(ptrType); } @@ -2162,11 +2107,11 @@ inline bool OpIter::readMemoryGrow(uint32_t* memoryIndex, return fail("failed to read memory flags"); } - if (*memoryIndex >= env_.numMemories()) { + if (*memoryIndex >= codeMeta_.numMemories()) { return fail("memory index out of range for memory.grow"); } - ValType ptrType = ToValType(env_.memories[*memoryIndex].indexType()); + ValType ptrType = ToValType(codeMeta_.memories[*memoryIndex].addressType()); if (!popWithType(ptrType, input)) { return false; } @@ -2242,15 +2187,14 @@ inline bool OpIter::readSelect(bool typed, StackType* type, } template -inline bool OpIter::readGetLocal(const ValTypeVector& locals, - uint32_t* id) { +inline bool OpIter::readGetLocal(uint32_t* id) { MOZ_ASSERT(Classify(op_) == OpKind::GetLocal); if (!readVarU32(id)) { return fail("unable to read local index"); } - if (*id >= locals.length()) { + if (*id >= locals_.length()) { return fail("local.get index out of range"); } @@ -2258,19 +2202,18 @@ inline bool OpIter::readGetLocal(const ValTypeVector& locals, return fail("local.get read from unset local"); } - return push(locals[*id]); + return push(locals_[*id]); } template -inline bool OpIter::readSetLocal(const ValTypeVector& locals, - uint32_t* id, Value* value) { +inline bool OpIter::readSetLocal(uint32_t* id, Value* value) { MOZ_ASSERT(Classify(op_) == OpKind::SetLocal); if (!readVarU32(id)) { return fail("unable to read local index"); } - if (*id >= locals.length()) { + if (*id >= locals_.length()) { return fail("local.set index out of range"); } @@ -2278,19 +2221,18 @@ inline bool OpIter::readSetLocal(const ValTypeVector& locals, unsetLocals_.set(*id, controlStackDepth()); } - return popWithType(locals[*id], value); + return popWithType(locals_[*id], value); } template -inline bool OpIter::readTeeLocal(const ValTypeVector& locals, - uint32_t* id, Value* value) { +inline bool OpIter::readTeeLocal(uint32_t* id, Value* value) { MOZ_ASSERT(Classify(op_) == OpKind::TeeLocal); if (!readVarU32(id)) { return fail("unable to read local index"); } - if (*id >= locals.length()) { + if (*id >= locals_.length()) { return fail("local.set index out of range"); } @@ -2299,7 +2241,7 @@ inline bool OpIter::readTeeLocal(const ValTypeVector& locals, } ValueVector single; - if (!checkTopTypeMatches(ResultType::Single(locals[*id]), &single, + if (!checkTopTypeMatches(ResultType::Single(locals_[*id]), &single, /*rewriteStackTypes=*/true)) { return false; } @@ -2316,20 +2258,19 @@ inline bool OpIter::readGetGlobal(uint32_t* id) { return false; } - if (*id >= env_.globals.length()) { + if (*id >= codeMeta_.globals.length()) { return fail("global.get index out of range"); } - // Initializer expressions can access immutable imported globals, or any - // previously defined immutable global with GC enabled. - if (kind_ == OpIter::InitExpr && (env_.globals[*id].isMutable() || - *id >= maxInitializedGlobalsIndexPlus1_)) { + // Initializer expressions can only access previously-defined immutable + // globals. + if (kind_ == OpIter::InitExpr && codeMeta_.globals[*id].isMutable()) { return fail( - "global.get in initializer expression must reference a global " - "immutable import"); + "global.get in initializer expression must reference a " + "previously-defined immutable global"); } - return push(env_.globals[*id].type()); + return push(codeMeta_.globals[*id].type()); } template @@ -2340,15 +2281,15 @@ inline bool OpIter::readSetGlobal(uint32_t* id, Value* value) { return false; } - if (*id >= env_.globals.length()) { + if (*id >= codeMeta_.globals.length()) { return fail("global.set index out of range"); } - if (!env_.globals[*id].isMutable()) { + if (!codeMeta_.globals[*id].isMutable()) { return fail("can't write an immutable global"); } - return popWithType(env_.globals[*id].type(), value); + return popWithType(codeMeta_.globals[*id].type(), value); } template @@ -2359,16 +2300,16 @@ inline bool OpIter::readTeeGlobal(uint32_t* id, Value* value) { return false; } - if (*id >= env_.globals.length()) { + if (*id >= codeMeta_.globals.length()) { return fail("global.set index out of range"); } - if (!env_.globals[*id].isMutable()) { + if (!codeMeta_.globals[*id].isMutable()) { return fail("can't write an immutable global"); } ValueVector single; - if (!checkTopTypeMatches(ResultType::Single(env_.globals[*id].type()), + if (!checkTopTypeMatches(ResultType::Single(codeMeta_.globals[*id].type()), &single, /*rewriteStackTypes=*/true)) { return false; @@ -2381,7 +2322,7 @@ inline bool OpIter::readTeeGlobal(uint32_t* id, Value* value) { template inline bool OpIter::readI32Const(int32_t* i32) { - MOZ_ASSERT(Classify(op_) == OpKind::I32); + MOZ_ASSERT(Classify(op_) == OpKind::I32Const); if (!d_.readI32Const(i32)) { return false; @@ -2392,7 +2333,7 @@ inline bool OpIter::readI32Const(int32_t* i32) { template inline bool OpIter::readI64Const(int64_t* i64) { - MOZ_ASSERT(Classify(op_) == OpKind::I64); + MOZ_ASSERT(Classify(op_) == OpKind::I64Const); if (!d_.readI64Const(i64)) { return false; @@ -2403,7 +2344,7 @@ inline bool OpIter::readI64Const(int64_t* i64) { template inline bool OpIter::readF32Const(float* f32) { - MOZ_ASSERT(Classify(op_) == OpKind::F32); + MOZ_ASSERT(Classify(op_) == OpKind::F32Const); if (!d_.readF32Const(f32)) { return false; @@ -2414,7 +2355,7 @@ inline bool OpIter::readF32Const(float* f32) { template inline bool OpIter::readF64Const(double* f64) { - MOZ_ASSERT(Classify(op_) == OpKind::F64); + MOZ_ASSERT(Classify(op_) == OpKind::F64Const); if (!d_.readF64Const(f64)) { return false; @@ -2430,31 +2371,24 @@ inline bool OpIter::readRefFunc(uint32_t* funcIndex) { if (!d_.readFuncIndex(funcIndex)) { return false; } - if (*funcIndex >= env_.funcs.length()) { + if (*funcIndex >= codeMeta_.funcs.length()) { return fail("function index out of range"); } - if (kind_ == OpIter::Func && !env_.funcs[*funcIndex].canRefFunc()) { + if (kind_ == OpIter::Func && !codeMeta_.funcs[*funcIndex].canRefFunc()) { return fail( "function index is not declared in a section before the code section"); } -#ifdef ENABLE_WASM_GC - // When function references enabled, push type index on the stack, e.g. for - // validation of the call_ref instruction. - if (env_.gcEnabled()) { - const uint32_t typeIndex = env_.funcs[*funcIndex].typeIndex; - const TypeDef& typeDef = env_.types->type(typeIndex); - return push(RefType::fromTypeDef(&typeDef, false)); - } -#endif - return push(RefType::func()); + const uint32_t typeIndex = codeMeta_.funcs[*funcIndex].typeIndex; + const TypeDef& typeDef = codeMeta_.types->type(typeIndex); + return push(RefType::fromTypeDef(&typeDef, false)); } template inline bool OpIter::readRefNull(RefType* type) { MOZ_ASSERT(Classify(op_) == OpKind::RefNull); - if (!d_.readRefNull(*env_.types, env_.features, type)) { + if (!d_.readRefNull(*codeMeta_.types, codeMeta_.features(), type)) { return false; } return push(*type); @@ -2462,7 +2396,7 @@ inline bool OpIter::readRefNull(RefType* type) { template inline bool OpIter::readRefIsNull(Value* input) { - MOZ_ASSERT(Classify(op_) == OpKind::Conversion); + MOZ_ASSERT(Classify(op_) == OpKind::RefIsNull); StackType type; if (!popWithRefType(input, &type)) { @@ -2582,19 +2516,19 @@ inline bool OpIter::popCallArgs(const ValTypeVector& expectedTypes, } template -inline bool OpIter::readCall(uint32_t* funcTypeIndex, +inline bool OpIter::readCall(uint32_t* funcIndex, ValueVector* argValues) { MOZ_ASSERT(Classify(op_) == OpKind::Call); - if (!readVarU32(funcTypeIndex)) { + if (!readVarU32(funcIndex)) { return fail("unable to read call function index"); } - if (*funcTypeIndex >= env_.funcs.length()) { + if (*funcIndex >= codeMeta_.funcs.length()) { return fail("callee index out of range"); } - const FuncType& funcType = *env_.funcs[*funcTypeIndex].type; + const FuncType& funcType = codeMeta_.getFuncType(*funcIndex); if (!popCallArgs(funcType.args(), argValues)) { return false; @@ -2603,21 +2537,22 @@ inline bool OpIter::readCall(uint32_t* funcTypeIndex, return push(ResultType::Vector(funcType.results())); } -#ifdef ENABLE_WASM_TAIL_CALLS template -inline bool OpIter::readReturnCall(uint32_t* funcTypeIndex, +inline bool OpIter::readReturnCall(uint32_t* funcIndex, ValueVector* argValues) { MOZ_ASSERT(Classify(op_) == OpKind::ReturnCall); - if (!readVarU32(funcTypeIndex)) { + featureUsage_ |= FeatureUsage::ReturnCall; + + if (!readVarU32(funcIndex)) { return fail("unable to read call function index"); } - if (*funcTypeIndex >= env_.funcs.length()) { + if (*funcIndex >= codeMeta_.funcs.length()) { return fail("callee index out of range"); } - const FuncType& funcType = *env_.funcs[*funcTypeIndex].type; + const FuncType& funcType = codeMeta_.getFuncType(*funcIndex); if (!popCallArgs(funcType.args(), argValues)) { return false; @@ -2634,7 +2569,6 @@ inline bool OpIter::readReturnCall(uint32_t* funcTypeIndex, afterUnconditionalBranch(); return true; } -#endif template inline bool OpIter::readCallIndirect(uint32_t* funcTypeIndex, @@ -2648,29 +2582,30 @@ inline bool OpIter::readCallIndirect(uint32_t* funcTypeIndex, return fail("unable to read call_indirect signature index"); } - if (*funcTypeIndex >= env_.numTypes()) { + if (*funcTypeIndex >= codeMeta_.numTypes()) { return fail("signature index out of range"); } if (!readVarU32(tableIndex)) { return fail("unable to read call_indirect table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { // Special case this for improved user experience. - if (!env_.tables.length()) { + if (!codeMeta_.tables.length()) { return fail("can't call_indirect without a table"); } return fail("table index out of range for call_indirect"); } - if (!env_.tables[*tableIndex].elemType.isFuncHierarchy()) { + if (!codeMeta_.tables[*tableIndex].elemType.isFuncHierarchy()) { return fail("indirect calls must go through a table of 'funcref'"); } - if (!popWithType(ValType::I32, callee)) { + if (!popWithType(ToValType(codeMeta_.tables[*tableIndex].addressType()), + callee)) { return false; } - const TypeDef& typeDef = env_.types->type(*funcTypeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*funcTypeIndex); if (!typeDef.isFuncType()) { return fail("expected signature type"); } @@ -2683,7 +2618,6 @@ inline bool OpIter::readCallIndirect(uint32_t* funcTypeIndex, return push(ResultType::Vector(funcType.results())); } -#ifdef ENABLE_WASM_TAIL_CALLS template inline bool OpIter::readReturnCallIndirect(uint32_t* funcTypeIndex, uint32_t* tableIndex, @@ -2692,32 +2626,35 @@ inline bool OpIter::readReturnCallIndirect(uint32_t* funcTypeIndex, MOZ_ASSERT(Classify(op_) == OpKind::ReturnCallIndirect); MOZ_ASSERT(funcTypeIndex != tableIndex); + featureUsage_ |= FeatureUsage::ReturnCall; + if (!readVarU32(funcTypeIndex)) { return fail("unable to read return_call_indirect signature index"); } - if (*funcTypeIndex >= env_.numTypes()) { + if (*funcTypeIndex >= codeMeta_.numTypes()) { return fail("signature index out of range"); } if (!readVarU32(tableIndex)) { return fail("unable to read return_call_indirect table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { // Special case this for improved user experience. - if (!env_.tables.length()) { + if (!codeMeta_.tables.length()) { return fail("can't return_call_indirect without a table"); } return fail("table index out of range for return_call_indirect"); } - if (!env_.tables[*tableIndex].elemType.isFuncHierarchy()) { + if (!codeMeta_.tables[*tableIndex].elemType.isFuncHierarchy()) { return fail("indirect calls must go through a table of 'funcref'"); } - if (!popWithType(ValType::I32, callee)) { + if (!popWithType(ToValType(codeMeta_.tables[*tableIndex].addressType()), + callee)) { return false; } - const TypeDef& typeDef = env_.types->type(*funcTypeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*funcTypeIndex); if (!typeDef.isFuncType()) { return fail("expected signature type"); } @@ -2738,61 +2675,57 @@ inline bool OpIter::readReturnCallIndirect(uint32_t* funcTypeIndex, afterUnconditionalBranch(); return true; } -#endif -#ifdef ENABLE_WASM_GC template -inline bool OpIter::readCallRef(const FuncType** funcType, - Value* callee, ValueVector* argValues) { +inline bool OpIter::readCallRef(uint32_t* funcTypeIndex, Value* callee, + ValueVector* argValues) { MOZ_ASSERT(Classify(op_) == OpKind::CallRef); - uint32_t funcTypeIndex; - if (!readFuncTypeIndex(&funcTypeIndex)) { + if (!readFuncTypeIndex(funcTypeIndex)) { return false; } - const TypeDef& typeDef = env_.types->type(funcTypeIndex); - *funcType = &typeDef.funcType(); + const TypeDef& typeDef = codeMeta_.types->type(*funcTypeIndex); + const FuncType& funcType = typeDef.funcType(); if (!popWithType(ValType(RefType::fromTypeDef(&typeDef, true)), callee)) { return false; } - if (!popCallArgs((*funcType)->args(), argValues)) { + if (!popCallArgs(funcType.args(), argValues)) { return false; } - return push(ResultType::Vector((*funcType)->results())); + return push(ResultType::Vector(funcType.results())); } -#endif -#if defined(ENABLE_WASM_TAIL_CALLS) && defined(ENABLE_WASM_GC) template -inline bool OpIter::readReturnCallRef(const FuncType** funcType, +inline bool OpIter::readReturnCallRef(uint32_t* funcTypeIndex, Value* callee, ValueVector* argValues) { MOZ_ASSERT(Classify(op_) == OpKind::ReturnCallRef); - uint32_t funcTypeIndex; - if (!readFuncTypeIndex(&funcTypeIndex)) { + featureUsage_ |= FeatureUsage::ReturnCall; + + if (!readFuncTypeIndex(funcTypeIndex)) { return false; } - const TypeDef& typeDef = env_.types->type(funcTypeIndex); - *funcType = &typeDef.funcType(); + const TypeDef& typeDef = codeMeta_.types->type(*funcTypeIndex); + const FuncType& funcType = typeDef.funcType(); if (!popWithType(ValType(RefType::fromTypeDef(&typeDef, true)), callee)) { return false; } - if (!popCallArgs((*funcType)->args(), argValues)) { + if (!popCallArgs(funcType.args(), argValues)) { return false; } // Check if callee results are subtypes of caller's. Control& body = controlStack_[0]; MOZ_ASSERT(body.kind() == LabelKind::Body); - if (!checkIsSubtypeOf(ResultType::Vector((*funcType)->results()), + if (!checkIsSubtypeOf(ResultType::Vector(funcType.results()), body.resultType())) { return false; } @@ -2800,11 +2733,10 @@ inline bool OpIter::readReturnCallRef(const FuncType** funcType, afterUnconditionalBranch(); return true; } -#endif template inline bool OpIter::readOldCallDirect(uint32_t numFuncImports, - uint32_t* funcTypeIndex, + uint32_t* funcIndex, ValueVector* argValues) { MOZ_ASSERT(Classify(op_) == OpKind::OldCallDirect); @@ -2817,13 +2749,13 @@ inline bool OpIter::readOldCallDirect(uint32_t numFuncImports, return fail("callee index out of range"); } - *funcTypeIndex = numFuncImports + funcDefIndex; + *funcIndex = numFuncImports + funcDefIndex; - if (*funcTypeIndex >= env_.funcs.length()) { + if (*funcIndex >= codeMeta_.funcs.length()) { return fail("callee index out of range"); } - const FuncType& funcType = *env_.funcs[*funcTypeIndex].type; + const FuncType& funcType = codeMeta_.getFuncType(*funcIndex); if (!popCallArgs(funcType.args(), argValues)) { return false; @@ -2842,11 +2774,11 @@ inline bool OpIter::readOldCallIndirect(uint32_t* funcTypeIndex, return fail("unable to read call_indirect signature index"); } - if (*funcTypeIndex >= env_.numTypes()) { + if (*funcTypeIndex >= codeMeta_.numTypes()) { return fail("signature index out of range"); } - const TypeDef& typeDef = env_.types->type(*funcTypeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*funcTypeIndex); if (!typeDef.isFuncType()) { return fail("expected signature type"); } @@ -2864,9 +2796,9 @@ inline bool OpIter::readOldCallIndirect(uint32_t* funcTypeIndex, } template -inline bool OpIter::readWake(LinearMemoryAddress* addr, - Value* count) { - MOZ_ASSERT(Classify(op_) == OpKind::Wake); +inline bool OpIter::readNotify(LinearMemoryAddress* addr, + Value* count) { + MOZ_ASSERT(Classify(op_) == OpKind::Notify); if (!popWithType(ValType::I32, count)) { return false; @@ -2948,7 +2880,7 @@ template inline bool OpIter::readAtomicRMW(LinearMemoryAddress* addr, ValType resultType, uint32_t byteSize, Value* value) { - MOZ_ASSERT(Classify(op_) == OpKind::AtomicBinOp); + MOZ_ASSERT(Classify(op_) == OpKind::AtomicRMW); if (!popWithType(resultType, value)) { return false; @@ -2968,7 +2900,7 @@ inline bool OpIter::readAtomicCmpXchg(LinearMemoryAddress* addr, uint32_t byteSize, Value* oldValue, Value* newValue) { - MOZ_ASSERT(Classify(op_) == OpKind::AtomicCompareExchange); + MOZ_ASSERT(Classify(op_) == OpKind::AtomicCmpXchg); if (!popWithType(resultType, newValue)) { return false; @@ -3004,17 +2936,17 @@ inline bool OpIter::readMemOrTableCopy(bool isMem, } if (isMem) { - if (*srcMemOrTableIndex >= env_.memories.length() || - *dstMemOrTableIndex >= env_.memories.length()) { + if (*srcMemOrTableIndex >= codeMeta_.memories.length() || + *dstMemOrTableIndex >= codeMeta_.memories.length()) { return fail("memory index out of range for memory.copy"); } } else { - if (*dstMemOrTableIndex >= env_.tables.length() || - *srcMemOrTableIndex >= env_.tables.length()) { + if (*dstMemOrTableIndex >= codeMeta_.tables.length() || + *srcMemOrTableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.copy"); } - ValType dstElemType = env_.tables[*dstMemOrTableIndex].elemType; - ValType srcElemType = env_.tables[*srcMemOrTableIndex].elemType; + ValType dstElemType = codeMeta_.tables[*dstMemOrTableIndex].elemType; + ValType srcElemType = codeMeta_.tables[*srcMemOrTableIndex].elemType; if (!checkIsSubtypeOf(srcElemType, dstElemType)) { return false; } @@ -3024,15 +2956,18 @@ inline bool OpIter::readMemOrTableCopy(bool isMem, ValType srcPtrType; ValType lenType; if (isMem) { - dstPtrType = ToValType(env_.memories[*dstMemOrTableIndex].indexType()); - srcPtrType = ToValType(env_.memories[*srcMemOrTableIndex].indexType()); - if (dstPtrType == ValType::I64 && srcPtrType == ValType::I64) { - lenType = ValType::I64; - } else { - lenType = ValType::I32; - } + dstPtrType = + ToValType(codeMeta_.memories[*dstMemOrTableIndex].addressType()); + srcPtrType = + ToValType(codeMeta_.memories[*srcMemOrTableIndex].addressType()); } else { - dstPtrType = srcPtrType = lenType = ValType::I32; + dstPtrType = ToValType(codeMeta_.tables[*dstMemOrTableIndex].addressType()); + srcPtrType = ToValType(codeMeta_.tables[*srcMemOrTableIndex].addressType()); + } + if (dstPtrType == ValType::I64 && srcPtrType == ValType::I64) { + lenType = ValType::I64; + } else { + lenType = ValType::I32; } if (!popWithType(lenType, len)) { @@ -3056,14 +2991,14 @@ inline bool OpIter::readDataOrElemDrop(bool isData, } if (isData) { - if (env_.dataCount.isNothing()) { + if (codeMeta_.dataCount.isNothing()) { return fail("data.drop requires a DataCount section"); } - if (*segIndex >= *env_.dataCount) { + if (*segIndex >= *codeMeta_.dataCount) { return fail("data.drop segment index out of range"); } } else { - if (*segIndex >= env_.elemSegments.length()) { + if (*segIndex >= codeMeta_.elemSegmentTypes.length()) { return fail("element segment index out of range for elem.drop"); } } @@ -3080,11 +3015,11 @@ inline bool OpIter::readMemFill(uint32_t* memoryIndex, Value* start, return fail("failed to read memory index"); } - if (*memoryIndex >= env_.numMemories()) { + if (*memoryIndex >= codeMeta_.numMemories()) { return fail("memory index out of range for memory.fill"); } - ValType ptrType = ToValType(env_.memories[*memoryIndex].indexType()); + ValType ptrType = ToValType(codeMeta_.memories[*memoryIndex].addressType()); if (!popWithType(ptrType, len)) { return false; @@ -3115,28 +3050,28 @@ inline bool OpIter::readMemOrTableInit(bool isMem, uint32_t* segIndex, } if (isMem) { - if (memOrTableIndex >= env_.memories.length()) { + if (memOrTableIndex >= codeMeta_.memories.length()) { return fail("memory index out of range for memory.init"); } *dstMemOrTableIndex = memOrTableIndex; - if (env_.dataCount.isNothing()) { + if (codeMeta_.dataCount.isNothing()) { return fail("memory.init requires a DataCount section"); } - if (*segIndex >= *env_.dataCount) { + if (*segIndex >= *codeMeta_.dataCount) { return fail("memory.init segment index out of range"); } } else { - if (memOrTableIndex >= env_.tables.length()) { + if (memOrTableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.init"); } *dstMemOrTableIndex = memOrTableIndex; - if (*segIndex >= env_.elemSegments.length()) { + if (*segIndex >= codeMeta_.elemSegmentTypes.length()) { return fail("table.init segment index out of range"); } - if (!checkIsSubtypeOf(env_.elemSegments[*segIndex].elemType, - env_.tables[*dstMemOrTableIndex].elemType)) { + if (!checkIsSubtypeOf(codeMeta_.elemSegmentTypes[*segIndex], + codeMeta_.tables[*dstMemOrTableIndex].elemType)) { return false; } } @@ -3150,8 +3085,8 @@ inline bool OpIter::readMemOrTableInit(bool isMem, uint32_t* segIndex, } ValType ptrType = - isMem ? ToValType(env_.memories[*dstMemOrTableIndex].indexType()) - : ValType::I32; + isMem ? ToValType(codeMeta_.memories[*dstMemOrTableIndex].addressType()) + : ToValType(codeMeta_.tables[*dstMemOrTableIndex].addressType()); return popWithType(ptrType, dst); } @@ -3163,17 +3098,19 @@ inline bool OpIter::readTableFill(uint32_t* tableIndex, Value* start, if (!readVarU32(tableIndex)) { return fail("unable to read table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.fill"); } - if (!popWithType(ValType::I32, len)) { + const TableDesc& table = codeMeta_.tables[*tableIndex]; + + if (!popWithType(ToValType(table.addressType()), len)) { return false; } - if (!popWithType(env_.tables[*tableIndex].elemType, val)) { + if (!popWithType(table.elemType, val)) { return false; } - return popWithType(ValType::I32, start); + return popWithType(ToValType(table.addressType()), start); } template @@ -3184,11 +3121,11 @@ inline bool OpIter::readMemDiscard(uint32_t* memoryIndex, Value* start, if (!readVarU32(memoryIndex)) { return fail("failed to read memory index"); } - if (*memoryIndex >= env_.memories.length()) { + if (*memoryIndex >= codeMeta_.memories.length()) { return fail("memory index out of range for memory.discard"); } - ValType ptrType = ToValType(env_.memories[*memoryIndex].indexType()); + ValType ptrType = ToValType(codeMeta_.memories[*memoryIndex].addressType()); if (!popWithType(ptrType, len)) { return false; @@ -3198,21 +3135,23 @@ inline bool OpIter::readMemDiscard(uint32_t* memoryIndex, Value* start, } template -inline bool OpIter::readTableGet(uint32_t* tableIndex, Value* index) { +inline bool OpIter::readTableGet(uint32_t* tableIndex, Value* address) { MOZ_ASSERT(Classify(op_) == OpKind::TableGet); if (!readVarU32(tableIndex)) { return fail("unable to read table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.get"); } - if (!popWithType(ValType::I32, index)) { + const TableDesc& table = codeMeta_.tables[*tableIndex]; + + if (!popWithType(ToValType(table.addressType()), address)) { return false; } - infalliblePush(env_.tables[*tableIndex].elemType); + infalliblePush(table.elemType); return true; } @@ -3224,38 +3163,42 @@ inline bool OpIter::readTableGrow(uint32_t* tableIndex, if (!readVarU32(tableIndex)) { return fail("unable to read table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.grow"); } - if (!popWithType(ValType::I32, delta)) { + const TableDesc& table = codeMeta_.tables[*tableIndex]; + + if (!popWithType(ToValType(table.addressType()), delta)) { return false; } - if (!popWithType(env_.tables[*tableIndex].elemType, initValue)) { + if (!popWithType(table.elemType, initValue)) { return false; } - infalliblePush(ValType::I32); + infalliblePush(ToValType(table.addressType())); return true; } template -inline bool OpIter::readTableSet(uint32_t* tableIndex, Value* index, +inline bool OpIter::readTableSet(uint32_t* tableIndex, Value* address, Value* value) { MOZ_ASSERT(Classify(op_) == OpKind::TableSet); if (!readVarU32(tableIndex)) { return fail("unable to read table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.set"); } - if (!popWithType(env_.tables[*tableIndex].elemType, value)) { + const TableDesc& table = codeMeta_.tables[*tableIndex]; + + if (!popWithType(table.elemType, value)) { return false; } - return popWithType(ValType::I32, index); + return popWithType(ToValType(table.addressType()), address); } template @@ -3267,11 +3210,11 @@ inline bool OpIter::readTableSize(uint32_t* tableIndex) { if (!readVarU32(tableIndex)) { return fail("unable to read table index"); } - if (*tableIndex >= env_.tables.length()) { + if (*tableIndex >= codeMeta_.tables.length()) { return fail("table index out of range for table.size"); } - return push(ValType::I32); + return push(ToValType(codeMeta_.tables[*tableIndex].addressType())); } template @@ -3280,12 +3223,12 @@ inline bool OpIter::readGcTypeIndex(uint32_t* typeIndex) { return false; } - if (*typeIndex >= env_.types->length()) { + if (*typeIndex >= codeMeta_.types->length()) { return fail("type index out of range"); } - if (!env_.types->type(*typeIndex).isStructType() && - !env_.types->type(*typeIndex).isArrayType()) { + if (!codeMeta_.types->type(*typeIndex).isStructType() && + !codeMeta_.types->type(*typeIndex).isArrayType()) { return fail("not a gc type"); } @@ -3298,11 +3241,11 @@ inline bool OpIter::readStructTypeIndex(uint32_t* typeIndex) { return fail("unable to read type index"); } - if (*typeIndex >= env_.types->length()) { + if (*typeIndex >= codeMeta_.types->length()) { return fail("type index out of range"); } - if (!env_.types->type(*typeIndex).isStructType()) { + if (!codeMeta_.types->type(*typeIndex).isStructType()) { return fail("not a struct type"); } @@ -3315,11 +3258,11 @@ inline bool OpIter::readArrayTypeIndex(uint32_t* typeIndex) { return fail("unable to read type index"); } - if (*typeIndex >= env_.types->length()) { + if (*typeIndex >= codeMeta_.types->length()) { return fail("type index out of range"); } - if (!env_.types->type(*typeIndex).isArrayType()) { + if (!codeMeta_.types->type(*typeIndex).isArrayType()) { return fail("not an array type"); } @@ -3332,11 +3275,11 @@ inline bool OpIter::readFuncTypeIndex(uint32_t* typeIndex) { return fail("unable to read type index"); } - if (*typeIndex >= env_.types->length()) { + if (*typeIndex >= codeMeta_.types->length()) { return fail("type index out of range"); } - if (!env_.types->type(*typeIndex).isFuncType()) { + if (!codeMeta_.types->type(*typeIndex).isFuncType()) { return fail("not an func type"); } @@ -3357,8 +3300,6 @@ inline bool OpIter::readFieldIndex(uint32_t* fieldIndex, return true; } -#ifdef ENABLE_WASM_GC - template inline bool OpIter::readStructNew(uint32_t* typeIndex, ValueVector* argValues) { @@ -3368,7 +3309,7 @@ inline bool OpIter::readStructNew(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const StructType& structType = typeDef.structType(); if (!argValues->resize(structType.fields_.length())) { @@ -3395,7 +3336,7 @@ inline bool OpIter::readStructNewDefault(uint32_t* typeIndex) { return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const StructType& structType = typeDef.structType(); if (!structType.isDefaultable()) { @@ -3417,7 +3358,7 @@ inline bool OpIter::readStructGet(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const StructType& structType = typeDef.structType(); if (!readFieldIndex(fieldIndex, structType)) { @@ -3452,7 +3393,7 @@ inline bool OpIter::readStructSet(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const StructType& structType = typeDef.structType(); if (!readFieldIndex(fieldIndex, structType)) { @@ -3480,7 +3421,7 @@ inline bool OpIter::readArrayNew(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); if (!popWithType(ValType::I32, numElements)) { @@ -3505,7 +3446,7 @@ inline bool OpIter::readArrayNewFixed(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); if (!readVarU32(numElements)) { @@ -3541,7 +3482,7 @@ inline bool OpIter::readArrayNewDefault(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); if (!popWithType(ValType::I32, numElements)) { @@ -3569,16 +3510,16 @@ inline bool OpIter::readArrayNewData(uint32_t* typeIndex, return fail("unable to read segment index"); } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); StorageType elemType = arrayType.elementType(); if (!elemType.isNumber() && !elemType.isPacked() && !elemType.isVector()) { return fail("element type must be i8/i16/i32/i64/f32/f64/v128"); } - if (env_.dataCount.isNothing()) { + if (codeMeta_.dataCount.isNothing()) { return fail("datacount section missing"); } - if (*segIndex >= *env_.dataCount) { + if (*segIndex >= *codeMeta_.dataCount) { return fail("segment index is out of range"); } @@ -3606,18 +3547,17 @@ inline bool OpIter::readArrayNewElem(uint32_t* typeIndex, return fail("unable to read segment index"); } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); StorageType dstElemType = arrayType.elementType(); if (!dstElemType.isRefType()) { return fail("element type is not a reftype"); } - if (*segIndex >= env_.elemSegments.length()) { + if (*segIndex >= codeMeta_.elemSegmentTypes.length()) { return fail("segment index is out of range"); } - const ModuleElemSegment& elemSeg = env_.elemSegments[*segIndex]; - RefType srcElemType = elemSeg.elemType; + RefType srcElemType = codeMeta_.elemSegmentTypes[*segIndex]; // srcElemType needs to be a subtype (child) of dstElemType if (!checkIsSubtypeOf(srcElemType, dstElemType.refType())) { return fail("incompatible element types"); @@ -3648,7 +3588,7 @@ inline bool OpIter::readArrayInitData(uint32_t* typeIndex, return fail("unable to read segment index"); } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); StorageType elemType = arrayType.elementType(); if (!elemType.isNumber() && !elemType.isPacked() && !elemType.isVector()) { @@ -3657,10 +3597,10 @@ inline bool OpIter::readArrayInitData(uint32_t* typeIndex, if (!arrayType.isMutable()) { return fail("destination array is not mutable"); } - if (env_.dataCount.isNothing()) { + if (codeMeta_.dataCount.isNothing()) { return fail("datacount section missing"); } - if (*segIndex >= *env_.dataCount) { + if (*segIndex >= *codeMeta_.dataCount) { return fail("segment index is out of range"); } @@ -3691,7 +3631,7 @@ inline bool OpIter::readArrayInitElem(uint32_t* typeIndex, return fail("unable to read segment index"); } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); StorageType dstElemType = arrayType.elementType(); if (!arrayType.isMutable()) { @@ -3700,12 +3640,11 @@ inline bool OpIter::readArrayInitElem(uint32_t* typeIndex, if (!dstElemType.isRefType()) { return fail("element type is not a reftype"); } - if (*segIndex >= env_.elemSegments.length()) { + if (*segIndex >= codeMeta_.elemSegmentTypes.length()) { return fail("segment index is out of range"); } - const ModuleElemSegment& elemSeg = env_.elemSegments[*segIndex]; - RefType srcElemType = elemSeg.elemType; + RefType srcElemType = codeMeta_.elemSegmentTypes[*segIndex]; // srcElemType needs to be a subtype (child) of dstElemType if (!checkIsSubtypeOf(srcElemType, dstElemType.refType())) { return fail("incompatible element types"); @@ -3733,7 +3672,7 @@ inline bool OpIter::readArrayGet(uint32_t* typeIndex, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); if (!popWithType(ValType::I32, index)) { @@ -3766,7 +3705,7 @@ inline bool OpIter::readArraySet(uint32_t* typeIndex, Value* val, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); if (!arrayType.isMutable()) { @@ -3796,30 +3735,27 @@ inline bool OpIter::readArrayLen(Value* ptr) { } template -inline bool OpIter::readArrayCopy(int32_t* elemSize, - bool* elemsAreRefTyped, +inline bool OpIter::readArrayCopy(uint32_t* dstArrayTypeIndex, + uint32_t* srcArrayTypeIndex, Value* dstArray, Value* dstIndex, Value* srcArray, Value* srcIndex, Value* numElements) { - // *elemSize is set to 1/2/4/8/16, and *elemsAreRefTyped is set to indicate - // *ref-typeness of elements. MOZ_ASSERT(Classify(op_) == OpKind::ArrayCopy); - uint32_t dstTypeIndex, srcTypeIndex; - if (!readArrayTypeIndex(&dstTypeIndex)) { + if (!readArrayTypeIndex(dstArrayTypeIndex)) { return false; } - if (!readArrayTypeIndex(&srcTypeIndex)) { + if (!readArrayTypeIndex(srcArrayTypeIndex)) { return false; } - // `dstTypeIndex`/`srcTypeIndex` are ensured by the above to both be array - // types. Reject if: + // `dstArrayTypeIndex`/`srcArrayTypeIndex` are ensured by the above to both be + // array types. Reject if: // * the dst array is not of mutable type // * the element types are incompatible - const TypeDef& dstTypeDef = env_.types->type(dstTypeIndex); + const TypeDef& dstTypeDef = codeMeta_.types->type(*dstArrayTypeIndex); const ArrayType& dstArrayType = dstTypeDef.arrayType(); - const TypeDef& srcTypeDef = env_.types->type(srcTypeIndex); + const TypeDef& srcTypeDef = codeMeta_.types->type(*srcArrayTypeIndex); const ArrayType& srcArrayType = srcTypeDef.arrayType(); StorageType dstElemType = dstArrayType.elementType(); StorageType srcElemType = srcArrayType.elementType(); @@ -3830,13 +3766,7 @@ inline bool OpIter::readArrayCopy(int32_t* elemSize, if (!checkIsSubtypeOf(srcElemType, dstElemType)) { return fail("incompatible element types"); } - bool dstIsRefType = dstElemType.isRefType(); - MOZ_ASSERT(dstIsRefType == srcElemType.isRefType()); - - *elemSize = int32_t(dstElemType.size()); - *elemsAreRefTyped = dstIsRefType; - MOZ_ASSERT(*elemSize >= 1 && *elemSize <= 16); - MOZ_ASSERT_IF(*elemsAreRefTyped, *elemSize == 4 || *elemSize == 8); + MOZ_ASSERT(dstElemType.isRefType() == srcElemType.isRefType()); if (!popWithType(ValType::I32, numElements)) { return false; @@ -3864,7 +3794,7 @@ inline bool OpIter::readArrayFill(uint32_t* typeIndex, Value* array, return false; } - const TypeDef& typeDef = env_.types->type(*typeIndex); + const TypeDef& typeDef = codeMeta_.types->type(*typeIndex); const ArrayType& arrayType = typeDef.arrayType(); if (!arrayType.isMutable()) { return fail("destination array is not mutable"); @@ -4068,8 +3998,6 @@ inline bool OpIter::readRefConversion(RefType operandType, return true; } -#endif // ENABLE_WASM_GC - #ifdef ENABLE_WASM_SIMD template @@ -4177,7 +4105,7 @@ inline bool OpIter::readVectorShuffle(Value* v1, Value* v2, template inline bool OpIter::readV128Const(V128* value) { - MOZ_ASSERT(Classify(op_) == OpKind::V128); + MOZ_ASSERT(Classify(op_) == OpKind::V128Const); if (!d_.readV128Const(value)) { return false; @@ -4267,7 +4195,7 @@ inline bool OpIter::readStackSwitch(StackSwitchKind* kind, Value* suspender, Value* fn, Value* data) { MOZ_ASSERT(Classify(op_) == OpKind::StackSwitch); - MOZ_ASSERT(env_.jsPromiseIntegrationEnabled()); + MOZ_ASSERT(codeMeta_.jsPromiseIntegrationEnabled()); uint32_t kind_; if (!d_.readVarU32(&kind_)) { return false; @@ -4281,22 +4209,28 @@ inline bool OpIter::readStackSwitch(StackSwitchKind* kind, return false; } # if DEBUG - // Verify that the function takes suspender and data as parameters and - // returns no values. + // Verify that the function takes suspender and data as parameters. MOZ_ASSERT((*kind == StackSwitchKind::ContinueOnSuspendable) == stackType.isNullableAsOperand()); if (!stackType.isNullableAsOperand()) { ValType valType = stackType.valType(); MOZ_ASSERT(valType.isRefType() && valType.typeDef()->isFuncType()); const FuncType& func = valType.typeDef()->funcType(); - MOZ_ASSERT(func.args().length() == 2 && func.results().empty() && - func.arg(0).isExternRef() && + MOZ_ASSERT(func.args().length() == 2 && func.arg(0).isExternRef() && ValType::isSubTypeOf(func.arg(1), RefType::any())); + MOZ_ASSERT_IF(*kind != StackSwitchKind::SwitchToMain, + func.results().empty()); + MOZ_ASSERT_IF(*kind == StackSwitchKind::SwitchToMain, + func.results().length() == 1 && func.result(0).isAnyRef()); } # endif if (!popWithType(ValType(RefType::extern_()), suspender)) { return false; } + // Returns a value only for SwitchToMain. + if (*kind == StackSwitchKind::SwitchToMain) { + return push(RefType::extern_()); + } return true; } #endif @@ -4317,7 +4251,7 @@ inline bool OpIter::readCallBuiltinModuleFunc( *builtinModuleFunc = &BuiltinModuleFuncs::getFromId(BuiltinModuleFuncId(id)); - if ((*builtinModuleFunc)->usesMemory() && env_.numMemories() == 0) { + if ((*builtinModuleFunc)->usesMemory() && codeMeta_.numMemories() == 0) { return fail("can't touch memory without memory"); } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmPI.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmPI.cpp index 52928459923..d244dc45ee6 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmPI.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmPI.cpp @@ -19,8 +19,17 @@ #include "wasm/WasmPI.h" #include "builtin/Promise.h" +#include "debugger/DebugAPI.h" +#include "debugger/Debugger.h" +#include "debugger/Environment.h" +#include "debugger/Frame.h" +#include "debugger/Script.h" +#include "debugger/Source.h" +#include "jit/arm/Simulator-arm.h" +#include "jit/JitRuntime.h" #include "jit/MIRGenerator.h" #include "js/CallAndConstruct.h" +#include "js/Printf.h" #include "vm/Iteration.h" #include "vm/JSContext.h" #include "vm/JSObject.h" @@ -30,12 +39,17 @@ #include "wasm/WasmContext.h" #include "wasm/WasmFeatures.h" #include "wasm/WasmGenerator.h" +#include "wasm/WasmIonCompile.h" // IonPlatformSupport #include "wasm/WasmValidate.h" #include "vm/JSObject-inl.h" #include "wasm/WasmGcObject-inl.h" #include "wasm/WasmInstance-inl.h" +#ifdef JS_CODEGEN_ARM64 +# include "jit/arm64/vixl/Simulator-vixl.h" +#endif + #ifdef XP_WIN # include "util/WindowsWrapper.h" #endif @@ -51,22 +65,23 @@ SuspenderObjectData::SuspenderObjectData(void* stackMemory) suspendableFP_(nullptr), suspendableSP_(static_cast(stackMemory) + SuspendableStackPlusRedZoneSize), - state_(SuspenderState::Initial) {} + state_(SuspenderState::Initial), + suspendedBy_(nullptr) {} void SuspenderObjectData::releaseStackMemory() { js_free(stackMemory_); stackMemory_ = nullptr; } -# ifdef _WIN64 +# if defined(_WIN32) // On WIN64, the Thread Information Block stack limits has to be modified to // avoid failures on SP checks. void SuspenderObjectData::updateTIBStackFields() { _NT_TIB* tib = reinterpret_cast<_NT_TIB*>(::NtCurrentTeb()); savedStackBase_ = tib->StackBase; savedStackLimit_ = tib->StackLimit; - uintptr_t stack_limit = (uintptr_t)stackMemory_ + SuspendableRedZoneSize; - uintptr_t stack_base = stack_limit + SuspendableStackSize; + uintptr_t stack_limit = (uintptr_t)stackMemory_; + uintptr_t stack_base = stack_limit + SuspendableStackPlusRedZoneSize; tib->StackBase = (void*)stack_base; tib->StackLimit = (void*)stack_limit; } @@ -78,10 +93,47 @@ void SuspenderObjectData::restoreTIBStackFields() { } # endif +# ifdef JS_SIMULATOR_ARM64 +void SuspenderObjectData::switchSimulatorToMain() { + auto* sim = Simulator::Current(); + suspendableSP_ = (void*)sim->xreg(Registers::sp, vixl::Reg31IsStackPointer); + suspendableFP_ = (void*)sim->xreg(Registers::fp); + sim->set_xreg(Registers::sp, (int64_t)mainSP_, vixl::Debugger::LogRegWrites, + vixl::Reg31IsStackPointer); + sim->set_xreg(Registers::fp, (int64_t)mainFP_); +} + +void SuspenderObjectData::switchSimulatorToSuspendable() { + auto* sim = Simulator::Current(); + mainSP_ = (void*)sim->xreg(Registers::sp, vixl::Reg31IsStackPointer); + mainFP_ = (void*)sim->xreg(Registers::fp); + sim->set_xreg(Registers::sp, (int64_t)suspendableSP_, + vixl::Debugger::LogRegWrites, vixl::Reg31IsStackPointer); + sim->set_xreg(Registers::fp, (int64_t)suspendableFP_); +} +# endif + +# ifdef JS_SIMULATOR_ARM +void SuspenderObjectData::switchSimulatorToMain() { + suspendableSP_ = (void*)Simulator::Current()->get_register(Simulator::sp); + suspendableFP_ = (void*)Simulator::Current()->get_register(Simulator::fp); + Simulator::Current()->set_register(Simulator::sp, (int)mainSP_); + Simulator::Current()->set_register(Simulator::fp, (int)mainFP_); +} + +void SuspenderObjectData::switchSimulatorToSuspendable() { + mainSP_ = (void*)Simulator::Current()->get_register(Simulator::sp); + mainFP_ = (void*)Simulator::Current()->get_register(Simulator::fp); + Simulator::Current()->set_register(Simulator::sp, (int)suspendableSP_); + Simulator::Current()->set_register(Simulator::fp, (int)suspendableFP_); +} +# endif + // Slots that used in various JSFunctionExtended below. const size_t SUSPENDER_SLOT = 0; const size_t WRAPPED_FN_SLOT = 1; const size_t CONTINUE_ON_SUSPENDABLE_SLOT = 1; +const size_t PROMISE_SLOT = 2; SuspenderContext::SuspenderContext() : activeSuspender_(nullptr), suspendedStacks_() {} @@ -105,32 +157,44 @@ void SuspenderContext::trace(JSTracer* trc) { } } -void SuspenderContext::traceRoots(JSTracer* trc) { - for (const SuspenderObjectData& data : suspendedStacks_) { - void* startFP = data.suspendableFP(); - void* returnAddress = data.suspendedReturnAddress(); - void* exitFP = data.suspendableExitFP(); - MOZ_ASSERT(startFP != exitFP); +static void TraceSuspendableStack(JSTracer* trc, + const SuspenderObjectData& data) { + void* startFP = data.suspendableFP(); + void* returnAddress = data.suspendedReturnAddress(); + void* exitFP = data.suspendableExitFP(); + MOZ_ASSERT(startFP != exitFP); - WasmFrameIter iter(static_cast(startFP), - returnAddress); - MOZ_ASSERT(iter.stackSwitched()); - uintptr_t highestByteVisitedInPrevWasmFrame = 0; - while (true) { - MOZ_ASSERT(!iter.done()); - uint8_t* nextPC = iter.resumePCinCurrentFrame(); - Instance* instance = iter.instance(); - TraceInstanceEdge(trc, instance, "WasmFrameIter instance"); - highestByteVisitedInPrevWasmFrame = instance->traceFrame( - trc, iter, nextPC, highestByteVisitedInPrevWasmFrame); - if (iter.frame() == exitFP) { - break; - } - ++iter; - if (iter.stackSwitched()) { - highestByteVisitedInPrevWasmFrame = 0; - } + WasmFrameIter iter(static_cast(startFP), returnAddress); + MOZ_ASSERT(iter.currentFrameStackSwitched()); + uintptr_t highestByteVisitedInPrevWasmFrame = 0; + while (true) { + MOZ_ASSERT(!iter.done()); + uint8_t* nextPC = iter.resumePCinCurrentFrame(); + Instance* instance = iter.instance(); + TraceInstanceEdge(trc, instance, "WasmFrameIter instance"); + highestByteVisitedInPrevWasmFrame = instance->traceFrame( + trc, iter, nextPC, highestByteVisitedInPrevWasmFrame); + if (iter.frame() == exitFP) { + break; } + ++iter; + if (iter.currentFrameStackSwitched()) { + highestByteVisitedInPrevWasmFrame = 0; + } + } +} + +void SuspenderContext::traceRoots(JSTracer* trc) { + // The suspendedStacks_ contains suspended stacks frames that need to be + // traced only during minor GC. The major GC tracing is happening via + // SuspenderObject::trace. + // Non-suspended stack frames are traced as part of TraceJitActivations. + if (!trc->isTenuringTracer()) { + return; + } + gc::AssertRootMarkingPhase(trc); + for (const SuspenderObjectData& data : suspendedStacks_) { + TraceSuspendableStack(trc, data); } } @@ -153,7 +217,9 @@ class SuspenderObject : public NativeObject { public: static const JSClass class_; - enum { DataSlot, PromisingPromiseSlot, SuspendingPromiseSlot, SlotCount }; + enum { DataSlot, PromisingPromiseSlot, SuspendingReturnTypeSlot, SlotCount }; + + enum class ReturnType : int32_t { Unknown, Promise, Exception }; static SuspenderObject* create(JSContext* cx) { for (;;) { @@ -195,7 +261,8 @@ class SuspenderObject : public NativeObject { suspender->initReservedSlot(DataSlot, PrivateValue(data)); suspender->initReservedSlot(PromisingPromiseSlot, NullValue()); - suspender->initReservedSlot(SuspendingPromiseSlot, NullValue()); + suspender->initReservedSlot(SuspendingReturnTypeSlot, + Int32Value(int32_t(ReturnType::Unknown))); return suspender; } @@ -209,14 +276,18 @@ class SuspenderObject : public NativeObject { setReservedSlot(PromisingPromiseSlot, ObjectOrNullValue(promise)); } - PromiseObject* suspendingPromise() const { - return &getReservedSlot(SuspendingPromiseSlot) - .toObject() - .as(); + ReturnType suspendingReturnType() const { + return ReturnType(getReservedSlot(SuspendingReturnTypeSlot).toInt32()); } - void setSuspendingPromise(Handle promise) { - setReservedSlot(SuspendingPromiseSlot, ObjectOrNullValue(promise)); + void setSuspendingReturnType(ReturnType type) { + // The SuspendingReturnTypeSlot will change after result is defined, + // and becomes invalid after GetSuspendingPromiseResult. The assert is + // checking if the result was processed by GetSuspendingPromiseResult. + MOZ_ASSERT((type == ReturnType::Unknown) != + (suspendingReturnType() == ReturnType::Unknown)); + + setReservedSlot(SuspendingReturnTypeSlot, Int32Value(int32_t(type))); } JS::NativeStackLimit getStackMemoryLimit() { @@ -241,18 +312,23 @@ class SuspenderObject : public NativeObject { void resume(JSContext* cx); void leave(JSContext* cx); + // Modifies frames to inject the suspendable stack back into the main one. + void forwardToSuspendable(); + private: static const JSClassOps classOps_; static void finalize(JS::GCContext* gcx, JSObject* obj); + static void trace(JSTracer* trc, JSObject* obj); }; static_assert(SuspenderObjectDataSlot == SuspenderObject::DataSlot); const JSClass SuspenderObject::class_ = { "SuspenderObject", - JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_BACKGROUND_FINALIZE, - &SuspenderObject::classOps_}; + JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_FOREGROUND_FINALIZE, + &SuspenderObject::classOps_, +}; const JSClassOps SuspenderObject::classOps_ = { nullptr, // addProperty @@ -264,7 +340,7 @@ const JSClassOps SuspenderObject::classOps_ = { finalize, // finalize nullptr, // call nullptr, // construct - nullptr, // trace + trace, // trace }; /* static */ @@ -274,15 +350,39 @@ void SuspenderObject::finalize(JS::GCContext* gcx, JSObject* obj) { return; } SuspenderObjectData* data = suspender.data(); - MOZ_RELEASE_ASSERT(data->state() == SuspenderState::Moribund); - MOZ_RELEASE_ASSERT(!data->stackMemory()); + if (data->state() == SuspenderState::Moribund) { + MOZ_RELEASE_ASSERT(!data->stackMemory()); + } else { + // Cleaning stack memory and removing from suspendableStacks_. + data->releaseStackMemory(); + if (SuspenderContext* scx = data->suspendedBy()) { + scx->suspendedStacks_.remove(data); + } + } js_free(data); } +/* static */ +void SuspenderObject::trace(JSTracer* trc, JSObject* obj) { + SuspenderObject& suspender = obj->as(); + if (!suspender.hasData()) { + return; + } + SuspenderObjectData& data = *suspender.data(); + // The SuspenderObjectData refers stacks frames that need to be traced + // only during major GC to determine if SuspenderObject content is + // reachable from JS. The frames must be suspended -- non-suspended + // stack frames are traced as part of TraceJitActivations. + if (!data.traceable() || trc->isTenuringTracer()) { + return; + } + TraceSuspendableStack(trc, data); +} + void SuspenderObject::setMoribund(JSContext* cx) { MOZ_ASSERT(state() == SuspenderState::Active); ResetInstanceStackLimits(cx); -# ifdef _WIN64 +# if defined(_WIN32) data()->restoreTIBStackFields(); # endif SuspenderObjectData* data = this->data(); @@ -297,7 +397,7 @@ void SuspenderObject::setMoribund(JSContext* cx) { void SuspenderObject::setActive(JSContext* cx) { data()->setState(SuspenderState::Active); UpdateInstanceStackLimitsForSuspendableStack(cx, getStackMemoryLimit()); -# ifdef _WIN64 +# if defined(_WIN32) data()->updateTIBStackFields(); # endif } @@ -305,7 +405,7 @@ void SuspenderObject::setActive(JSContext* cx) { void SuspenderObject::setSuspended(JSContext* cx) { data()->setState(SuspenderState::Suspended); ResetInstanceStackLimits(cx); -# ifdef _WIN64 +# if defined(_WIN32) data()->restoreTIBStackFields(); # endif } @@ -314,24 +414,67 @@ void SuspenderObject::enter(JSContext* cx) { MOZ_ASSERT(state() == SuspenderState::Initial); cx->wasm().promiseIntegration.setActiveSuspender(this); setActive(cx); +# ifdef DEBUG + cx->runtime()->jitRuntime()->disallowArbitraryCode(); +# endif } void SuspenderObject::suspend(JSContext* cx) { MOZ_ASSERT(state() == SuspenderState::Active); setSuspended(cx); cx->wasm().promiseIntegration.suspendedStacks_.pushFront(data()); + data()->setSuspendedBy(&cx->wasm().promiseIntegration); cx->wasm().promiseIntegration.setActiveSuspender(nullptr); +# ifdef DEBUG + cx->runtime()->jitRuntime()->clearDisallowArbitraryCode(); +# endif + + if (cx->realm()->isDebuggee()) { + WasmFrameIter iter(cx->activation()->asJit()); + while (true) { + MOZ_ASSERT(!iter.done()); + if (iter.debugEnabled()) { + DebugAPI::onSuspendWasmFrame(cx, iter.debugFrame()); + } + ++iter; + if (iter.currentFrameStackSwitched()) { + break; + } + } + } } void SuspenderObject::resume(JSContext* cx) { MOZ_ASSERT(state() == SuspenderState::Suspended); cx->wasm().promiseIntegration.setActiveSuspender(this); setActive(cx); + data()->setSuspendedBy(nullptr); cx->wasm().promiseIntegration.suspendedStacks_.remove(data()); +# ifdef DEBUG + cx->runtime()->jitRuntime()->disallowArbitraryCode(); +# endif + + if (cx->realm()->isDebuggee()) { + for (FrameIter iter(cx);; ++iter) { + MOZ_RELEASE_ASSERT(!iter.done(), "expecting stackSwitched()"); + if (iter.isWasm()) { + WasmFrameIter& wasmIter = iter.wasmFrame(); + if (wasmIter.currentFrameStackSwitched()) { + break; + } + if (wasmIter.debugEnabled()) { + DebugAPI::onResumeWasmFrame(cx, iter); + } + } + } + } } void SuspenderObject::leave(JSContext* cx) { cx->wasm().promiseIntegration.setActiveSuspender(nullptr); +# ifdef DEBUG + cx->runtime()->jitRuntime()->clearDisallowArbitraryCode(); +# endif // We are exiting alternative stack if state is active, // otherwise the stack was just suspended. switch (state()) { @@ -346,48 +489,17 @@ void SuspenderObject::leave(JSContext* cx) { } } -bool ParseSuspendingPromisingString(JSContext* cx, HandleValue val, - SuspenderArgPosition& result) { - if (val.isNullOrUndefined()) { - result = SuspenderArgPosition::None; - return true; - } - - RootedString str(cx, ToString(cx, val)); - if (!str) { - return false; - } - Rooted linear(cx, str->ensureLinear(cx)); - if (!linear) { - return false; - } - - if (StringEqualsLiteral(linear, "first")) { - result = SuspenderArgPosition::First; - } else if (StringEqualsLiteral(linear, "last")) { - result = SuspenderArgPosition::Last; - } else { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_ARG_POSITION); - return false; - } - return true; +void SuspenderObject::forwardToSuspendable() { + // Injecting suspendable stack back into main one at the exit frame. + SuspenderObjectData* data = this->data(); + uint8_t* mainExitFP = (uint8_t*)data->mainExitFP(); + *reinterpret_cast(mainExitFP + Frame::callerFPOffset()) = + data->suspendableFP(); + *reinterpret_cast(mainExitFP + Frame::returnAddressOffset()) = + data->suspendedReturnAddress(); } -using CallImportData = Instance::WasmJSPICallImportData; - -/*static*/ -bool CallImportData::Call(CallImportData* data) { - Instance* instance = data->instance; - JSContext* cx = instance->cx(); - return instance->callImport(cx, data->funcImportIndex, data->argc, - data->argv); -} - -bool CallImportOnMainThread(JSContext* cx, Instance* instance, - int32_t funcImportIndex, int32_t argc, - uint64_t* argv) { - CallImportData data = {instance, funcImportIndex, argc, argv}; +bool CallOnMainStack(JSContext* cx, CallOnMainStackFn fn, void* data) { Rooted suspender( cx, cx->wasm().promiseIntegration.activeSuspender()); SuspenderObjectData* stacks = suspender->data(); @@ -397,16 +509,28 @@ bool CallImportOnMainThread(JSContext* cx, Instance* instance, MOZ_ASSERT(suspender->state() == SuspenderState::Active); suspender->setSuspended(cx); +# ifdef JS_SIMULATOR +# if defined(JS_SIMULATOR_ARM64) || defined(JS_SIMULATOR_ARM) + // The simulator is using its own stack, however switching is needed for + // virtual registers. + stacks->switchSimulatorToMain(); + bool res = fn(data); + stacks->switchSimulatorToSuspendable(); +# else +# error "not supported" +# endif +# else // The platform specific code below inserts offsets as strings into inline // assembly. CHECK_OFFSETS verifies the specified literals in macros below. -# define CHECK_OFFSETS(MAIN_FP_OFFSET, MAIN_SP_OFFSET, SUSPENDABLE_FP_OFFSET, \ - SUSPENDABLE_SP_OFFSET) \ - static_assert((MAIN_FP_OFFSET) == SuspenderObjectData::offsetOfMainFP() && \ - (MAIN_SP_OFFSET) == SuspenderObjectData::offsetOfMainSP() && \ - (SUSPENDABLE_FP_OFFSET) == \ - SuspenderObjectData::offsetOfSuspendableFP() && \ - (SUSPENDABLE_SP_OFFSET) == \ - SuspenderObjectData::offsetOfSuspendableSP()); +# define CHECK_OFFSETS(MAIN_FP_OFFSET, MAIN_SP_OFFSET, \ + SUSPENDABLE_FP_OFFSET, SUSPENDABLE_SP_OFFSET) \ + static_assert( \ + (MAIN_FP_OFFSET) == SuspenderObjectData::offsetOfMainFP() && \ + (MAIN_SP_OFFSET) == SuspenderObjectData::offsetOfMainSP() && \ + (SUSPENDABLE_FP_OFFSET) == \ + SuspenderObjectData::offsetOfSuspendableFP() && \ + (SUSPENDABLE_SP_OFFSET) == \ + SuspenderObjectData::offsetOfSuspendableSP()); // The following assembly code temporarily switches FP/SP pointers to be on // main stack, while maintaining frames linking. After @@ -462,7 +586,7 @@ bool CallImportOnMainThread(JSContext* cx, Instance* instance, "\n mov sp, x27 " \ "\n mov %0, x0" \ : "=r"(res) \ - : "r"(stacks), "r"(CallImportData::Call), "r"(&data) \ + : "r"(stacks), "r"(fn), "r"(data) \ : "x0", "x3", "x27", CALLER_SAVED_REGS, "cc", "memory") INLINED_ASM(24, 32, 40, 48); @@ -493,8 +617,8 @@ bool CallImportOnMainThread(JSContext* cx, Instance* instance, \ "\n movq %%rax, %0" \ : "=r"(res) \ - : "r"(stacks), "r"(CallImportData::Call), "r"(&data) \ - : "rcx", "rax") + : "r"(stacks), "r"(fn), "r"(data) \ + : "rcx", "rax", "cc", "memory") INLINED_ASM(24, 32, 40, 48); # elif defined(__x86_64__) @@ -524,14 +648,113 @@ bool CallImportOnMainThread(JSContext* cx, Instance* instance, \ "\n movq %%rax, %0" \ : "=r"(res) \ - : "r"(stacks), "r"(CallImportData::Call), "r"(&data) \ - : "rdi", "rax") + : "r"(stacks), "r"(fn), "r"(data) \ + : "rdi", "rax", "cc", "memory") + INLINED_ASM(24, 32, 40, 48); +# elif defined(__i386__) || defined(_M_IX86) +# define CALLER_SAVED_REGS "eax", "ecx", "edx" +# define INLINED_ASM(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP) \ + CHECK_OFFSETS(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP); \ + asm("\n mov %1, %%edx" \ + "\n mov %%ebp, " #SUSPENDABLE_FP "(%%edx)" \ + "\n mov %%esp, " #SUSPENDABLE_SP "(%%edx)" \ + \ + "\n mov " #MAIN_FP "(%%edx), %%ebp" \ + "\n mov " #MAIN_SP "(%%edx), %%esp" \ + \ + "\n push %%edx" \ + "\n sub $8, %%esp" \ + "\n push %3" \ + "\n call *%2" \ + "\n add $12, %%esp" \ + "\n pop %%edx" \ + \ + "\n mov %%ebp, " #MAIN_FP "(%%edx)" \ + "\n mov %%esp, " #MAIN_SP "(%%edx)" \ + \ + "\n mov " #SUSPENDABLE_FP "(%%edx), %%ebp" \ + "\n mov " #SUSPENDABLE_SP "(%%edx), %%esp" \ + \ + "\n mov %%eax, %0" \ + : "=r"(res) \ + : "r"(stacks), "r"(fn), "r"(data) \ + : CALLER_SAVED_REGS, "cc", "memory") + INLINED_ASM(12, 16, 20, 24); + +# elif defined(__arm__) +# define INLINED_ASM(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP) \ + CHECK_OFFSETS(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP); \ + asm("\n mov r0, %1" \ + "\n mov r1, sp" \ + "\n str r11, [r0, #" #SUSPENDABLE_FP "]" \ + "\n str r1, [r0, #" #SUSPENDABLE_SP "]" \ + \ + "\n ldr r11, [r0, #" #MAIN_FP "]" \ + "\n ldr r1, [r0, #" #MAIN_SP "]" \ + "\n mov sp, r1" \ + \ + "\n str r0, [sp, #-8]! " \ + \ + "\n mov r0, %3" \ + "\n blx %2" \ + \ + "\n ldr r2, [sp], #8 " \ + \ + "\n mov r1, sp" \ + "\n str r11, [r2, #" #MAIN_FP "]" \ + "\n str r1, [r2, #" #MAIN_SP "]" \ + \ + "\n ldr r11, [r2, #" #SUSPENDABLE_FP "]" \ + "\n ldr r1, [r2, #" #SUSPENDABLE_SP "]" \ + "\n mov sp, r1" \ + "\n mov %0, r0" \ + : "=r"(res) \ + : "r"(stacks), "r"(fn), "r"(data) \ + : "r0", "r1", "r2", "r3", "cc", "memory") + INLINED_ASM(12, 16, 20, 24); + +#elif defined(__loongarch_lp64) +# define CALLER_SAVED_REGS \ + "$ra", "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7", \ + "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", \ + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", \ + "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", \ + "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23" +# define INLINED_ASM(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP) \ + CHECK_OFFSETS(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP); \ + asm volatile( \ + "\n move $a0, %1" \ + "\n st.d $fp, $a0, " #SUSPENDABLE_FP \ + "\n st.d $sp, $a0, " #SUSPENDABLE_SP \ + \ + "\n ld.d $fp, $a0, " #MAIN_FP \ + "\n ld.d $sp, $a0, " #MAIN_SP \ + \ + "\n addi.d $sp, $sp, -16" \ + "\n st.d $a0, $sp, 8" \ + \ + "\n move $a0, %3" \ + "\n jirl $ra, %2, 0" \ + \ + "\n ld.d $a3, $sp, 8" \ + "\n addi.d $sp, $sp, 16" \ + \ + "\n st.d $fp, $a3, " #MAIN_FP \ + "\n st.d $sp, $a3, " #MAIN_SP \ + \ + "\n ld.d $fp, $a3, " #SUSPENDABLE_FP \ + "\n ld.d $sp, $a3, " #SUSPENDABLE_SP \ + "\n move %0, $a0" \ + : "=r"(res) \ + : "r"(stacks), "r"(fn), "r"(data) \ + : "$a0", "$a3", CALLER_SAVED_REGS, "cc", "memory") INLINED_ASM(24, 32, 40, 48); # else MOZ_CRASH("Not supported for this platform"); # endif // clang-format on +# endif // JS_SIMULATOR bool ok = res; suspender->setActive(cx); @@ -558,7 +781,6 @@ static void CleanupActiveSuspender(JSContext* cx) { // (type $params (struct (field ..)*))) // (type $results (struct (field ..)*))) // (import "" "" (func $suspending.wrappedfn ..)) -// (import "" "" (func $suspending.add-promise-reactions ..)) // (func $suspending.exported .. ) // (func $suspending.trampoline ..) // (func $suspending.continue-on-suspendable ..) @@ -579,7 +801,6 @@ class SuspendingFunctionModuleFactory { enum FnIdx { WrappedFnIndex, - GetSuspendingResultsFnIndex, ExportedFnIndex, TrampolineFnIndex, ContinueOnSuspendableFnIndex @@ -588,17 +809,11 @@ class SuspendingFunctionModuleFactory { private: // Builds function that will be imported to wasm module: // (func $suspending.exported - // (param $suspender externref)? (param ..)* (param $suspender externref)? - // (result ..)* - // (local $suspender externref)? + // (param ..)* (result ..)* + // (local $suspender externref) // (local $results (ref $results)) - // ;; #if checkSuspender - // local.get $suspender - // call $builtin.check-suspender - // ;; #else // call $builtin.current-suspender // local.tee $suspender - // ;; #endif // ref.func $suspending.trampoline // local.get $i* // stuct.new $param-type @@ -609,13 +824,12 @@ class SuspendingFunctionModuleFactory { // local.set $results // (struct.get $results (local.get $results))* // ) - bool encodeExportedFunction(ModuleEnvironment& moduleEnv, uint32_t paramsSize, + bool encodeExportedFunction(CodeMetadata& codeMeta, uint32_t paramsSize, uint32_t resultSize, uint32_t paramsOffset, - uint32_t suspenderIndex, bool checkSuspender, RefType resultType, Bytes& bytecode) { - Encoder encoder(bytecode, *moduleEnv.types); + Encoder encoder(bytecode, *codeMeta.types); ValTypeVector locals; - if (!checkSuspender && !locals.emplaceBack(RefType::extern_())) { + if (!locals.emplaceBack(RefType::extern_())) { return false; } if (!locals.emplaceBack(resultType)) { @@ -625,33 +839,21 @@ class SuspendingFunctionModuleFactory { return false; } - if (checkSuspender) { - if (!encoder.writeOp(Op::LocalGet) || - !encoder.writeVarU32(suspenderIndex)) { - return false; - } - if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || - !encoder.writeVarU32((uint32_t)BuiltinModuleFuncId::CheckSuspender)) { - return false; - } - } else { - if (!encoder.writeOp(Op::I32Const) || !encoder.writeVarU32(0)) { - return false; - } - if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || - !encoder.writeVarU32( - (uint32_t)BuiltinModuleFuncId::CurrentSuspender)) { - return false; - } - if (!encoder.writeOp(Op::LocalTee) || - !encoder.writeVarU32(suspenderIndex)) { - return false; - } + const int suspenderIndex = paramsSize; + if (!encoder.writeOp(Op::I32Const) || !encoder.writeVarU32(0)) { + return false; + } + if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || + !encoder.writeVarU32((uint32_t)BuiltinModuleFuncId::CurrentSuspender)) { + return false; + } + if (!encoder.writeOp(Op::LocalTee) || + !encoder.writeVarU32(suspenderIndex)) { + return false; } // Results local is located after all params and suspender. - // Adding 1 to paramSize for checkSuspender and ! cases. - int resultsIndex = paramsSize + 1; + const int resultsIndex = paramsSize + 1; if (!encoder.writeOp(Op::RefFunc) || !encoder.writeVarU32(TrampolineFnIndex)) { @@ -700,27 +902,53 @@ class SuspendingFunctionModuleFactory { // Builds function that is called on main stack: // (func $suspending.trampoline - // (param $params (ref $suspender) (ref $param-type)) - // (result externref) - // local.get $suspender ;; for call $process-promise - // (struct.get $param-type $i (local.get $param))* - // call $suspending.wrappedfn - // ref.func $suspending.continue-on-suspendable - // call $suspending.add-promise-reactions + // (param $params (ref $suspender)) (param $param (ref $param-type)) + // (result anyref) + // local.get $suspender ;; for $builtin.forward-exn-to-suspended below + // block (result exnref) + // try_table (catch_all_ref 0) + // local.get $suspender ;; for call $add-promise-reactions + // (struct.get $param-type $i (local.get $param))* + // call $suspending.wrappedfn + // ref.func $suspending.continue-on-suspendable + // call $builtin.add-promise-reactions + // return + // end + // unreachable + // end + // call $builtin.forward-exn-to-suspended // ) // The function calls suspending import and returns into the // $promising.exported function because that was the top function // on the main stack. - bool encodeTrampolineFunction(ModuleEnvironment& moduleEnv, - uint32_t paramsSize, Bytes& bytecode) { - Encoder encoder(bytecode, *moduleEnv.types); + bool encodeTrampolineFunction(CodeMetadata& codeMeta, uint32_t paramsSize, + Bytes& bytecode) { + Encoder encoder(bytecode, *codeMeta.types); if (!EncodeLocalEntries(encoder, ValTypeVector())) { return false; } const uint32_t SuspenderIndex = 0; const uint32_t ParamsIndex = 1; - // For GetSuspendingResultsFnIndex call below. + if (!encoder.writeOp(Op::LocalGet) || + !encoder.writeVarU32(SuspenderIndex)) { + return false; + } + + if (!encoder.writeOp(Op::Block) || + !encoder.writeFixedU8(uint8_t(TypeCode::ExnRef))) { + return false; + } + + if (!encoder.writeOp(Op::TryTable) || + !encoder.writeFixedU8(uint8_t(TypeCode::BlockVoid)) || + !encoder.writeVarU32(1) || + !encoder.writeFixedU8(/* catch_all_ref = */ 0x03) || + !encoder.writeVarU32(0)) { + return false; + } + + // For AddPromiseReactions call below. if (!encoder.writeOp(Op::LocalGet) || !encoder.writeVarU32(SuspenderIndex)) { return false; @@ -738,13 +966,25 @@ class SuspendingFunctionModuleFactory { if (!encoder.writeOp(Op::Call) || !encoder.writeVarU32(WrappedFnIndex)) { return false; } - if (!encoder.writeOp(Op::RefFunc) || !encoder.writeVarU32(ContinueOnSuspendableFnIndex)) { return false; } - if (!encoder.writeOp(Op::Call) || - !encoder.writeVarU32(GetSuspendingResultsFnIndex)) { + + if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || + !encoder.writeVarU32( + (uint32_t)BuiltinModuleFuncId::AddPromiseReactions)) { + return false; + } + + if (!encoder.writeOp(Op::Return) || !encoder.writeOp(Op::End) || + !encoder.writeOp(Op::Unreachable) || !encoder.writeOp(Op::End)) { + return false; + } + + if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || + !encoder.writeVarU32( + (uint32_t)BuiltinModuleFuncId::ForwardExceptionToSuspended)) { return false; } @@ -753,22 +993,25 @@ class SuspendingFunctionModuleFactory { // Builds function that is called on main stack: // (func $suspending.continue-on-suspendable - // (param $params (ref $suspender)) + // (param $params (ref $suspender)) (param $results externref) // (result externref) // local.get $suspender // ref.null funcref - // ref.null anyref + // local.get $results + // any.convert_extern // stack-switch ContinueOnSuspendable // ) - bool encodeContinueOnSuspendableFunction(ModuleEnvironment& moduleEnv, + bool encodeContinueOnSuspendableFunction(CodeMetadata& codeMeta, uint32_t resultsSize, Bytes& bytecode) { - Encoder encoder(bytecode, *moduleEnv.types); + Encoder encoder(bytecode, *codeMeta.types); if (!EncodeLocalEntries(encoder, ValTypeVector())) { return false; } const uint32_t SuspenderIndex = 0; + const uint32_t ResultsIndex = 1; + if (!encoder.writeOp(Op::LocalGet) || !encoder.writeVarU32(SuspenderIndex)) { return false; @@ -777,8 +1020,8 @@ class SuspendingFunctionModuleFactory { !encoder.writeValType(ValType(RefType::func()))) { return false; } - if (!encoder.writeOp(Op::RefNull) || - !encoder.writeValType(ValType(RefType::any()))) { + if (!encoder.writeOp(Op::LocalGet) || !encoder.writeVarU32(ResultsIndex) || + !encoder.writeOp(GcOp::AnyConvertExtern)) { return false; } @@ -793,12 +1036,10 @@ class SuspendingFunctionModuleFactory { public: SharedModule build(JSContext* cx, HandleObject func, ValTypeVector&& params, - ValTypeVector&& results, - SuspenderArgPosition argPosition) { + ValTypeVector&& results) { FeatureOptions options; options.isBuiltinModule = true; - options.requireGC = true; - options.requireTailCalls = true; + options.requireExnref = true; ScriptedCaller scriptedCaller; SharedCompileArgs compileArgs = @@ -807,55 +1048,30 @@ class SuspendingFunctionModuleFactory { return nullptr; } - ModuleEnvironment moduleEnv(compileArgs->features); - MOZ_ASSERT(IonAvailable(cx)); + MutableModuleMetadata moduleMeta = js_new(); + if (!moduleMeta || !moduleMeta->init(*compileArgs)) { + return nullptr; + } + MutableCodeMetadata codeMeta = moduleMeta->codeMeta; + + MOZ_ASSERT(IonPlatformSupport()); CompilerEnvironment compilerEnv(CompileMode::Once, Tier::Optimized, DebugEnabled::False); compilerEnv.computeParameters(); - if (!moduleEnv.init()) { - return nullptr; - } - RefType suspenderType = RefType::extern_(); RefType promiseType = RefType::extern_(); - size_t paramsSize, paramsOffset, suspenderIndex; - size_t resultsSize = results.length(); - bool checkSuspender; ValTypeVector paramsWithoutSuspender; - switch (argPosition) { - case SuspenderArgPosition::First: - paramsSize = params.length() - 1; - paramsOffset = 1; - suspenderIndex = 0; - if (!paramsWithoutSuspender.append(params.begin() + 1, params.end())) { - ReportOutOfMemory(cx); - return nullptr; - } - checkSuspender = true; - break; - case SuspenderArgPosition::Last: - paramsSize = params.length() - 1; - paramsOffset = 0; - suspenderIndex = paramsSize - 1; - if (!paramsWithoutSuspender.append(params.begin(), params.end() - 1)) { - ReportOutOfMemory(cx); - return nullptr; - } - checkSuspender = true; - break; - default: - paramsSize = params.length(); - paramsOffset = 0; - suspenderIndex = paramsSize; - if (!paramsWithoutSuspender.append(params.begin(), params.end())) { - ReportOutOfMemory(cx); - return nullptr; - } - checkSuspender = false; - break; + + const size_t resultsSize = results.length(); + const size_t paramsSize = params.length(); + const size_t paramsOffset = 0; + if (!paramsWithoutSuspender.append(params.begin(), params.end())) { + ReportOutOfMemory(cx); + return nullptr; } + ValTypeVector resultsRef; if (!resultsRef.emplaceBack(promiseType)) { ReportOutOfMemory(cx); @@ -868,8 +1084,8 @@ class SuspendingFunctionModuleFactory { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.types->length() == ParamsTypeIndex); - if (!moduleEnv.types->addType(std::move(boxedParamsStruct))) { + MOZ_ASSERT(codeMeta->types->length() == ParamsTypeIndex); + if (!codeMeta->types->addType(std::move(boxedParamsStruct))) { return nullptr; } @@ -878,53 +1094,41 @@ class SuspendingFunctionModuleFactory { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.types->length() == ResultsTypeIndex); - if (!moduleEnv.types->addType(std::move(boxedResultType))) { + MOZ_ASSERT(codeMeta->types->length() == ResultsTypeIndex); + if (!codeMeta->types->addType(std::move(boxedResultType))) { return nullptr; } - MOZ_ASSERT(moduleEnv.funcs.length() == WrappedFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsWithoutSuspender), - std::move(resultsRef))) { - return nullptr; - } - - ValTypeVector paramsGetSuspendingResults, resultsGetSuspendingResults; - if (!paramsGetSuspendingResults.emplaceBack(suspenderType) || - !paramsGetSuspendingResults.emplaceBack(promiseType) || - !paramsGetSuspendingResults.emplaceBack(RefType::func())) { - ReportOutOfMemory(cx); - return nullptr; - } - MOZ_ASSERT(moduleEnv.funcs.length() == GetSuspendingResultsFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsGetSuspendingResults), - std::move(resultsGetSuspendingResults))) { + MOZ_ASSERT(codeMeta->funcs.length() == WrappedFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(paramsWithoutSuspender), + std::move(resultsRef))) { return nullptr; } // Imports names are not important, declare functions above as imports. - moduleEnv.numFuncImports = moduleEnv.funcs.length(); + codeMeta->numFuncImports = codeMeta->funcs.length(); // We will be looking up and using the exports function by index so // the name doesn't matter. - MOZ_ASSERT(moduleEnv.funcs.length() == ExportedFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(params), std::move(results), - /*declareForRef = */ true, - mozilla::Some(CacheableName()))) { + MOZ_ASSERT(codeMeta->funcs.length() == ExportedFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(params), std::move(results), + /*declareForRef = */ true, + mozilla::Some(CacheableName()))) { return nullptr; } ValTypeVector paramsTrampoline, resultsTrampoline; if (!paramsTrampoline.emplaceBack(suspenderType) || !paramsTrampoline.emplaceBack(RefType::fromTypeDef( - &(*moduleEnv.types)[ParamsTypeIndex], false))) { + &(*codeMeta->types)[ParamsTypeIndex], false)) || + !resultsTrampoline.emplaceBack(RefType::any())) { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.funcs.length() == TrampolineFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsTrampoline), - std::move(resultsTrampoline), - /*declareForRef = */ true)) { + MOZ_ASSERT(codeMeta->funcs.length() == TrampolineFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(paramsTrampoline), + std::move(resultsTrampoline), + /*declareForRef = */ true)) { return nullptr; } @@ -934,69 +1138,80 @@ class SuspendingFunctionModuleFactory { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.funcs.length() == ContinueOnSuspendableFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsContinueOnSuspendable), - std::move(resultsContinueOnSuspendable), - /*declareForRef = */ true)) { + MOZ_ASSERT(codeMeta->funcs.length() == ContinueOnSuspendableFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(paramsContinueOnSuspendable), + std::move(resultsContinueOnSuspendable), + /*declareForRef = */ true)) { return nullptr; } - ModuleGenerator mg(*compileArgs, &moduleEnv, &compilerEnv, nullptr, nullptr, - nullptr); - if (!mg.init(nullptr)) { + if (!moduleMeta->prepareForCompile(compilerEnv.mode())) { + return nullptr; + } + + ModuleGenerator mg(*codeMeta, compilerEnv, compilerEnv.initialState(), + nullptr, nullptr, nullptr); + if (!mg.initializeCompleteTier()) { return nullptr; } // Build functions and keep bytecodes around until the end. + uint32_t funcBytecodeOffset = CallSite::FIRST_VALID_BYTECODE_OFFSET; Bytes bytecode; if (!encodeExportedFunction( - moduleEnv, paramsSize, resultsSize, paramsOffset, suspenderIndex, - checkSuspender, - RefType::fromTypeDef(&(*moduleEnv.types)[ResultsTypeIndex], false), + *codeMeta, paramsSize, resultsSize, paramsOffset, + RefType::fromTypeDef(&(*codeMeta->types)[ResultsTypeIndex], false), bytecode)) { ReportOutOfMemory(cx); return nullptr; } - if (!mg.compileFuncDef(ExportedFnIndex, 0, bytecode.begin(), + if (!mg.compileFuncDef(ExportedFnIndex, funcBytecodeOffset, + bytecode.begin(), bytecode.begin() + bytecode.length())) { return nullptr; } + funcBytecodeOffset += bytecode.length(); + Bytes bytecode2; - if (!encodeTrampolineFunction(moduleEnv, paramsSize, bytecode2)) { + if (!encodeTrampolineFunction(*codeMeta, paramsSize, bytecode2)) { ReportOutOfMemory(cx); return nullptr; } - if (!mg.compileFuncDef(TrampolineFnIndex, 0, bytecode2.begin(), + if (!mg.compileFuncDef(TrampolineFnIndex, funcBytecodeOffset, + bytecode2.begin(), bytecode2.begin() + bytecode2.length())) { return nullptr; } + funcBytecodeOffset += bytecode2.length(); + Bytes bytecode3; - if (!encodeContinueOnSuspendableFunction(moduleEnv, paramsSize, + if (!encodeContinueOnSuspendableFunction(*codeMeta, paramsSize, bytecode3)) { ReportOutOfMemory(cx); return nullptr; } - if (!mg.compileFuncDef(ContinueOnSuspendableFnIndex, 0, bytecode3.begin(), + if (!mg.compileFuncDef(ContinueOnSuspendableFnIndex, funcBytecodeOffset, + bytecode3.begin(), bytecode3.begin() + bytecode3.length())) { return nullptr; } + funcBytecodeOffset += bytecode3.length(); + if (!mg.finishFuncDefs()) { return nullptr; } - SharedBytes shareableBytes = js_new(); - if (!shareableBytes) { - ReportOutOfMemory(cx); - return nullptr; - } - return mg.finishModule(*shareableBytes); + return mg.finishModule(BytecodeBufferOrSource(), *moduleMeta, + /*maybeCompleteTier2Listener=*/nullptr); } }; // Reaction on resolved/rejected suspending promise. static bool WasmPISuspendTaskContinue(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); + // The arg[0] has result of resolved promise, or rejection reason. Rooted callee(cx, &args.callee().as()); RootedValue suspender(cx, callee->getExtendedSlot(SUSPENDER_SLOT)); + RootedValue suspendingPromise(cx, callee->getExtendedSlot(PROMISE_SLOT)); // Convert result of the promise into the parameters/arguments for the // $suspending.continue-on-suspendable. @@ -1004,16 +1219,9 @@ static bool WasmPISuspendTaskContinue(JSContext* cx, unsigned argc, Value* vp) { cx, &callee->getExtendedSlot(CONTINUE_ON_SUSPENDABLE_SLOT) .toObject() .as()); - RootedValueVector argv(cx); - if (!argv.emplaceBack(suspender)) { - ReportOutOfMemory(cx); - return false; - } - MOZ_ASSERT(args.length() > 0); - if (!argv.emplaceBack(args[0])) { - ReportOutOfMemory(cx); - return false; - } + JS::RootedValueArray<2> argv(cx); + argv[0].set(suspender); + argv[1].set(suspendingPromise); JS::Rooted rval(cx); if (Call(cx, UndefinedHandleValue, continueOnSuspendable, argv, &rval)) { @@ -1031,31 +1239,6 @@ static bool WasmPISuspendTaskContinue(JSContext* cx, unsigned argc, Value* vp) { return RejectPromiseWithPendingError(cx, promise); } -// Collects returned suspending promising, and registers callbacks to -// react on it using WasmPISuspendTaskContinue. -// Seen as $suspending.add-promise-reactions in wasm. -static bool WasmPIAddPromiseReactions(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - Rooted suspenderObject( - cx, &args[0].toObject().as()); - RootedValue rval(cx, args[1]); - RootedFunction fn(cx, &args[2].toObject().as()); - - MOZ_ASSERT(rval.toObject().is(), - "WasmPIWrapSuspendingImport always returning a promise"); - Rooted promise(cx, &rval.toObject().as()); - suspenderObject->setSuspendingPromise(promise); - - // Pass fn here - RootedFunction then_( - cx, NewNativeFunction(cx, WasmPISuspendTaskContinue, 1, nullptr, - gc::AllocKind::FUNCTION_EXTENDED, GenericObject)); - then_->initExtendedSlot(SUSPENDER_SLOT, ObjectValue(*suspenderObject)); - then_->initExtendedSlot(CONTINUE_ON_SUSPENDABLE_SLOT, ObjectValue(*fn)); - return AddPromiseReactions(cx, promise, then_, then_); -} - // Wraps original import to catch all exceptions and convert result to a // promise. // Seen as $suspending.wrappedfn in wasm. @@ -1063,59 +1246,30 @@ static bool WasmPIWrapSuspendingImport(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); Rooted callee(cx, &args.callee().as()); - RootedFunction originalImportFunc( - cx, - &callee->getExtendedSlot(WRAPPED_FN_SLOT).toObject().as()); + RootedValue originalImportFunc(cx, callee->getExtendedSlot(WRAPPED_FN_SLOT)); // Catching exceptions here. RootedValue rval(cx); if (Call(cx, UndefinedHandleValue, originalImportFunc, args, &rval)) { - // Convert the result to a resolved promise. - RootedObject promiseConstructor(cx, GetPromiseConstructor(cx)); - RootedObject promiseObj(cx, PromiseResolve(cx, promiseConstructor, rval)); - if (!promiseObj) { - return false; - } - args.rval().setObject(*promiseObj); + // Convert the result to a resolved promise later in AddPromiseReactions. + args.rval().set(rval); return true; } - if (cx->isThrowingOutOfMemory()) { - return false; - } - - // Convert failure to a rejected promise. - RootedObject promiseObject(cx, NewPromiseObject(cx, nullptr)); - if (!promiseObject) { - return false; - } - args.rval().setObject(*promiseObject); - - Rooted promise(cx, &promiseObject->as()); - return RejectPromiseWithPendingError(cx, promise); + // Deferring pending exception to the handler in the + // $suspending.trampoline. + return false; } JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func, ValTypeVector&& params, - ValTypeVector&& results, - SuspenderArgPosition argPosition) { + ValTypeVector&& results) { MOZ_ASSERT(IsCallable(ObjectValue(*func)) && !IsCrossCompartmentWrapper(func)); - if (argPosition != SuspenderArgPosition::None) { - if (params.length() < 1 || - params[argPosition == SuspenderArgPosition::Last ? params.length() - 1 - : 0] != - RefType::extern_()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_EXPECTED_SUSPENDER); - return nullptr; - } - } - SuspendingFunctionModuleFactory moduleFactory; - SharedModule module = moduleFactory.build(cx, func, std::move(params), - std::move(results), argPosition); + SharedModule module = + moduleFactory.build(cx, func, std::move(params), std::move(results)); if (!module) { return nullptr; } @@ -1136,18 +1290,6 @@ JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func, return nullptr; } - // Add $suspending.add-promise-reactions to imports. - RootedFunction addPromiseReactions( - cx, NewNativeFunction(cx, WasmPIAddPromiseReactions, 3, nullptr, - gc::AllocKind::FUNCTION_EXTENDED, GenericObject)); - if (!addPromiseReactions) { - return nullptr; - } - if (!imports.get().funcs.append(addPromiseReactions)) { - ReportOutOfMemory(cx); - return nullptr; - } - Rooted instance(cx); if (!module->instantiate(cx, imports.get(), nullptr, &instance)) { // Can also trap on invalid input function. @@ -1173,18 +1315,17 @@ JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func, return nullptr; } return WasmSuspendingFunctionCreate(cx, func, std::move(params), - std::move(results), - SuspenderArgPosition::None); + std::move(results)); } // Promising // Builds a wasm module with following structure: // (module -// (type $params (struct (field ..)*))) -// (type $results (struct (field ..)*))) +// (type $params (struct (field ..)*)) +// (type $results (struct (field ..)*)) +// (type $create-suspender-result (struct (field externref externref))) // (import "" "" (func $promising.wrappedfn ..)) -// (import "" "" (func $promising.create-suspender ..)) // (func $promising.exported .. ) // (func $promising.trampoline ..) // (export "" (func $promising.exported)) @@ -1202,7 +1343,6 @@ class PromisingFunctionModuleFactory { enum FnIdx { WrappedFnIndex, - CreateSuspenderFnIndex, ExportedFnIndex, TrampolineFnIndex, }; @@ -1211,18 +1351,19 @@ class PromisingFunctionModuleFactory { // Builds function that will be exported for JS: // (func $promising.exported // (param ..)* (result externref) - // (local $promise externref) - // call $promising.create-suspender ;; -> (suspender,promise) - // local.set $promise + // (local $suspender externref) + // call $builtin.create-suspender + // local.tee $suspender + // call $builtin.create-promising-promise ;; -> (promise) + // local.get $suspender // ref.func $promising.trampoline // local.get $i* // stuct.new $param-type // stack-switch SwitchToSuspendable ;; <- (suspender,fn,data) - // local.get $promise // ) - bool encodeExportedFunction(ModuleEnvironment& moduleEnv, uint32_t paramsSize, + bool encodeExportedFunction(CodeMetadata& codeMeta, uint32_t paramsSize, Bytes& bytecode) { - Encoder encoder(bytecode, *moduleEnv.types); + Encoder encoder(bytecode, *codeMeta.types); ValTypeVector locals; if (!locals.emplaceBack(RefType::extern_())) { return false; @@ -1231,15 +1372,29 @@ class PromisingFunctionModuleFactory { return false; } - const uint32_t PromiseIndex = paramsSize; - if (!encoder.writeOp(Op::Call) || - !encoder.writeVarU32(CreateSuspenderFnIndex)) { + const uint32_t SuspenderIndex = paramsSize; + if (!encoder.writeOp(Op::I32Const) || !encoder.writeVarU32(0)) { return false; } - if (!encoder.writeOp(Op::LocalSet) || !encoder.writeVarU32(PromiseIndex)) { + if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || + !encoder.writeVarU32((uint32_t)BuiltinModuleFuncId::CreateSuspender)) { return false; } + if (!encoder.writeOp(Op::LocalTee) || + !encoder.writeVarU32(SuspenderIndex)) { + return false; + } + if (!encoder.writeOp(MozOp::CallBuiltinModuleFunc) || + !encoder.writeVarU32( + (uint32_t)BuiltinModuleFuncId::CreatePromisingPromise)) { + return false; + } + + if (!encoder.writeOp(Op::LocalGet) || + !encoder.writeVarU32(SuspenderIndex)) { + return false; + } if (!encoder.writeOp(Op::RefFunc) || !encoder.writeVarU32(TrampolineFnIndex)) { return false; @@ -1258,9 +1413,6 @@ class PromisingFunctionModuleFactory { return false; } - if (!encoder.writeOp(Op::LocalGet) || !encoder.writeVarU32(PromiseIndex)) { - return false; - } return encoder.writeOp(Op::End); } @@ -1276,11 +1428,9 @@ class PromisingFunctionModuleFactory { // struct.new $result-type // call $builtin.set-promising-promise-results // ) - bool encodeTrampolineFunction(ModuleEnvironment& moduleEnv, - uint32_t paramsSize, - SuspenderArgPosition argPosition, + bool encodeTrampolineFunction(CodeMetadata& codeMeta, uint32_t paramsSize, Bytes& bytecode) { - Encoder encoder(bytecode, *moduleEnv.types); + Encoder encoder(bytecode, *codeMeta.types); if (!EncodeLocalEntries(encoder, ValTypeVector())) { return false; } @@ -1293,12 +1443,6 @@ class PromisingFunctionModuleFactory { return false; } - if (argPosition == SuspenderArgPosition::First) { - if (!encoder.writeOp(Op::LocalGet) || - !encoder.writeVarU32(SuspenderIndex)) { - return false; - } - } for (uint32_t i = 0; i < paramsSize; i++) { if (!encoder.writeOp(Op::LocalGet) || !encoder.writeVarU32(ParamsIndex)) { return false; @@ -1308,12 +1452,6 @@ class PromisingFunctionModuleFactory { return false; } } - if (argPosition == SuspenderArgPosition::Last) { - if (!encoder.writeOp(Op::LocalGet) || - !encoder.writeVarU32(SuspenderIndex)) { - return false; - } - } if (!encoder.writeOp(Op::Call) || !encoder.writeVarU32(WrappedFnIndex)) { return false; } @@ -1333,18 +1471,14 @@ class PromisingFunctionModuleFactory { public: SharedModule build(JSContext* cx, HandleFunction fn, ValTypeVector&& params, - ValTypeVector&& results, - SuspenderArgPosition argPosition) { + ValTypeVector&& results) { const FuncType& fnType = fn->wasmTypeDef()->funcType(); size_t paramsSize = params.length(); RefType suspenderType = RefType::extern_(); - RefType promiseType = RefType::extern_(); FeatureOptions options; options.isBuiltinModule = true; - options.requireGC = true; - options.requireTailCalls = true; ScriptedCaller scriptedCaller; SharedCompileArgs compileArgs = @@ -1353,23 +1487,24 @@ class PromisingFunctionModuleFactory { return nullptr; } - ModuleEnvironment moduleEnv(compileArgs->features); - MOZ_ASSERT(IonAvailable(cx)); + MutableModuleMetadata moduleMeta = js_new(); + if (!moduleMeta || !moduleMeta->init(*compileArgs)) { + return nullptr; + } + MutableCodeMetadata codeMeta = moduleMeta->codeMeta; + + MOZ_ASSERT(IonPlatformSupport()); CompilerEnvironment compilerEnv(CompileMode::Once, Tier::Optimized, DebugEnabled::False); compilerEnv.computeParameters(); - if (!moduleEnv.init()) { - return nullptr; - } - StructType boxedParamsStruct; if (!StructType::createImmutable(params, &boxedParamsStruct)) { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.types->length() == ParamsTypeIndex); - if (!moduleEnv.types->addType(std::move(boxedParamsStruct))) { + MOZ_ASSERT(codeMeta->types->length() == ParamsTypeIndex); + if (!codeMeta->types->addType(std::move(boxedParamsStruct))) { return nullptr; } @@ -1378,8 +1513,8 @@ class PromisingFunctionModuleFactory { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.types->length() == ResultsTypeIndex); - if (!moduleEnv.types->addType(std::move(boxedResultType))) { + MOZ_ASSERT(codeMeta->types->length() == ResultsTypeIndex); + if (!codeMeta->types->addType(std::move(boxedResultType))) { return nullptr; } @@ -1390,112 +1525,82 @@ class PromisingFunctionModuleFactory { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.funcs.length() == WrappedFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsForWrapper), - std::move(resultsForWrapper))) { - return nullptr; - } - - ValTypeVector paramsCreateSuspender, resultsCreateSuspender; - if (!resultsCreateSuspender.emplaceBack(suspenderType) || - !resultsCreateSuspender.emplaceBack(promiseType)) { - ReportOutOfMemory(cx); - return nullptr; - } - MOZ_ASSERT(moduleEnv.funcs.length() == CreateSuspenderFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsCreateSuspender), - std::move(resultsCreateSuspender))) { + MOZ_ASSERT(codeMeta->funcs.length() == WrappedFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(paramsForWrapper), + std::move(resultsForWrapper))) { return nullptr; } // Imports names are not important, declare functions above as imports. - moduleEnv.numFuncImports = moduleEnv.funcs.length(); + codeMeta->numFuncImports = codeMeta->funcs.length(); // We will be looking up and using the exports function by index so // the name doesn't matter. - MOZ_ASSERT(moduleEnv.funcs.length() == ExportedFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(params), std::move(results), - /* declareFoRef = */ true, - mozilla::Some(CacheableName()))) { + MOZ_ASSERT(codeMeta->funcs.length() == ExportedFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(params), std::move(results), + /* declareFoRef = */ true, + mozilla::Some(CacheableName()))) { return nullptr; } ValTypeVector paramsTrampoline, resultsTrampoline; if (!paramsTrampoline.emplaceBack(suspenderType) || !paramsTrampoline.emplaceBack(RefType::fromTypeDef( - &(*moduleEnv.types)[ParamsTypeIndex], false))) { + &(*codeMeta->types)[ParamsTypeIndex], false))) { ReportOutOfMemory(cx); return nullptr; } - MOZ_ASSERT(moduleEnv.funcs.length() == TrampolineFnIndex); - if (!moduleEnv.addDefinedFunc(std::move(paramsTrampoline), - std::move(resultsTrampoline), - /* declareFoRef = */ true)) { + MOZ_ASSERT(codeMeta->funcs.length() == TrampolineFnIndex); + if (!moduleMeta->addDefinedFunc(std::move(paramsTrampoline), + std::move(resultsTrampoline), + /* declareFoRef = */ true)) { return nullptr; } - ModuleGenerator mg(*compileArgs, &moduleEnv, &compilerEnv, nullptr, nullptr, - nullptr); - if (!mg.init(nullptr)) { + if (!moduleMeta->prepareForCompile(compilerEnv.mode())) { + return nullptr; + } + + ModuleGenerator mg(*codeMeta, compilerEnv, compilerEnv.initialState(), + nullptr, nullptr, nullptr); + if (!mg.initializeCompleteTier()) { return nullptr; } // Build functions and keep bytecodes around until the end. Bytes bytecode; - if (!encodeExportedFunction(moduleEnv, paramsSize, bytecode)) { + uint32_t funcBytecodeOffset = CallSite::FIRST_VALID_BYTECODE_OFFSET; + if (!encodeExportedFunction(*codeMeta, paramsSize, bytecode)) { ReportOutOfMemory(cx); return nullptr; } - if (!mg.compileFuncDef(ExportedFnIndex, 0, bytecode.begin(), + if (!mg.compileFuncDef(ExportedFnIndex, funcBytecodeOffset, + bytecode.begin(), bytecode.begin() + bytecode.length())) { return nullptr; } + funcBytecodeOffset += bytecode.length(); + Bytes bytecode2; - if (!encodeTrampolineFunction(moduleEnv, paramsSize, argPosition, - bytecode2)) { + if (!encodeTrampolineFunction(*codeMeta, paramsSize, bytecode2)) { ReportOutOfMemory(cx); return nullptr; } - if (!mg.compileFuncDef(TrampolineFnIndex, 0, bytecode2.begin(), + if (!mg.compileFuncDef(TrampolineFnIndex, funcBytecodeOffset, + bytecode2.begin(), bytecode2.begin() + bytecode2.length())) { return nullptr; } + funcBytecodeOffset += bytecode2.length(); + if (!mg.finishFuncDefs()) { return nullptr; } - SharedBytes shareableBytes = js_new(); - if (!shareableBytes) { - ReportOutOfMemory(cx); - return nullptr; - } - return mg.finishModule(*shareableBytes); + return mg.finishModule(BytecodeBufferOrSource(), *moduleMeta, + /*maybeCompleteTier2Listener=*/nullptr); } }; -// Creates a suspender and promise (that will be returned to JS code). -// Seen as $promising.create-suspender to wasm. -static bool WasmPICreateSuspender(JSContext* cx, unsigned argc, Value* vp) { - Rooted suspenderObject(cx, SuspenderObject::create(cx)); - RootedObject promiseObject(cx, NewPromiseObject(cx, nullptr)); - if (!promiseObject) { - return false; - } - - Rooted promise(cx, &promiseObject->as()); - suspenderObject->setPromisingPromise(promise); - - CallArgs args = CallArgsFromVp(argc, vp); - Rooted results(cx, NewDenseEmptyArray(cx)); - if (!NewbornArrayPush(cx, results, ObjectValue(*suspenderObject))) { - return false; - } - if (!NewbornArrayPush(cx, results, ObjectValue(*promise))) { - return false; - } - args.rval().setObject(*results); - return true; -} - // Wraps call to wasm $promising.exported function to catch an exception and // return a promise instead. static bool WasmPIPromisingFunction(JSContext* cx, unsigned argc, Value* vp) { @@ -1529,63 +1634,26 @@ static bool WasmPIPromisingFunction(JSContext* cx, unsigned argc, Value* vp) { JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func, ValTypeVector&& params, - ValTypeVector&& results, - SuspenderArgPosition argPosition) { + ValTypeVector&& results) { RootedFunction wrappedWasmFunc(cx, &func->as()); MOZ_ASSERT(wrappedWasmFunc->isWasm()); const FuncType& wrappedWasmFuncType = wrappedWasmFunc->wasmTypeDef()->funcType(); - if (argPosition != SuspenderArgPosition::None) { - if (results.length() != 1 || results[0] != RefType::extern_()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_EXPECTED_PROMISE); - return nullptr; - } - - size_t paramsOffset, suspenderIndex; - switch (argPosition) { - case SuspenderArgPosition::First: - paramsOffset = 1; - suspenderIndex = 0; - break; - case SuspenderArgPosition::Last: - paramsOffset = 0; - suspenderIndex = params.length(); - break; - default: - MOZ_CRASH(); - } - - if (wrappedWasmFuncType.args().length() != params.length() + 1 || - wrappedWasmFuncType.args()[suspenderIndex] != RefType::extern_()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_EXPECTED_SUSPENDER); - return nullptr; - } - for (size_t i = 0; i < params.length(); i++) { - if (params[i] != wrappedWasmFuncType.args()[i + paramsOffset]) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_SIGNATURE_MISMATCH); - return nullptr; - } - } - } else { - MOZ_ASSERT(results.length() == 0 && params.length() == 0); - if (!results.append(RefType::extern_())) { - ReportOutOfMemory(cx); - return nullptr; - } - if (!params.append(wrappedWasmFuncType.args().begin(), - wrappedWasmFuncType.args().end())) { - ReportOutOfMemory(cx); - return nullptr; - } + MOZ_ASSERT(results.length() == 0 && params.length() == 0); + if (!results.append(RefType::extern_())) { + ReportOutOfMemory(cx); + return nullptr; + } + if (!params.append(wrappedWasmFuncType.args().begin(), + wrappedWasmFuncType.args().end())) { + ReportOutOfMemory(cx); + return nullptr; } PromisingFunctionModuleFactory moduleFactory; SharedModule module = moduleFactory.build( - cx, wrappedWasmFunc, std::move(params), std::move(results), argPosition); + cx, wrappedWasmFunc, std::move(params), std::move(results)); // Instantiate the module. Rooted imports(cx); @@ -1595,18 +1663,6 @@ JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func, return nullptr; } - // Add $promising.create-suspender to imports. - RootedFunction createSuspenderFunc( - cx, NewNativeFunction(cx, WasmPICreateSuspender, 0, nullptr, - gc::AllocKind::FUNCTION_EXTENDED, GenericObject)); - if (!createSuspenderFunc) { - return nullptr; - } - if (!imports.get().funcs.append(createSuspenderFunc)) { - ReportOutOfMemory(cx); - return nullptr; - } - Rooted instance(cx); if (!module->instantiate(cx, imports.get(), nullptr, &instance)) { MOZ_ASSERT(cx->isThrowingOutOfMemory()); @@ -1634,6 +1690,7 @@ JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func, // Gets active suspender. // The reserved parameter is a workaround for limitation in the // WasmBuiltinModule.yaml generator to always have params. +// Seen as $builtin.current-suspender to wasm. SuspenderObject* CurrentSuspender(Instance* instance, int32_t reserved) { MOZ_ASSERT(SASigCurrentSuspender.failureMode == FailureMode::FailOnNullPtr); JSContext* cx = instance->cx(); @@ -1646,45 +1703,73 @@ SuspenderObject* CurrentSuspender(Instance* instance, int32_t reserved) { return suspender; } -// Checks suspender value. -SuspenderObject* CheckSuspender(Instance* instance, JSObject* maybeSuspender) { - MOZ_ASSERT(SASigCheckSuspender.failureMode == FailureMode::FailOnNullPtr); +// Creates a suspender and promise (that will be returned to JS code). +// Seen as $builtin.create-suspender to wasm. +SuspenderObject* CreateSuspender(Instance* instance, int32_t reserved) { + MOZ_ASSERT(SASigCreateSuspender.failureMode == FailureMode::FailOnNullPtr); JSContext* cx = instance->cx(); - if (!maybeSuspender || !maybeSuspender->is() || - &maybeSuspender->as() != - cx->wasm().promiseIntegration.activeSuspender()) { - // Wrong suspender - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_INVALID_SUSPENDER); + return SuspenderObject::create(cx); +} + +// Creates a promise that will be returned at promising call. +// Seen as $builtin.create-promising-promise to wasm. +PromiseObject* CreatePromisingPromise(Instance* instance, + SuspenderObject* suspender) { + MOZ_ASSERT(SASigCreatePromisingPromise.failureMode == + FailureMode::FailOnNullPtr); + JSContext* cx = instance->cx(); + + Rooted suspenderObject(cx, suspender); + RootedObject promiseObject(cx, NewPromiseObject(cx, nullptr)); + if (!promiseObject) { return nullptr; } - SuspenderObject* suspenderObject = &maybeSuspender->as(); - if (suspenderObject->state() != SuspenderState::Active) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_JSPI_INVALID_STATE); - return nullptr; - } - return suspenderObject; + + Rooted promise(cx, &promiseObject->as()); + suspenderObject->setPromisingPromise(promise); + return promise.get(); } // Converts promise results into actual function result, or exception/trap // if rejected. -JSObject* GetSuspendingPromiseResult(Instance* instance, +// Seen as $builtin.get-suspending-promise-result to wasm. +JSObject* GetSuspendingPromiseResult(Instance* instance, void* result, SuspenderObject* suspender) { MOZ_ASSERT(SASigGetSuspendingPromiseResult.failureMode == FailureMode::FailOnNullPtr); JSContext* cx = instance->cx(); Rooted suspenderObject(cx, suspender); + RootedAnyRef resultRef(cx, AnyRef::fromCompiledCode(result)); - Rooted promise(cx, suspenderObject->suspendingPromise()); + SuspenderObject::ReturnType returnType = + suspenderObject->suspendingReturnType(); + MOZ_ASSERT(returnType != SuspenderObject::ReturnType::Unknown); + Rooted promise( + cx, returnType == SuspenderObject::ReturnType::Promise + ? &resultRef.toJSObject().as() + : nullptr); - if (promise->state() == JS::PromiseState::Rejected) { - RootedValue reason(cx, promise->reason()); - // Result is also the reason of promise rejection. +# ifdef DEBUG + auto resetReturnType = mozilla::MakeScopeExit([&suspenderObject]() { + suspenderObject->setSuspendingReturnType( + SuspenderObject::ReturnType::Unknown); + }); +# endif + + if (promise ? promise->state() == JS::PromiseState::Rejected + : returnType == SuspenderObject::ReturnType::Exception) { + // Promise was rejected or an exception was thrown, set pending exception + // and fail. + RootedValue reason( + cx, promise ? promise->reason() : resultRef.get().toJSValue()); cx->setPendingException(reason, ShouldCaptureStack::Maybe); return nullptr; } + // The exception and rejection are handled above -- expect resolved promise. + MOZ_ASSERT(promise->state() == JS::PromiseState::Fulfilled); + RootedValue jsValue(cx, promise->value()); + // Construct the results object. Rooted results( cx, instance->constantStructNewDefault( @@ -1692,16 +1777,10 @@ JSObject* GetSuspendingPromiseResult(Instance* instance, const FieldTypeVector& fields = results->typeDef().structType().fields_; if (fields.length() > 0) { - RootedValue jsValue(cx, promise->value()); - // The struct object is constructed based on returns of exported function. // It is the only way we can get ValType for Val::fromJSValue call. - auto bestTier = instance->code().bestTier(); - const wasm::FuncExport& funcExport = - instance->metadata(bestTier).lookupFuncExport( - SuspendingFunctionModuleFactory::ExportedFnIndex); - const wasm::FuncType& sig = - instance->metadata().getFuncExportType(funcExport); + const wasm::FuncType& sig = instance->codeMeta().getFuncType( + SuspendingFunctionModuleFactory::ExportedFnIndex); if (fields.length() == 1) { RootedVal val(cx); @@ -1744,7 +1823,59 @@ JSObject* GetSuspendingPromiseResult(Instance* instance, return results; } +// Collects returned suspending promising, and registers callbacks to +// react on it using WasmPISuspendTaskContinue. +// Seen as $builtin.add-promise-reactions to wasm. +void* AddPromiseReactions(Instance* instance, SuspenderObject* suspender, + void* result, JSFunction* continueOnSuspendable) { + MOZ_ASSERT(SASigAddPromiseReactions.failureMode == + FailureMode::FailOnInvalidRef); + JSContext* cx = instance->cx(); + + RootedAnyRef resultRef(cx, AnyRef::fromCompiledCode(result)); + RootedValue resultValue(cx, resultRef.get().toJSValue()); + Rooted suspenderObject(cx, suspender); + RootedFunction fn(cx, continueOnSuspendable); + + // Wrap a promise. + RootedObject promiseConstructor(cx, GetPromiseConstructor(cx)); + RootedObject promiseObj(cx, + PromiseResolve(cx, promiseConstructor, resultValue)); + if (!promiseObj) { + return AnyRef::invalid().forCompiledCode(); + } + Rooted promiseObject(cx, &promiseObj->as()); + + suspenderObject->setSuspendingReturnType( + SuspenderObject::ReturnType::Promise); + + // Add promise reactions + RootedFunction then_( + cx, NewNativeFunction(cx, WasmPISuspendTaskContinue, 1, nullptr, + gc::AllocKind::FUNCTION_EXTENDED, GenericObject)); + then_->initExtendedSlot(SUSPENDER_SLOT, ObjectValue(*suspenderObject)); + then_->initExtendedSlot(CONTINUE_ON_SUSPENDABLE_SLOT, ObjectValue(*fn)); + then_->initExtendedSlot(PROMISE_SLOT, ObjectValue(*promiseObject)); + if (!JS::AddPromiseReactions(cx, promiseObject, then_, then_)) { + return AnyRef::invalid().forCompiledCode(); + } + return AnyRef::fromJSObject(*promiseObject).forCompiledCode(); +} + +// Changes exit stack frame pointers to suspendable stack and recast exception +// to wasm reference. Seen as $builtin.forward-exn-to-suspended to wasm. +void* ForwardExceptionToSuspended(Instance* instance, + SuspenderObject* suspender, void* exception) { + MOZ_ASSERT(SASigForwardExceptionToSuspended.failureMode == + FailureMode::Infallible); + + suspender->forwardToSuspendable(); + suspender->setSuspendingReturnType(SuspenderObject::ReturnType::Exception); + return exception; +} + // Resolves the promise using results packed by wasm. +// Seen as $builtin.set-promising-promise-results to wasm. int32_t SetPromisingPromiseResults(Instance* instance, SuspenderObject* suspender, WasmStructObject* results) { diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmPI.h b/src/third_party/mozjs/extract/js/src/wasm/WasmPI.h index c07a4f15615..e3adc622c67 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmPI.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmPI.h @@ -22,6 +22,7 @@ #include "mozilla/DoublyLinkedList.h" // for DoublyLinkedListElement #include "js/TypeDecls.h" +#include "wasm/WasmAnyRef.h" #include "wasm/WasmTypeDef.h" // [SMDOC] JS Promise Integration @@ -103,20 +104,16 @@ namespace js { +class PromiseObject; class WasmStructObject; namespace wasm { +class SuspenderContext; class SuspenderObject; static const uint32_t SuspenderObjectDataSlot = 0; -enum SuspenderArgPosition { - None = -1, - First = 0, - Last = 1, -}; - enum SuspenderState { Initial, Moribund, @@ -146,9 +143,15 @@ class SuspenderObjectData // Stored return address for return to suspendable stack. void* suspendedReturnAddress_; + // Stored main stack exit/top frame pointer. + void* mainExitFP_; + SuspenderState state_; -#ifdef _WIN64 + // Identify context that is holding suspended stack, otherwise nullptr. + SuspenderContext* suspendedBy_; + +#if defined(_WIN32) // The storage of main stack limits during stack switching. // See updateTibFields and restoreTibFields below. void* savedStackBase_; @@ -161,9 +164,16 @@ class SuspenderObjectData inline SuspenderState state() const { return state_; } void setState(SuspenderState state) { state_ = state; } + inline bool traceable() const { return suspendedBy_ != nullptr; } + inline SuspenderContext* suspendedBy() const { return suspendedBy_; } + void setSuspendedBy(SuspenderContext* suspendedBy) { + suspendedBy_ = suspendedBy; + } + inline void* stackMemory() const { return stackMemory_; } inline void* mainFP() const { return mainFP_; } inline void* mainSP() const { return mainSP_; } + inline void* mainExitFP() const { return mainExitFP_; } inline void* suspendableFP() const { return suspendableFP_; } inline void* suspendableSP() const { return suspendableSP_; } inline void* suspendableExitFP() const { return suspendableExitFP_; } @@ -173,11 +183,16 @@ class SuspenderObjectData void releaseStackMemory(); -#ifdef _WIN64 +#if defined(_WIN32) void updateTIBStackFields(); void restoreTIBStackFields(); #endif +#if defined(JS_SIMULATOR_ARM64) || defined(JS_SIMULATOR_ARM) + void switchSimulatorToMain(); + void switchSimulatorToSuspendable(); +#endif + static constexpr size_t offsetOfMainFP() { return offsetof(SuspenderObjectData, mainFP_); } @@ -198,6 +213,10 @@ class SuspenderObjectData return offsetof(SuspenderObjectData, suspendableExitFP_); } + static constexpr size_t offsetOfMainExitFP() { + return offsetof(SuspenderObjectData, mainExitFP_); + } + static constexpr size_t offsetOfSuspendedReturnAddress() { return offsetof(SuspenderObjectData, suspendedReturnAddress_); } @@ -205,33 +224,36 @@ class SuspenderObjectData #ifdef ENABLE_WASM_JSPI -bool ParseSuspendingPromisingString(JSContext* cx, JS::HandleValue val, - SuspenderArgPosition& result); - -bool CallImportOnMainThread(JSContext* cx, Instance* instance, - int32_t funcImportIndex, int32_t argc, - uint64_t* argv); +using CallOnMainStackFn = bool (*)(void* data); +bool CallOnMainStack(JSContext* cx, CallOnMainStackFn fn, void* data); JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func, wasm::ValTypeVector&& params, - wasm::ValTypeVector&& results, - SuspenderArgPosition argPosition); + wasm::ValTypeVector&& results); JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func, const FuncType& type); JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func, wasm::ValTypeVector&& params, - wasm::ValTypeVector&& results, - SuspenderArgPosition argPosition); + wasm::ValTypeVector&& results); SuspenderObject* CurrentSuspender(Instance* instance, int reserved); -SuspenderObject* CheckSuspender(Instance* instance, JSObject* maybeSuspender); +SuspenderObject* CreateSuspender(Instance* instance, int reserved); -JSObject* GetSuspendingPromiseResult(Instance* instance, +PromiseObject* CreatePromisingPromise(Instance* instance, + SuspenderObject* suspender); + +JSObject* GetSuspendingPromiseResult(Instance* instance, void* result, SuspenderObject* suspender); +void* AddPromiseReactions(Instance* instance, SuspenderObject* suspender, + void* result, JSFunction* continueOnSuspendable); + +void* ForwardExceptionToSuspended(Instance* instance, + SuspenderObject* suspender, void* exception); + int32_t SetPromisingPromiseResults(Instance* instance, SuspenderObject* suspender, WasmStructObject* results); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.cpp index 4a6d9da5a7b..be24abb9af5 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.cpp @@ -19,8 +19,6 @@ #include "wasm/WasmProcess.h" #include "mozilla/Attributes.h" -#include "mozilla/BinarySearch.h" -#include "mozilla/ScopeExit.h" #include "gc/Memory.h" #include "threading/ExclusiveData.h" @@ -36,284 +34,79 @@ using namespace js; using namespace wasm; -using mozilla::BinarySearchIf; +mozilla::Atomic wasm::CodeExists(false); -// Per-process map from values of program-counter (pc) to CodeSegments. +// Per-process map from values of program-counter (pc) to CodeBlocks. // -// Whenever a new CodeSegment is ready to use, it has to be registered so that -// we can have fast lookups from pc to CodeSegments in numerous places. Since +// Whenever a new CodeBlock is ready to use, it has to be registered so that +// we can have fast lookups from pc to CodeBlocks in numerous places. Since // wasm compilation may be tiered, and the second tier doesn't have access to // any JSContext/JS::Compartment/etc lying around, we have to use a process-wide // map instead. -using CodeSegmentVector = Vector; +// This field is only atomic to handle buggy scenarios where we crash during +// startup or shutdown and thus racily perform wasm::LookupCodeBlock() from +// the crashing thread. -Atomic wasm::CodeExists(false); - -// Because of profiling, the thread running wasm might need to know to which -// CodeSegment the current PC belongs, during a call to lookup(). A lookup -// is a read-only operation, and we don't want to take a lock then -// (otherwise, we could have a deadlock situation if an async lookup -// happened on a given thread that was holding mutatorsMutex_ while getting -// sampled). Since the writer could be modifying the data that is getting -// looked up, the writer functions use spin-locks to know if there are any -// observers (i.e. calls to lookup()) of the atomic data. - -static Atomic sNumActiveLookups(0); - -class ProcessCodeSegmentMap { - // Since writes (insertions or removals) can happen on any background - // thread at the same time, we need a lock here. - - Mutex mutatorsMutex_ MOZ_UNANNOTATED; - - CodeSegmentVector segments1_; - CodeSegmentVector segments2_; - - // Except during swapAndWait(), there are no lookup() observers of the - // vector pointed to by mutableCodeSegments_ - - CodeSegmentVector* mutableCodeSegments_; - Atomic readonlyCodeSegments_; - - struct CodeSegmentPC { - const void* pc; - explicit CodeSegmentPC(const void* pc) : pc(pc) {} - int operator()(const CodeSegment* cs) const { - if (cs->containsCodePC(pc)) { - return 0; - } - if (pc < cs->base()) { - return -1; - } - return 1; - } - }; - - void swapAndWait() { - // Both vectors are consistent for lookup at this point although their - // contents are different: there is no way for the looked up PC to be - // in the code segment that is getting registered, because the code - // segment is not even fully created yet. - - // If a lookup happens before this instruction, then the - // soon-to-become-former read-only pointer is used during the lookup, - // which is valid. - - mutableCodeSegments_ = const_cast( - readonlyCodeSegments_.exchange(mutableCodeSegments_)); - - // If a lookup happens after this instruction, then the updated vector - // is used, which is valid: - // - in case of insertion, it means the new vector contains more data, - // but it's fine since the code segment is getting registered and thus - // isn't even fully created yet, so the code can't be running. - // - in case of removal, it means the new vector contains one less - // entry, but it's fine since unregistering means the code segment - // isn't used by any live instance anymore, thus PC can't be in the - // to-be-removed code segment's range. - - // A lookup could have happened on any of the two vectors. Wait for - // observers to be done using any vector before mutating. - - while (sNumActiveLookups > 0) { - } - } - - public: - ProcessCodeSegmentMap() - : mutatorsMutex_(mutexid::WasmCodeSegmentMap), - mutableCodeSegments_(&segments1_), - readonlyCodeSegments_(&segments2_) {} - - ~ProcessCodeSegmentMap() { - MOZ_RELEASE_ASSERT(sNumActiveLookups == 0); - MOZ_ASSERT(segments1_.empty()); - MOZ_ASSERT(segments2_.empty()); - segments1_.clearAndFree(); - segments2_.clearAndFree(); - } - - bool insert(const CodeSegment* cs) { - LockGuard lock(mutatorsMutex_); - - size_t index; - MOZ_ALWAYS_FALSE(BinarySearchIf(*mutableCodeSegments_, 0, - mutableCodeSegments_->length(), - CodeSegmentPC(cs->base()), &index)); - - if (!mutableCodeSegments_->insert(mutableCodeSegments_->begin() + index, - cs)) { - return false; - } - - CodeExists = true; - - swapAndWait(); - -#ifdef DEBUG - size_t otherIndex; - MOZ_ALWAYS_FALSE(BinarySearchIf(*mutableCodeSegments_, 0, - mutableCodeSegments_->length(), - CodeSegmentPC(cs->base()), &otherIndex)); - MOZ_ASSERT(index == otherIndex); -#endif - - // Although we could simply revert the insertion in the read-only - // vector, it is simpler to just crash and given that each CodeSegment - // consumes multiple pages, it is unlikely this insert() would OOM in - // practice - AutoEnterOOMUnsafeRegion oom; - if (!mutableCodeSegments_->insert(mutableCodeSegments_->begin() + index, - cs)) { - oom.crash("when inserting a CodeSegment in the process-wide map"); - } +static mozilla::Atomic sThreadSafeCodeBlockMap( + nullptr); +bool wasm::RegisterCodeBlock(const CodeBlock* cs) { + if (cs->length() == 0) { return true; } - void remove(const CodeSegment* cs) { - LockGuard lock(mutatorsMutex_); - - size_t index; - MOZ_ALWAYS_TRUE(BinarySearchIf(*mutableCodeSegments_, 0, - mutableCodeSegments_->length(), - CodeSegmentPC(cs->base()), &index)); - - mutableCodeSegments_->erase(mutableCodeSegments_->begin() + index); - - if (!mutableCodeSegments_->length()) { - CodeExists = false; - } - - swapAndWait(); - -#ifdef DEBUG - size_t otherIndex; - MOZ_ALWAYS_TRUE(BinarySearchIf(*mutableCodeSegments_, 0, - mutableCodeSegments_->length(), - CodeSegmentPC(cs->base()), &otherIndex)); - MOZ_ASSERT(index == otherIndex); -#endif - - mutableCodeSegments_->erase(mutableCodeSegments_->begin() + index); - } - - const CodeSegment* lookup(const void* pc) { - const CodeSegmentVector* readonly = readonlyCodeSegments_; - - size_t index; - if (!BinarySearchIf(*readonly, 0, readonly->length(), CodeSegmentPC(pc), - &index)) { - return nullptr; - } - - // It is fine returning a raw CodeSegment*, because we assume we are - // looking up a live PC in code which is on the stack, keeping the - // CodeSegment alive. - - return (*readonly)[index]; - } -}; - -// This field is only atomic to handle buggy scenarios where we crash during -// startup or shutdown and thus racily perform wasm::LookupCodeSegment() from -// the crashing thread. - -static Atomic sProcessCodeSegmentMap(nullptr); - -bool wasm::RegisterCodeSegment(const CodeSegment* cs) { - MOZ_ASSERT(cs->codeTier().code().initialized()); - // This function cannot race with startup/shutdown. - ProcessCodeSegmentMap* map = sProcessCodeSegmentMap; + ThreadSafeCodeBlockMap* map = sThreadSafeCodeBlockMap; MOZ_RELEASE_ASSERT(map); - return map->insert(cs); + bool result = map->insert(cs); + if (result) { + CodeExists = true; + } + return result; } -void wasm::UnregisterCodeSegment(const CodeSegment* cs) { +void wasm::UnregisterCodeBlock(const CodeBlock* cs) { + if (cs->length() == 0) { + return; + } + // This function cannot race with startup/shutdown. - ProcessCodeSegmentMap* map = sProcessCodeSegmentMap; + ThreadSafeCodeBlockMap* map = sThreadSafeCodeBlockMap; MOZ_RELEASE_ASSERT(map); - map->remove(cs); + size_t newCount = map->remove(cs); + if (newCount == 0) { + CodeExists = false; + } } -const CodeSegment* wasm::LookupCodeSegment( +const CodeBlock* wasm::LookupCodeBlock( const void* pc, const CodeRange** codeRange /*= nullptr */) { - // Since wasm::LookupCodeSegment() can race with wasm::ShutDown(), we must - // additionally keep sNumActiveLookups above zero for the duration we're - // using the ProcessCodeSegmentMap. wasm::ShutDown() spin-waits on - // sNumActiveLookups getting to zero. - - auto decObserver = mozilla::MakeScopeExit([&] { - MOZ_ASSERT(sNumActiveLookups > 0); - sNumActiveLookups--; - }); - sNumActiveLookups++; - - ProcessCodeSegmentMap* map = sProcessCodeSegmentMap; + ThreadSafeCodeBlockMap* map = sThreadSafeCodeBlockMap; if (!map) { return nullptr; } - if (const CodeSegment* found = map->lookup(pc)) { - if (codeRange) { - *codeRange = found->isModule() ? found->asModule()->lookupRange(pc) - : found->asLazyStub()->lookupRange(pc); - } - return found; - } - - if (codeRange) { - *codeRange = nullptr; - } - - return nullptr; + return map->lookup(pc, codeRange); } const Code* wasm::LookupCode(const void* pc, const CodeRange** codeRange /* = nullptr */) { - const CodeSegment* found = LookupCodeSegment(pc, codeRange); + const CodeBlock* found = LookupCodeBlock(pc, codeRange); MOZ_ASSERT_IF(!found && codeRange, !*codeRange); - return found ? &found->code() : nullptr; + return found ? found->code : nullptr; } bool wasm::InCompiledCode(void* pc) { - if (LookupCodeSegment(pc)) { + if (LookupCodeBlock(pc)) { return true; } const CodeRange* codeRange; - uint8_t* codeBase; + const uint8_t* codeBase; return LookupBuiltinThunk(pc, &codeRange, &codeBase); } -/** - * ReadLockFlag maintains a flag that can be mutated multiple times before it - * is read, at which point it maintains the same value. - */ -class ReadLockFlag { - private: - bool enabled_; - bool read_; - - public: - ReadLockFlag() : enabled_(false), read_(false) {} - - bool get() { - read_ = true; - return enabled_; - } - - bool set(bool enabled) { - if (read_) { - return false; - } - enabled_ = enabled; - return true; - } -}; - #ifdef WASM_SUPPORTS_HUGE_MEMORY /* * Some 64 bit systems greatly limit the range of available virtual memory. We @@ -335,51 +128,22 @@ static const size_t MinVirtualMemoryLimitForHugeMemory = size_t(1) << MinAddressBitsForHugeMemory; #endif -ExclusiveData sHugeMemoryEnabled32( - mutexid::WasmHugeMemoryEnabled); -ExclusiveData sHugeMemoryEnabled64( - mutexid::WasmHugeMemoryEnabled); +static bool sHugeMemoryEnabled32 = false; -static MOZ_NEVER_INLINE bool IsHugeMemoryEnabledHelper32() { - auto state = sHugeMemoryEnabled32.lock(); - return state->get(); -} - -static MOZ_NEVER_INLINE bool IsHugeMemoryEnabledHelper64() { - auto state = sHugeMemoryEnabled64.lock(); - return state->get(); -} - -bool wasm::IsHugeMemoryEnabled(wasm::IndexType t) { - if (t == IndexType::I32) { - static bool enabled32 = IsHugeMemoryEnabledHelper32(); - return enabled32; +bool wasm::IsHugeMemoryEnabled(wasm::AddressType t) { + if (t == AddressType::I64) { + // No support for huge memory with 64-bit memories + return false; } - static bool enabled64 = IsHugeMemoryEnabledHelper64(); - return enabled64; -} - -bool wasm::DisableHugeMemory() { - bool ok = true; - { - auto state = sHugeMemoryEnabled64.lock(); - ok = ok && state->set(false); - } - { - auto state = sHugeMemoryEnabled32.lock(); - ok = ok && state->set(false); - } - return ok; + return sHugeMemoryEnabled32; } void ConfigureHugeMemory() { #ifdef WASM_SUPPORTS_HUGE_MEMORY - bool ok = true; + MOZ_ASSERT(!sHugeMemoryEnabled32); - { - // Currently no huge memory for IndexType::I64, so always set to false. - auto state = sHugeMemoryEnabled64.lock(); - ok = ok && state->set(false); + if (JS::Prefs::wasm_disable_huge_memory()) { + return; } if (gc::SystemAddressBits() < MinAddressBitsForHugeMemory) { @@ -391,12 +155,7 @@ void ConfigureHugeMemory() { return; } - { - auto state = sHugeMemoryEnabled32.lock(); - ok = ok && state->set(true); - } - - MOZ_RELEASE_ASSERT(ok); + sHugeMemoryEnabled32 = true; #endif } @@ -404,16 +163,7 @@ const TagType* wasm::sWrappedJSValueTagType = nullptr; static bool InitTagForJSValue() { MutableTagType type = js_new(); - if (!type) { - return false; - } - - ValTypeVector args; - if (!args.append(ValType(RefType::extern_()))) { - return false; - } - - if (!type->initialize(std::move(args))) { + if (!type || !type->initialize(StaticTypeDefs::jsTag)) { return false; } MOZ_ASSERT(WrappedJSValueTagType_ValueOffset == type->argOffsets()[0]); @@ -424,7 +174,7 @@ static bool InitTagForJSValue() { } bool wasm::Init() { - MOZ_RELEASE_ASSERT(!sProcessCodeSegmentMap); + MOZ_RELEASE_ASSERT(!sThreadSafeCodeBlockMap); // Assert invariants that should universally hold true, but cannot be checked // at compile time. @@ -436,7 +186,7 @@ bool wasm::Init() { ConfigureHugeMemory(); AutoEnterOOMUnsafeRegion oomUnsafe; - ProcessCodeSegmentMap* map = js_new(); + ThreadSafeCodeBlockMap* map = js_new(); if (!map) { oomUnsafe.crash("js::wasm::Init"); } @@ -450,7 +200,7 @@ bool wasm::Init() { oomUnsafe.crash("js::wasm::Init"); } - sProcessCodeSegmentMap = map; + sThreadSafeCodeBlockMap = map; if (!InitTagForJSValue()) { oomUnsafe.crash("js::wasm::Init"); @@ -476,12 +226,12 @@ void wasm::ShutDown() { sWrappedJSValueTagType = nullptr; } - // After signalling shutdown by clearing sProcessCodeSegmentMap, wait for - // concurrent wasm::LookupCodeSegment()s to finish. - ProcessCodeSegmentMap* map = sProcessCodeSegmentMap; + // After signalling shutdown by clearing sThreadSafeCodeBlockMap, wait for + // concurrent wasm::LookupCodeBlock()s to finish. + ThreadSafeCodeBlockMap* map = sThreadSafeCodeBlockMap; MOZ_RELEASE_ASSERT(map); - sProcessCodeSegmentMap = nullptr; - while (sNumActiveLookups > 0) { + sThreadSafeCodeBlockMap = nullptr; + while (map->numActiveLookups() > 0) { } ReleaseBuiltinThunks(); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.h b/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.h index e107e8917a2..e3c1a53c07a 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmProcess.h @@ -28,18 +28,18 @@ namespace wasm { class Code; class CodeRange; -class CodeSegment; +class CodeBlock; class TagType; extern const TagType* sWrappedJSValueTagType; static constexpr uint32_t WrappedJSValueTagType_ValueOffset = 0; -// These methods return the wasm::CodeSegment (resp. wasm::Code) containing +// These methods return the wasm::CodeBlock (resp. wasm::Code) containing // the given pc, if any exist in the process. These methods do not take a lock, // and thus are safe to use in a profiling context. -const CodeSegment* LookupCodeSegment(const void* pc, - const CodeRange** codeRange = nullptr); +const CodeBlock* LookupCodeBlock(const void* pc, + const CodeRange** codeRange = nullptr); const Code* LookupCode(const void* pc, const CodeRange** codeRange = nullptr); @@ -52,20 +52,18 @@ bool InCompiledCode(void* pc); extern mozilla::Atomic CodeExists; -// These methods allow to (un)register CodeSegments so they can be looked up +// These methods allow to (un)register CodeBlocks so they can be looked up // via pc in the methods described above. -bool RegisterCodeSegment(const CodeSegment* cs); +bool RegisterCodeBlock(const CodeBlock* cs); -void UnregisterCodeSegment(const CodeSegment* cs); +void UnregisterCodeBlock(const CodeBlock* cs); // Whether this process is configured to use huge memory or not. Note that this // is not precise enough to tell whether a particular memory uses huge memory, // there are additional conditions for that. -bool IsHugeMemoryEnabled(IndexType t); - -[[nodiscard]] bool DisableHugeMemory(); +bool IsHugeMemoryEnabled(AddressType t); // Called once before/after the last VM execution which could execute or compile // wasm. diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmRealm.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmRealm.cpp index 61d8b96a444..47043866364 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmRealm.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmRealm.cpp @@ -42,22 +42,7 @@ struct InstanceComparator { if (instance == &target) { return 0; } - - // Instances can share code, so the segments can be equal (though they - // can't partially overlap). If the codeBases are equal, we sort by - // Instance address. Thus a Code may map to many instances. - - // Compare by the first tier, always. - - Tier instanceTier = instance->code().stableTier(); - Tier targetTier = target.code().stableTier(); - - if (instance->codeBase(instanceTier) == target.codeBase(targetTier)) { - return instance < &target ? -1 : 1; - } - - return target.codeBase(targetTier) < instance->codeBase(instanceTier) ? -1 - : 1; + return instance < &target ? -1 : 1; } }; @@ -132,7 +117,7 @@ void wasm::Realm::ensureProfilingLabels(bool profilingEnabled) { } } -void wasm::Realm::addSizeOfExcludingThis(MallocSizeOf mallocSizeOf, +void wasm::Realm::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* realmTables) { *realmTables += instances_.sizeOfExcludingThis(mallocSizeOf); } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.cpp index 02204cfd4b9..dfc02c86376 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.cpp @@ -33,6 +33,7 @@ using namespace js; using namespace js::wasm; using mozilla::Err; +using mozilla::Maybe; using mozilla::Ok; namespace js { @@ -121,16 +122,26 @@ CoderResult Coder::readBytes(void* dest, size_t length) { return Ok(); } +CoderResult Coder::readBytesRef(size_t length, + const uint8_t** bytesBegin) { + MOZ_RELEASE_ASSERT(buffer_ + length <= end_); + *bytesBegin = buffer_; + buffer_ += length; + return Ok(); +} + // Cacheable POD coding functions -template , bool> = true> -CoderResult CodePod(Coder& coder, T* item) { +template >, + typename = std::enable_if_t> +CoderResult CodePod(Coder& coder, T* item) { return coder.readBytes((void*)item, sizeof(T)); } template , bool> = true> + typename = std::enable_if_t>, + typename = std::enable_if_t> CoderResult CodePod(Coder& coder, const T* item) { STATIC_ASSERT_ENCODING_OR_SIZING; return coder.writeBytes((const void*)item, sizeof(T)); @@ -147,9 +158,9 @@ enum class Marker : uint32_t { CustomSections, Code, Metadata, - MetadataTier, - CodeTier, - ModuleSegment, + ModuleMetadata, + CodeMetadata, + CodeBlock }; template @@ -166,6 +177,43 @@ CoderResult Magic(Coder& coder, Marker item) { } } +// Coding function for a nullable pointer +// +// These functions will only code the inner value is not null. The +// coding function to use for the inner value is specified by a template +// parameter. + +template CodeT> +CoderResult CodeNullablePtr(Coder& coder, T* item) { + // Decode 'isNonNull' + uint8_t isNonNull; + MOZ_TRY(CodePod(coder, &isNonNull)); + + if (isNonNull == 1) { + // Code the inner type + MOZ_TRY(CodeT(coder, item)); + } else { + // Initialize to nullptr + *item = nullptr; + } + return Ok(); +} + +template CodeT> +CoderResult CodeNullablePtr(Coder& coder, const T* item) { + STATIC_ASSERT_ENCODING_OR_SIZING; + + // Encode or size 'isNonNull' + const uint8_t isNonNull = *item != nullptr; + MOZ_TRY(CodePod(coder, &isNonNull)); + + if (isNonNull) { + // Encode or size the inner value + MOZ_TRY(CodeT(coder, item)); + } + return Ok(); +} + // mozilla::Maybe coding functions // // These functions will only code the inner value if Maybe.isSome(). The @@ -211,9 +259,10 @@ CoderResult CodeMaybe(Coder& coder, const Maybe* item) { // this case, the whole contents of the vector are copied directly to/from the // buffer. -template , bool> = true> -CoderResult CodePodVector(Coder& coder, +template >, + typename = std::enable_if_t> +CoderResult CodePodVector(Coder& coder, Vector* item) { // Decode the length size_t length; @@ -230,7 +279,8 @@ CoderResult CodePodVector(Coder& coder, } template , bool> = true> + typename = std::enable_if_t>, + typename = std::enable_if_t> CoderResult CodePodVector(Coder& coder, const Vector* item) { STATIC_ASSERT_ENCODING_OR_SIZING; @@ -318,17 +368,35 @@ CoderResult CodeRefPtr(Coder& coder, CoderArg> item) { } } +// The same as CodeRefPtr, but allowing for nullable pointers. +template > CodeT> +CoderResult CodeNullableRefPtr(Coder& coder, + CoderArg> item) { + if constexpr (mode == MODE_DECODE) { + uint32_t isNull; + MOZ_TRY(CodePod(coder, &isNull)); + if (isNull == 0) { + MOZ_ASSERT(item->get() == nullptr); + return Ok(); + } + return CodeRefPtr(coder, item); + } else { + uint32_t isNull = !!item->get() ? 1 : 0; + MOZ_TRY(CodePod(coder, &isNull)); + if (isNull == 0) { + return Ok(); + } + return CodeRefPtr(coder, item); + } +} + // This function implements encoding and decoding of UniquePtr. // A coding function is provided for the inner value as a function parameter. -// The coding function may accept additional parameters to forward to the inner -// coding function. -// -// The inner coding function is provided as an argument instead of a template -// parameter in order to make the variable arguments template parameter -// simpler. -template -CoderResult CodeUniquePtr(Coder& coder, CoderArg> item, - CodeTFunctor innerCode, Args&&... args) { +template > CodeT> +CoderResult CodeUniquePtr(Coder& coder, + CoderArg> item) { if constexpr (mode == MODE_DECODE) { // The UniquePtr should not be initialized yet MOZ_ASSERT(!item->get()); @@ -340,25 +408,24 @@ CoderResult CodeUniquePtr(Coder& coder, CoderArg> item, } // Decode the inner type - MOZ_TRY(innerCode(coder, allocated.get(), std::forward(args)...)); + MOZ_TRY(CodeT(coder, allocated.get())); // Initialize the UniquePtr *item = std::move(allocated); return Ok(); } else { // Encode the inner type - return innerCode(coder, item->get(), std::forward(args)...); + return CodeT(coder, item->get()); } } -// CacheableChars coding functions +// UniqueChars coding functions static size_t StringLengthWithNullChar(const char* chars) { return chars ? strlen(chars) + 1 : 0; } -CoderResult CodeCacheableChars(Coder& coder, - CacheableChars* item) { +CoderResult CodeUniqueChars(Coder& coder, UniqueChars* item) { uint32_t lengthWithNullChar; MOZ_TRY(CodePod(coder, &lengthWithNullChar)); @@ -377,8 +444,8 @@ CoderResult CodeCacheableChars(Coder& coder, } template -CoderResult CodeCacheableChars(Coder& coder, const CacheableChars* item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CacheableChars, 8); +CoderResult CodeUniqueChars(Coder& coder, const UniqueChars* item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(UniqueChars, 8); STATIC_ASSERT_ENCODING_OR_SIZING; // Encode the length @@ -395,8 +462,24 @@ CoderResult CodeCacheableChars(Coder& coder, const CacheableChars* item) { return Ok(); } -// Code a CacheableName +// Code a CacheableChars. This just forwards to UniqueChars, as that's the +// only data in the class, via inheritance. +template +CoderResult CodeCacheableChars(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CacheableChars, 8); + return CodeUniqueChars(coder, (UniqueChars*)item); +} +// Code a ShareableChars. This functions only needs to forward to the inner +// unique chars. +template +CoderResult CodeShareableChars(Coder& coder, + CoderArg item) { + return CodeUniqueChars(coder, &item->chars); +} + +// Code a CacheableName template CoderResult CodeCacheableName(Coder& coder, CoderArg item) { @@ -405,13 +488,11 @@ CoderResult CodeCacheableName(Coder& coder, return Ok(); } -// Code a ShareableBytes. This function only needs to forward to the inner -// bytes vector. +// Code a ShareableBytes. template CoderResult CodeShareableBytes(Coder& coder, CoderArg item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ShareableBytes, 48); - return CodePodVector(coder, &item->bytes); + return CodePodVector(coder, &item->vector); } // WasmValType.h @@ -452,9 +533,8 @@ CoderResult CodePackedTypeCode(Coder& coder, } } -template -CoderResult CodeTypeDefRef(Coder& coder, - CoderArg item) { +template +CoderResult CodeTypeDefRef_Impl(Coder& coder, CoderArg item) { static constexpr uint32_t NullTypeIndex = UINT32_MAX; static_assert(NullTypeIndex > MaxTypes, "invariant"); @@ -473,6 +553,18 @@ CoderResult CodeTypeDefRef(Coder& coder, } } +template +CoderResult CodeTypeDefRef(Coder& coder, + CoderArg item) { + return CodeTypeDefRef_Impl(coder, item); +} + +template +CoderResult CodeTypeDefRef(Coder& coder, + CoderArg item) { + return CodeTypeDefRef_Impl(coder, item); +} + template CoderResult CodeValType(Coder& coder, CoderArg item) { return CodePackedTypeCode(coder, item->addressOfPacked()); @@ -540,7 +632,7 @@ CoderResult CodeFieldType(Coder& coder, CoderArg item) { template CoderResult CodeStructType(Coder& coder, CoderArg item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StructType, 184); + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StructType, 192); MOZ_TRY((CodeVector>(coder, &item->fields_))); if constexpr (mode == MODE_DECODE) { @@ -749,20 +841,16 @@ CoderResult CodeGlobalDesc(Coder& coder, template CoderResult CodeTagType(Coder& coder, CoderArg item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TagType, 232); + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TagType, 72); // We skip serializing/deserializing the size and argOffsets fields because // those are computed from the argTypes field when we deserialize. + MOZ_TRY(CodeTypeDefRef(coder, &item->type_)); if constexpr (mode == MODE_DECODE) { - ValTypeVector argTypes; - MOZ_TRY((CodeVector>( - coder, &argTypes))); - if (!item->initialize(std::move(argTypes))) { + if (!item->initialize(item->type_)) { return Err(OutOfMemory()); } - } else { - MOZ_TRY((CodeVector>(coder, - &item->argTypes()))); } + return Ok(); } @@ -813,15 +901,26 @@ CoderResult CodeCustomSection(Coder& coder, return Ok(); } +template +CoderResult CodeNameSection(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::NameSection, 56); + MOZ_TRY(CodePod(coder, &item->customSectionIndex)); + MOZ_TRY(CodePod(coder, &item->moduleName)); + MOZ_TRY(CodePodVector(coder, &item->funcNames)); + // We do not serialize `payload` because the ModuleMetadata will do that for + // us. + return Ok(); +} + template CoderResult CodeTableDesc(Coder& coder, CoderArg item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TableDesc, 112); + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TableDesc, 144); MOZ_TRY(CodeRefType(coder, &item->elemType)); MOZ_TRY(CodePod(coder, &item->isImported)); MOZ_TRY(CodePod(coder, &item->isExported)); MOZ_TRY(CodePod(coder, &item->isAsmJS)); - MOZ_TRY(CodePod(coder, &item->initialLength)); - MOZ_TRY(CodePod(coder, &item->maximumLength)); + MOZ_TRY(CodePod(coder, &item->limits)); MOZ_TRY( (CodeMaybe>(coder, &item->initExpr))); return Ok(); @@ -830,15 +929,93 @@ CoderResult CodeTableDesc(Coder& coder, CoderArg item) { // WasmCodegenTypes.h template -CoderResult CodeTrapSiteVectorArray(Coder& coder, - CoderArg item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TrapSiteVectorArray, 520); +CoderResult CodeTrapSitesForKind(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TrapSitesForKind, 160); +#ifdef DEBUG + MOZ_TRY(CodePodVector(coder, &item->machineInsns_)); +#endif + MOZ_TRY(CodePodVector(coder, &item->pcOffsets_)); + MOZ_TRY(CodePodVector(coder, &item->bytecodeOffsets_)); + // Inlining requires lazy tiering, which does not support serialization yet. + MOZ_RELEASE_ASSERT(item->inlinedCallerOffsetsMap_.empty()); + return Ok(); +} + +template +CoderResult CodeTrapSites(Coder& coder, CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TrapSites, 2080); for (Trap trap : mozilla::MakeEnumeratedRange(Trap::Limit)) { - MOZ_TRY(CodePodVector(coder, &(*item)[trap])); + MOZ_TRY(CodeTrapSitesForKind(coder, &item->array_[trap])); } return Ok(); } +template +CoderResult CodeCallSites(Coder& coder, CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CallSites, 160); + MOZ_TRY(CodePodVector(coder, &item->kinds_)); + MOZ_TRY(CodePodVector(coder, &item->lineOrBytecodes_)); + MOZ_TRY(CodePodVector(coder, &item->returnAddressOffsets_)); + // Inlining requires lazy tiering, which does not support serialization yet. + MOZ_RELEASE_ASSERT(item->inlinedCallerOffsetsMap_.empty()); + return Ok(); +} + +// WasmCompileArgs.h + +template +CoderResult CodeScriptedCaller(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ScriptedCaller, 16); + MOZ_TRY((CodeUniqueChars(coder, &item->filename))); + MOZ_TRY((CodePod(coder, &item->filenameIsURL))); + MOZ_TRY((CodePod(coder, &item->line))); + return Ok(); +} + +template +CoderResult CodeBuiltinModuleIds(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(BuiltinModuleIds, 16); + MOZ_TRY(CodePod(coder, &item->selfTest)); + MOZ_TRY(CodePod(coder, &item->intGemm)); + MOZ_TRY(CodePod(coder, &item->jsString)); + MOZ_TRY(CodePod(coder, &item->jsStringConstants)); + MOZ_TRY((CodeNullableRefPtr( + coder, &item->jsStringConstantsNamespace))); + return Ok(); +} + +template +CoderResult CodeFeatureArgs(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(FeatureArgs, 40); +#define WASM_FEATURE(NAME, LOWER_NAME, ...) \ + MOZ_TRY(CodePod(coder, &item->LOWER_NAME)); + JS_FOR_WASM_FEATURES(WASM_FEATURE) +#undef WASM_FEATURE + MOZ_TRY(CodePod(coder, &item->sharedMemory)); + MOZ_TRY(CodePod(coder, &item->simd)); + MOZ_TRY(CodePod(coder, &item->isBuiltinModule)); + MOZ_TRY(CodeBuiltinModuleIds(coder, &item->builtinModules)); + return Ok(); +} + +template +CoderResult CodeCompileArgs(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CompileArgs, 80); + MOZ_TRY((CodeScriptedCaller(coder, &item->scriptedCaller))); + MOZ_TRY((CodeUniqueChars(coder, &item->sourceMapURL))); + MOZ_TRY((CodePod(coder, &item->baselineEnabled))); + MOZ_TRY((CodePod(coder, &item->ionEnabled))); + MOZ_TRY((CodePod(coder, &item->debugEnabled))); + MOZ_TRY((CodePod(coder, &item->forceTiering))); + MOZ_TRY((CodeFeatureArgs(coder, &item->features))); + return Ok(); +} + // WasmGC.h CoderResult CodeStackMap(Coder& coder, @@ -876,25 +1053,15 @@ CoderResult CodeStackMap(Coder& coder, return Ok(); } -static uint32_t ComputeCodeOffset(const uint8_t* codeStart, - const uint8_t* codePtr) { - MOZ_RELEASE_ASSERT(codePtr >= codeStart); -#ifdef JS_64BIT - MOZ_RELEASE_ASSERT(codePtr < codeStart + UINT32_MAX); -#endif - return (uint32_t)(codePtr - codeStart); -} - CoderResult CodeStackMaps(Coder& coder, - CoderArg item, - const uint8_t* codeStart) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StackMaps, 48); + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StackMaps, 40); // Decode the amount of stack maps size_t length; MOZ_TRY(CodePod(coder, &length)); for (size_t i = 0; i < length; i++) { - // Decode the offset relative to codeStart + // Decode the offset uint32_t codeOffset; MOZ_TRY(CodePod(coder, &codeOffset)); @@ -903,37 +1070,32 @@ CoderResult CodeStackMaps(Coder& coder, MOZ_TRY(CodeStackMap(coder, &map)); // Add it to the map - const uint8_t* nextInsnAddr = codeStart + codeOffset; - if (!item->add(nextInsnAddr, map)) { + if (!item->add(codeOffset, map)) { return Err(OutOfMemory()); } } - // Finish the maps, asserting they are sorted - item->finishAlreadySorted(); return Ok(); } template CoderResult CodeStackMaps(Coder& coder, - CoderArg item, - const uint8_t* codeStart) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StackMaps, 48); + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StackMaps, 40); STATIC_ASSERT_ENCODING_OR_SIZING; // Encode the amount of stack maps size_t length = item->length(); MOZ_TRY(CodePod(coder, &length)); - for (size_t i = 0; i < length; i++) { - StackMaps::Maplet maplet = item->get(i); - uint32_t codeOffset = ComputeCodeOffset(codeStart, maplet.nextInsnAddr); + for (auto iter = item->mapping_.iter(); !iter.done(); iter.next()) { + uint32_t codeOffset = iter.get().key(); - // Encode the offset relative to codeStart + // Encode the offset MOZ_TRY(CodePod(coder, &codeOffset)); // Encode the stack map - MOZ_TRY(CodeStackMap(coder, maplet.map)); + MOZ_TRY(CodeStackMap(coder, iter.get().value())); } return Ok(); } @@ -957,210 +1119,402 @@ CoderResult CodeLinkData(Coder& coder, // SymbolicLinkArray depends on SymbolicAddress::Limit, which is changed // often. Exclude symbolicLinks field from trip wire value calculation. WASM_VERIFY_SERIALIZATION_FOR_SIZE( - wasm::LinkData, 48 + sizeof(wasm::LinkData::SymbolicLinkArray)); - if constexpr (mode == MODE_ENCODE) { - MOZ_ASSERT(item->tier == Tier::Serialized); - } + wasm::LinkData, 88 + sizeof(wasm::LinkData::SymbolicLinkArray)); MOZ_TRY(CodePod(coder, &item->pod())); MOZ_TRY(CodePodVector(coder, &item->internalLinks)); + MOZ_TRY(CodePodVector(coder, &item->callFarJumps)); MOZ_TRY(CodeSymbolicLinkArray(coder, &item->symbolicLinks)); return Ok(); } -CoderResult CodeModuleSegment(Coder& coder, - wasm::UniqueModuleSegment* item, - const wasm::LinkData& linkData) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ModuleSegment, 48); - // Assert we're decoding a ModuleSegment - MOZ_TRY(Magic(coder, Marker::ModuleSegment)); +// WasmMetadata.h - // Decode the code bytes length - size_t length; - MOZ_TRY(CodePod(coder, &length)); +template +CoderResult CodeCodeMetadata(Coder& coder, + CoderArg item) { + // NOTE: keep the field sequence here in sync with the sequence in the + // declaration of CodeMetadata. - // Allocate the code bytes - Maybe writable; - UniqueCodeBytes bytes = AllocateCodeBytes(writable, length); - if (!bytes) { - return Err(OutOfMemory()); + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CodeMetadata, 728); + // Serialization doesn't handle asm.js or debug enabled modules + MOZ_RELEASE_ASSERT(mode == MODE_SIZE || !item->isAsmJS()); + + MOZ_TRY(Magic(coder, Marker::CodeMetadata)); + + MOZ_TRY(CodePod(coder, &item->kind)); + MOZ_TRY((CodeRefPtr( + coder, &item->compileArgs))); + + MOZ_TRY(CodePod(coder, &item->numFuncImports)); + MOZ_TRY(CodePod(coder, &item->funcImportsAreJS)); + MOZ_TRY(CodePod(coder, &item->numGlobalImports)); + + // We must deserialize types first so that they're available for + // deserializing values that need types. + MOZ_TRY( + (CodeRefPtr(coder, &item->types))); + MOZ_TRY(CodePodVector(coder, &item->funcs)); + MOZ_TRY(( + CodeVector>(coder, &item->tables))); + MOZ_TRY(CodePodVector(coder, &item->memories)); + MOZ_TRY((CodeVector>(coder, &item->tags))); + MOZ_TRY((CodeVector>( + coder, &item->globals))); + + MOZ_TRY((CodeMaybe(coder, &item->startFuncIndex))); + + MOZ_TRY(( + CodeVector(coder, &item->elemSegmentTypes))); + + MOZ_TRY((CodeMaybe(coder, &item->dataCount))); + MOZ_TRY((CodePodVector(coder, &item->exportedFuncIndices))); + + // We do not serialize `asmJSSigToTableIndex` because we don't serialize + // asm.js. + + MOZ_TRY(CodePodVector(coder, &item->customSectionRanges)); + + MOZ_TRY((CodeMaybe(coder, + &item->codeSectionRange))); + + MOZ_TRY((CodeMaybe(coder, + &item->nameSection))); + + // TODO (bug 1907645): We do not serialize branch hints yet. + + MOZ_TRY(CodePod(coder, &item->funcDefsOffsetStart)); + MOZ_TRY(CodePod(coder, &item->funcImportsOffsetStart)); + MOZ_TRY(CodePod(coder, &item->funcExportsOffsetStart)); + MOZ_TRY(CodePod(coder, &item->typeDefsOffsetStart)); + MOZ_TRY(CodePod(coder, &item->memoriesOffsetStart)); + MOZ_TRY(CodePod(coder, &item->tablesOffsetStart)); + MOZ_TRY(CodePod(coder, &item->tagsOffsetStart)); + MOZ_TRY(CodePod(coder, &item->instanceDataLength)); + + if constexpr (mode == MODE_DECODE) { + MOZ_ASSERT(!item->isAsmJS()); } - // Decode the code bytes - MOZ_TRY(coder.readBytes(bytes.get(), length)); + return Ok(); +} - // Initialize the ModuleSegment - *item = js::MakeUnique(Tier::Serialized, std::move(bytes), - length, linkData); +template +CoderResult CodeCodeTailMetadata(Coder& coder, + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CodeTailMetadata, 384); + + if constexpr (mode == MODE_ENCODE) { + MOZ_ASSERT(!item->debugEnabled); + } + + MOZ_TRY((CodeNullablePtr< + mode, SharedBytes, + &CodeRefPtr>( + coder, &item->codeSectionBytecode))); + + if constexpr (mode == MODE_DECODE) { + int64_t inliningBudget; + MOZ_TRY(CodePod(coder, &inliningBudget)); + item->inliningBudget.lock().get() = inliningBudget; + } else { + int64_t inliningBudget = item->inliningBudget.lock().get(); + MOZ_TRY(CodePod(coder, &inliningBudget)); + } + + MOZ_TRY(CodePodVector(coder, &item->funcDefRanges)); + MOZ_TRY(CodePodVector(coder, &item->funcDefFeatureUsages)); + MOZ_TRY(CodePodVector(coder, &item->funcDefCallRefs)); + MOZ_TRY(CodePodVector(coder, &item->funcDefAllocSites)); + MOZ_TRY(CodePod(coder, &item->numCallRefMetrics)); + MOZ_TRY(CodePod(coder, &item->numAllocSites)); + + // Name section payload is handled by ModuleMetadata. + + if constexpr (mode == MODE_DECODE) { + // Initialize debugging state to disabled + item->debugEnabled = false; + } + + return Ok(); +} + +template +CoderResult CodeModuleMetadata(Coder& coder, + CoderArg item) { + // NOTE: keep the field sequence here in sync with the sequence in the + // declaration of ModuleMetadata. + + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ModuleMetadata, 272); + MOZ_TRY(Magic(coder, Marker::ModuleMetadata)); + + // The Visual Studio compiler struggles with the function pointers being + // passed as template parameters leading to C1001 Internal compiler errors. If + // these functions are instead passed as zero-capture lambdas (which are + // implicitly convertible to function pointers) the compiler handles it fine. + // However, clang and GCC does not think it is allowed to pass lambdas in this + // context which leads us to having two implementations for the different + // compilers. + #ifndef _MSC_VER + MOZ_TRY((CodeRefPtr(coder, + &item->codeMeta))); + MOZ_TRY((CodeRefPtr( + coder, &item->codeTailMeta))); + #else + MOZ_TRY((CodeRefPtr& coder, + CoderArg item) { + return CodeCodeMetadata(coder, std::move(item)); + }>(coder, &item->codeMeta))); + MOZ_TRY((CodeRefPtr& coder, + CoderArg item) { + return CodeCodeTailMetadata(coder, std::move(item)); + }>(coder, &item->codeTailMeta))); + #endif + if constexpr (mode == MODE_DECODE) { + item->codeTailMeta->codeMeta = item->codeMeta; + } + MOZ_TRY(Magic(coder, Marker::Imports)); + #ifndef _MSC_VER + MOZ_TRY((CodeVector>(coder, &item->imports))); + #else + MOZ_TRY((CodeVector& coder, CoderArg item) { + return CodeImport(coder, std::move(item)); + }>(coder, &item->imports))); + #endif + MOZ_TRY(Magic(coder, Marker::Exports)); + #ifndef _MSC_VER + MOZ_TRY((CodeVector>(coder, &item->exports))); + #else + MOZ_TRY((CodeVector& coder, CoderArg item) { + return CodeExport(coder, std::move(item)); + }>(coder, &item->exports))); + #endif + MOZ_TRY(Magic(coder, Marker::ElemSegments)); + #ifndef _MSC_VER + MOZ_TRY((CodeVector>( + coder, &item->elemSegments))); + #else + MOZ_TRY((CodeVector& coder, CoderArg item) { + return CodeModuleElemSegment(coder, std::move(item)); + }>(coder, &item->elemSegments))); + #endif + // not serialized: dataSegmentRanges + MOZ_TRY(Magic(coder, Marker::DataSegments)); + #ifndef _MSC_VER + MOZ_TRY( + (CodeVector>>( + coder, &item->dataSegments))); + #else + MOZ_TRY((CodeVector& coder, CoderArg item) { + return CodeRefPtr& coder, + CoderArg item) { + return CodeDataSegment( + coder, std::move(item)); + }>(coder, std::move(item)); + }>(coder, &item->dataSegments))); + #endif + MOZ_TRY(Magic(coder, Marker::CustomSections)); + #ifndef _MSC_VER + MOZ_TRY((CodeVector>( + coder, &item->customSections))); + #else + MOZ_TRY((CodeVector& coder, CoderArg item) { + return CodeCustomSection(coder, std::move(item)); + }>(coder, &item->customSections))); + #endif + MOZ_TRY(CodePod(coder, &item->featureUsage)); + + // Give CodeTailMetadata a pointer to our name payload now that we've + // deserialized it. + if constexpr (mode == MODE_DECODE) { + if (item->codeMeta->nameSection) { + item->codeTailMeta->nameSectionPayload = + item->customSections[item->codeMeta->nameSection->customSectionIndex] + .payload; + } + } + + return Ok(); +} + +// WasmCode.h + +template +CoderResult CodeFuncToCodeRangeMap( + Coder& coder, CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::FuncToCodeRangeMap, 80); + MOZ_TRY(CodePod(coder, &item->startFuncIndex_)); + MOZ_TRY(CodePodVector(coder, &item->funcToCodeRange_)); + return Ok(); +} + +CoderResult CodeCodeBlock(Coder& coder, + wasm::UniqueCodeBlock* item, + const wasm::LinkData& linkData) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CodeBlock, 2624); + *item = js::MakeUnique(CodeBlock::kindFromTier(Tier::Serialized)); if (!*item) { return Err(OutOfMemory()); } + MOZ_TRY(Magic(coder, Marker::CodeBlock)); + + // Decode the code byte range + size_t codeBytesLength; + const uint8_t* codeBytes; + MOZ_TRY(CodePod(coder, &codeBytesLength)); + MOZ_TRY(coder.readBytesRef(codeBytesLength, &codeBytes)); + + // Allocate a code segment using the code bytes + uint8_t* codeStart; + uint32_t allocationLength; + CodeSource codeSource(codeBytes, codeBytesLength, linkData, nullptr); + (*item)->segment = + CodeSegment::allocate(codeSource, nullptr, /* allowLastDitchGC */ true, + &codeStart, &allocationLength); + if (!(*item)->segment) { + return Err(OutOfMemory()); + } + (*item)->codeBase = codeStart; + (*item)->codeLength = codeSource.lengthBytes(); + + MOZ_TRY(CodeFuncToCodeRangeMap(coder, &(*item)->funcToCodeRange)); + MOZ_TRY(CodePodVector(coder, &(*item)->codeRanges)); + MOZ_TRY(CodeCallSites(coder, &(*item)->callSites)); + MOZ_TRY(CodeTrapSites(coder, &(*item)->trapSites)); + MOZ_TRY(CodePodVector(coder, &(*item)->funcExports)); + MOZ_TRY(CodeStackMaps(coder, &(*item)->stackMaps)); + MOZ_TRY(CodePodVector(coder, &(*item)->tryNotes)); + MOZ_TRY(CodePodVector(coder, &(*item)->codeRangeUnwindInfos)); return Ok(); } template -CoderResult CodeModuleSegment(Coder& coder, - CoderArg item, - const wasm::LinkData& linkData) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ModuleSegment, 48); +CoderResult CodeCodeBlock(Coder& coder, + CoderArg item, + const wasm::LinkData& linkData) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CodeBlock, 2624); STATIC_ASSERT_ENCODING_OR_SIZING; - MOZ_ASSERT((*item)->tier() == Tier::Serialized); - - // Mark that we're encoding a ModuleSegment - MOZ_TRY(Magic(coder, Marker::ModuleSegment)); - - // Encode the length - size_t length = (*item)->length(); - MOZ_TRY(CodePod(coder, &length)); + MOZ_TRY(Magic(coder, Marker::CodeBlock)); + // Encode the code bytes + MOZ_TRY(CodePod(coder, &item->codeLength)); if constexpr (mode == MODE_SIZE) { // Just calculate the length of bytes written - MOZ_TRY(coder.writeBytes((*item)->base(), length)); + MOZ_TRY(coder.writeBytes(item->codeBase, item->codeLength)); } else { // Get the start of where the code bytes will be written uint8_t* serializedBase = coder.buffer_; - // Write the code bytes - MOZ_TRY(coder.writeBytes((*item)->base(), length)); - + MOZ_TRY(coder.writeBytes(item->codeBase, item->codeLength)); // Unlink the code bytes written to the buffer StaticallyUnlink(serializedBase, linkData); } - return Ok(); -} -template -CoderResult CodeMetadataTier(Coder& coder, - CoderArg item, - const uint8_t* codeStart) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::MetadataTier, 896); - MOZ_TRY(Magic(coder, Marker::MetadataTier)); - MOZ_TRY(CodePodVector(coder, &item->funcToCodeRange)); + MOZ_TRY(CodeFuncToCodeRangeMap(coder, &item->funcToCodeRange)); MOZ_TRY(CodePodVector(coder, &item->codeRanges)); - MOZ_TRY(CodePodVector(coder, &item->callSites)); - MOZ_TRY(CodeTrapSiteVectorArray(coder, &item->trapSites)); - MOZ_TRY(CodePodVector(coder, &item->funcImports)); + MOZ_TRY(CodeCallSites(coder, &item->callSites)); + MOZ_TRY(CodeTrapSites(coder, &item->trapSites)); MOZ_TRY(CodePodVector(coder, &item->funcExports)); - MOZ_TRY(CodeStackMaps(coder, &item->stackMaps, codeStart)); + MOZ_TRY(CodeStackMaps(coder, &item->stackMaps)); MOZ_TRY(CodePodVector(coder, &item->tryNotes)); MOZ_TRY(CodePodVector(coder, &item->codeRangeUnwindInfos)); return Ok(); } -template -CoderResult CodeMetadata(Coder& coder, - CoderArg item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Metadata, 448); - if constexpr (mode == MODE_ENCODE) { - // Serialization doesn't handle asm.js or debug enabled modules - MOZ_ASSERT(!item->debugEnabled && item->debugFuncTypeIndices.empty()); - MOZ_ASSERT(!item->isAsmJS()); - } - - MOZ_TRY(Magic(coder, Marker::Metadata)); - MOZ_TRY(CodePod(coder, &item->pod())); - MOZ_TRY((CodeRefPtr( - coder, &item->types))); - MOZ_TRY(CodePodVector(coder, &item->memories)); - MOZ_TRY((CodeVector>( - coder, &item->globals))); - MOZ_TRY(( - CodeVector>(coder, &item->tables))); - MOZ_TRY((CodeVector>(coder, &item->tags))); - MOZ_TRY(CodePod(coder, &item->moduleName)); - MOZ_TRY(CodePodVector(coder, &item->funcNames)); - MOZ_TRY(CodeCacheableChars(coder, &item->filename)); - MOZ_TRY(CodeCacheableChars(coder, &item->sourceMapURL)); - - if constexpr (mode == MODE_DECODE) { - // Initialize debugging state to disabled - item->debugEnabled = false; - item->debugFuncTypeIndices.clear(); - } - - return Ok(); -} - -CoderResult CodeCodeTier(Coder& coder, wasm::UniqueCodeTier* item, - const wasm::LinkData& linkData) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CodeTier, 248); - UniqueMetadataTier metadata; - UniqueModuleSegment segment; - MOZ_TRY(Magic(coder, Marker::CodeTier)); - MOZ_TRY(CodeModuleSegment(coder, &segment, linkData)); - MOZ_TRY((CodeUniquePtr( - coder, &metadata, &CodeMetadataTier, segment->base()))); - *item = js::MakeUnique(std::move(metadata), std::move(segment)); - if (!*item) { - return Err(OutOfMemory()); - } - return Ok(); -} - -template -CoderResult CodeCodeTier(Coder& coder, - CoderArg item, - const wasm::LinkData& linkData) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::CodeTier, 248); - STATIC_ASSERT_ENCODING_OR_SIZING; - MOZ_TRY(Magic(coder, Marker::CodeTier)); - MOZ_TRY(CodeModuleSegment(coder, &item->segment_, linkData)); - MOZ_TRY((CodeUniquePtr(coder, &item->metadata_, - &CodeMetadataTier, - item->segment_->base()))); - return Ok(); -} - CoderResult CodeSharedCode(Coder& coder, wasm::SharedCode* item, - const wasm::LinkData& linkData, - const wasm::CustomSectionVector& customSections) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Code, 192); - MutableMetadata metadata; - UniqueCodeTier codeTier; - MOZ_TRY((CodeRefPtr(coder, &metadata))); - MOZ_TRY(CodeCodeTier(coder, &codeTier, linkData)); + const wasm::ModuleMetadata& moduleMeta) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Code, 976); - // Initialize metadata's name payload from the custom section - if (metadata->nameCustomSectionIndex) { - metadata->namePayload = - customSections[*metadata->nameCustomSectionIndex].payload; - } else { - MOZ_RELEASE_ASSERT(!metadata->moduleName); - MOZ_RELEASE_ASSERT(metadata->funcNames.empty()); - } + FuncImportVector funcImports; + MOZ_TRY(CodePodVector(coder, &funcImports)); - // Initialize the jump tables - JumpTables jumpTables; - if (!jumpTables.init(CompileMode::Once, codeTier->segment(), - codeTier->metadata().codeRanges)) { - return Err(OutOfMemory()); - } + UniqueCodeBlock sharedStubs; + UniqueLinkData sharedStubsLinkData; + MOZ_TRY((CodeUniquePtr( + coder, &sharedStubsLinkData))); + MOZ_TRY(CodeCodeBlock(coder, &sharedStubs, *sharedStubsLinkData)); + sharedStubs->sendToProfiler(*moduleMeta.codeMeta, *moduleMeta.codeTailMeta, + nullptr, FuncIonPerfSpewerSpan(), + FuncBaselinePerfSpewerSpan()); + + UniqueLinkData optimizedCodeLinkData; + UniqueCodeBlock optimizedCode; + MOZ_TRY((CodeUniquePtr( + coder, &optimizedCodeLinkData))); + MOZ_TRY(CodeCodeBlock(coder, &optimizedCode, *optimizedCodeLinkData)); + optimizedCode->sendToProfiler(*moduleMeta.codeMeta, *moduleMeta.codeTailMeta, + nullptr, FuncIonPerfSpewerSpan(), + FuncBaselinePerfSpewerSpan()); // Create and initialize the code - MutableCode code = - js_new(std::move(codeTier), *metadata, std::move(jumpTables)); - if (!code || !code->initialize(linkData)) { + MutableCode code = js_new(CompileMode::Once, *moduleMeta.codeMeta, + *moduleMeta.codeTailMeta, + /*codeMetaForAsmJS=*/nullptr); + if (!code || !code->initialize( + std::move(funcImports), std::move(sharedStubs), + std::move(sharedStubsLinkData), std::move(optimizedCode), + std::move(optimizedCodeLinkData), CompileAndLinkStats())) { return Err(OutOfMemory()); } + + // not serialized: debugStubOffset_ + + uint32_t offsetOfRequestTierUpStub = 0; + MOZ_TRY(CodePod(coder, &offsetOfRequestTierUpStub)); + code->setRequestTierUpStubOffset(offsetOfRequestTierUpStub); + + uint32_t offsetOfCallRefMetricsStub = 0; + MOZ_TRY(CodePod(coder, &offsetOfCallRefMetricsStub)); + code->setUpdateCallRefMetricsStubOffset(offsetOfCallRefMetricsStub); + *item = code; return Ok(); } template CoderResult CodeSharedCode(Coder& coder, - CoderArg item, - const wasm::LinkData& linkData) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Code, 192); + CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Code, 976); STATIC_ASSERT_ENCODING_OR_SIZING; - MOZ_TRY((CodeRefPtr( - coder, &(*item)->metadata_))); - MOZ_TRY(CodeCodeTier(coder, &(*item)->codeTier(Tier::Serialized), linkData)); + // Don't encode the CodeMetadata or CodeTailMetadata, that is handled by + // wasm::ModuleMetadata. + MOZ_TRY(CodePodVector(coder, &(*item)->funcImports())); + const CodeBlock& sharedStubsCodeBlock = (*item)->sharedStubs(); + const LinkData& sharedStubsLinkData = + *(*item)->codeBlockLinkData(sharedStubsCodeBlock); + MOZ_TRY(CodeLinkData(coder, &sharedStubsLinkData)); + MOZ_TRY(CodeCodeBlock(coder, &sharedStubsCodeBlock, sharedStubsLinkData)); + const CodeBlock& optimizedCodeBlock = + (*item)->completeTierCodeBlock(Tier::Serialized); + const LinkData& optimizedLinkData = + *(*item)->codeBlockLinkData(optimizedCodeBlock); + MOZ_TRY(CodeLinkData(coder, &optimizedLinkData)); + MOZ_TRY(CodeCodeBlock(coder, &optimizedCodeBlock, optimizedLinkData)); + + // not serialized: debugStubOffset_ + + uint32_t offsetOfRequestTierUpStub = (*item)->requestTierUpStubOffset(); + MOZ_TRY(CodePod(coder, &offsetOfRequestTierUpStub)); + + uint32_t offsetOfCallRefMetricsStub = + (*item)->updateCallRefMetricsStubOffset(); + MOZ_TRY(CodePod(coder, &offsetOfCallRefMetricsStub)); + return Ok(); } // WasmModule.h CoderResult CodeModule(Coder& coder, MutableModule* item) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Module, 256); + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Module, 56); JS::BuildIdCharVector currentBuildId; if (!GetOptimizedEncodingBuildId(¤tBuildId)) { return Err(OutOfMemory()); @@ -1170,58 +1524,25 @@ CoderResult CodeModule(Coder& coder, MutableModule* item) { MOZ_RELEASE_ASSERT(EqualContainers(currentBuildId, deserializedBuildId)); - CustomSectionVector customSections; - MOZ_TRY(Magic(coder, Marker::CustomSections)); - MOZ_TRY( - (CodeVector>( - coder, &customSections))); - - LinkData linkData(Tier::Serialized); - MOZ_TRY(Magic(coder, Marker::LinkData)); - MOZ_TRY(CodeLinkData(coder, &linkData)); + MutableModuleMetadata moduleMeta; + MOZ_TRY((CodeRefPtr( + coder, &moduleMeta))); SharedCode code; MOZ_TRY(Magic(coder, Marker::Code)); - MOZ_TRY(CodeSharedCode(coder, &code, linkData, customSections)); + MOZ_TRY(CodeSharedCode(coder, &code, *moduleMeta)); - ImportVector imports; - MOZ_TRY(Magic(coder, Marker::Imports)); - MOZ_TRY((CodeVector>( - coder, &imports))); - - ExportVector exports; - MOZ_TRY(Magic(coder, Marker::Exports)); - MOZ_TRY((CodeVector>( - coder, &exports))); - - DataSegmentVector dataSegments; - MOZ_TRY(Magic(coder, Marker::DataSegments)); - MOZ_TRY((CodeVector>>( - coder, &dataSegments))); - - // This must happen after deserializing code so we get type definitions. - ModuleElemSegmentVector elemSegments; - MOZ_TRY(Magic(coder, Marker::ElemSegments)); - MOZ_TRY( - (CodeVector>(coder, &elemSegments))); - - *item = js_new(*code, std::move(imports), std::move(exports), - std::move(dataSegments), std::move(elemSegments), - std::move(customSections), nullptr, + *item = js_new(*moduleMeta, *code, /* loggingDeserialized = */ true); return Ok(); } template -CoderResult CodeModule(Coder& coder, CoderArg item, - const wasm::LinkData& linkData) { - WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Module, 256); +CoderResult CodeModule(Coder& coder, CoderArg item) { + WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::Module, 56); STATIC_ASSERT_ENCODING_OR_SIZING; - MOZ_RELEASE_ASSERT(!item->metadata().debugEnabled); - MOZ_RELEASE_ASSERT(item->code_->hasTier(Tier::Serialized)); + MOZ_RELEASE_ASSERT(!item->code().debugEnabled()); + MOZ_RELEASE_ASSERT(item->code_->hasCompleteTier(Tier::Serialized)); JS::BuildIdCharVector currentBuildId; if (!GetOptimizedEncodingBuildId(¤tBuildId)) { @@ -1235,74 +1556,37 @@ CoderResult CodeModule(Coder& coder, CoderArg item, // context which leads us to having two implementations for the different // compilers. MOZ_TRY(CodePodVector(coder, ¤tBuildId)); - MOZ_TRY(Magic(coder, Marker::CustomSections)); #ifndef _MSC_VER - MOZ_TRY((CodeVector>( - coder, &item->customSections_))); + MOZ_TRY((CodeRefPtr( + coder, &item->moduleMeta_))); #else - MOZ_TRY( - (CodeVector& coder, CoderArg item) { - return CodeCustomSection(coder, std::move(item)); - }>(coder, &item->customSections_))); +MOZ_TRY( + (CodeRefPtr& coder, + CoderArg item) { + return CodeModuleMetadata(coder, std::move(item)); + }>(coder, &item->moduleMeta_))); #endif - MOZ_TRY(Magic(coder, Marker::LinkData)); - MOZ_TRY(CodeLinkData(coder, &linkData)); MOZ_TRY(Magic(coder, Marker::Code)); - MOZ_TRY(CodeSharedCode(coder, &item->code_, linkData)); - MOZ_TRY(Magic(coder, Marker::Imports)); -#ifndef _MSC_VER - MOZ_TRY( - (CodeVector>(coder, &item->imports_))); -#else - MOZ_TRY((CodeVector& coder, CoderArg item) { - return CodeImport(coder, std::move(item)); - }>(coder, &item->imports_))); -#endif - MOZ_TRY(Magic(coder, Marker::Exports)); -#ifndef _MSC_VER - MOZ_TRY( - (CodeVector>(coder, &item->exports_))); -#else - MOZ_TRY((CodeVector& coder, CoderArg item) { - return CodeExport(coder, std::move(item)); - }>(coder, &item->exports_))); -#endif - MOZ_TRY(Magic(coder, Marker::DataSegments)); -#ifndef _MSC_VER - MOZ_TRY( - (CodeVector>>( - coder, &item->dataSegments_))); -#else - MOZ_TRY((CodeVector& coder, - CoderArg> item) { - return CodeRefPtr& coder, - CoderArg item) { - return CodeDataSegment( - coder, std::move(item)); - }>(coder, std::move(item)); - }>(coder, &item->dataSegments_))); -#endif - MOZ_TRY(Magic(coder, Marker::ElemSegments)); -#ifndef _MSC_VER - MOZ_TRY((CodeVector>( - coder, &item->elemSegments_))); -#endif + MOZ_TRY(CodeSharedCode(coder, &item->code_)); return Ok(); } } // namespace wasm } // namespace js -static bool GetSerializedSize(const Module& module, const LinkData& linkData, - size_t* size) { - Coder coder(module.metadata().types.get()); - auto result = CodeModule(coder, &module, linkData); +bool Module::canSerialize() const { + // TODO(bug 1903131): JS string builtins don't support serialization + // TODO(bug 1913109): lazy tiering doesn't support serialization + return code_->mode() != CompileMode::LazyTiering && + !codeMeta().isBuiltinModule() && + codeMeta().features().builtinModules.hasNone() && + !code_->debugEnabled(); +} + +static bool GetSerializedSize(const Module& module, size_t* size) { + Coder coder(module.codeMeta().types.get()); + auto result = CodeModule(coder, &module); if (result.isErr()) { return false; } @@ -1310,12 +1594,12 @@ static bool GetSerializedSize(const Module& module, const LinkData& linkData, return true; } -bool Module::serialize(const LinkData& linkData, Bytes* bytes) const { - MOZ_RELEASE_ASSERT(!metadata().debugEnabled); - MOZ_RELEASE_ASSERT(code_->hasTier(Tier::Serialized)); +bool Module::serialize(Bytes* bytes) const { + MOZ_RELEASE_ASSERT(canSerialize()); + MOZ_RELEASE_ASSERT(code_->hasCompleteTier(Tier::Serialized)); size_t serializedSize; - if (!GetSerializedSize(*this, linkData, &serializedSize)) { + if (!GetSerializedSize(*this, &serializedSize)) { // An error is an overflow, return false return false; } @@ -1325,15 +1609,19 @@ bool Module::serialize(const LinkData& linkData, Bytes* bytes) const { return false; } - Coder coder(metadata().types.get(), bytes->begin(), + Coder coder(codeMeta().types.get(), bytes->begin(), serializedSize); - CoderResult result = CodeModule(coder, this, linkData); + CoderResult result = CodeModule(coder, this); if (result.isErr()) { // An error is an OOM, return false return false; } // Every byte is accounted for MOZ_RELEASE_ASSERT(coder.buffer_ == coder.end_); + + // Clear out link data now, it's no longer needed. + code().clearLinkData(); + return true; } @@ -1356,48 +1644,10 @@ void Module::initGCMallocBytesExcludingCode() { // calculate a value. We consume all errors, as they can only be overflow and // can be ignored until the end. constexpr CoderMode MODE = MODE_SIZE; - Coder coder(metadata().types.get()); - // The Visual Studio compiler struggles with the function pointers being - // passed as template parameters leading to C1001 Internal compiler errors. If - // these functions are instead passed as zero-capture lambdas (which are - // implicitly convertible to function pointers) the compiler handles it fine. - // However, clang and GCC does not think it is allowed to pass lambdas in this - // context which leads us to having two implementations for the different - // compilers. -#ifndef _MSC_VER - (void)CodeVector>(coder, &imports_); - (void)CodeVector>(coder, &exports_); - (void)CodeVector>>( - coder, &dataSegments_); - (void)CodeVector>( - coder, &elemSegments_); - (void)CodeVector>( - coder, &customSections_); -#else // _MSC_VER - (void)CodeVector& coder, CoderArg item) { - return CodeImport(coder, std::move(item)); - }>(coder, &imports_); - (void)CodeVector& coder, CoderArg item) { - return CodeExport(coder, std::move(item)); - }>(coder, &exports_); - (void)CodeVector& coder, - CoderArg> item) { - return CodeRefPtr& coder, - CoderArg item) { - return CodeDataSegment( - coder, std::move(item)); - }>(coder, std::move(item)); - }>(coder, &dataSegments_); - (void)CodeVector& coder, CoderArg item) { - return CodeCustomSection(coder, std::move(item)); - }>(coder, &customSections_); -#endif // _MSC_VER + Coder coder(codeMeta().types.get()); + + // Add the size of the ModuleMetadata + (void)CodeModuleMetadata(coder, moduleMeta_); // Overflow really shouldn't be possible here, but handle it anyways. size_t serializedSize = coder.size_.isValid() ? coder.size_.value() : 0; diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.h b/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.h index 89e11a43819..c7c9de4e0d0 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmSerialize.h @@ -180,6 +180,7 @@ struct Coder { const uint8_t* end_; CoderResult readBytes(void* dest, size_t length); + CoderResult readBytesRef(size_t length, const uint8_t** bytesBegin); }; // Macros to help types declare friendship with a coding function diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmShareable.h b/src/third_party/mozjs/extract/js/src/wasm/WasmShareable.h index a2df641c3fd..dc6d02e41d4 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmShareable.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmShareable.h @@ -26,8 +26,6 @@ namespace js { namespace wasm { -using mozilla::MallocSizeOf; - // This reusable base class factors out the logic for a resource that is shared // by multiple instances/modules but should only be counted once when computing // about:memory stats. @@ -39,7 +37,7 @@ template struct ShareableBase : AtomicRefCounted { using SeenSet = wasm::SeenSet; - size_t sizeOfIncludingThisIfNotSeen(MallocSizeOf mallocSizeOf, + size_t sizeOfIncludingThisIfNotSeen(mozilla::MallocSizeOf mallocSizeOf, SeenSet* seen) const { const T* self = static_cast(this); typename SeenSet::AddPtr p = seen->lookupForAdd(self); @@ -54,26 +52,64 @@ struct ShareableBase : AtomicRefCounted { // ShareableBytes is a reference-counted Vector of bytes. -struct ShareableBytes : ShareableBase { - // Vector is 'final', so instead make Vector a member and add boilerplate. - Bytes bytes; +// Vector is 'final' and cannot be inherited to combine with ShareableBase, so +// we need to define a wrapper class with boilerplate methods. +template +struct ShareableVector + : public ShareableBase> { + using VecT = mozilla::Vector; - ShareableBytes() = default; - explicit ShareableBytes(Bytes&& bytes) : bytes(std::move(bytes)) {} - size_t sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { - return bytes.sizeOfExcludingThis(mallocSizeOf); + VecT vector; + + size_t length() const { return vector.length(); } + bool empty() const { return vector.empty(); } + T* begin() { return vector.begin(); } + T* end() { return vector.end(); } + const T* begin() const { return vector.begin(); } + const T* end() const { return vector.end(); } + mozilla::Span span() const { + return mozilla::Span(begin(), end()); } - const uint8_t* begin() const { return bytes.begin(); } - const uint8_t* end() const { return bytes.end(); } - size_t length() const { return bytes.length(); } - bool append(const uint8_t* start, size_t len) { - return bytes.append(start, len); + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { + return vector.sizeOfExcludingThis(mallocSizeOf); + } + bool append(const T* start, size_t len) { return vector.append(start, len); } + bool appendAll(const VecT& other) { return vector.appendAll(other); } + void shrinkTo(size_t len) { return vector.shrinkTo(len); } + + ShareableVector() = default; + explicit ShareableVector(VecT&& vector) : vector(std::move(vector)) {} + + static const ShareableVector* fromSpan(mozilla::Span span) { + ShareableVector* vector = js_new(); + if (!vector) { + return nullptr; + } + + // If we succeed in allocating the vector but fail to append something to + // it, we need to delete this vector before returning. + if (!vector->append(span.data(), span.size())) { + js_free(vector); + return nullptr; + } + + return vector; } }; +using ShareableBytes = ShareableVector; using MutableBytes = RefPtr; using SharedBytes = RefPtr; +struct ShareableChars : public ShareableBase { + UniqueChars chars; + + ShareableChars() = default; + explicit ShareableChars(UniqueChars&& chars) : chars(std::move(chars)) {} +}; + +using SharedChars = RefPtr; + } // namespace wasm } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmSignalHandlers.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmSignalHandlers.cpp index f838b7bec0e..06954b3dd56 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmSignalHandlers.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmSignalHandlers.cpp @@ -18,7 +18,7 @@ #include "wasm/WasmSignalHandlers.h" -#include "mozilla/DebugOnly.h" +#include "mozilla/Casting.h" #include "mozilla/ThreadLocal.h" #include "threading/Thread.h" @@ -41,8 +41,6 @@ using namespace js; using namespace js::wasm; -using mozilla::DebugOnly; - #if !defined(JS_CODEGEN_NONE) // ============================================================================= @@ -425,7 +423,7 @@ struct macos_aarch64_context { static void SetContextPC(CONTEXT* context, uint8_t* pc) { # ifdef PC_sig - *reinterpret_cast(&PC_sig(context)) = pc; + *mozilla::BitwiseCast(&PC_sig(context)) = pc; # else MOZ_CRASH(); # endif @@ -433,7 +431,7 @@ static void SetContextPC(CONTEXT* context, uint8_t* pc) { static uint8_t* ContextToPC(CONTEXT* context) { # ifdef PC_sig - return reinterpret_cast(PC_sig(context)); + return mozilla::BitwiseCast(PC_sig(context)); # else MOZ_CRASH(); # endif @@ -441,7 +439,7 @@ static uint8_t* ContextToPC(CONTEXT* context) { static uint8_t* ContextToFP(CONTEXT* context) { # ifdef FP_sig - return reinterpret_cast(FP_sig(context)); + return mozilla::BitwiseCast(FP_sig(context)); # else MOZ_CRASH(); # endif @@ -449,7 +447,7 @@ static uint8_t* ContextToFP(CONTEXT* context) { static uint8_t* ContextToSP(CONTEXT* context) { # ifdef SP_sig - return reinterpret_cast(SP_sig(context)); + return mozilla::BitwiseCast(SP_sig(context)); # else MOZ_CRASH(); # endif @@ -459,7 +457,7 @@ static uint8_t* ContextToSP(CONTEXT* context) { defined(__loongarch__) || defined(__riscv) static uint8_t* ContextToLR(CONTEXT* context) { # ifdef LR_sig - return reinterpret_cast(LR_sig(context)); + return mozilla::BitwiseCast(LR_sig(context)); # else MOZ_CRASH(); # endif @@ -518,16 +516,14 @@ struct AutoHandlingTrap { MOZ_ASSERT(sAlreadyHandlingTrap.get()); uint8_t* pc = ContextToPC(context); - const CodeSegment* codeSegment = LookupCodeSegment(pc); - if (!codeSegment || !codeSegment->isModule()) { + const CodeBlock* codeBlock = LookupCodeBlock(pc); + if (!codeBlock) { return false; } - const ModuleSegment& segment = *codeSegment->asModule(); - Trap trap; - BytecodeOffset bytecode; - if (!segment.code().lookupTrap(pc, &trap, &bytecode)) { + TrapSite trapSite; + if (!codeBlock->lookupTrap(pc, &trap, &trapSite)) { return false; } @@ -539,7 +535,7 @@ struct AutoHandlingTrap { auto* frame = reinterpret_cast(ContextToFP(context)); Instance* instance = GetNearestEffectiveInstance(frame); - MOZ_RELEASE_ASSERT(&instance->code() == &segment.code() || + MOZ_RELEASE_ASSERT(&instance->code() == codeBlock->code || trap == Trap::IndirectCallBadSig); JSContext* cx = @@ -550,8 +546,8 @@ struct AutoHandlingTrap { // point of the trap to allow stack unwinding or resumption, both of which // will call finishWasmTrap(). jit::JitActivation* activation = cx->activation()->asJit(); - activation->startWasmTrap(trap, bytecode.offset(), ToRegisterState(context)); - SetContextPC(context, segment.trapCode()); + activation->startWasmTrap(trap, trapSite, ToRegisterState(context)); + SetContextPC(context, codeBlock->code->trapCode()); return true; } @@ -807,7 +803,7 @@ struct InstallState { InstallState() : tried(false), success(false) {} }; -static ExclusiveData sEagerInstallState( +MOZ_RUNINIT static ExclusiveData sEagerInstallState( mutexid::WasmSignalInstallState); #endif // !(JS_CODEGEN_NONE) @@ -889,7 +885,7 @@ void wasm::EnsureEagerProcessSignalHandlers() { } #ifndef JS_CODEGEN_NONE -static ExclusiveData sLazyInstallState( +MOZ_RUNINIT static ExclusiveData sLazyInstallState( mutexid::WasmSignalInstallState); static bool EnsureLazyProcessSignalHandlers() { @@ -983,16 +979,14 @@ bool wasm::MemoryAccessTraps(const RegisterState& regs, uint8_t* addr, #ifdef JS_CODEGEN_NONE return false; #else - const wasm::CodeSegment* codeSegment = wasm::LookupCodeSegment(regs.pc); - if (!codeSegment || !codeSegment->isModule()) { + const wasm::CodeBlock* codeBlock = wasm::LookupCodeBlock(regs.pc); + if (!codeBlock) { return false; } - const wasm::ModuleSegment& segment = *codeSegment->asModule(); - Trap trap; - BytecodeOffset bytecode; - if (!segment.code().lookupTrap(regs.pc, &trap, &bytecode)) { + TrapSite trapSite; + if (!codeBlock->code->lookupTrap(regs.pc, &trap, &trapSite)) { return false; } switch (trap) { @@ -1012,7 +1006,7 @@ bool wasm::MemoryAccessTraps(const RegisterState& regs, uint8_t* addr, const Instance& instance = *GetNearestEffectiveInstance(Frame::fromUntaggedWasmExitFP(regs.fp)); - MOZ_ASSERT(&instance.code() == &segment.code()); + MOZ_ASSERT(&instance.code() == codeBlock->code); switch (trap) { case Trap::OutOfBounds: @@ -1040,8 +1034,8 @@ bool wasm::MemoryAccessTraps(const RegisterState& regs, uint8_t* addr, JSContext* cx = TlsContext.get(); // Cold simulator helper function jit::JitActivation* activation = cx->activation()->asJit(); - activation->startWasmTrap(trap, bytecode.offset(), regs); - *newPC = segment.trapCode(); + activation->startWasmTrap(trap, trapSite, regs); + *newPC = codeBlock->code->trapCode(); return true; #endif } @@ -1051,23 +1045,21 @@ bool wasm::HandleIllegalInstruction(const RegisterState& regs, #ifdef JS_CODEGEN_NONE return false; #else - const wasm::CodeSegment* codeSegment = wasm::LookupCodeSegment(regs.pc); - if (!codeSegment || !codeSegment->isModule()) { + const wasm::CodeBlock* codeBlock = wasm::LookupCodeBlock(regs.pc); + if (!codeBlock) { return false; } - const wasm::ModuleSegment& segment = *codeSegment->asModule(); - Trap trap; - BytecodeOffset bytecode; - if (!segment.code().lookupTrap(regs.pc, &trap, &bytecode)) { + TrapSite trapSite; + if (!codeBlock->code->lookupTrap(regs.pc, &trap, &trapSite)) { return false; } JSContext* cx = TlsContext.get(); // Cold simulator helper function jit::JitActivation* activation = cx->activation()->asJit(); - activation->startWasmTrap(trap, bytecode.offset(), regs); - *newPC = segment.trapCode(); + activation->startWasmTrap(trap, trapSite, regs); + *newPC = codeBlock->code->trapCode(); return true; #endif } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.cpp index 23063390878..3f170d102ad 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.cpp @@ -24,6 +24,7 @@ using namespace js; using namespace js::wasm; const TypeDef* StaticTypeDefs::arrayMutI16 = nullptr; +const TypeDef* StaticTypeDefs::jsTag = nullptr; bool StaticTypeDefs::init() { RefPtr types = js_new(); @@ -31,13 +32,21 @@ bool StaticTypeDefs::init() { return false; } -#ifdef ENABLE_WASM_GC arrayMutI16 = types->addType(ArrayType(StorageType::I16, true)); if (!arrayMutI16) { return false; } arrayMutI16->recGroup().AddRef(); -#endif + + ValTypeVector params; + if (!params.append(ValType(RefType::extern_()))) { + return false; + } + jsTag = types->addType(FuncType(std::move(params), ValTypeVector())); + if (!jsTag) { + return false; + } + jsTag->recGroup().AddRef(); return true; } @@ -47,4 +56,20 @@ void StaticTypeDefs::destroy() { arrayMutI16->recGroup().Release(); arrayMutI16 = nullptr; } + if (jsTag) { + jsTag->recGroup().Release(); + jsTag = nullptr; + } +} + +bool StaticTypeDefs::addAllToTypeContext(TypeContext* types) { + for (const TypeDef* type : {arrayMutI16, jsTag}) { + MOZ_ASSERT(type, "static TypeDef was not initialized"); + SharedRecGroup recGroup = &type->recGroup(); + MOZ_ASSERT(recGroup->numTypes() == 1); + if (!types->addRecGroup(recGroup)) { + return false; + } + } + return true; } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.h b/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.h index d3a01ad26c4..6372ba6188d 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmStaticTypeDefs.h @@ -19,6 +19,8 @@ #ifndef wasm_static_type_defs #define wasm_static_type_defs +#include "wasm/WasmTypeDef.h" + namespace js { namespace wasm { @@ -30,9 +32,12 @@ class TypeDef; // definitions. Rethink this if we have more than several type definitions. struct StaticTypeDefs { static const TypeDef* arrayMutI16; + static const TypeDef* jsTag; [[nodiscard]] static bool init(); static void destroy(); + + [[nodiscard]] static bool addAllToTypeContext(TypeContext* types); }; } // namespace wasm diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.cpp index 3a180500301..d647871e683 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.cpp @@ -38,6 +38,11 @@ using namespace js; using namespace js::jit; using namespace js::wasm; +using mozilla::DebugOnly; +using mozilla::Maybe; +using mozilla::Nothing; +using mozilla::Some; + using MIRTypeVector = Vector; using ABIArgMIRTypeIter = jit::ABIArgIter; @@ -179,7 +184,16 @@ static void GenPrint(DebugChannel channel, MacroAssembler& masm, { MOZ_ASSERT(MaybeGetJitContext(), "codegen debug checks require a jit context"); +# ifdef JS_CODEGEN_ARM64 + if (IsCompilingWasm()) { + masm.setupWasmABICall(); + } else { + // JS ARM64 has an extra stack pointer which is not managed in WASM. + masm.setupUnalignedABICall(temp); + } +# else masm.setupUnalignedABICall(temp); +# endif passArgAndCall(IsCompilingWasm(), temp); } @@ -592,7 +606,7 @@ static void CallFuncExport(MacroAssembler& masm, const FuncExport& fe, if (funcPtr) { masm.call(*funcPtr); } else { - masm.call(CallSiteDesc(CallSiteDesc::Func), fe.funcIndex()); + masm.call(CallSiteDesc(CallSiteKind::Func), fe.funcIndex()); } } @@ -749,7 +763,7 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, // Copy parameters out of argv and into the wasm ABI registers/stack-slots. SetupABIArguments(masm, fe, funcType, argv, scratch); - masm.loadWasmPinnedRegsFromInstance(); + masm.loadWasmPinnedRegsFromInstance(mozilla::Nothing()); masm.storePtr(InstanceReg, Address(masm.getStackPointer(), WasmCalleeInstanceOffsetBeforeCall)); @@ -760,10 +774,10 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, CallFuncExport(masm, fe, funcPtr); masm.assertStackAlignment(WasmStackAlignment); - // Set the return value based on whether InstanceReg is the FailInstanceReg - // magic value (set by the throw stub). + // Set the return value based on whether InstanceReg is the + // InterpFailInstanceReg magic value (set by the exception handler). Label success, join; - masm.branchPtr(Assembler::NotEqual, InstanceReg, Imm32(FailInstanceReg), + masm.branchPtr(Assembler::NotEqual, InstanceReg, Imm32(InterpFailInstanceReg), &success); masm.move32(Imm32(false), scratch); masm.jump(&join); @@ -844,16 +858,14 @@ static void GenerateJitEntryLoadInstance(MacroAssembler& masm) { // Creates a JS fake exit frame for wasm, so the frame iterators just use // JSJit frame iteration. -static void GenerateJitEntryThrow(MacroAssembler& masm, unsigned frameSize) { +// +// Note: the caller must ensure InstanceReg is valid. +static void GenerateJitEntryThrow(MacroAssembler& masm) { AssertExpectedSP(masm); - MOZ_ASSERT(masm.framePushed() == frameSize); - - masm.freeStack(frameSize); + MOZ_ASSERT(masm.framePushed() == 0); MoveSPForJitABI(masm); - GenerateJitEntryLoadInstance(masm); - masm.loadPtr(Address(InstanceReg, Instance::offsetOfCx()), ScratchIonEntry); masm.enterFakeExitFrameForWasm(ScratchIonEntry, ScratchIonEntry, ExitFrameType::WasmGenericJitEntry); @@ -883,6 +895,8 @@ static void GenerateBigIntInitialization(MacroAssembler& masm, MOZ_ASSERT(input.reg != scratch); #endif + MOZ_ASSERT(masm.framePushed() == 0); + // We need to avoid clobbering other argument registers and the input. AllocatableRegisterSet regs(RegisterSet::Volatile()); LiveRegisterSet save(regs.asLiveSet()); @@ -904,7 +918,7 @@ static void GenerateBigIntInitialization(MacroAssembler& masm, ignore.add(scratch); masm.PopRegsInMaskIgnore(save, ignore); - masm.branchTest32(Assembler::Zero, scratch, scratch, fail); + masm.branchTestPtr(Assembler::Zero, scratch, scratch, fail); masm.initializeBigInt64(Scalar::BigInt64, scratch, input); } @@ -932,39 +946,54 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, // // GenerateJitEntryPrologue has additionally pushed the caller's frame // pointer. The stack pointer is now JitStackAlignment-aligned. + // + // We initialize an ExitFooterFrame (with ExitFrameType::WasmGenericJitEntry) + // immediately below the frame pointer to ensure FP is a valid JS JIT exit + // frame. MOZ_ASSERT(masm.framePushed() == 0); - unsigned normalBytesNeeded = StackArgBytesForWasmABI(funcType); + if (funcType.hasUnexposableArgOrRet()) { + GenerateJitEntryLoadInstance(masm); + CallSymbolicAddress(masm, !fe.hasEagerStubs(), + SymbolicAddress::ReportV128JSCall); + GenerateJitEntryThrow(masm); + return FinishOffsets(masm, offsets); + } + + // Avoid overlapping aligned stack arguments area with ExitFooterFrame. + const unsigned AlignedExitFooterFrameSize = + AlignBytes(ExitFooterFrame::Size(), WasmStackAlignment); + unsigned normalBytesNeeded = + AlignedExitFooterFrameSize + StackArgBytesForWasmABI(funcType); MIRTypeVector coerceArgTypes; MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Int32)); MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer)); MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer)); - unsigned oolBytesNeeded = StackArgBytesForWasmABI(coerceArgTypes); + unsigned oolBytesNeeded = + AlignedExitFooterFrameSize + StackArgBytesForWasmABI(coerceArgTypes); unsigned bytesNeeded = std::max(normalBytesNeeded, oolBytesNeeded); // Note the jit caller ensures the stack is aligned *after* the call // instruction. - unsigned frameSizeExclFP = StackDecrementForCall( - WasmStackAlignment, masm.framePushed(), bytesNeeded); + unsigned frameSize = StackDecrementForCall(WasmStackAlignment, + masm.framePushed(), bytesNeeded); // Reserve stack space for wasm ABI arguments, set up like this: // <-- ABI args | padding - masm.reserveStack(frameSizeExclFP); + masm.reserveStack(frameSize); - uint32_t frameSize = masm.framePushed(); + MOZ_ASSERT(masm.framePushed() == frameSize); + + // Initialize the ExitFooterFrame. + static_assert(ExitFooterFrame::Size() == sizeof(uintptr_t)); + masm.storePtr(ImmWord(uint32_t(ExitFrameType::WasmGenericJitEntry)), + Address(FramePointer, -int32_t(ExitFooterFrame::Size()))); GenerateJitEntryLoadInstance(masm); - if (funcType.hasUnexposableArgOrRet()) { - CallSymbolicAddress(masm, !fe.hasEagerStubs(), - SymbolicAddress::ReportV128JSCall); - GenerateJitEntryThrow(masm, frameSize); - return FinishOffsets(masm, offsets); - } - FloatRegister scratchF = ABINonArgDoubleReg; Register scratchG = ScratchIonEntry; ValueOperand scratchV = ScratchValIonEntry; @@ -986,56 +1015,53 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, Label next; switch (funcType.args()[i].kind()) { case ValType::I32: { - ScratchTagScope tag(masm, scratchV); - masm.splitTagForTest(scratchV, tag); + Label isDouble, isUndefinedOrNull, isBoolean; + { + ScratchTagScope tag(masm, scratchV); + masm.splitTagForTest(scratchV, tag); - // For int32 inputs, just skip. - masm.branchTestInt32(Assembler::Equal, tag, &next); + // For int32 inputs, just skip. + masm.branchTestInt32(Assembler::Equal, tag, &next); + + masm.branchTestDouble(Assembler::Equal, tag, &isDouble); + masm.branchTestUndefined(Assembler::Equal, tag, &isUndefinedOrNull); + masm.branchTestNull(Assembler::Equal, tag, &isUndefinedOrNull); + masm.branchTestBoolean(Assembler::Equal, tag, &isBoolean); + + // Other types (symbol, object, strings) go to the C++ call. + masm.jump(&oolCall); + } + + Label storeBack; // For double inputs, unbox, truncate and store back. - Label storeBack, notDouble; - masm.branchTestDouble(Assembler::NotEqual, tag, ¬Double); + masm.bind(&isDouble); { - ScratchTagScopeRelease _(&tag); masm.unboxDouble(scratchV, scratchF); masm.branchTruncateDoubleMaybeModUint32(scratchF, scratchG, &oolCall); masm.jump(&storeBack); } - masm.bind(¬Double); // For null or undefined, store 0. - Label nullOrUndefined, notNullOrUndefined; - masm.branchTestUndefined(Assembler::Equal, tag, &nullOrUndefined); - masm.branchTestNull(Assembler::NotEqual, tag, ¬NullOrUndefined); - masm.bind(&nullOrUndefined); + masm.bind(&isUndefinedOrNull); { - ScratchTagScopeRelease _(&tag); masm.storeValue(Int32Value(0), jitArgAddr); + masm.jump(&next); } - masm.jump(&next); - masm.bind(¬NullOrUndefined); - // For booleans, store the number value back. Other types (symbol, - // object, strings) go to the C++ call. - masm.branchTestBoolean(Assembler::NotEqual, tag, &oolCall); + // For booleans, store the number value back. + masm.bind(&isBoolean); masm.unboxBoolean(scratchV, scratchG); // fallthrough: masm.bind(&storeBack); - { - ScratchTagScopeRelease _(&tag); - masm.storeValue(JSVAL_TYPE_INT32, scratchG, jitArgAddr); - } + masm.storeValue(JSVAL_TYPE_INT32, scratchG, jitArgAddr); break; } case ValType::I64: { - ScratchTagScope tag(masm, scratchV); - masm.splitTagForTest(scratchV, tag); - // For BigInt inputs, just skip. Otherwise go to C++ for other // types that require creating a new BigInt or erroring. - masm.branchTestBigInt(Assembler::NotEqual, tag, &oolCall); - masm.jump(&next); + masm.branchTestBigInt(Assembler::NotEqual, scratchV, &oolCall); break; } case ValType::F32: @@ -1043,53 +1069,44 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, // Note we can reuse the same code for f32/f64 here, since for the // case of f32, the conversion of f64 to f32 will happen in the // second loop. - ScratchTagScope tag(masm, scratchV); - masm.splitTagForTest(scratchV, tag); - // For double inputs, just skip. - masm.branchTestDouble(Assembler::Equal, tag, &next); - - // For int32 inputs, convert and rebox. - Label storeBack, notInt32; + Label isInt32OrBoolean, isUndefined, isNull; { - ScratchTagScopeRelease _(&tag); - masm.branchTestInt32(Assembler::NotEqual, scratchV, ¬Int32); - masm.int32ValueToDouble(scratchV, scratchF); - masm.jump(&storeBack); + ScratchTagScope tag(masm, scratchV); + masm.splitTagForTest(scratchV, tag); + + // For double inputs, just skip. + masm.branchTestDouble(Assembler::Equal, tag, &next); + + masm.branchTestInt32(Assembler::Equal, tag, &isInt32OrBoolean); + masm.branchTestUndefined(Assembler::Equal, tag, &isUndefined); + masm.branchTestNull(Assembler::Equal, tag, &isNull); + masm.branchTestBoolean(Assembler::Equal, tag, &isInt32OrBoolean); + + // Other types (symbol, object, strings) go to the C++ call. + masm.jump(&oolCall); + } + + // For int32 and boolean inputs, convert and rebox. + masm.bind(&isInt32OrBoolean); + { + masm.convertInt32ToDouble(scratchV.payloadOrValueReg(), scratchF); + masm.boxDouble(scratchF, jitArgAddr); + masm.jump(&next); } - masm.bind(¬Int32); // For undefined (missing argument), store NaN. - Label notUndefined; - masm.branchTestUndefined(Assembler::NotEqual, tag, ¬Undefined); + masm.bind(&isUndefined); { - ScratchTagScopeRelease _(&tag); masm.storeValue(DoubleValue(JS::GenericNaN()), jitArgAddr); masm.jump(&next); } - masm.bind(¬Undefined); // +null is 0. - Label notNull; - masm.branchTestNull(Assembler::NotEqual, tag, ¬Null); + masm.bind(&isNull); { - ScratchTagScopeRelease _(&tag); masm.storeValue(DoubleValue(0.), jitArgAddr); } - masm.jump(&next); - masm.bind(¬Null); - - // For booleans, store the number value back. Other types (symbol, - // object, strings) go to the C++ call. - masm.branchTestBoolean(Assembler::NotEqual, tag, &oolCall); - masm.boolValueToDouble(scratchV, scratchF); - // fallthrough: - - masm.bind(&storeBack); - { - ScratchTagScopeRelease _(&tag); - masm.boxDouble(scratchF, jitArgAddr); - } break; } case ValType::Ref: { @@ -1201,31 +1218,25 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, GenPrintf(DebugChannel::Function, masm, "\n"); // Setup wasm register state. - masm.loadWasmPinnedRegsFromInstance(); + masm.loadWasmPinnedRegsFromInstance(mozilla::Nothing()); masm.storePtr(InstanceReg, Address(masm.getStackPointer(), WasmCalleeInstanceOffsetBeforeCall)); - // Call into the real function. Note that, due to the throw stub, instance - // and pinned registers may be clobbered. + // Call into the real function. masm.assertStackAlignment(WasmStackAlignment); CallFuncExport(masm, fe, funcPtr); masm.assertStackAlignment(WasmStackAlignment); - // If InstanceReg is equal to the FailInstanceReg magic value (set by the - // throw stub), then report the exception to the JIT caller by jumping into - // the exception stub. - Label exception; - masm.branchPtr(Assembler::Equal, InstanceReg, Imm32(FailInstanceReg), - &exception); - - // Pop arguments. - masm.freeStackTo(frameSize - frameSizeExclFP); - GenPrintf(DebugChannel::Function, masm, "wasm-function[%d]; returns ", fe.funcIndex()); + // Pop frame. + masm.moveToStackPtr(FramePointer); + masm.setFramePushed(0); + // Store the return value in the JSReturnOperand. + Label exception; const ValTypeVector& results = funcType.results(); if (results.length() == 0) { GenPrintf(DebugChannel::Function, masm, "void"); @@ -1236,6 +1247,7 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, case ValType::I32: GenPrintIsize(DebugChannel::Function, masm, ReturnReg); #ifdef JS_64BIT + // boxNonDouble requires a widened int32 value. masm.widenInt32(ReturnReg); #endif masm.boxNonDouble(JSVAL_TYPE_INT32, ReturnReg, JSReturnOperand); @@ -1256,27 +1268,17 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, break; } case ValType::I64: { - Label fail, done; GenPrintI64(DebugChannel::Function, masm, ReturnReg64); - GenerateBigIntInitialization(masm, 0, ReturnReg64, scratchG, fe, &fail); + MOZ_ASSERT(masm.framePushed() == 0); + GenerateBigIntInitialization(masm, 0, ReturnReg64, scratchG, fe, + &exception); masm.boxNonDouble(JSVAL_TYPE_BIGINT, scratchG, JSReturnOperand); - masm.jump(&done); - masm.bind(&fail); - // Fixup the stack for the exception tail so that we can share it. - masm.reserveStack(frameSizeExclFP); - masm.jump(&exception); - masm.bind(&done); - // Un-fixup the stack for the benefit of the assertion below. - masm.setFramePushed(0); break; } case ValType::V128: { MOZ_CRASH("unexpected return type when calling from ion to wasm"); } case ValType::Ref: { - // Per comment above, the call may have clobbered the instance - // register, so reload since unboxing will need it. - GenerateJitEntryLoadInstance(masm); GenPrintPtr(DebugChannel::Import, masm, ReturnReg); masm.convertWasmAnyRefToValue(InstanceReg, ReturnReg, JSReturnOperand, WasmJitEntryReturnScratch); @@ -1287,14 +1289,13 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, GenPrintf(DebugChannel::Function, masm, "\n"); - MOZ_ASSERT(masm.framePushed() == 0); - AssertExpectedSP(masm); GenerateJitEntryEpilogue(masm, offsets); MOZ_ASSERT(masm.framePushed() == 0); // Generate an OOL call to the C++ conversion path. - if (funcType.args().length()) { + bool hasFallThroughForException = false; + if (oolCall.used()) { masm.bind(&oolCall); masm.setFramePushed(frameSize); @@ -1302,11 +1303,11 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, // unify the BuiltinThunk's interface we call it here with wasm abi. jit::WasmABIArgIter argsIter(coerceArgTypes); - // argument 0: function export index. + // argument 0: function index. if (argsIter->kind() == ABIArg::GPR) { - masm.movePtr(ImmWord(funcExportIndex), argsIter->gpr()); + masm.movePtr(ImmWord(fe.funcIndex()), argsIter->gpr()); } else { - masm.storePtr(ImmWord(funcExportIndex), + masm.storePtr(ImmWord(fe.funcIndex()), Address(sp, argsIter->offsetFromArgBase())); } argsIter++; @@ -1339,13 +1340,17 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, // No widening is required, as the return value is used as a bool. masm.branchTest32(Assembler::NonZero, ReturnReg, ReturnReg, &rejoinBeforeCall); + + MOZ_ASSERT(masm.framePushed() == frameSize); + masm.freeStack(frameSize); + hasFallThroughForException = true; } - // Prepare to throw: reload InstanceReg from the frame. - masm.bind(&exception); - masm.setFramePushed(frameSize); - masm.freeStackTo(frameSize); - GenerateJitEntryThrow(masm, frameSize); + if (exception.used() || hasFallThroughForException) { + masm.bind(&exception); + MOZ_ASSERT(masm.framePushed() == 0); + GenerateJitEntryThrow(masm); + } return FinishOffsets(masm, offsets); } @@ -1356,7 +1361,7 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe, Register scratch, uint32_t* callOffset) { MOZ_ASSERT(!IsCompilingWasm()); - const FuncType& funcType = inst.metadata().getFuncExportType(fe); + const FuncType& funcType = inst.codeMeta().getFuncType(fe.funcIndex()); size_t framePushedAtStart = masm.framePushed(); @@ -1378,6 +1383,10 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe, masm.loadJSContext(scratch); masm.enterFakeExitFrame(scratch, scratch, ExitFrameType::DirectWasmJitCall); + static_assert(ExitFrameLayout::SizeWithFooter() % WasmStackAlignment == 0); + MOZ_ASSERT( + (masm.framePushed() + framePushedAtFakeFrame) % WasmStackAlignment == 0); + // Move stack arguments to their final locations. unsigned bytesNeeded = StackArgBytesForWasmABI(funcType); bytesNeeded = StackDecrementForCall( @@ -1505,13 +1514,13 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe, masm.movePtr(ImmPtr(&inst), InstanceReg); masm.storePtr(InstanceReg, Address(masm.getStackPointer(), WasmCalleeInstanceOffsetBeforeCall)); - masm.loadWasmPinnedRegsFromInstance(); + masm.loadWasmPinnedRegsFromInstance(mozilla::Nothing()); // Actual call. - const CodeTier& codeTier = inst.code().codeTier(inst.code().bestTier()); - const MetadataTier& metadata = codeTier.metadata(); - const CodeRange& codeRange = metadata.codeRange(fe); - void* callee = codeTier.segment().base() + codeRange.funcUncheckedCallEntry(); + const CodeBlock& codeBlock = inst.code().funcCodeBlock(fe.funcIndex()); + const CodeRange& codeRange = codeBlock.codeRange(fe); + void* callee = const_cast(codeBlock.base()) + + codeRange.funcUncheckedCallEntry(); masm.assertStackAlignment(WasmStackAlignment); MoveSPForJitABI(masm); @@ -1524,9 +1533,6 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe, masm.freeStackTo(fakeFramePushed); masm.assertStackAlignment(WasmStackAlignment); - masm.branchPtr(Assembler::Equal, InstanceReg, Imm32(wasm::FailInstanceReg), - masm.exceptionLabel()); - // Store the return value in the appropriate place. GenPrintf(DebugChannel::Function, masm, "wasm-function[%d]; returns ", fe.funcIndex()); @@ -1869,7 +1875,7 @@ static bool AddStackCheckForImportFunctionEntry(jit::MacroAssembler& masm, const FuncType& funcType, StackMaps* stackMaps) { std::pair pair = - masm.wasmReserveStackChecked(reserve, BytecodeOffset(0)); + masm.wasmReserveStackChecked(reserve, TrapSiteDesc()); // Attempt to create stack maps for masm.wasmReserveStackChecked. ArgTypeVector argTypes(funcType); @@ -1889,8 +1895,7 @@ static bool AddStackCheckForImportFunctionEntry(jit::MacroAssembler& masm, // In debug builds, we'll always have a stack map, even if there are no // refs to track. MOZ_ASSERT(stackMap); - if (stackMap && - !stackMaps->add((uint8_t*)(uintptr_t)trapInsnOffset.offset(), stackMap)) { + if (stackMap && !stackMaps->add(trapInsnOffset.offset(), stackMap)) { stackMap->destroy(); return false; } @@ -1905,7 +1910,7 @@ static bool AddStackCheckForImportFunctionEntry(jit::MacroAssembler& masm, // - normal entries, so that, if the import is re-exported, an entry stub can // be generated and called without any special cases static bool GenerateImportFunction(jit::MacroAssembler& masm, - const FuncImport& fi, + uint32_t funcImportInstanceOffset, const FuncType& funcType, CallIndirectId callIndirectId, FuncOffsets* offsets, StackMaps* stackMaps) { @@ -1958,15 +1963,15 @@ static bool GenerateImportFunction(jit::MacroAssembler& masm, } // Call the import exit stub. - CallSiteDesc desc(CallSiteDesc::Import); + CallSiteDesc desc(CallSiteKind::Import); MoveSPForJitABI(masm); - masm.wasmCallImport(desc, CalleeDesc::import(fi.instanceOffset())); + masm.wasmCallImport(desc, CalleeDesc::import(funcImportInstanceOffset)); // Restore the instance register and pinned regs, per wasm function ABI. masm.loadPtr( Address(masm.getStackPointer(), framePushed - sizeOfInstanceSlot), InstanceReg); - masm.loadWasmPinnedRegsFromInstance(); + masm.loadWasmPinnedRegsFromInstance(mozilla::Nothing()); // Restore cx->realm. masm.switchToWasmInstanceRealm(ABINonArgReturnReg0, ABINonArgReturnReg1); @@ -1977,37 +1982,6 @@ static bool GenerateImportFunction(jit::MacroAssembler& masm, static const unsigned STUBS_LIFO_DEFAULT_CHUNK_SIZE = 4 * 1024; -bool wasm::GenerateImportFunctions(const ModuleEnvironment& env, - const FuncImportVector& imports, - CompiledCode* code) { - LifoAlloc lifo(STUBS_LIFO_DEFAULT_CHUNK_SIZE); - TempAllocator alloc(&lifo); - WasmMacroAssembler masm(alloc, env); - - for (uint32_t funcIndex = 0; funcIndex < imports.length(); funcIndex++) { - const FuncImport& fi = imports[funcIndex]; - const FuncType& funcType = *env.funcs[funcIndex].type; - CallIndirectId callIndirectId = CallIndirectId::forFunc(env, funcIndex); - - FuncOffsets offsets; - if (!GenerateImportFunction(masm, fi, funcType, callIndirectId, &offsets, - &code->stackMaps)) { - return false; - } - if (!code->codeRanges.emplaceBack(funcIndex, /* bytecodeOffset = */ 0, - offsets, /* hasUnwindInfo = */ false)) { - return false; - } - } - - masm.finish(); - if (masm.oom()) { - return false; - } - - return code->swap(masm); -} - // Generate a stub that is called via the internal ABI derived from the // signature of the import and calls into an appropriate callImport C++ // function, having boxed all the ABI arguments into a homogeneous Value array. @@ -2180,10 +2154,12 @@ static bool GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, // Generate a stub that is called via the internal ABI derived from the // signature of the import and calls into a compatible JIT function, // having boxed all the ABI arguments into the JIT stack frame layout. -static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, +static bool GenerateImportJitExit(MacroAssembler& masm, + uint32_t funcImportInstanceOffset, const FuncType& funcType, - unsigned funcImportIndex, Label* throwLabel, - CallableOffsets* offsets) { + unsigned funcImportIndex, + uint32_t fallbackOffset, Label* throwLabel, + ImportOffsets* offsets) { AutoCreatedBy acb(masm, "GenerateImportJitExit"); AssertExpectedSP(masm); @@ -2212,7 +2188,7 @@ static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, totalJitFrameBytes) - sizeOfRetAddrAndFP; - GenerateJitExitPrologue(masm, jitFramePushed, offsets); + GenerateJitExitPrologue(masm, jitFramePushed, fallbackOffset, offsets); // 1. Descriptor. unsigned argc = funcType.args().length(); @@ -2253,7 +2229,7 @@ static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, // exit. masm.loadPtr( Address(InstanceReg, Instance::offsetInData( - fi.instanceOffset() + + funcImportInstanceOffset + offsetof(FuncImportInstanceData, callable))), callee); @@ -2340,8 +2316,8 @@ static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, masm.breakpoint(); break; case ValType::F32: - masm.convertValueToFloat(JSReturnOperand, ReturnFloat32Reg, - &oolConvert); + masm.convertValueToFloat32(JSReturnOperand, ReturnFloat32Reg, + &oolConvert); GenPrintF32(DebugChannel::Import, masm, ReturnFloat32Reg); break; case ValType::F64: @@ -2525,7 +2501,7 @@ bool wasm::GenerateBuiltinThunk(MacroAssembler& masm, ABIFunctionType abiType, if (i->argInRegister()) { #ifdef JS_CODEGEN_ARM // Non hard-fp passes the args values in GPRs. - if (!UseHardFpABI() && IsFloatingPointType(i.mirType())) { + if (!ARMFlags::UseHardFpABI() && IsFloatingPointType(i.mirType())) { FloatRegister input = i->fpu(); if (i.mirType() == MIRType::Float32) { masm.ma_vxfer(input, Register::FromCode(input.id())); @@ -2567,7 +2543,7 @@ bool wasm::GenerateBuiltinThunk(MacroAssembler& masm, ABIFunctionType abiType, // Non hard-fp passes the return values in GPRs. MIRType retType = ToMIRType(ABIType( std::underlying_type_t(abiType) & ABITypeArgMask)); - if (!UseHardFpABI() && IsFloatingPointType(retType)) { + if (!ARMFlags::UseHardFpABI() && IsFloatingPointType(retType)) { masm.ma_vxfer(r0, r1, d0); } #endif @@ -2763,7 +2739,7 @@ void wasm::GenerateJumpToCatchHandler(MacroAssembler& masm, Register rfe, Register scratch1, Register scratch2) { masm.loadPtr(Address(rfe, ResumeFromException::offsetOfInstance()), InstanceReg); - masm.loadWasmPinnedRegsFromInstance(); + masm.loadWasmPinnedRegsFromInstance(mozilla::Nothing()); masm.switchToWasmInstanceRealm(scratch1, scratch2); masm.loadPtr(Address(rfe, ResumeFromException::offsetOfTarget()), scratch1); masm.loadPtr(Address(rfe, ResumeFromException::offsetOfFramePointer()), @@ -2774,14 +2750,10 @@ void wasm::GenerateJumpToCatchHandler(MacroAssembler& masm, Register rfe, masm.jump(scratch1); } -// Generate a stub that restores the stack pointer to what it was on entry to -// the wasm activation, sets the return register to 'false' and then executes a -// return which will return from this wasm activation to the caller. This stub -// should only be called after the caller has reported an error. +// Generate a stub that calls the C++ exception handler. static bool GenerateThrowStub(MacroAssembler& masm, Label* throwLabel, Offsets* offsets) { Register scratch1 = ABINonArgReturnReg0; - Register scratch2 = ABINonArgReturnReg1; AssertExpectedSP(masm); masm.haltingAlign(CodeAlignment); @@ -2821,46 +2793,23 @@ static bool GenerateThrowStub(MacroAssembler& masm, Label* throwLabel, i++; MOZ_ASSERT(i.done()); - // WasmHandleThrow unwinds JitActivation::wasmExitFP() and returns the - // address of the return address on the stack this stub should return to. - // Set the FramePointer to a magic value to indicate a return by throw. + // WasmHandleThrow unwinds JitActivation::wasmExitFP() and initializes the + // ResumeFromException struct we allocated on the stack. // - // If there is a Wasm catch handler present, it will instead return the - // address of the handler to jump to and the FP/SP values to restore. + // It returns the address of the JIT's exception handler trampoline that we + // should jump to. This trampoline will return to the interpreter entry or + // jump to a catch handler. masm.call(SymbolicAddress::HandleThrow); - Label resumeCatch, leaveWasm; + // Ensure the ResumeFromException struct is on top of the stack. + masm.freeStack(frameSize); - masm.load32(Address(ReturnReg, offsetof(jit::ResumeFromException, kind)), - scratch1); - - masm.branch32(Assembler::Equal, scratch1, - Imm32(jit::ExceptionResumeKind::WasmCatch), &resumeCatch); - masm.branch32(Assembler::Equal, scratch1, - Imm32(jit::ExceptionResumeKind::Wasm), &leaveWasm); - - masm.breakpoint(); - - // The case where a Wasm catch handler was found while unwinding the stack. - masm.bind(&resumeCatch); - GenerateJumpToCatchHandler(masm, ReturnReg, scratch1, scratch2); - - // No catch handler was found, so we will just return out. - masm.bind(&leaveWasm); - masm.loadPtr(Address(ReturnReg, ResumeFromException::offsetOfFramePointer()), - FramePointer); - masm.loadPtr(Address(ReturnReg, ResumeFromException::offsetOfInstance()), - InstanceReg); - masm.loadPtr(Address(ReturnReg, ResumeFromException::offsetOfStackPointer()), - scratch1); - masm.moveToStackPtr(scratch1); + // Jump to the "return value check" code of the JIT's exception handler + // trampoline. On ARM64 ensure PSP matches SP. #ifdef JS_CODEGEN_ARM64 - masm.loadPtr(Address(scratch1, 0), lr); - masm.addToStackPtr(Imm32(8)); - masm.abiret(); -#else - masm.ret(); + masm.Mov(PseudoStackPointer64, sp); #endif + masm.jump(ReturnReg); return FinishOffsets(masm, offsets); } @@ -2869,16 +2818,17 @@ static const LiveRegisterSet AllAllocatableRegs = LiveRegisterSet(GeneralRegisterSet(Registers::AllocatableMask), FloatRegisterSet(FloatRegisters::AllMask)); -// Generate a stub that handle toggable enter/leave frame traps or breakpoints. -// The trap records frame pointer (via GenerateExitPrologue) and saves most of -// registers to not affect the code generated by WasmBaselineCompile. -static bool GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel, - CallableOffsets* offsets) { +// Generate a stub that handles toggleable enter/leave frame traps or +// breakpoints. The stub records the frame pointer (via GenerateExitPrologue) +// and saves most of registers, so as to not affect the code generated by +// WasmBaselineCompile. +static bool GenerateDebugStub(MacroAssembler& masm, Label* throwLabel, + CallableOffsets* offsets) { AssertExpectedSP(masm); masm.haltingAlign(CodeAlignment); masm.setFramePushed(0); - GenerateExitPrologue(masm, 0, ExitReason::Fixed::DebugTrap, offsets); + GenerateExitPrologue(masm, 0, ExitReason::Fixed::DebugStub, offsets); // Save all registers used between baseline compiler operations. masm.PushRegsInMask(AllAllocatableRegs); @@ -2917,11 +2867,359 @@ static bool GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel, masm.setFramePushed(framePushed); masm.PopRegsInMask(AllAllocatableRegs); - GenerateExitEpilogue(masm, 0, ExitReason::Fixed::DebugTrap, offsets); + GenerateExitEpilogue(masm, 0, ExitReason::Fixed::DebugStub, offsets); return FinishOffsets(masm, offsets); } +static bool GenerateRequestTierUpStub(MacroAssembler& masm, + CallableOffsets* offsets) { + // This is similar to GenerateDebugStub. As with that routine, all registers + // are saved, we call out to a C++ helper, then restore the registers. The + // helper can't fail, though. + // + // On entry to (the code generated by) this routine, we expect the requesting + // instance pointer to be in InstanceReg, regardless of the platform. + + AutoCreatedBy acb(masm, "GenerateRequestTierUpStub"); + AssertExpectedSP(masm); + masm.haltingAlign(CodeAlignment); + masm.setFramePushed(0); + + GenerateExitPrologue(masm, 0, ExitReason::Fixed::RequestTierUp, offsets); + + // Save all registers used between baseline compiler operations. + masm.PushRegsInMask(AllAllocatableRegs); + + uint32_t framePushed = masm.framePushed(); + + // This method might be called with unaligned stack -- aligning and + // saving old stack pointer at the top. +#ifdef JS_CODEGEN_ARM64 + // On ARM64 however the stack is always aligned. + static_assert(ABIStackAlignment == 16, "ARM64 SP alignment"); +#else + Register scratch = ABINonArgReturnReg0; + masm.moveStackPtrTo(scratch); + masm.subFromStackPtr(Imm32(sizeof(intptr_t))); + masm.andToStackPtr(Imm32(~(ABIStackAlignment - 1))); + masm.storePtr(scratch, Address(masm.getStackPointer(), 0)); +#endif + + if (ShadowStackSpace > 0) { + masm.subFromStackPtr(Imm32(ShadowStackSpace)); + } + masm.assertStackAlignment(ABIStackAlignment); + + // Pass InstanceReg as the first (and only) arg to the C++ routine. We + // expect that the only target to pass the first integer arg in memory is + // x86_32, and handle that specially. + ABIArgGenerator abi; + ABIArg arg = abi.next(MIRType::Pointer); +#ifndef JS_CODEGEN_X86 + // The arg rides in a reg. + MOZ_RELEASE_ASSERT(arg.kind() == ABIArg::GPR); + masm.movePtr(InstanceReg, arg.gpr()); +#else + // Ensure we don't need to consider ShadowStackSpace. + static_assert(ShadowStackSpace == 0); + // Ensure the ABIArgGenerator is consistent with the code generation + // assumptions we make here. + MOZ_RELEASE_ASSERT(arg.kind() == ABIArg::Stack && + arg.offsetFromArgBase() == 0); + // Get the arg on the stack without messing up the stack alignment. + masm.subFromStackPtr(Imm32(12)); + masm.push(InstanceReg); +#endif + + masm.call(SymbolicAddress::HandleRequestTierUp); + // The call can't fail (meaning, if it does fail, we ignore that) + +#ifdef JS_CODEGEN_X86 + // Remove the arg and padding we just pushed. + masm.addToStackPtr(Imm32(16)); +#endif + + if (ShadowStackSpace > 0) { + masm.addToStackPtr(Imm32(ShadowStackSpace)); + } +#ifndef JS_CODEGEN_ARM64 + masm.Pop(scratch); + masm.moveToStackPtr(scratch); +#endif + + masm.setFramePushed(framePushed); + masm.PopRegsInMask(AllAllocatableRegs); + + GenerateExitEpilogue(masm, 0, ExitReason::Fixed::RequestTierUp, offsets); + + return FinishOffsets(masm, offsets); +} + +static bool GenerateUpdateCallRefMetricsStub(MacroAssembler& masm, + CallableOffsets* offsets) { + // This is a stub which is entirely self-contained -- it calls no other + // functions, cannot fail, and creates a minimal stack frame. It can only + // use three registers, `regMetrics`, `regFuncRef` and `regScratch`, as set + // up below, and as described in BaseCompiler::updateCallRefMetrics. All + // other registers must remain unchanged. Also, we may read InstanceReg. + // + // `regMetrics` (the CallRefMetrics*) should satisfy + // CallRefMetrics::invariantsOK() both on entry to and exit from the code + // generated here. + + // `regMetrics` and `regFuncRef` are live at entry, but not `regScratch`. + const Register regMetrics = WasmCallRefCallScratchReg0; // CallRefMetrics* + const Register regFuncRef = WasmCallRefCallScratchReg1; // FuncExtended* + const Register regScratch = WasmCallRefCallScratchReg2; // scratch + + // At entry to the stub, `regMetrics` points at the CallRefMetrics, + // `regFuncRef` points at the FunctionExtended, `regScratch` is available as + // scratch, `regFuncRef` is known to be non-null, and, if the target0/count0 + // slot is in use, it is known not to match that slot. The call may or may + // not be cross-instance. + + // Briefly, what we generate here is: + // + // assert(regFuncRef is non-null) + // + // if (regFuncRef is a cross instance call) { + // regMetrics->countOther++; + // return; + // } + // + // assert(regFuncRef != regMetrics->targets[0]); + // + // for (i = 1; i < NUM_SLOTS; i++) { + // if (regFuncRef == regMetrics->targets[i]) { + // regMetrics->counts[i]++; + // if (regMetrics->counts[i-1] counts[i]) { + // // swap regMetrics->counts[i-1]/[i] and + // regMetrics->targets[i-1]/[i] + // } + // return; + // } + // } + // + // for (i = 0; i < NUM_SLOTS; i++) { + // if (regMetrics->targets[i] is nullptr) { + // regMetrics->targets[i] = regFuncRef; + // regMetrics->counts[i] = 1; + // return; + // } + // } + // + // regMetrics->countsOther++; + // return; + // + // And the loops are unrolled. + + // Frame setup and unwinding: we generate the absolute minimal frame setup + // (`push FP; FP := SP` / `pop FP; ret`). There is no register save/restore + // in the frame. The routine created here is a leaf and will neither trap + // nor invoke GC, so the unwindability requirements are minimal -- only the + // profiler will need to be able to unwind through it. + + // See declaration of CallRefMetrics for comments about assignments of + // funcrefs to `CallRefMetrics::targets[]` fields. + + AutoCreatedBy acb(masm, "GenerateUpdateCallRefMetricsStub"); + Label ret; + + AssertExpectedSP(masm); + masm.haltingAlign(CodeAlignment); + masm.setFramePushed(0); + + GenerateMinimalPrologue(masm, &offsets->begin); + +#ifdef DEBUG + // Assertion: we know the target is non-null at entry, because the in-line + // code created by BaseCompiler::callRef handles that case. + // if (regFuncRef == nullptr) { + // crash; + // } + Label after1; + masm.branchWasmAnyRefIsNull(/*isNull=*/false, regFuncRef, &after1); + + masm.breakpoint(); + + masm.bind(&after1); +#endif + + // If it is a cross-instance call, add it to the `countOther` bin. + // regScratch = regFuncRef->instance; + // if (regScratch != thisInstance) { + // regScratch = regMetrics->countOther; + // regScratch++; + // regMetrics->countOther = regScratch; + // return; + // } + Label after2; + const size_t offsetOfInstanceSlot = FunctionExtended::offsetOfExtendedSlot( + FunctionExtended::WASM_INSTANCE_SLOT); + masm.loadPtr(Address(regFuncRef, offsetOfInstanceSlot), regScratch); + masm.branchPtr(Assembler::Equal, InstanceReg, regScratch, &after2); + // + const size_t offsetOfCountOther = CallRefMetrics::offsetOfCountOther(); + masm.load32(Address(regMetrics, offsetOfCountOther), regScratch); + masm.add32(Imm32(1), regScratch); + masm.store32(regScratch, Address(regMetrics, offsetOfCountOther)); + masm.jump(&ret); + // + masm.bind(&after2); + +#ifdef DEBUG + // Assertion: we know it can't be a hit at slot zero, because the inline code + // also handles that case. + // regScratch = regMetrics->targets[0]; + // if (regScratch == regFuncRef) { + // crash; + // } + Label after3; + const size_t offsetOfTarget0 = CallRefMetrics::offsetOfTarget(0); + masm.loadPtr(Address(regMetrics, offsetOfTarget0), regScratch); + masm.branchPtr(Assembler::NotEqual, regScratch, regFuncRef, &after3); + + masm.breakpoint(); + + masm.bind(&after3); +#endif + + // If it matches slot one, increment count, swap with slot zero if needed + // regScratch = regMetrics->targets[1]; + // if (regFuncRef == regScratch) { + // // We need a second temp register (regScratch being the first). + // // We no longer need regFuncRef so use that as the second temp. + // regScratch = regMetrics->counts[0]; + // regFuncRef = regMetrics->counts[1]; + // regFuncRef++; + // regMetrics->counts[1] = regFuncRef; + // if (regScratch counts[0] and [1] respectively + // regMetrics->counts[0] = regFuncRef; + // regMetrics->counts[1] = regScratch; + // regScratch = regMetrics->targets[0]; + // regFuncRef = regMetrics->targets[1]; + // regMetrics->targets[0] = regFuncRef; + // regMetrics->targets[1] = regScratch; + // } + // return; + // } + // and the same for slots 2, 3, 4, etc + for (size_t i = 1; i < CallRefMetrics::NUM_SLOTS; i++) { + Label after4; + masm.loadPtr(Address(regMetrics, CallRefMetrics::offsetOfTarget(i)), + regScratch); + masm.branchPtr(Assembler::NotEqual, regFuncRef, regScratch, &after4); + + masm.load32(Address(regMetrics, CallRefMetrics::offsetOfCount(i - 1)), + regScratch); + masm.load32(Address(regMetrics, CallRefMetrics::offsetOfCount(i)), + regFuncRef); + masm.add32(Imm32(1), regFuncRef); + masm.store32(regFuncRef, + Address(regMetrics, CallRefMetrics::offsetOfCount(i))); + masm.branch32(Assembler::AboveOrEqual, regScratch, regFuncRef, &ret); + + masm.store32(regFuncRef, + Address(regMetrics, CallRefMetrics::offsetOfCount(i - 1))); + masm.store32(regScratch, + Address(regMetrics, CallRefMetrics::offsetOfCount(i))); + masm.loadPtr(Address(regMetrics, CallRefMetrics::offsetOfTarget(i - 1)), + regScratch); + masm.loadPtr(Address(regMetrics, CallRefMetrics::offsetOfTarget(i)), + regFuncRef); + masm.storePtr(regFuncRef, + Address(regMetrics, CallRefMetrics::offsetOfTarget(i - 1))); + masm.storePtr(regScratch, + Address(regMetrics, CallRefMetrics::offsetOfTarget(i))); + masm.jump(&ret); + + masm.bind(&after4); + } + + // Not found. Use the first unused slot, if available. This assumes that T + // is non-null; but that is assured us on entry (and asserted above). See + // CallRefMetrics::invariantsOK. + // if (regMetrics->targets[0] == nullptr) { + // regMetrics->targets[0] = regFuncRef; + // regMetrics->counts[0] = 1; + // return; + // } + // and the same for slots 1, 2, 3, 4, etc + for (size_t i = 0; i < CallRefMetrics::NUM_SLOTS; i++) { + Label after5; + masm.loadPtr(Address(regMetrics, CallRefMetrics::offsetOfTarget(i)), + regScratch); + masm.branchWasmAnyRefIsNull(/*isNull=*/false, regScratch, &after5); + + masm.storePtr(regFuncRef, + Address(regMetrics, CallRefMetrics::offsetOfTarget(i))); + masm.store32(Imm32(1), + Address(regMetrics, CallRefMetrics::offsetOfCount(i))); + masm.jump(&ret); + + masm.bind(&after5); + } + + // Not found, and we don't have a slot with which to track this new target + // individually. Instead just increment the "all others" bin. + // regScratch = regMetrics->countOther; + // regScratch++; + // regMetrics->countOther = regScratch; + // return; + masm.load32(Address(regMetrics, CallRefMetrics::offsetOfCountOther()), + regScratch); + masm.add32(Imm32(1), regScratch); + masm.store32(regScratch, + Address(regMetrics, CallRefMetrics::offsetOfCountOther())); + + masm.bind(&ret); + + MOZ_ASSERT(masm.framePushed() == 0); + GenerateMinimalEpilogue(masm, &offsets->ret); + + return FinishOffsets(masm, offsets); +} + +bool wasm::GenerateEntryStubs(const CodeMetadata& codeMeta, + const FuncExportVector& exports, + CompiledCode* code) { + LifoAlloc lifo(STUBS_LIFO_DEFAULT_CHUNK_SIZE, js::MallocArena); + TempAllocator alloc(&lifo); + JitContext jcx; + WasmMacroAssembler masm(alloc); + AutoCreatedBy acb(masm, "wasm::GenerateEntryStubs"); + + // Swap in already-allocated empty vectors to avoid malloc/free. + if (!code->swap(masm)) { + return false; + } + + JitSpew(JitSpew_Codegen, "# Emitting wasm export stubs"); + + Maybe noAbsolute; + for (size_t i = 0; i < exports.length(); i++) { + const FuncExport& fe = exports[i]; + const FuncType& funcType = codeMeta.getFuncType(fe.funcIndex()); + if (!fe.hasEagerStubs()) { + continue; + } + if (!GenerateEntryStubs(masm, i, fe, funcType, noAbsolute, + codeMeta.isAsmJS(), &code->codeRanges)) { + return false; + } + } + + masm.finish(); + if (masm.oom()) { + return false; + } + + return code->swap(masm); +} + bool wasm::GenerateEntryStubs(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& fe, const FuncType& funcType, const Maybe& callee, bool isAsmJS, @@ -2989,13 +3287,13 @@ bool wasm::GenerateProvisionalLazyJitEntryStub(MacroAssembler& masm, return FinishOffsets(masm, offsets); } -bool wasm::GenerateStubs(const ModuleEnvironment& env, +bool wasm::GenerateStubs(const CodeMetadata& codeMeta, const FuncImportVector& imports, const FuncExportVector& exports, CompiledCode* code) { - LifoAlloc lifo(STUBS_LIFO_DEFAULT_CHUNK_SIZE); + LifoAlloc lifo(STUBS_LIFO_DEFAULT_CHUNK_SIZE, js::MallocArena); TempAllocator alloc(&lifo); JitContext jcx; - WasmMacroAssembler masm(alloc, env); + WasmMacroAssembler masm(alloc); AutoCreatedBy acb(masm, "wasm::GenerateStubs"); // Swap in already-allocated empty vectors to avoid malloc/free. @@ -3009,7 +3307,21 @@ bool wasm::GenerateStubs(const ModuleEnvironment& env, for (uint32_t funcIndex = 0; funcIndex < imports.length(); funcIndex++) { const FuncImport& fi = imports[funcIndex]; - const FuncType& funcType = *env.funcs[funcIndex].type; + const FuncType& funcType = codeMeta.getFuncType(funcIndex); + + CallIndirectId callIndirectId = + CallIndirectId::forFunc(codeMeta, funcIndex); + + FuncOffsets wrapperOffsets; + if (!GenerateImportFunction( + masm, codeMeta.offsetOfFuncImportInstanceData(funcIndex), funcType, + callIndirectId, &wrapperOffsets, &code->stackMaps)) { + return false; + } + if (!code->codeRanges.emplaceBack(funcIndex, wrapperOffsets, + /* hasUnwindInfo = */ false)) { + return false; + } CallableOffsets interpOffsets; if (!GenerateImportInterpExit(masm, fi, funcType, funcIndex, &throwLabel, @@ -3027,9 +3339,10 @@ bool wasm::GenerateStubs(const ModuleEnvironment& env, continue; } - CallableOffsets jitOffsets; - if (!GenerateImportJitExit(masm, fi, funcType, funcIndex, &throwLabel, - &jitOffsets)) { + ImportOffsets jitOffsets; + if (!GenerateImportJitExit( + masm, codeMeta.offsetOfFuncImportInstanceData(funcIndex), funcType, + funcIndex, interpOffsets.begin, &throwLabel, &jitOffsets)) { return false; } if (!code->codeRanges.emplaceBack(CodeRange::ImportJitExit, funcIndex, @@ -3038,22 +3351,22 @@ bool wasm::GenerateStubs(const ModuleEnvironment& env, } } - JitSpew(JitSpew_Codegen, "# Emitting wasm export stubs"); + JitSpew(JitSpew_Codegen, "# Emitting wasm entry stubs"); Maybe noAbsolute; for (size_t i = 0; i < exports.length(); i++) { const FuncExport& fe = exports[i]; - const FuncType& funcType = (*env.types)[fe.typeIndex()].funcType(); + const FuncType& funcType = codeMeta.getFuncType(fe.funcIndex()); if (!fe.hasEagerStubs()) { continue; } - if (!GenerateEntryStubs(masm, i, fe, funcType, noAbsolute, env.isAsmJS(), - &code->codeRanges)) { + if (!GenerateEntryStubs(masm, i, fe, funcType, noAbsolute, + codeMeta.isAsmJS(), &code->codeRanges)) { return false; } } - JitSpew(JitSpew_Codegen, "# Emitting wasm exit stubs"); + JitSpew(JitSpew_Codegen, "# Emitting wasm trap, debug and throw stubs"); Offsets offsets; @@ -3065,10 +3378,26 @@ bool wasm::GenerateStubs(const ModuleEnvironment& env, } CallableOffsets callableOffsets; - if (!GenerateDebugTrapStub(masm, &throwLabel, &callableOffsets)) { + if (!GenerateDebugStub(masm, &throwLabel, &callableOffsets)) { return false; } - if (!code->codeRanges.emplaceBack(CodeRange::DebugTrap, callableOffsets)) { + if (!code->codeRanges.emplaceBack(CodeRange::DebugStub, callableOffsets)) { + return false; + } + + if (!GenerateRequestTierUpStub(masm, &callableOffsets)) { + return false; + } + if (!code->codeRanges.emplaceBack(CodeRange::RequestTierUpStub, + callableOffsets)) { + return false; + } + + if (!GenerateUpdateCallRefMetricsStub(masm, &callableOffsets)) { + return false; + } + if (!code->codeRanges.emplaceBack(CodeRange::UpdateCallRefMetricsStub, + callableOffsets)) { return false; } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.h b/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.h index be0bbeb0ed8..25cc4718200 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmStubs.h @@ -26,10 +26,6 @@ namespace js { namespace wasm { -using jit::FloatRegister; -using jit::Register; -using jit::Register64; - // ValType and location for a single result: either in a register or on the // stack. @@ -37,9 +33,9 @@ class ABIResult { ValType type_; enum class Location { Gpr, Gpr64, Fpr, Stack } loc_; union { - Register gpr_; - Register64 gpr64_; - FloatRegister fpr_; + jit::Register gpr_; + jit::Register64 gpr64_; + jit::FloatRegister fpr_; uint32_t stackOffset_; }; @@ -95,15 +91,15 @@ class ABIResult { static constexpr size_t StackSizeOfV128 = sizeof(V128); #endif - ABIResult(ValType type, Register gpr) + ABIResult(ValType type, jit::Register gpr) : type_(type), loc_(Location::Gpr), gpr_(gpr) { validate(); } - ABIResult(ValType type, Register64 gpr64) + ABIResult(ValType type, jit::Register64 gpr64) : type_(type), loc_(Location::Gpr64), gpr64_(gpr64) { validate(); } - ABIResult(ValType type, FloatRegister fpr) + ABIResult(ValType type, jit::FloatRegister fpr) : type_(type), loc_(Location::Fpr), fpr_(fpr) { validate(); } @@ -115,15 +111,15 @@ class ABIResult { ValType type() const { return type_; } bool onStack() const { return loc_ == Location::Stack; } bool inRegister() const { return !onStack(); } - Register gpr() const { + jit::Register gpr() const { MOZ_ASSERT(loc_ == Location::Gpr); return gpr_; } - Register64 gpr64() const { + jit::Register64 gpr64() const { MOZ_ASSERT(loc_ == Location::Gpr64); return gpr64_; } - FloatRegister fpr() const { + jit::FloatRegister fpr() const { MOZ_ASSERT(loc_ == Location::Fpr); return fpr_; } @@ -251,19 +247,19 @@ extern bool GenerateBuiltinThunk(jit::MacroAssembler& masm, ExitReason exitReason, void* funcPtr, CallableOffsets* offsets); -extern bool GenerateImportFunctions(const ModuleEnvironment& env, - const FuncImportVector& imports, - CompiledCode* code); - -extern bool GenerateStubs(const ModuleEnvironment& env, +extern bool GenerateStubs(const CodeMetadata& codeMeta, const FuncImportVector& imports, const FuncExportVector& exports, CompiledCode* code); +extern bool GenerateEntryStubs(const CodeMetadata& codeMeta, + const FuncExportVector& exports, + CompiledCode* code); + extern bool GenerateEntryStubs(jit::MacroAssembler& masm, size_t funcExportIndex, const FuncExport& fe, const FuncType& funcType, - const Maybe& callee, bool isAsmJS, - CodeRangeVector* codeRanges); + const mozilla::Maybe& callee, + bool isAsmJS, CodeRangeVector* codeRanges); extern void GenerateTrapExitRegisterOffsets(jit::RegisterOffsets* offsets, size_t* numWords); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.cpp index 99834d67408..e8f9aec50f5 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.cpp @@ -6,6 +6,17 @@ #include "wasm/WasmSummarizeInsn.h" +// for Loongson extension detection +#if defined(JS_CODEGEN_MIPS64) +# include "jit/mips-shared/Architecture-mips-shared.h" +#endif + +#if defined(JS_CODEGEN_RISCV64) +# include "jit/riscv64/constant/Constant-riscv64.h" +#endif + +using namespace js::jit; + using mozilla::Maybe; using mozilla::Nothing; using mozilla::Some; @@ -1444,6 +1455,284 @@ Maybe SummarizeTrapInstruction(const uint8_t* insnAddr) { return Nothing(); } +// ================================================================ mips64 ==== + +# elif defined(JS_CODEGEN_MIPS64) + +Maybe SummarizeTrapInstruction(const uint8_t* insnAddr) { + // Check instruction alignment. + MOZ_ASSERT(0 == (uintptr_t(insnAddr) & 3)); + + const uint32_t insn = *(uint32_t*)insnAddr; + +# define INSN(_maxIx, _minIx) \ + ((insn >> (_minIx)) & ((uint32_t(1) << ((_maxIx) - (_minIx) + 1)) - 1)) + + // MIPS64R2 instruction encoding document: + // https://scc.ustc.edu.cn/_upload/article/files/c6/06/45556c084631b2855f0022175eaf/W020100308600769158777.pdf#G254.1001018 + + // Loongson GS464 extension: + // No official encoding document. Refer to binutils-gdb/opcodes/mips-opc.c and + // https://github.com/FlyGoat/loongson-insn/blob/master/loongson-ext.md + // instead. + + // MacroAssembler::wasmTrapInstruction uses this to create SIGILL. + // teq zero, zero, 0x6 + if (insn == 0x000001b4) { + return Some(TrapMachineInsn::OfficialUD); + } + + // MIPS64 Encoding of the Opcode Field of memory access instructions. + // +--------+--------------------------------------------------------+ + // | bits | 28..26 | + // +--------+------+------+------+-------+------+------+------+------+ + // | 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | + // +--------+------+------+------+-------+------+------+------+------+ + // | 010 | | | | COP1X | | | | | + // | 011 | | | LDL | LDR | | | | | + // | 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | + // | 101 | SB | SH | SWL | SW | SDL | SDR | SWR | | + // | 110 | LL | LWC1 | LWC2 | | LLD | LDC1 | LDC2 | LD | + // | 111 | SC | SWC1 | SWC2 | | SCD | SDC1 | SDC2 | SD | + // +--------+------+------+------+-------+------+------+------+------+ + // Loongson GS464 Encoding of the Opcode and Function Field of memory access + // extension instructions. + // +--------+-------------------------------------------------------+ + // | bits | 2..0 | + // +--------+-----+-----+-----+-----+-------+-------+-------+-------+ + // | 31..26 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | + // +--------+-----+-----+-----+-----+-------+-------+-------+-------+ + // | 110010 | | | | |GSLWLC1|GSLWRC1|GSLDLC1|GSLDRC1| + // | 111010 | | | | |GSSWLC1|GSSWRC1|GSSDLC1|GSSDRC1| + // | 110110 |GSLBX|GSLHX|GSLWX|GSLDX| | |GSLWXC1|GSLDXC1| + // | 111110 |GSLBX|GSLHX|GSLWX|GSLDX| | |GSSWXC1|GSSDXC1| + // +--------+-----+-----+-----+-----+-------+-------+-------+-------+ + if (INSN(31, 29) == 0b010) { + // MIPS64 COP1X Encoding of Function Field of memory access instructions. + // +--------+-----------------------------------------------------+ + // | bits | 2..0 | + // +--------+-------+-------+-----+-----+-----+-------+-----+-----+ + // | 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | + // +--------+-------+-------+-----+-----+-----+-------+-----+-----+ + // | 000 | LWXC1 | LDXC1 | | | | LUXC1 | | | + // | 001 | SWXC1 | SDXC1 | | | | SUXC1 | | | + // +--------+-------+-------+-----+-----+-----+-------+-----+-----+ + switch (INSN(5, 0)) { + // lwxc1 + case 0b000000: + return Some(TrapMachineInsn::Load32); + // ldxc1 + case 0b000001: + // luxc1 + case 0b000101: + return Some(TrapMachineInsn::Load64); + // swxc1 + case 0b001000: + return Some(TrapMachineInsn::Store32); + // sdxc1 + case 0b001001: + // suxc1 + case 0b001101: + return Some(TrapMachineInsn::Store64); + default: + break; + } + } else if (INSN(31, 29) == 0b011) { + switch (INSN(28, 26)) { + // ldl + case 0b010: + // ldr + case 0b011: + return Some(TrapMachineInsn::Load64); + default: + break; + } + } else if (INSN(31, 29) == 0b100) { + switch (INSN(28, 26)) { + // lb + case 0b000: + return Some(TrapMachineInsn::Load8); + // lh + case 0b001: + return Some(TrapMachineInsn::Load16); + // lwl + case 0b010: + // lw + case 0b011: + return Some(TrapMachineInsn::Load32); + // lbu + case 0b100: + return Some(TrapMachineInsn::Load8); + // lhu + case 0b101: + return Some(TrapMachineInsn::Load16); + // lwr + case 0b110: + // lwu + case 0b111: + return Some(TrapMachineInsn::Load32); + } + } else if (INSN(31, 29) == 0b101) { + switch (INSN(28, 26)) { + // sb + case 0b000: + return Some(TrapMachineInsn::Store8); + // sh + case 0b001: + return Some(TrapMachineInsn::Store16); + // swl + case 0b010: + // sw + case 0b011: + return Some(TrapMachineInsn::Store32); + // sdl + case 0b100: + // sdr + case 0b101: + return Some(TrapMachineInsn::Store64); + // swr + case 0b110: + return Some(TrapMachineInsn::Store32); + // cache + case 0b111: + break; + } + } else if (INSN(31, 29) == 0b110) { + switch (INSN(28, 26)) { + // ll + case 0b000: + // lwc1 + case 0b001: + return Some(TrapMachineInsn::Load32); + // lwc2 + case 0b010: + if (jit::isLoongson()) { + switch (INSN(2, 0)) { + // gslsl + case 0b100: + // gslsr + case 0b101: + return Some(TrapMachineInsn::Load32); + // gsldl + case 0b110: + // gsldr + case 0b111: + return Some(TrapMachineInsn::Load64); + // invalid + default: + return Nothing(); + } + } + return Some(TrapMachineInsn::Load32); + // pref + case 0b011: + break; + // lld + case 0b100: + // ldc1 + case 0b101: + return Some(TrapMachineInsn::Load64); + // ldc2 + case 0b110: + if (jit::isLoongson()) { + switch (INSN(2, 0)) { + // gslbx + case 0b000: + return Some(TrapMachineInsn::Load8); + // gslhx + case 0b001: + return Some(TrapMachineInsn::Load16); + // gslwx + case 0b010: + // gslwx (float) + case 0b110: + return Some(TrapMachineInsn::Load32); + // gsldx + case 0b011: + // gsldx (double) + case 0b111: + return Some(TrapMachineInsn::Load64); + // invalid + default: + return Nothing(); + } + } + return Some(TrapMachineInsn::Load64); + // ld + case 0b111: + return Some(TrapMachineInsn::Load64); + } + } else if (INSN(31, 29) == 0b111) { + switch (INSN(28, 26)) { + // sc + case 0b000: + // swc1 + case 0b001: + return Some(TrapMachineInsn::Store32); + // swc2 + case 0b010: + if (jit::isLoongson()) { + switch (INSN(2, 0)) { + // gsssl + case 0b100: + // gsssr + case 0b101: + return Some(TrapMachineInsn::Store32); + // gssdl + case 0b110: + // gssdr + case 0b111: + return Some(TrapMachineInsn::Store64); + // invalid + default: + return Nothing(); + } + } + return Some(TrapMachineInsn::Store32); + // reserved encoding + case 0b011: + break; + // scd + case 0b100: + // sdc1 + case 0b101: + return Some(TrapMachineInsn::Store64); + // sdc2 + case 0b110: + if (jit::isLoongson()) { + switch (INSN(2, 0)) { + // gssbx + case 0b000: + return Some(TrapMachineInsn::Store8); + // gsshx + case 0b001: + return Some(TrapMachineInsn::Store16); + // gsswx + case 0b010: + // gsswx (float) + case 0b110: + return Some(TrapMachineInsn::Store32); + // gssdx + case 0b011: + // gssdx (double) + case 0b111: + return Some(TrapMachineInsn::Store64); + // invalid + default: + return Nothing(); + } + } + return Some(TrapMachineInsn::Store64); + // sd + case 0b111: + return Some(TrapMachineInsn::Store64); + } + } + +# undef INSN + return Nothing(); +} + // ================================================================== none ==== # elif defined(JS_CODEGEN_NONE) diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.h b/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.h index 93a82437e1d..5df96a4f5c8 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmSummarizeInsn.h @@ -22,7 +22,7 @@ namespace wasm { // must be the correct classification for the instruction. Return // `mozilla::Nothing` in case of doubt. // -// This function is only used by ModuleGenerator::finishCodeTier to audit wasm +// This function is only used by ModuleGenerator::finishCodeBlock to audit wasm // trap sites. So it doesn't need to handle the whole complexity of the // machine's instruction set. It only needs to handle the tiny sub-dialect // used by the trappable instructions we actually generate. diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmTable.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmTable.cpp index b1b228293bc..c8798031698 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmTable.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmTable.cpp @@ -19,7 +19,6 @@ #include "wasm/WasmTable.h" #include "mozilla/CheckedInt.h" -#include "mozilla/PodOperations.h" #include "vm/JSContext.h" #include "vm/Realm.h" @@ -33,21 +32,22 @@ using namespace js; using namespace js::wasm; using mozilla::CheckedInt; -using mozilla::PodZero; Table::Table(JSContext* cx, const TableDesc& desc, Handle maybeObject, FuncRefVector&& functions) : maybeObject_(maybeObject), observers_(cx->zone()), functions_(std::move(functions)), + addressType_(desc.addressType()), elemType_(desc.elemType), isAsmJS_(desc.isAsmJS), - length_(desc.initialLength), - maximum_(desc.maximumLength) { + length_(desc.initialLength()), + maximum_(desc.maximumLength()) { // Acquire a strong reference to the type definition this table may be // referencing. elemType_.AddRef(); MOZ_ASSERT(repr() == TableRepr::Func); + MOZ_ASSERT(length_ <= MaxTableElemsRuntime); } Table::Table(JSContext* cx, const TableDesc& desc, @@ -55,14 +55,16 @@ Table::Table(JSContext* cx, const TableDesc& desc, : maybeObject_(maybeObject), observers_(cx->zone()), objects_(std::move(objects)), + addressType_(desc.addressType()), elemType_(desc.elemType), isAsmJS_(desc.isAsmJS), - length_(desc.initialLength), - maximum_(desc.maximumLength) { + length_(desc.initialLength()), + maximum_(desc.maximumLength()) { // Acquire a strong reference to the type definition this table may be // referencing. elemType_.AddRef(); MOZ_ASSERT(repr() == TableRepr::Ref); + MOZ_ASSERT(length_ <= MaxTableElemsRuntime); } Table::~Table() { @@ -79,7 +81,7 @@ SharedTable Table::create(JSContext* cx, const TableDesc& desc, switch (desc.elemType.tableRepr()) { case TableRepr::Func: { FuncRefVector functions; - if (!functions.resize(desc.initialLength)) { + if (!functions.resize(desc.initialLength())) { ReportOutOfMemory(cx); return nullptr; } @@ -88,7 +90,7 @@ SharedTable Table::create(JSContext* cx, const TableDesc& desc, } case TableRepr::Ref: { TableAnyRefVector objects; - if (!objects.resize(desc.initialLength)) { + if (!objects.resize(desc.initialLength())) { ReportOutOfMemory(cx); return nullptr; } @@ -154,16 +156,16 @@ uint8_t* Table::instanceElements() const { return (uint8_t*)functions_.begin(); } -const FunctionTableElem& Table::getFuncRef(uint32_t index) const { +const FunctionTableElem& Table::getFuncRef(uint32_t address) const { MOZ_ASSERT(isFunction()); - return functions_[index]; + return functions_[address]; } -bool Table::getFuncRef(JSContext* cx, uint32_t index, +bool Table::getFuncRef(JSContext* cx, uint32_t address, MutableHandleFunction fun) const { MOZ_ASSERT(isFunction()); - const FunctionTableElem& elem = getFuncRef(index); + const FunctionTableElem& elem = getFuncRef(address); if (!elem.code) { fun.set(nullptr); return true; @@ -171,13 +173,10 @@ bool Table::getFuncRef(JSContext* cx, uint32_t index, Instance& instance = *elem.instance; const CodeRange& codeRange = *instance.code().lookupFuncRange(elem.code); - - Rooted instanceObj(cx, instance.object()); - return instanceObj->getExportedFunction(cx, instanceObj, - codeRange.funcIndex(), fun); + return instance.getExportedFunction(cx, codeRange.funcIndex(), fun); } -void Table::setFuncRef(uint32_t index, JSFunction* fun) { +void Table::setFuncRef(uint32_t address, JSFunction* fun) { MOZ_ASSERT(isFunction()); MOZ_ASSERT(fun->isWasm()); @@ -186,19 +185,13 @@ void Table::setFuncRef(uint32_t index, JSFunction* fun) { // must set the element to the function's underlying // CodeRange.funcCheckedCallEntry and Instance so that Table.get()s always // produce the same function object as was imported. - WasmInstanceObject* instanceObj = ExportedFunctionToInstanceObject(fun); - Instance& instance = instanceObj->instance(); - Tier tier = instance.code().bestTier(); - const CodeRange& calleeCodeRange = - instanceObj->getExportedFunctionCodeRange(fun, tier); - void* code = instance.codeBase(tier) + calleeCodeRange.funcCheckedCallEntry(); - setFuncRef(index, code, &instance); + setFuncRef(address, fun->wasmCheckedCallEntry(), &fun->wasmInstance()); } -void Table::setFuncRef(uint32_t index, void* code, Instance* instance) { +void Table::setFuncRef(uint32_t address, void* code, Instance* instance) { MOZ_ASSERT(isFunction()); - FunctionTableElem& elem = functions_[index]; + FunctionTableElem& elem = functions_[address]; if (elem.instance) { gc::PreWriteBarrier(elem.instance->objectUnbarriered()); } @@ -214,76 +207,60 @@ void Table::setFuncRef(uint32_t index, void* code, Instance* instance) { } } -void Table::fillFuncRef(uint32_t index, uint32_t fillCount, FuncRef ref, +void Table::fillFuncRef(uint32_t address, uint32_t fillCount, FuncRef ref, JSContext* cx) { MOZ_ASSERT(isFunction()); if (ref.isNull()) { - for (uint32_t i = index, end = index + fillCount; i != end; i++) { + for (uint32_t i = address, end = address + fillCount; i != end; i++) { setNull(i); } return; } RootedFunction fun(cx, ref.asJSFunction()); - MOZ_RELEASE_ASSERT(IsWasmExportedFunction(fun)); - - Rooted instanceObj( - cx, ExportedFunctionToInstanceObject(fun)); - uint32_t funcIndex = ExportedFunctionToFuncIndex(fun); - -#ifdef DEBUG - RootedFunction f(cx); - MOZ_ASSERT(instanceObj->getExportedFunction(cx, instanceObj, funcIndex, &f)); - MOZ_ASSERT(fun == f); -#endif - - Instance& instance = instanceObj->instance(); - Tier tier = instance.code().bestTier(); - const MetadataTier& metadata = instance.metadata(tier); - const CodeRange& codeRange = - metadata.codeRange(metadata.lookupFuncExport(funcIndex)); - void* code = instance.codeBase(tier) + codeRange.funcCheckedCallEntry(); - for (uint32_t i = index, end = index + fillCount; i != end; i++) { + void* code = fun->wasmCheckedCallEntry(); + Instance& instance = fun->wasmInstance(); + for (uint32_t i = address, end = address + fillCount; i != end; i++) { setFuncRef(i, code, &instance); } } -AnyRef Table::getAnyRef(uint32_t index) const { +AnyRef Table::getAnyRef(uint32_t address) const { MOZ_ASSERT(!isFunction()); - return objects_[index]; + return objects_[address]; } -void Table::setAnyRef(uint32_t index, AnyRef ref) { +void Table::setAnyRef(uint32_t address, AnyRef ref) { MOZ_ASSERT(!isFunction()); - objects_[index] = ref; + objects_[address] = ref; } -void Table::fillAnyRef(uint32_t index, uint32_t fillCount, AnyRef ref) { +void Table::fillAnyRef(uint32_t address, uint32_t fillCount, AnyRef ref) { MOZ_ASSERT(!isFunction()); - for (uint32_t i = index, end = index + fillCount; i != end; i++) { + for (uint32_t i = address, end = address + fillCount; i != end; i++) { objects_[i] = ref; } } -void Table::setRef(uint32_t index, AnyRef ref) { +void Table::setRef(uint32_t address, AnyRef ref) { if (ref.isNull()) { - setNull(index); + setNull(address); } else if (isFunction()) { JSFunction* func = &ref.toJSObject().as(); - setFuncRef(index, func); + setFuncRef(address, func); } else { - setAnyRef(index, ref); + setAnyRef(address, ref); } } -bool Table::getValue(JSContext* cx, uint32_t index, +bool Table::getValue(JSContext* cx, uint32_t address, MutableHandleValue result) const { switch (repr()) { case TableRepr::Func: { MOZ_RELEASE_ASSERT(!isAsmJS()); RootedFunction fun(cx); - if (!getFuncRef(cx, index, &fun)) { + if (!getFuncRef(cx, address, &fun)) { return false; } result.setObjectOrNull(fun); @@ -295,18 +272,18 @@ bool Table::getValue(JSContext* cx, uint32_t index, JSMSG_WASM_BAD_VAL_TYPE); return false; } - return ToJSValue(cx, &objects_[index], ValType(elemType_), result); + return ToJSValue(cx, &objects_[address], ValType(elemType_), result); } default: MOZ_CRASH(); } } -void Table::setNull(uint32_t index) { +void Table::setNull(uint32_t address) { switch (repr()) { case TableRepr::Func: { MOZ_RELEASE_ASSERT(!isAsmJS_); - FunctionTableElem& elem = functions_[index]; + FunctionTableElem& elem = functions_[address]; if (elem.instance) { gc::PreWriteBarrier(elem.instance->objectUnbarriered()); } @@ -316,7 +293,7 @@ void Table::setNull(uint32_t index) { break; } case TableRepr::Ref: { - setAnyRef(index, AnyRef::null()); + setAnyRef(address, AnyRef::null()); break; } } @@ -382,7 +359,7 @@ uint32_t Table::grow(uint32_t delta) { CheckedInt newLength = oldLength; newLength += delta; - if (!newLength.isValid() || newLength.value() > MaxTableLength) { + if (!newLength.isValid() || newLength.value() > MaxTableElemsRuntime) { return -1; } @@ -443,51 +420,51 @@ bool Table::addMovingGrowObserver(JSContext* cx, WasmInstanceObject* instance) { return true; } -void Table::fillUninitialized(uint32_t index, uint32_t fillCount, +void Table::fillUninitialized(uint32_t address, uint32_t fillCount, HandleAnyRef ref, JSContext* cx) { #ifdef DEBUG - assertRangeNull(index, fillCount); + assertRangeNull(address, fillCount); #endif // DEBUG switch (repr()) { case TableRepr::Func: { MOZ_RELEASE_ASSERT(!isAsmJS_); - fillFuncRef(index, fillCount, FuncRef::fromAnyRefUnchecked(ref), cx); + fillFuncRef(address, fillCount, FuncRef::fromAnyRefUnchecked(ref), cx); break; } case TableRepr::Ref: { - fillAnyRef(index, fillCount, ref); + fillAnyRef(address, fillCount, ref); break; } } } #ifdef DEBUG -void Table::assertRangeNull(uint32_t index, uint32_t length) const { +void Table::assertRangeNull(uint32_t address, uint32_t length) const { switch (repr()) { case TableRepr::Func: - for (uint32_t i = index; i < index + length; i++) { + for (uint32_t i = address; i < address + length; i++) { MOZ_ASSERT(getFuncRef(i).instance == nullptr); MOZ_ASSERT(getFuncRef(i).code == nullptr); } break; case TableRepr::Ref: - for (uint32_t i = index; i < index + length; i++) { + for (uint32_t i = address; i < address + length; i++) { MOZ_ASSERT(getAnyRef(i).isNull()); } break; } } -void Table::assertRangeNotNull(uint32_t index, uint32_t length) const { +void Table::assertRangeNotNull(uint32_t address, uint32_t length) const { switch (repr()) { case TableRepr::Func: - for (uint32_t i = index; i < index + length; i++) { + for (uint32_t i = address; i < address + length; i++) { MOZ_ASSERT_IF(!isAsmJS_, getFuncRef(i).instance != nullptr); MOZ_ASSERT(getFuncRef(i).code != nullptr); } break; case TableRepr::Ref: - for (uint32_t i = index; i < index + length; i++) { + for (uint32_t i = address; i < address + length; i++) { MOZ_ASSERT(!getAnyRef(i).isNull()); } break; @@ -495,7 +472,7 @@ void Table::assertRangeNotNull(uint32_t index, uint32_t length) const { } #endif // DEBUG -size_t Table::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { +size_t Table::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { if (isFunction()) { return functions_.sizeOfExcludingThis(mallocSizeOf); } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmTable.h b/src/third_party/mozjs/extract/js/src/wasm/WasmTable.h index f8f59644bbe..7b55af695c9 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmTable.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmTable.h @@ -46,10 +46,11 @@ class Table : public ShareableBase
{ InstanceSet observers_; FuncRefVector functions_; // either functions_ has data TableAnyRefVector objects_; // or objects_, but not both + const AddressType addressType_; const RefType elemType_; const bool isAsmJS_; uint32_t length_; - const Maybe maximum_; + const mozilla::Maybe maximum_; template friend struct js::MallocProvider; @@ -67,6 +68,7 @@ class Table : public ShareableBase
{ ~Table(); void trace(JSTracer* trc); + AddressType addressType() const { return addressType_; } RefType elemType() const { return elemType_; } TableRepr repr() const { return elemType_.tableRepr(); } @@ -77,7 +79,7 @@ class Table : public ShareableBase
{ bool isFunction() const { return elemType().isFuncHierarchy(); } uint32_t length() const { return length_; } - Maybe maximum() const { return maximum_; } + mozilla::Maybe maximum() const { return maximum_; } // Raw pointer to the table for use in TableInstanceData. uint8_t* instanceElements() const; @@ -86,27 +88,27 @@ class Table : public ShareableBase
{ // get/fillAnyRef is allowed only on table-of-anyref. // setNull is allowed on either. - const FunctionTableElem& getFuncRef(uint32_t index) const; - [[nodiscard]] bool getFuncRef(JSContext* cx, uint32_t index, + const FunctionTableElem& getFuncRef(uint32_t address) const; + [[nodiscard]] bool getFuncRef(JSContext* cx, uint32_t address, MutableHandleFunction fun) const; - void setFuncRef(uint32_t index, JSFunction* func); - void setFuncRef(uint32_t index, void* code, Instance* instance); - void fillFuncRef(uint32_t index, uint32_t fillCount, FuncRef ref, + void setFuncRef(uint32_t address, JSFunction* func); + void setFuncRef(uint32_t address, void* code, Instance* instance); + void fillFuncRef(uint32_t address, uint32_t fillCount, FuncRef ref, JSContext* cx); - AnyRef getAnyRef(uint32_t index) const; - void setAnyRef(uint32_t index, AnyRef ref); - void fillAnyRef(uint32_t index, uint32_t fillCount, AnyRef ref); + AnyRef getAnyRef(uint32_t address) const; + void setAnyRef(uint32_t address, AnyRef ref); + void fillAnyRef(uint32_t address, uint32_t fillCount, AnyRef ref); // Sets ref automatically using the correct setter depending on the ref and // table type (setNull, setFuncRef, or setAnyRef) - void setRef(uint32_t index, AnyRef ref); + void setRef(uint32_t address, AnyRef ref); - // Get the element at index and convert it to a JS value. - [[nodiscard]] bool getValue(JSContext* cx, uint32_t index, + // Get the element at address and convert it to a JS value. + [[nodiscard]] bool getValue(JSContext* cx, uint32_t address, MutableHandleValue result) const; - void setNull(uint32_t index); + void setNull(uint32_t address); // Copy entry from |srcTable| at |srcIndex| to this table at |dstIndex|. Used // by table.copy. May OOM if it needs to box up a function during an upcast. @@ -119,16 +121,16 @@ class Table : public ShareableBase
{ [[nodiscard]] bool addMovingGrowObserver(JSContext* cx, WasmInstanceObject* instance); - void fillUninitialized(uint32_t index, uint32_t fillCount, HandleAnyRef ref, + void fillUninitialized(uint32_t address, uint32_t fillCount, HandleAnyRef ref, JSContext* cx); #ifdef DEBUG - void assertRangeNull(uint32_t index, uint32_t length) const; - void assertRangeNotNull(uint32_t index, uint32_t length) const; + void assertRangeNull(uint32_t address, uint32_t length) const; + void assertRangeNotNull(uint32_t address, uint32_t length) const; #endif // DEBUG // about:memory reporting: - size_t sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const; + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; size_t gcMallocBytes() const; }; diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDecls.h b/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDecls.h index 1908f3dfeb7..70550b94d1e 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDecls.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDecls.h @@ -48,14 +48,14 @@ using WasmGlobalObjectVector = GCVector; using WasmTagObjectVector = GCVector; +struct CodeMetadataForAsmJS; + namespace wasm { -struct ModuleEnvironment; +struct ModuleMetadata; +struct CodeMetadata; class CodeRange; -class CodeTier; -class ModuleSegment; -struct Metadata; -struct MetadataTier; +class CodeBlock; class Decoder; class GeneratedSourceMap; class Instance; @@ -93,6 +93,19 @@ using UTF8Bytes = Vector; using InstanceVector = Vector; using UniqueCharsVector = Vector; +class RecGroup; +class TypeDef; +class TypeContext; +enum class TypeDefKind : uint8_t; + +template +class PackedType; + +class ValTypeTraits; +using ValType = PackedType; +class RefType; +class MaybeRefType; + } // namespace wasm } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.cpp index e0943d0f81a..04f6ebbe212 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.cpp @@ -36,8 +36,10 @@ using namespace js; using namespace js::jit; using namespace js::wasm; +using mozilla::CheckedInt32; using mozilla::CheckedUint32; using mozilla::IsPowerOfTwo; +using mozilla::MallocSizeOf; // [SMDOC] Immediate type signature encoding // @@ -218,8 +220,7 @@ static ImmediateType EncodeImmediateFuncType(const FuncType& funcType) { //========================================================================= // FuncType -void FuncType::initImmediateTypeId(bool gcEnabled, bool isFinal, - const TypeDef* superTypeDef, +void FuncType::initImmediateTypeId(bool isFinal, const TypeDef* superTypeDef, uint32_t recGroupLength) { // To improve the performance of the structural type check in // the call_indirect function prologue, we attempt to encode the @@ -235,7 +236,7 @@ void FuncType::initImmediateTypeId(bool gcEnabled, bool isFinal, // same reason applies. And finally, types in recursion groups of // size > 1 may not be considered equivalent even if they are // structurally equivalent in every respect. - if (gcEnabled && (!isFinal || superTypeDef || recGroupLength != 1)) { + if (!isFinal || superTypeDef || recGroupLength != 1) { immediateTypeId_ = NO_IMMEDIATE_TYPE_ID; return; } @@ -329,15 +330,26 @@ CheckedInt32 StructLayout::close() { } bool StructType::init() { + bool isDefaultable = true; + StructLayout layout; for (FieldType& field : fields_) { CheckedInt32 offset = layout.addField(field.type); if (!offset.isValid()) { return false; } + + // Add the offset to the list if (!fieldOffsets_.append(offset.value())) { return false; } + + // If any field is not defaultable, this whole struct is not defaultable + if (!field.type.isDefaultable()) { + isDefaultable = false; + } + + // If this field is not a ref, then don't add it to the trace lists if (!field.type.isRefRepr()) { continue; } @@ -361,8 +373,9 @@ bool StructType::init() { if (!size.isValid()) { return false; } - size_ = size.value(); + size_ = size.value(); + isDefaultable_ = isDefaultable; return true; } @@ -510,7 +523,7 @@ struct RecGroupHashPolicy { static HashNumber hash(Lookup lookup) { return lookup->hash(); } static bool match(const SharedRecGroup& lhs, Lookup rhs) { - return RecGroup::matches(*rhs, *lhs); + return RecGroup::isoEquals(*rhs, *lhs); } }; @@ -568,7 +581,7 @@ class TypeIdSet { } }; -ExclusiveData typeIdSet(mutexid::WasmTypeIdSet); +MOZ_RUNINIT ExclusiveData typeIdSet(mutexid::WasmTypeIdSet); void wasm::PurgeCanonicalTypes() { ExclusiveData::Guard locked = typeIdSet.lock(); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.h b/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.h index 12472ab1767..7dcf77de621 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmTypeDef.h @@ -35,9 +35,6 @@ namespace js { namespace wasm { -using mozilla::CheckedInt32; -using mozilla::MallocSizeOf; - class RecGroup; //========================================================================= @@ -113,7 +110,10 @@ class FuncType { public: FuncType() = default; FuncType(ValTypeVector&& args, ValTypeVector&& results) - : args_(std::move(args)), results_(std::move(results)) {} + : args_(std::move(args)), results_(std::move(results)) { + MOZ_ASSERT(args_.length() <= MaxParams); + MOZ_ASSERT(results_.length() <= MaxResults); + } FuncType(FuncType&&) = default; FuncType& operator=(FuncType&&) = default; @@ -130,8 +130,7 @@ class FuncType { ValType result(unsigned i) const { return results_[i]; } const ValTypeVector& results() const { return results_; } - void initImmediateTypeId(bool gcEnabled, bool isFinal, - const TypeDef* superTypeDef, + void initImmediateTypeId(bool isFinal, const TypeDef* superTypeDef, uint32_t recGroupLength); bool hasImmediateTypeId() const { return immediateTypeId_ != NO_IMMEDIATE_TYPE_ID; @@ -148,31 +147,31 @@ class FuncType { HashNumber hash(const RecGroup* recGroup) const { HashNumber hn = 0; for (const ValType& vt : args_) { - hn = mozilla::AddToHash(hn, vt.forMatch(recGroup).hash()); + hn = mozilla::AddToHash(hn, vt.forIsoEquals(recGroup).hash()); } for (const ValType& vt : results_) { - hn = mozilla::AddToHash(hn, vt.forMatch(recGroup).hash()); + hn = mozilla::AddToHash(hn, vt.forIsoEquals(recGroup).hash()); } return hn; } - // Matches two function types for isorecursive equality. See - // "Matching type definitions" in WasmValType.h for more background. - static bool matches(const RecGroup* lhsRecGroup, const FuncType& lhs, - const RecGroup* rhsRecGroup, const FuncType& rhs) { + // Compares two function types for isorecursive equality. See + // "Comparing type definitions" in WasmValType.h for more background. + static bool isoEquals(const RecGroup* lhsRecGroup, const FuncType& lhs, + const RecGroup* rhsRecGroup, const FuncType& rhs) { if (lhs.args_.length() != rhs.args_.length() || lhs.results_.length() != rhs.results_.length()) { return false; } for (uint32_t i = 0; i < lhs.args_.length(); i++) { - if (lhs.args_[i].forMatch(lhsRecGroup) != - rhs.args_[i].forMatch(rhsRecGroup)) { + if (lhs.args_[i].forIsoEquals(lhsRecGroup) != + rhs.args_[i].forIsoEquals(rhsRecGroup)) { return false; } } for (uint32_t i = 0; i < lhs.results_.length(); i++) { - if (lhs.results_[i].forMatch(lhsRecGroup) != - rhs.results_[i].forMatch(rhsRecGroup)) { + if (lhs.results_[i].forIsoEquals(lhsRecGroup) != + rhs.results_[i].forIsoEquals(rhsRecGroup)) { return false; } } @@ -253,7 +252,7 @@ class FuncType { // The Module owns a dense array of StructType values that represent the // structure types that the module knows about. It is created from the sparse -// array of types in the ModuleEnvironment when the Module is created. +// array of types in the ModuleMetadata when the Module is created. struct FieldType { StorageType type; @@ -265,17 +264,18 @@ struct FieldType { HashNumber hash(const RecGroup* recGroup) const { HashNumber hn = 0; - hn = mozilla::AddToHash(hn, type.forMatch(recGroup).hash()); + hn = mozilla::AddToHash(hn, type.forIsoEquals(recGroup).hash()); hn = mozilla::AddToHash(hn, HashNumber(isMutable)); return hn; } - // Matches two field types for isorecursive equality. See - // "Matching type definitions" in WasmValType.h for more background. - static bool matches(const RecGroup* lhsRecGroup, const FieldType& lhs, - const RecGroup* rhsRecGroup, const FieldType& rhs) { + // Compares two field types for isorecursive equality. See + // "Comparing type definitions" in WasmValType.h for more background. + static bool isoEquals(const RecGroup* lhsRecGroup, const FieldType& lhs, + const RecGroup* rhsRecGroup, const FieldType& rhs) { return lhs.isMutable == rhs.isMutable && - lhs.type.forMatch(lhsRecGroup) == rhs.type.forMatch(rhsRecGroup); + lhs.type.forIsoEquals(lhsRecGroup) == + rhs.type.forIsoEquals(rhsRecGroup); } // Checks if two struct fields are compatible in a given subtyping @@ -304,32 +304,35 @@ using OutlineTraceOffsetVector = Vector; class StructType { public: - FieldTypeVector fields_; // Field type and mutability - - uint32_t size_; // The size of the type in bytes. + // Vector of the fields in this struct + FieldTypeVector fields_; + // The total size of this struct in bytes + uint32_t size_; + // The offset for every struct field FieldOffsetVector fieldOffsets_; + // The offsets of fields that must be traced in the inline portion of wasm + // struct object. InlineTraceOffsetVector inlineTraceOffsets_; + // The offsets of fields that must be traced in the outline portion of wasm + // struct object. OutlineTraceOffsetVector outlineTraceOffsets_; + // Whether this struct only contains defaultable fields. + bool isDefaultable_; public: - StructType() : size_(0) {} + StructType() : size_(0), isDefaultable_(false) {} explicit StructType(FieldTypeVector&& fields) - : fields_(std::move(fields)), size_(0) {} + : fields_(std::move(fields)), size_(0) { + MOZ_ASSERT(fields_.length() <= MaxStructFields); + } StructType(StructType&&) = default; StructType& operator=(StructType&&) = default; [[nodiscard]] bool init(); - bool isDefaultable() const { - for (auto& field : fields_) { - if (!field.type.isDefaultable()) { - return false; - } - } - return true; - } + bool isDefaultable() const { return isDefaultable_; } uint32_t fieldOffset(uint32_t fieldIndex) const { return fieldOffsets_[fieldIndex]; @@ -343,17 +346,17 @@ class StructType { return hn; } - // Matches two struct types for isorecursive equality. See - // "Matching type definitions" in WasmValType.h for more background. - static bool matches(const RecGroup* lhsRecGroup, const StructType& lhs, - const RecGroup* rhsRecGroup, const StructType& rhs) { + // Compares two struct types for isorecursive equality. See + // "Comparing type definitions" in WasmValType.h for more background. + static bool isoEquals(const RecGroup* lhsRecGroup, const StructType& lhs, + const RecGroup* rhsRecGroup, const StructType& rhs) { if (lhs.fields_.length() != rhs.fields_.length()) { return false; } for (uint32_t i = 0; i < lhs.fields_.length(); i++) { const FieldType& lhsField = lhs.fields_[i]; const FieldType& rhsField = rhs.fields_[i]; - if (!FieldType::matches(lhsRecGroup, lhsField, rhsRecGroup, rhsField)) { + if (!FieldType::isoEquals(lhsRecGroup, lhsField, rhsRecGroup, rhsField)) { return false; } } @@ -404,16 +407,16 @@ using StructTypeVector = Vector; // Given that, it follows from (3) that all fields fall completely within // either the inline or outline areas; no field crosses the boundary. class StructLayout { - CheckedInt32 sizeSoFar = 0; + mozilla::CheckedInt32 sizeSoFar = 0; uint32_t structAlignment = 1; public: // The field adders return the offset of the the field. - CheckedInt32 addField(StorageType type); + mozilla::CheckedInt32 addField(StorageType type); // The close method rounds up the structure size to the appropriate // alignment and returns that size. - CheckedInt32 close(); + mozilla::CheckedInt32 close(); }; //========================================================================= @@ -443,12 +446,12 @@ class ArrayType { return fieldType_.hash(recGroup); } - // Matches two array types for isorecursive equality. See - // "Matching type definitions" in WasmValType.h for more background. - static bool matches(const RecGroup* lhsRecGroup, const ArrayType& lhs, - const RecGroup* rhsRecGroup, const ArrayType& rhs) { - return FieldType::matches(lhsRecGroup, lhs.fieldType_, rhsRecGroup, - rhs.fieldType_); + // Compares two array types for isorecursive equality. See + // "Comparing type definitions" in WasmValType.h for more background. + static bool isoEquals(const RecGroup* lhsRecGroup, const ArrayType& lhs, + const RecGroup* rhsRecGroup, const ArrayType& rhs) { + return FieldType::isoEquals(lhsRecGroup, lhs.fieldType_, rhsRecGroup, + rhs.fieldType_); } // Checks if two arrays are compatible in a given subtyping relationship. @@ -702,6 +705,8 @@ class TypeDef { bool isArrayType() const { return kind_ == TypeDefKind::Array; } + bool isGcType() const { return isStructType() || isArrayType(); } + const FuncType& funcType() const { MOZ_ASSERT(isFuncType()); return funcType_; @@ -732,14 +737,15 @@ class TypeDef { return arrayType_; } - // Get a value that can be used for matching type definitions across + // Get a value that can be used for comparing type definitions across // different recursion groups. - static inline uintptr_t forMatch(const TypeDef* typeDef, - const RecGroup* recGroup); + static inline uintptr_t forIsoEquals(const TypeDef* typeDef, + const RecGroup* recGroup); HashNumber hash() const { HashNumber hn = HashNumber(kind_); - hn = mozilla::AddToHash(hn, TypeDef::forMatch(superTypeDef_, &recGroup())); + hn = mozilla::AddToHash(hn, + TypeDef::forIsoEquals(superTypeDef_, &recGroup())); hn = mozilla::AddToHash(hn, isFinal_); switch (kind_) { case TypeDefKind::Func: @@ -757,29 +763,29 @@ class TypeDef { return hn; } - // Matches two type definitions for isorecursive equality. See - // "Matching type definitions" in WasmValType.h for more background. - static bool matches(const TypeDef& lhs, const TypeDef& rhs) { + // Compares two type definitions for isorecursive equality. See + // "Comparing type definitions" in WasmValType.h for more background. + static bool isoEquals(const TypeDef& lhs, const TypeDef& rhs) { if (lhs.kind_ != rhs.kind_) { return false; } if (lhs.isFinal_ != rhs.isFinal_) { return false; } - if (TypeDef::forMatch(lhs.superTypeDef_, &lhs.recGroup()) != - TypeDef::forMatch(rhs.superTypeDef_, &rhs.recGroup())) { + if (TypeDef::forIsoEquals(lhs.superTypeDef_, &lhs.recGroup()) != + TypeDef::forIsoEquals(rhs.superTypeDef_, &rhs.recGroup())) { return false; } switch (lhs.kind_) { case TypeDefKind::Func: - return FuncType::matches(&lhs.recGroup(), lhs.funcType_, - &rhs.recGroup(), rhs.funcType_); + return FuncType::isoEquals(&lhs.recGroup(), lhs.funcType_, + &rhs.recGroup(), rhs.funcType_); case TypeDefKind::Struct: - return StructType::matches(&lhs.recGroup(), lhs.structType_, - &rhs.recGroup(), rhs.structType_); + return StructType::isoEquals(&lhs.recGroup(), lhs.structType_, + &rhs.recGroup(), rhs.structType_); case TypeDefKind::Array: - return ArrayType::matches(&lhs.recGroup(), lhs.arrayType_, - &rhs.recGroup(), rhs.arrayType_); + return ArrayType::isoEquals(&lhs.recGroup(), lhs.arrayType_, + &rhs.recGroup(), rhs.arrayType_); case TypeDefKind::None: MOZ_CRASH("can't match TypeDefKind::None"); } @@ -831,7 +837,7 @@ class TypeDef { const SuperTypeVector* subSTV = subTypeDef->superTypeVector(); const SuperTypeVector* superSTV = superTypeDef->superTypeVector(); - // During construction of a recursion group, the super type vector may not + // During construction of a recursion group, the super type vectors may not // have been computed yet, in which case we need to fall back to a linear // search. if (!subSTV || !superSTV) { @@ -844,8 +850,12 @@ class TypeDef { return false; } - // The supertype vector does exist. So check it points back here. + // The supertype vectors do exist. Check that they point to the right + // places. + MOZ_ASSERT(subSTV); + MOZ_ASSERT(superSTV); MOZ_ASSERT(subSTV->typeDef() == subTypeDef); + MOZ_ASSERT(superSTV->typeDef() == superTypeDef); // We need to check if `superTypeDef` is one of `subTypeDef`s super types // by checking in `subTypeDef`s super type vector. We can use the static @@ -856,14 +866,14 @@ class TypeDef { return false; } - MOZ_ASSERT(superSTV); - MOZ_ASSERT(superSTV->typeDef() == superTypeDef); - return subSTV->type(subTypingDepth) == superSTV; } size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; WASM_DECLARE_FRIEND_SERIALIZE(TypeDef); + + inline void AddRef() const; + inline void Release() const; }; using SharedTypeDef = RefPtr; @@ -916,6 +926,10 @@ class RecGroup : public AtomicRefCounted { // Compute the size in bytes of a recursion group with the specified amount // of types. static constexpr size_t sizeOfRecGroup(uint32_t numTypes) { + // TypeDef can find containing RecGroup using only a 32-bit offset + static_assert(offsetof(RecGroup, types_) + sizeof(TypeDef) * MaxTypes <= + UINT32_MAX); + // We will not overflow in our calculation here static_assert(MaxTypes <= SIZE_MAX / sizeof(TypeDef)); return sizeof(RecGroup) + sizeof(TypeDef) * numTypes; } @@ -925,6 +939,9 @@ class RecGroup : public AtomicRefCounted { // type definitions are initialized so that strong references to external // recursion groups are taken. static RefPtr allocate(uint32_t numTypes) { + // Validation must ensure this + MOZ_RELEASE_ASSERT(numTypes <= MaxTypes); + // Allocate the recursion group with the correct size RecGroup* recGroup = (RecGroup*)js_malloc(sizeOfRecGroup(numTypes)); if (!recGroup) { @@ -981,6 +998,8 @@ class RecGroup : public AtomicRefCounted { switch (typeDef.kind()) { case TypeDefKind::Func: { const FuncType& funcType = typeDef.funcType(); + MOZ_RELEASE_ASSERT(funcType.args().length() <= MaxParams); + MOZ_RELEASE_ASSERT(funcType.results().length() <= MaxResults); for (auto type : funcType.args()) { visitValType(type); } @@ -991,6 +1010,7 @@ class RecGroup : public AtomicRefCounted { } case TypeDefKind::Struct: { const StructType& structType = typeDef.structType(); + MOZ_RELEASE_ASSERT(structType.fields_.length() <= MaxStructFields); for (const auto& field : structType.fields_) { visitStorageType(field.type); } @@ -1054,6 +1074,16 @@ class RecGroup : public AtomicRefCounted { return (uint32_t)groupTypeIndex; } + bool hasGcType() const { + for (uint32_t groupTypeIndex = 0; groupTypeIndex < numTypes(); + groupTypeIndex++) { + if (type(groupTypeIndex).isGcType()) { + return true; + } + } + return false; + } + HashNumber hash() const { HashNumber hn = 0; for (uint32_t i = 0; i < numTypes(); i++) { @@ -1062,14 +1092,14 @@ class RecGroup : public AtomicRefCounted { return hn; } - // Matches two recursion groups for isorecursive equality. See - // "Matching type definitions" in WasmValType.h for more background. - static bool matches(const RecGroup& lhs, const RecGroup& rhs) { + // Compares two recursion groups for isorecursive equality. See + // "Comparing type definitions" in WasmValType.h for more background. + static bool isoEquals(const RecGroup& lhs, const RecGroup& rhs) { if (lhs.numTypes() != rhs.numTypes()) { return false; } for (uint32_t i = 0; i < lhs.numTypes(); i++) { - if (!TypeDef::matches(lhs.type(i), rhs.type(i))) { + if (!TypeDef::isoEquals(lhs.type(i), rhs.type(i))) { return false; } } @@ -1091,7 +1121,6 @@ using SharedRecGroupVector = Vector; // A type context holds the recursion groups and corresponding type definitions // defined in a module. class TypeContext : public AtomicRefCounted { - FeatureArgs features_; // The pending recursion group that is currently being constructed MutableRecGroup pendingRecGroup_; // An in-order list of all the recursion groups defined in this module @@ -1106,10 +1135,9 @@ class TypeContext : public AtomicRefCounted { public: TypeContext() = default; - explicit TypeContext(const FeatureArgs& features) : features_(features) {} ~TypeContext(); - size_t sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const { + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { return types_.sizeOfExcludingThis(mallocSizeOf) + moduleIndices_.shallowSizeOfExcludingThis(mallocSizeOf); } @@ -1192,8 +1220,7 @@ class TypeContext : public AtomicRefCounted { return true; } - // Finish creation of a recursion group after type definitions have been - // initialized. This must be paired with `startGroup`. + // Add a pre-existing recursion group to this type context. [[nodiscard]] bool addRecGroup(SharedRecGroup recGroup) { // We must not have a pending group MOZ_ASSERT(!pendingRecGroup_); @@ -1240,6 +1267,15 @@ class TypeContext : public AtomicRefCounted { const SharedRecGroupVector& groups() const { return recGroups_; } + bool hasGcType() const { + for (const SharedRecGroup& recGroup : groups()) { + if (recGroup->hasGcType()) { + return true; + } + } + return false; + } + // Map from type definition to index uint32_t indexOf(const TypeDef& typeDef) const { @@ -1252,38 +1288,12 @@ class TypeContext : public AtomicRefCounted { using SharedTypeContext = RefPtr; using MutableTypeContext = RefPtr; -//========================================================================= -// TypeHandle - -// An unambiguous strong reference to a type definition in a specific type -// context. -class TypeHandle { - private: - SharedTypeContext context_; - uint32_t index_; - - public: - TypeHandle(SharedTypeContext context, uint32_t index) - : context_(context), index_(index) { - MOZ_ASSERT(index_ < context_->length()); - } - TypeHandle(SharedTypeContext context, const TypeDef& def) - : context_(context), index_(context->indexOf(def)) {} - - TypeHandle(const TypeHandle&) = default; - TypeHandle& operator=(const TypeHandle&) = default; - - const SharedTypeContext& context() const { return context_; } - uint32_t index() const { return index_; } - const TypeDef& def() const { return context_->type(index_); } -}; - //========================================================================= // misc /* static */ -inline uintptr_t TypeDef::forMatch(const TypeDef* typeDef, - const RecGroup* recGroup) { +inline uintptr_t TypeDef::forIsoEquals(const TypeDef* typeDef, + const RecGroup* recGroup) { // TypeDef is aligned sufficiently to allow a tag to distinguish a local type // reference (index) from a non-local type reference (pointer). static_assert(alignof(TypeDef) > 1); @@ -1302,11 +1312,11 @@ inline uintptr_t TypeDef::forMatch(const TypeDef* typeDef, } /* static */ -inline MatchTypeCode MatchTypeCode::forMatch(PackedTypeCode ptc, - const RecGroup* recGroup) { - MatchTypeCode mtc = {}; +inline IsoEqualsTypeCode IsoEqualsTypeCode::forIsoEquals( + PackedTypeCode ptc, const RecGroup* recGroup) { + IsoEqualsTypeCode mtc = {}; mtc.typeCode = PackedRepr(ptc.typeCode()); - mtc.typeRef = TypeDef::forMatch(ptc.typeDef(), recGroup); + mtc.typeRef = TypeDef::forIsoEquals(ptc.typeDef(), recGroup); mtc.nullable = ptc.isNullable(); return mtc; } @@ -1330,15 +1340,18 @@ void RefType::AddRef() const { if (!isTypeRef()) { return; } - typeDef()->recGroup().AddRef(); + typeDef()->AddRef(); } void RefType::Release() const { if (!isTypeRef()) { return; } - typeDef()->recGroup().Release(); + typeDef()->Release(); } +void TypeDef::AddRef() const { recGroup().AddRef(); } +void TypeDef::Release() const { recGroup().Release(); } + inline RefTypeHierarchy RefType::hierarchy() const { switch (kind()) { case RefType::Func: @@ -1415,35 +1428,35 @@ inline bool RefType::isSubTypeOf(RefType subType, RefType superType) { return true; } - // eqref is a subtype of anyref + // eq is a subtype of any if (subType.isEq() && superType.isAny()) { return true; } - // i31ref is a subtype of eqref + // i31 is a subtype of eq and any if (subType.isI31() && (superType.isAny() || superType.isEq())) { return true; } - // structref/arrayref are subtypes of eqref and anyref + // Abstract struct/array are subtypes of eq and any if ((subType.isStruct() || subType.isArray()) && (superType.isAny() || superType.isEq())) { return true; } - // Structs are subtypes of structref, eqref and anyref + // Concrete struct types are subtypes of struct, eq, and any if (subType.isTypeRef() && subType.typeDef()->isStructType() && (superType.isAny() || superType.isEq() || superType.isStruct())) { return true; } - // Arrays are subtypes of arrayref, eqref and anyref + // Concrete array types are subtypes of array, eq, and any if (subType.isTypeRef() && subType.typeDef()->isArrayType() && (superType.isAny() || superType.isEq() || superType.isArray())) { return true; } - // Funcs are subtypes of funcref + // Concrete func types are subtypes of func if (subType.isTypeRef() && subType.typeDef()->isFuncType() && superType.isFunc()) { return true; @@ -1454,23 +1467,23 @@ inline bool RefType::isSubTypeOf(RefType subType, RefType superType) { return TypeDef::isSubTypeOf(subType.typeDef(), superType.typeDef()); } - // No func is the bottom type of the func hierarchy + // nofunc is the bottom type of the func hierarchy if (subType.isNoFunc() && superType.hierarchy() == RefTypeHierarchy::Func) { return true; } - // No extern is the bottom type of the extern hierarchy + // noextern is the bottom type of the extern hierarchy if (subType.isNoExtern() && superType.hierarchy() == RefTypeHierarchy::Extern) { return true; } - // None is the bottom type of the any hierarchy + // none is the bottom type of the any hierarchy if (subType.isNone() && superType.hierarchy() == RefTypeHierarchy::Any) { return true; } - // No exn is the bottom type of the exn hierarchy + // noexn is the bottom type of the exn hierarchy if (subType.isNoExn() && superType.hierarchy() == RefTypeHierarchy::Exn) { return true; } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmUtility.h b/src/third_party/mozjs/extract/js/src/wasm/WasmUtility.h index 58b5c673f92..aab8c76af3d 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmUtility.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmUtility.h @@ -28,26 +28,24 @@ static inline bool EqualContainers(const Container1& lhs, "Must be trivially destructible"); \ namespace js { \ namespace wasm { \ - typedef Vector VectorName; - -using mozilla::MallocSizeOf; + using VectorName = Vector; template static inline size_t SizeOfVectorElementExcludingThis( - const T& elem, MallocSizeOf mallocSizeOf) { + const T& elem, mozilla::MallocSizeOf mallocSizeOf) { return elem.sizeOfExcludingThis(mallocSizeOf); } template static inline size_t SizeOfVectorElementExcludingThis( - const RefPtr& elem, MallocSizeOf mallocSizeOf) { + const RefPtr& elem, mozilla::MallocSizeOf mallocSizeOf) { return elem->sizeOfExcludingThis(mallocSizeOf); } template static inline size_t SizeOfVectorExcludingThis( const mozilla::Vector& vec, - MallocSizeOf mallocSizeOf) { + mozilla::MallocSizeOf mallocSizeOf) { size_t size = vec.sizeOfExcludingThis(mallocSizeOf); for (const T& t : vec) { size += SizeOfVectorElementExcludingThis(t, mallocSizeOf); @@ -56,8 +54,8 @@ static inline size_t SizeOfVectorExcludingThis( } template -static inline size_t SizeOfMaybeExcludingThis(const mozilla::Maybe& maybe, - MallocSizeOf mallocSizeOf) { +static inline size_t SizeOfMaybeExcludingThis( + const mozilla::Maybe& maybe, mozilla::MallocSizeOf mallocSizeOf) { return maybe ? maybe->sizeOfExcludingThis(mallocSizeOf) : 0; } diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmValType.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmValType.cpp index 0d9e1b24fb2..0c3eb2034c0 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmValType.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmValType.cpp @@ -37,35 +37,110 @@ using namespace js; using namespace js::wasm; RefType RefType::topType() const { - switch (kind()) { - case RefType::Any: - case RefType::Eq: - case RefType::I31: - case RefType::Array: - case RefType::Struct: - case RefType::None: - return RefType::any(); - case RefType::Func: - case RefType::NoFunc: - return RefType::func(); - case RefType::Extern: - case RefType::NoExtern: - return RefType::extern_(); - case RefType::Exn: - case RefType::NoExn: - return RefType::exn(); - case RefType::TypeRef: - switch (typeDef()->kind()) { - case TypeDefKind::Array: - case TypeDefKind::Struct: - return RefType::any(); - case TypeDefKind::Func: - return RefType::func(); - case TypeDefKind::None: - MOZ_CRASH("should not see TypeDefKind::None at this point"); - } + switch (hierarchy()) { + case wasm::RefTypeHierarchy::Any: + return wasm::RefType::any(); + case wasm::RefTypeHierarchy::Func: + return wasm::RefType::func(); + case wasm::RefTypeHierarchy::Extern: + return wasm::RefType::extern_(); + case wasm::RefTypeHierarchy::Exn: + return wasm::RefType::exn(); + default: + MOZ_CRASH("switch is exhaustive"); } - MOZ_CRASH("switch is exhaustive"); +} + +RefType RefType::bottomType() const { + switch (hierarchy()) { + case wasm::RefTypeHierarchy::Any: + return wasm::RefType::none(); + case wasm::RefTypeHierarchy::Func: + return wasm::RefType::nofunc(); + case wasm::RefTypeHierarchy::Extern: + return wasm::RefType::noextern(); + case wasm::RefTypeHierarchy::Exn: + return wasm::RefType::noexn(); + default: + MOZ_CRASH("switch is exhaustive"); + } +} + +static RefType FirstCommonSuperType(RefType a, RefType b, + std::initializer_list supers) { + for (RefType super : supers) { + if (RefType::isSubTypeOf(a, super) && RefType::isSubTypeOf(b, super)) { + return super; + } + } + MOZ_CRASH("failed to find common super type"); +} + +RefType RefType::leastUpperBound(RefType a, RefType b) { + // Types in different hierarchies have no common bound. Validation should + // always prevent two such types from being compared. + MOZ_RELEASE_ASSERT(a.hierarchy() == b.hierarchy()); + + // Whether the LUB is nullable can be determined by the nullability of a and + // b, regardless of their actual types. + bool nullable = a.isNullable() || b.isNullable(); + + // If one type is a subtype of the other, the higher type is the LUB - and we + // can capture nulls here too, as we know the nullability of the LUB. + if (RefType::isSubTypeOf(a, b.withIsNullable(nullable))) { + return b.withIsNullable(nullable); + } + if (RefType::isSubTypeOf(b, a.withIsNullable(nullable))) { + return a.withIsNullable(nullable); + } + + // Concrete types may share a concrete parent type. We can test b against all + // of a's parent types to see if this is true. + if (a.isTypeRef() && b.isTypeRef()) { + const TypeDef* aSuper = a.typeDef()->superTypeDef(); + while (aSuper) { + if (TypeDef::isSubTypeOf(b.typeDef(), aSuper)) { + return RefType(aSuper, nullable); + } + aSuper = aSuper->superTypeDef(); + } + } + + // Because wasm type hierarchies are pretty small and simple, we can + // essentially brute-force the LUB by simply iterating over all the abstract + // types bottom-to-top. The first one that is a super type of both a and b is + // the LUB. We are guaranteed to find a common bound because we have verified + // that the types have the same hierarchy and we will therefore at least find + // the hierarchy's top type. + // + // We test against the nullable versions of these types, and then apply the + // true nullability afterward. This is ok -- this finds the *kind* of the LUB + // (which we now know to be abstract), and applying the correct nullability + // will not affect this. For example, for the non-nullable types + // (ref $myStruct) and (ref $myArray), we will find (ref null eq), and then + // modify it to (ref eq), which is the correct LUB. + RefType common; + switch (a.hierarchy()) { + case RefTypeHierarchy::Any: + common = FirstCommonSuperType( + a, b, + {RefType::none(), RefType::i31(), RefType::struct_(), + RefType::array(), RefType::eq(), RefType::any()}); + break; + case RefTypeHierarchy::Func: + common = FirstCommonSuperType(a, b, {RefType::nofunc(), RefType::func()}); + break; + case RefTypeHierarchy::Extern: + common = + FirstCommonSuperType(a, b, {RefType::noextern(), RefType::extern_()}); + break; + case RefTypeHierarchy::Exn: + common = FirstCommonSuperType(a, b, {RefType::noexn(), RefType::exn()}); + break; + default: + MOZ_CRASH("unknown type hierarchy"); + } + return common.withIsNullable(nullable); } TypeDefKind RefType::typeDefKind() const { @@ -82,7 +157,7 @@ TypeDefKind RefType::typeDefKind() const { MOZ_CRASH("switch is exhaustive"); } -static bool ToRefType(JSContext* cx, JSLinearString* typeLinearStr, +static bool ToRefType(JSContext* cx, const JSLinearString* typeLinearStr, RefType* out) { if (StringEqualsLiteral(typeLinearStr, "anyfunc") || StringEqualsLiteral(typeLinearStr, "funcref")) { @@ -101,46 +176,42 @@ static bool ToRefType(JSContext* cx, JSLinearString* typeLinearStr, return true; } } -#ifdef ENABLE_WASM_GC - if (GcAvailable(cx)) { - if (StringEqualsLiteral(typeLinearStr, "anyref")) { - *out = RefType::any(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "eqref")) { - *out = RefType::eq(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "i31ref")) { - *out = RefType::i31(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "structref")) { - *out = RefType::struct_(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "arrayref")) { - *out = RefType::array(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "nullfuncref")) { - *out = RefType::nofunc(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "nullexternref")) { - *out = RefType::noextern(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "nullexnref")) { - *out = RefType::noexn(); - return true; - } - if (StringEqualsLiteral(typeLinearStr, "nullref")) { - *out = RefType::none(); - return true; - } + if (StringEqualsLiteral(typeLinearStr, "anyref")) { + *out = RefType::any(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "eqref")) { + *out = RefType::eq(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "i31ref")) { + *out = RefType::i31(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "structref")) { + *out = RefType::struct_(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "arrayref")) { + *out = RefType::array(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "nullfuncref")) { + *out = RefType::nofunc(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "nullexternref")) { + *out = RefType::noextern(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "nullexnref")) { + *out = RefType::noexn(); + return true; + } + if (StringEqualsLiteral(typeLinearStr, "nullref")) { + *out = RefType::none(); + return true; } -#endif JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_STRING_VAL_TYPE); @@ -336,7 +407,11 @@ UniqueChars wasm::ToString(StorageType type, const TypeContext* types) { return DuplicateString(literal); } -UniqueChars wasm::ToString(const Maybe& type, +UniqueChars wasm::ToString(const mozilla::Maybe& type, const TypeContext* types) { return type ? ToString(type.ref(), types) : JS_smprintf("%s", "void"); } + +UniqueChars wasm::ToString(const MaybeRefType& type, const TypeContext* types) { + return type ? ToString(type.value(), types) : JS_smprintf("%s", "void"); +} diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmValType.h b/src/third_party/mozjs/extract/js/src/wasm/WasmValType.h index b194b781136..119da87cacd 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmValType.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmValType.h @@ -32,13 +32,6 @@ namespace js { namespace wasm { -using mozilla::Maybe; - -class RecGroup; -class TypeDef; -class TypeContext; -enum class TypeDefKind : uint8_t; - // A PackedTypeCode represents any value type. union PackedTypeCode { public: @@ -49,8 +42,10 @@ union PackedTypeCode { static constexpr size_t TypeCodeBits = 8; static constexpr size_t TypeDefBits = 48; static constexpr size_t PointerTagBits = 2; + static constexpr size_t UnusedBits = 5; - static_assert(NullableBits + TypeCodeBits + TypeDefBits + PointerTagBits <= + static_assert(NullableBits + TypeCodeBits + TypeDefBits + PointerTagBits + + UnusedBits == (sizeof(PackedRepr) * 8), "enough bits"); @@ -66,21 +61,32 @@ union PackedTypeCode { // and ResultType, which can encode a ValType inside themselves in special // cases. PackedRepr pointerTag_ : PointerTagBits; + // The remaining bits are unused, but still need to be explicitly + // initialized to zero. + PackedRepr unused_ : UnusedBits; }; + explicit constexpr PackedTypeCode(PackedRepr bits) : bits_(bits) {} + + constexpr PackedTypeCode(PackedRepr nullable, PackedRepr typeCode, + PackedRepr typeDef) + : nullable_(nullable), + typeCode_(typeCode), + typeDef_(typeDef), + pointerTag_(0), + unused_(0) {} + public: + PackedTypeCode() = default; + static constexpr PackedRepr NoTypeCode = ((uint64_t)1 << TypeCodeBits) - 1; - static PackedTypeCode invalid() { - PackedTypeCode ptc = {}; - ptc.typeCode_ = NoTypeCode; - return ptc; + static constexpr PackedTypeCode invalid() { + return PackedTypeCode{false, NoTypeCode, 0}; } static constexpr PackedTypeCode fromBits(PackedRepr bits) { - PackedTypeCode ptc = {}; - ptc.bits_ = bits; - return ptc; + return PackedTypeCode{bits}; } static PackedTypeCode pack(TypeCode tc, const TypeDef* typeDef, @@ -88,27 +94,25 @@ union PackedTypeCode { MOZ_ASSERT(uint32_t(tc) <= ((1 << TypeCodeBits) - 1)); MOZ_ASSERT_IF(tc != AbstractTypeRefCode, typeDef == nullptr); MOZ_ASSERT_IF(tc == AbstractTypeRefCode, typeDef != nullptr); + auto tydef = static_cast(reinterpret_cast(typeDef)); #if defined(JS_64BIT) && defined(DEBUG) // Double check that `typeDef` only has 48 significant bits, with the top // 16 being zero. This is necessary since we will only store the lowest // 48 bits of it, as noted above. There's no equivalent check on 32 bit // targets since we can store the whole pointer. static_assert(sizeof(int64_t) == sizeof(uintptr_t)); - uint64_t w = (uint64_t)(uintptr_t)typeDef; - MOZ_ASSERT((w >> TypeDefBits) == 0); + MOZ_ASSERT((tydef >> TypeDefBits) == 0); #endif - PackedTypeCode ptc = {}; - ptc.typeCode_ = PackedRepr(tc); - ptc.typeDef_ = (uint64_t)(uintptr_t)typeDef; - ptc.nullable_ = isNullable; - return ptc; + return PackedTypeCode{isNullable, PackedRepr(tc), tydef}; } - static PackedTypeCode pack(TypeCode tc, bool nullable) { - return pack(tc, nullptr, nullable); + static constexpr PackedTypeCode pack(TypeCode tc, bool nullable) { + MOZ_ASSERT(uint32_t(tc) <= ((1 << TypeCodeBits) - 1)); + MOZ_ASSERT(tc != AbstractTypeRefCode); + return PackedTypeCode{nullable, PackedRepr(tc), 0}; } - static PackedTypeCode pack(TypeCode tc) { return pack(tc, nullptr, false); } + static constexpr PackedTypeCode pack(TypeCode tc) { return pack(tc, false); } constexpr bool isValid() const { return typeCode_ != NoTypeCode; } @@ -210,16 +214,16 @@ union SerializableTypeCode { WASM_DECLARE_CACHEABLE_POD(SerializableTypeCode); static_assert(sizeof(SerializableTypeCode) == sizeof(uintptr_t), "packed"); -// [SMDOC] Matching type definitions +// [SMDOC] Comparing type definitions // // WebAssembly type equality is structural, and we implement canonicalization // such that equality of pointers to type definitions means that the type // definitions are structurally equal. // -// 'Matching' is the algorithm used to determine if two types are equal while +// 'IsoEquals' is the algorithm used to determine if two types are equal while // canonicalizing types. // -// A match type code encodes a type code for use in equality and hashing +// A iso equals type code encodes a type code for use in equality and hashing // matching. It normalizes type references that are local to a recursion group // so that they can be bitwise compared to type references from other recursion // groups. @@ -245,7 +249,7 @@ static_assert(sizeof(SerializableTypeCode) == sizeof(uintptr_t), "packed"); // types that point to the function type instance before them. A bitwise // comparison of the element type pointers would fail. // -// To solve this, we use `MatchTypeCode` to convert the example to: +// To solve this, we use `IsoEqualsTypeCode` to convert the example to: // (rec (func $a)) // (rec // (func $b) @@ -261,12 +265,12 @@ static_assert(sizeof(SerializableTypeCode) == sizeof(uintptr_t), "packed"); // ) // // Now, comparing the element types will see that these are local type -// references of the same kinds. `MatchTypeCode` performs the same mechanism +// references of the same kinds. `IsoEqualsTypeCode` performs the same mechanism // as `tie` in the MVP presentation of type equality [1]. // // [1] // https://github.com/WebAssembly/gc/blob/main/proposals/gc/MVP.md#equivalence -union MatchTypeCode { +union IsoEqualsTypeCode { using PackedRepr = uint64_t; static constexpr size_t NullableBits = 1; @@ -287,11 +291,11 @@ union MatchTypeCode { "enough bits"); // Defined in WasmTypeDef.h to avoid a cycle while allowing inlining - static inline MatchTypeCode forMatch(PackedTypeCode ptc, - const RecGroup* recGroup); + static inline IsoEqualsTypeCode forIsoEquals(PackedTypeCode ptc, + const RecGroup* recGroup); - bool operator==(MatchTypeCode other) const { return bits == other.bits; } - bool operator!=(MatchTypeCode other) const { return bits != other.bits; } + bool operator==(IsoEqualsTypeCode other) const { return bits == other.bits; } + bool operator!=(IsoEqualsTypeCode other) const { return bits != other.bits; } HashNumber hash() const { return HashNumber(bits); } }; @@ -342,6 +346,11 @@ class RefType { RefType() : ptc_(PackedTypeCode::invalid()) {} explicit RefType(PackedTypeCode ptc) : ptc_(ptc) { MOZ_ASSERT(isValid()); } + static RefType fromKind(Kind kind, bool nullable) { + MOZ_ASSERT(kind != TypeRef); + return RefType(kind, nullable); + } + static RefType fromTypeCode(TypeCode tc, bool nullable) { MOZ_ASSERT(tc != AbstractTypeRefCode); return RefType(Kind(tc), nullable); @@ -359,8 +368,13 @@ class RefType { PackedTypeCode* addressOfPacked() { return &ptc_; } const PackedTypeCode* addressOfPacked() const { return &ptc_; } -#ifdef DEBUG + // Further restricts PackedTypeCode::isValid() to only those TypeCodes which + // represent a wasm reference type. bool isValid() const { + if (!ptc_.isValid()) { + return false; + } + MOZ_ASSERT((ptc_.typeCode() == AbstractTypeRefCode) == (ptc_.typeDef() != nullptr)); switch (ptc_.typeCode()) { @@ -382,7 +396,6 @@ class RefType { return false; } } -#endif static RefType func() { return RefType(Func, true); } static RefType extern_() { return RefType(Extern, true); } @@ -432,9 +445,15 @@ class RefType { static bool castPossible(RefType sourceType, RefType destType); // Gets the top of the given type's hierarchy, e.g. Any for structs and - // arrays, and Func for funcs + // arrays, and Func for funcs. RefType topType() const; + // Gets the bottom of the given type's hierarchy, e.g. None for structs and + // arrays, and NoFunc for funcs. + RefType bottomType() const; + + static RefType leastUpperBound(RefType a, RefType b); + // Gets the TypeDefKind associated with this RefType, e.g. TypeDefKind::Struct // for RefType::Struct. TypeDefKind typeDefKind() const; @@ -446,6 +465,8 @@ class RefType { bool operator!=(const RefType& that) const { return ptc_ != that.ptc_; } }; +using RefTypeVector = Vector; + class StorageTypeTraits { public: enum Kind { @@ -461,10 +482,8 @@ class StorageTypeTraits { static bool isValidTypeCode(TypeCode tc) { switch (tc) { -#ifdef ENABLE_WASM_GC case TypeCode::I8: case TypeCode::I16: -#endif case TypeCode::I32: case TypeCode::I64: case TypeCode::F32: @@ -476,7 +495,6 @@ class StorageTypeTraits { case TypeCode::ExternRef: case TypeCode::ExnRef: case TypeCode::NullExnRef: -#ifdef ENABLE_WASM_GC case TypeCode::AnyRef: case TypeCode::EqRef: case TypeCode::I31Ref: @@ -485,10 +503,7 @@ class StorageTypeTraits { case TypeCode::NullFuncRef: case TypeCode::NullExternRef: case TypeCode::NullAnyRef: -#endif -#ifdef ENABLE_WASM_GC case AbstractTypeRefCode: -#endif return true; default: return false; @@ -509,11 +524,9 @@ class StorageTypeTraits { static bool isPackedTypeCode(TypeCode tc) { switch (tc) { -#ifdef ENABLE_WASM_GC case TypeCode::I8: case TypeCode::I16: return true; -#endif default: return false; } @@ -542,7 +555,25 @@ class ValTypeTraits { Ref = uint8_t(AbstractReferenceTypeCode), }; - static bool isValidTypeCode(TypeCode tc) { + static const char* KindEnumName(Kind kind) { + switch (kind) { + case Kind::I32: + return "I32"; + case Kind::I64: + return "I64"; + case Kind::F32: + return "F32"; + case Kind::F64: + return "F64"; + case Kind::V128: + return "V128"; + case Kind::Ref: + return "Ref"; + } + MOZ_CRASH("Unknown kind"); + } + + static constexpr bool isValidTypeCode(TypeCode tc) { switch (tc) { case TypeCode::I32: case TypeCode::I64: @@ -555,7 +586,6 @@ class ValTypeTraits { case TypeCode::ExternRef: case TypeCode::ExnRef: case TypeCode::NullExnRef: -#ifdef ENABLE_WASM_GC case TypeCode::AnyRef: case TypeCode::EqRef: case TypeCode::I31Ref: @@ -564,10 +594,7 @@ class ValTypeTraits { case TypeCode::NullFuncRef: case TypeCode::NullExternRef: case TypeCode::NullAnyRef: -#endif -#ifdef ENABLE_WASM_GC case AbstractTypeRefCode: -#endif return true; default: return false; @@ -623,9 +650,10 @@ class PackedType : public T { } public: - PackedType() : tc_(PackedTypeCode::invalid()) {} + constexpr PackedType() : tc_(PackedTypeCode::invalid()) {} - MOZ_IMPLICIT PackedType(Kind c) : tc_(PackedTypeCode::pack(TypeCode(c))) { + MOZ_IMPLICIT constexpr PackedType(Kind c) + : tc_(PackedTypeCode::pack(TypeCode(c))) { MOZ_ASSERT(c != Kind::Ref); MOZ_ASSERT(isValid()); } @@ -634,7 +662,9 @@ class PackedType : public T { MOZ_ASSERT(isValid()); } - explicit PackedType(PackedTypeCode ptc) : tc_(ptc) { MOZ_ASSERT(isValid()); } + explicit constexpr PackedType(PackedTypeCode ptc) : tc_(ptc) { + MOZ_ASSERT(isValid()); + } inline void AddRef() const; inline void Release() const; @@ -690,15 +720,15 @@ class PackedType : public T { return PackedType(PackedTypeCode::fromBits(bits)); } - bool isValid() const { + constexpr bool isValid() const { if (!tc_.isValid()) { return false; } return T::isValidTypeCode(tc_.typeCode()); } - MatchTypeCode forMatch(const RecGroup* recGroup) const { - return MatchTypeCode::forMatch(tc_, recGroup); + IsoEqualsTypeCode forIsoEquals(const RecGroup* recGroup) const { + return IsoEqualsTypeCode::forIsoEquals(tc_, recGroup); } PackedTypeCode packed() const { @@ -863,6 +893,8 @@ class PackedType : public T { } } + MaybeRefType toMaybeRefType() const; + bool isValType() const { switch (tc_.typeCode()) { case TypeCode::I8: @@ -911,7 +943,6 @@ class PackedType : public T { bool operator!=(Kind that) const { return !(*this == that); } }; -using ValType = PackedType; using StorageType = PackedType; // The dominant use of this data type is for locals and args, and profiling @@ -919,6 +950,76 @@ using StorageType = PackedType; // allocation, both in terms of blocks and bytes. using ValTypeVector = Vector; +// A MaybeRefType behaves like a mozilla::Maybe, but saves space by +// reusing PackedTypeCode. If the inner RefType is not valid, it will be +// considered Nothing; otherwise it will be considered Some. +class MaybeRefType { + private: + RefType inner_; + + public: + // Creates a MaybeRefType that isNothing(). + MaybeRefType() { MOZ_ASSERT(isNothing()); } + + // Creates a MaybeRefType that isSome(). + explicit MaybeRefType(RefType type) : inner_(type) { + MOZ_RELEASE_ASSERT(isSome()); + } + + bool isSome() const { return inner_.isValid(); } + bool isNothing() const { return !isSome(); } + + /* Returns the inner RefType by value. Unsafe unless |isSome()|. */ + RefType& value() & { + MOZ_RELEASE_ASSERT(isSome()); + return inner_; + }; + const RefType& value() const& { + MOZ_RELEASE_ASSERT(isSome()); + return inner_; + }; + + RefType& valueOr(RefType& aDefault) { + if (isSome()) { + return value(); + } + return aDefault; + } + const RefType& valueOr(const RefType& aDefault) { + if (isSome()) { + return value(); + } + return aDefault; + } + + bool operator==(const MaybeRefType& other) { return inner_ == other.inner_; } + bool operator!=(const MaybeRefType& other) { return inner_ != other.inner_; } + + explicit operator bool() const { return isSome(); } + + mozilla::Maybe hierarchy() const { + if (isSome()) { + return mozilla::Some(value().hierarchy()); + } + return mozilla::Nothing(); + } + + static MaybeRefType leastUpperBound(MaybeRefType a, MaybeRefType b) { + if (a.isSome() && b.isSome()) { + return MaybeRefType(RefType::leastUpperBound(a.value(), b.value())); + } + return MaybeRefType(); + } +}; + +template +MaybeRefType PackedType::toMaybeRefType() const { + if (!isRefType()) { + return MaybeRefType(); + } + return MaybeRefType(refType()); +}; + // ValType utilities extern bool ToValType(JSContext* cx, HandleValue v, ValType* out); @@ -927,8 +1028,9 @@ extern bool ToRefType(JSContext* cx, HandleValue v, RefType* out); extern UniqueChars ToString(RefType type, const TypeContext* types); extern UniqueChars ToString(ValType type, const TypeContext* types); extern UniqueChars ToString(StorageType type, const TypeContext* types); -extern UniqueChars ToString(const Maybe& type, +extern UniqueChars ToString(const mozilla::Maybe& type, const TypeContext* types); +extern UniqueChars ToString(const MaybeRefType& type, const TypeContext* types); } // namespace wasm } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.cpp index e650fb0b092..e75373c005b 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.cpp @@ -26,6 +26,7 @@ #include "js/String.h" // JS::MaxStringLength #include "vm/JSContext.h" #include "vm/Realm.h" +#include "wasm/WasmDump.h" #include "wasm/WasmInitExpr.h" #include "wasm/WasmOpIter.h" #include "wasm/WasmTypeDecls.h" @@ -36,53 +37,12 @@ using namespace js::wasm; using mozilla::AsChars; using mozilla::CheckedInt; -using mozilla::CheckedInt32; using mozilla::IsUtf8; +using mozilla::Maybe; +using mozilla::Nothing; +using mozilla::Some; using mozilla::Span; -// Module environment helpers. - -bool ModuleEnvironment::addDefinedFunc( - ValTypeVector&& params, ValTypeVector&& results, bool declareForRef, - Maybe&& optionalExportedName) { - uint32_t typeIndex = types->length(); - FuncType funcType(std::move(params), std::move(results)); - if (!types->addType(std::move(funcType))) { - return false; - } - - FuncDesc funcDesc = FuncDesc(&(*types)[typeIndex].funcType(), typeIndex); - uint32_t funcIndex = funcs.length(); - if (!funcs.append(funcDesc)) { - return false; - } - if (declareForRef) { - declareFuncExported(funcIndex, true, true); - } - if (optionalExportedName.isSome()) { - if (!exports.emplaceBack(std::move(optionalExportedName.ref()), funcIndex, - DefinitionKind::Function)) { - return false; - } - } - return true; -} - -bool ModuleEnvironment::addImportedFunc(ValTypeVector&& params, - ValTypeVector&& results, - CacheableName&& importModName, - CacheableName&& importFieldName) { - MOZ_ASSERT(numFuncImports == funcs.length()); - if (!addDefinedFunc(std::move(params), std::move(results), false, - mozilla::Nothing())) { - return false; - } - numFuncImports++; - return imports.emplaceBack(std::move(importModName), - std::move(importFieldName), - DefinitionKind::Function); -} - // Misc helpers. bool wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals) { @@ -133,7 +93,7 @@ bool wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals) { } bool wasm::DecodeLocalEntriesWithParams(Decoder& d, - const ModuleEnvironment& env, + const CodeMetadata& codeMeta, uint32_t funcIndex, ValTypeVector* locals) { uint32_t numLocalEntries; @@ -141,7 +101,7 @@ bool wasm::DecodeLocalEntriesWithParams(Decoder& d, return d.fail("failed to read number of local entries"); } - if (!locals->appendAll(env.funcs[funcIndex].type->args())) { + if (!locals->appendAll(codeMeta.getFuncType(funcIndex).args())) { return false; } @@ -156,7 +116,7 @@ bool wasm::DecodeLocalEntriesWithParams(Decoder& d, } ValType type; - if (!d.readValType(*env.types, env.features, &type)) { + if (!d.readValType(*codeMeta.types, codeMeta.features(), &type)) { return false; } @@ -184,19 +144,44 @@ bool wasm::DecodeValidatedLocalEntries(const TypeContext& types, Decoder& d, return true; } -bool wasm::CheckIsSubtypeOf(Decoder& d, const ModuleEnvironment& env, +bool wasm::CheckIsSubtypeOf(Decoder& d, const CodeMetadata& codeMeta, + size_t opcodeOffset, ResultType subType, + ResultType superType) { + if (subType.length() != superType.length()) { + UniqueChars error( + JS_smprintf("type mismatch: expected %zu values, got %zu values", + superType.length(), subType.length())); + if (!error) { + return false; + } + MOZ_ASSERT(!ResultType::isSubTypeOf(subType, superType)); + return d.fail(opcodeOffset, error.get()); + } + for (uint32_t i = 0; i < subType.length(); i++) { + StorageType sub = subType[i].storageType(); + StorageType super = superType[i].storageType(); + if (!CheckIsSubtypeOf(d, codeMeta, opcodeOffset, sub, super)) { + MOZ_ASSERT(!ResultType::isSubTypeOf(subType, superType)); + return false; + } + } + MOZ_ASSERT(ResultType::isSubTypeOf(subType, superType)); + return true; +} + +bool wasm::CheckIsSubtypeOf(Decoder& d, const CodeMetadata& codeMeta, size_t opcodeOffset, StorageType subType, StorageType superType) { if (StorageType::isSubTypeOf(subType, superType)) { return true; } - UniqueChars subText = ToString(subType, env.types); + UniqueChars subText = ToString(subType, codeMeta.types); if (!subText) { return false; } - UniqueChars superText = ToString(superType, env.types); + UniqueChars superText = ToString(superType, codeMeta.types); if (!superText) { return false; } @@ -213,182 +198,295 @@ bool wasm::CheckIsSubtypeOf(Decoder& d, const ModuleEnvironment& env, // Function body validation. -static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, - uint32_t funcIndex, - const ValTypeVector& locals, - const uint8_t* bodyEnd, Decoder* d) { - ValidatingOpIter iter(env, *d); - - if (!iter.startFunction(funcIndex, locals)) { - return false; - } - -#define CHECK(c) \ - if (!(c)) return false; \ - break - +template +bool wasm::ValidateOps(ValidatingOpIter& iter, T& dumper, + const CodeMetadata& codeMeta) { while (true) { OpBytes op; if (!iter.readOp(&op)) { return false; } + // End instructions get handled differently since we don't actually want to + // dump the final `end`. Also, Else instructions need to have their + // indentation managed when dumping. + if (op.b0 != uint16_t(Op::End)) { + if (op.b0 == uint64_t(Op::Else)) { + dumper.endScope(); + } + dumper.dumpOpBegin(op); + if (op.b0 == uint64_t(Op::Else)) { + dumper.startScope(); + } + } + Nothing nothing; NothingVector nothings{}; - ResultType unusedType; + BlockType blockType; + ResultType resultType; switch (op.b0) { case uint16_t(Op::End): { LabelKind unusedKind; - if (!iter.readEnd(&unusedKind, &unusedType, ¬hings, ¬hings)) { + if (!iter.readEnd(&unusedKind, &resultType, ¬hings, ¬hings)) { return false; } iter.popEnd(); if (iter.controlStackEmpty()) { - return iter.endFunction(bodyEnd); + return true; + } + + // Only dump `end` if it was not the final `end` of the expression. + dumper.endScope(); + dumper.dumpOpBegin(op); + + break; + } + case uint16_t(Op::Nop): { + if (!iter.readNop()) { + return false; + } + break; + } + case uint16_t(Op::Drop): { + if (!iter.readDrop()) { + return false; } break; } - case uint16_t(Op::Nop): - CHECK(iter.readNop()); - case uint16_t(Op::Drop): - CHECK(iter.readDrop()); case uint16_t(Op::Call): { - uint32_t unusedIndex; + uint32_t funcIndex; NothingVector unusedArgs{}; - CHECK(iter.readCall(&unusedIndex, &unusedArgs)); + if (!iter.readCall(&funcIndex, &unusedArgs)) { + return false; + } + dumper.dumpFuncIndex(funcIndex); + break; } case uint16_t(Op::CallIndirect): { - uint32_t unusedIndex, unusedIndex2; + uint32_t funcTypeIndex, tableIndex; NothingVector unusedArgs{}; - CHECK(iter.readCallIndirect(&unusedIndex, &unusedIndex2, ¬hing, - &unusedArgs)); - } -#ifdef ENABLE_WASM_TAIL_CALLS - case uint16_t(Op::ReturnCall): { - if (!env.tailCallsEnabled()) { - return iter.unrecognizedOpcode(&op); + if (!iter.readCallIndirect(&funcTypeIndex, &tableIndex, ¬hing, + &unusedArgs)) { + return false; } - uint32_t unusedIndex; + dumper.dumpTableIndex(tableIndex); + dumper.dumpTypeIndex(funcTypeIndex, /*asTypeUse=*/true); + break; + } + case uint16_t(Op::ReturnCall): { + uint32_t funcIndex; NothingVector unusedArgs{}; - CHECK(iter.readReturnCall(&unusedIndex, &unusedArgs)); + if (!iter.readReturnCall(&funcIndex, &unusedArgs)) { + return false; + } + dumper.dumpFuncIndex(funcIndex); + break; } case uint16_t(Op::ReturnCallIndirect): { - if (!env.tailCallsEnabled()) { - return iter.unrecognizedOpcode(&op); - } - uint32_t unusedIndex, unusedIndex2; + uint32_t funcTypeIndex, tableIndex; NothingVector unusedArgs{}; - CHECK(iter.readReturnCallIndirect(&unusedIndex, &unusedIndex2, ¬hing, - &unusedArgs)); + if (!iter.readReturnCallIndirect(&funcTypeIndex, &tableIndex, ¬hing, + &unusedArgs)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + dumper.dumpTypeIndex(funcTypeIndex, /*asTypeUse=*/true); + break; } -#endif -#ifdef ENABLE_WASM_GC case uint16_t(Op::CallRef): { - if (!env.gcEnabled()) { - return iter.unrecognizedOpcode(&op); - } - const FuncType* unusedType; + uint32_t funcTypeIndex; NothingVector unusedArgs{}; - CHECK(iter.readCallRef(&unusedType, ¬hing, &unusedArgs)); + if (!iter.readCallRef(&funcTypeIndex, ¬hing, &unusedArgs)) { + return false; + } + dumper.dumpTypeIndex(funcTypeIndex); + break; } -# ifdef ENABLE_WASM_TAIL_CALLS case uint16_t(Op::ReturnCallRef): { - if (!env.gcEnabled() || !env.tailCallsEnabled()) { - return iter.unrecognizedOpcode(&op); - } - const FuncType* unusedType; + uint32_t funcTypeIndex; NothingVector unusedArgs{}; - CHECK(iter.readReturnCallRef(&unusedType, ¬hing, &unusedArgs)); + if (!iter.readReturnCallRef(&funcTypeIndex, ¬hing, &unusedArgs)) { + return false; + } + dumper.dumpTypeIndex(funcTypeIndex); + break; } -# endif -#endif case uint16_t(Op::I32Const): { - int32_t unused; - CHECK(iter.readI32Const(&unused)); + int32_t constant; + if (!iter.readI32Const(&constant)) { + return false; + } + dumper.dumpI32Const(constant); + break; } case uint16_t(Op::I64Const): { - int64_t unused; - CHECK(iter.readI64Const(&unused)); + int64_t constant; + if (!iter.readI64Const(&constant)) { + return false; + } + dumper.dumpI64Const(constant); + break; } case uint16_t(Op::F32Const): { - float unused; - CHECK(iter.readF32Const(&unused)); + float constant; + if (!iter.readF32Const(&constant)) { + return false; + } + dumper.dumpF32Const(constant); + break; } case uint16_t(Op::F64Const): { - double unused; - CHECK(iter.readF64Const(&unused)); + double constant; + if (!iter.readF64Const(&constant)) { + return false; + } + dumper.dumpF64Const(constant); + break; } case uint16_t(Op::LocalGet): { - uint32_t unused; - CHECK(iter.readGetLocal(locals, &unused)); + uint32_t localIndex; + if (!iter.readGetLocal(&localIndex)) { + return false; + } + dumper.dumpLocalIndex(localIndex); + break; } case uint16_t(Op::LocalSet): { - uint32_t unused; - CHECK(iter.readSetLocal(locals, &unused, ¬hing)); + uint32_t localIndex; + if (!iter.readSetLocal(&localIndex, ¬hing)) { + return false; + } + dumper.dumpLocalIndex(localIndex); + break; } case uint16_t(Op::LocalTee): { - uint32_t unused; - CHECK(iter.readTeeLocal(locals, &unused, ¬hing)); + uint32_t localIndex; + if (!iter.readTeeLocal(&localIndex, ¬hing)) { + return false; + } + dumper.dumpLocalIndex(localIndex); + break; } case uint16_t(Op::GlobalGet): { - uint32_t unused; - CHECK(iter.readGetGlobal(&unused)); + uint32_t globalIndex; + if (!iter.readGetGlobal(&globalIndex)) { + return false; + } + dumper.dumpGlobalIndex(globalIndex); + break; } case uint16_t(Op::GlobalSet): { - uint32_t unused; - CHECK(iter.readSetGlobal(&unused, ¬hing)); + uint32_t globalIndex; + if (!iter.readSetGlobal(&globalIndex, ¬hing)) { + return false; + } + dumper.dumpGlobalIndex(globalIndex); + break; } case uint16_t(Op::TableGet): { - uint32_t unusedTableIndex; - CHECK(iter.readTableGet(&unusedTableIndex, ¬hing)); + uint32_t tableIndex; + if (!iter.readTableGet(&tableIndex, ¬hing)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + break; } case uint16_t(Op::TableSet): { - uint32_t unusedTableIndex; - CHECK(iter.readTableSet(&unusedTableIndex, ¬hing, ¬hing)); + uint32_t tableIndex; + if (!iter.readTableSet(&tableIndex, ¬hing, ¬hing)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + break; } case uint16_t(Op::SelectNumeric): { StackType unused; - CHECK(iter.readSelect(/*typed*/ false, &unused, ¬hing, ¬hing, - ¬hing)); + if (!iter.readSelect(/*typed*/ false, &unused, ¬hing, ¬hing, + ¬hing)) { + return false; + } + break; } case uint16_t(Op::SelectTyped): { - StackType unused; - CHECK(iter.readSelect(/*typed*/ true, &unused, ¬hing, ¬hing, - ¬hing)); + StackType type; + if (!iter.readSelect(/*typed*/ true, &type, ¬hing, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpValType(type.valType()); + break; + } + case uint16_t(Op::Block): { + if (!iter.readBlock(&blockType)) { + return false; + } + dumper.dumpBlockType(blockType); + dumper.startScope(); + break; + } + case uint16_t(Op::Loop): { + if (!iter.readLoop(&blockType)) { + return false; + } + dumper.dumpBlockType(blockType); + dumper.startScope(); + break; + } + case uint16_t(Op::If): { + if (!iter.readIf(&blockType, ¬hing)) { + return false; + } + dumper.dumpBlockType(blockType); + dumper.startScope(); + break; + } + case uint16_t(Op::Else): { + if (!iter.readElse(&resultType, &resultType, ¬hings)) { + return false; + } + break; } - case uint16_t(Op::Block): - CHECK(iter.readBlock(&unusedType)); - case uint16_t(Op::Loop): - CHECK(iter.readLoop(&unusedType)); - case uint16_t(Op::If): - CHECK(iter.readIf(&unusedType, ¬hing)); - case uint16_t(Op::Else): - CHECK(iter.readElse(&unusedType, &unusedType, ¬hings)); case uint16_t(Op::I32Clz): case uint16_t(Op::I32Ctz): - case uint16_t(Op::I32Popcnt): - CHECK(iter.readUnary(ValType::I32, ¬hing)); + case uint16_t(Op::I32Popcnt): { + if (!iter.readUnary(ValType::I32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64Clz): case uint16_t(Op::I64Ctz): - case uint16_t(Op::I64Popcnt): - CHECK(iter.readUnary(ValType::I64, ¬hing)); + case uint16_t(Op::I64Popcnt): { + if (!iter.readUnary(ValType::I64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F32Abs): case uint16_t(Op::F32Neg): case uint16_t(Op::F32Ceil): case uint16_t(Op::F32Floor): case uint16_t(Op::F32Sqrt): case uint16_t(Op::F32Trunc): - case uint16_t(Op::F32Nearest): - CHECK(iter.readUnary(ValType::F32, ¬hing)); + case uint16_t(Op::F32Nearest): { + if (!iter.readUnary(ValType::F32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F64Abs): case uint16_t(Op::F64Neg): case uint16_t(Op::F64Ceil): case uint16_t(Op::F64Floor): case uint16_t(Op::F64Sqrt): case uint16_t(Op::F64Trunc): - case uint16_t(Op::F64Nearest): - CHECK(iter.readUnary(ValType::F64, ¬hing)); + case uint16_t(Op::F64Nearest): { + if (!iter.readUnary(ValType::F64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I32Add): case uint16_t(Op::I32Sub): case uint16_t(Op::I32Mul): @@ -403,8 +501,12 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint16_t(Op::I32ShrS): case uint16_t(Op::I32ShrU): case uint16_t(Op::I32Rotl): - case uint16_t(Op::I32Rotr): - CHECK(iter.readBinary(ValType::I32, ¬hing, ¬hing)); + case uint16_t(Op::I32Rotr): { + if (!iter.readBinary(ValType::I32, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64Add): case uint16_t(Op::I64Sub): case uint16_t(Op::I64Mul): @@ -419,24 +521,36 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint16_t(Op::I64ShrS): case uint16_t(Op::I64ShrU): case uint16_t(Op::I64Rotl): - case uint16_t(Op::I64Rotr): - CHECK(iter.readBinary(ValType::I64, ¬hing, ¬hing)); + case uint16_t(Op::I64Rotr): { + if (!iter.readBinary(ValType::I64, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F32Add): case uint16_t(Op::F32Sub): case uint16_t(Op::F32Mul): case uint16_t(Op::F32Div): case uint16_t(Op::F32Min): case uint16_t(Op::F32Max): - case uint16_t(Op::F32CopySign): - CHECK(iter.readBinary(ValType::F32, ¬hing, ¬hing)); + case uint16_t(Op::F32CopySign): { + if (!iter.readBinary(ValType::F32, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F64Add): case uint16_t(Op::F64Sub): case uint16_t(Op::F64Mul): case uint16_t(Op::F64Div): case uint16_t(Op::F64Min): case uint16_t(Op::F64Max): - case uint16_t(Op::F64CopySign): - CHECK(iter.readBinary(ValType::F64, ¬hing, ¬hing)); + case uint16_t(Op::F64CopySign): { + if (!iter.readBinary(ValType::F64, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I32Eq): case uint16_t(Op::I32Ne): case uint16_t(Op::I32LtS): @@ -446,8 +560,12 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint16_t(Op::I32GtS): case uint16_t(Op::I32GtU): case uint16_t(Op::I32GeS): - case uint16_t(Op::I32GeU): - CHECK(iter.readComparison(ValType::I32, ¬hing, ¬hing)); + case uint16_t(Op::I32GeU): { + if (!iter.readComparison(ValType::I32, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64Eq): case uint16_t(Op::I64Ne): case uint16_t(Op::I64LtS): @@ -457,374 +575,714 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint16_t(Op::I64GtS): case uint16_t(Op::I64GtU): case uint16_t(Op::I64GeS): - case uint16_t(Op::I64GeU): - CHECK(iter.readComparison(ValType::I64, ¬hing, ¬hing)); + case uint16_t(Op::I64GeU): { + if (!iter.readComparison(ValType::I64, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F32Eq): case uint16_t(Op::F32Ne): case uint16_t(Op::F32Lt): case uint16_t(Op::F32Le): case uint16_t(Op::F32Gt): - case uint16_t(Op::F32Ge): - CHECK(iter.readComparison(ValType::F32, ¬hing, ¬hing)); + case uint16_t(Op::F32Ge): { + if (!iter.readComparison(ValType::F32, ¬hing, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F64Eq): case uint16_t(Op::F64Ne): case uint16_t(Op::F64Lt): case uint16_t(Op::F64Le): case uint16_t(Op::F64Gt): - case uint16_t(Op::F64Ge): - CHECK(iter.readComparison(ValType::F64, ¬hing, ¬hing)); - case uint16_t(Op::I32Eqz): - CHECK(iter.readConversion(ValType::I32, ValType::I32, ¬hing)); + case uint16_t(Op::F64Ge): { + if (!iter.readComparison(ValType::F64, ¬hing, ¬hing)) { + return false; + } + break; + } + case uint16_t(Op::I32Eqz): { + if (!iter.readConversion(ValType::I32, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64Eqz): - case uint16_t(Op::I32WrapI64): - CHECK(iter.readConversion(ValType::I64, ValType::I32, ¬hing)); + case uint16_t(Op::I32WrapI64): { + if (!iter.readConversion(ValType::I64, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I32TruncF32S): case uint16_t(Op::I32TruncF32U): - case uint16_t(Op::I32ReinterpretF32): - CHECK(iter.readConversion(ValType::F32, ValType::I32, ¬hing)); + case uint16_t(Op::I32ReinterpretF32): { + if (!iter.readConversion(ValType::F32, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I32TruncF64S): - case uint16_t(Op::I32TruncF64U): - CHECK(iter.readConversion(ValType::F64, ValType::I32, ¬hing)); + case uint16_t(Op::I32TruncF64U): { + if (!iter.readConversion(ValType::F64, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64ExtendI32S): - case uint16_t(Op::I64ExtendI32U): - CHECK(iter.readConversion(ValType::I32, ValType::I64, ¬hing)); + case uint16_t(Op::I64ExtendI32U): { + if (!iter.readConversion(ValType::I32, ValType::I64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64TruncF32S): - case uint16_t(Op::I64TruncF32U): - CHECK(iter.readConversion(ValType::F32, ValType::I64, ¬hing)); + case uint16_t(Op::I64TruncF32U): { + if (!iter.readConversion(ValType::F32, ValType::I64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64TruncF64S): case uint16_t(Op::I64TruncF64U): - case uint16_t(Op::I64ReinterpretF64): - CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing)); + case uint16_t(Op::I64ReinterpretF64): { + if (!iter.readConversion(ValType::F64, ValType::I64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F32ConvertI32S): case uint16_t(Op::F32ConvertI32U): - case uint16_t(Op::F32ReinterpretI32): - CHECK(iter.readConversion(ValType::I32, ValType::F32, ¬hing)); + case uint16_t(Op::F32ReinterpretI32): { + if (!iter.readConversion(ValType::I32, ValType::F32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F32ConvertI64S): - case uint16_t(Op::F32ConvertI64U): - CHECK(iter.readConversion(ValType::I64, ValType::F32, ¬hing)); - case uint16_t(Op::F32DemoteF64): - CHECK(iter.readConversion(ValType::F64, ValType::F32, ¬hing)); + case uint16_t(Op::F32ConvertI64U): { + if (!iter.readConversion(ValType::I64, ValType::F32, ¬hing)) { + return false; + } + break; + } + case uint16_t(Op::F32DemoteF64): { + if (!iter.readConversion(ValType::F64, ValType::F32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F64ConvertI32S): - case uint16_t(Op::F64ConvertI32U): - CHECK(iter.readConversion(ValType::I32, ValType::F64, ¬hing)); + case uint16_t(Op::F64ConvertI32U): { + if (!iter.readConversion(ValType::I32, ValType::F64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::F64ConvertI64S): case uint16_t(Op::F64ConvertI64U): - case uint16_t(Op::F64ReinterpretI64): - CHECK(iter.readConversion(ValType::I64, ValType::F64, ¬hing)); - case uint16_t(Op::F64PromoteF32): - CHECK(iter.readConversion(ValType::F32, ValType::F64, ¬hing)); + case uint16_t(Op::F64ReinterpretI64): { + if (!iter.readConversion(ValType::I64, ValType::F64, ¬hing)) { + return false; + } + break; + } + case uint16_t(Op::F64PromoteF32): { + if (!iter.readConversion(ValType::F32, ValType::F64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I32Extend8S): - case uint16_t(Op::I32Extend16S): - CHECK(iter.readConversion(ValType::I32, ValType::I32, ¬hing)); + case uint16_t(Op::I32Extend16S): { + if (!iter.readConversion(ValType::I32, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I64Extend8S): case uint16_t(Op::I64Extend16S): - case uint16_t(Op::I64Extend32S): - CHECK(iter.readConversion(ValType::I64, ValType::I64, ¬hing)); + case uint16_t(Op::I64Extend32S): { + if (!iter.readConversion(ValType::I64, ValType::I64, ¬hing)) { + return false; + } + break; + } case uint16_t(Op::I32Load8S): case uint16_t(Op::I32Load8U): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I32, 1, &addr)); + if (!iter.readLoad(ValType::I32, 1, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I32Load16S): case uint16_t(Op::I32Load16U): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I32, 2, &addr)); + if (!iter.readLoad(ValType::I32, 2, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I32Load): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I32, 4, &addr)); + if (!iter.readLoad(ValType::I32, 4, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Load8S): case uint16_t(Op::I64Load8U): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I64, 1, &addr)); + if (!iter.readLoad(ValType::I64, 1, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Load16S): case uint16_t(Op::I64Load16U): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I64, 2, &addr)); + if (!iter.readLoad(ValType::I64, 2, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Load32S): case uint16_t(Op::I64Load32U): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I64, 4, &addr)); + if (!iter.readLoad(ValType::I64, 4, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Load): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::I64, 8, &addr)); + if (!iter.readLoad(ValType::I64, 8, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::F32Load): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::F32, 4, &addr)); + if (!iter.readLoad(ValType::F32, 4, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::F64Load): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::F64, 8, &addr)); + if (!iter.readLoad(ValType::F64, 8, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I32Store8): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I32, 1, &addr, ¬hing)); + if (!iter.readStore(ValType::I32, 1, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I32Store16): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I32, 2, &addr, ¬hing)); + if (!iter.readStore(ValType::I32, 2, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I32Store): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I32, 4, &addr, ¬hing)); + if (!iter.readStore(ValType::I32, 4, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Store8): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I64, 1, &addr, ¬hing)); + if (!iter.readStore(ValType::I64, 1, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Store16): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I64, 2, &addr, ¬hing)); + if (!iter.readStore(ValType::I64, 2, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Store32): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I64, 4, &addr, ¬hing)); + if (!iter.readStore(ValType::I64, 4, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::I64Store): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::I64, 8, &addr, ¬hing)); + if (!iter.readStore(ValType::I64, 8, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::F32Store): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::F32, 4, &addr, ¬hing)); + if (!iter.readStore(ValType::F32, 4, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::F64Store): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::F64, 8, &addr, ¬hing)); + if (!iter.readStore(ValType::F64, 8, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint16_t(Op::MemoryGrow): { uint32_t memoryIndex; - CHECK(iter.readMemoryGrow(&memoryIndex, ¬hing)); + if (!iter.readMemoryGrow(&memoryIndex, ¬hing)) { + return false; + } + dumper.dumpMemoryIndex(memoryIndex); + break; } case uint16_t(Op::MemorySize): { uint32_t memoryIndex; - CHECK(iter.readMemorySize(&memoryIndex)); + if (!iter.readMemorySize(&memoryIndex)) { + return false; + } + dumper.dumpMemoryIndex(memoryIndex); + break; } case uint16_t(Op::Br): { - uint32_t unusedDepth; - CHECK(iter.readBr(&unusedDepth, &unusedType, ¬hings)); + uint32_t depth; + if (!iter.readBr(&depth, &resultType, ¬hings)) { + return false; + } + dumper.dumpBlockDepth(depth); + break; } case uint16_t(Op::BrIf): { - uint32_t unusedDepth; - CHECK(iter.readBrIf(&unusedDepth, &unusedType, ¬hings, ¬hing)); + uint32_t depth; + if (!iter.readBrIf(&depth, &resultType, ¬hings, ¬hing)) { + return false; + } + dumper.dumpBlockDepth(depth); + break; } case uint16_t(Op::BrTable): { - Uint32Vector unusedDepths; - uint32_t unusedDefault; - CHECK(iter.readBrTable(&unusedDepths, &unusedDefault, &unusedType, - ¬hings, ¬hing)); - } - case uint16_t(Op::Return): - CHECK(iter.readReturn(¬hings)); - case uint16_t(Op::Unreachable): - CHECK(iter.readUnreachable()); -#ifdef ENABLE_WASM_GC - case uint16_t(Op::GcPrefix): { - if (!env.gcEnabled()) { - return iter.unrecognizedOpcode(&op); + Uint32Vector depths; + uint32_t defaultDepth; + if (!iter.readBrTable(&depths, &defaultDepth, &resultType, ¬hings, + ¬hing)) { + return false; } + dumper.dumpBlockDepths(depths); + dumper.dumpBlockDepth(defaultDepth); + break; + } + case uint16_t(Op::Return): { + if (!iter.readReturn(¬hings)) { + return false; + } + break; + } + case uint16_t(Op::Unreachable): { + if (!iter.readUnreachable()) { + return false; + } + break; + } + case uint16_t(Op::GcPrefix): { switch (op.b1) { case uint32_t(GcOp::StructNew): { - uint32_t unusedUint; + uint32_t typeIndex; NothingVector unusedArgs{}; - CHECK(iter.readStructNew(&unusedUint, &unusedArgs)); + if (!iter.readStructNew(&typeIndex, &unusedArgs)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::StructNewDefault): { - uint32_t unusedUint; - CHECK(iter.readStructNewDefault(&unusedUint)); + uint32_t typeIndex; + if (!iter.readStructNewDefault(&typeIndex)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::StructGet): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readStructGet(&unusedUint1, &unusedUint2, - FieldWideningOp::None, ¬hing)); + uint32_t typeIndex, fieldIndex; + if (!iter.readStructGet(&typeIndex, &fieldIndex, + FieldWideningOp::None, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpFieldIndex(fieldIndex); + break; } case uint32_t(GcOp::StructGetS): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readStructGet(&unusedUint1, &unusedUint2, - FieldWideningOp::Signed, ¬hing)); + uint32_t typeIndex, fieldIndex; + if (!iter.readStructGet(&typeIndex, &fieldIndex, + FieldWideningOp::Signed, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpFieldIndex(fieldIndex); + break; } case uint32_t(GcOp::StructGetU): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readStructGet(&unusedUint1, &unusedUint2, - FieldWideningOp::Unsigned, ¬hing)); + uint32_t typeIndex, fieldIndex; + if (!iter.readStructGet(&typeIndex, &fieldIndex, + FieldWideningOp::Unsigned, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpFieldIndex(fieldIndex); + break; } case uint32_t(GcOp::StructSet): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readStructSet(&unusedUint1, &unusedUint2, ¬hing, - ¬hing)); + uint32_t typeIndex, fieldIndex; + if (!iter.readStructSet(&typeIndex, &fieldIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpFieldIndex(fieldIndex); + break; } case uint32_t(GcOp::ArrayNew): { - uint32_t unusedUint; - CHECK(iter.readArrayNew(&unusedUint, ¬hing, ¬hing)); + uint32_t typeIndex; + if (!iter.readArrayNew(&typeIndex, ¬hing, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::ArrayNewFixed): { - uint32_t unusedUint1, unusedUint2; - CHECK( - iter.readArrayNewFixed(&unusedUint1, &unusedUint2, ¬hings)); + uint32_t typeIndex, numElements; + if (!iter.readArrayNewFixed(&typeIndex, &numElements, ¬hings)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpNumElements(numElements); + break; } case uint32_t(GcOp::ArrayNewDefault): { - uint32_t unusedUint; - CHECK(iter.readArrayNewDefault(&unusedUint, ¬hing)); + uint32_t typeIndex; + if (!iter.readArrayNewDefault(&typeIndex, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::ArrayNewData): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readArrayNewData(&unusedUint1, &unusedUint2, ¬hing, - ¬hing)); + uint32_t typeIndex, dataIndex; + if (!iter.readArrayNewData(&typeIndex, &dataIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpDataIndex(dataIndex); + break; } case uint32_t(GcOp::ArrayNewElem): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readArrayNewElem(&unusedUint1, &unusedUint2, ¬hing, - ¬hing)); + uint32_t typeIndex, elemIndex; + if (!iter.readArrayNewElem(&typeIndex, &elemIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpElemIndex(elemIndex); + break; } case uint32_t(GcOp::ArrayInitData): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readArrayInitData(&unusedUint1, &unusedUint2, ¬hing, - ¬hing, ¬hing, ¬hing)); + uint32_t typeIndex, dataIndex; + if (!iter.readArrayInitData(&typeIndex, &dataIndex, ¬hing, + ¬hing, ¬hing, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpDataIndex(dataIndex); + break; } case uint32_t(GcOp::ArrayInitElem): { - uint32_t unusedUint1, unusedUint2; - CHECK(iter.readArrayInitElem(&unusedUint1, &unusedUint2, ¬hing, - ¬hing, ¬hing, ¬hing)); + uint32_t typeIndex, elemIndex; + if (!iter.readArrayInitElem(&typeIndex, &elemIndex, ¬hing, + ¬hing, ¬hing, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + dumper.dumpElemIndex(elemIndex); + break; } case uint32_t(GcOp::ArrayGet): { - uint32_t unusedUint1; - CHECK(iter.readArrayGet(&unusedUint1, FieldWideningOp::None, - ¬hing, ¬hing)); + uint32_t typeIndex; + if (!iter.readArrayGet(&typeIndex, FieldWideningOp::None, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::ArrayGetS): { - uint32_t unusedUint1; - CHECK(iter.readArrayGet(&unusedUint1, FieldWideningOp::Signed, - ¬hing, ¬hing)); + uint32_t typeIndex; + if (!iter.readArrayGet(&typeIndex, FieldWideningOp::Signed, + ¬hing, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::ArrayGetU): { - uint32_t unusedUint1; - CHECK(iter.readArrayGet(&unusedUint1, FieldWideningOp::Unsigned, - ¬hing, ¬hing)); + uint32_t typeIndex; + if (!iter.readArrayGet(&typeIndex, FieldWideningOp::Unsigned, + ¬hing, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::ArraySet): { - uint32_t unusedUint1; - CHECK( - iter.readArraySet(&unusedUint1, ¬hing, ¬hing, ¬hing)); + uint32_t typeIndex; + if (!iter.readArraySet(&typeIndex, ¬hing, ¬hing, ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::ArrayLen): { - CHECK(iter.readArrayLen(¬hing)); + if (!iter.readArrayLen(¬hing)) { + return false; + } + break; } case uint32_t(GcOp::ArrayCopy): { - int32_t unusedInt; - bool unusedBool; - CHECK(iter.readArrayCopy(&unusedInt, &unusedBool, ¬hing, - ¬hing, ¬hing, ¬hing, ¬hing)); + uint32_t dstArrayTypeIndex; + uint32_t srcArrayTypeIndex; + if (!iter.readArrayCopy(&dstArrayTypeIndex, &srcArrayTypeIndex, + ¬hing, ¬hing, ¬hing, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTypeIndex(dstArrayTypeIndex); + dumper.dumpTypeIndex(srcArrayTypeIndex); + break; } case uint32_t(GcOp::ArrayFill): { - uint32_t unusedTypeIndex; - CHECK(iter.readArrayFill(&unusedTypeIndex, ¬hing, ¬hing, - ¬hing, ¬hing)); + uint32_t typeIndex; + if (!iter.readArrayFill(&typeIndex, ¬hing, ¬hing, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTypeIndex(typeIndex); + break; } case uint32_t(GcOp::RefI31): { - CHECK(iter.readConversion(ValType::I32, - ValType(RefType::i31().asNonNullable()), - ¬hing)); + if (!iter.readConversion(ValType::I32, + ValType(RefType::i31().asNonNullable()), + ¬hing)) { + return false; + } + break; } case uint32_t(GcOp::I31GetS): { - CHECK(iter.readConversion(ValType(RefType::i31()), ValType::I32, - ¬hing)); + if (!iter.readConversion(ValType(RefType::i31()), ValType::I32, + ¬hing)) { + return false; + } + break; } case uint32_t(GcOp::I31GetU): { - CHECK(iter.readConversion(ValType(RefType::i31()), ValType::I32, - ¬hing)); + if (!iter.readConversion(ValType(RefType::i31()), ValType::I32, + ¬hing)) { + return false; + } + break; } case uint16_t(GcOp::RefTest): { - RefType unusedSourceType; - RefType unusedDestType; - CHECK(iter.readRefTest(false, &unusedSourceType, &unusedDestType, - ¬hing)); + RefType srcType; + RefType destType; + if (!iter.readRefTest(false, &srcType, &destType, ¬hing)) { + return false; + } + dumper.dumpRefType(destType); + break; } case uint16_t(GcOp::RefTestNull): { - RefType unusedSourceType; - RefType unusedDestType; - CHECK(iter.readRefTest(true, &unusedSourceType, &unusedDestType, - ¬hing)); + RefType srcType; + RefType destType; + if (!iter.readRefTest(true, &srcType, &destType, ¬hing)) { + return false; + } + dumper.dumpRefType(srcType); + dumper.dumpRefType(destType); + break; } case uint16_t(GcOp::RefCast): { - RefType unusedSourceType; - RefType unusedDestType; - CHECK(iter.readRefCast(false, &unusedSourceType, &unusedDestType, - ¬hing)); + RefType srcType; + RefType destType; + if (!iter.readRefCast(false, &srcType, &destType, ¬hing)) { + return false; + } + dumper.dumpRefType(destType); + break; } case uint16_t(GcOp::RefCastNull): { - RefType unusedSourceType; - RefType unusedDestType; - CHECK(iter.readRefCast(true, &unusedSourceType, &unusedDestType, - ¬hing)); + RefType srcType; + RefType destType; + if (!iter.readRefCast(true, &srcType, &destType, ¬hing)) { + return false; + } + dumper.dumpRefType(destType); + break; } case uint16_t(GcOp::BrOnCast): { - uint32_t unusedRelativeDepth; - RefType unusedSourceType; - RefType unusedDestType; - CHECK(iter.readBrOnCast(true, &unusedRelativeDepth, - &unusedSourceType, &unusedDestType, - &unusedType, ¬hings)); + uint32_t relativeDepth; + RefType srcType; + RefType destType; + if (!iter.readBrOnCast(true, &relativeDepth, &srcType, &destType, + &resultType, ¬hings)) { + return false; + } + dumper.dumpBlockDepth(relativeDepth); + dumper.dumpRefType(srcType); + dumper.dumpRefType(destType); + break; } case uint16_t(GcOp::BrOnCastFail): { - uint32_t unusedRelativeDepth; - RefType unusedSourceType; - RefType unusedDestType; - CHECK(iter.readBrOnCast(false, &unusedRelativeDepth, - &unusedSourceType, &unusedDestType, - &unusedType, ¬hings)); + uint32_t relativeDepth; + RefType srcType; + RefType destType; + if (!iter.readBrOnCast(false, &relativeDepth, &srcType, &destType, + &resultType, ¬hings)) { + return false; + } + dumper.dumpBlockDepth(relativeDepth); + dumper.dumpRefType(srcType); + dumper.dumpRefType(destType); + break; } case uint16_t(GcOp::AnyConvertExtern): { - CHECK(iter.readRefConversion(RefType::extern_(), RefType::any(), - ¬hing)); + if (!iter.readRefConversion(RefType::extern_(), RefType::any(), + ¬hing)) { + return false; + } + break; } case uint16_t(GcOp::ExternConvertAny): { - CHECK(iter.readRefConversion(RefType::any(), RefType::extern_(), - ¬hing)); + if (!iter.readRefConversion(RefType::any(), RefType::extern_(), + ¬hing)) { + return false; + } + break; } default: return iter.unrecognizedOpcode(&op); } break; } -#endif #ifdef ENABLE_WASM_SIMD case uint16_t(Op::SimdPrefix): { - if (!env.simdAvailable()) { + if (!codeMeta.simdAvailable()) { return iter.unrecognizedOpcode(&op); } - uint32_t noIndex; + uint32_t laneIndex; switch (op.b1) { case uint32_t(SimdOp::I8x16ExtractLaneS): - case uint32_t(SimdOp::I8x16ExtractLaneU): - CHECK(iter.readExtractLane(ValType::I32, 16, &noIndex, ¬hing)); + case uint32_t(SimdOp::I8x16ExtractLaneU): { + if (!iter.readExtractLane(ValType::I32, 16, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } case uint32_t(SimdOp::I16x8ExtractLaneS): - case uint32_t(SimdOp::I16x8ExtractLaneU): - CHECK(iter.readExtractLane(ValType::I32, 8, &noIndex, ¬hing)); - case uint32_t(SimdOp::I32x4ExtractLane): - CHECK(iter.readExtractLane(ValType::I32, 4, &noIndex, ¬hing)); - case uint32_t(SimdOp::I64x2ExtractLane): - CHECK(iter.readExtractLane(ValType::I64, 2, &noIndex, ¬hing)); - case uint32_t(SimdOp::F32x4ExtractLane): - CHECK(iter.readExtractLane(ValType::F32, 4, &noIndex, ¬hing)); - case uint32_t(SimdOp::F64x2ExtractLane): - CHECK(iter.readExtractLane(ValType::F64, 2, &noIndex, ¬hing)); + case uint32_t(SimdOp::I16x8ExtractLaneU): { + if (!iter.readExtractLane(ValType::I32, 8, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::I32x4ExtractLane): { + if (!iter.readExtractLane(ValType::I32, 4, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::I64x2ExtractLane): { + if (!iter.readExtractLane(ValType::I64, 2, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::F32x4ExtractLane): { + if (!iter.readExtractLane(ValType::F32, 4, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::F64x2ExtractLane): { + if (!iter.readExtractLane(ValType::F64, 2, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } case uint32_t(SimdOp::I8x16Splat): case uint32_t(SimdOp::I16x8Splat): - case uint32_t(SimdOp::I32x4Splat): - CHECK(iter.readConversion(ValType::I32, ValType::V128, ¬hing)); - case uint32_t(SimdOp::I64x2Splat): - CHECK(iter.readConversion(ValType::I64, ValType::V128, ¬hing)); - case uint32_t(SimdOp::F32x4Splat): - CHECK(iter.readConversion(ValType::F32, ValType::V128, ¬hing)); - case uint32_t(SimdOp::F64x2Splat): - CHECK(iter.readConversion(ValType::F64, ValType::V128, ¬hing)); + case uint32_t(SimdOp::I32x4Splat): { + if (!iter.readConversion(ValType::I32, ValType::V128, ¬hing)) { + return false; + } + break; + } + case uint32_t(SimdOp::I64x2Splat): { + if (!iter.readConversion(ValType::I64, ValType::V128, ¬hing)) { + return false; + } + break; + } + case uint32_t(SimdOp::F32x4Splat): { + if (!iter.readConversion(ValType::F32, ValType::V128, ¬hing)) { + return false; + } + break; + } + case uint32_t(SimdOp::F64x2Splat): { + if (!iter.readConversion(ValType::F64, ValType::V128, ¬hing)) { + return false; + } + break; + } case uint32_t(SimdOp::V128AnyTrue): case uint32_t(SimdOp::I8x16AllTrue): @@ -834,27 +1292,61 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(SimdOp::I8x16Bitmask): case uint32_t(SimdOp::I16x8Bitmask): case uint32_t(SimdOp::I32x4Bitmask): - case uint32_t(SimdOp::I64x2Bitmask): - CHECK(iter.readConversion(ValType::V128, ValType::I32, ¬hing)); + case uint32_t(SimdOp::I64x2Bitmask): { + if (!iter.readConversion(ValType::V128, ValType::I32, ¬hing)) { + return false; + } + break; + } - case uint32_t(SimdOp::I8x16ReplaceLane): - CHECK(iter.readReplaceLane(ValType::I32, 16, &noIndex, ¬hing, - ¬hing)); - case uint32_t(SimdOp::I16x8ReplaceLane): - CHECK(iter.readReplaceLane(ValType::I32, 8, &noIndex, ¬hing, - ¬hing)); - case uint32_t(SimdOp::I32x4ReplaceLane): - CHECK(iter.readReplaceLane(ValType::I32, 4, &noIndex, ¬hing, - ¬hing)); - case uint32_t(SimdOp::I64x2ReplaceLane): - CHECK(iter.readReplaceLane(ValType::I64, 2, &noIndex, ¬hing, - ¬hing)); - case uint32_t(SimdOp::F32x4ReplaceLane): - CHECK(iter.readReplaceLane(ValType::F32, 4, &noIndex, ¬hing, - ¬hing)); - case uint32_t(SimdOp::F64x2ReplaceLane): - CHECK(iter.readReplaceLane(ValType::F64, 2, &noIndex, ¬hing, - ¬hing)); + case uint32_t(SimdOp::I8x16ReplaceLane): { + if (!iter.readReplaceLane(ValType::I32, 16, &laneIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::I16x8ReplaceLane): { + if (!iter.readReplaceLane(ValType::I32, 8, &laneIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::I32x4ReplaceLane): { + if (!iter.readReplaceLane(ValType::I32, 4, &laneIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::I64x2ReplaceLane): { + if (!iter.readReplaceLane(ValType::I64, 2, &laneIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::F32x4ReplaceLane): { + if (!iter.readReplaceLane(ValType::F32, 4, &laneIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } + case uint32_t(SimdOp::F64x2ReplaceLane): { + if (!iter.readReplaceLane(ValType::F64, 2, &laneIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLaneIndex(laneIndex); + break; + } case uint32_t(SimdOp::I8x16Eq): case uint32_t(SimdOp::I8x16Ne): @@ -975,8 +1467,12 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(SimdOp::I64x2ExtmulHighI32x4S): case uint32_t(SimdOp::I64x2ExtmulLowI32x4U): case uint32_t(SimdOp::I64x2ExtmulHighI32x4U): - case uint32_t(SimdOp::I16x8Q15MulrSatS): - CHECK(iter.readBinary(ValType::V128, ¬hing, ¬hing)); + case uint32_t(SimdOp::I16x8Q15MulrSatS): { + if (!iter.readBinary(ValType::V128, ¬hing, ¬hing)) { + return false; + } + break; + } case uint32_t(SimdOp::I8x16Neg): case uint32_t(SimdOp::I16x8Neg): @@ -1027,8 +1523,12 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(SimdOp::I16x8ExtaddPairwiseI8x16S): case uint32_t(SimdOp::I16x8ExtaddPairwiseI8x16U): case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8S): - case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8U): - CHECK(iter.readUnary(ValType::V128, ¬hing)); + case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8U): { + if (!iter.readUnary(ValType::V128, ¬hing)) { + return false; + } + break; + } case uint32_t(SimdOp::I8x16Shl): case uint32_t(SimdOp::I8x16ShrS): @@ -1041,119 +1541,219 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(SimdOp::I32x4ShrU): case uint32_t(SimdOp::I64x2Shl): case uint32_t(SimdOp::I64x2ShrS): - case uint32_t(SimdOp::I64x2ShrU): - CHECK(iter.readVectorShift(¬hing, ¬hing)); + case uint32_t(SimdOp::I64x2ShrU): { + if (!iter.readVectorShift(¬hing, ¬hing)) { + return false; + } + break; + } - case uint32_t(SimdOp::V128Bitselect): - CHECK( - iter.readTernary(ValType::V128, ¬hing, ¬hing, ¬hing)); + case uint32_t(SimdOp::V128Bitselect): { + if (!iter.readTernary(ValType::V128, ¬hing, ¬hing, + ¬hing)) { + return false; + } + break; + } case uint32_t(SimdOp::I8x16Shuffle): { V128 mask; - CHECK(iter.readVectorShuffle(¬hing, ¬hing, &mask)); + if (!iter.readVectorShuffle(¬hing, ¬hing, &mask)) { + return false; + } + dumper.dumpVectorMask(mask); + break; } case uint32_t(SimdOp::V128Const): { - V128 noVector; - CHECK(iter.readV128Const(&noVector)); + V128 constant; + if (!iter.readV128Const(&constant)) { + return false; + } + dumper.dumpV128Const(constant); + break; } case uint32_t(SimdOp::V128Load): { LinearMemoryAddress addr; - CHECK(iter.readLoad(ValType::V128, 16, &addr)); + if (!iter.readLoad(ValType::V128, 16, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load8Splat): { LinearMemoryAddress addr; - CHECK(iter.readLoadSplat(1, &addr)); + if (!iter.readLoadSplat(1, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load16Splat): { LinearMemoryAddress addr; - CHECK(iter.readLoadSplat(2, &addr)); + if (!iter.readLoadSplat(2, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load32Splat): { LinearMemoryAddress addr; - CHECK(iter.readLoadSplat(4, &addr)); + if (!iter.readLoadSplat(4, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load64Splat): { LinearMemoryAddress addr; - CHECK(iter.readLoadSplat(8, &addr)); + if (!iter.readLoadSplat(8, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load8x8S): case uint32_t(SimdOp::V128Load8x8U): { LinearMemoryAddress addr; - CHECK(iter.readLoadExtend(&addr)); + if (!iter.readLoadExtend(&addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load16x4S): case uint32_t(SimdOp::V128Load16x4U): { LinearMemoryAddress addr; - CHECK(iter.readLoadExtend(&addr)); + if (!iter.readLoadExtend(&addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load32x2S): case uint32_t(SimdOp::V128Load32x2U): { LinearMemoryAddress addr; - CHECK(iter.readLoadExtend(&addr)); + if (!iter.readLoadExtend(&addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Store): { LinearMemoryAddress addr; - CHECK(iter.readStore(ValType::V128, 16, &addr, ¬hing)); + if (!iter.readStore(ValType::V128, 16, &addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load32Zero): { LinearMemoryAddress addr; - CHECK(iter.readLoadSplat(4, &addr)); + if (!iter.readLoadSplat(4, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load64Zero): { LinearMemoryAddress addr; - CHECK(iter.readLoadSplat(8, &addr)); + if (!iter.readLoadSplat(8, &addr)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(SimdOp::V128Load8Lane): { LinearMemoryAddress addr; - CHECK(iter.readLoadLane(1, &addr, &noIndex, ¬hing)); + if (!iter.readLoadLane(1, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Load16Lane): { LinearMemoryAddress addr; - CHECK(iter.readLoadLane(2, &addr, &noIndex, ¬hing)); + if (!iter.readLoadLane(2, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Load32Lane): { LinearMemoryAddress addr; - CHECK(iter.readLoadLane(4, &addr, &noIndex, ¬hing)); + if (!iter.readLoadLane(4, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Load64Lane): { LinearMemoryAddress addr; - CHECK(iter.readLoadLane(8, &addr, &noIndex, ¬hing)); + if (!iter.readLoadLane(8, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Store8Lane): { LinearMemoryAddress addr; - CHECK(iter.readStoreLane(1, &addr, &noIndex, ¬hing)); + if (!iter.readStoreLane(1, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Store16Lane): { LinearMemoryAddress addr; - CHECK(iter.readStoreLane(2, &addr, &noIndex, ¬hing)); + if (!iter.readStoreLane(2, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Store32Lane): { LinearMemoryAddress addr; - CHECK(iter.readStoreLane(4, &addr, &noIndex, ¬hing)); + if (!iter.readStoreLane(4, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } case uint32_t(SimdOp::V128Store64Lane): { LinearMemoryAddress addr; - CHECK(iter.readStoreLane(8, &addr, &noIndex, ¬hing)); + if (!iter.readStoreLane(8, &addr, &laneIndex, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + dumper.dumpLaneIndex(laneIndex); + break; } # ifdef ENABLE_WASM_RELAXED_SIMD @@ -1165,38 +1765,50 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(SimdOp::I16x8RelaxedLaneSelect): case uint32_t(SimdOp::I32x4RelaxedLaneSelect): case uint32_t(SimdOp::I64x2RelaxedLaneSelect): - case uint32_t(SimdOp::I32x4DotI8x16I7x16AddS): { - if (!env.v128RelaxedEnabled()) { + case uint32_t(SimdOp::I32x4RelaxedDotI8x16I7x16AddS): { + if (!codeMeta.v128RelaxedEnabled()) { return iter.unrecognizedOpcode(&op); } - CHECK( - iter.readTernary(ValType::V128, ¬hing, ¬hing, ¬hing)); + if (!iter.readTernary(ValType::V128, ¬hing, ¬hing, + ¬hing)) { + return false; + } + break; } case uint32_t(SimdOp::F32x4RelaxedMin): case uint32_t(SimdOp::F32x4RelaxedMax): case uint32_t(SimdOp::F64x2RelaxedMin): case uint32_t(SimdOp::F64x2RelaxedMax): case uint32_t(SimdOp::I16x8RelaxedQ15MulrS): - case uint32_t(SimdOp::I16x8DotI8x16I7x16S): { - if (!env.v128RelaxedEnabled()) { + case uint32_t(SimdOp::I16x8RelaxedDotI8x16I7x16S): { + if (!codeMeta.v128RelaxedEnabled()) { return iter.unrecognizedOpcode(&op); } - CHECK(iter.readBinary(ValType::V128, ¬hing, ¬hing)); + if (!iter.readBinary(ValType::V128, ¬hing, ¬hing)) { + return false; + } + break; } case uint32_t(SimdOp::I32x4RelaxedTruncF32x4S): case uint32_t(SimdOp::I32x4RelaxedTruncF32x4U): case uint32_t(SimdOp::I32x4RelaxedTruncF64x2SZero): case uint32_t(SimdOp::I32x4RelaxedTruncF64x2UZero): { - if (!env.v128RelaxedEnabled()) { + if (!codeMeta.v128RelaxedEnabled()) { return iter.unrecognizedOpcode(&op); } - CHECK(iter.readUnary(ValType::V128, ¬hing)); + if (!iter.readUnary(ValType::V128, ¬hing)) { + return false; + } + break; } case uint32_t(SimdOp::I8x16RelaxedSwizzle): { - if (!env.v128RelaxedEnabled()) { + if (!codeMeta.v128RelaxedEnabled()) { return iter.unrecognizedOpcode(&op); } - CHECK(iter.readBinary(ValType::V128, ¬hing, ¬hing)); + if (!iter.readBinary(ValType::V128, ¬hing, ¬hing)) { + return false; + } + break; } # endif @@ -1210,248 +1822,418 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint16_t(Op::MiscPrefix): { switch (op.b1) { case uint32_t(MiscOp::I32TruncSatF32S): - case uint32_t(MiscOp::I32TruncSatF32U): - CHECK(iter.readConversion(ValType::F32, ValType::I32, ¬hing)); + case uint32_t(MiscOp::I32TruncSatF32U): { + if (!iter.readConversion(ValType::F32, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint32_t(MiscOp::I32TruncSatF64S): - case uint32_t(MiscOp::I32TruncSatF64U): - CHECK(iter.readConversion(ValType::F64, ValType::I32, ¬hing)); + case uint32_t(MiscOp::I32TruncSatF64U): { + if (!iter.readConversion(ValType::F64, ValType::I32, ¬hing)) { + return false; + } + break; + } case uint32_t(MiscOp::I64TruncSatF32S): - case uint32_t(MiscOp::I64TruncSatF32U): - CHECK(iter.readConversion(ValType::F32, ValType::I64, ¬hing)); + case uint32_t(MiscOp::I64TruncSatF32U): { + if (!iter.readConversion(ValType::F32, ValType::I64, ¬hing)) { + return false; + } + break; + } case uint32_t(MiscOp::I64TruncSatF64S): - case uint32_t(MiscOp::I64TruncSatF64U): - CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing)); + case uint32_t(MiscOp::I64TruncSatF64U): { + if (!iter.readConversion(ValType::F64, ValType::I64, ¬hing)) { + return false; + } + break; + } case uint32_t(MiscOp::MemoryCopy): { - uint32_t unusedDestMemIndex; - uint32_t unusedSrcMemIndex; - CHECK(iter.readMemOrTableCopy(/*isMem=*/true, &unusedDestMemIndex, - ¬hing, &unusedSrcMemIndex, - ¬hing, ¬hing)); + uint32_t destMemIndex; + uint32_t srcMemIndex; + if (!iter.readMemOrTableCopy(/*isMem=*/true, &destMemIndex, + ¬hing, &srcMemIndex, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpMemoryIndex(destMemIndex); + dumper.dumpMemoryIndex(srcMemIndex); + break; } case uint32_t(MiscOp::DataDrop): { - uint32_t unusedSegIndex; - CHECK(iter.readDataOrElemDrop(/*isData=*/true, &unusedSegIndex)); + uint32_t dataIndex; + if (!iter.readDataOrElemDrop(/*isData=*/true, &dataIndex)) { + return false; + } + dumper.dumpDataIndex(dataIndex); + break; } case uint32_t(MiscOp::MemoryFill): { uint32_t memoryIndex; - CHECK(iter.readMemFill(&memoryIndex, ¬hing, ¬hing, ¬hing)); + if (!iter.readMemFill(&memoryIndex, ¬hing, ¬hing, ¬hing)) { + return false; + } + dumper.dumpMemoryIndex(memoryIndex); + break; } case uint32_t(MiscOp::MemoryInit): { - uint32_t unusedSegIndex; - uint32_t unusedMemoryIndex; - CHECK(iter.readMemOrTableInit(/*isMem=*/true, &unusedSegIndex, - &unusedMemoryIndex, ¬hing, - ¬hing, ¬hing)); + uint32_t dataIndex; + uint32_t memoryIndex; + if (!iter.readMemOrTableInit(/*isMem=*/true, &dataIndex, + &memoryIndex, ¬hing, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpMemoryIndex(memoryIndex); + dumper.dumpDataIndex(dataIndex); + break; } case uint32_t(MiscOp::TableCopy): { - uint32_t unusedDestTableIndex; - uint32_t unusedSrcTableIndex; - CHECK(iter.readMemOrTableCopy( - /*isMem=*/false, &unusedDestTableIndex, ¬hing, - &unusedSrcTableIndex, ¬hing, ¬hing)); + uint32_t destTableIndex; + uint32_t srcTableIndex; + if (!iter.readMemOrTableCopy( + /*isMem=*/false, &destTableIndex, ¬hing, &srcTableIndex, + ¬hing, ¬hing)) { + return false; + } + dumper.dumpTableIndex(destTableIndex); + dumper.dumpTableIndex(srcTableIndex); + break; } case uint32_t(MiscOp::ElemDrop): { - uint32_t unusedSegIndex; - CHECK(iter.readDataOrElemDrop(/*isData=*/false, &unusedSegIndex)); + uint32_t elemIndex; + if (!iter.readDataOrElemDrop(/*isData=*/false, &elemIndex)) { + return false; + } + dumper.dumpElemIndex(elemIndex); + break; } case uint32_t(MiscOp::TableInit): { - uint32_t unusedSegIndex; - uint32_t unusedTableIndex; - CHECK(iter.readMemOrTableInit(/*isMem=*/false, &unusedSegIndex, - &unusedTableIndex, ¬hing, ¬hing, - ¬hing)); + uint32_t elemIndex; + uint32_t tableIndex; + if (!iter.readMemOrTableInit(/*isMem=*/false, &elemIndex, + &tableIndex, ¬hing, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + dumper.dumpElemIndex(elemIndex); + break; } case uint32_t(MiscOp::TableFill): { - uint32_t unusedTableIndex; - CHECK(iter.readTableFill(&unusedTableIndex, ¬hing, ¬hing, - ¬hing)); + uint32_t tableIndex; + if (!iter.readTableFill(&tableIndex, ¬hing, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + break; } #ifdef ENABLE_WASM_MEMORY_CONTROL case uint32_t(MiscOp::MemoryDiscard): { - if (!env.memoryControlEnabled()) { + if (!codeMeta.memoryControlEnabled()) { return iter.unrecognizedOpcode(&op); } - uint32_t unusedMemoryIndex; - CHECK(iter.readMemDiscard(&unusedMemoryIndex, ¬hing, ¬hing)); + uint32_t memoryIndex; + if (!iter.readMemDiscard(&memoryIndex, ¬hing, ¬hing)) { + return false; + } + dumper.dumpMemoryIndex(memoryIndex); + break; } #endif case uint32_t(MiscOp::TableGrow): { - uint32_t unusedTableIndex; - CHECK(iter.readTableGrow(&unusedTableIndex, ¬hing, ¬hing)); + uint32_t tableIndex; + if (!iter.readTableGrow(&tableIndex, ¬hing, ¬hing)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + break; } case uint32_t(MiscOp::TableSize): { - uint32_t unusedTableIndex; - CHECK(iter.readTableSize(&unusedTableIndex)); + uint32_t tableIndex; + if (!iter.readTableSize(&tableIndex)) { + return false; + } + dumper.dumpTableIndex(tableIndex); + break; } default: return iter.unrecognizedOpcode(&op); } break; } -#ifdef ENABLE_WASM_GC case uint16_t(Op::RefAsNonNull): { - if (!env.gcEnabled()) { - return iter.unrecognizedOpcode(&op); + if (!iter.readRefAsNonNull(¬hing)) { + return false; } - CHECK(iter.readRefAsNonNull(¬hing)); + break; } case uint16_t(Op::BrOnNull): { - if (!env.gcEnabled()) { - return iter.unrecognizedOpcode(&op); + uint32_t depth; + if (!iter.readBrOnNull(&depth, &resultType, ¬hings, ¬hing)) { + return false; } - uint32_t unusedDepth; - CHECK( - iter.readBrOnNull(&unusedDepth, &unusedType, ¬hings, ¬hing)); + dumper.dumpBlockDepth(depth); + break; } case uint16_t(Op::BrOnNonNull): { - if (!env.gcEnabled()) { - return iter.unrecognizedOpcode(&op); + uint32_t depth; + if (!iter.readBrOnNonNull(&depth, &resultType, ¬hings, ¬hing)) { + return false; } - uint32_t unusedDepth; - CHECK(iter.readBrOnNonNull(&unusedDepth, &unusedType, ¬hings, - ¬hing)); + dumper.dumpBlockDepth(depth); + break; } -#endif -#ifdef ENABLE_WASM_GC case uint16_t(Op::RefEq): { - if (!env.gcEnabled()) { - return iter.unrecognizedOpcode(&op); + if (!iter.readComparison(RefType::eq(), ¬hing, ¬hing)) { + return false; } - CHECK(iter.readComparison(RefType::eq(), ¬hing, ¬hing)); + break; } -#endif case uint16_t(Op::RefFunc): { - uint32_t unusedIndex; - CHECK(iter.readRefFunc(&unusedIndex)); + uint32_t funcIndex; + if (!iter.readRefFunc(&funcIndex)) { + return false; + } + dumper.dumpFuncIndex(funcIndex); + break; } case uint16_t(Op::RefNull): { RefType type; - CHECK(iter.readRefNull(&type)); + if (!iter.readRefNull(&type)) { + return false; + } + dumper.dumpHeapType(type); + break; } case uint16_t(Op::RefIsNull): { Nothing nothing; - CHECK(iter.readRefIsNull(¬hing)); + if (!iter.readRefIsNull(¬hing)) { + return false; + } + break; + } + case uint16_t(Op::Try): { + if (!iter.readTry(&blockType)) { + return false; + } + dumper.dumpBlockType(blockType); + break; } - case uint16_t(Op::Try): - CHECK(iter.readTry(&unusedType)); case uint16_t(Op::Catch): { LabelKind unusedKind; - uint32_t unusedIndex; - CHECK(iter.readCatch(&unusedKind, &unusedIndex, &unusedType, - &unusedType, ¬hings)); + uint32_t tagIndex; + if (!iter.readCatch(&unusedKind, &tagIndex, &resultType, &resultType, + ¬hings)) { + return false; + } + dumper.dumpTagIndex(tagIndex); + break; } case uint16_t(Op::CatchAll): { LabelKind unusedKind; - CHECK(iter.readCatchAll(&unusedKind, &unusedType, &unusedType, - ¬hings)); + if (!iter.readCatchAll(&unusedKind, &resultType, &resultType, + ¬hings)) { + return false; + } + break; } case uint16_t(Op::Delegate): { - uint32_t unusedDepth; - if (!iter.readDelegate(&unusedDepth, &unusedType, ¬hings)) { + uint32_t depth; + if (!iter.readDelegate(&depth, &resultType, ¬hings)) { return false; } iter.popDelegate(); + dumper.dumpBlockDepth(depth); break; } case uint16_t(Op::Throw): { - uint32_t unusedIndex; - CHECK(iter.readThrow(&unusedIndex, ¬hings)); + uint32_t tagIndex; + if (!iter.readThrow(&tagIndex, ¬hings)) { + return false; + } + dumper.dumpTagIndex(tagIndex); + break; } case uint16_t(Op::Rethrow): { - uint32_t unusedDepth; - CHECK(iter.readRethrow(&unusedDepth)); + uint32_t depth; + if (!iter.readRethrow(&depth)) { + return false; + } + dumper.dumpBlockDepth(depth); + break; } case uint16_t(Op::ThrowRef): { - if (!env.exnrefEnabled()) { + if (!codeMeta.exnrefEnabled()) { return iter.unrecognizedOpcode(&op); } - CHECK(iter.readThrowRef(¬hing)); + if (!iter.readThrowRef(¬hing)) { + return false; + } + break; } case uint16_t(Op::TryTable): { - if (!env.exnrefEnabled()) { + if (!codeMeta.exnrefEnabled()) { return iter.unrecognizedOpcode(&op); } TryTableCatchVector catches; - CHECK(iter.readTryTable(&unusedType, &catches)); + if (!iter.readTryTable(&blockType, &catches)) { + return false; + } + dumper.dumpTryTableCatches(catches); + break; } case uint16_t(Op::ThreadPrefix): { // Though thread ops can be used on nonshared memories, we make them // unavailable if shared memory has been disabled in the prefs, for // maximum predictability and safety and consistency with JS. - if (env.sharedMemoryEnabled() == Shareable::False) { + if (codeMeta.sharedMemoryEnabled() == Shareable::False) { return iter.unrecognizedOpcode(&op); } switch (op.b1) { - case uint32_t(ThreadOp::Wake): { + case uint32_t(ThreadOp::Notify): { LinearMemoryAddress addr; - CHECK(iter.readWake(&addr, ¬hing)); + if (!iter.readNotify(&addr, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32Wait): { LinearMemoryAddress addr; - CHECK(iter.readWait(&addr, ValType::I32, 4, ¬hing, ¬hing)); + if (!iter.readWait(&addr, ValType::I32, 4, ¬hing, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64Wait): { LinearMemoryAddress addr; - CHECK(iter.readWait(&addr, ValType::I64, 8, ¬hing, ¬hing)); + if (!iter.readWait(&addr, ValType::I64, 8, ¬hing, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::Fence): { - CHECK(iter.readFence()); + if (!iter.readFence()) { + return false; + } + break; } case uint32_t(ThreadOp::I32AtomicLoad): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I32, 4)); + if (!iter.readAtomicLoad(&addr, ValType::I32, 4)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicLoad): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I64, 8)); + if (!iter.readAtomicLoad(&addr, ValType::I64, 8)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicLoad8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I32, 1)); + if (!iter.readAtomicLoad(&addr, ValType::I32, 1)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicLoad16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I32, 2)); + if (!iter.readAtomicLoad(&addr, ValType::I32, 2)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicLoad8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I64, 1)); + if (!iter.readAtomicLoad(&addr, ValType::I64, 1)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicLoad16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I64, 2)); + if (!iter.readAtomicLoad(&addr, ValType::I64, 2)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicLoad32U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicLoad(&addr, ValType::I64, 4)); + if (!iter.readAtomicLoad(&addr, ValType::I64, 4)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicStore): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I32, 4, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I32, 4, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicStore): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I64, 8, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I64, 8, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicStore8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I32, 1, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I32, 1, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicStore16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I32, 2, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I32, 2, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicStore8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I64, 1, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I64, 1, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicStore16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I64, 2, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I64, 2, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicStore32U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicStore(&addr, ValType::I64, 4, ¬hing)); + if (!iter.readAtomicStore(&addr, ValType::I64, 4, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicAdd): case uint32_t(ThreadOp::I32AtomicSub): @@ -1460,7 +2242,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I32AtomicXor): case uint32_t(ThreadOp::I32AtomicXchg): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I32, 4, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I32, 4, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicAdd): case uint32_t(ThreadOp::I64AtomicSub): @@ -1469,7 +2255,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I64AtomicXor): case uint32_t(ThreadOp::I64AtomicXchg): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I64, 8, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I64, 8, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicAdd8U): case uint32_t(ThreadOp::I32AtomicSub8U): @@ -1478,7 +2268,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I32AtomicXor8U): case uint32_t(ThreadOp::I32AtomicXchg8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I32, 1, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I32, 1, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicAdd16U): case uint32_t(ThreadOp::I32AtomicSub16U): @@ -1487,7 +2281,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I32AtomicXor16U): case uint32_t(ThreadOp::I32AtomicXchg16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I32, 2, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I32, 2, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicAdd8U): case uint32_t(ThreadOp::I64AtomicSub8U): @@ -1496,7 +2294,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I64AtomicXor8U): case uint32_t(ThreadOp::I64AtomicXchg8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I64, 1, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I64, 1, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicAdd16U): case uint32_t(ThreadOp::I64AtomicSub16U): @@ -1505,7 +2307,11 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I64AtomicXor16U): case uint32_t(ThreadOp::I64AtomicXchg16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I64, 2, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I64, 2, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicAdd32U): case uint32_t(ThreadOp::I64AtomicSub32U): @@ -1514,42 +2320,74 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(ThreadOp::I64AtomicXor32U): case uint32_t(ThreadOp::I64AtomicXchg32U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicRMW(&addr, ValType::I64, 4, ¬hing)); + if (!iter.readAtomicRMW(&addr, ValType::I64, 4, ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicCmpXchg): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 4, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I32, 4, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicCmpXchg): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 8, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 8, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicCmpXchg8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 1, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I32, 1, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I32AtomicCmpXchg16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 2, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I32, 2, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicCmpXchg8U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 1, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 1, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicCmpXchg16U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 2, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 2, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } case uint32_t(ThreadOp::I64AtomicCmpXchg32U): { LinearMemoryAddress addr; - CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 4, ¬hing, - ¬hing)); + if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 4, ¬hing, + ¬hing)) { + return false; + } + dumper.dumpLinearMemoryAddress(addr); + break; } default: return iter.unrecognizedOpcode(&op); @@ -1561,25 +2399,43 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, default: return iter.unrecognizedOpcode(&op); } + + dumper.dumpOpEnd(); } MOZ_CRASH("unreachable"); - -#undef CHECK } -bool wasm::ValidateFunctionBody(const ModuleEnvironment& env, +template bool wasm::ValidateOps(ValidatingOpIter& iter, + NopOpDumper& dumper, + const CodeMetadata& codeMeta); +template bool wasm::ValidateOps(ValidatingOpIter& iter, + OpDumper& dumper, + const CodeMetadata& codeMeta); + +bool wasm::ValidateFunctionBody(const CodeMetadata& codeMeta, uint32_t funcIndex, uint32_t bodySize, Decoder& d) { const uint8_t* bodyBegin = d.currentPosition(); + const uint8_t* bodyEnd = bodyBegin + bodySize; ValTypeVector locals; - if (!DecodeLocalEntriesWithParams(d, env, funcIndex, &locals)) { + if (!DecodeLocalEntriesWithParams(d, codeMeta, funcIndex, &locals)) { return false; } - return DecodeFunctionBodyExprs(env, funcIndex, locals, bodyBegin + bodySize, - &d); + ValidatingOpIter iter(codeMeta, d, locals); + NopOpDumper visitor; + + if (!iter.startFunction(funcIndex)) { + return false; + } + + if (!ValidateOps(iter, visitor, codeMeta)) { + return false; + } + + return iter.endFunction(bodyEnd); } // Section macros. @@ -1603,21 +2459,22 @@ static bool DecodePreamble(Decoder& d) { return true; } -static bool DecodeValTypeVector(Decoder& d, ModuleEnvironment* env, +static bool DecodeValTypeVector(Decoder& d, CodeMetadata* codeMeta, uint32_t count, ValTypeVector* valTypes) { if (!valTypes->resize(count)) { return false; } for (uint32_t i = 0; i < count; i++) { - if (!d.readValType(*env->types, env->features, &(*valTypes)[i])) { + if (!d.readValType(*codeMeta->types, codeMeta->features(), + &(*valTypes)[i])) { return false; } } return true; } -static bool DecodeFuncType(Decoder& d, ModuleEnvironment* env, +static bool DecodeFuncType(Decoder& d, CodeMetadata* codeMeta, FuncType* funcType) { uint32_t numArgs; if (!d.readVarU32(&numArgs)) { @@ -1627,7 +2484,7 @@ static bool DecodeFuncType(Decoder& d, ModuleEnvironment* env, return d.fail("too many arguments in signature"); } ValTypeVector args; - if (!DecodeValTypeVector(d, env, numArgs, &args)) { + if (!DecodeValTypeVector(d, codeMeta, numArgs, &args)) { return false; } @@ -1639,7 +2496,7 @@ static bool DecodeFuncType(Decoder& d, ModuleEnvironment* env, return d.fail("too many returns in signature"); } ValTypeVector results; - if (!DecodeValTypeVector(d, env, numResults, &results)) { + if (!DecodeValTypeVector(d, codeMeta, numResults, &results)) { return false; } @@ -1647,12 +2504,8 @@ static bool DecodeFuncType(Decoder& d, ModuleEnvironment* env, return true; } -static bool DecodeStructType(Decoder& d, ModuleEnvironment* env, +static bool DecodeStructType(Decoder& d, CodeMetadata* codeMeta, StructType* structType) { - if (!env->gcEnabled()) { - return d.fail("gc not enabled"); - } - uint32_t numFields; if (!d.readVarU32(&numFields)) { return d.fail("Bad number of fields"); @@ -1668,7 +2521,8 @@ static bool DecodeStructType(Decoder& d, ModuleEnvironment* env, } for (uint32_t i = 0; i < numFields; i++) { - if (!d.readStorageType(*env->types, env->features, &fields[i].type)) { + if (!d.readStorageType(*codeMeta->types, codeMeta->features(), + &fields[i].type)) { return false; } @@ -1691,14 +2545,11 @@ static bool DecodeStructType(Decoder& d, ModuleEnvironment* env, return true; } -static bool DecodeArrayType(Decoder& d, ModuleEnvironment* env, +static bool DecodeArrayType(Decoder& d, CodeMetadata* codeMeta, ArrayType* arrayType) { - if (!env->gcEnabled()) { - return d.fail("gc not enabled"); - } - StorageType elementType; - if (!d.readStorageType(*env->types, env->features, &elementType)) { + if (!d.readStorageType(*codeMeta->types, codeMeta->features(), + &elementType)) { return false; } @@ -1715,9 +2566,9 @@ static bool DecodeArrayType(Decoder& d, ModuleEnvironment* env, return true; } -static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Type, env, &range, "type")) { +static bool DecodeTypeSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Type, codeMeta, &range, "type")) { return false; } if (!range) { @@ -1739,28 +2590,32 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { recGroupIndex++) { uint32_t recGroupLength = 1; - // Decode an optional recursion group length, if the GC proposal is - // enabled. - if (env->gcEnabled()) { - uint8_t firstTypeCode; - if (!d.peekByte(&firstTypeCode)) { - return d.fail("expected type form"); - } + uint8_t firstTypeCode; + if (!d.peekByte(&firstTypeCode)) { + return d.fail("expected type form"); + } - if (firstTypeCode == (uint8_t)TypeCode::RecGroup) { - // Skip over the prefix byte that was peeked. - d.uncheckedReadFixedU8(); + if (firstTypeCode == (uint8_t)TypeCode::RecGroup) { + // Skip over the prefix byte that was peeked. + d.uncheckedReadFixedU8(); - // Read the number of types in this recursion group - if (!d.readVarU32(&recGroupLength)) { - return d.fail("expected recursion group length"); - } + // Read the number of types in this recursion group + if (!d.readVarU32(&recGroupLength)) { + return d.fail("expected recursion group length"); } } + // Check if we've reached our implementation defined limit of type + // definitions. + mozilla::CheckedUint32 newNumTypes(codeMeta->types->length()); + newNumTypes += recGroupLength; + if (!newNumTypes.isValid() || newNumTypes.value() > MaxTypes) { + return d.fail("too many types"); + } + // Start a recursion group. This will extend the type context with empty // type definitions to be filled. - MutableRecGroup recGroup = env->types->startRecGroup(recGroupLength); + MutableRecGroup recGroup = codeMeta->types->startRecGroup(recGroupLength); if (!recGroup) { return false; } @@ -1770,13 +2625,10 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { for (uint32_t recGroupTypeIndex = 0; recGroupTypeIndex < recGroupLength; recGroupTypeIndex++) { uint32_t typeIndex = - env->types->length() - recGroupLength + recGroupTypeIndex; + codeMeta->types->length() - recGroupLength + recGroupTypeIndex; - // Check if we've reached our implementation defined limit of type - // definitions. - if (typeIndex >= MaxTypes) { - return d.fail("too many types"); - } + // This is ensured by above + MOZ_ASSERT(typeIndex < MaxTypes); uint8_t form; const TypeDef* superTypeDef = nullptr; @@ -1784,11 +2636,9 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { // By default, all types are final unless the sub keyword is specified. bool finalTypeFlag = true; - // Decode an optional declared super type index, if the GC proposal is - // enabled. - if (env->gcEnabled() && d.peekByte(&form) && - (form == (uint8_t)TypeCode::SubNoFinalType || - form == (uint8_t)TypeCode::SubFinalType)) { + // Decode an optional declared super type index. + if (d.peekByte(&form) && (form == (uint8_t)TypeCode::SubNoFinalType || + form == (uint8_t)TypeCode::SubFinalType)) { if (form == (uint8_t)TypeCode::SubNoFinalType) { finalTypeFlag = false; } @@ -1819,7 +2669,7 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { return d.fail("invalid super type index"); } - superTypeDef = &env->types->type(superTypeDefIndex); + superTypeDef = &codeMeta->types->type(superTypeDefIndex); } } @@ -1832,7 +2682,7 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { switch (form) { case uint8_t(TypeCode::Func): { FuncType funcType; - if (!DecodeFuncType(d, env, &funcType)) { + if (!DecodeFuncType(d, codeMeta, &funcType)) { return false; } *typeDef = std::move(funcType); @@ -1840,7 +2690,7 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { } case uint8_t(TypeCode::Struct): { StructType structType; - if (!DecodeStructType(d, env, &structType)) { + if (!DecodeStructType(d, codeMeta, &structType)) { return false; } *typeDef = std::move(structType); @@ -1848,7 +2698,7 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { } case uint8_t(TypeCode::Array): { ArrayType arrayType; - if (!DecodeArrayType(d, env, &arrayType)) { + if (!DecodeArrayType(d, codeMeta, &arrayType)) { return false; } *typeDef = std::move(arrayType); @@ -1869,8 +2719,8 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { } if (typeDef->isFuncType()) { - typeDef->funcType().initImmediateTypeId( - env->gcEnabled(), typeDef->isFinal(), superTypeDef, recGroupLength); + typeDef->funcType().initImmediateTypeId(typeDef->isFinal(), + superTypeDef, recGroupLength); } } @@ -1889,7 +2739,7 @@ static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) { } // Finish the recursion group, which will canonicalize the types. - if (!env->types->endRecGroup()) { + if (!codeMeta->types->endRecGroup()) { return false; } } @@ -1945,12 +2795,13 @@ static bool DecodeFuncTypeIndex(Decoder& d, const SharedTypeContext& types, return true; } -static bool DecodeLimitBound(Decoder& d, IndexType indexType, uint64_t* bound) { - if (indexType == IndexType::I64) { +static bool DecodeLimitBound(Decoder& d, AddressType addressType, + uint64_t* bound) { + if (addressType == AddressType::I64) { return d.readVarU64(bound); } - // Spec tests assert that we only decode a LEB32 when index type is I32. + // Spec tests assert that we only decode a LEB32 when address type is I32. uint32_t bound32; if (!d.readVarU32(&bound32)) { return false; @@ -1973,7 +2824,7 @@ static bool DecodeLimits(Decoder& d, LimitsKind kind, Limits* limits) { uint32_t(flags & ~uint8_t(mask))); } - // Memory limits may be shared or specify an alternate index type + // Memory limits may be shared if (kind == LimitsKind::Memory) { if ((flags & uint8_t(LimitsFlags::IsShared)) && !(flags & uint8_t(LimitsFlags::HasMaximum))) { @@ -1983,38 +2834,39 @@ static bool DecodeLimits(Decoder& d, LimitsKind kind, Limits* limits) { limits->shared = (flags & uint8_t(LimitsFlags::IsShared)) ? Shareable::True : Shareable::False; - -#ifdef ENABLE_WASM_MEMORY64 - limits->indexType = - (flags & uint8_t(LimitsFlags::IsI64)) ? IndexType::I64 : IndexType::I32; -#else - limits->indexType = IndexType::I32; - if (flags & uint8_t(LimitsFlags::IsI64)) { - return d.fail("i64 is not supported for memory limits"); - } -#endif } else { limits->shared = Shareable::False; - limits->indexType = IndexType::I32; } +#ifdef ENABLE_WASM_MEMORY64 + limits->addressType = (flags & uint8_t(LimitsFlags::IsI64)) + ? AddressType::I64 + : AddressType::I32; +#else + limits->addressType = AddressType::I32; + if (flags & uint8_t(LimitsFlags::IsI64)) { + return d.fail("i64 is not supported for memory or table limits"); + } +#endif + uint64_t initial; - if (!DecodeLimitBound(d, limits->indexType, &initial)) { + if (!DecodeLimitBound(d, limits->addressType, &initial)) { return d.fail("expected initial length"); } limits->initial = initial; if (flags & uint8_t(LimitsFlags::HasMaximum)) { uint64_t maximum; - if (!DecodeLimitBound(d, limits->indexType, &maximum)) { + if (!DecodeLimitBound(d, limits->addressType, &maximum)) { return d.fail("expected maximum length"); } if (limits->initial > maximum) { return d.failf( - "memory size minimum must not be greater than maximum; " + "%s size minimum must not be greater than maximum; " "maximum length %" PRIu64 " is less than initial length %" PRIu64, - maximum, limits->initial); + kind == LimitsKind::Memory ? "memory" : "table", maximum, + limits->initial); } limits->maximum.emplace(maximum); @@ -2023,13 +2875,24 @@ static bool DecodeLimits(Decoder& d, LimitsKind kind, Limits* limits) { return true; } -static bool DecodeTableTypeAndLimits(Decoder& d, ModuleEnvironment* env) { +// Combined decoding for both table types and the augmented form of table types +// that can include init expressions: +// +// https://wasm-dsl.github.io/spectec/core/binary/types.html#table-types +// https://wasm-dsl.github.io/spectec/core/binary/modules.html#table-section +// +// Only defined tables are therefore allowed to have init expressions, not +// imported tables. +static bool DecodeTableType(Decoder& d, CodeMetadata* codeMeta, bool isImport) { bool initExprPresent = false; uint8_t typeCode; if (!d.peekByte(&typeCode)) { return d.fail("expected type code"); } if (typeCode == (uint8_t)TypeCode::TableHasInitExpr) { + if (isImport) { + return d.fail("imported tables cannot have initializer expressions"); + } d.uncheckedReadFixedU8(); uint8_t flags; if (!d.readFixedU8(&flags) || flags != 0) { @@ -2039,7 +2902,7 @@ static bool DecodeTableTypeAndLimits(Decoder& d, ModuleEnvironment* env) { } RefType tableElemType; - if (!d.readRefType(*env->types, env->features, &tableElemType)) { + if (!d.readRefType(*codeMeta->types, codeMeta->features(), &tableElemType)) { return false; } @@ -2048,45 +2911,41 @@ static bool DecodeTableTypeAndLimits(Decoder& d, ModuleEnvironment* env) { return false; } - // Decoding limits for a table only supports i32 - MOZ_ASSERT(limits.indexType == IndexType::I32); + if (limits.addressType == AddressType::I64 && !codeMeta->memory64Enabled()) { + return d.fail("memory64 is disabled"); + } // If there's a maximum, check it is in range. The check to exclude // initial > maximum is carried out by the DecodeLimits call above, so // we don't repeat it here. - if (limits.initial > MaxTableLimitField || + if (limits.initial > MaxTableElemsValidation(limits.addressType) || ((limits.maximum.isSome() && - limits.maximum.value() > MaxTableLimitField))) { + limits.maximum.value() > + MaxTableElemsValidation(limits.addressType)))) { return d.fail("too many table elements"); } - if (env->tables.length() >= MaxTables) { + if (codeMeta->tables.length() >= MaxTables) { return d.fail("too many tables"); } - // The rest of the runtime expects table limits to be within a 32-bit range. - static_assert(MaxTableLimitField <= UINT32_MAX, "invariant"); - uint32_t initialLength = uint32_t(limits.initial); - Maybe maximumLength; - if (limits.maximum) { - maximumLength = Some(uint32_t(*limits.maximum)); - } - Maybe initExpr; if (initExprPresent) { InitExpr initializer; - if (!InitExpr::decodeAndValidate(d, env, tableElemType, &initializer)) { + if (!InitExpr::decodeAndValidate(d, codeMeta, tableElemType, + &initializer)) { return false; } initExpr = Some(std::move(initializer)); } else { - if (!tableElemType.isNullable()) { + if (!tableElemType.isNullable() && !isImport) { return d.fail("table with non-nullable references requires initializer"); } } - return env->tables.emplaceBack(tableElemType, initialLength, maximumLength, - std::move(initExpr), /* isAsmJS */ false); + return codeMeta->tables.emplaceBack(limits, tableElemType, + std::move(initExpr), + /* isAsmJS */ false, isImport); } static bool DecodeGlobalType(Decoder& d, const SharedTypeContext& types, @@ -2109,13 +2968,13 @@ static bool DecodeGlobalType(Decoder& d, const SharedTypeContext& types, return true; } -static bool DecodeMemoryTypeAndLimits(Decoder& d, ModuleEnvironment* env, +static bool DecodeMemoryTypeAndLimits(Decoder& d, CodeMetadata* codeMeta, MemoryDescVector* memories) { - if (!env->features.multiMemory && env->numMemories() == 1) { + if (!codeMeta->features().multiMemory && codeMeta->numMemories() == 1) { return d.fail("already have default memory"); } - if (env->numMemories() >= MaxMemories) { + if (codeMeta->numMemories() >= MaxMemories) { return d.fail("too many memories"); } @@ -2124,7 +2983,7 @@ static bool DecodeMemoryTypeAndLimits(Decoder& d, ModuleEnvironment* env, return false; } - uint64_t maxField = MaxMemoryLimitField(limits.indexType); + uint64_t maxField = MaxMemoryPagesValidation(limits.addressType); if (limits.initial > maxField) { return d.fail("initial memory size too big"); @@ -2135,18 +2994,18 @@ static bool DecodeMemoryTypeAndLimits(Decoder& d, ModuleEnvironment* env, } if (limits.shared == Shareable::True && - env->sharedMemoryEnabled() == Shareable::False) { + codeMeta->sharedMemoryEnabled() == Shareable::False) { return d.fail("shared memory is disabled"); } - if (limits.indexType == IndexType::I64 && !env->memory64Enabled()) { + if (limits.addressType == AddressType::I64 && !codeMeta->memory64Enabled()) { return d.fail("memory64 is disabled"); } return memories->emplaceBack(MemoryDesc(limits)); } -static bool DecodeTag(Decoder& d, ModuleEnvironment* env, TagKind* tagKind, +static bool DecodeTag(Decoder& d, CodeMetadata* codeMeta, TagKind* tagKind, uint32_t* funcTypeIndex) { uint32_t tagCode; if (!d.readVarU32(&tagCode)) { @@ -2161,19 +3020,20 @@ static bool DecodeTag(Decoder& d, ModuleEnvironment* env, TagKind* tagKind, if (!d.readVarU32(funcTypeIndex)) { return d.fail("expected function index in tag"); } - if (*funcTypeIndex >= env->numTypes()) { + if (*funcTypeIndex >= codeMeta->numTypes()) { return d.fail("function type index in tag out of bounds"); } - if (!(*env->types)[*funcTypeIndex].isFuncType()) { + if (!(*codeMeta->types)[*funcTypeIndex].isFuncType()) { return d.fail("function type index must index a function type"); } - if ((*env->types)[*funcTypeIndex].funcType().results().length() != 0) { + if ((*codeMeta->types)[*funcTypeIndex].funcType().results().length() != 0) { return d.fail("tag function types must not return anything"); } return true; } -static bool DecodeImport(Decoder& d, ModuleEnvironment* env) { +static bool DecodeImport(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { CacheableName moduleName; if (!DecodeName(d, &moduleName)) { return d.fail("expected valid import module name"); @@ -2194,27 +3054,25 @@ static bool DecodeImport(Decoder& d, ModuleEnvironment* env) { switch (importKind) { case DefinitionKind::Function: { uint32_t funcTypeIndex; - if (!DecodeFuncTypeIndex(d, env->types, &funcTypeIndex)) { + if (!DecodeFuncTypeIndex(d, codeMeta->types, &funcTypeIndex)) { return false; } - if (!env->funcs.append(FuncDesc( - &env->types->type(funcTypeIndex).funcType(), funcTypeIndex))) { + if (!codeMeta->funcs.append(FuncDesc(funcTypeIndex))) { return false; } - if (env->funcs.length() > MaxFuncs) { + if (codeMeta->funcs.length() > MaxFuncs) { return d.fail("too many functions"); } break; } case DefinitionKind::Table: { - if (!DecodeTableTypeAndLimits(d, env)) { + if (!DecodeTableType(d, codeMeta, /*isImport=*/true)) { return false; } - env->tables.back().isImported = true; break; } case DefinitionKind::Memory: { - if (!DecodeMemoryTypeAndLimits(d, env, &env->memories)) { + if (!DecodeMemoryTypeAndLimits(d, codeMeta, &codeMeta->memories)) { return false; } break; @@ -2222,14 +3080,15 @@ static bool DecodeImport(Decoder& d, ModuleEnvironment* env) { case DefinitionKind::Global: { ValType type; bool isMutable; - if (!DecodeGlobalType(d, env->types, env->features, &type, &isMutable)) { + if (!DecodeGlobalType(d, codeMeta->types, codeMeta->features(), &type, + &isMutable)) { return false; } - if (!env->globals.append( - GlobalDesc(type, isMutable, env->globals.length()))) { + if (!codeMeta->globals.append( + GlobalDesc(type, isMutable, codeMeta->globals.length()))) { return false; } - if (env->globals.length() > MaxGlobals) { + if (codeMeta->globals.length() > MaxGlobals) { return d.fail("too many globals"); } break; @@ -2237,21 +3096,18 @@ static bool DecodeImport(Decoder& d, ModuleEnvironment* env) { case DefinitionKind::Tag: { TagKind tagKind; uint32_t funcTypeIndex; - if (!DecodeTag(d, env, &tagKind, &funcTypeIndex)) { - return false; - } - ValTypeVector args; - if (!args.appendAll((*env->types)[funcTypeIndex].funcType().args())) { + if (!DecodeTag(d, codeMeta, &tagKind, &funcTypeIndex)) { return false; } MutableTagType tagType = js_new(); - if (!tagType || !tagType->initialize(std::move(args))) { + if (!tagType || + !tagType->initialize(&(*codeMeta->types)[funcTypeIndex])) { return false; } - if (!env->tags.emplaceBack(tagKind, tagType)) { + if (!codeMeta->tags.emplaceBack(tagKind, tagType)) { return false; } - if (env->tags.length() > MaxTags) { + if (codeMeta->tags.length() > MaxTags) { return d.fail("too many tags"); } break; @@ -2260,13 +3116,14 @@ static bool DecodeImport(Decoder& d, ModuleEnvironment* env) { return d.fail("unsupported import kind"); } - return env->imports.emplaceBack(std::move(moduleName), std::move(fieldName), - importKind); + return moduleMeta->imports.emplaceBack(std::move(moduleName), + std::move(fieldName), importKind); } static bool CheckImportsAgainstBuiltinModules(Decoder& d, - ModuleEnvironment* env) { - const BuiltinModuleIds& builtinModules = env->features.builtinModules; + CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + const BuiltinModuleIds& builtinModules = codeMeta->features().builtinModules; // Skip this pass if there are no builtin modules enabled if (builtinModules.hasNone()) { @@ -2274,13 +3131,15 @@ static bool CheckImportsAgainstBuiltinModules(Decoder& d, } uint32_t importFuncIndex = 0; - for (auto& import : env->imports) { + uint32_t importGlobalIndex = 0; + for (auto& import : moduleMeta->imports) { Maybe builtinModule = ImportMatchesBuiltinModule(import.module.utf8Bytes(), builtinModules); switch (import.kind) { case DefinitionKind::Function: { - const FuncDesc& func = env->funcs[importFuncIndex]; + const FuncDesc& func = codeMeta->funcs[importFuncIndex]; + uint32_t funcIndex = importFuncIndex; importFuncIndex += 1; // Skip this import if it doesn't refer to a builtin module. We do have @@ -2290,17 +3149,45 @@ static bool CheckImportsAgainstBuiltinModules(Decoder& d, } // Check if this import refers to a builtin module function - Maybe builtinFunc = - ImportMatchesBuiltinModuleFunc(import.field.utf8Bytes(), - *builtinModule); - if (!builtinFunc) { + const BuiltinModuleFunc* builtinFunc = nullptr; + BuiltinModuleFuncId builtinFuncId; + if (!ImportMatchesBuiltinModuleFunc(import.field.utf8Bytes(), + *builtinModule, &builtinFunc, + &builtinFuncId)) { return d.fail("unrecognized builtin module field"); } - const TypeDef& importTypeDef = (*env->types)[func.typeIndex]; - if (!TypeDef::isSubTypeOf((*builtinFunc)->typeDef(), &importTypeDef)) { - return d.failf("type mismatch in %s", (*builtinFunc)->exportName()); + const TypeDef& importTypeDef = (*codeMeta->types)[func.typeIndex]; + if (!TypeDef::isSubTypeOf(builtinFunc->typeDef(), &importTypeDef)) { + return d.failf("type mismatch in %s", builtinFunc->exportName()); } + + codeMeta->knownFuncImports[funcIndex] = builtinFuncId; + break; + } + case DefinitionKind::Global: { + const GlobalDesc& global = codeMeta->globals[importGlobalIndex]; + importGlobalIndex += 1; + + // Skip this import if it doesn't refer to a builtin module. We do have + // to increment the import global index regardless though. + if (!builtinModule) { + continue; + } + + // Only the imported string constants module has globals defined. + if (*builtinModule != BuiltinModuleId::JSStringConstants) { + return d.fail("unrecognized builtin module field"); + } + + // All imported globals must match a provided global type of + // `(global (ref extern))`. + if (global.isMutable() || + !ValType::isSubTypeOf(ValType(RefType::extern_().asNonNullable()), + global.type())) { + return d.failf("type mismatch"); + } + break; } default: { @@ -2315,9 +3202,10 @@ static bool CheckImportsAgainstBuiltinModules(Decoder& d, return true; } -static bool DecodeImportSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Import, env, &range, "import")) { +static bool DecodeImportSection(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Import, codeMeta, &range, "import")) { return false; } if (!range) { @@ -2334,7 +3222,7 @@ static bool DecodeImportSection(Decoder& d, ModuleEnvironment* env) { } for (uint32_t i = 0; i < numImports; i++) { - if (!DecodeImport(d, env)) { + if (!DecodeImport(d, codeMeta, moduleMeta)) { return false; } } @@ -2343,14 +3231,17 @@ static bool DecodeImportSection(Decoder& d, ModuleEnvironment* env) { return false; } - env->numFuncImports = env->funcs.length(); - env->numGlobalImports = env->globals.length(); + codeMeta->numFuncImports = codeMeta->funcs.length(); + if (!codeMeta->knownFuncImports.resize(codeMeta->numFuncImports)) { + return false; + } + codeMeta->numGlobalImports = codeMeta->globals.length(); return true; } -static bool DecodeFunctionSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Function, env, &range, "function")) { +static bool DecodeFunctionSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Function, codeMeta, &range, "function")) { return false; } if (!range) { @@ -2362,31 +3253,30 @@ static bool DecodeFunctionSection(Decoder& d, ModuleEnvironment* env) { return d.fail("expected number of function definitions"); } - CheckedInt numFuncs = env->funcs.length(); + CheckedInt numFuncs = codeMeta->funcs.length(); numFuncs += numDefs; if (!numFuncs.isValid() || numFuncs.value() > MaxFuncs) { return d.fail("too many functions"); } - if (!env->funcs.reserve(numFuncs.value())) { + if (!codeMeta->funcs.reserve(numFuncs.value())) { return false; } for (uint32_t i = 0; i < numDefs; i++) { uint32_t funcTypeIndex; - if (!DecodeFuncTypeIndex(d, env->types, &funcTypeIndex)) { + if (!DecodeFuncTypeIndex(d, codeMeta->types, &funcTypeIndex)) { return false; } - env->funcs.infallibleAppend( - FuncDesc(&env->types->type(funcTypeIndex).funcType(), funcTypeIndex)); + codeMeta->funcs.infallibleAppend(funcTypeIndex); } return d.finishSection(*range, "function"); } -static bool DecodeTableSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Table, env, &range, "table")) { +static bool DecodeTableSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Table, codeMeta, &range, "table")) { return false; } if (!range) { @@ -2399,7 +3289,7 @@ static bool DecodeTableSection(Decoder& d, ModuleEnvironment* env) { } for (uint32_t i = 0; i < numTables; ++i) { - if (!DecodeTableTypeAndLimits(d, env)) { + if (!DecodeTableType(d, codeMeta, /*isImport=*/false)) { return false; } } @@ -2407,9 +3297,9 @@ static bool DecodeTableSection(Decoder& d, ModuleEnvironment* env) { return d.finishSection(*range, "table"); } -static bool DecodeMemorySection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Memory, env, &range, "memory")) { +static bool DecodeMemorySection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Memory, codeMeta, &range, "memory")) { return false; } if (!range) { @@ -2421,12 +3311,12 @@ static bool DecodeMemorySection(Decoder& d, ModuleEnvironment* env) { return d.fail("failed to read number of memories"); } - if (!env->features.multiMemory && numMemories > 1) { + if (!codeMeta->features().multiMemory && numMemories > 1) { return d.fail("the number of memories must be at most one"); } for (uint32_t i = 0; i < numMemories; ++i) { - if (!DecodeMemoryTypeAndLimits(d, env, &env->memories)) { + if (!DecodeMemoryTypeAndLimits(d, codeMeta, &codeMeta->memories)) { return false; } } @@ -2434,9 +3324,9 @@ static bool DecodeMemorySection(Decoder& d, ModuleEnvironment* env) { return d.finishSection(*range, "memory"); } -static bool DecodeGlobalSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Global, env, &range, "global")) { +static bool DecodeGlobalSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Global, codeMeta, &range, "global")) { return false; } if (!range) { @@ -2448,38 +3338,39 @@ static bool DecodeGlobalSection(Decoder& d, ModuleEnvironment* env) { return d.fail("expected number of globals"); } - CheckedInt numGlobals = env->globals.length(); + CheckedInt numGlobals = codeMeta->globals.length(); numGlobals += numDefs; if (!numGlobals.isValid() || numGlobals.value() > MaxGlobals) { return d.fail("too many globals"); } - if (!env->globals.reserve(numGlobals.value())) { + if (!codeMeta->globals.reserve(numGlobals.value())) { return false; } for (uint32_t i = 0; i < numDefs; i++) { ValType type; bool isMutable; - if (!DecodeGlobalType(d, env->types, env->features, &type, &isMutable)) { + if (!DecodeGlobalType(d, codeMeta->types, codeMeta->features(), &type, + &isMutable)) { return false; } InitExpr initializer; - if (!InitExpr::decodeAndValidate(d, env, type, &initializer)) { + if (!InitExpr::decodeAndValidate(d, codeMeta, type, &initializer)) { return false; } - env->globals.infallibleAppend( + codeMeta->globals.infallibleAppend( GlobalDesc(std::move(initializer), isMutable)); } return d.finishSection(*range, "global"); } -static bool DecodeTagSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Tag, env, &range, "tag")) { +static bool DecodeTagSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Tag, codeMeta, &range, "tag")) { return false; } if (!range) { @@ -2491,31 +3382,27 @@ static bool DecodeTagSection(Decoder& d, ModuleEnvironment* env) { return d.fail("expected number of tags"); } - CheckedInt numTags = env->tags.length(); + CheckedInt numTags = codeMeta->tags.length(); numTags += numDefs; if (!numTags.isValid() || numTags.value() > MaxTags) { return d.fail("too many tags"); } - if (!env->tags.reserve(numTags.value())) { + if (!codeMeta->tags.reserve(numTags.value())) { return false; } for (uint32_t i = 0; i < numDefs; i++) { TagKind tagKind; uint32_t funcTypeIndex; - if (!DecodeTag(d, env, &tagKind, &funcTypeIndex)) { - return false; - } - ValTypeVector args; - if (!args.appendAll((*env->types)[funcTypeIndex].funcType().args())) { + if (!DecodeTag(d, codeMeta, &tagKind, &funcTypeIndex)) { return false; } MutableTagType tagType = js_new(); - if (!tagType || !tagType->initialize(std::move(args))) { + if (!tagType || !tagType->initialize(&(*codeMeta->types)[funcTypeIndex])) { return false; } - env->tags.infallibleEmplaceBack(tagKind, tagType); + codeMeta->tags.infallibleEmplaceBack(tagKind, tagType); } return d.finishSection(*range, "tag"); @@ -2539,7 +3426,8 @@ using NameSet = HashSet, NameHasher, SystemAllocPolicy>; return dupSet->add(p, exportName->utf8Bytes()); } -static bool DecodeExport(Decoder& d, ModuleEnvironment* env, NameSet* dupSet) { +static bool DecodeExport(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta, NameSet* dupSet) { CacheableName fieldName; if (!DecodeExportName(d, dupSet, &fieldName)) { return false; @@ -2557,14 +3445,14 @@ static bool DecodeExport(Decoder& d, ModuleEnvironment* env, NameSet* dupSet) { return d.fail("expected function index"); } - if (funcIndex >= env->numFuncs()) { + if (funcIndex >= codeMeta->numFuncs()) { return d.fail("exported function index out of bounds"); } - env->declareFuncExported(funcIndex, /* eager */ true, - /* canRefFunc */ true); - return env->exports.emplaceBack(std::move(fieldName), funcIndex, - DefinitionKind::Function); + codeMeta->funcs[funcIndex].declareFuncExported(/* eager */ true, + /* canRefFunc */ true); + return moduleMeta->exports.emplaceBack(std::move(fieldName), funcIndex, + DefinitionKind::Function); } case DefinitionKind::Table: { uint32_t tableIndex; @@ -2572,12 +3460,12 @@ static bool DecodeExport(Decoder& d, ModuleEnvironment* env, NameSet* dupSet) { return d.fail("expected table index"); } - if (tableIndex >= env->tables.length()) { + if (tableIndex >= codeMeta->tables.length()) { return d.fail("exported table index out of bounds"); } - env->tables[tableIndex].isExported = true; - return env->exports.emplaceBack(std::move(fieldName), tableIndex, - DefinitionKind::Table); + codeMeta->tables[tableIndex].isExported = true; + return moduleMeta->exports.emplaceBack(std::move(fieldName), tableIndex, + DefinitionKind::Table); } case DefinitionKind::Memory: { uint32_t memoryIndex; @@ -2585,12 +3473,12 @@ static bool DecodeExport(Decoder& d, ModuleEnvironment* env, NameSet* dupSet) { return d.fail("expected memory index"); } - if (memoryIndex >= env->numMemories()) { + if (memoryIndex >= codeMeta->numMemories()) { return d.fail("exported memory index out of bounds"); } - return env->exports.emplaceBack(std::move(fieldName), memoryIndex, - DefinitionKind::Memory); + return moduleMeta->exports.emplaceBack(std::move(fieldName), memoryIndex, + DefinitionKind::Memory); } case DefinitionKind::Global: { uint32_t globalIndex; @@ -2598,28 +3486,28 @@ static bool DecodeExport(Decoder& d, ModuleEnvironment* env, NameSet* dupSet) { return d.fail("expected global index"); } - if (globalIndex >= env->globals.length()) { + if (globalIndex >= codeMeta->globals.length()) { return d.fail("exported global index out of bounds"); } - GlobalDesc* global = &env->globals[globalIndex]; + GlobalDesc* global = &codeMeta->globals[globalIndex]; global->setIsExport(); - return env->exports.emplaceBack(std::move(fieldName), globalIndex, - DefinitionKind::Global); + return moduleMeta->exports.emplaceBack(std::move(fieldName), globalIndex, + DefinitionKind::Global); } case DefinitionKind::Tag: { uint32_t tagIndex; if (!d.readVarU32(&tagIndex)) { return d.fail("expected tag index"); } - if (tagIndex >= env->tags.length()) { + if (tagIndex >= codeMeta->tags.length()) { return d.fail("exported tag index out of bounds"); } - env->tags[tagIndex].isExport = true; - return env->exports.emplaceBack(std::move(fieldName), tagIndex, - DefinitionKind::Tag); + codeMeta->tags[tagIndex].isExport = true; + return moduleMeta->exports.emplaceBack(std::move(fieldName), tagIndex, + DefinitionKind::Tag); } default: return d.fail("unexpected export kind"); @@ -2628,9 +3516,10 @@ static bool DecodeExport(Decoder& d, ModuleEnvironment* env, NameSet* dupSet) { MOZ_CRASH("unreachable"); } -static bool DecodeExportSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Export, env, &range, "export")) { +static bool DecodeExportSection(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Export, codeMeta, &range, "export")) { return false; } if (!range) { @@ -2649,7 +3538,7 @@ static bool DecodeExportSection(Decoder& d, ModuleEnvironment* env) { } for (uint32_t i = 0; i < numExports; i++) { - if (!DecodeExport(d, env, &dupSet)) { + if (!DecodeExport(d, codeMeta, moduleMeta, &dupSet)) { return false; } } @@ -2657,9 +3546,10 @@ static bool DecodeExportSection(Decoder& d, ModuleEnvironment* env) { return d.finishSection(*range, "export"); } -static bool DecodeStartSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Start, env, &range, "start")) { +static bool DecodeStartSection(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Start, codeMeta, &range, "start")) { return false; } if (!range) { @@ -2671,11 +3561,11 @@ static bool DecodeStartSection(Decoder& d, ModuleEnvironment* env) { return d.fail("failed to read start func index"); } - if (funcIndex >= env->numFuncs()) { + if (funcIndex >= codeMeta->numFuncs()) { return d.fail("unknown start function"); } - const FuncType& funcType = *env->funcs[funcIndex].type; + const FuncType& funcType = codeMeta->getFuncType(funcIndex); if (funcType.results().length() > 0) { return d.fail("start function must not return anything"); } @@ -2684,8 +3574,9 @@ static bool DecodeStartSection(Decoder& d, ModuleEnvironment* env) { return d.fail("start function must be nullary"); } - env->declareFuncExported(funcIndex, /* eager */ true, /* canFuncRef */ false); - env->startFuncIndex = Some(funcIndex); + codeMeta->funcs[funcIndex].declareFuncExported(/* eager */ true, + /* canFuncRef */ false); + codeMeta->startFuncIndex = Some(funcIndex); return d.finishSection(*range, "start"); } @@ -2707,7 +3598,8 @@ static inline ModuleElemSegment::Kind NormalizeElemSegmentKind( MOZ_CRASH("unexpected elem segment kind"); } -static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { +static bool DecodeElemSegment(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { uint32_t segmentFlags; if (!d.readVarU32(&segmentFlags)) { return d.fail("expected elem segment flags field"); @@ -2725,7 +3617,7 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { if (segmentKind == ElemSegmentKind::Active || segmentKind == ElemSegmentKind::ActiveWithTableIndex) { - if (env->tables.length() == 0) { + if (codeMeta->tables.length() == 0) { return d.fail("active elem segment requires a table"); } @@ -2734,13 +3626,15 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { !d.readVarU32(&tableIndex)) { return d.fail("expected table index"); } - if (tableIndex >= env->tables.length()) { + if (tableIndex >= codeMeta->tables.length()) { return d.fail("table index out of range for element segment"); } seg.tableIndex = tableIndex; InitExpr offset; - if (!InitExpr::decodeAndValidate(d, env, ValType::I32, &offset)) { + if (!InitExpr::decodeAndValidate( + d, codeMeta, ToValType(codeMeta->tables[tableIndex].addressType()), + &offset)) { return false; } seg.offsetIfActive.emplace(std::move(offset)); @@ -2760,11 +3654,15 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { // the type or definition kind of the payload. `Active` element segments are // restricted to MVP behavior, which assumes only function indices. if (segmentKind == ElemSegmentKind::Active) { - elemType = RefType::func(); + // Bizarrely, the spec prescribes that the default type is (ref func) when + // encoding function indices, and (ref null func) when encoding expressions. + elemType = payload == ElemSegmentPayload::Expressions + ? RefType::func() + : RefType::func().asNonNullable(); } else { switch (payload) { case ElemSegmentPayload::Expressions: { - if (!d.readRefType(*env->types, env->features, &elemType)) { + if (!d.readRefType(*codeMeta->types, codeMeta->features(), &elemType)) { return false; } } break; @@ -2777,7 +3675,7 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { if (elemKind != uint8_t(DefinitionKind::Function)) { return d.fail("invalid element kind"); } - elemType = RefType::func(); + elemType = RefType::func().asNonNullable(); } break; } } @@ -2785,8 +3683,8 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { // For active segments, check if the element type is compatible with the // destination table type. if (seg.active()) { - RefType tblElemType = env->tables[seg.tableIndex].elemType; - if (!CheckIsSubtypeOf(d, *env, d.currentOffset(), + RefType tblElemType = codeMeta->tables[seg.tableIndex].elemType; + if (!CheckIsSubtypeOf(d, *codeMeta, d.currentOffset(), ValType(elemType).storageType(), ValType(tblElemType).storageType())) { return false; @@ -2803,7 +3701,7 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { return d.fail("too many elements in element segment"); } - bool isAsmJS = seg.active() && env->tables[seg.tableIndex].isAsmJS; + bool isAsmJS = seg.active() && codeMeta->tables[seg.tableIndex].isAsmJS; switch (payload) { case ElemSegmentPayload::Indices: { @@ -2818,14 +3716,14 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { return d.fail("failed to read element index"); } // The only valid type of index right now is a function index. - if (elemIndex >= env->numFuncs()) { + if (elemIndex >= codeMeta->numFuncs()) { return d.fail("element index out of range"); } seg.elemIndices.infallibleAppend(elemIndex); if (!isAsmJS) { - env->declareFuncExported(elemIndex, /*eager=*/false, - /*canRefFunc=*/true); + codeMeta->funcs[elemIndex].declareFuncExported(/*eager=*/false, + /*canRefFunc=*/true); } } } break; @@ -2835,7 +3733,7 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { seg.elemExpressions.count = numElems; for (uint32_t i = 0; i < numElems; i++) { Maybe unusedLiteral; - if (!DecodeConstantExpression(d, env, elemType, &unusedLiteral)) { + if (!DecodeConstantExpression(d, codeMeta, elemType, &unusedLiteral)) { return false; } } @@ -2846,13 +3744,16 @@ static bool DecodeElemSegment(Decoder& d, ModuleEnvironment* env) { } break; } - env->elemSegments.infallibleAppend(std::move(seg)); + codeMeta->elemSegmentTypes.infallibleAppend(seg.elemType); + moduleMeta->elemSegments.infallibleAppend(std::move(seg)); + return true; } -static bool DecodeElemSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Elem, env, &range, "elem")) { +static bool DecodeElemSection(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Elem, codeMeta, &range, "elem")) { return false; } if (!range) { @@ -2868,12 +3769,13 @@ static bool DecodeElemSection(Decoder& d, ModuleEnvironment* env) { return d.fail("too many elem segments"); } - if (!env->elemSegments.reserve(numSegments)) { + if (!moduleMeta->elemSegments.reserve(numSegments) || + !codeMeta->elemSegmentTypes.reserve(numSegments)) { return false; } for (uint32_t i = 0; i < numSegments; i++) { - if (!DecodeElemSegment(d, env)) { + if (!DecodeElemSegment(d, codeMeta, moduleMeta)) { return false; } } @@ -2881,9 +3783,9 @@ static bool DecodeElemSection(Decoder& d, ModuleEnvironment* env) { return d.finishSection(*range, "elem"); } -static bool DecodeDataCountSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::DataCount, env, &range, "datacount")) { +static bool DecodeDataCountSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::DataCount, codeMeta, &range, "datacount")) { return false; } if (!range) { @@ -2895,13 +3797,13 @@ static bool DecodeDataCountSection(Decoder& d, ModuleEnvironment* env) { return d.fail("expected data segment count"); } - env->dataCount.emplace(dataCount); + codeMeta->dataCount.emplace(dataCount); return d.finishSection(*range, "datacount"); } bool wasm::StartsCodeSection(const uint8_t* begin, const uint8_t* end, - SectionRange* codeSection) { + BytecodeRange* codeSection) { UniqueChars unused; Decoder d(begin, end, 0, &unused); @@ -2911,17 +3813,21 @@ bool wasm::StartsCodeSection(const uint8_t* begin, const uint8_t* end, while (!d.done()) { uint8_t id; - SectionRange range; + BytecodeRange range; if (!d.readSectionHeader(&id, &range)) { return false; } if (id == uint8_t(SectionId::Code)) { + if (range.size() > MaxCodeSectionBytes) { + return false; + } + *codeSection = range; return true; } - if (!d.readBytes(range.size)) { + if (!d.readBytes(range.size())) { return false; } } @@ -2930,7 +3836,7 @@ bool wasm::StartsCodeSection(const uint8_t* begin, const uint8_t* end, } #ifdef ENABLE_WASM_BRANCH_HINTING -static bool ParseBranchHintingSection(Decoder& d, ModuleEnvironment* env) { +static bool ParseBranchHintingSection(Decoder& d, CodeMetadata* codeMeta) { uint32_t functionCount; if (!d.readVarU32(&functionCount)) { return d.fail("failed to read function count"); @@ -2943,8 +3849,8 @@ static bool ParseBranchHintingSection(Decoder& d, ModuleEnvironment* env) { } // Disallow branch hints on imported functions. - if ((functionIndex >= env->funcs.length()) || - (functionIndex < env->numFuncImports)) { + if ((functionIndex >= codeMeta->funcs.length()) || + (functionIndex < codeMeta->numFuncImports)) { return d.fail("invalid function index in branch hint"); } @@ -2989,8 +3895,8 @@ static bool ParseBranchHintingSection(Decoder& d, ModuleEnvironment* env) { } // Save this collection in the module - if (!env->branchHints.addHintsForFunc(functionIndex, - std::move(hintVector))) { + if (!codeMeta->branchHints.addHintsForFunc(functionIndex, + std::move(hintVector))) { return false; } } @@ -2998,9 +3904,9 @@ static bool ParseBranchHintingSection(Decoder& d, ModuleEnvironment* env) { return true; } -static bool DecodeBranchHintingSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startCustomSection(BranchHintingSectionName, env, &range)) { +static bool DecodeBranchHintingSection(Decoder& d, CodeMetadata* codeMeta) { + MaybeBytecodeRange range; + if (!d.startCustomSection(BranchHintingSectionName, codeMeta, &range)) { return false; } if (!range) { @@ -3008,86 +3914,94 @@ static bool DecodeBranchHintingSection(Decoder& d, ModuleEnvironment* env) { } // Skip this custom section if errors are encountered during parsing. - env->parsedBranchHints = ParseBranchHintingSection(d, env); + if (!ParseBranchHintingSection(d, codeMeta)) { + codeMeta->branchHints.setFailedAndClear(); + } - d.finishCustomSection(BranchHintingSectionName, *range); + if (!d.finishCustomSection(BranchHintingSectionName, *range)) { + codeMeta->branchHints.setFailedAndClear(); + } return true; } #endif -bool wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env) { +bool wasm::DecodeModuleEnvironment(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { if (!DecodePreamble(d)) { return false; } - if (!DecodeTypeSection(d, env)) { + if (!DecodeTypeSection(d, codeMeta)) { return false; } - if (!DecodeImportSection(d, env)) { + if (!DecodeImportSection(d, codeMeta, moduleMeta)) { return false; } // Eagerly check imports for future link errors against any known builtin // module. - if (!CheckImportsAgainstBuiltinModules(d, env)) { + if (!CheckImportsAgainstBuiltinModules(d, codeMeta, moduleMeta)) { return false; } - if (!DecodeFunctionSection(d, env)) { + if (!DecodeFunctionSection(d, codeMeta)) { return false; } - if (!DecodeTableSection(d, env)) { + if (!DecodeTableSection(d, codeMeta)) { return false; } - if (!DecodeMemorySection(d, env)) { + if (!DecodeMemorySection(d, codeMeta)) { return false; } - if (!DecodeTagSection(d, env)) { + if (!DecodeTagSection(d, codeMeta)) { return false; } - if (!DecodeGlobalSection(d, env)) { + if (!DecodeGlobalSection(d, codeMeta)) { return false; } - if (!DecodeExportSection(d, env)) { + if (!DecodeExportSection(d, codeMeta, moduleMeta)) { return false; } - if (!DecodeStartSection(d, env)) { + if (!DecodeStartSection(d, codeMeta, moduleMeta)) { return false; } - if (!DecodeElemSection(d, env)) { + if (!DecodeElemSection(d, codeMeta, moduleMeta)) { return false; } - if (!DecodeDataCountSection(d, env)) { + if (!DecodeDataCountSection(d, codeMeta)) { return false; } #ifdef ENABLE_WASM_BRANCH_HINTING - if (env->branchHintingEnabled() && !DecodeBranchHintingSection(d, env)) { + if (codeMeta->branchHintingEnabled() && + !DecodeBranchHintingSection(d, codeMeta)) { return false; } #endif - if (!d.startSection(SectionId::Code, env, &env->codeSection, "code")) { + if (!d.startSection(SectionId::Code, codeMeta, &codeMeta->codeSectionRange, + "code")) { return false; } - if (env->codeSection && env->codeSection->size > MaxCodeSectionBytes) { + if (codeMeta->codeSectionRange && + codeMeta->codeSectionRange->size() > MaxCodeSectionBytes) { return d.fail("code section too big"); } return true; } -static bool DecodeFunctionBody(Decoder& d, const ModuleEnvironment& env, +static bool DecodeFunctionBody(Decoder& d, const CodeMetadata& codeMeta, uint32_t funcIndex) { uint32_t bodySize; if (!d.readVarU32(&bodySize)) { @@ -3102,12 +4016,12 @@ static bool DecodeFunctionBody(Decoder& d, const ModuleEnvironment& env, return d.fail("function body length too big"); } - return ValidateFunctionBody(env, funcIndex, bodySize, d); + return ValidateFunctionBody(codeMeta, funcIndex, bodySize, d); } -static bool DecodeCodeSection(Decoder& d, ModuleEnvironment* env) { - if (!env->codeSection) { - if (env->numFuncDefs() != 0) { +static bool DecodeCodeSection(Decoder& d, CodeMetadata* codeMeta) { + if (!codeMeta->codeSectionRange) { + if (codeMeta->numFuncDefs() != 0) { return d.fail("expected code section"); } return true; @@ -3118,27 +4032,29 @@ static bool DecodeCodeSection(Decoder& d, ModuleEnvironment* env) { return d.fail("expected function body count"); } - if (numFuncDefs != env->numFuncDefs()) { + if (numFuncDefs != codeMeta->numFuncDefs()) { return d.fail( "function body count does not match function signature count"); } for (uint32_t funcDefIndex = 0; funcDefIndex < numFuncDefs; funcDefIndex++) { - if (!DecodeFunctionBody(d, *env, env->numFuncImports + funcDefIndex)) { + if (!DecodeFunctionBody(d, *codeMeta, + codeMeta->numFuncImports + funcDefIndex)) { return false; } } - return d.finishSection(*env->codeSection, "code"); + return d.finishSection(*codeMeta->codeSectionRange, "code"); } -static bool DecodeDataSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startSection(SectionId::Data, env, &range, "data")) { +static bool DecodeDataSection(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + MaybeBytecodeRange range; + if (!d.startSection(SectionId::Data, codeMeta, &range, "data")) { return false; } if (!range) { - if (env->dataCount.isSome() && *env->dataCount > 0) { + if (codeMeta->dataCount.isSome() && *codeMeta->dataCount > 0) { return d.fail("number of data segments does not match declared count"); } return true; @@ -3153,7 +4069,7 @@ static bool DecodeDataSection(Decoder& d, ModuleEnvironment* env) { return d.fail("too many data segments"); } - if (env->dataCount.isSome() && numSegments != *env->dataCount) { + if (codeMeta->dataCount.isSome() && numSegments != *codeMeta->dataCount) { return d.fail("number of data segments does not match declared count"); } @@ -3175,50 +4091,51 @@ static bool DecodeDataSection(Decoder& d, ModuleEnvironment* env) { DataSegmentKind initializerKind = DataSegmentKind(initializerKindVal); if (initializerKind != DataSegmentKind::Passive && - env->numMemories() == 0) { + codeMeta->numMemories() == 0) { return d.fail("active data segment requires a memory section"); } - DataSegmentEnv seg; + DataSegmentRange segRange; if (initializerKind == DataSegmentKind::ActiveWithMemoryIndex) { - if (!d.readVarU32(&seg.memoryIndex)) { + if (!d.readVarU32(&segRange.memoryIndex)) { return d.fail("expected memory index"); } } else if (initializerKind == DataSegmentKind::Active) { - seg.memoryIndex = 0; + segRange.memoryIndex = 0; } else { - seg.memoryIndex = InvalidMemoryIndex; + segRange.memoryIndex = InvalidMemoryIndex; } if (initializerKind == DataSegmentKind::Active || initializerKind == DataSegmentKind::ActiveWithMemoryIndex) { - if (seg.memoryIndex >= env->numMemories()) { + if (segRange.memoryIndex >= codeMeta->numMemories()) { return d.fail("invalid memory index"); } InitExpr segOffset; - ValType exprType = ToValType(env->memories[seg.memoryIndex].indexType()); - if (!InitExpr::decodeAndValidate(d, env, exprType, &segOffset)) { + ValType exprType = + ToValType(codeMeta->memories[segRange.memoryIndex].addressType()); + if (!InitExpr::decodeAndValidate(d, codeMeta, exprType, &segOffset)) { return false; } - seg.offsetIfActive.emplace(std::move(segOffset)); + segRange.offsetIfActive.emplace(std::move(segOffset)); } - if (!d.readVarU32(&seg.length)) { + if (!d.readVarU32(&segRange.length)) { return d.fail("expected segment size"); } - if (seg.length > MaxDataSegmentLengthPages * PageSize) { + if (segRange.length > MaxDataSegmentLengthPages * PageSize) { return d.fail("segment size too big"); } - seg.bytecodeOffset = d.currentOffset(); + segRange.bytecodeOffset = d.currentOffset(); - if (!d.readBytes(seg.length)) { + if (!d.readBytes(segRange.length)) { return d.fail("data segment shorter than declared"); } - if (!env->dataSegments.append(std::move(seg))) { + if (!moduleMeta->dataSegmentRanges.append(std::move(segRange))) { return false; } } @@ -3227,8 +4144,9 @@ static bool DecodeDataSection(Decoder& d, ModuleEnvironment* env) { } static bool DecodeModuleNameSubsection(Decoder& d, - const CustomSectionEnv& nameSection, - ModuleEnvironment* env) { + const CustomSectionRange& nameSection, + CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { Maybe endOffset; if (!d.startNameSubsection(NameType::Module, &endOffset)) { return false; @@ -3242,9 +4160,9 @@ static bool DecodeModuleNameSubsection(Decoder& d, return d.fail("failed to read module name length"); } - MOZ_ASSERT(d.currentOffset() >= nameSection.payloadOffset); + MOZ_ASSERT(d.currentOffset() >= nameSection.payload.start); moduleName.offsetInNamePayload = - d.currentOffset() - nameSection.payloadOffset; + d.currentOffset() - nameSection.payload.start; const uint8_t* bytes; if (!d.readBytes(moduleName.length, &bytes)) { @@ -3256,13 +4174,14 @@ static bool DecodeModuleNameSubsection(Decoder& d, } // Only save the module name if the whole subsection validates. - env->moduleName.emplace(moduleName); + codeMeta->nameSection->moduleName = moduleName; return true; } static bool DecodeFunctionNameSubsection(Decoder& d, - const CustomSectionEnv& nameSection, - ModuleEnvironment* env) { + const CustomSectionRange& nameSection, + CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { Maybe endOffset; if (!d.startNameSubsection(NameType::Function, &endOffset)) { return false; @@ -3285,7 +4204,7 @@ static bool DecodeFunctionNameSubsection(Decoder& d, } // Names must refer to real functions and be given in ascending order. - if (funcIndex >= env->numFuncs() || funcIndex < funcNames.length()) { + if (funcIndex >= codeMeta->numFuncs() || funcIndex < funcNames.length()) { return d.fail("invalid function index"); } @@ -3303,9 +4222,9 @@ static bool DecodeFunctionNameSubsection(Decoder& d, return false; } - MOZ_ASSERT(d.currentOffset() >= nameSection.payloadOffset); + MOZ_ASSERT(d.currentOffset() >= nameSection.payload.start); funcName.offsetInNamePayload = - d.currentOffset() - nameSection.payloadOffset; + d.currentOffset() - nameSection.payload.start; if (!d.readBytes(funcName.length)) { return d.fail("unable to read function name bytes"); @@ -3318,60 +4237,63 @@ static bool DecodeFunctionNameSubsection(Decoder& d, return false; } - // To encourage fully valid function names subsections; only save names if - // the entire subsection decoded correctly. - env->funcNames = std::move(funcNames); + // Only save names if the entire subsection decoded correctly. + codeMeta->nameSection->funcNames = std::move(funcNames); return true; } -static bool DecodeNameSection(Decoder& d, ModuleEnvironment* env) { - MaybeSectionRange range; - if (!d.startCustomSection(NameSectionName, env, &range)) { +static bool DecodeNameSection(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + MaybeBytecodeRange range; + if (!d.startCustomSection(NameSectionName, codeMeta, &range)) { return false; } if (!range) { return true; } - env->nameCustomSectionIndex = Some(env->customSections.length() - 1); - const CustomSectionEnv& nameSection = env->customSections.back(); + // MONGODB MODIFICATION: Rewrite compound literal syntax not supported by MSVC + codeMeta->nameSection.emplace(NameSection{ + .customSectionIndex = + uint32_t(codeMeta->customSectionRanges.length() - 1), + }); + const CustomSectionRange& nameSection = codeMeta->customSectionRanges.back(); // Once started, custom sections do not report validation errors. - if (!DecodeModuleNameSubsection(d, nameSection, env)) { + if (!DecodeModuleNameSubsection(d, nameSection, codeMeta, moduleMeta)) { goto finish; } - if (!DecodeFunctionNameSubsection(d, nameSection, env)) { + if (!DecodeFunctionNameSubsection(d, nameSection, codeMeta, moduleMeta)) { goto finish; } - while (d.currentOffset() < range->end()) { + while (d.currentOffset() < range->end) { if (!d.skipNameSubsection()) { goto finish; } } finish: - d.finishCustomSection(NameSectionName, *range); + if (!d.finishCustomSection(NameSectionName, *range)) { + codeMeta->nameSection = mozilla::Nothing(); + } return true; } -bool wasm::DecodeModuleTail(Decoder& d, ModuleEnvironment* env) { - if (!DecodeDataSection(d, env)) { +bool wasm::DecodeModuleTail(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta) { + if (!DecodeDataSection(d, codeMeta, moduleMeta)) { return false; } - if (!DecodeNameSection(d, env)) { + if (!DecodeNameSection(d, codeMeta, moduleMeta)) { return false; } while (!d.done()) { - if (!d.skipCustomSection(env)) { - if (d.resilientMode()) { - d.clearError(); - return true; - } + if (!d.skipCustomSection(codeMeta)) { return false; } } @@ -3381,26 +4303,59 @@ bool wasm::DecodeModuleTail(Decoder& d, ModuleEnvironment* env) { // Validate algorithm. -bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode, +bool wasm::Validate(JSContext* cx, const BytecodeSource& bytecode, const FeatureOptions& options, UniqueChars* error) { - Decoder d(bytecode.bytes, 0, error); - FeatureArgs features = FeatureArgs::build(cx, options); - ModuleEnvironment env(features); - if (!env.init()) { + SharedCompileArgs compileArgs = CompileArgs::buildForValidation(features); + if (!compileArgs) { + return false; + } + MutableModuleMetadata moduleMeta = js_new(); + if (!moduleMeta || !moduleMeta->init(*compileArgs)) { + return false; + } + MutableCodeMetadata codeMeta = moduleMeta->codeMeta; + + Decoder envDecoder(bytecode.envSpan(), bytecode.envRange().start, error); + if (!DecodeModuleEnvironment(envDecoder, codeMeta, moduleMeta)) { return false; } - if (!DecodeModuleEnvironment(d, &env)) { - return false; - } + if (bytecode.hasCodeSection()) { + // DecodeModuleEnvironment will stop and return true if there is an unknown + // section before the code section. We must check this and return an error. + if (!moduleMeta->codeMeta->codeSectionRange) { + envDecoder.fail("unknown section before code section"); + return false; + } - if (!DecodeCodeSection(d, &env)) { - return false; - } + // Our pre-parse that split the module should ensure that after we've + // parsed the environment there are no bytes left. + MOZ_RELEASE_ASSERT(envDecoder.done()); - if (!DecodeModuleTail(d, &env)) { - return false; + Decoder codeDecoder(bytecode.codeSpan(), bytecode.codeRange().start, error); + if (!DecodeCodeSection(codeDecoder, codeMeta)) { + return false; + } + // Our pre-parse that split the module should ensure that after we've + // parsed the code section there are no bytes left. + MOZ_RELEASE_ASSERT(codeDecoder.done()); + + Decoder tailDecoder(bytecode.tailSpan(), bytecode.tailRange().start, error); + if (!DecodeModuleTail(tailDecoder, codeMeta, moduleMeta)) { + return false; + } + // Decoding the module tail should consume all remaining bytes. + MOZ_RELEASE_ASSERT(tailDecoder.done()); + } else { + if (!DecodeCodeSection(envDecoder, codeMeta)) { + return false; + } + if (!DecodeModuleTail(envDecoder, codeMeta, moduleMeta)) { + return false; + } + // Decoding the module tail should consume all remaining bytes. + MOZ_RELEASE_ASSERT(envDecoder.done()); } MOZ_ASSERT(!*error, "unreported error in decoding"); diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.h b/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.h index 4dab19416ce..68a507aac83 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmValidate.h @@ -28,185 +28,13 @@ #include "wasm/WasmCompile.h" #include "wasm/WasmCompileArgs.h" #include "wasm/WasmModuleTypes.h" +#include "wasm/WasmOpIter.h" #include "wasm/WasmProcess.h" #include "wasm/WasmTypeDef.h" namespace js { namespace wasm { -using mozilla::Some; - -// ModuleEnvironment contains all the state necessary to process or render -// functions, and all of the state necessary to validate all aspects of the -// functions. -// -// A ModuleEnvironment is created by decoding all the sections before the wasm -// code section and then used immutably during. When compiling a module using a -// ModuleGenerator, the ModuleEnvironment holds state shared between the -// ModuleGenerator thread and background compile threads. All the threads -// are given a read-only view of the ModuleEnvironment, thus preventing race -// conditions. - -struct ModuleEnvironment { - // Constant parameters for the entire compilation: - const ModuleKind kind; - const FeatureArgs features; - - // Module fields decoded from the module environment (or initialized while - // validating an asm.js module) and immutable during compilation: - Maybe dataCount; - MemoryDescVector memories; - MutableTypeContext types; - FuncDescVector funcs; - BranchHintCollection branchHints; - uint32_t numFuncImports; - uint32_t numGlobalImports; - GlobalDescVector globals; - TagDescVector tags; - TableDescVector tables; - Uint32Vector asmJSSigToTableIndex; - ImportVector imports; - ExportVector exports; - Maybe startFuncIndex; - ModuleElemSegmentVector elemSegments; - MaybeSectionRange codeSection; - - // The start offset of the FuncImportInstanceData[] section of the instance - // data. There is one entry for every imported function. - uint32_t funcImportsOffsetStart; - // The start offset of the TypeDefInstanceData[] section of the instance - // data. There is one entry for every type. - uint32_t typeDefsOffsetStart; - // The start offset of the MemoryInstanceData[] section of the instance data. - // There is one entry for every memory. - uint32_t memoriesOffsetStart; - // The start offset of the TableInstanceData[] section of the instance data. - // There is one entry for every table. - uint32_t tablesOffsetStart; - // The start offset of the tag section of the instance data. There is one - // entry for every tag. - uint32_t tagsOffsetStart; - - // Fields decoded as part of the wasm module tail: - DataSegmentEnvVector dataSegments; - CustomSectionEnvVector customSections; - Maybe nameCustomSectionIndex; - Maybe moduleName; - NameVector funcNames; - - // Indicates whether the branch hint section was successfully parsed. - bool parsedBranchHints; - - explicit ModuleEnvironment(FeatureArgs features, - ModuleKind kind = ModuleKind::Wasm) - : kind(kind), - features(features), - numFuncImports(0), - numGlobalImports(0), - funcImportsOffsetStart(UINT32_MAX), - typeDefsOffsetStart(UINT32_MAX), - memoriesOffsetStart(UINT32_MAX), - tablesOffsetStart(UINT32_MAX), - tagsOffsetStart(UINT32_MAX), - parsedBranchHints(false) {} - - [[nodiscard]] bool init() { - types = js_new(features); - return types; - } - - size_t numTables() const { return tables.length(); } - size_t numTypes() const { return types->length(); } - size_t numFuncs() const { return funcs.length(); } - size_t numFuncDefs() const { return funcs.length() - numFuncImports; } - - bool funcIsImport(uint32_t funcIndex) const { - return funcIndex < numFuncImports; - } - size_t numMemories() const { return memories.length(); } - -#define WASM_FEATURE(NAME, SHORT_NAME, ...) \ - bool SHORT_NAME##Enabled() const { return features.SHORT_NAME; } - JS_FOR_WASM_FEATURES(WASM_FEATURE) -#undef WASM_FEATURE - Shareable sharedMemoryEnabled() const { return features.sharedMemory; } - bool simdAvailable() const { return features.simd; } - - bool isAsmJS() const { return kind == ModuleKind::AsmJS; } - // A builtin module is a host constructed wasm module that exports host - // functionality, using special opcodes. Otherwise, it has the same rules - // as wasm modules and so it does not get a new ModuleKind. - bool isBuiltinModule() const { return features.isBuiltinModule; } - - bool hugeMemoryEnabled(uint32_t memoryIndex) const { - return !isAsmJS() && memoryIndex < memories.length() && - IsHugeMemoryEnabled(memories[memoryIndex].indexType()); - } - bool usesSharedMemory(uint32_t memoryIndex) const { - return memoryIndex < memories.length() && memories[memoryIndex].isShared(); - } - - void declareFuncExported(uint32_t funcIndex, bool eager, bool canRefFunc) { - FuncFlags flags = funcs[funcIndex].flags; - - // Set the `Exported` flag, if not set. - flags = FuncFlags(uint8_t(flags) | uint8_t(FuncFlags::Exported)); - - // Merge in the `Eager` and `CanRefFunc` flags, if they're set. Be sure - // to not unset them if they've already been set. - if (eager) { - flags = FuncFlags(uint8_t(flags) | uint8_t(FuncFlags::Eager)); - } - if (canRefFunc) { - flags = FuncFlags(uint8_t(flags) | uint8_t(FuncFlags::CanRefFunc)); - } - - funcs[funcIndex].flags = flags; - } - - uint32_t offsetOfFuncImportInstanceData(uint32_t funcIndex) const { - MOZ_ASSERT(funcIndex < numFuncImports); - return funcImportsOffsetStart + funcIndex * sizeof(FuncImportInstanceData); - } - - uint32_t offsetOfTypeDefInstanceData(uint32_t typeIndex) const { - MOZ_ASSERT(typeIndex < types->length()); - return typeDefsOffsetStart + typeIndex * sizeof(TypeDefInstanceData); - } - - uint32_t offsetOfTypeDef(uint32_t typeIndex) const { - return offsetOfTypeDefInstanceData(typeIndex) + - offsetof(TypeDefInstanceData, typeDef); - } - uint32_t offsetOfSuperTypeVector(uint32_t typeIndex) const { - return offsetOfTypeDefInstanceData(typeIndex) + - offsetof(TypeDefInstanceData, superTypeVector); - } - - uint32_t offsetOfMemoryInstanceData(uint32_t memoryIndex) const { - MOZ_ASSERT(memoryIndex < memories.length()); - return memoriesOffsetStart + memoryIndex * sizeof(MemoryInstanceData); - } - uint32_t offsetOfTableInstanceData(uint32_t tableIndex) const { - MOZ_ASSERT(tableIndex < tables.length()); - return tablesOffsetStart + tableIndex * sizeof(TableInstanceData); - } - - uint32_t offsetOfTagInstanceData(uint32_t tagIndex) const { - MOZ_ASSERT(tagIndex < tags.length()); - return tagsOffsetStart + tagIndex * sizeof(TagInstanceData); - } - - bool addDefinedFunc( - ValTypeVector&& params, ValTypeVector&& results, - bool declareForRef = false, - Maybe&& optionalExportedName = mozilla::Nothing()); - - bool addImportedFunc(ValTypeVector&& params, ValTypeVector&& results, - CacheableName&& importModName, - CacheableName&& importFieldName); -}; - // ElemSegmentFlags provides methods for decoding and encoding the flags field // of an element segment. This is needed as the flags field has a non-trivial // encoding that is effectively split into independent `kind` and `payload` @@ -237,11 +65,11 @@ class ElemSegmentFlags { encoded_ = uint32_t(kind) | uint32_t(payload); } - static Maybe construct(uint32_t encoded) { + static mozilla::Maybe construct(uint32_t encoded) { if (encoded > uint32_t(Flags::AllFlags)) { - return Nothing(); + return mozilla::Nothing(); } - return Some(ElemSegmentFlags(encoded)); + return mozilla::Some(ElemSegmentFlags(encoded)); } uint32_t encoded() const { return encoded_; } @@ -258,22 +86,22 @@ class ElemSegmentFlags { // OpIter specialized for validation. class NothingVector { - Nothing unused_; + mozilla::Nothing unused_; public: bool reserve(size_t size) { return true; } bool resize(size_t length) { return true; } - Nothing& operator[](size_t) { return unused_; } - Nothing& back() { return unused_; } + mozilla::Nothing& operator[](size_t) { return unused_; } + mozilla::Nothing& back() { return unused_; } size_t length() const { return 0; } - bool append(Nothing& nothing) { return true; } - void infallibleAppend(Nothing& nothing) {} + bool append(mozilla::Nothing& nothing) { return true; } + void infallibleAppend(mozilla::Nothing& nothing) {} }; struct ValidatingPolicy { - using Value = Nothing; + using Value = mozilla::Nothing; using ValueVector = NothingVector; - using ControlItem = Nothing; + using ControlItem = mozilla::Nothing; }; template @@ -283,7 +111,10 @@ using ValidatingOpIter = OpIter; // Shared subtyping function across validation. -[[nodiscard]] bool CheckIsSubtypeOf(Decoder& d, const ModuleEnvironment& env, +[[nodiscard]] bool CheckIsSubtypeOf(Decoder& d, const CodeMetadata& codeMeta, + size_t opcodeOffset, ResultType subType, + ResultType superType); +[[nodiscard]] bool CheckIsSubtypeOf(Decoder& d, const CodeMetadata& codeMeta, size_t opcodeOffset, StorageType subType, StorageType superType); @@ -303,19 +134,19 @@ using ValidatingOpIter = OpIter; // to generate the full local entries for use in validation [[nodiscard]] bool DecodeLocalEntriesWithParams(Decoder& d, - const ModuleEnvironment& env, + const CodeMetadata& codeMeta, uint32_t funcIndex, ValTypeVector* locals); // Returns whether the given [begin, end) prefix of a module's bytecode starts a -// code section and, if so, returns the SectionRange of that code section. +// code section and, if so, returns the BytecodeRange of that code section. // Note that, even if this function returns 'false', [begin, end) may actually // be a valid module in the special case when there are no function defs and the // code section is not present. Such modules can be valid so the caller must // handle this special case. [[nodiscard]] bool StartsCodeSection(const uint8_t* begin, const uint8_t* end, - SectionRange* codeSection); + BytecodeRange* codeSection); // Calling DecodeModuleEnvironment decodes all sections up to the code section // and performs full validation of all those sections. The client must then @@ -323,22 +154,62 @@ using ValidatingOpIter = OpIter; // and finally call DecodeModuleTail to decode all remaining sections after the // code section (again, performing full validation). -[[nodiscard]] bool DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env); +[[nodiscard]] bool DecodeModuleEnvironment(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* moduleMeta); -[[nodiscard]] bool ValidateFunctionBody(const ModuleEnvironment& env, +[[nodiscard]] bool ValidateFunctionBody(const CodeMetadata& codeMeta, uint32_t funcIndex, uint32_t bodySize, Decoder& d); -[[nodiscard]] bool DecodeModuleTail(Decoder& d, ModuleEnvironment* env); +[[nodiscard]] bool DecodeModuleTail(Decoder& d, CodeMetadata* codeMeta, + ModuleMetadata* meta); // Validate an entire module, returning true if the module was validated // successfully. If Validate returns false: // - if *error is null, the caller should report out-of-memory // - otherwise, there was a legitimate error described by *error -[[nodiscard]] bool Validate(JSContext* cx, const ShareableBytes& bytecode, +[[nodiscard]] bool Validate(JSContext* cx, const BytecodeSource& bytecode, const FeatureOptions& options, UniqueChars* error); +struct NopOpDumper { + void dumpOpBegin(OpBytes op) {} + void dumpOpEnd() {} + void dumpTypeIndex(uint32_t typeIndex, bool asTypeUse = false) {} + void dumpFuncIndex(uint32_t funcIndex) {} + void dumpTableIndex(uint32_t tableIndex) {} + void dumpGlobalIndex(uint32_t globalIndex) {} + void dumpMemoryIndex(uint32_t memoryIndex) {} + void dumpElemIndex(uint32_t elemIndex) {} + void dumpDataIndex(uint32_t dataIndex) {} + void dumpTagIndex(uint32_t tagIndex) {} + void dumpLocalIndex(uint32_t localIndex) {} + void dumpBlockType(BlockType type) {} + void dumpI32Const(int32_t constant) {} + void dumpI64Const(int64_t constant) {} + void dumpF32Const(float constant) {} + void dumpF64Const(double constant) {} + void dumpV128Const(V128 constant) {} + void dumpVectorMask(V128 mask) {} + void dumpRefType(RefType type) {} + void dumpHeapType(RefType type) {} + void dumpValType(ValType type) {} + void dumpTryTableCatches(const TryTableCatchVector& catches) {} + void dumpLinearMemoryAddress(LinearMemoryAddress addr) {} + void dumpBlockDepth(uint32_t relativeDepth) {} + void dumpBlockDepths(const Uint32Vector& relativeDepths) {} + void dumpFieldIndex(uint32_t fieldIndex) {} + void dumpNumElements(uint32_t numElements) {} + void dumpLaneIndex(uint32_t laneIndex) {} + + void startScope() {}; + void endScope() {}; +}; + +template +[[nodiscard]] bool ValidateOps(ValidatingOpIter& iter, T& dumper, + const CodeMetadata& codeMeta); + } // namespace wasm } // namespace js diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmValue.cpp b/src/third_party/mozjs/extract/js/src/wasm/WasmValue.cpp index 824cc0e2ccc..9960e31c706 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmValue.cpp +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmValue.cpp @@ -114,55 +114,9 @@ void Val::trace(JSTracer* trc) const { } } -bool wasm::CheckRefType(JSContext* cx, RefType targetType, HandleValue v, - MutableHandleFunction fnval, - MutableHandleAnyRef refval) { - if (!targetType.isNullable() && v.isNull()) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_REF_NONNULLABLE_VALUE); - return false; - } - - switch (targetType.kind()) { - case RefType::Func: - return CheckFuncRefValue(cx, v, fnval); - case RefType::Extern: - return AnyRef::fromJSValue(cx, v, refval); - case RefType::Exn: - // Break to the non-exposable case - break; - case RefType::Any: - return CheckAnyRefValue(cx, v, refval); - case RefType::NoFunc: - return CheckNullFuncRefValue(cx, v, fnval); - case RefType::NoExn: - return CheckNullExnRefValue(cx, v, refval); - case RefType::NoExtern: - return CheckNullExternRefValue(cx, v, refval); - case RefType::None: - return CheckNullRefValue(cx, v, refval); - case RefType::Eq: - return CheckEqRefValue(cx, v, refval); - case RefType::I31: - return CheckI31RefValue(cx, v, refval); - case RefType::Struct: - return CheckStructRefValue(cx, v, refval); - case RefType::Array: - return CheckArrayRefValue(cx, v, refval); - case RefType::TypeRef: - return CheckTypeRefValue(cx, targetType.typeDef(), v, refval); - } - - MOZ_ASSERT(!ValType(targetType).isExposable()); - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_VAL_TYPE); - return false; -} - -bool wasm::CheckFuncRefValue(JSContext* cx, HandleValue v, - MutableHandleFunction fun) { +bool CheckFuncRefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (v.isNull()) { - MOZ_ASSERT(!fun); + vp.set(AnyRef::null()); return true; } @@ -170,8 +124,8 @@ bool wasm::CheckFuncRefValue(JSContext* cx, HandleValue v, JSObject& obj = v.toObject(); if (obj.is()) { JSFunction* f = &obj.as(); - if (IsWasmExportedFunction(f)) { - fun.set(f); + if (f->isWasm()) { + vp.set(AnyRef::fromJSObject(*f)); return true; } } @@ -182,8 +136,7 @@ bool wasm::CheckFuncRefValue(JSContext* cx, HandleValue v, return false; } -bool wasm::CheckAnyRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckAnyRefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (!AnyRef::fromJSValue(cx, v, vp)) { MOZ_ASSERT(cx->isThrowingOutOfMemory()); return false; @@ -191,19 +144,19 @@ bool wasm::CheckAnyRefValue(JSContext* cx, HandleValue v, return true; } -bool wasm::CheckNullFuncRefValue(JSContext* cx, HandleValue v, - MutableHandleFunction fun) { +bool CheckNullFuncRefValue(JSContext* cx, HandleValue v, + MutableHandleAnyRef vp) { if (!v.isNull()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_NULL_FUNCREF_VALUE); return false; } - MOZ_ASSERT(!fun); + vp.set(AnyRef::null()); return true; } -bool wasm::CheckNullExnRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckNullExnRefValue(JSContext* cx, HandleValue v, + MutableHandleAnyRef vp) { if (!v.isNull()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_NULL_EXNREF_VALUE); @@ -214,8 +167,8 @@ bool wasm::CheckNullExnRefValue(JSContext* cx, HandleValue v, return true; } -bool wasm::CheckNullExternRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckNullExternRefValue(JSContext* cx, HandleValue v, + MutableHandleAnyRef vp) { if (!v.isNull()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_NULL_EXTERNREF_VALUE); @@ -226,8 +179,7 @@ bool wasm::CheckNullExternRefValue(JSContext* cx, HandleValue v, return true; } -bool wasm::CheckNullRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckNullRefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (!v.isNull()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_NULL_ANYREF_VALUE); @@ -238,8 +190,7 @@ bool wasm::CheckNullRefValue(JSContext* cx, HandleValue v, return true; } -bool wasm::CheckEqRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckEqRefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (!AnyRef::fromJSValue(cx, v, vp)) { MOZ_ASSERT(cx->isThrowingOutOfMemory()); return false; @@ -255,8 +206,7 @@ bool wasm::CheckEqRefValue(JSContext* cx, HandleValue v, return false; } -bool wasm::CheckI31RefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckI31RefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (!AnyRef::fromJSValue(cx, v, vp)) { MOZ_ASSERT(cx->isThrowingOutOfMemory()); return false; @@ -271,8 +221,7 @@ bool wasm::CheckI31RefValue(JSContext* cx, HandleValue v, return false; } -bool wasm::CheckStructRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckStructRefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (v.isNull()) { vp.set(AnyRef::null()); return true; @@ -291,8 +240,7 @@ bool wasm::CheckStructRefValue(JSContext* cx, HandleValue v, return false; } -bool wasm::CheckArrayRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp) { +bool CheckArrayRefValue(JSContext* cx, HandleValue v, MutableHandleAnyRef vp) { if (v.isNull()) { vp.set(AnyRef::null()); return true; @@ -311,8 +259,8 @@ bool wasm::CheckArrayRefValue(JSContext* cx, HandleValue v, return false; } -bool wasm::CheckTypeRefValue(JSContext* cx, const TypeDef* typeDef, - HandleValue v, MutableHandleAnyRef vp) { +bool CheckTypeRefValue(JSContext* cx, const TypeDef* typeDef, HandleValue v, + MutableHandleAnyRef vp) { if (v.isNull()) { vp.set(AnyRef::null()); return true; @@ -339,6 +287,55 @@ bool wasm::CheckTypeRefValue(JSContext* cx, const TypeDef* typeDef, return false; } +bool wasm::CheckRefType(JSContext* cx, RefType targetType, HandleValue v, + MutableHandleAnyRef vp) { + if (!targetType.isNullable() && v.isNull()) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_BAD_REF_NONNULLABLE_VALUE); + return false; + } + + switch (targetType.kind()) { + case RefType::Func: + return CheckFuncRefValue(cx, v, vp); + case RefType::Extern: + return AnyRef::fromJSValue(cx, v, vp); + case RefType::Exn: + // Break to the non-exposable case + break; + case RefType::Any: + return CheckAnyRefValue(cx, v, vp); + case RefType::NoFunc: + return CheckNullFuncRefValue(cx, v, vp); + case RefType::NoExn: + return CheckNullExnRefValue(cx, v, vp); + case RefType::NoExtern: + return CheckNullExternRefValue(cx, v, vp); + case RefType::None: + return CheckNullRefValue(cx, v, vp); + case RefType::Eq: + return CheckEqRefValue(cx, v, vp); + case RefType::I31: + return CheckI31RefValue(cx, v, vp); + case RefType::Struct: + return CheckStructRefValue(cx, v, vp); + case RefType::Array: + return CheckArrayRefValue(cx, v, vp); + case RefType::TypeRef: + return CheckTypeRefValue(cx, targetType.typeDef(), v, vp); + } + + MOZ_ASSERT(!ValType(targetType).isExposable()); + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_BAD_VAL_TYPE); + return false; +} + +bool wasm::CheckRefType(JSContext* cx, RefType targetType, HandleValue v) { + RootedAnyRef any(cx, AnyRef::null()); + return CheckRefType(cx, targetType, v, &any); +} + class wasm::NoDebug { public: template @@ -486,11 +483,11 @@ bool ToWebAssemblyValue_nullexternref(JSContext* cx, HandleValue val, template bool ToWebAssemblyValue_funcref(JSContext* cx, HandleValue val, void** loc, bool mustWrite64) { - RootedFunction fun(cx); - if (!CheckFuncRefValue(cx, val, &fun)) { + RootedAnyRef result(cx, AnyRef::null()); + if (!CheckFuncRefValue(cx, val, &result)) { return false; } - loc[0] = fun; + loc[0] = result.get().forCompiledCode(); #ifndef JS_64BIT if (mustWrite64) { loc[1] = nullptr; @@ -503,11 +500,11 @@ bool ToWebAssemblyValue_funcref(JSContext* cx, HandleValue val, void** loc, template bool ToWebAssemblyValue_nullfuncref(JSContext* cx, HandleValue val, void** loc, bool mustWrite64) { - RootedFunction fun(cx); - if (!CheckNullFuncRefValue(cx, val, &fun)) { + RootedAnyRef result(cx, AnyRef::null()); + if (!CheckNullFuncRefValue(cx, val, &result)) { return false; } - loc[0] = fun; + loc[0] = result.get().forCompiledCode(); #ifndef JS_64BIT if (mustWrite64) { loc[1] = nullptr; @@ -673,15 +670,11 @@ bool wasm::ToWebAssemblyValue(JSContext* cx, HandleValue val, ValType type, case ValType::V128: break; case ValType::Ref: -#ifdef ENABLE_WASM_GC if (!type.isNullable() && val.isNull()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_REF_NONNULLABLE_VALUE); return false; } -#else - MOZ_ASSERT(type.isNullable()); -#endif switch (type.refTypeKind()) { case RefType::Func: return ToWebAssemblyValue_funcref(cx, val, (void**)loc, diff --git a/src/third_party/mozjs/extract/js/src/wasm/WasmValue.h b/src/third_party/mozjs/extract/js/src/wasm/WasmValue.h index ddb2463883d..22bc097473f 100644 --- a/src/third_party/mozjs/extract/js/src/wasm/WasmValue.h +++ b/src/third_party/mozjs/extract/js/src/wasm/WasmValue.h @@ -19,6 +19,8 @@ #ifndef wasm_val_h #define wasm_val_h +#include + #include "js/Class.h" // JSClassOps, ClassSpec #include "vm/JSObject.h" #include "vm/NativeObject.h" // NativeObject @@ -55,12 +57,7 @@ struct V128 { } bool operator==(const V128& rhs) const { - for (size_t i = 0; i < sizeof(bytes); i++) { - if (bytes[i] != rhs.bytes[i]) { - return false; - } - } - return true; + return memcmp(bytes, rhs.bytes, sizeof(bytes)) == 0; } bool operator!=(const V128& rhs) const { return !(*this == rhs); } @@ -350,64 +347,17 @@ using ValVectorN = GCVector; template using RootedValVectorN = Rooted>; -// Check a value against the given reference type. If the targetType -// is RefType::Extern then the test always passes, but the value may be boxed. -// If the test passes then the value is stored either in fnval (for -// RefType::Func) or in refval (for other types); this split is not strictly -// necessary but is convenient for the users of this function. -// -// This can return false if the type check fails, or if a boxing into AnyRef -// throws an OOM. +// Check if a JS value matches against a given reference type. +// Returns true and gives the corresponding wasm::AnyRef value for the JS value +// if the type check succeeds. Returns false and sets an error if the type +// check fails, or boxing the wasm::AnyRef failed due to an OOM. [[nodiscard]] extern bool CheckRefType(JSContext* cx, RefType targetType, - HandleValue v, - MutableHandleFunction fnval, - MutableHandleAnyRef refval); + HandleValue v, MutableHandleAnyRef vp); +// The same as above, but discards the resulting wasm::AnyRef. This may still +// fail due to an OOM. +[[nodiscard]] extern bool CheckRefType(JSContext* cx, RefType targetType, + HandleValue v); -// The same as above for when the target type is 'funcref'. -[[nodiscard]] extern bool CheckFuncRefValue(JSContext* cx, HandleValue v, - MutableHandleFunction fun); - -// The same as above for when the target type is 'anyref'. -[[nodiscard]] extern bool CheckAnyRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'nullexnref'. -[[nodiscard]] extern bool CheckNullExnRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'nullexternref'. -[[nodiscard]] extern bool CheckNullExternRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'nullfuncref'. -[[nodiscard]] extern bool CheckNullFuncRefValue(JSContext* cx, HandleValue v, - MutableHandleFunction fun); - -// The same as above for when the target type is 'nullref'. -[[nodiscard]] extern bool CheckNullRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'eqref'. -[[nodiscard]] extern bool CheckEqRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'i31ref'. -[[nodiscard]] extern bool CheckI31RefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'structref'. -[[nodiscard]] extern bool CheckStructRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is 'arrayref'. -[[nodiscard]] extern bool CheckArrayRefValue(JSContext* cx, HandleValue v, - MutableHandleAnyRef vp); - -// The same as above for when the target type is '(ref T)'. -[[nodiscard]] extern bool CheckTypeRefValue(JSContext* cx, - const TypeDef* typeDef, - HandleValue v, - MutableHandleAnyRef vp); class NoDebug; class DebugCodegenVal; diff --git a/src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-slow.txt b/src/third_party/mozjs/extract/js/src/wasm/test.js similarity index 100% rename from src/third_party/mozjs/extract/js/src/devtools/automation/smoosh-jstests-slow.txt rename to src/third_party/mozjs/extract/js/src/wasm/test.js diff --git a/src/third_party/mozjs/extract/js/src/xsum/LICENSE b/src/third_party/mozjs/extract/js/src/xsum/LICENSE new file mode 100644 index 00000000000..dcbe2574571 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/xsum/LICENSE @@ -0,0 +1,23 @@ +This software for exact summation of floating-point values is licensed +under the "MIT license", included here. + +Copyright 2015, 2018, 2021, 2024 Radford M. Neal + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/third_party/mozjs/extract/js/src/xsum/README.md b/src/third_party/mozjs/extract/js/src/xsum/README.md new file mode 100644 index 00000000000..095aa3c5da0 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/xsum/README.md @@ -0,0 +1,15 @@ +# Xsum library + +The xsum library is imported from https://gitlab.com/radfordneal/xsum manually +the directory contains a reduced version of the xsum library as required for +the implementation of the +[Math.sumPrecise proposal](https://tc39.es/proposal-math-sum/#sec-math.sumprecise) +since the library isn't expected to have frequent updates, the manual vendoring +process was followed. In addition to importing select code a few modifications +were made to the code: + +- The files were updated from .c files (as found in the original repository) +to c++ files, .cpp. +- The code was updated to not use C specific syntax specifically the orginal +code extensively used the ["restrict type qualifier"](https://en.cppreference.com/w/c/language/restrict) +whose usage has been removed to comply with C++ syntax. diff --git a/src/third_party/mozjs/extract/js/src/xsum/moz.build b/src/third_party/mozjs/extract/js/src/xsum/moz.build new file mode 100644 index 00000000000..dc7a4f2497f --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/xsum/moz.build @@ -0,0 +1,20 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +FINAL_LIBRARY = "js" + +# Includes should be relative to parent path +LOCAL_INCLUDES += ["!..", ".."] + +include("../js-config.mozbuild") +include("../js-cxxflags.mozbuild") + +SOURCES += [ + 'xsum.cpp', +] + +# Suppress warnings in third-party code. +SOURCES['xsum.cpp'].flags += ['-Wno-implicit-fallthrough', '-Wno-format', '-Wno-unused-value'] diff --git a/src/third_party/mozjs/extract/js/src/xsum/xsum.cpp b/src/third_party/mozjs/extract/js/src/xsum/xsum.cpp new file mode 100644 index 00000000000..cd3ae66cf3e --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/xsum/xsum.cpp @@ -0,0 +1,1043 @@ +/* FUNCTIONS FOR EXACT SUMMATION. */ + +/* Copyright 2015, 2018, 2021, 2024 Radford M. Neal + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include "xsum.h" + +/* ---------------------- IMPLEMENTATION ASSUMPTIONS ----------------------- */ + +/* This code makes the following assumptions: + + o The 'double' type is a IEEE-754 standard 64-bit floating-point value. + + o The 'int64_t' and 'uint64_t' types exist, for 64-bit signed and + unsigned integers. + + o The 'endianness' of 'double' and 64-bit integers is consistent + between these types - that is, looking at the bits of a 'double' + value as an 64-bit integer will have the expected result. + + o Right shifts of a signed operand produce the results expected for + a two's complement representation. + + o Rounding should be done in the "round to nearest, ties to even" mode. +*/ + +/* --------------------------- CONFIGURATION ------------------------------- */ + +/* IMPLEMENTATION OPTIONS. Can be set to either 0 or 1, whichever seems + to be fastest. */ + +#define USE_SIMD 1 /* Use SIMD intrinsics (SSE2/AVX) if available? */ + +#define USE_MEMSET_SMALL \ + 1 /* Use memset rather than a loop (for small mem)? \ + */ +#define USE_MEMSET_LARGE \ + 1 /* Use memset rather than a loop (for large mem)? \ + */ +#define USE_USED_LARGE 1 /* Use the used flags in a large accumulator? */ + +#define OPT_SMALL 0 /* Class of manual optimization for operations on */ + /* small accumulator: 0 (none), 1, 2, 3 (SIMD) */ +#define OPT_CARRY 1 /* Use manually optimized carry propagation? */ + +#define OPT_LARGE_SUM 1 /* Should manually optimized routines be used for */ +#define OPT_LARGE_SQNORM 1 /* operations using the large accumulator? */ +#define OPT_LARGE_DOT 1 + +#define OPT_SIMPLE_SUM 1 /* Should manually optimized routines be used for */ +#define OPT_SIMPLE_SQNORM 1 /* operations done with simple FP arithmetic? */ +#define OPT_SIMPLE_DOT 1 + +#define OPT_KAHAN_SUM 0 /* Use manually optimized routine for Kahan sum? */ + +#define INLINE_SMALL 1 /* Inline more of the small accumulator routines? */ + /* (Not currently used) */ +#define INLINE_LARGE 1 /* Inline more of the large accumulator routines? */ + +/* INCLUDE INTEL INTRINSICS IF USED AND AVAILABLE. */ + +#if USE_SIMD && __SSE2__ +# include +#endif + +/* COPY A 64-BIT QUANTITY - DOUBLE TO 64-BIT INT OR VICE VERSA. The + arguments are destination and source variables (not values). */ + +#define COPY64(dst, src) memcpy(&(dst), &(src), sizeof(double)) + +/* OPTIONAL INCLUSION OF PBINARY MODULE. Used for debug output. */ + +#ifdef PBINARY +# include "pbinary.h" +#else +# define pbinary_int64(x, y) 0 +# define pbinary_double(x) 0 +#endif + +/* SET UP DEBUG FLAG. It's a variable if debuging is enabled, and a + constant if disabled (so that no code will be generated then). */ + +int xsum_debug = 0; + +#ifndef DEBUG +# define xsum_debug 0 +#endif + +/* SET UP INLINE / NOINLINE MACROS. */ + +#if __GNUC__ +# define INLINE inline __attribute__((always_inline)) +# define NOINLINE __attribute__((noinline)) +#else +# define INLINE inline +# define NOINLINE +#endif + +/* ------------------------ INTERNAL ROUTINES ------------------------------- */ + +/* ADD AN INF OR NAN TO A SMALL ACCUMULATOR. This only changes the flags, + not the chunks in the accumulator, which retains the sum of the finite + terms (which is perhaps sometimes useful to access, though no function + to do so is defined at present). A NaN with larger payload (seen as a + 52-bit unsigned integer) takes precedence, with the sign of the NaN always + being positive. This ensures that the order of summing NaN values doesn't + matter. */ + +static NOINLINE void xsum_small_add_inf_nan(xsum_small_accumulator* sacc, + xsum_int ivalue) { + xsum_int mantissa; + double fltv; + + mantissa = ivalue & XSUM_MANTISSA_MASK; + + if (mantissa == 0) /* Inf */ + { + if (sacc->Inf == 0) { /* no previous Inf */ + sacc->Inf = ivalue; + } else if (sacc->Inf != ivalue) { /* previous Inf was opposite sign */ + COPY64(fltv, ivalue); + fltv = fltv - fltv; /* result will be a NaN */ + COPY64(sacc->Inf, fltv); + } + } else /* NaN */ + { /* Choose the NaN with the bigger payload and clear its sign. Using <= + ensures that we will choose the first NaN over the previous zero. */ + if ((sacc->NaN & XSUM_MANTISSA_MASK) <= mantissa) { + sacc->NaN = ivalue & ~XSUM_SIGN_MASK; + } + } +} + +/* PROPAGATE CARRIES TO NEXT CHUNK IN A SMALL ACCUMULATOR. Needs to + be called often enough that accumulated carries don't overflow out + the top, as indicated by sacc->adds_until_propagate. Returns the + index of the uppermost non-zero chunk (0 if number is zero). + + After carry propagation, the uppermost non-zero chunk will indicate + the sign of the number, and will not be -1 (all 1s). It will be in + the range -2^XSUM_LOW_MANTISSA_BITS to 2^XSUM_LOW_MANTISSA_BITS - 1. + Lower chunks will be non-negative, and in the range from 0 up to + 2^XSUM_LOW_MANTISSA_BITS - 1. */ + +static NOINLINE int xsum_carry_propagate(xsum_small_accumulator* sacc) { + int i, u, uix; + + if (xsum_debug) printf("\nCARRY PROPAGATING IN SMALL ACCUMULATOR\n"); + + /* Set u to the index of the uppermost non-zero (for now) chunk, or + return with value 0 if there is none. */ + +#if OPT_CARRY + + { + u = XSUM_SCHUNKS - 1; + switch (XSUM_SCHUNKS & 0x3) /* get u to be a multiple of 4 minus one */ + { + case 3: + if (sacc->chunk[u] != 0) { + goto found2; + } + u -= 1; /* XSUM_SCHUNKS is a */ + case 2: + if (sacc->chunk[u] != 0) /* constant, so the */ + { + goto found2; /* compiler will do */ + } /* simple code here */ + u -= 1; + case 1: + if (sacc->chunk[u] != 0) { + goto found2; + } + u -= 1; + case 0:; + } + + do /* here, u should be a multiple of 4 minus one, and at least 3 */ + { +# if USE_SIMD && __AVX__ + { + __m256i ch; + ch = _mm256_loadu_si256((__m256i*)(sacc->chunk + u - 3)); + if (!_mm256_testz_si256(ch, ch)) { + goto found; + } + u -= 4; + if (u < 0) /* never actually happens, because value of XSUM_SCHUNKS */ + { + break; /* is such that u < 0 occurs at end of do loop instead */ + } + ch = _mm256_loadu_si256((__m256i*)(sacc->chunk + u - 3)); + if (!_mm256_testz_si256(ch, ch)) { + goto found; + } + u -= 4; + } +# else + { + if (sacc->chunk[u] | sacc->chunk[u - 1] | sacc->chunk[u - 2] | + sacc->chunk[u - 3]) { + goto found; + } + u -= 4; + } +# endif + + } while (u >= 0); + + if (xsum_debug) printf("number is zero (1)\n"); + uix = 0; + goto done; + + found: + if (sacc->chunk[u] != 0) { + goto found2; + } + u -= 1; + if (sacc->chunk[u] != 0) { + goto found2; + } + u -= 1; + if (sacc->chunk[u] != 0) { + goto found2; + } + u -= 1; + + found2:; + } + +#else /* Non-optimized search for uppermost non-zero chunk */ + + { + for (u = XSUM_SCHUNKS - 1; sacc->chunk[u] == 0; u--) { + if (u == 0) { + if (xsum_debug) printf("number is zero (1)\n"); + uix = 0; + goto done; + } + } + } + +#endif + + /* At this point, sacc->chunk[u] must be non-zero */ + // MONGODB MODIFICATION: Use portable format specifier + if (xsum_debug) printf("u: %d, sacc->chunk[u]: %" PRId64, u, sacc->chunk[u]); + + /* Carry propagate, starting at the low-order chunks. Note that the + loop limit of u may be increased inside the loop. */ + + i = 0; /* set to the index of the next non-zero chunck, from bottom */ + +#if OPT_CARRY + { + /* Quickly skip over unused low-order chunks. Done here at the start + on the theory that there are often many unused low-order chunks, + justifying some overhead to begin, but later stretches of unused + chunks may not be as large. */ + + int e = u - 3; /* go only to 3 before so won't access beyond chunk array */ + + do { +# if USE_SIMD && __AVX__ + { + __m256i ch; + ch = _mm256_loadu_si256((__m256i*)(sacc->chunk + i)); + if (!_mm256_testz_si256(ch, ch)) { + break; + } + i += 4; + if (i >= e) { + break; + } + ch = _mm256_loadu_si256((__m256i*)(sacc->chunk + i)); + if (!_mm256_testz_si256(ch, ch)) { + break; + } + } +# else + { + if (sacc->chunk[i] | sacc->chunk[i + 1] | sacc->chunk[i + 2] | + sacc->chunk[i + 3]) { + break; + } + } +# endif + + i += 4; + + } while (i <= e); + } +#endif + + uix = -1; /* indicates that a non-zero chunk has not been found yet */ + + do { + xsum_schunk c; /* Set to the chunk at index i (next non-zero one) */ + xsum_schunk clow; /* Low-order bits of c */ + xsum_schunk chigh; /* High-order bits of c */ + + /* Find the next non-zero chunk, setting i to its index, or break out + of loop if there is none. Note that the chunk at index u is not + necessarily non-zero - it was initially, but u or the chunk at u + may have changed. */ + +#if OPT_CARRY + { + c = sacc->chunk[i]; + if (c != 0) { + goto nonzero; + } + i += 1; + if (i > u) { + break; /* reaching here is only possible when u == i initially, */ + } /* with the last add to a chunk having changed it to 0 */ + + for (;;) { + c = sacc->chunk[i]; + if (c != 0) { + goto nonzero; + } + i += 1; + c = sacc->chunk[i]; + if (c != 0) { + goto nonzero; + } + i += 1; + c = sacc->chunk[i]; + if (c != 0) { + goto nonzero; + } + i += 1; + c = sacc->chunk[i]; + if (c != 0) { + goto nonzero; + } + i += 1; + } + } +#else + { + do { + c = sacc->chunk[i]; + if (c != 0) { + goto nonzero; + } + i += 1; + } while (i <= u); + + break; + } +#endif + + /* Propagate possible carry from this chunk to next chunk up. */ + + nonzero: + chigh = c >> XSUM_LOW_MANTISSA_BITS; + if (chigh == 0) { + uix = i; + i += 1; + continue; /* no need to change this chunk */ + } + + if (u == i) { + if (chigh == -1) { + uix = i; + break; /* don't propagate -1 into the region of all zeros above */ + } + u = i + 1; /* we will change chunk[u+1], so we'll need to look at it */ + } + + clow = c & XSUM_LOW_MANTISSA_MASK; + if (clow != 0) { + uix = i; + } + + /* We now change chunk[i] and add to chunk[i+1]. Note that i+1 should be + in range (no bigger than XSUM_CHUNKS-1) if summing memory, since + the number of chunks is big enough to hold any sum, and we do not + store redundant chunks with values 0 or -1 above previously non-zero + chunks. But other add operations might cause overflow, in which + case we produce a NaN with all 1s as payload. (We can't reliably produce + an Inf of the right sign.) */ + + sacc->chunk[i] = clow; + if (i + 1 >= XSUM_SCHUNKS) { + xsum_small_add_inf_nan( + sacc, + ((xsum_int)XSUM_EXP_MASK << XSUM_MANTISSA_BITS) | XSUM_MANTISSA_MASK); + u = i; + } else { + sacc->chunk[i + 1] += + chigh; /* note: this could make this chunk be zero */ + } + + i += 1; + + } while (i <= u); + + if (xsum_debug) printf(" uix: %d new u: %d\n", uix, u); + + /* Check again for the number being zero, since carry propagation might + have created zero from something that initially looked non-zero. */ + + if (uix < 0) { + if (xsum_debug) printf("number is zero (2)\n"); + uix = 0; + goto done; + } + + /* While the uppermost chunk is negative, with value -1, combine it with + the chunk below (if there is one) to produce the same number but with + one fewer non-zero chunks. */ + + while (sacc->chunk[uix] == -1 && + uix > 0) { /* Left shift of a negative number is undefined according to + the standard, so do a multiply - it's all presumably + constant-folded by the compiler.*/ + sacc->chunk[uix - 1] += + ((xsum_schunk)-1) * (((xsum_schunk)1) << XSUM_LOW_MANTISSA_BITS); + sacc->chunk[uix] = 0; + uix -= 1; + } + + /* We can now add one less than the total allowed terms before the + next carry propagate. */ + +done: + sacc->adds_until_propagate = XSUM_SMALL_CARRY_TERMS - 1; + + /* Return index of uppermost non-zero chunk. */ + + return uix; +} + +/* ------------------------ EXTERNAL ROUTINES ------------------------------- */ + +/* INITIALIZE A SMALL ACCUMULATOR TO ZERO. */ + +void xsum_small_init(xsum_small_accumulator* sacc) { + sacc->adds_until_propagate = XSUM_SMALL_CARRY_TERMS; + sacc->Inf = sacc->NaN = 0; +#if USE_MEMSET_SMALL + { memset(sacc->chunk, 0, XSUM_SCHUNKS * sizeof(xsum_schunk)); } +#elif USE_SIMD && __AVX__ && XSUM_SCHUNKS == 67 + { + xsum_schunk* ch = sacc->chunk; + __m256i z = _mm256_setzero_si256(); + _mm256_storeu_si256((__m256i*)(ch + 0), z); + _mm256_storeu_si256((__m256i*)(ch + 4), z); + _mm256_storeu_si256((__m256i*)(ch + 8), z); + _mm256_storeu_si256((__m256i*)(ch + 12), z); + _mm256_storeu_si256((__m256i*)(ch + 16), z); + _mm256_storeu_si256((__m256i*)(ch + 20), z); + _mm256_storeu_si256((__m256i*)(ch + 24), z); + _mm256_storeu_si256((__m256i*)(ch + 28), z); + _mm256_storeu_si256((__m256i*)(ch + 32), z); + _mm256_storeu_si256((__m256i*)(ch + 36), z); + _mm256_storeu_si256((__m256i*)(ch + 40), z); + _mm256_storeu_si256((__m256i*)(ch + 44), z); + _mm256_storeu_si256((__m256i*)(ch + 48), z); + _mm256_storeu_si256((__m256i*)(ch + 52), z); + _mm256_storeu_si256((__m256i*)(ch + 56), z); + _mm256_storeu_si256((__m256i*)(ch + 60), z); + _mm_storeu_si128((__m128i*)(ch + 64), _mm256_castsi256_si128(z)); + _mm_storeu_si64(ch + 66, _mm256_castsi256_si128(z)); + } +#else + { + xsum_schunk* p; + int n; + p = sacc->chunk; + n = XSUM_SCHUNKS; + do { + *p++ = 0; + n -= 1; + } while (n > 0); + } +#endif +} + +/* ADD ONE NUMBER TO A SMALL ACCUMULATOR ASSUMING NO CARRY PROPAGATION REQ'D. + This function is declared INLINE regardless of the setting of INLINE_SMALL + and for good performance it must be inlined by the compiler (otherwise the + procedure call overhead will result in substantial inefficiency). */ + +static INLINE void xsum_add1_no_carry(xsum_small_accumulator* sacc, + xsum_flt value) { + xsum_int ivalue; + xsum_int mantissa; + xsum_expint exp, low_exp, high_exp; + xsum_schunk* chunk_ptr; + + if (xsum_debug) { + printf("ADD1 %+.17le\n ", (double)value); + pbinary_double((double)value); + printf("\n"); + } + + /* Extract exponent and mantissa. Split exponent into high and low parts. */ + + COPY64(ivalue, value); + + exp = (ivalue >> XSUM_MANTISSA_BITS) & XSUM_EXP_MASK; + mantissa = ivalue & XSUM_MANTISSA_MASK; + high_exp = exp >> XSUM_LOW_EXP_BITS; + low_exp = exp & XSUM_LOW_EXP_MASK; + + if (xsum_debug) { + printf(" high exp: "); + pbinary_int64(high_exp, XSUM_HIGH_EXP_BITS); + printf(" low exp: "); + pbinary_int64(low_exp, XSUM_LOW_EXP_BITS); + printf("\n"); + } + + /* Categorize number as normal, denormalized, or Inf/NaN according to + the value of the exponent field. */ + + if (exp == 0) /* zero or denormalized */ + { /* If it's a zero (positive or negative), we do nothing. */ + if (mantissa == 0) { + return; + } + /* Denormalized mantissa has no implicit 1, but exponent is 1 not 0. */ + exp = low_exp = 1; + } else if (exp == XSUM_EXP_MASK) /* Inf or NaN */ + { /* Just update flags in accumulator structure. */ + xsum_small_add_inf_nan(sacc, ivalue); + return; + } else /* normalized */ + { /* OR in implicit 1 bit at top of mantissa */ + mantissa |= (xsum_int)1 << XSUM_MANTISSA_BITS; + } + + if (xsum_debug) { + printf(" mantissa: "); + pbinary_int64(mantissa, XSUM_MANTISSA_BITS + 1); + printf("\n"); + } + + /* Use high part of exponent as index of chunk, and low part of + exponent to give position within chunk. Fetch the two chunks + that will be modified. */ + + chunk_ptr = sacc->chunk + high_exp; + + /* Separate mantissa into two parts, after shifting, and add to (or + subtract from) this chunk and the next higher chunk (which always + exists since there are three extra ones at the top). + + Note that low_mantissa will have at most XSUM_LOW_MANTISSA_BITS bits, + while high_mantissa will have at most XSUM_MANTISSA_BITS bits, since + even though the high mantissa includes the extra implicit 1 bit, it will + also be shifted right by at least one bit. */ + + xsum_int split_mantissa[2]; + split_mantissa[0] = ((xsum_uint)mantissa << low_exp) & XSUM_LOW_MANTISSA_MASK; + split_mantissa[1] = mantissa >> (XSUM_LOW_MANTISSA_BITS - low_exp); + + /* Add to, or subtract from, the two affected chunks. */ + +#if OPT_SMALL == 1 + { + xsum_int ivalue_sign = ivalue < 0 ? -1 : 1; + chunk_ptr[0] += ivalue_sign * split_mantissa[0]; + chunk_ptr[1] += ivalue_sign * split_mantissa[1]; + } +#elif OPT_SMALL == 2 + { + xsum_int ivalue_neg = + ivalue >> (XSUM_SCHUNK_BITS - 1); /* all 0s if +ve, all 1s if -ve */ + chunk_ptr[0] += (split_mantissa[0] ^ ivalue_neg) + (ivalue_neg & 1); + chunk_ptr[1] += (split_mantissa[1] ^ ivalue_neg) + (ivalue_neg & 1); + } +#elif OPT_SMALL == 3 && USE_SIMD && __SSE2__ + { + xsum_int ivalue_neg = + ivalue >> (XSUM_SCHUNK_BITS - 1); /* all 0s if +ve, all 1s if -ve */ + _mm_storeu_si128( + (__m128i*)chunk_ptr, + _mm_add_epi64( + _mm_loadu_si128((__m128i*)chunk_ptr), + _mm_add_epi64( + _mm_set1_epi64((__m64)(ivalue_neg & 1)), + _mm_xor_si128(_mm_set1_epi64((__m64)ivalue_neg), + _mm_loadu_si128((__m128i*)split_mantissa))))); + } +#else + { + if (ivalue < 0) { + chunk_ptr[0] -= split_mantissa[0]; + chunk_ptr[1] -= split_mantissa[1]; + } else { + chunk_ptr[0] += split_mantissa[0]; + chunk_ptr[1] += split_mantissa[1]; + } + } +#endif + + if (xsum_debug) { + if (ivalue < 0) { + printf(" -high man: "); + pbinary_int64(-split_mantissa[1], XSUM_MANTISSA_BITS); + printf("\n -low man: "); + pbinary_int64(-split_mantissa[0], XSUM_LOW_MANTISSA_BITS); + printf("\n"); + } else { + printf(" high man: "); + pbinary_int64(split_mantissa[1], XSUM_MANTISSA_BITS); + printf("\n low man: "); + pbinary_int64(split_mantissa[0], XSUM_LOW_MANTISSA_BITS); + printf("\n"); + } + } +} + +/* ADD ONE DOUBLE TO A SMALL ACCUMULATOR. This is equivalent to, but + somewhat faster than, calling xsum_small_addv with a vector of one + value. */ + +void xsum_small_add1(xsum_small_accumulator* sacc, xsum_flt value) { + if (sacc->adds_until_propagate == 0) { + (void)xsum_carry_propagate(sacc); + } + + xsum_add1_no_carry(sacc, value); + + sacc->adds_until_propagate -= 1; +} + +/* RETURN THE RESULT OF ROUNDING A SMALL ACCUMULATOR. The rounding mode + is to nearest, with ties to even. The small accumulator may be modified + by this operation (by carry propagation being done), but the value it + represents should not change. */ + +xsum_flt xsum_small_round(xsum_small_accumulator* sacc) { + xsum_int ivalue; + xsum_schunk lower; + int i, j, e, more; + xsum_int intv; + double fltv; + + if (xsum_debug) printf("\nROUNDING SMALL ACCUMULATOR\n"); + + /* See if we have a NaN from one of the numbers being a NaN, in + which case we return the NaN with largest payload, or an infinite + result (+Inf, -Inf, or a NaN if both +Inf and -Inf occurred). + Note that we do NOT return NaN if we have both an infinite number + and a sum of other numbers that overflows with opposite sign, + since there is no real ambiguity regarding the sign in such a case. */ + + if (sacc->NaN != 0) { + COPY64(fltv, sacc->NaN); + return fltv; + } + + if (sacc->Inf != 0) { + COPY64(fltv, sacc->Inf); + return fltv; + } + + /* If none of the numbers summed were infinite or NaN, we proceed to + propagate carries, as a preliminary to finding the magnitude of + the sum. This also ensures that the sign of the result can be + determined from the uppermost non-zero chunk. + + We also find the index, i, of this uppermost non-zero chunk, as + the value returned by xsum_carry_propagate, and set ivalue to + sacc->chunk[i]. Note that ivalue will not be 0 or -1, unless + i is 0 (the lowest chunk), in which case it will be handled by + the code for denormalized numbers. */ + + i = xsum_carry_propagate(sacc); + + if (xsum_debug) xsum_small_display(sacc); + + ivalue = sacc->chunk[i]; + + /* Handle a possible denormalized number, including zero. */ + + if (i <= 1) { + /* Check for zero value, in which case we can return immediately. */ + + if (ivalue == 0) { + return 0.0; + } + + /* Check if it is actually a denormalized number. It always is if only + the lowest chunk is non-zero. If the highest non-zero chunk is the + next-to-lowest, we check the magnitude of the absolute value. + Note that the real exponent is 1 (not 0), so we need to shift right + by 1 here. */ + + if (i == 0) { + intv = ivalue >= 0 ? ivalue : -ivalue; + intv >>= 1; + if (ivalue < 0) { + intv |= XSUM_SIGN_MASK; + } + if (xsum_debug) { + printf("denormalized with i==0: intv %016llx\n", (long long)intv); + } + COPY64(fltv, intv); + return fltv; + } else { /* Note: Left shift of -ve number is undefined, so do a multiply + instead, which is probably optimized to a shift. */ + intv = ivalue * ((xsum_int)1 << (XSUM_LOW_MANTISSA_BITS - 1)) + + (sacc->chunk[0] >> 1); + if (intv < 0) { + if (intv > -((xsum_int)1 << XSUM_MANTISSA_BITS)) { + intv = (-intv) | XSUM_SIGN_MASK; + if (xsum_debug) { + printf("denormalized with i==1: intv %016llx\n", (long long)intv); + } + COPY64(fltv, intv); + return fltv; + } + } else /* non-negative */ + { + if ((xsum_uint)intv < (xsum_uint)1 << XSUM_MANTISSA_BITS) { + if (xsum_debug) { + printf("denormalized with i==1: intv %016llx\n", (long long)intv); + } + COPY64(fltv, intv); + return fltv; + } + } + /* otherwise, it's not actually denormalized, so fall through to below */ + } + } + + /* Find the location of the uppermost 1 bit in the absolute value of + the upper chunk by converting it (as a signed integer) to a + floating point value, and looking at the exponent. Then set + 'more' to the number of bits from the lower chunk (and maybe the + next lower) that are needed to fill out the mantissa of the + result (including the top implicit 1 bit), plus two extra bits to + help decide on rounding. For negative numbers, it may turn out + later that we need another bit, because negating a negative value + may carry out of the top here, but not carry out of the top once + more bits are shifted into the bottom later on. */ + + fltv = (xsum_flt)ivalue; /* finds position of topmost 1 bit of |ivalue| */ + COPY64(intv, fltv); + e = (intv >> XSUM_MANTISSA_BITS) & XSUM_EXP_MASK; /* e-bias is in 0..32 */ + more = 2 + XSUM_MANTISSA_BITS + XSUM_EXP_BIAS - e; + + if (xsum_debug) { + printf("e: %d, more: %d, ivalue: %016llx\n", e, more, + (long long)ivalue); + } + + /* Change 'ivalue' to put in 'more' bits from lower chunks into the bottom. + Also set 'j' to the index of the lowest chunk from which these bits came, + and 'lower' to the remaining bits of that chunk not now in 'ivalue'. + Note that 'lower' initially has at least one bit in it, which we can + later move into 'ivalue' if it turns out that one more bit is needed. */ + + ivalue *= (xsum_int)1 << more; /* multiply, since << of negative undefined */ + if (xsum_debug) { + printf("after ivalue <<= more, ivalue: %016llx\n", + (long long)ivalue); + } + j = i - 1; + lower = sacc->chunk[j]; /* must exist, since denormalized if i==0 */ + if (more >= XSUM_LOW_MANTISSA_BITS) { + more -= XSUM_LOW_MANTISSA_BITS; + ivalue += lower << more; + if (xsum_debug) { + printf("after ivalue += lower << more, ivalue: %016llx\n", + (long long)ivalue); + } + j -= 1; + lower = j < 0 ? 0 : sacc->chunk[j]; + } + ivalue += lower >> (XSUM_LOW_MANTISSA_BITS - more); + lower &= ((xsum_schunk)1 << (XSUM_LOW_MANTISSA_BITS - more)) - 1; + + if (xsum_debug) { + printf("after final add to ivalue, ivalue: %016llx\n", + (long long)ivalue); + printf("j: %d, e: %d, |ivalue|: %016llx, lower: %016llx (a)\n", j, e, + (long long)(ivalue < 0 ? -ivalue : ivalue), (long long)lower); + printf(" mask of low 55 bits: 007fffffffffffff, mask: %016llx\n", + (long long)((xsum_schunk)1 << (XSUM_LOW_MANTISSA_BITS - more)) - 1); + } + + /* Decide on rounding, with separate code for positive and negative values. + + At this point, 'ivalue' has the signed mantissa bits, plus two extra + bits, with 'e' recording the exponent position for these within their + top chunk. For positive 'ivalue', the bits in 'lower' and chunks + below 'j' add to the absolute value; for negative 'ivalue' they + subtract. + + After setting 'ivalue' to the tentative unsigned mantissa + (shifted left 2), and 'intv' to have the correct sign, this + code goes to done_rounding if it finds that just discarding lower + order bits is correct, and to round_away_from_zero if instead the + magnitude should be increased by one in the lowest mantissa bit. */ + + if (ivalue >= 0) /* number is positive, lower bits are added to magnitude */ + { + intv = 0; /* positive sign */ + + if ((ivalue & 2) == 0) /* extra bits are 0x */ + { + if (xsum_debug) { + printf("+, no adjustment, since remainder adds <1/2\n"); + } + goto done_rounding; + } + + if ((ivalue & 1) != 0) /* extra bits are 11 */ + { + if (xsum_debug) { + printf("+, round away from 0, since remainder adds >1/2\n"); + } + goto round_away_from_zero; + } + + if ((ivalue & 4) != 0) /* low bit is 1 (odd), extra bits are 10 */ + { + if (xsum_debug) { + printf("+odd, round away from 0, since remainder adds >=1/2\n"); + } + goto round_away_from_zero; + } + + if (lower == 0) /* see if any lower bits are non-zero */ + { + while (j > 0) { + j -= 1; + if (sacc->chunk[j] != 0) { + lower = 1; + break; + } + } + } + + if (lower != 0) /* low bit 0 (even), extra bits 10, non-zero lower bits */ + { + if (xsum_debug) { + printf("+even, round away from 0, since remainder adds >1/2\n"); + } + goto round_away_from_zero; + } else /* low bit 0 (even), extra bits 10, all lower bits 0 */ + { + if (xsum_debug) { + printf("+even, no adjustment, since reaminder adds exactly 1/2\n"); + } + goto done_rounding; + } + } + + else /* number is negative, lower bits are subtracted from magnitude */ + { + /* Check for a negative 'ivalue' that when negated doesn't contain a full + mantissa's worth of bits, plus one to help rounding. If so, move one + more bit into 'ivalue' from 'lower' (and remove it from 'lower'). + This happens when the negation of the upper part of 'ivalue' has the + form 10000... but the negation of the full 'ivalue' is not 10000... */ + + if (((-ivalue) & ((xsum_int)1 << (XSUM_MANTISSA_BITS + 2))) == 0) { + int pos = (xsum_schunk)1 << (XSUM_LOW_MANTISSA_BITS - 1 - more); + ivalue *= 2; /* note that left shift undefined if ivalue is negative */ + if (lower & pos) { + ivalue += 1; + lower &= ~pos; + } + e -= 1; + if (xsum_debug) { + printf("j: %d, e: %d, |ivalue|: %016llx, lower: %016llx (b)\n", j, e, + (long long)(ivalue < 0 ? -ivalue : ivalue), (long long)lower); + } + } + + intv = XSUM_SIGN_MASK; /* negative sign */ + ivalue = -ivalue; /* ivalue now contains the absolute value */ + + if ((ivalue & 3) == 3) /* extra bits are 11 */ + { + if (xsum_debug) { + printf("-, round away from 0, since remainder adds >1/2\n"); + } + goto round_away_from_zero; + } + + if ((ivalue & 3) <= 1) /* extra bits are 00 or 01 */ + { + if (xsum_debug) { + printf( + "-, no adjustment, since remainder adds <=1/4 or subtracts <1/4\n"); + } + goto done_rounding; + } + + if ((ivalue & 4) == 0) /* low bit is 0 (even), extra bits are 10 */ + { + if (xsum_debug) { + printf("-even, no adjustment, since remainder adds <=1/2\n"); + } + goto done_rounding; + } + + if (lower == 0) /* see if any lower bits are non-zero */ + { + while (j > 0) { + j -= 1; + if (sacc->chunk[j] != 0) { + lower = 1; + break; + } + } + } + + if (lower != 0) /* low bit 1 (odd), extra bits 10, non-zero lower bits */ + { + if (xsum_debug) { + printf("-odd, no adjustment, since remainder adds <1/2\n"); + } + goto done_rounding; + } else /* low bit 1 (odd), extra bits are 10, lower bits are all 0 */ + { + if (xsum_debug) { + printf("-odd, round away from 0, since remainder adds exactly 1/2\n"); + } + goto round_away_from_zero; + } + } + +round_away_from_zero: + + /* Round away from zero, then check for carry having propagated out the + top, and shift if so. */ + + ivalue += 4; /* add 1 to low-order mantissa bit */ + if (ivalue & ((xsum_int)1 << (XSUM_MANTISSA_BITS + 3))) { + ivalue >>= 1; + e += 1; + } + +done_rounding:; + + /* Get rid of the bottom 2 bits that were used to decide on rounding. */ + + ivalue >>= 2; + + /* Adjust to the true exponent, accounting for where this chunk is. */ + + e += (i << XSUM_LOW_EXP_BITS) - XSUM_EXP_BIAS - XSUM_MANTISSA_BITS; + + /* If exponent has overflowed, change to plus or minus Inf and return. */ + + if (e >= XSUM_EXP_MASK) { + intv |= (xsum_int)XSUM_EXP_MASK << XSUM_MANTISSA_BITS; + COPY64(fltv, intv); + if (xsum_debug) { + printf("Final rounded result: %.17le (overflowed)\n ", fltv); + pbinary_double(fltv); + printf("\n"); + } + return fltv; + } + + /* Put exponent and mantissa into intv, which already has the sign, + then copy into fltv. */ + + intv += (xsum_int)e << XSUM_MANTISSA_BITS; + intv += ivalue & XSUM_MANTISSA_MASK; /* mask out the implicit 1 bit */ + COPY64(fltv, intv); + + if (xsum_debug) { + printf("Final rounded result: %.17le\n ", fltv); + pbinary_double(fltv); + printf("\n"); + if ((ivalue >> XSUM_MANTISSA_BITS) != 1) abort(); + } + + return fltv; +} + +/* ------------------------- DEBUGGING ROUTINES ----------------------------- */ + +/* DISPLAY A SMALL ACCUMULATOR. */ + +void xsum_small_display(xsum_small_accumulator* sacc) { + int i, dots; + printf("Small accumulator:"); + if (sacc->Inf) { + printf(" %cInf", sacc->Inf > 0 ? '+' : '-'); + if ((sacc->Inf & ((xsum_uint)XSUM_EXP_MASK << XSUM_MANTISSA_BITS)) != + ((xsum_uint)XSUM_EXP_MASK << XSUM_MANTISSA_BITS)) { + printf(" BUT WRONG CONTENTS: %llx", (long long)sacc->Inf); + } + } + if (sacc->NaN) { + printf(" NaN (%llx)", (long long)sacc->NaN); + } + printf("\n"); + dots = 0; + for (i = XSUM_SCHUNKS - 1; i >= 0; i--) { + if (sacc->chunk[i] == 0) { + if (!dots) printf(" ...\n"); + dots = 1; + } else { + printf( + "%5d %5d ", i, + (int)((i << XSUM_LOW_EXP_BITS) - XSUM_EXP_BIAS - XSUM_MANTISSA_BITS)); + pbinary_int64((int64_t)sacc->chunk[i] >> 32, XSUM_SCHUNK_BITS - 32); + printf(" "); + pbinary_int64((int64_t)sacc->chunk[i] & 0xffffffff, 32); + printf("\n"); + dots = 0; + } + } + printf("\n"); +} diff --git a/src/third_party/mozjs/extract/js/src/xsum/xsum.h b/src/third_party/mozjs/extract/js/src/xsum/xsum.h new file mode 100644 index 00000000000..2761b5de716 --- /dev/null +++ b/src/third_party/mozjs/extract/js/src/xsum/xsum.h @@ -0,0 +1,141 @@ +/* INTERFACE TO FUNCTIONS FOR EXACT SUMMATION. */ + +/* Copyright 2015, 2018, 2021 Radford M. Neal + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef XSUM_H +#define XSUM_H + +#include +#include +#include + +/* CONSTANTS DEFINING THE FLOATING POINT FORMAT. */ + +typedef double xsum_flt; /* C floating point type sums are done for */ + +typedef int64_t xsum_int; /* Signed integer type for a fp value */ +typedef uint64_t xsum_uint; /* Unsigned integer type for a fp value */ +typedef int_fast16_t xsum_expint; /* Integer type for holding an exponent */ + +#define XSUM_MANTISSA_BITS 52 /* Bits in fp mantissa, excludes implict 1 */ +#define XSUM_EXP_BITS 11 /* Bits in fp exponent */ + +#define XSUM_MANTISSA_MASK \ + (((xsum_int)1 << XSUM_MANTISSA_BITS) - 1) /* Mask for mantissa bits */ + +#define XSUM_EXP_MASK ((1 << XSUM_EXP_BITS) - 1) /* Mask for exponent */ + +#define XSUM_EXP_BIAS \ + ((1 << (XSUM_EXP_BITS - 1)) - 1) /* Bias added to signed exponent */ + +#define XSUM_SIGN_BIT \ + (XSUM_MANTISSA_BITS + XSUM_EXP_BITS) /* Position of sign bit */ + +#define XSUM_SIGN_MASK ((xsum_uint)1 << XSUM_SIGN_BIT) /* Mask for sign bit */ + +/* CONSTANTS DEFINING THE SMALL ACCUMULATOR FORMAT. */ + +#define XSUM_SCHUNK_BITS 64 /* Bits in chunk of the small accumulator */ +typedef int64_t xsum_schunk; /* Integer type of small accumulator chunk */ + +#define XSUM_LOW_EXP_BITS 5 /* # of low bits of exponent, in one chunk */ + +#define XSUM_LOW_EXP_MASK \ + ((1 << XSUM_LOW_EXP_BITS) - 1) /* Mask for low-order exponent bits */ + +#define XSUM_HIGH_EXP_BITS \ + (XSUM_EXP_BITS - XSUM_LOW_EXP_BITS) /* # of high exponent bits for index */ + +#define XSUM_HIGH_EXP_MASK \ + ((1 << HIGH_EXP_BITS) - 1) /* Mask for high-order exponent bits */ + +#define XSUM_SCHUNKS \ + ((1 << XSUM_HIGH_EXP_BITS) + 3) /* # of chunks in small accumulator */ + +#define XSUM_LOW_MANTISSA_BITS \ + (1 << XSUM_LOW_EXP_BITS) /* Bits in low part of mantissa */ + +#define XSUM_HIGH_MANTISSA_BITS \ + (XSUM_MANTISSA_BITS - XSUM_LOW_MANTISSA_BITS) /* Bits in high part */ + +#define XSUM_LOW_MANTISSA_MASK \ + (((xsum_int)1 << XSUM_LOW_MANTISSA_BITS) - 1) /* Mask for low bits */ + +#define XSUM_SMALL_CARRY_BITS \ + ((XSUM_SCHUNK_BITS - 1) - XSUM_MANTISSA_BITS) /* Bits sums can carry into */ + +#define XSUM_SMALL_CARRY_TERMS \ + ((1 << XSUM_SMALL_CARRY_BITS) - 1) /* # terms can add before need prop. */ + +typedef struct { + xsum_schunk chunk[XSUM_SCHUNKS]; /* Chunks making up small accumulator */ + xsum_int Inf; /* If non-zero, +Inf, -Inf, or NaN */ + xsum_int NaN; /* If non-zero, a NaN value with payload */ + int adds_until_propagate; /* Number of remaining adds before carry */ +} xsum_small_accumulator; /* propagation must be done again */ + +/* CONSTANTS DEFINING THE LARGE ACCUMULATOR FORMAT. */ + +#define XSUM_LCHUNK_BITS 64 /* Bits in chunk of the large accumulator */ +typedef uint64_t xsum_lchunk; /* Integer type of large accumulator chunk, + must be EXACTLY 64 bits in size */ + +#define XSUM_LCOUNT_BITS (64 - XSUM_MANTISSA_BITS) /* # of bits in count */ +typedef int_least16_t xsum_lcount; /* Signed int type of counts for large acc.*/ + +#define XSUM_LCHUNKS \ + (1 << (XSUM_EXP_BITS + 1)) /* # of chunks in large accumulator */ + +typedef uint64_t xsum_used; /* Unsigned type for holding used flags */ + +typedef struct { + xsum_lchunk chunk[XSUM_LCHUNKS]; /* Chunks making up large accumulator */ + xsum_lcount count[XSUM_LCHUNKS]; /* Counts of # adds remaining for chunks, + or -1 if not used yet or special. */ + xsum_used chunks_used[XSUM_LCHUNKS / 64]; /* Bits indicate chunks in use */ + xsum_used used_used; /* Bits indicate chunk_used entries not 0 */ + xsum_small_accumulator sacc; /* The small accumulator to condense into */ +} xsum_large_accumulator; + +/* TYPE FOR LENGTHS OF ARRAYS. Must be a signed integer type. Set to + ptrdiff_t here on the assumption that this will be big enough, but + not unnecessarily big, which seems to be true. */ + +typedef ptrdiff_t xsum_length; + +/* FUNCTIONS FOR EXACT SUMMATION, WITH POSSIBLE DIVISION BY AN INTEGER. */ + +void xsum_small_init(xsum_small_accumulator*); +void xsum_small_add1(xsum_small_accumulator*, xsum_flt); +xsum_flt xsum_small_round(xsum_small_accumulator*); + +/* FUNCTIONS USEFUL FOR TESTING AND DEBUGGING. */ + +void xsum_small_display(xsum_small_accumulator*); + +/* DEBUG FLAG. Set to non-zero for debug ouptut. Ignored unless xsum.c + is compiled with -DDEBUG. */ + +extern int xsum_debug; + +#endif diff --git a/src/third_party/mozjs/extract/mfbt/Alignment.h b/src/third_party/mozjs/extract/mfbt/Alignment.h index c38e00d12c4..8f459339308 100644 --- a/src/third_party/mozjs/extract/mfbt/Alignment.h +++ b/src/third_party/mozjs/extract/mfbt/Alignment.h @@ -15,48 +15,6 @@ namespace mozilla { -/* - * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many - * bytes of alignment a given type needs. - */ -template -class AlignmentFinder { - struct Aligner { - char mChar; - T mT; - - // Aligner may be used to check alignment of types with deleted dtors. This - // results in such specializations having implicitly deleted dtors, which - // causes fatal warnings on MSVC (see bug 1481005). As we don't create - // Aligners, we can avoid this warning by explicitly deleting the dtor. - ~Aligner() = delete; - }; - - public: - static const size_t alignment = sizeof(Aligner) - sizeof(T); -}; - -#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder::alignment - -namespace detail { -template -struct AlignasHelper { - T mT; -}; -} // namespace detail - -/* - * Use this instead of alignof to align struct field as if it is inside - * a struct. On some platforms, there exist types which have different - * alignment between when it is used on its own and when it is used on - * a struct field. - * - * Known examples are 64bit types (uint64_t, double) on 32bit Linux, - * where they have 8byte alignment on their own, and 4byte alignment - * when in struct. - */ -#define MOZ_ALIGNAS_IN_STRUCT(T) alignas(mozilla::detail::AlignasHelper) - /* * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types. * diff --git a/src/third_party/mozjs/extract/mfbt/Array.h b/src/third_party/mozjs/extract/mfbt/Array.h index 55b724a2882..abdcf67fb58 100644 --- a/src/third_party/mozjs/extract/mfbt/Array.h +++ b/src/third_party/mozjs/extract/mfbt/Array.h @@ -22,7 +22,7 @@ namespace mozilla { template -class Array { +class MOZ_GSL_OWNER Array { T mArr[_Length]; public: @@ -39,14 +39,14 @@ class Array { "parameter Length"); } - T& operator[](size_t aIndex) { + constexpr T& operator[](size_t aIndex) MOZ_LIFETIME_BOUND { if (MOZ_UNLIKELY(aIndex >= Length)) { detail::InvalidArrayIndex_CRASH(aIndex, Length); } return mArr[aIndex]; } - const T& operator[](size_t aIndex) const { + constexpr const T& operator[](size_t aIndex) const MOZ_LIFETIME_BOUND { if (MOZ_UNLIKELY(aIndex >= Length)) { detail::InvalidArrayIndex_CRASH(aIndex, Length); } @@ -75,6 +75,9 @@ class Array { constexpr const_iterator end() const { return mArr + Length; } constexpr const_iterator cend() const { return end(); } + // Method for std::size. + constexpr size_t size() const { return Length; } + // Methods for reverse iterating. reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { diff --git a/src/third_party/mozjs/extract/mfbt/ArrayUtils.h b/src/third_party/mozjs/extract/mfbt/ArrayUtils.h index 78eec5dabad..073036b038b 100644 --- a/src/third_party/mozjs/extract/mfbt/ArrayUtils.h +++ b/src/third_party/mozjs/extract/mfbt/ArrayUtils.h @@ -19,17 +19,13 @@ #ifdef __cplusplus # include +# include # include # include "mozilla/Alignment.h" namespace mozilla { -template -class Array; -template -class EnumeratedArray; - /* * Safely subtract two pointers when it is known that aEnd >= aBegin, yielding a * size_t result. @@ -48,47 +44,6 @@ MOZ_ALWAYS_INLINE size_t PointerRangeSize(T* aBegin, T* aEnd) { return (size_t(aEnd) - size_t(aBegin)) / sizeof(T); } -/* - * Compute the length of an array with constant length. (Use of this method - * with a non-array pointer will not compile.) - * - * Beware of the implicit trailing '\0' when using this with string constants. - */ -template -constexpr size_t ArrayLength(T (&aArr)[N]) { - return N; -} - -template -constexpr size_t ArrayLength(const Array& aArr) { - return N; -} - -template -constexpr size_t ArrayLength(const EnumeratedArray& aArr) { - return N; -} - -/* - * Compute the address one past the last element of a constant-length array. - * - * Beware of the implicit trailing '\0' when using this with string constants. - */ -template -constexpr T* ArrayEnd(T (&aArr)[N]) { - return aArr + ArrayLength(aArr); -} - -template -constexpr T* ArrayEnd(Array& aArr) { - return &aArr[0] + ArrayLength(aArr); -} - -template -constexpr const T* ArrayEnd(const Array& aArr) { - return &aArr[0] + ArrayLength(aArr); -} - /** * std::equal has subpar ergonomics. */ @@ -108,7 +63,7 @@ namespace detail { template struct AlignedChecker { static void test(const Pointee* aPtr) { - MOZ_ASSERT((uintptr_t(aPtr) % MOZ_ALIGNOF(AlignType)) == 0, + MOZ_ASSERT((uintptr_t(aPtr) % alignof(AlignType)) == 0, "performing a range-check with a misaligned pointer"); } }; @@ -158,31 +113,8 @@ inline bool IsInRange(const T* aPtr, uintptr_t aBegin, uintptr_t aEnd) { reinterpret_cast(aEnd)); } -namespace detail { - -/* - * Helper for the MOZ_ARRAY_LENGTH() macro to make the length a typesafe - * compile-time constant even on compilers lacking constexpr support. - */ -template -char (&ArrayLengthHelper(T (&array)[N]))[N]; - -} /* namespace detail */ - } /* namespace mozilla */ #endif /* __cplusplus */ -/* - * MOZ_ARRAY_LENGTH() is an alternative to mozilla::ArrayLength() for C files - * that can't use C++ template functions and for static_assert() calls that - * can't call ArrayLength() when it is not a C++11 constexpr function. - */ -#ifdef __cplusplus -# define MOZ_ARRAY_LENGTH(array) \ - sizeof(mozilla::detail::ArrayLengthHelper(array)) -#else -# define MOZ_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0])) -#endif - #endif /* mozilla_ArrayUtils_h */ diff --git a/src/third_party/mozjs/extract/mfbt/Assertions.h b/src/third_party/mozjs/extract/mfbt/Assertions.h index 0b7395177d2..12fb4370870 100644 --- a/src/third_party/mozjs/extract/mfbt/Assertions.h +++ b/src/third_party/mozjs/extract/mfbt/Assertions.h @@ -53,9 +53,13 @@ MOZ_END_EXTERN_C #if defined(MOZ_HAS_MOZGLUE) || defined(MOZILLA_INTERNAL_API) static inline void AnnotateMozCrashReason(const char* reason) { gMozCrashReason = reason; - // See bug 1681846, on 32-bit Android ARM the compiler removes the store to - // gMozCrashReason if this barrier is not present. - asm volatile("" ::: "memory"); + // The following assembly fakes a memory read/write to the compiler, which + // prevents the removal of gMozCrashReason store. See bug 1681846 and 1945507. +# if defined(__clang__) + asm volatile("" : "+r,m"(gMozCrashReason) : : "memory"); +# else + asm volatile("" : "+m,r"(gMozCrashReason) : : "memory"); +# endif } # define MOZ_CRASH_ANNOTATE(...) AnnotateMozCrashReason(__VA_ARGS__) #else @@ -95,7 +99,10 @@ MOZ_BEGIN_EXTERN_C #if defined(ANDROID) && defined(MOZ_DUMP_ASSERTION_STACK) MOZ_MAYBE_UNUSED static void MOZ_ReportAssertionFailurePrintFrame( const char* aBuf) { - __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", "%s\n", aBuf); + __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", "%s", aBuf); +} +MOZ_MAYBE_UNUSED static void MOZ_CrashPrintFrame(const char* aBuf) { + __android_log_print(ANDROID_LOG_FATAL, "MOZ_Crash", "%s", aBuf); } #endif @@ -144,6 +151,10 @@ MOZ_MAYBE_UNUSED static MOZ_COLD MOZ_NEVER_INLINE void MOZ_ReportCrash( __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH", "[%d] Hit MOZ_CRASH(%s) at %s:%d\n", MOZ_GET_PID(), aStr, aFilename, aLine); +# if defined(MOZ_DUMP_ASSERTION_STACK) + MozWalkTheStackWithWriter(MOZ_CrashPrintFrame, CallerPC(), + /* aMaxFrames */ 0); +# endif #else # if defined(MOZ_BUFFER_STDERR) char msg[1024] = ""; @@ -226,6 +237,57 @@ MOZ_NoReturn(int aLine) { #else +/* + * MOZ_CrashSequence() executes a sequence that causes the process to crash by + * writing the line number specified in the `aLine` parameter to the address + * provide by `aAddress`. The store is implemented as volatile assembly code to + * ensure it's always included in the output and always executed. + */ +static inline void MOZ_CrashSequence(void* aAddress, intptr_t aLine) { +# if defined(__i386__) || defined(__x86_64__) + asm volatile( + "mov %1, (%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__arm__) || defined(__aarch64__) + asm volatile( + "str %1,[%0];\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__riscv) && (__riscv_xlen == 64) + asm volatile( + "sd %1,0(%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__sparc__) && defined(__arch64__) + asm volatile( + "stx %1,[%0];\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__loongarch64) + asm volatile( + "st.d %1,%0,0;\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +// MONGODB MODIFICATION: Implement for ppc64le and s390x +# elif defined(__powerpc64__) + asm volatile( + "std %1, 0(%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__s390x__) + asm volatile( + "stg %1, 0(%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# else +# warning \ + "Unsupported architecture, replace the code below with assembly suitable to crash the process" + asm volatile("" ::: "memory"); + *((volatile int*)aAddress) = aLine; /* NOLINT */ +# endif +} + /* * MOZ_CRASH_WRITE_ADDR is the address to be used when performing a forced * crash. NULL is preferred however if for some reason NULL cannot be used @@ -237,22 +299,22 @@ MOZ_NoReturn(int aLine) { * SEGV at 0x0. */ # ifdef MOZ_UBSAN -# define MOZ_CRASH_WRITE_ADDR 0x1 +# define MOZ_CRASH_WRITE_ADDR ((void*)0x1) # else # define MOZ_CRASH_WRITE_ADDR NULL # endif # ifdef __cplusplus -# define MOZ_REALLY_CRASH(line) \ - do { \ - *((volatile int*)MOZ_CRASH_WRITE_ADDR) = line; /* NOLINT */ \ - MOZ_NOMERGE ::abort(); \ +# define MOZ_REALLY_CRASH(line) \ + do { \ + MOZ_CrashSequence(MOZ_CRASH_WRITE_ADDR, line); \ + MOZ_NOMERGE ::abort(); \ } while (false) # else -# define MOZ_REALLY_CRASH(line) \ - do { \ - *((volatile int*)MOZ_CRASH_WRITE_ADDR) = line; /* NOLINT */ \ - MOZ_NOMERGE abort(); \ +# define MOZ_REALLY_CRASH(line) \ + do { \ + MOZ_CrashSequence(MOZ_CRASH_WRITE_ADDR, line); \ + MOZ_NOMERGE abort(); \ } while (false) # endif #endif @@ -272,13 +334,13 @@ MOZ_NoReturn(int aLine) { * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's * obvious why we're crashing. * - * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an - * explanation-string, we print the string to stderr. Otherwise, we don't - * print anything; this is because we want MOZ_CRASH to be 100% safe in release - * builds, and it's hard to print to stderr safely when memory might have been - * corrupted. + * If we're a DEBUG, ASAN or FUZZING build and we crash at a MOZ_CRASH which + * provides an explanation-string, we print the string to stderr. Otherwise, + * we don't print anything; this is because we want MOZ_CRASH to be 100% safe + * in release builds, and it's hard to print to stderr safely when memory might + * have been corrupted. */ -#if !(defined(DEBUG) || defined(FUZZING)) +#if !(defined(DEBUG) || defined(MOZ_ASAN) || defined(FUZZING)) # define MOZ_CRASH(...) \ do { \ MOZ_FUZZING_HANDLE_CRASH_EVENT4("MOZ_CRASH", __FILE__, __LINE__, NULL); \ @@ -295,6 +357,19 @@ MOZ_NoReturn(int aLine) { } while (false) #endif +/* + * MOZ_DIAGNOSTIC_CRASH acts like MOZ_CRASH in a MOZ_DIAGNOSTIC_ASSERT_ENABLED + * build, and does nothing otherwise. See the comment later in this file for a + * description of when MOZ_DIAGNOSTIC_ASSERT_ENABLED is defined. + */ +#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) +# define MOZ_DIAGNOSTIC_CRASH(...) MOZ_CRASH(__VA_ARGS__) +#else +# define MOZ_DIAGNOSTIC_CRASH(...) \ + do { /* nothing */ \ + } while (false) +#endif + /* * MOZ_CRASH_UNSAFE(explanation-string) can be used if the explanation string * cannot be a string literal (but no other processing needs to be done on it). @@ -310,7 +385,7 @@ MOZ_NoReturn(int aLine) { static MOZ_ALWAYS_INLINE_EVEN_DEBUG MOZ_COLD MOZ_NORETURN void MOZ_Crash( const char* aFilename, int aLine, const char* aReason) { MOZ_FUZZING_HANDLE_CRASH_EVENT4("MOZ_CRASH", aFilename, aLine, aReason); -#if defined(DEBUG) || defined(FUZZING) +#if defined(DEBUG) || defined(MOZ_ASAN) || defined(FUZZING) MOZ_ReportCrash(aReason, aFilename, aLine); #endif MOZ_CRASH_ANNOTATE(aReason); @@ -480,7 +555,7 @@ struct AssertionConditionType { ("MOZ_ASSERT", __VA_ARGS__)) #else # define MOZ_ASSERT(...) \ - do { \ + do { /* nothing */ \ } while (false) #endif /* DEBUG */ @@ -491,7 +566,7 @@ struct AssertionConditionType { ("MOZ_DIAGNOSTIC_ASSERT", __VA_ARGS__)) #else # define MOZ_DIAGNOSTIC_ASSERT(...) \ - do { \ + do { /* nothing */ \ } while (false) #endif @@ -528,7 +603,7 @@ struct AssertionConditionType { } while (false) #else # define MOZ_ASSERT_IF(cond, expr) \ - do { \ + do { /* nothing */ \ } while (false) #endif @@ -548,7 +623,7 @@ struct AssertionConditionType { } while (false) #else # define MOZ_DIAGNOSTIC_ASSERT_IF(cond, expr) \ - do { \ + do { /* nothing */ \ } while (false) #endif @@ -647,18 +722,18 @@ struct AssertionConditionType { #endif /* - * MOZ_ALWAYS_TRUE(expr) and friends always evaluate the provided expression, - * in debug builds and in release builds both. Then, in debug builds and - * Nightly and early beta builds, the value of the expression is - * asserted either true or false using MOZ_DIAGNOSTIC_ASSERT. + * MOZ_ALWAYS_TRUE(expr) and friends always evaluate the provided expression, in + * both debug and release builds. Then, in debug builds and Nightly and early + * beta builds, we crash using the string value of the expression as the message + * using MOZ_DIAGNOSTIC_CRASH. */ -#define MOZ_ALWAYS_TRUE(expr) \ - do { \ - if (MOZ_LIKELY(expr)) { \ - /* Silence [[nodiscard]]. */ \ - } else { \ - MOZ_DIAGNOSTIC_ASSERT(false, #expr); \ - } \ +#define MOZ_ALWAYS_TRUE(expr) \ + do { \ + if (MOZ_LIKELY(expr)) { \ + /* Silence [[nodiscard]]. */ \ + } else { \ + MOZ_DIAGNOSTIC_CRASH(#expr); \ + } \ } while (false) #define MOZ_ALWAYS_FALSE(expr) MOZ_ALWAYS_TRUE(!(expr)) @@ -670,10 +745,10 @@ struct AssertionConditionType { */ #ifdef FUZZING # define MOZ_CRASH_UNLESS_FUZZING(...) \ - do { \ + do { /* nothing */ \ } while (0) # define MOZ_ASSERT_UNLESS_FUZZING(...) \ - do { \ + do { /* nothing */ \ } while (0) #else # define MOZ_CRASH_UNLESS_FUZZING(...) MOZ_CRASH(__VA_ARGS__) diff --git a/src/third_party/mozjs/extract/mfbt/Atomics.h b/src/third_party/mozjs/extract/mfbt/Atomics.h index e5da5c07a95..9ca056c92ec 100644 --- a/src/third_party/mozjs/extract/mfbt/Atomics.h +++ b/src/third_party/mozjs/extract/mfbt/Atomics.h @@ -28,6 +28,11 @@ #include #include +#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || \ + defined(_M_X64) +# include +#endif + namespace mozilla { /** @@ -60,7 +65,7 @@ namespace mozilla { * the modes we provide below, or not relevant for the CPUs we support * in Gecko. These three modes are confusing enough as it is! */ -enum MemoryOrdering { +enum MemoryOrdering : uint8_t { /* * Relaxed ordering is the simplest memory ordering: none at all. * When the result of a write is observed, nothing may be inferred @@ -507,6 +512,37 @@ class Atomic : protected detail::AtomicBase { Atomic(Atomic& aOther) = delete; }; +/** + * Atomic implementation for double type. + */ +template +class Atomic : protected detail::AtomicBase { + typedef typename detail::AtomicBase Base; + + public: + constexpr Atomic() : Base() {} + explicit constexpr Atomic(double aInit) : Base(aInit) {} + + operator double() const { + return double(Base::Intrinsics::load(Base::mValue)); + } + + double operator=(double aVal) { return Base::operator=(aVal); } + + private: + Atomic(Atomic& aOther) = delete; +}; + +// Relax the CPU during a spinlock. It's a good idea to place this in a +// spinlock so that the CPU doesn't pipeline the loop otherwise flushing the +// pipeline when the loop finally breaks can be expensive. +inline void cpu_pause() { +#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || \ + defined(_M_X64) + _mm_pause(); +#endif +} + } // namespace mozilla namespace std { diff --git a/src/third_party/mozjs/extract/mfbt/Attributes.h b/src/third_party/mozjs/extract/mfbt/Attributes.h index 130288c5122..d5401b0eb40 100644 --- a/src/third_party/mozjs/extract/mfbt/Attributes.h +++ b/src/third_party/mozjs/extract/mfbt/Attributes.h @@ -448,6 +448,39 @@ # define MOZ_NO_STACK_PROTECTOR /* no support */ #endif +/** + * MOZ_GSL_OWNER indicates that objects of the type this annotation is attached + * to own some kind of resources, generally memory. + * + * See: https://clang.llvm.org/docs/AttributeReference.html#owner + */ +#if defined(__clang__) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(gsl::Owner) +# define MOZ_GSL_OWNER [[gsl::Owner]] +# else +# define MOZ_GSL_OWNER /* nothing */ +# endif +#else +# define MOZ_GSL_OWNER /* nothing */ +#endif + +/** + * MOZ_GSL_POINTER indicates that objects of the type this annotation is + * attached to provide a non-owning view on some kind of resources, generally + * memory. + * + * See: https://clang.llvm.org/docs/AttributeReference.html#pointer + */ +#if defined(__clang__) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(gsl::Pointer) +# define MOZ_GSL_POINTER [[gsl::Pointer]] +# else +# define MOZ_GSL_POINTER /* nothing */ +# endif +#else +# define MOZ_GSL_POINTER /* nothing */ +#endif + /** * MOZ_LIFETIME_BOUND indicates that objects that are referred to by that * parameter may also be referred to by the return value of the annotated @@ -465,6 +498,21 @@ # define MOZ_LIFETIME_BOUND /* nothing */ #endif +/** + * MOZ_LIFETIME_CAPTURE_BY(x) indicates that objects that are referred to + * by that parameter may also be referred to by x. + * See: https://clang.llvm.org/docs/AttributeReference.html#lifetime-capture-by + */ +#if defined(__clang__) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(clang::lifetime_capture_by) +# define MOZ_LIFETIME_CAPTURE_BY(x) [[clang::lifetime_capture_by(x)]] +# else +# define MOZ_LIFETIME_CAPTURE_BY(x) /* nothing */ +# endif +#else +# define MOZ_LIFETIME_CAPTURE_BY(x) /* nothing */ +#endif + #ifdef __cplusplus /** @@ -618,6 +666,11 @@ * expression. If a member of another class uses this class, or if another * class inherits from this class, then it is considered to be a non-heap * class as well, although this attribute need not be provided in such cases. + * MOZ_CONSTINIT: pre-C++20 equivalent to `constinit`. + * MOZ_RUNINIT: Applies to global variables with runtime initialization. + * MOZ_GLOBINIT: Applies to global variables with potential runtime + * initialization (e.g. inside macro or when initialisation status depends on + * template parameter). * MOZ_HEAP_CLASS: Applies to all classes. Any class with this annotation is * expected to live on the heap, so it is a compile-time error to use it, or * an array of such objects, as the type of a variable declaration, or as a @@ -855,12 +908,17 @@ # define MOZ_MAY_CALL_AFTER_MUST_RETURN \ __attribute__((annotate("moz_may_call_after_must_return"))) # define MOZ_KNOWN_LIVE __attribute__((annotate("moz_known_live"))) -# ifndef XGILL_PLUGIN +# ifdef MOZ_CLANG_PLUGIN # define MOZ_UNANNOTATED __attribute__((annotate("moz_unannotated"))) # define MOZ_ANNOTATED __attribute__((annotate("moz_annotated"))) +# define MOZ_RUNINIT __attribute__((annotate("moz_global_var"))) +# define MOZ_GLOBINIT \ + MOZ_RUNINIT __attribute__((annotate("moz_generated"))) # else # define MOZ_UNANNOTATED /* nothing */ # define MOZ_ANNOTATED /* nothing */ +# define MOZ_RUNINIT /* nothing */ +# define MOZ_GLOBINIT /* nothing */ # endif /* @@ -868,11 +926,11 @@ * warning, so use pragmas to disable the warning. */ # ifdef __clang__ -# define MOZ_HEAP_ALLOCATOR \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((annotate("moz_heap_allocator"))) \ - _Pragma("clang diagnostic pop") +# define MOZ_HEAP_ALLOCATOR \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((annotate("moz_heap_allocator"))) _Pragma( \ + "clang diagnostic pop") # else # define MOZ_HEAP_ALLOCATOR __attribute__((annotate("moz_heap_allocator"))) # endif @@ -882,6 +940,8 @@ # define MOZ_CAN_RUN_SCRIPT_BOUNDARY /* nothing */ # define MOZ_MUST_OVERRIDE /* nothing */ # define MOZ_STATIC_CLASS /* nothing */ +# define MOZ_RUNINIT /* nothing */ +# define MOZ_GLOBINIT /* nothing */ # define MOZ_STATIC_LOCAL_CLASS /* nothing */ # define MOZ_STACK_CLASS /* nothing */ # define MOZ_NONHEAP_CLASS /* nothing */ @@ -1033,6 +1093,19 @@ # define MOZ_EMPTY_BASES #endif +/** + * Pre- C++20 equivalent to constinit + */ +#if defined(__cpp_constinit) +# define MOZ_CONSTINIT constinit +#elif defined(__clang__) +# define MOZ_CONSTINIT [[clang::require_constant_initialization]] +#elif MOZ_GCC_VERSION_AT_LEAST(10, 1, 0) +# define MOZ_CONSTINIT __constinit +#else +# define MOZ_CONSTINIT +#endif + // XXX: GCC somehow does not allow attributes before lambda return types, while // clang requires so. See also bug 1627007. #ifdef __clang__ diff --git a/src/third_party/mozjs/extract/mfbt/BitSet.h b/src/third_party/mozjs/extract/mfbt/BitSet.h index 7c03fb87ce6..9e2264a6e30 100644 --- a/src/third_party/mozjs/extract/mfbt/BitSet.h +++ b/src/third_party/mozjs/extract/mfbt/BitSet.h @@ -8,24 +8,48 @@ #define mozilla_BitSet_h #include "mozilla/Array.h" -#include "mozilla/ArrayUtils.h" #include "mozilla/MathAlgorithms.h" -#include "mozilla/PodOperations.h" #include "mozilla/Span.h" namespace mozilla { +enum MemoryOrdering : uint8_t; +template +class Atomic; + +namespace detail { + +template +struct UnwrapMaybeAtomic { + using Type = T; +}; +template +struct UnwrapMaybeAtomic> { + using Type = T; +}; + +} // namespace detail + /** * An object like std::bitset but which provides access to the underlying * storage. * + * The type |StorageType| must be an unsigned integer or a mozilla::Atomic + * wrapping an unsigned integer. Use of atomic types makes word access atomic, + * but does not make operations that operate on the whole bitset atomic. + * * The limited API is due to expedience only; feel free to flesh out any * std::bitset-like members. */ -template +template class BitSet { - static_assert(std::is_unsigned_v, - "The Word type must be an unsigned integral type"); + public: + using Word = typename detail::UnwrapMaybeAtomic::Type; + static_assert(sizeof(Word) == sizeof(StorageType)); + static_assert( + std::is_unsigned_v, + "StorageType must be an unsigned integral type, or equivalent Atomic"); + static_assert(N != 0); private: static constexpr size_t kBitsPerWord = 8 * sizeof(Word); @@ -34,7 +58,7 @@ class BitSet { static constexpr Word kPaddingMask = Word(-1) >> kPaddingBits; // The zeroth bit in the bitset is the least significant bit of mStorage[0]. - Array mStorage; + Array mStorage; constexpr void ResetPaddingBits() { if constexpr (kPaddingBits != 0) { @@ -45,20 +69,24 @@ class BitSet { public: class Reference { public: - Reference(BitSet& aBitSet, size_t aPos) + Reference(BitSet& aBitSet, size_t aPos) : mBitSet(aBitSet), mPos(aPos) {} Reference& operator=(bool aValue) { auto bit = Word(1) << (mPos % kBitsPerWord); auto& word = mBitSet.mStorage[mPos / kBitsPerWord]; - word = (word & ~bit) | (aValue ? bit : 0); + if (aValue) { + word |= bit; + } else { + word &= ~bit; + } return *this; } - MOZ_IMPLICIT operator bool() const { return mBitSet.Test(mPos); } + MOZ_IMPLICIT operator bool() const { return mBitSet.test(mPos); } private: - BitSet& mBitSet; + BitSet& mBitSet; size_t mPos; }; @@ -67,23 +95,27 @@ class BitSet { BitSet(const BitSet& aOther) { *this = aOther; } BitSet& operator=(const BitSet& aOther) { - PodCopy(mStorage.begin(), aOther.mStorage.begin(), kNumWords); + for (size_t i = 0; i < std::size(mStorage); i++) { + mStorage[i] = Word(aOther.mStorage[i]); + } return *this; } - explicit BitSet(Span aStorage) { - PodCopy(mStorage.begin(), aStorage.Elements(), kNumWords); + explicit BitSet(Span aStorage) { + for (size_t i = 0; i < std::size(mStorage); i++) { + mStorage[i] = Word(aStorage[i]); + } } - static constexpr size_t Size() { return N; } + static constexpr size_t size() { return N; } - constexpr bool Test(size_t aPos) const { + constexpr bool test(size_t aPos) const { MOZ_ASSERT(aPos < N); return mStorage[aPos / kBitsPerWord] & (Word(1) << (aPos % kBitsPerWord)); } constexpr bool IsEmpty() const { - for (const Word& word : mStorage) { + for (const StorageType& word : mStorage) { if (word) { return false; } @@ -93,21 +125,21 @@ class BitSet { explicit constexpr operator bool() { return !IsEmpty(); } - constexpr bool operator[](size_t aPos) const { return Test(aPos); } + constexpr bool operator[](size_t aPos) const { return test(aPos); } Reference operator[](size_t aPos) { MOZ_ASSERT(aPos < N); return {*this, aPos}; } - BitSet operator|(const BitSet& aOther) { + BitSet operator|(const BitSet& aOther) { BitSet result = *this; result |= aOther; return result; } - BitSet& operator|=(const BitSet& aOther) { - for (size_t i = 0; i < ArrayLength(mStorage); i++) { + BitSet& operator|=(const BitSet& aOther) { + for (size_t i = 0; i < std::size(mStorage); i++) { mStorage[i] |= aOther.mStorage[i]; } return *this; @@ -119,27 +151,27 @@ class BitSet { return result; } - BitSet& operator&=(const BitSet& aOther) { - for (size_t i = 0; i < ArrayLength(mStorage); i++) { + BitSet& operator&=(const BitSet& aOther) { + for (size_t i = 0; i < std::size(mStorage); i++) { mStorage[i] &= aOther.mStorage[i]; } return *this; } - BitSet operator&(const BitSet& aOther) const { + BitSet operator&(const BitSet& aOther) const { BitSet result = *this; result &= aOther; return result; } - bool operator==(const BitSet& aOther) const { + bool operator==(const BitSet& aOther) const { return mStorage == aOther.mStorage; } size_t Count() const { size_t count = 0; - for (const Word& word : mStorage) { + for (const StorageType& word : mStorage) { if constexpr (kBitsPerWord > 32) { count += CountPopulation64(word); } else { @@ -151,25 +183,80 @@ class BitSet { } // Set all bits to false. - void ResetAll() { PodArrayZero(mStorage); } + void ResetAll() { + for (StorageType& word : mStorage) { + word = Word(0); + } + } // Set all bits to true. void SetAll() { - memset(mStorage.begin(), 0xff, kNumWords * sizeof(Word)); + for (StorageType& word : mStorage) { + word = ~Word(0); + } ResetPaddingBits(); } void Flip() { - for (Word& word : mStorage) { + for (StorageType& word : mStorage) { word = ~word; } ResetPaddingBits(); } - Span Storage() { return mStorage; } + // Return the position of the first bit set, or SIZE_MAX if none. + size_t FindFirst() const { return FindNext(0); } - Span Storage() const { return mStorage; } + // Return the position of the next bit set starting from |aFromPos| inclusive, + // or SIZE_MAX if none. + size_t FindNext(size_t aFromPos) const { + MOZ_ASSERT(aFromPos < N); + size_t wordIndex = aFromPos / kBitsPerWord; + size_t bitIndex = aFromPos % kBitsPerWord; + + Word word = mStorage[wordIndex]; + // Mask word containing |aFromPos|. + word &= (Word(-1) << bitIndex); + while (word == 0) { + wordIndex++; + if (wordIndex == kNumWords) { + return SIZE_MAX; + } + word = mStorage[wordIndex]; + } + + uint_fast8_t pos = CountTrailingZeroes(word); + return wordIndex * kBitsPerWord + pos; + } + + size_t FindLast() const { return FindPrev(size() - 1); } + + // Return the position of the previous bit set starting from |aFromPos| + // inclusive, or SIZE_MAX if none. + size_t FindPrev(size_t aFromPos) const { + MOZ_ASSERT(aFromPos < N); + size_t wordIndex = aFromPos / kBitsPerWord; + size_t bitIndex = aFromPos % kBitsPerWord; + + Word word = mStorage[wordIndex]; + // Mask word containing |aFromPos|. + word &= Word(-1) >> (kBitsPerWord - 1 - bitIndex); + while (word == 0) { + if (wordIndex == 0) { + return SIZE_MAX; + } + wordIndex--; + word = mStorage[wordIndex]; + } + + uint_fast8_t pos = FindMostSignificantBit(word); + return wordIndex * kBitsPerWord + pos; + } + + Span Storage() { return mStorage; } + + Span Storage() const { return mStorage; } }; } // namespace mozilla diff --git a/src/third_party/mozjs/extract/mfbt/Buffer.h b/src/third_party/mozjs/extract/mfbt/Buffer.h index c4e0a4be92e..12156e58e07 100644 --- a/src/third_party/mozjs/extract/mfbt/Buffer.h +++ b/src/third_party/mozjs/extract/mfbt/Buffer.h @@ -39,7 +39,7 @@ class Buffer final { * Construct zero-lenth Buffer (without actually pointing to a heap * allocation). */ - Buffer() : mData(nullptr), mLength(0){}; + Buffer() : mData(nullptr), mLength(0) {}; /** * Construct from raw parts. diff --git a/src/third_party/mozjs/extract/mfbt/Casting.h b/src/third_party/mozjs/extract/mfbt/Casting.h index 6247d6e9865..82d358c27a6 100644 --- a/src/third_party/mozjs/extract/mfbt/Casting.h +++ b/src/third_party/mozjs/extract/mfbt/Casting.h @@ -10,7 +10,11 @@ #define mozilla_Casting_h #include "mozilla/Assertions.h" +#include "mozilla/Sprintf.h" +#include "fmt/format.h" + +#include #include #include #include @@ -78,6 +82,70 @@ constexpr uint64_t safe_integer_unsigned() { return std::pow(2, std::numeric_limits::digits); } +template +const char* TypeToStringFallback(); + +template +inline constexpr const char* TypeToString() { + return TypeToStringFallback(); +} + +#define T2S(type) \ + template <> \ + inline constexpr const char* TypeToString() { \ + return #type; \ + } + +#define T2SF(type) \ + template <> \ + inline constexpr const char* TypeToStringFallback() { \ + return #type; \ + } + +T2S(uint8_t); +T2S(uint16_t); +T2S(uint32_t); +T2S(uint64_t); +T2S(int8_t); +T2S(int16_t); +T2S(int32_t); +T2S(int64_t); +T2S(char16_t); +T2S(char32_t); +T2SF(int); +T2SF(unsigned int); +T2SF(long); +T2SF(unsigned long); +T2S(float); +T2S(double); + +#undef T2S +#undef T2SF + +template +inline void DiagnosticMessage(In aIn, char aDiagnostic[1024]) { + if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + static_assert(sizeof(wchar_t) <= sizeof(int32_t)); + // Characters types are printed in hexadecimal for two reasons: + // - to easily debug problems with non-printable characters. + // - {fmt} refuses to format a string with mixed character type. + // It's always possible to cast them to int64_t for lossless printing of the + // value. + auto [out, size] = fmt::format_to_n( + aDiagnostic, 1023, + FMT_STRING("Cannot cast {:x} from {} to {}: out of range"), + static_cast(aIn), TypeToString(), TypeToString()); + *out = 0; + } else { + auto [out, size] = fmt::format_to_n( + aDiagnostic, 1023, + FMT_STRING("Cannot cast {} from {} to {}: out of range"), aIn, + TypeToString(), TypeToString()); + *out = 0; + } +} + // This is working around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81676, // fixed in gcc-10 // MONGODB MODIFICATION: Only enable for GCC. @@ -186,7 +254,14 @@ bool IsInBounds(In aIn) { template inline To AssertedCast(const From aFrom) { static_assert(std::is_arithmetic_v && std::is_arithmetic_v); - MOZ_ASSERT((detail::IsInBounds(aFrom))); +#ifdef DEBUG + if (!detail::IsInBounds(aFrom)) { + char buf[1024]; + detail::DiagnosticMessage(aFrom, buf); + fprintf(stderr, "AssertedCast error: %s\n", buf); + MOZ_CRASH(); + } +#endif return static_cast(aFrom); } @@ -204,6 +279,60 @@ inline To ReleaseAssertedCast(const From aFrom) { return static_cast(aFrom); } +/** + * Cast from type From to type To, clamping to minimum and maximum value of the + * destination type if needed. + */ +template +inline To SaturatingCast(const From aFrom) { + static_assert(std::is_arithmetic_v && std::is_arithmetic_v); + // This implementation works up to 64-bits integers. + static_assert(sizeof(From) <= 8 && sizeof(To) <= 8); + constexpr bool fromFloat = std::is_floating_point_v; + constexpr bool toFloat = std::is_floating_point_v; + + // It's not clear what the caller wants here, it could be round, truncate, + // closest value, etc. + static_assert((fromFloat && !toFloat) || (!fromFloat && !toFloat), + "Handle manually depending on desired behaviour"); + + // If the source is floating point and the destination isn't, it can be that + // casting changes the value unexpectedly. Casting to double and clamping to + // the max of the destination type is correct, this also handles infinity. + if constexpr (fromFloat) { + if (aFrom > static_cast(std::numeric_limits::max())) { + return std::numeric_limits::max(); + } + if (aFrom < static_cast(std::numeric_limits::lowest())) { + return std::numeric_limits::lowest(); + } + return static_cast(aFrom); + } + // Source and destination are of opposite signedness + if constexpr (std::is_signed_v != std::is_signed_v) { + // Input is negative, output is unsigned, return 0 + if (std::is_signed_v && aFrom < 0) { + return 0; + } + // At this point the input is positive, cast everything to uint64_t for + // simplicity and compare + uint64_t inflated = AssertedCast(aFrom); + if (inflated > static_cast(std::numeric_limits::max())) { + return std::numeric_limits::max(); + } + return static_cast(aFrom); + } else { + // Regular case: clamp to destination type range + if (aFrom > std::numeric_limits::max()) { + return std::numeric_limits::max(); + } + if (aFrom < std::numeric_limits::lowest()) { + return std::numeric_limits::lowest(); + } + return static_cast(aFrom); + } +} + namespace detail { template diff --git a/src/third_party/mozjs/extract/mfbt/ChaosMode.cpp b/src/third_party/mozjs/extract/mfbt/ChaosMode.cpp index d090e8a37e9..b2a6fd40d44 100644 --- a/src/third_party/mozjs/extract/mfbt/ChaosMode.cpp +++ b/src/third_party/mozjs/extract/mfbt/ChaosMode.cpp @@ -10,8 +10,8 @@ namespace mozilla { namespace detail { -Atomic gChaosModeCounter(0); -ChaosFeature gChaosFeatures = None; +Atomic gChaosModeCounter(0); +ChaosFeature gChaosFeatures = ChaosFeature::Any; } /* namespace detail */ } /* namespace mozilla */ diff --git a/src/third_party/mozjs/extract/mfbt/ChaosMode.h b/src/third_party/mozjs/extract/mfbt/ChaosMode.h index faf7acddf39..722a665d9a5 100644 --- a/src/third_party/mozjs/extract/mfbt/ChaosMode.h +++ b/src/third_party/mozjs/extract/mfbt/ChaosMode.h @@ -15,7 +15,7 @@ namespace mozilla { -enum ChaosFeature { +enum class ChaosFeature : uint32_t { None = 0x0, // Altering thread scheduling. ThreadScheduling = 0x1, @@ -37,7 +37,7 @@ enum ChaosFeature { }; namespace detail { -extern MFBT_DATA Atomic gChaosModeCounter; +extern MFBT_DATA Atomic gChaosModeCounter; extern MFBT_DATA ChaosFeature gChaosFeatures; } // namespace detail @@ -53,17 +53,14 @@ class ChaosMode { } static bool isActive(ChaosFeature aFeature) { - if (detail::gChaosModeCounter > 0) { - return true; - } - return detail::gChaosFeatures & aFeature; + return detail::gChaosModeCounter > 0 && + (uint32_t(detail::gChaosFeatures) & uint32_t(aFeature)); } /** * Increase the chaos mode activation level. An equivalent number of * calls to leaveChaosMode must be made in order to restore the original - * chaos mode state. If the activation level is nonzero all chaos mode - * features are activated. + * chaos mode state. */ static void enterChaosMode() { detail::gChaosModeCounter++; } @@ -83,6 +80,15 @@ class ChaosMode { MOZ_ASSERT(aBound != 0); return uint32_t(rand()) % aBound; } + + /** + * Returns a somewhat (but not uniformly) random int32_t <= aLow and >= aHigh. + * Not to be used for anything except ChaosMode, since it's not very random. + */ + static int32_t randomInt32InRange(int32_t aLow, int32_t aHigh) { + MOZ_ASSERT(aHigh >= aLow); + return (int32_t(rand()) % (aHigh - aLow + 1)) + aLow; + } }; } /* namespace mozilla */ diff --git a/src/third_party/mozjs/extract/mfbt/Compression.h b/src/third_party/mozjs/extract/mfbt/Compression.h deleted file mode 100644 index d9f787c0b46..00000000000 --- a/src/third_party/mozjs/extract/mfbt/Compression.h +++ /dev/null @@ -1,218 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Various simple compression/decompression functions. */ - -#ifndef mozilla_Compression_h_ -#define mozilla_Compression_h_ - -#include "mozilla/Assertions.h" -#include "mozilla/Types.h" -#include "mozilla/ResultVariant.h" -#include "mozilla/Span.h" -#include "mozilla/UniquePtr.h" - -struct LZ4F_cctx_s; // compression context -struct LZ4F_dctx_s; // decompression context - -namespace mozilla { -namespace Compression { - -/** - * LZ4 is a very fast byte-wise compression algorithm. - * - * Compared to Google's Snappy it is faster to compress and decompress and - * generally produces output of about the same size. - * - * Compared to zlib it compresses at about 10x the speed, decompresses at about - * 4x the speed and produces output of about 1.5x the size. - */ - -class LZ4 { - public: - /** - * Compresses |aInputSize| bytes from |aSource| into |aDest|. Destination - * buffer must be already allocated, and must be sized to handle worst cases - * situations (input data not compressible). Worst case size evaluation is - * provided by function maxCompressedSize() - * - * @param aInputSize is the input size. Max supported value is ~1.9GB - * @return the number of bytes written in buffer |aDest| - */ - static MFBT_API size_t compress(const char* aSource, size_t aInputSize, - char* aDest); - - /** - * Compress |aInputSize| bytes from |aSource| into an output buffer - * |aDest| of maximum size |aMaxOutputSize|. If it cannot achieve it, - * compression will stop, and result of the function will be zero, - * |aDest| will still be written to, but since the number of input - * bytes consumed is not returned the result is not usable. - * - * This function never writes outside of provided output buffer. - * - * @param aInputSize is the input size. Max supported value is ~1.9GB - * @param aMaxOutputSize is the size of the destination buffer (which must - * be already allocated) - * @return the number of bytes written in buffer |aDest| or 0 if the - * compression fails - */ - static MFBT_API size_t compressLimitedOutput(const char* aSource, - size_t aInputSize, char* aDest, - size_t aMaxOutputSize); - - /** - * If the source stream is malformed, the function will stop decoding - * and return false. - * - * This function never writes beyond aDest + aMaxOutputSize, and is - * therefore protected against malicious data packets. - * - * Note: Destination buffer must be already allocated. This version is - * slightly slower than the decompress without the aMaxOutputSize. - * - * @param aInputSize is the length of the input compressed data - * @param aMaxOutputSize is the size of the destination buffer (which must be - * already allocated) - * @param aOutputSize the actual number of bytes decoded in the destination - * buffer (necessarily <= aMaxOutputSize) - * @return true on success, false on failure - */ - [[nodiscard]] static MFBT_API bool decompress(const char* aSource, - size_t aInputSize, char* aDest, - size_t aMaxOutputSize, - size_t* aOutputSize); - - /** - * If the source stream is malformed, the function will stop decoding - * and return false. - * - * This function never writes beyond aDest + aMaxOutputSize, and is - * therefore protected against malicious data packets. It also ignores - * unconsumed input upon reaching aMaxOutputSize and can therefore be used - * for partial decompression. - * - * Note: Destination buffer must be already allocated. This version is - * slightly slower than the decompress without the aMaxOutputSize. - * - * @param aInputSize is the length of the input compressed data - * @param aMaxOutputSize is the size of the destination buffer (which must be - * already allocated) - * @param aOutputSize the actual number of bytes decoded in the destination - * buffer (necessarily <= aMaxOutputSize) - * @return true on success, false on failure - */ - [[nodiscard]] static MFBT_API bool decompressPartial(const char* aSource, - size_t aInputSize, - char* aDest, - size_t aMaxOutputSize, - size_t* aOutputSize); - - /* - * Provides the maximum size that LZ4 may output in a "worst case" - * scenario (input data not compressible) primarily useful for memory - * allocation of output buffer. - * note : this function is limited by "int" range (2^31-1) - * - * @param aInputSize is the input size. Max supported value is ~1.9GB - * @return maximum output size in a "worst case" scenario - */ - static inline size_t maxCompressedSize(size_t aInputSize) { - size_t max = (aInputSize + (aInputSize / 255) + 16); - MOZ_ASSERT(max > aInputSize); - return max; - } -}; - -/** - * Context for LZ4 Frame-based streaming compression. Use this if you - * want to incrementally compress something or if you want to compress - * something such that another application can read it. - */ -class LZ4FrameCompressionContext final { - public: - MFBT_API LZ4FrameCompressionContext(int aCompressionLevel, size_t aMaxSrcSize, - bool aChecksum, bool aStableSrc = false); - - MFBT_API ~LZ4FrameCompressionContext(); - - size_t GetRequiredWriteBufferLength() { return mWriteBufLen; } - - /** - * Begin streaming frame-based compression. - * - * @return a Result with a Span containing the frame header, or an lz4 error - * code (size_t). - */ - MFBT_API Result, size_t> BeginCompressing( - Span aWriteBuffer); - - /** - * Continue streaming frame-based compression with the provided input. - * - * @param aInput input buffer to be compressed. - * @return a Result with a Span containing compressed output, or an lz4 error - * code (size_t). - */ - MFBT_API Result, size_t> ContinueCompressing( - Span aInput); - - /** - * Finalize streaming frame-based compression with the provided input. - * - * @return a Result with a Span containing compressed output and the frame - * footer, or an lz4 error code (size_t). - */ - MFBT_API Result, size_t> EndCompressing(); - - private: - LZ4F_cctx_s* mContext; - int mCompressionLevel; - bool mGenerateChecksum; - bool mStableSrc; - size_t mMaxSrcSize; - size_t mWriteBufLen; - Span mWriteBuffer; -}; - -struct LZ4FrameDecompressionResult { - size_t mSizeRead; - size_t mSizeWritten; - bool mFinished; -}; - -/** - * Context for LZ4 Frame-based streaming decompression. Use this if you - * want to decompress something compressed by LZ4FrameCompressionContext - * or by another application. - */ -class LZ4FrameDecompressionContext final { - public: - explicit MFBT_API LZ4FrameDecompressionContext(bool aStableDest = false); - MFBT_API ~LZ4FrameDecompressionContext(); - - /** - * Decompress a buffer/part of a buffer compressed with - * LZ4FrameCompressionContext or another application. - * - * @param aOutput output buffer to be write results into. - * @param aInput input buffer to be decompressed. - * @return a Result with information on bytes read/written and whether we - * completely decompressed the input into the output, or an lz4 error code - * (size_t). - */ - MFBT_API Result Decompress( - Span aOutput, Span aInput); - - private: - LZ4F_dctx_s* mContext; - bool mStableDest; -}; - -} /* namespace Compression */ -} /* namespace mozilla */ - -#endif /* mozilla_Compression_h_ */ diff --git a/src/third_party/mozjs/extract/mfbt/DefineEnum.h b/src/third_party/mozjs/extract/mfbt/DefineEnum.h index afcff10e521..e5a6aaeaf20 100644 --- a/src/third_party/mozjs/extract/mfbt/DefineEnum.h +++ b/src/third_party/mozjs/extract/mfbt/DefineEnum.h @@ -10,6 +10,7 @@ #define mozilla_DefineEnum_h #include // for size_t +#include // for std::ostream #include "mozilla/MacroArgs.h" // for MOZ_ARG_COUNT #include "mozilla/MacroForEach.h" // for MOZ_FOR_EACH @@ -84,6 +85,14 @@ * and have names prefixed with "s" instead of "k" as per * naming convention. * + * - A |_TOSTRING| variant, which generates an EnumValueToString function, + * converting the enum items to strings, and implements an "operator<<", + * providing a consistent way to convert enums to strings by + * mozilla::ToString function regardless of their definition context. + * For users needing C-string compatibility for logging in restricted + * contexts or performance sensitive applications, EnumValueToString is + * preferred. + * * (and combinations of these). */ @@ -150,7 +159,61 @@ #define MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AT_CLASS_SCOPE(aEnumName, aBaseName, \ aEnumerators) \ - MOZ_DEFINE_ENUM_AT_CLASS_SCOPE_IMPL(aEnumName, class, \ - : aBaseName, aEnumerators) + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE_IMPL(aEnumName, class, : aBaseName, \ + aEnumerators) + +#define MOZ_DEFINE_ENUM_TO_ENUM_TEXT(aEnumeratorDecl) #aEnumeratorDecl + +#define MOZ_DEFINE_ENUM_TOSTRING_FUNC_IMPL(aEnumName, aEnumerators, aFriend) \ + inline static const char* EnumValueToString(const aEnumName& aEnum) { \ + static constexpr const char* kMappedStrings[] = {MOZ_FOR_EACH_SEPARATED( \ + MOZ_DEFINE_ENUM_TO_ENUM_TEXT, (, ), (), aEnumerators)}; \ + return kMappedStrings[static_cast(aEnum)]; \ + } \ + aFriend inline std::ostream& operator<<(std::ostream& aStream, \ + const aEnumName& aEnum) { \ + aStream << EnumValueToString(aEnum); \ + return aStream; \ + } + +#define MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IMPL(aEnumName, aEnumerators, ) + +#define MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IMPL(aEnumName, aEnumerators, friend) + +#define MOZ_DEFINE_ENUM_WITH_BASE_AND_TOSTRING(aEnumName, aBaseName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_WITH_BASE(aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(aEnumName, aBaseName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS_WITH_BASE(aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_WITH_TOSTRING_AT_CLASS_SCOPE(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_WITH_BASE_AND_TOSTRING_AT_CLASS_SCOPE( \ + aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(aEnumName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS_AT_CLASS_SCOPE(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING_AT_CLASS_SCOPE( \ + aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AT_CLASS_SCOPE(aEnumName, aBaseName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) #endif // mozilla_DefineEnum_h diff --git a/src/third_party/mozjs/extract/mfbt/DoublyLinkedList.h b/src/third_party/mozjs/extract/mfbt/DoublyLinkedList.h index df178440d2d..ed7b8e66ccc 100644 --- a/src/third_party/mozjs/extract/mfbt/DoublyLinkedList.h +++ b/src/third_party/mozjs/extract/mfbt/DoublyLinkedList.h @@ -368,6 +368,38 @@ class DoublyLinkedList final { } return !ElementNotInList(aElm); } + + /** + * Returns whether an element is linked correctly to its predecessor and/or + * successor, if any. Used for internal sanity checks. + */ + bool ElementIsLinkedWell(T* aElm) { + MOZ_ASSERT(aElm); + if (!ElementProbablyInList(aElm)) { + return false; + } + T* next = ElementAccess::Get(aElm).mNext; + if (next) { + if (ElementAccess::Get(next).mPrev != aElm) { + return false; + } + } else { + if (aElm != mTail) { + return false; + } + } + T* prev = ElementAccess::Get(aElm).mPrev; + if (prev) { + if (ElementAccess::Get(prev).mNext != aElm) { + return false; + } + } else { + if (aElm != mHead) { + return false; + } + } + return true; + } }; /** diff --git a/src/third_party/mozjs/extract/mfbt/EnumSet.h b/src/third_party/mozjs/extract/mfbt/EnumSet.h index 712e03d3f3d..c9bc82d1da7 100644 --- a/src/third_party/mozjs/extract/mfbt/EnumSet.h +++ b/src/third_party/mozjs/extract/mfbt/EnumSet.h @@ -52,6 +52,8 @@ class EnumSet { } } + constexpr explicit EnumSet(Serialized aValue) : mBitField(aValue) {} + #ifdef DEBUG constexpr EnumSet(const EnumSet& aEnumSet) : mBitField(aEnumSet.mBitField) {} @@ -82,7 +84,7 @@ class EnumSet { /** * Union */ - void operator+=(const EnumSet& aEnumSet) { + constexpr void operator+=(const EnumSet& aEnumSet) { IncVersion(); mBitField |= aEnumSet.mBitField; } @@ -90,7 +92,7 @@ class EnumSet { /** * Union */ - EnumSet operator+(const EnumSet& aEnumSet) const { + constexpr EnumSet operator+(const EnumSet& aEnumSet) const { EnumSet result(*this); result += aEnumSet; return result; @@ -99,7 +101,7 @@ class EnumSet { /** * Remove an element */ - void operator-=(T aEnum) { + constexpr void operator-=(T aEnum) { IncVersion(); mBitField &= ~(BitFor(aEnum)); } @@ -107,7 +109,7 @@ class EnumSet { /** * Remove an element */ - EnumSet operator-(T aEnum) const { + constexpr EnumSet operator-(T aEnum) const { EnumSet result(*this); result -= aEnum; return result; @@ -116,7 +118,7 @@ class EnumSet { /** * Remove a set of elements */ - void operator-=(const EnumSet& aEnumSet) { + constexpr void operator-=(const EnumSet& aEnumSet) { IncVersion(); mBitField &= ~(aEnumSet.mBitField); } @@ -124,7 +126,7 @@ class EnumSet { /** * Remove a set of elements */ - EnumSet operator-(const EnumSet& aEnumSet) const { + constexpr EnumSet operator-(const EnumSet& aEnumSet) const { EnumSet result(*this); result -= aEnumSet; return result; @@ -133,7 +135,7 @@ class EnumSet { /** * Clear */ - void clear() { + constexpr void clear() { IncVersion(); mBitField = Serialized(); } @@ -141,7 +143,7 @@ class EnumSet { /** * Intersection */ - void operator&=(const EnumSet& aEnumSet) { + constexpr void operator&=(const EnumSet& aEnumSet) { IncVersion(); mBitField &= aEnumSet.mBitField; } @@ -149,7 +151,7 @@ class EnumSet { /** * Intersection */ - EnumSet operator&(const EnumSet& aEnumSet) const { + constexpr EnumSet operator&(const EnumSet& aEnumSet) const { EnumSet result(*this); result &= aEnumSet; return result; @@ -158,36 +160,38 @@ class EnumSet { /** * Equality */ - bool operator==(const EnumSet& aEnumSet) const { + constexpr bool operator==(const EnumSet& aEnumSet) const { return mBitField == aEnumSet.mBitField; } /** * Equality */ - bool operator==(T aEnum) const { return mBitField == BitFor(aEnum); } + constexpr bool operator==(T aEnum) const { + return mBitField == BitFor(aEnum); + } /** * Not equal */ - bool operator!=(const EnumSet& aEnumSet) const { + constexpr bool operator!=(const EnumSet& aEnumSet) const { return !operator==(aEnumSet); } /** * Not equal */ - bool operator!=(T aEnum) const { return !operator==(aEnum); } + constexpr bool operator!=(T aEnum) const { return !operator==(aEnum); } /** * Test is an element is contained in the set. */ - bool contains(T aEnum) const { return HasBitFor(aEnum); } + constexpr bool contains(T aEnum) const { return HasBitFor(aEnum); } /** * Test if a set is contained in the set. */ - bool contains(const EnumSet& aEnumSet) const { + constexpr bool contains(const EnumSet& aEnumSet) const { return (mBitField & aEnumSet.mBitField) == aEnumSet.mBitField; } @@ -206,7 +210,7 @@ class EnumSet { } } - bool isEmpty() const { + constexpr bool isEmpty() const { if constexpr (std::is_unsigned_v) { return mBitField == 0; } else { @@ -319,7 +323,12 @@ class EnumSet { } constexpr bool HasBitAt(size_t aPos) const { - return static_cast(mBitField & BitAt(aPos)); + if constexpr (std::is_unsigned_v) { + return mBitField & BitAt(aPos); + } else { + // for std::bitset and mozilla::BitSet + return mBitField.test(aPos); + } } constexpr void IncVersion() { @@ -332,7 +341,7 @@ class EnumSet { if constexpr (std::is_unsigned_v) { return sizeof(Serialized) * 8; } else { - return Serialized::Size(); + return Serialized().size(); } } diff --git a/src/third_party/mozjs/extract/mfbt/EnumTypeTraits.h b/src/third_party/mozjs/extract/mfbt/EnumTypeTraits.h index 09ead3d0e96..84ad19c607b 100644 --- a/src/third_party/mozjs/extract/mfbt/EnumTypeTraits.h +++ b/src/third_party/mozjs/extract/mfbt/EnumTypeTraits.h @@ -63,6 +63,7 @@ struct EnumTypeFitsWithin /** * Get the underlying value of an enum, but typesafe. + * TODO: Replace with std::to_underlying when available. * * example: * diff --git a/src/third_party/mozjs/extract/mfbt/EnumeratedArray.h b/src/third_party/mozjs/extract/mfbt/EnumeratedArray.h index c1e7eeccddd..cb9b326d7f0 100644 --- a/src/third_party/mozjs/extract/mfbt/EnumeratedArray.h +++ b/src/third_party/mozjs/extract/mfbt/EnumeratedArray.h @@ -61,9 +61,11 @@ class EnumeratedArray { MOZ_IMPLICIT constexpr EnumeratedArray(Args&&... aArgs) : mArray{std::forward(aArgs)...} {} - ValueType& operator[](Enum aIndex) { return mArray[size_t(aIndex)]; } + constexpr ValueType& operator[](Enum aIndex) { + return mArray[size_t(aIndex)]; + } - const ValueType& operator[](Enum aIndex) const { + constexpr const ValueType& operator[](Enum aIndex) const { return mArray[size_t(aIndex)]; } @@ -80,6 +82,9 @@ class EnumeratedArray { const_iterator end() const { return mArray.end(); } const_iterator cend() const { return mArray.cend(); } + // Method for std::size. + constexpr size_t size() const { return mArray.size(); } + // Methods for reverse iterating. reverse_iterator rbegin() { return mArray.rbegin(); } const_reverse_iterator rbegin() const { return mArray.rbegin(); } diff --git a/src/third_party/mozjs/extract/mfbt/FloatingPoint.h b/src/third_party/mozjs/extract/mfbt/FloatingPoint.h index f4ae36257bb..ad9362152ae 100644 --- a/src/third_party/mozjs/extract/mfbt/FloatingPoint.h +++ b/src/third_party/mozjs/extract/mfbt/FloatingPoint.h @@ -151,7 +151,7 @@ struct FloatingPoint final : private detail::FloatingPointTrait { static_assert((kExponentBits & kSignificandBits) == 0, "exponent bits shouldn't overlap significand bits"); - static_assert((kSignBit | kExponentBits | kSignificandBits) == ~Bits(0), + static_assert((kSignBit | kExponentBits | kSignificandBits) == Bits(~0), "all bits accounted for"); }; @@ -216,24 +216,14 @@ static MOZ_ALWAYS_INLINE int_fast16_t ExponentComponent(T aValue) { /** Returns +Infinity. */ template -static MOZ_ALWAYS_INLINE T PositiveInfinity() { - /* - * Positive infinity has all exponent bits set, sign bit set to 0, and no - * significand. - */ - typedef FloatingPoint Traits; - return BitwiseCast(Traits::kExponentBits); +static constexpr MOZ_ALWAYS_INLINE T PositiveInfinity() { + return std::numeric_limits::infinity(); } /** Returns -Infinity. */ template -static MOZ_ALWAYS_INLINE T NegativeInfinity() { - /* - * Negative infinity has all exponent bits set, sign bit set to 1, and no - * significand. - */ - typedef FloatingPoint Traits; - return BitwiseCast(Traits::kSignBit | Traits::kExponentBits); +static constexpr MOZ_ALWAYS_INLINE T NegativeInfinity() { + return -std::numeric_limits::infinity(); } /** @@ -306,10 +296,14 @@ SpecificNaN(int signbit, typename FloatingPoint::Bits significand) { /** Computes the smallest non-zero positive float/double value. */ template -static MOZ_ALWAYS_INLINE T MinNumberValue() { - typedef FloatingPoint Traits; - typedef typename Traits::Bits Bits; - return BitwiseCast(Bits(1)); +static constexpr MOZ_ALWAYS_INLINE T MinNumberValue() { + return std::numeric_limits::denorm_min(); +} + +/** Computes the largest positive float/double value. */ +template +static constexpr MOZ_ALWAYS_INLINE T MaxNumberValue() { + return std::numeric_limits::max(); } namespace detail { diff --git a/src/third_party/mozjs/extract/mfbt/HashTable.h b/src/third_party/mozjs/extract/mfbt/HashTable.h index 9f3f42b40ec..6ef91045177 100644 --- a/src/third_party/mozjs/extract/mfbt/HashTable.h +++ b/src/third_party/mozjs/extract/mfbt/HashTable.h @@ -180,6 +180,9 @@ class HashMap { HashMap(HashMap&& aRhs) = default; HashMap& operator=(HashMap&& aRhs) = default; + // Swap the contents of this hash map with another. + void swap(HashMap& aOther) { mImpl.swap(aOther.mImpl); } + // -- Status and sizing ---------------------------------------------------- // The map's current generation. @@ -477,6 +480,9 @@ class HashSet { HashSet(HashSet&& aRhs) = default; HashSet& operator=(HashSet&& aRhs) = default; + // Swap the contents of this hash set with another. + void swap(HashSet& aOther) { mImpl.swap(aOther.mImpl); } + // -- Status and sizing ---------------------------------------------------- // The set's current generation. @@ -1558,6 +1564,29 @@ class HashTable : private AllocPolicy { return *this; } + void swap(HashTable& aOther) { + ReentrancyGuard g1(*this); + ReentrancyGuard g2(aOther); + + // Manual swap of generation because it's a bitfield + uint64_t generation = mGen; + mGen = aOther.mGen; + aOther.mGen = generation; + + // Manual swap of hashShift because it's a bitfield + uint64_t hashShift = mHashShift; + mHashShift = aOther.mHashShift; + aOther.mHashShift = hashShift; + + std::swap(mTable, aOther.mTable); + std::swap(mEntryCount, aOther.mEntryCount); + std::swap(mRemovedCount, aOther.mRemovedCount); +#ifdef DEBUG + std::swap(mMutationCount, aOther.mMutationCount); + std::swap(mEntered, aOther.mEntered); +#endif + } + private: void moveFrom(HashTable& aRhs) { mGen = aRhs.mGen; diff --git a/src/third_party/mozjs/extract/mfbt/JSONWriter.h b/src/third_party/mozjs/extract/mfbt/JSONWriter.h index f779ee98378..7e37e3ce6ad 100644 --- a/src/third_party/mozjs/extract/mfbt/JSONWriter.h +++ b/src/third_party/mozjs/extract/mfbt/JSONWriter.h @@ -250,8 +250,8 @@ class JSONWriter { static constexpr Span scTopObjectEndString = MakeStringSpan("}"); static constexpr Span scTrueString = MakeStringSpan("true"); - JSONWriteFunc& mWriter; const UniquePtr mMaybeOwnedWriter; + JSONWriteFunc& mWriter; Vector mNeedComma; // do we need a comma at depth N? Vector mNeedNewlines; // do we need newlines at depth N? size_t mDepth; // the current nesting depth @@ -352,8 +352,8 @@ class JSONWriter { explicit JSONWriter(UniquePtr aWriter, CollectionStyle aStyle = MultiLineStyle) - : mWriter(*aWriter), - mMaybeOwnedWriter(std::move(aWriter)), + : mMaybeOwnedWriter(std::move(aWriter)), + mWriter(*mMaybeOwnedWriter), mNeedComma(), mNeedNewlines(), mDepth(0) { @@ -365,7 +365,7 @@ class JSONWriter { // Returns the JSONWriteFunc passed in at creation, for temporary use. The // JSONWriter object still owns the JSONWriteFunc. - JSONWriteFunc& WriteFunc() const { return mWriter; } + JSONWriteFunc& WriteFunc() const MOZ_LIFETIME_BOUND { return mWriter; } // For all the following functions, the "Prints:" comment indicates what the // basic output looks like. However, it doesn't indicate the whitespace and diff --git a/src/third_party/mozjs/extract/mfbt/LinkedList.h b/src/third_party/mozjs/extract/mfbt/LinkedList.h index 850b8594c75..15e53e80c1d 100644 --- a/src/third_party/mozjs/extract/mfbt/LinkedList.h +++ b/src/third_party/mozjs/extract/mfbt/LinkedList.h @@ -409,13 +409,13 @@ class LinkedListElement { template class LinkedList { private: - typedef typename detail::LinkedListElementTraits Traits; - typedef typename Traits::RawType RawType; - typedef typename Traits::ConstRawType ConstRawType; - typedef typename Traits::ClientType ClientType; - typedef typename Traits::ConstClientType ConstClientType; - typedef LinkedListElement* ElementType; - typedef const LinkedListElement* ConstElementType; + using Traits = typename detail::LinkedListElementTraits; + using RawType = typename Traits::RawType; + using ConstRawType = typename Traits::ConstRawType; + using ClientType = typename Traits::ClientType; + using ConstClientType = typename Traits::ConstClientType; + using ElementType = LinkedListElement*; + using ConstElementType = const LinkedListElement*; LinkedListElement sentinel; @@ -445,6 +445,9 @@ class LinkedList { } }; + using const_iterator = Iterator; + using iterator = Iterator; + LinkedList() : sentinel(LinkedListElement::NodeKind::Sentinel) {} LinkedList(LinkedList&& aOther) : sentinel(std::move(aOther.sentinel)) {} @@ -701,6 +704,11 @@ class LinkedList { LinkedList(const LinkedList& aOther) = delete; }; +template +size_t RangeSizeEstimate(const LinkedList&) { + return 0; +} + template inline void ImplCycleCollectionUnlink(LinkedList>& aField) { aField.clear(); diff --git a/src/third_party/mozjs/extract/mfbt/Literals.h b/src/third_party/mozjs/extract/mfbt/Literals.h index d1d403afaeb..97f24af8003 100644 --- a/src/third_party/mozjs/extract/mfbt/Literals.h +++ b/src/third_party/mozjs/extract/mfbt/Literals.h @@ -16,19 +16,19 @@ // // size_t page_size = 4_KiB; // -constexpr size_t operator"" _KiB(unsigned long long int aNum) { +constexpr size_t operator""_KiB(unsigned long long int aNum) { return size_t(aNum) * 1024; } -constexpr size_t operator"" _KiB(long double aNum) { +constexpr size_t operator""_KiB(long double aNum) { return size_t(aNum * 1024); } -constexpr size_t operator"" _MiB(unsigned long long int aNum) { +constexpr size_t operator""_MiB(unsigned long long int aNum) { return size_t(aNum) * 1024_KiB; } -constexpr size_t operator"" _MiB(long double aNum) { +constexpr size_t operator""_MiB(long double aNum) { return size_t(aNum * 1024_KiB); } diff --git a/src/third_party/mozjs/extract/mfbt/MathAlgorithms.h b/src/third_party/mozjs/extract/mfbt/MathAlgorithms.h index 5ac810c22c1..a94de1fd4c0 100644 --- a/src/third_party/mozjs/extract/mfbt/MathAlgorithms.h +++ b/src/third_party/mozjs/extract/mfbt/MathAlgorithms.h @@ -310,28 +310,24 @@ inline uint_fast8_t CeilingLog2Size(size_t aValue) { return CeilingLog2(aValue); } -namespace detail { - -template -class FloorLog2; - +/** + * Compute the bit position of the most significant bit set in + * |aValue|. Requires that |aValue| is non-zero. + */ template -class FloorLog2 { - public: - static uint_fast8_t compute(const T aValue) { - return 31u - CountLeadingZeroes32(aValue | 1); +inline uint_fast8_t FindMostSignificantBit(T aValue) { + static_assert(sizeof(T) <= 8); + static_assert(std::is_integral_v); + MOZ_ASSERT(aValue != 0); + // This casts to 32-bits + if constexpr (sizeof(T) <= 4) { + return 31u - CountLeadingZeroes32(aValue); } -}; - -template -class FloorLog2 { - public: - static uint_fast8_t compute(const T aValue) { - return 63u - CountLeadingZeroes64(aValue | 1); + // This doesn't + if constexpr (sizeof(T) == 8) { + return 63u - CountLeadingZeroes64(aValue); } -}; - -} // namespace detail +} /** * Compute the log of the greatest power of 2 less than or equal to |aValue|. @@ -343,7 +339,7 @@ class FloorLog2 { */ template inline constexpr uint_fast8_t FloorLog2(const T aValue) { - return detail::FloorLog2::compute(aValue); + return FindMostSignificantBit(aValue | 1); } /** A FloorLog2 variant that accepts only size_t. */ @@ -405,21 +401,6 @@ constexpr bool IsPowerOfTwo(T x) { return x && (x & (x - 1)) == 0; } -template -inline T Clamp(const T aValue, const T aMin, const T aMax) { - static_assert(std::is_integral_v, - "Clamp accepts only integral types, so that it doesn't have" - " to distinguish differently-signed zeroes (which users may" - " or may not care to distinguish, likely at a perf cost) or" - " to decide how to clamp NaN or a range with a NaN" - " endpoint."); - MOZ_ASSERT(aMin <= aMax); - - if (aValue <= aMin) return aMin; - if (aValue >= aMax) return aMax; - return aValue; -} - template inline uint_fast8_t CountTrailingZeroes(T aValue) { static_assert(sizeof(T) <= 8); diff --git a/src/third_party/mozjs/extract/mfbt/Maybe.h b/src/third_party/mozjs/extract/mfbt/Maybe.h index e938356b9fc..79d1c1052ca 100644 --- a/src/third_party/mozjs/extract/mfbt/Maybe.h +++ b/src/third_party/mozjs/extract/mfbt/Maybe.h @@ -249,7 +249,7 @@ struct MaybeStorage : MaybeStorageBase { protected: char mIsSome = false; // not bool -- guarantees minimal space consumption - MaybeStorage() = default; + constexpr MaybeStorage() = default; explicit MaybeStorage(const T& aVal) : MaybeStorageBase{aVal}, mIsSome{true} {} explicit MaybeStorage(T&& aVal) @@ -364,7 +364,7 @@ constexpr Maybe Some(T&& aValue); * functions |Some()| and |Nothing()|. */ template -class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe +class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_GSL_OWNER Maybe : private detail::MaybeStorage, public detail::Maybe_CopyMove_Enabler { template @@ -579,23 +579,24 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe constexpr const T* operator->() const; /* Returns the contents of this Maybe by ref. Unsafe unless |isSome()|. */ - constexpr T& ref() &; - constexpr const T& ref() const&; - constexpr T&& ref() &&; - constexpr const T&& ref() const&&; + constexpr T& ref() & MOZ_LIFETIME_BOUND; + constexpr const T& ref() const& MOZ_LIFETIME_BOUND; + constexpr T&& ref() && MOZ_LIFETIME_BOUND; + constexpr const T&& ref() const&& MOZ_LIFETIME_BOUND; /* * Returns the contents of this Maybe by ref. If |isNothing()|, returns * the default value provided. */ - constexpr T& refOr(T& aDefault) { + constexpr T& refOr(T& aDefault MOZ_LIFETIME_BOUND) MOZ_LIFETIME_BOUND { if (isSome()) { return ref(); } return aDefault; } - constexpr const T& refOr(const T& aDefault) const { + constexpr const T& refOr(const T& aDefault MOZ_LIFETIME_BOUND) const + MOZ_LIFETIME_BOUND { if (isSome()) { return ref(); } @@ -622,10 +623,10 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe return aFunc(); } - constexpr T& operator*() &; - constexpr const T& operator*() const&; - constexpr T&& operator*() &&; - constexpr const T&& operator*() const&&; + constexpr T& operator*() & MOZ_LIFETIME_BOUND; + constexpr const T& operator*() const& MOZ_LIFETIME_BOUND; + constexpr T&& operator*() && MOZ_LIFETIME_BOUND; + constexpr const T&& operator*() const&& MOZ_LIFETIME_BOUND; /* If |isSome()|, runs the provided function or functor on the contents of * this Maybe. */ diff --git a/src/third_party/mozjs/extract/mfbt/MaybeStorageBase.h b/src/third_party/mozjs/extract/mfbt/MaybeStorageBase.h index 2732d78d053..9469d427eb3 100644 --- a/src/third_party/mozjs/extract/mfbt/MaybeStorageBase.h +++ b/src/third_party/mozjs/extract/mfbt/MaybeStorageBase.h @@ -46,7 +46,7 @@ struct MaybeStorageBase { } mStorage; public: - MaybeStorageBase() = default; + constexpr MaybeStorageBase() = default; explicit MaybeStorageBase(const T& aVal) : mStorage{aVal} {} explicit MaybeStorageBase(T&& aVal) : mStorage{std::move(aVal)} {} template @@ -63,7 +63,7 @@ struct MaybeStorageBase { using NonConstT = std::remove_const_t; union Union { - constexpr Union() : dummy() {} + constexpr Union() : empty() {} constexpr explicit Union(const T& aVal) : val{aVal} {} constexpr explicit Union(T&& aVal) : val{std::move(aVal)} {} template @@ -71,7 +71,7 @@ struct MaybeStorageBase { : val{std::forward(aArgs)...} {} NonConstT val; - char dummy; + char empty; } mStorage; public: diff --git a/src/third_party/mozjs/extract/mfbt/NeverDestroyed.h b/src/third_party/mozjs/extract/mfbt/NeverDestroyed.h index fe3b366c694..dcb8a007cd8 100644 --- a/src/third_party/mozjs/extract/mfbt/NeverDestroyed.h +++ b/src/third_party/mozjs/extract/mfbt/NeverDestroyed.h @@ -26,8 +26,8 @@ namespace mozilla { // This type must only be used with static local members within a function, // which will be enforced by the clang static analysis. template -class MOZ_STATIC_LOCAL_CLASS MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS - NeverDestroyed { +class MOZ_STATIC_LOCAL_CLASS +MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS NeverDestroyed { public: static_assert( !std::is_trivially_destructible_v, diff --git a/src/third_party/mozjs/extract/mfbt/PodOperations.h b/src/third_party/mozjs/extract/mfbt/PodOperations.h index f4e5da4c799..3c10090eede 100644 --- a/src/third_party/mozjs/extract/mfbt/PodOperations.h +++ b/src/third_party/mozjs/extract/mfbt/PodOperations.h @@ -32,12 +32,16 @@ class NotNull; /** Set the contents of |aT| to 0. */ template static MOZ_ALWAYS_INLINE void PodZero(T* aT) { + static_assert(std::is_trivially_copyable_v, + "PodZero requires trivially copyable types"); memset(aT, 0, sizeof(T)); } /** Set the contents of |aNElem| elements starting at |aT| to 0. */ template static MOZ_ALWAYS_INLINE void PodZero(T* aT, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodZero requires trivially copyable types"); /* * This function is often called with 'aNElem' small; we use an inline loop * instead of calling 'memset' with a non-constant length. The compiler @@ -69,50 +73,50 @@ static void PodZero(T (&aT)[N], size_t aNElem) = delete; /** Set the contents of the array |aT| to zero. */ template static MOZ_ALWAYS_INLINE void PodArrayZero(T (&aT)[N]) { + static_assert(std::is_trivially_copyable_v, + "PodArrayZero requires trivially copyable types"); memset(aT, 0, N * sizeof(T)); } template static MOZ_ALWAYS_INLINE void PodArrayZero(Array& aArr) { + static_assert(std::is_trivially_copyable_v, + "PodArrayZero requires trivially copyable types"); memset(&aArr[0], 0, N * sizeof(T)); } -/** - * Assign |*aSrc| to |*aDst|. The locations must not be the same and must not - * overlap. - */ -template -static MOZ_ALWAYS_INLINE void PodAssign(T* aDst, const T* aSrc) { - MOZ_ASSERT(aDst + 1 <= aSrc || aSrc + 1 <= aDst, - "destination and source must not overlap"); - memcpy(reinterpret_cast(aDst), reinterpret_cast(aSrc), - sizeof(T)); -} - /** * Copy |aNElem| T elements from |aSrc| to |aDst|. The two memory ranges must * not overlap! */ template static MOZ_ALWAYS_INLINE void PodCopy(T* aDst, const T* aSrc, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodCopy requires trivially copyable types"); MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst, "destination and source must not overlap"); + +// Linux memcpy for small sizes seems slower than on other +// platforms. So we use a loop for small sizes there only. +// +// See Bug 1967062 for details. +#if defined(XP_LINUX) if (aNElem < 128) { - /* - * Avoid using operator= in this loop, as it may have been - * intentionally deleted by the POD type. - */ for (const T* srcend = aSrc + aNElem; aSrc < srcend; aSrc++, aDst++) { - PodAssign(aDst, aSrc); + *aDst = *aSrc; } - } else { - memcpy(aDst, aSrc, aNElem * sizeof(T)); + return; } +#endif + + memcpy(aDst, aSrc, aNElem * sizeof(T)); } template static MOZ_ALWAYS_INLINE void PodCopy(volatile T* aDst, const volatile T* aSrc, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodCopy requires trivially copyable types"); MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst, "destination and source must not overlap"); @@ -145,6 +149,8 @@ static MOZ_ALWAYS_INLINE void PodArrayCopy(T (&aDst)[N], const T (&aSrc)[N]) { */ template static MOZ_ALWAYS_INLINE void PodMove(T* aDst, const T* aSrc, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodMove requires trivially copyable types"); MOZ_ASSERT(aNElem <= SIZE_MAX / sizeof(T), "trying to move an impossible number of elements"); memmove(aDst, aSrc, aNElem * sizeof(T)); diff --git a/src/third_party/mozjs/extract/mfbt/Poison.cpp b/src/third_party/mozjs/extract/mfbt/Poison.cpp index d4ec08e7039..d70774e4087 100644 --- a/src/third_party/mozjs/extract/mfbt/Poison.cpp +++ b/src/third_party/mozjs/extract/mfbt/Poison.cpp @@ -198,8 +198,9 @@ static uintptr_t GetPoisonValue(uintptr_t aBase, uintptr_t aSize) { // specifically comes before libxul, so nearly all gecko code runs strictly // after this.) extern "C" { -uintptr_t gMozillaPoisonSize = GetDesiredRegionSize(); -uintptr_t gMozillaPoisonBase = ReservePoisonArea(gMozillaPoisonSize); -uintptr_t gMozillaPoisonValue = +MOZ_RUNINIT uintptr_t gMozillaPoisonSize = GetDesiredRegionSize(); +MOZ_RUNINIT uintptr_t gMozillaPoisonBase = + ReservePoisonArea(gMozillaPoisonSize); +MOZ_RUNINIT uintptr_t gMozillaPoisonValue = GetPoisonValue(gMozillaPoisonBase, gMozillaPoisonSize); } diff --git a/src/third_party/mozjs/extract/mfbt/RefCounted.cpp b/src/third_party/mozjs/extract/mfbt/RefCounted.cpp new file mode 100644 index 00000000000..fe43f610063 --- /dev/null +++ b/src/third_party/mozjs/extract/mfbt/RefCounted.cpp @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/RefCounted.h" + +namespace mozilla::detail { + +#ifdef MOZ_REFCOUNTED_LEAK_CHECKING +MFBT_DATA LogAddRefFunc gLogAddRefFunc = nullptr; +MFBT_DATA LogReleaseFunc gLogReleaseFunc = nullptr; +MFBT_DATA size_t gNumStaticCtors = 0; +MFBT_DATA const char* gLastStaticCtorTypeName = nullptr; + +MFBT_API void RefCountLogger::SetLeakCheckingFunctions( + LogAddRefFunc aLogAddRefFunc, LogReleaseFunc aLogReleaseFunc) { + if (gNumStaticCtors > 0) { + // RefCountLogger was used before this point. Print a warning, similar to + // ASSERT_ACTIVITY_IS_LEGAL. We do this here because SpiderMonkey standalone + // and shell builds don't call this function and we don't want to report any + // warnings in that case. + fprintf(stderr, + "RefCounted objects addrefed/released (static ctor?) total: %zu, " + "last type: %s\n", + gNumStaticCtors, gLastStaticCtorTypeName); + gNumStaticCtors = 0; + gLastStaticCtorTypeName = nullptr; + } + gLogAddRefFunc = aLogAddRefFunc; + gLogReleaseFunc = aLogReleaseFunc; +} +#endif // MOZ_REFCOUNTED_LEAK_CHECKING + +} // namespace mozilla::detail diff --git a/src/third_party/mozjs/extract/mfbt/RefCounted.h b/src/third_party/mozjs/extract/mfbt/RefCounted.h index 5c083f3524f..a0686919822 100644 --- a/src/third_party/mozjs/extract/mfbt/RefCounted.h +++ b/src/third_party/mozjs/extract/mfbt/RefCounted.h @@ -24,11 +24,7 @@ # include #endif // __wasi__ -#if defined(MOZILLA_INTERNAL_API) -# include "nsXPCOM.h" -#endif - -#if defined(MOZILLA_INTERNAL_API) && defined(NS_BUILD_REFCNT_LOGGING) +#if defined(MOZ_SUPPORT_LEAKCHECKING) && defined(NS_BUILD_REFCNT_LOGGING) # define MOZ_REFCOUNTED_LEAK_CHECKING #endif @@ -58,13 +54,26 @@ namespace mozilla { * Note that when deriving from RefCounted or AtomicRefCounted, you * should add MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public * section of your class, where ClassName is the name of your class. - * - * Note: SpiderMonkey should use js::RefCounted instead since that type - * will use appropriate js_delete and also not break ref-count logging. */ namespace detail { const MozRefCountType DEAD = 0xffffdead; +#ifdef MOZ_REFCOUNTED_LEAK_CHECKING +// When this header is included in SpiderMonkey code, NS_LogAddRef and +// NS_LogRelease are not available. To work around this, we call these +// functions through a function pointer set by SetLeakCheckingFunctions. +// Note: these are globals because GCC on Linux reports undefined-reference +// errors when they're static members of the RefCountLogger class. +using LogAddRefFunc = void (*)(void* aPtr, MozRefCountType aNewRefCnt, + const char* aTypeName, uint32_t aClassSize); +using LogReleaseFunc = void (*)(void* aPtr, MozRefCountType aNewRefCnt, + const char* aTypeName); +extern MFBT_DATA LogAddRefFunc gLogAddRefFunc; +extern MFBT_DATA LogReleaseFunc gLogReleaseFunc; +extern MFBT_DATA size_t gNumStaticCtors; +extern MFBT_DATA const char* gLastStaticCtorTypeName; +#endif + // When building code that gets compiled into Gecko, try to use the // trace-refcount leak logging facilities. class RefCountLogger { @@ -78,10 +87,20 @@ class RefCountLogger { const void* pointer = aPointer; const char* typeName = aPointer->typeName(); uint32_t typeSize = aPointer->typeSize(); - NS_LogAddRef(const_cast(pointer), aRefCount, typeName, typeSize); + if (gLogAddRefFunc) { + gLogAddRefFunc(const_cast(pointer), aRefCount, typeName, typeSize); + } else { + gNumStaticCtors++; + gLastStaticCtorTypeName = typeName; + } #endif } +#ifdef MOZ_REFCOUNTED_LEAK_CHECKING + static MFBT_API void SetLeakCheckingFunctions(LogAddRefFunc aLogAddRefFunc, + LogReleaseFunc aLogReleaseFunc); +#endif + // Created by `RefCounted`-like classes to log a successful Release call in // the Gecko leak-logging system. The constructor should be invoked before the // refcount is decremented to avoid invoking `typeName()` with a zero @@ -100,7 +119,12 @@ class RefCountLogger { void logRelease(MozRefCountType aRefCount) { #ifdef MOZ_REFCOUNTED_LEAK_CHECKING MOZ_ASSERT(aRefCount != DEAD); - NS_LogRelease(const_cast(mPointer), aRefCount, mTypeName); + if (gLogReleaseFunc) { + gLogReleaseFunc(const_cast(mPointer), aRefCount, mTypeName); + } else { + gNumStaticCtors++; + gLastStaticCtorTypeName = mTypeName; + } #endif } diff --git a/src/third_party/mozjs/extract/mfbt/RefPtr.h b/src/third_party/mozjs/extract/mfbt/RefPtr.h index 27f22356bab..80257d8bd64 100644 --- a/src/third_party/mozjs/extract/mfbt/RefPtr.h +++ b/src/third_party/mozjs/extract/mfbt/RefPtr.h @@ -83,7 +83,7 @@ class MOZ_IS_REFPTR RefPtr { // Constructors - RefPtr() + constexpr RefPtr() : mRawPtr(nullptr) // default constructor {} @@ -431,7 +431,7 @@ inline void ImplCycleCollectionUnlink(RefPtr& aField) { template inline void ImplCycleCollectionTraverse( - nsCycleCollectionTraversalCallback& aCallback, RefPtr& aField, + nsCycleCollectionTraversalCallback& aCallback, const RefPtr& aField, const char* aName, uint32_t aFlags = 0) { CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); } diff --git a/src/third_party/mozjs/extract/mfbt/SegmentedVector.h b/src/third_party/mozjs/extract/mfbt/SegmentedVector.h index c22c3e8d1f5..0198d81e9e6 100644 --- a/src/third_party/mozjs/extract/mfbt/SegmentedVector.h +++ b/src/third_party/mozjs/extract/mfbt/SegmentedVector.h @@ -224,10 +224,8 @@ class SegmentedVector : private AllocPolicy { } // Equivalent to calling |PopLast| |aNumElements| times, but potentially - // more efficient. + // more efficient. It is safe to call this even when aNumElements > Length(). void PopLastN(uint32_t aNumElements) { - MOZ_ASSERT(aNumElements <= Length()); - Segment* last; // Pop full segments for as long as we can. Note that this loop diff --git a/src/third_party/mozjs/extract/mfbt/Span.h b/src/third_party/mozjs/extract/mfbt/Span.h index ca754f3810f..132349bf7e4 100644 --- a/src/third_party/mozjs/extract/mfbt/Span.h +++ b/src/third_party/mozjs/extract/mfbt/Span.h @@ -365,7 +365,7 @@ class extent_type { * Subspan etc. */ template -class Span { +class MOZ_GSL_POINTER Span { public: // constants and types using element_type = ElementType; @@ -405,12 +405,14 @@ class Span { /** * Constructor for pointer and length. */ - constexpr Span(pointer aPtr, index_type aLength) : storage_(aPtr, aLength) {} + constexpr Span(pointer aPtr MOZ_LIFETIME_BOUND, index_type aLength) + : storage_(aPtr, aLength) {} /** * Constructor for start pointer and pointer past end. */ - constexpr Span(pointer aStartPtr, pointer aEndPtr) + constexpr Span(pointer aStartPtr MOZ_LIFETIME_BOUND, + pointer aEndPtr MOZ_LIFETIME_BOUND) : storage_(aStartPtr, std::distance(aStartPtr, aEndPtr)) {} /** @@ -438,7 +440,7 @@ class Span { * Constructor for C array. */ template - constexpr MOZ_IMPLICIT Span(element_type (&aArr)[N]) + constexpr MOZ_IMPLICIT Span(element_type (&aArr MOZ_LIFETIME_BOUND)[N]) : storage_(&aArr[0], span_details::extent_type()) {} // Implicit constructors for char* and char16_t* pointers are deleted in order @@ -463,7 +465,8 @@ class Span { */ template > - constexpr MOZ_IMPLICIT Span(std::array& aArr) + constexpr MOZ_IMPLICIT Span( + std::array& aArr MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -471,7 +474,8 @@ class Span { */ template constexpr MOZ_IMPLICIT Span( - const std::array, N>& aArr) + const std::array, N>& aArr + MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -479,7 +483,8 @@ class Span { */ template > - constexpr MOZ_IMPLICIT Span(mozilla::Array& aArr) + constexpr MOZ_IMPLICIT Span( + mozilla::Array& aArr MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -487,7 +492,8 @@ class Span { */ template constexpr MOZ_IMPLICIT Span( - const mozilla::Array, N>& aArr) + const mozilla::Array, N>& aArr + MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -496,15 +502,17 @@ class Span { template > constexpr MOZ_IMPLICIT Span( - mozilla::EnumeratedArray& aArr) + mozilla::EnumeratedArray& aArr + MOZ_LIFETIME_BOUND) : storage_(&aArr[Enum(0)], span_details::extent_type()) {} /** * Constructor for const mozilla::EnumeratedArray. */ template - constexpr MOZ_IMPLICIT Span(const mozilla::EnumeratedArray< - Enum, std::remove_const_t, N>& aArr) + constexpr MOZ_IMPLICIT Span( + const mozilla::EnumeratedArray, + N>& aArr MOZ_LIFETIME_BOUND) : storage_(&aArr[Enum(0)], span_details::extent_type()) {} /** @@ -512,7 +520,8 @@ class Span { */ template , class DeleterType> - constexpr Span(const mozilla::UniquePtr& aPtr, + constexpr Span(const mozilla::UniquePtr& aPtr + MOZ_LIFETIME_BOUND, index_type aLength) : storage_(aPtr.get(), aLength) {} diff --git a/src/third_party/mozjs/extract/mfbt/StringBuffer.h b/src/third_party/mozjs/extract/mfbt/StringBuffer.h index 6927b54dfc2..eb75d5b3611 100644 --- a/src/third_party/mozjs/extract/mfbt/StringBuffer.h +++ b/src/third_party/mozjs/extract/mfbt/StringBuffer.h @@ -9,10 +9,13 @@ #include #include +#include "mozilla/CheckedInt.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Assertions.h" #include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Maybe.h" #include "mozilla/RefCounted.h" +#include "mozmemory.h" namespace mozilla { @@ -50,21 +53,55 @@ class StringBuffer { * * @return new string buffer or null if out of memory. */ - static already_AddRefed Alloc(size_t aSize) { + static already_AddRefed Alloc( + size_t aSize, mozilla::Maybe aArena = mozilla::Nothing()) { MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed"); MOZ_ASSERT(sizeof(StringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(StringBuffer) + aSize > aSize, "mStorageSize will truncate"); - auto* hdr = (StringBuffer*)malloc(sizeof(StringBuffer) + aSize); - if (hdr) { - hdr->mRefCount = 1; - hdr->mStorageSize = aSize; - detail::RefCountLogger::logAddRef(hdr, 1); + size_t bytes = sizeof(StringBuffer) + aSize; + //MONGODB Modification: We must use our custom arena_malloc function instead of the mozJS one. + void* hdr = aArena ? js_arena_malloc(*aArena, bytes) : malloc(bytes); + if (!hdr) { + return nullptr; } + return ConstructInPlace(hdr, aSize); + } + + /** + * Like Alloc, but use aBuffer instead of allocating a new buffer. This can + * be used when the caller already has a malloced buffer of the right size and + * allocating a new one would be too expensive. + * + * aStorageSize must be the string's length in bytes (including the null + * terminator). The caller must initialize all of these bytes either before or + * after calling this function. + * + * @return the new StringBuffer header. + */ + static already_AddRefed ConstructInPlace(void* aBuffer, + size_t aStorageSize) { + MOZ_ASSERT(aBuffer, "must have a valid buffer"); + MOZ_ASSERT(aStorageSize != 0, "zero capacity StringBuffer not allowed"); + auto* hdr = new (aBuffer) StringBuffer(); + hdr->mRefCount = 1; + hdr->mStorageSize = aStorageSize; + detail::RefCountLogger::logAddRef(hdr, 1); return already_AddRefed(hdr); } + /** + * Returns true if (aLength + 1) * sizeof(CharT) is a valid allocation size + * for Alloc. Adds +1 to aLength for the null-terminator. + */ + template + static constexpr bool IsValidLength(size_t aLength) { + auto checkedSize = + (CheckedUint32(aLength) + 1) * sizeof(CharT) + sizeof(StringBuffer); + return checkedSize.isValid(); + } + /** * Returns a string buffer initialized with the given string on it, or null on * OOM. @@ -79,6 +116,10 @@ class StringBuffer { size_t aLength) { return DoCreate(aData, aLength); } + static already_AddRefed Create(const unsigned char* aData, + size_t aLength) { + return DoCreate(aData, aLength); + } /** * Resizes the given string buffer to the specified storage size. This @@ -91,7 +132,9 @@ class StringBuffer { * * @see IsReadonly */ - static StringBuffer* Realloc(StringBuffer* aHdr, size_t aSize) { + static StringBuffer* Realloc( + StringBuffer* aHdr, size_t aSize, + mozilla::Maybe aArena = mozilla::Nothing()) { MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed"); MOZ_ASSERT(sizeof(StringBuffer) + aSize <= size_t(uint32_t(-1)) && sizeof(StringBuffer) + aSize > aSize, @@ -108,7 +151,10 @@ class StringBuffer { logger.logRelease(0); } - aHdr = (StringBuffer*)realloc(aHdr, sizeof(StringBuffer) + aSize); + size_t bytes = sizeof(StringBuffer) + aSize; + //MONGODB Modification: We must use our custom arena_realloc function instead of the mozJS one. + aHdr = aArena ? (StringBuffer*)js_arena_realloc(*aArena, aHdr, bytes) + : (StringBuffer*)realloc(aHdr, bytes); if (aHdr) { detail::RefCountLogger::logAddRef(aHdr, 1); aHdr->mStorageSize = aSize; @@ -170,6 +216,14 @@ class StringBuffer { */ uint32_t StorageSize() const { return mStorageSize; } + /** + * This function returns the allocation size of a string buffer in bytes. + * This includes the size of the StringBuffer header. + */ + uint32_t AllocationSize() const { + return sizeof(StringBuffer) + StorageSize(); + } + /** * If this method returns false, then the caller can be sure that their * reference to the string buffer is the only reference to the string @@ -210,6 +264,21 @@ class StringBuffer { #endif } + /** + * Alias for IsReadOnly. + */ + bool HasMultipleReferences() const { return IsReadonly(); } + +#ifdef DEBUG + /** + * Returns the buffer's reference count. This is only exposed for logging and + * testing purposes. + */ + uint32_t RefCount() const { + return mRefCount.load(std::memory_order_acquire); + } +#endif + /** * This measures the size only if the StringBuffer is unshared. */ diff --git a/src/third_party/mozjs/extract/mfbt/Try.h b/src/third_party/mozjs/extract/mfbt/Try.h index a650a33ea27..fa6ec09fb77 100644 --- a/src/third_party/mozjs/extract/mfbt/Try.h +++ b/src/third_party/mozjs/extract/mfbt/Try.h @@ -10,10 +10,41 @@ #include "mozilla/Result.h" /** - * MOZ_TRY(expr) is the C++ equivalent of Rust's `try!(expr);`. First, it - * evaluates expr, which must produce a Result value. On success, it - * discards the result altogether. On error, it immediately returns an error - * Result from the enclosing function. + * MOZ_TRY(expr) is the C++ equivalent of Rust's `target = try!(expr);`, using + * gcc's statement expressions [0]. First, it evaluates expr, which must produce + * a Result value. On success, the result's success value is 'returned' as + * rvalue. On error, immediately returns the error result. This pattern allows + * to directly assign the success value: + * + * ``` + * SuccessValue val = MOZ_TRY(Func()); + * ``` + * + * Where `Func()` returns a `Result` and is called in a + * function that returns `Result`. + * + * [0]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html + */ +#ifndef _MSC_VER + +#define MOZ_TRY(expr) \ + __extension__({ \ + auto mozTryVarTempResult = ::mozilla::ToResult(expr); \ + if (MOZ_UNLIKELY(mozTryVarTempResult.isErr())) { \ + return mozTryVarTempResult.propagateErr(); \ + } \ + mozTryVarTempResult.unwrap(); \ + }) + +#else + +/** + * MONGODB MODIFICATION: statement expressions are a gcc extension + * unsupported by MSVC, reimplement with standard C++. + * + * This implementation doesn't return the result of expr, + * so MOZ_TRY_VAR should be used instead. If this is necessary + * behavior, consider implementing using a lambda */ #define MOZ_TRY(expr) \ do { \ @@ -23,12 +54,34 @@ } \ } while (0) +#endif // _MSC_VER + /** * MOZ_TRY_VAR(target, expr) is the C++ equivalent of Rust's `target = * try!(expr);`. First, it evaluates expr, which must produce a Result value. On * success, the result's success value is assigned to target. On error, * immediately returns the error result. |target| must be an lvalue. + * + * This macro is obsolete and its usages should be replaced with `MOZ_TRY`. */ +#ifndef _MSC_VER + +#define MOZ_TRY_VAR(target, expr) (target) = MOZ_TRY(expr); + +#else + +/** + * MONGODB MODIFICATION: statement expressions are a gcc extension + * unsupported by MSVC, reimplement with standard C++. + */ +#define MOZ_TRY(expr) \ + do { \ + auto mozTryTempResult_ = ::mozilla::ToResult(expr); \ + if (MOZ_UNLIKELY(mozTryTempResult_.isErr())) { \ + return mozTryTempResult_.propagateErr(); \ + } \ + } while (0) + #define MOZ_TRY_VAR(target, expr) \ do { \ auto mozTryVarTempResult_ = (expr); \ @@ -38,4 +91,6 @@ (target) = mozTryVarTempResult_.unwrap(); \ } while (0) +#endif // _MSC_VER + #endif // mozilla_Try_h diff --git a/src/third_party/mozjs/extract/mfbt/TsanOptions.h b/src/third_party/mozjs/extract/mfbt/TsanOptions.h deleted file mode 100644 index f276251038b..00000000000 --- a/src/third_party/mozjs/extract/mfbt/TsanOptions.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Default options for ThreadSanitizer. */ - -#ifndef mozilla_TsanOptions_h -#define mozilla_TsanOptions_h - -#include "mozilla/Compiler.h" - -#ifndef _MSC_VER // Not supported by clang-cl yet - -// -// When running with ThreadSanitizer, we need to explicitly set some -// options specific to our codebase to prevent errors during runtime. -// To override these, set the TSAN_OPTIONS environment variable. -// -// Currently, these are: -// -// abort_on_error=1 - Causes TSan to abort instead of using exit(). -// halt_on_error=1 - Causes TSan to stop on the first race detected. -// -// report_signal_unsafe=0 - Required to avoid TSan deadlocks when -// receiving external signals (e.g. SIGINT manually on console). -// -// allocator_may_return_null=1 - Tell TSan to return NULL when an allocation -// fails instead of aborting the program. This allows us to handle failing -// allocations the same way we would handle them with a regular allocator and -// also uncovers potential bugs that might occur in these situations. -// -extern "C" const char* __tsan_default_options() { - return "halt_on_error=1:abort_on_error=1:report_signal_unsafe=0" - ":allocator_may_return_null=1"; -} - -// These are default suppressions for external libraries that probably -// every application would want to include if it potentially loads external -// libraries like GTK/X and hence their dependencies. -# define MOZ_TSAN_DEFAULT_EXTLIB_SUPPRESSIONS \ - "called_from_lib:libappmenu-gtk3-parser\n" \ - "called_from_lib:libatk-1\n" \ - "called_from_lib:libcairo.so\n" \ - "called_from_lib:libcairo-gobject\n" \ - "called_from_lib:libdconfsettings\n" \ - "called_from_lib:libEGL_nvidia\n" \ - "called_from_lib:libfontconfig.so\n" \ - "called_from_lib:libfontconfig1\n" \ - "called_from_lib:libgdk-3\n" \ - "called_from_lib:libgdk_pixbuf\n" \ - "called_from_lib:libgdk-x11\n" \ - "called_from_lib:libgio-2\n" \ - "called_from_lib:libglib-1\n" \ - "called_from_lib:libglib-2\n" \ - "called_from_lib:libgobject\n" \ - "called_from_lib:libgtk-3\n" \ - "called_from_lib:libgtk-x11\n" \ - "called_from_lib:libgvfscommon\n" \ - "called_from_lib:libgvfsdbus\n" \ - "called_from_lib:libibus-1\n" \ - "called_from_lib:libnvidia-eglcore\n" \ - "called_from_lib:libnvidia-glsi\n" \ - "called_from_lib:libogg.so\n" \ - "called_from_lib:libpango-1\n" \ - "called_from_lib:libpangocairo\n" \ - "called_from_lib:libpangoft2\n" \ - "called_from_lib:pango-basic-fc\n" \ - "called_from_lib:libpixman-1\n" \ - "called_from_lib:libpulse.so\n" \ - "called_from_lib:libpulsecommon\n" \ - "called_from_lib:libsecret-1\n" \ - "called_from_lib:libunity-gtk3-parser\n" \ - "called_from_lib:libvorbis.so\n" \ - "called_from_lib:libvorbisfile\n" \ - "called_from_lib:libwayland-client\n" \ - "called_from_lib:libX11.so\n" \ - "called_from_lib:libX11-xcb\n" \ - "called_from_lib:libXau\n" \ - "called_from_lib:libxcb.so\n" \ - "called_from_lib:libXcomposite\n" \ - "called_from_lib:libXcursor\n" \ - "called_from_lib:libXdamage\n" \ - "called_from_lib:libXdmcp\n" \ - "called_from_lib:libXext\n" \ - "called_from_lib:libXfixes\n" \ - "called_from_lib:libXi.so\n" \ - "called_from_lib:libXrandr\n" \ - "called_from_lib:libXrender\n" \ - "called_from_lib:libXss\n" - -#endif // _MSC_VER - -#endif /* mozilla_TsanOptions_h */ diff --git a/src/third_party/mozjs/extract/mfbt/UniquePtr.h b/src/third_party/mozjs/extract/mfbt/UniquePtr.h index 9b51e58db31..b7b41520366 100644 --- a/src/third_party/mozjs/extract/mfbt/UniquePtr.h +++ b/src/third_party/mozjs/extract/mfbt/UniquePtr.h @@ -187,7 +187,7 @@ struct PointerType { * |UniquePtr&&| argument. */ template -class UniquePtr { +class MOZ_GSL_OWNER UniquePtr { public: typedef T ElementType; typedef D DeleterType; @@ -214,12 +214,13 @@ class UniquePtr { /** * Construct a UniquePtr containing |aPtr|. */ - explicit UniquePtr(Pointer aPtr) : mTuple(aPtr, DeleterType()) { + explicit UniquePtr(Pointer aPtr MOZ_LIFETIME_BOUND) + : mTuple(aPtr, DeleterType()) { static_assert(!std::is_pointer_v, "must provide a deleter instance"); static_assert(!std::is_reference_v, "must provide a deleter instance"); } - UniquePtr(Pointer aPtr, + UniquePtr(Pointer aPtr MOZ_LIFETIME_BOUND, std::conditional_t, D, const D&> aD1) : mTuple(aPtr, aD1) {} @@ -273,21 +274,21 @@ class UniquePtr { return *this; } - std::add_lvalue_reference_t operator*() const { + std::add_lvalue_reference_t operator*() const MOZ_LIFETIME_BOUND { MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr with *"); return *get(); } - Pointer operator->() const { + Pointer operator->() const MOZ_LIFETIME_BOUND { MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr with ->"); return get(); } explicit operator bool() const { return get() != nullptr; } - Pointer get() const { return ptr(); } + Pointer get() const MOZ_LIFETIME_BOUND { return ptr(); } - DeleterType& get_deleter() { return del(); } - const DeleterType& get_deleter() const { return del(); } + DeleterType& get_deleter() MOZ_LIFETIME_BOUND { return del(); } + const DeleterType& get_deleter() const MOZ_LIFETIME_BOUND { return del(); } [[nodiscard]] Pointer release() { Pointer p = ptr(); diff --git a/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.cpp b/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.cpp index 229c9421960..3b509fb9e0a 100644 --- a/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.cpp +++ b/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.cpp @@ -32,4 +32,25 @@ void FileHandleDeleter::operator()(FileHandleHelper aHelper) { } } // namespace detail + +#ifndef __wasm__ +UniqueFileHandle DuplicateFileHandle(detail::FileHandleType aFile) { +# ifdef XP_WIN + if (aFile != INVALID_HANDLE_VALUE && aFile != NULL) { + HANDLE handle; + HANDLE currentProcess = ::GetCurrentProcess(); + if (::DuplicateHandle(currentProcess, aFile, currentProcess, &handle, 0, + false, DUPLICATE_SAME_ACCESS)) { + return UniqueFileHandle{handle}; + } + } +# else + if (aFile != -1) { + return UniqueFileHandle{dup(aFile)}; + } +# endif + return nullptr; +} +#endif + } // namespace mozilla diff --git a/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.h b/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.h index 2679440e501..565d4bf1fce 100644 --- a/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.h +++ b/src/third_party/mozjs/extract/mfbt/UniquePtrExtensions.h @@ -93,28 +93,29 @@ struct FreePolicy { void operator()(const void* ptr) { free(const_cast(ptr)); } }; -#if defined(XP_WIN) +#if !defined(RUST_BINDGEN) +# if defined(XP_WIN) // Can't include to get the actual definition of HANDLE // because of namespace pollution. typedef void* FileHandleType; -#elif defined(XP_UNIX) +# elif defined(XP_UNIX) typedef int FileHandleType; -#else -# error "Unsupported OS?" -#endif +# else +# error "Unsupported OS?" +# endif struct FileHandleHelper { MOZ_IMPLICIT FileHandleHelper(FileHandleType aHandle) : mHandle(aHandle) { -#if defined(XP_UNIX) && (defined(DEBUG) || defined(FUZZING)) +# if defined(XP_UNIX) && (defined(DEBUG) || defined(FUZZING)) MOZ_RELEASE_ASSERT(aHandle == kInvalidHandle || aHandle > 2); -#endif +# endif } MOZ_IMPLICIT constexpr FileHandleHelper(std::nullptr_t) : mHandle(kInvalidHandle) {} bool operator!=(std::nullptr_t) const { -#ifdef XP_WIN +# ifdef XP_WIN // Windows uses both nullptr and INVALID_HANDLE_VALUE (-1 cast to // HANDLE) in different situations, but nullptr is more reliably // null while -1 is also valid input to some calls that take @@ -123,20 +124,20 @@ struct FileHandleHelper { if (mHandle == (void*)-1) { return false; } -#endif +# endif return mHandle != kInvalidHandle; } operator FileHandleType() const { return mHandle; } -#ifdef XP_WIN +# ifdef XP_WIN // NSPR uses an integer type for PROsfd, so this conversion is // provided for working with it without needing reinterpret casts // everywhere. operator std::intptr_t() const { return reinterpret_cast(mHandle); } -#endif +# endif // When there's only one user-defined conversion operator, the // compiler will use that to derive equality, but that doesn't work @@ -148,13 +149,13 @@ struct FileHandleHelper { private: FileHandleType mHandle; -#ifdef XP_WIN +# ifdef XP_WIN // See above for why this is nullptr. (Also, INVALID_HANDLE_VALUE // can't be expressed as a constexpr.) static constexpr FileHandleType kInvalidHandle = nullptr; -#else +# else static constexpr FileHandleType kInvalidHandle = -1; -#endif +# endif }; struct FileHandleDeleter { @@ -162,6 +163,7 @@ struct FileHandleDeleter { using receiver = FileHandleType; MFBT_API void operator()(FileHandleHelper aHelper); }; +#endif #if defined(XP_DARWIN) && !defined(RUST_BINDGEN) struct MachPortHelper { @@ -215,11 +217,21 @@ struct MachPortSetDeleter { template using UniqueFreePtr = UniquePtr>; +#if !defined(RUST_BINDGEN) // A RAII class for the OS construct used for open files and similar // objects: a file descriptor on Unix or a handle on Windows. using UniqueFileHandle = UniquePtr; +# ifndef __wasm__ +// WASI does not have `dup` +MFBT_API UniqueFileHandle DuplicateFileHandle(detail::FileHandleType aFile); +inline UniqueFileHandle DuplicateFileHandle(const UniqueFileHandle& aFile) { + return DuplicateFileHandle(aFile.get()); +} +# endif +#endif + #if defined(XP_DARWIN) && !defined(RUST_BINDGEN) // A RAII class for a Mach port that names a send right. using UniqueMachSendRight = diff --git a/src/third_party/mozjs/extract/mfbt/Utf8.cpp b/src/third_party/mozjs/extract/mfbt/Utf8.cpp index 143d01f768d..f8e02790aea 100644 --- a/src/third_party/mozjs/extract/mfbt/Utf8.cpp +++ b/src/third_party/mozjs/extract/mfbt/Utf8.cpp @@ -3,6 +3,8 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#define MOZ_PRETEND_NO_JSRUST 1 + #include "mozilla/Latin1.h" #include "mozilla/Maybe.h" #include "mozilla/TextUtils.h" @@ -39,8 +41,8 @@ MFBT_API bool mozilla::detail::IsValidUtf8(const void* aCodeUnits, } #if !MOZ_HAS_JSRUST() -#include // for std::shared_ptr -#include // for UConverter +# include // for std::shared_ptr +# include // for UConverter std::tuple _getUConverter() { static thread_local UErrorCode uConverterErr = U_ZERO_ERROR; @@ -105,7 +107,7 @@ std::tuple mozilla::ConvertUtf16toUtf8Partial( break; } return std::make_tuple(static_cast(srcPtr - srcOrigPtr), - static_cast(dstPtr - dstOrigPtr)); + static_cast(dstPtr - dstOrigPtr)); } else { // We do not need to handle it, as the problematic character will be // replaced with a REPLACEMENT CHARACTER. @@ -121,7 +123,7 @@ std::tuple mozilla::ConvertUtf16toUtf8Partial( } return std::make_tuple(static_cast(srcPtr - srcOrigPtr), - static_cast(dstPtr - dstOrigPtr)); + static_cast(dstPtr - dstOrigPtr)); } size_t mozilla::ConvertUtf16toUtf8(mozilla::Span aSource, diff --git a/src/third_party/mozjs/extract/mfbt/Variant.h b/src/third_party/mozjs/extract/mfbt/Variant.h index d1db3a2cc92..848499f81d9 100644 --- a/src/third_party/mozjs/extract/mfbt/Variant.h +++ b/src/third_party/mozjs/extract/mfbt/Variant.h @@ -567,7 +567,8 @@ struct VariantIndex { * instead. */ template -class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { +class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS +MOZ_NON_PARAM MOZ_GSL_OWNER Variant { friend struct IPC::ParamTraits>; friend struct mozilla::ipc::IPDLParamTraits>; @@ -739,7 +740,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Mutable lvalue-reference. */ template - T& as() & { + T& as() & MOZ_LIFETIME_BOUND { static_assert( detail::SelectVariantType::count == 1, "provided a type not uniquely found in this Variant's type list"); @@ -748,7 +749,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - typename detail::Nth::Type& as() & { + typename detail::Nth::Type& as() & MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -757,7 +758,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Immutable const lvalue-reference. */ template - const T& as() const& { + const T& as() const& MOZ_LIFETIME_BOUND { static_assert(detail::SelectVariantType::count == 1, "provided a type not found in this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -765,7 +766,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - const typename detail::Nth::Type& as() const& { + const typename detail::Nth::Type& as() const& MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -774,7 +775,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Mutable rvalue-reference. */ template - T&& as() && { + T&& as() && MOZ_LIFETIME_BOUND { static_assert( detail::SelectVariantType::count == 1, "provided a type not uniquely found in this Variant's type list"); @@ -783,7 +784,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - typename detail::Nth::Type&& as() && { + typename detail::Nth::Type&& as() && MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -793,7 +794,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Immutable const rvalue-reference. */ template - const T&& as() const&& { + const T&& as() const&& MOZ_LIFETIME_BOUND { static_assert(detail::SelectVariantType::count == 1, "provided a type not found in this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -801,7 +802,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - const typename detail::Nth::Type&& as() const&& { + const typename detail::Nth::Type&& as() const&& MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); diff --git a/src/third_party/mozjs/extract/mfbt/Vector.h b/src/third_party/mozjs/extract/mfbt/Vector.h index 380e2725486..84e5845de66 100644 --- a/src/third_party/mozjs/extract/mfbt/Vector.h +++ b/src/third_party/mozjs/extract/mfbt/Vector.h @@ -339,7 +339,7 @@ struct VectorTesting; */ template -class MOZ_NON_PARAM Vector final : private AllocPolicy { +class MOZ_NON_PARAM MOZ_GSL_OWNER Vector final : private AllocPolicy { /* utilities */ static constexpr bool kElemIsPod = std::is_trivial_v && std::is_standard_layout_v; diff --git a/src/third_party/mozjs/extract/mfbt/WasiAtomic.h b/src/third_party/mozjs/extract/mfbt/WasiAtomic.h index ba222e91c0c..9753257ba40 100644 --- a/src/third_party/mozjs/extract/mfbt/WasiAtomic.h +++ b/src/third_party/mozjs/extract/mfbt/WasiAtomic.h @@ -7,12 +7,13 @@ #ifndef mozilla_WasiAtomic_h #define mozilla_WasiAtomic_h +#include // For _LIBCPP_VERSION and ptrdiff_t + // Clang >= 14 supports for wasm targets. #if _LIBCPP_VERSION >= 14000 # include #else -# include // For ptrdiff_t # include // WASI doesn't support and we use it as single-threaded for now. diff --git a/src/third_party/mozjs/extract/mfbt/WrappingOperations.h b/src/third_party/mozjs/extract/mfbt/WrappingOperations.h index bd67ac34f18..99d28f68f41 100644 --- a/src/third_party/mozjs/extract/mfbt/WrappingOperations.h +++ b/src/third_party/mozjs/extract/mfbt/WrappingOperations.h @@ -17,8 +17,9 @@ * 2) They implement this functionality *safely*, without invoking signed * integer overflow that has undefined behavior in C++. * 3) They play nice with compiler-based integer-overflow sanitizers (see - * build/autoconf/sanitize.m4), that in appropriately configured builds - * verify at runtime that integral arithmetic doesn't overflow. + * build/moz.configure/toolchain.configure), that in appropriately + * configured builds verify at runtime that integral arithmetic doesn't + * overflow. */ #ifndef mozilla_WrappingOperations_h diff --git a/src/third_party/mozjs/extract/mfbt/lz4/LICENSE b/src/third_party/mozjs/extract/mfbt/lz4/LICENSE deleted file mode 100644 index 488491695a6..00000000000 --- a/src/third_party/mozjs/extract/mfbt/lz4/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -LZ4 Library -Copyright (c) 2011-2020, Yann Collet -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/third_party/mozjs/extract/mfbt/lz4/README.md b/src/third_party/mozjs/extract/mfbt/lz4/README.md deleted file mode 100644 index 08d1cef2bf8..00000000000 --- a/src/third_party/mozjs/extract/mfbt/lz4/README.md +++ /dev/null @@ -1,169 +0,0 @@ -LZ4 - Library Files -================================ - -The `/lib` directory contains many files, but depending on project's objectives, -not all of them are required. -Limited systems may want to reduce the nb of source files to include -as a way to reduce binary size and dependencies. - -Capabilities are added at the "level" granularity, detailed below. - -#### Level 1 : Minimal LZ4 build - -The minimum required is **`lz4.c`** and **`lz4.h`**, -which provides the fast compression and decompression algorithms. -They generate and decode data using the [LZ4 block format]. - - -#### Level 2 : High Compression variant - -For more compression ratio at the cost of compression speed, -the High Compression variant called **lz4hc** is available. -Add files **`lz4hc.c`** and **`lz4hc.h`**. -This variant also compresses data using the [LZ4 block format], -and depends on regular `lib/lz4.*` source files. - - -#### Level 3 : Frame support, for interoperability - -In order to produce compressed data compatible with `lz4` command line utility, -it's necessary to use the [official interoperable frame format]. -This format is generated and decoded automatically by the **lz4frame** library. -Its public API is described in `lib/lz4frame.h`. -In order to work properly, lz4frame needs all other modules present in `/lib`, -including, lz4 and lz4hc, and also **xxhash**. -So it's necessary to also include `xxhash.c` and `xxhash.h`. - - -#### Level 4 : File compression operations - -As a helper around file operations, -the library has been recently extended with `lz4file.c` and `lz4file.h` -(still considered experimental at the time of this writing). -These helpers allow opening, reading, writing, and closing files -using transparent LZ4 compression / decompression. -As a consequence, using `lz4file` adds a dependency on ``. - -`lz4file` relies on `lz4frame` in order to produce compressed data -conformant to the [LZ4 Frame format] specification. -Consequently, to enable this capability, -it's necessary to include all `*.c` and `*.h` files from `lib/` directory. - - -#### Advanced / Experimental API - -Definitions which are not guaranteed to remain stable in future versions, -are protected behind macros, such as `LZ4_STATIC_LINKING_ONLY`. -As the name suggests, these definitions should only be invoked -in the context of static linking ***only***. -Otherwise, dependent application may fail on API or ABI break in the future. -The associated symbols are also not exposed by the dynamic library by default. -Should they be nonetheless needed, it's possible to force their publication -by using build macros `LZ4_PUBLISH_STATIC_FUNCTIONS` -and `LZ4F_PUBLISH_STATIC_FUNCTIONS`. - - -#### Build macros - -The following build macro can be selected to adjust source code behavior at compilation time : - -- `LZ4_FAST_DEC_LOOP` : this triggers a speed optimized decompression loop, more powerful on modern cpus. - This loop works great on `x86`, `x64` and `aarch64` cpus, and is automatically enabled for them. - It's also possible to enable or disable it manually, by passing `LZ4_FAST_DEC_LOOP=1` or `0` to the preprocessor. - For example, with `gcc` : `-DLZ4_FAST_DEC_LOOP=1`, - and with `make` : `CPPFLAGS+=-DLZ4_FAST_DEC_LOOP=1 make lz4`. - -- `LZ4_DISTANCE_MAX` : control the maximum offset that the compressor will allow. - Set to 65535 by default, which is the maximum value supported by lz4 format. - Reducing maximum distance will reduce opportunities for LZ4 to find matches, - hence will produce a worse compression ratio. - Setting a smaller max distance could allow compatibility with specific decoders with limited memory budget. - This build macro only influences the compressed output of the compressor. - -- `LZ4_DISABLE_DEPRECATE_WARNINGS` : invoking a deprecated function will make the compiler generate a warning. - This is meant to invite users to update their source code. - Should this be a problem, it's generally possible to make the compiler ignore these warnings, - for example with `-Wno-deprecated-declarations` on `gcc`, - or `_CRT_SECURE_NO_WARNINGS` for Visual Studio. - This build macro offers another project-specific method - by defining `LZ4_DISABLE_DEPRECATE_WARNINGS` before including the LZ4 header files. - -- `LZ4_FORCE_SW_BITCOUNT` : by default, the compression algorithm tries to determine lengths - by using bitcount instructions, generally implemented as fast single instructions in many cpus. - In case the target cpus doesn't support it, or compiler intrinsic doesn't work, or feature bad performance, - it's possible to use an optimized software path instead. - This is achieved by setting this build macros. - In most cases, it's not expected to be necessary, - but it can be legitimately considered for less common platforms. - -- `LZ4_ALIGN_TEST` : alignment test ensures that the memory area - passed as argument to become a compression state is suitably aligned. - This test can be disabled if it proves flaky, by setting this value to 0. - -- `LZ4_USER_MEMORY_FUNCTIONS` : replace calls to ``'s `malloc()`, `calloc()` and `free()` - by user-defined functions, which must be named `LZ4_malloc()`, `LZ4_calloc()` and `LZ4_free()`. - User functions must be available at link time. - -- `LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION` : - Remove support of dynamic memory allocation. - For more details, see description of this macro in `lib/lz4.c`. - -- `LZ4_FREESTANDING` : by setting this build macro to 1, - LZ4/HC removes dependencies on the C standard library, - including allocation functions and `memmove()`, `memcpy()`, and `memset()`. - This build macro is designed to help use LZ4/HC in restricted environments - (embedded, bootloader, etc). - For more details, see description of this macro in `lib/lz4.h`. - - - -#### Amalgamation - -lz4 source code can be amalgamated into a single file. -One can combine all source code into `lz4_all.c` by using following command: -``` -cat lz4.c lz4hc.c lz4frame.c > lz4_all.c -``` -(`cat` file order is important) then compile `lz4_all.c`. -All `*.h` files present in `/lib` remain necessary to compile `lz4_all.c`. - - -#### Windows : using MinGW+MSYS to create DLL - -DLL can be created using MinGW+MSYS with the `make liblz4` command. -This command creates `dll\liblz4.dll` and the import library `dll\liblz4.lib`. -To override the `dlltool` command when cross-compiling on Linux, just set the `DLLTOOL` variable. Example of cross compilation on Linux with mingw-w64 64 bits: -``` -make BUILD_STATIC=no CC=x86_64-w64-mingw32-gcc DLLTOOL=x86_64-w64-mingw32-dlltool OS=Windows_NT -``` -The import library is only required with Visual C++. -The header files `lz4.h`, `lz4hc.h`, `lz4frame.h` and the dynamic library -`dll\liblz4.dll` are required to compile a project using gcc/MinGW. -The dynamic library has to be added to linking options. -It means that if a project that uses LZ4 consists of a single `test-dll.c` -file it should be linked with `dll\liblz4.dll`. For example: -``` - $(CC) $(CFLAGS) -Iinclude/ test-dll.c -o test-dll dll\liblz4.dll -``` -The compiled executable will require LZ4 DLL which is available at `dll\liblz4.dll`. - - -#### Miscellaneous - -Other files present in the directory are not source code. They are : - - - `LICENSE` : contains the BSD license text - - `Makefile` : `make` script to compile and install lz4 library (static and dynamic) - - `liblz4.pc.in` : for `pkg-config` (used in `make install`) - - `README.md` : this file - -[official interoperable frame format]: ../doc/lz4_Frame_format.md -[LZ4 Frame format]: ../doc/lz4_Frame_format.md -[LZ4 block format]: ../doc/lz4_Block_format.md - - -#### License - -All source material within __lib__ directory are BSD 2-Clause licensed. -See [LICENSE](LICENSE) for details. -The license is also reminded at the top of each source file. diff --git a/src/third_party/mozjs/extract/mfbt/lz4/README.mozilla b/src/third_party/mozjs/extract/mfbt/lz4/README.mozilla deleted file mode 100644 index 3974a200900..00000000000 --- a/src/third_party/mozjs/extract/mfbt/lz4/README.mozilla +++ /dev/null @@ -1,18 +0,0 @@ -This directory contains the LZ4 source from the upstream repo: -https://github.com/lz4/lz4/ - -Current version: 1.9.4 [5ff839680134437dbf4678f3d0c7b371d84f4964] - -Our in-tree copy of LZ4 does not depend on any generated files from the -upstream build system, only the lz4*.{c,h} files found in the lib -sub-directory. Therefore, it should be sufficient to simply overwrite -the in-tree files with the updated ones from upstream. - -If the collection of source files changes, manual updates to moz.build may be -needed as we don't use the upstream makefiles. - -Note that we do NOT use the copy of xxhash.{c,h} from the LZ4 repo. We -instead use the newer release from that project's upstream repo: -https://github.com/Cyan4973/xxHash - -Current version: 0.8.1 [35b0373c697b5f160d3db26b1cbb45a0d5ba788c] diff --git a/src/third_party/mozjs/extract/mfbt/moz.build b/src/third_party/mozjs/extract/mfbt/moz.build index f2b694ae766..f6b85bf7a97 100644 --- a/src/third_party/mozjs/extract/mfbt/moz.build +++ b/src/third_party/mozjs/extract/mfbt/moz.build @@ -35,7 +35,6 @@ EXPORTS.mozilla = [ "CheckedInt.h", "CompactPair.h", "Compiler.h", - "Compression.h", "DbgMacro.h", "DebugOnly.h", "DefineEnum.h", @@ -159,15 +158,9 @@ if CONFIG["OS_ARCH"] == "WASI": "WasiAtomic.h", ] -if CONFIG["MOZ_TSAN"]: - EXPORTS.mozilla += [ - "TsanOptions.h", - ] - UNIFIED_SOURCES += [ "Assertions.cpp", "ChaosMode.cpp", - "Compression.cpp", "double-conversion/double-conversion/bignum-dtoa.cc", "double-conversion/double-conversion/bignum.cc", "double-conversion/double-conversion/cached-powers.cc", @@ -181,6 +174,7 @@ UNIFIED_SOURCES += [ "JSONWriter.cpp", "Poison.cpp", "RandomNum.cpp", + "RefCounted.cpp", "SHA1.cpp", "TaggedAnonymousMemory.cpp", "UniquePtrExtensions.cpp", @@ -197,23 +191,17 @@ if CONFIG["MOZ_BUILD_APP"] not in ( DEFINES["IMPL_MFBT"] = True -SOURCES += [ - "lz4/lz4.c", - "lz4/lz4file.c", - "lz4/lz4frame.c", - "lz4/lz4hc.c", - "lz4/xxhash.c", -] - -SOURCES["lz4/xxhash.c"].flags += ["-Wno-unused-function"] - DisableStlWrapping() OS_LIBS += CONFIG["LIBATOMIC_LIBS"] -DEFINES["LZ4LIB_VISIBILITY"] = "" +# For RefCounted.cpp +DEFINES["MOZ_SUPPORT_LEAKCHECKING"] = True # This is kind of gross because this is not a subdirectory, # but pure_virtual requires mfbt to build and some projects # don't use mfbt. DIRS += ["../build/pure_virtual"] + +if CONFIG["MOZ_BUILD_APP"] != "memory": + FINAL_LIBRARY = "mozglue" diff --git a/src/third_party/mozjs/extract/modules/fdlibm/math_private.h b/src/third_party/mozjs/extract/modules/fdlibm/math_private.h index b588a5905f4..45f7401dd64 100644 --- a/src/third_party/mozjs/extract/modules/fdlibm/math_private.h +++ b/src/third_party/mozjs/extract/modules/fdlibm/math_private.h @@ -678,6 +678,8 @@ irintl(long double x) #ifdef DEBUG #if defined(__amd64__) || defined(__i386__) #define breakpoint() asm("int $3") +#elif defined(__wasm__) +#define breakpoint() __builtin_trap() #else #include diff --git a/src/third_party/mozjs/extract/mozglue/misc/AutoProfilerLabel.cpp b/src/third_party/mozjs/extract/mozglue/misc/AutoProfilerLabel.cpp index 5fd820cc5ba..c6d01c2700e 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/AutoProfilerLabel.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/AutoProfilerLabel.cpp @@ -53,7 +53,8 @@ class MOZ_RAII AutoProfilerLabelData { static uint32_t sGeneration; }; -/* static */ AutoProfilerLabelData::Mutex AutoProfilerLabelData::sAPLMutex; +MOZ_RUNINIT /* static */ AutoProfilerLabelData::Mutex + AutoProfilerLabelData::sAPLMutex; /* static */ ProfilerLabelEnter AutoProfilerLabelData::sEnter = nullptr; /* static */ ProfilerLabelExit AutoProfilerLabelData::sExit = nullptr; /* static */ uint32_t AutoProfilerLabelData::sGeneration = 0; diff --git a/src/third_party/mozjs/extract/mozglue/misc/AwakeTimeStamp.cpp b/src/third_party/mozjs/extract/mozglue/misc/AwakeTimeStamp.cpp index a5c8ed4abd6..a67c3e49a8a 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/AwakeTimeStamp.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/AwakeTimeStamp.cpp @@ -31,11 +31,26 @@ double AwakeTimeDuration::ToMicroseconds() const { return static_cast(mValueUs); } +AwakeTimeDuration AwakeTimeDuration::FromSeconds(uint64_t aSeconds) { + return AwakeTimeDuration(aSeconds * 1000000); +} +AwakeTimeDuration AwakeTimeDuration::FromMilliseconds(uint64_t aMilliseconds) { + return AwakeTimeDuration(aMilliseconds * 1000); +} +AwakeTimeDuration AwakeTimeDuration::FromMicroseconds(uint64_t aMicroseconds) { + return AwakeTimeDuration(aMicroseconds); +} + AwakeTimeDuration AwakeTimeStamp::operator-( AwakeTimeStamp const& aOther) const { return AwakeTimeDuration(mValueUs - aOther.mValueUs); } +AwakeTimeStamp AwakeTimeStamp::operator-( + AwakeTimeDuration const& aOther) const { + return AwakeTimeStamp(mValueUs - aOther.mValueUs); +} + AwakeTimeStamp AwakeTimeStamp::operator+( const AwakeTimeDuration& aDuration) const { return AwakeTimeStamp(mValueUs + aDuration.mValueUs); @@ -57,10 +72,12 @@ void AwakeTimeStamp::operator-=(const AwakeTimeDuration& aOther) { # include # include -AwakeTimeStamp AwakeTimeStamp::NowLoRes() { +AwakeTimeStamp AwakeTimeStamp::Now() { return AwakeTimeStamp(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / kNSperUS); } +AwakeTimeStamp AwakeTimeStamp::NowLoRes() { return Now(); } + #elif defined(XP_WIN) // Number of hundreds of nanoseconds in a microsecond @@ -74,6 +91,13 @@ AwakeTimeStamp AwakeTimeStamp::NowLoRes() { return AwakeTimeStamp(interrupt_time / kHNSperUS); } +AwakeTimeStamp AwakeTimeStamp::Now() { + ULONGLONG interrupt_time; + QueryUnbiasedInterruptTimePrecise(&interrupt_time); + + return AwakeTimeStamp(interrupt_time / kHNSperUS); +} + #else // Linux and other POSIX but not macOS # include @@ -81,13 +105,15 @@ uint64_t TimespecToMicroseconds(struct timespec aTs) { return aTs.tv_sec * kUSperS + aTs.tv_nsec / kNSperUS; } -AwakeTimeStamp AwakeTimeStamp::NowLoRes() { +AwakeTimeStamp AwakeTimeStamp::Now() { struct timespec ts = {0}; DebugOnly rv = clock_gettime(CLOCK_MONOTONIC, &ts); MOZ_ASSERT(!rv); return AwakeTimeStamp(TimespecToMicroseconds(ts)); } +AwakeTimeStamp AwakeTimeStamp::NowLoRes() { return Now(); } + #endif }; // namespace mozilla diff --git a/src/third_party/mozjs/extract/mozglue/misc/LoggingCore.cpp b/src/third_party/mozjs/extract/mozglue/misc/LoggingCore.cpp new file mode 100644 index 00000000000..022ffc850cf --- /dev/null +++ b/src/third_party/mozjs/extract/mozglue/misc/LoggingCore.cpp @@ -0,0 +1,18 @@ +/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "LoggingCore.h" + +#include + +namespace mozilla { + +LogLevel ToLogLevel(int32_t aLevel) { + aLevel = std::min(aLevel, static_cast(LogLevel::Verbose)); + aLevel = std::max(aLevel, static_cast(LogLevel::Disabled)); + return static_cast(aLevel); +} + +} // namespace mozilla diff --git a/src/third_party/mozjs/extract/mozglue/misc/Now.cpp b/src/third_party/mozjs/extract/mozglue/misc/Now.cpp new file mode 100644 index 00000000000..038b3041fcd --- /dev/null +++ b/src/third_party/mozjs/extract/mozglue/misc/Now.cpp @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Now.h" + +#ifdef XP_WIN +# include "mozilla/DynamicallyLinkedFunctionPtr.h" +#endif // XP_WIN + +#include + +#include "mozilla/TimeStamp.h" +#include "mozilla/Maybe.h" +#include "mozilla/Assertions.h" + +namespace mozilla { + +// Apple things +#if defined(__APPLE__) && defined(__MACH__) +# include +# include +# include +# include + +static constexpr uint64_t kNSperMS = 1000000; + +Maybe NowExcludingSuspendMs() { + return Some(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / kNSperMS); +} + +Maybe NowIncludingSuspendMs() { + return Some(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) / kNSperMS); +} + +#elif defined(XP_WIN) + +// Number of hundreds of nanoseconds in a millisecond +static constexpr uint64_t kHNSperMS = 10000; + +Maybe NowExcludingSuspendMs() { + ULONGLONG interrupt_time; + if (!QueryUnbiasedInterruptTime(&interrupt_time)) { + return Nothing(); + } + return Some(interrupt_time / kHNSperMS); +} + +Maybe NowIncludingSuspendMs() { + static const mozilla::StaticDynamicallyLinkedFunctionPtr + pQueryInterruptTime(L"KernelBase.dll", "QueryInterruptTime"); + if (!pQueryInterruptTime) { + // On Windows, this does include the time the computer was suspended so it's + // an adequate fallback. + TimeStamp processCreation = TimeStamp::ProcessCreation(); + TimeStamp now = TimeStamp::Now(); + if (!processCreation.IsNull() && !now.IsNull()) { + return Some(uint64_t((now - processCreation).ToMilliseconds())); + } else { + return Nothing(); + } + } + ULONGLONG interrupt_time; + pQueryInterruptTime(&interrupt_time); + return Some(interrupt_time / kHNSperMS); +} + +#elif defined(XP_UNIX) // including BSDs and Android +# include + +// Number of nanoseconds in a millisecond. +static constexpr uint64_t kNSperMS = 1000000; + +static uint64_t TimespecToMilliseconds(struct timespec aTs) { + return aTs.tv_sec * 1000 + aTs.tv_nsec / kNSperMS; +} + +Maybe NowExcludingSuspendMs() { + struct timespec ts = {0}; + +# ifdef XP_OPENBSD + if (clock_gettime(CLOCK_UPTIME, &ts)) { +# else + if (clock_gettime(CLOCK_MONOTONIC, &ts)) { +# endif + return Nothing(); + } + return Some(TimespecToMilliseconds(ts)); +} + +Maybe NowIncludingSuspendMs() { +# ifndef CLOCK_BOOTTIME + return Nothing(); +# else + struct timespec ts = {0}; + + if (clock_gettime(CLOCK_BOOTTIME, &ts)) { + return Nothing(); + } + return Some(TimespecToMilliseconds(ts)); +# endif +} + +#else // catch all + +Maybe NowExcludingSuspendMs() { return Nothing(); } +Maybe NowIncludingSuspendMs() { return Nothing(); } + +#endif + +} // namespace mozilla diff --git a/src/third_party/mozjs/extract/mozglue/misc/PreXULSkeletonUI.cpp b/src/third_party/mozjs/extract/mozglue/misc/PreXULSkeletonUI.cpp index 1b17837fc17..e4cda5df2ef 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/PreXULSkeletonUI.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/PreXULSkeletonUI.cpp @@ -7,6 +7,7 @@ #include "PreXULSkeletonUI.h" #include +#include #include #include #include @@ -96,6 +97,13 @@ NormalizedRGB Lerp(const NormalizedRGB& a, const NormalizedRGB& b, double x) { // Produces a smooth curve in [0,1] based on a linear input in [0,1] double SmoothStep3(double x) { return x * x * (3.0 - 2.0 * x); } +struct Margin { + int top = 0; + int right = 0; + int bottom = 0; + int left = 0; +}; + static const wchar_t kPreXULSkeletonUIKeyPath[] = L"SOFTWARE" L"\\" MOZ_APP_VENDOR L"\\" MOZ_APP_BASENAME L"\\PreXULSkeletonUISettings"; @@ -114,9 +122,20 @@ static Vector* sAnimatedRects = nullptr; static int sTotalChromeHeight = 0; static volatile LONG sAnimationControlFlag = 0; static bool sMaximized = false; -static int sNonClientVerticalMargins = 0; -static int sNonClientHorizontalMargins = 0; static uint32_t sDpi = 0; +// See nsWindow::mNonClientOffset +static Margin sNonClientOffset; +static int sCaptionHeight = 0; +static int sHorizontalResizeMargin = 0; +static int sVerticalResizeMargin = 0; + +// See nsWindow::NonClientSizeMargin() +static Margin NonClientSizeMargin() { + return Margin{sCaptionHeight + sVerticalResizeMargin - sNonClientOffset.top, + sHorizontalResizeMargin - sNonClientOffset.right, + sVerticalResizeMargin - sNonClientOffset.bottom, + sHorizontalResizeMargin - sNonClientOffset.left}; +} // Color values needed by the animation loop static uint32_t sAnimationColor; @@ -124,46 +143,31 @@ static uint32_t sToolbarForegroundColor; static ThemeMode sTheme = ThemeMode::Invalid; -typedef BOOL(WINAPI* EnableNonClientDpiScalingProc)(HWND); -static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling = NULL; -typedef int(WINAPI* GetSystemMetricsForDpiProc)(int, UINT); -GetSystemMetricsForDpiProc sGetSystemMetricsForDpi = NULL; -typedef UINT(WINAPI* GetDpiForWindowProc)(HWND); -GetDpiForWindowProc sGetDpiForWindow = NULL; -typedef ATOM(WINAPI* RegisterClassWProc)(const WNDCLASSW*); -RegisterClassWProc sRegisterClassW = NULL; -typedef HICON(WINAPI* LoadIconWProc)(HINSTANCE, LPCWSTR); -LoadIconWProc sLoadIconW = NULL; -typedef HICON(WINAPI* LoadCursorWProc)(HINSTANCE, LPCWSTR); -LoadCursorWProc sLoadCursorW = NULL; -typedef HWND(WINAPI* CreateWindowExWProc)(DWORD, LPCWSTR, LPCWSTR, DWORD, int, - int, int, int, HWND, HMENU, HINSTANCE, - LPVOID); -CreateWindowExWProc sCreateWindowExW = NULL; -typedef BOOL(WINAPI* ShowWindowProc)(HWND, int); -ShowWindowProc sShowWindow = NULL; -typedef BOOL(WINAPI* SetWindowPosProc)(HWND, HWND, int, int, int, int, UINT); -SetWindowPosProc sSetWindowPos = NULL; -typedef HDC(WINAPI* GetWindowDCProc)(HWND); -GetWindowDCProc sGetWindowDC = NULL; -typedef int(WINAPI* FillRectProc)(HDC, const RECT*, HBRUSH); -FillRectProc sFillRect = NULL; -typedef BOOL(WINAPI* DeleteObjectProc)(HGDIOBJ); -DeleteObjectProc sDeleteObject = NULL; -typedef int(WINAPI* ReleaseDCProc)(HWND, HDC); -ReleaseDCProc sReleaseDC = NULL; -typedef HMONITOR(WINAPI* MonitorFromWindowProc)(HWND, DWORD); -MonitorFromWindowProc sMonitorFromWindow = NULL; -typedef BOOL(WINAPI* GetMonitorInfoWProc)(HMONITOR, LPMONITORINFO); -GetMonitorInfoWProc sGetMonitorInfoW = NULL; -typedef LONG_PTR(WINAPI* SetWindowLongPtrWProc)(HWND, int, LONG_PTR); -SetWindowLongPtrWProc sSetWindowLongPtrW = NULL; -typedef int(WINAPI* StretchDIBitsProc)(HDC, int, int, int, int, int, int, int, - int, const VOID*, const BITMAPINFO*, - UINT, DWORD); -StretchDIBitsProc sStretchDIBits = NULL; -typedef HBRUSH(WINAPI* CreateSolidBrushProc)(COLORREF); -CreateSolidBrushProc sCreateSolidBrush = NULL; +#define MOZ_DECL_IMPORTED_WIN32_FN(name) \ + static decltype(&::name) s##name = nullptr +MOZ_DECL_IMPORTED_WIN32_FN(EnableNonClientDpiScaling); +MOZ_DECL_IMPORTED_WIN32_FN(GetSystemMetricsForDpi); +MOZ_DECL_IMPORTED_WIN32_FN(GetDpiForWindow); +MOZ_DECL_IMPORTED_WIN32_FN(RegisterClassW); +MOZ_DECL_IMPORTED_WIN32_FN(LoadIconW); +MOZ_DECL_IMPORTED_WIN32_FN(LoadCursorW); +MOZ_DECL_IMPORTED_WIN32_FN(CreateWindowExW); +MOZ_DECL_IMPORTED_WIN32_FN(ShowWindow); +MOZ_DECL_IMPORTED_WIN32_FN(SetWindowPos); +MOZ_DECL_IMPORTED_WIN32_FN(GetWindowDC); +MOZ_DECL_IMPORTED_WIN32_FN(GetWindowRect); +MOZ_DECL_IMPORTED_WIN32_FN(MapWindowPoints); +MOZ_DECL_IMPORTED_WIN32_FN(FillRect); +MOZ_DECL_IMPORTED_WIN32_FN(DeleteObject); +MOZ_DECL_IMPORTED_WIN32_FN(ReleaseDC); +MOZ_DECL_IMPORTED_WIN32_FN(MonitorFromWindow); +MOZ_DECL_IMPORTED_WIN32_FN(GetMonitorInfoW); +MOZ_DECL_IMPORTED_WIN32_FN(SetWindowLongPtrW); +MOZ_DECL_IMPORTED_WIN32_FN(StretchDIBits); +MOZ_DECL_IMPORTED_WIN32_FN(CreateSolidBrush); +MOZ_DECL_IMPORTED_WIN32_FN(DwmGetWindowAttribute); +MOZ_DECL_IMPORTED_WIN32_FN(DwmSetWindowAttribute); +#undef MOZ_DECL_IMPORTED_WIN32_FN static int sWindowWidth; static int sWindowHeight; @@ -670,6 +674,17 @@ bool RasterizeAnimatedRect(const ColorRect& colorRect, return true; } +bool FillRectWithColor(HDC hdc, LPCRECT rect, uint32_t mozColor) { + HBRUSH brush = sCreateSolidBrush(RGB((mozColor & 0xff0000) >> 16, + (mozColor & 0x00ff00) >> 8, + (mozColor & 0x0000ff) >> 0)); + int fillRectResult = sFillRect(hdc, rect, brush); + + sDeleteObject(brush); + + return !!fillRectResult; +} + Result DrawSkeletonUI( HWND hWnd, CSSPixelSpan urlbarCSSSpan, CSSPixelSpan searchbarCSSSpan, Vector& springs, const ThemeColors& currentTheme, @@ -699,17 +714,19 @@ Result DrawSkeletonUI( sToolbarForegroundColor = currentTheme.toolbarForegroundColor; bool menubarShown = flags.contains(SkeletonUIFlag::MenubarShown); + bool verticalTabs = flags.contains(SkeletonUIFlag::VerticalTabs); bool bookmarksToolbarShown = flags.contains(SkeletonUIFlag::BookmarksToolbarShown); bool rtlEnabled = flags.contains(SkeletonUIFlag::RtlEnabled); int chromeHorMargin = CSSToDevPixels(2, sCSSToDevPixelScaling); - int verticalOffset = sMaximized ? sNonClientVerticalMargins : 0; + int verticalOffset = sMaximized ? sVerticalResizeMargin : 0; int horizontalOffset = - sNonClientHorizontalMargins - (sMaximized ? 0 : chromeHorMargin); + sHorizontalResizeMargin - (sMaximized ? 0 : chromeHorMargin); // found in tabs.inc.css, "--tab-min-height" + 2 * "--tab-block-margin" - int tabBarHeight = CSSToDevPixels(44, sCSSToDevPixelScaling); + int tabBarHeight = + verticalTabs ? 0 : CSSToDevPixels(44, sCSSToDevPixelScaling); int selectedTabBorderWidth = CSSToDevPixels(2, sCSSToDevPixelScaling); // found in tabs.inc.css, "--tab-block-margin" int titlebarSpacerWidth = horizontalOffset + @@ -779,7 +796,7 @@ Result DrawSkeletonUI( Vector rects; ColorRect menubar = {}; - menubar.color = currentTheme.tabBarColor; + menubar.color = currentTheme.titlebarColor; menubar.x = 0; menubar.y = verticalOffset; menubar.width = sWindowWidth; @@ -795,7 +812,7 @@ Result DrawSkeletonUI( // The (traditionally dark blue on Windows) background of the tab bar. ColorRect tabBar = {}; - tabBar.color = currentTheme.tabBarColor; + tabBar.color = currentTheme.titlebarColor; tabBar.x = 0; tabBar.y = menubar.y + menubar.height; tabBar.width = sWindowWidth; @@ -805,38 +822,47 @@ Result DrawSkeletonUI( return Err(PreXULSkeletonUIError::OOM); } - // The initial selected tab - ColorRect selectedTab = {}; - selectedTab.color = currentTheme.tabColor; - selectedTab.x = titlebarSpacerWidth; - selectedTab.y = menubar.y + menubar.height + selectedTabMarginTop; - selectedTab.width = selectedTabWidth; - selectedTab.height = - tabBar.y + tabBar.height - selectedTab.y - selectedTabMarginBottom; - selectedTab.borderColor = currentTheme.tabOutlineColor; - selectedTab.borderWidth = selectedTabBorderWidth; - selectedTab.borderRadius = selectedTabBorderRadius; - selectedTab.flipIfRTL = true; - if (!rects.append(selectedTab)) { - return Err(PreXULSkeletonUIError::OOM); - } + if (!verticalTabs) { + // The initial selected tab + ColorRect selectedTab = {}; + selectedTab.color = currentTheme.tabColor; + selectedTab.x = titlebarSpacerWidth; + selectedTab.y = menubar.y + menubar.height + selectedTabMarginTop; + selectedTab.width = selectedTabWidth; + selectedTab.height = + tabBar.y + tabBar.height - selectedTab.y - selectedTabMarginBottom; + selectedTab.borderColor = currentTheme.tabOutlineColor; + selectedTab.borderWidth = selectedTabBorderWidth; + selectedTab.borderRadius = selectedTabBorderRadius; + selectedTab.flipIfRTL = true; + if (!rects.append(selectedTab)) { + return Err(PreXULSkeletonUIError::OOM); + } - // A placeholder rect representing text that will fill the selected tab title - ColorRect tabTextPlaceholder = {}; - tabTextPlaceholder.color = currentTheme.toolbarForegroundColor; - tabTextPlaceholder.x = selectedTab.x + tabPlaceholderBarMarginLeft; - tabTextPlaceholder.y = selectedTab.y + tabPlaceholderBarMarginTop; - tabTextPlaceholder.width = tabPlaceholderBarWidth; - tabTextPlaceholder.height = tabPlaceholderBarHeight; - tabTextPlaceholder.borderRadius = placeholderBorderRadius; - tabTextPlaceholder.flipIfRTL = true; - if (!rects.append(tabTextPlaceholder)) { - return Err(PreXULSkeletonUIError::OOM); + // A placeholder rect representing text that will fill the selected tab + // title + ColorRect tabTextPlaceholder = {}; + tabTextPlaceholder.color = currentTheme.toolbarForegroundColor; + tabTextPlaceholder.x = selectedTab.x + tabPlaceholderBarMarginLeft; + tabTextPlaceholder.y = selectedTab.y + tabPlaceholderBarMarginTop; + tabTextPlaceholder.width = tabPlaceholderBarWidth; + tabTextPlaceholder.height = tabPlaceholderBarHeight; + tabTextPlaceholder.borderRadius = placeholderBorderRadius; + tabTextPlaceholder.flipIfRTL = true; + if (!rects.append(tabTextPlaceholder)) { + return Err(PreXULSkeletonUIError::OOM); + } + + if (!sAnimatedRects->append(tabTextPlaceholder)) { + return Err(PreXULSkeletonUIError::OOM); + } } // The toolbar background ColorRect toolbar = {}; - toolbar.color = currentTheme.backgroundColor; + // In the vertical tabs case the main toolbar is in the titlebar: + toolbar.color = + verticalTabs ? currentTheme.titlebarColor : currentTheme.backgroundColor; toolbar.x = 0; toolbar.y = tabBar.y + tabBarHeight; toolbar.width = sWindowWidth; @@ -1027,8 +1053,7 @@ Result DrawSkeletonUI( return Err(PreXULSkeletonUIError::BadWindowDimensions); } - if (!sAnimatedRects->append(tabTextPlaceholder) || - !sAnimatedRects->append(urlbarTextPlaceholder)) { + if (!sAnimatedRects->append(urlbarTextPlaceholder)) { return Err(PreXULSkeletonUIError::OOM); } @@ -1080,15 +1105,10 @@ Result DrawSkeletonUI( // Then, we just fill the rest with FillRect RECT rect = {0, sTotalChromeHeight, sWindowWidth, sWindowHeight}; - HBRUSH brush = - sCreateSolidBrush(RGB((currentTheme.backgroundColor & 0xff0000) >> 16, - (currentTheme.backgroundColor & 0x00ff00) >> 8, - (currentTheme.backgroundColor & 0x0000ff) >> 0)); - int fillRectResult = sFillRect(hdc, &rect, brush); + bool const fillRectOk = + FillRectWithColor(hdc, &rect, currentTheme.backgroundColor); - sDeleteObject(brush); - - if (fillRectResult == 0) { + if (!fillRectOk) { return Err(PreXULSkeletonUIError::FailedFillingBottomRect); } @@ -1282,19 +1302,12 @@ LRESULT WINAPI PreXULSkeletonUIProc(HWND hWnd, UINT msg, WPARAM wParam, wParam ? &(reinterpret_cast(lParam))->rgrc[0] : (reinterpret_cast(lParam)); - // These match the margins set in browser-tabsintitlebar.js with - // default prefs on Windows. Bug 1673092 tracks lining this up with - // that more correctly instead of hard-coding it. - int horizontalOffset = - sNonClientHorizontalMargins - - (sMaximized ? 0 : CSSToDevPixels(2, sCSSToDevPixelScaling)); - int verticalOffset = - sNonClientHorizontalMargins - - (sMaximized ? 0 : CSSToDevPixels(2, sCSSToDevPixelScaling)); - clientRect->top = clientRect->top; - clientRect->left += horizontalOffset; - clientRect->right -= horizontalOffset; - clientRect->bottom -= verticalOffset; + Margin margin = NonClientSizeMargin(); + clientRect->top += margin.top; + clientRect->left += margin.left; + clientRect->right -= margin.right; + clientRect->bottom -= margin.bottom; + return 0; } @@ -1336,8 +1349,8 @@ ThemeColors GetTheme(ThemeMode themeId) { theme.toolbarForegroundColor = 0x6a6a6d; theme.tabOutlineColor = 0x1c1b22; // controlled by css variable --lwt-accent-color - theme.tabBarColor = 0x1c1b22; - // controlled by --toolbar-non-lwt-textcolor in browser.css + theme.titlebarColor = 0x1c1b22; + // controlled by --toolbar-color in browser.css theme.chromeContentDividerColor = 0x0c0c0d; // controlled by css variable --toolbar-field-background-color theme.urlbarColor = 0x42414d; @@ -1347,14 +1360,12 @@ ThemeColors GetTheme(ThemeMode themeId) { case ThemeMode::Light: case ThemeMode::Default: default: - // --toolbar-non-lwt-bgcolor in browser.css + // --toolbar-bgcolor in browser.css theme.backgroundColor = 0xf9f9fb; theme.tabColor = 0xf9f9fb; theme.toolbarForegroundColor = 0xdddde1; theme.tabOutlineColor = 0xdddde1; - // found in browser-aero.css ":root[tabsintitlebar]:not(:-moz-lwtheme)" - // (set to "hsl(235,33%,19%)") - theme.tabBarColor = 0xf0f0f4; + theme.titlebarColor = 0xeaeaed; // --chrome-content-separator-color in browser.css theme.chromeContentDividerColor = 0xe1e1e2; // controlled by css variable --toolbar-color @@ -1388,11 +1399,20 @@ Result OpenPreXULSkeletonUIRegKey() { Result LoadGdi32AndUser32Procedures() { HMODULE user32Dll = ::LoadLibraryW(L"user32"); HMODULE gdi32Dll = ::LoadLibraryW(L"gdi32"); + HMODULE dwmapiDll = ::LoadLibraryW(L"dwmapi.dll"); - if (!user32Dll || !gdi32Dll) { + if (!user32Dll || !gdi32Dll || !dwmapiDll) { return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); } +#define MOZ_LOAD_OR_FAIL(dll_handle, name) \ + do { \ + s##name = (decltype(&::name))::GetProcAddress(dll_handle, #name); \ + if (!s##name) { \ + return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); \ + } \ + } while (0) + auto getThreadDpiAwarenessContext = (decltype(GetThreadDpiAwarenessContext)*)::GetProcAddress( user32Dll, "GetThreadDpiAwarenessContext"); @@ -1402,89 +1422,37 @@ Result LoadGdi32AndUser32Procedures() { if (getThreadDpiAwarenessContext && areDpiAwarenessContextsEqual && areDpiAwarenessContextsEqual(getThreadDpiAwarenessContext(), DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) { - // EnableNonClientDpiScaling is optional - we can handle not having it. - sEnableNonClientDpiScaling = - (EnableNonClientDpiScalingProc)::GetProcAddress( - user32Dll, "EnableNonClientDpiScaling"); + // EnableNonClientDpiScaling is first available in Win10 Build 1607, but + // it's optional - we can handle not having it. + Unused << [&]() -> Result { + MOZ_LOAD_OR_FAIL(user32Dll, EnableNonClientDpiScaling); + return Ok{}; + }(); } - sGetSystemMetricsForDpi = (GetSystemMetricsForDpiProc)::GetProcAddress( - user32Dll, "GetSystemMetricsForDpi"); - if (!sGetSystemMetricsForDpi) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sGetDpiForWindow = - (GetDpiForWindowProc)::GetProcAddress(user32Dll, "GetDpiForWindow"); - if (!sGetDpiForWindow) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sRegisterClassW = - (RegisterClassWProc)::GetProcAddress(user32Dll, "RegisterClassW"); - if (!sRegisterClassW) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sCreateWindowExW = - (CreateWindowExWProc)::GetProcAddress(user32Dll, "CreateWindowExW"); - if (!sCreateWindowExW) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sShowWindow = (ShowWindowProc)::GetProcAddress(user32Dll, "ShowWindow"); - if (!sShowWindow) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sSetWindowPos = (SetWindowPosProc)::GetProcAddress(user32Dll, "SetWindowPos"); - if (!sSetWindowPos) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sGetWindowDC = (GetWindowDCProc)::GetProcAddress(user32Dll, "GetWindowDC"); - if (!sGetWindowDC) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sFillRect = (FillRectProc)::GetProcAddress(user32Dll, "FillRect"); - if (!sFillRect) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sReleaseDC = (ReleaseDCProc)::GetProcAddress(user32Dll, "ReleaseDC"); - if (!sReleaseDC) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sLoadIconW = (LoadIconWProc)::GetProcAddress(user32Dll, "LoadIconW"); - if (!sLoadIconW) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sLoadCursorW = (LoadCursorWProc)::GetProcAddress(user32Dll, "LoadCursorW"); - if (!sLoadCursorW) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sMonitorFromWindow = - (MonitorFromWindowProc)::GetProcAddress(user32Dll, "MonitorFromWindow"); - if (!sMonitorFromWindow) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sGetMonitorInfoW = - (GetMonitorInfoWProc)::GetProcAddress(user32Dll, "GetMonitorInfoW"); - if (!sGetMonitorInfoW) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sSetWindowLongPtrW = - (SetWindowLongPtrWProc)::GetProcAddress(user32Dll, "SetWindowLongPtrW"); - if (!sSetWindowLongPtrW) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sStretchDIBits = - (StretchDIBitsProc)::GetProcAddress(gdi32Dll, "StretchDIBits"); - if (!sStretchDIBits) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sCreateSolidBrush = - (CreateSolidBrushProc)::GetProcAddress(gdi32Dll, "CreateSolidBrush"); - if (!sCreateSolidBrush) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } - sDeleteObject = (DeleteObjectProc)::GetProcAddress(gdi32Dll, "DeleteObject"); - if (!sDeleteObject) { - return Err(PreXULSkeletonUIError::FailedLoadingDynamicProcs); - } + MOZ_LOAD_OR_FAIL(user32Dll, GetSystemMetricsForDpi); + MOZ_LOAD_OR_FAIL(user32Dll, GetDpiForWindow); + MOZ_LOAD_OR_FAIL(user32Dll, RegisterClassW); + MOZ_LOAD_OR_FAIL(user32Dll, CreateWindowExW); + MOZ_LOAD_OR_FAIL(user32Dll, ShowWindow); + MOZ_LOAD_OR_FAIL(user32Dll, SetWindowPos); + MOZ_LOAD_OR_FAIL(user32Dll, GetWindowDC); + MOZ_LOAD_OR_FAIL(user32Dll, GetWindowRect); + MOZ_LOAD_OR_FAIL(user32Dll, MapWindowPoints); + MOZ_LOAD_OR_FAIL(user32Dll, FillRect); + MOZ_LOAD_OR_FAIL(user32Dll, ReleaseDC); + MOZ_LOAD_OR_FAIL(user32Dll, LoadIconW); + MOZ_LOAD_OR_FAIL(user32Dll, LoadCursorW); + MOZ_LOAD_OR_FAIL(user32Dll, MonitorFromWindow); + MOZ_LOAD_OR_FAIL(user32Dll, GetMonitorInfoW); + MOZ_LOAD_OR_FAIL(user32Dll, SetWindowLongPtrW); + MOZ_LOAD_OR_FAIL(gdi32Dll, StretchDIBits); + MOZ_LOAD_OR_FAIL(gdi32Dll, CreateSolidBrush); + MOZ_LOAD_OR_FAIL(gdi32Dll, DeleteObject); + MOZ_LOAD_OR_FAIL(dwmapiDll, DwmGetWindowAttribute); + MOZ_LOAD_OR_FAIL(dwmapiDll, DwmSetWindowAttribute); + +#undef MOZ_LOAD_OR_FAIL return Ok(); } @@ -1953,7 +1921,7 @@ static Result CreateAndStorePreXULSkeletonUIImpl( sThemeRegSuffix))); ThemeMode themeMode = static_cast(theme); if (themeMode == ThemeMode::Default) { - if (IsSystemDarkThemeEnabled() == true) { + if (IsSystemDarkThemeEnabled()) { themeMode = ThemeMode::Dark; } } @@ -1978,14 +1946,60 @@ static Result CreateAndStorePreXULSkeletonUIImpl( return Err(PreXULSkeletonUIError::CreateWindowFailed); } - sShowWindow(sPreXULSkeletonUIWindow, showCmd); + // DWM displays garbage immediately on Show(), and that garbage is usually + // mostly #FFFFFF. To avoid a bright flash when the window is first created, + // cloak the window while showing it, and fill it with the appropriate + // background color before uncloaking it. + { + constexpr static auto const CloakWindow = [](HWND hwnd, BOOL state) { + sDwmSetWindowAttribute(sPreXULSkeletonUIWindow, DWMWA_CLOAK, &state, + sizeof(state)); + }; + // Equivalent to ::OffsetRect, with no dynamic-symbol resolution needed. + constexpr static auto const OffsetRect = [](LPRECT rect, int dx, int dy) { + rect->left += dx; + rect->top += dy; + rect->right += dx; + rect->bottom += dy; + }; + + CloakWindow(sPreXULSkeletonUIWindow, TRUE); + auto const _uncloak = + MakeScopeExit([&]() { CloakWindow(sPreXULSkeletonUIWindow, FALSE); }); + sShowWindow(sPreXULSkeletonUIWindow, showCmd); + + HDC hdc = sGetWindowDC(sPreXULSkeletonUIWindow); + if (!hdc) { + return Err(PreXULSkeletonUIError::FailedGettingDC); + } + auto const _cleanupDC = + MakeScopeExit([&] { sReleaseDC(sPreXULSkeletonUIWindow, hdc); }); + + // This should match the related code in nsWindow::Show. + RECT rect; + sGetWindowRect(sPreXULSkeletonUIWindow, &rect); // includes non-client area + // screen-to-client (handling RTL if necessary) + sMapWindowPoints(HWND_DESKTOP, sPreXULSkeletonUIWindow, (LPPOINT)&rect, 2); + // client-to-window (no RTL handling needed) + OffsetRect(&rect, -rect.left, -rect.top); + FillRectWithColor(hdc, &rect, currentTheme.backgroundColor); + } sDpi = sGetDpiForWindow(sPreXULSkeletonUIWindow); - sNonClientHorizontalMargins = - sGetSystemMetricsForDpi(SM_CXFRAME, sDpi) + - sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi); - sNonClientVerticalMargins = sGetSystemMetricsForDpi(SM_CYFRAME, sDpi) + - sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi); + sHorizontalResizeMargin = sGetSystemMetricsForDpi(SM_CXFRAME, sDpi) + + sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi); + sVerticalResizeMargin = sGetSystemMetricsForDpi(SM_CYFRAME, sDpi) + + sGetSystemMetricsForDpi(SM_CXPADDEDBORDER, sDpi); + sCaptionHeight = sGetSystemMetricsForDpi(SM_CYCAPTION, sDpi); + + // These match the offsets that we get with default prefs. We don't use the + // skeleton ui if tabsInTitlebar is disabled, see bug 1673092. + if (sMaximized) { + sNonClientOffset = Margin{sCaptionHeight, 0, 0, 0}; + } else { + // See nsWindow::NormalWindowNonClientOffset() + sNonClientOffset = Margin{sCaptionHeight + sVerticalResizeMargin, 0, 0, 0}; + } if (sMaximized) { HMONITOR monitor = @@ -2003,9 +2017,9 @@ static Result CreateAndStorePreXULSkeletonUIImpl( } sWindowWidth = - mi.rcWork.right - mi.rcWork.left + sNonClientHorizontalMargins * 2; + mi.rcWork.right - mi.rcWork.left + sHorizontalResizeMargin * 2; sWindowHeight = - mi.rcWork.bottom - mi.rcWork.top + sNonClientVerticalMargins * 2; + mi.rcWork.bottom - mi.rcWork.top + sVerticalResizeMargin * 2; } else { sWindowWidth = static_cast(windowWidth); sWindowHeight = static_cast(windowHeight); @@ -2075,10 +2089,6 @@ HWND ConsumePreXULSkeletonUIHandle() { return result; } -Maybe GetPreXULSkeletonUIErrorReason() { - return sErrorReason; -} - Result PersistPreXULSkeletonUIValues( const SkeletonUISettings& settings) { if (!sPreXULSkeletonUIEnabled) { @@ -2123,6 +2133,9 @@ Result PersistPreXULSkeletonUIValues( if (settings.uiDensity == SkeletonUIDensity::Compact) { flags += SkeletonUIFlag::CompactDensity; } + if (settings.verticalTabs) { + flags += SkeletonUIFlag::VerticalTabs; + } uint32_t flagsUint = flags.serialize(); MOZ_TRY(WriteRegUint(regKey, GetRegValueName(binPath.get(), sFlagsRegSuffix), diff --git a/src/third_party/mozjs/extract/mozglue/misc/ProcessType.cpp b/src/third_party/mozjs/extract/mozglue/misc/ProcessType.cpp index 031d2423289..3c82d6a4663 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/ProcessType.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/ProcessType.cpp @@ -15,27 +15,19 @@ using namespace mozilla::startup; namespace mozilla { namespace startup { GeckoProcessType sChildProcessType = GeckoProcessType_Default; +GeckoChildID sGeckoChildID = 0; } // namespace startup void SetGeckoProcessType(const char* aProcessTypeString) { -#if !defined(DEBUG) - // If not a DEBUG build then just return if sChildProcessType has already been - // set and is not fork server. In DEBUG builds we will check that process type - // matches the one already set if it is not fork server. if (sChildProcessType != GeckoProcessType_Default && sChildProcessType != GeckoProcessType_ForkServer) { - return; + MOZ_CRASH("Cannot set GeckoProcessType multiple times."); } -#endif #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \ process_bin_type, procinfo_typename, \ webidl_typename, allcaps_name) \ if (std::strcmp(aProcessTypeString, string_name) == 0) { \ - MOZ_ASSERT_IF( \ - sChildProcessType != GeckoProcessType_Default && \ - sChildProcessType != GeckoProcessType_ForkServer, \ - sChildProcessType == GeckoProcessType::GeckoProcessType_##enum_name); \ sChildProcessType = GeckoProcessType::GeckoProcessType_##enum_name; \ return; \ } @@ -55,4 +47,12 @@ void SetGeckoProcessType(const char* aProcessTypeString) { MOZ_CRASH("aProcessTypeString is not valid."); } +void SetGeckoChildID(const char* aGeckoChildIDString) { + sGeckoChildID = atoi(aGeckoChildIDString); + + if (sGeckoChildID <= 0) { + MOZ_CRASH("aGeckoChildIDString is not valid."); + } +} + } // namespace mozilla diff --git a/src/third_party/mozjs/extract/mozglue/misc/SIMD.cpp b/src/third_party/mozjs/extract/mozglue/misc/SIMD.cpp index 3893de57b32..61ac994c231 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/SIMD.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/SIMD.cpp @@ -478,6 +478,14 @@ const char16_t* SIMD::memchr16(const char16_t* ptr, char16_t value, return memchr16SSE2(ptr, value, length); } +const uint32_t* SIMD::memchr32(const uint32_t* ptr, uint32_t value, + size_t length) { + if (SupportsAVX2()) { + return memchr32AVX2(ptr, value, length); + } + return FindInBufferNaive(ptr, value, length); +} + const uint64_t* SIMD::memchr64(const uint64_t* ptr, uint64_t value, size_t length) { if (SupportsAVX2()) { @@ -524,6 +532,11 @@ const char16_t* SIMD::memchr16SSE2(const char16_t* ptr, char16_t value, return memchr16(ptr, value, length); } +const uint32_t* SIMD::memchr32(const uint32_t* ptr, uint32_t value, + size_t length) { + return FindInBufferNaive(ptr, value, length); +} + const uint64_t* SIMD::memchr64(const uint64_t* ptr, uint64_t value, size_t length) { return FindInBufferNaive(ptr, value, length); diff --git a/src/third_party/mozjs/extract/mozglue/misc/SIMD_avx2.cpp b/src/third_party/mozjs/extract/mozglue/misc/SIMD_avx2.cpp index a1467c7a559..8585a2534be 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/SIMD_avx2.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/SIMD_avx2.cpp @@ -47,13 +47,16 @@ __m128i CmpEq128(__m128i a, __m128i b) { template __m256i CmpEq256(__m256i a, __m256i b) { static_assert(sizeof(TValue) == 1 || sizeof(TValue) == 2 || - sizeof(TValue) == 8); + sizeof(TValue) == 4 || sizeof(TValue) == 8); if (sizeof(TValue) == 1) { return _mm256_cmpeq_epi8(a, b); } if (sizeof(TValue) == 2) { return _mm256_cmpeq_epi16(a, b); } + if (sizeof(TValue) == 4) { + return _mm256_cmpeq_epi32(a, b); + } return _mm256_cmpeq_epi64(a, b); } @@ -156,7 +159,7 @@ const TValue* Check4x32Bytes(__m256i needle, uintptr_t a, uintptr_t b, template const TValue* FindInBufferAVX2(const TValue* ptr, TValue value, size_t length) { static_assert(sizeof(TValue) == 1 || sizeof(TValue) == 2 || - sizeof(TValue) == 8); + sizeof(TValue) == 4 || sizeof(TValue) == 8); static_assert(std::is_unsigned::value); // Load our needle into a 32-byte register @@ -165,6 +168,8 @@ const TValue* FindInBufferAVX2(const TValue* ptr, TValue value, size_t length) { needle = _mm256_set1_epi8(value); } else if (sizeof(TValue) == 2) { needle = _mm256_set1_epi16(value); + } else if (sizeof(TValue) == 4) { + needle = _mm256_set1_epi32(value); } else { needle = _mm256_set1_epi64x(value); } @@ -173,7 +178,7 @@ const TValue* FindInBufferAVX2(const TValue* ptr, TValue value, size_t length) { uintptr_t cur = reinterpret_cast(ptr); uintptr_t end = cur + numBytes; - if (numBytes < 8 || (sizeof(TValue) == 8 && numBytes < 32)) { + if (numBytes < 8 || (sizeof(TValue) >= 4 && numBytes < 32)) { while (cur < end) { if (GetAs(cur) == value) { return reinterpret_cast(cur); @@ -183,7 +188,7 @@ const TValue* FindInBufferAVX2(const TValue* ptr, TValue value, size_t length) { return nullptr; } - if constexpr (sizeof(TValue) != 8) { + if constexpr (sizeof(TValue) < 4) { if (numBytes < 32) { __m128i needle_narrow; if (sizeof(TValue) == 1) { @@ -264,6 +269,11 @@ const char16_t* SIMD::memchr16AVX2(const char16_t* ptr, char16_t value, return FindInBufferAVX2(ptr, value, length); } +const uint32_t* SIMD::memchr32AVX2(const uint32_t* ptr, uint32_t value, + size_t length) { + return FindInBufferAVX2(ptr, value, length); +} + const uint64_t* SIMD::memchr64AVX2(const uint64_t* ptr, uint64_t value, size_t length) { return FindInBufferAVX2(ptr, value, length); @@ -284,6 +294,11 @@ const char16_t* SIMD::memchr16AVX2(const char16_t* ptr, char16_t value, MOZ_RELEASE_ASSERT(false, "AVX2 not supported in this binary."); } +const uint32_t* SIMD::memchr32AVX2(const uint32_t* ptr, uint32_t value, + size_t length) { + MOZ_RELEASE_ASSERT(false, "AVX2 not supported in this binary."); +} + const uint64_t* SIMD::memchr64AVX2(const uint64_t* ptr, uint64_t value, size_t length) { MOZ_RELEASE_ASSERT(false, "AVX2 not supported in this binary."); diff --git a/src/third_party/mozjs/extract/mozglue/misc/SSE.cpp b/src/third_party/mozjs/extract/mozglue/misc/SSE.cpp index 74f3917788d..61060e46e60 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/SSE.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/SSE.cpp @@ -7,6 +7,8 @@ #include "SSE.h" +#include "mozilla/Attributes.h" + #ifdef HAVE_CPUID_H // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64 # include @@ -169,39 +171,39 @@ namespace sse_private { #if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) # if !defined(MOZILLA_PRESUME_MMX) -bool mmx_enabled = has_cpuid_bits(1u, edx, (1u << 23)); +MOZ_RUNINIT bool mmx_enabled = has_cpuid_bits(1u, edx, (1u << 23)); # endif # if !defined(MOZILLA_PRESUME_SSE) -bool sse_enabled = has_cpuid_bits(1u, edx, (1u << 25)); +MOZ_RUNINIT bool sse_enabled = has_cpuid_bits(1u, edx, (1u << 25)); # endif # if !defined(MOZILLA_PRESUME_SSE2) -bool sse2_enabled = has_cpuid_bits(1u, edx, (1u << 26)); +MOZ_RUNINIT bool sse2_enabled = has_cpuid_bits(1u, edx, (1u << 26)); # endif # if !defined(MOZILLA_PRESUME_SSE3) -bool sse3_enabled = has_cpuid_bits(1u, ecx, (1u << 0)); +MOZ_RUNINIT bool sse3_enabled = has_cpuid_bits(1u, ecx, (1u << 0)); # endif # if !defined(MOZILLA_PRESUME_SSSE3) -bool ssse3_enabled = has_cpuid_bits(1u, ecx, (1u << 9)); +MOZ_RUNINIT bool ssse3_enabled = has_cpuid_bits(1u, ecx, (1u << 9)); # endif # if !defined(MOZILLA_PRESUME_SSE4A) -bool sse4a_enabled = has_cpuid_bits(0x80000001u, ecx, (1u << 6)); +MOZ_RUNINIT bool sse4a_enabled = has_cpuid_bits(0x80000001u, ecx, (1u << 6)); # endif # if !defined(MOZILLA_PRESUME_SSE4_1) -bool sse4_1_enabled = has_cpuid_bits(1u, ecx, (1u << 19)); +MOZ_RUNINIT bool sse4_1_enabled = has_cpuid_bits(1u, ecx, (1u << 19)); # endif # if !defined(MOZILLA_PRESUME_SSE4_2) -bool sse4_2_enabled = has_cpuid_bits(1u, ecx, (1u << 20)); +MOZ_RUNINIT bool sse4_2_enabled = has_cpuid_bits(1u, ecx, (1u << 20)); # endif # if !defined(MOZILLA_PRESUME_FMA3) -bool fma3_enabled = has_cpuid_bits(1u, ecx, (1u << 12)); +MOZ_RUNINIT bool fma3_enabled = has_cpuid_bits(1u, ecx, (1u << 12)); # endif # if !defined(MOZILLA_PRESUME_AVX) || !defined(MOZILLA_PRESUME_AVX2) @@ -225,22 +227,22 @@ static bool has_avx() { # endif // !MOZILLA_PRESUME_AVX || !MOZILLA_PRESUME_AVX2 # if !defined(MOZILLA_PRESUME_AVX) -bool avx_enabled = has_avx(); +MOZ_RUNINIT bool avx_enabled = has_avx(); # endif # if !defined(MOZILLA_PRESUME_AVX2) -bool avx2_enabled = has_avx() && has_cpuid_bits(7u, ebx, (1u << 5)); +MOZ_RUNINIT bool avx2_enabled = has_avx() && has_cpuid_bits(7u, ebx, (1u << 5)); # endif # if !defined(MOZILLA_PRESUME_AVXVNNI) -bool avxvnni_enabled = has_cpuid_bits_ex(7u, eax, (1u << 4)); +MOZ_RUNINIT bool avxvnni_enabled = has_cpuid_bits_ex(7u, eax, (1u << 4)); # endif # if !defined(MOZILLA_PRESUME_AES) -bool aes_enabled = has_cpuid_bits(1u, ecx, (1u << 25)); +MOZ_RUNINIT bool aes_enabled = has_cpuid_bits(1u, ecx, (1u << 25)); # endif -bool has_constant_tsc = has_cpuid_bits(0x80000007u, edx, (1u << 8)); +MOZ_RUNINIT bool has_constant_tsc = has_cpuid_bits(0x80000007u, edx, (1u << 8)); #endif diff --git a/src/third_party/mozjs/extract/mozglue/misc/StackWalk.cpp b/src/third_party/mozjs/extract/mozglue/misc/StackWalk.cpp index 18fd3464b01..cc62b4d7859 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/StackWalk.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/StackWalk.cpp @@ -6,6 +6,7 @@ /* API for getting a stack trace of the C/C++ stack on the current thread */ +#include "mozilla/Array.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Atomics.h" #include "mozilla/Attributes.h" @@ -61,6 +62,9 @@ using namespace mozilla; #if HAVE___LIBC_STACK_END extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so +# ifdef __aarch64__ +static Atomic ldso_base; +# endif #endif #ifdef ANDROID @@ -117,16 +121,58 @@ class FrameSkipper { # error Too old imagehlp.h # endif -// DbgHelp functions are not thread-safe and should therefore be protected by -// using this critical section. Only use the critical section after a -// successful call to InitializeDbgHelp(). -CRITICAL_SECTION gDbgHelpCS; - # if defined(_M_AMD64) || defined(_M_ARM64) -// Because various Win64 APIs acquire function-table locks, we need a way of -// preventing stack walking while those APIs are being called. Otherwise, the -// stack walker may suspend a thread holding such a lock, and deadlock when the -// stack unwind code attempts to wait for that lock. +// We must use RtlLookupFunctionEntry to do stack walking on x86-64 and arm64, +// but internally this function does a blocking shared acquire of SRW locks +// that live in ntdll and are not exported. This is problematic when we want to +// suspend a thread and walk its stack, like we do in the profiler and the +// background hang reporter. If the suspended thread happens to hold one of the +// locks exclusively while suspended, then the stack walking thread will +// deadlock if it calls RtlLookupFunctionEntry. +// +// Note that we only care about deadlocks between the stack walking thread and +// the suspended thread. Any other deadlock scenario is considered out of +// scope, because they are unlikely to be our fault -- these other scenarios +// imply that some thread that we did not suspend is stuck holding one of the +// locks exclusively, and exclusive acquisition of these locks only happens for +// a brief time during Microsoft API calls (e.g. LdrLoadDll, LdrUnloadDll). +// +// We use one of two alternative strategies to gracefully fail to capture a +// stack instead of running into a deadlock: +// (1) collect pointers to the ntdll internal locks at stack walk +// initialization, then try to acquire them non-blockingly before +// initiating any stack walk; +// or (2) mark all code paths that can potentially end up doing an exclusive +// acquisition of the locks as stack walk suppression paths, then check +// if any thread is currently on a stack walk suppression path before +// initiating any stack walk; +// +// Strategy (2) can only avoid all deadlocks under the easily wronged +// assumption that we have correctly identified all existing paths that should +// be stack suppression paths. With strategy (2) we cannot collect stacks e.g. +// during the whole duration of a DLL load happening on any thread so the +// profiling results are worse. +// +// Strategy (1) guarantees no deadlock. It also gives better profiling results +// because it is more fine-grained. Therefore we always prefer strategy (1), +// and we only use strategy (2) as a fallback. + +// Strategy (1): Ntdll Internal Locks +// +// The external stack walk initialization code will feed us pointers to the +// ntdll internal locks. Once we have them, we no longer need to rely on +// strategy (2). +static Atomic sStackWalkLocksInitialized; +static Array sStackWalkLocks; + +MFBT_API +void InitializeStackWalkLocks(const Array& aStackWalkLocks) { + sStackWalkLocks[0] = reinterpret_cast(aStackWalkLocks[0]); + sStackWalkLocks[1] = reinterpret_cast(aStackWalkLocks[1]); + sStackWalkLocksInitialized = true; +} + +// Strategy (2): Stack Walk Suppressions // // We're using an atomic counter rather than a critical section because we // don't require mutual exclusion with the stack walker. If the stack walker @@ -157,6 +203,24 @@ AutoSuppressStackWalking::~AutoSuppressStackWalking() { DesuppressStackWalking(); } +bool IsStackWalkingSafe() { + // Use strategy (1), if initialized. + if (sStackWalkLocksInitialized) { + bool isSafe = false; + if (::TryAcquireSRWLockShared(sStackWalkLocks[0])) { + if (::TryAcquireSRWLockShared(sStackWalkLocks[1])) { + isSafe = true; + ::ReleaseSRWLockShared(sStackWalkLocks[1]); + } + ::ReleaseSRWLockShared(sStackWalkLocks[0]); + } + return isSafe; + } + + // Otherwise, fall back to strategy (2). + return sStackWalkSuppressions == 0; +} + static uint8_t* sJitCodeRegionStart; static size_t sJitCodeRegionSize; uint8_t* sMsMpegJitCodeRegionStart; @@ -196,26 +260,109 @@ static void PrintError(const char* aPrefix) { LocalFree(lpMsgBuf); } -enum class DbgHelpInitFlags : bool { - BasicInit, - WithSymbolSupport, +class MOZ_RAII AutoCriticalSection { + public: + explicit inline AutoCriticalSection(LPCRITICAL_SECTION aCriticalSection) + : mCriticalSection{aCriticalSection} { + ::EnterCriticalSection(mCriticalSection); + } + inline ~AutoCriticalSection() { ::LeaveCriticalSection(mCriticalSection); } + + AutoCriticalSection(AutoCriticalSection&& other) = delete; + AutoCriticalSection operator=(AutoCriticalSection&& other) = delete; + AutoCriticalSection(const AutoCriticalSection&) = delete; + AutoCriticalSection operator=(const AutoCriticalSection&) = delete; + + private: + LPCRITICAL_SECTION mCriticalSection; }; -// This function ensures that DbgHelp.dll is loaded in the current process, -// and initializes the gDbgHelpCS critical section that we use to protect calls -// to DbgHelp functions. If DbgHelpInitFlags::WithSymbolSupport is set, we -// additionally call the symbol initialization functions from DbgHelp so that -// symbol-related functions can be used. -// -// This function is thread-safe and reentrancy-safe. In debug and fuzzing -// builds, MOZ_ASSERT and MOZ_CRASH walk the stack to print it before actually -// crashing. Hence *any* MOZ_ASSERT or MOZ_CRASH failure reached from -// InitializeDbgHelp() leads to rentrancy (see bug 1869997 for an example). -// Such failures can occur indirectly when we load dbghelp.dll, because we -// override various Microsoft-internal functions that are called upon DLL -// loading. -[[nodiscard]] static bool InitializeDbgHelp( - DbgHelpInitFlags aInitFlags = DbgHelpInitFlags::BasicInit) { +// A thread-safe safe object interface for Microsoft's DbgHelp.dll. DbgHelp +// APIs are not thread-safe and they require the use of a unique HANDLE value +// as an identifier for the current session. All this is handled internally by +// DbgHelpWrapper. +class DbgHelpWrapper { + public: + explicit inline DbgHelpWrapper() : DbgHelpWrapper(InitFlag::BasicInit) {} + DbgHelpWrapper(DbgHelpWrapper&& other) = delete; + DbgHelpWrapper operator=(DbgHelpWrapper&& other) = delete; + DbgHelpWrapper(const DbgHelpWrapper&) = delete; + DbgHelpWrapper operator=(const DbgHelpWrapper&) = delete; + + inline bool ReadyToUse() { return mInitSuccess; } + + inline BOOL StackWalk64( + DWORD aMachineType, HANDLE aThread, LPSTACKFRAME64 aStackFrame, + PVOID aContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 aReadMemoryRoutine, + PFUNCTION_TABLE_ACCESS_ROUTINE64 aFunctionTableAccessRoutine, + PGET_MODULE_BASE_ROUTINE64 aGetModuleBaseRoutine, + PTRANSLATE_ADDRESS_ROUTINE64 aTranslateAddress) { + if (!ReadyToUse()) { + return FALSE; + } + + AutoCriticalSection guard(&sCriticalSection); + return ::StackWalk64(aMachineType, sSessionId, aThread, aStackFrame, + aContextRecord, aReadMemoryRoutine, + aFunctionTableAccessRoutine, aGetModuleBaseRoutine, + aTranslateAddress); + } + + protected: + enum class InitFlag : bool { + BasicInit, + WithSymbolSupport, + }; + + explicit inline DbgHelpWrapper(InitFlag initFlag) { + mInitSuccess = Initialize(initFlag); + } + + // DbgHelp functions are not thread-safe and should therefore be protected + // by using this critical section through a AutoCriticalSection. + static CRITICAL_SECTION sCriticalSection; + + // DbgHelp functions require a unique HANDLE hProcess that should be the same + // throughout the current session. We refer to this handle as a session id. + // Ideally the session id should be a valid HANDLE to the target process, + // which in our case is the current process. + // + // However, in order to avoid conflicts with other sessions, the session id + // should be unique and therefore not just GetCurrentProcess(), which other + // pieces of code tend to already use (see bug 1699328). + // + // We therefore define sSessionId as a duplicate of the current process + // handle, a solution that meets all the requirements listed above. + static HANDLE sSessionId; + + private: + bool mInitSuccess; + + // This function initializes sCriticalSection, sSessionId and loads DbgHelp. + // It also calls SymInitialize if called with aInitFlag::WithSymbolSupport. + // It is thread-safe and reentrancy-safe. + [[nodiscard]] static bool Initialize(InitFlag aInitFlag); + + // In debug and fuzzing builds, MOZ_ASSERT and MOZ_CRASH walk the stack to + // print it before actually crashing. This code path uses a DbgHelpWrapper + // object, hence *any* MOZ_ASSERT or MOZ_CRASH failure reached from + // Initialize() leads to rentrancy (see bug 1869997 for an example). Such + // failures can occur indirectly when we load dbghelp.dll, because we + // override various Microsoft-internal functions that are called upon DLL + // loading. We protect against reentrancy by keeping track of the ID of the + // thread that runs the initialization code. + static Atomic sInitializationThreadId; +}; + +CRITICAL_SECTION DbgHelpWrapper::sCriticalSection{}; +Atomic DbgHelpWrapper::sInitializationThreadId{0}; +HANDLE DbgHelpWrapper::sSessionId{nullptr}; + +// Thread-safety here is ensured by the C++ standard: scoped static +// initialization is thread-safe. sInitializationThreadId is used to protect +// against reentrancy -- and only for that purpose. +[[nodiscard]] /* static */ bool DbgHelpWrapper::Initialize( + DbgHelpWrapper::InitFlag aInitFlag) { // In the code below, it is only safe to reach MOZ_ASSERT or MOZ_CRASH while // sInitializationThreadId is set to the current thread id. static Atomic sInitializationThreadId{0}; @@ -233,9 +380,17 @@ enum class DbgHelpInitFlags : bool { } static const bool sHasInitializedDbgHelp = [currentThreadId]() { + // Per the C++ standard, only one thread evers reaches this path. sInitializationThreadId = currentThreadId; - ::InitializeCriticalSection(&gDbgHelpCS); + ::InitializeCriticalSection(&sCriticalSection); + + if (!::DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), + GetCurrentProcess(), &sSessionId, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + return false; + } + bool dbgHelpLoaded = static_cast(::LoadLibraryW(L"dbghelp.dll")); MOZ_ASSERT(dbgHelpLoaded); @@ -245,18 +400,23 @@ enum class DbgHelpInitFlags : bool { // If we don't need symbol initialization, we are done. If we need it, we // can only proceed if DbgHelp initialization was successful. - if (aInitFlags == DbgHelpInitFlags::BasicInit || !sHasInitializedDbgHelp) { + if (aInitFlag == InitFlag::BasicInit || !sHasInitializedDbgHelp) { return sHasInitializedDbgHelp; } static const bool sHasInitializedSymbols = [currentThreadId]() { + // Per the C++ standard, only one thread evers reaches this path. sInitializationThreadId = currentThreadId; - EnterCriticalSection(&gDbgHelpCS); - SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); - bool symbolsInitialized = SymInitialize(GetCurrentProcess(), nullptr, TRUE); - /* XXX At some point we need to arrange to call SymCleanup */ - LeaveCriticalSection(&gDbgHelpCS); + bool symbolsInitialized = false; + + { + AutoCriticalSection guard(&sCriticalSection); + ::SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); + symbolsInitialized = + static_cast(::SymInitializeW(sSessionId, nullptr, TRUE)); + /* XXX At some point we need to arrange to call SymCleanup */ + } if (!symbolsInitialized) { PrintError("SymInitialize"); @@ -270,6 +430,38 @@ enum class DbgHelpInitFlags : bool { return sHasInitializedSymbols; } +// Some APIs such as SymFromAddr also require that the session id has gone +// through SymInitialize. This is handled by child class DbgHelpWrapperSym. +class DbgHelpWrapperSym : public DbgHelpWrapper { + public: + explicit DbgHelpWrapperSym() : DbgHelpWrapper(InitFlag::WithSymbolSupport) {} + + inline BOOL SymFromAddr(DWORD64 aAddress, PDWORD64 aDisplacement, + PSYMBOL_INFO aSymbol) { + if (!ReadyToUse()) { + return FALSE; + } + + AutoCriticalSection guard(&sCriticalSection); + return ::SymFromAddr(sSessionId, aAddress, aDisplacement, aSymbol); + } + + BOOL SymGetModuleInfoEspecial64(DWORD64 aAddr, PIMAGEHLP_MODULE64 aModuleInfo, + PIMAGEHLP_LINE64 aLineInfo); + + private: + // Helpers for SymGetModuleInfoEspecial64 + struct CallbackEspecial64UserContext { + HANDLE mSessionId; + DWORD64 mAddr; + }; + + static BOOL CALLBACK CallbackEspecial64(PCSTR aModuleName, + DWORD64 aModuleBase, + ULONG aModuleSize, + PVOID aUserContext); +}; + // Wrapper around a reference to a CONTEXT, to simplify access to main // platform-specific execution registers. // It also avoids using CONTEXT* nullable pointers. @@ -332,7 +524,8 @@ static void DoMozStackWalkThread(MozWalkStackCallback aCallback, void* aClosure, HANDLE aThread, CONTEXT* aContext) { # if defined(_M_IX86) - if (!InitializeDbgHelp()) { + DbgHelpWrapper dbgHelp; + if (!dbgHelp.ReadyToUse()) { return; } # endif @@ -375,17 +568,18 @@ static void DoMozStackWalkThread(MozWalkStackCallback aCallback, # endif # if defined(_M_AMD64) || defined(_M_ARM64) - // If there are any active suppressions, then at least one thread (we don't - // know which) is holding a lock that can deadlock RtlVirtualUnwind. Since - // that thread may be the one that we're trying to unwind, we can't proceed. + // If at least one thread (we don't know which) may be holding a lock that + // can deadlock RtlLookupFunctionEntry, we can't proceed because that thread + // may be the one that we're trying to walk the stack of. // - // But if there are no suppressions, then our target thread can't be holding - // a lock, and it's safe to proceed. By virtue of being suspended, the target - // thread can't acquire any new locks during the unwind process, so we only - // need to do this check once. After that, sStackWalkSuppressions can be - // changed by other threads while we're unwinding, and that's fine because - // we can't deadlock with those threads. - if (sStackWalkSuppressions) { + // But if there is no such thread by this point, then our target thread can't + // be holding a lock, so it's safe to proceed. By virtue of being suspended, + // the target thread can't acquire any new locks during our stack walking, so + // we only need to do this check once. Other threads may temporarily acquire + // the locks while we're walking the stack, but that's mostly fine -- calling + // RtlLookupFunctionEntry will make us wait for them to release the locks, + // but at least we won't deadlock. + if (!IsStackWalkingSafe()) { return; } @@ -403,15 +597,12 @@ static void DoMozStackWalkThread(MozWalkStackCallback aCallback, # if defined(_M_IX86) // 32-bit frame unwinding. - // Debug routines are not threadsafe, so grab the lock. - EnterCriticalSection(&gDbgHelpCS); - BOOL ok = - StackWalk64(IMAGE_FILE_MACHINE_I386, ::GetCurrentProcess(), - targetThread, &frame64, context.CONTEXTPtr(), nullptr, - SymFunctionTableAccess64, // function table access routine - SymGetModuleBase64, // module base routine - 0); - LeaveCriticalSection(&gDbgHelpCS); + BOOL ok = dbgHelp.StackWalk64( + IMAGE_FILE_MACHINE_I386, targetThread, &frame64, context.CONTEXTPtr(), + nullptr, + ::SymFunctionTableAccess64, // function table access routine + ::SymGetModuleBase64, // module base routine + 0); if (ok) { addr = frame64.AddrPC.Offset; @@ -515,10 +706,12 @@ MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, aMaxFrames, aClosure, nullptr, nullptr); } -static BOOL CALLBACK callbackEspecial64(PCSTR aModuleName, DWORD64 aModuleBase, - ULONG aModuleSize, PVOID aUserContext) { +/* static */ BOOL CALLBACK +DbgHelpWrapperSym::CallbackEspecial64(PCSTR aModuleName, DWORD64 aModuleBase, + ULONG aModuleSize, PVOID aUserContext) { BOOL retval = TRUE; - DWORD64 addr = *(DWORD64*)aUserContext; + auto context = reinterpret_cast(aUserContext); + DWORD64 addr = context->mAddr; /* * You'll want to control this if we are running on an @@ -533,8 +726,8 @@ static BOOL CALLBACK callbackEspecial64(PCSTR aModuleName, DWORD64 aModuleBase, if (addressIncreases ? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize)) : (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize))) { - retval = !!SymLoadModule64(GetCurrentProcess(), nullptr, (PSTR)aModuleName, - nullptr, aModuleBase, aModuleSize); + retval = !!::SymLoadModule64(context->mSessionId, nullptr, aModuleName, + nullptr, aModuleBase, aModuleSize); if (!retval) { PrintError("SymLoadModule64"); } @@ -571,9 +764,13 @@ static BOOL CALLBACK callbackEspecial64(PCSTR aModuleName, DWORD64 aModuleBase, # define NS_IMAGEHLP_MODULE64_SIZE sizeof(IMAGEHLP_MODULE64) # endif -BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, - PIMAGEHLP_MODULE64 aModuleInfo, - PIMAGEHLP_LINE64 aLineInfo) { +BOOL DbgHelpWrapperSym::SymGetModuleInfoEspecial64( + DWORD64 aAddr, PIMAGEHLP_MODULE64 aModuleInfo, PIMAGEHLP_LINE64 aLineInfo) { + if (!ReadyToUse()) { + return FALSE; + } + + AutoCriticalSection guard(&sCriticalSection); BOOL retval = FALSE; /* @@ -588,26 +785,24 @@ BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, * Give it a go. * It may already be loaded. */ - retval = SymGetModuleInfo64(aProcess, aAddr, aModuleInfo); + retval = ::SymGetModuleInfo64(sSessionId, aAddr, aModuleInfo); if (retval == FALSE) { /* * Not loaded, here's the magic. * Go through all the modules. */ - // Need to cast to PENUMLOADED_MODULES_CALLBACK64 because the - // constness of the first parameter of - // PENUMLOADED_MODULES_CALLBACK64 varies over SDK versions (from - // non-const to const over time). See bug 391848 and bug - // 415426. - BOOL enumRes = EnumerateLoadedModules64( - aProcess, (PENUMLOADED_MODULES_CALLBACK64)callbackEspecial64, - (PVOID)&aAddr); + CallbackEspecial64UserContext context{ + .mSessionId = sSessionId, + .mAddr = aAddr, + }; + BOOL enumRes = ::EnumerateLoadedModules64( + sSessionId, CallbackEspecial64, reinterpret_cast(&context)); if (enumRes != FALSE) { /* * One final go. * If it fails, then well, we have other problems. */ - retval = SymGetModuleInfo64(aProcess, aAddr, aModuleInfo); + retval = ::SymGetModuleInfo64(sSessionId, aAddr, aModuleInfo); } } @@ -618,7 +813,8 @@ BOOL SymGetModuleInfoEspecial64(HANDLE aProcess, DWORD64 aAddr, if (retval != FALSE && aLineInfo) { DWORD displacement = 0; BOOL lineRes = FALSE; - lineRes = SymGetLineFromAddr64(aProcess, aAddr, &displacement, aLineInfo); + lineRes = + ::SymGetLineFromAddr64(sSessionId, aAddr, &displacement, aLineInfo); if (!lineRes) { // Clear out aLineInfo to indicate that it's not valid memset(aLineInfo, 0, sizeof(*aLineInfo)); @@ -637,37 +833,29 @@ MFBT_API bool MozDescribeCodeAddress(void* aPC, aDetails->function[0] = '\0'; aDetails->foffset = 0; - if (!InitializeDbgHelp(DbgHelpInitFlags::WithSymbolSupport)) { + DbgHelpWrapperSym dbgHelp; + if (!dbgHelp.ReadyToUse()) { return false; } - HANDLE myProcess = ::GetCurrentProcess(); - BOOL ok; - - // debug routines are not threadsafe, so grab the lock. - EnterCriticalSection(&gDbgHelpCS); - - // // Attempt to load module info before we attempt to resolve the symbol. // This just makes sure we get good info if available. - // - DWORD64 addr = (DWORD64)aPC; IMAGEHLP_MODULE64 modInfo; IMAGEHLP_LINE64 lineInfo; BOOL modInfoRes; - modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, &lineInfo); + modInfoRes = dbgHelp.SymGetModuleInfoEspecial64(addr, &modInfo, &lineInfo); if (modInfoRes) { strncpy(aDetails->library, modInfo.LoadedImageName, sizeof(aDetails->library)); - aDetails->library[mozilla::ArrayLength(aDetails->library) - 1] = '\0'; + aDetails->library[std::size(aDetails->library) - 1] = '\0'; aDetails->loffset = (char*)aPC - (char*)modInfo.BaseOfImage; if (lineInfo.FileName) { strncpy(aDetails->filename, lineInfo.FileName, sizeof(aDetails->filename)); - aDetails->filename[mozilla::ArrayLength(aDetails->filename) - 1] = '\0'; + aDetails->filename[std::size(aDetails->filename) - 1] = '\0'; aDetails->lineno = lineInfo.LineNumber; } } @@ -680,15 +868,14 @@ MFBT_API bool MozDescribeCodeAddress(void* aPC, pSymbol->MaxNameLen = MAX_SYM_NAME; DWORD64 displacement; - ok = SymFromAddr(myProcess, addr, &displacement, pSymbol); + BOOL ok = dbgHelp.SymFromAddr(addr, &displacement, pSymbol); if (ok) { strncpy(aDetails->function, pSymbol->Name, sizeof(aDetails->function)); - aDetails->function[mozilla::ArrayLength(aDetails->function) - 1] = '\0'; + aDetails->function[std::size(aDetails->function) - 1] = '\0'; aDetails->foffset = static_cast(displacement); } - LeaveCriticalSection(&gDbgHelpCS); // release our lock return true; } @@ -762,7 +949,8 @@ MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, # elif defined(ANDROID) pthread_attr_t sattr; pthread_attr_init(&sattr); - pthread_getattr_np(pthread_self(), &sattr); + int rc = pthread_getattr_np(pthread_self(), &sattr); + MOZ_RELEASE_ASSERT(rc == 0, "pthread_getattr_np failed"); void* stackBase = stackEnd = nullptr; size_t stackSize = 0; if (gettid() != getpid()) { @@ -806,8 +994,38 @@ struct unwind_info { static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context, void* closure) { + _Unwind_Reason_Code ret = _URC_NO_REASON; unwind_info* info = static_cast(closure); void* pc = reinterpret_cast(_Unwind_GetIP(context)); +# if HAVE___LIBC_STACK_END && defined(__aarch64__) + // Work around https://sourceware.org/bugzilla/show_bug.cgi?id=32612 + // The _dl_tlsdesc_dynamic function can't be unwound through with + // _Unwind_Backtrace when glibc is built with aarch64 PAC (that leads + // to a crash). + // Unfortunately, we can't get the address of that specific function, so + // we just disallow all of ld-linux-aarch64.so.1: when we hit an address + // in there, we make _Unwind_Backtrace stop. + // In the case of _dl_tlsdesc_dynamic, this would stop the stackwalk at + // tls_get_addr_tail, which is enough information to know the stack comes + // from ld.so, and we even get inlining info giving us malloc, + // allocate_dtv_entry and allocate_and_init, which is plenty enough and + // better than nothing^Hcrashing. + // To figure out whether the frame falls into ld-linux-aarch64.so.1, we + // use __libc_stack_end (which lives there and is .data) as upper bound + // (assuming .data comes after .text), and get the base address of the + // library via dladdr. + if (!ldso_base) { + Dl_info info; + dladdr(&__libc_stack_end, &info); + ldso_base = (uintptr_t)info.dli_fbase; + } + if (ldso_base && ((uintptr_t)pc > ldso_base) && + (uintptr_t)pc < (uintptr_t)&__libc_stack_end) { + // Any error code will do, we just want to stop the walk even when + // we haven't reached the limit. + ret = _URC_FOREIGN_EXCEPTION_CAUGHT; + } +# endif // TODO Use something like '_Unwind_GetGR()' to get the stack pointer. if (!info->skipper.ShouldSkipPC(pc)) { info->numFrames++; @@ -817,7 +1035,7 @@ static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context, return _URC_FOREIGN_EXCEPTION_CAUGHT; } } - return _URC_NO_REASON; + return ret; } MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, @@ -866,7 +1084,7 @@ bool MFBT_API MozDescribeCodeAddress(void* aPC, } strncpy(aDetails->library, info.dli_fname, sizeof(aDetails->library)); - aDetails->library[mozilla::ArrayLength(aDetails->library) - 1] = '\0'; + aDetails->library[std::size(aDetails->library) - 1] = '\0'; aDetails->loffset = (char*)aPC - (char*)info.dli_fbase; # if !defined(XP_FREEBSD) @@ -884,7 +1102,7 @@ bool MFBT_API MozDescribeCodeAddress(void* aPC, if (aDetails->function[0] == '\0') { // Just use the mangled symbol if demangling failed. strncpy(aDetails->function, symbol, sizeof(aDetails->function)); - aDetails->function[mozilla::ArrayLength(aDetails->function) - 1] = '\0'; + aDetails->function[std::size(aDetails->function) - 1] = '\0'; } aDetails->foffset = (char*)aPC - (char*)info.dli_saddr; diff --git a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp.cpp b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp.cpp index f77cf631323..3f2da17c80e 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp.cpp @@ -43,7 +43,7 @@ struct TimeStampInitialization { ~TimeStampInitialization() { TimeStamp::Shutdown(); } }; -static TimeStampInitialization sInitOnce; +MOZ_RUNINIT static TimeStampInitialization sInitOnce; MFBT_API TimeStamp TimeStamp::ProcessCreation() { if (sInitOnce.mProcessCreation.IsNull()) { diff --git a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_darwin.cpp b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_darwin.cpp index ec29917985d..6c7e1b87a88 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_darwin.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_darwin.cpp @@ -132,8 +132,7 @@ void TimeStamp::Startup() { // sake of ToSecondsSigDigits() for (sResolutionSigDigs = 1; !(sResolutionSigDigs == sResolution || 10 * sResolutionSigDigs > sResolution); - sResolutionSigDigs *= 10) - ; + sResolutionSigDigs *= 10); gInitialized = true; } diff --git a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_posix.cpp b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_posix.cpp index ba32a230eb0..6f87118a103 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_posix.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_posix.cpp @@ -197,8 +197,7 @@ void TimeStamp::Startup() { // sake of ToSecondsSigDigits() for (sResolutionSigDigs = 1; !(sResolutionSigDigs == sResolution || 10 * sResolutionSigDigs > sResolution); - sResolutionSigDigs *= 10) - ; + sResolutionSigDigs *= 10); gInitialized = true; } @@ -321,14 +320,16 @@ uint64_t TimeStamp::ComputeProcessUptime() { } int mib[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID, - getpid(), + // clang-format off + CTL_KERN, + KERN_PROC, + KERN_PROC_PID, + getpid(), # if defined(__NetBSD__) || defined(__OpenBSD__) - sizeof(KINFO_PROC), - 1, + sizeof(KINFO_PROC), + 1, # endif + // clang-format on }; u_int mibLen = sizeof(mib) / sizeof(mib[0]); diff --git a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_windows.cpp b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_windows.cpp index 81da34409d1..5ad23138b05 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_windows.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/TimeStamp_windows.cpp @@ -245,8 +245,7 @@ static void InitResolution() { // sake of ToSecondsSigDigits() ULONGLONG sigDigs; for (sigDigs = 1; !(sigDigs == result || 10 * sigDigs > result); - sigDigs *= 10) - ; + sigDigs *= 10); sResolutionSigDigs = sigDigs; } diff --git a/src/third_party/mozjs/extract/mozglue/misc/Uptime.cpp b/src/third_party/mozjs/extract/mozglue/misc/Uptime.cpp index 924b1543591..42f97c1671d 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/Uptime.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/Uptime.cpp @@ -6,118 +6,15 @@ #include "Uptime.h" -#ifdef XP_WIN -# include "mozilla/DynamicallyLinkedFunctionPtr.h" -#endif // XP_WIN - -#include - -#include "mozilla/TimeStamp.h" -#include "mozilla/Maybe.h" -#include "mozilla/Assertions.h" +#include "mozilla/Now.h" using namespace mozilla; namespace { -Maybe NowIncludingSuspendMs(); -Maybe NowExcludingSuspendMs(); static Maybe mStartExcludingSuspendMs; static Maybe mStartIncludingSuspendMs; -// Apple things -#if defined(__APPLE__) && defined(__MACH__) -# include -# include -# include -# include - -const uint64_t kNSperMS = 1000000; - -Maybe NowExcludingSuspendMs() { - return Some(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / kNSperMS); -} - -Maybe NowIncludingSuspendMs() { - return Some(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) / kNSperMS); -} - -#elif defined(XP_WIN) - -// Number of hundreds of nanoseconds in a millisecond -static constexpr uint64_t kHNSperMS = 10000; - -Maybe NowExcludingSuspendMs() { - ULONGLONG interrupt_time; - if (!QueryUnbiasedInterruptTime(&interrupt_time)) { - return Nothing(); - } - return Some(interrupt_time / kHNSperMS); -} - -Maybe NowIncludingSuspendMs() { - static const mozilla::StaticDynamicallyLinkedFunctionPtr - pQueryInterruptTime(L"KernelBase.dll", "QueryInterruptTime"); - if (!pQueryInterruptTime) { - // On Windows, this does include the time the computer was suspended so it's - // an adequate fallback. - TimeStamp processCreation = TimeStamp::ProcessCreation(); - TimeStamp now = TimeStamp::Now(); - if (!processCreation.IsNull() && !now.IsNull()) { - return Some(uint64_t((now - processCreation).ToMilliseconds())); - } else { - return Nothing(); - } - } - ULONGLONG interrupt_time; - pQueryInterruptTime(&interrupt_time); - return Some(interrupt_time / kHNSperMS); -} - -#elif defined(XP_UNIX) // including BSDs and Android -# include - -// Number of nanoseconds in a millisecond. -static constexpr uint64_t kNSperMS = 1000000; - -uint64_t TimespecToMilliseconds(struct timespec aTs) { - return aTs.tv_sec * 1000 + aTs.tv_nsec / kNSperMS; -} - -Maybe NowExcludingSuspendMs() { - struct timespec ts = {0}; - -# ifdef XP_OPENBSD - if (clock_gettime(CLOCK_UPTIME, &ts)) { -# else - if (clock_gettime(CLOCK_MONOTONIC, &ts)) { -# endif - return Nothing(); - } - return Some(TimespecToMilliseconds(ts)); -} - -Maybe NowIncludingSuspendMs() { -# ifndef CLOCK_BOOTTIME - return Nothing(); -# else - struct timespec ts = {0}; - - if (clock_gettime(CLOCK_BOOTTIME, &ts)) { - return Nothing(); - } - return Some(TimespecToMilliseconds(ts)); -# endif -} - -#else // catch all - -Maybe NowExcludingSuspendMs() { return Nothing(); } -Maybe NowIncludingSuspendMs() { return Nothing(); } - -#endif - }; // anonymous namespace namespace mozilla { diff --git a/src/third_party/mozjs/extract/mozglue/misc/WindowsDiagnostics.cpp b/src/third_party/mozjs/extract/mozglue/misc/WindowsDiagnostics.cpp index 03fb39749fb..6aac4920175 100644 --- a/src/third_party/mozjs/extract/mozglue/misc/WindowsDiagnostics.cpp +++ b/src/third_party/mozjs/extract/mozglue/misc/WindowsDiagnostics.cpp @@ -13,19 +13,19 @@ #include #include -#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && defined(_M_X64) +#if defined(_M_AMD64) namespace mozilla { -static OnSingleStepCallback sOnSingleStepCallback{}; +MOZ_RUNINIT static OnSingleStepCallback sOnSingleStepCallback{}; static void* sOnSingleStepCallbackState = nullptr; static bool sIsSingleStepping = false; MFBT_API AutoOnSingleStepCallback::AutoOnSingleStepCallback( OnSingleStepCallback aOnSingleStepCallback, void* aState) { - MOZ_DIAGNOSTIC_ASSERT(!sIsSingleStepping && !sOnSingleStepCallback && - !sOnSingleStepCallbackState, - "Single-stepping is already active"); + MOZ_RELEASE_ASSERT(!sIsSingleStepping && !sOnSingleStepCallback && + !sOnSingleStepCallbackState, + "Single-stepping is already active"); sOnSingleStepCallback = std::move(aOnSingleStepCallback); sOnSingleStepCallbackState = aState; @@ -42,7 +42,7 @@ MFBT_API AutoOnSingleStepCallback::~AutoOnSingleStepCallback() { // a first single-step exception. It is then up to the exception handler to // keep the trap flag enabled so that a new single step exception gets // triggered with the following instruction. -MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void EnableTrapFlag() { +MFBT_API MOZ_NEVER_INLINE MOZ_NAKED void EnableTrapFlag() { asm volatile( "pushfq;" "orw $0x100,(%rsp);" @@ -53,7 +53,7 @@ MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void EnableTrapFlag() { // This function does not do anything special, but when we reach its address // while single-stepping the exception handler will know that it is now time to // leave the trap flag turned off. -MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void DisableTrapFlag() { +MFBT_API MOZ_NEVER_INLINE MOZ_NAKED void DisableTrapFlag() { asm volatile("retq;"); } @@ -78,4 +78,4 @@ MFBT_API LONG SingleStepExceptionHandler(_EXCEPTION_POINTERS* aExceptionInfo) { } // namespace mozilla -#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED && _M_X64 +#endif // _M_AMD64 diff --git a/src/third_party/mozjs/extract/mfbt/Compression.cpp b/src/third_party/mozjs/extract/mozglue/static/Compression.cpp similarity index 100% rename from src/third_party/mozjs/extract/mfbt/Compression.cpp rename to src/third_party/mozjs/extract/mozglue/static/Compression.cpp diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4.c b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4.c similarity index 91% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4.c rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4.c index 654bfdf32f9..a2f7abee19f 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4.c +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4.c @@ -1,6 +1,6 @@ /* LZ4 - Fast LZ compression algorithm - Copyright (C) 2011-2020, Yann Collet. + Copyright (C) 2011-2023, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -37,7 +37,8 @@ **************************************/ /* * LZ4_HEAPMODE : - * Select how default compression functions will allocate memory for their hash table, + * Select how stateless compression functions like `LZ4_compress_default()` + * allocate memory for their hash table, * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). */ #ifndef LZ4_HEAPMODE @@ -78,7 +79,7 @@ ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \ || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) # define LZ4_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) +# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) || defined(_MSC_VER) # define LZ4_FORCE_MEMORY_ACCESS 1 # endif #endif @@ -105,15 +106,13 @@ # define LZ4_SRC_INCLUDED 1 #endif -#ifndef LZ4_STATIC_LINKING_ONLY -#define LZ4_STATIC_LINKING_ONLY -#endif - #ifndef LZ4_DISABLE_DEPRECATE_WARNINGS -#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */ +# define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */ #endif -#define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */ +#ifndef LZ4_STATIC_LINKING_ONLY +# define LZ4_STATIC_LINKING_ONLY +#endif #include "lz4.h" /* see also "memory routines" below */ @@ -125,14 +124,17 @@ # include /* only present in VS2005+ */ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ # pragma warning(disable : 6237) /* disable: C6237: conditional expression is always 0 */ +# pragma warning(disable : 6239) /* disable: C6239: ( && ) always evaluates to the result of */ +# pragma warning(disable : 6240) /* disable: C6240: ( && ) always evaluates to the result of */ +# pragma warning(disable : 6326) /* disable: C6326: Potential comparison of a constant with another constant */ #endif /* _MSC_VER */ #ifndef LZ4_FORCE_INLINE -# ifdef _MSC_VER /* Visual Studio */ +# if defined (_MSC_VER) && !defined (__clang__) /* MSVC */ # define LZ4_FORCE_INLINE static __forceinline # else # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# ifdef __GNUC__ +# if defined (__GNUC__) || defined (__clang__) # define LZ4_FORCE_INLINE static inline __attribute__((always_inline)) # else # define LZ4_FORCE_INLINE static inline @@ -279,7 +281,7 @@ static const int LZ4_minLength = (MFLIMIT+1); static int g_debuglog_enable = 1; # define DEBUGLOG(l, ...) { \ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ - fprintf(stderr, __FILE__ ": "); \ + fprintf(stderr, __FILE__ " %i: ", __LINE__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, " \n"); \ } } @@ -364,6 +366,11 @@ static unsigned LZ4_isLittleEndian(void) return one.c[0]; } +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#define LZ4_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#elif defined(_MSC_VER) +#define LZ4_PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +#endif #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) /* lie to the compiler about data alignment; use with caution */ @@ -379,14 +386,16 @@ static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ /* currently only defined for gcc and icc */ -typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) LZ4_unalign; +LZ4_PACK(typedef struct { U16 u16; }) LZ4_unalign16; +LZ4_PACK(typedef struct { U32 u32; }) LZ4_unalign32; +LZ4_PACK(typedef struct { reg_t uArch; }) LZ4_unalignST; -static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign*)ptr)->u16; } -static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign*)ptr)->u32; } -static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalign*)ptr)->uArch; } +static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign16*)ptr)->u16; } +static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign32*)ptr)->u32; } +static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalignST*)ptr)->uArch; } -static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign*)memPtr)->u16 = value; } -static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign*)memPtr)->u32 = value; } +static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign16*)memPtr)->u16 = value; } +static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign32*)memPtr)->u32 = value; } #else /* safe and portable access using memcpy() */ @@ -424,10 +433,22 @@ static U16 LZ4_readLE16(const void* memPtr) return LZ4_read16(memPtr); } else { const BYTE* p = (const BYTE*)memPtr; - return (U16)((U16)p[0] + (p[1]<<8)); + return (U16)((U16)p[0] | (p[1]<<8)); } } +#ifdef LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT +static U32 LZ4_readLE32(const void* memPtr) +{ + if (LZ4_isLittleEndian()) { + return LZ4_read32(memPtr); + } else { + const BYTE* p = (const BYTE*)memPtr; + return (U32)p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); + } +} +#endif + static void LZ4_writeLE16(void* memPtr, U16 value) { if (LZ4_isLittleEndian()) { @@ -509,7 +530,7 @@ LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd) /* LZ4_memcpy_using_offset() presumes : * - dstEnd >= dstPtr + MINMATCH - * - there is at least 8 bytes available to write after dstEnd */ + * - there is at least 12 bytes available to write after dstEnd */ LZ4_FORCE_INLINE void LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset) { @@ -524,12 +545,12 @@ LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const si case 2: LZ4_memcpy(v, srcPtr, 2); LZ4_memcpy(&v[2], srcPtr, 2); -#if defined(_MSC_VER) && (_MSC_VER <= 1933) /* MSVC 2022 ver 17.3 or earlier */ +#if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */ # pragma warning(push) # pragma warning(disable : 6385) /* warning C6385: Reading invalid data from 'v'. */ #endif LZ4_memcpy(&v[4], v, 4); -#if defined(_MSC_VER) && (_MSC_VER <= 1933) /* MSVC 2022 ver 17.3 or earlier */ +#if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */ # pragma warning(pop) #endif break; @@ -776,7 +797,12 @@ LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType) LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) { if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); + +#ifdef LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT + return LZ4_hash4(LZ4_readLE32(p), tableType); +#else return LZ4_hash4(LZ4_read32(p), tableType); +#endif } LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType) @@ -803,23 +829,19 @@ LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableT } } +/* LZ4_putPosition*() : only used in byPtr mode */ LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h, - void* tableBase, tableType_t const tableType, - const BYTE* srcBase) + void* tableBase, tableType_t const tableType) { - switch (tableType) - { - case clearedTable: { /* illegal! */ assert(0); return; } - case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } - case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } - case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } - } + const BYTE** const hashTable = (const BYTE**)tableBase; + assert(tableType == byPtr); (void)tableType; + hashTable[h] = p; } -LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType) { U32 const h = LZ4_hashPosition(p, tableType); - LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); + LZ4_putPositionOnHash(p, h, tableBase, tableType); } /* LZ4_getIndexOnHash() : @@ -844,20 +866,18 @@ LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_ assert(0); return 0; /* forbidden case */ } -static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType, const BYTE* srcBase) +static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType) { - if (tableType == byPtr) { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; } - if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h] + srcBase; } - { const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ + assert(tableType == byPtr); (void)tableType; + { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; } } LZ4_FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, - const void* tableBase, tableType_t tableType, - const BYTE* srcBase) + const void* tableBase, tableType_t tableType) { U32 const h = LZ4_hashPosition(p, tableType); - return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); + return LZ4_getPositionOnHash(h, tableBase, tableType); } LZ4_FORCE_INLINE void @@ -901,9 +921,9 @@ LZ4_prepareTable(LZ4_stream_t_internal* const cctx, cctx->dictSize = 0; } -/** LZ4_compress_generic() : +/** LZ4_compress_generic_validated() : * inlined, to ensure branches are decided at compilation time. - * Presumed already validated at this stage: + * The following conditions are presumed already validated: * - source != NULL * - inputSize > 0 */ @@ -921,10 +941,10 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( const int acceleration) { int result; - const BYTE* ip = (const BYTE*) source; + const BYTE* ip = (const BYTE*)source; U32 const startIndex = cctx->currentOffset; - const BYTE* base = (const BYTE*) source - startIndex; + const BYTE* base = (const BYTE*)source - startIndex; const BYTE* lowLimit; const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx; @@ -932,7 +952,8 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary; const U32 dictSize = dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize; - const U32 dictDelta = (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with index in current context */ + const U32 dictDelta = + (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with indexes in current context */ int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx); U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */ @@ -957,11 +978,11 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType); assert(ip != NULL); + if (tableType == byU16) assert(inputSize=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */ - if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */ assert(acceleration >= 1); lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0); @@ -981,7 +1002,12 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( if (inputSizehashTable, tableType, base); + { U32 const h = LZ4_hashPosition(ip, tableType); + if (tableType == byPtr) { + LZ4_putPositionOnHash(ip, h, cctx->hashTable, byPtr); + } else { + LZ4_putIndexOnHash(startIndex, h, cctx->hashTable, tableType); + } } ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ @@ -1004,9 +1030,9 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; assert(ip < mflimitPlusOne); - match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); + match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType); forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); + LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType); } while ( (match+LZ4_DISTANCE_MAX < ip) || (LZ4_read32(match) != LZ4_read32(ip)) ); @@ -1077,7 +1103,10 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( /* Catch up */ filledIp = ip; - while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } + assert(ip > anchor); /* this is always true as ip has been advanced before entering the main loop */ + if ((match > lowLimit) && unlikely(ip[-1] == match[-1])) { + do { ip--; match--; } while (((ip > anchor) & (match > lowLimit)) && (unlikely(ip[-1] == match[-1]))); + } /* Encode Literals */ { unsigned const litLength = (unsigned)(ip - anchor); @@ -1092,7 +1121,7 @@ LZ4_FORCE_INLINE int LZ4_compress_generic_validated( goto _last_literals; } if (litLength >= RUN_MASK) { - int len = (int)(litLength - RUN_MASK); + unsigned len = litLength - RUN_MASK; *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255; *op++ = (BYTE)len; @@ -1204,13 +1233,19 @@ _next_match: if (ip >= mflimitPlusOne) break; /* Fill table */ - LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); + { U32 const h = LZ4_hashPosition(ip-2, tableType); + if (tableType == byPtr) { + LZ4_putPositionOnHash(ip-2, h, cctx->hashTable, byPtr); + } else { + U32 const idx = (U32)((ip-2) - base); + LZ4_putIndexOnHash(idx, h, cctx->hashTable, tableType); + } } /* Test next position */ if (tableType == byPtr) { - match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); - LZ4_putPosition(ip, cctx->hashTable, tableType, base); + match = LZ4_getPosition(ip, cctx->hashTable, tableType); + LZ4_putPosition(ip, cctx->hashTable, tableType); if ( (match+LZ4_DISTANCE_MAX >= ip) && (LZ4_read32(match) == LZ4_read32(ip)) ) { token=op++; *token=0; goto _next_match; } @@ -1224,6 +1259,7 @@ _next_match: if (dictDirective == usingDictCtx) { if (matchIndex < startIndex) { /* there was no match, try the dictionary */ + assert(tableType == byU32); matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); match = dictBase + matchIndex; lowLimit = dictionary; /* required for match length counter */ @@ -1377,9 +1413,10 @@ int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int */ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration) { - LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; + LZ4_stream_t_internal* const ctx = &((LZ4_stream_t*)state)->internal_donotuse; if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; + assert(ctx != NULL); if (dstCapacity >= LZ4_compressBound(srcSize)) { if (srcSize < LZ4_64Klimit) { @@ -1413,17 +1450,17 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst } -int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +int LZ4_compress_fast(const char* src, char* dest, int srcSize, int dstCapacity, int acceleration) { int result; #if (LZ4_HEAPMODE) - LZ4_stream_t* ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + LZ4_stream_t* const ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ if (ctxPtr == NULL) return 0; #else LZ4_stream_t ctx; LZ4_stream_t* const ctxPtr = &ctx; #endif - result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + result = LZ4_compress_fast_extState(ctxPtr, src, dest, srcSize, dstCapacity, acceleration); #if (LZ4_HEAPMODE) FREEMEM(ctxPtr); @@ -1432,43 +1469,51 @@ int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutp } -int LZ4_compress_default(const char* src, char* dst, int srcSize, int maxOutputSize) +int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity) { - return LZ4_compress_fast(src, dst, srcSize, maxOutputSize, 1); + return LZ4_compress_fast(src, dst, srcSize, dstCapacity, 1); } /* Note!: This function leaves the stream in an unclean/broken state! * It is not safe to subsequently use the same state with a _fastReset() or * _continue() call without resetting it. */ -static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) +static int LZ4_compress_destSize_extState_internal(LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration) { void* const s = LZ4_initStream(state, sizeof (*state)); assert(s != NULL); (void)s; if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ - return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); + return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, acceleration); } else { if (*srcSizePtr < LZ4_64Klimit) { - return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, 1); + return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, acceleration); } else { tableType_t const addrMode = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; - return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, 1); + return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, acceleration); } } } +int LZ4_compress_destSize_extState(void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration) +{ + int const r = LZ4_compress_destSize_extState_internal((LZ4_stream_t*)state, src, dst, srcSizePtr, targetDstSize, acceleration); + /* clean the state on exit */ + LZ4_initStream(state, sizeof (LZ4_stream_t)); + return r; +} + int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) { #if (LZ4_HEAPMODE) - LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + LZ4_stream_t* const ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ if (ctx == NULL) return 0; #else LZ4_stream_t ctxBody; - LZ4_stream_t* ctx = &ctxBody; + LZ4_stream_t* const ctx = &ctxBody; #endif - int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + int result = LZ4_compress_destSize_extState_internal(ctx, src, dst, srcSizePtr, targetDstSize, 1); #if (LZ4_HEAPMODE) FREEMEM(ctx); @@ -1537,14 +1582,17 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_stream) #endif +typedef enum { _ld_fast, _ld_slow } LoadDict_mode_e; #define HASH_UNIT sizeof(reg_t) -int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +int LZ4_loadDict_internal(LZ4_stream_t* LZ4_dict, + const char* dictionary, int dictSize, + LoadDict_mode_e _ld) { - LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; const tableType_t tableType = byU32; const BYTE* p = (const BYTE*)dictionary; const BYTE* const dictEnd = p + dictSize; - const BYTE* base; + U32 idx32; DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict); @@ -1567,19 +1615,46 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) } if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; - base = dictEnd - dict->currentOffset; dict->dictionary = p; dict->dictSize = (U32)(dictEnd - p); dict->tableType = (U32)tableType; + idx32 = dict->currentOffset - dict->dictSize; while (p <= dictEnd-HASH_UNIT) { - LZ4_putPosition(p, dict->hashTable, tableType, base); - p+=3; + U32 const h = LZ4_hashPosition(p, tableType); + /* Note: overwriting => favors positions end of dictionary */ + LZ4_putIndexOnHash(idx32, h, dict->hashTable, tableType); + p+=3; idx32+=3; + } + + if (_ld == _ld_slow) { + /* Fill hash table with additional references, to improve compression capability */ + p = dict->dictionary; + idx32 = dict->currentOffset - dict->dictSize; + while (p <= dictEnd-HASH_UNIT) { + U32 const h = LZ4_hashPosition(p, tableType); + U32 const limit = dict->currentOffset - 64 KB; + if (LZ4_getIndexOnHash(h, dict->hashTable, tableType) <= limit) { + /* Note: not overwriting => favors positions beginning of dictionary */ + LZ4_putIndexOnHash(idx32, h, dict->hashTable, tableType); + } + p++; idx32++; + } } return (int)dict->dictSize; } +int LZ4_loadDict(LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +{ + return LZ4_loadDict_internal(LZ4_dict, dictionary, dictSize, _ld_fast); +} + +int LZ4_loadDictSlow(LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +{ + return LZ4_loadDict_internal(LZ4_dict, dictionary, dictSize, _ld_slow); +} + void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream) { const LZ4_stream_t_internal* dictCtx = (dictionaryStream == NULL) ? NULL : @@ -1711,7 +1786,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, /* Hidden debug function, to force-test external dictionary mode */ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize) { - LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; + LZ4_stream_t_internal* const streamPtr = &LZ4_dict->internal_donotuse; int result; LZ4_renormDictT(streamPtr, srcSize); @@ -1774,7 +1849,7 @@ typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; * does not know end of input * presumes input is well formed * note : will consume at least one byte */ -size_t read_long_length_no_check(const BYTE** pp) +static size_t read_long_length_no_check(const BYTE** pp) { size_t b, l = 0; do { b = **pp; (*pp)++; l += b; } while (b==255); @@ -1911,6 +1986,17 @@ read_variable_length(const BYTE** ip, const BYTE* ilimit, if (initial_check && unlikely((*ip) >= ilimit)) { /* read limit reached */ return rvl_error; } + s = **ip; + (*ip)++; + length += s; + if (unlikely((*ip) > ilimit)) { /* read limit reached */ + return rvl_error; + } + /* accumulator overflow detection (32-bit mode only) */ + if ((sizeof(length) < 8) && unlikely(length > ((Rvl_t)(-1)/2)) ) { + return rvl_error; + } + if (likely(s != 255)) return length; do { s = **ip; (*ip)++; @@ -1919,10 +2005,10 @@ read_variable_length(const BYTE** ip, const BYTE* ilimit, return rvl_error; } /* accumulator overflow detection (32-bit mode only) */ - if ((sizeof(length)<8) && unlikely(length > ((Rvl_t)(-1)/2)) ) { + if ((sizeof(length) < 8) && unlikely(length > ((Rvl_t)(-1)/2)) ) { return rvl_error; } - } while (s==255); + } while (s == 255); return length; } @@ -1988,63 +2074,73 @@ LZ4_decompress_generic( * note : fast loop may show a regression for some client arm chips. */ #if LZ4_FAST_DEC_LOOP if ((oend - op) < FASTLOOP_SAFE_DISTANCE) { - DEBUGLOG(6, "skip fast decode loop"); + DEBUGLOG(6, "move to safe decode loop"); goto safe_decode; } /* Fast loop : decode sequences as long as output < oend-FASTLOOP_SAFE_DISTANCE */ + DEBUGLOG(6, "using fast decode loop"); while (1) { /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */ assert(oend - op >= FASTLOOP_SAFE_DISTANCE); assert(ip < iend); token = *ip++; length = token >> ML_BITS; /* literal length */ + DEBUGLOG(7, "blockPos%6u: litLength token = %u", (unsigned)(op-(BYTE*)dst), (unsigned)length); /* decode literal length */ if (length == RUN_MASK) { size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1); - if (addl == rvl_error) { goto _output_error; } + if (addl == rvl_error) { + DEBUGLOG(6, "error reading long literal length"); + goto _output_error; + } length += addl; if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ /* copy literals */ - cpy = op+length; LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); - if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; } - LZ4_wildCopy32(op, ip, cpy); - ip += length; op = cpy; - } else { - cpy = op+length; - DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length); + if ((op+length>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; } + LZ4_wildCopy32(op, ip, op+length); + ip += length; op += length; + } else if (ip <= iend-(16 + 1/*max lit + offset + nextToken*/)) { /* We don't need to check oend, since we check it once for each loop below */ - if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; } + DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length); /* Literals can only be <= 14, but hope compilers optimize better when copy by a register size */ LZ4_memcpy(op, ip, 16); - ip += length; op = cpy; + ip += length; op += length; + } else { + goto safe_literal_copy; } /* get offset */ offset = LZ4_readLE16(ip); ip+=2; + DEBUGLOG(6, "blockPos%6u: offset = %u", (unsigned)(op-(BYTE*)dst), (unsigned)offset); match = op - offset; assert(match <= op); /* overflow check */ /* get matchlength */ length = token & ML_MASK; + DEBUGLOG(7, " match length token = %u (len==%u)", (unsigned)length, (unsigned)length+MINMATCH); if (length == ML_MASK) { size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0); - if (addl == rvl_error) { goto _output_error; } + if (addl == rvl_error) { + DEBUGLOG(5, "error reading long match length"); + goto _output_error; + } length += addl; length += MINMATCH; + DEBUGLOG(7, " long match length == %u", (unsigned)length); if (unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */ - if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { goto safe_match_copy; } } else { length += MINMATCH; if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { + DEBUGLOG(7, "moving to safe_match_copy (ml==%u)", (unsigned)length); goto safe_match_copy; } @@ -2062,7 +2158,10 @@ LZ4_decompress_generic( continue; } } } - if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ + if ( checkOffset && (unlikely(match + dictSize < lowPrefix)) ) { + DEBUGLOG(5, "Error : pos=%zi, offset=%zi => outside buffers", op-lowPrefix, op-match); + goto _output_error; + } /* match starting within external dictionary */ if ((dict==usingExtDict) && (match < lowPrefix)) { assert(dictEnd != NULL); @@ -2071,7 +2170,8 @@ LZ4_decompress_generic( DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd"); length = MIN(length, (size_t)(oend-op)); } else { - goto _output_error; /* end-of-block condition violated */ + DEBUGLOG(6, "end-of-block condition violated") + goto _output_error; } } if (length <= (size_t)(lowPrefix-match)) { @@ -2111,10 +2211,12 @@ LZ4_decompress_generic( #endif /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */ + DEBUGLOG(6, "using safe decode loop"); while (1) { assert(ip < iend); token = *ip++; length = token >> ML_BITS; /* literal length */ + DEBUGLOG(7, "blockPos%6u: litLength token = %u", (unsigned)(op-(BYTE*)dst), (unsigned)length); /* A two-stage shortcut for the most common case: * 1) If the literal length is 0..14, and there is enough space, @@ -2135,6 +2237,7 @@ LZ4_decompress_generic( /* The second stage: prepare for match copying, decode full info. * If it doesn't work out, the info won't be wasted. */ length = token & ML_MASK; /* match length */ + DEBUGLOG(7, "blockPos%6u: matchLength token = %u (len=%u)", (unsigned)(op-(BYTE*)dst), (unsigned)length, (unsigned)length + 4); offset = LZ4_readLE16(ip); ip += 2; match = op - offset; assert(match <= op); /* check overflow */ @@ -2166,11 +2269,12 @@ LZ4_decompress_generic( if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ } - /* copy literals */ - cpy = op+length; #if LZ4_FAST_DEC_LOOP safe_literal_copy: #endif + /* copy literals */ + cpy = op+length; + LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) { /* We've either hit the input parsing restriction or the output parsing restriction. @@ -2206,9 +2310,10 @@ LZ4_decompress_generic( * so check that we exactly consume the input and don't overrun the output buffer. */ if ((ip+length != iend) || (cpy > oend)) { - DEBUGLOG(6, "should have been last run of literals") - DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend); - DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend); + DEBUGLOG(5, "should have been last run of literals") + DEBUGLOG(5, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend); + DEBUGLOG(5, "or cpy(%p) > (oend-MFLIMIT)(%p)", cpy, oend-MFLIMIT); + DEBUGLOG(5, "after writing %u bytes / %i bytes available", (unsigned)(op-(BYTE*)dst), outputSize); goto _output_error; } } @@ -2234,6 +2339,7 @@ LZ4_decompress_generic( /* get matchlength */ length = token & ML_MASK; + DEBUGLOG(7, "blockPos%6u: matchLength token = %u", (unsigned)(op-(BYTE*)dst), (unsigned)length); _copy_match: if (length == ML_MASK) { @@ -2323,7 +2429,7 @@ LZ4_decompress_generic( while (op < cpy) { *op++ = *match++; } } else { LZ4_memcpy(op, match, 8); - if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); } + if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); } } op = cpy; /* wildcopy correction */ } @@ -2418,6 +2524,7 @@ int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const void* dictStart, size_t dictSize) { + DEBUGLOG(5, "LZ4_decompress_safe_forceExtDict"); return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, decode_full_block, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4.h b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4.h similarity index 88% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4.h rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4.h index 491c6087c41..80e3e5ca04d 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4.h +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4.h @@ -1,7 +1,7 @@ /* * LZ4 - Fast LZ compression algorithm * Header File - * Copyright (C) 2011-2020, Yann Collet. + * Copyright (C) 2011-2023, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) @@ -129,8 +129,8 @@ extern "C" { /*------ Version ------*/ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ -#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */ -#define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */ +#define LZ4_VERSION_MINOR 10 /* for new (non-breaking) interface capabilities */ +#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */ #define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) @@ -144,23 +144,25 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; /*-************************************ -* Tuning parameter +* Tuning memory usage **************************************/ -#define LZ4_MEMORY_USAGE_MIN 10 -#define LZ4_MEMORY_USAGE_DEFAULT 14 -#define LZ4_MEMORY_USAGE_MAX 20 - /*! * LZ4_MEMORY_USAGE : - * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; ) - * Increasing memory usage improves compression ratio, at the cost of speed. + * Can be selected at compile time, by setting LZ4_MEMORY_USAGE. + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB) + * Increasing memory usage improves compression ratio, generally at the cost of speed. * Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality. - * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + * Default value is 14, for 16KB, which nicely fits into most L1 caches. */ #ifndef LZ4_MEMORY_USAGE # define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT #endif +/* These are absolute limits, they should not be changed by users */ +#define LZ4_MEMORY_USAGE_MIN 10 +#define LZ4_MEMORY_USAGE_DEFAULT 14 +#define LZ4_MEMORY_USAGE_MAX 20 + #if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN) # error "LZ4_MEMORY_USAGE is too small !" #endif @@ -189,8 +191,9 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity); /*! LZ4_decompress_safe() : - * compressedSize : is the exact complete size of the compressed block. - * dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size. + * @compressedSize : is the exact complete size of the compressed block. + * @dstCapacity : is the size of destination buffer (which must be already allocated), + * presumed an upper bound of decompressed size. * @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity) * If destination buffer is not large enough, decoding will stop and output an error code (negative value). * If the source stream is detected malformed, the function will stop decoding and return a negative result. @@ -242,20 +245,20 @@ LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int d LZ4LIB_API int LZ4_sizeofState(void); LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); - /*! LZ4_compress_destSize() : * Reverse the logic : compresses as much data as possible from 'src' buffer - * into already allocated buffer 'dst', of size >= 'targetDestSize'. + * into already allocated buffer 'dst', of size >= 'dstCapacity'. * This function either compresses the entire 'src' content into 'dst' if it's large enough, * or fill 'dst' buffer completely with as much data as possible from 'src'. * note: acceleration parameter is fixed to "default". * - * *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'. + * *srcSizePtr : in+out parameter. Initially contains size of input. + * Will be modified to indicate how many bytes where read from 'src' to fill 'dst'. * New value is necessarily <= input value. - * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize) + * @return : Nb bytes written into 'dst' (necessarily <= dstCapacity) * or 0 if compression fails. * - * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+): + * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed in v1.9.2+): * the produced compressed content could, in specific circumstances, * require to be decompressed into a destination buffer larger * by at least 1 byte than the content to decompress. @@ -266,8 +269,7 @@ LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* d * a dstCapacity which is > decompressedSize, by at least 1 byte. * See https://github.com/lz4/lz4/issues/859 for details */ -LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize); - +LZ4LIB_API int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize); /*! LZ4_decompress_safe_partial() : * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src', @@ -311,7 +313,7 @@ LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcS ***********************************************/ typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ -/** +/*! Note about RC_INVOKED - RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio). @@ -361,13 +363,58 @@ LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); * LZ4_loadDict() triggers a reset, so any previous data will be forgotten. * The same dictionary will have to be loaded on decompression side for successful decoding. * Dictionary are useful for better compression of small data (KB range). - * While LZ4 accept any input as dictionary, - * results are generally better when using Zstandard's Dictionary Builder. + * While LZ4 itself accepts any input as dictionary, dictionary efficiency is also a topic. + * When in doubt, employ the Zstandard's Dictionary Builder. * Loading a size of 0 is allowed, and is the same as reset. - * @return : loaded dictionary size, in bytes (necessarily <= 64 KB) + * @return : loaded dictionary size, in bytes (note: only the last 64 KB are loaded) */ LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); +/*! LZ4_loadDictSlow() : v1.10.0+ + * Same as LZ4_loadDict(), + * but uses a bit more cpu to reference the dictionary content more thoroughly. + * This is expected to slightly improve compression ratio. + * The extra-cpu cost is likely worth it if the dictionary is re-used across multiple sessions. + * @return : loaded dictionary size, in bytes (note: only the last 64 KB are loaded) + */ +LZ4LIB_API int LZ4_loadDictSlow(LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/*! LZ4_attach_dictionary() : stable since v1.10.0 + * + * This allows efficient re-use of a static dictionary multiple times. + * + * Rather than re-loading the dictionary buffer into a working context before + * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a + * working LZ4_stream_t, this function introduces a no-copy setup mechanism, + * in which the working stream references @dictionaryStream in-place. + * + * Several assumptions are made about the state of @dictionaryStream. + * Currently, only states which have been prepared by LZ4_loadDict() or + * LZ4_loadDictSlow() should be expected to work. + * + * Alternatively, the provided @dictionaryStream may be NULL, + * in which case any existing dictionary stream is unset. + * + * If a dictionary is provided, it replaces any pre-existing stream history. + * The dictionary contents are the only history that can be referenced and + * logically immediately precede the data compressed in the first subsequent + * compression call. + * + * The dictionary will only remain attached to the working stream through the + * first compression call, at the end of which it is cleared. + * @dictionaryStream stream (and source buffer) must remain in-place / accessible / unchanged + * through the completion of the compression session. + * + * Note: there is no equivalent LZ4_attach_*() method on the decompression side + * because there is no initialization cost, hence no need to share the cost across multiple sessions. + * To decompress LZ4 blocks using dictionary, attached or not, + * just employ the regular LZ4_setStreamDecode() for streaming, + * or the stateless LZ4_decompress_safe_usingDict() for one-shot decompression. + */ +LZ4LIB_API void +LZ4_attach_dictionary(LZ4_stream_t* workingStream, + const LZ4_stream_t* dictionaryStream); + /*! LZ4_compress_fast_continue() : * Compress 'src' content using data from previously compressed blocks, for better compression ratio. * 'dst' buffer must be already allocated. @@ -443,11 +490,24 @@ LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize); #define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */ -/*! LZ4_decompress_*_continue() : - * These decoding functions allow decompression of consecutive blocks in "streaming" mode. - * A block is an unsplittable entity, it must be presented entirely to a decompression function. - * Decompression functions only accepts one block at a time. - * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded. +/*! LZ4_decompress_safe_continue() : + * This decoding function allows decompression of consecutive blocks in "streaming" mode. + * The difference with the usual independent blocks is that + * new blocks are allowed to find references into former blocks. + * A block is an unsplittable entity, and must be presented entirely to the decompression function. + * LZ4_decompress_safe_continue() only accepts one block at a time. + * It's modeled after `LZ4_decompress_safe()` and behaves similarly. + * + * @LZ4_streamDecode : decompression state, tracking the position in memory of past data + * @compressedSize : exact complete size of one compressed block. + * @dstCapacity : size of destination buffer (which must be already allocated), + * must be an upper bound of decompressed size. + * @return : number of bytes decompressed into destination buffer (necessarily <= dstCapacity) + * If destination buffer is not large enough, decoding will stop and output an error code (negative value). + * If the source stream is detected malformed, the function will stop decoding and return a negative result. + * + * The last 64KB of previously decoded data *must* remain available and unmodified + * at the memory position where they were previously decoded. * If less than 64KB of data has been decoded, all the data must be present. * * Special : if decompression side sets a ring buffer, it must respect one of the following conditions : @@ -474,10 +534,10 @@ LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, int srcSize, int dstCapacity); -/*! LZ4_decompress_*_usingDict() : - * These decoding functions work the same as - * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() - * They are stand-alone, and don't need an LZ4_streamDecode_t structure. +/*! LZ4_decompress_safe_usingDict() : + * Works the same as + * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_safe_continue() + * However, it's stateless: it doesn't need any LZ4_streamDecode_t state. * Dictionary is presumed stable : it must remain accessible and unmodified during decompression. * Performance tip : Decompression speed can be substantially increased * when dst == dictStart + dictSize. @@ -487,6 +547,12 @@ LZ4_decompress_safe_usingDict(const char* src, char* dst, int srcSize, int dstCapacity, const char* dictStart, int dictSize); +/*! LZ4_decompress_safe_partial_usingDict() : + * Behaves the same as LZ4_decompress_safe_partial() + * with the added ability to specify a memory segment for past data. + * Performance tip : Decompression speed can be substantially increased + * when dst == dictStart + dictSize. + */ LZ4LIB_API int LZ4_decompress_safe_partial_usingDict(const char* src, char* dst, int compressedSize, @@ -526,9 +592,9 @@ LZ4_decompress_safe_partial_usingDict(const char* src, char* dst, #define LZ4_STATIC_3504398509 #ifdef LZ4_PUBLISH_STATIC_FUNCTIONS -#define LZ4LIB_STATIC_API LZ4LIB_API +# define LZ4LIB_STATIC_API LZ4LIB_API #else -#define LZ4LIB_STATIC_API +# define LZ4LIB_STATIC_API #endif @@ -544,36 +610,11 @@ LZ4_decompress_safe_partial_usingDict(const char* src, char* dst, */ LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); -/*! LZ4_attach_dictionary() : - * This is an experimental API that allows - * efficient use of a static dictionary many times. - * - * Rather than re-loading the dictionary buffer into a working context before - * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a - * working LZ4_stream_t, this function introduces a no-copy setup mechanism, - * in which the working stream references the dictionary stream in-place. - * - * Several assumptions are made about the state of the dictionary stream. - * Currently, only streams which have been prepared by LZ4_loadDict() should - * be expected to work. - * - * Alternatively, the provided dictionaryStream may be NULL, - * in which case any existing dictionary stream is unset. - * - * If a dictionary is provided, it replaces any pre-existing stream history. - * The dictionary contents are the only history that can be referenced and - * logically immediately precede the data compressed in the first subsequent - * compression call. - * - * The dictionary will only remain attached to the working stream through the - * first compression call, at the end of which it is cleared. The dictionary - * stream (and source buffer) must remain in-place / accessible / unchanged - * through the completion of the first compression call on the stream. +/*! LZ4_compress_destSize_extState() : introduced in v1.10.0 + * Same as LZ4_compress_destSize(), but using an externally allocated state. + * Also: exposes @acceleration */ -LZ4LIB_STATIC_API void -LZ4_attach_dictionary(LZ4_stream_t* workingStream, - const LZ4_stream_t* dictionaryStream); - +int LZ4_compress_destSize_extState(void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration); /*! In-place compression and decompression * @@ -685,7 +726,7 @@ struct LZ4_stream_t_internal { /* Implicit padding to ensure structure is aligned */ }; -#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */ +#define LZ4_STREAM_MINSIZE ((1UL << (LZ4_MEMORY_USAGE)) + 32) /* static size, for inter-version compatibility */ union LZ4_stream_u { char minStateSize[LZ4_STREAM_MINSIZE]; LZ4_stream_t_internal internal_donotuse; @@ -706,7 +747,7 @@ union LZ4_stream_u { * Note2: An LZ4_stream_t structure guarantees correct alignment and size. * Note3: Before v1.9.0, use LZ4_resetStream() instead **/ -LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); +LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* stateBuffer, size_t size); /*! LZ4_streamDecode_t : @@ -818,11 +859,12 @@ LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4 * But they may happen if input data is invalid (error or intentional tampering). * As a consequence, use these functions in trusted environments with trusted data **only**. */ -LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead") +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_partial() instead") LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize); -LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead") +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider migrating towards LZ4_decompress_safe_continue() instead. " + "Note that the contract will change (requires block's compressed size, instead of decompressed size)") LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize); -LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead") +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_partial_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize); /*! LZ4_resetStream() : diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4file.c b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4file.c similarity index 67% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4file.c rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4file.c index eaf9b1704d2..a4197ea80dd 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4file.c +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4file.c @@ -31,11 +31,21 @@ * - LZ4 homepage : http://www.lz4.org * - LZ4 source repository : https://github.com/lz4/lz4 */ -#include +#include /* malloc, free */ #include +#include #include "lz4.h" #include "lz4file.h" +static LZ4F_errorCode_t returnErrorCode(LZ4F_errorCodes code) +{ + return (LZ4F_errorCode_t)-(ptrdiff_t)code; +} +#undef RETURN_ERROR +#define RETURN_ERROR(e) return returnErrorCode(LZ4F_ERROR_ ## e) + +/* ===== read API ===== */ + struct LZ4_readFile_s { LZ4F_dctx* dctxPtr; FILE* fp; @@ -45,76 +55,80 @@ struct LZ4_readFile_s { size_t srcBufMaxSize; }; -struct LZ4_writeFile_s { - LZ4F_cctx* cctxPtr; - FILE* fp; - LZ4_byte* dstBuf; - size_t maxWriteSize; - size_t dstBufMaxSize; - LZ4F_errorCode_t errCode; -}; +static void LZ4F_freeReadFile(LZ4_readFile_t* lz4fRead) +{ + if (lz4fRead==NULL) return; + LZ4F_freeDecompressionContext(lz4fRead->dctxPtr); + free(lz4fRead->srcBuf); + free(lz4fRead); +} + +static void LZ4F_freeAndNullReadFile(LZ4_readFile_t** statePtr) +{ + assert(statePtr != NULL); + LZ4F_freeReadFile(*statePtr); + *statePtr = NULL; +} LZ4F_errorCode_t LZ4F_readOpen(LZ4_readFile_t** lz4fRead, FILE* fp) { char buf[LZ4F_HEADER_SIZE_MAX]; size_t consumedSize; LZ4F_errorCode_t ret; - LZ4F_frameInfo_t info; if (fp == NULL || lz4fRead == NULL) { - return -LZ4F_ERROR_GENERIC; + RETURN_ERROR(parameter_null); } *lz4fRead = (LZ4_readFile_t*)calloc(1, sizeof(LZ4_readFile_t)); if (*lz4fRead == NULL) { - return -LZ4F_ERROR_allocation_failed; + RETURN_ERROR(allocation_failed); } - ret = LZ4F_createDecompressionContext(&(*lz4fRead)->dctxPtr, LZ4F_getVersion()); + ret = LZ4F_createDecompressionContext(&(*lz4fRead)->dctxPtr, LZ4F_VERSION); if (LZ4F_isError(ret)) { - free(*lz4fRead); + LZ4F_freeAndNullReadFile(lz4fRead); return ret; } (*lz4fRead)->fp = fp; consumedSize = fread(buf, 1, sizeof(buf), (*lz4fRead)->fp); if (consumedSize != sizeof(buf)) { - free(*lz4fRead); - return -LZ4F_ERROR_GENERIC; + LZ4F_freeAndNullReadFile(lz4fRead); + RETURN_ERROR(io_read); } - ret = LZ4F_getFrameInfo((*lz4fRead)->dctxPtr, &info, buf, &consumedSize); - if (LZ4F_isError(ret)) { - LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr); - free(*lz4fRead); - return ret; + { LZ4F_frameInfo_t info; + LZ4F_errorCode_t const r = LZ4F_getFrameInfo((*lz4fRead)->dctxPtr, &info, buf, &consumedSize); + if (LZ4F_isError(r)) { + LZ4F_freeAndNullReadFile(lz4fRead); + return r; } - switch (info.blockSizeID) { - case LZ4F_default : - case LZ4F_max64KB : - (*lz4fRead)->srcBufMaxSize = 64 * 1024; - break; - case LZ4F_max256KB: - (*lz4fRead)->srcBufMaxSize = 256 * 1024; - break; - case LZ4F_max1MB: - (*lz4fRead)->srcBufMaxSize = 1 * 1024 * 1024; - break; - case LZ4F_max4MB: - (*lz4fRead)->srcBufMaxSize = 4 * 1024 * 1024; - break; - default: - LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr); - free(*lz4fRead); - return -LZ4F_ERROR_maxBlockSize_invalid; + switch (info.blockSizeID) { + case LZ4F_default : + case LZ4F_max64KB : + (*lz4fRead)->srcBufMaxSize = 64 * 1024; + break; + case LZ4F_max256KB: + (*lz4fRead)->srcBufMaxSize = 256 * 1024; + break; + case LZ4F_max1MB: + (*lz4fRead)->srcBufMaxSize = 1 * 1024 * 1024; + break; + case LZ4F_max4MB: + (*lz4fRead)->srcBufMaxSize = 4 * 1024 * 1024; + break; + default: + LZ4F_freeAndNullReadFile(lz4fRead); + RETURN_ERROR(maxBlockSize_invalid); + } } (*lz4fRead)->srcBuf = (LZ4_byte*)malloc((*lz4fRead)->srcBufMaxSize); if ((*lz4fRead)->srcBuf == NULL) { - LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr); - free(lz4fRead); - return -LZ4F_ERROR_allocation_failed; + LZ4F_freeAndNullReadFile(lz4fRead); + RETURN_ERROR(allocation_failed); } (*lz4fRead)->srcBufSize = sizeof(buf) - consumedSize; @@ -129,7 +143,7 @@ size_t LZ4F_read(LZ4_readFile_t* lz4fRead, void* buf, size_t size) size_t next = 0; if (lz4fRead == NULL || buf == NULL) - return -LZ4F_ERROR_GENERIC; + RETURN_ERROR(parameter_null); while (next < size) { size_t srcsize = lz4fRead->srcBufSize - lz4fRead->srcBufNext; @@ -142,12 +156,10 @@ size_t LZ4F_read(LZ4_readFile_t* lz4fRead, void* buf, size_t size) lz4fRead->srcBufSize = ret; srcsize = lz4fRead->srcBufSize; lz4fRead->srcBufNext = 0; - } - else if (ret == 0) { + } else if (ret == 0) { break; - } - else { - return -LZ4F_ERROR_GENERIC; + } else { + RETURN_ERROR(io_read); } } @@ -171,24 +183,48 @@ size_t LZ4F_read(LZ4_readFile_t* lz4fRead, void* buf, size_t size) LZ4F_errorCode_t LZ4F_readClose(LZ4_readFile_t* lz4fRead) { if (lz4fRead == NULL) - return -LZ4F_ERROR_GENERIC; - LZ4F_freeDecompressionContext(lz4fRead->dctxPtr); - free(lz4fRead->srcBuf); - free(lz4fRead); + RETURN_ERROR(parameter_null); + LZ4F_freeReadFile(lz4fRead); return LZ4F_OK_NoError; } +/* ===== write API ===== */ + +struct LZ4_writeFile_s { + LZ4F_cctx* cctxPtr; + FILE* fp; + LZ4_byte* dstBuf; + size_t maxWriteSize; + size_t dstBufMaxSize; + LZ4F_errorCode_t errCode; +}; + +static void LZ4F_freeWriteFile(LZ4_writeFile_t* state) +{ + if (state == NULL) return; + LZ4F_freeCompressionContext(state->cctxPtr); + free(state->dstBuf); + free(state); +} + +static void LZ4F_freeAndNullWriteFile(LZ4_writeFile_t** statePtr) +{ + assert(statePtr != NULL); + LZ4F_freeWriteFile(*statePtr); + *statePtr = NULL; +} + LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4F_preferences_t* prefsPtr) { LZ4_byte buf[LZ4F_HEADER_SIZE_MAX]; size_t ret; if (fp == NULL || lz4fWrite == NULL) - return -LZ4F_ERROR_GENERIC; + RETURN_ERROR(parameter_null); - *lz4fWrite = (LZ4_writeFile_t*)malloc(sizeof(LZ4_writeFile_t)); + *lz4fWrite = (LZ4_writeFile_t*)calloc(1, sizeof(LZ4_writeFile_t)); if (*lz4fWrite == NULL) { - return -LZ4F_ERROR_allocation_failed; + RETURN_ERROR(allocation_failed); } if (prefsPtr != NULL) { switch (prefsPtr->frameInfo.blockSizeID) { @@ -206,8 +242,8 @@ LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4 (*lz4fWrite)->maxWriteSize = 4 * 1024 * 1024; break; default: - free(lz4fWrite); - return -LZ4F_ERROR_maxBlockSize_invalid; + LZ4F_freeAndNullWriteFile(lz4fWrite); + RETURN_ERROR(maxBlockSize_invalid); } } else { (*lz4fWrite)->maxWriteSize = 64 * 1024; @@ -216,30 +252,25 @@ LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4 (*lz4fWrite)->dstBufMaxSize = LZ4F_compressBound((*lz4fWrite)->maxWriteSize, prefsPtr); (*lz4fWrite)->dstBuf = (LZ4_byte*)malloc((*lz4fWrite)->dstBufMaxSize); if ((*lz4fWrite)->dstBuf == NULL) { - free(*lz4fWrite); - return -LZ4F_ERROR_allocation_failed; + LZ4F_freeAndNullWriteFile(lz4fWrite); + RETURN_ERROR(allocation_failed); } - ret = LZ4F_createCompressionContext(&(*lz4fWrite)->cctxPtr, LZ4F_getVersion()); + ret = LZ4F_createCompressionContext(&(*lz4fWrite)->cctxPtr, LZ4F_VERSION); if (LZ4F_isError(ret)) { - free((*lz4fWrite)->dstBuf); - free(*lz4fWrite); + LZ4F_freeAndNullWriteFile(lz4fWrite); return ret; } ret = LZ4F_compressBegin((*lz4fWrite)->cctxPtr, buf, LZ4F_HEADER_SIZE_MAX, prefsPtr); if (LZ4F_isError(ret)) { - LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr); - free((*lz4fWrite)->dstBuf); - free(*lz4fWrite); + LZ4F_freeAndNullWriteFile(lz4fWrite); return ret; } if (ret != fwrite(buf, 1, ret, fp)) { - LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr); - free((*lz4fWrite)->dstBuf); - free(*lz4fWrite); - return -LZ4F_ERROR_GENERIC; + LZ4F_freeAndNullWriteFile(lz4fWrite); + RETURN_ERROR(io_write); } (*lz4fWrite)->fp = fp; @@ -247,15 +278,15 @@ LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4 return LZ4F_OK_NoError; } -size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, void* buf, size_t size) +size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, const void* buf, size_t size) { - LZ4_byte* p = (LZ4_byte*)buf; + const LZ4_byte* p = (const LZ4_byte*)buf; size_t remain = size; size_t chunk; size_t ret; if (lz4fWrite == NULL || buf == NULL) - return -LZ4F_ERROR_GENERIC; + RETURN_ERROR(parameter_null); while (remain) { if (remain > lz4fWrite->maxWriteSize) chunk = lz4fWrite->maxWriteSize; @@ -271,9 +302,9 @@ size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, void* buf, size_t size) return ret; } - if(ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) { - lz4fWrite->errCode = -LZ4F_ERROR_GENERIC; - return -LZ4F_ERROR_GENERIC; + if (ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) { + lz4fWrite->errCode = returnErrorCode(LZ4F_ERROR_io_write); + RETURN_ERROR(io_write); } p += chunk; @@ -287,8 +318,9 @@ LZ4F_errorCode_t LZ4F_writeClose(LZ4_writeFile_t* lz4fWrite) { LZ4F_errorCode_t ret = LZ4F_OK_NoError; - if (lz4fWrite == NULL) - return -LZ4F_ERROR_GENERIC; + if (lz4fWrite == NULL) { + RETURN_ERROR(parameter_null); + } if (lz4fWrite->errCode == LZ4F_OK_NoError) { ret = LZ4F_compressEnd(lz4fWrite->cctxPtr, @@ -299,13 +331,11 @@ LZ4F_errorCode_t LZ4F_writeClose(LZ4_writeFile_t* lz4fWrite) } if (ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) { - ret = -LZ4F_ERROR_GENERIC; + ret = returnErrorCode(LZ4F_ERROR_io_write); } } out: - LZ4F_freeCompressionContext(lz4fWrite->cctxPtr); - free(lz4fWrite->dstBuf); - free(lz4fWrite); + LZ4F_freeWriteFile(lz4fWrite); return ret; } diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4file.h b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4file.h similarity index 98% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4file.h rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4file.h index 5527130720f..598ad705ea9 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4file.h +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4file.h @@ -38,7 +38,7 @@ extern "C" { #ifndef LZ4FILE_H #define LZ4FILE_H -#include +#include /* FILE* */ #include "lz4frame_static.h" typedef struct LZ4_readFile_s LZ4_readFile_t; @@ -78,7 +78,7 @@ LZ4FLIB_STATIC_API LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, * `buf` write data buffer. * `size` write data buffer size. */ -LZ4FLIB_STATIC_API size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, void* buf, size_t size); +LZ4FLIB_STATIC_API size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, const void* buf, size_t size); /*! LZ4F_writeClose() : * Close lz4file handle. diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4frame.c b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame.c similarity index 89% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4frame.c rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame.c index 174f9ae4f21..f89c0557995 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4frame.c +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame.c @@ -44,6 +44,7 @@ /*-************************************ * Compiler Options **************************************/ +#include #ifdef _MSC_VER /* Visual Studio */ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ #endif @@ -54,8 +55,8 @@ **************************************/ /* * LZ4F_HEAPMODE : - * Select how default compression functions will allocate memory for their hash table, - * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). + * Control how LZ4F_compressFrame allocates the Compression State, + * either on stack (0:default, fastest), or in memory heap (1:requires malloc()). */ #ifndef LZ4F_HEAPMODE # define LZ4F_HEAPMODE 0 @@ -125,8 +126,9 @@ static void* LZ4F_malloc(size_t s, LZ4F_CustomMem cmem) static void LZ4F_free(void* p, LZ4F_CustomMem cmem) { - /* custom malloc defined : use it */ + if (p == NULL) return; if (cmem.customFree != NULL) { + /* custom allocation defined : use it */ cmem.customFree(cmem.opaqueState, p); return; } @@ -153,7 +155,7 @@ static void LZ4F_free(void* p, LZ4F_CustomMem cmem) static int g_debuglog_enable = 1; # define DEBUGLOG(l, ...) { \ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ - fprintf(stderr, __FILE__ ": "); \ + fprintf(stderr, __FILE__ " (%i): ", __LINE__ ); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, " \n"); \ } } @@ -186,9 +188,9 @@ static U32 LZ4F_readLE32 (const void* src) { const BYTE* const srcPtr = (const BYTE*)src; U32 value32 = srcPtr[0]; - value32 += ((U32)srcPtr[1])<< 8; - value32 += ((U32)srcPtr[2])<<16; - value32 += ((U32)srcPtr[3])<<24; + value32 |= ((U32)srcPtr[1])<< 8; + value32 |= ((U32)srcPtr[2])<<16; + value32 |= ((U32)srcPtr[3])<<24; return value32; } @@ -205,13 +207,13 @@ static U64 LZ4F_readLE64 (const void* src) { const BYTE* const srcPtr = (const BYTE*)src; U64 value64 = srcPtr[0]; - value64 += ((U64)srcPtr[1]<<8); - value64 += ((U64)srcPtr[2]<<16); - value64 += ((U64)srcPtr[3]<<24); - value64 += ((U64)srcPtr[4]<<32); - value64 += ((U64)srcPtr[5]<<40); - value64 += ((U64)srcPtr[6]<<48); - value64 += ((U64)srcPtr[7]<<56); + value64 |= ((U64)srcPtr[1]<<8); + value64 |= ((U64)srcPtr[2]<<16); + value64 |= ((U64)srcPtr[3]<<24); + value64 |= ((U64)srcPtr[4]<<32); + value64 |= ((U64)srcPtr[5]<<40); + value64 |= ((U64)srcPtr[6]<<48); + value64 |= ((U64)srcPtr[7]<<56); return value64; } @@ -257,14 +259,15 @@ static const size_t BFSize = LZ4F_BLOCK_CHECKSUM_SIZE; /* block footer : checks * Structures and local types **************************************/ -typedef enum { LZ4B_COMPRESSED, LZ4B_UNCOMPRESSED} LZ4F_blockCompression_t; +typedef enum { LZ4B_COMPRESSED, LZ4B_UNCOMPRESSED} LZ4F_BlockCompressMode_e; +typedef enum { ctxNone, ctxFast, ctxHC } LZ4F_CtxType_e; typedef struct LZ4F_cctx_s { LZ4F_CustomMem cmem; LZ4F_preferences_t prefs; U32 version; - U32 cStage; + U32 cStage; /* 0 : compression uninitialized ; 1 : initialized, can compress */ const LZ4F_CDict* cdict; size_t maxBlockSize; size_t maxBufferSize; @@ -275,8 +278,8 @@ typedef struct LZ4F_cctx_s XXH32_state_t xxh; void* lz4CtxPtr; U16 lz4CtxAlloc; /* sized for: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */ - U16 lz4CtxState; /* in use as: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */ - LZ4F_blockCompression_t blockCompression; + U16 lz4CtxType; /* in use as: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */ + LZ4F_BlockCompressMode_e blockCompressMode; } LZ4F_cctx_t; @@ -314,9 +317,14 @@ static LZ4F_errorCode_t LZ4F_returnErrorCode(LZ4F_errorCodes code) #define RETURN_ERROR(e) return LZ4F_returnErrorCode(LZ4F_ERROR_ ## e) -#define RETURN_ERROR_IF(c,e) if (c) RETURN_ERROR(e) +#define RETURN_ERROR_IF(c,e) do { \ + if (c) { \ + DEBUGLOG(3, "Error: " #c); \ + RETURN_ERROR(e); \ + } \ + } while (0) -#define FORWARD_IF_ERROR(r) if (LZ4F_isError(r)) return (r) +#define FORWARD_IF_ERROR(r) do { if (LZ4F_isError(r)) return (r); } while (0) unsigned LZ4F_getVersion(void) { return LZ4F_VERSION; } @@ -429,6 +437,7 @@ size_t LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx, BYTE* dstPtr = dstStart; BYTE* const dstEnd = dstStart + dstCapacity; + DEBUGLOG(4, "LZ4F_compressFrame_usingCDict (srcSize=%u)", (unsigned)srcSize); if (preferencesPtr!=NULL) prefs = *preferencesPtr; else @@ -494,7 +503,7 @@ size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, LZ4_initStream(&lz4ctx, sizeof(lz4ctx)); cctxPtr->lz4CtxPtr = &lz4ctx; cctxPtr->lz4CtxAlloc = 1; - cctxPtr->lz4CtxState = 1; + cctxPtr->lz4CtxType = ctxFast; } #endif DEBUGLOG(4, "LZ4F_compressFrame"); @@ -539,18 +548,19 @@ LZ4F_createCDict_advanced(LZ4F_CustomMem cmem, const void* dictBuffer, size_t di dictSize = 64 KB; } cdict->dictContent = LZ4F_malloc(dictSize, cmem); + /* note: using @cmem to allocate => can't use default create */ cdict->fastCtx = (LZ4_stream_t*)LZ4F_malloc(sizeof(LZ4_stream_t), cmem); - if (cdict->fastCtx) - LZ4_initStream(cdict->fastCtx, sizeof(LZ4_stream_t)); cdict->HCCtx = (LZ4_streamHC_t*)LZ4F_malloc(sizeof(LZ4_streamHC_t), cmem); - if (cdict->HCCtx) - LZ4_initStream(cdict->HCCtx, sizeof(LZ4_streamHC_t)); if (!cdict->dictContent || !cdict->fastCtx || !cdict->HCCtx) { LZ4F_freeCDict(cdict); return NULL; } memcpy(cdict->dictContent, dictStart, dictSize); - LZ4_loadDict (cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize); + LZ4_initStream(cdict->fastCtx, sizeof(LZ4_stream_t)); + LZ4_loadDictSlow(cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize); + LZ4_initStreamHC(cdict->HCCtx, sizeof(LZ4_streamHC_t)); + /* note: we don't know at this point which compression level is going to be used + * as a consequence, HCCtx is created for the more common HC mode */ LZ4_setCompressionLevel(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT); LZ4_loadDictHC(cdict->HCCtx, (const char*)cdict->dictContent, (int)dictSize); return cdict; @@ -616,7 +626,6 @@ LZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned v return LZ4F_OK_NoError; } - LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr) { if (cctxPtr != NULL) { /* support free on NULL */ @@ -641,7 +650,7 @@ static void LZ4F_initStream(void* ctx, int level, LZ4F_blockMode_t blockMode) { if (level < LZ4HC_CLEVEL_MIN) { - if (cdict != NULL || blockMode == LZ4F_blockLinked) { + if (cdict || blockMode == LZ4F_blockLinked) { /* In these cases, we will call LZ4_compress_fast_continue(), * which needs an already reset context. Otherwise, we'll call a * one-shot API. The non-continued APIs internally perform their own @@ -649,11 +658,18 @@ static void LZ4F_initStream(void* ctx, * tableType they need the context to be in. So in that case this * would be misguided / wasted work. */ LZ4_resetStream_fast((LZ4_stream_t*)ctx); + if (cdict) + LZ4_attach_dictionary((LZ4_stream_t*)ctx, cdict->fastCtx); } - LZ4_attach_dictionary((LZ4_stream_t *)ctx, cdict ? cdict->fastCtx : NULL); + /* In these cases, we'll call a one-shot API. + * The non-continued APIs internally perform their own resets + * at the beginning of their calls, where they know + * which tableType they need the context to be in. + * Therefore, a reset here would be wasted work. */ } else { LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level); - LZ4_attach_HC_dictionary((LZ4_streamHC_t *)ctx, cdict ? cdict->HCCtx : NULL); + if (cdict) + LZ4_attach_HC_dictionary((LZ4_streamHC_t*)ctx, cdict->HCCtx); } } @@ -668,14 +684,12 @@ static int ctxTypeID_to_size(int ctxTypeID) { } } -/*! LZ4F_compressBegin_usingCDict() : - * init streaming compression AND writes frame header into @dstBuffer. - * @dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - * @return : number of bytes written into @dstBuffer for the header - * or an error code (can be tested using LZ4F_isError()) +/* LZ4F_compressBegin_internal() + * Note: only accepts @cdict _or_ @dictBuffer as non NULL. */ -size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, +size_t LZ4F_compressBegin_internal(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, + const void* dictBuffer, size_t dictSize, const LZ4F_CDict* cdict, const LZ4F_preferences_t* preferencesPtr) { @@ -685,70 +699,84 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, RETURN_ERROR_IF(dstCapacity < maxFHSize, dstMaxSize_tooSmall); if (preferencesPtr == NULL) preferencesPtr = &prefNull; - cctxPtr->prefs = *preferencesPtr; + cctx->prefs = *preferencesPtr; /* cctx Management */ - { U16 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; + { U16 const ctxTypeID = (cctx->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; int requiredSize = ctxTypeID_to_size(ctxTypeID); - int allocatedSize = ctxTypeID_to_size(cctxPtr->lz4CtxAlloc); + int allocatedSize = ctxTypeID_to_size(cctx->lz4CtxAlloc); if (allocatedSize < requiredSize) { /* not enough space allocated */ - LZ4F_free(cctxPtr->lz4CtxPtr, cctxPtr->cmem); - if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { + LZ4F_free(cctx->lz4CtxPtr, cctx->cmem); + if (cctx->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { /* must take ownership of memory allocation, * in order to respect custom allocator contract */ - cctxPtr->lz4CtxPtr = LZ4F_malloc(sizeof(LZ4_stream_t), cctxPtr->cmem); - if (cctxPtr->lz4CtxPtr) - LZ4_initStream(cctxPtr->lz4CtxPtr, sizeof(LZ4_stream_t)); + cctx->lz4CtxPtr = LZ4F_malloc(sizeof(LZ4_stream_t), cctx->cmem); + if (cctx->lz4CtxPtr) + LZ4_initStream(cctx->lz4CtxPtr, sizeof(LZ4_stream_t)); } else { - cctxPtr->lz4CtxPtr = LZ4F_malloc(sizeof(LZ4_streamHC_t), cctxPtr->cmem); - if (cctxPtr->lz4CtxPtr) - LZ4_initStreamHC(cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t)); + cctx->lz4CtxPtr = LZ4F_malloc(sizeof(LZ4_streamHC_t), cctx->cmem); + if (cctx->lz4CtxPtr) + LZ4_initStreamHC(cctx->lz4CtxPtr, sizeof(LZ4_streamHC_t)); } - RETURN_ERROR_IF(cctxPtr->lz4CtxPtr == NULL, allocation_failed); - cctxPtr->lz4CtxAlloc = ctxTypeID; - cctxPtr->lz4CtxState = ctxTypeID; - } else if (cctxPtr->lz4CtxState != ctxTypeID) { + RETURN_ERROR_IF(cctx->lz4CtxPtr == NULL, allocation_failed); + cctx->lz4CtxAlloc = ctxTypeID; + cctx->lz4CtxType = ctxTypeID; + } else if (cctx->lz4CtxType != ctxTypeID) { /* otherwise, a sufficient buffer is already allocated, * but we need to reset it to the correct context type */ - if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { - LZ4_initStream((LZ4_stream_t*)cctxPtr->lz4CtxPtr, sizeof(LZ4_stream_t)); + if (cctx->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { + LZ4_initStream((LZ4_stream_t*)cctx->lz4CtxPtr, sizeof(LZ4_stream_t)); } else { - LZ4_initStreamHC((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t)); - LZ4_setCompressionLevel((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); + LZ4_initStreamHC((LZ4_streamHC_t*)cctx->lz4CtxPtr, sizeof(LZ4_streamHC_t)); + LZ4_setCompressionLevel((LZ4_streamHC_t*)cctx->lz4CtxPtr, cctx->prefs.compressionLevel); } - cctxPtr->lz4CtxState = ctxTypeID; + cctx->lz4CtxType = ctxTypeID; } } /* Buffer Management */ - if (cctxPtr->prefs.frameInfo.blockSizeID == 0) - cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; - cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID); + if (cctx->prefs.frameInfo.blockSizeID == 0) + cctx->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; + cctx->maxBlockSize = LZ4F_getBlockSize(cctx->prefs.frameInfo.blockSizeID); { size_t const requiredBuffSize = preferencesPtr->autoFlush ? - ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) : /* only needs past data up to window size */ - cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0); + ((cctx->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) : /* only needs past data up to window size */ + cctx->maxBlockSize + ((cctx->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0); - if (cctxPtr->maxBufferSize < requiredBuffSize) { - cctxPtr->maxBufferSize = 0; - LZ4F_free(cctxPtr->tmpBuff, cctxPtr->cmem); - cctxPtr->tmpBuff = (BYTE*)LZ4F_calloc(requiredBuffSize, cctxPtr->cmem); - RETURN_ERROR_IF(cctxPtr->tmpBuff == NULL, allocation_failed); - cctxPtr->maxBufferSize = requiredBuffSize; + if (cctx->maxBufferSize < requiredBuffSize) { + cctx->maxBufferSize = 0; + LZ4F_free(cctx->tmpBuff, cctx->cmem); + cctx->tmpBuff = (BYTE*)LZ4F_malloc(requiredBuffSize, cctx->cmem); + RETURN_ERROR_IF(cctx->tmpBuff == NULL, allocation_failed); + cctx->maxBufferSize = requiredBuffSize; } } - cctxPtr->tmpIn = cctxPtr->tmpBuff; - cctxPtr->tmpInSize = 0; - (void)XXH32_reset(&(cctxPtr->xxh), 0); + cctx->tmpIn = cctx->tmpBuff; + cctx->tmpInSize = 0; + (void)XXH32_reset(&(cctx->xxh), 0); /* context init */ - cctxPtr->cdict = cdict; - if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) { + cctx->cdict = cdict; + if (cctx->prefs.frameInfo.blockMode == LZ4F_blockLinked) { /* frame init only for blockLinked : blockIndependent will be init at each block */ - LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel, LZ4F_blockLinked); + LZ4F_initStream(cctx->lz4CtxPtr, cdict, cctx->prefs.compressionLevel, LZ4F_blockLinked); } if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) { - LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed); + LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctx->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed); } + if (dictBuffer) { + assert(cdict == NULL); + RETURN_ERROR_IF(dictSize > INT_MAX, parameter_invalid); + if (cctx->lz4CtxType == ctxFast) { + /* lz4 fast*/ + LZ4_loadDict((LZ4_stream_t*)cctx->lz4CtxPtr, (const char*)dictBuffer, (int)dictSize); + } else { + /* lz4hc */ + assert(cctx->lz4CtxType == ctxHC); + LZ4_loadDictHC((LZ4_streamHC_t*)cctx->lz4CtxPtr, (const char*)dictBuffer, (int)dictSize); + } + } + + /* Stage 2 : Write Frame Header */ /* Magic Number */ LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER); @@ -757,22 +785,22 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, /* FLG Byte */ *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */ - + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5) - + ((cctxPtr->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4) - + ((unsigned)(cctxPtr->prefs.frameInfo.contentSize > 0) << 3) - + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2) - + (cctxPtr->prefs.frameInfo.dictID > 0) ); + + ((cctx->prefs.frameInfo.blockMode & _1BIT ) << 5) + + ((cctx->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4) + + ((unsigned)(cctx->prefs.frameInfo.contentSize > 0) << 3) + + ((cctx->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2) + + (cctx->prefs.frameInfo.dictID > 0) ); /* BD Byte */ - *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4); + *dstPtr++ = (BYTE)((cctx->prefs.frameInfo.blockSizeID & _3BITS) << 4); /* Optional Frame content size field */ - if (cctxPtr->prefs.frameInfo.contentSize) { - LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize); + if (cctx->prefs.frameInfo.contentSize) { + LZ4F_writeLE64(dstPtr, cctx->prefs.frameInfo.contentSize); dstPtr += 8; - cctxPtr->totalInSize = 0; + cctx->totalInSize = 0; } /* Optional dictionary ID field */ - if (cctxPtr->prefs.frameInfo.dictID) { - LZ4F_writeLE32(dstPtr, cctxPtr->prefs.frameInfo.dictID); + if (cctx->prefs.frameInfo.dictID) { + LZ4F_writeLE32(dstPtr, cctx->prefs.frameInfo.dictID); dstPtr += 4; } /* Header CRC Byte */ @@ -780,24 +808,54 @@ size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, dstPtr++; } - cctxPtr->cStage = 1; /* header written, now request input data block */ + cctx->cStage = 1; /* header written, now request input data block */ return (size_t)(dstPtr - dstStart); } - -/*! LZ4F_compressBegin() : - * init streaming compression AND writes frame header into @dstBuffer. - * @dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - * @preferencesPtr can be NULL, in which case default parameters are selected. - * @return : number of bytes written into dstBuffer for the header - * or an error code (can be tested using LZ4F_isError()) - */ -size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr, +size_t LZ4F_compressBegin(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const LZ4F_preferences_t* preferencesPtr) { - return LZ4F_compressBegin_usingCDict(cctxPtr, dstBuffer, dstCapacity, - NULL, preferencesPtr); + return LZ4F_compressBegin_internal(cctx, dstBuffer, dstCapacity, + NULL, 0, + NULL, preferencesPtr); +} + +/* LZ4F_compressBegin_usingDictOnce: + * Hidden implementation, + * employed for multi-threaded compression + * when frame defines linked blocks */ +size_t LZ4F_compressBegin_usingDictOnce(LZ4F_cctx* cctx, + void* dstBuffer, size_t dstCapacity, + const void* dict, size_t dictSize, + const LZ4F_preferences_t* preferencesPtr) +{ + return LZ4F_compressBegin_internal(cctx, dstBuffer, dstCapacity, + dict, dictSize, + NULL, preferencesPtr); +} + +size_t LZ4F_compressBegin_usingDict(LZ4F_cctx* cctx, + void* dstBuffer, size_t dstCapacity, + const void* dict, size_t dictSize, + const LZ4F_preferences_t* preferencesPtr) +{ + /* note : incorrect implementation : + * this will only use the dictionary once, + * instead of once *per* block when frames defines independent blocks */ + return LZ4F_compressBegin_usingDictOnce(cctx, dstBuffer, dstCapacity, + dict, dictSize, + preferencesPtr); +} + +size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctx, + void* dstBuffer, size_t dstCapacity, + const LZ4F_CDict* cdict, + const LZ4F_preferences_t* preferencesPtr) +{ + return LZ4F_compressBegin_internal(cctx, dstBuffer, dstCapacity, + NULL, 0, + cdict, preferencesPtr); } @@ -891,9 +949,10 @@ static int LZ4F_doNotCompressBlock(void* ctx, const char* src, char* dst, int sr return 0; } -static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level, LZ4F_blockCompression_t compressMode) +static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level, LZ4F_BlockCompressMode_e compressMode) { - if (compressMode == LZ4B_UNCOMPRESSED) return LZ4F_doNotCompressBlock; + if (compressMode == LZ4B_UNCOMPRESSED) + return LZ4F_doNotCompressBlock; if (level < LZ4HC_CLEVEL_MIN) { if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlock; return LZ4F_compressBlock_continue; @@ -931,7 +990,7 @@ static size_t LZ4F_compressUpdateImpl(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr, - LZ4F_blockCompression_t blockCompression) + LZ4F_BlockCompressMode_e blockCompression) { size_t const blockSize = cctxPtr->maxBlockSize; const BYTE* srcPtr = (const BYTE*)srcBuffer; @@ -951,10 +1010,10 @@ static size_t LZ4F_compressUpdateImpl(LZ4F_cctx* cctxPtr, RETURN_ERROR(dstMaxSize_tooSmall); /* flush currently written block, to continue with new block compression */ - if (cctxPtr->blockCompression != blockCompression) { + if (cctxPtr->blockCompressMode != blockCompression) { bytesWritten = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr); dstPtr += bytesWritten; - cctxPtr->blockCompression = blockCompression; + cctxPtr->blockCompressMode = blockCompression; } if (compressOptionsPtr == NULL) compressOptionsPtr = &k_cOptionsNull; @@ -1068,13 +1127,9 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr, compressOptionsPtr, LZ4B_COMPRESSED); } -/*! LZ4F_compressUpdate() : - * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. - * When successful, the function always entirely consumes @srcBuffer. - * src data is either buffered or compressed into @dstBuffer. - * If previously an uncompressed block was written, buffered data is flushed - * before appending compressed data is continued. - * This is only supported when LZ4F_blockIndependent is used +/*! LZ4F_uncompressedUpdate() : + * Same as LZ4F_compressUpdate(), but requests blocks to be sent uncompressed. + * This symbol is only supported when LZ4F_blockIndependent is used * @dstCapacity MUST be >= LZ4F_compressBound(srcSize, preferencesPtr). * @compressOptionsPtr is optional : provide NULL to mean "default". * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered. @@ -1084,8 +1139,8 @@ size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr, size_t LZ4F_uncompressedUpdate(LZ4F_cctx* cctxPtr, void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, - const LZ4F_compressOptions_t* compressOptionsPtr) { - RETURN_ERROR_IF(cctxPtr->prefs.frameInfo.blockMode != LZ4F_blockIndependent, blockMode_invalid); + const LZ4F_compressOptions_t* compressOptionsPtr) +{ return LZ4F_compressUpdateImpl(cctxPtr, dstBuffer, dstCapacity, srcBuffer, srcSize, @@ -1115,7 +1170,7 @@ size_t LZ4F_flush(LZ4F_cctx* cctxPtr, (void)compressOptionsPtr; /* not useful (yet) */ /* select compression function */ - compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel, cctxPtr->blockCompression); + compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel, cctxPtr->blockCompressMode); /* compress tmp buffer */ dstPtr += LZ4F_makeBlock(dstPtr, @@ -1170,13 +1225,12 @@ size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr, if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) { U32 const xxh = XXH32_digest(&(cctxPtr->xxh)); RETURN_ERROR_IF(dstCapacity < 8, dstMaxSize_tooSmall); - DEBUGLOG(5,"Writing 32-bit content checksum"); + DEBUGLOG(5,"Writing 32-bit content checksum (0x%0X)", xxh); LZ4F_writeLE32(dstPtr, xxh); dstPtr+=4; /* content Checksum */ } cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */ - cctxPtr->maxBufferSize = 0; /* reuse HC context */ if (cctxPtr->prefs.frameInfo.contentSize) { if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize) @@ -1270,13 +1324,14 @@ LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx) /*==--- Streaming Decompression operations ---==*/ - void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx) { + DEBUGLOG(5, "LZ4F_resetDecompressionContext"); dctx->dStage = dstage_getFrameHeader; dctx->dict = NULL; dctx->dictSize = 0; dctx->skipChecksum = 0; + dctx->frameRemainingSize = 0; } @@ -1333,6 +1388,7 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize if (((FLG>>1)&_1BIT) != 0) RETURN_ERROR(reservedFlag_set); /* Reserved bit */ if (version != 1) RETURN_ERROR(headerVersion_wrong); /* Version Number, only supported value */ } + DEBUGLOG(6, "contentSizeFlag: %u", contentSizeFlag); /* Frame Header Size */ frameHeaderSize = minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0); @@ -1369,8 +1425,9 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize dctx->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag; dctx->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID; dctx->maxBlockSize = LZ4F_getBlockSize((LZ4F_blockSizeID_t)blockSizeID); - if (contentSizeFlag) + if (contentSizeFlag) { dctx->frameRemainingSize = dctx->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6); + } if (dictIDFlag) dctx->frameInfo.dictID = LZ4F_readLE32(srcPtr + frameHeaderSize - 5); @@ -1570,7 +1627,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, size_t nextSrcSizeHint = 1; - DEBUGLOG(5, "LZ4F_decompress : %p,%u => %p,%u", + DEBUGLOG(5, "LZ4F_decompress: src[%p](%u) => dst[%p](%u)", srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr); if (dstBuffer == NULL) assert(*dstSizePtr == 0); MEM_INIT(&optionsNull, 0, sizeof(optionsNull)); @@ -1722,10 +1779,10 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, /* history management (linked blocks only)*/ if (dctx->frameInfo.blockMode == LZ4F_blockLinked) { LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0); - } } - - srcPtr += sizeToCopy; - dstPtr += sizeToCopy; + } + srcPtr += sizeToCopy; + dstPtr += sizeToCopy; + } if (sizeToCopy == dctx->tmpInTarget) { /* all done */ if (dctx->frameInfo.blockChecksumFlag) { dctx->tmpInSize = 0; @@ -1959,6 +2016,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx, if (!dctx->skipChecksum) { U32 const readCRC = LZ4F_readLE32(selectedIn); U32 const resultCRC = XXH32_digest(&(dctx->xxh)); + DEBUGLOG(4, "frame checksum: stored 0x%0X vs 0x%0X processed", readCRC, resultCRC); #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION RETURN_ERROR_IF(readCRC != resultCRC, contentChecksum_invalid); #else diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4frame.h b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame.h similarity index 84% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4frame.h rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame.h index 1bdf6c4fcba..b8ae3227670 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4frame.h +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame.h @@ -173,16 +173,16 @@ typedef LZ4F_contentChecksum_t contentChecksum_t; * setting all parameters to default. * It's then possible to update selectively some parameters */ typedef struct { - LZ4F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB; 0 == default */ - LZ4F_blockMode_t blockMode; /* LZ4F_blockLinked, LZ4F_blockIndependent; 0 == default */ - LZ4F_contentChecksum_t contentChecksumFlag; /* 1: frame terminated with 32-bit checksum of decompressed data; 0: disabled (default) */ + LZ4F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB; 0 == default (LZ4F_max64KB) */ + LZ4F_blockMode_t blockMode; /* LZ4F_blockLinked, LZ4F_blockIndependent; 0 == default (LZ4F_blockLinked) */ + LZ4F_contentChecksum_t contentChecksumFlag; /* 1: add a 32-bit checksum of frame's decompressed data; 0 == default (disabled) */ LZ4F_frameType_t frameType; /* read-only field : LZ4F_frame or LZ4F_skippableFrame */ unsigned long long contentSize; /* Size of uncompressed content ; 0 == unknown */ unsigned dictID; /* Dictionary ID, sent by compressor to help decoder select correct dictionary; 0 == no dictID provided */ - LZ4F_blockChecksum_t blockChecksumFlag; /* 1: each block followed by a checksum of block's compressed data; 0: disabled (default) */ + LZ4F_blockChecksum_t blockChecksumFlag; /* 1: each block followed by a checksum of block's compressed data; 0 == default (disabled) */ } LZ4F_frameInfo_t; -#define LZ4F_INIT_FRAMEINFO { LZ4F_default, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum } /* v1.8.3+ */ +#define LZ4F_INIT_FRAMEINFO { LZ4F_max64KB, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum } /* v1.8.3+ */ /*! LZ4F_preferences_t : * makes it possible to supply advanced compression instructions to streaming interface. @@ -204,7 +204,26 @@ typedef struct { * Simple compression function ***********************************/ -LZ4FLIB_API int LZ4F_compressionLevel_max(void); /* v1.8.0+ */ +/*! LZ4F_compressFrame() : + * Compress srcBuffer content into an LZ4-compressed frame. + * It's a one shot operation, all input content is consumed, and all output is generated. + * + * Note : it's a stateless operation (no LZ4F_cctx state needed). + * In order to reduce load on the allocator, LZ4F_compressFrame(), by default, + * uses the stack to allocate space for the compression state and some table. + * If this usage of the stack is too much for your application, + * consider compiling `lz4frame.c` with compile-time macro LZ4F_HEAPMODE set to 1 instead. + * All state allocations will use the Heap. + * It also means each invocation of LZ4F_compressFrame() will trigger several internal alloc/free invocations. + * + * @dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). + * @preferencesPtr is optional : one can provide NULL, in which case all preferences are set to default. + * @return : number of bytes written into dstBuffer. + * or an error code if it fails (can be tested using LZ4F_isError()) + */ +LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, + const void* srcBuffer, size_t srcSize, + const LZ4F_preferences_t* preferencesPtr); /*! LZ4F_compressFrameBound() : * Returns the maximum possible compressed size with LZ4F_compressFrame() given srcSize and preferences. @@ -214,16 +233,11 @@ LZ4FLIB_API int LZ4F_compressionLevel_max(void); /* v1.8.0+ */ */ LZ4FLIB_API size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr); -/*! LZ4F_compressFrame() : - * Compress an entire srcBuffer into a valid LZ4 frame. - * dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default. - * @return : number of bytes written into dstBuffer. - * or an error code if it fails (can be tested using LZ4F_isError()) + +/*! LZ4F_compressionLevel_max() : + * @return maximum allowed compression level (currently: 12) */ -LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, - const void* srcBuffer, size_t srcSize, - const LZ4F_preferences_t* preferencesPtr); +LZ4FLIB_API int LZ4F_compressionLevel_max(void); /* v1.8.0+ */ /*-*********************************** @@ -278,7 +292,7 @@ LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx); /*! LZ4F_compressBegin() : * will write the frame header into dstBuffer. * dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - * `prefsPtr` is optional : you can provide NULL as argument, all preferences will then be set to default. + * `prefsPtr` is optional : NULL can be provided to set all preferences to default. * @return : number of bytes written into dstBuffer for the header * or an error code (which can be tested using LZ4F_isError()) */ @@ -355,8 +369,9 @@ typedef struct LZ4F_dctx_s LZ4F_dctx; /* incomplete type */ typedef LZ4F_dctx* LZ4F_decompressionContext_t; /* compatibility with previous API versions */ typedef struct { - unsigned stableDst; /* pledges that last 64KB decompressed data will remain available unmodified between invocations. - * This optimization skips storage operations in tmp buffers. */ + unsigned stableDst; /* pledges that last 64KB decompressed data is present right before @dstBuffer pointer. + * This optimization skips internal storage operations. + * Once set, this pledge must remain valid up to the end of current frame. */ unsigned skipChecksums; /* disable checksum calculation and verification, even when one is present in frame, to save CPU time. * Setting this option to 1 once disables all checksums for the rest of the frame. */ unsigned reserved1; /* must be set to zero for forward compatibility */ @@ -463,6 +478,11 @@ LZ4F_getFrameInfo(LZ4F_dctx* dctx, * `dstBuffer` can freely change between each consecutive function invocation. * `dstBuffer` content will be overwritten. * + * Note: if `LZ4F_getFrameInfo()` is called before `LZ4F_decompress()`, srcBuffer must be updated to reflect + * the number of bytes consumed after reading the frame header. Failure to update srcBuffer before calling + * `LZ4F_decompress()` will cause decompression failure or, even worse, successful but incorrect decompression. + * See the `LZ4F_getFrameInfo()` docs for details. + * * @return : an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call. * Schematically, it's the size of the current (or remaining) compressed block + header of next block. * Respecting the hint provides some small speed benefit, because it skips intermediate buffers. @@ -493,6 +513,109 @@ LZ4F_decompress(LZ4F_dctx* dctx, LZ4FLIB_API void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx); /* always successful */ +/********************************** + * Dictionary compression API + *********************************/ + +/* A Dictionary is useful for the compression of small messages (KB range). + * It dramatically improves compression efficiency. + * + * LZ4 can ingest any input as dictionary, though only the last 64 KB are useful. + * Better results are generally achieved by using Zstandard's Dictionary Builder + * to generate a high-quality dictionary from a set of samples. + * + * The same dictionary will have to be used on the decompression side + * for decoding to be successful. + * To help identify the correct dictionary at decoding stage, + * the frame header allows optional embedding of a dictID field. + */ + +/*! LZ4F_compressBegin_usingDict() : stable since v1.10 + * Inits dictionary compression streaming, and writes the frame header into dstBuffer. + * @dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. + * @prefsPtr is optional : one may provide NULL as argument, + * however, it's the only way to provide dictID in the frame header. + * @dictBuffer must outlive the compression session. + * @return : number of bytes written into dstBuffer for the header, + * or an error code (which can be tested using LZ4F_isError()) + * NOTE: The LZ4Frame spec allows each independent block to be compressed with the dictionary, + * but this entry supports a more limited scenario, where only the first block uses the dictionary. + * This is still useful for small data, which only need one block anyway. + * For larger inputs, one may be more interested in LZ4F_compressFrame_usingCDict() below. + */ +LZ4FLIB_API size_t +LZ4F_compressBegin_usingDict(LZ4F_cctx* cctx, + void* dstBuffer, size_t dstCapacity, + const void* dictBuffer, size_t dictSize, + const LZ4F_preferences_t* prefsPtr); + +/*! LZ4F_decompress_usingDict() : stable since v1.10 + * Same as LZ4F_decompress(), using a predefined dictionary. + * Dictionary is used "in place", without any preprocessing. +** It must remain accessible throughout the entire frame decoding. */ +LZ4FLIB_API size_t +LZ4F_decompress_usingDict(LZ4F_dctx* dctxPtr, + void* dstBuffer, size_t* dstSizePtr, + const void* srcBuffer, size_t* srcSizePtr, + const void* dict, size_t dictSize, + const LZ4F_decompressOptions_t* decompressOptionsPtr); + +/***************************************** + * Bulk processing dictionary compression + *****************************************/ + +/* Loading a dictionary has a cost, since it involves construction of tables. + * The Bulk processing dictionary API makes it possible to share this cost + * over an arbitrary number of compression jobs, even concurrently, + * markedly improving compression latency for these cases. + * + * Note that there is no corresponding bulk API for the decompression side, + * because dictionary does not carry any initialization cost for decompression. + * Use the regular LZ4F_decompress_usingDict() there. + */ +typedef struct LZ4F_CDict_s LZ4F_CDict; + +/*! LZ4_createCDict() : stable since v1.10 + * When compressing multiple messages / blocks using the same dictionary, it's recommended to initialize it just once. + * LZ4_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. + * LZ4_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. + * @dictBuffer can be released after LZ4_CDict creation, since its content is copied within CDict. */ +LZ4FLIB_API LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize); +LZ4FLIB_API void LZ4F_freeCDict(LZ4F_CDict* CDict); + +/*! LZ4_compressFrame_usingCDict() : stable since v1.10 + * Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary. + * @cctx must point to a context created by LZ4F_createCompressionContext(). + * If @cdict==NULL, compress without a dictionary. + * @dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). + * If this condition is not respected, function will fail (@return an errorCode). + * The LZ4F_preferences_t structure is optional : one may provide NULL as argument, + * but it's not recommended, as it's the only way to provide @dictID in the frame header. + * @return : number of bytes written into dstBuffer. + * or an error code if it fails (can be tested using LZ4F_isError()) + * Note: for larger inputs generating multiple independent blocks, + * this entry point uses the dictionary for each block. */ +LZ4FLIB_API size_t +LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const LZ4F_CDict* cdict, + const LZ4F_preferences_t* preferencesPtr); + +/*! LZ4F_compressBegin_usingCDict() : stable since v1.10 + * Inits streaming dictionary compression, and writes the frame header into dstBuffer. + * @dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. + * @prefsPtr is optional : one may provide NULL as argument, + * note however that it's the only way to insert a @dictID in the frame header. + * @cdict must outlive the compression session. + * @return : number of bytes written into dstBuffer for the header, + * or an error code, which can be tested using LZ4F_isError(). */ +LZ4FLIB_API size_t +LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctx, + void* dstBuffer, size_t dstCapacity, + const LZ4F_CDict* cdict, + const LZ4F_preferences_t* prefsPtr); + #if defined (__cplusplus) } @@ -503,11 +626,8 @@ LZ4FLIB_API void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx); /* always su #if defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843) #define LZ4F_H_STATIC_09782039843 -#if defined (__cplusplus) -extern "C" { -#endif - -/* These declarations are not stable and may change in the future. +/* Note : + * The below declarations are not stable and may change in the future. * They are therefore only safe to depend on * when the caller is statically linked against the library. * To access their declarations, define LZ4F_STATIC_LINKING_ONLY. @@ -517,6 +637,11 @@ extern "C" { * by defining LZ4F_PUBLISH_STATIC_FUNCTIONS. * Use at your own risk. */ + +#if defined (__cplusplus) +extern "C" { +#endif + #ifdef LZ4F_PUBLISH_STATIC_FUNCTIONS # define LZ4FLIB_STATIC_API LZ4FLIB_API #else @@ -530,7 +655,7 @@ extern "C" { ITEM(ERROR_GENERIC) \ ITEM(ERROR_maxBlockSize_invalid) \ ITEM(ERROR_blockMode_invalid) \ - ITEM(ERROR_contentChecksumFlag_invalid) \ + ITEM(ERROR_parameter_invalid) \ ITEM(ERROR_compressionLevel_invalid) \ ITEM(ERROR_headerVersion_wrong) \ ITEM(ERROR_blockChecksum_invalid) \ @@ -548,6 +673,8 @@ extern "C" { ITEM(ERROR_frameDecoding_alreadyStarted) \ ITEM(ERROR_compressionState_uninitialized) \ ITEM(ERROR_parameter_null) \ + ITEM(ERROR_io_write) \ + ITEM(ERROR_io_read) \ ITEM(ERROR_maxCode) #define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM, @@ -558,22 +685,26 @@ typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM) LZ4FLIB_STATIC_API LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult); +/********************************** + * Advanced compression operations + *********************************/ /*! LZ4F_getBlockSize() : - * Return, in scalar format (size_t), - * the maximum block size associated with blockSizeID. + * @return, in scalar format (size_t), + * the maximum block size associated with @blockSizeID, + * or an error code (can be tested using LZ4F_isError()) if @blockSizeID is invalid. **/ LZ4FLIB_STATIC_API size_t LZ4F_getBlockSize(LZ4F_blockSizeID_t blockSizeID); /*! LZ4F_uncompressedUpdate() : - * LZ4F_uncompressedUpdate() can be called repetitively to add as much data uncompressed data as necessary. + * LZ4F_uncompressedUpdate() can be called repetitively to add data stored as uncompressed blocks. * Important rule: dstCapacity MUST be large enough to store the entire source buffer as * no compression is done for this operation * If this condition is not respected, LZ4F_uncompressedUpdate() will fail (result is an errorCode). * After an error, the state is left in a UB state, and must be re-initialized or freed. - * If previously a compressed block was written, buffered data is flushed + * If previously a compressed block was written, buffered data is flushed first, * before appending uncompressed data is continued. - * This is only supported when LZ4F_blockIndependent is used + * This operation is only supported when LZ4F_blockIndependent is used. * `cOptPtr` is optional : NULL can be provided, in which case all options are set to default. * @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered). * or an error code if it fails (which can be tested using LZ4F_isError()) @@ -585,82 +716,10 @@ LZ4F_uncompressedUpdate(LZ4F_cctx* cctx, const LZ4F_compressOptions_t* cOptPtr); /********************************** - * Bulk processing dictionary API + * Custom memory allocation *********************************/ -/* A Dictionary is useful for the compression of small messages (KB range). - * It dramatically improves compression efficiency. - * - * LZ4 can ingest any input as dictionary, though only the last 64 KB are useful. - * Best results are generally achieved by using Zstandard's Dictionary Builder - * to generate a high-quality dictionary from a set of samples. - * - * Loading a dictionary has a cost, since it involves construction of tables. - * The Bulk processing dictionary API makes it possible to share this cost - * over an arbitrary number of compression jobs, even concurrently, - * markedly improving compression latency for these cases. - * - * The same dictionary will have to be used on the decompression side - * for decoding to be successful. - * To help identify the correct dictionary at decoding stage, - * the frame header allows optional embedding of a dictID field. - */ -typedef struct LZ4F_CDict_s LZ4F_CDict; - -/*! LZ4_createCDict() : - * When compressing multiple messages / blocks using the same dictionary, it's recommended to load it just once. - * LZ4_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. - * LZ4_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. - * `dictBuffer` can be released after LZ4_CDict creation, since its content is copied within CDict */ -LZ4FLIB_STATIC_API LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize); -LZ4FLIB_STATIC_API void LZ4F_freeCDict(LZ4F_CDict* CDict); - - -/*! LZ4_compressFrame_usingCDict() : - * Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary. - * cctx must point to a context created by LZ4F_createCompressionContext(). - * If cdict==NULL, compress without a dictionary. - * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - * If this condition is not respected, function will fail (@return an errorCode). - * The LZ4F_preferences_t structure is optional : you may provide NULL as argument, - * but it's not recommended, as it's the only way to provide dictID in the frame header. - * @return : number of bytes written into dstBuffer. - * or an error code if it fails (can be tested using LZ4F_isError()) */ -LZ4FLIB_STATIC_API size_t -LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const LZ4F_CDict* cdict, - const LZ4F_preferences_t* preferencesPtr); - - -/*! LZ4F_compressBegin_usingCDict() : - * Inits streaming dictionary compression, and writes the frame header into dstBuffer. - * dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - * `prefsPtr` is optional : you may provide NULL as argument, - * however, it's the only way to provide dictID in the frame header. - * @return : number of bytes written into dstBuffer for the header, - * or an error code (which can be tested using LZ4F_isError()) */ -LZ4FLIB_STATIC_API size_t -LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const LZ4F_CDict* cdict, - const LZ4F_preferences_t* prefsPtr); - - -/*! LZ4F_decompress_usingDict() : - * Same as LZ4F_decompress(), using a predefined dictionary. - * Dictionary is used "in place", without any preprocessing. -** It must remain accessible throughout the entire frame decoding. */ -LZ4FLIB_STATIC_API size_t -LZ4F_decompress_usingDict(LZ4F_dctx* dctxPtr, - void* dstBuffer, size_t* dstSizePtr, - const void* srcBuffer, size_t* srcSizePtr, - const void* dict, size_t dictSize, - const LZ4F_decompressOptions_t* decompressOptionsPtr); - - -/*! Custom memory allocation : +/*! Custom memory allocation : v1.9.4+ * These prototypes make it possible to pass custom allocation/free functions. * LZ4F_customMem is provided at state creation time, using LZ4F_create*_advanced() listed below. * All allocation/free operations will be completed using these custom variants instead of regular ones. diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4frame_static.h b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame_static.h similarity index 100% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4frame_static.h rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4frame_static.h diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4hc.c b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4hc.c similarity index 64% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4hc.c rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4hc.c index b21ad6bb599..4d8c36a6978 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4hc.c +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4hc.c @@ -39,9 +39,10 @@ ***************************************/ /*! HEAPMODE : - * Select how default compression function will allocate workplace memory, - * in stack (0:fastest), or in heap (1:requires malloc()). - * Since workplace is rather large, heap mode is recommended. + * Select how stateless HC compression functions like `LZ4_compress_HC()` + * allocate memory for their workspace: + * in stack (0:fastest), or in heap (1:default, requires malloc()). + * Since workspace is rather large, heap mode is recommended. **/ #ifndef LZ4HC_HEAPMODE # define LZ4HC_HEAPMODE 1 @@ -51,19 +52,19 @@ /*=== Dependency ===*/ #define LZ4_HC_STATIC_LINKING_ONLY #include "lz4hc.h" +#include -/*=== Common definitions ===*/ -#if defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wunused-function" -#endif -#if defined (__clang__) -# pragma clang diagnostic ignored "-Wunused-function" -#endif - -#define LZ4_COMMONDEFS_ONLY +/*=== Shared lz4.c code ===*/ #ifndef LZ4_SRC_INCLUDED -#include "lz4.c" /* LZ4_count, constants, mem */ +# if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +# endif +# if defined (__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +# endif +# define LZ4_COMMONDEFS_ONLY +# include "lz4.c" /* LZ4_count, constants, mem */ #endif @@ -79,17 +80,158 @@ typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive; /*=== Macros ===*/ #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define MAX(a,b) ( (a) > (b) ? (a) : (b) ) -#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG)) -#define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */ + + +/*=== Levels definition ===*/ +typedef enum { lz4mid, lz4hc, lz4opt } lz4hc_strat_e; +typedef struct { + lz4hc_strat_e strat; + int nbSearches; + U32 targetLength; +} cParams_t; +static const cParams_t k_clTable[LZ4HC_CLEVEL_MAX+1] = { + { lz4mid, 2, 16 }, /* 0, unused */ + { lz4mid, 2, 16 }, /* 1, unused */ + { lz4mid, 2, 16 }, /* 2 */ + { lz4hc, 4, 16 }, /* 3 */ + { lz4hc, 8, 16 }, /* 4 */ + { lz4hc, 16, 16 }, /* 5 */ + { lz4hc, 32, 16 }, /* 6 */ + { lz4hc, 64, 16 }, /* 7 */ + { lz4hc, 128, 16 }, /* 8 */ + { lz4hc, 256, 16 }, /* 9 */ + { lz4opt, 96, 64 }, /*10==LZ4HC_CLEVEL_OPT_MIN*/ + { lz4opt, 512,128 }, /*11 */ + { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */ +}; + +static cParams_t LZ4HC_getCLevelParams(int cLevel) +{ + /* note : clevel convention is a bit different from lz4frame, + * possibly something worth revisiting for consistency */ + if (cLevel < 1) + cLevel = LZ4HC_CLEVEL_DEFAULT; + cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel); + return k_clTable[cLevel]; +} + + +/*=== Hashing ===*/ +#define LZ4HC_HASHSIZE 4 +#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG)) +static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); } + +#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) +/* lie to the compiler about data alignment; use with caution */ +static U64 LZ4_read64(const void* memPtr) { return *(const U64*) memPtr; } + +#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) +/* __pack instructions are safer, but compiler specific */ +LZ4_PACK(typedef struct { U64 u64; }) LZ4_unalign64; +static U64 LZ4_read64(const void* ptr) { return ((const LZ4_unalign64*)ptr)->u64; } + +#else /* safe and portable access using memcpy() */ +static U64 LZ4_read64(const void* memPtr) +{ + U64 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; +} + +#endif /* LZ4_FORCE_MEMORY_ACCESS */ + +#define LZ4MID_HASHSIZE 8 +#define LZ4MID_HASHLOG (LZ4HC_HASH_LOG-1) +#define LZ4MID_HASHTABLESIZE (1 << LZ4MID_HASHLOG) + +static U32 LZ4MID_hash4(U32 v) { return (v * 2654435761U) >> (32-LZ4MID_HASHLOG); } +static U32 LZ4MID_hash4Ptr(const void* ptr) { return LZ4MID_hash4(LZ4_read32(ptr)); } +/* note: hash7 hashes the lower 56-bits. + * It presumes input was read using little endian.*/ +static U32 LZ4MID_hash7(U64 v) { return (U32)(((v << (64-56)) * 58295818150454627ULL) >> (64-LZ4MID_HASHLOG)) ; } +static U64 LZ4_readLE64(const void* memPtr); +static U32 LZ4MID_hash8Ptr(const void* ptr) { return LZ4MID_hash7(LZ4_readLE64(ptr)); } + +static U64 LZ4_readLE64(const void* memPtr) +{ + if (LZ4_isLittleEndian()) { + return LZ4_read64(memPtr); + } else { + const BYTE* p = (const BYTE*)memPtr; + /* note: relies on the compiler to simplify this expression */ + return (U64)p[0] | ((U64)p[1]<<8) | ((U64)p[2]<<16) | ((U64)p[3]<<24) + | ((U64)p[4]<<32) | ((U64)p[5]<<40) | ((U64)p[6]<<48) | ((U64)p[7]<<56); + } +} + + +/*=== Count match length ===*/ +LZ4_FORCE_INLINE +unsigned LZ4HC_NbCommonBytes32(U32 val) +{ + assert(val != 0); + if (LZ4_isLittleEndian()) { +# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r; + _BitScanReverse(&r, val); + return (unsigned)((31 - r) >> 3); +# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ + ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (unsigned)__builtin_clz(val) >> 3; +# else + val >>= 8; + val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) | + (val + 0x00FF0000)) >> 24; + return (unsigned)val ^ 3; +# endif + } else { +# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r; + _BitScanForward(&r, val); + return (unsigned)(r >> 3); +# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ + ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (unsigned)__builtin_ctz(val) >> 3; +# else + const U32 m = 0x01010101; + return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24; +# endif + } +} + +/** LZ4HC_countBack() : + * @return : negative value, nb of common bytes before ip/match */ +LZ4_FORCE_INLINE +int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match, + const BYTE* const iMin, const BYTE* const mMin) +{ + int back = 0; + int const min = (int)MAX(iMin - ip, mMin - match); + assert(min <= 0); + assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31)); + assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31)); + + while ((back - min) > 3) { + U32 const v = LZ4_read32(ip + back - 4) ^ LZ4_read32(match + back - 4); + if (v) { + return (back - (int)LZ4HC_NbCommonBytes32(v)); + } else back -= 4; /* 4-byte step */ + } + /* check remainder if any */ + while ( (back > min) + && (ip[back-1] == match[back-1]) ) + back--; + return back; +} + +/*=== Chain table updates ===*/ #define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */ /* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */ #define UPDATABLE(ip, op, anchor) &ip, &op, &anchor -static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); } - /************************************** -* HC Compression +* Init **************************************/ static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4) { @@ -101,6 +243,7 @@ static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start) { size_t const bufferSize = (size_t)(hc4->end - hc4->prefixStart); size_t newStartingOffset = bufferSize + hc4->dictLimit; + DEBUGLOG(5, "LZ4HC_init_internal"); assert(newStartingOffset >= bufferSize); /* check overflow */ if (newStartingOffset > 1 GB) { LZ4HC_clearTables(hc4); @@ -116,6 +259,524 @@ static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start) } +/************************************** +* Encode +**************************************/ +/* LZ4HC_encodeSequence() : + * @return : 0 if ok, + * 1 if buffer issue detected */ +LZ4_FORCE_INLINE int LZ4HC_encodeSequence ( + const BYTE** _ip, + BYTE** _op, + const BYTE** _anchor, + int matchLength, + int offset, + limitedOutput_directive limit, + BYTE* oend) +{ +#define ip (*_ip) +#define op (*_op) +#define anchor (*_anchor) + + size_t length; + BYTE* const token = op++; + +#if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6) + static const BYTE* start = NULL; + static U32 totalCost = 0; + U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start); + U32 const ll = (U32)(ip - anchor); + U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0; + U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0; + U32 const cost = 1 + llAdd + ll + 2 + mlAdd; + if (start==NULL) start = anchor; /* only works for single segment */ + /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */ + DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5i, cost:%4u + %5u", + pos, + (U32)(ip - anchor), matchLength, offset, + cost, totalCost); + totalCost += cost; +#endif + + /* Encode Literal length */ + length = (size_t)(ip - anchor); + LZ4_STATIC_ASSERT(notLimited == 0); + /* Check output limit */ + if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) { + DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)", + (int)length, (int)(oend - op)); + return 1; + } + if (length >= RUN_MASK) { + size_t len = length - RUN_MASK; + *token = (RUN_MASK << ML_BITS); + for(; len >= 255 ; len -= 255) *op++ = 255; + *op++ = (BYTE)len; + } else { + *token = (BYTE)(length << ML_BITS); + } + + /* Copy Literals */ + LZ4_wildCopy8(op, anchor, op + length); + op += length; + + /* Encode Offset */ + assert(offset <= LZ4_DISTANCE_MAX ); + assert(offset > 0); + LZ4_writeLE16(op, (U16)(offset)); op += 2; + + /* Encode MatchLength */ + assert(matchLength >= MINMATCH); + length = (size_t)matchLength - MINMATCH; + if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) { + DEBUGLOG(6, "Not enough room to write match length"); + return 1; /* Check output limit */ + } + if (length >= ML_MASK) { + *token += ML_MASK; + length -= ML_MASK; + for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; } + if (length >= 255) { length -= 255; *op++ = 255; } + *op++ = (BYTE)length; + } else { + *token += (BYTE)(length); + } + + /* Prepare next loop */ + ip += matchLength; + anchor = ip; + + return 0; + +#undef ip +#undef op +#undef anchor +} + + +typedef struct { + int off; + int len; + int back; /* negative value */ +} LZ4HC_match_t; + +LZ4HC_match_t LZ4HC_searchExtDict(const BYTE* ip, U32 ipIndex, + const BYTE* const iLowLimit, const BYTE* const iHighLimit, + const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex, + int currentBestML, int nbAttempts) +{ + size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit; + U32 lDictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)]; + U32 matchIndex = lDictMatchIndex + gDictEndIndex - (U32)lDictEndIndex; + int offset = 0, sBack = 0; + assert(lDictEndIndex <= 1 GB); + if (lDictMatchIndex>0) + DEBUGLOG(7, "lDictEndIndex = %zu, lDictMatchIndex = %u", lDictEndIndex, lDictMatchIndex); + while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) { + const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + lDictMatchIndex; + + if (LZ4_read32(matchPtr) == LZ4_read32(ip)) { + int mlt; + int back = 0; + const BYTE* vLimit = ip + (lDictEndIndex - lDictMatchIndex); + if (vLimit > iHighLimit) vLimit = iHighLimit; + mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; + back = (ip > iLowLimit) ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0; + mlt -= back; + if (mlt > currentBestML) { + currentBestML = mlt; + offset = (int)(ipIndex - matchIndex); + sBack = back; + DEBUGLOG(7, "found match of length %i within extDictCtx", currentBestML); + } } + + { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, lDictMatchIndex); + lDictMatchIndex -= nextOffset; + matchIndex -= nextOffset; + } } + + { LZ4HC_match_t md; + md.len = currentBestML; + md.off = offset; + md.back = sBack; + return md; + } +} + +typedef LZ4HC_match_t (*LZ4MID_searchIntoDict_f)(const BYTE* ip, U32 ipIndex, + const BYTE* const iHighLimit, + const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex); + +static LZ4HC_match_t LZ4MID_searchHCDict(const BYTE* ip, U32 ipIndex, + const BYTE* const iHighLimit, + const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex) +{ + return LZ4HC_searchExtDict(ip,ipIndex, + ip, iHighLimit, + dictCtx, gDictEndIndex, + MINMATCH-1, 2); +} + +static LZ4HC_match_t LZ4MID_searchExtDict(const BYTE* ip, U32 ipIndex, + const BYTE* const iHighLimit, + const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex) +{ + size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit; + const U32* const hash4Table = dictCtx->hashTable; + const U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE; + DEBUGLOG(7, "LZ4MID_searchExtDict (ipIdx=%u)", ipIndex); + + /* search long match first */ + { U32 l8DictMatchIndex = hash8Table[LZ4MID_hash8Ptr(ip)]; + U32 m8Index = l8DictMatchIndex + gDictEndIndex - (U32)lDictEndIndex; + assert(lDictEndIndex <= 1 GB); + if (ipIndex - m8Index <= LZ4_DISTANCE_MAX) { + const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + l8DictMatchIndex; + const size_t safeLen = MIN(lDictEndIndex - l8DictMatchIndex, (size_t)(iHighLimit - ip)); + int mlt = (int)LZ4_count(ip, matchPtr, ip + safeLen); + if (mlt >= MINMATCH) { + LZ4HC_match_t md; + DEBUGLOG(7, "Found long ExtDict match of len=%u", mlt); + md.len = mlt; + md.off = (int)(ipIndex - m8Index); + md.back = 0; + return md; + } + } + } + + /* search for short match second */ + { U32 l4DictMatchIndex = hash4Table[LZ4MID_hash4Ptr(ip)]; + U32 m4Index = l4DictMatchIndex + gDictEndIndex - (U32)lDictEndIndex; + if (ipIndex - m4Index <= LZ4_DISTANCE_MAX) { + const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + l4DictMatchIndex; + const size_t safeLen = MIN(lDictEndIndex - l4DictMatchIndex, (size_t)(iHighLimit - ip)); + int mlt = (int)LZ4_count(ip, matchPtr, ip + safeLen); + if (mlt >= MINMATCH) { + LZ4HC_match_t md; + DEBUGLOG(7, "Found short ExtDict match of len=%u", mlt); + md.len = mlt; + md.off = (int)(ipIndex - m4Index); + md.back = 0; + return md; + } + } + } + + /* nothing found */ + { LZ4HC_match_t const md = {0, 0, 0 }; + return md; + } +} + +/************************************** +* Mid Compression (level 2) +**************************************/ + +LZ4_FORCE_INLINE void +LZ4MID_addPosition(U32* hTable, U32 hValue, U32 index) +{ + hTable[hValue] = index; +} + +#define ADDPOS8(_p, _idx) LZ4MID_addPosition(hash8Table, LZ4MID_hash8Ptr(_p), _idx) +#define ADDPOS4(_p, _idx) LZ4MID_addPosition(hash4Table, LZ4MID_hash4Ptr(_p), _idx) + +/* Fill hash tables with references into dictionary. + * The resulting table is only exploitable by LZ4MID (level 2) */ +static void +LZ4MID_fillHTable (LZ4HC_CCtx_internal* cctx, const void* dict, size_t size) +{ + U32* const hash4Table = cctx->hashTable; + U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE; + const BYTE* const prefixPtr = (const BYTE*)dict; + U32 const prefixIdx = cctx->dictLimit; + U32 const target = prefixIdx + (U32)size - LZ4MID_HASHSIZE; + U32 idx = cctx->nextToUpdate; + assert(dict == cctx->prefixStart); + DEBUGLOG(4, "LZ4MID_fillHTable (size:%zu)", size); + if (size <= LZ4MID_HASHSIZE) + return; + + for (; idx < target; idx += 3) { + ADDPOS4(prefixPtr+idx-prefixIdx, idx); + ADDPOS8(prefixPtr+idx+1-prefixIdx, idx+1); + } + + idx = (size > 32 KB + LZ4MID_HASHSIZE) ? target - 32 KB : cctx->nextToUpdate; + for (; idx < target; idx += 1) { + ADDPOS8(prefixPtr+idx-prefixIdx, idx); + } + + cctx->nextToUpdate = target; +} + +static LZ4MID_searchIntoDict_f select_searchDict_function(const LZ4HC_CCtx_internal* dictCtx) +{ + if (dictCtx == NULL) return NULL; + if (LZ4HC_getCLevelParams(dictCtx->compressionLevel).strat == lz4mid) + return LZ4MID_searchExtDict; + return LZ4MID_searchHCDict; +} + +static int LZ4MID_compress ( + LZ4HC_CCtx_internal* const ctx, + const char* const src, + char* const dst, + int* srcSizePtr, + int const maxOutputSize, + const limitedOutput_directive limit, + const dictCtx_directive dict + ) +{ + U32* const hash4Table = ctx->hashTable; + U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE; + const BYTE* ip = (const BYTE*)src; + const BYTE* anchor = ip; + const BYTE* const iend = ip + *srcSizePtr; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = (iend - LASTLITERALS); + const BYTE* const ilimit = (iend - LZ4MID_HASHSIZE); + BYTE* op = (BYTE*)dst; + BYTE* oend = op + maxOutputSize; + + const BYTE* const prefixPtr = ctx->prefixStart; + const U32 prefixIdx = ctx->dictLimit; + const U32 ilimitIdx = (U32)(ilimit - prefixPtr) + prefixIdx; + const BYTE* const dictStart = ctx->dictStart; + const U32 dictIdx = ctx->lowLimit; + const U32 gDictEndIndex = ctx->lowLimit; + const LZ4MID_searchIntoDict_f searchIntoDict = (dict == usingDictCtxHc) ? select_searchDict_function(ctx->dictCtx) : NULL; + unsigned matchLength; + unsigned matchDistance; + + /* input sanitization */ + DEBUGLOG(5, "LZ4MID_compress (%i bytes)", *srcSizePtr); + if (dict == usingDictCtxHc) DEBUGLOG(5, "usingDictCtxHc"); + assert(*srcSizePtr >= 0); + if (*srcSizePtr) assert(src != NULL); + if (maxOutputSize) assert(dst != NULL); + if (*srcSizePtr < 0) return 0; /* invalid */ + if (maxOutputSize < 0) return 0; /* invalid */ + if (*srcSizePtr > LZ4_MAX_INPUT_SIZE) { + /* forbidden: no input is allowed to be that large */ + return 0; + } + if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ + if (*srcSizePtr < LZ4_minLength) + goto _lz4mid_last_literals; /* Input too small, no compression (all literals) */ + + /* main loop */ + while (ip <= mflimit) { + const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx; + /* search long match */ + { U32 const h8 = LZ4MID_hash8Ptr(ip); + U32 const pos8 = hash8Table[h8]; + assert(h8 < LZ4MID_HASHTABLESIZE); + assert(pos8 < ipIndex); + LZ4MID_addPosition(hash8Table, h8, ipIndex); + if (ipIndex - pos8 <= LZ4_DISTANCE_MAX) { + /* match candidate found */ + if (pos8 >= prefixIdx) { + const BYTE* const matchPtr = prefixPtr + pos8 - prefixIdx; + assert(matchPtr < ip); + matchLength = LZ4_count(ip, matchPtr, matchlimit); + if (matchLength >= MINMATCH) { + DEBUGLOG(7, "found long match at pos %u (len=%u)", pos8, matchLength); + matchDistance = ipIndex - pos8; + goto _lz4mid_encode_sequence; + } + } else { + if (pos8 >= dictIdx) { + /* extDict match candidate */ + const BYTE* const matchPtr = dictStart + (pos8 - dictIdx); + const size_t safeLen = MIN(prefixIdx - pos8, (size_t)(matchlimit - ip)); + matchLength = LZ4_count(ip, matchPtr, ip + safeLen); + if (matchLength >= MINMATCH) { + DEBUGLOG(7, "found long match at ExtDict pos %u (len=%u)", pos8, matchLength); + matchDistance = ipIndex - pos8; + goto _lz4mid_encode_sequence; + } + } + } + } } + /* search short match */ + { U32 const h4 = LZ4MID_hash4Ptr(ip); + U32 const pos4 = hash4Table[h4]; + assert(h4 < LZ4MID_HASHTABLESIZE); + assert(pos4 < ipIndex); + LZ4MID_addPosition(hash4Table, h4, ipIndex); + if (ipIndex - pos4 <= LZ4_DISTANCE_MAX) { + /* match candidate found */ + if (pos4 >= prefixIdx) { + /* only search within prefix */ + const BYTE* const matchPtr = prefixPtr + (pos4 - prefixIdx); + assert(matchPtr < ip); + assert(matchPtr >= prefixPtr); + matchLength = LZ4_count(ip, matchPtr, matchlimit); + if (matchLength >= MINMATCH) { + /* short match found, let's just check ip+1 for longer */ + U32 const h8 = LZ4MID_hash8Ptr(ip+1); + U32 const pos8 = hash8Table[h8]; + U32 const m2Distance = ipIndex + 1 - pos8; + matchDistance = ipIndex - pos4; + if ( m2Distance <= LZ4_DISTANCE_MAX + && pos8 >= prefixIdx /* only search within prefix */ + && likely(ip < mflimit) + ) { + const BYTE* const m2Ptr = prefixPtr + (pos8 - prefixIdx); + unsigned ml2 = LZ4_count(ip+1, m2Ptr, matchlimit); + if (ml2 > matchLength) { + LZ4MID_addPosition(hash8Table, h8, ipIndex+1); + ip++; + matchLength = ml2; + matchDistance = m2Distance; + } } + goto _lz4mid_encode_sequence; + } + } else { + if (pos4 >= dictIdx) { + /* extDict match candidate */ + const BYTE* const matchPtr = dictStart + (pos4 - dictIdx); + const size_t safeLen = MIN(prefixIdx - pos4, (size_t)(matchlimit - ip)); + matchLength = LZ4_count(ip, matchPtr, ip + safeLen); + if (matchLength >= MINMATCH) { + DEBUGLOG(7, "found match at ExtDict pos %u (len=%u)", pos4, matchLength); + matchDistance = ipIndex - pos4; + goto _lz4mid_encode_sequence; + } + } + } + } } + /* no match found in prefix */ + if ( (dict == usingDictCtxHc) + && (ipIndex - gDictEndIndex < LZ4_DISTANCE_MAX - 8) ) { + /* search a match into external dictionary */ + LZ4HC_match_t dMatch = searchIntoDict(ip, ipIndex, + matchlimit, + ctx->dictCtx, gDictEndIndex); + if (dMatch.len >= MINMATCH) { + DEBUGLOG(7, "found Dictionary match (offset=%i)", dMatch.off); + assert(dMatch.back == 0); + matchLength = (unsigned)dMatch.len; + matchDistance = (unsigned)dMatch.off; + goto _lz4mid_encode_sequence; + } + } + /* no match found */ + ip += 1 + ((ip-anchor) >> 9); /* skip faster over incompressible data */ + continue; + +_lz4mid_encode_sequence: + /* catch back */ + while (((ip > anchor) & ((U32)(ip-prefixPtr) > matchDistance)) && (unlikely(ip[-1] == ip[-(int)matchDistance-1]))) { + ip--; matchLength++; + }; + + /* fill table with beginning of match */ + ADDPOS8(ip+1, ipIndex+1); + ADDPOS8(ip+2, ipIndex+2); + ADDPOS4(ip+1, ipIndex+1); + + /* encode */ + { BYTE* const saved_op = op; + /* LZ4HC_encodeSequence always updates @op; on success, it updates @ip and @anchor */ + if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + (int)matchLength, (int)matchDistance, + limit, oend) ) { + op = saved_op; /* restore @op value before failed LZ4HC_encodeSequence */ + goto _lz4mid_dest_overflow; + } + } + + /* fill table with end of match */ + { U32 endMatchIdx = (U32)(ip-prefixPtr) + prefixIdx; + U32 pos_m2 = endMatchIdx - 2; + if (pos_m2 < ilimitIdx) { + if (likely(ip - prefixPtr > 5)) { + ADDPOS8(ip-5, endMatchIdx - 5); + } + ADDPOS8(ip-3, endMatchIdx - 3); + ADDPOS8(ip-2, endMatchIdx - 2); + ADDPOS4(ip-2, endMatchIdx - 2); + ADDPOS4(ip-1, endMatchIdx - 1); + } + } + } + +_lz4mid_last_literals: + /* Encode Last Literals */ + { size_t lastRunSize = (size_t)(iend - anchor); /* literals */ + size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255; + size_t const totalSize = 1 + llAdd + lastRunSize; + if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ + if (limit && (op + totalSize > oend)) { + if (limit == limitedOutput) return 0; /* not enough space in @dst */ + /* adapt lastRunSize to fill 'dest' */ + lastRunSize = (size_t)(oend - op) - 1 /*token*/; + llAdd = (lastRunSize + 256 - RUN_MASK) / 256; + lastRunSize -= llAdd; + } + DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize); + ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */ + + if (lastRunSize >= RUN_MASK) { + size_t accumulator = lastRunSize - RUN_MASK; + *op++ = (RUN_MASK << ML_BITS); + for(; accumulator >= 255 ; accumulator -= 255) + *op++ = 255; + *op++ = (BYTE) accumulator; + } else { + *op++ = (BYTE)(lastRunSize << ML_BITS); + } + assert(lastRunSize <= (size_t)(oend - op)); + LZ4_memcpy(op, anchor, lastRunSize); + op += lastRunSize; + } + + /* End */ + DEBUGLOG(5, "compressed %i bytes into %i bytes", *srcSizePtr, (int)((char*)op - dst)); + assert(ip >= (const BYTE*)src); + assert(ip <= iend); + *srcSizePtr = (int)(ip - (const BYTE*)src); + assert((char*)op >= dst); + assert(op <= oend); + assert((char*)op - dst < INT_MAX); + return (int)((char*)op - dst); + +_lz4mid_dest_overflow: + if (limit == fillOutput) { + /* Assumption : @ip, @anchor, @optr and @matchLength must be set correctly */ + size_t const ll = (size_t)(ip - anchor); + size_t const ll_addbytes = (ll + 240) / 255; + size_t const ll_totalCost = 1 + ll_addbytes + ll; + BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */ + DEBUGLOG(6, "Last sequence is overflowing : %u literals, %u remaining space", + (unsigned)ll, (unsigned)(oend-op)); + if (op + ll_totalCost <= maxLitPos) { + /* ll validated; now adjust match length */ + size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost)); + size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255); + assert(maxMlSize < INT_MAX); + if ((size_t)matchLength > maxMlSize) matchLength= (unsigned)maxMlSize; + if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + matchLength >= MFLIMIT) { + DEBUGLOG(6, "Let's encode a last sequence (ll=%u, ml=%u)", (unsigned)ll, matchLength); + LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + (int)matchLength, (int)matchDistance, + notLimited, oend); + } } + DEBUGLOG(6, "Let's finish with a run of literals (%u bytes left)", (unsigned)(oend-op)); + goto _lz4mid_last_literals; + } + /* compression failed */ + return 0; +} + + +/************************************** +* HC Compression - Search +**************************************/ + /* Update chains up to ip (excluded) */ LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip) { @@ -140,23 +801,6 @@ LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip) hc4->nextToUpdate = target; } -/** LZ4HC_countBack() : - * @return : negative value, nb of common bytes before ip/match */ -LZ4_FORCE_INLINE -int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match, - const BYTE* const iMin, const BYTE* const mMin) -{ - int back = 0; - int const min = (int)MAX(iMin - ip, mMin - match); - assert(min <= 0); - assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31)); - assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31)); - while ( (back > min) - && (ip[back-1] == match[back-1]) ) - back--; - return back; -} - #if defined(_MSC_VER) # define LZ4HC_rotl32(x,r) _rotl(x,r) #else @@ -236,22 +880,21 @@ static int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex) typedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e; typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e; -LZ4_FORCE_INLINE int + +LZ4_FORCE_INLINE LZ4HC_match_t LZ4HC_InsertAndGetWiderMatch ( LZ4HC_CCtx_internal* const hc4, const BYTE* const ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit, int longest, - const BYTE** matchpos, - const BYTE** startpos, const int maxNbAttempts, const int patternAnalysis, const int chainSwap, const dictCtx_directive dict, const HCfavor_e favorDecSpeed) { U16* const chainTable = hc4->chainTable; - U32* const HashTable = hc4->hashTable; - const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx; + U32* const hashTable = hc4->hashTable; + const LZ4HC_CCtx_internal* const dictCtx = hc4->dictCtx; const BYTE* const prefixPtr = hc4->prefixStart; const U32 prefixIdx = hc4->dictLimit; const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx; @@ -267,22 +910,24 @@ LZ4HC_InsertAndGetWiderMatch ( U32 matchIndex; repeat_state_e repeat = rep_untested; size_t srcPatternLength = 0; + int offset = 0, sBack = 0; DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch"); /* First Match */ - LZ4HC_Insert(hc4, ip); - matchIndex = HashTable[LZ4HC_hashPtr(ip)]; - DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)", - matchIndex, lowestMatchIndex); + LZ4HC_Insert(hc4, ip); /* insert all prior positions up to ip (excluded) */ + matchIndex = hashTable[LZ4HC_hashPtr(ip)]; + DEBUGLOG(7, "First candidate match for pos %u found at index %u / %u (lowestMatchIndex)", + ipIndex, matchIndex, lowestMatchIndex); while ((matchIndex>=lowestMatchIndex) && (nbAttempts>0)) { int matchLength=0; nbAttempts--; assert(matchIndex < ipIndex); if (favorDecSpeed && (ipIndex - matchIndex < 8)) { - /* do nothing */ + /* do nothing: + * favorDecSpeed intentionally skips matches with offset < 8 */ } else if (matchIndex >= prefixIdx) { /* within current Prefix */ - const BYTE* const matchPtr = prefixPtr + matchIndex - prefixIdx; + const BYTE* const matchPtr = prefixPtr + (matchIndex - prefixIdx); assert(matchPtr < ip); assert(longest >= 1); if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) { @@ -292,10 +937,11 @@ LZ4HC_InsertAndGetWiderMatch ( matchLength -= back; if (matchLength > longest) { longest = matchLength; - *matchpos = matchPtr + back; - *startpos = ip + back; + offset = (int)(ipIndex - matchIndex); + sBack = back; + DEBUGLOG(7, "Found match of len=%i within prefix, offset=%i, back=%i", longest, offset, -back); } } } - } else { /* lowestMatchIndex <= matchIndex < dictLimit */ + } else { /* lowestMatchIndex <= matchIndex < dictLimit : within Ext Dict */ const BYTE* const matchPtr = dictStart + (matchIndex - dictIdx); assert(matchIndex >= dictIdx); if ( likely(matchIndex <= prefixIdx - 4) @@ -310,8 +956,9 @@ LZ4HC_InsertAndGetWiderMatch ( matchLength -= back; if (matchLength > longest) { longest = matchLength; - *matchpos = prefixPtr - prefixIdx + matchIndex + back; /* virtual pos, relative to ip, to retrieve offset */ - *startpos = ip + back; + offset = (int)(ipIndex - matchIndex); + sBack = back; + DEBUGLOG(7, "Found match of len=%i within dict, offset=%i, back=%i", longest, offset, -back); } } } if (chainSwap && matchLength==longest) { /* better match => select a better chain */ @@ -344,6 +991,7 @@ LZ4HC_InsertAndGetWiderMatch ( if (repeat == rep_untested) { if ( ((pattern & 0xFFFF) == (pattern >> 16)) & ((pattern & 0xFF) == (pattern >> 24)) ) { + DEBUGLOG(7, "Repeat pattern detected, char %02X", pattern >> 24); repeat = rep_confirmed; srcPatternLength = LZ4HC_countPattern(ip+sizeof(pattern), iHighLimit, pattern) + sizeof(pattern); } else { @@ -352,7 +1000,7 @@ LZ4HC_InsertAndGetWiderMatch ( if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex) && LZ4HC_protectDictEnd(prefixIdx, matchCandidateIdx) ) { const int extDict = matchCandidateIdx < prefixIdx; - const BYTE* const matchPtr = (extDict ? dictStart - dictIdx : prefixPtr - prefixIdx) + matchCandidateIdx; + const BYTE* const matchPtr = extDict ? dictStart + (matchCandidateIdx - dictIdx) : prefixPtr + (matchCandidateIdx - prefixIdx); if (LZ4_read32(matchPtr) == pattern) { /* good candidate */ const BYTE* const iLimit = extDict ? dictEnd : iHighLimit; size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern); @@ -398,8 +1046,9 @@ LZ4HC_InsertAndGetWiderMatch ( if ((size_t)(ip - prefixPtr) + prefixIdx - matchIndex > LZ4_DISTANCE_MAX) break; assert(maxML < 2 GB); longest = (int)maxML; - *matchpos = prefixPtr - prefixIdx + matchIndex; /* virtual pos, relative to ip, to retrieve offset */ - *startpos = ip; + offset = (int)(ipIndex - matchIndex); + assert(sBack == 0); + DEBUGLOG(7, "Found repeat pattern match of len=%i, offset=%i", longest, offset); } { U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex); if (distToNextPattern > matchIndex) break; /* avoid overflow */ @@ -416,11 +1065,12 @@ LZ4HC_InsertAndGetWiderMatch ( if ( dict == usingDictCtxHc && nbAttempts > 0 - && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) { + && withinStartDistance) { size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit; U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)]; assert(dictEndOffset <= 1 GB); matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset; + if (dictMatchIndex>0) DEBUGLOG(7, "dictEndOffset = %zu, dictMatchIndex = %u => relative matchIndex = %i", dictEndOffset, dictMatchIndex, (int)dictMatchIndex - (int)dictEndOffset); while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) { const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + dictMatchIndex; @@ -434,8 +1084,9 @@ LZ4HC_InsertAndGetWiderMatch ( mlt -= back; if (mlt > longest) { longest = mlt; - *matchpos = prefixPtr - prefixIdx + matchIndex + back; - *startpos = ip + back; + offset = (int)(ipIndex - matchIndex); + sBack = back; + DEBUGLOG(7, "found match of length %i within extDictCtx", longest); } } { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex); @@ -443,112 +1094,29 @@ LZ4HC_InsertAndGetWiderMatch ( matchIndex -= nextOffset; } } } - return longest; + { LZ4HC_match_t md; + assert(longest >= 0); + md.len = longest; + md.off = offset; + md.back = sBack; + return md; + } } -LZ4_FORCE_INLINE int +LZ4_FORCE_INLINE LZ4HC_match_t LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */ const BYTE* const ip, const BYTE* const iLimit, - const BYTE** matchpos, const int maxNbAttempts, const int patternAnalysis, const dictCtx_directive dict) { - const BYTE* uselessPtr = ip; + DEBUGLOG(7, "LZ4HC_InsertAndFindBestMatch"); /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), * but this won't be the case here, as we define iLowLimit==ip, * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ - return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, matchpos, &uselessPtr, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio); + return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio); } -/* LZ4HC_encodeSequence() : - * @return : 0 if ok, - * 1 if buffer issue detected */ -LZ4_FORCE_INLINE int LZ4HC_encodeSequence ( - const BYTE** _ip, - BYTE** _op, - const BYTE** _anchor, - int matchLength, - const BYTE* const match, - limitedOutput_directive limit, - BYTE* oend) -{ -#define ip (*_ip) -#define op (*_op) -#define anchor (*_anchor) - - size_t length; - BYTE* const token = op++; - -#if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6) - static const BYTE* start = NULL; - static U32 totalCost = 0; - U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start); - U32 const ll = (U32)(ip - anchor); - U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0; - U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0; - U32 const cost = 1 + llAdd + ll + 2 + mlAdd; - if (start==NULL) start = anchor; /* only works for single segment */ - /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */ - DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5u, cost:%4u + %5u", - pos, - (U32)(ip - anchor), matchLength, (U32)(ip-match), - cost, totalCost); - totalCost += cost; -#endif - - /* Encode Literal length */ - length = (size_t)(ip - anchor); - LZ4_STATIC_ASSERT(notLimited == 0); - /* Check output limit */ - if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) { - DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)", - (int)length, (int)(oend - op)); - return 1; - } - if (length >= RUN_MASK) { - size_t len = length - RUN_MASK; - *token = (RUN_MASK << ML_BITS); - for(; len >= 255 ; len -= 255) *op++ = 255; - *op++ = (BYTE)len; - } else { - *token = (BYTE)(length << ML_BITS); - } - - /* Copy Literals */ - LZ4_wildCopy8(op, anchor, op + length); - op += length; - - /* Encode Offset */ - assert( (ip - match) <= LZ4_DISTANCE_MAX ); /* note : consider providing offset as a value, rather than as a pointer difference */ - LZ4_writeLE16(op, (U16)(ip - match)); op += 2; - - /* Encode MatchLength */ - assert(matchLength >= MINMATCH); - length = (size_t)matchLength - MINMATCH; - if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) { - DEBUGLOG(6, "Not enough room to write match length"); - return 1; /* Check output limit */ - } - if (length >= ML_MASK) { - *token += ML_MASK; - length -= ML_MASK; - for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; } - if (length >= 255) { length -= 255; *op++ = 255; } - *op++ = (BYTE)length; - } else { - *token += (BYTE)(length); - } - - /* Prepare next loop */ - ip += matchLength; - anchor = ip; - - return 0; -} -#undef ip -#undef op -#undef anchor LZ4_FORCE_INLINE int LZ4HC_compress_hashChain ( LZ4HC_CCtx_internal* const ctx, @@ -574,127 +1142,130 @@ LZ4_FORCE_INLINE int LZ4HC_compress_hashChain ( BYTE* op = (BYTE*) dest; BYTE* oend = op + maxOutputSize; - int ml0, ml, ml2, ml3; const BYTE* start0; - const BYTE* ref0; - const BYTE* ref = NULL; const BYTE* start2 = NULL; - const BYTE* ref2 = NULL; const BYTE* start3 = NULL; - const BYTE* ref3 = NULL; + LZ4HC_match_t m0, m1, m2, m3; + const LZ4HC_match_t nomatch = {0, 0, 0}; /* init */ + DEBUGLOG(5, "LZ4HC_compress_hashChain (dict?=>%i)", dict); *srcSizePtr = 0; if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ /* Main Loop */ while (ip <= mflimit) { - ml = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, &ref, maxNbAttempts, patternAnalysis, dict); - if (ml encode ML1 */ + if (m2.len <= m1.len) { /* No better match => encode ML1 immediately */ optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; + if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + m1.len, m1.off, + limit, oend) ) + goto _dest_overflow; continue; } if (start0 < ip) { /* first match was skipped at least once */ - if (start2 < ip + ml0) { /* squeezing ML1 between ML0(original ML1) and ML2 */ - ip = start0; ref = ref0; ml = ml0; /* restore initial ML1 */ + if (start2 < ip + m0.len) { /* squeezing ML1 between ML0(original ML1) and ML2 */ + ip = start0; m1 = m0; /* restore initial Match1 */ } } /* Here, start0==ip */ if ((start2 - ip) < 3) { /* First Match too small : removed */ - ml = ml2; ip = start2; - ref =ref2; + m1 = m2; goto _Search2; } _Search3: - /* At this stage, we have : - * ml2 > ml1, and - * ip1+3 <= ip2 (usually < ip1+ml1) */ if ((start2 - ip) < OPTIMAL_ML) { int correction; - int new_ml = ml; + int new_ml = m1.len; if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML; - if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH; + if (ip+new_ml > start2 + m2.len - MINMATCH) + new_ml = (int)(start2 - ip) + m2.len - MINMATCH; correction = new_ml - (int)(start2 - ip); if (correction > 0) { start2 += correction; - ref2 += correction; - ml2 -= correction; + m2.len -= correction; } } - /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */ - if (start2 + ml2 <= mflimit) { - ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, - start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, + if (start2 + m2.len <= mflimit) { + start3 = start2 + m2.len - 3; + m3 = LZ4HC_InsertAndGetWiderMatch(ctx, + start3, start2, matchlimit, m2.len, maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio); + start3 += m3.back; } else { - ml3 = ml2; + m3 = nomatch; /* do not search further */ } - if (ml3 == ml2) { /* No better match => encode ML1 and ML2 */ + if (m3.len <= m2.len) { /* No better match => encode ML1 and ML2 */ /* ip & ref are known; Now for ml */ - if (start2 < ip+ml) ml = (int)(start2 - ip); + if (start2 < ip+m1.len) m1.len = (int)(start2 - ip); /* Now, encode 2 sequences */ optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; + if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + m1.len, m1.off, + limit, oend) ) + goto _dest_overflow; ip = start2; optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) { - ml = ml2; - ref = ref2; + if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + m2.len, m2.off, + limit, oend) ) { + m1 = m2; goto _dest_overflow; } continue; } - if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */ - if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */ - if (start2 < ip+ml) { - int correction = (int)(ip+ml - start2); + if (start3 < ip+m1.len+3) { /* Not enough space for match 2 : remove it */ + if (start3 >= (ip+m1.len)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */ + if (start2 < ip+m1.len) { + int correction = (int)(ip+m1.len - start2); start2 += correction; - ref2 += correction; - ml2 -= correction; - if (ml2 < MINMATCH) { + m2.len -= correction; + if (m2.len < MINMATCH) { start2 = start3; - ref2 = ref3; - ml2 = ml3; + m2 = m3; } } optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; + if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + m1.len, m1.off, + limit, oend) ) + goto _dest_overflow; ip = start3; - ref = ref3; - ml = ml3; + m1 = m3; start0 = start2; - ref0 = ref2; - ml0 = ml2; + m0 = m2; goto _Search2; } start2 = start3; - ref2 = ref3; - ml2 = ml3; + m2 = m3; goto _Search3; } @@ -703,29 +1274,32 @@ _Search3: * let's write the first one ML1. * ip & ref are known; Now decide ml. */ - if (start2 < ip+ml) { + if (start2 < ip+m1.len) { if ((start2 - ip) < OPTIMAL_ML) { int correction; - if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; - if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; - correction = ml - (int)(start2 - ip); + if (m1.len > OPTIMAL_ML) m1.len = OPTIMAL_ML; + if (ip + m1.len > start2 + m2.len - MINMATCH) + m1.len = (int)(start2 - ip) + m2.len - MINMATCH; + correction = m1.len - (int)(start2 - ip); if (correction > 0) { start2 += correction; - ref2 += correction; - ml2 -= correction; + m2.len -= correction; } } else { - ml = (int)(start2 - ip); + m1.len = (int)(start2 - ip); } } optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; + if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), + m1.len, m1.off, + limit, oend) ) + goto _dest_overflow; /* ML2 becomes ML1 */ - ip = start2; ref = ref2; ml = ml2; + ip = start2; m1 = m2; /* ML3 becomes ML2 */ - start2 = start3; ref2 = ref3; ml2 = ml3; + start2 = start3; m2 = m3; /* let's find a new ML3 */ goto _Search3; @@ -765,7 +1339,7 @@ _last_literals: _dest_overflow: if (limit == fillOutput) { - /* Assumption : ip, anchor, ml and ref must be set correctly */ + /* Assumption : @ip, @anchor, @optr and @m1 must be set correctly */ size_t const ll = (size_t)(ip - anchor); size_t const ll_addbytes = (ll + 240) / 255; size_t const ll_totalCost = 1 + ll_addbytes + ll; @@ -776,10 +1350,10 @@ _dest_overflow: /* ll validated; now adjust match length */ size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost)); size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255); - assert(maxMlSize < INT_MAX); assert(ml >= 0); - if ((size_t)ml > maxMlSize) ml = (int)maxMlSize; - if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ml >= MFLIMIT) { - LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, notLimited, oend); + assert(maxMlSize < INT_MAX); assert(m1.len >= 0); + if ((size_t)m1.len > maxMlSize) m1.len = (int)maxMlSize; + if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + m1.len >= MFLIMIT) { + LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, notLimited, oend); } } goto _last_literals; } @@ -796,54 +1370,34 @@ static int LZ4HC_compress_optimal( LZ4HC_CCtx_internal* ctx, const dictCtx_directive dict, const HCfavor_e favorDecSpeed); - -LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - const limitedOutput_directive limit, - const dictCtx_directive dict - ) +LZ4_FORCE_INLINE int +LZ4HC_compress_generic_internal ( + LZ4HC_CCtx_internal* const ctx, + const char* const src, + char* const dst, + int* const srcSizePtr, + int const dstCapacity, + int cLevel, + const limitedOutput_directive limit, + const dictCtx_directive dict + ) { - typedef enum { lz4hc, lz4opt } lz4hc_strat_e; - typedef struct { - lz4hc_strat_e strat; - int nbSearches; - U32 targetLength; - } cParams_t; - static const cParams_t clTable[LZ4HC_CLEVEL_MAX+1] = { - { lz4hc, 2, 16 }, /* 0, unused */ - { lz4hc, 2, 16 }, /* 1, unused */ - { lz4hc, 2, 16 }, /* 2, unused */ - { lz4hc, 4, 16 }, /* 3 */ - { lz4hc, 8, 16 }, /* 4 */ - { lz4hc, 16, 16 }, /* 5 */ - { lz4hc, 32, 16 }, /* 6 */ - { lz4hc, 64, 16 }, /* 7 */ - { lz4hc, 128, 16 }, /* 8 */ - { lz4hc, 256, 16 }, /* 9 */ - { lz4opt, 96, 64 }, /*10==LZ4HC_CLEVEL_OPT_MIN*/ - { lz4opt, 512,128 }, /*11 */ - { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */ - }; - - DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)", - ctx, src, *srcSizePtr, limit); + DEBUGLOG(5, "LZ4HC_compress_generic_internal(src=%p, srcSize=%d)", + src, *srcSizePtr); if (limit == fillOutput && dstCapacity < 1) return 0; /* Impossible to store anything */ - if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */ + if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */ ctx->end += *srcSizePtr; - if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe something to review */ - cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel); - { cParams_t const cParam = clTable[cLevel]; + { cParams_t const cParam = LZ4HC_getCLevelParams(cLevel); HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio; int result; - if (cParam.strat == lz4hc) { + if (cParam.strat == lz4mid) { + result = LZ4MID_compress(ctx, + src, dst, srcSizePtr, dstCapacity, + limit, dict); + } else if (cParam.strat == lz4hc) { result = LZ4HC_compress_hashChain(ctx, src, dst, srcSizePtr, dstCapacity, cParam.nbSearches, limit, dict); @@ -852,7 +1406,7 @@ LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal ( result = LZ4HC_compress_optimal(ctx, src, dst, srcSizePtr, dstCapacity, cParam.nbSearches, cParam.targetLength, limit, - cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */ + cLevel >= LZ4HC_CLEVEL_MAX, /* ultra mode */ dict, favor); } if (result <= 0) ctx->dirty = 1; @@ -877,6 +1431,13 @@ LZ4HC_compress_generic_noDictCtx ( return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx); } +static int isStateCompatible(const LZ4HC_CCtx_internal* ctx1, const LZ4HC_CCtx_internal* ctx2) +{ + int const isMid1 = LZ4HC_getCLevelParams(ctx1->compressionLevel).strat == lz4mid; + int const isMid2 = LZ4HC_getCLevelParams(ctx2->compressionLevel).strat == lz4mid; + return !(isMid1 ^ isMid2); +} + static int LZ4HC_compress_generic_dictCtx ( LZ4HC_CCtx_internal* const ctx, @@ -893,7 +1454,7 @@ LZ4HC_compress_generic_dictCtx ( if (position >= 64 KB) { ctx->dictCtx = NULL; return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); - } else if (position == 0 && *srcSizePtr > 4 KB) { + } else if (position == 0 && *srcSizePtr > 4 KB && isStateCompatible(ctx, ctx->dictCtx)) { LZ4_memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal)); LZ4HC_setExternalDict(ctx, (const BYTE *)src); ctx->compressionLevel = (short)cLevel; @@ -965,6 +1526,7 @@ int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, in LZ4_streamHC_t state; LZ4_streamHC_t* const statePtr = &state; #endif + DEBUGLOG(5, "LZ4_compress_HC") cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel); #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 FREEMEM(statePtr); @@ -1032,18 +1594,16 @@ void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) { - DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel); - if (LZ4_streamHCPtr->internal_donotuse.dirty) { + LZ4HC_CCtx_internal* const s = &LZ4_streamHCPtr->internal_donotuse; + DEBUGLOG(5, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel); + if (s->dirty) { LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); } else { - /* preserve end - prefixStart : can trigger clearTable's threshold */ - if (LZ4_streamHCPtr->internal_donotuse.end != NULL) { - LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.prefixStart; - } else { - assert(LZ4_streamHCPtr->internal_donotuse.prefixStart == NULL); - } - LZ4_streamHCPtr->internal_donotuse.prefixStart = NULL; - LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; + assert(s->end >= s->prefixStart); + s->dictLimit += (U32)(s->end - s->prefixStart); + s->prefixStart = NULL; + s->end = NULL; + s->dictCtx = NULL; } LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); } @@ -1067,7 +1627,9 @@ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize) { LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; - DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d)", LZ4_streamHCPtr, dictionary, dictSize); + cParams_t cp; + DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d, clevel=%d)", LZ4_streamHCPtr, dictionary, dictSize, ctxPtr->compressionLevel); + assert(dictSize >= 0); assert(LZ4_streamHCPtr != NULL); if (dictSize > 64 KB) { dictionary += (size_t)dictSize - 64 KB; @@ -1077,10 +1639,15 @@ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, { int const cLevel = ctxPtr->compressionLevel; LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); LZ4_setCompressionLevel(LZ4_streamHCPtr, cLevel); + cp = LZ4HC_getCLevelParams(cLevel); } LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary); ctxPtr->end = (const BYTE*)dictionary + dictSize; - if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); + if (cp.strat == lz4mid) { + LZ4MID_fillHTable (ctxPtr, dictionary, (size_t)dictSize); + } else { + if (dictSize >= LZ4HC_HASHSIZE) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); + } return dictSize; } @@ -1093,8 +1660,10 @@ void LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock) { DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock); - if (ctxPtr->end >= ctxPtr->prefixStart + 4) - LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ + if ( (ctxPtr->end >= ctxPtr->prefixStart + 4) + && (LZ4HC_getCLevelParams(ctxPtr->compressionLevel).strat != lz4mid) ) { + LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ + } /* Only one memory segment for extDict, so any previous extDict is lost at this stage */ ctxPtr->lowLimit = ctxPtr->dictLimit; @@ -1119,7 +1688,8 @@ LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, LZ4_streamHCPtr, src, *srcSizePtr, limit); assert(ctxPtr != NULL); /* auto-init if forgotten */ - if (ctxPtr->prefixStart == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src); + if (ctxPtr->prefixStart == NULL) + LZ4HC_init_internal (ctxPtr, (const BYTE*) src); /* Check overflow */ if ((size_t)(ctxPtr->end - ctxPtr->prefixStart) + ctxPtr->dictLimit > 2 GB) { @@ -1140,7 +1710,8 @@ LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, if (sourceEnd > dictEnd) sourceEnd = dictEnd; ctxPtr->lowLimit += (U32)(sourceEnd - ctxPtr->dictStart); ctxPtr->dictStart += (U32)(sourceEnd - ctxPtr->dictStart); - if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) { + /* invalidate dictionary is it's too small */ + if (ctxPtr->dictLimit - ctxPtr->lowLimit < LZ4HC_HASHSIZE) { ctxPtr->lowLimit = ctxPtr->dictLimit; ctxPtr->dictStart = ctxPtr->prefixStart; } } } @@ -1150,6 +1721,7 @@ LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int srcSize, int dstCapacity) { + DEBUGLOG(5, "LZ4_compress_HC_continue"); if (dstCapacity < LZ4_compressBound(srcSize)) return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, limitedOutput); else @@ -1162,7 +1734,6 @@ int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const ch } - /* LZ4_saveDictHC : * save history content * into a user-provided buffer @@ -1179,10 +1750,10 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS if (dictSize > prefixSize) dictSize = prefixSize; if (safeBuffer == NULL) assert(dictSize == 0); if (dictSize > 0) - LZ4_memmove(safeBuffer, streamPtr->end - dictSize, dictSize); + LZ4_memmove(safeBuffer, streamPtr->end - dictSize, (size_t)dictSize); { U32 const endIndex = (U32)(streamPtr->end - streamPtr->prefixStart) + streamPtr->dictLimit; - streamPtr->end = (const BYTE*)safeBuffer + dictSize; - streamPtr->prefixStart = streamPtr->end - dictSize; + streamPtr->end = (safeBuffer == NULL) ? NULL : (const BYTE*)safeBuffer + dictSize; + streamPtr->prefixStart = (const BYTE*)safeBuffer; streamPtr->dictLimit = endIndex - (U32)dictSize; streamPtr->lowLimit = endIndex - (U32)dictSize; streamPtr->dictStart = streamPtr->prefixStart; @@ -1193,75 +1764,6 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS } -/*************************************************** -* Deprecated Functions -***************************************************/ - -/* These functions currently generate deprecation warnings */ - -/* Wrappers for deprecated compression functions */ -int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); } -int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); } -int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } -int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); } -int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); } -int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); } -int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } -int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); } -int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); } -int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); } - - -/* Deprecated streaming functions */ -int LZ4_sizeofStreamStateHC(void) { return sizeof(LZ4_streamHC_t); } - -/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t) - * @return : 0 on success, !=0 if error */ -int LZ4_resetStreamStateHC(void* state, char* inputBuffer) -{ - LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4)); - if (hc4 == NULL) return 1; /* init failed */ - LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); - return 0; -} - -#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) -void* LZ4_createHC (const char* inputBuffer) -{ - LZ4_streamHC_t* const hc4 = LZ4_createStreamHC(); - if (hc4 == NULL) return NULL; /* not enough memory */ - LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); - return hc4; -} - -int LZ4_freeHC (void* LZ4HC_Data) -{ - if (!LZ4HC_Data) return 0; /* support free on NULL */ - FREEMEM(LZ4HC_Data); - return 0; -} -#endif - -int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel) -{ - return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, notLimited); -} - -int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel) -{ - return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput); -} - -char* LZ4_slideInputBufferHC(void* LZ4HC_Data) -{ - LZ4_streamHC_t* const ctx = (LZ4_streamHC_t*)LZ4HC_Data; - const BYTE* bufferStart = ctx->internal_donotuse.prefixStart - ctx->internal_donotuse.dictLimit + ctx->internal_donotuse.lowLimit; - LZ4_resetStreamHC_fast(ctx, ctx->internal_donotuse.compressionLevel); - /* avoid const char * -> char * conversion warning :( */ - return (char*)(uptrval)bufferStart; -} - - /* ================================================ * LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX]) * ===============================================*/ @@ -1282,7 +1784,6 @@ LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen) return price; } - /* requires mlen >= MINMATCH */ LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen) { @@ -1298,12 +1799,6 @@ LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen) return price; } - -typedef struct { - int off; - int len; -} LZ4HC_match_t; - LZ4_FORCE_INLINE LZ4HC_match_t LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx, const BYTE* ip, const BYTE* const iHighLimit, @@ -1311,19 +1806,17 @@ LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx, const dictCtx_directive dict, const HCfavor_e favorDecSpeed) { - LZ4HC_match_t match = { 0 , 0 }; - const BYTE* matchPtr = NULL; + LZ4HC_match_t const match0 = { 0 , 0, 0 }; /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), * but this won't be the case here, as we define iLowLimit==ip, - * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ - int matchLength = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, &matchPtr, &ip, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed); - if (matchLength <= minLen) return match; + ** so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ + LZ4HC_match_t md = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed); + assert(md.back == 0); + if (md.len <= minLen) return match0; if (favorDecSpeed) { - if ((matchLength>18) & (matchLength<=36)) matchLength=18; /* favor shortcut */ + if ((md.len>18) & (md.len<=36)) md.len=18; /* favor dec.speed (shortcut) */ } - match.len = matchLength; - match.off = (int)(ip-matchPtr); - return match; + return md; } @@ -1356,7 +1849,7 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx, BYTE* opSaved = (BYTE*) dst; BYTE* oend = op + dstCapacity; int ovml = MINMATCH; /* overflow - last sequence */ - const BYTE* ovref = NULL; + int ovoff = 0; /* init */ #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 @@ -1379,11 +1872,10 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx, if ((size_t)firstMatch.len > sufficient_len) { /* good enough solution : immediate encoding */ int const firstML = firstMatch.len; - const BYTE* const matchPos = ip - firstMatch.off; opSaved = op; - if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend) ) { /* updates ip, op and anchor */ + if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, firstMatch.off, limit, oend) ) { /* updates ip, op and anchor */ ovml = firstML; - ovref = matchPos; + ovoff = firstMatch.off; goto _dest_overflow; } continue; @@ -1401,11 +1893,11 @@ static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx, rPos, cost, opt[rPos].litlen); } } /* set prices using initial match */ - { int mlen = MINMATCH; - int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */ + { int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */ int const offset = firstMatch.off; + int mlen; assert(matchML < LZ4_OPT_NUM); - for ( ; mlen <= matchML ; mlen++) { + for (mlen = MINMATCH ; mlen <= matchML ; mlen++) { int const cost = LZ4HC_sequencePrice(llen, mlen); opt[mlen].mlen = mlen; opt[mlen].off = offset; @@ -1557,9 +2049,9 @@ encode: /* cur, last_match_pos, best_mlen, best_off must be set */ assert(ml >= MINMATCH); assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX)); opSaved = op; - if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend) ) { /* updates ip, op and anchor */ + if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, offset, limit, oend) ) { /* updates ip, op and anchor */ ovml = ml; - ovref = ip - offset; + ovoff = offset; goto _dest_overflow; } } } } /* while (ip <= mflimit) */ @@ -1618,14 +2110,83 @@ if (limit == fillOutput) { if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) { DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml); DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip, anchor); - LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovref, notLimited, oend); + LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovoff, notLimited, oend); DEBUGLOG(6, "After : ip = %p, anchor = %p", ip, anchor); } } goto _last_literals; } _return_label: #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 - FREEMEM(opt); + if (opt) FREEMEM(opt); #endif return retval; } + + +/*************************************************** +* Deprecated Functions +***************************************************/ + +/* These functions currently generate deprecation warnings */ + +/* Wrappers for deprecated compression functions */ +int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); } +int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); } +int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } +int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); } +int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); } +int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); } +int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } +int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); } +int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); } +int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); } + + +/* Deprecated streaming functions */ +int LZ4_sizeofStreamStateHC(void) { return sizeof(LZ4_streamHC_t); } + +/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t) + * @return : 0 on success, !=0 if error */ +int LZ4_resetStreamStateHC(void* state, char* inputBuffer) +{ + LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4)); + if (hc4 == NULL) return 1; /* init failed */ + LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); + return 0; +} + +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +void* LZ4_createHC (const char* inputBuffer) +{ + LZ4_streamHC_t* const hc4 = LZ4_createStreamHC(); + if (hc4 == NULL) return NULL; /* not enough memory */ + LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); + return hc4; +} + +int LZ4_freeHC (void* LZ4HC_Data) +{ + if (!LZ4HC_Data) return 0; /* support free on NULL */ + FREEMEM(LZ4HC_Data); + return 0; +} +#endif + +int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel) +{ + return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, notLimited); +} + +int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel) +{ + return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput); +} + +char* LZ4_slideInputBufferHC(void* LZ4HC_Data) +{ + LZ4HC_CCtx_internal* const s = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse; + const BYTE* const bufferStart = s->prefixStart - s->dictLimit + s->lowLimit; + LZ4_resetStreamHC_fast((LZ4_streamHC_t*)LZ4HC_Data, s->compressionLevel); + /* ugly conversion trick, required to evade (const char*) -> (char*) cast-qual warning :( */ + return (char*)(uptrval)bufferStart; +} diff --git a/src/third_party/mozjs/extract/mfbt/lz4/lz4hc.h b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4hc.h similarity index 93% rename from src/third_party/mozjs/extract/mfbt/lz4/lz4hc.h rename to src/third_party/mozjs/extract/mozglue/static/lz4/lz4hc.h index e937acfefd8..992bc8cdd77 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/lz4hc.h +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/lz4hc.h @@ -44,7 +44,7 @@ extern "C" { /* --- Useful constants --- */ -#define LZ4HC_CLEVEL_MIN 3 +#define LZ4HC_CLEVEL_MIN 2 #define LZ4HC_CLEVEL_DEFAULT 9 #define LZ4HC_CLEVEL_OPT_MIN 10 #define LZ4HC_CLEVEL_MAX 12 @@ -126,6 +126,8 @@ LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); After reset, a first "fictional block" can be designated as initial dictionary, using LZ4_loadDictHC() (Optional). + Note: In order for LZ4_loadDictHC() to create the correct data structure, + it is essential to set the compression level _before_ loading the dictionary. Invoke LZ4_compress_HC_continue() to compress each successive block. The number of blocks is unlimited. @@ -135,12 +137,12 @@ LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); It's allowed to update compression level anytime between blocks, using LZ4_setCompressionLevel() (experimental). - 'dst' buffer should be sized to handle worst case scenarios + @dst buffer should be sized to handle worst case scenarios (see LZ4_compressBound(), it ensures compression success). In case of failure, the API does not guarantee recovery, so the state _must_ be reset. To ensure compression success - whenever `dst` buffer size cannot be made >= LZ4_compressBound(), + whenever @dst buffer size cannot be made >= LZ4_compressBound(), consider using LZ4_compress_HC_continue_destSize(). Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks, @@ -176,6 +178,34 @@ LZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize); +/*! LZ4_attach_HC_dictionary() : stable since v1.10.0 + * This API allows for the efficient re-use of a static dictionary many times. + * + * Rather than re-loading the dictionary buffer into a working context before + * each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a + * working LZ4_streamHC_t, this function introduces a no-copy setup mechanism, + * in which the working stream references the dictionary stream in-place. + * + * Several assumptions are made about the state of the dictionary stream. + * Currently, only streams which have been prepared by LZ4_loadDictHC() should + * be expected to work. + * + * Alternatively, the provided dictionary stream pointer may be NULL, in which + * case any existing dictionary stream is unset. + * + * A dictionary should only be attached to a stream without any history (i.e., + * a stream that has just been reset). + * + * The dictionary will remain attached to the working stream only for the + * current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the + * dictionary context association from the working stream. The dictionary + * stream (and source buffer) must remain in-place / accessible / unchanged + * through the lifetime of the stream session. + */ +LZ4LIB_API void +LZ4_attach_HC_dictionary(LZ4_streamHC_t* working_stream, + const LZ4_streamHC_t* dictionary_stream); + /*^********************************************** * !!!!!! STATIC LINKING ONLY !!!!!! @@ -204,18 +234,18 @@ LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, in typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal; struct LZ4HC_CCtx_internal { - LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE]; - LZ4_u16 chainTable[LZ4HC_MAXD]; - const LZ4_byte* end; /* next block here to continue on current prefix */ + LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE]; + LZ4_u16 chainTable[LZ4HC_MAXD]; + const LZ4_byte* end; /* next block here to continue on current prefix */ const LZ4_byte* prefixStart; /* Indexes relative to this position */ const LZ4_byte* dictStart; /* alternate reference for extDict */ - LZ4_u32 dictLimit; /* below that point, need extDict */ - LZ4_u32 lowLimit; /* below that point, no more dict */ - LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */ - short compressionLevel; - LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set, - otherwise, favor compression ratio */ - LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */ + LZ4_u32 dictLimit; /* below that point, need extDict */ + LZ4_u32 lowLimit; /* below that point, no more history */ + LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */ + short compressionLevel; + LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set, + otherwise, favor compression ratio */ + LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */ const LZ4HC_CCtx_internal* dictCtx; }; @@ -376,35 +406,6 @@ LZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset ( int srcSize, int dstCapacity, int compressionLevel); -/*! LZ4_attach_HC_dictionary() : - * This is an experimental API that allows for the efficient use of a - * static dictionary many times. - * - * Rather than re-loading the dictionary buffer into a working context before - * each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a - * working LZ4_streamHC_t, this function introduces a no-copy setup mechanism, - * in which the working stream references the dictionary stream in-place. - * - * Several assumptions are made about the state of the dictionary stream. - * Currently, only streams which have been prepared by LZ4_loadDictHC() should - * be expected to work. - * - * Alternatively, the provided dictionary stream pointer may be NULL, in which - * case any existing dictionary stream is unset. - * - * A dictionary should only be attached to a stream without any history (i.e., - * a stream that has just been reset). - * - * The dictionary will remain attached to the working stream only for the - * current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the - * dictionary context association from the working stream. The dictionary - * stream (and source buffer) must remain in-place / accessible / unchanged - * through the lifetime of the stream session. - */ -LZ4LIB_STATIC_API void LZ4_attach_HC_dictionary( - LZ4_streamHC_t *working_stream, - const LZ4_streamHC_t *dictionary_stream); - #if defined (__cplusplus) } #endif diff --git a/src/third_party/mozjs/extract/mfbt/lz4/xxhash.c b/src/third_party/mozjs/extract/mozglue/static/lz4/xxhash.c similarity index 91% rename from src/third_party/mozjs/extract/mfbt/lz4/xxhash.c rename to src/third_party/mozjs/extract/mozglue/static/lz4/xxhash.c index 083b039d70d..e60cc37f13c 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/xxhash.c +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/xxhash.c @@ -1,6 +1,6 @@ /* * xxHash - Extremely Fast Hash algorithm - * Copyright (C) 2012-2021 Yann Collet + * Copyright (C) 2012-2023 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * @@ -32,12 +32,11 @@ * - xxHash source repository: https://github.com/Cyan4973/xxHash */ - /* * xxhash.c instantiates functions defined in xxhash.h */ -#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ -#define XXH_IMPLEMENTATION /* access definitions */ +#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ +#define XXH_IMPLEMENTATION /* access definitions */ #include "xxhash.h" diff --git a/src/third_party/mozjs/extract/mfbt/lz4/xxhash.h b/src/third_party/mozjs/extract/mozglue/static/lz4/xxhash.h similarity index 88% rename from src/third_party/mozjs/extract/mfbt/lz4/xxhash.h rename to src/third_party/mozjs/extract/mozglue/static/lz4/xxhash.h index a18e8c762da..78fc2e8dbf6 100644 --- a/src/third_party/mozjs/extract/mfbt/lz4/xxhash.h +++ b/src/third_party/mozjs/extract/mozglue/static/lz4/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (C) 2012-2021 Yann Collet + * Copyright (C) 2012-2023 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * @@ -130,6 +130,7 @@ * } * @endcode * + * * @anchor streaming_example * **Streaming** * @@ -165,6 +166,77 @@ * } * @endcode * + * Streaming functions generate the xxHash value from an incremental input. + * This method is slower than single-call functions, due to state management. + * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. + * + * An XXH state must first be allocated using `XXH*_createState()`. + * + * Start a new hash by initializing the state with a seed using `XXH*_reset()`. + * + * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. + * + * The function returns an error code, with 0 meaning OK, and any other value + * meaning there is an error. + * + * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. + * This function returns the nn-bits hash as an int or long long. + * + * It's still possible to continue inserting input into the hash state after a + * digest, and generate new hash values later on by invoking `XXH*_digest()`. + * + * When done, release the state using `XXH*_freeState()`. + * + * + * @anchor canonical_representation_example + * **Canonical Representation** + * + * The default return values from XXH functions are unsigned 32, 64 and 128 bit + * integers. + * This the simplest and fastest format for further post-processing. + * + * However, this leaves open the question of what is the order on the byte level, + * since little and big endian conventions will store the same number differently. + * + * The canonical representation settles this issue by mandating big-endian + * convention, the same convention as human-readable numbers (large digits first). + * + * When writing hash values to storage, sending them over a network, or printing + * them, it's highly recommended to use the canonical representation to ensure + * portability across a wider range of systems, present and future. + * + * The following functions allow transformation of hash values to and from + * canonical format. + * + * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(), + * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(), + * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(), + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which prints XXH32_hash_t in human readable format + * void printXxh32(XXH32_hash_t hash) + * { + * XXH32_canonical_t cano; + * XXH32_canonicalFromHash(&cano, hash); + * size_t i; + * for(i = 0; i < sizeof(cano.digest); ++i) { + * printf("%02x", cano.digest[i]); + * } + * printf("\n"); + * } + * + * // Example for a function which converts XXH32_canonical_t to XXH32_hash_t + * XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano) + * { + * XXH32_hash_t hash = XXH32_hashFromCanonical(&cano); + * return hash; + * } + * @endcode + * + * * @file xxhash.h * xxHash prototypes and implementation */ @@ -261,7 +333,7 @@ extern "C" { /* make all functions private */ # undef XXH_PUBLIC_API # if defined(__GNUC__) -# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# define XXH_PUBLIC_API static __inline __attribute__((__unused__)) # elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define XXH_PUBLIC_API static inline # elif defined(_MSC_VER) @@ -373,7 +445,7 @@ extern "C" { /*! @brief Marks a global symbol. */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) -# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT @@ -449,7 +521,7 @@ extern "C" { /* specific declaration modes for Windows */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) -# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT @@ -461,9 +533,9 @@ extern "C" { #endif #if defined (__GNUC__) -# define XXH_CONSTF __attribute__((const)) -# define XXH_PUREF __attribute__((pure)) -# define XXH_MALLOCF __attribute__((malloc)) +# define XXH_CONSTF __attribute__((__const__)) +# define XXH_PUREF __attribute__((__pure__)) +# define XXH_MALLOCF __attribute__((__malloc__)) #else # define XXH_CONSTF /* disable */ # define XXH_PUREF @@ -475,7 +547,7 @@ extern "C" { ***************************************/ #define XXH_VERSION_MAJOR 0 #define XXH_VERSION_MINOR 8 -#define XXH_VERSION_RELEASE 2 +#define XXH_VERSION_RELEASE 3 /*! @brief Version number, encoded as two digits each */ #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) @@ -517,7 +589,11 @@ typedef uint32_t XXH32_hash_t; #elif !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include +# ifdef _AIX +# include +# else +# include +# endif typedef uint32_t XXH32_hash_t; #else @@ -551,10 +627,6 @@ typedef uint32_t XXH32_hash_t; /*! * @brief Calculates the 32-bit hash of @p input using xxHash32. * - * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark): 5.4 GB/s - * - * See @ref single_shot_example "Single Shot Example" for an example. - * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 32-bit seed to alter the hash's output predictably. @@ -564,63 +636,44 @@ typedef uint32_t XXH32_hash_t; * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * - * @return The calculated 32-bit hash value. + * @return The calculated 32-bit xxHash32 value. * - * @see - * XXH64(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): - * Direct equivalents for the other variants of xxHash. - * @see - * XXH32_createState(), XXH32_update(), XXH32_digest(): Streaming version. + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); #ifndef XXH_NO_STREAM -/*! - * Streaming functions generate the xxHash value from an incremental input. - * This method is slower than single-call functions, due to state management. - * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. - * - * An XXH state must first be allocated using `XXH*_createState()`. - * - * Start a new hash by initializing the state with a seed using `XXH*_reset()`. - * - * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. - * - * The function returns an error code, with 0 meaning OK, and any other value - * meaning there is an error. - * - * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. - * This function returns the nn-bits hash as an int or long long. - * - * It's still possible to continue inserting input into the hash state after a - * digest, and generate new hash values later on by invoking `XXH*_digest()`. - * - * When done, release the state using `XXH*_freeState()`. - * - * @see streaming_example at the top of @ref xxhash.h for an example. - */ - /*! * @typedef struct XXH32_state_s XXH32_state_t * @brief The opaque state struct for the XXH32 streaming API. * * @see XXH32_state_s for details. + * @see @ref streaming_example "Streaming Example" */ typedef struct XXH32_state_s XXH32_state_t; /*! * @brief Allocates an @ref XXH32_state_t. * - * Must be freed with XXH32_freeState(). - * @return An allocated XXH32_state_t on success, `NULL` on failure. + * @return An allocated pointer of @ref XXH32_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH32_freeState(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); /*! * @brief Frees an @ref XXH32_state_t. * - * Must be allocated with XXH32_createState(). * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). - * @return XXH_OK. + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH32_createState(). + * + * @see @ref streaming_example "Streaming Example" + * */ XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); /*! @@ -636,23 +689,24 @@ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_ /*! * @brief Resets an @ref XXH32_state_t to begin a new hash. * - * This function resets and seeds a state. Call it before @ref XXH32_update(). - * * @param statePtr The state struct to reset. * @param seed The 32-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH32_update(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); /*! * @brief Consumes a block of @p input to an @ref XXH32_state_t. * - * Call this to incrementally consume blocks of data. - * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. @@ -664,48 +718,36 @@ XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); /*! * @brief Returns the calculated hash value from an @ref XXH32_state_t. * - * @note - * Calling XXH32_digest() will not affect @p statePtr, so you can update, - * digest, and update again. - * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * - * @return The calculated xxHash32 value from that state. + * @return The calculated 32-bit xxHash32 value from that state. + * + * @note + * Calling XXH32_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ -/* - * The default return values from XXH functions are unsigned 32 and 64 bit - * integers. - * This the simplest and fastest format for further post-processing. - * - * However, this leaves open the question of what is the order on the byte level, - * since little and big endian conventions will store the same number differently. - * - * The canonical representation settles this issue by mandating big-endian - * convention, the same convention as human-readable numbers (large digits first). - * - * When writing hash values to storage, sending them over a network, or printing - * them, it's highly recommended to use the canonical representation to ensure - * portability across a wider range of systems, present and future. - * - * The following functions allow transformation of hash values to and from - * canonical format. - */ - /*! * @brief Canonical (big endian) representation of @ref XXH32_hash_t. */ @@ -716,11 +758,13 @@ typedef struct { /*! * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. * - * @param dst The @ref XXH32_canonical_t pointer to be stored to. + * @param dst The @ref XXH32_canonical_t pointer to be stored to. * @param hash The @ref XXH32_hash_t to be converted. * * @pre * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); @@ -733,6 +777,8 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t * @p src must not be `NULL`. * * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); @@ -794,7 +840,7 @@ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canoni * As of writing this, only supported by clang. */ #if XXH_HAS_ATTRIBUTE(noescape) -# define XXH_NOESCAPE __attribute__((noescape)) +# define XXH_NOESCAPE __attribute__((__noescape__)) #else # define XXH_NOESCAPE #endif @@ -821,7 +867,11 @@ typedef uint64_t XXH64_hash_t; #elif !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include +# ifdef _AIX +# include +# else +# include +# endif typedef uint64_t XXH64_hash_t; #else # include @@ -851,9 +901,6 @@ typedef uint64_t XXH64_hash_t; /*! * @brief Calculates the 64-bit hash of @p input using xxHash64. * - * This function usually runs faster on 64-bit systems, but slower on 32-bit - * systems (see benchmark). - * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 64-bit seed to alter the hash's output predictably. @@ -863,13 +910,9 @@ typedef uint64_t XXH64_hash_t; * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * - * @return The calculated 64-bit hash. + * @return The calculated 64-bit xxHash64 value. * - * @see - * XXH32(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): - * Direct equivalents for the other variants of xxHash. - * @see - * XXH64_createState(), XXH64_update(), XXH64_digest(): Streaming version. + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); @@ -879,23 +922,32 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size * @brief The opaque state struct for the XXH64 streaming API. * * @see XXH64_state_s for details. + * @see @ref streaming_example "Streaming Example" */ typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ /*! * @brief Allocates an @ref XXH64_state_t. * - * Must be freed with XXH64_freeState(). - * @return An allocated XXH64_state_t on success, `NULL` on failure. + * @return An allocated pointer of @ref XXH64_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH64_freeState(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); /*! * @brief Frees an @ref XXH64_state_t. * - * Must be allocated with XXH64_createState(). * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). - * @return XXH_OK. + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH64_createState(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); @@ -912,23 +964,24 @@ XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const /*! * @brief Resets an @ref XXH64_state_t to begin a new hash. * - * This function resets and seeds a state. Call it before @ref XXH64_update(). - * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH64_update(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); /*! * @brief Consumes a block of @p input to an @ref XXH64_state_t. * - * Call this to incrementally consume blocks of data. - * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. @@ -940,23 +993,30 @@ XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated hash value from an @ref XXH64_state_t. * - * @note - * Calling XXH64_digest() will not affect @p statePtr, so you can update, - * digest, and update again. - * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * - * @return The calculated xxHash64 value from that state. + * @return The calculated 64-bit xxHash64 value from that state. + * + * @note + * Calling XXH64_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); #endif /* !XXH_NO_STREAM */ @@ -975,6 +1035,8 @@ typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t * * @pre * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); @@ -987,6 +1049,8 @@ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, * @p src must not be `NULL`. * * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); @@ -1046,40 +1110,74 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const * * The API supports one-shot hashing, streaming mode, and custom secrets. */ + +/*! + * @ingroup tuning + * @brief Possible values for @ref XXH_VECTOR. + * + * Unless set explicitly, determined automatically. + */ +# define XXH_SCALAR 0 /*!< Portable scalar version */ +# define XXH_SSE2 1 /*!< SSE2 for Pentium 4, Opteron, all x86_64. */ +# define XXH_AVX2 2 /*!< AVX2 for Haswell and Bulldozer */ +# define XXH_AVX512 3 /*!< AVX512 for Skylake and Icelake */ +# define XXH_NEON 4 /*!< NEON for most ARMv7-A, all AArch64, and WASM SIMD128 */ +# define XXH_VSX 5 /*!< VSX and ZVector for POWER8/z13 (64-bit) */ +# define XXH_SVE 6 /*!< SVE for some ARMv8-A and ARMv9-A */ +# define XXH_LSX 7 /*!< LSX (128-bit SIMD) for LoongArch64 */ + + /*-********************************************************************** * XXH3 64-bit variant ************************************************************************/ /*! - * @brief 64-bit unseeded variant of XXH3. + * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input. * - * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of 0, however - * it may have slightly better performance due to constant propagation of the - * defaults. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. * - * @see - * XXH32(), XXH64(), XXH3_128bits(): equivalent for the other xxHash algorithms * @see * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants - * @see - * XXH3_64bits_reset(), XXH3_64bits_update(), XXH3_64bits_digest(): Streaming version. + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); /*! - * @brief 64-bit seeded variant of XXH3 + * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input. * - * This variant generates a custom secret on the fly based on default secret - * altered using the `seed` value. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. * - * While this operation is decently fast, note that it's not completely free. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. * * @note * seed == 0 produces the same results as @ref XXH3_64bits(). * - * @param input The data to hash - * @param length The length - * @param seed The 64-bit seed to alter the state. + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); @@ -1093,22 +1191,36 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const vo #define XXH3_SECRET_SIZE_MIN 136 /*! - * @brief 64-bit variant of XXH3 with a custom "secret". + * @brief Calculates 64-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. * * It's possible to provide any blob of bytes as a "secret" to generate the hash. * This makes it more difficult for an external actor to prepare an intentional collision. - * The main condition is that secretSize *must* be large enough (>= XXH3_SECRET_SIZE_MIN). + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). * However, the quality of the secret impacts the dispersion of the hash algorithm. * Therefore, the secret _must_ look like a bunch of random bytes. * Avoid "trivial" or structured data such as repeated sequences or a text document. * Whenever in doubt about the "randomness" of the blob of bytes, - * consider employing "XXH3_generateSecret()" instead (see below). + * consider employing @ref XXH3_generateSecret() instead (see below). * It will generate a proper high entropy secret derived from the blob of bytes. * Another advantage of using XXH3_generateSecret() is that * it guarantees that all bits within the initial blob of bytes * will impact every bit of the output. * This is not necessarily the case when using the blob of bytes directly * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); @@ -1123,9 +1235,10 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const */ /*! - * @brief The state struct for the XXH3 streaming API. + * @brief The opaque state struct for the XXH3 streaming API. * * @see XXH3_state_s for details. + * @see @ref streaming_example "Streaming Example" */ typedef struct XXH3_state_s XXH3_state_t; XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); @@ -1144,15 +1257,20 @@ XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOE /*! * @brief Resets an @ref XXH3_state_t to begin a new hash. * - * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_64bits_update(). - * Digest will be equivalent to `XXH3_64bits()`. - * * @param statePtr The state struct to reset. * * @pre * @p statePtr must not be `NULL`. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits()`. + * + * @see @ref streaming_example "Streaming Example" * */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); @@ -1160,36 +1278,54 @@ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* stateP /*! * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. * - * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_64bits_update(). - * Digest will be equivalent to `XXH3_64bits_withSeed()`. - * * @param statePtr The state struct to reset. - * @param seed The 64-bit seed to alter the state. + * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits_withSeed()`. + * + * @see @ref streaming_example "Streaming Example" * */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); /*! - * XXH3_64bits_reset_withSecret(): - * `secret` is referenced, it _must outlive_ the hash streaming session. - * Similar to one-shot API, `secretSize` must be >= `XXH3_SECRET_SIZE_MIN`, + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * `secret` is referenced, it _must outlive_ the hash streaming session. + * + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, * and the quality of produced hash values depends on secret's entropy * (secret's content should look like a bunch of random bytes). * When in doubt about the randomness of a candidate `secret`, * consider employing `XXH3_generateSecret()` instead (see below). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); /*! * @brief Consumes a block of @p input to an @ref XXH3_state_t. * - * Call this to incrementally consume blocks of data. - * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. @@ -1201,23 +1337,30 @@ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_stat * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. * - * @note - * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, - * digest, and update again. - * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated XXH3 64-bit hash value from that state. + * + * @note + * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); #endif /* !XXH_NO_STREAM */ @@ -1242,26 +1385,71 @@ typedef struct { } XXH128_hash_t; /*! - * @brief Unseeded 128-bit variant of XXH3 + * @brief Calculates 128-bit unseeded variant of XXH3 of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. * * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead * for shorter inputs. * - * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of 0, however + * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however * it may have slightly better performance due to constant propagation of the * defaults. * - * @see - * XXH32(), XXH64(), XXH3_64bits(): equivalent for the other xxHash algorithms - * @see - * XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants - * @see - * XXH3_128bits_reset(), XXH3_128bits_update(), XXH3_128bits_digest(): Streaming version. + * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); -/*! @brief Seeded 128-bit variant of XXH3. @see XXH3_64bits_withSeed(). */ +/*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); -/*! @brief Custom secret 128-bit variant of XXH3. @see XXH3_64bits_withSecret(). */ +/*! + * @brief Calculates 128-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ @@ -1281,36 +1469,65 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE cons /*! * @brief Resets an @ref XXH3_state_t to begin a new hash. * - * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_128bits_update(). - * Digest will be equivalent to `XXH3_128bits()`. - * * @param statePtr The state struct to reset. * * @pre * @p statePtr must not be `NULL`. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits()`. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); /*! * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. * - * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_128bits_update(). - * Digest will be equivalent to `XXH3_128bits_withSeed()`. - * * @param statePtr The state struct to reset. - * @param seed The 64-bit seed to alter the state. + * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits_withSeed()`. + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); -/*! @brief Custom secret 128-bit variant of XXH3. @see XXH_64bits_reset_withSecret(). */ +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * `secret` is referenced, it _must outlive_ the hash streaming session. + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + * + * @see @ref streaming_example "Streaming Example" + */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); /*! @@ -1324,28 +1541,32 @@ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_sta * * @pre * @p statePtr must not be `NULL`. - * @pre + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * - * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. * - * @note - * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, - * digest, and update again. - * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated XXH3 128-bit hash value from that state. + * + * @note + * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); #endif /* !XXH_NO_STREAM */ @@ -1355,18 +1576,27 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const X * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ /*! - * XXH128_isEqual(): - * Return: 1 if `h1` and `h2` are equal, 0 if they are not. + * @brief Check equality of two XXH128_hash_t values + * + * @param h1 The 128-bit hash value. + * @param h2 Another 128-bit hash value. + * + * @return `1` if `h1` and `h2` are equal. + * @return `0` if they are not. */ XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); /*! * @brief Compares two @ref XXH128_hash_t + * * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. * - * @return: >0 if *h128_1 > *h128_2 - * =0 if *h128_1 == *h128_2 - * <0 if *h128_1 < *h128_2 + * @param h128_1 Left-hand side value + * @param h128_2 Right-hand side value + * + * @return >0 if @p h128_1 > @p h128_2 + * @return =0 if @p h128_1 == @p h128_2 + * @return <0 if @p h128_1 < @p h128_2 */ XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); @@ -1378,11 +1608,12 @@ typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical /*! * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. * - * @param dst The @ref XXH128_canonical_t pointer to be stored to. + * @param dst The @ref XXH128_canonical_t pointer to be stored to. * @param hash The @ref XXH128_hash_t to be converted. * * @pre * @p dst must not be `NULL`. + * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); @@ -1395,6 +1626,7 @@ XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* ds * @p src must not be `NULL`. * * @return The converted hash. + * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); @@ -1440,9 +1672,9 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE con struct XXH32_state_s { XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ - XXH32_hash_t v[4]; /*!< Accumulator lanes */ - XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ - XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ + XXH32_hash_t acc[4]; /*!< Accumulator lanes */ + unsigned char buffer[16]; /*!< Internal buffer for partial reads. */ + XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */ XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ }; /* typedef'd to XXH32_state_t */ @@ -1463,9 +1695,9 @@ struct XXH32_state_s { */ struct XXH64_state_s { XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ - XXH64_hash_t v[4]; /*!< Accumulator lanes */ - XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ - XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ + XXH64_hash_t acc[4]; /*!< Accumulator lanes */ + unsigned char buffer[32]; /*!< Internal buffer for partial reads.. */ + XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */ XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ }; /* typedef'd to XXH64_state_t */ @@ -1473,8 +1705,7 @@ struct XXH64_state_s { #ifndef XXH_NO_XXH3 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ -# include -# define XXH_ALIGN(n) alignas(n) +# define XXH_ALIGN(n) _Alignas(n) #elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ /* In C++ alignas() is a keyword */ # define XXH_ALIGN(n) alignas(n) @@ -1587,7 +1818,20 @@ struct XXH3_state_s { /*! - * simple alias to pre-selected XXH3_128bits variant + * @brief Calculates the 128-bit hash of @p data using XXH3. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p len is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 128-bit XXH3 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); @@ -1596,9 +1840,16 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, siz /* Symbols defined below must be considered tied to a specific library version. */ /*! - * XXH3_generateSecret(): + * @brief Derive a high-entropy secret from any user-defined content, named customSeed. + * + * @param secretBuffer A writable buffer for derived high-entropy secret data. + * @param secretSize Size of secretBuffer, in bytes. Must be >= XXH3_SECRET_SIZE_MIN. + * @param customSeed A user-defined content. + * @param customSeedSize Size of customSeed, in bytes. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. * - * Derive a high-entropy secret from any user-defined content, named customSeed. * The generated secret can be used in combination with `*_withSecret()` functions. * The `_withSecret()` variants are useful to provide a higher level of protection * than 64-bit seed, as it becomes much more difficult for an external actor to @@ -1651,6 +1902,9 @@ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer /*! * @brief Generate the same secret as the _withSeed() variants. * + * @param secretBuffer A writable buffer of @ref XXH3_SECRET_DEFAULT_SIZE bytes + * @param seed The 64-bit seed to alter the hash result predictably. + * * The generated secret can be used in combination with *`*_withSecret()` and `_withSecretandSeed()` variants. * @@ -1670,7 +1924,7 @@ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer * }; * // Fast, caches the seeded secret for future uses. * class HashFast { - * unsigned char secret[XXH3_SECRET_SIZE_MIN]; + * unsigned char secret[XXH3_SECRET_DEFAULT_SIZE]; * public: * HashFast(XXH64_hash_t s) { * XXH3_generateSecret_fromSeed(secret, seed); @@ -1682,15 +1936,26 @@ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer * } * }; * @endcode - * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes - * @param seed The seed to seed the state. */ XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); /*! - * These variants generate hash values using either - * @p seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes) - * or @p secret for "large" keys (>= XXH3_MIDSIZE_MAX). + * @brief Maximum size of "short" key in bytes. + */ +#define XXH3_MIDSIZE_MAX 240 + +/*! + * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * These variants generate hash values using either: + * - @p seed for "short" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes) + * - @p secret for "large" keys (>= @ref XXH3_MIDSIZE_MAX). * * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. * `_withSeed()` has to generate the secret on the fly for "large" keys. @@ -1717,22 +1982,71 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed); -/*! @copydoc XXH3_64bits_withSecretandSeed() */ + +/*! + * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The memory segment to be hashed, at least @p len bytes in size. + * @param length The length of @p data, in bytes. + * @param secret The secret used to alter hash result predictably. + * @param secretSize The length of @p secret, in bytes (must be >= XXH3_SECRET_SIZE_MIN) + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed(): contract is the same. + */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); + #ifndef XXH_NO_STREAM -/*! @copydoc XXH3_64bits_withSecretandSeed() */ +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed(). Contract is identical. + */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); -/*! @copydoc XXH3_64bits_withSecretandSeed() */ + +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed(). Contract is identical. + * + * Note: there was a bug in an earlier version of this function (<= v0.8.2) + * that would make it generate an incorrect hash value + * when @p seed == 0 and @p length < XXH3_MIDSIZE_MAX + * and @p secret is different from XXH3_generateSecret_fromSeed(). + * As stated in the contract, the correct hash result must be + * the same as XXH3_128bits_withSeed() when @p length <= XXH3_MIDSIZE_MAX. + * Results generated by this older version are wrong, hence not comparable. + */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); + #endif /* !XXH_NO_STREAM */ #endif /* !XXH_NO_XXH3 */ @@ -2100,15 +2414,15 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) #if XXH_NO_INLINE_HINTS /* disable inlining hints */ # if defined(__GNUC__) || defined(__clang__) -# define XXH_FORCE_INLINE static __attribute__((unused)) +# define XXH_FORCE_INLINE static __attribute__((__unused__)) # else # define XXH_FORCE_INLINE static # endif # define XXH_NO_INLINE static /* enable inlining hints */ #elif defined(__GNUC__) || defined(__clang__) -# define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused)) -# define XXH_NO_INLINE static __attribute__((noinline)) +# define XXH_FORCE_INLINE static __inline__ __attribute__((__always_inline__, __unused__)) +# define XXH_NO_INLINE static __attribute__((__noinline__)) #elif defined(_MSC_VER) /* Visual Studio */ # define XXH_FORCE_INLINE static __forceinline # define XXH_NO_INLINE static __declspec(noinline) @@ -2121,12 +2435,34 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) # define XXH_NO_INLINE static #endif +#if defined(XXH_INLINE_ALL) +# define XXH_STATIC XXH_FORCE_INLINE +#else +# define XXH_STATIC static +#endif + #if XXH3_INLINE_SECRET # define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE #else # define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE #endif +#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ +# define XXH_RESTRICT /* disable */ +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ +# define XXH_RESTRICT restrict +#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ + || (defined (__clang__)) \ + || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ + || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) +/* + * There are a LOT more compilers that recognize __restrict but this + * covers the major ones. + */ +# define XXH_RESTRICT __restrict +#else +# define XXH_RESTRICT /* disable */ +#endif /* ************************************* * Debug @@ -2206,10 +2542,14 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) #if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t xxh_u8; +# ifdef _AIX +# include +# else +# include +# endif + typedef uint8_t xxh_u8; #else - typedef unsigned char xxh_u8; + typedef unsigned char xxh_u8; #endif typedef XXH32_hash_t xxh_u32; @@ -2295,11 +2635,11 @@ static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES -typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; +typedef union { xxh_u32 u32; } __attribute__((__packed__)) unalign; #endif static xxh_u32 XXH_read32(const void* ptr) { - typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32; + typedef __attribute__((__aligned__(1))) xxh_u32 xxh_unalign32; return *((const xxh_unalign32*)ptr); } @@ -2445,6 +2785,9 @@ static int XXH_isLittleEndian(void) && XXH_HAS_BUILTIN(__builtin_rotateleft64) # define XXH_rotl32 __builtin_rotateleft32 # define XXH_rotl64 __builtin_rotateleft64 +#elif XXH_HAS_BUILTIN(__builtin_stdc_rotate_left) +# define XXH_rotl32 __builtin_stdc_rotate_left +# define XXH_rotl64 __builtin_stdc_rotate_left /* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ #elif defined(_MSC_VER) # define XXH_rotl32(x,r) _rotl(x,r) @@ -2590,7 +2933,7 @@ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) #if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) /* * UGLY HACK: - * A compiler fence is the only thing that prevents GCC and Clang from + * A compiler fence is used to prevent GCC and Clang from * autovectorizing the XXH32 loop (pragmas and attributes don't work for some * reason) without globally disabling SSE4.1. * @@ -2651,6 +2994,61 @@ static xxh_u32 XXH32_avalanche(xxh_u32 hash) #define XXH_get32bits(p) XXH_readLE32_align(p, align) +/*! + * @internal + * @brief Sets up the initial accumulator state for XXH32(). + */ +XXH_FORCE_INLINE void +XXH32_initAccs(xxh_u32 *acc, xxh_u32 seed) +{ + XXH_ASSERT(acc != NULL); + acc[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + acc[1] = seed + XXH_PRIME32_2; + acc[2] = seed + 0; + acc[3] = seed - XXH_PRIME32_1; +} + +/*! + * @internal + * @brief Consumes a block of data for XXH32(). + * + * @return the end input pointer. + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH32_consumeLong( + xxh_u32 *XXH_RESTRICT acc, + xxh_u8 const *XXH_RESTRICT input, + size_t len, + XXH_alignment align +) +{ + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 15; + XXH_ASSERT(acc != NULL); + XXH_ASSERT(input != NULL); + XXH_ASSERT(len >= 16); + do { + acc[0] = XXH32_round(acc[0], XXH_get32bits(input)); input += 4; + acc[1] = XXH32_round(acc[1], XXH_get32bits(input)); input += 4; + acc[2] = XXH32_round(acc[2], XXH_get32bits(input)); input += 4; + acc[3] = XXH32_round(acc[3], XXH_get32bits(input)); input += 4; + } while (input < limit); + + return input; +} + +/*! + * @internal + * @brief Merges the accumulator lanes together for XXH32() + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u32 +XXH32_mergeAccs(const xxh_u32 *acc) +{ + XXH_ASSERT(acc != NULL); + return XXH_rotl32(acc[0], 1) + XXH_rotl32(acc[1], 7) + + XXH_rotl32(acc[2], 12) + XXH_rotl32(acc[3], 18); +} + /*! * @internal * @brief Processes the last 0-15 bytes of @p ptr. @@ -2763,22 +3161,12 @@ XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment if (input==NULL) XXH_ASSERT(len == 0); if (len>=16) { - const xxh_u8* const bEnd = input + len; - const xxh_u8* const limit = bEnd - 15; - xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; - xxh_u32 v2 = seed + XXH_PRIME32_2; - xxh_u32 v3 = seed + 0; - xxh_u32 v4 = seed - XXH_PRIME32_1; + xxh_u32 acc[4]; + XXH32_initAccs(acc, seed); - do { - v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4; - v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4; - v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4; - v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4; - } while (input < limit); + input = XXH32_consumeLong(acc, input, len, align); - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) - + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + h32 = XXH32_mergeAccs(acc); } else { h32 = seed + XXH_PRIME32_5; } @@ -2834,10 +3222,7 @@ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t s { XXH_ASSERT(statePtr != NULL); memset(statePtr, 0, sizeof(*statePtr)); - statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; - statePtr->v[1] = seed + XXH_PRIME32_2; - statePtr->v[2] = seed + 0; - statePtr->v[3] = seed - XXH_PRIME32_1; + XXH32_initAccs(statePtr->acc, seed); return XXH_OK; } @@ -2851,45 +3236,37 @@ XXH32_update(XXH32_state_t* state, const void* input, size_t len) return XXH_OK; } - { const xxh_u8* p = (const xxh_u8*)input; - const xxh_u8* const bEnd = p + len; + state->total_len_32 += (XXH32_hash_t)len; + state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); - state->total_len_32 += (XXH32_hash_t)len; - state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); + XXH_ASSERT(state->bufferedSize < sizeof(state->buffer)); + if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */ + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } - if (state->memsize + len < 16) { /* fill in tmp buffer */ - XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len); - state->memsize += (XXH32_hash_t)len; - return XXH_OK; + { const xxh_u8* xinput = (const xxh_u8*)input; + const xxh_u8* const bEnd = xinput + len; + + if (state->bufferedSize) { /* non-empty buffer: complete first */ + XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize); + xinput += sizeof(state->buffer) - state->bufferedSize; + /* then process one round */ + (void)XXH32_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned); + state->bufferedSize = 0; } - if (state->memsize) { /* some data left from previous update */ - XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize); - { const xxh_u32* p32 = state->mem32; - state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++; - state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++; - state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++; - state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32)); - } - p += 16-state->memsize; - state->memsize = 0; + XXH_ASSERT(xinput <= bEnd); + if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) { + /* Process the remaining data */ + xinput = XXH32_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned); } - if (p <= bEnd-16) { - const xxh_u8* const limit = bEnd - 16; - - do { - state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4; - state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4; - state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4; - state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4; - } while (p<=limit); - - } - - if (p < bEnd) { - XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); + if (xinput < bEnd) { + /* Copy the leftover to the tmp buffer */ + XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput)); + state->bufferedSize = (unsigned)(bEnd-xinput); } } @@ -2903,36 +3280,20 @@ XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) xxh_u32 h32; if (state->large_len) { - h32 = XXH_rotl32(state->v[0], 1) - + XXH_rotl32(state->v[1], 7) - + XXH_rotl32(state->v[2], 12) - + XXH_rotl32(state->v[3], 18); + h32 = XXH32_mergeAccs(state->acc); } else { - h32 = state->v[2] /* == seed */ + XXH_PRIME32_5; + h32 = state->acc[2] /* == seed */ + XXH_PRIME32_5; } h32 += state->total_len_32; - return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); + return XXH32_finalize(h32, state->buffer, state->bufferedSize, XXH_aligned); } #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ -/*! - * @ingroup XXH32_family - * The default return values from XXH functions are unsigned 32 and 64 bit - * integers. - * - * The canonical representation uses big endian convention, the same convention - * as human-readable numbers (large digits first). - * - * This way, hash values can be written into a file or buffer, remaining - * comparable across different systems. - * - * The following functions allow transformation of hash values to and from their - * canonical format. - */ +/*! @ingroup XXH32_family */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); @@ -2987,11 +3348,11 @@ static xxh_u64 XXH_read64(const void* memPtr) * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES -typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; +typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((__packed__)) unalign64; #endif static xxh_u64 XXH_read64(const void* ptr) { - typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64; + typedef __attribute__((__aligned__(1))) xxh_u64 xxh_unalign64; return *((const xxh_unalign64*)ptr); } @@ -3110,6 +3471,23 @@ static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) acc += input * XXH_PRIME64_2; acc = XXH_rotl64(acc, 31); acc *= XXH_PRIME64_1; +#if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * DISABLE AUTOVECTORIZATION: + * A compiler fence is used to prevent GCC and Clang from + * autovectorizing the XXH64 loop (pragmas and attributes don't work for some + * reason) without globally disabling AVX512. + * + * Autovectorization of XXH64 tends to be detrimental, + * though the exact outcome may change depending on exact cpu and compiler version. + * For information, it has been reported as detrimental for Skylake-X, + * but possibly beneficial for Zen4. + * + * The default is to disable auto-vectorization, + * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable. + */ + XXH_COMPILER_GUARD(acc); +#endif return acc; } @@ -3135,6 +3513,85 @@ static xxh_u64 XXH64_avalanche(xxh_u64 hash) #define XXH_get64bits(p) XXH_readLE64_align(p, align) +/*! + * @internal + * @brief Sets up the initial accumulator state for XXH64(). + */ +XXH_FORCE_INLINE void +XXH64_initAccs(xxh_u64 *acc, xxh_u64 seed) +{ + XXH_ASSERT(acc != NULL); + acc[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + acc[1] = seed + XXH_PRIME64_2; + acc[2] = seed + 0; + acc[3] = seed - XXH_PRIME64_1; +} + +/*! + * @internal + * @brief Consumes a block of data for XXH64(). + * + * @return the end input pointer. + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH64_consumeLong( + xxh_u64 *XXH_RESTRICT acc, + xxh_u8 const *XXH_RESTRICT input, + size_t len, + XXH_alignment align +) +{ + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 31; + XXH_ASSERT(acc != NULL); + XXH_ASSERT(input != NULL); + XXH_ASSERT(len >= 32); + do { + /* reroll on 32-bit */ + if (sizeof(void *) < sizeof(xxh_u64)) { + size_t i; + for (i = 0; i < 4; i++) { + acc[i] = XXH64_round(acc[i], XXH_get64bits(input)); + input += 8; + } + } else { + acc[0] = XXH64_round(acc[0], XXH_get64bits(input)); input += 8; + acc[1] = XXH64_round(acc[1], XXH_get64bits(input)); input += 8; + acc[2] = XXH64_round(acc[2], XXH_get64bits(input)); input += 8; + acc[3] = XXH64_round(acc[3], XXH_get64bits(input)); input += 8; + } + } while (input < limit); + + return input; +} + +/*! + * @internal + * @brief Merges the accumulator lanes together for XXH64() + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u64 +XXH64_mergeAccs(const xxh_u64 *acc) +{ + XXH_ASSERT(acc != NULL); + { + xxh_u64 h64 = XXH_rotl64(acc[0], 1) + XXH_rotl64(acc[1], 7) + + XXH_rotl64(acc[2], 12) + XXH_rotl64(acc[3], 18); + /* reroll on 32-bit */ + if (sizeof(void *) < sizeof(xxh_u64)) { + size_t i; + for (i = 0; i < 4; i++) { + h64 = XXH64_mergeRound(h64, acc[i]); + } + } else { + h64 = XXH64_mergeRound(h64, acc[0]); + h64 = XXH64_mergeRound(h64, acc[1]); + h64 = XXH64_mergeRound(h64, acc[2]); + h64 = XXH64_mergeRound(h64, acc[3]); + } + return h64; + } +} + /*! * @internal * @brief Processes the last 0-31 bytes of @p ptr. @@ -3150,7 +3607,7 @@ static xxh_u64 XXH64_avalanche(xxh_u64 hash) * @return The finalized hash * @see XXH32_finalize(). */ -static XXH_PUREF xxh_u64 +XXH_STATIC XXH_PUREF xxh_u64 XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { if (ptr==NULL) XXH_ASSERT(len == 0); @@ -3200,27 +3657,13 @@ XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment xxh_u64 h64; if (input==NULL) XXH_ASSERT(len == 0); - if (len>=32) { - const xxh_u8* const bEnd = input + len; - const xxh_u8* const limit = bEnd - 31; - xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; - xxh_u64 v2 = seed + XXH_PRIME64_2; - xxh_u64 v3 = seed + 0; - xxh_u64 v4 = seed - XXH_PRIME64_1; + if (len>=32) { /* Process a large block of data */ + xxh_u64 acc[4]; + XXH64_initAccs(acc, seed); - do { - v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8; - v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8; - v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8; - v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8; - } while (inputv[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; - statePtr->v[1] = seed + XXH_PRIME64_2; - statePtr->v[2] = seed + 0; - statePtr->v[3] = seed - XXH_PRIME64_1; + XXH64_initAccs(statePtr->acc, seed); return XXH_OK; } @@ -3292,42 +3732,36 @@ XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, return XXH_OK; } - { const xxh_u8* p = (const xxh_u8*)input; - const xxh_u8* const bEnd = p + len; + state->total_len += len; - state->total_len += len; + XXH_ASSERT(state->bufferedSize <= sizeof(state->buffer)); + if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */ + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } - if (state->memsize + len < 32) { /* fill in tmp buffer */ - XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len); - state->memsize += (xxh_u32)len; - return XXH_OK; + { const xxh_u8* xinput = (const xxh_u8*)input; + const xxh_u8* const bEnd = xinput + len; + + if (state->bufferedSize) { /* non-empty buffer => complete first */ + XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize); + xinput += sizeof(state->buffer) - state->bufferedSize; + /* and process one round */ + (void)XXH64_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned); + state->bufferedSize = 0; } - if (state->memsize) { /* tmp buffer is full */ - XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize); - state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0)); - state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1)); - state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2)); - state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3)); - p += 32 - state->memsize; - state->memsize = 0; + XXH_ASSERT(xinput <= bEnd); + if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) { + /* Process the remaining data */ + xinput = XXH64_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned); } - if (p+32 <= bEnd) { - const xxh_u8* const limit = bEnd - 32; - - do { - state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8; - state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8; - state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8; - state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8; - } while (p<=limit); - - } - - if (p < bEnd) { - XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); + if (xinput < bEnd) { + /* Copy the leftover to the tmp buffer */ + XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput)); + state->bufferedSize = (unsigned)(bEnd-xinput); } } @@ -3341,18 +3775,14 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state xxh_u64 h64; if (state->total_len >= 32) { - h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18); - h64 = XXH64_mergeRound(h64, state->v[0]); - h64 = XXH64_mergeRound(h64, state->v[1]); - h64 = XXH64_mergeRound(h64, state->v[2]); - h64 = XXH64_mergeRound(h64, state->v[3]); + h64 = XXH64_mergeAccs(state->acc); } else { - h64 = state->v[2] /*seed*/ + XXH_PRIME64_5; + h64 = state->acc[2] /*seed*/ + XXH_PRIME64_5; } h64 += (xxh_u64) state->total_len; - return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); + return XXH64_finalize(h64, state->buffer, (size_t)state->total_len, XXH_aligned); } #endif /* !XXH_NO_STREAM */ @@ -3387,22 +3817,6 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can /* === Compiler specifics === */ -#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ -# define XXH_RESTRICT /* disable */ -#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ -# define XXH_RESTRICT restrict -#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ - || (defined (__clang__)) \ - || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ - || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) -/* - * There are a LOT more compilers that recognize __restrict but this - * covers the major ones. - */ -# define XXH_RESTRICT __restrict -#else -# define XXH_RESTRICT /* disable */ -#endif #if (defined(__GNUC__) && (__GNUC__ >= 3)) \ || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ @@ -3416,7 +3830,11 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can #ifndef XXH_HAS_INCLUDE # ifdef __has_include -# define XXH_HAS_INCLUDE(x) __has_include(x) +/* + * Not defined as XXH_HAS_INCLUDE(x) (function-like) because + * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) + */ +# define XXH_HAS_INCLUDE __has_include # else # define XXH_HAS_INCLUDE(x) 0 # endif @@ -3437,6 +3855,8 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can # include # elif defined(__SSE2__) # include +# elif defined(__loongarch_sx) +# include # endif #endif @@ -3533,33 +3953,6 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can * implementation. */ # define XXH_VECTOR XXH_SCALAR -/*! - * @ingroup tuning - * @brief Possible values for @ref XXH_VECTOR. - * - * Note that these are actually implemented as macros. - * - * If this is not defined, it is detected automatically. - * internal macro XXH_X86DISPATCH overrides this. - */ -enum XXH_VECTOR_TYPE /* fake enum */ { - XXH_SCALAR = 0, /*!< Portable scalar version */ - XXH_SSE2 = 1, /*!< - * SSE2 for Pentium 4, Opteron, all x86_64. - * - * @note SSE2 is also guaranteed on Windows 10, macOS, and - * Android x86. - */ - XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ - XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ - XXH_NEON = 4, /*!< - * NEON for most ARMv7-A, all AArch64, and WASM SIMD128 - * via the SIMDeverywhere polyfill provided with the - * Emscripten SDK. - */ - XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ - XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */ -}; /*! * @ingroup tuning * @brief Selects the minimum alignment for XXH3's accumulators. @@ -3574,13 +3967,6 @@ enum XXH_VECTOR_TYPE /* fake enum */ { /* Actual definition */ #ifndef XXH_DOXYGEN -# define XXH_SCALAR 0 -# define XXH_SSE2 1 -# define XXH_AVX2 2 -# define XXH_AVX512 3 -# define XXH_NEON 4 -# define XXH_VSX 5 -# define XXH_SVE 6 #endif #ifndef XXH_VECTOR /* can be defined on command line */ @@ -3605,6 +3991,8 @@ enum XXH_VECTOR_TYPE /* fake enum */ { || (defined(__s390x__) && defined(__VEC__)) \ && defined(__GNUC__) /* TODO: IBM XL */ # define XXH_VECTOR XXH_VSX +# elif defined(__loongarch_sx) +# define XXH_VECTOR XXH_LSX # else # define XXH_VECTOR XXH_SCALAR # endif @@ -3642,6 +4030,8 @@ enum XXH_VECTOR_TYPE /* fake enum */ { # define XXH_ACC_ALIGN 64 # elif XXH_VECTOR == XXH_SVE /* sve */ # define XXH_ACC_ALIGN 64 +# elif XXH_VECTOR == XXH_LSX /* lsx */ +# define XXH_ACC_ALIGN 64 # endif #endif @@ -3655,7 +4045,7 @@ enum XXH_VECTOR_TYPE /* fake enum */ { #endif #if defined(__GNUC__) || defined(__clang__) -# define XXH_ALIASING __attribute__((may_alias)) +# define XXH_ALIASING __attribute__((__may_alias__)) #else # define XXH_ALIASING /* nothing */ #endif @@ -4408,8 +4798,6 @@ XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, } } -#define XXH3_MIDSIZE_MAX 240 - XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, @@ -5281,6 +5669,71 @@ XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, #endif +#if (XXH_VECTOR == XXH_LSX) +#define _LSX_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w)) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_lsx( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { + __m128i* const xacc = (__m128i *) acc; + const __m128i* const xinput = (const __m128i *) input; + const __m128i* const xsecret = (const __m128i *) secret; + + for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) { + /* data_vec = xinput[i]; */ + __m128i const data_vec = __lsx_vld(xinput + i, 0); + /* key_vec = xsecret[i]; */ + __m128i const key_vec = __lsx_vld(xsecret + i, 0); + /* data_key = data_vec ^ key_vec; */ + __m128i const data_key = __lsx_vxor_v(data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32); + // __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m128i const product = __lsx_vmulwev_d_wu(data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m128i const data_swap = __lsx_vshuf4i_w(data_vec, _LSX_SHUFFLE(1, 0, 3, 2)); + __m128i const sum = __lsx_vadd_d(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = __lsx_vadd_d(product, sum); + } + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(lsx) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_lsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { + __m128i* const xacc = (__m128i*) acc; + const __m128i* const xsecret = (const __m128i *) secret; + const __m128i prime32 = __lsx_vreplgr2vr_w((int)XXH_PRIME32_1); + + for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m128i const acc_vec = xacc[i]; + __m128i const shifted = __lsx_vsrli_d(acc_vec, 47); + __m128i const data_vec = __lsx_vxor_v(acc_vec, shifted); + /* xacc[i] ^= xsecret[i]; */ + __m128i const key_vec = __lsx_vld(xsecret + i, 0); + __m128i const data_key = __lsx_vxor_v(data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m128i const data_key_hi = __lsx_vsrli_d(data_key, 32); + __m128i const prod_lo = __lsx_vmulwev_d_wu(data_key, prime32); + __m128i const prod_hi = __lsx_vmulwev_d_wu(data_key_hi, prime32); + xacc[i] = __lsx_vadd_d(prod_lo, __lsx_vslli_d(prod_hi, 32)); + } + } +} + +#endif + /* scalar variants - universal */ #if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) @@ -5511,6 +5964,12 @@ typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); #define XXH3_scrambleAcc XXH3_scrambleAcc_scalar #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar +#elif (XXH_VECTOR == XXH_LSX) +#define XXH3_accumulate_512 XXH3_accumulate_512_lsx +#define XXH3_accumulate XXH3_accumulate_lsx +#define XXH3_scrambleAcc XXH3_scrambleAcc_lsx +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + #else /* scalar */ #define XXH3_accumulate_512 XXH3_accumulate_512_scalar @@ -5566,7 +6025,7 @@ XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret acc[1] ^ XXH_readLE64(secret+8) ); } -static XXH64_hash_t +static XXH_PUREF XXH64_hash_t XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) { xxh_u64 result64 = start; @@ -5593,6 +6052,15 @@ XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secre return XXH3_avalanche(result64); } +/* do not align on 8, so that the secret is different from the accumulator */ +#define XXH_SECRET_MERGEACCS_START 11 + +static XXH_PUREF XXH64_hash_t +XXH3_finalizeLong_64b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 len) +{ + return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, len * XXH_PRIME64_1); +} + #define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } @@ -5608,10 +6076,8 @@ XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); - /* do not align on 8, so that the secret is different from the accumulator */ -#define XXH_SECRET_MERGEACCS_START 11 XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); - return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); + return XXH3_finalizeLong_64b(acc, (const xxh_u8*)secret, (xxh_u64)len); } /* @@ -5747,7 +6213,7 @@ XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH /* === XXH3 streaming === */ #ifndef XXH_NO_STREAM /* - * Malloc's a pointer that is always aligned to align. + * Malloc's a pointer that is always aligned to @align. * * This must be freed with `XXH_alignedFree()`. * @@ -5815,8 +6281,12 @@ static void XXH_alignedFree(void* p) /*! * @brief Allocate an @ref XXH3_state_t. * - * Must be freed with XXH3_freeState(). - * @return An allocated XXH3_state_t on success, `NULL` on failure. + * @return An allocated pointer of @ref XXH3_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH3_freeState(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) { @@ -5830,9 +6300,13 @@ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) /*! * @brief Frees an @ref XXH3_state_t. * - * Must be allocated with XXH3_createState(). * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). - * @return XXH_OK. + * + * @return @ref XXH_OK. + * + * @note Must be allocated with XXH3_createState(). + * + * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) { @@ -6111,9 +6585,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* if (state->totalLen > XXH3_MIDSIZE_MAX) { XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; XXH3_digest_long(acc, state, secret); - return XXH3_mergeAccs(acc, - secret + XXH_SECRET_MERGEACCS_START, - (xxh_u64)state->totalLen * XXH_PRIME64_1); + return XXH3_finalizeLong_64b(acc, secret, (xxh_u64)state->totalLen); } /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ if (state->useSeed) @@ -6405,6 +6877,17 @@ XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, } } +static XXH_PUREF XXH128_hash_t +XXH3_finalizeLong_128b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, xxh_u64 len) +{ + XXH128_hash_t h128; + h128.low64 = XXH3_finalizeLong_64b(acc, secret, len); + h128.high64 = XXH3_mergeAccs(acc, secret + secretSize + - XXH_STRIPE_LEN - XXH_SECRET_MERGEACCS_START, + ~(len * XXH_PRIME64_2)); + return h128; +} + XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, @@ -6418,16 +6901,7 @@ XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); - { XXH128_hash_t h128; - h128.low64 = XXH3_mergeAccs(acc, - secret + XXH_SECRET_MERGEACCS_START, - (xxh_u64)len * XXH_PRIME64_1); - h128.high64 = XXH3_mergeAccs(acc, - secret + secretSize - - sizeof(acc) - XXH_SECRET_MERGEACCS_START, - ~((xxh_u64)len * XXH_PRIME64_2)); - return h128; - } + return XXH3_finalizeLong_128b(acc, secret, secretSize, (xxh_u64)len); } /* @@ -6610,19 +7084,10 @@ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_ XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; XXH3_digest_long(acc, state, secret); XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); - { XXH128_hash_t h128; - h128.low64 = XXH3_mergeAccs(acc, - secret + XXH_SECRET_MERGEACCS_START, - (xxh_u64)state->totalLen * XXH_PRIME64_1); - h128.high64 = XXH3_mergeAccs(acc, - secret + state->secretLimit + XXH_STRIPE_LEN - - sizeof(acc) - XXH_SECRET_MERGEACCS_START, - ~((xxh_u64)state->totalLen * XXH_PRIME64_2)); - return h128; - } + return XXH3_finalizeLong_128b(acc, secret, state->secretLimit + XXH_STRIPE_LEN, (xxh_u64)state->totalLen); } /* len <= XXH3_MIDSIZE_MAX : short code */ - if (state->seed) + if (state->useSeed) return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); diff --git a/src/third_party/mozjs/get-sources.sh b/src/third_party/mozjs/get-sources.sh index 2c7a16ce367..7eb25541b9f 100755 --- a/src/third_party/mozjs/get-sources.sh +++ b/src/third_party/mozjs/get-sources.sh @@ -8,18 +8,21 @@ set -vx NAME=spidermonkey -VERSION="128.11.0esr" -LIB_GIT_BRANCH=spidermonkey-esr128.11-cpp-only -LIB_GIT_REVISION=5acd3be6c9563ad3e7ca6182285c69a38de47bab +VERSION="140.3.0esr" +LIB_GIT_BRANCH=aveselova/spidermonkey-esr140.3-cpp-only +LIB_GIT_REVISION=54ce5c4f64002c110069eba7861399fbf4b24ecc LIB_GIT_REPO=git@github.com:mongodb-forks/spidermonkey.git +# If a local spidermonkey repo exists, this is much faster than fetching from git: +# LIB_GIT_REPO=/home/ubuntu/spidermonkey/.git DEST_DIR=$(git rev-parse --show-toplevel)/src/third_party/mozjs LIB_GIT_DIR=$(mktemp -d /tmp/import-spidermonkey.XXXXXX) +# Windows: +# LIB_GIT_DIR=$(mktemp -d /z/import-spidermonkey.XXXXXX) trap "rm -rf $LIB_GIT_DIR" EXIT git clone $LIB_GIT_REPO $LIB_GIT_DIR -git -C $LIB_GIT_DIR checkout $LIB_GIT_BRANCH git -C $LIB_GIT_DIR checkout $LIB_GIT_REVISION test -d $DEST_DIR/mozilla-release && rm -rf $DEST_DIR/mozilla-release diff --git a/src/third_party/mozjs/include/AwakeTimeStamp.h b/src/third_party/mozjs/include/AwakeTimeStamp.h index b95ef9e77e9..6c6a358fbe3 100644 --- a/src/third_party/mozjs/include/AwakeTimeStamp.h +++ b/src/third_party/mozjs/include/AwakeTimeStamp.h @@ -23,12 +23,16 @@ class AwakeTimeDuration; // // Some arithmetic and ordering operations are supported, when they make sense. // -// This timestamp shouldn't be considered to be high-resolution, and is suitable -// to measure time from a hundred of milliseconds (because of Windows -// limitations). +// When using NowLoRes(), the timestamp shouldn't be considered to be +// high-resolution, and is suitable to measure time from a hundred of +// milliseconds (because of Windows limitations). +// Now() can be a bit more expensive on Windows, and is precise. Both +// methods are equivalent on non-Windows. class AwakeTimeStamp { public: + using DurationType = AwakeTimeDuration; MFBT_API static AwakeTimeStamp NowLoRes(); + MFBT_API static AwakeTimeStamp Now(); MFBT_API void operator+=(const AwakeTimeDuration& aOther); MFBT_API void operator-=(const AwakeTimeDuration& aOther); MFBT_API bool operator<(const AwakeTimeStamp& aOther) const { @@ -50,6 +54,7 @@ class AwakeTimeStamp { return !(*this == aOther); } MFBT_API AwakeTimeDuration operator-(AwakeTimeStamp const& aOther) const; + MFBT_API AwakeTimeStamp operator-(AwakeTimeDuration const& aOther) const; MFBT_API AwakeTimeStamp operator+(const AwakeTimeDuration& aDuration) const; private: @@ -71,6 +76,9 @@ class AwakeTimeDuration { MFBT_API double ToSeconds() const; MFBT_API double ToMilliseconds() const; MFBT_API double ToMicroseconds() const; + static MFBT_API AwakeTimeDuration FromSeconds(uint64_t aSeconds); + static MFBT_API AwakeTimeDuration FromMilliseconds(uint64_t aMilliseconds); + static MFBT_API AwakeTimeDuration FromMicroseconds(uint64_t aMicroseconds); MFBT_API void operator+=(const AwakeTimeDuration& aDuration) { mValueUs += aDuration.mValueUs; } diff --git a/src/third_party/mozjs/include/BaseProfilingCategory.h b/src/third_party/mozjs/include/BaseProfilingCategory.h new file mode 100644 index 00000000000..d6f7148c913 --- /dev/null +++ b/src/third_party/mozjs/include/BaseProfilingCategory.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BaseProfilingCategory_h +#define BaseProfilingCategory_h + +#include "mozilla/Span.h" +#include "mozilla/Types.h" + +#include + +#include "ProfilingCategoryList.h" + +namespace mozilla { +namespace baseprofiler { + +// clang-format off + +// An enum that lists all possible category pairs in one list. +// This is the enum that is used in profiler stack labels. Having one list that +// includes subcategories from all categories in one list allows assigning the +// category pair to a stack label with just one number. +#define CATEGORY_ENUM_BEGIN_CATEGORY(name, labelAsString, color) +#define CATEGORY_ENUM_SUBCATEGORY(supercategory, name, labelAsString) name, +#define CATEGORY_ENUM_END_CATEGORY +enum class ProfilingCategoryPair : uint32_t { + MOZ_PROFILING_CATEGORY_LIST(CATEGORY_ENUM_BEGIN_CATEGORY, + CATEGORY_ENUM_SUBCATEGORY, + CATEGORY_ENUM_END_CATEGORY) + COUNT, + LAST = COUNT - 1, +}; +#undef CATEGORY_ENUM_BEGIN_CATEGORY +#undef CATEGORY_ENUM_SUBCATEGORY +#undef CATEGORY_ENUM_END_CATEGORY + +// An enum that lists just the categories without their subcategories. +#define SUPERCATEGORY_ENUM_BEGIN_CATEGORY(name, labelAsString, color) name, +#define SUPERCATEGORY_ENUM_SUBCATEGORY(supercategory, name, labelAsString) +#define SUPERCATEGORY_ENUM_END_CATEGORY +enum class ProfilingCategory : uint32_t { + MOZ_PROFILING_CATEGORY_LIST(SUPERCATEGORY_ENUM_BEGIN_CATEGORY, + SUPERCATEGORY_ENUM_SUBCATEGORY, + SUPERCATEGORY_ENUM_END_CATEGORY) + COUNT, + LAST = COUNT - 1, +}; +#undef SUPERCATEGORY_ENUM_BEGIN_CATEGORY +#undef SUPERCATEGORY_ENUM_SUBCATEGORY +#undef SUPERCATEGORY_ENUM_END_CATEGORY + +// clang-format on + +struct ProfilingCategoryInfo { + const char* mName; + const char* mColor; + const mozilla::Span mSubcategoryNames; +}; + +struct ProfilingCategoryPairInfo { + ProfilingCategory mCategory; + uint32_t mSubcategoryIndex; + const char* mLabel; +}; + +MFBT_API mozilla::Span GetProfilingCategoryList(); + +MFBT_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo( + ProfilingCategoryPair aCategoryPair); + +} // namespace baseprofiler +} // namespace mozilla + +#endif /* BaseProfilingCategory_h */ diff --git a/src/third_party/mozjs/include/LoggingCore.h b/src/third_party/mozjs/include/LoggingCore.h new file mode 100644 index 00000000000..4cc14f90488 --- /dev/null +++ b/src/third_party/mozjs/include/LoggingCore.h @@ -0,0 +1,49 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Shared logging infrastructure across different binaries. + +#ifndef _mozilla_LoggingCore_h +#define _mozilla_LoggingCore_h + +#include "mozilla/Atomics.h" +#include "mozilla/Types.h" + +namespace mozilla { +// While not a 100% mapping to PR_LOG's numeric values, mozilla::LogLevel does +// maintain a direct mapping for the Disabled, Debug and Verbose levels. +// +// Mappings of LogLevel to PR_LOG's numeric values: +// +// +---------+------------------+-----------------+ +// | Numeric | NSPR Logging | Mozilla Logging | +// +---------+------------------+-----------------+ +// | 0 | PR_LOG_NONE | Disabled | +// | 1 | PR_LOG_ALWAYS | Error | +// | 2 | PR_LOG_ERROR | Warning | +// | 3 | PR_LOG_WARNING | Info | +// | 4 | PR_LOG_DEBUG | Debug | +// | 5 | PR_LOG_DEBUG + 1 | Verbose | +// +---------+------------------+-----------------+ +// +enum class LogLevel { + Disabled = 0, + Error, + Warning, + Info, + Debug, + Verbose, +}; + +/** + * Safely converts an integer into a valid LogLevel. + */ +MFBT_API LogLevel ToLogLevel(int32_t aLevel); + +using AtomicLogLevel = Atomic; + +} // namespace mozilla + +#endif /* _mozilla_LoggingCore_h */ diff --git a/src/third_party/mozjs/include/NativeNt.h b/src/third_party/mozjs/include/NativeNt.h index 932dcd0a7b0..e28ad0f2914 100644 --- a/src/third_party/mozjs/include/NativeNt.h +++ b/src/third_party/mozjs/include/NativeNt.h @@ -554,7 +554,7 @@ class MOZ_RAII PEHeaders final { WORD wLength; WORD wValueLength; WORD wType; - WCHAR szKey[16]; // ArrayLength(L"VS_VERSION_INFO") + WCHAR szKey[16]; // std::size(L"VS_VERSION_INFO") // Additional data goes here, aligned on a 4-byte boundary }; @@ -913,6 +913,12 @@ class MOZ_RAII PEHeaders final { IMAGE_SCN_MEM_READ); } + // There may be other data sections in the binary besides .data + Maybe> GetDataSectionInfo() const { + return FindSection(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE); + } + static bool IsValid(PIMAGE_IMPORT_DESCRIPTOR aImpDesc) { return aImpDesc && aImpDesc->OriginalFirstThunk != 0; } @@ -1024,8 +1030,8 @@ class MOZ_RAII PEHeaders final { const wchar_t kVersionInfoKey[] = L"VS_VERSION_INFO"; if (::RtlCompareMemory(aVerInfo->szKey, kVersionInfoKey, - ArrayLength(kVersionInfoKey)) != - ArrayLength(kVersionInfoKey)) { + std::size(kVersionInfoKey)) != + std::size(kVersionInfoKey)) { return nullptr; } diff --git a/src/third_party/mozjs/include/Now.h b/src/third_party/mozjs/include/Now.h new file mode 100644 index 00000000000..cafc69f761a --- /dev/null +++ b/src/third_party/mozjs/include/Now.h @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_Now_h +#define mozilla_Now_h + +#include + +#include "mozilla/Maybe.h" + +namespace mozilla { + +// Returns monotonic milliseconds elapsed since an arbitrary reference point, +// excluding time when the system was suspended. +MFBT_API Maybe NowExcludingSuspendMs(); +// Returns monotonic milliseconds elapsed since an arbitrary reference point, +// including time when the system was suspended. +MFBT_API Maybe NowIncludingSuspendMs(); + +}; // namespace mozilla + +#endif // mozilla_Now_h diff --git a/src/third_party/mozjs/include/PreXULSkeletonUI.h b/src/third_party/mozjs/include/PreXULSkeletonUI.h index c0549cd4e62..8f0c9b1a65b 100644 --- a/src/third_party/mozjs/include/PreXULSkeletonUI.h +++ b/src/third_party/mozjs/include/PreXULSkeletonUI.h @@ -21,8 +21,8 @@ namespace mozilla { // to not vary based off of any user settings for the initial toplevel window, // so we're safe here for now. static const DWORD kPreXULSkeletonUIWindowStyle = - WS_CLIPCHILDREN | WS_DLGFRAME | WS_BORDER | WS_MAXIMIZEBOX | - WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU; + WS_OVERLAPPED | WS_CLIPCHILDREN | WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | + WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU; static const DWORD kPreXULSkeletonUIWindowStyleEx = WS_EX_WINDOWEDGE; struct CSSPixelSpan { @@ -50,6 +50,7 @@ struct SkeletonUISettings { bool menubarShown; bool bookmarksToolbarShown; bool rtlEnabled; + bool verticalTabs; SkeletonUIDensity uiDensity; }; @@ -61,12 +62,13 @@ enum class SkeletonUIFlag : uint8_t { RtlEnabled, TouchDensity, CompactDensity, + VerticalTabs }; struct ThemeColors { uint32_t backgroundColor; uint32_t toolbarForegroundColor; - uint32_t tabBarColor; + uint32_t titlebarColor; uint32_t tabColor; uint32_t tabOutlineColor; uint32_t chromeContentDividerColor; @@ -101,61 +103,6 @@ enum class PreXULSkeletonUIError : uint32_t { Unknown, }; -inline const wchar_t* GetPreXULSkeletonUIErrorString( - PreXULSkeletonUIError error) { - switch (error) { - case PreXULSkeletonUIError::None: - return L"None"; - case PreXULSkeletonUIError::Disabled: - return L"Disabled"; - case PreXULSkeletonUIError::OOM: - return L"OOM"; - case PreXULSkeletonUIError::Cmdline: - return L"Cmdline"; - case PreXULSkeletonUIError::EnvVars: - return L"EnvVars"; - case PreXULSkeletonUIError::FailedToOpenRegistryKey: - return L"FailedToOpenRegistryKey"; - case PreXULSkeletonUIError::RegistryError: - return L"RegistryError"; - case PreXULSkeletonUIError::FailedLoadingDynamicProcs: - return L"FailedLoadingDynamicProcs"; - case PreXULSkeletonUIError::FailedGettingLock: - return L"FailedGettingLock"; - case PreXULSkeletonUIError::FilesystemFailure: - return L"FilesystemFailure"; - case PreXULSkeletonUIError::NoStartWithLastProfile: - return L"NoStartWithLastProfile"; - case PreXULSkeletonUIError::FailedRegisteringWindowClass: - return L"FailedRegisteringWindowClass"; - case PreXULSkeletonUIError::CorruptData: - return L"CorruptData"; - case PreXULSkeletonUIError::BadWindowDimensions: - return L"BadWindowDimensions"; - case PreXULSkeletonUIError::FailedGettingMonitorInfo: - return L"FailedGettingMonitorInfo"; - case PreXULSkeletonUIError::EnabledKeyDoesNotExist: - return L"EnabledKeyDoesNotExist"; - case PreXULSkeletonUIError::CreateWindowFailed: - return L"CreateWindowFailed"; - case PreXULSkeletonUIError::FailedGettingDC: - return L"FailedGettingDC"; - case PreXULSkeletonUIError::FailedBlitting: - return L"FailedBlitting"; - case PreXULSkeletonUIError::FailedFillingBottomRect: - return L"FailedFillingBottomRect"; - case PreXULSkeletonUIError::CrashedOnce: - return L"CrashedOnce"; - case PreXULSkeletonUIError::BadUIDensity: - return L"BadUIDensity"; - case PreXULSkeletonUIError::Unknown: - return L"Unknown"; - } - - MOZ_ASSERT_UNREACHABLE(); - return L"Unknown"; -} - enum class PreXULSkeletonUIProgress : uint32_t { Started, Completed, @@ -166,7 +113,6 @@ MFBT_API void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc, MFBT_API void CleanupProcessRuntime(); MFBT_API bool GetPreXULSkeletonUIWasShown(); MFBT_API HWND ConsumePreXULSkeletonUIHandle(); -MFBT_API Maybe GetPreXULSkeletonUIErrorReason(); MFBT_API bool WasPreXULSkeletonUIMaximized(); MFBT_API Result PersistPreXULSkeletonUIValues( const SkeletonUISettings& settings); diff --git a/src/third_party/mozjs/include/ProcessType.h b/src/third_party/mozjs/include/ProcessType.h index 890ed4faacf..012cd046e61 100644 --- a/src/third_party/mozjs/include/ProcessType.h +++ b/src/third_party/mozjs/include/ProcessType.h @@ -22,9 +22,16 @@ enum GeckoProcessType { GeckoProcessType_Invalid = GeckoProcessType_End }; +// Integral type used for GeckoChildIDs. A ChildID of -1 is used as the invalid +// sentinel, and 0 indicates the parent process. +using GeckoChildID = int32_t; + +inline constexpr GeckoChildID kInvalidGeckoChildID = -1; + namespace mozilla { namespace startup { extern MFBT_DATA GeckoProcessType sChildProcessType; +extern MFBT_DATA GeckoChildID sGeckoChildID; } // namespace startup /** @@ -39,6 +46,18 @@ MOZ_ALWAYS_INLINE GeckoProcessType GetGeckoProcessType() { */ MFBT_API void SetGeckoProcessType(const char* aProcessTypeString); +/** + * @return the GeckoChildID of the current process. + */ +MOZ_ALWAYS_INLINE GeckoChildID GetGeckoChildID() { + return startup::sGeckoChildID; +} + +/** + * Set the gecko child id based on a null-terminated byte string. + */ +MFBT_API void SetGeckoChildID(const char* aGeckoChildIDString); + } // namespace mozilla #endif // IPC_PROCESSTYPE_H_ diff --git a/src/third_party/mozjs/include/ProfilingCategoryList.h b/src/third_party/mozjs/include/ProfilingCategoryList.h new file mode 100644 index 00000000000..63e27a8f721 --- /dev/null +++ b/src/third_party/mozjs/include/ProfilingCategoryList.h @@ -0,0 +1,150 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef baseprofiler_ProfilingCategoryList_h +#define baseprofiler_ProfilingCategoryList_h + +/* This file is generated by generate_profiling_categories.py from + profiling_categories.yaml. DO NOT EDIT! */ + +// Profiler sub-categories are applied to each sampled stack to describe the +// type of workload that the CPU is busy with. Only one sub-category can be +// assigned so be mindful that these are non-overlapping. The active category is +// set by pushing a label to the profiling stack, or by the unwinder in cases +// such as JITs. A profile sample in arbitrary C++/Rust will typically be +// categorized based on the top of the label stack. +// +// The list of available color names for categories is: +// transparent +// blue +// green +// grey +// lightblue +// magenta +// orange +// purple +// yellow + +// clang-format off + +#define MOZ_PROFILING_CATEGORY_LIST(BEGIN_CATEGORY, SUBCATEGORY, END_CATEGORY) \ + BEGIN_CATEGORY(IDLE, "Idle", "transparent") \ + SUBCATEGORY(IDLE, IDLE, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(OTHER, "Other", "grey") \ + SUBCATEGORY(OTHER, OTHER, "Other") \ + SUBCATEGORY(OTHER, OTHER_PreferenceRead, "Preference Read") \ + SUBCATEGORY(OTHER, OTHER_Profiling, "Profiling") \ + END_CATEGORY \ + BEGIN_CATEGORY(TEST, "Test", "darkgray") \ + SUBCATEGORY(TEST, TEST, "Test") \ + END_CATEGORY \ + BEGIN_CATEGORY(LAYOUT, "Layout", "purple") \ + SUBCATEGORY(LAYOUT, LAYOUT, "Other") \ + SUBCATEGORY(LAYOUT, LAYOUT_FrameConstruction, "Frame construction") \ + SUBCATEGORY(LAYOUT, LAYOUT_Reflow, "Reflow") \ + SUBCATEGORY(LAYOUT, LAYOUT_CSSParsing, "CSS parsing") \ + SUBCATEGORY(LAYOUT, LAYOUT_SelectorQuery, "Selector query") \ + SUBCATEGORY(LAYOUT, LAYOUT_StyleComputation, "Style computation") \ + SUBCATEGORY(LAYOUT, LAYOUT_Destroy, "Layout cleanup") \ + SUBCATEGORY(LAYOUT, LAYOUT_Printing, "Printing") \ + END_CATEGORY \ + BEGIN_CATEGORY(JS, "JavaScript", "yellow") \ + SUBCATEGORY(JS, JS, "Other") \ + SUBCATEGORY(JS, JS_Parsing, "Parsing") \ + SUBCATEGORY(JS, JS_BaselineCompilation, "JIT Compile (baseline)") \ + SUBCATEGORY(JS, JS_IonCompilation, "JIT Compile (ion)") \ + SUBCATEGORY(JS, JS_Interpreter, "Interpreter") \ + SUBCATEGORY(JS, JS_BaselineInterpret, "JIT (baseline-interpreter)") \ + SUBCATEGORY(JS, JS_Baseline, "JIT (baseline)") \ + SUBCATEGORY(JS, JS_IonMonkey, "JIT (ion)") \ + SUBCATEGORY(JS, JS_Builtin, "Builtin API") \ + SUBCATEGORY(JS, JS_WasmIon, "Wasm (ion)") \ + SUBCATEGORY(JS, JS_WasmBaseline, "Wasm (baseline)") \ + SUBCATEGORY(JS, JS_WasmOther, "Wasm (other)") \ + END_CATEGORY \ + BEGIN_CATEGORY(GCCC, "GC / CC", "orange") \ + SUBCATEGORY(GCCC, GCCC, "Other") \ + SUBCATEGORY(GCCC, GCCC_MinorGC, "Minor GC") \ + SUBCATEGORY(GCCC, GCCC_MajorGC, "Major GC (Other)") \ + SUBCATEGORY(GCCC, GCCC_MajorGC_Mark, "Major GC (Mark)") \ + SUBCATEGORY(GCCC, GCCC_MajorGC_Sweep, "Major GC (Sweep)") \ + SUBCATEGORY(GCCC, GCCC_MajorGC_Compact, "Major GC (Compact)") \ + SUBCATEGORY(GCCC, GCCC_UnmarkGray, "Unmark Gray") \ + SUBCATEGORY(GCCC, GCCC_Barrier, "Barrier") \ + SUBCATEGORY(GCCC, GCCC_FreeSnowWhite, "CC (Free Snow White)") \ + SUBCATEGORY(GCCC, GCCC_BuildGraph, "CC (Build Graph)") \ + SUBCATEGORY(GCCC, GCCC_ScanRoots, "CC (Scan Roots)") \ + SUBCATEGORY(GCCC, GCCC_CollectWhite, "CC (Collect White)") \ + SUBCATEGORY(GCCC, GCCC_Finalize, "CC (Finalize)") \ + END_CATEGORY \ + BEGIN_CATEGORY(NETWORK, "Network", "lightblue") \ + SUBCATEGORY(NETWORK, NETWORK, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(GRAPHICS, "Graphics", "green") \ + SUBCATEGORY(GRAPHICS, GRAPHICS, "Other") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_DisplayListBuilding, "DisplayList building") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_DisplayListMerging, "DisplayList merging") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_LayerBuilding, "Layer building") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_TileAllocation, "Tile allocation") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_WRDisplayList, "WebRender display list") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_Rasterization, "Rasterization") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_FlushingAsyncPaints, "Flushing async paints") \ + SUBCATEGORY(GRAPHICS, GRAPHICS_ImageDecoding, "Image decoding") \ + END_CATEGORY \ + BEGIN_CATEGORY(DOM, "DOM", "blue") \ + SUBCATEGORY(DOM, DOM, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(JAVA_ANDROID, "Android", "yellow") \ + SUBCATEGORY(JAVA_ANDROID, JAVA_ANDROID, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(JAVA_ANDROIDX, "AndroidX", "orange") \ + SUBCATEGORY(JAVA_ANDROIDX, JAVA_ANDROIDX, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(JAVA_LANGUAGE, "Java", "blue") \ + SUBCATEGORY(JAVA_LANGUAGE, JAVA_LANGUAGE, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(JAVA_MOZILLA, "Mozilla", "green") \ + SUBCATEGORY(JAVA_MOZILLA, JAVA_MOZILLA, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(JAVA_KOTLIN, "Kotlin", "purple") \ + SUBCATEGORY(JAVA_KOTLIN, JAVA_KOTLIN, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(JAVA_BLOCKED, "Blocked", "lightblue") \ + SUBCATEGORY(JAVA_BLOCKED, JAVA_BLOCKED, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(MAILNEWS, "Mailnews", "brown") \ + SUBCATEGORY(MAILNEWS, MAILNEWS, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(IPC, "IPC", "lightgreen") \ + SUBCATEGORY(IPC, IPC, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(MEDIA, "Media", "orange") \ + SUBCATEGORY(MEDIA, MEDIA, "Other") \ + SUBCATEGORY(MEDIA, MEDIA_CUBEB, "Cubeb") \ + SUBCATEGORY(MEDIA, MEDIA_PLAYBACK, "Playback") \ + SUBCATEGORY(MEDIA, MEDIA_RT, "Real-time rendering") \ + END_CATEGORY \ + BEGIN_CATEGORY(A11Y, "Accessibility", "brown") \ + SUBCATEGORY(A11Y, A11Y, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(PROFILER, "Profiler", "lightred") \ + SUBCATEGORY(PROFILER, PROFILER, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(TIMER, "Timer", "grey") \ + SUBCATEGORY(TIMER, TIMER, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(REMOTE_PROTOCOL, "Remote-Protocol", "grey") \ + SUBCATEGORY(REMOTE_PROTOCOL, REMOTE_PROTOCOL, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(SANDBOX, "Sandbox", "grey") \ + SUBCATEGORY(SANDBOX, SANDBOX, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(TELEMETRY, "Telemetry", "grey") \ + SUBCATEGORY(TELEMETRY, TELEMETRY, "Other") \ + END_CATEGORY + +// clang-format on + +#endif // baseprofiler_ProfilingCategoryList_h diff --git a/src/third_party/mozjs/include/SIMD.h b/src/third_party/mozjs/include/SIMD.h index 3d171856567..18b78fbcdb5 100644 --- a/src/third_party/mozjs/include/SIMD.h +++ b/src/third_party/mozjs/include/SIMD.h @@ -54,6 +54,15 @@ class SIMD { static MFBT_API const char16_t* memchr16AVX2(const char16_t* ptr, char16_t value, size_t length); + // Search through `ptr[0..length]` for the first occurrence of `value` and + // return the pointer to it, or nullptr if it cannot be found. + static MFBT_API const uint32_t* memchr32(const uint32_t* ptr, uint32_t value, + size_t length); + + // This function just restricts our execution to the AVX2 path + static MFBT_API const uint32_t* memchr32AVX2(const uint32_t* ptr, + uint32_t value, size_t length); + // Search through `ptr[0..length]` for the first occurrence of `value` and // return the pointer to it, or nullptr if it cannot be found. static MFBT_API const uint64_t* memchr64(const uint64_t* ptr, uint64_t value, diff --git a/src/third_party/mozjs/include/StackWalk_windows.h b/src/third_party/mozjs/include/StackWalk_windows.h index 81c81257810..ddc86b398a5 100644 --- a/src/third_party/mozjs/include/StackWalk_windows.h +++ b/src/third_party/mozjs/include/StackWalk_windows.h @@ -7,12 +7,30 @@ #ifndef mozilla_StackWalk_windows_h #define mozilla_StackWalk_windows_h +#include "mozilla/Array.h" #include "mozilla/Types.h" #if defined(_M_AMD64) || defined(_M_ARM64) /** - * Allow stack walkers to work around the egregious win64 dynamic lookup table - * list API by locking around SuspendThread to avoid deadlock. + * This function enables strategy (1) for avoiding deadlocks between the stack + * walking thread and the suspended thread. In aStackWalkLocks the caller must + * provide pointers to the two ntdll-internal SRW locks acquired by + * RtlLookupFunctionEntry. These locks are LdrpInvertedFunctionTableSRWLock and + * RtlpDynamicFunctionTableLock -- we don't need to know which one is which. + * Until InitializeStackWalkLocks function is called, strategy (2) is used. + * + * See comment in StackWalk.cpp + */ +MFBT_API +void InitializeStackWalkLocks(const mozilla::Array& aStackWalkLocks); + +/** + * As part of strategy (2) for avoiding deadlocks between the stack walking + * thread and the suspended thread, we mark stack walk suppression paths by + * putting them under the scope of a AutoSuppressStackWalking object. Any code + * path that may do an exclusive acquire of LdrpInvertedFunctionTableSRWLock or + * RtlpDynamicFunctionTableLock should be marked this way, to ensure that + * strategy (2) can properly mitigate all deadlock scenarios. * * See comment in StackWalk.cpp */ diff --git a/src/third_party/mozjs/include/TimeStamp.h b/src/third_party/mozjs/include/TimeStamp.h index 635b62cf137..81e7515a956 100644 --- a/src/third_party/mozjs/include/TimeStamp.h +++ b/src/third_party/mozjs/include/TimeStamp.h @@ -387,6 +387,7 @@ static_assert(sizeof(TimeStampValue) > 8); */ class TimeStamp { public: + using DurationType = TimeDuration; /** * Initialize to the "null" moment */ diff --git a/src/third_party/mozjs/include/WindowsDiagnostics.h b/src/third_party/mozjs/include/WindowsDiagnostics.h index 09bc314e893..d9a03ef10c2 100644 --- a/src/third_party/mozjs/include/WindowsDiagnostics.h +++ b/src/third_party/mozjs/include/WindowsDiagnostics.h @@ -86,9 +86,7 @@ struct WinErrorState { bool operator!=(WinErrorState const& that) const { return !operator==(that); } }; -// TODO This code does not have tests. Only use it on paths that are already -// known to crash. Add tests before using it in release builds. -#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && defined(_M_X64) +#if defined(_M_AMD64) using OnSingleStepCallback = std::function; @@ -108,9 +106,6 @@ MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void EnableTrapFlag(); MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void DisableTrapFlag(); MFBT_API LONG SingleStepExceptionHandler(_EXCEPTION_POINTERS* aExceptionInfo); -// This block uses nt::PEHeaders and thus depends on NativeNt.h. -# if !defined(IMPL_MFBT) - // Run aCallbackToRun instruction by instruction, and between each instruction // call aOnSingleStepCallback. Single-stepping ends when aOnSingleStepCallback // returns false (in which case aCallbackToRun will continue to run @@ -140,6 +135,9 @@ CollectSingleStepData(CallbackToRun aCallbackToRun, return WindowsDiagnosticsError::None; } +// This block uses nt::PEHeaders and thus depends on NativeNt.h. +# if !defined(IMPL_MFBT) + template struct ModuleSingleStepData { uint32_t mStepsLog[NMaxSteps]{}; @@ -288,7 +286,7 @@ WindowsDiagnosticsError CollectModuleSingleStepData( # endif // !IMPL_MFBT -#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED && _M_X64 +#endif // _M_AMD64 } // namespace mozilla diff --git a/src/third_party/mozjs/include/WindowsDpiAwareness.h b/src/third_party/mozjs/include/WindowsDpiAwareness.h index 589415da6d0..4ba641cc95a 100644 --- a/src/third_party/mozjs/include/WindowsDpiAwareness.h +++ b/src/third_party/mozjs/include/WindowsDpiAwareness.h @@ -21,9 +21,9 @@ typedef enum DPI_AWARENESS { DPI_AWARENESS_PER_MONITOR_AWARE = 2 } DPI_AWARENESS; -# define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1) -# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2) -# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) +# define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT) - 1) +# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT) - 2) +# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT) - 3) # define DPI_AWARENESS_CONTEXT_DECLARED #endif // (DPI_AWARENESS_CONTEXT_DECLARED) diff --git a/src/third_party/mozjs/include/WindowsUnwindInfo.h b/src/third_party/mozjs/include/WindowsUnwindInfo.h index 3667b5f2bc8..be76670d2d9 100644 --- a/src/third_party/mozjs/include/WindowsUnwindInfo.h +++ b/src/third_party/mozjs/include/WindowsUnwindInfo.h @@ -290,7 +290,7 @@ class IterableUnwindInfo { : mInfo(aInfo), mIndex(aIndex), mSlotsCount(aSlotsCount), - mIsValid(aIsValid){}; + mIsValid(aIsValid) {}; UnwindInfo& mInfo; uint8_t mIndex; diff --git a/src/third_party/mozjs/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/include/js/AllocPolicy.h b/src/third_party/mozjs/include/js/AllocPolicy.h index 72c449293c5..880527e8cb0 100644 --- a/src/third_party/mozjs/include/js/AllocPolicy.h +++ b/src/third_party/mozjs/include/js/AllocPolicy.h @@ -25,8 +25,7 @@ class FrontendContext; enum class AllocFunction { Malloc, Calloc, Realloc }; -/* Base class allocation policies providing allocation methods. */ -class AllocPolicyBase { +class ArenaAllocPolicyBase { public: template T* maybe_pod_arena_malloc(arena_id_t arenaId, size_t numElems) { @@ -54,7 +53,11 @@ class AllocPolicyBase { size_t newSize) { return maybe_pod_arena_realloc(arenaId, p, oldSize, newSize); } +}; +/* Base class allocation policies providing allocation methods. */ +class AllocPolicyBase : public ArenaAllocPolicyBase { + public: template T* maybe_pod_malloc(size_t numElems) { return maybe_pod_arena_malloc(js::MallocArena, numElems); @@ -86,6 +89,44 @@ class AllocPolicyBase { } }; +/* + * Base class allocation policies providing allocation methods for allocations + * off the main thread. + */ +class BackgroundAllocPolicyBase : ArenaAllocPolicyBase { + public: + template + T* maybe_pod_malloc(size_t numElems) { + return maybe_pod_arena_malloc(js::BackgroundMallocArena, numElems); + } + template + T* maybe_pod_calloc(size_t numElems) { + return maybe_pod_arena_calloc(js::BackgroundMallocArena, numElems); + } + template + T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) { + return maybe_pod_arena_realloc(js::BackgroundMallocArena, p, oldSize, + newSize); + } + template + T* pod_malloc(size_t numElems) { + return pod_arena_malloc(js::BackgroundMallocArena, numElems); + } + template + T* pod_calloc(size_t numElems) { + return pod_arena_calloc(js::BackgroundMallocArena, numElems); + } + template + T* pod_realloc(T* p, size_t oldSize, size_t newSize) { + return pod_arena_realloc(js::BackgroundMallocArena, p, oldSize, newSize); + } + + template + void free_(T* p, size_t numElems = 0) { + js_free(p); + } +}; + /* Policy for using system memory functions and doing no error reporting. */ class SystemAllocPolicy : public AllocPolicyBase { public: @@ -93,6 +134,12 @@ class SystemAllocPolicy : public AllocPolicyBase { bool checkSimulatedOOM() const { return !js::oom::ShouldFailWithOOM(); } }; +class BackgroundSystemAllocPolicy : public BackgroundAllocPolicyBase { + public: + void reportAllocOverflow() const {} + bool checkSimulatedOOM() const { return !js::oom::ShouldFailWithOOM(); } +}; + MOZ_COLD JS_PUBLIC_API void ReportOutOfMemory(JSContext* cx); MOZ_COLD JS_PUBLIC_API void ReportOutOfMemory(FrontendContext* fc); diff --git a/src/third_party/mozjs/include/js/CharacterEncoding.h b/src/third_party/mozjs/include/js/CharacterEncoding.h index 9d1df4664b4..2f5c8ca0197 100644 --- a/src/third_party/mozjs/include/js/CharacterEncoding.h +++ b/src/third_party/mozjs/include/js/CharacterEncoding.h @@ -261,13 +261,6 @@ extern JS_PUBLIC_API TwoByteCharsZ UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars& utf8, size_t* outlen, arena_id_t destArenaId); -/* - * Like UTF8CharsToNewTwoByteCharsZ, but for ConstUTF8CharsZ. - */ -extern JS_PUBLIC_API TwoByteCharsZ -UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, - size_t* outlen, arena_id_t destArenaId); - /* * The same as UTF8CharsToNewTwoByteCharsZ(), except that any malformed UTF-8 * characters will be replaced by \uFFFD. No exception will be thrown for @@ -277,10 +270,6 @@ extern JS_PUBLIC_API TwoByteCharsZ LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars& utf8, size_t* outlen, arena_id_t destArenaId); -extern JS_PUBLIC_API TwoByteCharsZ -LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, - size_t* outlen, arena_id_t destArenaId); - /* * Returns the length of the char buffer required to encode |s| as UTF8. * Does not include the null-terminator. @@ -329,15 +318,6 @@ extern JS_PUBLIC_API Latin1CharsZ UTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars& utf8, size_t* outlen, arena_id_t destArenaId); -/* - * Return a null-terminated Latin-1 string copied from the input string, - * storing its length (excluding null terminator) in |*outlen|. Non-Latin-1 - * codepoints are replaced by '?'. Returns Latin1CharsZ() on failure. - */ -extern JS_PUBLIC_API Latin1CharsZ -LossyUTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars& utf8, - size_t* outlen, arena_id_t destArenaId); - /* * Returns true if all characters in the given null-terminated string are * ASCII, i.e. < 0x80, false otherwise. diff --git a/src/third_party/mozjs/include/js/Class.h b/src/third_party/mozjs/include/js/Class.h index 0c9833cbcfa..5875af2c07f 100644 --- a/src/third_party/mozjs/include/js/Class.h +++ b/src/third_party/mozjs/include/js/Class.h @@ -813,11 +813,6 @@ enum class ESClass { BigInt, Function, // Note: Only JSFunction objects. -#ifdef ENABLE_RECORD_TUPLE - Record, - Tuple, -#endif - /** None of the above. */ Other }; diff --git a/src/third_party/mozjs/include/js/CompilationAndEvaluation.h b/src/third_party/mozjs/include/js/CompilationAndEvaluation.h index fee0aecbb09..c8e64b007d2 100644 --- a/src/third_party/mozjs/include/js/CompilationAndEvaluation.h +++ b/src/third_party/mozjs/include/js/CompilationAndEvaluation.h @@ -27,6 +27,7 @@ union Utf8Unit; namespace JS { +class JS_PUBLIC_API EnvironmentChain; class JS_PUBLIC_API InstantiateOptions; class JS_PUBLIC_API ReadOnlyCompileOptions; @@ -84,12 +85,12 @@ extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx, * objects that should end up on the script's scope chain. */ extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx, - JS::HandleObjectVector envChain, + const JS::EnvironmentChain& envChain, JS::Handle script, JS::MutableHandle rval); extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx, - JS::HandleObjectVector envChain, + const JS::EnvironmentChain& envChain, JS::Handle script); namespace JS { @@ -108,7 +109,8 @@ extern JS_PUBLIC_API bool Evaluate(JSContext* cx, * the global object on it; that's implicit. It needs to contain the other * objects that should end up on the script's scope chain. */ -extern JS_PUBLIC_API bool Evaluate(JSContext* cx, HandleObjectVector envChain, +extern JS_PUBLIC_API bool Evaluate(JSContext* cx, + const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, SourceText& srcBuf, MutableHandle rval); @@ -173,7 +175,7 @@ extern JS_PUBLIC_API JSScript* CompileUtf8Path( * global must not be explicitly included in the scope chain. */ extern JS_PUBLIC_API JSFunction* CompileFunction( - JSContext* cx, HandleObjectVector envChain, + JSContext* cx, const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, const char* name, unsigned nargs, const char* const* argnames, SourceText& srcBuf); @@ -185,7 +187,7 @@ extern JS_PUBLIC_API JSFunction* CompileFunction( * global must not be explicitly included in the scope chain. */ extern JS_PUBLIC_API JSFunction* CompileFunction( - JSContext* cx, HandleObjectVector envChain, + JSContext* cx, const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, const char* name, unsigned nargs, const char* const* argnames, SourceText& srcBuf); @@ -194,7 +196,7 @@ extern JS_PUBLIC_API JSFunction* CompileFunction( * Rust-friendly ergonomics. */ extern JS_PUBLIC_API JSFunction* CompileFunctionUtf8( - JSContext* cx, HandleObjectVector envChain, + JSContext* cx, const JS::EnvironmentChain& envChain, const ReadOnlyCompileOptions& options, const char* name, unsigned nargs, const char* const* argnames, const char* utf8, size_t length); diff --git a/src/third_party/mozjs/include/js/CompileOptions.h b/src/third_party/mozjs/include/js/CompileOptions.h index 01a84b23986..e0c10b8d5b8 100644 --- a/src/third_party/mozjs/include/js/CompileOptions.h +++ b/src/third_party/mozjs/include/js/CompileOptions.h @@ -62,7 +62,10 @@ #include "js/CharacterEncoding.h" // JS::ConstUTF8CharsZ #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin -#include "js/TypeDecls.h" // JS::MutableHandle (fwd) +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +# include "js/Prefs.h" // JS::Prefs::* +#endif +#include "js/TypeDecls.h" // JS::MutableHandle (fwd) namespace js { class FrontendContext; @@ -124,22 +127,29 @@ class JS_PUBLIC_API PrefableCompileOptions { public: PrefableCompileOptions() : importAttributes_(false), - importAttributesAssertSyntax_(false), sourcePragmas_(true), - throwOnAsmJSValidationFailure_(false) {} +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + explicitResourceManagement_( + JS::Prefs::experimental_explicit_resource_management()), +#endif + throwOnAsmJSValidationFailure_(false) { + } bool importAttributes() const { return importAttributes_; } PrefableCompileOptions& setImportAttributes(bool enabled) { importAttributes_ = enabled; return *this; } - bool importAttributesAssertSyntax() const { - return importAttributesAssertSyntax_; + +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + bool explicitResourceManagement() const { + return explicitResourceManagement_; } - PrefableCompileOptions& setImportAttributesAssertSyntax(bool enabled) { - importAttributesAssertSyntax_ = enabled; + PrefableCompileOptions& setExplicitResourceManagement(bool enabled) { + explicitResourceManagement_ = enabled; return *this; } +#endif // Enable/disable support for parsing '//(#@) source(Mapping)?URL=' pragmas. bool sourcePragmas() const { return sourcePragmas_; } @@ -176,9 +186,11 @@ class JS_PUBLIC_API PrefableCompileOptions { void dumpWith(Printer& print) const { # define PrintFields_(Name) print(#Name, Name) PrintFields_(importAttributes_); - PrintFields_(importAttributesAssertSyntax_); PrintFields_(sourcePragmas_); PrintFields_(throwOnAsmJSValidationFailure_); +# ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + PrintFields_(explicitResourceManagement_); +# endif # undef PrintFields_ switch (asmJSOption_) { @@ -204,11 +216,16 @@ class JS_PUBLIC_API PrefableCompileOptions { private: // ==== Syntax-related options. ==== bool importAttributes_ : 1; - bool importAttributesAssertSyntax_ : 1; // The context has specified that source pragmas should be parsed. bool sourcePragmas_ : 1; +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // The context has specified that explicit resource management syntax + // should be parsed. + bool explicitResourceManagement_ : 1; +#endif + // ==== asm.js options. ==== bool throwOnAsmJSValidationFailure_ : 1; @@ -315,16 +332,6 @@ class JS_PUBLIC_API TransitiveCompileOptions { // called. There is currently no mechanism to release the data sooner. bool usePinnedBytecode = false; - // De-optimize ES module's top-level `var`s, in order to define all of them - // on the ModuleEnvironmentObject, instead of local slot. - // - // This is used for providing all global variables in Cu.import return value - // (see bug 1766761 for more details), and this is temporary solution until - // ESM-ification finishes. - // - // WARNING: This option will eventually be removed. - bool deoptimizeModuleGlobalVars = false; - PrefableCompileOptions prefableOptions_; /** @@ -390,10 +397,12 @@ class JS_PUBLIC_API TransitiveCompileOptions { } bool importAttributes() const { return prefableOptions_.importAttributes(); } - bool importAttributesAssertSyntax() const { - return prefableOptions_.importAttributesAssertSyntax(); - } bool sourcePragmas() const { return prefableOptions_.sourcePragmas(); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + bool explicitResourceManagement() const { + return prefableOptions_.explicitResourceManagement(); + } +#endif bool throwOnAsmJSValidationFailure() const { return prefableOptions_.throwOnAsmJSValidationFailure(); } @@ -435,7 +444,6 @@ class JS_PUBLIC_API TransitiveCompileOptions { PrintFields_(topLevelAwait); PrintFields_(borrowBuffer); PrintFields_(usePinnedBytecode); - PrintFields_(deoptimizeModuleGlobalVars); PrintFields_(introductionType); PrintFields_(introductionLineno); PrintFields_(introductionOffset); @@ -709,13 +717,16 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final return *this; } + void warnAboutConflictingDelazification() const; CompileOptions& setEagerDelazificationStrategy( DelazificationOption strategy) { - // forceFullParse is at the moment considered as a non-overridable strategy. - MOZ_RELEASE_ASSERT(eagerDelazificationStrategy_ != - DelazificationOption::ParseEverythingEagerly || - strategy == - DelazificationOption::ParseEverythingEagerly); + const auto PEE = DelazificationOption::ParseEverythingEagerly; + if (eagerDelazificationStrategy_ == PEE && strategy != PEE) { + // Parse Everything Eagerly cannot be replaced, do noting. + warnAboutConflictingDelazification(); + return *this; + } + eagerDelazificationStrategy_ = strategy; return *this; } @@ -746,17 +757,22 @@ class JS_PUBLIC_API InstantiateOptions { bool hideScriptFromDebugger = false; bool deferDebugMetadata = false; - InstantiateOptions() = default; + DelazificationOption eagerDelazificationStrategy_ = + DelazificationOption::OnDemandOnly; + + InstantiateOptions(); explicit InstantiateOptions(const ReadOnlyCompileOptions& options) : skipFilenameValidation(options.skipFilenameValidation_), hideScriptFromDebugger(options.hideScriptFromDebugger_), - deferDebugMetadata(options.deferDebugMetadata_) {} + deferDebugMetadata(options.deferDebugMetadata_), + eagerDelazificationStrategy_(options.eagerDelazificationStrategy()) {} void copyTo(CompileOptions& options) const { options.skipFilenameValidation_ = skipFilenameValidation; options.hideScriptFromDebugger_ = hideScriptFromDebugger; options.deferDebugMetadata_ = deferDebugMetadata; + options.setEagerDelazificationStrategy(eagerDelazificationStrategy_); } bool hideFromNewScriptInitial() const { @@ -772,6 +788,29 @@ class JS_PUBLIC_API InstantiateOptions { MOZ_ASSERT(skipFilenameValidation == false); MOZ_ASSERT(hideScriptFromDebugger == false); MOZ_ASSERT(deferDebugMetadata == false); + MOZ_ASSERT(eagerDelazificationStrategy_ == + DelazificationOption::OnDemandOnly); + } + + // Assert that all fields have values compatible with the default value. + // + // This can be used in the same way as assertDefault, in case the + // setForceFullParse() is used on the original compile options. + void assertCompatibleWithDefault() const { + MOZ_ASSERT(skipFilenameValidation == false); + MOZ_ASSERT(hideScriptFromDebugger == false); + MOZ_ASSERT(deferDebugMetadata == false); + + // The instantiation step uses the eagerDelazificationStrategy_ field + // only for TransitiveCompileOptions::populateDelazificationCache(). + // + // Both the default OnDemandOnly and + // the ParseEverythingEagerly from setForceFullParse() returns + // false, and they're are compatible. + MOZ_ASSERT(eagerDelazificationStrategy_ == + DelazificationOption::OnDemandOnly || + eagerDelazificationStrategy_ == + DelazificationOption::ParseEverythingEagerly); } #endif }; diff --git a/src/third_party/mozjs/include/js/ContextOptions.h b/src/third_party/mozjs/include/js/ContextOptions.h index 0ac79c0ec70..c619e6760b7 100644 --- a/src/third_party/mozjs/include/js/ContextOptions.h +++ b/src/third_party/mozjs/include/js/ContextOptions.h @@ -24,7 +24,6 @@ class JS_PUBLIC_API ContextOptions { ContextOptions() : wasm_(true), wasmForTrustedPrinciples_(true), - wasmVerbose_(false), wasmBaseline_(true), wasmIon_(true), testWasmAwaitTier2_(false), @@ -34,10 +33,6 @@ class JS_PUBLIC_API ContextOptions { asyncStackCaptureDebuggeeOnly_(false), throwOnDebuggeeWouldRun_(true), dumpStackOnDebuggeeWouldRun_(false), -#ifdef JS_ENABLE_SMOOSH - trackNotImplemented_(false), - trySmoosh_(false), -#endif fuzzing_(false) { } // clang-format on @@ -71,12 +66,6 @@ class JS_PUBLIC_API ContextOptions { return *this; } - bool wasmVerbose() const { return wasmVerbose_; } - ContextOptions& setWasmVerbose(bool flag) { - wasmVerbose_ = flag; - return *this; - } - bool wasmBaseline() const { return wasmBaseline_; } ContextOptions& setWasmBaseline(bool flag) { wasmBaseline_ = flag; @@ -122,14 +111,6 @@ class JS_PUBLIC_API ContextOptions { return *this; } - bool importAttributesAssertSyntax() const { - return compileOptions_.importAttributesAssertSyntax(); - } - ContextOptions& setImportAttributesAssertSyntax(bool enabled) { - compileOptions_.setImportAttributesAssertSyntax(enabled); - return *this; - } - // Override to allow disabling the eval restriction security checks for // this context. bool disableEvalSecurityChecks() const { return disableEvalSecurityChecks_; } @@ -173,24 +154,6 @@ class JS_PUBLIC_API ContextOptions { return *this; } -#ifdef JS_ENABLE_SMOOSH - // Track Number of Not Implemented Calls by writing to a file - bool trackNotImplemented() const { return trackNotImplemented_; } - ContextOptions& setTrackNotImplemented(bool flag) { - trackNotImplemented_ = flag; - return *this; - } - - // Try compiling SmooshMonkey frontend first, and fallback to C++ - // implementation when it fails. - bool trySmoosh() const { return trySmoosh_; } - ContextOptions& setTrySmoosh(bool flag) { - trySmoosh_ = flag; - return *this; - } - -#endif // JS_ENABLE_SMOOSH - bool fuzzing() const { return fuzzing_; } // Defined out-of-line because it depends on a compile-time option ContextOptions& setFuzzing(bool flag); @@ -209,7 +172,6 @@ class JS_PUBLIC_API ContextOptions { // WASM options. bool wasm_ : 1; bool wasmForTrustedPrinciples_ : 1; - bool wasmVerbose_ : 1; bool wasmBaseline_ : 1; bool wasmIon_ : 1; bool testWasmAwaitTier2_ : 1; @@ -223,10 +185,6 @@ class JS_PUBLIC_API ContextOptions { bool asyncStackCaptureDebuggeeOnly_ : 1; bool throwOnDebuggeeWouldRun_ : 1; bool dumpStackOnDebuggeeWouldRun_ : 1; -#ifdef JS_ENABLE_SMOOSH - bool trackNotImplemented_ : 1; - bool trySmoosh_ : 1; -#endif bool fuzzing_ : 1; // Compile options. diff --git a/src/third_party/mozjs/include/js/Conversions.h b/src/third_party/mozjs/include/js/Conversions.h index 63a9c5111ee..c12a6caae10 100644 --- a/src/third_party/mozjs/include/js/Conversions.h +++ b/src/third_party/mozjs/include/js/Conversions.h @@ -272,17 +272,6 @@ inline JSObject* ToObject(JSContext* cx, HandleValue v) { return js::ToObjectSlow(cx, v, false); } -#ifdef ENABLE_RECORD_TUPLE -inline JSObject* ToObjectOrGetObjectPayload(JSContext* cx, HandleValue v) { - detail::AssertArgumentsAreSane(cx, v); - - if (v.hasObjectPayload()) { - return &v.getObjectPayload(); - } - return js::ToObjectSlow(cx, v, false); -} -#endif - /** * Convert a double value to UnsignedInteger (an unsigned integral type) using * ECMAScript-style semantics (that is, in like manner to how ECMAScript's @@ -372,8 +361,9 @@ inline UnsignedInteger ToUnsignedInteger(double d) { } // Compute the congruent value in the signed range. - return (bits & mozilla::FloatingPoint::kSignBit) ? ~result + 1 - : result; + return (bits & mozilla::FloatingPoint::kSignBit) + ? UnsignedInteger(~result) + 1 + : result; } template diff --git a/src/third_party/mozjs/include/js/Debug.h b/src/third_party/mozjs/include/js/Debug.h index 837ae2a1819..6417f500a94 100644 --- a/src/third_party/mozjs/include/js/Debug.h +++ b/src/third_party/mozjs/include/js/Debug.h @@ -11,7 +11,9 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/BaseProfilerUtils.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/Vector.h" #include @@ -29,6 +31,136 @@ class Debugger; extern JS_PUBLIC_API bool JS_DefineDebuggerObject(JSContext* cx, JS::HandleObject obj); +// If the JS execution tracer is running, this will generate a +// ENTRY_KIND_LABEL_ENTER entry with the specified label. +// The consumer of the trace can then, for instance, correlate all code running +// after this entry and before the corresponding ENTRY_KIND_LABEL_LEAVE with the +// provided label. +// If the tracer is not running, this does nothing. +extern JS_PUBLIC_API void JS_TracerEnterLabelLatin1(JSContext* cx, + const char* label); +extern JS_PUBLIC_API void JS_TracerEnterLabelTwoByte(JSContext* cx, + const char16_t* label); + +extern JS_PUBLIC_API bool JS_TracerIsTracing(JSContext* cx); + +// If the JS execution tracer is running, this will generate a +// ENTRY_KIND_LABEL_LEAVE entry with the specified label. +// It is up to the consumer to decide what to do with a ENTRY_KIND_LABEL_LEAVE +// entry is encountered without a corresponding ENTRY_KIND_LABEL_ENTER. +// If the tracer is not running, this does nothing. +extern JS_PUBLIC_API void JS_TracerLeaveLabelLatin1(JSContext* cx, + const char* label); +extern JS_PUBLIC_API void JS_TracerLeaveLabelTwoByte(JSContext* cx, + const char16_t* label); + +#ifdef MOZ_EXECUTION_TRACING + +// This will begin execution tracing for the JSContext, i.e., this will begin +// recording every entrance into / exit from a function for the given context. +// The trace can be read via JS_TracerSnapshotTrace, and populates the +// ExecutionTrace struct defined below. +// +// This throws if the code coverage is active for any realm in the context. +extern JS_PUBLIC_API bool JS_TracerBeginTracing(JSContext* cx); + +// This ends execution tracing for the JSContext, discards the tracing +// buffers, and clears some caches used for tracing. JS_TracerSnapshotTrace +// should be called *before* JS_TracerEndTracing if you want to read the trace +// data for this JSContext. +extern JS_PUBLIC_API bool JS_TracerEndTracing(JSContext* cx); + +namespace JS { + +// This is populated by JS_TracerSnapshotTrace and just represent a minimal +// structure for natively representing an execution trace across a range of +// JSContexts (see below). The core of the trace is an array of events, each of +// which is a tagged union with data corresponding to that event. Events can +// also point into various tables, and store all of their string data in a +// contiguous UTF-8 stringBuffer (each string is null-terminated within the +// buffer.) +struct ExecutionTrace { + enum class EventKind : uint8_t { + FunctionEnter = 0, + FunctionLeave = 1, + LabelEnter = 2, + LabelLeave = 3, + + // NOTE: the `Error` event has no TracedEvent payload, and will always + // represent the end of the trace when encountered. + Error = 4, + }; + + enum class ImplementationType : uint8_t { + Interpreter = 0, + Baseline = 1, + Ion = 2, + Wasm = 3, + }; + + struct TracedEvent { + EventKind kind; + union { + // For FunctionEnter / FunctionLeave + struct { + ImplementationType implementation; + + // 1-origin line number of the function + uint32_t lineNumber; + + // 1-origin column of the function + uint32_t column; + + // Keys into the thread's scriptUrls HashMap. This key can be missing + // from the HashMap, although ideally that situation is rare (it is + // more likely in long running traces with *many* unique functions + // and/or scripts) + uint32_t scriptId; + + // ID to the realm that the frame was in. It's used for finding which + // frame comes from which window/page. + uint64_t realmID; + + // Keys into the thread's atoms HashMap. This key can be missing from + // the HashMap as well (see comment above scriptId) + uint32_t functionNameId; + } functionEvent; + + // For LabelEnter / LabelLeave + struct { + size_t label; // Indexes directly into the trace's stringBuffer + } labelEvent; + }; + // Milliseconds since process creation + double time; + }; + + struct TracedJSContext { + mozilla::baseprofiler::BaseProfilerThreadId id; + + // Maps ids to indices into the trace's stringBuffer + mozilla::HashMap scriptUrls; + + // Similar to scriptUrls + mozilla::HashMap atoms; + + mozilla::Vector events; + }; + + mozilla::Vector stringBuffer; + + // This will be populated with an entry for each context which had tracing + // enabled via JS_TracerBeginTracing. + mozilla::Vector contexts; +}; +} // namespace JS + +// Captures the trace for all JSContexts in the process which are currently +// tracing. +extern JS_PUBLIC_API bool JS_TracerSnapshotTrace(JS::ExecutionTrace& trace); + +#endif /* MOZ_EXECUTION_TRACING */ + namespace JS { namespace dbg { @@ -302,52 +434,6 @@ JS_PUBLIC_API bool IsDebugger(JSObject& obj); JS_PUBLIC_API bool GetDebuggeeGlobals(JSContext* cx, JSObject& dbgObj, MutableHandleObjectVector vector); -// Hooks for reporting where JavaScript execution began. -// -// Our performance tools would like to be able to label blocks of JavaScript -// execution with the function name and source location where execution began: -// the event handler, the callback, etc. -// -// Construct an instance of this class on the stack, providing a JSContext -// belonging to the runtime in which execution will occur. Each time we enter -// JavaScript --- specifically, each time we push a JavaScript stack frame that -// has no older JS frames younger than this AutoEntryMonitor --- we will -// call the appropriate |Entry| member function to indicate where we've begun -// execution. - -class MOZ_STACK_CLASS JS_PUBLIC_API AutoEntryMonitor { - JSContext* cx_; - AutoEntryMonitor* savedMonitor_; - - public: - explicit AutoEntryMonitor(JSContext* cx); - ~AutoEntryMonitor(); - - // SpiderMonkey reports the JavaScript entry points occuring within this - // AutoEntryMonitor's scope to the following member functions, which the - // embedding is expected to override. - // - // It is important to note that |asyncCause| is owned by the caller and its - // lifetime must outlive the lifetime of the AutoEntryMonitor object. It is - // strongly encouraged that |asyncCause| be a string constant or similar - // statically allocated string. - - // We have begun executing |function|. Note that |function| may not be the - // actual closure we are running, but only the canonical function object to - // which the script refers. - virtual void Entry(JSContext* cx, JSFunction* function, - HandleValue asyncStack, const char* asyncCause) = 0; - - // Execution has begun at the entry point of |script|, which is not a - // function body. (This is probably being executed by 'eval' or some - // JSAPI equivalent.) - virtual void Entry(JSContext* cx, JSScript* script, HandleValue asyncStack, - const char* asyncCause) = 0; - - // Execution of the function or script has ended. - virtual void Exit(JSContext* cx) {} -}; - // Returns true if there's any debugger attached to the given context where // the debugger's "shouldAvoidSideEffects" property is true. // diff --git a/src/third_party/mozjs/include/js/EnvironmentChain.h b/src/third_party/mozjs/include/js/EnvironmentChain.h new file mode 100644 index 00000000000..7d37184b521 --- /dev/null +++ b/src/third_party/mozjs/include/js/EnvironmentChain.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_EnvironmentChain_h +#define js_EnvironmentChain_h + +#include "mozilla/Attributes.h" // MOZ_RAII + +#include // size_t + +#include "jstypes.h" // JS_PUBLIC_API + +#include "js/GCVector.h" // JS::RootedVector + +struct JS_PUBLIC_API JSContext; +class JS_PUBLIC_API JSObject; + +namespace JS { + +enum class SupportUnscopables : bool { No = false, Yes = true }; + +/** + * JS::EnvironmentChain stores a list of objects to put on the environment + * chain. + * + * Internally the engine will create a non-syntactic 'with' environment for each + * of these objects. Note that 'with' environments aren't optimized well so you + * should use this class only if you really have to. + * + * The SupportUnscopables enum class controls whether these non-syntactic 'with' + * environments support Symbol.unscopables similar to syntactic 'with' + * statements in JS. + * + * Passing SupportUnscopables::No is better for performance because it lets us + * skip the Symbol.unscopables property lookup. Some Web APIs require supporting + * Symbol.unscopables though. In Firefox, SupportUnscopables::Yes is used for + * event handlers. + */ +class MOZ_RAII JS_PUBLIC_API EnvironmentChain { + JS::RootedObjectVector chain_; + SupportUnscopables supportUnscopables_; + + public: + EnvironmentChain(JSContext* cx, SupportUnscopables supportUnscopables) + : chain_(cx), supportUnscopables_(supportUnscopables) {} + + EnvironmentChain(const EnvironmentChain&) = delete; + void operator=(const EnvironmentChain&) = delete; + + [[nodiscard]] bool append(JSObject* obj) { return chain_.append(obj); } + bool empty() const { return chain_.empty(); } + size_t length() const { return chain_.length(); } + + RootedObjectVector& chain() { return chain_; } + const RootedObjectVector& chain() const { return chain_; } + + void setSupportUnscopables(SupportUnscopables supportUnscopables) { + supportUnscopables_ = supportUnscopables; + } + SupportUnscopables supportUnscopables() const { return supportUnscopables_; } +}; + +} // namespace JS + +#endif /* js_EnvironmentChain_h */ diff --git a/src/third_party/mozjs/include/js/ErrorReport.h b/src/third_party/mozjs/include/js/ErrorReport.h index 9bf824dea26..4975cdf8692 100644 --- a/src/third_party/mozjs/include/js/ErrorReport.h +++ b/src/third_party/mozjs/include/js/ErrorReport.h @@ -62,24 +62,40 @@ enum ErrorArgumentsType { * using the generalized error reporting mechanism. (One side effect of this * type is to not prepend 'Error:' to warning messages.) This value can go away * if we ever decide to use an entirely separate mechanism for warnings. + * + * The errors and warnings are arranged in alphabetically within their + * respective categories as defined in the comments below. */ enum JSExnType { + // Generic Errors JSEXN_ERR, JSEXN_FIRST = JSEXN_ERR, + // Internal Errors JSEXN_INTERNALERR, + // ECMAScript Errors JSEXN_AGGREGATEERR, JSEXN_EVALERR, JSEXN_RANGEERR, JSEXN_REFERENCEERR, +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + JSEXN_SUPPRESSEDERR, +#endif JSEXN_SYNTAXERR, JSEXN_TYPEERR, JSEXN_URIERR, + // Debugger Errors JSEXN_DEBUGGEEWOULDRUN, + // WASM Errors JSEXN_WASMCOMPILEERROR, JSEXN_WASMLINKERROR, JSEXN_WASMRUNTIMEERROR, +#ifdef ENABLE_WASM_JSPI + JSEXN_WASMSUSPENDERROR, +#endif JSEXN_ERROR_LIMIT, + // Warnings JSEXN_WARN = JSEXN_ERROR_LIMIT, + // Error Notes JSEXN_NOTE, JSEXN_LIMIT }; @@ -540,6 +556,20 @@ extern JS_PUBLIC_API bool CreateError( JSErrorReport* report, HandleString message, Handle> cause, MutableHandleValue rval); +/** + * An uncatchable exception is used to terminate execution by returning false + * or nullptr without reporting a pending exception on the context. These + * exceptions are called "uncatchable" because try-catch can't be used to catch + * them. + * + * This is mainly used to terminate JS execution from the interrupt handler. + * + * If the context has a pending exception, this function will clear it. Also, in + * debug builds, it sets a flag on the context to improve exception handling + * assertions in the engine. + */ +extern JS_PUBLIC_API void ReportUncatchableException(JSContext* cx); + } /* namespace JS */ #endif /* js_ErrorReport_h */ diff --git a/src/third_party/mozjs/include/js/GCAPI.h b/src/third_party/mozjs/include/js/GCAPI.h index fcaeb7262ed..1d3a33f63d1 100644 --- a/src/third_party/mozjs/include/js/GCAPI.h +++ b/src/third_party/mozjs/include/js/GCAPI.h @@ -28,7 +28,6 @@ namespace js { namespace gc { class GCRuntime; } // namespace gc -class JS_PUBLIC_API SliceBudget; namespace gcstats { struct Statistics; } // namespace gcstats @@ -36,6 +35,8 @@ struct Statistics; namespace JS { +class JS_PUBLIC_API SliceBudget; + // Options used when starting a GC. enum class GCOptions : uint32_t { // Normal GC invocation. @@ -261,14 +262,6 @@ typedef enum JSGCParamKey { */ JSGC_MIN_EMPTY_CHUNK_COUNT = 21, - /** - * We never keep more than this many unused chunks in the free chunk pool. - * - * Pref: javascript.options.mem.gc_max_empty_chunk_count - * Default: MaxEmptyChunkCount - */ - JSGC_MAX_EMPTY_CHUNK_COUNT = 22, - /** * Whether compacting GC is enabled. * @@ -488,6 +481,33 @@ typedef enum JSGCParamKey { */ JSGC_SLICE_NUMBER = 54, + /** + * Whether the nursery is enabled. + * + * Pref: javascript.options.mem.gc_generational + * Default: true + */ + JSGC_NURSERY_ENABLED = 55, + + /* + * Whether we are in high frequency GC mode, where the time between + * collections is less than that specified by JSGC_HIGH_FREQUENCY_TIME_LIMIT. + */ + JSGC_HIGH_FREQUENCY_MODE = 56, + + /** + * The engine attempts to keep nursery collection time less than this limit by + * restricting the size of the nursery. + * + * This only happens in optimized builds. It does not happen during pageload + * (as indicated by js::gc::SetPerformanceHint). + * + * Setting this to zero disables this feature. + * + * Default: 4 + * Pref: javascript.options.mem.nursery_max_time_goal_ms + */ + JSGC_NURSERY_MAX_TIME_GOAL_MS = 57, } JSGCParamKey; /* @@ -505,7 +525,7 @@ typedef void (*JSTraceDataOp)(JSTracer* trc, void* data); * While tracing this should check the budget and return false if it has been * exceeded. When passed an unlimited budget it should always return true. */ -typedef bool (*JSGrayRootsTracer)(JSTracer* trc, js::SliceBudget& budget, +typedef bool (*JSGrayRootsTracer)(JSTracer* trc, JS::SliceBudget& budget, void* data); typedef enum JSGCStatus { JSGC_BEGIN, JSGC_END } JSGCStatus; @@ -651,7 +671,7 @@ namespace JS { D(DOCSHELL, 54) \ D(HTML_PARSER, 55) \ D(DOM_TESTUTILS, 56) \ - D(PREPARE_FOR_PAGELOAD, 57) \ + D(PREPARE_FOR_PAGELOAD, LAST_FIREFOX_REASON) \ \ /* Reasons reserved for embeddings. */ \ D(RESERVED1, FIRST_RESERVED_REASON) \ @@ -666,6 +686,7 @@ namespace JS { enum class GCReason { FIRST_FIREFOX_REASON = 33, + LAST_FIREFOX_REASON = 57, FIRST_RESERVED_REASON = 90, #define MAKE_REASON(name, val) name = val, @@ -692,6 +713,18 @@ extern JS_PUBLIC_API const char* ExplainGCReason(JS::GCReason reason); */ extern JS_PUBLIC_API bool InternalGCReason(JS::GCReason reason); +/** + * Get a statically allocated C string explaining the given Abort reason. + * Input is the integral value of the enum. + */ +extern JS_PUBLIC_API const char* ExplainGCAbortReason(uint32_t reason); + +/** + * Get a statically allocated C string describing the Phase. + * Input is the integral value of the enum. + */ +extern JS_PUBLIC_API const char* GetGCPhaseName(uint32_t phase); + /* * Zone GC: * @@ -778,7 +811,7 @@ extern JS_PUBLIC_API void NonIncrementalGC(JSContext* cx, JS::GCOptions options, extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx, JS::GCOptions options, GCReason reason, - const js::SliceBudget& budget); + const JS::SliceBudget& budget); /** * Perform a slice of an ongoing incremental collection. When this function @@ -789,7 +822,7 @@ extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx, * shorter than the requested interval. */ extern JS_PUBLIC_API void IncrementalGCSlice(JSContext* cx, GCReason reason, - const js::SliceBudget& budget); + const JS::SliceBudget& budget); /** * Return whether an incremental GC has work to do on the foreground thread and @@ -957,7 +990,7 @@ typedef void (*DoCycleCollectionCallback)(JSContext* cx); extern JS_PUBLIC_API DoCycleCollectionCallback SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback); -using CreateSliceBudgetCallback = js::SliceBudget (*)(JS::GCReason reason, +using CreateSliceBudgetCallback = JS::SliceBudget (*)(JS::GCReason reason, int64_t millis); /** @@ -971,14 +1004,6 @@ using CreateSliceBudgetCallback = js::SliceBudget (*)(JS::GCReason reason, extern JS_PUBLIC_API void SetCreateGCSliceBudgetCallback( JSContext* cx, CreateSliceBudgetCallback cb); -/** - * Incremental GC defaults to enabled, but may be disabled for testing or in - * embeddings that have not yet implemented barriers on their native classes. - * There is not currently a way to re-enable incremental GC once it has been - * disabled on the runtime. - */ -extern JS_PUBLIC_API void DisableIncrementalGC(JSContext* cx); - /** * Returns true if incremental GC is enabled. Simply having incremental GC * enabled is not sufficient to ensure incremental collections are happening. diff --git a/src/third_party/mozjs/include/js/GCHashTable.h b/src/third_party/mozjs/include/js/GCHashTable.h index 5d9b0e9c771..7e71d0a5dfd 100644 --- a/src/third_party/mozjs/include/js/GCHashTable.h +++ b/src/third_party/mozjs/include/js/GCHashTable.h @@ -646,6 +646,21 @@ class WeakCache> final bool needsIncrementalBarrier() const override { return barrierTracer; } + // Steal the contents of this weak cache. + Set stealContents() { + // This operation is not currently allowed while barriers are in place + // since it doesn't make sense to steal the contents while we are + // sweeping. + MOZ_ASSERT(!barrierTracer); + + auto rval = std::move(set); + // Ensure set is in a specified (empty) state after the move + set.clear(); + + // Return set; no move to avoid invalidating NRVO. + return rval; + } + private: static bool entryNeedsSweep(JSTracer* barrierTracer, const Entry& prior) { Entry entry(prior); diff --git a/src/third_party/mozjs/include/js/GCPolicyAPI.h b/src/third_party/mozjs/include/js/GCPolicyAPI.h index ad0b0fc941b..6ec149da4fd 100644 --- a/src/third_party/mozjs/include/js/GCPolicyAPI.h +++ b/src/third_party/mozjs/include/js/GCPolicyAPI.h @@ -165,6 +165,10 @@ struct GCPolicy> { static bool traceWeak(JSTracer* trc, JS::Heap* thingp) { return !*thingp || js::gc::TraceWeakEdge(trc, thingp); } + static bool needsSweep(JSTracer* trc, const JS::Heap* thingp) { + T* thing = const_cast(thingp->unsafeAddress()); + return thing && js::gc::EdgeNeedsSweepUnbarrieredSlow(thing); + } }; // GCPolicy> forwards the contained pointer to GCPolicy. @@ -255,6 +259,36 @@ struct GCPolicy> { static bool isValid(const mozilla::Result& t) { return true; } }; +template +struct GCPolicy> { + using T = std::tuple; + static void trace(JSTracer* trc, T* tp, const char* name) { + traceFieldsFrom<0>(trc, *tp, name); + } + static bool isValid(const T& t) { return areFieldsValidFrom<0>(t); } + + private: + template + static void traceFieldsFrom(JSTracer* trc, T& tuple, const char* name) { + if constexpr (N != std::tuple_size_v) { + using F = std::tuple_element_t; + GCPolicy::trace(trc, &std::get(tuple), name); + traceFieldsFrom(trc, tuple, name); + } + } + + template + static bool areFieldsValidFrom(const T& tuple) { + if constexpr (N != std::tuple_size_v) { + using F = std::tuple_element_t; + return GCPolicy::isValid(std::get(tuple)) && + areFieldsValidFrom(tuple); + } + + return true; + } +}; + } // namespace JS #endif // GCPolicyAPI_h diff --git a/src/third_party/mozjs/include/js/GCVector.h b/src/third_party/mozjs/include/js/GCVector.h index 897acb71e74..7f62fa25619 100644 --- a/src/third_party/mozjs/include/js/GCVector.h +++ b/src/third_party/mozjs/include/js/GCVector.h @@ -160,7 +160,7 @@ class GCVector { } size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { - return vector.sizeOfIncludingThis(mallocSizeOf); + return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf); } void trace(JSTracer* trc) { diff --git a/src/third_party/mozjs/include/js/HeapAPI.h b/src/third_party/mozjs/include/js/HeapAPI.h index 1c0ce355141..6b3fd9aa0cd 100644 --- a/src/third_party/mozjs/include/js/HeapAPI.h +++ b/src/third_party/mozjs/include/js/HeapAPI.h @@ -25,8 +25,6 @@ /* These values are private to the JS engine. */ namespace js { -class NurseryDecommitTask; - JS_PUBLIC_API bool CurrentThreadCanAccessZone(JS::Zone* zone); // To prevent false sharing, some data structures are aligned to a typical cache @@ -37,7 +35,7 @@ namespace gc { class Arena; struct Cell; -class TenuredChunk; +class ArenaChunk; class StoreBuffer; class TenuredCell; @@ -53,6 +51,7 @@ const size_t PageShift = 12; // Expected page size, so we could initialze ArenasPerPage at compile-time. // The actual system page size should be queried by SystemPageSize(). const size_t PageSize = size_t(1) << PageShift; +const size_t PageMask = PageSize - 1; constexpr size_t ArenasPerPage = PageSize / ArenaSize; const size_t ChunkShift = 20; @@ -84,7 +83,8 @@ const size_t ArenaBitmapWords = HowMany(ArenaBitmapBits, JS_BITS_PER_WORD); enum class ChunkKind : uint8_t { Invalid = 0, - TenuredHeap, + TenuredArenas, + MediumBuffers, NurseryToSpace, NurseryFromSpace }; @@ -97,13 +97,13 @@ class ChunkBase { // Initialize a tenured heap chunk. explicit ChunkBase(JSRuntime* rt) { MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0); - initBaseForTenuredChunk(rt); + initBaseForArenaChunk(rt); } - void initBaseForTenuredChunk(JSRuntime* rt) { + void initBaseForArenaChunk(JSRuntime* rt) { runtime = rt; storeBuffer = nullptr; - kind = ChunkKind::TenuredHeap; + kind = ChunkKind::TenuredArenas; nurseryChunkIndex = UINT8_MAX; } @@ -113,20 +113,33 @@ class ChunkBase { runtime(rt), kind(kind), nurseryChunkIndex(chunkIndex) { - MOZ_ASSERT(kind == ChunkKind::NurseryFromSpace || - kind == ChunkKind::NurseryToSpace); + MOZ_ASSERT(isNurseryChunk()); MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0); MOZ_ASSERT(storeBuffer); } + ChunkBase(JSRuntime* rt, ChunkKind kind) + : storeBuffer(nullptr), + runtime(rt), + kind(kind), + nurseryChunkIndex(UINT8_MAX) {} + public: ChunkKind getKind() const { - MOZ_ASSERT_IF(storeBuffer, kind == ChunkKind::NurseryToSpace || - kind == ChunkKind::NurseryFromSpace); - MOZ_ASSERT_IF(!storeBuffer, kind == ChunkKind::TenuredHeap); + MOZ_ASSERT_IF(storeBuffer, isNurseryChunk()); + MOZ_ASSERT_IF(!storeBuffer, isTenuredChunk()); return kind; } + bool isNurseryChunk() const { + return kind == ChunkKind::NurseryToSpace || + kind == ChunkKind::NurseryFromSpace; + } + + bool isTenuredChunk() const { + return kind == ChunkKind::TenuredArenas || kind == ChunkKind::MediumBuffers; + } + // The store buffer for pointers from tenured things to things in this // chunk. Will be non-null if and only if this is a nursery chunk. StoreBuffer* storeBuffer; @@ -139,12 +152,12 @@ class ChunkBase { uint8_t nurseryChunkIndex; }; -// Information about tenured heap chunks. -struct TenuredChunkInfo { +// Information about tenured heap chunks containing arenas. +struct ArenaChunkInfo { private: friend class ChunkPool; - TenuredChunk* next = nullptr; - TenuredChunk* prev = nullptr; + ArenaChunk* next = nullptr; + ArenaChunk* prev = nullptr; public: /* Number of free arenas, either committed or decommitted. */ @@ -152,6 +165,9 @@ struct TenuredChunkInfo { /* Number of free, committed arenas. */ uint32_t numArenasFreeCommitted; + + /* Whether this chunk is the chunk currently being allocated from. */ + bool isCurrentChunk = false; }; /* @@ -180,7 +196,7 @@ const size_t BitsPerPageWithHeaders = (ArenaSize + ArenaBitmapBytes) * ArenasPerPage * CHAR_BIT + ArenasPerPage + 1; const size_t ChunkBitsAvailable = - (ChunkSize - sizeof(ChunkBase) - sizeof(TenuredChunkInfo)) * CHAR_BIT; + (ChunkSize - sizeof(ChunkBase) - sizeof(ArenaChunkInfo)) * CHAR_BIT; const size_t PagesPerChunk = ChunkBitsAvailable / BitsPerPageWithHeaders; const size_t ArenasPerChunk = PagesPerChunk * ArenasPerPage; const size_t FreeCommittedBits = ArenasPerChunk; @@ -190,7 +206,7 @@ const size_t BitsPerArenaWithHeaders = (DecommitBits / ArenasPerChunk) + 1; const size_t CalculatedChunkSizeRequired = - sizeof(ChunkBase) + sizeof(TenuredChunkInfo) + + sizeof(ChunkBase) + sizeof(ArenaChunkInfo) + RoundUp(ArenasPerChunk * ArenaBitmapBytes, sizeof(uintptr_t)) + RoundUp(FreeCommittedBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT + RoundUp(DecommitBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT + @@ -205,10 +221,13 @@ static_assert(CalculatedChunkPadSize * CHAR_BIT < BitsPerArenaWithHeaders, static_assert(ArenasPerChunk == 252, "Do not accidentally change our heap's density."); +const size_t FirstArenaOffset = ChunkSize - ArenasPerChunk * ArenaSize; + // Mark bitmaps are atomic because they can be written by gray unmarking on the // main thread while read by sweeping on a background thread. The former does // not affect the result of the latter. using MarkBitmapWord = mozilla::Atomic; +static constexpr size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT; /* * Live objects are marked black or gray. Everything reachable from a JS root is @@ -227,30 +246,77 @@ enum class ColorBit : uint32_t { BlackBit = 0, GrayOrBlackBit = 1 }; enum class MarkColor : uint8_t { Gray = 1, Black = 2 }; // Mark bitmap for a tenured heap chunk. -struct alignas(TypicalCacheLineSize) MarkBitmap { - static constexpr size_t WordCount = ArenaBitmapWords * ArenasPerChunk; +template +class alignas(TypicalCacheLineSize) MarkBitmap { + static constexpr size_t ByteCount = + (ChunkSize - FirstThingOffset) / BytesPerMarkBit; + static constexpr size_t WordCount = HowMany(ByteCount, MarkBitmapWordBits); MarkBitmapWord bitmap[WordCount]; - inline void getMarkWordAndMask(const TenuredCell* cell, ColorBit colorBit, - MarkBitmapWord** wordp, uintptr_t* maskp); + public: + static constexpr size_t FirstThingAdjustmentBits = + FirstThingOffset / BytesPerMarkBit; + + static constexpr size_t FirstThingAdjustmentWords = + FirstThingAdjustmentBits / MarkBitmapWordBits; + + MOZ_ALWAYS_INLINE void getMarkWordAndMask(const void* cell, ColorBit colorBit, + MarkBitmapWord** wordp, + uintptr_t* maskp) { + // Note: the JIT pre-barrier trampolines inline this code. Update + // MacroAssembler::emitPreBarrierFastPath code too when making changes here! + + MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell); + + size_t offset = uintptr_t(cell) & ChunkMask; + MOZ_ASSERT(offset >= FirstThingOffset); + + const size_t bit = offset / BytesPerMarkBit + size_t(colorBit); + size_t word = bit / MarkBitmapWordBits - FirstThingAdjustmentWords; + MOZ_ASSERT(word < WordCount); + *wordp = &bitmap[word]; + *maskp = uintptr_t(1) << (bit % MarkBitmapWordBits); + } // The following are not exported and are defined in gc/Heap.h: - inline bool markBit(const TenuredCell* cell, ColorBit colorBit); - inline bool isMarkedAny(const TenuredCell* cell); - inline bool isMarkedBlack(const TenuredCell* cell); - inline bool isMarkedGray(const TenuredCell* cell); - inline bool markIfUnmarked(const TenuredCell* cell, MarkColor color); - inline bool markIfUnmarkedAtomic(const TenuredCell* cell, MarkColor color); - inline void markBlack(const TenuredCell* cell); - inline void markBlackAtomic(const TenuredCell* cell); + MOZ_ALWAYS_INLINE bool markBit(const void* cell, ColorBit colorBit) { + MarkBitmapWord* word; + uintptr_t mask; + getMarkWordAndMask(cell, colorBit, &word, &mask); + return *word & mask; + } + + MOZ_ALWAYS_INLINE bool isMarkedAny(const void* cell) { + return markBit(cell, ColorBit::BlackBit) || + markBit(cell, ColorBit::GrayOrBlackBit); + } + + MOZ_ALWAYS_INLINE bool isMarkedBlack(const void* cell) { + // Return true if BlackBit is set. + return markBit(cell, ColorBit::BlackBit); + } + + MOZ_ALWAYS_INLINE bool isMarkedGray(const void* cell) { + // Return true if GrayOrBlackBit is set and BlackBit is not set. + return !markBit(cell, ColorBit::BlackBit) && + markBit(cell, ColorBit::GrayOrBlackBit); + } + + inline bool markIfUnmarked(const void* cell, MarkColor color); + inline bool markIfUnmarkedThreadSafe(const void* cell, MarkColor color); + inline void markBlack(const void* cell); + inline void markBlackAtomic(const void* cell); inline void copyMarkBit(TenuredCell* dst, const TenuredCell* src, ColorBit colorBit); - inline void unmark(const TenuredCell* cell); + inline void unmark(const void* cell); + inline void unmarkOneBit(const void* cell, ColorBit colorBit); inline MarkBitmapWord* arenaBits(Arena* arena); + + inline void copyFrom(const MarkBitmap& other); + inline void clear(); }; -static_assert(ArenaBitmapBytes * ArenasPerChunk == sizeof(MarkBitmap), - "Ensure our MarkBitmap actually covers all arenas."); +using ChunkMarkBitmap = MarkBitmap; // Bitmap with one bit per page used for decommitted page set. using ChunkPageBitmap = mozilla::BitSet; @@ -258,21 +324,26 @@ using ChunkPageBitmap = mozilla::BitSet; // Bitmap with one bit per arena used for free committed arena set. using ChunkArenaBitmap = mozilla::BitSet; -// Base class containing data members for a tenured heap chunk. -class TenuredChunkBase : public ChunkBase { +// Base class for a tenured heap chunk containing fixed size arenas. +class ArenaChunkBase : public ChunkBase { public: - TenuredChunkInfo info; - MarkBitmap markBits; + ArenaChunkInfo info; + ChunkMarkBitmap markBits; ChunkArenaBitmap freeCommittedArenas; ChunkPageBitmap decommittedPages; protected: - explicit TenuredChunkBase(JSRuntime* runtime) : ChunkBase(runtime) { + explicit ArenaChunkBase(JSRuntime* runtime) : ChunkBase(runtime) { + static_assert(sizeof(markBits) == ArenaBitmapBytes * ArenasPerChunk, + "Ensure our MarkBitmap actually covers all arenas."); info.numArenasFree = ArenasPerChunk; } + void initAsCommitted(); void initAsDecommitted(); }; +static_assert(FirstArenaOffset == + RoundUp(sizeof(gc::ArenaChunkBase), ArenaSize)); /* * We sometimes use an index to refer to a cell in an arena. The index for a @@ -282,17 +353,8 @@ class TenuredChunkBase : public ChunkBase { const size_t ArenaCellIndexBytes = CellAlignBytes; const size_t MaxArenaCellIndex = ArenaSize / CellAlignBytes; -const size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT; - -constexpr size_t FirstArenaAdjustmentBits = - RoundUp(sizeof(gc::TenuredChunkBase), ArenaSize) / gc::CellBytesPerMarkBit; - -static_assert((FirstArenaAdjustmentBits % MarkBitmapWordBits) == 0); -constexpr size_t FirstArenaAdjustmentWords = - FirstArenaAdjustmentBits / MarkBitmapWordBits; - const size_t ChunkStoreBufferOffset = offsetof(ChunkBase, storeBuffer); -const size_t ChunkMarkBitmapOffset = offsetof(TenuredChunkBase, markBits); +const size_t ChunkMarkBitmapOffset = offsetof(ArenaChunkBase, markBits); // Hardcoded offsets into Arena class. const size_t ArenaZoneOffset = 2 * sizeof(uint32_t); @@ -428,6 +490,9 @@ class JS_PUBLIC_API GCCellPtr { return asCell(); } + bool operator==(const GCCellPtr other) const { return ptr == other.ptr; } + bool operator!=(const GCCellPtr other) const { return ptr != other.ptr; } + // Simplify checks to the kind. template >> bool is() const { @@ -518,55 +583,31 @@ void ApplyGCThingTyped(GCCellPtr thing, F&& f) { } /* namespace JS */ -// These are defined in the toplevel namespace instead of within JS so that -// they won't shadow other operator== overloads (see bug 1456512.) - -inline bool operator==(JS::GCCellPtr ptr1, JS::GCCellPtr ptr2) { - return ptr1.asCell() == ptr2.asCell(); -} - -inline bool operator!=(JS::GCCellPtr ptr1, JS::GCCellPtr ptr2) { - return !(ptr1 == ptr2); -} - namespace js { namespace gc { -/* static */ -MOZ_ALWAYS_INLINE void MarkBitmap::getMarkWordAndMask(const TenuredCell* cell, - ColorBit colorBit, - MarkBitmapWord** wordp, - uintptr_t* maskp) { - // Note: the JIT pre-barrier trampolines inline this code. Update - // MacroAssembler::emitPreBarrierFastPath code too when making changes here! - - MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell); - - size_t offset = uintptr_t(cell) & ChunkMask; - const size_t bit = offset / CellBytesPerMarkBit + size_t(colorBit); - size_t word = bit / MarkBitmapWordBits - FirstArenaAdjustmentWords; - MOZ_ASSERT(word < WordCount); - *wordp = &bitmap[word]; - *maskp = uintptr_t(1) << (bit % MarkBitmapWordBits); -} - namespace detail { -static MOZ_ALWAYS_INLINE ChunkBase* GetCellChunkBase(const Cell* cell) { - MOZ_ASSERT(cell); - auto* chunk = reinterpret_cast(uintptr_t(cell) & ~ChunkMask); +// `addr` must be an address within GC-controlled memory. Note that it cannot +// point just past GC-controlled memory. +static MOZ_ALWAYS_INLINE ChunkBase* GetGCAddressChunkBase(const void* addr) { + MOZ_ASSERT(addr); + auto* chunk = reinterpret_cast(uintptr_t(addr) & ~ChunkMask); MOZ_ASSERT(chunk->runtime); MOZ_ASSERT(chunk->kind != ChunkKind::Invalid); return chunk; } -static MOZ_ALWAYS_INLINE TenuredChunkBase* GetCellChunkBase( +static MOZ_ALWAYS_INLINE ChunkBase* GetCellChunkBase(const Cell* cell) { + return GetGCAddressChunkBase(cell); +} + +static MOZ_ALWAYS_INLINE ArenaChunkBase* GetCellChunkBase( const TenuredCell* cell) { MOZ_ASSERT(cell); - auto* chunk = - reinterpret_cast(uintptr_t(cell) & ~ChunkMask); + auto* chunk = reinterpret_cast(uintptr_t(cell) & ~ChunkMask); MOZ_ASSERT(chunk->runtime); - MOZ_ASSERT(chunk->kind == ChunkKind::TenuredHeap); + MOZ_ASSERT(chunk->kind == ChunkKind::TenuredArenas); return chunk; } @@ -580,17 +621,11 @@ static MOZ_ALWAYS_INLINE JS::Zone* GetTenuredGCThingZone(const void* ptr) { static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedBlack( const TenuredCell* cell) { - // Return true if BlackBit is set. - MOZ_ASSERT(cell); MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); - MarkBitmapWord* blackWord; - uintptr_t blackMask; - TenuredChunkBase* chunk = GetCellChunkBase(cell); - chunk->markBits.getMarkWordAndMask(cell, js::gc::ColorBit::BlackBit, - &blackWord, &blackMask); - return *blackWord & blackMask; + ArenaChunkBase* chunk = GetCellChunkBase(cell); + return chunk->markBits.isMarkedBlack(cell); } static MOZ_ALWAYS_INLINE bool NonBlackCellIsMarkedGray( @@ -601,16 +636,15 @@ static MOZ_ALWAYS_INLINE bool NonBlackCellIsMarkedGray( MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); MOZ_ASSERT(!TenuredCellIsMarkedBlack(cell)); - MarkBitmapWord* grayWord; - uintptr_t grayMask; - TenuredChunkBase* chunk = GetCellChunkBase(cell); - chunk->markBits.getMarkWordAndMask(cell, js::gc::ColorBit::GrayOrBlackBit, - &grayWord, &grayMask); - return *grayWord & grayMask; + ArenaChunkBase* chunk = GetCellChunkBase(cell); + return chunk->markBits.markBit(cell, ColorBit::GrayOrBlackBit); } static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedGray(const TenuredCell* cell) { - return !TenuredCellIsMarkedBlack(cell) && NonBlackCellIsMarkedGray(cell); + MOZ_ASSERT(cell); + MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); + ArenaChunkBase* chunk = GetCellChunkBase(cell); + return chunk->markBits.isMarkedGray(cell); } static MOZ_ALWAYS_INLINE bool CellIsMarkedGray(const Cell* cell) { @@ -631,15 +665,15 @@ extern JS_PUBLIC_API void AssertCellIsNotGray(const Cell* cell); extern JS_PUBLIC_API bool ObjectIsMarkedBlack(const JSObject* obj); #endif -MOZ_ALWAYS_INLINE bool CellHasStoreBuffer(const Cell* cell) { - return GetCellChunkBase(cell)->storeBuffer; +MOZ_ALWAYS_INLINE bool ChunkPtrHasStoreBuffer(const void* ptr) { + return GetGCAddressChunkBase(ptr)->storeBuffer; } } /* namespace detail */ MOZ_ALWAYS_INLINE bool IsInsideNursery(const Cell* cell) { MOZ_ASSERT(cell); - return detail::CellHasStoreBuffer(cell); + return detail::ChunkPtrHasStoreBuffer(cell); } MOZ_ALWAYS_INLINE bool IsInsideNursery(const TenuredCell* cell) { @@ -749,14 +783,6 @@ static MOZ_ALWAYS_INLINE bool GCThingIsMarkedGrayInCC(GCCellPtr thing) { extern JS_PUBLIC_API JS::TraceKind GCThingTraceKind(void* thing); -extern JS_PUBLIC_API void EnableNurseryStrings(JSContext* cx); - -extern JS_PUBLIC_API void DisableNurseryStrings(JSContext* cx); - -extern JS_PUBLIC_API void EnableNurseryBigInts(JSContext* cx); - -extern JS_PUBLIC_API void DisableNurseryBigInts(JSContext* cx); - /* * Returns true when writes to GC thing pointers (and reads from weak pointers) * must call an incremental barrier. This is generally only true when running @@ -860,6 +886,16 @@ static MOZ_ALWAYS_INLINE bool EdgeNeedsSweepUnbarriered(JSObject** objp) { return EdgeNeedsSweepUnbarrieredSlow(objp); } +/* + * Sample data about internally mapped memory. This includes all GC heap + * allocations (and excludes js_alloc allocations). + */ +struct ProfilerMemoryCounts { + size_t bytes = 0; + uint64_t operations = 0; +}; +JS_PUBLIC_API ProfilerMemoryCounts GetProfilerMemoryCounts(); + } // namespace gc } // namespace js diff --git a/src/third_party/mozjs/include/js/HelperThreadAPI.h b/src/third_party/mozjs/include/js/HelperThreadAPI.h index 646da69925e..36f6a341c60 100644 --- a/src/third_party/mozjs/include/js/HelperThreadAPI.h +++ b/src/third_party/mozjs/include/js/HelperThreadAPI.h @@ -32,6 +32,10 @@ extern JS_PUBLIC_API void SetHelperThreadTaskCallback( // Function to call from external thread pool to run a helper thread task. extern JS_PUBLIC_API void RunHelperThreadTask(HelperThreadTask* task); +// Function to get the name of the helper thread task. +extern JS_PUBLIC_API const char* GetHelperThreadTaskName( + HelperThreadTask* task); + } // namespace JS #endif // js_HelperThreadAPI_h diff --git a/src/third_party/mozjs/include/js/Id.h b/src/third_party/mozjs/include/js/Id.h index 087f9e61c9a..60ea2c4b49f 100644 --- a/src/third_party/mozjs/include/js/Id.h +++ b/src/third_party/mozjs/include/js/Id.h @@ -199,7 +199,7 @@ class PropertyKey { MOZ_ALWAYS_INLINE bool isAtom(JSAtom* atom) const { MOZ_ASSERT(PropertyKey::isNonIntAtom(atom)); - return isAtom() && toAtom() == atom; + return *this == NonIntAtom(atom); } MOZ_ALWAYS_INLINE JSAtom* toAtom() const { @@ -292,6 +292,15 @@ struct BarrierMethods { } return nullptr; } + static void writeBarriers(jsid* idp, jsid prev, jsid next) { + if (prev.isString()) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev.toString())); + } + if (prev.isSymbol()) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev.toSymbol())); + } + postWriteBarrier(idp, prev, next); + } static void postWriteBarrier(jsid* idp, jsid prev, jsid next) { MOZ_ASSERT_IF(next.isString(), !gc::IsInsideNursery(next.toString())); } diff --git a/src/third_party/mozjs/include/js/Initialization.h b/src/third_party/mozjs/include/js/Initialization.h index 46715b6c4f1..d8ad67e413a 100644 --- a/src/third_party/mozjs/include/js/Initialization.h +++ b/src/third_party/mozjs/include/js/Initialization.h @@ -118,7 +118,6 @@ inline bool JS_IsInitialized(void) { namespace JS { // Reference to a sequence of bytes. -// TODO: This type should be Span (Bug 1709135) using SelfHostedCache = mozilla::Span; // Callback function used to copy the SelfHosted content to memory or to disk. diff --git a/src/third_party/mozjs/include/js/JSON.h b/src/third_party/mozjs/include/js/JSON.h index feef53f755e..2cf546e9c8d 100644 --- a/src/third_party/mozjs/include/js/JSON.h +++ b/src/third_party/mozjs/include/js/JSON.h @@ -26,12 +26,19 @@ using JSONWriteCallback = bool (*)(const char16_t* buf, uint32_t len, * * In cases where JSON.stringify would return undefined, this function calls * |callback| with the string "null". + * + * If a length hint is passed, space will be reserved for at least that many + * characters. */ extern JS_PUBLIC_API bool JS_Stringify(JSContext* cx, JS::MutableHandle value, JS::Handle replacer, JS::Handle space, JSONWriteCallback callback, void* data); +extern JS_PUBLIC_API bool JS_StringifyWithLengthHint( + JSContext* cx, JS::MutableHandle value, + JS::Handle replacer, JS::Handle space, + JSONWriteCallback callback, void* data, size_t lengthHint); namespace JS { diff --git a/src/third_party/mozjs/include/js/JitCodeAPI.h b/src/third_party/mozjs/include/js/JitCodeAPI.h deleted file mode 100644 index e1cdad20836..00000000000 --- a/src/third_party/mozjs/include/js/JitCodeAPI.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* SpiderMonkey API for obtaining JitCode information. */ - -#ifndef js_JitCodeAPI_h -#define js_JitCodeAPI_h - -#include "js/AllocPolicy.h" -#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin -#include "js/Initialization.h" -#include "js/Printf.h" -#include "js/Vector.h" - -namespace JS { - -enum class JitTier { Baseline, IC, Ion, Other }; - -class JitOpcodeDictionary { - typedef js::Vector StringVector; - - public: - JitOpcodeDictionary(); - - StringVector& GetBaselineDictionary() { return baselineDictionary; } - StringVector& GetIonDictionary() { return ionDictionary; } - StringVector& GetInlineCacheDictionary() { return icDictionary; } - - private: - StringVector baselineDictionary; - StringVector icDictionary; - StringVector ionDictionary; -}; - -struct JitCodeSourceInfo { - UniqueChars filename; - uint32_t offset = 0; - - // Line number (1-origin). - uint32_t lineno = 0; - // Column number in UTF-16 code units. - JS::LimitedColumnNumberOneOrigin colno; -}; - -struct JitCodeIRInfo { - uint32_t offset = 0; - uint32_t opcode = 0; - UniqueChars str; -}; - -typedef js::Vector - SourceInfoVector; -typedef js::Vector IRInfoVector; - -struct JitCodeRecord { - UniqueChars functionName; - uint64_t code_addr = 0; - uint32_t instructionSize = 0; - JitTier tier = JitTier::Other; - - SourceInfoVector sourceInfo; - IRInfoVector irInfo; -}; - -class JitCodeIterator { - void getDataForIndex(size_t iteratorIndex); - - public: - JitCodeIterator(); - ~JitCodeIterator(); - - void operator++(int) { - iteratorIndex++; - getDataForIndex(iteratorIndex); - } - - explicit operator bool() const { return data != nullptr; } - - SourceInfoVector& sourceData() { return data->sourceInfo; } - - IRInfoVector& irData() { return data->irInfo; } - - const char* functionName() const { return data->functionName.get(); } - uint64_t code_addr() const { return data->code_addr; } - uint32_t instructionSize() { return data->instructionSize; } - JitTier jit_tier() const { return data->tier; } - - private: - JitCodeRecord* data = nullptr; - size_t iteratorIndex = 0; -}; - -} // namespace JS - -#endif /* js_JitCodeAPI_h */ diff --git a/src/third_party/mozjs/include/js/MapAndSet.h b/src/third_party/mozjs/include/js/MapAndSet.h index 754379dc820..43530bbb729 100644 --- a/src/third_party/mozjs/include/js/MapAndSet.h +++ b/src/third_party/mozjs/include/js/MapAndSet.h @@ -31,6 +31,12 @@ extern JS_PUBLIC_API bool MapHas(JSContext* cx, HandleObject obj, extern JS_PUBLIC_API bool MapSet(JSContext* cx, HandleObject obj, HandleValue key, HandleValue val); +#ifdef NIGHTLY_BUILD +extern JS_PUBLIC_API bool MapGetOrInsert(JSContext* cx, HandleObject obj, + HandleValue key, HandleValue val, + MutableHandleValue rval); +#endif // #ifdef NIGHTLY_BUILD + extern JS_PUBLIC_API bool MapDelete(JSContext* cx, HandleObject obj, HandleValue key, bool* rval); diff --git a/src/third_party/mozjs/include/js/MemoryMetrics.h b/src/third_party/mozjs/include/js/MemoryMetrics.h index 305ab1feb0a..289558992d9 100644 --- a/src/third_party/mozjs/include/js/MemoryMetrics.h +++ b/src/third_party/mozjs/include/js/MemoryMetrics.h @@ -181,18 +181,17 @@ struct InefficientNonFlatteningStringHashPolicy { namespace JS { struct ClassInfo { -#define FOR_EACH_SIZE(MACRO) \ - MACRO(Objects, GCHeapUsed, objectsGCHeap) \ - MACRO(Objects, MallocHeap, objectsMallocHeapSlots) \ - MACRO(Objects, MallocHeap, objectsMallocHeapElementsNormal) \ - MACRO(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \ - MACRO(Objects, MallocHeap, objectsMallocHeapGlobalData) \ - MACRO(Objects, MallocHeap, objectsMallocHeapGlobalVarNamesSet) \ - MACRO(Objects, MallocHeap, objectsMallocHeapMisc) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsNormal) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsShared) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsWasm) \ - MACRO(Objects, NonHeap, objectsNonHeapElementsWasmShared) \ +#define FOR_EACH_SIZE(MACRO) \ + MACRO(Objects, GCHeapUsed, objectsGCHeap) \ + MACRO(Objects, MallocHeap, objectsMallocHeapSlots) \ + MACRO(Objects, MallocHeap, objectsMallocHeapElementsNormal) \ + MACRO(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \ + MACRO(Objects, MallocHeap, objectsMallocHeapGlobalData) \ + MACRO(Objects, MallocHeap, objectsMallocHeapMisc) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsNormal) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsShared) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsWasm) \ + MACRO(Objects, NonHeap, objectsNonHeapElementsWasmShared) \ MACRO(Objects, NonHeap, objectsNonHeapCodeWasm) ClassInfo() = default; @@ -554,7 +553,8 @@ struct UnusedGCThingSizes { MACRO(Other, GCHeapUnused, bigInt) \ MACRO(Other, GCHeapUnused, jitcode) \ MACRO(Other, GCHeapUnused, scope) \ - MACRO(Other, GCHeapUnused, regExpShared) + MACRO(Other, GCHeapUnused, regExpShared) \ + MACRO(Other, GCHeapUnused, smallBuffer) UnusedGCThingSizes() = default; UnusedGCThingSizes(UnusedGCThingSizes&& other) = default; @@ -597,6 +597,9 @@ struct UnusedGCThingSizes { case JS::TraceKind::RegExpShared: regExpShared += n; break; + case JS::TraceKind::SmallBuffer: + smallBuffer += n; + break; default: MOZ_CRASH("Bad trace kind for UnusedGCThingSizes"); } @@ -625,6 +628,36 @@ struct UnusedGCThingSizes { #undef FOR_EACH_SIZE }; +struct GCBufferStats { +#define FOR_EACH_SIZE(MACRO) \ + MACRO(Other, MallocHeap, usedBytes) \ + MACRO(Other, MallocHeap, freeBytes) \ + MACRO(Other, MallocHeap, adminBytes) + + GCBufferStats() = default; + GCBufferStats(GCBufferStats&& other) = default; + + void addSizes(const GCBufferStats& other) { FOR_EACH_SIZE(ADD_OTHER_SIZE); } + + size_t totalSize() const { + size_t n = 0; + FOR_EACH_SIZE(ADD_SIZE_TO_N); + return n; + } + + void addToTabSizes(JS::TabSizes* sizes) const { + FOR_EACH_SIZE(ADD_TO_TAB_SIZES); + } + + void addToServoSizes(JS::ServoSizes* sizes) const { + FOR_EACH_SIZE(ADD_TO_SERVO_SIZES); + } + + FOR_EACH_SIZE(DECL_SIZE_ZERO); + +#undef FOR_EACH_SIZE +}; + struct ZoneStats { #define FOR_EACH_SIZE(MACRO) \ MACRO(Other, GCHeapUsed, symbolsGCHeap) \ @@ -642,6 +675,7 @@ struct ZoneStats { MACRO(Other, MallocHeap, scopesMallocHeap) \ MACRO(Other, GCHeapUsed, regExpSharedsGCHeap) \ MACRO(Other, MallocHeap, regExpSharedsMallocHeap) \ + MACRO(Other, GCHeapUsed, smallBuffersGCHeap) \ MACRO(Other, MallocHeap, zoneObject) \ MACRO(Other, MallocHeap, regexpZone) \ MACRO(Other, MallocHeap, jitZone) \ @@ -662,6 +696,7 @@ struct ZoneStats { void addSizes(const ZoneStats& other) { MOZ_ASSERT(isTotals); FOR_EACH_SIZE(ADD_OTHER_SIZE); + gcBuffers.addSizes(other.gcBuffers); unusedGCThings.addSizes(other.unusedGCThings); stringInfo.add(other.stringInfo); shapeInfo.add(other.shapeInfo); @@ -679,6 +714,7 @@ struct ZoneStats { void addToTabSizes(JS::TabSizes* sizes) const { MOZ_ASSERT(isTotals); FOR_EACH_SIZE(ADD_TO_TAB_SIZES); + gcBuffers.addToTabSizes(sizes); unusedGCThings.addToTabSizes(sizes); stringInfo.addToTabSizes(sizes); shapeInfo.addToTabSizes(sizes); @@ -687,6 +723,7 @@ struct ZoneStats { void addToServoSizes(JS::ServoSizes* sizes) const { MOZ_ASSERT(isTotals); FOR_EACH_SIZE(ADD_TO_SERVO_SIZES); + gcBuffers.addToServoSizes(sizes); unusedGCThings.addToServoSizes(sizes); stringInfo.addToServoSizes(sizes); shapeInfo.addToServoSizes(sizes); @@ -695,6 +732,8 @@ struct ZoneStats { FOR_EACH_SIZE(DECL_SIZE_ZERO); + GCBufferStats gcBuffers; + // These string measurements are initially for all strings. At the end, // if the measurement granularity is FineGrained, we subtract the // measurements of the notable script sources and move them into diff --git a/src/third_party/mozjs/include/js/Modules.h b/src/third_party/mozjs/include/js/Modules.h index 4a8d45acb07..73f8586ae8d 100644 --- a/src/third_party/mozjs/include/js/Modules.h +++ b/src/third_party/mozjs/include/js/Modules.h @@ -36,7 +36,15 @@ union Utf8Unit; namespace JS { -enum class ModuleType : uint32_t { Unknown = 0, JavaScript, JSON }; +// This enum is used to index into an array, and we assume that we have +// sequential numbers starting at zero for the unknown type. +enum class ModuleType : uint32_t { + Unknown = 0, + JavaScript, + JSON, + + Limit = JSON, +}; /** * The HostResolveImportedModule hook. @@ -179,6 +187,15 @@ extern JS_PUBLIC_API JSObject* CompileJsonModule( JSContext* cx, const ReadOnlyCompileOptions& options, SourceText& srcBuf); +/** + * Parse the given source buffer as a JSON module in the scope of the current + * global of cx and return a synthetic module record. An error is reported if a + * UTF-8 encoding error is encountered. + */ +extern JS_PUBLIC_API JSObject* CompileJsonModule( + JSContext* cx, const ReadOnlyCompileOptions& options, + SourceText& srcBuf); + /** * Set a private value associated with a source text module record. */ @@ -197,6 +214,11 @@ extern JS_PUBLIC_API void ClearModulePrivate(JSObject* module); */ extern JS_PUBLIC_API Value GetModulePrivate(JSObject* module); +/** + * Checks if the given module is a cyclic module. + */ +extern JS_PUBLIC_API bool IsCyclicModule(JSObject* module); + /* * Perform the ModuleLink operation on the given source text module record. * @@ -267,16 +289,28 @@ extern JS_PUBLIC_API void GetRequestedModuleSourcePos( JSContext* cx, Handle moduleRecord, uint32_t index, uint32_t* lineNumber, JS::ColumnNumberOneOrigin* columnNumber); +/* + * Get the module type of a requested module. + */ +extern JS_PUBLIC_API ModuleType GetRequestedModuleType( + JSContext* cx, Handle moduleRecord, uint32_t index); + /* * Get the top-level script for a module which has not yet been executed. */ extern JS_PUBLIC_API JSScript* GetModuleScript(Handle moduleRecord); extern JS_PUBLIC_API JSObject* CreateModuleRequest( - JSContext* cx, Handle specifierArg); + JSContext* cx, Handle specifierArg, ModuleType moduleType); extern JS_PUBLIC_API JSString* GetModuleRequestSpecifier( JSContext* cx, Handle moduleRequestArg); +/* + * Get the module type of the specified module request. + */ +extern JS_PUBLIC_API ModuleType +GetModuleRequestType(JSContext* cx, Handle moduleRequestArg); + /* * Get the module record for a module script. */ diff --git a/src/third_party/mozjs/include/js/NativeStackLimits.h b/src/third_party/mozjs/include/js/NativeStackLimits.h new file mode 100644 index 00000000000..8b787fa3761 --- /dev/null +++ b/src/third_party/mozjs/include/js/NativeStackLimits.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_public_NativeStackLimit_h +#define js_public_NativeStackLimit_h + +#include "mozilla/Assertions.h" // MOZ_ASSERT + +#include // size_t +#include // uint32_t, uintptr_t, UINTPTR_MAX +#include // std::move + +namespace JS { + +using NativeStackSize = size_t; + +using NativeStackBase = uintptr_t; + +using NativeStackLimit = uintptr_t; + +#if JS_STACK_GROWTH_DIRECTION > 0 +constexpr NativeStackLimit NativeStackLimitMin = 0; +constexpr NativeStackLimit NativeStackLimitMax = UINTPTR_MAX; +#else +constexpr NativeStackLimit NativeStackLimitMin = UINTPTR_MAX; +constexpr NativeStackLimit NativeStackLimitMax = 0; +#endif + +#ifdef __wasi__ +// We build with the "stack-first" wasm-ld option, so the stack grows downward +// toward zero. Let's set a limit just a bit above this so that we catch an +// overflow before a Wasm trap occurs. +constexpr NativeStackLimit WASINativeStackLimit = 1024; +#endif // __wasi__ + +inline NativeStackLimit GetNativeStackLimit(NativeStackBase base, + NativeStackSize size) { +#if JS_STACK_GROWTH_DIRECTION > 0 + MOZ_ASSERT(base <= size_t(-1) - size); + return base + size - 1; +#else // stack grows up + MOZ_ASSERT(base >= size); + return base - (size - 1); +#endif // stack grows down +} + +} // namespace JS + +#endif /* js_public_NativeStackLimit_h */ diff --git a/src/third_party/mozjs/include/js/ObjectWithStashedPointer.h b/src/third_party/mozjs/include/js/ObjectWithStashedPointer.h new file mode 100644 index 00000000000..6769c0b0f69 --- /dev/null +++ b/src/third_party/mozjs/include/js/ObjectWithStashedPointer.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_public_ObjectWithStashedPointer_h +#define js_public_ObjectWithStashedPointer_h + +#include "jstypes.h" // JS_PUBLIC_API + +#include "js/RootingAPI.h" // JS::Handle + +struct JS_PUBLIC_API JSContext; +class JS_PUBLIC_API JSObject; + +namespace JS { + +namespace detail { +using UntypedFreeFunction = void (*)(void*); + +extern JS_PUBLIC_API JSObject* NewObjectWithUntypedStashedPointer( + JSContext* cx, void* ptr, UntypedFreeFunction freeFunc); + +extern JS_PUBLIC_API void* ObjectGetUntypedStashedPointer(JSContext* cx, + JSObject* obj); +} // namespace detail + +/** + * Convenience function for creating a JS object that has an embedder C++ + * pointer stashed in it. The JS object assumes ownership of the pointer. When + * the JS object is finalized, freeFunc will be called on the pointer to free + * it. + * + * The pointer is not known to the garbage collector, and not traced. If it + * points to a GC thing, the embedder is responsible for tracing it manually. + * + * freeFunc must not call any JSAPI functions that could cause a garbage + * collection. + */ +template +inline JSObject* NewObjectWithStashedPointer(JSContext* cx, T* ptr, + F freeFunc) { + using FreeFunction = void (*)(T*); + static_assert(std::is_convertible_v, + "free function is not of a compatible type"); + return detail::NewObjectWithUntypedStashedPointer( + cx, ptr, + reinterpret_cast( + static_cast(freeFunc))); +} + +/** + * As above, but without a free function for the pointer. + */ +template +inline JSObject* NewObjectWithStashedPointer(JSContext* cx, T* ptr) { + return detail::NewObjectWithUntypedStashedPointer(cx, ptr, nullptr); +} + +/** + * Retrieve the stashed pointer from an object created using + * NewObjectWithStashedPointer(). + */ +template +inline T* ObjectGetStashedPointer(JSContext* cx, JSObject* obj) { + return static_cast(detail::ObjectGetUntypedStashedPointer(cx, obj)); +} + +} // namespace JS + +#endif // js_public_ObjectWithStashedPointer_h diff --git a/src/third_party/mozjs/include/js/Prefs.h b/src/third_party/mozjs/include/js/Prefs.h index 60d67ff7cd9..2de11337c9c 100644 --- a/src/third_party/mozjs/include/js/Prefs.h +++ b/src/third_party/mozjs/include/js/Prefs.h @@ -121,26 +121,6 @@ class Prefs { }; -/** - * Specification for whether weak refs should be enabled and if so whether the - * FinalizationRegistry.cleanupSome method should be present. - */ -enum class WeakRefSpecifier { - Disabled, - EnabledWithCleanupSome, - EnabledWithoutCleanupSome -}; - -inline WeakRefSpecifier GetWeakRefsEnabled() { - if (!Prefs::weakrefs()) { - return WeakRefSpecifier::Disabled; - } - if (Prefs::experimental_weakrefs_expose_cleanupSome()) { - return WeakRefSpecifier::EnabledWithCleanupSome; - } - return WeakRefSpecifier::EnabledWithoutCleanupSome; -} - }; // namespace JS #endif /* js_Prefs_h */ diff --git a/src/third_party/mozjs/include/js/PrefsGenerated.h b/src/third_party/mozjs/include/js/PrefsGenerated.h index e9ec5de6d19..2a8dc429733 100644 --- a/src/third_party/mozjs/include/js/PrefsGenerated.h +++ b/src/third_party/mozjs/include/js/PrefsGenerated.h @@ -12,129 +12,237 @@ #include #define JS_PREF_CLASS_FIELDS \ - static bool array_grouping_;\ - static bool arraybuffer_transfer_;\ - static bool destructuring_fuse_;\ - static bool experimental_arraybuffer_resizable_;\ - static bool experimental_new_set_methods_;\ + static bool atomics_wait_async_;\ + static mozilla::Atomic dom_alloc_site_;\ + static bool experimental_atomics_pause_;\ + static mozilla::Atomic experimental_dictionary_teleporting_;\ + static mozilla::Atomic experimental_error_capture_stack_trace_;\ + static mozilla::Atomic experimental_error_iserror_;\ + static mozilla::Atomic experimental_import_attributes_;\ + static mozilla::Atomic experimental_json_parse_with_source_;\ + static bool experimental_math_sumprecise_;\ + static bool experimental_promise_try_;\ + static bool experimental_regexp_duplicate_named_groups_;\ + static bool experimental_regexp_modifiers_;\ + static bool experimental_self_hosted_cache_;\ static mozilla::Atomic experimental_shadow_realms_;\ - static bool experimental_sharedarraybuffer_growable_;\ + static bool experimental_temporal_;\ + static bool experimental_uint8array_base64_;\ static bool experimental_weakrefs_expose_cleanupSome_;\ + static uint32_t ion_regalloc_;\ static bool property_error_message_fix_;\ static bool site_based_pretenuring_;\ static mozilla::Atomic tests_uint32_pref_;\ - static bool use_emulates_undefined_fuse_;\ static mozilla::Atomic use_fdlibm_for_sin_cos_tan_;\ - static bool wasm_branch_hinting_;\ + static mozilla::Atomic warn_asmjs_deprecation_;\ + static mozilla::Atomic wasm_branch_hinting_;\ + static mozilla::Atomic wasm_call_ref_inlining_;\ + static mozilla::Atomic wasm_call_ref_inlining_percent_;\ + static mozilla::Atomic wasm_direct_inlining_;\ + static bool wasm_disable_huge_memory_;\ static bool wasm_exnref_;\ - static bool wasm_gc_;\ - static bool wasm_js_promise_integration_;\ - static bool wasm_js_string_builtins_;\ - static bool wasm_memory64_;\ - static bool wasm_memory_control_;\ + static mozilla::Atomic wasm_gc_;\ + static mozilla::Atomic wasm_inlining_level_;\ + static mozilla::Atomic wasm_js_promise_integration_;\ + static mozilla::Atomic wasm_js_string_builtins_;\ + static mozilla::Atomic wasm_lazy_tiering_;\ + static mozilla::Atomic wasm_lazy_tiering_for_gc_;\ + static mozilla::Atomic wasm_lazy_tiering_level_;\ + static mozilla::Atomic wasm_lazy_tiering_synchronous_;\ + static mozilla::Atomic wasm_memory64_;\ + static mozilla::Atomic wasm_memory_control_;\ static bool wasm_moz_intgemm_;\ - static bool wasm_multi_memory_;\ - static bool wasm_relaxed_simd_;\ - static bool wasm_tail_calls_;\ - static bool wasm_test_serialization_;\ - static bool weakrefs_;\ - static bool well_formed_unicode_strings_;\ + static mozilla::Atomic wasm_multi_memory_;\ + static mozilla::Atomic wasm_relaxed_simd_;\ + static mozilla::Atomic wasm_tail_calls_;\ + static mozilla::Atomic wasm_test_serialization_;\ + static mozilla::Atomic wasm_trace_api_;\ + static mozilla::Atomic wasm_unroll_factor_;\ + static mozilla::Atomic wasm_unroll_loops_;\ #define JS_PREF_CLASS_FIELDS_INIT \ - bool JS::Prefs::array_grouping_{true};\ - bool JS::Prefs::arraybuffer_transfer_{true};\ - bool JS::Prefs::destructuring_fuse_{true};\ - bool JS::Prefs::experimental_arraybuffer_resizable_{true};\ - bool JS::Prefs::experimental_new_set_methods_{true};\ + bool JS::Prefs::atomics_wait_async_{false};\ + mozilla::Atomic JS::Prefs::dom_alloc_site_{true};\ + bool JS::Prefs::experimental_atomics_pause_{true};\ + mozilla::Atomic JS::Prefs::experimental_dictionary_teleporting_{true};\ + mozilla::Atomic JS::Prefs::experimental_error_capture_stack_trace_{true};\ + mozilla::Atomic JS::Prefs::experimental_error_iserror_{true};\ + mozilla::Atomic JS::Prefs::experimental_import_attributes_{true};\ + mozilla::Atomic JS::Prefs::experimental_json_parse_with_source_{true};\ + bool JS::Prefs::experimental_math_sumprecise_{true};\ + bool JS::Prefs::experimental_promise_try_{true};\ + bool JS::Prefs::experimental_regexp_duplicate_named_groups_{true};\ + bool JS::Prefs::experimental_regexp_modifiers_{true};\ + bool JS::Prefs::experimental_self_hosted_cache_{false};\ mozilla::Atomic JS::Prefs::experimental_shadow_realms_{false};\ - bool JS::Prefs::experimental_sharedarraybuffer_growable_{true};\ + bool JS::Prefs::experimental_temporal_{true};\ + bool JS::Prefs::experimental_uint8array_base64_{true};\ bool JS::Prefs::experimental_weakrefs_expose_cleanupSome_{false};\ - bool JS::Prefs::property_error_message_fix_{false};\ + uint32_t JS::Prefs::ion_regalloc_{0};\ + bool JS::Prefs::property_error_message_fix_{true};\ bool JS::Prefs::site_based_pretenuring_{true};\ mozilla::Atomic JS::Prefs::tests_uint32_pref_{1};\ - bool JS::Prefs::use_emulates_undefined_fuse_{true};\ - mozilla::Atomic JS::Prefs::use_fdlibm_for_sin_cos_tan_{false};\ - bool JS::Prefs::wasm_branch_hinting_{false};\ - bool JS::Prefs::wasm_exnref_{false};\ - bool JS::Prefs::wasm_gc_{true};\ - bool JS::Prefs::wasm_js_promise_integration_{false};\ - bool JS::Prefs::wasm_js_string_builtins_{false};\ - bool JS::Prefs::wasm_memory64_{false};\ - bool JS::Prefs::wasm_memory_control_{false};\ + mozilla::Atomic JS::Prefs::use_fdlibm_for_sin_cos_tan_{true};\ + mozilla::Atomic JS::Prefs::warn_asmjs_deprecation_{true};\ + mozilla::Atomic JS::Prefs::wasm_branch_hinting_{false};\ + mozilla::Atomic JS::Prefs::wasm_call_ref_inlining_{true};\ + mozilla::Atomic JS::Prefs::wasm_call_ref_inlining_percent_{40};\ + mozilla::Atomic JS::Prefs::wasm_direct_inlining_{true};\ + bool JS::Prefs::wasm_disable_huge_memory_{false};\ + bool JS::Prefs::wasm_exnref_{true};\ + mozilla::Atomic JS::Prefs::wasm_gc_{false};\ + mozilla::Atomic JS::Prefs::wasm_inlining_level_{5};\ + mozilla::Atomic JS::Prefs::wasm_js_promise_integration_{false};\ + mozilla::Atomic JS::Prefs::wasm_js_string_builtins_{true};\ + mozilla::Atomic JS::Prefs::wasm_lazy_tiering_{true};\ + mozilla::Atomic JS::Prefs::wasm_lazy_tiering_for_gc_{true};\ + mozilla::Atomic JS::Prefs::wasm_lazy_tiering_level_{5};\ + mozilla::Atomic JS::Prefs::wasm_lazy_tiering_synchronous_{false};\ + mozilla::Atomic JS::Prefs::wasm_memory64_{true};\ + mozilla::Atomic JS::Prefs::wasm_memory_control_{false};\ bool JS::Prefs::wasm_moz_intgemm_{false};\ - bool JS::Prefs::wasm_multi_memory_{true};\ - bool JS::Prefs::wasm_relaxed_simd_{false};\ - bool JS::Prefs::wasm_tail_calls_{true};\ - bool JS::Prefs::wasm_test_serialization_{false};\ - bool JS::Prefs::weakrefs_{true};\ - bool JS::Prefs::well_formed_unicode_strings_{true};\ + mozilla::Atomic JS::Prefs::wasm_multi_memory_{true};\ + mozilla::Atomic JS::Prefs::wasm_relaxed_simd_{false};\ + mozilla::Atomic JS::Prefs::wasm_tail_calls_{false};\ + mozilla::Atomic JS::Prefs::wasm_test_serialization_{false};\ + mozilla::Atomic JS::Prefs::wasm_trace_api_{false};\ + mozilla::Atomic JS::Prefs::wasm_unroll_factor_{3};\ + mozilla::Atomic JS::Prefs::wasm_unroll_loops_{false};\ #define FOR_EACH_JS_PREF(MACRO) \ - MACRO("array_grouping", array_grouping, bool, setAtStartup_array_grouping, true)\ - MACRO("arraybuffer_transfer", arraybuffer_transfer, bool, setAtStartup_arraybuffer_transfer, true)\ - MACRO("destructuring_fuse", destructuring_fuse, bool, setAtStartup_destructuring_fuse, true)\ - MACRO("experimental.arraybuffer_resizable", experimental_arraybuffer_resizable, bool, setAtStartup_experimental_arraybuffer_resizable, true)\ - MACRO("experimental.new_set_methods", experimental_new_set_methods, bool, setAtStartup_experimental_new_set_methods, true)\ + MACRO("atomics_wait_async", atomics_wait_async, bool, setAtStartup_atomics_wait_async, true)\ + MACRO("dom_alloc_site", dom_alloc_site, bool, set_dom_alloc_site, false)\ + MACRO("experimental.atomics_pause", experimental_atomics_pause, bool, setAtStartup_experimental_atomics_pause, true)\ + MACRO("experimental.dictionary_teleporting", experimental_dictionary_teleporting, bool, set_experimental_dictionary_teleporting, false)\ + MACRO("experimental.error_capture_stack_trace", experimental_error_capture_stack_trace, bool, set_experimental_error_capture_stack_trace, false)\ + MACRO("experimental.error_iserror", experimental_error_iserror, bool, set_experimental_error_iserror, false)\ + MACRO("experimental.import_attributes", experimental_import_attributes, bool, set_experimental_import_attributes, false)\ + MACRO("experimental.json_parse_with_source", experimental_json_parse_with_source, bool, set_experimental_json_parse_with_source, false)\ + MACRO("experimental.math_sumprecise", experimental_math_sumprecise, bool, setAtStartup_experimental_math_sumprecise, true)\ + MACRO("experimental.promise_try", experimental_promise_try, bool, setAtStartup_experimental_promise_try, true)\ + MACRO("experimental.regexp_duplicate_named_groups", experimental_regexp_duplicate_named_groups, bool, setAtStartup_experimental_regexp_duplicate_named_groups, true)\ + MACRO("experimental.regexp_modifiers", experimental_regexp_modifiers, bool, setAtStartup_experimental_regexp_modifiers, true)\ + MACRO("experimental.self_hosted_cache", experimental_self_hosted_cache, bool, setAtStartup_experimental_self_hosted_cache, true)\ MACRO("experimental.shadow_realms", experimental_shadow_realms, bool, set_experimental_shadow_realms, false)\ - MACRO("experimental.sharedarraybuffer_growable", experimental_sharedarraybuffer_growable, bool, setAtStartup_experimental_sharedarraybuffer_growable, true)\ + MACRO("experimental.temporal", experimental_temporal, bool, setAtStartup_experimental_temporal, true)\ + MACRO("experimental.uint8array_base64", experimental_uint8array_base64, bool, setAtStartup_experimental_uint8array_base64, true)\ MACRO("experimental.weakrefs.expose_cleanupSome", experimental_weakrefs_expose_cleanupSome, bool, setAtStartup_experimental_weakrefs_expose_cleanupSome, true)\ + MACRO("ion.regalloc", ion_regalloc, uint32_t, setAtStartup_ion_regalloc, true)\ MACRO("property_error_message_fix", property_error_message_fix, bool, setAtStartup_property_error_message_fix, true)\ MACRO("site_based_pretenuring", site_based_pretenuring, bool, setAtStartup_site_based_pretenuring, true)\ MACRO("tests.uint32-pref", tests_uint32_pref, uint32_t, set_tests_uint32_pref, false)\ - MACRO("use_emulates_undefined_fuse", use_emulates_undefined_fuse, bool, setAtStartup_use_emulates_undefined_fuse, true)\ MACRO("use_fdlibm_for_sin_cos_tan", use_fdlibm_for_sin_cos_tan, bool, set_use_fdlibm_for_sin_cos_tan, false)\ - MACRO("wasm_branch_hinting", wasm_branch_hinting, bool, setAtStartup_wasm_branch_hinting, true)\ + MACRO("warn_asmjs_deprecation", warn_asmjs_deprecation, bool, set_warn_asmjs_deprecation, false)\ + MACRO("wasm_branch_hinting", wasm_branch_hinting, bool, set_wasm_branch_hinting, false)\ + MACRO("wasm_call_ref_inlining", wasm_call_ref_inlining, bool, set_wasm_call_ref_inlining, false)\ + MACRO("wasm_call_ref_inlining_percent", wasm_call_ref_inlining_percent, uint32_t, set_wasm_call_ref_inlining_percent, false)\ + MACRO("wasm_direct_inlining", wasm_direct_inlining, bool, set_wasm_direct_inlining, false)\ + MACRO("wasm_disable_huge_memory", wasm_disable_huge_memory, bool, setAtStartup_wasm_disable_huge_memory, true)\ MACRO("wasm_exnref", wasm_exnref, bool, setAtStartup_wasm_exnref, true)\ - MACRO("wasm_gc", wasm_gc, bool, setAtStartup_wasm_gc, true)\ - MACRO("wasm_js_promise_integration", wasm_js_promise_integration, bool, setAtStartup_wasm_js_promise_integration, true)\ - MACRO("wasm_js_string_builtins", wasm_js_string_builtins, bool, setAtStartup_wasm_js_string_builtins, true)\ - MACRO("wasm_memory64", wasm_memory64, bool, setAtStartup_wasm_memory64, true)\ - MACRO("wasm_memory_control", wasm_memory_control, bool, setAtStartup_wasm_memory_control, true)\ + MACRO("wasm_gc", wasm_gc, bool, set_wasm_gc, false)\ + MACRO("wasm_inlining_level", wasm_inlining_level, uint32_t, set_wasm_inlining_level, false)\ + MACRO("wasm_js_promise_integration", wasm_js_promise_integration, bool, set_wasm_js_promise_integration, false)\ + MACRO("wasm_js_string_builtins", wasm_js_string_builtins, bool, set_wasm_js_string_builtins, false)\ + MACRO("wasm_lazy_tiering", wasm_lazy_tiering, bool, set_wasm_lazy_tiering, false)\ + MACRO("wasm_lazy_tiering_for_gc", wasm_lazy_tiering_for_gc, bool, set_wasm_lazy_tiering_for_gc, false)\ + MACRO("wasm_lazy_tiering_level", wasm_lazy_tiering_level, uint32_t, set_wasm_lazy_tiering_level, false)\ + MACRO("wasm_lazy_tiering_synchronous", wasm_lazy_tiering_synchronous, bool, set_wasm_lazy_tiering_synchronous, false)\ + MACRO("wasm_memory64", wasm_memory64, bool, set_wasm_memory64, false)\ + MACRO("wasm_memory_control", wasm_memory_control, bool, set_wasm_memory_control, false)\ MACRO("wasm_moz_intgemm", wasm_moz_intgemm, bool, setAtStartup_wasm_moz_intgemm, true)\ - MACRO("wasm_multi_memory", wasm_multi_memory, bool, setAtStartup_wasm_multi_memory, true)\ - MACRO("wasm_relaxed_simd", wasm_relaxed_simd, bool, setAtStartup_wasm_relaxed_simd, true)\ - MACRO("wasm_tail_calls", wasm_tail_calls, bool, setAtStartup_wasm_tail_calls, true)\ - MACRO("wasm_test_serialization", wasm_test_serialization, bool, setAtStartup_wasm_test_serialization, true)\ - MACRO("weakrefs", weakrefs, bool, setAtStartup_weakrefs, true)\ - MACRO("well_formed_unicode_strings", well_formed_unicode_strings, bool, setAtStartup_well_formed_unicode_strings, true)\ + MACRO("wasm_multi_memory", wasm_multi_memory, bool, set_wasm_multi_memory, false)\ + MACRO("wasm_relaxed_simd", wasm_relaxed_simd, bool, set_wasm_relaxed_simd, false)\ + MACRO("wasm_tail_calls", wasm_tail_calls, bool, set_wasm_tail_calls, false)\ + MACRO("wasm_test_serialization", wasm_test_serialization, bool, set_wasm_test_serialization, false)\ + MACRO("wasm_trace_api", wasm_trace_api, bool, set_wasm_trace_api, false)\ + MACRO("wasm_unroll_factor", wasm_unroll_factor, uint32_t, set_wasm_unroll_factor, false)\ + MACRO("wasm_unroll_loops", wasm_unroll_loops, bool, set_wasm_unroll_loops, false)\ #define SET_JS_PREFS_FROM_BROWSER_PREFS \ - JS::Prefs::setAtStartup_array_grouping(mozilla::StaticPrefs::javascript_options_array_grouping());\ - JS::Prefs::setAtStartup_arraybuffer_transfer(mozilla::StaticPrefs::javascript_options_arraybuffer_transfer());\ - JS::Prefs::setAtStartup_destructuring_fuse(mozilla::StaticPrefs::javascript_options_destructuring_fuse());\ - JS::Prefs::setAtStartup_experimental_arraybuffer_resizable(mozilla::StaticPrefs::javascript_options_experimental_arraybuffer_resizable());\ - JS::Prefs::setAtStartup_experimental_new_set_methods(mozilla::StaticPrefs::javascript_options_experimental_new_set_methods());\ + JS::Prefs::setAtStartup_atomics_wait_async(mozilla::StaticPrefs::javascript_options_atomics_wait_async());\ + JS::Prefs::set_dom_alloc_site(mozilla::StaticPrefs::javascript_options_dom_alloc_site());\ + JS::Prefs::setAtStartup_experimental_atomics_pause(mozilla::StaticPrefs::javascript_options_experimental_atomics_pause());\ + JS::Prefs::set_experimental_dictionary_teleporting(mozilla::StaticPrefs::javascript_options_experimental_dictionary_teleporting());\ + JS::Prefs::set_experimental_error_capture_stack_trace(mozilla::StaticPrefs::javascript_options_experimental_error_capture_stack_trace());\ + JS::Prefs::set_experimental_error_iserror(mozilla::StaticPrefs::javascript_options_experimental_error_iserror());\ + JS::Prefs::set_experimental_import_attributes(mozilla::StaticPrefs::javascript_options_experimental_import_attributes());\ + JS::Prefs::set_experimental_json_parse_with_source(mozilla::StaticPrefs::javascript_options_experimental_json_parse_with_source());\ + JS::Prefs::setAtStartup_experimental_math_sumprecise(mozilla::StaticPrefs::javascript_options_experimental_math_sumprecise());\ + JS::Prefs::setAtStartup_experimental_promise_try(mozilla::StaticPrefs::javascript_options_experimental_promise_try());\ + JS::Prefs::setAtStartup_experimental_regexp_duplicate_named_groups(mozilla::StaticPrefs::javascript_options_experimental_regexp_duplicate_named_groups());\ + JS::Prefs::setAtStartup_experimental_regexp_modifiers(mozilla::StaticPrefs::javascript_options_experimental_regexp_modifiers());\ + JS::Prefs::setAtStartup_experimental_self_hosted_cache(mozilla::StaticPrefs::javascript_options_experimental_self_hosted_cache());\ JS::Prefs::set_experimental_shadow_realms(mozilla::StaticPrefs::javascript_options_experimental_shadow_realms());\ - JS::Prefs::setAtStartup_experimental_sharedarraybuffer_growable(mozilla::StaticPrefs::javascript_options_experimental_sharedarraybuffer_growable());\ + JS::Prefs::setAtStartup_experimental_temporal(mozilla::StaticPrefs::javascript_options_experimental_temporal());\ + JS::Prefs::setAtStartup_experimental_uint8array_base64(mozilla::StaticPrefs::javascript_options_experimental_uint8array_base64());\ JS::Prefs::setAtStartup_experimental_weakrefs_expose_cleanupSome(mozilla::StaticPrefs::javascript_options_experimental_weakrefs_expose_cleanupSome());\ + JS::Prefs::setAtStartup_ion_regalloc(mozilla::StaticPrefs::javascript_options_ion_regalloc());\ JS::Prefs::setAtStartup_property_error_message_fix(mozilla::StaticPrefs::javascript_options_property_error_message_fix());\ JS::Prefs::setAtStartup_site_based_pretenuring(mozilla::StaticPrefs::javascript_options_site_based_pretenuring_DoNotUseDirectly());\ JS::Prefs::set_tests_uint32_pref(mozilla::StaticPrefs::javascript_options_tests_uint32_pref());\ - JS::Prefs::setAtStartup_use_emulates_undefined_fuse(mozilla::StaticPrefs::javascript_options_use_emulates_undefined_fuse_DoNotUseDirectly());\ JS::Prefs::set_use_fdlibm_for_sin_cos_tan(mozilla::StaticPrefs::javascript_options_use_fdlibm_for_sin_cos_tan());\ - JS::Prefs::setAtStartup_wasm_branch_hinting(mozilla::StaticPrefs::javascript_options_wasm_branch_hinting());\ + JS::Prefs::set_warn_asmjs_deprecation(mozilla::StaticPrefs::javascript_options_warn_asmjs_deprecation());\ + JS::Prefs::set_wasm_branch_hinting(mozilla::StaticPrefs::javascript_options_wasm_branch_hinting());\ + JS::Prefs::set_wasm_call_ref_inlining(mozilla::StaticPrefs::javascript_options_wasm_call_ref_inlining());\ + JS::Prefs::set_wasm_call_ref_inlining_percent(mozilla::StaticPrefs::javascript_options_wasm_call_ref_inlining_percent());\ + JS::Prefs::set_wasm_direct_inlining(mozilla::StaticPrefs::javascript_options_wasm_direct_inlining());\ + JS::Prefs::setAtStartup_wasm_disable_huge_memory(mozilla::StaticPrefs::javascript_options_wasm_disable_huge_memory());\ JS::Prefs::setAtStartup_wasm_exnref(mozilla::StaticPrefs::javascript_options_wasm_exnref());\ - JS::Prefs::setAtStartup_wasm_gc(mozilla::StaticPrefs::javascript_options_wasm_gc());\ - JS::Prefs::setAtStartup_wasm_js_promise_integration(mozilla::StaticPrefs::javascript_options_wasm_js_promise_integration());\ - JS::Prefs::setAtStartup_wasm_js_string_builtins(mozilla::StaticPrefs::javascript_options_wasm_js_string_builtins());\ - JS::Prefs::setAtStartup_wasm_memory64(mozilla::StaticPrefs::javascript_options_wasm_memory64());\ - JS::Prefs::setAtStartup_wasm_memory_control(mozilla::StaticPrefs::javascript_options_wasm_memory_control());\ + JS::Prefs::set_wasm_gc(mozilla::StaticPrefs::javascript_options_wasm_gc());\ + JS::Prefs::set_wasm_inlining_level(mozilla::StaticPrefs::javascript_options_wasm_inlining_level());\ + JS::Prefs::set_wasm_js_promise_integration(mozilla::StaticPrefs::javascript_options_wasm_js_promise_integration());\ + JS::Prefs::set_wasm_js_string_builtins(mozilla::StaticPrefs::javascript_options_wasm_js_string_builtins());\ + JS::Prefs::set_wasm_lazy_tiering(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering());\ + JS::Prefs::set_wasm_lazy_tiering_for_gc(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering_for_gc());\ + JS::Prefs::set_wasm_lazy_tiering_level(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering_level());\ + JS::Prefs::set_wasm_lazy_tiering_synchronous(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering_synchronous());\ + JS::Prefs::set_wasm_memory64(mozilla::StaticPrefs::javascript_options_wasm_memory64());\ + JS::Prefs::set_wasm_memory_control(mozilla::StaticPrefs::javascript_options_wasm_memory_control());\ JS::Prefs::setAtStartup_wasm_moz_intgemm(mozilla::StaticPrefs::javascript_options_wasm_moz_intgemm());\ - JS::Prefs::setAtStartup_wasm_multi_memory(mozilla::StaticPrefs::javascript_options_wasm_multi_memory());\ - JS::Prefs::setAtStartup_wasm_relaxed_simd(mozilla::StaticPrefs::javascript_options_wasm_relaxed_simd());\ - JS::Prefs::setAtStartup_wasm_tail_calls(mozilla::StaticPrefs::javascript_options_wasm_tail_calls());\ - JS::Prefs::setAtStartup_wasm_test_serialization(mozilla::StaticPrefs::javascript_options_wasm_test_serialization());\ - JS::Prefs::setAtStartup_weakrefs(mozilla::StaticPrefs::javascript_options_weakrefs());\ - JS::Prefs::setAtStartup_well_formed_unicode_strings(mozilla::StaticPrefs::javascript_options_well_formed_unicode_strings());\ + JS::Prefs::set_wasm_multi_memory(mozilla::StaticPrefs::javascript_options_wasm_multi_memory());\ + JS::Prefs::set_wasm_relaxed_simd(mozilla::StaticPrefs::javascript_options_wasm_relaxed_simd());\ + JS::Prefs::set_wasm_tail_calls(mozilla::StaticPrefs::javascript_options_wasm_tail_calls());\ + JS::Prefs::set_wasm_test_serialization(mozilla::StaticPrefs::javascript_options_wasm_test_serialization());\ + JS::Prefs::set_wasm_trace_api(mozilla::StaticPrefs::javascript_options_wasm_trace_api());\ + JS::Prefs::set_wasm_unroll_factor(mozilla::StaticPrefs::javascript_options_wasm_unroll_factor());\ + JS::Prefs::set_wasm_unroll_loops(mozilla::StaticPrefs::javascript_options_wasm_unroll_loops());\ #define SET_NON_STARTUP_JS_PREFS_FROM_BROWSER_PREFS \ + JS::Prefs::set_dom_alloc_site(mozilla::StaticPrefs::javascript_options_dom_alloc_site());\ + JS::Prefs::set_experimental_dictionary_teleporting(mozilla::StaticPrefs::javascript_options_experimental_dictionary_teleporting());\ + JS::Prefs::set_experimental_error_capture_stack_trace(mozilla::StaticPrefs::javascript_options_experimental_error_capture_stack_trace());\ + JS::Prefs::set_experimental_error_iserror(mozilla::StaticPrefs::javascript_options_experimental_error_iserror());\ + JS::Prefs::set_experimental_import_attributes(mozilla::StaticPrefs::javascript_options_experimental_import_attributes());\ + JS::Prefs::set_experimental_json_parse_with_source(mozilla::StaticPrefs::javascript_options_experimental_json_parse_with_source());\ JS::Prefs::set_experimental_shadow_realms(mozilla::StaticPrefs::javascript_options_experimental_shadow_realms());\ JS::Prefs::set_tests_uint32_pref(mozilla::StaticPrefs::javascript_options_tests_uint32_pref());\ JS::Prefs::set_use_fdlibm_for_sin_cos_tan(mozilla::StaticPrefs::javascript_options_use_fdlibm_for_sin_cos_tan());\ + JS::Prefs::set_warn_asmjs_deprecation(mozilla::StaticPrefs::javascript_options_warn_asmjs_deprecation());\ + JS::Prefs::set_wasm_branch_hinting(mozilla::StaticPrefs::javascript_options_wasm_branch_hinting());\ + JS::Prefs::set_wasm_call_ref_inlining(mozilla::StaticPrefs::javascript_options_wasm_call_ref_inlining());\ + JS::Prefs::set_wasm_call_ref_inlining_percent(mozilla::StaticPrefs::javascript_options_wasm_call_ref_inlining_percent());\ + JS::Prefs::set_wasm_direct_inlining(mozilla::StaticPrefs::javascript_options_wasm_direct_inlining());\ + JS::Prefs::set_wasm_gc(mozilla::StaticPrefs::javascript_options_wasm_gc());\ + JS::Prefs::set_wasm_inlining_level(mozilla::StaticPrefs::javascript_options_wasm_inlining_level());\ + JS::Prefs::set_wasm_js_promise_integration(mozilla::StaticPrefs::javascript_options_wasm_js_promise_integration());\ + JS::Prefs::set_wasm_js_string_builtins(mozilla::StaticPrefs::javascript_options_wasm_js_string_builtins());\ + JS::Prefs::set_wasm_lazy_tiering(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering());\ + JS::Prefs::set_wasm_lazy_tiering_for_gc(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering_for_gc());\ + JS::Prefs::set_wasm_lazy_tiering_level(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering_level());\ + JS::Prefs::set_wasm_lazy_tiering_synchronous(mozilla::StaticPrefs::javascript_options_wasm_lazy_tiering_synchronous());\ + JS::Prefs::set_wasm_memory64(mozilla::StaticPrefs::javascript_options_wasm_memory64());\ + JS::Prefs::set_wasm_memory_control(mozilla::StaticPrefs::javascript_options_wasm_memory_control());\ + JS::Prefs::set_wasm_multi_memory(mozilla::StaticPrefs::javascript_options_wasm_multi_memory());\ + JS::Prefs::set_wasm_relaxed_simd(mozilla::StaticPrefs::javascript_options_wasm_relaxed_simd());\ + JS::Prefs::set_wasm_tail_calls(mozilla::StaticPrefs::javascript_options_wasm_tail_calls());\ + JS::Prefs::set_wasm_test_serialization(mozilla::StaticPrefs::javascript_options_wasm_test_serialization());\ + JS::Prefs::set_wasm_trace_api(mozilla::StaticPrefs::javascript_options_wasm_trace_api());\ + JS::Prefs::set_wasm_unroll_factor(mozilla::StaticPrefs::javascript_options_wasm_unroll_factor());\ + JS::Prefs::set_wasm_unroll_loops(mozilla::StaticPrefs::javascript_options_wasm_unroll_loops());\ diff --git a/src/third_party/mozjs/include/js/Principals.h b/src/third_party/mozjs/include/js/Principals.h index 609b1ecff68..bce823b3062 100644 --- a/src/third_party/mozjs/include/js/Principals.h +++ b/src/third_party/mozjs/include/js/Principals.h @@ -26,12 +26,21 @@ struct JSPrincipals { #ifdef JS_DEBUG /* A helper to facilitate principals debugging. */ - uint32_t debugToken; + uint32_t debugToken = 0; #endif JSPrincipals() = default; - void setDebugToken(uint32_t token) { + struct RefCount { + const int32_t value; + constexpr explicit RefCount(int32_t value) : value(value) {} + RefCount(const RefCount&) = delete; + }; + /* Initialize a JSPrincipals with the given refcount in a constexpr-compatible + * way. */ + explicit constexpr JSPrincipals(RefCount c) : refcount{c.value} {} + + void setDebugToken(int32_t token) { #ifdef JS_DEBUG debugToken = token; #endif @@ -68,23 +77,54 @@ typedef bool (*JSSubsumesOp)(JSPrincipals* first, JSPrincipals* second); namespace JS { enum class RuntimeCode { JS, WASM }; +enum class CompilationType { DirectEval, IndirectEval, Function, Undefined }; } // namespace JS /* * Used to check if a CSP instance wants to disable eval() and friends. * See JSContext::isRuntimeCodeGenEnabled() in vm/JSContext.cpp. * - * `code` is the JavaScript source code passed to eval/Function, but nullptr - * for Wasm. + * codeString, compilationType, parameterStrings, bodyString, parameterArgs, + * and bodyArg are defined in the "Dynamic Code Brand Checks" spec + * (see https://tc39.es/proposal-dynamic-code-brand-checks). * - * Returning `false` from this callback will prevent the execution/compilation - * of the code. + * An Undefined compilationType is used for cases that are not covered by that + * spec and unused parameters are null/empty. Currently, this includes Wasm + * (only check if compilation is enabled) and ShadowRealmEval (only check + * codeString). + * + * `outCanCompileStrings` is set to false if this callback prevents the + * execution/compilation of the code and to true otherwise. + * + * Return false on failure, true on success. The |outCanCompileStrings| + * parameter should not be modified in case of failure. */ -typedef bool (*JSCSPEvalChecker)(JSContext* cx, JS::RuntimeCode kind, - JS::HandleString code); +typedef bool (*JSCSPEvalChecker)( + JSContext* cx, JS::RuntimeCode kind, JS::Handle codeString, + JS::CompilationType compilationType, + JS::Handle> parameterStrings, + JS::Handle bodyString, + JS::Handle> parameterArgs, + JS::Handle bodyArg, bool* outCanCompileStrings); + +/* + * Provide a string of code from an Object argument, to be used by eval. + * See JSContext::getCodeForEval() in vm/JSContext.cpp as well as + * https://tc39.es/proposal-dynamic-code-brand-checks/#sec-hostgetcodeforeval + * + * `code` is the JavaScript object passed by the user. + * `outCode` is the JavaScript string to be actually executed, with nullptr + * meaning NO-CODE. + * + * Return false on failure, true on success. The |outCode| parameter should not + * be modified in case of failure. + */ +typedef bool (*JSCodeForEvalOp)(JSContext* cx, JS::HandleObject code, + JS::MutableHandle outCode); struct JSSecurityCallbacks { JSCSPEvalChecker contentSecurityPolicyAllows; + JSCodeForEvalOp codeForEvalGets; JSSubsumesOp subsumes; }; diff --git a/src/third_party/mozjs/include/js/Printer.h b/src/third_party/mozjs/include/js/Printer.h index 644ffa9176c..e7a651c024b 100644 --- a/src/third_party/mozjs/include/js/Printer.h +++ b/src/third_party/mozjs/include/js/Printer.h @@ -10,6 +10,7 @@ #include "mozilla/Attributes.h" #include "mozilla/glue/Debug.h" #include "mozilla/Range.h" +#include "mozilla/Vector.h" #include #include @@ -139,7 +140,7 @@ class LifoAlloc; // of chunks allocated with a LifoAlloc. class JS_PUBLIC_API GenericPrinter { protected: - bool hadOOM_; // whether reportOutOfMemory() has been called. + bool hadOOM_; // whether setPendingOutOfMemory() has been called. constexpr GenericPrinter() : hadOOM_(false) {} @@ -151,6 +152,7 @@ class JS_PUBLIC_API GenericPrinter { // still report any of the previous errors. virtual void put(const char* s, size_t len) = 0; inline void put(const char* s) { put(s, strlen(s)); } + inline void put(mozilla::Span s) { put(s.data(), s.size()); }; // Put a mozilla::Span / mozilla::Range of Latin1Char or char16_t characters // in the output. @@ -202,11 +204,11 @@ class JS_PUBLIC_API GenericPrinter { virtual size_t index() const { return 0; } // In some printers, this ensure that the content is fully written. - virtual void flush() { /* Do nothing */ - } + virtual void flush() { /* Do nothing */ } - // Report that a string operation failed to get the memory it requested. - virtual void reportOutOfMemory(); + // Set a flag that a string operation failed to get the memory it requested. + // The pending out of memory error should be handled by the consumer. + virtual void setPendingOutOfMemory(); // Return true if this Sprinter ran out of memory. virtual bool hadOutOfMemory() const { return hadOOM_; } @@ -469,7 +471,7 @@ class JS_PUBLIC_API EscapePrinter final : public GenericPrinter { } size_t index() const final { return out.index(); } void flush() final { out.flush(); } - void reportOutOfMemory() final { out.reportOutOfMemory(); } + void setPendingOutOfMemory() final { out.setPendingOutOfMemory(); } bool hadOutOfMemory() const final { return out.hadOutOfMemory(); } }; @@ -490,43 +492,118 @@ class JS_PUBLIC_API StringEscape { void convertInto(GenericPrinter& out, char16_t c); }; -// A GenericPrinter that formats everything at a nested indentation level. -class JS_PUBLIC_API IndentedPrinter final : public GenericPrinter { +class JS_PUBLIC_API WATStringEscape { + public: + bool isSafeChar(char16_t c); + void convertInto(GenericPrinter& out, char16_t c); +}; + +// A GenericPrinter that can format its output in a structured way, with nice +// formatting. +// +// Suppose you want to print wasm structs, and you want to change the +// presentation depending on the number of fields: +// +// (struct) +// (struct (field i32)) +// (struct +// (field i32) +// (field i64) +// ) +// +// All three of these can be handled identically with quite straightforward +// code: +// +// out.printf("(struct"); +// { +// StructuredPrinter::Scope _(out); +// +// for (auto field : fields) { +// out.brk(" ", "\n"); +// out.printf("(field "); +// DumpFieldType(field.type, out); +// out.printf(")"); +// } +// out.brk("", "\n"); +// +// if (fields.length() > 1) { +// out.expand(); +// } +// } +// out.printf(")"); +// +// The `brk` method can be used to emit one of two "break" characters depending +// on whether the output is "expanded" or "collapsed". The decision about which +// style to emit is made later, by conditionally calling `out.expand()`. +// Additionally, the use of `StructuredPrinter::Scope` ensures that the struct +// fields are indented *if* the output is expanded. +// +// Newlines may still be printed at any time. Newlines will force the current +// scope to be expanded, along with any parent scopes. +class JS_PUBLIC_API StructuredPrinter final : public GenericPrinter { GenericPrinter& out_; - // The number of indents to insert at the beginning of each line. - uint32_t indentLevel_; + // The number of spaces to insert for each indent. - uint32_t indentAmount_; - // Whether we have seen a line ending and should insert an indent at the - // next line fragment. + int indentAmount_; bool pendingIndent_; - // Put an indent to `out_` - void putIndent(); - // Put `s` to `out_`, inserting an indent if we need to - void putWithMaybeIndent(const char* s, size_t len); + // The index of the last expanded scope (or -1 if all scopes are collapsed). + int expandedDepth_ = -1; - public: - explicit IndentedPrinter(GenericPrinter& out, uint32_t indentLevel = 0, - uint32_t indentAmount = 2) - : out_(out), - indentLevel_(indentLevel), - indentAmount_(indentAmount), - pendingIndent_(false) {} - - // Automatically insert and remove and indent for a scope - class AutoIndent { - IndentedPrinter& printer_; - - public: - explicit AutoIndent(IndentedPrinter& printer) : printer_(printer) { - printer_.setIndentLevel(printer_.indentLevel() + 1); - } - ~AutoIndent() { printer_.setIndentLevel(printer_.indentLevel() - 1); } + struct Break { + uint32_t bufferPos; + bool isCollapsed; + const char* collapsed; + const char* expanded; }; - uint32_t indentLevel() const { return indentLevel_; } - void setIndentLevel(uint32_t indentLevel) { indentLevel_ = indentLevel; } + struct ScopeInfo { + uint32_t startPos; + int indent; + }; + + // Content is buffered while in collapsed mode in case it gets expanded later. + mozilla::Vector buffer_; + // Info about break characters in the buffer. + // Cleared when the buffer is cleared. + mozilla::Vector breaks_; + // The stack of scopes maintained by the printer. + mozilla::Vector scopes_; + + int scopeDepth() { return int(scopes_.length()) - 1; } + + void putIndent(int level = -1); + void putBreak(const Break& brk); + void putWithMaybeIndent(const char* s, size_t len, int level = -1); + + public: + explicit StructuredPrinter(GenericPrinter& out, int indentAmount = 2) + : out_(out), indentAmount_(indentAmount) { + pushScope(); + } + ~StructuredPrinter() { + popScope(); + flush(); + } + + void pushScope(); + void popScope(); + + void brk(const char* collapsed, const char* expanded); + void expand(); + bool isExpanded(); + + void flush() override; + + class Scope { + StructuredPrinter& printer_; + + public: + explicit Scope(StructuredPrinter& printer) : printer_(printer) { + printer_.pushScope(); + } + ~Scope() { printer_.popScope(); } + }; virtual void put(const char* s, size_t len) override; using GenericPrinter::put; // pick up |inline void put(const char* s);| diff --git a/src/third_party/mozjs/include/js/ProfilingCategoryList.h b/src/third_party/mozjs/include/js/ProfilingCategoryList.h index 0213363f551..63e27a8f721 100644 --- a/src/third_party/mozjs/include/js/ProfilingCategoryList.h +++ b/src/third_party/mozjs/include/js/ProfilingCategoryList.h @@ -114,6 +114,9 @@ BEGIN_CATEGORY(JAVA_BLOCKED, "Blocked", "lightblue") \ SUBCATEGORY(JAVA_BLOCKED, JAVA_BLOCKED, "Other") \ END_CATEGORY \ + BEGIN_CATEGORY(MAILNEWS, "Mailnews", "brown") \ + SUBCATEGORY(MAILNEWS, MAILNEWS, "Other") \ + END_CATEGORY \ BEGIN_CATEGORY(IPC, "IPC", "lightgreen") \ SUBCATEGORY(IPC, IPC, "Other") \ END_CATEGORY \ @@ -134,6 +137,12 @@ END_CATEGORY \ BEGIN_CATEGORY(REMOTE_PROTOCOL, "Remote-Protocol", "grey") \ SUBCATEGORY(REMOTE_PROTOCOL, REMOTE_PROTOCOL, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(SANDBOX, "Sandbox", "grey") \ + SUBCATEGORY(SANDBOX, SANDBOX, "Other") \ + END_CATEGORY \ + BEGIN_CATEGORY(TELEMETRY, "Telemetry", "grey") \ + SUBCATEGORY(TELEMETRY, TELEMETRY, "Other") \ END_CATEGORY // clang-format on diff --git a/src/third_party/mozjs/include/js/ProfilingFrameIterator.h b/src/third_party/mozjs/include/js/ProfilingFrameIterator.h index bbad2b1244c..6c5bf2c717d 100644 --- a/src/third_party/mozjs/include/js/ProfilingFrameIterator.h +++ b/src/third_party/mozjs/include/js/ProfilingFrameIterator.h @@ -55,7 +55,7 @@ class MOZ_NON_PARAM JS_PUBLIC_API ProfilingFrameIterator { void* endStackAddress_ = nullptr; Kind kind_; - static const unsigned StorageSpace = 8 * sizeof(void*); + static const unsigned StorageSpace = 9 * sizeof(void*); alignas(void*) unsigned char storage_[StorageSpace]; void* storage() { return storage_; } @@ -136,6 +136,8 @@ class MOZ_NON_PARAM JS_PUBLIC_API ProfilingFrameIterator { // - is weakly monotonically increasing (may be equal for successive frames) // - will compare greater than newer native and psuedo-stack frame addresses // and less than older native and psuedo-stack frame addresses + // The exception is at the point of stack switching between the main stack + // and a suspendable one (see WebAssembly JS Promise Integration proposal). void* stackAddress() const; enum FrameKind { diff --git a/src/third_party/mozjs/include/js/ProfilingStack.h b/src/third_party/mozjs/include/js/ProfilingStack.h index b9b96c27dc1..77f635189ef 100644 --- a/src/third_party/mozjs/include/js/ProfilingStack.h +++ b/src/third_party/mozjs/include/js/ProfilingStack.h @@ -8,6 +8,8 @@ #define js_ProfilingStack_h #include "mozilla/Atomics.h" +#include "mozilla/BaseProfilerMarkersPrerequisites.h" +#include "mozilla/TimeStamp.h" #include @@ -362,9 +364,11 @@ JS_PUBLIC_API void SetContextProfilingStack(JSContext* cx, JS_PUBLIC_API void EnableContextProfilingStack(JSContext* cx, bool enabled); -JS_PUBLIC_API void RegisterContextProfilingEventMarker(JSContext* cx, - void (*fn)(const char*, - const char*)); +JS_PUBLIC_API void RegisterContextProfilingEventMarker( + JSContext* cx, + void (*mark)(mozilla::MarkerCategory, const char*, const char*), + void (*interval)(mozilla::MarkerCategory, const char*, mozilla::TimeStamp, + const char*)); } // namespace js diff --git a/src/third_party/mozjs/include/js/Promise.h b/src/third_party/mozjs/include/js/Promise.h index 75bc7fd8370..e48e621560e 100644 --- a/src/third_party/mozjs/include/js/Promise.h +++ b/src/third_party/mozjs/include/js/Promise.h @@ -36,19 +36,36 @@ class JS_PUBLIC_API JobQueue { virtual ~JobQueue() = default; /** - * Ask the embedding for the incumbent global. + * Ask the embedding for the host defined data. * - * SpiderMonkey doesn't itself have a notion of incumbent globals as defined + * This is the step 5 in + * https://html.spec.whatwg.org/multipage/webappapis.html#hostmakejobcallback + * + * SpiderMonkey doesn't itself have a notion of host defined data as defined * by the HTML spec, so we need the embedding to provide this. See * dom/script/ScriptSettings.h for details. + * + * If the embedding has the host defined data, this method should return the + * host defined data via the `data` out parameter and return `true`. + * The object in the `data` out parameter can belong to any compartment. + * If the embedding doesn't need the host defined data, this method should + * set the `data` out parameter to `nullptr` and return `true`. + * If any error happens while generating the host defined data, this method + * should set a pending exception to `cx` and return `false`. */ - virtual JSObject* getIncumbentGlobal(JSContext* cx) = 0; + virtual bool getHostDefinedData(JSContext* cx, + JS::MutableHandle data) const = 0; /** * Enqueue a reaction job `job` for `promise`, which was allocated at - * `allocationSite`. Provide `incumbentGlobal` as the incumbent global for + * `allocationSite`. Provide `hostDefineData` as the host defined data for * the reaction job's execution. * + * The `hostDefinedData` value comes from `getHostDefinedData` method. + * The object is unwrapped, and it can belong to a different compartment + * than the current compartment. It can be `nullptr` if `getHostDefinedData` + * returns `nullptr`. + * * `promise` can be null if the promise is optimized out. * `promise` is guaranteed not to be optimized out if the promise has * non-default user-interaction flag. @@ -56,7 +73,7 @@ class JS_PUBLIC_API JobQueue { virtual bool enqueuePromiseJob(JSContext* cx, JS::HandleObject promise, JS::HandleObject job, JS::HandleObject allocationSite, - JS::HandleObject incumbentGlobal) = 0; + JS::HandleObject hostDefinedData) = 0; /** * Run all jobs in the queue. Running one job may enqueue others; continue to @@ -546,27 +563,65 @@ extern JS_PUBLIC_API JSObject* GetWaitForAllPromise( * on a JSContext thread when requested via DispatchToEventLoopCallback. */ class JS_PUBLIC_API Dispatchable { - protected: - // Dispatchables are created and destroyed by SpiderMonkey. - Dispatchable() = default; + public: + // Destruction of Dispatchables is public in order to be used with + // UniquePtrs. Their destruction by SpiderMonkey is enforced by + // ReleaseFailedTask. virtual ~Dispatchable() = default; - public: // ShuttingDown indicates that SpiderMonkey should abort async tasks to // expedite shutdown. enum MaybeShuttingDown { NotShuttingDown, ShuttingDown }; // Called by the embedding after DispatchToEventLoopCallback succeeds. + // Used to correctly release the unique ptr and call the run task. + static void Run(JSContext* cx, js::UniquePtr&& task, + MaybeShuttingDown maybeShuttingDown); + + // Used to correctly release the unique ptr. Relies on the + // OffThreadRuntimePromiseState to handle cleanup via iteration over the + // live() set. + static void ReleaseFailedTask(js::UniquePtr&& task); + + protected: + // Dispatchables are created exclusively by SpiderMonkey. + Dispatchable() = default; + + // These two methods must be implemented in order to correctly handle + // success and failure cases for the task. + + // Used to execute the task, run on the owning thread. + // A subclass should override this method to + // 1) execute the task as necessary and + // 2) delete the task. virtual void run(JSContext* cx, MaybeShuttingDown maybeShuttingDown) = 0; + + // Used to transfer the task back to the runtime if the embedding, upon + // taking ownership of the task, fails to dispatch and run it. This allows + // the runtime to delete the task during shutdown. This method can be called + // from any thread. + // Typically, this will be used with a UniquePtr like so: + // auto task = myTask.release(); + // task->transferToRuntime(); + virtual void transferToRuntime() = 0; }; /** - * Callback to dispatch a JS::Dispatchable to a JSContext's thread's event loop. + * Callbacks to dispatch a JS::Dispatchable to a JSContext's thread's event + * loop. * * The DispatchToEventLoopCallback set on a particular JSContext must accept * JS::Dispatchable instances and arrange for their `run` methods to be called * eventually on the JSContext's thread. This is used for cross-thread dispatch, - * so the callback itself must be safe to call from any thread. + * so the callback itself must be safe to call from any thread. It cannot + * trigger a GC. + * + * The DelayedDispatchToEventLoopCallback in addition takes a delay, and it + * must accept JS::Dispatchable instances and arrange for their `run` methods + * to be called after the delay on the JSContext's thread. + * The embeddings must have its own timeout manager to handle the delay. + * If a timeout manager is not available for given context, it should return + * false, optionally with a warning message printed. * * If the callback returns `true`, it must eventually run the given * Dispatchable; otherwise, SpiderMonkey may leak memory or hang. @@ -577,17 +632,21 @@ class JS_PUBLIC_API Dispatchable { * all subsequently submitted runnables as well. * * To establish a DispatchToEventLoopCallback, the embedding may either call - * InitDispatchToEventLoop to provide its own, or call js::UseInternalJobQueues + * InitDispatchsToEventLoop to provide its own, or call js::UseInternalJobQueues * to select a default implementation built into SpiderMonkey. This latter * depends on the embedding to call js::RunJobs on the JavaScript thread to * process queued Dispatchables at appropriate times. */ -typedef bool (*DispatchToEventLoopCallback)(void* closure, - Dispatchable* dispatchable); +typedef bool (*DispatchToEventLoopCallback)( + void* closure, js::UniquePtr&& dispatchable); -extern JS_PUBLIC_API void InitDispatchToEventLoop( - JSContext* cx, DispatchToEventLoopCallback callback, void* closure); +typedef bool (*DelayedDispatchToEventLoopCallback)( + void* closure, js::UniquePtr&& dispatchable, uint32_t delay); + +extern JS_PUBLIC_API void InitDispatchsToEventLoop( + JSContext* cx, DispatchToEventLoopCallback callback, + DelayedDispatchToEventLoopCallback delayedCallback, void* closure); /** * When a JSRuntime is destroyed it implicitly cancels all async tasks in diff --git a/src/third_party/mozjs/include/js/PropertySpec.h b/src/third_party/mozjs/include/js/PropertySpec.h index 0c37e598fbc..91782073c95 100644 --- a/src/third_party/mozjs/include/js/PropertySpec.h +++ b/src/third_party/mozjs/include/js/PropertySpec.h @@ -452,6 +452,6 @@ struct JSFunctionSpec { #define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \ JS_FNSPEC(::JS::SymbolCode::symbol, call, info, nargs, flags, selfHostedName) #define JS_FNSPEC(name, call, info, nargs, flags, selfHostedName) \ - { JSFunctionSpec::Name(name), {call, info}, nargs, flags, selfHostedName } + {JSFunctionSpec::Name(name), {call, info}, nargs, flags, selfHostedName} #endif // js_PropertySpec_h diff --git a/src/third_party/mozjs/include/js/ProtoKey.h b/src/third_party/mozjs/include/js/ProtoKey.h index fe8a191f06e..c335d5cb0e1 100644 --- a/src/third_party/mozjs/include/js/ProtoKey.h +++ b/src/third_party/mozjs/include/js/ProtoKey.h @@ -41,12 +41,6 @@ # define IF_INTL(REAL, IMAGINARY) IMAGINARY #endif -#ifdef JS_HAS_TEMPORAL_API -# define IF_TEMPORAL(REAL, IMAGINARY) REAL -#else -# define IF_TEMPORAL(REAL, IMAGINARY) IMAGINARY -#endif - #ifdef ENABLE_WASM_TYPE_REFLECTIONS # define IF_WASM_TYPE(REAL, IMAGINARY) REAL #else @@ -65,109 +59,112 @@ # define IF_NIGHTLY(REAL, IMAGINARY) IMAGINARY #endif -#define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL, REAL_IF_TEMPORAL, \ - REAL_IF_WASM_TYPE, REAL_IF_WASM_JSPI, \ - REAL_IF_NIGHTLY) \ - IMAGINARY(Null, dummy) \ - REAL(Object, OCLASP(Plain)) \ - REAL(Function, &FunctionClass) \ - IMAGINARY(BoundFunction, OCLASP(BoundFunction)) \ - REAL(Array, OCLASP(Array)) \ - REAL(Boolean, OCLASP(Boolean)) \ - REAL(JSON, CLASP(JSON)) \ - REAL(Date, OCLASP(Date)) \ - REAL(Math, CLASP(Math)) \ - REAL(Number, OCLASP(Number)) \ - REAL(String, OCLASP(String)) \ - REAL(RegExp, OCLASP(RegExp)) \ - REAL(Error, ERROR_CLASP(JSEXN_ERR)) \ - REAL(InternalError, ERROR_CLASP(JSEXN_INTERNALERR)) \ - REAL(AggregateError, ERROR_CLASP(JSEXN_AGGREGATEERR)) \ - REAL(EvalError, ERROR_CLASP(JSEXN_EVALERR)) \ - REAL(RangeError, ERROR_CLASP(JSEXN_RANGEERR)) \ - REAL(ReferenceError, ERROR_CLASP(JSEXN_REFERENCEERR)) \ - REAL(SyntaxError, ERROR_CLASP(JSEXN_SYNTAXERR)) \ - REAL(TypeError, ERROR_CLASP(JSEXN_TYPEERR)) \ - REAL(URIError, ERROR_CLASP(JSEXN_URIERR)) \ - REAL(DebuggeeWouldRun, ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \ - REAL(CompileError, ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \ - REAL(LinkError, ERROR_CLASP(JSEXN_WASMLINKERROR)) \ - REAL(RuntimeError, ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \ - REAL(ArrayBuffer, OCLASP(FixedLengthArrayBuffer)) \ - REAL(Int8Array, TYPED_ARRAY_CLASP(Int8)) \ - REAL(Uint8Array, TYPED_ARRAY_CLASP(Uint8)) \ - REAL(Int16Array, TYPED_ARRAY_CLASP(Int16)) \ - REAL(Uint16Array, TYPED_ARRAY_CLASP(Uint16)) \ - REAL(Int32Array, TYPED_ARRAY_CLASP(Int32)) \ - REAL(Uint32Array, TYPED_ARRAY_CLASP(Uint32)) \ - REAL(Float32Array, TYPED_ARRAY_CLASP(Float32)) \ - REAL(Float64Array, TYPED_ARRAY_CLASP(Float64)) \ - REAL(Uint8ClampedArray, TYPED_ARRAY_CLASP(Uint8Clamped)) \ - REAL(BigInt64Array, TYPED_ARRAY_CLASP(BigInt64)) \ - REAL(BigUint64Array, TYPED_ARRAY_CLASP(BigUint64)) \ - REAL_IF_NIGHTLY(Float16Array, TYPED_ARRAY_CLASP(Float16)) \ - REAL(BigInt, OCLASP(BigInt)) \ - REAL(Proxy, CLASP(Proxy)) \ - REAL(WeakMap, OCLASP(WeakMap)) \ - REAL(Map, OCLASP(Map)) \ - REAL(Set, OCLASP(Set)) \ - REAL(DataView, OCLASP(FixedLengthDataView)) \ - REAL(Symbol, OCLASP(Symbol)) \ - REAL(ShadowRealm, OCLASP(ShadowRealm)) \ - REAL(SharedArrayBuffer, OCLASP(FixedLengthSharedArrayBuffer)) \ - REAL_IF_INTL(Intl, CLASP(Intl)) \ - REAL_IF_INTL(Collator, OCLASP(Collator)) \ - REAL_IF_INTL(DateTimeFormat, OCLASP(DateTimeFormat)) \ - REAL_IF_INTL(DisplayNames, OCLASP(DisplayNames)) \ - REAL_IF_INTL(ListFormat, OCLASP(ListFormat)) \ - REAL_IF_INTL(Locale, OCLASP(Locale)) \ - REAL_IF_INTL(NumberFormat, OCLASP(NumberFormat)) \ - REAL_IF_INTL(PluralRules, OCLASP(PluralRules)) \ - REAL_IF_INTL(RelativeTimeFormat, OCLASP(RelativeTimeFormat)) \ - REAL_IF_INTL(Segmenter, OCLASP(Segmenter)) \ - REAL(Reflect, CLASP(Reflect)) \ - REAL(WeakSet, OCLASP(WeakSet)) \ - REAL(TypedArray, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \ - REAL(Atomics, OCLASP(Atomics)) \ - REAL(SavedFrame, &js::SavedFrame::class_) \ - REAL(Promise, OCLASP(Promise)) \ - REAL(AsyncFunction, CLASP(AsyncFunction)) \ - REAL(GeneratorFunction, CLASP(GeneratorFunction)) \ - REAL(AsyncGeneratorFunction, CLASP(AsyncGeneratorFunction)) \ - REAL(WebAssembly, OCLASP(WasmNamespace)) \ - REAL(WasmModule, OCLASP(WasmModule)) \ - REAL(WasmInstance, OCLASP(WasmInstance)) \ - REAL(WasmMemory, OCLASP(WasmMemory)) \ - REAL(WasmTable, OCLASP(WasmTable)) \ - REAL(WasmGlobal, OCLASP(WasmGlobal)) \ - REAL(WasmTag, OCLASP(WasmTag)) \ - REAL_IF_WASM_TYPE(WasmFunction, CLASP(WasmFunction)) \ - REAL_IF_WASM_JSPI(WasmSuspending, OCLASP(WasmSuspending)) \ - REAL(WasmException, OCLASP(WasmException)) \ - REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \ - REAL(WeakRef, OCLASP(WeakRef)) \ - REAL(Iterator, OCLASP(Iterator)) \ - REAL(AsyncIterator, OCLASP(AsyncIterator)) \ - REAL_IF_TEMPORAL(Temporal, OCLASP(temporal::Temporal)) \ - REAL_IF_TEMPORAL(Calendar, OCLASP(temporal::Calendar)) \ - REAL_IF_TEMPORAL(Duration, OCLASP(temporal::Duration)) \ - REAL_IF_TEMPORAL(Instant, OCLASP(temporal::Instant)) \ - REAL_IF_TEMPORAL(PlainDate, OCLASP(temporal::PlainDate)) \ - REAL_IF_TEMPORAL(PlainDateTime, OCLASP(temporal::PlainDateTime)) \ - REAL_IF_TEMPORAL(PlainMonthDay, OCLASP(temporal::PlainMonthDay)) \ - REAL_IF_TEMPORAL(PlainYearMonth, OCLASP(temporal::PlainYearMonth)) \ - REAL_IF_TEMPORAL(PlainTime, OCLASP(temporal::PlainTime)) \ - REAL_IF_TEMPORAL(TemporalNow, OCLASP(temporal::TemporalNow)) \ - REAL_IF_TEMPORAL(TimeZone, OCLASP(temporal::TimeZone)) \ - REAL_IF_TEMPORAL(ZonedDateTime, OCLASP(temporal::ZonedDateTime)) \ - IF_RECORD_TUPLE(REAL(Record, (&RecordType::class_))) \ - IF_RECORD_TUPLE(REAL(Tuple, (&TupleType::class_))) +#define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL, REAL_IF_WASM_TYPE, \ + REAL_IF_WASM_JSPI, REAL_IF_NIGHTLY) \ + IMAGINARY(Null, dummy) \ + REAL(Object, OCLASP(Plain)) \ + REAL(Function, &FunctionClass) \ + IMAGINARY(BoundFunction, OCLASP(BoundFunction)) \ + REAL(Array, OCLASP(Array)) \ + REAL(Boolean, OCLASP(Boolean)) \ + REAL(JSON, CLASP(JSON)) \ + REAL(Date, OCLASP(Date)) \ + REAL(Math, CLASP(Math)) \ + REAL(Number, OCLASP(Number)) \ + REAL(String, OCLASP(String)) \ + REAL(RegExp, OCLASP(RegExp)) \ + REAL(Error, ERROR_CLASP(JSEXN_ERR)) \ + REAL(InternalError, ERROR_CLASP(JSEXN_INTERNALERR)) \ + REAL(AggregateError, ERROR_CLASP(JSEXN_AGGREGATEERR)) \ + REAL(EvalError, ERROR_CLASP(JSEXN_EVALERR)) \ + REAL(RangeError, ERROR_CLASP(JSEXN_RANGEERR)) \ + REAL(ReferenceError, ERROR_CLASP(JSEXN_REFERENCEERR)) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT( \ + REAL(SuppressedError, ERROR_CLASP(JSEXN_SUPPRESSEDERR))) \ + REAL(SyntaxError, ERROR_CLASP(JSEXN_SYNTAXERR)) \ + REAL(TypeError, ERROR_CLASP(JSEXN_TYPEERR)) \ + REAL(URIError, ERROR_CLASP(JSEXN_URIERR)) \ + REAL(DebuggeeWouldRun, ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \ + REAL(CompileError, ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \ + REAL(LinkError, ERROR_CLASP(JSEXN_WASMLINKERROR)) \ + REAL(RuntimeError, ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \ + REAL_IF_WASM_JSPI(SuspendError, ERROR_CLASP(JSEXN_WASMSUSPENDERROR)) \ + REAL(ArrayBuffer, OCLASP(FixedLengthArrayBuffer)) \ + REAL(Int8Array, TYPED_ARRAY_CLASP(Int8)) \ + REAL(Uint8Array, TYPED_ARRAY_CLASP(Uint8)) \ + REAL(Int16Array, TYPED_ARRAY_CLASP(Int16)) \ + REAL(Uint16Array, TYPED_ARRAY_CLASP(Uint16)) \ + REAL(Int32Array, TYPED_ARRAY_CLASP(Int32)) \ + REAL(Uint32Array, TYPED_ARRAY_CLASP(Uint32)) \ + REAL(Float32Array, TYPED_ARRAY_CLASP(Float32)) \ + REAL(Float64Array, TYPED_ARRAY_CLASP(Float64)) \ + REAL(Uint8ClampedArray, TYPED_ARRAY_CLASP(Uint8Clamped)) \ + REAL(BigInt64Array, TYPED_ARRAY_CLASP(BigInt64)) \ + REAL(BigUint64Array, TYPED_ARRAY_CLASP(BigUint64)) \ + REAL(Float16Array, TYPED_ARRAY_CLASP(Float16)) \ + REAL(BigInt, OCLASP(BigInt)) \ + REAL(Proxy, CLASP(Proxy)) \ + REAL(WeakMap, OCLASP(WeakMap)) \ + REAL(Map, OCLASP(Map)) \ + REAL(Set, OCLASP(Set)) \ + REAL(DataView, OCLASP(FixedLengthDataView)) \ + REAL(Symbol, OCLASP(Symbol)) \ + REAL(ShadowRealm, OCLASP(ShadowRealm)) \ + REAL(SharedArrayBuffer, OCLASP(FixedLengthSharedArrayBuffer)) \ + REAL_IF_INTL(Intl, CLASP(Intl)) \ + REAL_IF_INTL(Collator, OCLASP(Collator)) \ + REAL_IF_INTL(DateTimeFormat, OCLASP(DateTimeFormat)) \ + REAL_IF_INTL(DisplayNames, OCLASP(DisplayNames)) \ + REAL_IF_INTL(DurationFormat, OCLASP(DurationFormat)) \ + REAL_IF_INTL(ListFormat, OCLASP(ListFormat)) \ + REAL_IF_INTL(Locale, OCLASP(Locale)) \ + REAL_IF_INTL(NumberFormat, OCLASP(NumberFormat)) \ + REAL_IF_INTL(PluralRules, OCLASP(PluralRules)) \ + REAL_IF_INTL(RelativeTimeFormat, OCLASP(RelativeTimeFormat)) \ + REAL_IF_INTL(Segmenter, OCLASP(Segmenter)) \ + REAL(Reflect, CLASP(Reflect)) \ + REAL(WeakSet, OCLASP(WeakSet)) \ + REAL(TypedArray, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \ + REAL(Atomics, OCLASP(Atomics)) \ + REAL(SavedFrame, &js::SavedFrame::class_) \ + REAL(Promise, OCLASP(Promise)) \ + REAL(AsyncFunction, CLASP(AsyncFunction)) \ + REAL(GeneratorFunction, CLASP(GeneratorFunction)) \ + REAL(AsyncGeneratorFunction, CLASP(AsyncGeneratorFunction)) \ + REAL(WebAssembly, OCLASP(WasmNamespace)) \ + REAL(WasmModule, OCLASP(WasmModule)) \ + REAL(WasmInstance, OCLASP(WasmInstance)) \ + REAL(WasmMemory, OCLASP(WasmMemory)) \ + REAL(WasmTable, OCLASP(WasmTable)) \ + REAL(WasmGlobal, OCLASP(WasmGlobal)) \ + REAL(WasmTag, OCLASP(WasmTag)) \ + REAL_IF_WASM_TYPE(WasmFunction, CLASP(WasmFunction)) \ + REAL_IF_WASM_JSPI(WasmSuspending, OCLASP(WasmSuspending)) \ + REAL(WasmException, OCLASP(WasmException)) \ + REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \ + REAL(WeakRef, OCLASP(WeakRef)) \ + REAL(Iterator, OCLASP(Iterator)) \ + REAL(AsyncIterator, OCLASP(AsyncIterator)) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT( \ + REAL(DisposableStack, OCLASP(DisposableStack))) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT( \ + REAL(AsyncDisposableStack, OCLASP(AsyncDisposableStack))) \ + REAL_IF_INTL(Temporal, OCLASP(temporal::Temporal)) \ + REAL_IF_INTL(Duration, OCLASP(temporal::Duration)) \ + REAL_IF_INTL(Instant, OCLASP(temporal::Instant)) \ + REAL_IF_INTL(PlainDate, OCLASP(temporal::PlainDate)) \ + REAL_IF_INTL(PlainDateTime, OCLASP(temporal::PlainDateTime)) \ + REAL_IF_INTL(PlainMonthDay, OCLASP(temporal::PlainMonthDay)) \ + REAL_IF_INTL(PlainYearMonth, OCLASP(temporal::PlainYearMonth)) \ + REAL_IF_INTL(PlainTime, OCLASP(temporal::PlainTime)) \ + REAL_IF_INTL(TemporalNow, OCLASP(temporal::TemporalNow)) \ + REAL_IF_INTL(ZonedDateTime, OCLASP(temporal::ZonedDateTime)) -#define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \ - JS_FOR_PROTOTYPES_( \ - REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), IF_TEMPORAL(REAL, IMAGINARY), \ - IF_WASM_TYPE(REAL, IMAGINARY), IF_WASM_JSPI(REAL, IMAGINARY), \ - IF_NIGHTLY(REAL, IMAGINARY)) +#define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \ + JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), \ + IF_WASM_TYPE(REAL, IMAGINARY), \ + IF_WASM_JSPI(REAL, IMAGINARY), \ + IF_NIGHTLY(REAL, IMAGINARY)) #define JS_FOR_EACH_PROTOTYPE(MACRO) JS_FOR_PROTOTYPES(MACRO, MACRO) diff --git a/src/third_party/mozjs/include/js/Proxy.h b/src/third_party/mozjs/include/js/Proxy.h index 45ba4a1376f..4c50831b612 100644 --- a/src/third_party/mozjs/include/js/Proxy.h +++ b/src/third_party/mozjs/include/js/Proxy.h @@ -100,6 +100,10 @@ class JS_PUBLIC_API Wrapper; * organized in the following hierarchy: * * BaseProxyHandler + * | | + * | NurseryAllocableProxyHandler + * | // allocated in the nursery; disallows + * | // overriding finalize method * | * ForwardingProxyHandler // has a target and forwards internal methods * | @@ -378,6 +382,17 @@ class JS_PUBLIC_API BaseProxyHandler { virtual bool isScripted() const { return false; } }; +class JS_PUBLIC_API NurseryAllocableProxyHandler : public BaseProxyHandler { + using BaseProxyHandler::BaseProxyHandler; + + // Don't allow overriding the default finalize method. + void finalize(JS::GCContext* gcx, JSObject* proxy) const final { + BaseProxyHandler::finalize(gcx, proxy); + } + // Can allocate in the nursery as long as we use the default finalize method. + bool canNurseryAllocate() const override { return true; } +}; + extern JS_PUBLIC_DATA const JSClass ProxyClass; inline bool IsProxy(const JSObject* obj) { @@ -463,12 +478,12 @@ constexpr ptrdiff_t ProxyReservedSlots::offsetOfPrivateSlot() { offsetof(ProxyValueArray, privateSlot); } -// All proxies share the same data layout. Following the object's shape and -// type, the proxy has a ProxyDataLayout structure with a pointer to an array -// of values and the proxy's handler. This is designed both so that proxies can -// be easily swapped with other objects (via RemapWrapper) and to mimic the -// layout of other objects (proxies and other objects have the same size) so -// that common code can access either type of object. +// All proxies share the same data layout. Following the object's shape, the +// proxy has a ProxyDataLayout structure with a pointer to an array of values +// and the proxy's handler. This is designed both so that proxies can be easily +// swapped with other objects (via RemapWrapper) and to mimic the layout of +// other objects (proxies and other objects have the same size) so that common +// code can access either type of object. // // See GetReservedOrProxyPrivateSlot below. struct ProxyDataLayout { @@ -554,9 +569,8 @@ inline void SetProxyReservedSlot(JSObject* obj, size_t n, inline void SetProxyPrivate(JSObject* obj, const JS::Value& value) { #ifdef DEBUG - if (gc::detail::ObjectIsMarkedBlack(obj)) { - JS::AssertValueIsNotGray(value); - } + JS::AssertObjectIsNotGray(obj); + JS::AssertValueIsNotGray(value); #endif JS::Value* vp = &detail::GetProxyDataLayout(obj)->values()->privateSlot; @@ -693,10 +707,9 @@ class JS_PUBLIC_API AutoWaivePolicy : public AutoEnterPolicy { } }; #else -class JS_PUBLIC_API AutoWaivePolicy { - public: - AutoWaivePolicy(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, - BaseProxyHandler::Action act) {} +class JS_PUBLIC_API AutoWaivePolicy{ + public : AutoWaivePolicy(JSContext * cx, JS::HandleObject proxy, + JS::HandleId id, BaseProxyHandler::Action act){} }; #endif @@ -741,14 +754,14 @@ constexpr unsigned CheckProxyFlags() { return Flags; } -#define PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, classSpec) \ - { \ - name, \ - JSClass::NON_NATIVE | JSCLASS_IS_PROXY | \ - JSCLASS_DELAY_METADATA_BUILDER | js::CheckProxyFlags(), \ - &js::ProxyClassOps, classSpec, &js::ProxyClassExtension, \ - &js::ProxyObjectOps \ - } +#define PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, classSpec) \ + {name, \ + JSClass::NON_NATIVE | JSCLASS_IS_PROXY | JSCLASS_DELAY_METADATA_BUILDER | \ + js::CheckProxyFlags(), \ + &js::ProxyClassOps, \ + classSpec, \ + &js::ProxyClassExtension, \ + &js::ProxyObjectOps} #define PROXY_CLASS_DEF(name, flags) \ PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, JS_NULL_CLASS_SPEC) diff --git a/src/third_party/mozjs/include/js/Realm.h b/src/third_party/mozjs/include/js/Realm.h index 3421a9fed3b..065b1fc1119 100644 --- a/src/third_party/mozjs/include/js/Realm.h +++ b/src/third_party/mozjs/include/js/Realm.h @@ -106,6 +106,8 @@ extern JS_PUBLIC_API JS::Handle GetRealmObjectPrototypeHandle( JSContext* cx); extern JS_PUBLIC_API JSObject* GetRealmFunctionPrototype(JSContext* cx); +extern JS_PUBLIC_API JS::Handle GetRealmFunctionPrototypeHandle( + JSContext* cx); extern JS_PUBLIC_API JSObject* GetRealmArrayPrototype(JSContext* cx); @@ -142,6 +144,14 @@ extern JS_PUBLIC_API JS::Realm* EnterRealm(JSContext* cx, JSObject* target); extern JS_PUBLIC_API void LeaveRealm(JSContext* cx, JS::Realm* oldRealm); +/** + * Reset the seed for Math.random() within the current realm. + * + * Enables embedders to reset the seed at controlled points, e.g. after + * resuming execution from an instance snapshot of SpiderMonkey's VM. + */ +extern JS_PUBLIC_API void ResetRealmMathRandomSeed(JSContext* cx); + } // namespace JS /* diff --git a/src/third_party/mozjs/include/js/RealmOptions.h b/src/third_party/mozjs/include/js/RealmOptions.h index b3ab20915a0..40c20846a84 100644 --- a/src/third_party/mozjs/include/js/RealmOptions.h +++ b/src/third_party/mozjs/include/js/RealmOptions.h @@ -113,6 +113,12 @@ class JS_PUBLIC_API RealmCreationOptions { // Determines whether this realm should preserve JIT code on non-shrinking // GCs. + // + // Useful for embedders who know their code is relatively stable. See + // Bug 1068697 for motivation. + // + // This is a hint not a guarantee and can be overriden by other heuristics in + // the engine. bool preserveJitCode() const { return preserveJitCode_; } RealmCreationOptions& setPreserveJitCode(bool flag) { preserveJitCode_ = flag; diff --git a/src/third_party/mozjs/include/js/RefCounted.h b/src/third_party/mozjs/include/js/RefCounted.h index de5a72f2d8b..1a58f892017 100644 --- a/src/third_party/mozjs/include/js/RefCounted.h +++ b/src/third_party/mozjs/include/js/RefCounted.h @@ -14,11 +14,7 @@ // These types implement the same interface as mozilla::(Atomic)RefCounted and // must be used instead of mozilla::(Atomic)RefCounted for everything in -// SpiderMonkey. There are two reasons: -// - Release() needs to call js_delete, not delete -// - SpiderMonkey does not have MOZILLA_INTERNAL_API defined which can lead -// to ODR violations that show up as spurious leak reports when ref-counted -// types are allocated by SpiderMonkey and released by Gecko (or vice versa). +// SpiderMonkey. This is because Release() needs to call js_delete, not delete. namespace js { diff --git a/src/third_party/mozjs/include/js/RegExpFlags.h b/src/third_party/mozjs/include/js/RegExpFlags.h index e4663786fcf..bf6bcb4e7b9 100644 --- a/src/third_party/mozjs/include/js/RegExpFlags.h +++ b/src/third_party/mozjs/include/js/RegExpFlags.h @@ -79,7 +79,7 @@ class RegExpFlags { using Flag = uint8_t; private: - Flag flags_; + Flag flags_ = 0; public: RegExpFlags() = default; @@ -159,7 +159,7 @@ inline RegExpFlags& operator^=(RegExpFlags& flags, RegExpFlags::Flag flag) { inline RegExpFlags operator&(const RegExpFlags& lhs, const RegExpFlags& rhs) { RegExpFlags result = lhs; result &= rhs; - return lhs; + return result; } inline RegExpFlags operator|(const RegExpFlags& lhs, const RegExpFlags& rhs) { diff --git a/src/third_party/mozjs/include/js/RootingAPI.h b/src/third_party/mozjs/include/js/RootingAPI.h index eaae2db1b7e..c252d0b9bbd 100644 --- a/src/third_party/mozjs/include/js/RootingAPI.h +++ b/src/third_party/mozjs/include/js/RootingAPI.h @@ -13,6 +13,7 @@ #include "mozilla/LinkedList.h" #include "mozilla/Maybe.h" +#include #include #include @@ -23,10 +24,10 @@ #include "js/GCPolicyAPI.h" #include "js/GCTypeMacros.h" // JS_FOR_EACH_PUBLIC_{,TAGGED_}GC_POINTER_TYPE #include "js/HashTable.h" -#include "js/HeapAPI.h" // StackKindCount +#include "js/HeapAPI.h" // StackKindCount +#include "js/NativeStackLimits.h" // JS::NativeStackLimit #include "js/ProfilingStack.h" #include "js/Realm.h" -#include "js/Stack.h" // JS::NativeStackLimit #include "js/TypeDecls.h" #include "js/UniquePtr.h" @@ -172,18 +173,18 @@ struct Cell; // Assignment operators on a base class are hidden by the implicitly defined // operator= on the derived class. Thus, define the operator= directly on the // class as we would need to manually pass it through anyway. -#define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \ - Wrapper& operator=(const T& p) { \ - set(p); \ - return *this; \ - } \ - Wrapper& operator=(T&& p) { \ - set(std::move(p)); \ - return *this; \ - } \ - Wrapper& operator=(const Wrapper& other) { \ - set(other.get()); \ - return *this; \ +#define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \ + Wrapper& operator=(const T& p) { \ + set(p); \ + return *this; \ + } \ + Wrapper& operator=(T&& p) { \ + set(std::move(p)); \ + return *this; \ + } \ + Wrapper& operator=(const Wrapper& other) { \ + set(other.get()); \ + return *this; \ } #define DELETE_ASSIGNMENT_OPS(Wrapper, T) \ @@ -205,11 +206,6 @@ namespace JS { JS_PUBLIC_API void HeapObjectPostWriteBarrier(JSObject** objp, JSObject* prev, JSObject* next); -JS_PUBLIC_API void HeapStringPostWriteBarrier(JSString** objp, JSString* prev, - JSString* next); -JS_PUBLIC_API void HeapBigIntPostWriteBarrier(JS::BigInt** bip, - JS::BigInt* prev, - JS::BigInt* next); JS_PUBLIC_API void HeapObjectWriteBarriers(JSObject** objp, JSObject* prev, JSObject* next); JS_PUBLIC_API void HeapStringWriteBarriers(JSString** objp, JSString* prev, @@ -244,8 +240,8 @@ struct SafelyInitialized { // doesn't offer a type trait indicating whether a class's constructor is // user-defined, which better approximates our desired semantics.) constexpr bool IsNonTriviallyDefaultConstructibleClassOrUnion = - (std::is_class_v || - std::is_union_v)&&!std::is_trivially_default_constructible_v; + (std::is_class_v || std::is_union_v) && + !std::is_trivially_default_constructible_v; static_assert(IsPointer || IsNonTriviallyDefaultConstructibleClassOrUnion, "T() must evaluate to a safely-initialized T"); @@ -281,13 +277,9 @@ inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {} * * Heap implements the following barriers: * + * - Pre-write barrier (necessary for incremental GC). * - Post-write barrier (necessary for generational GC). - * - Read barrier (necessary for incremental GC and cycle collector - * integration). - * - * Note Heap does not have a pre-write barrier as used internally in the - * engine. The read barrier is used to mark anything read from a Heap during - * an incremental GC. + * - Read barrier (necessary for cycle collector integration). * * Heap may be moved or destroyed outside of GC finalization and hence may be * used in dynamic storage such as a Vector. @@ -302,8 +294,6 @@ inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {} */ template class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { - // Please note: this can actually also be used by nsXBLMaybeCompiled, for - // legacy reasons. static_assert(js::IsHeapConstructibleType::value, "Type T must be a public GC pointer type"); @@ -316,7 +306,7 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { "Heap must be binary compatible with T."); } explicit Heap(const T& p) : ptr(p) { - postWriteBarrier(SafelyInitialized::create(), ptr); + writeBarriers(SafelyInitialized::create(), ptr); } /* @@ -325,25 +315,24 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { * breaks common usage of move semantics, so we need to define both, even * though they are equivalent. */ - explicit Heap(const Heap& other) : ptr(other.getWithoutExpose()) { - postWriteBarrier(SafelyInitialized::create(), ptr); + explicit Heap(const Heap& other) : ptr(other.unbarrieredGet()) { + writeBarriers(SafelyInitialized::create(), ptr); } - Heap(Heap&& other) : ptr(other.getWithoutExpose()) { - postWriteBarrier(SafelyInitialized::create(), ptr); + Heap(Heap&& other) : ptr(other.unbarrieredGet()) { + writeBarriers(SafelyInitialized::create(), ptr); } Heap& operator=(Heap&& other) { - set(other.getWithoutExpose()); + set(other.unbarrieredGet()); other.set(SafelyInitialized::create()); return *this; } + // Copy constructor defined by DECLARE_POINTER_ASSIGN_OPS. - ~Heap() { postWriteBarrier(ptr, SafelyInitialized::create()); } + ~Heap() { writeBarriers(ptr, SafelyInitialized::create()); } DECLARE_POINTER_CONSTREF_OPS(T); - DECLARE_POINTER_ASSIGN_OPS(Heap, T); - - const T* address() const { return &ptr; } + DECLARE_POINTER_ASSIGN_OPS(Heap, T); void exposeToActiveJS() const { js::BarrierMethods::exposeToJS(ptr); } @@ -351,32 +340,25 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations> { exposeToActiveJS(); return ptr; } - const T& getWithoutExpose() const { - js::BarrierMethods::readBarrier(ptr); - return ptr; - } const T& unbarrieredGet() const { return ptr; } void set(const T& newPtr) { T tmp = ptr; ptr = newPtr; - postWriteBarrier(tmp, ptr); + writeBarriers(tmp, ptr); } - - T* unsafeGet() { return &ptr; } - void unbarrieredSet(const T& newPtr) { ptr = newPtr; } + T* unsafeAddress() { return &ptr; } + const T* unsafeAddress() const { return &ptr; } + explicit operator bool() const { return bool(js::BarrierMethods::asGCThingOrNull(ptr)); } - explicit operator bool() { - return bool(js::BarrierMethods::asGCThingOrNull(ptr)); - } private: - void postWriteBarrier(const T& prev, const T& next) { - js::BarrierMethods::postWriteBarrier(&ptr, prev, next); + void writeBarriers(const T& prev, const T& next) { + js::BarrierMethods::writeBarriers(&ptr, prev, next); } T ptr; @@ -448,7 +430,7 @@ inline void AssertObjectIsNotGray(const JS::Heap& obj) {} * it has two important differences: * * 1) Pointers which are statically known to only reference "tenured" objects - * can avoid the extra overhead of SpiderMonkey's write barriers. + * can avoid the extra overhead of SpiderMonkey's post write barriers. * * 2) Objects in the "tenured" heap have stronger alignment restrictions than * those in the "nursery", so it is possible to store flags in the lower @@ -473,6 +455,9 @@ inline void AssertObjectIsNotGray(const JS::Heap& obj) {} */ template class TenuredHeap : public js::HeapOperations> { + static_assert(js::IsHeapConstructibleType::value, + "Type T must be a public GC pointer type"); + public: using ElementType = T; @@ -480,12 +465,29 @@ class TenuredHeap : public js::HeapOperations> { static_assert(sizeof(T) == sizeof(TenuredHeap), "TenuredHeap must be binary compatible with T."); } - explicit TenuredHeap(T p) : bits(0) { setPtr(p); } + + explicit TenuredHeap(T p) : bits(0) { unbarrieredSetPtr(p); } explicit TenuredHeap(const TenuredHeap& p) : bits(0) { - setPtr(p.getPtr()); + unbarrieredSetPtr(p.getPtr()); } + TenuredHeap& operator=(T p) { + setPtr(p); + return *this; + } + TenuredHeap& operator=(const TenuredHeap& other) { + preWriteBarrier(); + bits = other.bits; + return *this; + } + + ~TenuredHeap() { preWriteBarrier(); } + void setPtr(T newPtr) { + preWriteBarrier(); + unbarrieredSetPtr(newPtr); + } + void unbarrieredSetPtr(T newPtr) { MOZ_ASSERT((reinterpret_cast(newPtr) & flagsMask) == 0); MOZ_ASSERT(js::gc::IsCellPointerValidOrNull(newPtr)); if (newPtr) { @@ -526,19 +528,6 @@ class TenuredHeap : public js::HeapOperations> { explicit operator bool() const { return bool(js::BarrierMethods::asGCThingOrNull(unbarrieredGetPtr())); } - explicit operator bool() { - return bool(js::BarrierMethods::asGCThingOrNull(unbarrieredGetPtr())); - } - - TenuredHeap& operator=(T p) { - setPtr(p); - return *this; - } - - TenuredHeap& operator=(const TenuredHeap& other) { - bits = other.bits; - return *this; - } private: enum { @@ -546,6 +535,12 @@ class TenuredHeap : public js::HeapOperations> { flagsMask = (1 << maskBits) - 1, }; + void preWriteBarrier() { + if (T prev = unbarrieredGetPtr()) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev)); + } + } + uintptr_t bits; }; @@ -583,6 +578,8 @@ template class MutableHandle; template class Rooted; +template +class RootedField; template class PersistentRooted; @@ -662,6 +659,11 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleOperations> { MutableHandle& root, std::enable_if_t, int> dummy = 0); + template + inline MOZ_IMPLICIT Handle( + const RootedField& rootedField, + std::enable_if_t, int> dummy = 0); + DECLARE_POINTER_CONSTREF_OPS(T); DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr); @@ -700,6 +702,8 @@ class MOZ_STACK_CLASS MutableHandle using ElementType = T; inline MOZ_IMPLICIT MutableHandle(Rooted* root); + template + inline MOZ_IMPLICIT MutableHandle(RootedField* root); inline MOZ_IMPLICIT MutableHandle(PersistentRooted* root); private: @@ -783,7 +787,10 @@ struct PtrBarrierMethodsBase { template struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(T** vp, T* prev, T* next) { + static void writeBarriers(T** vp, T* prev, T* next) { + if (prev) { + JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev)); + } if (next) { JS::AssertGCThingIsNotNurseryAllocable( reinterpret_cast(next)); @@ -794,6 +801,9 @@ struct BarrierMethods : public detail::PtrBarrierMethodsBase { template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { + static void writeBarriers(JSObject** vp, JSObject* prev, JSObject* next) { + JS::HeapObjectWriteBarriers(vp, prev, next); + } static void postWriteBarrier(JSObject** vp, JSObject* prev, JSObject* next) { JS::HeapObjectPostWriteBarrier(vp, prev, next); } @@ -807,11 +817,11 @@ struct BarrierMethods template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(JSFunction** vp, JSFunction* prev, - JSFunction* next) { - JS::HeapObjectPostWriteBarrier(reinterpret_cast(vp), - reinterpret_cast(prev), - reinterpret_cast(next)); + static void writeBarriers(JSFunction** vp, JSFunction* prev, + JSFunction* next) { + JS::HeapObjectWriteBarriers(reinterpret_cast(vp), + reinterpret_cast(prev), + reinterpret_cast(next)); } static void exposeToJS(JSFunction* fun) { if (fun) { @@ -823,17 +833,25 @@ struct BarrierMethods template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(JSString** vp, JSString* prev, JSString* next) { - JS::HeapStringPostWriteBarrier(vp, prev, next); + static void writeBarriers(JSString** vp, JSString* prev, JSString* next) { + JS::HeapStringWriteBarriers(vp, prev, next); + } +}; + +template <> +struct BarrierMethods + : public detail::PtrBarrierMethodsBase { + static void writeBarriers(JSScript** vp, JSScript* prev, JSScript* next) { + JS::HeapScriptWriteBarriers(vp, prev, next); } }; template <> struct BarrierMethods : public detail::PtrBarrierMethodsBase { - static void postWriteBarrier(JS::BigInt** vp, JS::BigInt* prev, - JS::BigInt* next) { - JS::HeapBigIntPostWriteBarrier(vp, prev, next); + static void writeBarriers(JS::BigInt** vp, JS::BigInt* prev, + JS::BigInt* next) { + JS::HeapBigIntWriteBarriers(vp, prev, next); } }; @@ -1145,11 +1163,19 @@ using RootedTraits = template class MOZ_RAII Rooted : public detail::RootedTraits::StackBase, public js::RootedOperations> { + // Intentionally store a pointer into the stack. +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 12) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdangling-pointer" +#endif inline void registerWithRootLists(RootedListHeads& roots) { this->stack = &roots[JS::MapTypeToRootKind::kind]; this->prev = *this->stack; *this->stack = this; } +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 12) +# pragma GCC diagnostic pop +#endif inline RootedListHeads& rootLists(RootingContext* cx) { return cx->stackRoots_; @@ -1220,7 +1246,7 @@ class MOZ_RAII Rooted : public detail::RootedTraits::StackBase, } DECLARE_POINTER_CONSTREF_OPS(T); - DECLARE_POINTER_ASSIGN_OPS(Rooted, T); + DECLARE_POINTER_ASSIGN_OPS(Rooted, T); T& get() { return ptr; } const T& get() const { return ptr; } @@ -1243,6 +1269,86 @@ struct DefineComparisonOps> : std::true_type { } // namespace detail +template +using RootedTuple = Rooted>; + +// Reference to a field in a RootedTuple. This is a drop-in replacement for an +// individual Rooted. +// +// This is very similar to a MutableHandle but with two differences: it has an +// assignment operator so doesn't require set() to be called and its address +// converts to a MutableHandle in the same way as a Rooted. +// +// The field is specified by the type parameter, optionally disambiguated by +// supplying the field index too. +// +// Used like this: +// +// RootedTuple roots(cx); +// RootedField obj(roots); +// RootedField str(roots); +// +// or: +// +// RootedTuple roots(cx); +// RootedField str(roots); +// RootedField obj1(roots); +// RootedField obj2(roots); +template +class MOZ_RAII RootedField : public js::RootedOperations> { + T* ptr; + friend class Handle; + friend class MutableHandle; + + public: + using ElementType = T; + + template + explicit RootedField(RootedTuple& rootedTuple) { + using Tuple = std::tuple; + if constexpr (N == SIZE_MAX) { + ptr = &std::get(rootedTuple.get()); + } else { + static_assert(N < std::tuple_size_v); + static_assert(std::is_same_v>); + ptr = &std::get(rootedTuple.get()); + } + } + template + explicit RootedField(RootedTuple& rootedTuple, S&& value) + : RootedField(rootedTuple) { + *ptr = std::forward(value); + } + + T& get() { return *ptr; } + const T& get() const { return *ptr; } + void set(const T& value) { + *ptr = value; + MOZ_ASSERT(GCPolicy::isValid(*ptr)); + } + void set(T&& value) { + *ptr = std::move(value); + MOZ_ASSERT(GCPolicy::isValid(*ptr)); + } + + using WrapperT = RootedField; + DECLARE_POINTER_CONSTREF_OPS(T); + DECLARE_POINTER_ASSIGN_OPS(WrapperT, T); + // DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr); + // DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr); + + private: + RootedField() = delete; + RootedField(const RootedField& other) = delete; +}; + +namespace detail { +template +struct DefineComparisonOps> : std::true_type { + static const T& get(const JS::RootedField& v) { return v.get(); } +}; +} // namespace detail + } /* namespace JS */ namespace js { @@ -1342,6 +1448,14 @@ inline Handle::Handle( ptr = reinterpret_cast(root.address()); } +template +template +inline Handle::Handle( + const RootedField& rootedField, + std::enable_if_t, int> dummy) { + ptr = reinterpret_cast(rootedField.ptr); +} + template inline MutableHandle::MutableHandle(Rooted* root) { static_assert(sizeof(MutableHandle) == sizeof(T*), @@ -1349,6 +1463,12 @@ inline MutableHandle::MutableHandle(Rooted* root) { ptr = root->address(); } +template +template +inline MutableHandle::MutableHandle(RootedField* rootedField) { + ptr = rootedField->ptr; +} + template inline MutableHandle::MutableHandle(PersistentRooted* root) { static_assert(sizeof(MutableHandle) == sizeof(T*), @@ -1480,7 +1600,7 @@ class PersistentRooted : public detail::RootedTraits::PersistentBase, } DECLARE_POINTER_CONSTREF_OPS(T); - DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T); + DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T); T& get() { return ptr; } const T& get() const { return ptr; } diff --git a/src/third_party/mozjs/include/js/SliceBudget.h b/src/third_party/mozjs/include/js/SliceBudget.h index 44450204840..40edd5b8181 100644 --- a/src/third_party/mozjs/include/js/SliceBudget.h +++ b/src/third_party/mozjs/include/js/SliceBudget.h @@ -16,7 +16,7 @@ #include "jstypes.h" -namespace js { +namespace JS { struct JS_PUBLIC_API TimeBudget { const mozilla::TimeDuration budget; @@ -140,6 +140,6 @@ class JS_PUBLIC_API SliceBudget { int describe(char* buffer, size_t maxlen) const; }; -} // namespace js +} // namespace JS #endif /* js_SliceBudget_h */ diff --git a/src/third_party/mozjs/include/js/Stack.h b/src/third_party/mozjs/include/js/Stack.h index 7384e92d398..bf9c845615c 100644 --- a/src/third_party/mozjs/include/js/Stack.h +++ b/src/third_party/mozjs/include/js/Stack.h @@ -17,44 +17,9 @@ #include "jstypes.h" // JS_PUBLIC_API +#include "js/NativeStackLimits.h" #include "js/Principals.h" // JSPrincipals, JS_HoldPrincipals, JS_DropPrincipals -#include "js/TypeDecls.h" // JSContext, Handle*, MutableHandle* - -namespace JS { - -using NativeStackSize = size_t; - -using NativeStackBase = uintptr_t; - -using NativeStackLimit = uintptr_t; - -#if JS_STACK_GROWTH_DIRECTION > 0 -constexpr NativeStackLimit NativeStackLimitMin = 0; -constexpr NativeStackLimit NativeStackLimitMax = UINTPTR_MAX; -#else -constexpr NativeStackLimit NativeStackLimitMin = UINTPTR_MAX; -constexpr NativeStackLimit NativeStackLimitMax = 0; -#endif - -#ifdef __wasi__ -// We build with the "stack-first" wasm-ld option, so the stack grows downward -// toward zero. Let's set a limit just a bit above this so that we catch an -// overflow before a Wasm trap occurs. -constexpr NativeStackLimit WASINativeStackLimit = 1024; -#endif // __wasi__ - -inline NativeStackLimit GetNativeStackLimit(NativeStackBase base, - NativeStackSize size) { -#if JS_STACK_GROWTH_DIRECTION > 0 - MOZ_ASSERT(base <= size_t(-1) - size); - return base + size - 1; -#else // stack grows up - MOZ_ASSERT(base >= size); - return base - (size - 1); -#endif // stack grows down -} - -} // namespace JS +#include "js/RootingAPI.h" /** * Set the size of the native stack that should not be exceed. To disable @@ -177,7 +142,8 @@ using StackCapture = mozilla::Variant; */ extern JS_PUBLIC_API bool CaptureCurrentStack( JSContext* cx, MutableHandleObject stackp, - StackCapture&& capture = StackCapture(AllFrames())); + StackCapture&& capture = StackCapture(AllFrames()), + HandleObject startAfter = nullptr); /** * Returns true if capturing stack trace data to associate with an asynchronous diff --git a/src/third_party/mozjs/include/js/String.h b/src/third_party/mozjs/include/js/String.h index 3e003f291c4..41645d2bc1d 100644 --- a/src/third_party/mozjs/include/js/String.h +++ b/src/third_party/mozjs/include/js/String.h @@ -11,13 +11,15 @@ #include "js/shadow/String.h" // JS::shadow::String -#include "mozilla/Assertions.h" // MOZ_ASSERT -#include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE -#include "mozilla/Likely.h" // MOZ_LIKELY -#include "mozilla/Maybe.h" // mozilla::Maybe -#include "mozilla/Range.h" // mozilla::Range -#include "mozilla/Span.h" // mozilla::Span - // std::tuple +#include "mozilla/Assertions.h" // MOZ_ASSERT +#include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE +#include "mozilla/Likely.h" // MOZ_LIKELY +#include "mozilla/Maybe.h" // mozilla::Maybe +#include "mozilla/Range.h" // mozilla::Range +#include "mozilla/RefPtr.h" // RefPtr +#include "mozilla/Span.h" // mozilla::Span + // std::tuple +#include "mozilla/StringBuffer.h" // mozilla::StringBuffer #include // std::copy_n #include // size_t @@ -102,6 +104,63 @@ extern JS_PUBLIC_API JSString* JS_NewUCStringCopyN(JSContext* cx, extern JS_PUBLIC_API JSString* JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s); +namespace JS { + +/** + * Create a new JSString possibly backed by |buffer|. The contents of |buffer| + * will be interpreted as an array of Latin1 characters. + * + * Note that the returned string is not guaranteed to use |buffer|: as an + * optimization, this API can return an inline string or a previously allocated + * string. + * + * Increments the buffer's refcount iff the JS string holds a reference to it. + */ +extern JS_PUBLIC_API JSString* NewStringFromLatin1Buffer( + JSContext* cx, RefPtr buffer, size_t length); + +/** + * Like NewStringFromLatin1Buffer, but can be used to avoid refcounting overhead + * in cases where the returned string doesn't use the buffer. The caller must + * ensure the buffer outlives this call. + */ +extern JS_PUBLIC_API JSString* NewStringFromKnownLiveLatin1Buffer( + JSContext* cx, mozilla::StringBuffer* buffer, size_t length); + +/** + * Similar to NewStringFromLatin1Buffer but for char16_t buffers. + */ +extern JS_PUBLIC_API JSString* NewStringFromTwoByteBuffer( + JSContext* cx, RefPtr buffer, size_t length); + +/** + * Similar to NewStringFromKnownLiveLatin1Buffer but for char16_t buffers. + */ +extern JS_PUBLIC_API JSString* NewStringFromKnownLiveTwoByteBuffer( + JSContext* cx, mozilla::StringBuffer* buffer, size_t length); + +/** + * Similar to NewStringFromLatin1Buffer but for UTF8 buffers. + * + * This can create a Latin1 string backed by |buffer| iff the utf8 buffer + * contains only ASCII chars. If there are non-ASCII chars, |buffer| can't be + * used so this API will copy and inflate the characters for the new JS string. + * + * Note that |length| must be the (byte) length of the UTF8 buffer. + */ +extern JS_PUBLIC_API JSString* NewStringFromUTF8Buffer( + JSContext* cx, RefPtr buffer, size_t length); + +/** + * Like NewStringFromUTF8Buffer, but can be used to avoid refcounting overhead + * in cases where the returned string doesn't use the buffer. The caller must + * ensure the buffer outlives this call. + */ +extern JS_PUBLIC_API JSString* NewStringFromKnownLiveUTF8Buffer( + JSContext* cx, mozilla::StringBuffer* buffer, size_t length); + +} // namespace JS + extern JS_PUBLIC_API JSString* JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length); @@ -430,6 +489,46 @@ MOZ_ALWAYS_INLINE bool IsExternalUCString( return true; } +/** + * If the provided string is backed by a StringBuffer for latin-1 storage, + * return true and set |*buffer| to the string buffer. + * + * Note: this function doesn't increment the buffer's refcount. The buffer + * remains valid as long as the provided string is kept alive. + */ +MOZ_ALWAYS_INLINE bool IsLatin1StringWithStringBuffer( + JSString* str, mozilla::StringBuffer** buffer) { + shadow::String* s = shadow::AsShadowString(str); + + if (!s->hasStringBuffer() || !s->hasLatin1Chars()) { + return false; + } + + void* data = const_cast(s->nonInlineCharsLatin1); + *buffer = mozilla::StringBuffer::FromData(data); + return true; +} + +/** + * If the provided string is backed by a StringBuffer for char16_t storage, + * return true and set |*buffer| to the string buffer. + * + * Note: this function doesn't increment the buffer's refcount. The buffer + * remains valid as long as the provided string is kept alive. + */ +MOZ_ALWAYS_INLINE bool IsTwoByteStringWithStringBuffer( + JSString* str, mozilla::StringBuffer** buffer) { + shadow::String* s = shadow::AsShadowString(str); + + if (!s->hasStringBuffer() || s->hasLatin1Chars()) { + return false; + } + + void* data = const_cast(s->nonInlineCharsTwoByte); + *buffer = mozilla::StringBuffer::FromData(data); + return true; +} + namespace detail { extern JS_PUBLIC_API JSLinearString* StringToLinearStringSlow(JSContext* cx, diff --git a/src/third_party/mozjs/include/js/StructuredClone.h b/src/third_party/mozjs/include/js/StructuredClone.h index ab151a3be56..db78536701e 100644 --- a/src/third_party/mozjs/include/js/StructuredClone.h +++ b/src/third_party/mozjs/include/js/StructuredClone.h @@ -10,6 +10,7 @@ #include "mozilla/Attributes.h" #include "mozilla/BufferList.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/StringBuffer.h" #include #include @@ -154,6 +155,13 @@ enum class StructuredCloneScope : uint32_t { */ DifferentProcess, + /** + * Values greater than this are temporary markers used when the actual scope + * is not yet known. The allowed scope will be resolved by the time + * readHeader() is complete. + */ + LastResolvedScope = DifferentProcess, + /** * Handle a backwards-compatibility case with IndexedDB (bug 1434308): when * reading, this means to treat legacy SameProcess data as if it were @@ -311,6 +319,11 @@ typedef void (*StructuredCloneErrorOp)(JSContext* cx, uint32_t errorid, * If this readTransfer() hook is called and produces an object, then the * read() hook will *not* be called for the same object, since the main data * will only contain a backreference to the already-read object. + * + * The clone buffer will relinquish ownership of this Transferable if and only + * if this hook returns true -- as in, the freeTransfer hook will not be called + * on this entry if this hook returns true, but it will still be called if it + * returns false. */ typedef bool (*ReadTransferStructuredCloneOp)( JSContext* cx, JSStructuredCloneReader* r, @@ -351,11 +364,13 @@ typedef bool (*TransferStructuredCloneOp)(JSContext* cx, * encountered later and the incomplete serialization is discarded. * * 2. During deserialization: before an object is Transferred to, an error - * is encountered and the incompletely deserialized clone is discarded. + * is encountered and the incompletely deserialized clone is discarded. This + * will happen with internally-implemented Transferables as well as those + * where the readTransfer hook returns false. * * 3. Serialized data that includes Transferring is never deserialized (eg when * the receiver disappears before reading in the message), and the clone data - * is destroyed. + * is destroyed. * */ typedef void (*FreeTransferStructuredCloneOp)( @@ -469,6 +484,10 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData { OwnTransferablePolicy::NoTransferables; js::SharedArrayRawBufferRefs refsHeld_; + using StringBuffers = + js::Vector, 4, js::SystemAllocPolicy>; + StringBuffers stringBufferRefsHeld_; + friend struct JSStructuredCloneWriter; friend class JS_PUBLIC_API JSAutoStructuredCloneBuffer; template diff --git a/src/third_party/mozjs/include/js/Symbol.h b/src/third_party/mozjs/include/js/Symbol.h index d45a58cffab..2f021cb9e78 100644 --- a/src/third_party/mozjs/include/js/Symbol.h +++ b/src/third_party/mozjs/include/js/Symbol.h @@ -49,21 +49,22 @@ extern JS_PUBLIC_API Symbol* GetSymbolFor(JSContext* cx, Handle key); extern JS_PUBLIC_API JSString* GetSymbolDescription(Handle symbol); /* Well-known symbols. */ -#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(MACRO) \ - MACRO(isConcatSpreadable) \ - MACRO(iterator) \ - MACRO(match) \ - MACRO(replace) \ - MACRO(search) \ - MACRO(species) \ - MACRO(hasInstance) \ - MACRO(split) \ - MACRO(toPrimitive) \ - MACRO(toStringTag) \ - MACRO(unscopables) \ - MACRO(asyncIterator) \ - MACRO(matchAll) \ - IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(dispose)) +#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(MACRO) \ + MACRO(isConcatSpreadable) \ + MACRO(iterator) \ + MACRO(match) \ + MACRO(replace) \ + MACRO(search) \ + MACRO(species) \ + MACRO(hasInstance) \ + MACRO(split) \ + MACRO(toPrimitive) \ + MACRO(toStringTag) \ + MACRO(unscopables) \ + MACRO(asyncIterator) \ + MACRO(matchAll) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(dispose)) \ + IF_EXPLICIT_RESOURCE_MANAGEMENT(MACRO(asyncDispose)) enum class SymbolCode : uint32_t { // There is one SymbolCode for each well-known symbol. diff --git a/src/third_party/mozjs/include/js/TraceKind.h b/src/third_party/mozjs/include/js/TraceKind.h index 268db56957d..de6fb22e5fb 100644 --- a/src/third_party/mozjs/include/js/TraceKind.h +++ b/src/third_party/mozjs/include/js/TraceKind.h @@ -22,6 +22,9 @@ class PropMap; class RegExpShared; class Shape; class Scope; +namespace gc { +class SmallBuffer; +} // namespace gc namespace jit { class JitCode; } // namespace jit @@ -63,6 +66,7 @@ enum class TraceKind { RegExpShared, GetterSetter, PropMap, + SmallBuffer }; // GCCellPtr packs the trace kind into the low bits of the pointer for common @@ -88,20 +92,21 @@ struct MapTypeToTraceKind { // also means they can be used as a keys in WeakMap. // clang-format off -#define JS_FOR_EACH_TRACEKIND(D) \ - /* name type canBeGray inCCGraph */ \ - D(BaseShape, js::BaseShape, true, false) \ - D(JitCode, js::jit::JitCode, true, false) \ - D(Scope, js::Scope, true, true) \ - D(Object, JSObject, true, true) \ - D(Script, js::BaseScript, true, true) \ - D(Shape, js::Shape, true, false) \ - D(String, JSString, false, false) \ - D(Symbol, JS::Symbol, false, false) \ - D(BigInt, JS::BigInt, false, false) \ - D(RegExpShared, js::RegExpShared, true, true) \ - D(GetterSetter, js::GetterSetter, true, true) \ - D(PropMap, js::PropMap, false, false) +#define JS_FOR_EACH_TRACEKIND(D) \ + /* name type canBeGray inCCGraph */ \ + D(BaseShape, js::BaseShape, true, false) \ + D(JitCode, js::jit::JitCode, true, false) \ + D(Scope, js::Scope, true, true) \ + D(Object, JSObject, true, true) \ + D(Script, js::BaseScript, true, true) \ + D(Shape, js::Shape, true, false) \ + D(String, JSString, false, false) \ + D(Symbol, JS::Symbol, false, false) \ + D(BigInt, JS::BigInt, false, false) \ + D(RegExpShared, js::RegExpShared, true, true) \ + D(GetterSetter, js::GetterSetter, true, true) \ + D(PropMap, js::PropMap, false, false) \ + D(SmallBuffer, js::gc::SmallBuffer, false, false) // clang-format on // Returns true if the JS::TraceKind is represented as a node in cycle collector diff --git a/src/third_party/mozjs/include/js/TracingAPI.h b/src/third_party/mozjs/include/js/TracingAPI.h index 4db1b0a30ca..dfc145d9f98 100644 --- a/src/third_party/mozjs/include/js/TracingAPI.h +++ b/src/third_party/mozjs/include/js/TracingAPI.h @@ -48,6 +48,7 @@ enum class TracerKind { UnmarkGray, VerifyTraceProtoAndIface, CompartmentCheck, + HeapCheck }; enum class WeakMapTraceAction { @@ -135,7 +136,8 @@ class TracingContext { // currently set tracing context. class Functor { public: - virtual void operator()(TracingContext* tcx, char* buf, size_t bufsize) = 0; + virtual void operator()(TracingContext* tcx, const char* name, char* buf, + size_t bufsize) = 0; }; private: @@ -348,7 +350,7 @@ template inline void TraceEdge(JSTracer* trc, JS::Heap* thingp, const char* name) { MOZ_ASSERT(thingp); if (*thingp) { - js::gc::TraceExternalEdge(trc, thingp->unsafeGet(), name); + js::gc::TraceExternalEdge(trc, thingp->unsafeAddress(), name); } } @@ -358,7 +360,7 @@ inline void TraceEdge(JSTracer* trc, JS::TenuredHeap* thingp, MOZ_ASSERT(thingp); if (T ptr = thingp->unbarrieredGetPtr()) { js::gc::TraceExternalEdge(trc, &ptr, name); - thingp->setPtr(ptr); + thingp->unbarrieredSetPtr(ptr); } } diff --git a/src/third_party/mozjs/include/js/Transcoding.h b/src/third_party/mozjs/include/js/Transcoding.h index 9a5c6102ad7..61943088a87 100644 --- a/src/third_party/mozjs/include/js/Transcoding.h +++ b/src/third_party/mozjs/include/js/Transcoding.h @@ -19,8 +19,15 @@ #include "js/TypeDecls.h" +// Underlying opaque type. +namespace js::frontend { +struct InitialStencilAndDelazifications; +} // namespace js::frontend + namespace JS { +using Stencil = js::frontend::InitialStencilAndDelazifications; + class JS_PUBLIC_API ReadOnlyCompileOptions; using TranscodeBuffer = mozilla::Vector; @@ -79,52 +86,6 @@ inline bool IsTranscodingBytecodeAligned(const void* offset) { return IsTranscodingBytecodeOffsetAligned(size_t(offset)); } -// Finish incremental encoding started by JS::StartIncrementalEncoding. -// -// * Regular script case -// the |script| argument must be the top-level script returned from -// |JS::InstantiateGlobalStencil| with the same stencil -// -// * Module script case -// the |script| argument must be the script returned by -// |JS::GetModuleScript| called on the module returned by -// |JS::InstantiateModuleStencil| with the same stencil -// -// NOTE: |JS::GetModuleScript| doesn't work after evaluating the -// module script. For the case, use Handle variant of -// this function below. -// -// The |buffer| argument of |FinishIncrementalEncoding| is used for appending -// the encoded bytecode into the buffer. If any of these functions failed, the -// content of |buffer| would be undefined. -// -// |buffer| contains encoded CompilationStencil. -// -// If the `buffer` isn't empty, the start of the `buffer` should meet -// IsTranscodingBytecodeAligned, and the length should meet -// IsTranscodingBytecodeOffsetAligned. -// -// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means -// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, -// IsTranscodingBytecodeAligned should be guaranteed to meet by -// malloc, used by MallocAllocPolicy in mozilla::Vector. -extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx, - Handle script, - TranscodeBuffer& buffer); - -// Similar to |JS::FinishIncrementalEncoding|, but receives module obect. -// -// The |module| argument must be the module returned by -// |JS::InstantiateModuleStencil| with the same stencil that's passed to -// |JS::StartIncrementalEncoding|. -extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx, - Handle module, - TranscodeBuffer& buffer); - -// Abort incremental encoding started by JS::StartIncrementalEncoding. -extern JS_PUBLIC_API void AbortIncrementalEncoding(Handle script); -extern JS_PUBLIC_API void AbortIncrementalEncoding(Handle module); - // Check if the compile options and script's flag matches. // // JS::DecodeScript* and JS::DecodeOffThreadScript internally check this. diff --git a/src/third_party/mozjs/include/js/TypeDecls.h b/src/third_party/mozjs/include/js/TypeDecls.h index d82405b17c0..ea95dc4e987 100644 --- a/src/third_party/mozjs/include/js/TypeDecls.h +++ b/src/third_party/mozjs/include/js/TypeDecls.h @@ -47,10 +47,6 @@ typedef unsigned char Latin1Char; class JS_PUBLIC_API Symbol; class JS_PUBLIC_API BigInt; -#ifdef ENABLE_RECORD_TUPLE -class JS_PUBLIC_API RecordType; -class JS_PUBLIC_API TupleType; -#endif class JS_PUBLIC_API Value; class JS_PUBLIC_API Compartment; @@ -130,18 +126,6 @@ using MutableHandleVector = MutableHandle>; using jsid = JS::PropertyKey; -#ifdef ENABLE_RECORD_TUPLE -// This takes 1 or 2 parameters. ... is just used so that -// it's possible to omit the comma when passing a single -// param: -// IF_RECORD_TUPLE(doThis) -// IF_RECORD_TUPLE(doThis, elseThis) -# define IF_RECORD_TUPLE(x, ...) x -#else -# define IF_RECORD_TUPLE(x, ...) __VA_ARGS__ -#endif - -// Follows the same pattern as IF_RECORD_TUPLE #ifdef ENABLE_DECORATORS # define IF_DECORATORS(x, ...) x #else diff --git a/src/third_party/mozjs/include/js/UbiNode.h b/src/third_party/mozjs/include/js/UbiNode.h index 15edea070e4..aa187afc44c 100644 --- a/src/third_party/mozjs/include/js/UbiNode.h +++ b/src/third_party/mozjs/include/js/UbiNode.h @@ -1164,6 +1164,26 @@ class JS_PUBLIC_API Concrete : TracerConcrete { static const char16_t concreteTypeName[]; }; +template <> +class JS_PUBLIC_API Concrete + : TracerConcrete { + protected: + explicit Concrete(js::gc::SmallBuffer* ptr) + : TracerConcrete(ptr) {} + + public: + static void construct(void* storage, js::gc::SmallBuffer* ptr) { + new (storage) Concrete(ptr); + } + + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + + CoarseType coarseType() const final { return CoarseType::Object; } + + const char16_t* typeName() const override { return concreteTypeName; } + static const char16_t concreteTypeName[]; +}; + // The ubi::Node null pointer. Any attempt to operate on a null ubi::Node // asserts. template <> diff --git a/src/third_party/mozjs/include/js/Utility.h b/src/third_party/mozjs/include/js/Utility.h index 25e351d740f..d80e2cc06d3 100644 --- a/src/third_party/mozjs/include/js/Utility.h +++ b/src/third_party/mozjs/include/js/Utility.h @@ -43,6 +43,16 @@ extern MOZ_NORETURN MOZ_COLD JS_PUBLIC_API void JS_Assert(const char* s, # include "jscustomallocator.h" #else +/* + * MONGODB MODIFICATION: These functions are implemented by jscustomallocator + * This logic is unused when running Without JS_USE_CUSTOM_ALLOCATOR + */ +namespace mongo { +namespace sm { +JS_PUBLIC_API void check_oom_on_mmap_allocation(size_t bytes); +} // namespace sm +} // namespace mongo + namespace js { /* @@ -54,20 +64,22 @@ namespace js { * adding new thread types. */ enum ThreadType { - THREAD_TYPE_NONE = 0, // 0 - THREAD_TYPE_MAIN, // 1 - THREAD_TYPE_WASM_COMPILE_TIER1, // 2 - THREAD_TYPE_WASM_COMPILE_TIER2, // 3 - THREAD_TYPE_ION, // 4 - THREAD_TYPE_COMPRESS, // 5 - THREAD_TYPE_GCPARALLEL, // 6 - THREAD_TYPE_PROMISE_TASK, // 7 - THREAD_TYPE_ION_FREE, // 8 - THREAD_TYPE_WASM_GENERATOR_TIER2, // 9 - THREAD_TYPE_WORKER, // 10 - THREAD_TYPE_DELAZIFY, // 11 - THREAD_TYPE_DELAZIFY_FREE, // 12 - THREAD_TYPE_MAX // Used to check shell function arguments + THREAD_TYPE_NONE = 0, // 0 + THREAD_TYPE_MAIN, // 1 + THREAD_TYPE_WASM_COMPILE_TIER1, // 2 + THREAD_TYPE_WASM_COMPILE_TIER2, // 3 + THREAD_TYPE_BASELINE, // 4 + THREAD_TYPE_ION, // 5 + THREAD_TYPE_COMPRESS, // 6 + THREAD_TYPE_GCPARALLEL, // 7 + THREAD_TYPE_PROMISE_TASK, // 8 + THREAD_TYPE_ION_FREE, // 9 + THREAD_TYPE_WASM_GENERATOR_COMPLETE_TIER2, // 10 + THREAD_TYPE_WASM_COMPILE_PARTIAL_TIER2, // 11 + THREAD_TYPE_WORKER, // 12 + THREAD_TYPE_DELAZIFY, // 13 + THREAD_TYPE_DELAZIFY_FREE, // 14 + THREAD_TYPE_MAX // Used to check shell function arguments }; namespace oom { @@ -86,7 +98,7 @@ namespace oom { // Define the range of threads tested by simulated OOM testing and the // like. Testing worker threads is not supported. const ThreadType FirstThreadTypeToTest = THREAD_TYPE_MAIN; -const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_GENERATOR_TIER2; +const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_COMPILE_PARTIAL_TIER2; extern bool InitThreadType(void); extern void SetThreadType(ThreadType); @@ -95,7 +107,7 @@ extern JS_PUBLIC_API uint32_t GetThreadType(void); # else inline bool InitThreadType(void) { return true; } -inline void SetThreadType(ThreadType t){}; +inline void SetThreadType(ThreadType t) {}; inline uint32_t GetThreadType(void) { return 0; } inline uint32_t GetAllocationThreadType(void) { return 0; } inline uint32_t GetStackCheckThreadType(void) { return 0; } @@ -352,7 +364,21 @@ struct MOZ_RAII JS_PUBLIC_DATA AutoEnterOOMUnsafeRegion { namespace js { +// The following two arenas require a little bit of clarification. We have +// observed that, particularly on devices with heterogeneous CPU architectures +// where background work can run on significantly slower cores than main thread +// work, the lock contention in the allocator can be a big problem for the +// main thread. So we introduced an arena for background allocations which can +// reduce that contention. +// +// The general rule for these is: if it's easy to determine at the time of +// authorship that an allocation will be *off* the main thread, use the +// BackgroundMallocArena, and vice versa. If it is hard to determine, just make +// a guess, and that will be fine. Do not spend too much time on this, and +// don't do anything fancy at runtime to try to determine which to use. extern JS_PUBLIC_DATA arena_id_t MallocArena; +extern JS_PUBLIC_DATA arena_id_t BackgroundMallocArena; + extern JS_PUBLIC_DATA arena_id_t ArrayBufferContentsArena; extern JS_PUBLIC_DATA arena_id_t StringBufferArena; diff --git a/src/third_party/mozjs/include/js/Value.h b/src/third_party/mozjs/include/js/Value.h index 98f0f9273b2..c70d5b6888f 100644 --- a/src/third_party/mozjs/include/js/Value.h +++ b/src/third_party/mozjs/include/js/Value.h @@ -170,9 +170,6 @@ enum JSValueType : uint8_t { JSVAL_TYPE_SYMBOL = 0x07, JSVAL_TYPE_PRIVATE_GCTHING = 0x08, JSVAL_TYPE_BIGINT = 0x09, -#ifdef ENABLE_RECORD_TUPLE - JSVAL_TYPE_EXTENDED_PRIMITIVE = 0x0b, -#endif JSVAL_TYPE_OBJECT = 0x0c, // This type never appears in a Value; it's only an out-of-band value. @@ -191,9 +188,6 @@ enum class ValueType : uint8_t { Symbol = JSVAL_TYPE_SYMBOL, PrivateGCThing = JSVAL_TYPE_PRIVATE_GCTHING, BigInt = JSVAL_TYPE_BIGINT, -#ifdef ENABLE_RECORD_TUPLE - ExtendedPrimitive = JSVAL_TYPE_EXTENDED_PRIMITIVE, -#endif Object = JSVAL_TYPE_OBJECT, }; } // namespace JS @@ -214,10 +208,6 @@ enum JSValueTag : uint32_t { JSVAL_TAG_SYMBOL = JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL, JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING, JSVAL_TAG_BIGINT = JSVAL_TAG_CLEAR | JSVAL_TYPE_BIGINT, -# ifdef ENABLE_RECORD_TUPLE - JSVAL_TAG_EXTENDED_PRIMITIVE = - JSVAL_TAG_CLEAR | JSVAL_TYPE_EXTENDED_PRIMITIVE, -# endif JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT }; @@ -237,10 +227,6 @@ enum JSValueTag : uint32_t { JSVAL_TAG_SYMBOL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL, JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING, JSVAL_TAG_BIGINT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BIGINT, -# ifdef ENABLE_RECORD_TUPLE - JSVAL_TAG_EXTENDED_PRIMITIVE = - JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_EXTENDED_PRIMITIVE, -# endif JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT }; @@ -262,10 +248,6 @@ enum JSValueShiftedTag : uint64_t { JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (uint64_t(JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT), JSVAL_SHIFTED_TAG_BIGINT = (uint64_t(JSVAL_TAG_BIGINT) << JSVAL_TAG_SHIFT), -# ifdef ENABLE_RECORD_TUPLE - JSVAL_SHIFTED_TAG_EXTENDED_PRIMITIVE = - (uint64_t(JSVAL_TYPE_EXTENDED_PRIMITIVE) << JSVAL_TAG_SHIFT), -# endif JSVAL_SHIFTED_TAG_OBJECT = (uint64_t(JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) }; @@ -403,14 +385,7 @@ class JS_PUBLIC_API GenericPrinter; class JSONPrinter; static inline JS::Value PoisonedObjectValue(uintptr_t poison); -#ifdef ENABLE_RECORD_TUPLE -// Re-defined in vm/RecordTupleBoxShared.h. We cannot include that -// file because it circularly includes this one. -bool IsExtendedPrimitive(const JSObject& obj); -namespace gc { -bool MaybeForwardedIsExtendedPrimitive(const JSObject& obj); -} // namespace gc -#endif + } // namespace js namespace JS { @@ -631,23 +606,10 @@ class alignas(8) Value { void setObject(JSObject& obj) { MOZ_ASSERT(js::gc::IsCellPointerValid(&obj)); -#ifdef ENABLE_RECORD_TUPLE - MOZ_ASSERT(!js::gc::MaybeForwardedIsExtendedPrimitive(obj)); -#endif setObjectNoCheck(&obj); MOZ_ASSERT(&toObject() == &obj); } -#ifdef ENABLE_RECORD_TUPLE - void setExtendedPrimitive(JSObject& obj) { - MOZ_ASSERT(js::gc::IsCellPointerValid(&obj)); - MOZ_ASSERT(js::gc::MaybeForwardedIsExtendedPrimitive(obj)); - asBits_ = - bitsFromTagAndPayload(JSVAL_TAG_EXTENDED_PRIMITIVE, PayloadType(&obj)); - MOZ_ASSERT(&toExtendedPrimitive() == &obj); - } -#endif - void changeGCThingPayload(js::gc::Cell* cell) { MOZ_ASSERT(js::gc::IsCellPointerValid(cell)); #ifdef DEBUG @@ -813,6 +775,8 @@ class alignas(8) Value { bool isDouble() const { return detail::ValueIsDouble(asBits_); } + bool isNaN() const { return isDouble() && std::isnan(toDouble()); } + bool isNumber() const { #if defined(JS_NUNBOX32) MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR); @@ -837,16 +801,6 @@ class alignas(8) Value { #endif } -#ifdef ENABLE_RECORD_TUPLE - bool isExtendedPrimitive() const { - return toTag() == JSVAL_TAG_EXTENDED_PRIMITIVE; - } -#endif - - bool hasObjectPayload() const { - return isObject() || IF_RECORD_TUPLE(isExtendedPrimitive(), false); - } - bool isPrimitive() const { #if defined(JS_NUNBOX32) return uint32_t(toTag()) < uint32_t(detail::ValueUpperExclPrimitiveTag); @@ -910,11 +864,6 @@ class alignas(8) Value { if (MOZ_UNLIKELY(isPrivateGCThing())) { return JS::GCThingTraceKind(toGCThing()); } -#ifdef ENABLE_RECORD_TUPLE - if (isExtendedPrimitive()) { - return JS::TraceKind::Object; - } -#endif return JS::TraceKind(toTag() & 0x03); } @@ -990,24 +939,6 @@ class alignas(8) Value { #endif } -#ifdef ENABLE_RECORD_TUPLE - JSObject& toExtendedPrimitive() const { - MOZ_ASSERT(isExtendedPrimitive()); -# if defined(JS_PUNBOX64) - MOZ_ASSERT((asBits_ & detail::ValueGCThingPayloadMask) != 0); -# endif - return *unboxGCPointer(); - } -#endif - - JSObject& getObjectPayload() const { -#ifdef ENABLE_RECORD_TUPLE - return isExtendedPrimitive() ? toExtendedPrimitive() : toObject(); -#else - return toObject(); -#endif - } - js::gc::Cell* toGCThing() const { MOZ_ASSERT(isGCThing()); #if defined(JS_NUNBOX32) @@ -1224,14 +1155,6 @@ static inline Value ObjectValue(JSObject& obj) { return v; } -#ifdef ENABLE_RECORD_TUPLE -static inline Value ExtendedPrimitiveValue(JSObject& obj) { - Value v; - v.setExtendedPrimitive(obj); - return v; -} -#endif - static inline Value MagicValue(JSWhyMagic why) { Value v; v.setMagic(why); @@ -1329,6 +1252,10 @@ struct BarrierMethods { static gc::Cell* asGCThingOrNull(const JS::Value& v) { return v.isGCThing() ? v.toGCThing() : nullptr; } + static void writeBarriers(JS::Value* v, const JS::Value& prev, + const JS::Value& next) { + JS::HeapValueWriteBarriers(v, prev, next); + } static void postWriteBarrier(JS::Value* v, const JS::Value& prev, const JS::Value& next) { JS::HeapValuePostWriteBarrier(v, prev, next); @@ -1370,10 +1297,6 @@ class WrappedPtrOperations { bool isSymbol() const { return value().isSymbol(); } bool isBigInt() const { return value().isBigInt(); } bool isObject() const { return value().isObject(); } -#ifdef ENABLE_RECORD_TUPLE - bool isExtendedPrimitive() const { return value().isExtendedPrimitive(); } -#endif - bool hasObjectPayload() const { return value().hasObjectPayload(); } bool isMagic() const { return value().isMagic(); } bool isMagic(JSWhyMagic why) const { return value().isMagic(why); } bool isGCThing() const { return value().isGCThing(); } @@ -1393,12 +1316,6 @@ class WrappedPtrOperations { JS::BigInt* toBigInt() const { return value().toBigInt(); } JSObject& toObject() const { return value().toObject(); } JSObject* toObjectOrNull() const { return value().toObjectOrNull(); } -#ifdef ENABLE_RECORD_TUPLE - JSObject& toExtendedPrimitive() const { - return value().toExtendedPrimitive(); - } -#endif - JSObject& getObjectPayload() const { return value().getObjectPayload(); } JS::GCCellPtr toGCCellPtr() const { return value().toGCCellPtr(); } gc::Cell* toGCThing() const { return value().toGCThing(); } JS::TraceKind traceKind() const { return value().traceKind(); } @@ -1448,11 +1365,6 @@ class MutableWrappedPtrOperations void setBigInt(JS::BigInt* bi) { set(JS::BigIntValue(bi)); } void setObject(JSObject& obj) { set(JS::ObjectValue(obj)); } void setObjectOrNull(JSObject* arg) { set(JS::ObjectOrNullValue(arg)); } -#ifdef ENABLE_RECORD_TUPLE - void setExtendedPrimitive(JSObject& obj) { - return set(JS::ExtendedPrimitiveValue(obj)); - } -#endif void setPrivate(void* ptr) { set(JS::PrivateValue(ptr)); } void setPrivateUint32(uint32_t ui) { set(JS::PrivateUint32Value(ui)); } void setPrivateGCThing(js::gc::Cell* cell) { @@ -1481,11 +1393,8 @@ auto MapGCThingTyped(const JS::Value& val, F&& f) { MOZ_ASSERT(gc::IsCellPointerValid(str)); return mozilla::Some(f(str)); } -#ifdef ENABLE_RECORD_TUPLE - case JS::ValueType::ExtendedPrimitive: -#endif case JS::ValueType::Object: { - JSObject* obj = &val.getObjectPayload(); + JSObject* obj = &val.toObject(); MOZ_ASSERT(gc::IsCellPointerValid(obj)); return mozilla::Some(f(obj)); } diff --git a/src/third_party/mozjs/include/js/WasmFeatures.h b/src/third_party/mozjs/include/js/WasmFeatures.h index 30c1bcca26b..82fb41e7e58 100644 --- a/src/third_party/mozjs/include/js/WasmFeatures.h +++ b/src/third_party/mozjs/include/js/WasmFeatures.h @@ -42,11 +42,6 @@ #else # define WASM_RELAXED_SIMD_ENABLED 0 #endif -#ifdef ENABLE_WASM_GC -# define WASM_GC_ENABLED 1 -#else -# define WASM_GC_ENABLED 0 -#endif #ifdef ENABLE_WASM_MEMORY64 # define WASM_MEMORY64_ENABLED 1 #else @@ -57,11 +52,6 @@ #else # define WASM_MEMORY_CONTROL_ENABLED 0 #endif -#ifdef ENABLE_WASM_TAIL_CALLS -# define WASM_TAIL_CALLS_ENABLED 1 -#else -# define WASM_TAIL_CALLS_ENABLED 0 -#endif #ifdef ENABLE_WASM_JSPI # define WASM_JSPI_ENABLED 1 #else @@ -99,15 +89,6 @@ /* flag force enable */ false, \ /* flag fuzz enable */ true, \ /* preference name */ exnref) \ - FEATURE( \ - /* capitalized name */ Gc, \ - /* lower case name */ gc, \ - /* compile predicate */ WASM_GC_ENABLED, \ - /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ true, \ - /* flag force enable */ false, \ - /* flag fuzz enable */ false, \ - /* preference name */ gc) \ FEATURE( \ /* capitalized name */ JSStringBuiltins, \ /* lower case name */ jsStringBuiltins, \ @@ -153,30 +134,21 @@ /* flag force enable */ false, \ /* flag fuzz enable */ true, \ /* preference name */ multi_memory) \ - FEATURE( \ - /* capitalized name */ TailCalls, \ - /* lower case name */ tailCalls, \ - /* compile predicate */ WASM_TAIL_CALLS_ENABLED, \ - /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ true, \ - /* flag force enable */ false, \ - /* flag fuzz enable */ true, \ - /* preference name */ tail_calls) \ FEATURE( \ /* capitalized name */ JSPromiseIntegration, \ /* lower case name */ jsPromiseIntegration, \ /* compile predicate */ WASM_JSPI_ENABLED, \ - /* compiler predicate */ IonAvailable(cx), \ + /* compiler predicate */ IonPlatformSupport(), \ /* flag predicate */ true, \ /* flag force enable */ false, \ - /* flag fuzz enable */ false, \ + /* flag fuzz enable */ true, \ /* preference name */ js_promise_integration) \ FEATURE( \ /* capitalized name */ MozIntGemm, \ /* lower case name */ mozIntGemm, \ /* compile predicate */ WASM_MOZ_INTGEMM_ENABLED, \ /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ IsSimdPrivilegedContext(cx), \ + /* flag predicate */ IsPrivilegedContext(cx), \ /* flag force enable */ false, \ /* flag fuzz enable */ false, \ /* preference name */ moz_intgemm) \ @@ -196,7 +168,7 @@ /* compiler predicate */ IonAvailable(cx), \ /* flag predicate */ true, \ /* flag force enable */ false, \ - /* flag fuzz enable */ false, \ + /* flag fuzz enable */ true, \ /* preference name */ branch_hinting) // clang-format on diff --git a/src/third_party/mozjs/include/js/Wrapper.h b/src/third_party/mozjs/include/js/Wrapper.h index 197d76f11fc..75f1e3132dd 100644 --- a/src/third_party/mozjs/include/js/Wrapper.h +++ b/src/third_party/mozjs/include/js/Wrapper.h @@ -255,6 +255,9 @@ class JS_PUBLIC_API CrossCompartmentWrapper : public Wrapper { // Allocate CrossCompartmentWrappers in the nursery. virtual bool canNurseryAllocate() const override { return true; } + void finalize(JS::GCContext* gcx, JSObject* proxy) const final { + Wrapper::finalize(gcx, proxy); + } static const CrossCompartmentWrapper singleton; static const CrossCompartmentWrapper singletonWithPrototype; diff --git a/src/third_party/mozjs/include/js/experimental/BindingAllocs.h b/src/third_party/mozjs/include/js/experimental/BindingAllocs.h new file mode 100644 index 00000000000..d033cbda61d --- /dev/null +++ b/src/third_party/mozjs/include/js/experimental/BindingAllocs.h @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Special allocation functions for DOM binding code. + * + */ + +#ifndef js_experimental_BindingAllocs_h +#define js_experimental_BindingAllocs_h + +#include "jstypes.h" + +/** + * Unlike JS_NewObject, JS_NewObjectWithGivenProtoAndUseAllocSite does not + * compute a default proto. If proto is nullptr, the JS object will have `null` + * as [[Prototype]]. + * + * If the JIT code has set an allocation site, this allocation will consume that + * allocation site. This only happens for DOM calls with Object return type. + * + * Must be called with a non-null clasp. + * + */ +extern JS_PUBLIC_API JSObject* JS_NewObjectWithGivenProtoAndUseAllocSite( + JSContext* cx, const JSClass* clasp, JS::Handle proto); + +#endif // js_experimental_BindingAllocs_h diff --git a/src/third_party/mozjs/include/js/experimental/JSStencil.h b/src/third_party/mozjs/include/js/experimental/JSStencil.h index 780c3e1c627..5423f28c295 100644 --- a/src/third_party/mozjs/include/js/experimental/JSStencil.h +++ b/src/third_party/mozjs/include/js/experimental/JSStencil.h @@ -38,6 +38,7 @@ struct CompilationStencil; struct CompilationGCOutput; struct CompilationInput; struct PreallocatedCompilationGCOutput; +struct InitialStencilAndDelazifications; } // namespace frontend } // namespace js @@ -47,7 +48,7 @@ struct PreallocatedCompilationGCOutput; namespace JS { -using Stencil = js::frontend::CompilationStencil; +using Stencil = js::frontend::InitialStencilAndDelazifications; using FrontendContext = js::FrontendContext; // Temporary storage used during instantiating Stencil. @@ -193,6 +194,7 @@ extern JS_PUBLIC_API JSObject* InstantiateModuleStencil( namespace JS { // Serialize the Stencil into the transcode buffer. +// This fails if the stencil contains asm.js. extern JS_PUBLIC_API TranscodeResult EncodeStencil(JSContext* cx, Stencil* stencil, TranscodeBuffer& buffer); @@ -205,10 +207,59 @@ extern JS_PUBLIC_API TranscodeResult DecodeStencil(JS::FrontendContext* fc, const ReadOnlyDecodeOptions& options, const TranscodeRange& range, Stencil** stencilOut); -// Register an encoder on its script source, such that all functions can be -// encoded as they are delazified. -extern JS_PUBLIC_API bool StartIncrementalEncoding(JSContext* cx, - RefPtr&& stencil); +// ************************************************************************ +// Collect delazifications +// ************************************************************************ + +// Start collecting delazifications for given script or module's source object. +// +// If the source object is already collecting delazifications, alreadyStarted is +// set to true and returns true. alreadyStarted is set to false otherwise. +extern JS_PUBLIC_API bool StartCollectingDelazifications( + JSContext* cx, JS::Handle script, Stencil* stencil, + bool& alreadyStarted); + +extern JS_PUBLIC_API bool StartCollectingDelazifications( + JSContext* cx, JS::Handle module, Stencil* stencil, + bool& alreadyStarted); + +// Finish collecting delazifications and retrieve the result. +// +// With |buffer| out-parameter, the result is encoded and appended to the +// buffer. If failed, the content of |buffer| would be undefined. +// +// If the `buffer` isn't empty, the start of the `buffer` should meet +// JS::IsTranscodingBytecodeAligned, and the length should meet +// JS::IsTranscodingBytecodeOffsetAligned. +// +// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means +// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, +// IsTranscodingBytecodeAligned should be guaranteed to meet by +// malloc, used by MallocAllocPolicy in mozilla::Vector. +extern JS_PUBLIC_API bool FinishCollectingDelazifications( + JSContext* cx, Handle script, TranscodeBuffer& buffer); + +// Similar to |JS::FinishCollectingDelazifications|, but receives module obect. +extern JS_PUBLIC_API bool FinishCollectingDelazifications( + JSContext* cx, Handle module, TranscodeBuffer& buffer); + +// Instead of transcoding to a buffer, return the JS::Stencil that reflects +// the delazification from the execution. +extern JS_PUBLIC_API bool FinishCollectingDelazifications( + JSContext* cx, Handle script, JS::Stencil** stencilOut); + +extern JS_PUBLIC_API void AbortCollectingDelazifications( + Handle script); +extern JS_PUBLIC_API void AbortCollectingDelazifications( + Handle module); + +// ************************************************************************ +// Cache +// ************************************************************************ + +// Returns true if the stencil is compatible with caching. +// This returns false if the stencil contains asm.js. +extern JS_PUBLIC_API bool IsStencilCacheable(JS::Stencil* stencil); } // namespace JS diff --git a/src/third_party/mozjs/include/js/experimental/LoggingInterface.h b/src/third_party/mozjs/include/js/experimental/LoggingInterface.h new file mode 100644 index 00000000000..4ee3c13f384 --- /dev/null +++ b/src/third_party/mozjs/include/js/experimental/LoggingInterface.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// An experimental logging interface for connecting the JS Engine to some +// (*cough*Gecko*cough*) consumer. + +#ifndef _js_experimental_LoggingInterface_h_ +#define _js_experimental_LoggingInterface_h_ + +#include "mozilla/LoggingCore.h" + +#include "jstypes.h" +#include "fmt/format.h" +#include "js/GCAPI.h" + +struct JSContext; + +namespace JS { + +// An Opaque pointer to a LoggerType. It must be possible for this logger type +// to conform to the interface below, using the LogLevel type exported in +// mozglue LoggingCore.h +// +// There are some requirements that we cannot express through the type-system: +// +// - A Logger must outlive any caller. This is an obvious statement, but in the +// context of the JS engine means that a logger must live until after the JS +// engine is shutdown. +// - A logger cannot move. The logging interfaces assumes 1) That an +// OpaqueLogger will remain a valid handle to a logger for the entire duration +// of an initialize JS library, and 2) We are able to cache a reference to the +// log level of a particular logger (see getLevelRef below). +using OpaqueLogger = void*; + +// [SMDOC] Logging Interface +// +// The logging interface contains a set of function pointers which explain how +// to talk to an embedder provided logging system. +// +// The design of the JS Consumer of this relies heavily on these to be freely +// copyable. +struct LoggingInterface { + // Acquire a new logger for a given name. + // + // This interface has no way of indicating backwards that a logger is no + // longer needed, and as such this pointer needs to be kept alive by the + // embedding for the lifetime of the JS engine. + OpaqueLogger (*getLoggerByName)(const char* loggerName) = nullptr; + + // Print a message to a particular logger with a particular level and + // format. + void (*logPrintVA)(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + const char* aFmt, va_list ap) + MOZ_FORMAT_PRINTF(3, 0) = nullptr; + + void (*logPrintFMT)(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + fmt::string_view, fmt::format_args); + + // Return a reference to the provided OpaqueLogger's level ref; Implementation + // wise this can be a small violation of encapsulation but is intended to help + // ensure that we can build lightweight logging without egregious costs to + // simply check even if a mesage will the writen + mozilla::AtomicLogLevel& (*getLevelRef)(OpaqueLogger) = nullptr; + + // Wrapper function for calling va-version + void logPrint(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + const char* aFmt, ...) MOZ_FORMAT_PRINTF(4, 5) { + JS::AutoSuppressGCAnalysis suppress; + va_list ap; + va_start(ap, aFmt); + this->logPrintVA(aModule, aLevel, aFmt, ap); + va_end(ap); + } + + template + void logPrintFmt(const OpaqueLogger aModule, mozilla::LogLevel aLevel, + fmt::format_string aFmt, T&&... aArgs) { + JS::AutoSuppressGCAnalysis suppress; + this->logPrintFMT(aModule, aLevel, aFmt, fmt::make_format_args(aArgs...)); + } + + // Used to ensure that before we use an interface, it's successfully been + // completely filled in. + bool isComplete() const { + return getLoggerByName && logPrintVA && getLevelRef; + } +}; + +// Install the logging interface. This will also install the interface into +// any JS loggers +extern JS_PUBLIC_API bool SetLoggingInterface(LoggingInterface& iface); + +} // namespace JS + +#endif /* _js_experimental_LoggingInterface_h_ */ diff --git a/src/third_party/mozjs/include/js/experimental/TypedData.h b/src/third_party/mozjs/include/js/experimental/TypedData.h index 39d691b039d..61bb1306d67 100644 --- a/src/third_party/mozjs/include/js/experimental/TypedData.h +++ b/src/third_party/mozjs/include/js/experimental/TypedData.h @@ -135,8 +135,6 @@ namespace js { extern JS_PUBLIC_API JSObject* UnwrapArrayBufferView(JSObject* obj); -extern JS_PUBLIC_API JSObject* UnwrapReadableStream(JSObject* obj); - namespace detail { constexpr size_t TypedArrayLengthSlot = 1; @@ -710,6 +708,11 @@ struct BarrierMethods> { static gc::Cell* asGCThingOrNull(T view) { return reinterpret_cast(view.asObjectUnbarriered()); } + static void writeBarriers(T* viewp, T prev, T next) { + BarrierMethods::writeBarriers(viewp->addressOfObject(), + prev.asObjectUnbarriered(), + next.asObjectUnbarriered()); + } static void postWriteBarrier(T* viewp, T prev, T next) { BarrierMethods::postWriteBarrier(viewp->addressOfObject(), prev.asObjectUnbarriered(), diff --git a/src/third_party/mozjs/include/js/friend/ErrorNumbers.msg b/src/third_party/mozjs/include/js/friend/ErrorNumbers.msg index 3155e3179e7..e01318afe3e 100644 --- a/src/third_party/mozjs/include/js/friend/ErrorNumbers.msg +++ b/src/third_party/mozjs/include/js/friend/ErrorNumbers.msg @@ -136,7 +136,7 @@ MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class construc MSG_DEF(JSMSG_BAD_HERITAGE, 2, JSEXN_TYPEERR, "class heritage {0} is {1}") MSG_DEF(JSMSG_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0} is not an object or null") MSG_DEF(JSMSG_CONSTRUCTOR_DISABLED, 1, JSEXN_TYPEERR, "{0} is disabled") -MSG_DEF(JSMSG_NO_DISPOSE_IN_USING, 0, JSEXN_TYPEERR, "'Symbol.dispose' property is not callable") +MSG_DEF(JSMSG_DISPOSE_NOT_CALLABLE, 0, JSEXN_TYPEERR, "'Symbol.dispose' property is not callable") MSG_DEF(JSMSG_DISPOSABLE_NOT_OBJ, 0, JSEXN_TYPEERR, "Value to be disposed is not an object") // JSON @@ -225,8 +225,11 @@ MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC, 0, JSEXN_SYNTAXERR, "await is only valid MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC_OR_MODULE, 0, JSEXN_SYNTAXERR, "await is only valid in async functions, async generators and modules") MSG_DEF(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "top level await is not supported in this context") MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)") +MSG_DEF(JSMSG_BAD_CLASS_MEMBER_DEF, 0, JSEXN_SYNTAXERR, "bad class member definition") MSG_DEF(JSMSG_BAD_COALESCE_MIXING, 0, JSEXN_SYNTAXERR, "cannot use `??` unparenthesized within `||` and `&&` expressions") MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration") +MSG_DEF(JSMSG_BAD_USING_DECL, 0, JSEXN_SYNTAXERR, "missing = in using declaration") +MSG_DEF(JSMSG_BAD_CONSTRUCTOR_DEF, 0, JSEXN_SYNTAXERR, "a class constructor definition must be a plain public method") MSG_DEF(JSMSG_BAD_CONTINUE, 0, JSEXN_SYNTAXERR, "continue must be inside loop") MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 0, JSEXN_SYNTAXERR, "invalid destructuring assignment operator") MSG_DEF(JSMSG_BAD_DESTRUCT_TARGET, 0, JSEXN_SYNTAXERR, "invalid destructuring target") @@ -239,7 +242,6 @@ MSG_DEF(JSMSG_BAD_STARTING_FOROF_LHS, 1, JSEXN_SYNTAXERR, "an expression X in ' MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand") MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side") MSG_DEF(JSMSG_BAD_LOCAL_STRING_EXPORT, 0, JSEXN_SYNTAXERR, "string exports can't be used without 'from'") -MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition") MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'") MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id") MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function") @@ -258,6 +260,7 @@ MSG_DEF(JSMSG_BRACKET_OPENED, 2, JSEXN_NOTE, "[ opened at line {0}, col MSG_DEF(JSMSG_CATCH_IDENTIFIER, 0, JSEXN_SYNTAXERR, "missing identifier in catch") MSG_DEF(JSMSG_CATCH_OR_FINALLY, 0, JSEXN_SYNTAXERR, "missing catch or finally after try") MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "catch without try") +MSG_DEF(JSMSG_CLASS_STATIC_PROTO, 0, JSEXN_SYNTAXERR, "a class may not have a static property named 'prototype'") MSG_DEF(JSMSG_COLON_AFTER_CASE, 0, JSEXN_SYNTAXERR, "missing : after case label") MSG_DEF(JSMSG_COLON_AFTER_ID, 0, JSEXN_SYNTAXERR, "missing : after property id") MSG_DEF(JSMSG_COLON_IN_COND, 0, JSEXN_SYNTAXERR, "missing : in conditional expression") @@ -282,10 +285,10 @@ MSG_DEF(JSMSG_DEPRECATED_OCTAL_LITERAL,0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal MSG_DEF(JSMSG_DEPRECATED_OCTAL_ESCAPE ,0, JSEXN_SYNTAXERR, "octal escape sequences can't be used in untagged template literals or in strict mode code") MSG_DEF(JSMSG_DEPRECATED_EIGHT_OR_NINE_ESCAPE, 0, JSEXN_SYNTAXERR, "the escapes \\8 and \\9 can't be used in untagged template literals or in strict mode code") MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_WARN, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead") +MSG_DEF(JSMSG_DUPLICATE_CONSTRUCTOR, 0, JSEXN_SYNTAXERR, "a class cannot have more than one constructor definition") MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export name '{0}'") MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}") MSG_DEF(JSMSG_DUPLICATE_LABEL, 0, JSEXN_SYNTAXERR, "duplicate label") -MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal") MSG_DEF(JSMSG_DUPLICATE_PROTO_PROPERTY, 0, JSEXN_SYNTAXERR, "property name __proto__ appears more than once in object literal") MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?") MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level of a module") @@ -328,7 +331,7 @@ MSG_DEF(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT, 0, JSEXN_SYNTAXERR, "expected n MSG_DEF(JSMSG_NO_BINDING_NAME, 0, JSEXN_SYNTAXERR, "missing binding name") MSG_DEF(JSMSG_NO_EXPORT_NAME, 0, JSEXN_SYNTAXERR, "missing export name") MSG_DEF(JSMSG_NO_IMPORT_NAME, 0, JSEXN_SYNTAXERR, "missing import name") -MSG_DEF(JSMSG_NO_VARIABLE_NAME, 0, JSEXN_SYNTAXERR, "missing variable name") +MSG_DEF(JSMSG_NO_VARIABLE_NAME, 1, JSEXN_SYNTAXERR, "missing variable name, got {0}") MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 0, JSEXN_SYNTAXERR, "missing ) after argument list") MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing ) after catch") MSG_DEF(JSMSG_PAREN_AFTER_COND, 0, JSEXN_SYNTAXERR, "missing ) after condition") @@ -388,7 +391,7 @@ MSG_DEF(JSMSG_BAD_LINE_NUMBER, 0, JSEXN_RANGEERR, "line number out of ra MSG_DEF(JSMSG_BAD_NEWTARGET, 0, JSEXN_SYNTAXERR, "new.target only allowed within functions") MSG_DEF(JSMSG_BAD_NEW_OPTIONAL, 0, JSEXN_SYNTAXERR, "new keyword cannot be used with an optional chain") MSG_DEF(JSMSG_BAD_OPTIONAL_TEMPLATE, 0, JSEXN_SYNTAXERR, "tagged template cannot be used with optional chain") -MSG_DEF(JSMSG_IMPORT_ASSERTIONS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "import assertions are not currently supported") +MSG_DEF(JSMSG_IMPORT_ATTRIBUTES_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "import attributes are not currently supported") MSG_DEF(JSMSG_ILLEGAL_PRIVATE_FIELD, 0, JSEXN_SYNTAXERR, "private fields aren't valid in this context") MSG_DEF(JSMSG_ILLEGAL_PRIVATE_NAME, 0, JSEXN_SYNTAXERR, "private names aren't valid in this context") MSG_DEF(JSMSG_INVALID_PRIVATE_NAME_PRECEDENCE, 0, JSEXN_SYNTAXERR, "invalid use of private name due to operator precedence") @@ -419,10 +422,6 @@ MSG_DEF(JSMSG_CANT_CONVERT_TO_WIDE, 0, JSEXN_ERR, "can't convert to wide stri MSG_DEF(JSMSG_CANT_CONVERT_WIDE_TO_UTF8, 0, JSEXN_ERR, "can't convert wide string to UTF-8") MSG_DEF(JSMSG_CANT_CONVERT_UTF8_TO_WIDE, 0, JSEXN_ERR, "can't convert UTF-8 to wide string") -// SmooshMonkey -MSG_DEF(JSMSG_SMOOSH_COMPILE_ERROR, 1, JSEXN_SYNTAXERR, "{0}") -MSG_DEF(JSMSG_SMOOSH_UNIMPLEMENTED, 1, JSEXN_INTERNALERR, "{0}") - // asm.js MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}") MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 1, JSEXN_TYPEERR, "asm.js link error: {0}") @@ -437,7 +436,7 @@ MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}") MSG_DEF(JSMSG_WASM_BAD_IMPORT_TYPE, 2, JSEXN_WASMLINKERROR, "import object field '{0}' is not a {1}") MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 2, JSEXN_WASMLINKERROR, "imported function '{0}.{1}' signature mismatch") MSG_DEF(JSMSG_WASM_BAD_TAG_SIG, 2, JSEXN_WASMLINKERROR, "imported tag '{0}.{1}' signature mismatch") -MSG_DEF(JSMSG_WASM_BAD_IMP_INDEX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible index type") +MSG_DEF(JSMSG_WASM_BAD_IMP_ADDRESS, 2, JSEXN_WASMLINKERROR, "imported {0} with incompatible address type {1}") MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible size") MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible maximum size") MSG_DEF(JSMSG_WASM_IMP_SHARED_REQD, 0, JSEXN_WASMLINKERROR, "imported unshared memory but shared required") @@ -464,6 +463,7 @@ MSG_DEF(JSMSG_WASM_ARRAY_IMP_LIMIT, 0, JSEXN_WASMRUNTIMEERROR, "too many arra MSG_DEF(JSMSG_WASM_ARRAY_NEW_ELEM_NOT_IMPLEMENTED, 0, JSEXN_WASMRUNTIMEERROR, "array.new_elem does not yet support the expression encoding of element segments") MSG_DEF(JSMSG_WASM_BAD_RANGE, 2, JSEXN_RANGEERR, "bad {0} {1}") MSG_DEF(JSMSG_WASM_BAD_GROW, 1, JSEXN_RANGEERR, "failed to grow {0}") +MSG_DEF(JSMSG_WASM_MAX_LT_INITIAL, 1, JSEXN_RANGEERR, "initial {0} size cannot be greater than maximum") MSG_DEF(JSMSG_WASM_TABLE_OUT_OF_BOUNDS, 0, JSEXN_WASMRUNTIMEERROR, "table index out of bounds") MSG_DEF(JSMSG_WASM_BAD_ENFORCE_RANGE, 2, JSEXN_TYPEERR, "bad {0} {1}") MSG_DEF(JSMSG_WASM_BAD_BUF_ARG, 0, JSEXN_TYPEERR, "first argument must be an ArrayBuffer or typed array object") @@ -485,15 +485,15 @@ MSG_DEF(JSMSG_WASM_BAD_ARRAYREF_VALUE, 0, JSEXN_TYPEERR, "can only pass a W MSG_DEF(JSMSG_WASM_BAD_TYPEREF_VALUE, 0, JSEXN_TYPEERR, "bad type") MSG_DEF(JSMSG_WASM_BAD_VAL_TYPE, 0, JSEXN_TYPEERR, "cannot pass value to or from JS") MSG_DEF(JSMSG_WASM_BAD_STRING_VAL_TYPE, 0, JSEXN_TYPEERR, "bad value type") -MSG_DEF(JSMSG_WASM_BAD_STRING_IDX_TYPE, 0, JSEXN_TYPEERR, "bad index type") +MSG_DEF(JSMSG_WASM_BAD_STRING_ADDR_TYPE, 0, JSEXN_TYPEERR, "bad address type") MSG_DEF(JSMSG_WASM_BAD_EXN_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Tag") MSG_DEF(JSMSG_WASM_BAD_EXN_PAYLOAD, 0, JSEXN_TYPEERR, "second argument must be an object") MSG_DEF(JSMSG_WASM_BAD_EXN_PAYLOAD_LEN, 2, JSEXN_TYPEERR, "expected {0} values but got {1}") MSG_DEF(JSMSG_WASM_BAD_EXN_TAG, 0, JSEXN_TYPEERR, "exception's tag did not match the provided exception tag") MSG_DEF(JSMSG_WASM_BAD_EXN_OPTIONS, 0, JSEXN_TYPEERR, "argument cannot be converted to an ExceptionOptions") +MSG_DEF(JSMSG_WASM_BAD_FUNCTION_TYPE, 1, JSEXN_TYPEERR, "too many function {0}") MSG_DEF(JSMSG_WASM_BAD_FUNCTION_VALUE, 0, JSEXN_TYPEERR, "second argument must be a function") MSG_DEF(JSMSG_WASM_BAD_COMPILE_OPTIONS, 0, JSEXN_TYPEERR, "argument cannot be converted to a CompileOptions") -MSG_DEF(JSMSG_WASM_UNKNOWN_BUILTIN, 0, JSEXN_TYPEERR, "unknown builtin") MSG_DEF(JSMSG_WASM_DUPLICATE_BUILTIN, 0, JSEXN_TYPEERR, "duplicate builtin") MSG_DEF(JSMSG_WASM_BAD_CODEPOINT, 0, JSEXN_WASMRUNTIMEERROR, "bad codepoint") MSG_DEF(JSMSG_WASM_NO_TRANSFER, 0, JSEXN_TYPEERR, "cannot transfer WebAssembly/asm.js ArrayBuffer") @@ -505,15 +505,22 @@ MSG_DEF(JSMSG_WASM_NONSHARED_WAIT, 0, JSEXN_WASMRUNTIMEERROR, "atomic wait o MSG_DEF(JSMSG_WASM_SUPPLY_ONLY_ONE, 2, JSEXN_TYPEERR, "exactly one of {0} and {1} must be supplied") MSG_DEF(JSMSG_WASM_MISSING_REQUIRED, 1, JSEXN_TYPEERR, "Missing required argument {0}") MSG_DEF(JSMSG_WASM_MODIFIED_GC_OBJECT, 0, JSEXN_TYPEERR, "can't modify WebAssembly GC objects") +MSG_DEF(JSMSG_WASM_ARRAYBUFFER_PAGE_MULTIPLE, 0, JSEXN_RANGEERR, "can only grow by WebAssembly page multiples") +MSG_DEF(JSMSG_WASM_ARRAYBUFFER_CANNOT_SHRINK, 0, JSEXN_RANGEERR, "cannot shrink WebAssembly memory") +MSG_DEF(JSMSG_WASM_MEMORY_NOT_RESIZABLE, 0, JSEXN_TYPEERR, "WebAssembly memory non-resizable, maximum length is not provided") + +// Wasm/asm.js deprecation warnings +MSG_DEF(JSMSG_WASM_LEGACY_EXCEPTIONS_DEPRECATED, 0, JSEXN_WARN, "The WebAssembly exception handling 'try' instruction is deprecated and should no longer be used. Please recompile to use the 'try_table' instruction instead.") +MSG_DEF(JSMSG_USE_ASM_DEPRECATED, 0, JSEXN_WARN, "asm.js is deprecated and should no longer be used. Please recompile using WebAssembly to get the best performance.") // JSPI -MSG_DEF(JSMSG_JSPI_ARG_POSITION, 0, JSEXN_TYPEERR, "Invalid argument position value") -MSG_DEF(JSMSG_JSPI_INVALID_SUSPENDER, 0, JSEXN_WASMRUNTIMEERROR, "Invalid suspender") -MSG_DEF(JSMSG_JSPI_INVALID_STATE, 0, JSEXN_WASMRUNTIMEERROR, "Invalid state") -MSG_DEF(JSMSG_JSPI_EXPECTED_SUSPENDER, 0, JSEXN_TYPEERR, "Expected externref for suspender") -MSG_DEF(JSMSG_JSPI_EXPECTED_PROMISE, 0, JSEXN_TYPEERR, "Expected externref for returned promise") -MSG_DEF(JSMSG_JSPI_SIGNATURE_MISMATCH, 0, JSEXN_TYPEERR, "Signature mismatch") -MSG_DEF(JSMSG_JSPI_SUSPENDER_LIMIT, 0, JSEXN_WASMRUNTIMEERROR, "Too many suspenders") +MSG_DEF(JSMSG_JSPI_ARG_POSITION, 0, JSEXN_TYPEERR, "Invalid argument position value") +MSG_DEF(JSMSG_JSPI_INVALID_SUSPENDER, 0, IF_WASM_JSPI(JSEXN_WASMSUSPENDERROR, JSEXN_WASMRUNTIMEERROR), "Invalid suspender") +MSG_DEF(JSMSG_JSPI_INVALID_STATE, 0, IF_WASM_JSPI(JSEXN_WASMSUSPENDERROR, JSEXN_WASMRUNTIMEERROR), "Invalid state") +MSG_DEF(JSMSG_JSPI_EXPECTED_SUSPENDER, 0, JSEXN_TYPEERR, "Expected externref for suspender") +MSG_DEF(JSMSG_JSPI_EXPECTED_PROMISE, 0, JSEXN_TYPEERR, "Expected externref for returned promise") +MSG_DEF(JSMSG_JSPI_SIGNATURE_MISMATCH, 0, JSEXN_TYPEERR, "Signature mismatch") +MSG_DEF(JSMSG_JSPI_SUSPENDER_LIMIT, 0, IF_WASM_JSPI(JSEXN_WASMSUSPENDERROR, JSEXN_WASMRUNTIMEERROR), "Too many suspenders") // Proxy MSG_DEF(JSMSG_BAD_GETPROTOTYPEOF_TRAP_RETURN,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler returned a non-object, non-null value") @@ -595,8 +602,10 @@ MSG_DEF(JSMSG_DEBUGGEE_WOULD_RUN, 2, JSEXN_DEBUGGEEWOULDRUN, "debuggee '{0} MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined") MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true") MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so") -MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'") -MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'displayURL', 'url', or 'source' property") +MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line', or 'start' and 'end', and either 'displayURL', 'url', or 'source'") +MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 1, JSEXN_TYPEERR, "findScripts query object has {0}, but no 'displayURL', 'url', or 'source' property") +MSG_DEF(JSMSG_QUERY_USE_START_AND_END_TOGETHER, 0, JSEXN_ERR, "findScripts query object's 'start' and 'end' properties must be used together") +MSG_DEF(JSMSG_QUERY_START_LINE_IS_AFTER_END, 0, JSEXN_ERR, "findScripts query object's 'start.line' property is greater than its 'end.line' property, but it must be less than or equal to 'end.line'") MSG_DEF(JSMSG_DEBUG_CANT_SET_OPT_ENV, 1, JSEXN_REFERENCEERR, "can't set '{0}' in an optimized-out environment") MSG_DEF(JSMSG_DEBUG_INVISIBLE_COMPARTMENT, 0, JSEXN_TYPEERR, "object in compartment marked as invisible to Debugger") MSG_DEF(JSMSG_DEBUG_CENSUS_BREAKDOWN, 1, JSEXN_TYPEERR, "unrecognized 'by' value in takeCensus breakdown: {0}") @@ -606,6 +615,8 @@ MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_FULFILLED, 0, JSEXN_TYPEERR, "Promise hasn't bee MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_REJECTED, 0, JSEXN_TYPEERR, "Promise hasn't been rejected") MSG_DEF(JSMSG_DEBUG_NO_BINARY_SOURCE, 0, JSEXN_ERR, "WebAssembly binary source is not available") MSG_DEF(JSMSG_DEBUG_EXCLUSIVE_FRAME_COVERAGE, 0, JSEXN_ERR, "onEnterFrame and collectCoverageInfo cannot be active at the same time") +MSG_DEF(JSMSG_DEBUG_EXCLUSIVE_EXECUTION_TRACE_COVERAGE, 0, JSEXN_ERR, "execution trace and collectCoverageInfo cannot be active at the same time") +MSG_DEF(JSMSG_NATIVE_TRACING_BUFFER_MALFORMED, 0, JSEXN_ERR, "bad data encountered while reading the native tracing buffer") // Testing functions MSG_DEF(JSMSG_TESTING_SCRIPTS_ONLY, 0, JSEXN_TYPEERR, "only works on scripts") @@ -628,7 +639,7 @@ MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 1, JSEXN_RANGEERR, "invalid locale matche MSG_DEF(JSMSG_INVALID_OPTION_VALUE, 2, JSEXN_RANGEERR, "invalid value {1} for option {0}") MSG_DEF(JSMSG_INVALID_TIME_ZONE, 1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}") MSG_DEF(JSMSG_INVALID_DATETIME_OPTION, 2, JSEXN_TYPEERR, "can't set option {0} when {1} is used") -MSG_DEF(JSMSG_INVALID_DATETIME_STYLE, 2, JSEXN_TYPEERR, "can't set option {0} in Date.{1}()") +MSG_DEF(JSMSG_INVALID_DATETIME_STYLE, 2, JSEXN_TYPEERR, "can't set option {0} for {1} formats") MSG_DEF(JSMSG_UNDEFINED_CURRENCY, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style") MSG_DEF(JSMSG_UNDEFINED_UNIT, 0, JSEXN_TYPEERR, "undefined unit in NumberFormat() with unit style") MSG_DEF(JSMSG_UNDEFINED_DATE, 2, JSEXN_TYPEERR, "undefined {0}-date in DateTimeFormat.{1}()") @@ -637,6 +648,16 @@ MSG_DEF(JSMSG_UNDEFINED_TYPE, 0, JSEXN_TYPEERR, "missing \"type\" optio MSG_DEF(JSMSG_NAN_NUMBER_RANGE, 3, JSEXN_RANGEERR, "range can't {0} with NaN in {1}.{2}()") MSG_DEF(JSMSG_INVALID_NUMBER_OPTION, 2, JSEXN_TYPEERR, "can't set option {0} when {1} is used") MSG_DEF(JSMSG_UNEQUAL_FRACTION_DIGITS, 0, JSEXN_RANGEERR, "fraction digits must be the same when roundingIncrement is used") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_NON_NUMERIC_OPTION, 2, JSEXN_RANGEERR, "invalid non-numeric value {0} for option {1}") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION, 1, JSEXN_RANGEERR, "{0} can't use \"numeric\" style with \"always\" display") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_STYLE, 1, JSEXN_RANGEERR, "{0} can't use \"always\" display when style defaults to \"numeric\"") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_DISPLAY_OPTION_DEFAULT_DISPLAY, 1, JSEXN_RANGEERR, "{0} can't use \"numeric\" style when display defaults to \"always\"") +MSG_DEF(JSMSG_INTL_DURATION_NOT_INTEGER, 1, JSEXN_RANGEERR, "{0} isn't a valid duration value because it isn't an integer") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_SIGN, 0, JSEXN_RANGEERR, "duration elements must have the same sign") +MSG_DEF(JSMSG_INTL_DURATION_INVALID_LIMIT, 0, JSEXN_RANGEERR, "duration elements must be below valid limits") +MSG_DEF(JSMSG_INTL_DURATION_MISSING_UNIT, 0, JSEXN_TYPEERR, "Duration-like objects must have at least one duration unit") +MSG_DEF(JSMSG_INTL_DURATION_UNEXPECTED_STRING, 0, JSEXN_RANGEERR, "duration can't be a string") +MSG_DEF(JSMSG_INVALID_FORMAT_OPTIONS, 1, JSEXN_TYPEERR, "can't format {0} using the requested options") // RegExp MSG_DEF(JSMSG_BAD_CLASS_RANGE, 0, JSEXN_SYNTAXERR, "invalid range in character class") @@ -644,6 +665,8 @@ MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 0, JSEXN_SYNTAXERR, "\\ at end of pattern MSG_DEF(JSMSG_EXEC_NOT_OBJORNULL, 0, JSEXN_TYPEERR, "RegExp exec method should return object or null") MSG_DEF(JSMSG_INVALID_DECIMAL_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid decimal escape in regular expression") MSG_DEF(JSMSG_INVALID_GROUP, 0, JSEXN_SYNTAXERR, "invalid regexp group") +MSG_DEF(JSMSG_REPEATED_FLAG, 0, JSEXN_SYNTAXERR, "repeated flag in regexp modifier") +MSG_DEF(JSMSG_INVALID_FLAG_GROUP, 0, JSEXN_SYNTAXERR, "invalid flag group") MSG_DEF(JSMSG_INVALID_IDENTITY_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid identity escape in regular expression") MSG_DEF(JSMSG_INVALID_UNICODE_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid unicode escape in regular expression") MSG_DEF(JSMSG_MISSING_PAREN, 0, JSEXN_SYNTAXERR, "unterminated parenthetical") @@ -668,6 +691,7 @@ MSG_DEF(JSMSG_INCOMPATIBLE_REGEXP_GETTER, 2, JSEXN_TYPEERR, "RegExp.prototype.{ MSG_DEF(JSMSG_INVALID_CLASS_SET_OP, 0, JSEXN_SYNTAXERR, "invalid class set operation in regular expression") MSG_DEF(JSMSG_INVALID_CHAR_IN_CLASS, 0, JSEXN_SYNTAXERR, "invalid character in class in regular expression") MSG_DEF(JSMSG_NEGATED_CLASS_WITH_STR, 0, JSEXN_SYNTAXERR, "negated character class with strings in regular expression") +MSG_DEF(JSMSG_MULTIPLE_FLAG_DASHES, 0, JSEXN_SYNTAXERR, "multiple dashes in flag group") // Typed object MSG_DEF(JSMSG_TYPEDOBJECT_SETTING_IMMUTABLE, 0, JSEXN_ERR, "setting immutable field") @@ -726,6 +750,7 @@ MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol t // Atomics and futexes MSG_DEF(JSMSG_ATOMICS_BAD_ARRAY, 0, JSEXN_TYPEERR, "invalid array type for the operation") MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 0, JSEXN_TYPEERR, "waiting is not allowed on this thread") +MSG_DEF(JSMSG_ATOMICS_PAUSE_BAD_COUNT, 0, JSEXN_TYPEERR, "Atomics.pause called with non-integral Number") // XPConnect wrappers and DOM bindings MSG_DEF(JSMSG_CANT_SET_INTERPOSED, 1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'") @@ -733,7 +758,7 @@ MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't define elemen MSG_DEF(JSMSG_CANT_DELETE_WINDOW_ELEMENT, 0, JSEXN_TYPEERR, "can't delete elements from a Window object") MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_NAMED_PROPERTY, 1, JSEXN_TYPEERR, "can't define property {0} on window's named properties object") MSG_DEF(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY, 1, JSEXN_TYPEERR, "can't delete property {0} from window's named properties object") -MSG_DEF(JSMSG_CANT_PREVENT_EXTENSIONS, 0, JSEXN_TYPEERR, "can't prevent extensions on this proxy object") +MSG_DEF(JSMSG_CANT_PREVENT_EXTENSIONS, 0, JSEXN_TYPEERR, "can't prevent extensions on this object") MSG_DEF(JSMSG_CANT_DEFINE_WINDOW_NC, 0, JSEXN_TYPEERR, "can't define non-configurable property on WindowProxy") MSG_DEF(JSMSG_NO_NAMED_SETTER, 2, JSEXN_TYPEERR, "{0} doesn't have a named property setter for '{1}'") MSG_DEF(JSMSG_NO_INDEXED_SETTER, 2, JSEXN_TYPEERR, "{0} doesn't have an indexed property setter for '{1}'") @@ -759,6 +784,7 @@ MSG_DEF(JSMSG_IMPORT_MAPS_NOT_A_MAP, 0, JSEXN_TYPEERR, "the top-level value need MSG_DEF(JSMSG_IMPORT_MAPS_IMPORTS_NOT_A_MAP, 0, JSEXN_TYPEERR, "the imports top-level key needs to be a JSON object") MSG_DEF(JSMSG_IMPORT_MAPS_SCOPES_NOT_A_MAP, 0, JSEXN_TYPEERR, "the scopes top-level key needs to be a JSON object") MSG_DEF(JSMSG_IMPORT_MAPS_SCOPE_VALUE_NOT_A_MAP, 1, JSEXN_TYPEERR, "the value of the scope with prefix '{0}' needs to be a JSON object") +MSG_DEF(JSMSG_IMPORT_MAPS_INTEGRITY_NOT_A_MAP, 0, JSEXN_TYPEERR, "the integrity top-level key needs to be a JSON object") // Import Attributes MSG_DEF(JSMSG_IMPORT_ATTRIBUTES_STATIC_IMPORT_UNSUPPORTED_ATTRIBUTE, 1, JSEXN_SYNTAXERR, "Unsupported import attribute: {0}") @@ -785,29 +811,6 @@ MSG_DEF(JSMSG_NOT_AN_ASYNC_GENERATOR, 0, JSEXN_TYPEERR, "Not an async generator MSG_DEF(JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.asyncIterator]() returned a non-object value") MSG_DEF(JSMSG_SUSPENDED_QUEUE_NOT_EMPTY, 0, JSEXN_INTERNALERR, "Async generator is in invalid state due to debugger interaction") -// ReadableStream -MSG_DEF(JSMSG_READABLESTREAM_UNDERLYINGSOURCE_TYPE_WRONG,0, JSEXN_RANGEERR,"'underlyingSource.type' must be \"bytes\" or undefined.") -MSG_DEF(JSMSG_READABLESTREAM_BYTES_TYPE_NOT_IMPLEMENTED, 0, JSEXN_RANGEERR,"support for 'new ReadableStream({ type: \"bytes\" })' is not yet implemented") -MSG_DEF(JSMSG_READABLESTREAM_BYOB_READER_FOR_NON_BYTE_STREAM,0,JSEXN_TYPEERR,"can't get a BYOB reader for a non-byte stream") -MSG_DEF(JSMSG_READABLESTREAM_INVALID_READER_MODE, 0, JSEXN_TYPEERR,"'mode' must be \"byob\" or undefined.") -MSG_DEF(JSMSG_NUMBER_MUST_BE_FINITE_NON_NEGATIVE, 1, JSEXN_RANGEERR, "'{0}' must be a finite, non-negative number.") -MSG_DEF(JSMSG_READABLESTREAM_LOCKED_METHOD, 1, JSEXN_TYPEERR, "'{0}' can't be called on a locked stream.") -MSG_DEF(JSMSG_READABLESTREAM_LOCKED, 0, JSEXN_TYPEERR, "A Reader may only be created for an unlocked ReadableStream.") -MSG_DEF(JSMSG_READABLESTREAM_NOT_DEFAULT_CONTROLLER, 1, JSEXN_TYPEERR, "{0} requires a ReadableStreamDefaultController.") -MSG_DEF(JSMSG_READABLESTREAMREADER_NOT_OWNED, 1, JSEXN_TYPEERR, "The ReadableStream reader method '{0}' may only be called on a reader owned by a stream.") -MSG_DEF(JSMSG_READABLESTREAMREADER_NOT_EMPTY, 1, JSEXN_TYPEERR, "The ReadableStream reader method '{0}' may not be called on a reader with read requests.") -MSG_DEF(JSMSG_READABLESTREAMREADER_RELEASED, 0, JSEXN_TYPEERR, "The ReadableStream reader was released.") -MSG_DEF(JSMSG_READABLESTREAMCONTROLLER_CLOSED, 1, JSEXN_TYPEERR, "'{0}' called on a stream already closing.") -MSG_DEF(JSMSG_READABLESTREAMCONTROLLER_NOT_READABLE, 1, JSEXN_TYPEERR, "'{0}' may only be called on a stream in the 'readable' state.") -MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_BAD_CHUNKSIZE,0, JSEXN_RANGEERR, "ReadableByteStreamController requires a positive integer or undefined for 'autoAllocateChunkSize'.") -MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_BAD_CHUNK, 1, JSEXN_TYPEERR, "{0} passed a bad chunk.") -MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_CLOSE_PENDING_PULL, 0, JSEXN_TYPEERR, "The ReadableByteStreamController cannot be closed while the buffer is being filled.") - -// Other Stream-related -MSG_DEF(JSMSG_STREAM_MISSING_HIGHWATERMARK, 0, JSEXN_TYPEERR, "'highWaterMark' must not be undefined.") -MSG_DEF(JSMSG_STREAM_INVALID_HIGHWATERMARK, 0, JSEXN_RANGEERR, "'highWaterMark' must be a non-negative, non-NaN number.") -MSG_DEF(JSMSG_STREAM_CONSUME_ERROR, 0, JSEXN_TYPEERR, "error consuming stream body") - // (wasm) Response-related MSG_DEF(JSMSG_WASM_ERROR_CONSUMING_RESPONSE, 0, JSEXN_TYPEERR, "WebAssembly: There was an error consuming the Response") MSG_DEF(JSMSG_WASM_BAD_RESPONSE_VALUE, 0, JSEXN_TYPEERR, "WebAssembly: Expected Response or Promise resolving to Response") @@ -841,15 +844,6 @@ MSG_DEF(JSMSG_NEGATIVE_LIMIT, 0, JSEXN_RANGEERR, "Ite // Set MSG_DEF(JSMSG_SET_NEGATIVE_SIZE, 0, JSEXN_RANGEERR, "Set size must be non-negative") -// Record and Tuple -MSG_DEF(JSMSG_RECORD_TUPLE_NO_OBJECT, 0, JSEXN_TYPEERR, "Record and Tuple can only contain primitive values") -MSG_DEF(JSMSG_RECORD_NO_PROTO, 0, JSEXN_SYNTAXERR, "__proto__ is not a valid literal key in records") -MSG_DEF(JSMSG_RECORD_NO_SYMBOL_KEY, 0, JSEXN_TYPEERR, "Symbols cannot be used as record keys") -MSG_DEF(JSMSG_BAD_TUPLE_INDEX, 0, JSEXN_RANGEERR, "index out of range for tuple") -MSG_DEF(JSMSG_BAD_TUPLE_OBJECT, 0, JSEXN_TYPEERR, "value of TupleObject must be a Tuple") -MSG_DEF(JSMSG_RECORD_TUPLE_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert Record or Tuple to number") - - // Shadow Realms MSG_DEF(JSMSG_NOT_SHADOW_REALM, 0, JSEXN_TYPEERR, "Object is not a ShadowRealm") MSG_DEF(JSMSG_SHADOW_REALM_EVALUATE_NOT_STRING, 0, JSEXN_TYPEERR, "a ShadowRealm can only evaluate a string") @@ -872,86 +866,109 @@ MSG_DEF(JSMSG_TEMPORAL_INVALID_UNIT_RANGE, 0, JSEXN_RANGEERR, "smallest MSG_DEF(JSMSG_TEMPORAL_INVALID_UNIT_OPTION, 2, JSEXN_RANGEERR, "{0} is not a valid {1} option in this context") MSG_DEF(JSMSG_TEMPORAL_INVALID_NUMBER, 1, JSEXN_RANGEERR, "{0} must be larger than zero") MSG_DEF(JSMSG_TEMPORAL_INVALID_INTEGER, 1, JSEXN_RANGEERR, "{0} must be an integer") -MSG_DEF(JSMSG_TEMPORAL_INVALID_OBJECT, 2, JSEXN_TYPEERR, "{0} must not be a {1} object") -MSG_DEF(JSMSG_TEMPORAL_MISSING_OPTION, 1, JSEXN_RANGEERR, "undefined {0} option") -MSG_DEF(JSMSG_TEMPORAL_MISSING_PROPERTY, 1, JSEXN_TYPEERR, "{0} property is undefined") -MSG_DEF(JSMSG_TEMPORAL_UNEXPECTED_PROPERTY, 1, JSEXN_TYPEERR, "{0} property is not undefined") +MSG_DEF(JSMSG_TEMPORAL_MISSING_OPTION, 1, JSEXN_RANGEERR, "required option {0} is undefined") +MSG_DEF(JSMSG_TEMPORAL_MISSING_PROPERTY, 1, JSEXN_TYPEERR, "required property {0} is undefined") +MSG_DEF(JSMSG_TEMPORAL_UNEXPECTED_PROPERTY, 1, JSEXN_TYPEERR, "expected property {0} to be undefined") MSG_DEF(JSMSG_TEMPORAL_MISSING_TEMPORAL_FIELDS, 0, JSEXN_TYPEERR, "object must have at least one temporal property") -MSG_DEF(JSMSG_TEMPORAL_DUPLICATE_PROPERTY, 1, JSEXN_RANGEERR, "duplicate property name \"{0}\"") -MSG_DEF(JSMSG_TEMPORAL_INVALID_PROPERTY, 1, JSEXN_RANGEERR, "invalid property name \"{0}\"") MSG_DEF(JSMSG_TEMPORAL_INSTANT_INVALID, 0, JSEXN_RANGEERR, "epoch nanoseconds too large") MSG_DEF(JSMSG_TEMPORAL_INSTANT_NONINTEGER, 1, JSEXN_RANGEERR, "Instant must be an integer, but received {0}") MSG_DEF(JSMSG_TEMPORAL_INSTANT_BAD_DURATION, 1, JSEXN_RANGEERR, "duration \"{0}\" property must be zero") MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_INVALID_IDENTIFIER, 1, JSEXN_RANGEERR, "invalid time zone: {0}") -MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_NANOS_RANGE, 1, JSEXN_RANGEERR, "nanoseconds out of range: {0}") MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_INCOMPATIBLE, 2, JSEXN_RANGEERR, "time zones \"{0}\" and \"{1}\" aren't compatible") MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_INSTANT_AMBIGUOUS, 0, JSEXN_RANGEERR, "instant is ambiguous") -MSG_DEF(JSMSG_TEMPORAL_TIMEZONE_OFFSET_SHIFT_ONE_DAY, 0, JSEXN_RANGEERR, "time zone offset shift must not exceed a 24-hour span") MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_SIGN, 2, JSEXN_RANGEERR, "duration value \"{0}\" has a mismatched sign: {1}") -MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE, 2, JSEXN_RANGEERR, "duration value \"{0}\" is {1}") -MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME, 0, JSEXN_RANGEERR, "time duration values must be lower than 2**53 seconds") +MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NON_FINITE, 2, JSEXN_RANGEERR, "duration value \"{0}\" is non-finite: {1}") +MSG_DEF(JSMSG_TEMPORAL_DURATION_INVALID_NORMALIZED_TIME, 0, JSEXN_RANGEERR, "time duration values must be smaller than 2**53 seconds") MSG_DEF(JSMSG_TEMPORAL_DURATION_MISSING_UNIT, 0, JSEXN_TYPEERR, "Duration-like objects must have at least one duration unit") MSG_DEF(JSMSG_TEMPORAL_DURATION_NOT_INTEGER, 2, JSEXN_RANGEERR, "{0} isn't a valid {1} duration because it isn't an integer") MSG_DEF(JSMSG_TEMPORAL_DURATION_MISSING_UNIT_SPECIFIER, 0, JSEXN_RANGEERR, "at least one of \"smallestUnit\" and \"largestUnit\" must be present") MSG_DEF(JSMSG_TEMPORAL_DURATION_UNCOMPARABLE, 1, JSEXN_RANGEERR, "can't compare durations when \"{0}\" is undefined") -MSG_DEF(JSMSG_TEMPORAL_DURATION_COMBINE_INVALID_SIGN, 0, JSEXN_RANGEERR, "can't combine date- and time-durations with different signs") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_ID, 1, JSEXN_RANGEERR, "invalid calendar: {0}") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_MISSING_FIELD, 1, JSEXN_TYPEERR, "missing \"{0}\" calendar field") -MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_FIELD, 1, JSEXN_RANGEERR, "invalid calendar field name \"{0}\"") -MSG_DEF(JSMSG_TEMPORAL_CALENDAR_DUPLICATE_FIELD, 1, JSEXN_RANGEERR, "duplicate calendar field \"{0}\"") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_OVERFLOW_FIELD, 2, JSEXN_RANGEERR, "calendar field \"{0}\" is too large: {1}") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_MONTHCODE, 1, JSEXN_RANGEERR, "invalid \"monthCode\" calendar field: {0}") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INVALID_ERA, 1, JSEXN_RANGEERR, "invalid \"era\" calendar field: {0}") MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE, 2, JSEXN_RANGEERR, "calendars \"{0}\" and \"{1}\" aren't compatible") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid iso dates") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_YEAR, 2, JSEXN_RANGEERR, "\"year\" and computed \"year\" calendar fields are inconsistent: {0} - {1}") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE_MONTHCODE, 2, JSEXN_RANGEERR, "\"monthCode\" and \"month\" calendar fields are inconsistent: {0} - {1}") +MSG_DEF(JSMSG_TEMPORAL_CALENDAR_INTERNAL_ERROR, 0, JSEXN_ERR, "internal error while computing calendar data") +MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid ISO date values") MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_INVALID_VALUE, 4, JSEXN_RANGEERR, "date value \"{0}\" not in {1}..{2}: {3}") MSG_DEF(JSMSG_TEMPORAL_PLAIN_DATE_TIME_INVALID, 0, JSEXN_RANGEERR, "arguments must be valid ISO date-time values") MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_INVALID, 0, JSEXN_RANGEERR, "arguments must be valid ISO time values") MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_INVALID_VALUE, 4, JSEXN_RANGEERR, "time value \"{0}\" not in {1}..{2}: {3}") MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_MISSING_UNIT, 0, JSEXN_TYPEERR, "Time-like objects must have at least one time unit") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_TIME_CALENDAR_NOT_ISO8601, 1, JSEXN_RANGEERR, "PlainTime only supports the \"iso8601\" calendar: {0}") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid iso dates") -MSG_DEF(JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID, 0, JSEXN_RANGEERR, "year-month-day must be valid iso dates") +MSG_DEF(JSMSG_TEMPORAL_PLAIN_MONTH_DAY_INVALID, 0, JSEXN_RANGEERR, "month-day must be valid ISO date values") +MSG_DEF(JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID, 0, JSEXN_RANGEERR, "year-month must be valid ISO date values") MSG_DEF(JSMSG_TEMPORAL_ZONED_DATE_TIME_NO_TIME_FOUND, 0, JSEXN_RANGEERR, "date-time can't be represented in the given time zone") -MSG_DEF(JSMSG_TEMPORAL_ZONED_DATE_TIME_INCORRECT_SIGN, 1, JSEXN_RANGEERR, "computed {0} has an incorrect sign") MSG_DEF(JSMSG_TEMPORAL_ZONED_DATE_TIME_INCONSISTENT_INSTANT, 0, JSEXN_RANGEERR, "time zone computed inconsistent instant values") -MSG_DEF(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR, 0, JSEXN_RANGEERR, "year 0 must not start with \"-\"") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR, 0, JSEXN_RANGEERR, "signed year must be followed by six digits") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_YEAR, 0, JSEXN_RANGEERR, "missing four digit year") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MONTH, 0, JSEXN_RANGEERR, "missing two digit month") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DAY, 0, JSEXN_RANGEERR, "missing two digit day") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_HOUR, 0, JSEXN_RANGEERR, "missing two digit hour") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE, 0, JSEXN_RANGEERR, "missing two digit minute") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_SECOND, 0, JSEXN_RANGEERR, "missing two digit second") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_SIGN, 0, JSEXN_RANGEERR, "missing time zone sign") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MONTH, 0, JSEXN_RANGEERR, "month must be a number from 1 to 12") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DAY, 0, JSEXN_RANGEERR, "day must be a number from 1 to 31") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_HOUR, 0, JSEXN_RANGEERR, "hour must be a number from 0 to 23") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE, 0, JSEXN_RANGEERR, "minute must be a number from 0 to 59") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SECOND, 0, JSEXN_RANGEERR, "second must be a number from 0 to 59") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND, 0, JSEXN_RANGEERR, "second must be a number from 0 to 60") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_TIMEZONE, 0, JSEXN_RANGEERR, "missing '[' before time zone annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_TIMEZONE, 0, JSEXN_RANGEERR, "missing ']' after time zone annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE, 0, JSEXN_RANGEERR, "missing time zone") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_NAME, 0, JSEXN_RANGEERR, "missing time zone name") -MSG_DEF(JSMSG_TEMPORAL_PARSER_GARBAGE_AFTER_INPUT, 0, JSEXN_RANGEERR, "unexpected garbage after end of input") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DESIGNATOR, 0, JSEXN_RANGEERR, "missing duration designator 'P'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIME_DESIGNATOR, 0, JSEXN_RANGEERR, "missing time designator 'T'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS, 0, JSEXN_RANGEERR, "missing duration digits") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_MINUTES, 0, JSEXN_RANGEERR, "invalid duration minutes after fractional hours") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_SECONDS, 0, JSEXN_RANGEERR, "invalid duration seconds after fractional hours or minutes") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_KEY, 0, JSEXN_RANGEERR, "invalid annotation key") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_VALUE, 0, JSEXN_RANGEERR, "invalid annotation value") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_CALENDAR_NAME, 0, JSEXN_RANGEERR, "invalid calendar name") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_ANNOTATION, 0, JSEXN_RANGEERR, "missing ']' before annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_ANNOTATION, 0, JSEXN_RANGEERR, "missing ']' after annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_ASSIGNMENT_IN_ANNOTATION, 0, JSEXN_RANGEERR, "missing '=' in annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_CRITICAL_ANNOTATION, 0, JSEXN_RANGEERR, "unexpected critical annotation") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DATE_TIME_SEPARATOR, 0, JSEXN_RANGEERR, "missing date-time separator 'T'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_MONTH_DAY, 0, JSEXN_RANGEERR, "time is ambiguous with a month-day") -MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_YEAR_MONTH, 0, JSEXN_RANGEERR, "time is ambiguous with a year-month") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR, 0, JSEXN_RANGEERR, "unexpected UTC designator 'Z'") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME, 0, JSEXN_RANGEERR, "unexpected UTC designator 'Z' without a bracketed time zone") -MSG_DEF(JSMSG_TEMPORAL_PARSER_MONTH_DAY_CALENDAR_NOT_ISO8601, 0, JSEXN_RANGEERR, "Month-Day formats only support the \"iso8601\" calendar") -MSG_DEF(JSMSG_TEMPORAL_PARSER_YEAR_MONTH_CALENDAR_NOT_ISO8601, 0, JSEXN_RANGEERR, "Year-Month formats only support the \"iso8601\" calendar") -MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE, 0, JSEXN_RANGEERR, "time zone offset must not contain seconds precision") +MSG_DEF(JSMSG_TEMPORAL_PARSER_NEGATIVE_ZERO_YEAR, 1, JSEXN_RANGEERR, "can't parse {0}: year 0 must not start with \"-\"") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_EXTENDED_YEAR, 1, JSEXN_RANGEERR, "can't parse {0}: signed year must be followed by six digits") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_YEAR, 1, JSEXN_RANGEERR, "can't parse {0}: missing four digit year") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MONTH, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit month") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DAY, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit day") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_HOUR, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit hour") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_MINUTE, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit minute") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_SECOND, 1, JSEXN_RANGEERR, "can't parse {0}: missing two digit second") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_SIGN, 1, JSEXN_RANGEERR, "can't parse {0}: missing time zone sign") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MONTH, 1, JSEXN_RANGEERR, "can't parse {0}: month must be a number from 1 to 12") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DAY, 1, JSEXN_RANGEERR, "can't parse {0}: day must be a number from 1 to 31") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_HOUR, 1, JSEXN_RANGEERR, "can't parse {0}: hour must be a number from 0 to 23") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_MINUTE, 1, JSEXN_RANGEERR, "can't parse {0}: minute must be a number from 0 to 59") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SECOND, 1, JSEXN_RANGEERR, "can't parse {0}: second must be a number from 0 to 59") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_LEAPSECOND, 1, JSEXN_RANGEERR, "can't parse {0}: second must be a number from 0 to 60") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: missing '[' before time zone annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: missing ']' after time zone annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: missing time zone") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIMEZONE_NAME, 1, JSEXN_RANGEERR, "can't parse {0}: missing time zone name") +MSG_DEF(JSMSG_TEMPORAL_PARSER_UNEXPECTED_CHARACTERS_AT_END, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected characters at end of string") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing duration designator 'P'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_TIME_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing time designator 'T'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_DIGITS, 1, JSEXN_RANGEERR, "can't parse {0}: missing duration digits") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DURATION_UNIT_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing duration unit designator") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_MINUTES, 1, JSEXN_RANGEERR, "can't parse {0}: invalid duration minutes after fractional hours") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_DURATION_SECONDS, 1, JSEXN_RANGEERR, "can't parse {0}: invalid duration seconds after fractional hours or minutes") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_KEY, 1, JSEXN_RANGEERR, "can't parse {0}: invalid annotation key") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_ANNOTATION_VALUE, 1, JSEXN_RANGEERR, "can't parse {0}: invalid annotation value") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_BEFORE_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: missing '[' before annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_BRACKET_AFTER_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: missing ']' after annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_ASSIGNMENT_IN_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: missing '=' in annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_CRITICAL_ANNOTATION, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected critical annotation") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MISSING_DATE_TIME_SEPARATOR, 1, JSEXN_RANGEERR, "can't parse {0}: missing date-time separator 'T'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_MONTH_DAY, 1, JSEXN_RANGEERR, "can't parse {0}: time is ambiguous with a month-day") +MSG_DEF(JSMSG_TEMPORAL_PARSER_AMBIGUOUS_TIME_YEAR_MONTH, 1, JSEXN_RANGEERR, "can't parse {0}: time is ambiguous with a year-month") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected UTC designator 'Z'") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_UTC_DESIGNATOR_WITHOUT_NAME, 1, JSEXN_RANGEERR, "can't parse {0}: unexpected UTC designator 'Z' without a bracketed time zone") +MSG_DEF(JSMSG_TEMPORAL_PARSER_MONTH_DAY_CALENDAR_NOT_ISO8601, 1, JSEXN_RANGEERR, "can't parse {0}: Month-Day formats only support the \"iso8601\" calendar") +MSG_DEF(JSMSG_TEMPORAL_PARSER_YEAR_MONTH_CALENDAR_NOT_ISO8601, 1, JSEXN_RANGEERR, "can't parse {0}: Year-Month formats only support the \"iso8601\" calendar") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INVALID_SUBMINUTE_TIMEZONE, 1, JSEXN_RANGEERR, "can't parse {0}: time zone offset must not contain seconds precision") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INCONSISTENT_DATE_SEPARATOR, 1, JSEXN_RANGEERR, "can't parse {0}: date separator '-' must be consistent") +MSG_DEF(JSMSG_TEMPORAL_PARSER_INCONSISTENT_TIME_SEPARATOR, 1, JSEXN_RANGEERR, "can't parse {0}: time separator ':' must be consistent") +MSG_DEF(JSMSG_TEMPORAL_PARSER_EMPTY_STRING, 1, JSEXN_RANGEERR, "can't parse empty string as {0}") + +// Explicit Resource Management + +// TODO: Improve the messaging for suppressed errors (Bug 1906150) +MSG_DEF(JSMSG_ERROR_WAS_SUPPRESSED, 0, IF_EXPLICIT_RESOURCE_MANAGEMENT(JSEXN_SUPPRESSEDERR, JSEXN_INTERNALERR), "An error is suppressed because another error happened while disposing an object") + +// DisposableStack +MSG_DEF(JSMSG_DISPOSABLE_STACK_DISPOSED, 0, JSEXN_REFERENCEERR, "DisposableStack has already been disposed") + +// Iterator.range +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_START, 0, JSEXN_TYPEERR, "The 'start' argument must be a number or BigInt") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_START_RANGEERR, 0, JSEXN_RANGEERR, "The 'start' argument cannot be NaN") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_END_RANGEERR, 0, JSEXN_RANGEERR, "The 'end' argument cannot be NaN") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_END, 0, JSEXN_TYPEERR, "The 'end' argument must be a number or BigInt") +MSG_DEF(JSMSG_ITERATOR_RANGE_START_INFINITY, 0, JSEXN_RANGEERR, "The 'start' argument must be a finite number") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NAN, 0, JSEXN_RANGEERR, "The 'step' argument must not be NaN") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NOT_NUMBER, 0, JSEXN_TYPEERR, "The 'step' argument must be a number") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NOT_FINITE, 0, JSEXN_RANGEERR, "The 'step' argument must be a finite number") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_ZERO, 0, JSEXN_RANGEERR, "The 'step' argument must not be zero when 'start' is not equal to 'end'") +MSG_DEF(JSMSG_ITERATOR_RANGE_INVALID_STEP, 0, JSEXN_TYPEERR, "The 'step' or options argument must be a valid number, BigInt, or an Object with valid properties") +MSG_DEF(JSMSG_ITERATOR_RANGE_STEP_NOT_BIGINT, 0, JSEXN_TYPEERR, "The 'step' argument must be a BigInt when iterating over BigInt ranges") + +// Math.sumPrecise +MSG_DEF(JSMSG_SUMPRECISE_TOO_MANY_VALUES, 0, JSEXN_RANGEERR, "too many values passed to Math.sumPrecise") +MSG_DEF(JSMSG_SUMPRECISE_EXPECTED_NUMBER, 0, JSEXN_TYPEERR, "values passed to Math.sumPrecise must be numbers") //clang-format on diff --git a/src/third_party/mozjs/include/js/friend/JSMEnvironment.h b/src/third_party/mozjs/include/js/friend/JSMEnvironment.h index ad16f2ba626..36d3337c971 100644 --- a/src/third_party/mozjs/include/js/friend/JSMEnvironment.h +++ b/src/third_party/mozjs/include/js/friend/JSMEnvironment.h @@ -45,6 +45,8 @@ namespace JS { +class JS_PUBLIC_API EnvironmentChain; + /** * Allocate a new environment in the current compartment that is compatible with * JSM shared loading. @@ -68,7 +70,7 @@ extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(JSContext* cx, // temporarily placed on the environment chain. extern JS_PUBLIC_API bool ExecuteInJSMEnvironment( JSContext* cx, Handle script, Handle jsmEnv, - Handle> targetObj); + const EnvironmentChain& targetObj); // Used by native methods to determine the JSMEnvironment of caller if possible // by looking at stack frames. Returns nullptr if top frame isn't a scripted diff --git a/src/third_party/mozjs/include/js/friend/UsageStatistics.h b/src/third_party/mozjs/include/js/friend/UsageStatistics.h index 2560dcbbb9f..43862ecc067 100644 --- a/src/third_party/mozjs/include/js/friend/UsageStatistics.h +++ b/src/third_party/mozjs/include/js/friend/UsageStatistics.h @@ -17,12 +17,12 @@ struct JS_PUBLIC_API JSContext; class JS_PUBLIC_API JSObject; /* - * Telemetry reasons passed to the accumulate telemetry callback. + * Legacy telemetry metrics passed to the accumulate telemetry callback. * * It's OK for these enum values to change as they will be mapped to a fixed * member of the mozilla::Telemetry::HistogramID enum by the callback. */ -#define FOR_EACH_JS_METRIC(_) \ +#define FOR_EACH_JS_LEGACY_METRIC(_) \ _(GC_REASON_2, Enumeration) \ _(GC_IS_COMPARTMENTAL, Boolean) \ _(GC_ZONE_COUNT, QuantityDistribution) \ @@ -60,9 +60,6 @@ class JS_PUBLIC_API JSObject; _(GC_TIME_BETWEEN_S, TimeDuration_S) \ _(GC_TIME_BETWEEN_SLICES_MS, TimeDuration_MS) \ _(GC_SLICE_COUNT, QuantityDistribution) \ - _(DESERIALIZE_BYTES, MemoryDistribution) \ - _(DESERIALIZE_ITEMS, QuantityDistribution) \ - _(DESERIALIZE_US, TimeDuration_US) \ _(GC_EFFECTIVENESS, MemoryDistribution) \ _(GC_PARALLEL_MARK, Boolean) \ _(GC_PARALLEL_MARK_SPEEDUP, Integer) \ @@ -70,6 +67,20 @@ class JS_PUBLIC_API JSObject; _(GC_PARALLEL_MARK_INTERRUPTIONS, Integer) \ _(GC_TASK_START_DELAY_US, TimeDuration_US) +/* + * Append any glean only telemetry metrics to the following list. + * However, unlike the legacy list, each glean metric must be manually added + * to the switch statement in AccumulateTelemetryCallback(). + */ +#define FOR_EACH_JS_GLEAN_METRIC(_) \ + _(ION_COMPILE_TIME, TimeDuration_US) \ + _(GC_GLEAN_SLOW_PHASE, Enumeration) \ + _(GC_GLEAN_SLOW_TASK, Enumeration) + +#define FOR_EACH_JS_METRIC(_) \ + FOR_EACH_JS_LEGACY_METRIC(_) \ + FOR_EACH_JS_GLEAN_METRIC(_) + // clang-format off #define ENUM_DEF(NAME, _) NAME, enum class JSMetric { @@ -84,21 +95,29 @@ using JSAccumulateTelemetryDataCallback = void (*)(JSMetric, uint32_t); extern JS_PUBLIC_API void JS_SetAccumulateTelemetryCallback( JSContext* cx, JSAccumulateTelemetryDataCallback callback); -#define FOR_EACH_JS_USE_COUNTER(_) \ - _(ASMJS, AsmJS) \ - _(WASM, Wasm) \ - _(WASM_LEGACY_EXCEPTIONS, WasmLegacyExceptions) \ - _(SUBCLASSING_ARRAY_TYPE_II, SubclassingArrayTypeII) \ - _(SUBCLASSING_ARRAY_TYPE_III, SubclassingArrayTypeIII) \ - _(SUBCLASSING_PROMISE_TYPE_II, SubclassingPromiseTypeII) \ - _(SUBCLASSING_PROMISE_TYPE_III, SubclassingPromiseTypeIII) \ - _(SUBCLASSING_TYPEDARRAY_TYPE_II, SubclassingTypedArrayTypeII) \ - _(SUBCLASSING_TYPEDARRAY_TYPE_III, SubclassingTypedArrayTypeIII) \ - _(SUBCLASSING_ARRAYBUFFER_TYPE_III, SubclassingArrayBufferTypeIII) \ - _(SUBCLASSING_SHAREDARRAYBUFFER_TYPE_III, \ - SubclassingSharedArrayBufferTypeIII) \ - _(SUBCLASSING_REGEXP_TYPE_III, SubclassingRegExpTypeIII) \ - _(SUBCLASSING_REGEXP_TYPE_IV, SubclassingRegExpTypeIV) +#define FOR_EACH_JS_USE_COUNTER(_) \ + _(ASMJS, AsmJS) \ + _(WASM, Wasm) \ + _(WASM_LEGACY_EXCEPTIONS, WasmLegacyExceptions) \ + _(ISHTMLDDA_FUSE, IsHTMLDDAFuse) \ + _(OPTIMIZE_GET_ITERATOR_FUSE, OptimizeGetIteratorFuse) \ + _(THENABLE_USE, ThenableUse) \ + _(THENABLE_USE_PROTO, ThenableUseProto) \ + _(THENABLE_USE_STANDARD_PROTO, ThenableUseStandardProto) \ + _(THENABLE_USE_OBJECT_PROTO, ThenableUseObjectProto) \ + _(LEGACY_LANG_SUBTAG, LegacyLangSubtag) \ + _(IC_STUB_TOO_LARGE, ICStubTooLarge) \ + _(IC_STUB_OOM, ICStubOOM) \ + _(ERRORSTACK_GETTER, ErrorStackGetter) \ + _(ERRORSTACK_GETTER_NO_ERRORDATA, ErrorStackGetterNoErrorData) \ + _(ERRORSTACK_SETTER, ErrorStackSetter) \ + _(ERRORSTACK_SETTER_NONSTRING, ErrorStackSetterNonString) \ + _(ERRORSTACK_SETTER_NO_ERRORDATA, ErrorStackSetterNoErrorData) \ + _(DATEPARSE, DateParse) \ + _(DATEPARSE_IMPL_DEF, DateParseImplDef) \ + _(OPTIMIZE_ARRAY_SPECIES_FUSE, OptimizeArraySpeciesFuse) \ + _(OPTIMIZE_PROMISE_LOOKUP_FUSE, OptimizePromiseLookupFuse) \ + _(REGEXP_SYMBOL_PROTOCOL_ON_PRIMITIVE, RegExpSymbolProtocolOnPrimitive) /* * Use counter names passed to the accumulate use counter callback. diff --git a/src/third_party/mozjs/include/js/shadow/String.h b/src/third_party/mozjs/include/js/shadow/String.h index cae853cc5d9..6e144319993 100644 --- a/src/third_party/mozjs/include/js/shadow/String.h +++ b/src/third_party/mozjs/include/js/shadow/String.h @@ -35,6 +35,7 @@ struct String { static constexpr uint32_t LINEAR_BIT = js::Bit(4); static constexpr uint32_t INLINE_CHARS_BIT = js::Bit(6); static constexpr uint32_t LATIN1_CHARS_BIT = js::Bit(10); + static constexpr uint32_t HAS_STRING_BUFFER_BIT = js::Bit(12); static constexpr uint32_t EXTERNAL_FLAGS = LINEAR_BIT | js::Bit(8); static constexpr uint32_t TYPE_FLAGS_MASK = js::BitMask(10) - js::BitMask(3); static constexpr uint32_t PERMANENT_ATOM_MASK = ATOM_BIT | js::Bit(8); @@ -68,6 +69,7 @@ struct String { bool isLinear() const { return flags() & LINEAR_BIT; } bool hasLatin1Chars() const { return flags() & LATIN1_CHARS_BIT; } + bool hasStringBuffer() const { return flags() & HAS_STRING_BUFFER_BIT; } // For hot code, prefer other type queries. bool isExternal() const { diff --git a/src/third_party/mozjs/include/jsapi.h b/src/third_party/mozjs/include/jsapi.h index ad34f469eb4..c2fdfd016ca 100644 --- a/src/third_party/mozjs/include/jsapi.h +++ b/src/third_party/mozjs/include/jsapi.h @@ -822,9 +822,8 @@ extern JS_PUBLIC_API JSObject* JS_NewObjectForConstructor( /************************************************************************/ -extern JS_PUBLIC_API void JS_SetParallelParsingEnabled(JSContext* cx, - bool enabled); - +extern JS_PUBLIC_API void JS_SetOffthreadBaselineCompilationEnabled( + JSContext* cx, bool enabled); extern JS_PUBLIC_API void JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled); @@ -862,7 +861,8 @@ extern JS_PUBLIC_API void JS_SetOffthreadIonCompilationEnabled(JSContext* cx, Register(WASM_DELAY_TIER2, "wasm.delay-tier2") \ Register(WASM_JIT_BASELINE, "wasm.baseline") \ Register(WASM_JIT_OPTIMIZING, "wasm.optimizing") \ - Register(REGEXP_DUPLICATE_NAMED_GROUPS, "regexp.duplicate-named-groups") // clang-format on + Register(REGEXP_DUPLICATE_NAMED_GROUPS, "regexp.duplicate-named-groups") \ + Register(REGEXP_MODIFIERS, "regexp.modifiers") // clang-format on typedef enum JSJitCompilerOption { #define JIT_COMPILER_DECLARE(key, str) JSJITCOMPILER_##key, @@ -951,9 +951,11 @@ class MOZ_RAII JS_PUBLIC_API AutoFilename { * * If a the embedding has hidden the scripted caller for the topmost activation * record, this will also return false. + * + * This never throws an exception. */ extern JS_PUBLIC_API bool DescribeScriptedCaller( - JSContext* cx, AutoFilename* filename = nullptr, uint32_t* lineno = nullptr, + AutoFilename* filename, JSContext* cx, uint32_t* lineno = nullptr, JS::ColumnNumberOneOrigin* column = nullptr); extern JS_PUBLIC_API JSObject* GetScriptedCallerGlobal(JSContext* cx); diff --git a/src/third_party/mozjs/include/jsfriendapi.h b/src/third_party/mozjs/include/jsfriendapi.h index 85b0cc85496..979969e2ef5 100644 --- a/src/third_party/mozjs/include/jsfriendapi.h +++ b/src/third_party/mozjs/include/jsfriendapi.h @@ -453,7 +453,8 @@ JS_PUBLIC_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base, * * If it is, returns true and outputs the index in *indexp. */ -JS_PUBLIC_API bool StringIsArrayIndex(JSLinearString* str, uint32_t* indexp); +JS_PUBLIC_API bool StringIsArrayIndex(const JSLinearString* str, + uint32_t* indexp); /** * Overload of StringIsArrayIndex taking a (char16_t*,length) pair. Behaves @@ -483,8 +484,11 @@ JS_PUBLIC_API bool IsObjectInContextCompartment(JSObject* obj, using DOMInstanceClassHasProtoAtDepth = bool (*)(const JSClass*, uint32_t, uint32_t); +using DOMInstanceClassIsError = bool (*)(const JSClass*); + struct JSDOMCallbacks { DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto; + DOMInstanceClassIsError instanceClassIsError; }; using DOMCallbacks = struct JSDOMCallbacks; @@ -505,15 +509,12 @@ extern JS_PUBLIC_API JSLinearString* GetErrorTypeName(JSContext* cx, int16_t exnType); /* Implemented in CrossCompartmentWrapper.cpp. */ -typedef enum NukeReferencesToWindow { - NukeWindowReferences, - DontNukeWindowReferences -} NukeReferencesToWindow; +enum NukeReferencesToWindow { NukeWindowReferences, DontNukeWindowReferences }; -typedef enum NukeReferencesFromTarget { +enum NukeReferencesFromTarget { NukeAllReferences, NukeIncomingReferences, -} NukeReferencesFromTarget; +}; /* * These filters are designed to be ephemeral stack classes, and thus don't @@ -708,8 +709,8 @@ extern JS_PUBLIC_API bool IsSavedFrame(JSObject* obj); #if defined(XP_WIN) // Parameters use void* types to avoid #including windows.h. The return value of // this function is returned from the exception handler. -typedef long (*JitExceptionHandler)(void* exceptionRecord, // PEXECTION_RECORD - void* context); // PCONTEXT +using JitExceptionHandler = long (*)(void* exceptionRecord, // PEXECTION_RECORD + void* context); // PCONTEXT /** * Windows uses "structured exception handling" to handle faults. When a fault diff --git a/src/third_party/mozjs/include/jspubtd.h b/src/third_party/mozjs/include/jspubtd.h index e7cd0739965..1f0252677ec 100644 --- a/src/third_party/mozjs/include/jspubtd.h +++ b/src/third_party/mozjs/include/jspubtd.h @@ -43,10 +43,6 @@ enum JSType { JSTYPE_BOOLEAN, /* boolean */ JSTYPE_SYMBOL, /* symbol */ JSTYPE_BIGINT, /* bigint */ -#ifdef ENABLE_RECORD_TUPLE - JSTYPE_RECORD, /* record */ - JSTYPE_TUPLE, /* tuple */ -#endif JSTYPE_LIMIT }; @@ -68,12 +64,6 @@ inline const char* JSTypeToString(JSType type) { return "symbol"; case JSTYPE_BIGINT: return "bigint"; -#ifdef ENABLE_RECORD_TUPLE - case JSTYPE_RECORD: - return "record"; - case JSTYPE_TUPLE: - return "tuple"; -#endif default: MOZ_ASSERT_UNREACHABLE("Unknown JSType"); } diff --git a/src/third_party/mozjs/include/malloc_decls.h b/src/third_party/mozjs/include/malloc_decls.h index ec56344a374..7d63cfcc7b7 100644 --- a/src/third_party/mozjs/include/malloc_decls.h +++ b/src/third_party/mozjs/include/malloc_decls.h @@ -27,6 +27,15 @@ # define MALLOC_FUNCS_ALL \ (MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC | MALLOC_FUNCS_ARENA) +// Some malloc operations require extra includes. Before using this header with +// MALLOC_FUNCS unset or containing MALLOC_FUNCS_JEMALLOC you must include +// this header once, outside a struct/class definition and without MALLOC_DECL +// set and it will include headers it may later need. +# if !defined(MALLOC_DECL) && defined(__cplusplus) +# include +# include "mozilla/Maybe.h" +# endif + #endif // malloc_decls_h #ifndef MALLOC_FUNCS @@ -72,6 +81,10 @@ MALLOC_DECL(jemalloc_stats_internal, void, jemalloc_stats_t*, // Return the size of the jemalloc_bin_stats_t array. MALLOC_DECL(jemalloc_stats_num_bins, size_t) +// Return some of the information that jemalloc_stats returns but works +// off-main-thread and is faster. +MALLOC_DECL(jemalloc_stats_lite, void, jemalloc_stats_lite_t*) + // Tell jemalloc this is the main thread. jemalloc will use this to validate // that main thread only arenas are only used on the main thread. MALLOC_DECL(jemalloc_set_main_thread, void) @@ -107,9 +120,64 @@ MALLOC_DECL(jemalloc_purge_freed_pages, void) // down subsequent allocations so it is recommended to use it only when // memory needs to be reclaimed at all costs (see bug 805855). This function // provides functionality similar to mallctl("arenas.purge") in jemalloc 3. -// It may only be used from the main thread. +// Note that if called on a different thread than the main thread, only arenas +// that are not created with ARENA_FLAG_THREAD_MAIN_THREAD_ONLY will be purged. MALLOC_DECL(jemalloc_free_dirty_pages, void) +// Set the default modifier for mMaxDirty. The value is the number of shifts +// applied to the value. Positive value is handled as <<, negative >>. +// Arenas may override the default modifier. +MALLOC_DECL(moz_set_max_dirty_page_modifier, void, int32_t) + +// Enable or disable deferred purging. Returns the former state. +// If enabled, jemalloc will not purge anything until either +// jemalloc_free_[excess]_dirty_pages or moz_may_purge_now are called +// explicitly. Disabling it may cause an immediate synchronous purge of all +// arenas. +// Must be called only on the main thread. +// Parameters: +// bool: enable/disable +MALLOC_DECL(moz_enable_deferred_purge, bool, bool) + +// Perform some purging. +// +// Returns a purge_result_t with the following meaning: +// Done: Purge has completed for all arenas. +// NeedsMore: There may be an arena that needs to be purged now. The caller +// may call moz_may_purge_one_now again. +// WantsLater: There is at least one arena that might want a purge later, +// according to aReuseGraceMS passed. But none requesting purge +// now. +// +// Parameters: +// aPeekOnly: If true, it won't process any purge but just return if some is +// needed now or wanted later. +// aReuseGraceMS: The time to wait after a significant re-use happened before +// purging memory in an arena. +// aKeepGoing: Used to determine if it should continue processing purge +// requests and may be used to implement a work budget. It will +// exit if there's no more requests, if it finishes processing an +// arena or if this parameter returns false. +// +// The cost of calling this when there is no pending purge is: a mutex +// lock/unlock and iterating the list of purges. The mutex is never held during +// expensive operations. +# ifdef __cplusplus +MALLOC_DECL(moz_may_purge_now, purge_result_t, bool, uint32_t, + const mozilla::Maybe>&) +# endif + +// Free dirty pages until the max dirty pages threshold is satisfied. Useful +// after lowering the max dirty pages threshold to get RSS back to normal. +// This behaves just like a synchronous purge on all arenas. +// Note that if called on a different thread than the main thread, only arenas +// that are not created with ARENA_FLAG_THREAD_MAIN_THREAD_ONLY will be purged. +MALLOC_DECL(jemalloc_free_excess_dirty_pages, void) + +// Change the value of opt_randomize_small to control small allocation +// randomization and maybe perform a reinitialization of the arena's PRNG. +MALLOC_DECL(jemalloc_reset_small_alloc_randomization, void, bool) + // Opt in or out of a thread local arena (bool argument is whether to opt-in // (true) or out (false)). MALLOC_DECL(jemalloc_thread_local_arena, void, bool) @@ -119,7 +187,6 @@ MALLOC_DECL(jemalloc_ptr_info, void, const void*, jemalloc_ptr_info_t*) # endif # if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_BASE - // Creates a separate arena, and returns its id, valid to use with moz_arena_* // functions. A helper is provided in mozmemory.h that doesn't take any // arena_params_t: moz_create_arena. @@ -129,12 +196,6 @@ MALLOC_DECL(moz_create_arena_with_params, arena_id_t, arena_params_t*) // Passing an invalid id (inexistent or already disposed) to this function // will crash. The arena must be empty prior to calling this function. MALLOC_DECL(moz_dispose_arena, void, arena_id_t) - -// Set the default modifier for mMaxDirty. The value is the number of shifts -// applied to the value. Positive value is handled as <<, negative >>. -// Arenas may override the default modifier. -MALLOC_DECL(moz_set_max_dirty_page_modifier, void, int32_t) - # endif # if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_ALLOC diff --git a/src/third_party/mozjs/include/mozilla/Alignment.h b/src/third_party/mozjs/include/mozilla/Alignment.h index c38e00d12c4..8f459339308 100644 --- a/src/third_party/mozjs/include/mozilla/Alignment.h +++ b/src/third_party/mozjs/include/mozilla/Alignment.h @@ -15,48 +15,6 @@ namespace mozilla { -/* - * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many - * bytes of alignment a given type needs. - */ -template -class AlignmentFinder { - struct Aligner { - char mChar; - T mT; - - // Aligner may be used to check alignment of types with deleted dtors. This - // results in such specializations having implicitly deleted dtors, which - // causes fatal warnings on MSVC (see bug 1481005). As we don't create - // Aligners, we can avoid this warning by explicitly deleting the dtor. - ~Aligner() = delete; - }; - - public: - static const size_t alignment = sizeof(Aligner) - sizeof(T); -}; - -#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder::alignment - -namespace detail { -template -struct AlignasHelper { - T mT; -}; -} // namespace detail - -/* - * Use this instead of alignof to align struct field as if it is inside - * a struct. On some platforms, there exist types which have different - * alignment between when it is used on its own and when it is used on - * a struct field. - * - * Known examples are 64bit types (uint64_t, double) on 32bit Linux, - * where they have 8byte alignment on their own, and 4byte alignment - * when in struct. - */ -#define MOZ_ALIGNAS_IN_STRUCT(T) alignas(mozilla::detail::AlignasHelper) - /* * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types. * diff --git a/src/third_party/mozjs/include/mozilla/Array.h b/src/third_party/mozjs/include/mozilla/Array.h index 55b724a2882..abdcf67fb58 100644 --- a/src/third_party/mozjs/include/mozilla/Array.h +++ b/src/third_party/mozjs/include/mozilla/Array.h @@ -22,7 +22,7 @@ namespace mozilla { template -class Array { +class MOZ_GSL_OWNER Array { T mArr[_Length]; public: @@ -39,14 +39,14 @@ class Array { "parameter Length"); } - T& operator[](size_t aIndex) { + constexpr T& operator[](size_t aIndex) MOZ_LIFETIME_BOUND { if (MOZ_UNLIKELY(aIndex >= Length)) { detail::InvalidArrayIndex_CRASH(aIndex, Length); } return mArr[aIndex]; } - const T& operator[](size_t aIndex) const { + constexpr const T& operator[](size_t aIndex) const MOZ_LIFETIME_BOUND { if (MOZ_UNLIKELY(aIndex >= Length)) { detail::InvalidArrayIndex_CRASH(aIndex, Length); } @@ -75,6 +75,9 @@ class Array { constexpr const_iterator end() const { return mArr + Length; } constexpr const_iterator cend() const { return end(); } + // Method for std::size. + constexpr size_t size() const { return Length; } + // Methods for reverse iterating. reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { diff --git a/src/third_party/mozjs/include/mozilla/ArrayUtils.h b/src/third_party/mozjs/include/mozilla/ArrayUtils.h index 78eec5dabad..073036b038b 100644 --- a/src/third_party/mozjs/include/mozilla/ArrayUtils.h +++ b/src/third_party/mozjs/include/mozilla/ArrayUtils.h @@ -19,17 +19,13 @@ #ifdef __cplusplus # include +# include # include # include "mozilla/Alignment.h" namespace mozilla { -template -class Array; -template -class EnumeratedArray; - /* * Safely subtract two pointers when it is known that aEnd >= aBegin, yielding a * size_t result. @@ -48,47 +44,6 @@ MOZ_ALWAYS_INLINE size_t PointerRangeSize(T* aBegin, T* aEnd) { return (size_t(aEnd) - size_t(aBegin)) / sizeof(T); } -/* - * Compute the length of an array with constant length. (Use of this method - * with a non-array pointer will not compile.) - * - * Beware of the implicit trailing '\0' when using this with string constants. - */ -template -constexpr size_t ArrayLength(T (&aArr)[N]) { - return N; -} - -template -constexpr size_t ArrayLength(const Array& aArr) { - return N; -} - -template -constexpr size_t ArrayLength(const EnumeratedArray& aArr) { - return N; -} - -/* - * Compute the address one past the last element of a constant-length array. - * - * Beware of the implicit trailing '\0' when using this with string constants. - */ -template -constexpr T* ArrayEnd(T (&aArr)[N]) { - return aArr + ArrayLength(aArr); -} - -template -constexpr T* ArrayEnd(Array& aArr) { - return &aArr[0] + ArrayLength(aArr); -} - -template -constexpr const T* ArrayEnd(const Array& aArr) { - return &aArr[0] + ArrayLength(aArr); -} - /** * std::equal has subpar ergonomics. */ @@ -108,7 +63,7 @@ namespace detail { template struct AlignedChecker { static void test(const Pointee* aPtr) { - MOZ_ASSERT((uintptr_t(aPtr) % MOZ_ALIGNOF(AlignType)) == 0, + MOZ_ASSERT((uintptr_t(aPtr) % alignof(AlignType)) == 0, "performing a range-check with a misaligned pointer"); } }; @@ -158,31 +113,8 @@ inline bool IsInRange(const T* aPtr, uintptr_t aBegin, uintptr_t aEnd) { reinterpret_cast(aEnd)); } -namespace detail { - -/* - * Helper for the MOZ_ARRAY_LENGTH() macro to make the length a typesafe - * compile-time constant even on compilers lacking constexpr support. - */ -template -char (&ArrayLengthHelper(T (&array)[N]))[N]; - -} /* namespace detail */ - } /* namespace mozilla */ #endif /* __cplusplus */ -/* - * MOZ_ARRAY_LENGTH() is an alternative to mozilla::ArrayLength() for C files - * that can't use C++ template functions and for static_assert() calls that - * can't call ArrayLength() when it is not a C++11 constexpr function. - */ -#ifdef __cplusplus -# define MOZ_ARRAY_LENGTH(array) \ - sizeof(mozilla::detail::ArrayLengthHelper(array)) -#else -# define MOZ_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0])) -#endif - #endif /* mozilla_ArrayUtils_h */ diff --git a/src/third_party/mozjs/include/mozilla/Assertions.h b/src/third_party/mozjs/include/mozilla/Assertions.h index 0b7395177d2..12fb4370870 100644 --- a/src/third_party/mozjs/include/mozilla/Assertions.h +++ b/src/third_party/mozjs/include/mozilla/Assertions.h @@ -53,9 +53,13 @@ MOZ_END_EXTERN_C #if defined(MOZ_HAS_MOZGLUE) || defined(MOZILLA_INTERNAL_API) static inline void AnnotateMozCrashReason(const char* reason) { gMozCrashReason = reason; - // See bug 1681846, on 32-bit Android ARM the compiler removes the store to - // gMozCrashReason if this barrier is not present. - asm volatile("" ::: "memory"); + // The following assembly fakes a memory read/write to the compiler, which + // prevents the removal of gMozCrashReason store. See bug 1681846 and 1945507. +# if defined(__clang__) + asm volatile("" : "+r,m"(gMozCrashReason) : : "memory"); +# else + asm volatile("" : "+m,r"(gMozCrashReason) : : "memory"); +# endif } # define MOZ_CRASH_ANNOTATE(...) AnnotateMozCrashReason(__VA_ARGS__) #else @@ -95,7 +99,10 @@ MOZ_BEGIN_EXTERN_C #if defined(ANDROID) && defined(MOZ_DUMP_ASSERTION_STACK) MOZ_MAYBE_UNUSED static void MOZ_ReportAssertionFailurePrintFrame( const char* aBuf) { - __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", "%s\n", aBuf); + __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", "%s", aBuf); +} +MOZ_MAYBE_UNUSED static void MOZ_CrashPrintFrame(const char* aBuf) { + __android_log_print(ANDROID_LOG_FATAL, "MOZ_Crash", "%s", aBuf); } #endif @@ -144,6 +151,10 @@ MOZ_MAYBE_UNUSED static MOZ_COLD MOZ_NEVER_INLINE void MOZ_ReportCrash( __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH", "[%d] Hit MOZ_CRASH(%s) at %s:%d\n", MOZ_GET_PID(), aStr, aFilename, aLine); +# if defined(MOZ_DUMP_ASSERTION_STACK) + MozWalkTheStackWithWriter(MOZ_CrashPrintFrame, CallerPC(), + /* aMaxFrames */ 0); +# endif #else # if defined(MOZ_BUFFER_STDERR) char msg[1024] = ""; @@ -226,6 +237,57 @@ MOZ_NoReturn(int aLine) { #else +/* + * MOZ_CrashSequence() executes a sequence that causes the process to crash by + * writing the line number specified in the `aLine` parameter to the address + * provide by `aAddress`. The store is implemented as volatile assembly code to + * ensure it's always included in the output and always executed. + */ +static inline void MOZ_CrashSequence(void* aAddress, intptr_t aLine) { +# if defined(__i386__) || defined(__x86_64__) + asm volatile( + "mov %1, (%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__arm__) || defined(__aarch64__) + asm volatile( + "str %1,[%0];\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__riscv) && (__riscv_xlen == 64) + asm volatile( + "sd %1,0(%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__sparc__) && defined(__arch64__) + asm volatile( + "stx %1,[%0];\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__loongarch64) + asm volatile( + "st.d %1,%0,0;\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +// MONGODB MODIFICATION: Implement for ppc64le and s390x +# elif defined(__powerpc64__) + asm volatile( + "std %1, 0(%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# elif defined(__s390x__) + asm volatile( + "stg %1, 0(%0);\n" // Write the line number to the crashing address + : // no output registers + : "r"(aAddress), "r"(aLine)); +# else +# warning \ + "Unsupported architecture, replace the code below with assembly suitable to crash the process" + asm volatile("" ::: "memory"); + *((volatile int*)aAddress) = aLine; /* NOLINT */ +# endif +} + /* * MOZ_CRASH_WRITE_ADDR is the address to be used when performing a forced * crash. NULL is preferred however if for some reason NULL cannot be used @@ -237,22 +299,22 @@ MOZ_NoReturn(int aLine) { * SEGV at 0x0. */ # ifdef MOZ_UBSAN -# define MOZ_CRASH_WRITE_ADDR 0x1 +# define MOZ_CRASH_WRITE_ADDR ((void*)0x1) # else # define MOZ_CRASH_WRITE_ADDR NULL # endif # ifdef __cplusplus -# define MOZ_REALLY_CRASH(line) \ - do { \ - *((volatile int*)MOZ_CRASH_WRITE_ADDR) = line; /* NOLINT */ \ - MOZ_NOMERGE ::abort(); \ +# define MOZ_REALLY_CRASH(line) \ + do { \ + MOZ_CrashSequence(MOZ_CRASH_WRITE_ADDR, line); \ + MOZ_NOMERGE ::abort(); \ } while (false) # else -# define MOZ_REALLY_CRASH(line) \ - do { \ - *((volatile int*)MOZ_CRASH_WRITE_ADDR) = line; /* NOLINT */ \ - MOZ_NOMERGE abort(); \ +# define MOZ_REALLY_CRASH(line) \ + do { \ + MOZ_CrashSequence(MOZ_CRASH_WRITE_ADDR, line); \ + MOZ_NOMERGE abort(); \ } while (false) # endif #endif @@ -272,13 +334,13 @@ MOZ_NoReturn(int aLine) { * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's * obvious why we're crashing. * - * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an - * explanation-string, we print the string to stderr. Otherwise, we don't - * print anything; this is because we want MOZ_CRASH to be 100% safe in release - * builds, and it's hard to print to stderr safely when memory might have been - * corrupted. + * If we're a DEBUG, ASAN or FUZZING build and we crash at a MOZ_CRASH which + * provides an explanation-string, we print the string to stderr. Otherwise, + * we don't print anything; this is because we want MOZ_CRASH to be 100% safe + * in release builds, and it's hard to print to stderr safely when memory might + * have been corrupted. */ -#if !(defined(DEBUG) || defined(FUZZING)) +#if !(defined(DEBUG) || defined(MOZ_ASAN) || defined(FUZZING)) # define MOZ_CRASH(...) \ do { \ MOZ_FUZZING_HANDLE_CRASH_EVENT4("MOZ_CRASH", __FILE__, __LINE__, NULL); \ @@ -295,6 +357,19 @@ MOZ_NoReturn(int aLine) { } while (false) #endif +/* + * MOZ_DIAGNOSTIC_CRASH acts like MOZ_CRASH in a MOZ_DIAGNOSTIC_ASSERT_ENABLED + * build, and does nothing otherwise. See the comment later in this file for a + * description of when MOZ_DIAGNOSTIC_ASSERT_ENABLED is defined. + */ +#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) +# define MOZ_DIAGNOSTIC_CRASH(...) MOZ_CRASH(__VA_ARGS__) +#else +# define MOZ_DIAGNOSTIC_CRASH(...) \ + do { /* nothing */ \ + } while (false) +#endif + /* * MOZ_CRASH_UNSAFE(explanation-string) can be used if the explanation string * cannot be a string literal (but no other processing needs to be done on it). @@ -310,7 +385,7 @@ MOZ_NoReturn(int aLine) { static MOZ_ALWAYS_INLINE_EVEN_DEBUG MOZ_COLD MOZ_NORETURN void MOZ_Crash( const char* aFilename, int aLine, const char* aReason) { MOZ_FUZZING_HANDLE_CRASH_EVENT4("MOZ_CRASH", aFilename, aLine, aReason); -#if defined(DEBUG) || defined(FUZZING) +#if defined(DEBUG) || defined(MOZ_ASAN) || defined(FUZZING) MOZ_ReportCrash(aReason, aFilename, aLine); #endif MOZ_CRASH_ANNOTATE(aReason); @@ -480,7 +555,7 @@ struct AssertionConditionType { ("MOZ_ASSERT", __VA_ARGS__)) #else # define MOZ_ASSERT(...) \ - do { \ + do { /* nothing */ \ } while (false) #endif /* DEBUG */ @@ -491,7 +566,7 @@ struct AssertionConditionType { ("MOZ_DIAGNOSTIC_ASSERT", __VA_ARGS__)) #else # define MOZ_DIAGNOSTIC_ASSERT(...) \ - do { \ + do { /* nothing */ \ } while (false) #endif @@ -528,7 +603,7 @@ struct AssertionConditionType { } while (false) #else # define MOZ_ASSERT_IF(cond, expr) \ - do { \ + do { /* nothing */ \ } while (false) #endif @@ -548,7 +623,7 @@ struct AssertionConditionType { } while (false) #else # define MOZ_DIAGNOSTIC_ASSERT_IF(cond, expr) \ - do { \ + do { /* nothing */ \ } while (false) #endif @@ -647,18 +722,18 @@ struct AssertionConditionType { #endif /* - * MOZ_ALWAYS_TRUE(expr) and friends always evaluate the provided expression, - * in debug builds and in release builds both. Then, in debug builds and - * Nightly and early beta builds, the value of the expression is - * asserted either true or false using MOZ_DIAGNOSTIC_ASSERT. + * MOZ_ALWAYS_TRUE(expr) and friends always evaluate the provided expression, in + * both debug and release builds. Then, in debug builds and Nightly and early + * beta builds, we crash using the string value of the expression as the message + * using MOZ_DIAGNOSTIC_CRASH. */ -#define MOZ_ALWAYS_TRUE(expr) \ - do { \ - if (MOZ_LIKELY(expr)) { \ - /* Silence [[nodiscard]]. */ \ - } else { \ - MOZ_DIAGNOSTIC_ASSERT(false, #expr); \ - } \ +#define MOZ_ALWAYS_TRUE(expr) \ + do { \ + if (MOZ_LIKELY(expr)) { \ + /* Silence [[nodiscard]]. */ \ + } else { \ + MOZ_DIAGNOSTIC_CRASH(#expr); \ + } \ } while (false) #define MOZ_ALWAYS_FALSE(expr) MOZ_ALWAYS_TRUE(!(expr)) @@ -670,10 +745,10 @@ struct AssertionConditionType { */ #ifdef FUZZING # define MOZ_CRASH_UNLESS_FUZZING(...) \ - do { \ + do { /* nothing */ \ } while (0) # define MOZ_ASSERT_UNLESS_FUZZING(...) \ - do { \ + do { /* nothing */ \ } while (0) #else # define MOZ_CRASH_UNLESS_FUZZING(...) MOZ_CRASH(__VA_ARGS__) diff --git a/src/third_party/mozjs/include/mozilla/Atomics.h b/src/third_party/mozjs/include/mozilla/Atomics.h index e5da5c07a95..9ca056c92ec 100644 --- a/src/third_party/mozjs/include/mozilla/Atomics.h +++ b/src/third_party/mozjs/include/mozilla/Atomics.h @@ -28,6 +28,11 @@ #include #include +#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || \ + defined(_M_X64) +# include +#endif + namespace mozilla { /** @@ -60,7 +65,7 @@ namespace mozilla { * the modes we provide below, or not relevant for the CPUs we support * in Gecko. These three modes are confusing enough as it is! */ -enum MemoryOrdering { +enum MemoryOrdering : uint8_t { /* * Relaxed ordering is the simplest memory ordering: none at all. * When the result of a write is observed, nothing may be inferred @@ -507,6 +512,37 @@ class Atomic : protected detail::AtomicBase { Atomic(Atomic& aOther) = delete; }; +/** + * Atomic implementation for double type. + */ +template +class Atomic : protected detail::AtomicBase { + typedef typename detail::AtomicBase Base; + + public: + constexpr Atomic() : Base() {} + explicit constexpr Atomic(double aInit) : Base(aInit) {} + + operator double() const { + return double(Base::Intrinsics::load(Base::mValue)); + } + + double operator=(double aVal) { return Base::operator=(aVal); } + + private: + Atomic(Atomic& aOther) = delete; +}; + +// Relax the CPU during a spinlock. It's a good idea to place this in a +// spinlock so that the CPU doesn't pipeline the loop otherwise flushing the +// pipeline when the loop finally breaks can be expensive. +inline void cpu_pause() { +#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || \ + defined(_M_X64) + _mm_pause(); +#endif +} + } // namespace mozilla namespace std { diff --git a/src/third_party/mozjs/include/mozilla/Attributes.h b/src/third_party/mozjs/include/mozilla/Attributes.h index 130288c5122..d5401b0eb40 100644 --- a/src/third_party/mozjs/include/mozilla/Attributes.h +++ b/src/third_party/mozjs/include/mozilla/Attributes.h @@ -448,6 +448,39 @@ # define MOZ_NO_STACK_PROTECTOR /* no support */ #endif +/** + * MOZ_GSL_OWNER indicates that objects of the type this annotation is attached + * to own some kind of resources, generally memory. + * + * See: https://clang.llvm.org/docs/AttributeReference.html#owner + */ +#if defined(__clang__) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(gsl::Owner) +# define MOZ_GSL_OWNER [[gsl::Owner]] +# else +# define MOZ_GSL_OWNER /* nothing */ +# endif +#else +# define MOZ_GSL_OWNER /* nothing */ +#endif + +/** + * MOZ_GSL_POINTER indicates that objects of the type this annotation is + * attached to provide a non-owning view on some kind of resources, generally + * memory. + * + * See: https://clang.llvm.org/docs/AttributeReference.html#pointer + */ +#if defined(__clang__) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(gsl::Pointer) +# define MOZ_GSL_POINTER [[gsl::Pointer]] +# else +# define MOZ_GSL_POINTER /* nothing */ +# endif +#else +# define MOZ_GSL_POINTER /* nothing */ +#endif + /** * MOZ_LIFETIME_BOUND indicates that objects that are referred to by that * parameter may also be referred to by the return value of the annotated @@ -465,6 +498,21 @@ # define MOZ_LIFETIME_BOUND /* nothing */ #endif +/** + * MOZ_LIFETIME_CAPTURE_BY(x) indicates that objects that are referred to + * by that parameter may also be referred to by x. + * See: https://clang.llvm.org/docs/AttributeReference.html#lifetime-capture-by + */ +#if defined(__clang__) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(clang::lifetime_capture_by) +# define MOZ_LIFETIME_CAPTURE_BY(x) [[clang::lifetime_capture_by(x)]] +# else +# define MOZ_LIFETIME_CAPTURE_BY(x) /* nothing */ +# endif +#else +# define MOZ_LIFETIME_CAPTURE_BY(x) /* nothing */ +#endif + #ifdef __cplusplus /** @@ -618,6 +666,11 @@ * expression. If a member of another class uses this class, or if another * class inherits from this class, then it is considered to be a non-heap * class as well, although this attribute need not be provided in such cases. + * MOZ_CONSTINIT: pre-C++20 equivalent to `constinit`. + * MOZ_RUNINIT: Applies to global variables with runtime initialization. + * MOZ_GLOBINIT: Applies to global variables with potential runtime + * initialization (e.g. inside macro or when initialisation status depends on + * template parameter). * MOZ_HEAP_CLASS: Applies to all classes. Any class with this annotation is * expected to live on the heap, so it is a compile-time error to use it, or * an array of such objects, as the type of a variable declaration, or as a @@ -855,12 +908,17 @@ # define MOZ_MAY_CALL_AFTER_MUST_RETURN \ __attribute__((annotate("moz_may_call_after_must_return"))) # define MOZ_KNOWN_LIVE __attribute__((annotate("moz_known_live"))) -# ifndef XGILL_PLUGIN +# ifdef MOZ_CLANG_PLUGIN # define MOZ_UNANNOTATED __attribute__((annotate("moz_unannotated"))) # define MOZ_ANNOTATED __attribute__((annotate("moz_annotated"))) +# define MOZ_RUNINIT __attribute__((annotate("moz_global_var"))) +# define MOZ_GLOBINIT \ + MOZ_RUNINIT __attribute__((annotate("moz_generated"))) # else # define MOZ_UNANNOTATED /* nothing */ # define MOZ_ANNOTATED /* nothing */ +# define MOZ_RUNINIT /* nothing */ +# define MOZ_GLOBINIT /* nothing */ # endif /* @@ -868,11 +926,11 @@ * warning, so use pragmas to disable the warning. */ # ifdef __clang__ -# define MOZ_HEAP_ALLOCATOR \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((annotate("moz_heap_allocator"))) \ - _Pragma("clang diagnostic pop") +# define MOZ_HEAP_ALLOCATOR \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((annotate("moz_heap_allocator"))) _Pragma( \ + "clang diagnostic pop") # else # define MOZ_HEAP_ALLOCATOR __attribute__((annotate("moz_heap_allocator"))) # endif @@ -882,6 +940,8 @@ # define MOZ_CAN_RUN_SCRIPT_BOUNDARY /* nothing */ # define MOZ_MUST_OVERRIDE /* nothing */ # define MOZ_STATIC_CLASS /* nothing */ +# define MOZ_RUNINIT /* nothing */ +# define MOZ_GLOBINIT /* nothing */ # define MOZ_STATIC_LOCAL_CLASS /* nothing */ # define MOZ_STACK_CLASS /* nothing */ # define MOZ_NONHEAP_CLASS /* nothing */ @@ -1033,6 +1093,19 @@ # define MOZ_EMPTY_BASES #endif +/** + * Pre- C++20 equivalent to constinit + */ +#if defined(__cpp_constinit) +# define MOZ_CONSTINIT constinit +#elif defined(__clang__) +# define MOZ_CONSTINIT [[clang::require_constant_initialization]] +#elif MOZ_GCC_VERSION_AT_LEAST(10, 1, 0) +# define MOZ_CONSTINIT __constinit +#else +# define MOZ_CONSTINIT +#endif + // XXX: GCC somehow does not allow attributes before lambda return types, while // clang requires so. See also bug 1627007. #ifdef __clang__ diff --git a/src/third_party/mozjs/include/mozilla/AwakeTimeStamp.h b/src/third_party/mozjs/include/mozilla/AwakeTimeStamp.h index b95ef9e77e9..6c6a358fbe3 100644 --- a/src/third_party/mozjs/include/mozilla/AwakeTimeStamp.h +++ b/src/third_party/mozjs/include/mozilla/AwakeTimeStamp.h @@ -23,12 +23,16 @@ class AwakeTimeDuration; // // Some arithmetic and ordering operations are supported, when they make sense. // -// This timestamp shouldn't be considered to be high-resolution, and is suitable -// to measure time from a hundred of milliseconds (because of Windows -// limitations). +// When using NowLoRes(), the timestamp shouldn't be considered to be +// high-resolution, and is suitable to measure time from a hundred of +// milliseconds (because of Windows limitations). +// Now() can be a bit more expensive on Windows, and is precise. Both +// methods are equivalent on non-Windows. class AwakeTimeStamp { public: + using DurationType = AwakeTimeDuration; MFBT_API static AwakeTimeStamp NowLoRes(); + MFBT_API static AwakeTimeStamp Now(); MFBT_API void operator+=(const AwakeTimeDuration& aOther); MFBT_API void operator-=(const AwakeTimeDuration& aOther); MFBT_API bool operator<(const AwakeTimeStamp& aOther) const { @@ -50,6 +54,7 @@ class AwakeTimeStamp { return !(*this == aOther); } MFBT_API AwakeTimeDuration operator-(AwakeTimeStamp const& aOther) const; + MFBT_API AwakeTimeStamp operator-(AwakeTimeDuration const& aOther) const; MFBT_API AwakeTimeStamp operator+(const AwakeTimeDuration& aDuration) const; private: @@ -71,6 +76,9 @@ class AwakeTimeDuration { MFBT_API double ToSeconds() const; MFBT_API double ToMilliseconds() const; MFBT_API double ToMicroseconds() const; + static MFBT_API AwakeTimeDuration FromSeconds(uint64_t aSeconds); + static MFBT_API AwakeTimeDuration FromMilliseconds(uint64_t aMilliseconds); + static MFBT_API AwakeTimeDuration FromMicroseconds(uint64_t aMicroseconds); MFBT_API void operator+=(const AwakeTimeDuration& aDuration) { mValueUs += aDuration.mValueUs; } diff --git a/src/third_party/mozjs/include/mozilla/BaseAndGeckoProfilerDetail.h b/src/third_party/mozjs/include/mozilla/BaseAndGeckoProfilerDetail.h new file mode 100644 index 00000000000..9b2f17e7434 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseAndGeckoProfilerDetail.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Internal Base and Gecko Profiler utilities. +// It should declare or define things that are used in both profilers, but not +// needed outside of the profilers. +// In particular, it is *not* included in popular headers like BaseProfiler.h +// and GeckoProfiler.h, to avoid rebuilding the world when this is modified. + +#ifndef BaseAndGeckoProfilerDetail_h +#define BaseAndGeckoProfilerDetail_h + +#include "mozilla/BaseProfilerUtils.h" +#include "mozilla/Span.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/Types.h" +#include "mozilla/UniquePtr.h" + +namespace mozilla { + +class ProfileBufferChunkManagerWithLocalLimit; + +// Centrally defines the version of the gecko profiler JSON format. +const int GECKO_PROFILER_FORMAT_VERSION = 31; + +namespace baseprofiler::detail { + +[[nodiscard]] MFBT_API TimeStamp GetProfilingStartTime(); + +[[nodiscard]] MFBT_API UniquePtr +ExtractBaseProfilerChunkManager(); + +// If the current thread is registered, returns its registration time, otherwise +// a null timestamp. +[[nodiscard]] MFBT_API TimeStamp GetThreadRegistrationTime(); + +} // namespace baseprofiler::detail + +namespace profiler::detail { + +// True if the filter is exactly "pid:". +[[nodiscard]] MFBT_API bool FilterHasPid( + const char* aFilter, baseprofiler::BaseProfilerProcessId aPid = + baseprofiler::profiler_current_process_id()); + +// Only true if the filters only contain "pid:..." strings, and *none* of them +// is exactly "pid:". E.g.: +// - [], 123 -> false (no pids) +// - ["main"], 123 -> false (not all pids) +// - ["main", "pid:123"], 123 -> false (not all pids) +// - ["pid:123"], 123 -> false (all pids, including "pid:123") +// - ["pid:123", "pid:456"], 123 -> false (all pids, including "pid:123") +// - ["pid:456"], 123 -> true (all pids, but no "pid:123") +// - ["pid:456", "pid:789"], 123 -> true (all pids, but no "pid:123") +[[nodiscard]] MFBT_API bool FiltersExcludePid( + Span aFilters, + baseprofiler::BaseProfilerProcessId aPid = + baseprofiler::profiler_current_process_id()); + +} // namespace profiler::detail + +} // namespace mozilla + +#endif // BaseAndGeckoProfilerDetail_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfileJSONWriter.h b/src/third_party/mozjs/include/mozilla/BaseProfileJSONWriter.h new file mode 100644 index 00000000000..eba171e1be8 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfileJSONWriter.h @@ -0,0 +1,618 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BASEPROFILEJSONWRITER_H +#define BASEPROFILEJSONWRITER_H + +#include "mozilla/FailureLatch.h" +#include "mozilla/HashFunctions.h" +#include "mozilla/HashTable.h" +#include "mozilla/JSONWriter.h" +#include "mozilla/Maybe.h" +#include "mozilla/NotNull.h" +#include "mozilla/ProgressLogger.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/UniquePtrExtensions.h" +#include "mozilla/Flow.h" + +#include +#include +#include +#include + +namespace mozilla { +namespace baseprofiler { + +class SpliceableJSONWriter; + +// On average, profile JSONs are large enough such that we want to avoid +// reallocating its buffer when expanding. Additionally, the contents of the +// profile are not accessed until the profile is entirely written. For these +// reasons we use a chunked writer that keeps an array of chunks, which is +// concatenated together after writing is finished. +class ChunkedJSONWriteFunc final : public JSONWriteFunc, public FailureLatch { + public: + friend class SpliceableJSONWriter; + + explicit ChunkedJSONWriteFunc(FailureLatch& aFailureLatch) + : mFailureLatch(WrapNotNullUnchecked(&aFailureLatch)) { + (void)AllocChunk(kChunkSize); + } + + [[nodiscard]] bool IsEmpty() const { + MOZ_ASSERT_IF(!mChunkPtr, !mChunkEnd && mChunkList.length() == 0 && + mChunkLengths.length() == 0); + return !mChunkPtr; + } + + // Length of data written so far, excluding null terminator. + [[nodiscard]] size_t Length() const { + MOZ_ASSERT(mChunkLengths.length() == mChunkList.length()); + size_t totalLen = 0; + for (size_t i = 0; i < mChunkLengths.length(); i++) { + MOZ_ASSERT(strlen(mChunkList[i].get()) == mChunkLengths[i]); + totalLen += mChunkLengths[i]; + } + return totalLen; + } + + void Write(const Span& aStr) final { + if (Failed()) { + return; + } + + MOZ_ASSERT(mChunkPtr >= mChunkList.back().get() && mChunkPtr <= mChunkEnd); + MOZ_ASSERT(mChunkEnd >= mChunkList.back().get() + mChunkLengths.back()); + MOZ_ASSERT(*mChunkPtr == '\0'); + + // Most strings to be written are small, but subprocess profiles (e.g., + // from the content process in e10s) may be huge. If the string is larger + // than a chunk, allocate its own chunk. + char* newPtr; + if (aStr.size() >= kChunkSize) { + if (!AllocChunk(aStr.size() + 1)) { + return; + } + newPtr = mChunkPtr + aStr.size(); + } else { + newPtr = mChunkPtr + aStr.size(); + if (newPtr >= mChunkEnd) { + if (!AllocChunk(kChunkSize)) { + return; + } + newPtr = mChunkPtr + aStr.size(); + } + } + + memcpy(mChunkPtr, aStr.data(), aStr.size()); + *newPtr = '\0'; + mChunkPtr = newPtr; + mChunkLengths.back() += aStr.size(); + } + + [[nodiscard]] bool CopyDataIntoLazilyAllocatedBuffer( + const std::function& aAllocator) const { + // Request a buffer for the full content plus a null terminator. + if (Failed()) { + return false; + } + + char* ptr = aAllocator(Length() + 1); + + if (!ptr) { + // Failed to allocate memory. + return false; + } + + for (size_t i = 0; i < mChunkList.length(); i++) { + size_t len = mChunkLengths[i]; + memcpy(ptr, mChunkList[i].get(), len); + ptr += len; + } + *ptr = '\0'; + return true; + } + + [[nodiscard]] UniquePtr CopyData() const { + UniquePtr c; + if (!CopyDataIntoLazilyAllocatedBuffer([&](size_t allocationSize) { + c = MakeUnique(allocationSize); + return c.get(); + })) { + // Something went wrong, make sure the returned pointer is null even if + // the allocation happened. + c = nullptr; + } + return c; + } + + void Take(ChunkedJSONWriteFunc&& aOther) { + SetFailureFrom(aOther); + if (Failed()) { + return; + } + + for (size_t i = 0; i < aOther.mChunkList.length(); i++) { + MOZ_ALWAYS_TRUE(mChunkLengths.append(aOther.mChunkLengths[i])); + MOZ_ALWAYS_TRUE(mChunkList.append(std::move(aOther.mChunkList[i]))); + } + mChunkPtr = mChunkList.back().get() + mChunkLengths.back(); + mChunkEnd = mChunkPtr; + aOther.Clear(); + } + + FAILURELATCH_IMPL_PROXY(*mFailureLatch) + + // Change the failure latch to be used here, and if the previous latch was + // already in failure state, set that failure in the new latch. + // This allows using this WriteFunc in isolation, before attempting to bring + // it into another operation group with its own FailureLatch. + void ChangeFailureLatchAndForwardState(FailureLatch& aFailureLatch) { + aFailureLatch.SetFailureFrom(*this); + mFailureLatch = WrapNotNullUnchecked(&aFailureLatch); + } + + private: + void Clear() { + mChunkPtr = nullptr; + mChunkEnd = nullptr; + mChunkList.clear(); + mChunkLengths.clear(); + } + + void ClearAndSetFailure(std::string aFailure) { + Clear(); + SetFailure(std::move(aFailure)); + } + + [[nodiscard]] bool ClearAndSetFailureAndFalse(std::string aFailure) { + ClearAndSetFailure(std::move(aFailure)); + return false; + } + + [[nodiscard]] bool AllocChunk(size_t aChunkSize) { + if (Failed()) { + if (mChunkPtr) { + // FailureLatch is in failed state, but chunks have not been cleared yet + // (error must have happened elsewhere). + Clear(); + } + return false; + } + + MOZ_ASSERT(mChunkLengths.length() == mChunkList.length()); + UniquePtr newChunk = MakeUniqueFallible(aChunkSize); + if (!newChunk) { + return ClearAndSetFailureAndFalse( + "OOM in ChunkedJSONWriteFunc::AllocChunk allocating new chunk"); + } + mChunkPtr = newChunk.get(); + mChunkEnd = mChunkPtr + aChunkSize; + *mChunkPtr = '\0'; + if (!mChunkLengths.append(0)) { + return ClearAndSetFailureAndFalse( + "OOM in ChunkedJSONWriteFunc::AllocChunk appending length"); + } + if (!mChunkList.append(std::move(newChunk))) { + return ClearAndSetFailureAndFalse( + "OOM in ChunkedJSONWriteFunc::AllocChunk appending new chunk"); + } + return true; + } + + static const size_t kChunkSize = 4096 * 512; + + // Pointer for writing inside the current chunk. + // + // The current chunk is always at the back of mChunkList, i.e., + // mChunkList.back() <= mChunkPtr <= mChunkEnd. + char* mChunkPtr = nullptr; + + // Pointer to the end of the current chunk. + // + // The current chunk is always at the back of mChunkList, i.e., + // mChunkEnd >= mChunkList.back() + mChunkLengths.back(). + char* mChunkEnd = nullptr; + + // List of chunks and their lengths. + // + // For all i, the length of the string in mChunkList[i] is + // mChunkLengths[i]. + Vector> mChunkList; + Vector mChunkLengths; + + NotNull mFailureLatch; +}; + +struct OStreamJSONWriteFunc final : public JSONWriteFunc { + explicit OStreamJSONWriteFunc(std::ostream& aStream) : mStream(aStream) {} + + void Write(const Span& aStr) final { + std::string_view sv(aStr.data(), aStr.size()); + mStream << sv; + } + + std::ostream& mStream; +}; + +class UniqueJSONStrings; + +class SpliceableJSONWriter : public JSONWriter, public FailureLatch { + public: + SpliceableJSONWriter(JSONWriteFunc& aWriter, FailureLatch& aFailureLatch) + : JSONWriter(aWriter, JSONWriter::SingleLineStyle), + mFailureLatch(WrapNotNullUnchecked(&aFailureLatch)) {} + + SpliceableJSONWriter(UniquePtr aWriter, + FailureLatch& aFailureLatch) + : JSONWriter(std::move(aWriter), JSONWriter::SingleLineStyle), + mFailureLatch(WrapNotNullUnchecked(&aFailureLatch)) {} + + void StartBareList() { StartCollection(scEmptyString, scEmptyString); } + + void EndBareList() { EndCollection(scEmptyString); } + + // Output a time (int64_t given in nanoseconds) in milliseconds. trim zeroes. + // E.g.: 1'234'567'890 -> "1234.56789" + void TimeI64NsProperty(const Span& aMaybePropertyName, + int64_t aTime_ns) { + if (aTime_ns == 0) { + Scalar(aMaybePropertyName, MakeStringSpan("0")); + return; + } + + static constexpr int64_t million = 1'000'000; + const int64_t absNanos = std::abs(aTime_ns); + const int64_t integerMilliseconds = absNanos / million; + auto remainderNanoseconds = static_cast(absNanos % million); + + // Plenty enough to fit INT64_MIN (-9223372036854775808). + static constexpr size_t DIGITS_MAX = 23; + char buf[DIGITS_MAX + 1]; + int len = + snprintf(buf, DIGITS_MAX, (aTime_ns >= 0) ? "%" PRIu64 : "-%" PRIu64, + integerMilliseconds); + if (remainderNanoseconds != 0) { + buf[len++] = '.'; + // Output up to 6 fractional digits. Exit early if the rest would + // be trailing zeros. + uint32_t powerOfTen = static_cast(million / 10); + for (;;) { + auto digit = remainderNanoseconds / powerOfTen; + buf[len++] = '0' + static_cast(digit); + remainderNanoseconds %= powerOfTen; + if (remainderNanoseconds == 0) { + break; + } + powerOfTen /= 10; + if (powerOfTen == 0) { + break; + } + } + } + + Scalar(aMaybePropertyName, Span(buf, len)); + } + + // Output a (double) time in milliseconds, with at best nanosecond precision. + void TimeDoubleMsProperty(const Span& aMaybePropertyName, + double aTime_ms) { + const double dTime_ns = aTime_ms * 1'000'000.0; + // Make sure it's well within int64_t range. + // 2^63 nanoseconds is almost 300 years; these times are relative to + // firefox startup, this should be enough for most uses. + if (dTime_ns >= 0.0) { + MOZ_RELEASE_ASSERT(dTime_ns < double(INT64_MAX - 1)); + } else { + MOZ_RELEASE_ASSERT(dTime_ns > double(INT64_MIN + 2)); + } + // Round to nearest integer nanosecond. The conversion to integer truncates + // the fractional part, so first we need to push it 0.5 away from zero. + const int64_t iTime_ns = + (dTime_ns >= 0.0) ? int64_t(dTime_ns + 0.5) : int64_t(dTime_ns - 0.5); + TimeI64NsProperty(aMaybePropertyName, iTime_ns); + } + + // Output a (double) time in milliseconds, with at best nanosecond precision. + void TimeDoubleMsElement(double aTime_ms) { + TimeDoubleMsProperty(nullptr, aTime_ms); + } + + // This function must be used to correctly stream timestamps in profiles. + // Null timestamps don't output anything. + void TimeProperty(const Span& aMaybePropertyName, + const TimeStamp& aTime) { + if (!aTime.IsNull()) { + TimeDoubleMsProperty( + aMaybePropertyName, + (aTime - TimeStamp::ProcessCreation()).ToMilliseconds()); + } + } + + // JSON doesn't support 64bit integers so we encode them as hex strings + static std::array HexString(uint64_t aId) { + std::array buf = {}; + static const char* hex_digits = "0123456789abcdef"; + for (int i = 0; i < 16; i++) { + buf[i] = hex_digits[(aId >> (60 - i * 4)) & 0xf]; + } + buf[16] = '0'; // null terminate the string + return buf; + } + + // We store flows as strings because JS can't handle 64 bit numbers in JSON + void FlowProperty(const Span& aName, Flow aFlow) { + UniqueStringProperty(aName, HexString(aFlow.Id())); + } + + void NullElements(uint32_t aCount) { + for (uint32_t i = 0; i < aCount; i++) { + NullElement(); + } + } + + void Splice(const Span& aStr) { + Separator(); + WriteFunc().Write(aStr); + mNeedComma[mDepth] = true; + } + + void Splice(const char* aStr, size_t aLen) { + Separator(); + WriteFunc().Write(Span(aStr, aLen)); + mNeedComma[mDepth] = true; + } + + // Splice the given JSON directly in, without quoting. + void SplicedJSONProperty(const Span& aMaybePropertyName, + const Span& aJsonValue) { + Scalar(aMaybePropertyName, aJsonValue); + } + + void CopyAndSplice(const ChunkedJSONWriteFunc& aFunc) { + Separator(); + for (size_t i = 0; i < aFunc.mChunkList.length(); i++) { + WriteFunc().Write( + Span(aFunc.mChunkList[i].get(), aFunc.mChunkLengths[i])); + } + mNeedComma[mDepth] = true; + } + + // Takes the chunks from aFunc and write them. If move is not possible + // (e.g., using OStreamJSONWriteFunc), aFunc's chunks are copied and its + // storage cleared. + virtual void TakeAndSplice(ChunkedJSONWriteFunc&& aFunc) { + Separator(); + for (size_t i = 0; i < aFunc.mChunkList.length(); i++) { + WriteFunc().Write( + Span(aFunc.mChunkList[i].get(), aFunc.mChunkLengths[i])); + } + aFunc.mChunkPtr = nullptr; + aFunc.mChunkEnd = nullptr; + aFunc.mChunkList.clear(); + aFunc.mChunkLengths.clear(); + mNeedComma[mDepth] = true; + } + + // Set (or reset) the pointer to a UniqueJSONStrings. + void SetUniqueStrings(UniqueJSONStrings& aUniqueStrings) { + MOZ_RELEASE_ASSERT(!mUniqueStrings); + mUniqueStrings = &aUniqueStrings; + } + + // Set (or reset) the pointer to a UniqueJSONStrings. + void ResetUniqueStrings() { + MOZ_RELEASE_ASSERT(mUniqueStrings); + mUniqueStrings = nullptr; + } + + // Add `aStr` to the unique-strings list (if not already there), and write its + // index as a named object property. + inline void UniqueStringProperty(const Span& aName, + const Span& aStr); + + // Add `aStr` to the unique-strings list (if not already there), and write its + // index as an array element. + inline void UniqueStringElement(const Span& aStr); + + // THe following functions override JSONWriter functions non-virtually. The + // goal is to try and prevent calls that specify a style, which would be + // ignored anyway because the whole thing is single-lined. It's fine if some + // calls still make it through a `JSONWriter&`, no big deal. + void Start() { JSONWriter::Start(); } + void StartArrayProperty(const Span& aName) { + JSONWriter::StartArrayProperty(aName); + } + template + void StartArrayProperty(const char (&aName)[N]) { + JSONWriter::StartArrayProperty(Span(aName, N)); + } + void StartArrayElement() { JSONWriter::StartArrayElement(); } + void StartObjectProperty(const Span& aName) { + JSONWriter::StartObjectProperty(aName); + } + template + void StartObjectProperty(const char (&aName)[N]) { + JSONWriter::StartObjectProperty(Span(aName, N)); + } + void StartObjectElement() { JSONWriter::StartObjectElement(); } + + FAILURELATCH_IMPL_PROXY(*mFailureLatch) + + protected: + NotNull mFailureLatch; + + private: + UniqueJSONStrings* mUniqueStrings = nullptr; +}; + +class SpliceableChunkedJSONWriter final : public SpliceableJSONWriter { + public: + explicit SpliceableChunkedJSONWriter(FailureLatch& aFailureLatch) + : SpliceableJSONWriter(MakeUnique(aFailureLatch), + aFailureLatch) {} + + // Access the ChunkedJSONWriteFunc as reference-to-const, usually to copy data + // out. + const ChunkedJSONWriteFunc& ChunkedWriteFunc() const { + return ChunkedWriteFuncRef(); + } + + // Access the ChunkedJSONWriteFunc as rvalue-reference, usually to take its + // data out. This writer shouldn't be used anymore after this. + ChunkedJSONWriteFunc&& TakeChunkedWriteFunc() { + ChunkedJSONWriteFunc& ref = ChunkedWriteFuncRef(); +#ifdef DEBUG + mTaken = true; +#endif // + return std::move(ref); + } + + // Adopts the chunks from aFunc without copying. + void TakeAndSplice(ChunkedJSONWriteFunc&& aFunc) override { + MOZ_ASSERT(!mTaken); + Separator(); + ChunkedWriteFuncRef().Take(std::move(aFunc)); + mNeedComma[mDepth] = true; + } + + void ChangeFailureLatchAndForwardState(FailureLatch& aFailureLatch) { + mFailureLatch = WrapNotNullUnchecked(&aFailureLatch); + return ChunkedWriteFuncRef().ChangeFailureLatchAndForwardState( + aFailureLatch); + } + + private: + const ChunkedJSONWriteFunc& ChunkedWriteFuncRef() const { + MOZ_ASSERT(!mTaken); + // The WriteFunc was non-fallibly allocated as a ChunkedJSONWriteFunc in the + // only constructor above, so it's safe to cast to ChunkedJSONWriteFunc&. + return static_cast(WriteFunc()); + } + + ChunkedJSONWriteFunc& ChunkedWriteFuncRef() { + MOZ_ASSERT(!mTaken); + // The WriteFunc was non-fallibly allocated as a ChunkedJSONWriteFunc in the + // only constructor above, so it's safe to cast to ChunkedJSONWriteFunc&. + return static_cast(WriteFunc()); + } + +#ifdef DEBUG + bool mTaken = false; +#endif +}; + +class JSONSchemaWriter { + JSONWriter& mWriter; + uint32_t mIndex; + + public: + explicit JSONSchemaWriter(JSONWriter& aWriter) : mWriter(aWriter), mIndex(0) { + aWriter.StartObjectProperty("schema", + SpliceableJSONWriter::SingleLineStyle); + } + + void WriteField(const Span& aName) { + mWriter.IntProperty(aName, mIndex++); + } + + template + void WriteField(const char (&aName)[Np1]) { + WriteField(Span(aName, Np1 - 1)); + } + + ~JSONSchemaWriter() { mWriter.EndObject(); } +}; + +// This class helps create an indexed list of unique strings, and inserts the +// index as a JSON value. The collected list of unique strings can later be +// inserted as a JSON array. +// This can be useful for elements/properties with many repeated strings. +// +// With only JSONWriter w, +// `w.WriteElement("a"); w.WriteElement("b"); w.WriteElement("a");` +// when done inside a JSON array, will generate: +// `["a", "b", "c"]` +// +// With UniqueStrings u, +// `u.WriteElement(w, "a"); u.WriteElement(w, "b"); u.WriteElement(w, "a");` +// when done inside a JSON array, will generate: +// `[0, 1, 0]` +// and later, `u.SpliceStringTableElements(w)` (inside a JSON array), will +// output the corresponding indexed list of unique strings: +// `["a", "b"]` +class UniqueJSONStrings final : public FailureLatch { + public: + // Start an empty list of unique strings. + MFBT_API explicit UniqueJSONStrings(FailureLatch& aFailureLatch); + + // Start with a copy of the strings from another list. + MFBT_API UniqueJSONStrings(FailureLatch& aFailureLatch, + const UniqueJSONStrings& aOther, + ProgressLogger aProgressLogger); + + MFBT_API ~UniqueJSONStrings(); + + // Add `aStr` to the list (if not already there), and write its index as a + // named object property. + void WriteProperty(SpliceableJSONWriter& aWriter, + const Span& aName, + const Span& aStr) { + if (const Maybe maybeIndex = GetOrAddIndex(aStr); maybeIndex) { + aWriter.IntProperty(aName, *maybeIndex); + } else { + aWriter.SetFailureFrom(*this); + } + } + + // Add `aStr` to the list (if not already there), and write its index as an + // array element. + void WriteElement(SpliceableJSONWriter& aWriter, + const Span& aStr) { + if (const Maybe maybeIndex = GetOrAddIndex(aStr); maybeIndex) { + aWriter.IntElement(*maybeIndex); + } else if (!aWriter.Failed()) { + aWriter.SetFailureFrom(*this); + } + } + + // Splice all collected unique strings into an array. This should only be done + // once, and then this UniqueStrings shouldn't be used anymore. + MFBT_API void SpliceStringTableElements(SpliceableJSONWriter& aWriter); + + FAILURELATCH_IMPL_PROXY(mStringTableWriter) + + void ChangeFailureLatchAndForwardState(FailureLatch& aFailureLatch) { + mStringTableWriter.ChangeFailureLatchAndForwardState(aFailureLatch); + } + + private: + MFBT_API void ClearAndSetFailure(std::string aFailure); + + // If `aStr` is already listed, return its index. + // Otherwise add it to the list and return the new index. + MFBT_API Maybe GetOrAddIndex(const Span& aStr); + + SpliceableChunkedJSONWriter mStringTableWriter; + HashMap mStringHashToIndexMap; +}; + +void SpliceableJSONWriter::UniqueStringProperty(const Span& aName, + const Span& aStr) { + MOZ_RELEASE_ASSERT(mUniqueStrings); + mUniqueStrings->WriteProperty(*this, aName, aStr); +} + +// Add `aStr` to the list (if not already there), and write its index as an +// array element. +void SpliceableJSONWriter::UniqueStringElement(const Span& aStr) { + MOZ_RELEASE_ASSERT(mUniqueStrings); + mUniqueStrings->WriteElement(*this, aStr); +} + +} // namespace baseprofiler +} // namespace mozilla + +#endif // BASEPROFILEJSONWRITER_H diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerCounts.h b/src/third_party/mozjs/include/mozilla/BaseProfilerCounts.h new file mode 100644 index 00000000000..f7f186f8186 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerCounts.h @@ -0,0 +1,281 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BaseProfilerCounts_h +#define BaseProfilerCounts_h + +#ifndef MOZ_GECKO_PROFILER + +# define BASE_PROFILER_DEFINE_COUNT_TOTAL(label, category, description) +# define BASE_PROFILER_DEFINE_COUNT(label, category, description) +# define BASE_PROFILER_DEFINE_STATIC_COUNT_TOTAL(label, category, description) +# define AUTO_BASE_PROFILER_COUNT_TOTAL(label, count) +# define AUTO_BASE_PROFILER_COUNT(label) +# define AUTO_BASE_PROFILER_STATIC_COUNT(label, count) +# define AUTO_BASE_PROFILER_FORCE_ALLOCATION(label) + +#else + +# include "mozilla/Assertions.h" +# include "mozilla/Atomics.h" + +namespace mozilla { +namespace baseprofiler { + +class BaseProfilerCount; +MFBT_API void profiler_add_sampled_counter(BaseProfilerCount* aCounter); +MFBT_API void profiler_remove_sampled_counter(BaseProfilerCount* aCounter); + +typedef Atomic ProfilerAtomicSigned; +typedef Atomic ProfilerAtomicUnsigned; + +// Counter support +// There are two types of counters: +// 1) a simple counter which can be added to or subtracted from. This could +// track the number of objects of a type, the number of calls to something +// (reflow, JIT, etc). +// 2) a combined counter which has the above, plus a number-of-calls counter +// that is incremented by 1 for each call to modify the count. This provides +// an optional source for a 'heatmap' of access. This can be used (for +// example) to track the amount of memory allocated, and provide a heatmap of +// memory operations (allocs/frees). +// +// Counters are sampled by the profiler once per sample-period. At this time, +// all counters are global to the process. In the future, there might be more +// versions with per-thread or other discriminators. +// +// Typical usage: +// There are two ways to use counters: With heap-created counter objects, +// or using macros. Note: the macros use statics, and will be slightly +// faster/smaller, and you need to care about creating them before using +// them. They're similar to the use-pattern for the other AUTO_PROFILER* +// macros, but they do need the PROFILER_DEFINE* to be use to instantiate +// the statics. +// +// PROFILER_DEFINE_COUNT(mything, "JIT", "Some JIT byte count") +// ... +// void foo() { ... AUTO_PROFILER_COUNT(mything, number_of_bytes_used); ... } +// +// or (to also get a heatmap) +// +// PROFILER_DEFINE_COUNT_TOTAL(mything, "JIT", "Some JIT byte count") +// ... +// void foo() { +// ... +// AUTO_PROFILER_COUNT_TOTAL(mything, number_of_bytes_generated); +// ... +// } +// +// To use without statics/macros: +// +// UniquePtr myCounter; +// ... +// myCounter = +// MakeUnique("mything", "JIT", "Some JIT byte count")); +// ... +// void foo() { ... myCounter->Add(number_of_bytes_generated0; ... } + +class BaseProfilerCount { + public: + BaseProfilerCount(const char* aLabel, ProfilerAtomicSigned* aCounter, + ProfilerAtomicUnsigned* aNumber, const char* aCategory, + const char* aDescription) + : mLabel(aLabel), + mCategory(aCategory), + mDescription(aDescription), + mCounter(aCounter), + mNumber(aNumber) { +# define COUNTER_CANARY 0xDEADBEEF +# ifdef DEBUG + mCanary = COUNTER_CANARY; + mPrevNumber = 0; +# endif + // Can't call profiler_* here since this may be non-xul-library + } +# ifdef DEBUG + ~BaseProfilerCount() { mCanary = 0; } +# endif + + void Sample(int64_t& aCounter, uint64_t& aNumber) { + MOZ_ASSERT(mCanary == COUNTER_CANARY); + + aCounter = *mCounter; + aNumber = mNumber ? *mNumber : 0; +# ifdef DEBUG + MOZ_ASSERT(aNumber >= mPrevNumber); + mPrevNumber = aNumber; +# endif + } + + // We don't define ++ and Add() here, since the static defines directly + // increment the atomic counters, and the subclasses implement ++ and + // Add() directly. + + // These typically are static strings (for example if you use the macros + // below) + const char* mLabel; + const char* mCategory; + const char* mDescription; + // We're ok with these being un-ordered in race conditions. These are + // pointers because we want to be able to use statics and increment them + // directly. Otherwise we could just have them inline, and not need the + // constructor args. + // These can be static globals (using the macros below), though they + // don't have to be - their lifetime must be longer than the use of them + // by the profiler (see profiler_add/remove_sampled_counter()). If you're + // using a lot of these, they probably should be allocated at runtime (see + // class ProfilerCountOnly below). + ProfilerAtomicSigned* mCounter; + ProfilerAtomicUnsigned* mNumber; // may be null + +# ifdef DEBUG + uint32_t mCanary; + uint64_t mPrevNumber; // value of number from the last Sample() +# endif +}; + +// Designed to be allocated dynamically, and simply incremented with obj++ +// or obj->Add(n) +class ProfilerCounter final : public BaseProfilerCount { + public: + ProfilerCounter(const char* aLabel, const char* aCategory, + const char* aDescription) + : BaseProfilerCount(aLabel, &mCounter, nullptr, aCategory, aDescription) { + // Assume we're in libxul + profiler_add_sampled_counter(this); + } + + ~ProfilerCounter() { profiler_remove_sampled_counter(this); } + + BaseProfilerCount& operator++() { + Add(1); + return *this; + } + + void Add(int64_t aNumber) { mCounter += aNumber; } + + ProfilerAtomicSigned mCounter; +}; + +// Also keeps a heatmap (number of calls to ++/Add()) +class ProfilerCounterTotal final : public BaseProfilerCount { + public: + ProfilerCounterTotal(const char* aLabel, const char* aCategory, + const char* aDescription) + : BaseProfilerCount(aLabel, &mCounter, &mNumber, aCategory, + aDescription) { + // Assume we're in libxul + profiler_add_sampled_counter(this); + } + + ~ProfilerCounterTotal() { profiler_remove_sampled_counter(this); } + + BaseProfilerCount& operator++() { + Add(1); + return *this; + } + + void Add(int64_t aNumber) { + mCounter += aNumber; + mNumber++; + } + + ProfilerAtomicSigned mCounter; + ProfilerAtomicUnsigned mNumber; +}; + +// Defines a counter that is sampled on each profiler tick, with a running +// count (signed), and number-of-instances. Note that because these are two +// independent Atomics, there is a possiblity that count will not include +// the last call, but number of uses will. I think this is not worth +// worrying about +# define BASE_PROFILER_DEFINE_COUNT_TOTAL(label, category, description) \ + ProfilerAtomicSigned profiler_count_##label(0); \ + ProfilerAtomicUnsigned profiler_number_##label(0); \ + const char profiler_category_##label[] = category; \ + const char profiler_description_##label[] = description; \ + UniquePtr<::mozilla::baseprofiler::BaseProfilerCount> AutoCount_##label; + +// This counts, but doesn't keep track of the number of calls to +// AUTO_PROFILER_COUNT() +# define BASE_PROFILER_DEFINE_COUNT(label, category, description) \ + ProfilerAtomicSigned profiler_count_##label(0); \ + const char profiler_category_##label[] = category; \ + const char profiler_description_##label[] = description; \ + UniquePtr<::mozilla::baseprofiler::BaseProfilerCount> AutoCount_##label; + +// This will create a static initializer if used, but avoids a possible +// allocation. +# define BASE_PROFILER_DEFINE_STATIC_COUNT_TOTAL(label, category, \ + description) \ + ProfilerAtomicSigned profiler_count_##label(0); \ + ProfilerAtomicUnsigned profiler_number_##label(0); \ + ::mozilla::baseprofiler::BaseProfilerCount AutoCount_##label( \ + #label, &profiler_count_##label, &profiler_number_##label, category, \ + description); + +// If we didn't care about static initializers, we could avoid the need for +// a ptr to the BaseProfilerCount object. + +// XXX It would be better to do this without the if() and without the +// theoretical race to set the UniquePtr (i.e. possible leak). +# define AUTO_BASE_PROFILER_COUNT_TOTAL(label, count) \ + do { \ + profiler_number_##label++; /* do this first*/ \ + profiler_count_##label += count; \ + if (!AutoCount_##label) { \ + /* Ignore that we could call this twice in theory, and that we leak \ + * them \ + */ \ + AutoCount_##label.reset(new BaseProfilerCount( \ + #label, &profiler_count_##label, &profiler_number_##label, \ + profiler_category_##label, profiler_description_##label)); \ + ::mozilla::baseprofiler::profiler_add_sampled_counter( \ + AutoCount_##label.get()); \ + } \ + } while (0) + +# define AUTO_BASE_PROFILER_COUNT(label, count) \ + do { \ + profiler_count_##label += count; /* do this first*/ \ + if (!AutoCount_##label) { \ + /* Ignore that we could call this twice in theory, and that we leak \ + * them \ + */ \ + AutoCount_##label.reset(new BaseProfilerCount( \ + #label, nullptr, &profiler_number_##label, \ + profiler_category_##label, profiler_description_##label)); \ + ::mozilla::baseprofiler::profiler_add_sampled_counter( \ + AutoCount_##label.get()); \ + } \ + } while (0) + +# define AUTO_BASE_PROFILER_STATIC_COUNT(label, count) \ + do { \ + profiler_number_##label++; /* do this first*/ \ + profiler_count_##label += count; \ + } while (0) + +// if we need to force the allocation +# define AUTO_BASE_PROFILER_FORCE_ALLOCATION(label) \ + do { \ + if (!AutoCount_##label) { \ + /* Ignore that we could call this twice in theory, and that we leak \ + * them \ + */ \ + AutoCount_##label.reset( \ + new ::mozilla::baseprofiler::BaseProfilerCount( \ + #label, &profiler_count_##label, &profiler_number_##label, \ + profiler_category_##label, profiler_description_##label)); \ + } \ + } while (0) + +} // namespace baseprofiler +} // namespace mozilla + +#endif // !MOZ_GECKO_PROFILER + +#endif // BaseProfilerCounts_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerDetail.h b/src/third_party/mozjs/include/mozilla/BaseProfilerDetail.h new file mode 100644 index 00000000000..6ecf6e117b1 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerDetail.h @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Internal Base Profiler utilities. + +#ifndef BaseProfilerDetail_h +#define BaseProfilerDetail_h + +#include "mozilla/Atomics.h" +#include "mozilla/Attributes.h" +#include "mozilla/Maybe.h" +#include "mozilla/PlatformMutex.h" +#include "mozilla/PlatformRWLock.h" +#include "mozilla/BaseProfilerUtils.h" + +namespace mozilla { +namespace baseprofiler { + +namespace detail { + +// Thin shell around mozglue PlatformMutex, for Base Profiler internal use. +class MOZ_CAPABILITY("mutex") BaseProfilerMutex + : private ::mozilla::detail::MutexImpl { + public: + BaseProfilerMutex() : ::mozilla::detail::MutexImpl() {} + explicit BaseProfilerMutex(const char* aName) + : ::mozilla::detail::MutexImpl(), mName(aName) {} + + BaseProfilerMutex(const BaseProfilerMutex&) = delete; + BaseProfilerMutex& operator=(const BaseProfilerMutex&) = delete; + BaseProfilerMutex(BaseProfilerMutex&&) = delete; + BaseProfilerMutex& operator=(BaseProfilerMutex&&) = delete; + +#ifdef DEBUG + ~BaseProfilerMutex() { + MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(), + "BaseProfilerMutex should have been unlocked when destroyed"); + } +#endif // DEBUG + + [[nodiscard]] bool IsLockedOnCurrentThread() const { + return BaseProfilerThreadId::FromNumber(mOwningThreadId) == + baseprofiler::profiler_current_thread_id(); + } + + void AssertCurrentThreadOwns() const MOZ_ASSERT_CAPABILITY(this) { + MOZ_ASSERT(IsLockedOnCurrentThread()); + } + + void Lock() MOZ_CAPABILITY_ACQUIRE() { + const BaseProfilerThreadId tid = baseprofiler::profiler_current_thread_id(); + MOZ_ASSERT(tid.IsSpecified()); + MOZ_ASSERT(!IsLockedOnCurrentThread(), "Recursive locking"); + ::mozilla::detail::MutexImpl::lock(); + MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(), + "Not unlocked properly"); + mOwningThreadId = tid.ToNumber(); + } + + [[nodiscard]] bool TryLock() MOZ_TRY_ACQUIRE(true) { + const BaseProfilerThreadId tid = baseprofiler::profiler_current_thread_id(); + MOZ_ASSERT(tid.IsSpecified()); + MOZ_ASSERT(!IsLockedOnCurrentThread(), "Recursive locking"); + if (!::mozilla::detail::MutexImpl::tryLock()) { + // Failed to lock, nothing more to do. + return false; + } + MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(), + "Not unlocked properly"); + mOwningThreadId = tid.ToNumber(); + return true; + } + + void Unlock() MOZ_CAPABILITY_RELEASE() { + MOZ_ASSERT(IsLockedOnCurrentThread(), "Unlocking when not locked here"); + // We're still holding the mutex here, so it's safe to just reset + // `mOwningThreadId`. + mOwningThreadId = BaseProfilerThreadId{}.ToNumber(); + ::mozilla::detail::MutexImpl::unlock(); + } + + const char* GetName() const { return mName; } + + private: + // Thread currently owning the lock, or 0. + // Atomic because it may be read at any time independent of the mutex. + // Relaxed because threads only need to know if they own it already, so: + // - If it's their id, only *they* wrote that value with a locked mutex. + // - If it's different from their thread id it doesn't matter what other + // number it is (0 or another id) and that it can change again at any time. + Atomic + mOwningThreadId; + + const char* mName = nullptr; +}; + +// RAII class to lock a mutex. +class MOZ_RAII BaseProfilerAutoLock { + public: + explicit BaseProfilerAutoLock(BaseProfilerMutex& aMutex) : mMutex(aMutex) { + mMutex.Lock(); + } + + BaseProfilerAutoLock(const BaseProfilerAutoLock&) = delete; + BaseProfilerAutoLock& operator=(const BaseProfilerAutoLock&) = delete; + BaseProfilerAutoLock(BaseProfilerAutoLock&&) = delete; + BaseProfilerAutoLock& operator=(BaseProfilerAutoLock&&) = delete; + + ~BaseProfilerAutoLock() { mMutex.Unlock(); } + + private: + BaseProfilerMutex& mMutex; +}; + +// Thin shell around mozglue PlatformMutex, for Base Profiler internal use. +// Actual mutex may be disabled at construction time. +class BaseProfilerMaybeMutex : private ::mozilla::detail::MutexImpl { + public: + explicit BaseProfilerMaybeMutex(bool aActivate) { + if (aActivate) { + mMaybeMutex.emplace(); + } + } + + BaseProfilerMaybeMutex(const BaseProfilerMaybeMutex&) = delete; + BaseProfilerMaybeMutex& operator=(const BaseProfilerMaybeMutex&) = delete; + BaseProfilerMaybeMutex(BaseProfilerMaybeMutex&&) = delete; + BaseProfilerMaybeMutex& operator=(BaseProfilerMaybeMutex&&) = delete; + + ~BaseProfilerMaybeMutex() = default; + + bool IsActivated() const { return mMaybeMutex.isSome(); } + + [[nodiscard]] bool IsActivatedAndLockedOnCurrentThread() const { + if (!IsActivated()) { + // Not activated, so we can never be locked. + return false; + } + return mMaybeMutex->IsLockedOnCurrentThread(); + } + + void AssertCurrentThreadOwns() const { +#ifdef DEBUG + if (IsActivated()) { + mMaybeMutex->AssertCurrentThreadOwns(); + } +#endif // DEBUG + } + + MOZ_PUSH_IGNORE_THREAD_SAFETY + void Lock() { + if (IsActivated()) { + mMaybeMutex->Lock(); + } + } + + void Unlock() { + if (IsActivated()) { + mMaybeMutex->Unlock(); + } + } + MOZ_POP_THREAD_SAFETY + + private: + Maybe mMaybeMutex; +}; + +// RAII class to lock a mutex. +class MOZ_RAII BaseProfilerMaybeAutoLock { + public: + explicit BaseProfilerMaybeAutoLock(BaseProfilerMaybeMutex& aMaybeMutex) + : mMaybeMutex(aMaybeMutex) { + mMaybeMutex.Lock(); + } + + BaseProfilerMaybeAutoLock(const BaseProfilerMaybeAutoLock&) = delete; + BaseProfilerMaybeAutoLock& operator=(const BaseProfilerMaybeAutoLock&) = + delete; + BaseProfilerMaybeAutoLock(BaseProfilerMaybeAutoLock&&) = delete; + BaseProfilerMaybeAutoLock& operator=(BaseProfilerMaybeAutoLock&&) = delete; + + ~BaseProfilerMaybeAutoLock() { mMaybeMutex.Unlock(); } + + private: + BaseProfilerMaybeMutex& mMaybeMutex; +}; + +class BaseProfilerSharedMutex : public ::mozilla::detail::RWLockImpl { + public: +#ifdef DEBUG + ~BaseProfilerSharedMutex() { + MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(), + "BaseProfilerMutex should have been unlocked when destroyed"); + } +#endif // DEBUG + + [[nodiscard]] bool IsLockedExclusiveOnCurrentThread() const { + return BaseProfilerThreadId::FromNumber(mOwningThreadId) == + baseprofiler::profiler_current_thread_id(); + } + + void LockExclusive() { + const BaseProfilerThreadId tid = baseprofiler::profiler_current_thread_id(); + MOZ_ASSERT(tid.IsSpecified()); + MOZ_ASSERT(!IsLockedExclusiveOnCurrentThread(), "Recursive locking"); + ::mozilla::detail::RWLockImpl::writeLock(); + MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(), + "Not unlocked properly"); + mOwningThreadId = tid.ToNumber(); + } + + void UnlockExclusive() { + MOZ_ASSERT(IsLockedExclusiveOnCurrentThread(), + "Unlocking when not locked here"); + // We're still holding the mutex here, so it's safe to just reset + // `mOwningThreadId`. + mOwningThreadId = BaseProfilerThreadId{}.ToNumber(); + writeUnlock(); + } + + void LockShared() { readLock(); } + + void UnlockShared() { readUnlock(); } + + private: + // Thread currently owning the exclusive lock, or 0. + // Atomic because it may be read at any time independent of the mutex. + // Relaxed because threads only need to know if they own it already, so: + // - If it's their id, only *they* wrote that value with a locked mutex. + // - If it's different from their thread id it doesn't matter what other + // number it is (0 or another id) and that it can change again at any time. + Atomic + mOwningThreadId; +}; + +// RAII class to lock a shared mutex exclusively. +class MOZ_RAII BaseProfilerAutoLockExclusive { + public: + explicit BaseProfilerAutoLockExclusive(BaseProfilerSharedMutex& aSharedMutex) + : mSharedMutex(aSharedMutex) { + mSharedMutex.LockExclusive(); + } + + BaseProfilerAutoLockExclusive(const BaseProfilerAutoLockExclusive&) = delete; + BaseProfilerAutoLockExclusive& operator=( + const BaseProfilerAutoLockExclusive&) = delete; + BaseProfilerAutoLockExclusive(BaseProfilerAutoLockExclusive&&) = delete; + BaseProfilerAutoLockExclusive& operator=(BaseProfilerAutoLockExclusive&&) = + delete; + + ~BaseProfilerAutoLockExclusive() { mSharedMutex.UnlockExclusive(); } + + private: + BaseProfilerSharedMutex& mSharedMutex; +}; + +// RAII class to lock a shared mutex non-exclusively, other +// BaseProfilerAutoLockShared's may happen in other threads. +class MOZ_RAII BaseProfilerAutoLockShared { + public: + explicit BaseProfilerAutoLockShared(BaseProfilerSharedMutex& aSharedMutex) + : mSharedMutex(aSharedMutex) { + mSharedMutex.LockShared(); + } + + BaseProfilerAutoLockShared(const BaseProfilerAutoLockShared&) = delete; + BaseProfilerAutoLockShared& operator=(const BaseProfilerAutoLockShared&) = + delete; + BaseProfilerAutoLockShared(BaseProfilerAutoLockShared&&) = delete; + BaseProfilerAutoLockShared& operator=(BaseProfilerAutoLockShared&&) = delete; + + ~BaseProfilerAutoLockShared() { mSharedMutex.UnlockShared(); } + + private: + BaseProfilerSharedMutex& mSharedMutex; +}; + +} // namespace detail +} // namespace baseprofiler +} // namespace mozilla + +#endif // BaseProfilerDetail_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerLabels.h b/src/third_party/mozjs/include/mozilla/BaseProfilerLabels.h new file mode 100644 index 00000000000..8da596e3abf --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerLabels.h @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This header contains all definitions related to Base Profiler labels (outside +// of XUL). +// It is safe to include unconditionally, and only defines empty macros if +// MOZ_GECKO_PROFILER is not set. + +#ifndef BaseProfilerLabels_h +#define BaseProfilerLabels_h + +#ifndef MOZ_GECKO_PROFILER + +# define AUTO_BASE_PROFILER_LABEL(label, categoryPair) +# define AUTO_BASE_PROFILER_LABEL_CATEGORY_PAIR(categoryPair) +# define AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr) +# define AUTO_BASE_PROFILER_LABEL_DYNAMIC_STRING(label, categoryPair, str) +# define AUTO_BASE_PROFILER_LABEL_FAST(label, categoryPair, ctx) +# define AUTO_BASE_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, \ + categoryPair, ctx, flags) + +#else // !MOZ_GECKO_PROFILER + +# include "BaseProfilingStack.h" + +# include "mozilla/Attributes.h" +# include "mozilla/Maybe.h" +# include "mozilla/BaseProfilerRAIIMacro.h" +# include "mozilla/BaseProfilerState.h" +# include "mozilla/ThreadLocal.h" + +# include +# include + +namespace mozilla::baseprofiler { + +// Insert an RAII object in this scope to enter a label stack frame. Any +// samples collected in this scope will contain this label in their stack. +// The label argument must be a static C string. It is usually of the +// form "ClassName::FunctionName". (Ideally we'd use the compiler to provide +// that for us, but __func__ gives us the function name without the class +// name.) If the label applies to only part of a function, you can qualify it +// like this: "ClassName::FunctionName:PartName". +// +// Use AUTO_BASE_PROFILER_LABEL_DYNAMIC_* if you want to add additional / +// dynamic information to the label stack frame. +# define AUTO_BASE_PROFILER_LABEL(label, categoryPair) \ + ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII( \ + label, nullptr, \ + ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair) + +// Similar to AUTO_BASE_PROFILER_LABEL, but with only one argument: the category +// pair. The label string is taken from the category pair. This is convenient +// for labels like +// AUTO_BASE_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_LayerBuilding) which would +// otherwise just repeat the string. +# define AUTO_BASE_PROFILER_LABEL_CATEGORY_PAIR(categoryPair) \ + ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII( \ + "", nullptr, \ + ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair, \ + uint32_t(::mozilla::baseprofiler::ProfilingStackFrame::Flags:: \ + LABEL_DETERMINED_BY_CATEGORY_PAIR)) + +// Similar to AUTO_BASE_PROFILER_LABEL, but with an additional string. The +// inserted RAII object stores the cStr pointer in a field; it does not copy the +// string. +// +// WARNING: This means that the string you pass to this macro needs to live at +// least until the end of the current scope. Be careful using this macro with +// ns[C]String; the other AUTO_BASE_PROFILER_LABEL_DYNAMIC_* macros below are +// preferred because they avoid this problem. +// +// If the profiler samples the current thread and walks the label stack while +// this RAII object is on the stack, it will copy the supplied string into the +// profile buffer. So there's one string copy operation, and it happens at +// sample time. +// +// Compare this to the plain AUTO_BASE_PROFILER_LABEL macro, which only accepts +// literal strings: When the label stack frames generated by +// AUTO_BASE_PROFILER_LABEL are sampled, no string copy needs to be made because +// the profile buffer can just store the raw pointers to the literal strings. +// Consequently, AUTO_BASE_PROFILER_LABEL frames take up considerably less space +// in the profile buffer than AUTO_BASE_PROFILER_LABEL_DYNAMIC_* frames. +# define AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr) \ + ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII( \ + label, cStr, \ + ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair) + +// Similar to AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR, but takes an std::string. +// +// Note: The use of the Maybe<>s ensures the scopes for the dynamic string and +// the AutoProfilerLabel are appropriate, while also not incurring the runtime +// cost of the string assignment unless the profiler is active. Therefore, +// unlike AUTO_BASE_PROFILER_LABEL and AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR, +// this macro doesn't push/pop a label when the profiler is inactive. +# define AUTO_BASE_PROFILER_LABEL_DYNAMIC_STRING(label, categoryPair, str) \ + Maybe autoStr; \ + Maybe<::mozilla::baseprofiler::AutoProfilerLabel> raiiObjectString; \ + if (::mozilla::baseprofiler::profiler_is_active()) { \ + autoStr.emplace(str); \ + raiiObjectString.emplace( \ + label, autoStr->c_str(), \ + ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair); \ + } + +// Similar to AUTO_BASE_PROFILER_LABEL, but accepting a JSContext* parameter, +// and a no-op if the profiler is disabled. Used to annotate functions for which +// overhead in the range of nanoseconds is noticeable. It avoids overhead from +// the TLS lookup because it can get the ProfilingStack from the JS context, and +// avoids almost all overhead in the case where the profiler is disabled. +# define AUTO_BASE_PROFILER_LABEL_FAST(label, categoryPair, ctx) \ + ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII( \ + ctx, label, nullptr, \ + ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair) + +// Similar to AUTO_BASE_PROFILER_LABEL_FAST, but also takes an extra string and +// an additional set of flags. The flags parameter should carry values from the +// ProfilingStackFrame::Flags enum. +# define AUTO_BASE_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, \ + categoryPair, ctx, flags) \ + ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII( \ + ctx, label, dynamicString, \ + ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair, flags) + +// This class creates a non-owning ProfilingStack reference. Objects of this +// class are stack-allocated, and so exist within a thread, and are thus bounded +// by the lifetime of the thread, which ensures that the references held can't +// be used after the ProfilingStack is destroyed. +class MOZ_RAII AutoProfilerLabel { + public: + // This is the AUTO_BASE_PROFILER_LABEL and AUTO_BASE_PROFILER_LABEL_DYNAMIC + // variant. + AutoProfilerLabel(const char* aLabel, const char* aDynamicString, + ProfilingCategoryPair aCategoryPair, uint32_t aFlags = 0) { + // Get the ProfilingStack from TLS. + Push(GetProfilingStack(), aLabel, aDynamicString, aCategoryPair, aFlags); + } + + void Push(ProfilingStack* aProfilingStack, const char* aLabel, + const char* aDynamicString, ProfilingCategoryPair aCategoryPair, + uint32_t aFlags = 0) { + // This function runs both on and off the main thread. + + mProfilingStack = aProfilingStack; + if (mProfilingStack) { + mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this, + aCategoryPair, aFlags); + } + } + + ~AutoProfilerLabel() { + // This function runs both on and off the main thread. + + if (mProfilingStack) { + mProfilingStack->pop(); + } + } + + MFBT_API static ProfilingStack* GetProfilingStack(); + + private: + // We save a ProfilingStack pointer in the ctor so we don't have to redo the + // TLS lookup in the dtor. + ProfilingStack* mProfilingStack; + + public: + // See the comment on the definition in platform.cpp for details about this. + static MOZ_THREAD_LOCAL(ProfilingStack*) sProfilingStack; +}; + +} // namespace mozilla::baseprofiler + +#endif // !MOZ_GECKO_PROFILER + +#endif // BaseProfilerLabels_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerMarkerTypes.h b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkerTypes.h new file mode 100644 index 00000000000..b2cec18a7a3 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkerTypes.h @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BaseProfilerMarkerTypes_h +#define BaseProfilerMarkerTypes_h + +// This header contains common marker type definitions. +// +// It #include's "mozilla/BaseProfilerMarkers.h", see that file for how to +// define other marker types, and how to add markers to the profiler buffers. +// +// If you don't need to use these common types, #include +// "mozilla/BaseProfilerMarkers.h" instead. +// +// Types in this files can be defined without relying on xpcom. +// Others are defined in "ProfilerMarkerTypes.h". + +// !!! /!\ WORK IN PROGRESS /!\ !!! +// This file contains draft marker definitions, but most are not used yet. +// Further work is needed to complete these definitions, and use them to convert +// existing PROFILER_ADD_MARKER calls. See meta bug 1661394. + +#include "mozilla/BaseProfilerMarkers.h" + +namespace mozilla::baseprofiler::markers { + +struct MediaSampleMarker { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("MediaSample"); + } + static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter, + int64_t aSampleStartTimeUs, + int64_t aSampleEndTimeUs, + int64_t aQueueLength) { + aWriter.IntProperty("sampleStartTimeUs", aSampleStartTimeUs); + aWriter.IntProperty("sampleEndTimeUs", aSampleEndTimeUs); + aWriter.IntProperty("queueLength", aQueueLength); + } + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + schema.AddKeyLabelFormat("sampleStartTimeUs", "Sample start time", + MS::Format::Microseconds); + schema.AddKeyLabelFormat("sampleEndTimeUs", "Sample end time", + MS::Format::Microseconds); + schema.AddKeyLabelFormat("queueLength", "Queue length", + MS::Format::Integer); + return schema; + } +}; + +struct VideoFallingBehindMarker { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("VideoFallingBehind"); + } + static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter, + int64_t aVideoFrameStartTimeUs, + int64_t aMediaCurrentTimeUs) { + aWriter.IntProperty("videoFrameStartTimeUs", aVideoFrameStartTimeUs); + aWriter.IntProperty("mediaCurrentTimeUs", aMediaCurrentTimeUs); + } + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + schema.AddKeyLabelFormat("videoFrameStartTimeUs", "Video frame start time", + MS::Format::Microseconds); + schema.AddKeyLabelFormat("mediaCurrentTimeUs", "Media current time", + MS::Format::Microseconds); + return schema; + } +}; + +struct ContentBuildMarker { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("CONTENT_FULL_PAINT_TIME"); + } + static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter) {} + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + return schema; + } +}; + +struct MediaEngineMarker { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("MediaEngine"); + } + static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, + uint64_t aMediaEngineId) { + aWriter.IntProperty("id", aMediaEngineId); + } + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + schema.AddKeyLabelFormat("id", "Id", MS::Format::Integer); + return schema; + } +}; + +struct MediaEngineTextMarker { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("MediaEngineText"); + } + static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, + uint64_t aMediaEngineId, + const ProfilerString8View& aText) { + aWriter.IntProperty("id", aMediaEngineId); + aWriter.StringProperty("text", aText); + } + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + schema.AddKeyLabelFormat("id", "Id", MS::Format::Integer); + schema.AddKeyLabelFormat("text", "Details", MS::Format::String); + return schema; + } +}; + +struct VideoSinkRenderMarker { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("VideoSinkRender"); + } + static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, + int64_t aClockTimeUs) { + aWriter.IntProperty("clockTimeUs", aClockTimeUs); + } + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + schema.AddKeyLabelFormat("clockTimeUs", "Clock time", + MS::Format::Microseconds); + return schema; + } +}; + +} // namespace mozilla::baseprofiler::markers + +#endif // BaseProfilerMarkerTypes_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerMarkers.h b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkers.h new file mode 100644 index 00000000000..00ed8c1ed8e --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkers.h @@ -0,0 +1,268 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Markers are useful to delimit something important happening such as the first +// paint. Unlike labels, which are only recorded in the profile buffer if a +// sample is collected while the label is on the label stack, markers will +// always be recorded in the profile buffer. +// +// This header contains basic definitions necessary to create marker types, and +// to add markers to the profiler buffers. +// +// If basic marker types are needed, #include +// "mozilla/BaseProfilerMarkerTypes.h" instead. +// +// But if you want to create your own marker type locally, you can #include this +// header only; look at mozilla/BaseProfilerMarkerTypes.h for examples of how to +// define types, and mozilla/BaseProfilerMarkerPrerequisites.h for some +// supporting types. +// +// To then record markers: +// - Use `baseprofiler::AddMarker(...)` from mozglue or other libraries that +// are outside of xul, especially if they may happen outside of xpcom's +// lifetime (typically startup, shutdown, or tests). +// - Otherwise #include "ProfilerMarkers.h" instead, and use +// `profiler_add_marker(...)`. +// See these functions for more details. + +#ifndef BaseProfilerMarkers_h +#define BaseProfilerMarkers_h + +#include "mozilla/BaseProfilerMarkersDetail.h" +#include "mozilla/BaseProfilerLabels.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/Unused.h" + +#include +#include +#include + +namespace mozilla::baseprofiler { + +#ifdef MOZ_GECKO_PROFILER +// Forward-declaration. TODO: Move to more common header, see bug 1681416. +MFBT_API bool profiler_capture_backtrace_into( + ProfileChunkedBuffer& aChunkedBuffer, StackCaptureOptions aCaptureOptions); + +// Add a marker to a given buffer. `AddMarker()` and related macros should be +// used in most cases, see below for more information about them and the +// parameters; This function may be useful when markers need to be recorded in a +// local buffer outside of the main profiler buffer. +template +ProfileBufferBlockIndex AddMarkerToBuffer( + ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName, + const MarkerCategory& aCategory, MarkerOptions&& aOptions, + MarkerType aMarkerType, const PayloadArguments&... aPayloadArguments) { + Unused << aMarkerType; // Only the empty object type is useful. + AUTO_BASE_PROFILER_LABEL("baseprofiler::AddMarkerToBuffer", PROFILER); + return base_profiler_markers_detail::AddMarkerToBuffer( + aBuffer, aName, aCategory, std::move(aOptions), + // Do not capture a stack if the NoMarkerStacks feature is set. + profiler_active_without_feature(ProfilerFeature::NoMarkerStacks) + ? ::mozilla::baseprofiler::profiler_capture_backtrace_into + : nullptr, + aPayloadArguments...); +} + +// Add a marker (without payload) to a given buffer. +inline ProfileBufferBlockIndex AddMarkerToBuffer( + ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName, + const MarkerCategory& aCategory, MarkerOptions&& aOptions = {}) { + return AddMarkerToBuffer(aBuffer, aName, aCategory, std::move(aOptions), + markers::NoPayload{}); +} +#endif // MOZ_GECKO_PROFILER + +// Add a marker to the Base Profiler buffer. +// - aName: Main name of this marker. +// - aCategory: Category for this marker. +// - aOptions: Optional settings (such as timing, inner window id, +// backtrace...), see `MarkerOptions` for details. +// - aMarkerType: Empty object that specifies the type of marker. +// - aPayloadArguments: Arguments expected by this marker type's +// ` StreamJSONMarkerData` function. +template +ProfileBufferBlockIndex AddMarker( + const ProfilerString8View& aName, const MarkerCategory& aCategory, + MarkerOptions&& aOptions, MarkerType aMarkerType, + const PayloadArguments&... aPayloadArguments) { +#ifndef MOZ_GECKO_PROFILER + return {}; +#else + // Record base markers whenever the core buffer is in session. + // TODO: When profiler_thread_is_being_profiled becomes available from + // mozglue, use it instead. + ProfileChunkedBuffer& coreBuffer = + ::mozilla::baseprofiler::profiler_get_core_buffer(); + if (!coreBuffer.IsInSession()) { + return {}; + } + return ::mozilla::baseprofiler::AddMarkerToBuffer( + coreBuffer, aName, aCategory, std::move(aOptions), aMarkerType, + aPayloadArguments...); +#endif +} + +// Add a marker (without payload) to the Base Profiler buffer. +inline ProfileBufferBlockIndex AddMarker(const ProfilerString8View& aName, + const MarkerCategory& aCategory, + MarkerOptions&& aOptions = {}) { + return AddMarker(aName, aCategory, std::move(aOptions), markers::NoPayload{}); +} + +} // namespace mozilla::baseprofiler + +// Same as `AddMarker()` (without payload). This macro is safe to use even if +// MOZ_GECKO_PROFILER is not #defined. +#define BASE_PROFILER_MARKER_UNTYPED(markerName, categoryName, ...) \ + do { \ + AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_UNTYPED); \ + ::mozilla::baseprofiler::AddMarker( \ + markerName, ::mozilla::baseprofiler::category::categoryName, \ + ##__VA_ARGS__); \ + } while (false) + +// Same as `AddMarker()` (with payload). This macro is safe to use even if +// MOZ_GECKO_PROFILER is not #defined. +#define BASE_PROFILER_MARKER(markerName, categoryName, options, MarkerType, \ + ...) \ + do { \ + AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_with_##MarkerType); \ + ::mozilla::baseprofiler::AddMarker( \ + markerName, ::mozilla::baseprofiler::category::categoryName, options, \ + ::mozilla::baseprofiler::markers::MarkerType{}, ##__VA_ARGS__); \ + } while (false) + +namespace mozilla::baseprofiler::markers { +// Most common marker type. Others are in BaseProfilerMarkerTypes.h. +struct TextMarker : public BaseMarkerType { + static constexpr const char* Name = "Text"; + // It's not possible to add a single meaningful description to this marker + // type since it can be used by various different markers. + static constexpr const char* Description = nullptr; + + static constexpr bool StoreName = true; + + using MS = MarkerSchema; + static constexpr MS::PayloadField PayloadFields[] = + // XXX - This is confusingly labeled 'name'. We probably want to fix that. + {{"name", MS::InputType::CString, "Details", MS::Format::String, + MS::PayloadFlags::Searchable}}; + + static constexpr MS::Location Locations[] = {MS::Location::MarkerChart, + MS::Location::MarkerTable}; + + static constexpr const char* ChartLabel = "{marker.data.name}"; + static constexpr const char* TableLabel = + "{marker.name} - {marker.data.name}"; + + static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter, + const ProfilerString8View& aText) { + aWriter.StringProperty("name", aText); + } +}; + +// Keep this struct in sync with the `gecko_profiler::marker::Tracing` Rust +// counterpart. +struct Tracing : public BaseMarkerType { + static constexpr const char* Name = "tracing"; + // It's not possible to add a single meaningful description to this marker + // type since it can be used by various different markers. + static constexpr const char* Description = nullptr; + + static constexpr bool StoreName = true; + + using MS = MarkerSchema; + static constexpr MS::PayloadField PayloadFields[] = { + {"category", MS::InputType::CString, "Type", MS::Format::String, + MS::PayloadFlags::Searchable}}; + + static constexpr MS::Location Locations[] = {MS::Location::MarkerChart, + MS::Location::MarkerTable, + MS::Location::TimelineOverview}; + + static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter, + const ProfilerString8View& aCategory) { + if (aCategory.Length() != 0) { + aWriter.StringProperty("category", aCategory); + } + } +}; +} // namespace mozilla::baseprofiler::markers + +// Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is +// not #defined. +#define BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, text) \ + do { \ + AUTO_PROFILER_STATS(BASE_PROFILER_MARKER_TEXT); \ + ::mozilla::baseprofiler::AddMarker( \ + markerName, ::mozilla::baseprofiler::category::categoryName, options, \ + ::mozilla::baseprofiler::markers::TextMarker{}, text); \ + } while (false) + +namespace mozilla::baseprofiler { + +// RAII object that adds a BASE_PROFILER_MARKER_TEXT when destroyed; the +// marker's timing will be the interval from construction (unless an instant or +// start time is already specified in the provided options) until destruction. +class MOZ_RAII AutoProfilerTextMarker { + public: + AutoProfilerTextMarker(const char* aMarkerName, + const MarkerCategory& aCategory, + MarkerOptions&& aOptions, const std::string& aText) + : mMarkerName(aMarkerName), + mCategory(aCategory), + mOptions(std::move(aOptions)), + mText(aText) { + MOZ_ASSERT(mOptions.Timing().EndTime().IsNull(), + "AutoProfilerTextMarker options shouldn't have an end time"); + if (profiler_is_active_and_unpaused() && + mOptions.Timing().StartTime().IsNull()) { + mOptions.Set(MarkerTiming::InstantNow()); + } + } + + ~AutoProfilerTextMarker() { + if (profiler_is_active_and_unpaused()) { + mOptions.TimingRef().SetIntervalEnd(); + AUTO_PROFILER_STATS(AUTO_BASE_PROFILER_MARKER_TEXT); + AddMarker(ProfilerString8View::WrapNullTerminatedString(mMarkerName), + mCategory, std::move(mOptions), markers::TextMarker{}, mText); + } + } + + protected: + const char* mMarkerName; + MarkerCategory mCategory; + MarkerOptions mOptions; + std::string mText; +}; + +#ifdef MOZ_GECKO_PROFILER +extern template MFBT_API ProfileBufferBlockIndex +AddMarker(const ProfilerString8View&, const MarkerCategory&, MarkerOptions&&, + markers::TextMarker, const std::string&); + +extern template MFBT_API ProfileBufferBlockIndex +AddMarkerToBuffer(ProfileChunkedBuffer&, const ProfilerString8View&, + const MarkerCategory&, MarkerOptions&&, markers::NoPayload); + +extern template MFBT_API ProfileBufferBlockIndex AddMarkerToBuffer( + ProfileChunkedBuffer&, const ProfilerString8View&, const MarkerCategory&, + MarkerOptions&&, markers::TextMarker, const std::string&); +#endif // MOZ_GECKO_PROFILER + +} // namespace mozilla::baseprofiler + +// Creates an AutoProfilerTextMarker RAII object. This macro is safe to use +// even if MOZ_GECKO_PROFILER is not #defined. +#define AUTO_BASE_PROFILER_MARKER_TEXT(markerName, categoryName, options, \ + text) \ + ::mozilla::baseprofiler::AutoProfilerTextMarker PROFILER_RAII( \ + markerName, ::mozilla::baseprofiler::category::categoryName, options, \ + text) + +#endif // BaseProfilerMarkers_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerMarkersDetail.h b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkersDetail.h new file mode 100644 index 00000000000..259944cffcb --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkersDetail.h @@ -0,0 +1,743 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BaseProfilerMarkersDetail_h +#define BaseProfilerMarkersDetail_h + +#ifndef BaseProfilerMarkers_h +# error "This header should only be #included by BaseProfilerMarkers.h" +#endif + +#include "mozilla/BaseProfilerMarkersPrerequisites.h" + +// ~~ HERE BE DRAGONS ~~ +// +// Everything below is internal implementation detail, you shouldn't need to +// look at it unless working on the profiler code. + +#include "mozilla/BaseProfileJSONWriter.h" +#include "mozilla/ProfileBufferEntryKinds.h" + +#include +#include +#include + +namespace mozilla::baseprofiler { +// Implemented in platform.cpp +MFBT_API ProfileChunkedBuffer& profiler_get_core_buffer(); +} // namespace mozilla::baseprofiler + +namespace mozilla::base_profiler_markers_detail { + +struct Streaming { + // A `MarkerDataDeserializer` is a free function that can read a serialized + // payload from an `EntryReader` and streams it as JSON object properties. + using MarkerDataDeserializer = void (*)(ProfileBufferEntryReader&, + baseprofiler::SpliceableJSONWriter&); + + // A `MarkerTypeNameFunction` is a free function that returns the name of the + // marker type. + using MarkerTypeNameFunction = Span (*)(); + + // A `MarkerSchemaFunction` is a free function that returns a + // `MarkerSchema`, which contains all the information needed to stream + // the display schema associated with a marker type. + using MarkerSchemaFunction = MarkerSchema (*)(); + + struct MarkerTypeFunctions { + MarkerDataDeserializer mMarkerDataDeserializer = nullptr; + MarkerTypeNameFunction mMarkerTypeNameFunction = nullptr; + MarkerSchemaFunction mMarkerSchemaFunction = nullptr; + }; + + // A `DeserializerTag` will be added before the payload, to help select the + // correct deserializer when reading back the payload. + using DeserializerTag = uint8_t; + + // Store a deserializer (and other marker-type-specific functions) and get its + // `DeserializerTag`. + // This is intended to be only used once per deserializer when a new marker + // type is used for the first time, so it should be called to initialize a + // `static const` tag that will be re-used by all markers of the corresponding + // payload type -- see use below. + MFBT_API static DeserializerTag TagForMarkerTypeFunctions( + MarkerDataDeserializer aDeserializer, + MarkerTypeNameFunction aMarkerTypeNameFunction, + MarkerSchemaFunction aMarkerSchemaFunction); + + // Get the `MarkerDataDeserializer` for a given `DeserializerTag`. + MFBT_API static MarkerDataDeserializer DeserializerForTag( + DeserializerTag aTag); + + // Retrieve all MarkerTypeFunctions's. + // While this object lives, no other operations can happen on this list. + class LockedMarkerTypeFunctionsList { + public: + MFBT_API LockedMarkerTypeFunctionsList(); + MFBT_API ~LockedMarkerTypeFunctionsList(); + + LockedMarkerTypeFunctionsList(const LockedMarkerTypeFunctionsList&) = + delete; + LockedMarkerTypeFunctionsList& operator=( + const LockedMarkerTypeFunctionsList&) = delete; + + auto begin() const { return mMarkerTypeFunctionsSpan.begin(); } + auto end() const { return mMarkerTypeFunctionsSpan.end(); } + + private: + Span mMarkerTypeFunctionsSpan; + }; +}; + +// This helper will examine a marker type's `StreamJSONMarkerData` function, see +// specialization below. +template +struct StreamFunctionTypeHelper; + +// Helper specialization that takes the expected +// `StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter&, ...)` function and +// provide information about the `...` parameters. +template +struct StreamFunctionTypeHelper { + constexpr static size_t scArity = sizeof...(As); + using TupleType = + std::tuple>...>; + + // Serialization function that takes the exact same parameter types + // (const-ref'd) as `StreamJSONMarkerData`. This has to be inside the helper + // because only here can we access the raw parameter pack `As...`. + // And because we're using the same argument types through + // references-to-const, permitted implicit conversions can happen. + static ProfileBufferBlockIndex Serialize( + ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName, + const MarkerCategory& aCategory, MarkerOptions&& aOptions, + Streaming::DeserializerTag aDeserializerTag, const As&... aAs) { + // Note that options are first after the entry kind, because they contain + // the thread id, which is handled first to filter markers by threads. + return aBuffer.PutObjects(ProfileBufferEntryKind::Marker, aOptions, aName, + aCategory, aDeserializerTag, + MarkerPayloadType::Cpp, aAs...); + } +}; + +// Helper for a marker type. +// A marker type is defined in a `struct` with some expected static member +// functions. See example in BaseProfilerMarkers.h. +template +struct MarkerTypeSerialization { + // Definitions to access the expected + // `StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter&, ...)` function + // and its parameters. + using StreamFunctionType = + StreamFunctionTypeHelper; + constexpr static size_t scStreamFunctionParameterCount = + StreamFunctionType::scArity; + using StreamFunctionUserParametersTuple = + typename StreamFunctionType::TupleType; + template + using StreamFunctionParameter = + std::tuple_element_t; + + template + static ProfileBufferBlockIndex Serialize(ProfileChunkedBuffer& aBuffer, + const ProfilerString8View& aName, + const MarkerCategory& aCategory, + MarkerOptions&& aOptions, + const Ts&... aTs) { + static_assert(!std::is_same_v, + "NoPayload should have been handled in the caller."); + // Register marker type functions, and get the tag for this deserializer. + // Note that the tag is stored in a function-static object, and this + // function is static in a templated struct, so there should only be one tag + // per MarkerType. + // Making the tag class-static may have been more efficient (to avoid a + // thread-safe init check at every call), but random global static + // initialization order would make it more complex to coordinate with + // `Streaming::TagForMarkerTypeFunctions()`, and also would add a (small) + // cost for everybody, even the majority of users not using the profiler. + static const Streaming::DeserializerTag tag = + Streaming::TagForMarkerTypeFunctions(Deserialize, + MarkerType::MarkerTypeName, + MarkerType::MarkerTypeDisplay); + return StreamFunctionType::Serialize(aBuffer, aName, aCategory, + std::move(aOptions), tag, aTs...); + } + + private: + // This templated function will recursively deserialize each argument expected + // by `MarkerType::StreamJSONMarkerData()` on the stack, and call it at the + // end. E.g., for `StreamJSONMarkerData(int, char)`: + // - DeserializeArguments<0>(aER, aWriter) reads an int and calls: + // - DeserializeArguments<1>(aER, aWriter, const int&) reads a char and calls: + // - MarkerType::StreamJSONMarkerData(aWriter, const int&, const char&). + // Prototyping on godbolt showed that clang and gcc can flatten these + // recursive calls into one function with successive reads followed by the one + // stream call; tested up to 40 arguments: https://godbolt.org/z/5KeeM4 + template + static void DeserializeArguments(ProfileBufferEntryReader& aEntryReader, + baseprofiler::SpliceableJSONWriter& aWriter, + const Args&... aArgs) { + static_assert(sizeof...(Args) == i, + "We should have collected `i` arguments so far"); + if constexpr (i < scStreamFunctionParameterCount) { + // Deserialize the i-th argument on this stack. + auto argument = aEntryReader.ReadObject>(); + // Add our local argument to the next recursive call. + DeserializeArguments(aEntryReader, aWriter, aArgs..., argument); + } else { + // We've read all the arguments, finally call the `StreamJSONMarkerData` + // function, which should write the appropriate JSON elements for this + // marker type. Note that the MarkerType-specific "type" element is + // already written. + MarkerType::StreamJSONMarkerData(aWriter, aArgs...); + } + } + + public: + static void Deserialize(ProfileBufferEntryReader& aEntryReader, + baseprofiler::SpliceableJSONWriter& aWriter) { + aWriter.StringProperty("type", MarkerType::MarkerTypeName()); + DeserializeArguments(aEntryReader, aWriter); + } +}; + +template <> +struct MarkerTypeSerialization<::mozilla::baseprofiler::markers::NoPayload> { + // Nothing! NoPayload has special handling avoiding payload work. +}; + +template +static ProfileBufferBlockIndex AddMarkerWithOptionalStackToBuffer( + ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName, + const MarkerCategory& aCategory, MarkerOptions&& aOptions, + const Ts&... aTs) { + if constexpr (std::is_same_v) { + static_assert(sizeof...(Ts) == 0, + "NoPayload does not accept any payload arguments."); + // Special case for NoPayload where there is a stack or inner window id: + // Because these options would be stored in the payload 'data' object, but + // there is no such object for NoPayload, we convert the marker to another + // type (without user fields in the 'data' object), so that the stack and/or + // inner window id are not lost. + // TODO: Remove this when bug 1646714 lands. + if (aOptions.Stack().GetChunkedBuffer() || + !aOptions.InnerWindowId().IsUnspecified()) { + struct NoPayloadUserData { + static constexpr Span MarkerTypeName() { + return MakeStringSpan("NoPayloadUserData"); + } + static void StreamJSONMarkerData( + baseprofiler::SpliceableJSONWriter& aWriter) { + // No user payload. + } + static mozilla::MarkerSchema MarkerTypeDisplay() { + using MS = mozilla::MarkerSchema; + MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable}; + // No user data to display. + return schema; + } + }; + return MarkerTypeSerialization::Serialize( + aBuffer, aName, aCategory, std::move(aOptions)); + } + + // Note that options are first after the entry kind, because they contain + // the thread id, which is handled first to filter markers by threads. + return aBuffer.PutObjects( + ProfileBufferEntryKind::Marker, std::move(aOptions), aName, aCategory, + base_profiler_markers_detail::Streaming::DeserializerTag(0)); + } else { + return MarkerTypeSerialization::Serialize( + aBuffer, aName, aCategory, std::move(aOptions), aTs...); + } +} + +// Pointer to a function that can capture a backtrace into the provided +// `ProfileChunkedBuffer`, and returns true when successful. +using OptionalBacktraceCaptureFunction = bool (*)(ProfileChunkedBuffer&, + StackCaptureOptions); + +// Use a pre-allocated and cleared chunked buffer in the main thread's +// `AddMarkerToBuffer()`. +// Null if not the main thread, or if profilers are not active. +MFBT_API ProfileChunkedBuffer* GetClearedBufferForMainThreadAddMarker(); +// Called by the profiler(s) when starting/stopping. Safe to nest. +MFBT_API void EnsureBufferForMainThreadAddMarker(); +MFBT_API void ReleaseBufferForMainThreadAddMarker(); + +// Add a marker with the given name, options, and arguments to the given buffer. +// Because this may be called from either Base or Gecko Profiler functions, the +// appropriate backtrace-capturing function must also be provided. +template +ProfileBufferBlockIndex AddMarkerToBuffer( + ProfileChunkedBuffer& aBuffer, const ProfilerString8View& aName, + const MarkerCategory& aCategory, MarkerOptions&& aOptions, + OptionalBacktraceCaptureFunction aOptionalBacktraceCaptureFunction, + const Ts&... aTs) { + if (aOptions.ThreadId().IsUnspecified()) { + // If yet unspecified, set thread to this thread where the marker is added. + aOptions.Set(MarkerThreadId::CurrentThread()); + } + + if (aOptions.IsTimingUnspecified()) { + // If yet unspecified, set timing to this instant of adding the marker. + aOptions.Set(MarkerTiming::InstantNow()); + } + + StackCaptureOptions captureOptions = aOptions.Stack().CaptureOptions(); + if (captureOptions != StackCaptureOptions::NoStack && + // Backtrace capture function will be nullptr if the profiler + // NoMarkerStacks feature is set. + aOptionalBacktraceCaptureFunction != nullptr) { + // A capture was requested, let's attempt to do it here&now. This avoids a + // lot of allocations that would be necessary if capturing a backtrace + // separately. + // TODO reduce internal profiler stack levels, see bug 1659872. + auto CaptureStackAndAddMarker = [&](ProfileChunkedBuffer& aChunkedBuffer) { + aOptions.StackRef().UseRequestedBacktrace( + aOptionalBacktraceCaptureFunction(aChunkedBuffer, captureOptions) + ? &aChunkedBuffer + : nullptr); + // This call must be made from here, while chunkedBuffer is in scope. + return AddMarkerWithOptionalStackToBuffer( + aBuffer, aName, aCategory, std::move(aOptions), aTs...); + }; + + if (ProfileChunkedBuffer* buffer = GetClearedBufferForMainThreadAddMarker(); + buffer) { + // Use a pre-allocated buffer for the main thread (because it's the most + // used thread, and most sensitive to overhead), so it's only allocated + // once. It could be null if this is not the main thread, or no profilers + // are currently active. + return CaptureStackAndAddMarker(*buffer); + } + // TODO use a local on-stack byte buffer to remove last allocation. + ProfileBufferChunkManagerSingle chunkManager( + ProfileBufferChunkManager::scExpectedMaximumStackSize); + ProfileChunkedBuffer chunkedBuffer( + ProfileChunkedBuffer::ThreadSafety::WithoutMutex, chunkManager); + return CaptureStackAndAddMarker(chunkedBuffer); + } + + return AddMarkerWithOptionalStackToBuffer( + aBuffer, aName, aCategory, std::move(aOptions), aTs...); +} + +// Assuming aEntryReader points right after the entry type (being Marker), this +// reads the remainder of the marker and outputs it. +// - GetWriterForThreadCallback, called first, after the thread id is read: +// (ThreadId) -> SpliceableJSONWriter* or null +// If null, nothing will be output, but aEntryReader will still be read fully. +// - StackCallback, only called if GetWriterForThreadCallback didn't return +// null, and if the marker contains a stack: +// (ProfileChunkedBuffer&) -> void +// - RustMarkerCallback, only called if GetWriterForThreadCallback didn't return +// null, and if the marker contains a Rust payload: +// (DeserializerTag) -> void +template +void DeserializeAfterKindAndStream( + ProfileBufferEntryReader& aEntryReader, + GetWriterForThreadCallback&& aGetWriterForThreadCallback, + StackCallback&& aStackCallback, RustMarkerCallback&& aRustMarkerCallback) { + // Each entry is made up of the following: + // ProfileBufferEntry::Kind::Marker, <- already read by caller + // options, <- next location in entries + // name, + // payload + const MarkerOptions options = aEntryReader.ReadObject(); + + baseprofiler::SpliceableJSONWriter* writer = + std::forward(aGetWriterForThreadCallback)( + options.ThreadId().ThreadId()); + if (!writer) { + // No writer associated with this thread id, drop it. + aEntryReader.SetRemainingBytes(0); + return; + } + + // Write the information to JSON with the following schema: + // [name, startTime, endTime, phase, category, data] + writer->StartArrayElement(); + { + writer->UniqueStringElement(aEntryReader.ReadObject()); + + const double startTime = options.Timing().GetStartTime(); + writer->TimeDoubleMsElement(startTime); + + const double endTime = options.Timing().GetEndTime(); + writer->TimeDoubleMsElement(endTime); + + writer->IntElement(static_cast(options.Timing().MarkerPhase())); + + MarkerCategory category = aEntryReader.ReadObject(); + writer->IntElement(static_cast(category.GetCategory())); + + if (const auto tag = + aEntryReader.ReadObject(); + tag != 0) { + writer->StartObjectElement(); + { + // Stream "common props". + + // TODO: Move this to top-level tuple, when frontend supports it. + if (!options.InnerWindowId().IsUnspecified()) { + // Here, we are converting uint64_t to double. Both Browsing Context + // and Inner Window IDs are created using + // `nsContentUtils::GenerateProcessSpecificId`, which is specifically + // designed to only use 53 of the 64 bits to be lossless when passed + // into and out of JS as a double. + writer->DoubleProperty( + "innerWindowID", + static_cast(options.InnerWindowId().Id())); + } + + // TODO: Move this to top-level tuple, when frontend supports it. + if (ProfileChunkedBuffer* chunkedBuffer = + options.Stack().GetChunkedBuffer(); + chunkedBuffer) { + writer->StartObjectProperty("stack"); + { + std::forward(aStackCallback)(*chunkedBuffer); + } + writer->EndObject(); + } + + auto payloadType = static_cast( + aEntryReader.ReadObject< + std::underlying_type_t>()); + + // Stream the payload, including the type. + switch (payloadType) { + case mozilla::MarkerPayloadType::Cpp: { + mozilla::base_profiler_markers_detail::Streaming:: + MarkerDataDeserializer deserializer = + mozilla::base_profiler_markers_detail::Streaming:: + DeserializerForTag(tag); + MOZ_RELEASE_ASSERT(deserializer); + deserializer(aEntryReader, *writer); + MOZ_ASSERT(aEntryReader.RemainingBytes() == 0u); + break; + } + case mozilla::MarkerPayloadType::Rust: + std::forward(aRustMarkerCallback)(tag); + MOZ_ASSERT(aEntryReader.RemainingBytes() == 0u); + break; + default: + MOZ_ASSERT_UNREACHABLE("Unknown payload type."); + break; + } + } + writer->EndObject(); + } + } + writer->EndArray(); + MOZ_ASSERT(aEntryReader.RemainingBytes() == 0u); +} + +} // namespace mozilla::base_profiler_markers_detail + +namespace mozilla { + +// ---------------------------------------------------------------------------- +// Serializer, Deserializer: ProfilerStringView + +// The serialization starts with a ULEB128 number that encodes both whether the +// ProfilerStringView is literal (Least Significant Bit = 0) or not (LSB = 1), +// plus the string length (excluding null terminator) in bytes, shifted left by +// 1 bit. Following that number: +// - If literal, the string pointer value. +// - If non-literal, the contents as bytes (excluding null terminator if any). +template +struct ProfileBufferEntryWriter::Serializer> { + static Length Bytes(const ProfilerStringView& aString) { + MOZ_RELEASE_ASSERT( + aString.Length() < std::numeric_limits::max() / 2, + "Double the string length doesn't fit in Length type"); + const Length stringLength = static_cast(aString.Length()); + if (aString.IsLiteral()) { + // Literal -> Length shifted left and LSB=0, then pointer. + return ULEB128Size(stringLength << 1 | 0u) + + static_cast(sizeof(const CHAR*)); + } + // Non-literal -> Length shifted left and LSB=1, then string size in bytes. + return ULEB128Size((stringLength << 1) | 1u) + stringLength * sizeof(CHAR); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const ProfilerStringView& aString) { + MOZ_RELEASE_ASSERT( + aString.Length() < std::numeric_limits::max() / 2, + "Double the string length doesn't fit in Length type"); + const Span span = aString; + if (aString.IsLiteral()) { + // Literal -> Length shifted left and LSB=0, then pointer. + aEW.WriteULEB128(span.Length() << 1 | 0u); + aEW.WriteObject(WrapProfileBufferRawPointer(span.Elements())); + return; + } + // Non-literal -> Length shifted left and LSB=1, then string size in bytes. + aEW.WriteULEB128(span.Length() << 1 | 1u); + aEW.WriteBytes(span.Elements(), span.LengthBytes()); + } +}; + +template +struct ProfileBufferEntryReader::Deserializer> { + static void ReadInto(ProfileBufferEntryReader& aER, + ProfilerStringView& aString) { + aString = Read(aER); + } + + static ProfilerStringView Read(ProfileBufferEntryReader& aER) { + const Length lengthAndIsLiteral = aER.ReadULEB128(); + const Length stringLength = lengthAndIsLiteral >> 1; + if ((lengthAndIsLiteral & 1u) == 0u) { + // LSB==0 -> Literal string, read the string pointer. + return ProfilerStringView( + aER.ReadObject(), stringLength, + ProfilerStringView::Ownership::Literal); + } + // LSB==1 -> Not a literal string. + ProfileBufferEntryReader::DoubleSpanOfConstBytes spans = + aER.ReadSpans(stringLength * sizeof(CHAR)); + if (MOZ_LIKELY(spans.IsSingleSpan()) && + reinterpret_cast(spans.mFirstOrOnly.Elements()) % + alignof(CHAR) == + 0u) { + // Only a single span, correctly aligned for the CHAR type, we can just + // refer to it directly, assuming that this ProfilerStringView will not + // outlive the chunk. + return ProfilerStringView( + reinterpret_cast(spans.mFirstOrOnly.Elements()), + stringLength, ProfilerStringView::Ownership::Reference); + } else { + // Two spans, we need to concatenate them; or one span, but misaligned. + // Allocate a buffer to store the string (plus terminal, for safety), and + // give it to the ProfilerStringView; Note that this is a secret use of + // ProfilerStringView, which is intended to only be used between + // deserialization and JSON streaming. + CHAR* buffer = new CHAR[stringLength + 1]; + spans.CopyBytesTo(buffer); + buffer[stringLength] = CHAR(0); + return ProfilerStringView( + buffer, stringLength, + ProfilerStringView::Ownership::OwnedThroughStringView); + } + } +}; + +// Serializer, Deserializer: MarkerCategory + +// The serialization contains both category numbers encoded as ULEB128. +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(const MarkerCategory& aCategory) { + return ULEB128Size(static_cast(aCategory.CategoryPair())); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const MarkerCategory& aCategory) { + aEW.WriteULEB128(static_cast(aCategory.CategoryPair())); + } +}; + +template <> +struct ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, + MarkerCategory& aCategory) { + aCategory = Read(aER); + } + + static MarkerCategory Read(ProfileBufferEntryReader& aER) { + return MarkerCategory(static_cast( + aER.ReadULEB128())); + } +}; + +// ---------------------------------------------------------------------------- +// Serializer, Deserializer: MarkerTiming + +// The serialization starts with the marker phase, followed by one or two +// timestamps as needed. +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(const MarkerTiming& aTiming) { + MOZ_ASSERT(!aTiming.IsUnspecified()); + const auto phase = aTiming.MarkerPhase(); + switch (phase) { + case MarkerTiming::Phase::Instant: + return SumBytes(phase, aTiming.StartTime()); + case MarkerTiming::Phase::Interval: + return SumBytes(phase, aTiming.StartTime(), aTiming.EndTime()); + case MarkerTiming::Phase::IntervalStart: + return SumBytes(phase, aTiming.StartTime()); + case MarkerTiming::Phase::IntervalEnd: + return SumBytes(phase, aTiming.EndTime()); + default: + MOZ_RELEASE_ASSERT(phase == MarkerTiming::Phase::Instant || + phase == MarkerTiming::Phase::Interval || + phase == MarkerTiming::Phase::IntervalStart || + phase == MarkerTiming::Phase::IntervalEnd); + return 0; // Only to avoid build errors. + } + } + + static void Write(ProfileBufferEntryWriter& aEW, + const MarkerTiming& aTiming) { + MOZ_ASSERT(!aTiming.IsUnspecified()); + const auto phase = aTiming.MarkerPhase(); + switch (phase) { + case MarkerTiming::Phase::Instant: + aEW.WriteObjects(phase, aTiming.StartTime()); + return; + case MarkerTiming::Phase::Interval: + aEW.WriteObjects(phase, aTiming.StartTime(), aTiming.EndTime()); + return; + case MarkerTiming::Phase::IntervalStart: + aEW.WriteObjects(phase, aTiming.StartTime()); + return; + case MarkerTiming::Phase::IntervalEnd: + aEW.WriteObjects(phase, aTiming.EndTime()); + return; + default: + MOZ_RELEASE_ASSERT(phase == MarkerTiming::Phase::Instant || + phase == MarkerTiming::Phase::Interval || + phase == MarkerTiming::Phase::IntervalStart || + phase == MarkerTiming::Phase::IntervalEnd); + return; + } + } +}; + +template <> +struct ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, MarkerTiming& aTiming) { + aTiming.mPhase = aER.ReadObject(); + switch (aTiming.mPhase) { + case MarkerTiming::Phase::Instant: + aTiming.mStartTime = aER.ReadObject(); + aTiming.mEndTime = TimeStamp{}; + break; + case MarkerTiming::Phase::Interval: + aTiming.mStartTime = aER.ReadObject(); + aTiming.mEndTime = aER.ReadObject(); + break; + case MarkerTiming::Phase::IntervalStart: + aTiming.mStartTime = aER.ReadObject(); + aTiming.mEndTime = TimeStamp{}; + break; + case MarkerTiming::Phase::IntervalEnd: + aTiming.mStartTime = TimeStamp{}; + aTiming.mEndTime = aER.ReadObject(); + break; + default: + MOZ_RELEASE_ASSERT(aTiming.mPhase == MarkerTiming::Phase::Instant || + aTiming.mPhase == MarkerTiming::Phase::Interval || + aTiming.mPhase == + MarkerTiming::Phase::IntervalStart || + aTiming.mPhase == MarkerTiming::Phase::IntervalEnd); + break; + } + } + + static MarkerTiming Read(ProfileBufferEntryReader& aER) { + TimeStamp start; + TimeStamp end; + auto phase = aER.ReadObject(); + switch (phase) { + case MarkerTiming::Phase::Instant: + start = aER.ReadObject(); + break; + case MarkerTiming::Phase::Interval: + start = aER.ReadObject(); + end = aER.ReadObject(); + break; + case MarkerTiming::Phase::IntervalStart: + start = aER.ReadObject(); + break; + case MarkerTiming::Phase::IntervalEnd: + end = aER.ReadObject(); + break; + default: + MOZ_RELEASE_ASSERT(phase == MarkerTiming::Phase::Instant || + phase == MarkerTiming::Phase::Interval || + phase == MarkerTiming::Phase::IntervalStart || + phase == MarkerTiming::Phase::IntervalEnd); + break; + } + return MarkerTiming(start, end, phase); + } +}; + +// ---------------------------------------------------------------------------- +// Serializer, Deserializer: MarkerStack + +// The serialization only contains the `ProfileChunkedBuffer` from the +// backtrace; if there is no backtrace or if it's empty, this will implicitly +// store a nullptr (see +// `ProfileBufferEntryWriter::Serializer`). +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(const MarkerStack& aStack) { + return SumBytes(aStack.GetChunkedBuffer()); + } + + static void Write(ProfileBufferEntryWriter& aEW, const MarkerStack& aStack) { + aEW.WriteObject(aStack.GetChunkedBuffer()); + } +}; + +template <> +struct ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, MarkerStack& aStack) { + aStack = Read(aER); + } + + static MarkerStack Read(ProfileBufferEntryReader& aER) { + return MarkerStack(aER.ReadObject>()); + } +}; + +// ---------------------------------------------------------------------------- +// Serializer, Deserializer: MarkerOptions + +// The serialization contains all members (either trivially-copyable, or they +// provide their specialization above). +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(const MarkerOptions& aOptions) { + return SumBytes(aOptions.ThreadId(), aOptions.Timing(), aOptions.Stack(), + aOptions.InnerWindowId()); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const MarkerOptions& aOptions) { + aEW.WriteObjects(aOptions.ThreadId(), aOptions.Timing(), aOptions.Stack(), + aOptions.InnerWindowId()); + } +}; + +template <> +struct ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, MarkerOptions& aOptions) { + aER.ReadIntoObjects(aOptions.mThreadId, aOptions.mTiming, aOptions.mStack, + aOptions.mInnerWindowId); + } + + static MarkerOptions Read(ProfileBufferEntryReader& aER) { + MarkerOptions options; + ReadInto(aER, options); + return options; + } +}; + +} // namespace mozilla + +#endif // BaseProfilerMarkersDetail_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerMarkersPrerequisites.h b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkersPrerequisites.h new file mode 100644 index 00000000000..f6625e2f94e --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerMarkersPrerequisites.h @@ -0,0 +1,1131 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This header contains basic definitions required to create marker types, and +// to add markers to the profiler buffers. +// +// In most cases, #include "mozilla/BaseProfilerMarkers.h" instead, or +// #include "mozilla/BaseProfilerMarkerTypes.h" for common marker types. + +#ifndef BaseProfilerMarkersPrerequisites_h +#define BaseProfilerMarkersPrerequisites_h + +namespace mozilla { + +enum class StackCaptureOptions { + NoStack, // No stack captured. + Full, // Capture a full stack, including label frames, JS frames and + // native frames. + NonNative, // Capture a stack without native frames for reduced overhead. +}; + +} + +#include "BaseProfileJSONWriter.h" +#include "BaseProfilingCategory.h" +#include "mozilla/Maybe.h" +#include "mozilla/ProfileChunkedBuffer.h" +#include "mozilla/BaseProfilerState.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/Variant.h" + +#include +#include +#include +#include +#include +#include + +// The header defines "None" as a macro that expands to "0L". +// This is terrible because we have an enum variant named "None" too in this +// file. To work around this, we undefine the macro "None". +#ifdef None +# undef None +#endif + +namespace mozilla { + +// Return a NotNull pointing at the literal empty string `""`. +template +constexpr const CHAR* LiteralEmptyStringPointer() { + static_assert(std::is_same_v || std::is_same_v, + "Only char and char16_t are supported in Firefox"); + if constexpr (std::is_same_v) { + return ""; + } + if constexpr (std::is_same_v) { + return u""; + } +} + +// Return a string_view pointing at the literal empty string. +template +constexpr std::basic_string_view LiteralEmptyStringView() { + static_assert(std::is_same_v || std::is_same_v, + "Only char and char16_t are supported in Firefox"); + // Use `operator""sv()` from . + using namespace std::literals::string_view_literals; + if constexpr (std::is_same_v) { + return ""sv; + } + if constexpr (std::is_same_v) { + return u""sv; + } +} + +// General string view, optimized for short on-stack life before serialization, +// and between deserialization and JSON-streaming. +template +class MOZ_STACK_CLASS ProfilerStringView { + public: + // Default constructor points at "" (literal empty string). + constexpr ProfilerStringView() = default; + + // Don't allow copy. + ProfilerStringView(const ProfilerStringView&) = delete; + ProfilerStringView& operator=(const ProfilerStringView&) = delete; + + // Allow move. For consistency the moved-from string is always reset to "". + constexpr ProfilerStringView(ProfilerStringView&& aOther) + : mStringView(std::move(aOther.mStringView)), + mOwnership(aOther.mOwnership) { + if (mOwnership == Ownership::OwnedThroughStringView) { + // We now own the buffer, make the other point at the literal "". + aOther.mStringView = LiteralEmptyStringView(); + aOther.mOwnership = Ownership::Literal; + } + } + constexpr ProfilerStringView& operator=(ProfilerStringView&& aOther) { + mStringView = std::move(aOther.mStringView); + mOwnership = aOther.mOwnership; + if (mOwnership == Ownership::OwnedThroughStringView) { + // We now own the buffer, make the other point at the literal "". + aOther.mStringView = LiteralEmptyStringView(); + aOther.mOwnership = Ownership::Literal; + } + return *this; + } + + ~ProfilerStringView() { + if (MOZ_UNLIKELY(mOwnership == Ownership::OwnedThroughStringView)) { + // We own the buffer pointed at by mStringView, destroy it. + // This is only used between deserialization and streaming. + delete mStringView.data(); + } + } + + // Implicit construction from nullptr, points at "" (literal empty string). + constexpr MOZ_IMPLICIT ProfilerStringView(decltype(nullptr)) {} + + // Implicit constructor from a literal string. + template + constexpr MOZ_IMPLICIT ProfilerStringView(const CHAR (&aLiteralString)[Np1]) + : ProfilerStringView(aLiteralString, Np1 - 1, Ownership::Literal) {} + + // Constructor from a non-literal string. + constexpr ProfilerStringView(const CHAR* aString, size_t aLength) + : ProfilerStringView(aString, aLength, Ownership::Reference) {} + + // Implicit constructor from a string_view. + constexpr MOZ_IMPLICIT ProfilerStringView( + const std::basic_string_view& aStringView) + : ProfilerStringView(aStringView.data(), aStringView.length(), + Ownership::Reference) {} + + // Implicit constructor from an expiring string_view. We assume that the + // pointed-at string will outlive this ProfilerStringView. + constexpr MOZ_IMPLICIT ProfilerStringView( + std::basic_string_view&& aStringView) + : ProfilerStringView(aStringView.data(), aStringView.length(), + Ownership::Reference) {} + + // Implicit constructor from std::string. + constexpr MOZ_IMPLICIT ProfilerStringView( + const std::basic_string& aString) + : ProfilerStringView(aString.data(), aString.length(), + Ownership::Reference) {} + + // Construction from a raw pointer to a null-terminated string. + // This is a named class-static function to make it more obvious where work is + // being done (to determine the string length), and encourage users to instead + // provide a length, if already known. + // TODO: Find callers and convert them to constructor instead if possible. + static constexpr ProfilerStringView WrapNullTerminatedString( + const CHAR* aString) { + return ProfilerStringView( + aString, aString ? std::char_traits::length(aString) : 0, + Ownership::Reference); + } + + // Implicit constructor for an object with member functions `Data()` + // `Length()`, and `IsLiteral()`, common in xpcom strings. + template < + typename String, + typename DataReturnType = decltype(std::declval().Data()), + typename LengthReturnType = + decltype(std::declval().Length()), + typename IsLiteralReturnType = + decltype(std::declval().IsLiteral()), + typename = + std::enable_if_t && + std::is_integral_v && + std::is_same_v>> + constexpr MOZ_IMPLICIT ProfilerStringView(const String& aString) + : ProfilerStringView( + static_cast(aString.Data()), aString.Length(), + aString.IsLiteral() ? Ownership::Literal : Ownership::Reference) {} + + [[nodiscard]] constexpr const std::basic_string_view& StringView() + const { + return mStringView; + } + + [[nodiscard]] constexpr size_t Length() const { return mStringView.length(); } + + [[nodiscard]] constexpr bool IsLiteral() const { + return mOwnership == Ownership::Literal; + } + [[nodiscard]] constexpr bool IsReference() const { + return mOwnership == Ownership::Reference; + } + // No `IsOwned...()` because it's a secret, only used internally! + + [[nodiscard]] Span AsSpan() const { + return Span(mStringView.data(), mStringView.length()); + } + [[nodiscard]] operator Span() const { return AsSpan(); } + + private: + enum class Ownership { Literal, Reference, OwnedThroughStringView }; + + // Allow deserializer to store anything here. + friend ProfileBufferEntryReader::Deserializer; + + constexpr ProfilerStringView(const CHAR* aString, size_t aLength, + Ownership aOwnership) + : mStringView(aString ? std::basic_string_view(aString, aLength) + : LiteralEmptyStringView()), + mOwnership(aString ? aOwnership : Ownership::Literal) {} + + // String view to an outside string (literal or reference). + // We may actually own the pointed-at buffer, but it is only used internally + // between deserialization and JSON streaming. + std::basic_string_view mStringView = LiteralEmptyStringView(); + + Ownership mOwnership = Ownership::Literal; +}; + +using ProfilerString8View = ProfilerStringView; +using ProfilerString16View = ProfilerStringView; + +// This compulsory marker parameter contains the required category information. +class MarkerCategory { + public: + // Constructor from category pair (includes both super- and sub-categories). + constexpr explicit MarkerCategory( + baseprofiler::ProfilingCategoryPair aCategoryPair) + : mCategoryPair(aCategoryPair) {} + + // Returns the stored category pair. + constexpr baseprofiler::ProfilingCategoryPair CategoryPair() const { + return mCategoryPair; + } + + // Returns the super-category from the stored category pair. + baseprofiler::ProfilingCategory GetCategory() const { + return GetProfilingCategoryPairInfo(mCategoryPair).mCategory; + } + + private: + baseprofiler::ProfilingCategoryPair mCategoryPair = + baseprofiler::ProfilingCategoryPair::OTHER; +}; + +namespace baseprofiler::category { + +// Each category pair name constructs a MarkerCategory. +// E.g.: mozilla::baseprofiler::category::OTHER_Profiling +// Profiler macros will take the category name alone without namespace. +// E.g.: `PROFILER_MARKER_UNTYPED("name", OTHER_Profiling)` +#define CATEGORY_ENUM_BEGIN_CATEGORY(name, labelAsString, color) +#define CATEGORY_ENUM_SUBCATEGORY(supercategory, name, labelAsString) \ + static constexpr MarkerCategory name{ProfilingCategoryPair::name}; +#define CATEGORY_ENUM_END_CATEGORY +MOZ_PROFILING_CATEGORY_LIST(CATEGORY_ENUM_BEGIN_CATEGORY, + CATEGORY_ENUM_SUBCATEGORY, + CATEGORY_ENUM_END_CATEGORY) +#undef CATEGORY_ENUM_BEGIN_CATEGORY +#undef CATEGORY_ENUM_SUBCATEGORY +#undef CATEGORY_ENUM_END_CATEGORY + +// Import `MarkerCategory` into this namespace. This will allow using this type +// dynamically in macros that prepend `::mozilla::baseprofiler::category::` to +// the given category, e.g.: +// `PROFILER_MARKER_UNTYPED("name", MarkerCategory(...))` +using MarkerCategory = ::mozilla::MarkerCategory; + +} // namespace baseprofiler::category + +// The classes below are all embedded in a `MarkerOptions` object. +class MarkerOptions; + +// This marker option captures a given thread id. +// If left unspecified (by default construction) during the add-marker call, the +// current thread id will be used then. +class MarkerThreadId { + public: + // Default constructor, keeps the thread id unspecified. + constexpr MarkerThreadId() = default; + + // Constructor from a given thread id. + constexpr explicit MarkerThreadId( + baseprofiler::BaseProfilerThreadId aThreadId) + : mThreadId(aThreadId) {} + + // Use the current thread's id. + static MarkerThreadId CurrentThread() { + return MarkerThreadId(baseprofiler::profiler_current_thread_id()); + } + + // Use the main thread's id. This can be useful to record a marker from a + // possibly-unregistered thread, and display it in the main thread track. + static MarkerThreadId MainThread() { + return MarkerThreadId(baseprofiler::profiler_main_thread_id()); + } + + [[nodiscard]] constexpr baseprofiler::BaseProfilerThreadId ThreadId() const { + return mThreadId; + } + + [[nodiscard]] constexpr bool IsUnspecified() const { + return !mThreadId.IsSpecified(); + } + + private: + baseprofiler::BaseProfilerThreadId mThreadId; +}; + +// This marker option contains marker timing information. +// This class encapsulates the logic for correctly storing a marker based on its +// Use the static methods to create the MarkerTiming. This is a transient object +// that is being used to enforce the constraints of the combinations of the +// data. +class MarkerTiming { + public: + // The following static methods are used to create the MarkerTiming based on + // the type that it is. + + static MarkerTiming InstantAt(const TimeStamp& aTime) { + MOZ_ASSERT(!aTime.IsNull(), "Time is null for an instant marker."); + return MarkerTiming{aTime, TimeStamp{}, MarkerTiming::Phase::Instant}; + } + + static MarkerTiming InstantNow() { return InstantAt(TimeStamp::Now()); } + + static MarkerTiming Interval(const TimeStamp& aStartTime, + const TimeStamp& aEndTime) { + MOZ_ASSERT(!aStartTime.IsNull(), + "Start time is null for an interval marker."); + MOZ_ASSERT(!aEndTime.IsNull(), "End time is null for an interval marker."); + return MarkerTiming{aStartTime, aEndTime, MarkerTiming::Phase::Interval}; + } + + static MarkerTiming IntervalUntilNowFrom(const TimeStamp& aStartTime) { + return Interval(aStartTime, TimeStamp::Now()); + } + + static MarkerTiming IntervalStart(const TimeStamp& aTime = TimeStamp::Now()) { + MOZ_ASSERT(!aTime.IsNull(), "Time is null for an interval start marker."); + return MarkerTiming{aTime, TimeStamp{}, MarkerTiming::Phase::IntervalStart}; + } + + static MarkerTiming IntervalEnd(const TimeStamp& aTime = TimeStamp::Now()) { + MOZ_ASSERT(!aTime.IsNull(), "Time is null for an interval end marker."); + return MarkerTiming{TimeStamp{}, aTime, MarkerTiming::Phase::IntervalEnd}; + } + + // Set the interval end in this timing. + // If there was already a start time, this makes it a full interval. + void SetIntervalEnd(const TimeStamp& aTime = TimeStamp::Now()) { + MOZ_ASSERT(!aTime.IsNull(), "Time is null for an interval end marker."); + mEndTime = aTime; + mPhase = mStartTime.IsNull() ? Phase::IntervalEnd : Phase::Interval; + } + + [[nodiscard]] const TimeStamp& StartTime() const { return mStartTime; } + [[nodiscard]] const TimeStamp& EndTime() const { return mEndTime; } + + // The phase differentiates Instant markers from Interval markers. + // Interval markers can either carry both timestamps on a single marker, + // or they can be split into individual Start and End markers, which are + // associated with each other via the marker name. + // + // The numeric representation of this enum value is also exposed in the + // ETW trace event's Phase field. + enum class Phase : uint8_t { + Instant = 0, + Interval = 1, + IntervalStart = 2, + IntervalEnd = 3, + }; + + [[nodiscard]] Phase MarkerPhase() const { + MOZ_ASSERT(!IsUnspecified()); + return mPhase; + } + + // The following getter methods are used to put the value into the buffer for + // storage. + [[nodiscard]] double GetStartTime() const { + MOZ_ASSERT(!IsUnspecified()); + // If mStartTime is null (e.g., for IntervalEnd), this will output 0.0 as + // expected. + return MarkerTiming::timeStampToDouble(mStartTime); + } + + [[nodiscard]] double GetEndTime() const { + MOZ_ASSERT(!IsUnspecified()); + // If mEndTime is null (e.g., for Instant or IntervalStart), this will + // output 0.0 as expected. + return MarkerTiming::timeStampToDouble(mEndTime); + } + + [[nodiscard]] uint8_t GetPhase() const { + MOZ_ASSERT(!IsUnspecified()); + return static_cast(mPhase); + } + + // This is a constructor for Rust FFI bindings. It must not be used outside of + // this! Please see the other static constructors above. + static void UnsafeConstruct(MarkerTiming* aMarkerTiming, + const TimeStamp& aStartTime, + const TimeStamp& aEndTime, Phase aPhase) { + new (aMarkerTiming) MarkerTiming{aStartTime, aEndTime, aPhase}; + } + + private: + friend ProfileBufferEntryWriter::Serializer; + friend ProfileBufferEntryReader::Deserializer; + friend MarkerOptions; + + // Default timing leaves it internally "unspecified", serialization getters + // and add-marker functions will default to `InstantNow()`. + constexpr MarkerTiming() = default; + + // This should only be used by internal profiler code. + [[nodiscard]] bool IsUnspecified() const { + return mStartTime.IsNull() && mEndTime.IsNull(); + } + + // Full constructor, used by static factory functions. + constexpr MarkerTiming(const TimeStamp& aStartTime, const TimeStamp& aEndTime, + Phase aPhase) + : mStartTime(aStartTime), mEndTime(aEndTime), mPhase(aPhase) {} + + static double timeStampToDouble(const TimeStamp& time) { + if (time.IsNull()) { + // The Phase lets us know not to use this value. + return 0; + } + return (time - TimeStamp::ProcessCreation()).ToMilliseconds(); + } + + TimeStamp mStartTime; + TimeStamp mEndTime; + Phase mPhase = Phase::Instant; +}; + +// This marker option allows three cases: +// - By default, no stacks are captured. +// - The caller can request a stack capture, and the add-marker code will take +// care of it in the most efficient way. +// - The caller can still provide an existing backtrace, for cases where a +// marker reports something that happened elsewhere. +class MarkerStack { + public: + // Default constructor, no capture. + constexpr MarkerStack() = default; + + // Disallow copy. + MarkerStack(const MarkerStack&) = delete; + MarkerStack& operator=(const MarkerStack&) = delete; + + // Allow move. + MarkerStack(MarkerStack&& aOther) + : mCaptureOptions(aOther.mCaptureOptions), + mOptionalChunkedBufferStorage( + std::move(aOther.mOptionalChunkedBufferStorage)), + mChunkedBuffer(aOther.mChunkedBuffer) { + AssertInvariants(); + aOther.Clear(); + } + MarkerStack& operator=(MarkerStack&& aOther) { + mCaptureOptions = aOther.mCaptureOptions; + mOptionalChunkedBufferStorage = + std::move(aOther.mOptionalChunkedBufferStorage); + mChunkedBuffer = aOther.mChunkedBuffer; + AssertInvariants(); + aOther.Clear(); + return *this; + } + + // Take ownership of a backtrace. If null or empty, equivalent to NoStack(). + explicit MarkerStack(UniquePtr&& aExternalChunkedBuffer) + : mOptionalChunkedBufferStorage( + (!aExternalChunkedBuffer || aExternalChunkedBuffer->IsEmpty()) + ? nullptr + : std::move(aExternalChunkedBuffer)), + mChunkedBuffer(mOptionalChunkedBufferStorage.get()) { + AssertInvariants(); + } + + // Use an existing backtrace stored elsewhere, which the user must guarantee + // is alive during the add-marker call. If empty, equivalent to NoStack(). + explicit MarkerStack(ProfileChunkedBuffer& aExternalChunkedBuffer) + : mChunkedBuffer(aExternalChunkedBuffer.IsEmpty() + ? nullptr + : &aExternalChunkedBuffer) { + AssertInvariants(); + } + + // Don't capture a stack in this marker. + static MarkerStack NoStack() { + return MarkerStack(StackCaptureOptions::NoStack); + } + + // Capture a stack when adding this marker. + static MarkerStack Capture( + StackCaptureOptions aCaptureOptions = StackCaptureOptions::Full) { + // Actual capture will be handled inside profiler_add_marker. + return MarkerStack(aCaptureOptions); + } + + // Optionally capture a stack, useful for avoiding long-winded ternaries. + static MarkerStack MaybeCapture(bool aDoCapture) { + return aDoCapture ? Capture() : NoStack(); + } + + // Use an existing backtrace stored elsewhere, which the user must guarantee + // is alive during the add-marker call. If empty, equivalent to NoStack(). + static MarkerStack UseBacktrace( + ProfileChunkedBuffer& aExternalChunkedBuffer) { + return MarkerStack(aExternalChunkedBuffer); + } + + // Take ownership of a backtrace previously captured with + // `profiler_capture_backtrace()`. If null, equivalent to NoStack(). + static MarkerStack TakeBacktrace( + UniquePtr&& aExternalChunkedBuffer) { + return MarkerStack(std::move(aExternalChunkedBuffer)); + } + + // Construct with the given capture options. + static MarkerStack WithCaptureOptions(StackCaptureOptions aCaptureOptions) { + return MarkerStack(aCaptureOptions); + } + + [[nodiscard]] StackCaptureOptions CaptureOptions() const { + return mCaptureOptions; + } + + ProfileChunkedBuffer* GetChunkedBuffer() const { return mChunkedBuffer; } + + // Use backtrace after a request. If null, equivalent to NoStack(). + void UseRequestedBacktrace(ProfileChunkedBuffer* aExternalChunkedBuffer) { + MOZ_RELEASE_ASSERT(mCaptureOptions != StackCaptureOptions::NoStack); + mCaptureOptions = StackCaptureOptions::NoStack; + if (aExternalChunkedBuffer && !aExternalChunkedBuffer->IsEmpty()) { + // We only need to use the provided buffer if it is not empty. + mChunkedBuffer = aExternalChunkedBuffer; + } + AssertInvariants(); + } + + void Clear() { + mCaptureOptions = StackCaptureOptions::NoStack; + mOptionalChunkedBufferStorage.reset(); + mChunkedBuffer = nullptr; + AssertInvariants(); + } + + private: + explicit MarkerStack(StackCaptureOptions aCaptureOptions) + : mCaptureOptions(aCaptureOptions) { + AssertInvariants(); + } + + // This should be called after every constructor and non-const function. + void AssertInvariants() const { +#ifdef DEBUG + if (mCaptureOptions != StackCaptureOptions::NoStack) { + MOZ_ASSERT(!mOptionalChunkedBufferStorage, + "We should not hold a buffer when capture is requested"); + MOZ_ASSERT(!mChunkedBuffer, + "We should not point at a buffer when capture is requested"); + } else { + if (mOptionalChunkedBufferStorage) { + MOZ_ASSERT(mChunkedBuffer == mOptionalChunkedBufferStorage.get(), + "Non-null mOptionalChunkedBufferStorage must be pointed-at " + "by mChunkedBuffer"); + } + if (mChunkedBuffer) { + MOZ_ASSERT(!mChunkedBuffer->IsEmpty(), + "Non-null mChunkedBuffer must not be empty"); + } + } +#endif // DEBUG + } + + StackCaptureOptions mCaptureOptions = StackCaptureOptions::NoStack; + + // Optional storage for the backtrace, in case it was captured before the + // add-marker call. + UniquePtr mOptionalChunkedBufferStorage; + + // If not null, this points to the backtrace. It may point to a backtrace + // temporarily stored on the stack, or to mOptionalChunkedBufferStorage. + ProfileChunkedBuffer* mChunkedBuffer = nullptr; +}; + +// This marker option captures a given inner window id. +class MarkerInnerWindowId { + public: + // Default constructor, it leaves the id unspecified. + constexpr MarkerInnerWindowId() = default; + + // Constructor with a specified inner window id. + constexpr explicit MarkerInnerWindowId(uint64_t i) : mInnerWindowId(i) {} + + // Constructor with either specified inner window id or Nothing. + constexpr explicit MarkerInnerWindowId(const Maybe& i) + : mInnerWindowId(i.valueOr(scNoId)) {} + + // Explicit option with unspecified id. + constexpr static MarkerInnerWindowId NoId() { return MarkerInnerWindowId{}; } + + [[nodiscard]] bool IsUnspecified() const { return mInnerWindowId == scNoId; } + + [[nodiscard]] constexpr uint64_t Id() const { return mInnerWindowId; } + + private: + static constexpr uint64_t scNoId = 0; + uint64_t mInnerWindowId = scNoId; +}; + +// This class combines each of the possible marker options above. +class MarkerOptions { + public: + // Constructor from individual options (including none). + // Implicit to allow `{}` and one option type as-is. + // Options that are not provided here are defaulted. In particular, timing + // defaults to `MarkerTiming::InstantNow()` when the marker is recorded. + template + MOZ_IMPLICIT MarkerOptions(Options&&... aOptions) { + (Set(std::forward(aOptions)), ...); + } + + // Disallow copy. + MarkerOptions(const MarkerOptions&) = delete; + MarkerOptions& operator=(const MarkerOptions&) = delete; + + // Allow move. + MarkerOptions(MarkerOptions&&) = default; + MarkerOptions& operator=(MarkerOptions&&) = default; + + // The embedded `MarkerTiming` hasn't been specified yet. + [[nodiscard]] bool IsTimingUnspecified() const { + return mTiming.IsUnspecified(); + } + + // Each option may be added in a chain by e.g.: + // `options.Set(MarkerThreadId(123)).Set(MarkerTiming::IntervalEnd())`. + // When passed to an add-marker function, it must be an rvalue, either created + // on the spot, or `std::move`d from storage, e.g.: + // `PROFILER_MARKER_UNTYPED("...", std::move(options).Set(...))`; + // + // Options can be read by their name (without "Marker"), e.g.: `o.ThreadId()`. + // Add "Ref" for a non-const reference, e.g.: `o.ThreadIdRef() = ...;` +#define FUNCTIONS_ON_MEMBER(NAME) \ + MarkerOptions& Set(Marker##NAME&& a##NAME)& { \ + m##NAME = std::move(a##NAME); \ + return *this; \ + } \ + \ + MarkerOptions&& Set(Marker##NAME&& a##NAME)&& { \ + m##NAME = std::move(a##NAME); \ + return std::move(*this); \ + } \ + \ + const Marker##NAME& NAME() const { return m##NAME; } \ + \ + Marker##NAME& NAME##Ref() { return m##NAME; } + + FUNCTIONS_ON_MEMBER(ThreadId); + FUNCTIONS_ON_MEMBER(Timing); + FUNCTIONS_ON_MEMBER(Stack); + FUNCTIONS_ON_MEMBER(InnerWindowId); +#undef FUNCTIONS_ON_MEMBER + + private: + friend ProfileBufferEntryReader::Deserializer; + + MarkerThreadId mThreadId; + MarkerTiming mTiming; + MarkerStack mStack; + MarkerInnerWindowId mInnerWindowId; +}; + +} // namespace mozilla + +namespace mozilla::baseprofiler::markers { + +// Default marker payload types, with no extra information, not even a marker +// type and payload. This is intended for label-only markers. +struct NoPayload final {}; + +} // namespace mozilla::baseprofiler::markers + +namespace mozilla { + +class JSONWriter; + +// This class collects all the information necessary to stream the JSON schema +// that informs the front-end how to display a type of markers. +// It will be created and populated in `MarkerTypeDisplay()` functions in each +// marker type definition, see Add/Set functions. +class MarkerSchema { + public: + // This is used to describe a C++ type that is expected to be specified to + // the marker and used in PayloadField. This type is the expected input type + // to the marker data. + enum class InputType { + Uint64, + Uint32, + Uint8, + Boolean, + CString, + String, + TimeStamp, + TimeDuration + }; + + enum class Location : unsigned { + MarkerChart, + MarkerTable, + // This adds markers to the main marker timeline in the header. + TimelineOverview, + // In the timeline, this is a section that breaks out markers that are + // related to memory. When memory counters are enabled, this is its own + // track, otherwise it is displayed with the main thread. + TimelineMemory, + // This adds markers to the IPC timeline area in the header. + TimelineIPC, + // This adds markers to the FileIO timeline area in the header. + TimelineFileIO, + // TODO - This is not supported yet. + StackChart + }; + + // Used as constructor parameter, to explicitly specify that the location (and + // other display options) are handled as a special case in the front-end. + // In this case, *no* schema will be output for this type. + struct SpecialFrontendLocation {}; + + enum class Format { + // ---------------------------------------------------- + // String types. + + // Show the URL, and handle PII sanitization + Url, + // Show the file path, and handle PII sanitization. + FilePath, + // Show arbitrary string and handle PII sanitization + SanitizedString, + // Important, do not put URL or file path information here, as it will not + // be sanitized. Please be careful with including other types of PII here as + // well. + // e.g. "Label: Some String" + String, + + // Show a string from a UniqueStringArray given an index in the profile. + // e.g. 1, given string table ["hello", "world"] will show "world" + UniqueString, + + // ---------------------------------------------------- + // Numeric types + + // For time data that represents a duration of time. + // e.g. "Label: 5s, 5ms, 5μs" + Duration, + // Data that happened at a specific time, relative to the start of the + // profile. e.g. "Label: 15.5s, 20.5ms, 30.5μs" + Time, + // The following are alternatives to display a time only in a specific unit + // of time. + Seconds, // "Label: 5s" + Milliseconds, // "Label: 5ms" + Microseconds, // "Label: 5μs" + Nanoseconds, // "Label: 5ns" + // e.g. "Label: 5.55mb, 5 bytes, 312.5kb" + Bytes, + // This should be a value between 0 and 1. + // "Label: 50%" + Percentage, + // The integer should be used for generic representations of numbers. + // Do not use it for time information. + // "Label: 52, 5,323, 1,234,567" + Integer, + // The decimal should be used for generic representations of numbers. + // Do not use it for time information. + // "Label: 52.23, 0.0054, 123,456.78" + Decimal, + + // A flow is a u64 identifier that's unique across processes. All of + // the markers with same flow id before a terminating flow id will be + // considered part of the same "flow" and linked together. + Flow, + // A terminating flow ends a flow of a particular id and allows that id + // to be reused again. It often makes sense for destructors to create + // a marker with a field of this type. + TerminatingFlow + }; + + // This represents groups of markers which MarkerTypes can expose to indicate + // what group they belong to (multiple groups are allowed combined in bitwise + // or). This is currently only used for ETW filtering. In the long run this + // should be generalized to gecko markers. + enum class ETWMarkerGroup : uint64_t { + Generic = 1, + UserMarkers = 1 << 1, + Memory = 1 << 2, + Scheduling = 1 << 3, + Text = 1 << 4, + Tracing = 1 << 5 + }; + + // Flags which describe additional information for a PayloadField. + enum class PayloadFlags : uint32_t { None = 0, Searchable = 1 }; + + // This is one field of payload to be used for additional marker data. + struct PayloadField { + // Key identifying the marker. + const char* Key; + // Input type, this represents the data type specified. + InputType InputTy; + // Label, additional description. + const char* Label = nullptr; + // Format as written to the JSON. + Format Fmt = Format::String; + // Optional PayloadFlags. + PayloadFlags Flags = PayloadFlags::None; + }; + + enum class Searchable { NotSearchable, Searchable }; + enum class GraphType { Line, Bar, FilledLine }; + enum class GraphColor { + Blue, + Green, + Grey, + Ink, + Magenta, + Orange, + Purple, + Red, + Teal, + Yellow + }; + + // Marker schema, with a non-empty list of locations where markers should be + // shown. + // Tech note: Even though `aLocations` are templated arguments, they are + // assigned to an `enum class` object, so they can only be of that enum type. + template + explicit MarkerSchema(Location aLocation, Locations... aLocations) + : mLocations{aLocation, aLocations...} {} + + // Alternative constructor for MarkerSchema. + explicit MarkerSchema(const mozilla::MarkerSchema::Location* aLocations, + size_t aLength) + : mLocations(aLocations, aLocations + aLength) {} + + // Marker schema for types that have special frontend handling. + // Nothing else should be set in this case. + // Implicit to allow quick return from MarkerTypeDisplay functions. + MOZ_IMPLICIT MarkerSchema(SpecialFrontendLocation) {} + + // Caller must specify location(s) or SpecialFrontendLocation above. + MarkerSchema() = delete; + + // Optional labels in the marker chart, the chart tooltip, and the marker + // table. If not provided, the marker "name" will be used. The given string + // can contain element keys in braces to include data elements streamed by + // `StreamJSONMarkerData()`. E.g.: "This is {text}" + +#define LABEL_SETTER(name) \ + MarkerSchema& Set##name(std::string a##name) { \ + m##name = std::move(a##name); \ + return *this; \ + } + + LABEL_SETTER(ChartLabel) + LABEL_SETTER(TooltipLabel) + LABEL_SETTER(TableLabel) + +#undef LABEL_SETTER + + MarkerSchema& SetAllLabels(std::string aText) { + // Here we set the same text in each label. + // TODO: Move to a single "label" field once the front-end allows it. + SetChartLabel(aText); + SetTooltipLabel(aText); + SetTableLabel(std::move(aText)); + return *this; + } + + MarkerSchema& SetIsStackBased() { + mIsStackBased = true; + return *this; + } + + // Each data element that is streamed by `StreamJSONMarkerData()` can be + // displayed as indicated by using one of the `Add...` function below. + // Each `Add...` will add a line in the full marker description. Parameters: + // - `aKey`: Element property name as streamed by `StreamJSONMarkerData()`. + // - `aLabel`: Optional prefix. Defaults to the key name. + // - `aFormat`: How to format the data element value, see `Format` above. + // - `aSearchable`: Optional, indicates if the value is used in searches, + // defaults to false. + + MarkerSchema& AddKeyFormat(std::string aKey, Format aFormat) { + mData.emplace_back(mozilla::VariantType{}, + DynamicData{std::move(aKey), mozilla::Nothing{}, aFormat, + mozilla::Nothing{}}); + return *this; + } + + MarkerSchema& AddKeyLabelFormat(std::string aKey, std::string aLabel, + Format aFormat) { + mData.emplace_back( + mozilla::VariantType{}, + DynamicData{std::move(aKey), mozilla::Some(std::move(aLabel)), aFormat, + mozilla::Nothing{}}); + return *this; + } + + MarkerSchema& AddKeyFormatSearchable(std::string aKey, Format aFormat, + Searchable aSearchable) { + mData.emplace_back(mozilla::VariantType{}, + DynamicData{std::move(aKey), mozilla::Nothing{}, aFormat, + mozilla::Some(aSearchable)}); + return *this; + } + + MarkerSchema& AddKeyLabelFormatSearchable(std::string aKey, + std::string aLabel, Format aFormat, + Searchable aSearchable) { + mData.emplace_back( + mozilla::VariantType{}, + DynamicData{std::move(aKey), mozilla::Some(std::move(aLabel)), aFormat, + mozilla::Some(aSearchable)}); + return *this; + } + + // The display may also include static rows. + + MarkerSchema& AddStaticLabelValue(std::string aLabel, std::string aValue) { + mData.emplace_back(mozilla::VariantType{}, + StaticData{std::move(aLabel), std::move(aValue)}); + return *this; + } + + // Markers can be shown as timeline tracks. + + MarkerSchema& AddChart(std::string aKey, GraphType aType) { + mGraphs.emplace_back(GraphData{std::move(aKey), aType, mozilla::Nothing{}}); + return *this; + } + + MarkerSchema& AddChartColor(std::string aKey, GraphType aType, + GraphColor aColor) { + mGraphs.emplace_back( + GraphData{std::move(aKey), aType, mozilla::Some(aColor)}); + return *this; + } + + // Internal streaming function. + MFBT_API void Stream(JSONWriter& aWriter, const Span& aName) &&; + + private: + MFBT_API static Span LocationToStringSpan(Location aLocation); + MFBT_API static Span FormatToStringSpan(Format aFormat); + MFBT_API static Span GraphTypeToStringSpan(GraphType aType); + MFBT_API static Span GraphColorToStringSpan(GraphColor aColor); + + // List of marker display locations. Empty for SpecialFrontendLocation. + std::vector mLocations; + // Labels for different places. + std::string mChartLabel; + std::string mTooltipLabel; + std::string mTableLabel; + bool mIsStackBased = false; + // Main display, made of zero or more rows of key+label+format or label+value. + private: + struct DynamicData { + std::string mKey; + mozilla::Maybe mLabel; + Format mFormat; + mozilla::Maybe mSearchable; + }; + struct StaticData { + std::string mLabel; + std::string mValue; + }; + using DataRow = mozilla::Variant; + using DataRowVector = std::vector; + + DataRowVector mData; + + struct GraphData { + std::string mKey; + GraphType mType; + mozilla::Maybe mColor; + }; + std::vector mGraphs; +}; + +namespace detail { +// GCC doesn't allow this to live inside the class. +template +static void StreamPayload(baseprofiler::SpliceableJSONWriter& aWriter, + const Span aKey, + const PayloadType& aPayload) { + aWriter.StringProperty(aKey, aPayload); +} + +template +inline void StreamPayload(baseprofiler::SpliceableJSONWriter& aWriter, + const Span aKey, + const Maybe& aPayload) { + if (aPayload.isSome()) { + StreamPayload(aWriter, aKey, *aPayload); + } else { + aWriter.NullProperty(aKey); + } +} + +template <> +inline void StreamPayload(baseprofiler::SpliceableJSONWriter& aWriter, + const Span aKey, + const bool& aPayload) { + aWriter.BoolProperty(aKey, aPayload); +} + +template <> +inline void StreamPayload( + baseprofiler::SpliceableJSONWriter& aWriter, const Span aKey, + const ProfilerString8View& aPayload) { + aWriter.StringProperty(aKey, aPayload); +} + +template <> +inline void StreamPayload(baseprofiler::SpliceableJSONWriter& aWriter, + const Span aKey, + const Flow& aPayload) { + aWriter.FlowProperty(aKey, aPayload); +} + +} // namespace detail + +// This helper class is used by MarkerTypes that want to support the general +// MarkerType object schema. When using this the markers will also transmit +// their payload to the ETW tracer as well as requiring less inline code. +// This is a curiously recurring template, the template argument is the child +// class itself. +template +struct BaseMarkerType { + static constexpr const char* Description = nullptr; + + static constexpr const char* AllLabels = nullptr; + static constexpr const char* ChartLabel = nullptr; + static constexpr const char* TableLabel = nullptr; + static constexpr const char* TooltipLabel = nullptr; + + // Setting this property to true is a promise that the the marker will nest + // properly. i.e. it can't have a partially overlapping time range with any + // other stack based markers on the same thread. + static constexpr bool IsStackBased = false; + + // This indicates whether this marker type wants the names passed to the + // individual marker calls stores along with the marker. + static constexpr bool StoreName = false; + + static constexpr MarkerSchema::ETWMarkerGroup Group = + MarkerSchema::ETWMarkerGroup::Generic; + + static MarkerSchema MarkerTypeDisplay() { + using MS = MarkerSchema; + MS schema{T::Locations, std::size(T::Locations)}; + if (T::AllLabels) { + schema.SetAllLabels(T::AllLabels); + } + if (T::ChartLabel) { + schema.SetChartLabel(T::ChartLabel); + } + if (T::TableLabel) { + schema.SetTableLabel(T::TableLabel); + } + if (T::TooltipLabel) { + schema.SetTooltipLabel(T::TooltipLabel); + } + if (T::IsStackBased) { + schema.SetIsStackBased(); + } + for (const MS::PayloadField field : T::PayloadFields) { + if (field.Label) { + if (uint32_t(field.Flags) & uint32_t(MS::PayloadFlags::Searchable)) { + schema.AddKeyLabelFormatSearchable(field.Key, field.Label, field.Fmt, + MS::Searchable::Searchable); + } else { + schema.AddKeyLabelFormat(field.Key, field.Label, field.Fmt); + } + } else { + if (uint32_t(field.Flags) & uint32_t(MS::PayloadFlags::Searchable)) { + schema.AddKeyFormatSearchable(field.Key, field.Fmt, + MS::Searchable::Searchable); + } else { + schema.AddKeyFormat(field.Key, field.Fmt); + } + } + } + if (T::Description) { + schema.AddStaticLabelValue("Description", T::Description); + } + return schema; + } + + static constexpr Span MarkerTypeName() { + return MakeStringSpan(T::Name); + } + + // This is called by the child class since the child class version of this + // function is used to infer the argument types by the profile buffer and + // allows the child to do any special data conversion it needs to do. + // Optionally the child can opt not to use this at all and write the data + // out itself. + template + static void StreamJSONMarkerDataImpl( + baseprofiler::SpliceableJSONWriter& aWriter, + const PayloadArguments&... aPayloadArguments) { + size_t i = 0; + (detail::StreamPayload(aWriter, MakeStringSpan(T::PayloadFields[i++].Key), + aPayloadArguments), + ...); + } +}; +} // namespace mozilla + +#endif // BaseProfilerMarkersPrerequisites_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerRAIIMacro.h b/src/third_party/mozjs/include/mozilla/BaseProfilerRAIIMacro.h new file mode 100644 index 00000000000..b89f7e1f773 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerRAIIMacro.h @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BaseProfilerRAIIMacro_h +#define BaseProfilerRAIIMacro_h + +// Macros used by the AUTO_PROFILER_* macros to generate unique variable names. +#define PROFILER_RAII_PASTE(id, line) id##line +#define PROFILER_RAII_EXPAND(id, line) PROFILER_RAII_PASTE(id, line) +#define PROFILER_RAII PROFILER_RAII_EXPAND(raiiObject, __LINE__) + +#endif // BaseProfilerRAIIMacro_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerState.h b/src/third_party/mozjs/include/mozilla/BaseProfilerState.h new file mode 100644 index 00000000000..6031805061e --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerState.h @@ -0,0 +1,429 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// The Gecko Profiler is an always-on profiler that takes fast and low overhead +// samples of the program execution using only userspace functionality for +// portability. The goal of this module is to provide performance data in a +// generic cross-platform way without requiring custom tools or kernel support. +// +// Samples are collected to form a timeline with optional timeline event +// (markers) used for filtering. The samples include both native stacks and +// platform-independent "label stack" frames. + +#ifndef BaseProfilerState_h +#define BaseProfilerState_h + +// This header contains most functions that give information about the Base +// Profiler: Whether it is active or not, paused, the selected features, and +// some generic process and thread information. +// It is safe to include unconditionally, but uses of structs and functions must +// be guarded by `#ifdef MOZ_GECKO_PROFILER`. + +#include "mozilla/BaseProfilerUtils.h" + +#ifndef MOZ_GECKO_PROFILER + +# define AUTO_PROFILER_STATS(name) + +namespace mozilla::baseprofiler { + +[[nodiscard]] inline bool profiler_is_active() { return false; } +[[nodiscard]] inline bool profiler_is_active_and_unpaused() { return false; } + +} // namespace mozilla::baseprofiler + +#else // !MOZ_GECKO_PROFILER + +# include "mozilla/Atomics.h" +# include "mozilla/Maybe.h" + +# include +# include + +// Uncomment the following line to display profiler runtime statistics at +// shutdown. +// # define PROFILER_RUNTIME_STATS + +# ifdef PROFILER_RUNTIME_STATS +# include "mozilla/TimeStamp.h" +# endif + +namespace mozilla::baseprofiler { + +# ifdef PROFILER_RUNTIME_STATS +// This class gathers durations and displays some basic stats when destroyed. +// It is intended to be used as a static variable (see `AUTO_PROFILER_STATS` +// below), to display stats at the end of the program. +class StaticBaseProfilerStats { + public: + explicit StaticBaseProfilerStats(const char* aName) : mName(aName) {} + + ~StaticBaseProfilerStats() { + // Using unsigned long long for computations and printfs. + using ULL = unsigned long long; + ULL n = static_cast(mNumberDurations); + if (n != 0) { + ULL sumNs = static_cast(mSumDurationsNs); + printf( + "[%d] Profiler stats `%s`: %llu ns / %llu = %llu ns, max %llu ns\n", + int(profiler_current_process_id().ToNumber()), mName, sumNs, n, + sumNs / n, static_cast(mLongestDurationNs)); + } else { + printf("[%d] Profiler stats `%s`: (nothing)\n", + int(profiler_current_process_id().ToNumber()), mName); + } + } + + void AddDurationFrom(TimeStamp aStart) { + DurationNs duration = static_cast( + (TimeStamp::Now() - aStart).ToMicroseconds() * 1000 + 0.5); + mSumDurationsNs += duration; + ++mNumberDurations; + // Update mLongestDurationNs if this one is longer. + for (;;) { + DurationNs longest = mLongestDurationNs; + if (MOZ_LIKELY(longest >= duration)) { + // This duration is not the longest, nothing to do. + break; + } + if (MOZ_LIKELY(mLongestDurationNs.compareExchange(longest, duration))) { + // Successfully updated `mLongestDurationNs` with the new value. + break; + } + // Otherwise someone else just updated `mLongestDurationNs`, we need to + // try again by looping. + } + } + + private: + using DurationNs = uint64_t; + using Count = uint32_t; + + Atomic mSumDurationsNs{0}; + Atomic mLongestDurationNs{0}; + Atomic mNumberDurations{0}; + const char* mName; +}; + +// RAII object that measure its scoped lifetime duration and reports it to a +// `StaticBaseProfilerStats`. +class MOZ_RAII AutoProfilerStats { + public: + explicit AutoProfilerStats(StaticBaseProfilerStats& aStats) + : mStats(aStats), mStart(TimeStamp::Now()) {} + + ~AutoProfilerStats() { mStats.AddDurationFrom(mStart); } + + private: + StaticBaseProfilerStats& mStats; + TimeStamp mStart; +}; + +// Macro that should be used to collect basic statistics from measurements of +// block durations, from where this macro is, until the end of its enclosing +// scope. The name is used in the static variable name and when displaying stats +// at the end of the program; Another location could use the same name but their +// stats will not be combined, so use different name if these locations should +// be distinguished. +# define AUTO_PROFILER_STATS(name) \ + static ::mozilla::baseprofiler::StaticBaseProfilerStats sStat##name( \ + #name); \ + ::mozilla::baseprofiler::AutoProfilerStats autoStat##name(sStat##name); + +# else // PROFILER_RUNTIME_STATS + +# define AUTO_PROFILER_STATS(name) + +# endif // PROFILER_RUNTIME_STATS else + +//--------------------------------------------------------------------------- +// Profiler features +//--------------------------------------------------------------------------- + +# if defined(__APPLE__) && defined(__aarch64__) +# define POWER_HELP "Sample per process power use" +# elif defined(__APPLE__) && defined(__x86_64__) +# define POWER_HELP \ + "Record the power used by the entire system with each sample." +# elif defined(__linux__) && defined(__x86_64__) +# define POWER_HELP \ + "Record the power used by the entire system with each sample. " \ + "Only available with Intel CPUs and requires setting " \ + "the sysctl kernel.perf_event_paranoid to 0." +# elif defined(_MSC_VER) +# define POWER_HELP \ + "Record the value of every energy meter available on the system with " \ + "each sample. Only available on Windows 11 with Intel CPUs." +# else +# define POWER_HELP "Not supported on this platform." +# endif + +// Higher-order macro containing all the feature info in one place. Define +// |MACRO| appropriately to extract the relevant parts. Note that the number +// values are used internally only and so can be changed without consequence. +// Any changes to this list should also be applied to the feature list in +// toolkit/components/extensions/schemas/geckoProfiler.json. +// *** Synchronize with lists in ProfilerState.h and geckoProfiler.json *** +# define BASE_PROFILER_FOR_EACH_FEATURE(MACRO) \ + MACRO(0, "java", Java, "Profile Java code, Android only") \ + \ + MACRO(1, "js", JS, \ + "Get the JS engine to expose the JS stack to the profiler") \ + \ + MACRO(2, "mainthreadio", MainThreadIO, "Add main thread file I/O") \ + \ + MACRO(3, "fileio", FileIO, \ + "Add file I/O from all profiled threads, implies mainthreadio") \ + \ + MACRO(4, "fileioall", FileIOAll, \ + "Add file I/O from all threads, implies fileio") \ + \ + MACRO(5, "nomarkerstacks", NoMarkerStacks, \ + "Markers do not capture stacks, to reduce overhead") \ + \ + MACRO(6, "screenshots", Screenshots, \ + "Take a snapshot of the window on every composition") \ + \ + MACRO(7, "seqstyle", SequentialStyle, \ + "Disable parallel traversal in styling") \ + \ + MACRO(8, "stackwalk", StackWalk, \ + "Walk the C++ stack, not available on all platforms") \ + \ + MACRO(9, "jsallocations", JSAllocations, \ + "Have the JavaScript engine track allocations") \ + \ + MACRO(10, "nostacksampling", NoStackSampling, \ + "Disable all stack sampling: Cancels \"js\", \"stackwalk\" and " \ + "labels") \ + \ + MACRO(11, "nativeallocations", NativeAllocations, \ + "Collect the stacks from a smaller subset of all native " \ + "allocations, biasing towards collecting larger allocations") \ + \ + MACRO(12, "ipcmessages", IPCMessages, \ + "Have the IPC layer track cross-process messages") \ + \ + MACRO(13, "audiocallbacktracing", AudioCallbackTracing, \ + "Audio callback tracing") \ + \ + MACRO(14, "cpu", CPUUtilization, "CPU utilization") \ + \ + MACRO(15, "notimerresolutionchange", NoTimerResolutionChange, \ + "Do not adjust the timer resolution for fast sampling, so that " \ + "other Firefox timers do not get affected") \ + \ + MACRO(16, "cpuallthreads", CPUAllThreads, \ + "Sample the CPU utilization of all registered threads") \ + \ + MACRO(17, "samplingallthreads", SamplingAllThreads, \ + "Sample the stacks of all registered threads") \ + \ + MACRO(18, "markersallthreads", MarkersAllThreads, \ + "Record markers from all registered threads") \ + \ + MACRO(19, "unregisteredthreads", UnregisteredThreads, \ + "Discover and profile unregistered threads -- beware: expensive!") \ + \ + MACRO(20, "processcpu", ProcessCPU, \ + "Sample the CPU utilization of each process") \ + \ + MACRO(21, "power", Power, POWER_HELP) \ + \ + MACRO(22, "cpufreq", CPUFrequency, \ + "Record the clock frequency of " \ + "every CPU core for every profiler sample.") \ + \ + MACRO(23, "bandwidth", Bandwidth, \ + "Record the network bandwidth used for every profiler sample.") \ + \ + MACRO(24, "memory", Memory, \ + "Track the memory allocations and deallocations per process over " \ + "time.") \ + \ + MACRO(25, "tracing", Tracing, \ + "Instead of sampling periodically, captures information about " \ + "every function executed for the duration (JS only)") \ + \ + MACRO(26, "sandbox", Sandbox, \ + "Report sandbox syscalls and logs in the " \ + "profiler.") \ + \ + MACRO(27, "flows", Flows, \ + "Include all flow-related markers. These markers show the program" \ + "better but can cause more overhead in some places than normal.") + +// *** Synchronize with lists in ProfilerState.h and geckoProfiler.json *** + +struct ProfilerFeature { +# define DECLARE(n_, str_, Name_, desc_) \ + static constexpr uint32_t Name_ = (1u << n_); \ + [[nodiscard]] static constexpr bool Has##Name_(uint32_t aFeatures) { \ + return aFeatures & Name_; \ + } \ + static constexpr void Set##Name_(uint32_t& aFeatures) { \ + aFeatures |= Name_; \ + } \ + static constexpr void Clear##Name_(uint32_t& aFeatures) { \ + aFeatures &= ~Name_; \ + } + + // Define a bitfield constant, a getter, and two setters for each feature. + BASE_PROFILER_FOR_EACH_FEATURE(DECLARE) + +# undef DECLARE +}; + +namespace detail { + +// RacyFeatures is only defined in this header file so that its methods can +// be inlined into profiler_is_active(). Please do not use anything from the +// detail namespace outside the profiler. + +// Within the profiler's code, the preferred way to check profiler activeness +// and features is via ActivePS(). However, that requires locking gPSMutex. +// There are some hot operations where absolute precision isn't required, so we +// duplicate the activeness/feature state in a lock-free manner in this class. +class RacyFeatures { + public: + MFBT_API static void SetActive(uint32_t aFeatures); + + MFBT_API static void SetInactive(); + + MFBT_API static void SetPaused(); + + MFBT_API static void SetUnpaused(); + + MFBT_API static void SetSamplingPaused(); + + MFBT_API static void SetSamplingUnpaused(); + + [[nodiscard]] MFBT_API static mozilla::Maybe FeaturesIfActive() { + if (uint32_t af = sActiveAndFeatures; af & Active) { + // Active, remove the Active&Paused bits to get all features. + return Some(af & ~(Active | Paused | SamplingPaused)); + } + return Nothing(); + } + + [[nodiscard]] MFBT_API static bool IsActive(); + + [[nodiscard]] MFBT_API static bool IsActiveWithFeature(uint32_t aFeature); + + [[nodiscard]] MFBT_API static bool IsActiveWithoutFeature(uint32_t aFeature); + + // True if profiler is active, and not fully paused. + // Note that periodic sampling *could* be paused! + [[nodiscard]] MFBT_API static bool IsActiveAndUnpaused(); + + // True if profiler is active, and sampling is not paused (though generic + // `SetPaused()` or specific `SetSamplingPaused()`). + [[nodiscard]] MFBT_API static bool IsActiveAndSamplingUnpaused(); + + private: + static constexpr uint32_t Active = 1u << 31; + static constexpr uint32_t Paused = 1u << 30; + static constexpr uint32_t SamplingPaused = 1u << 29; + +// Ensure Active/Paused don't overlap with any of the feature bits. +# define NO_OVERLAP(n_, str_, Name_, desc_) \ + static_assert(ProfilerFeature::Name_ != SamplingPaused, \ + "bad feature value"); + + BASE_PROFILER_FOR_EACH_FEATURE(NO_OVERLAP); + +# undef NO_OVERLAP + + // We combine the active bit with the feature bits so they can be read or + // written in a single atomic operation. + // TODO: Could this be MFBT_DATA for better inlining optimization? + MFBT_DATA static Atomic sActiveAndFeatures; +}; + +MFBT_API bool IsThreadBeingProfiled(); + +} // namespace detail + +//--------------------------------------------------------------------------- +// Get information from the profiler +//--------------------------------------------------------------------------- + +// Is the profiler active? Note: the return value of this function can become +// immediately out-of-date. E.g. the profile might be active but then +// profiler_stop() is called immediately afterward. One common and reasonable +// pattern of usage is the following: +// +// if (profiler_is_active()) { +// ExpensiveData expensiveData = CreateExpensiveData(); +// PROFILER_OPERATION(expensiveData); +// } +// +// where PROFILER_OPERATION is a no-op if the profiler is inactive. In this +// case the profiler_is_active() check is just an optimization -- it prevents +// us calling CreateExpensiveData() unnecessarily in most cases, but the +// expensive data will end up being created but not used if another thread +// stops the profiler between the CreateExpensiveData() and PROFILER_OPERATION +// calls. +[[nodiscard]] inline bool profiler_is_active() { + return baseprofiler::detail::RacyFeatures::IsActive(); +} + +// Same as profiler_is_active(), but also checks if the profiler is not paused. +[[nodiscard]] inline bool profiler_is_active_and_unpaused() { + return baseprofiler::detail::RacyFeatures::IsActiveAndUnpaused(); +} + +// Is the profiler active and unpaused, and is the current thread being +// profiled? (Same caveats and recommented usage as profiler_is_active().) +[[nodiscard]] inline bool profiler_thread_is_being_profiled() { + return baseprofiler::detail::RacyFeatures::IsActiveAndUnpaused() && + baseprofiler::detail::IsThreadBeingProfiled(); +} + +// Is the profiler active and paused? Returns false if the profiler is inactive. +[[nodiscard]] MFBT_API bool profiler_is_paused(); + +// Is the profiler active and sampling is paused? Returns false if the profiler +// is inactive. +[[nodiscard]] MFBT_API bool profiler_is_sampling_paused(); + +// Is the current thread sleeping? +[[nodiscard]] MFBT_API bool profiler_thread_is_sleeping(); + +// Get all the features supported by the profiler that are accepted by +// profiler_start(). The result is the same whether the profiler is active or +// not. +[[nodiscard]] MFBT_API uint32_t profiler_get_available_features(); + +// Returns the full feature set if the profiler is active. +// Note: the return value can become immediately out-of-date, much like the +// return value of profiler_is_active(). +[[nodiscard]] inline mozilla::Maybe profiler_features_if_active() { + return baseprofiler::detail::RacyFeatures::FeaturesIfActive(); +} + +// Check if a profiler feature (specified via the ProfilerFeature type) is +// active. Returns false if the profiler is inactive. Note: the return value +// can become immediately out-of-date, much like the return value of +// profiler_is_active(). +[[nodiscard]] MFBT_API bool profiler_feature_active(uint32_t aFeature); + +// Check if the profiler is active without a feature (specified via the +// ProfilerFeature type). Note: the return value can become immediately +// out-of-date, much like the return value of profiler_is_active(). +[[nodiscard]] MFBT_API bool profiler_active_without_feature(uint32_t aFeature); + +// Returns true if any of the profiler mutexes are currently locked *on the +// current thread*. This may be used by re-entrant code that may call profiler +// functions while the same of a different profiler mutex is locked, which could +// deadlock. +[[nodiscard]] bool profiler_is_locked_on_current_thread(); + +} // namespace mozilla::baseprofiler + +#endif // !MOZ_GECKO_PROFILER + +#endif // BaseProfilerState_h diff --git a/src/third_party/mozjs/include/mozilla/BaseProfilerUtils.h b/src/third_party/mozjs/include/mozilla/BaseProfilerUtils.h new file mode 100644 index 00000000000..ab02e03b955 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/BaseProfilerUtils.h @@ -0,0 +1,227 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BaseProfilerUtils_h +#define BaseProfilerUtils_h + +// This header contains most process- and thread-related functions. +// It is safe to include unconditionally. + +// --------------------------------------------- WASI process & thread ids +#if defined(__wasi__) + +namespace mozilla::baseprofiler::detail { +using ProcessIdType = unsigned; +using ThreadIdType = unsigned; +} // namespace mozilla::baseprofiler::detail + +// --------------------------------------------- Windows process & thread ids +#elif defined(XP_WIN) + +namespace mozilla::baseprofiler::detail { +using ProcessIdType = int; +using ThreadIdType = unsigned long; +} // namespace mozilla::baseprofiler::detail + +// --------------------------------------------- Non-Windows process id +#else +// All non-Windows platforms are assumed to be POSIX, which has getpid(). + +# include +namespace mozilla::baseprofiler::detail { +using ProcessIdType = decltype(getpid()); +} // namespace mozilla::baseprofiler::detail + +// --------------------------------------------- Non-Windows thread id +// ------------------------------------------------------- macOS +# if defined(XP_MACOSX) + +namespace mozilla::baseprofiler::detail { +using ThreadIdType = uint64_t; +} // namespace mozilla::baseprofiler::detail + +// ------------------------------------------------------- Android +// Test Android before Linux, because Linux includes Android. +# elif defined(__ANDROID__) || defined(ANDROID) + +# include +namespace mozilla::baseprofiler::detail { +using ThreadIdType = decltype(gettid()); +} // namespace mozilla::baseprofiler::detail + +// ------------------------------------------------------- Linux +# elif defined(XP_LINUX) + +namespace mozilla::baseprofiler::detail { +using ThreadIdType = long; +} // namespace mozilla::baseprofiler::detail + +// ------------------------------------------------------- FreeBSD +# elif defined(XP_FREEBSD) + +namespace mozilla::baseprofiler::detail { +using ThreadIdType = long; +} // namespace mozilla::baseprofiler::detail + +// ------------------------------------------------------- Others +# else + +# include + +namespace mozilla::baseprofiler::detail { +using ThreadIdType = std::thread::id; +} // namespace mozilla::baseprofiler::detail + +# endif +#endif // End of non-XP_WIN. + +#include +#include +#include + +namespace mozilla::baseprofiler { + +// Trivially-copyable class containing a process id. It may be left unspecified. +class BaseProfilerProcessId { + public: + using NativeType = detail::ProcessIdType; + + using NumberType = + std::conditional_t<(sizeof(NativeType) <= 4), uint32_t, uint64_t>; + static_assert(sizeof(NativeType) <= sizeof(NumberType)); + + // Unspecified process id. + constexpr BaseProfilerProcessId() = default; + + [[nodiscard]] constexpr bool IsSpecified() const { + return mProcessId != scUnspecified; + } + + // Construct from a native type. + [[nodiscard]] static BaseProfilerProcessId FromNativeId( + const NativeType& aNativeProcessId) { + BaseProfilerProcessId id; + // Convert trivially-copyable native id by copying its bits. + static_assert(std::is_trivially_copyable_v); + memcpy(&id.mProcessId, &aNativeProcessId, sizeof(NativeType)); + return id; + } + + // Get the process id as a number, which may be unspecified. + // This should only be used for serialization or logging. + [[nodiscard]] constexpr NumberType ToNumber() const { return mProcessId; } + + // BaseProfilerProcessId from given number (which may be unspecified). + constexpr static BaseProfilerProcessId FromNumber( + const NumberType& aProcessId) { + BaseProfilerProcessId id; + id.mProcessId = aProcessId; + return id; + } + + [[nodiscard]] constexpr bool operator==( + const BaseProfilerProcessId& aOther) const { + return mProcessId == aOther.mProcessId; + } + [[nodiscard]] constexpr bool operator!=( + const BaseProfilerProcessId& aOther) const { + return mProcessId != aOther.mProcessId; + } + + private: + static constexpr NumberType scUnspecified = 0; + NumberType mProcessId = scUnspecified; +}; + +// Check traits. These should satisfy usage in std::atomic. +static_assert(std::is_trivially_copyable_v); +static_assert(std::is_copy_constructible_v); +static_assert(std::is_move_constructible_v); +static_assert(std::is_copy_assignable_v); +static_assert(std::is_move_assignable_v); + +// Trivially-copyable class containing a thread id. It may be left unspecified. +class BaseProfilerThreadId { + public: + using NativeType = detail::ThreadIdType; + + using NumberType = + std::conditional_t<(sizeof(NativeType) <= 4), uint32_t, uint64_t>; + static_assert(sizeof(NativeType) <= sizeof(NumberType)); + + // Unspecified thread id. + constexpr BaseProfilerThreadId() = default; + + [[nodiscard]] constexpr bool IsSpecified() const { + return mThreadId != scUnspecified; + } + + // Construct from a native type. + [[nodiscard]] static BaseProfilerThreadId FromNativeId( + const NativeType& aNativeThreadId) { + BaseProfilerThreadId id; + // Convert trivially-copyable native id by copying its bits. + static_assert(std::is_trivially_copyable_v); + memcpy(&id.mThreadId, &aNativeThreadId, sizeof(NativeType)); + return id; + } + + // Get the thread id as a number, which may be unspecified. + // This should only be used for serialization or logging. + [[nodiscard]] constexpr NumberType ToNumber() const { return mThreadId; } + + // BaseProfilerThreadId from given number (which may be unspecified). + constexpr static BaseProfilerThreadId FromNumber( + const NumberType& aThreadId) { + BaseProfilerThreadId id; + id.mThreadId = aThreadId; + return id; + } + + [[nodiscard]] constexpr bool operator==( + const BaseProfilerThreadId& aOther) const { + return mThreadId == aOther.mThreadId; + } + [[nodiscard]] constexpr bool operator!=( + const BaseProfilerThreadId& aOther) const { + return mThreadId != aOther.mThreadId; + } + + private: + static constexpr NumberType scUnspecified = 0; + NumberType mThreadId = scUnspecified; +}; + +// Check traits. These should satisfy usage in std::atomic. +static_assert(std::is_trivially_copyable_v); +static_assert(std::is_copy_constructible_v); +static_assert(std::is_move_constructible_v); +static_assert(std::is_copy_assignable_v); +static_assert(std::is_move_assignable_v); + +} // namespace mozilla::baseprofiler + +#include "mozilla/Types.h" + +namespace mozilla::baseprofiler { + +// Get the current process's ID. +[[nodiscard]] MFBT_API BaseProfilerProcessId profiler_current_process_id(); + +// Get the current thread's ID. +[[nodiscard]] MFBT_API BaseProfilerThreadId profiler_current_thread_id(); + +// Must be called at least once from the main thread, before any other main- +// thread id function. +MFBT_API void profiler_init_main_thread_id(); + +[[nodiscard]] MFBT_API BaseProfilerThreadId profiler_main_thread_id(); + +[[nodiscard]] MFBT_API bool profiler_is_main_thread(); + +} // namespace mozilla::baseprofiler + +#endif // BaseProfilerUtils_h diff --git a/src/third_party/mozjs/include/mozilla/BitSet.h b/src/third_party/mozjs/include/mozilla/BitSet.h index 7c03fb87ce6..9e2264a6e30 100644 --- a/src/third_party/mozjs/include/mozilla/BitSet.h +++ b/src/third_party/mozjs/include/mozilla/BitSet.h @@ -8,24 +8,48 @@ #define mozilla_BitSet_h #include "mozilla/Array.h" -#include "mozilla/ArrayUtils.h" #include "mozilla/MathAlgorithms.h" -#include "mozilla/PodOperations.h" #include "mozilla/Span.h" namespace mozilla { +enum MemoryOrdering : uint8_t; +template +class Atomic; + +namespace detail { + +template +struct UnwrapMaybeAtomic { + using Type = T; +}; +template +struct UnwrapMaybeAtomic> { + using Type = T; +}; + +} // namespace detail + /** * An object like std::bitset but which provides access to the underlying * storage. * + * The type |StorageType| must be an unsigned integer or a mozilla::Atomic + * wrapping an unsigned integer. Use of atomic types makes word access atomic, + * but does not make operations that operate on the whole bitset atomic. + * * The limited API is due to expedience only; feel free to flesh out any * std::bitset-like members. */ -template +template class BitSet { - static_assert(std::is_unsigned_v, - "The Word type must be an unsigned integral type"); + public: + using Word = typename detail::UnwrapMaybeAtomic::Type; + static_assert(sizeof(Word) == sizeof(StorageType)); + static_assert( + std::is_unsigned_v, + "StorageType must be an unsigned integral type, or equivalent Atomic"); + static_assert(N != 0); private: static constexpr size_t kBitsPerWord = 8 * sizeof(Word); @@ -34,7 +58,7 @@ class BitSet { static constexpr Word kPaddingMask = Word(-1) >> kPaddingBits; // The zeroth bit in the bitset is the least significant bit of mStorage[0]. - Array mStorage; + Array mStorage; constexpr void ResetPaddingBits() { if constexpr (kPaddingBits != 0) { @@ -45,20 +69,24 @@ class BitSet { public: class Reference { public: - Reference(BitSet& aBitSet, size_t aPos) + Reference(BitSet& aBitSet, size_t aPos) : mBitSet(aBitSet), mPos(aPos) {} Reference& operator=(bool aValue) { auto bit = Word(1) << (mPos % kBitsPerWord); auto& word = mBitSet.mStorage[mPos / kBitsPerWord]; - word = (word & ~bit) | (aValue ? bit : 0); + if (aValue) { + word |= bit; + } else { + word &= ~bit; + } return *this; } - MOZ_IMPLICIT operator bool() const { return mBitSet.Test(mPos); } + MOZ_IMPLICIT operator bool() const { return mBitSet.test(mPos); } private: - BitSet& mBitSet; + BitSet& mBitSet; size_t mPos; }; @@ -67,23 +95,27 @@ class BitSet { BitSet(const BitSet& aOther) { *this = aOther; } BitSet& operator=(const BitSet& aOther) { - PodCopy(mStorage.begin(), aOther.mStorage.begin(), kNumWords); + for (size_t i = 0; i < std::size(mStorage); i++) { + mStorage[i] = Word(aOther.mStorage[i]); + } return *this; } - explicit BitSet(Span aStorage) { - PodCopy(mStorage.begin(), aStorage.Elements(), kNumWords); + explicit BitSet(Span aStorage) { + for (size_t i = 0; i < std::size(mStorage); i++) { + mStorage[i] = Word(aStorage[i]); + } } - static constexpr size_t Size() { return N; } + static constexpr size_t size() { return N; } - constexpr bool Test(size_t aPos) const { + constexpr bool test(size_t aPos) const { MOZ_ASSERT(aPos < N); return mStorage[aPos / kBitsPerWord] & (Word(1) << (aPos % kBitsPerWord)); } constexpr bool IsEmpty() const { - for (const Word& word : mStorage) { + for (const StorageType& word : mStorage) { if (word) { return false; } @@ -93,21 +125,21 @@ class BitSet { explicit constexpr operator bool() { return !IsEmpty(); } - constexpr bool operator[](size_t aPos) const { return Test(aPos); } + constexpr bool operator[](size_t aPos) const { return test(aPos); } Reference operator[](size_t aPos) { MOZ_ASSERT(aPos < N); return {*this, aPos}; } - BitSet operator|(const BitSet& aOther) { + BitSet operator|(const BitSet& aOther) { BitSet result = *this; result |= aOther; return result; } - BitSet& operator|=(const BitSet& aOther) { - for (size_t i = 0; i < ArrayLength(mStorage); i++) { + BitSet& operator|=(const BitSet& aOther) { + for (size_t i = 0; i < std::size(mStorage); i++) { mStorage[i] |= aOther.mStorage[i]; } return *this; @@ -119,27 +151,27 @@ class BitSet { return result; } - BitSet& operator&=(const BitSet& aOther) { - for (size_t i = 0; i < ArrayLength(mStorage); i++) { + BitSet& operator&=(const BitSet& aOther) { + for (size_t i = 0; i < std::size(mStorage); i++) { mStorage[i] &= aOther.mStorage[i]; } return *this; } - BitSet operator&(const BitSet& aOther) const { + BitSet operator&(const BitSet& aOther) const { BitSet result = *this; result &= aOther; return result; } - bool operator==(const BitSet& aOther) const { + bool operator==(const BitSet& aOther) const { return mStorage == aOther.mStorage; } size_t Count() const { size_t count = 0; - for (const Word& word : mStorage) { + for (const StorageType& word : mStorage) { if constexpr (kBitsPerWord > 32) { count += CountPopulation64(word); } else { @@ -151,25 +183,80 @@ class BitSet { } // Set all bits to false. - void ResetAll() { PodArrayZero(mStorage); } + void ResetAll() { + for (StorageType& word : mStorage) { + word = Word(0); + } + } // Set all bits to true. void SetAll() { - memset(mStorage.begin(), 0xff, kNumWords * sizeof(Word)); + for (StorageType& word : mStorage) { + word = ~Word(0); + } ResetPaddingBits(); } void Flip() { - for (Word& word : mStorage) { + for (StorageType& word : mStorage) { word = ~word; } ResetPaddingBits(); } - Span Storage() { return mStorage; } + // Return the position of the first bit set, or SIZE_MAX if none. + size_t FindFirst() const { return FindNext(0); } - Span Storage() const { return mStorage; } + // Return the position of the next bit set starting from |aFromPos| inclusive, + // or SIZE_MAX if none. + size_t FindNext(size_t aFromPos) const { + MOZ_ASSERT(aFromPos < N); + size_t wordIndex = aFromPos / kBitsPerWord; + size_t bitIndex = aFromPos % kBitsPerWord; + + Word word = mStorage[wordIndex]; + // Mask word containing |aFromPos|. + word &= (Word(-1) << bitIndex); + while (word == 0) { + wordIndex++; + if (wordIndex == kNumWords) { + return SIZE_MAX; + } + word = mStorage[wordIndex]; + } + + uint_fast8_t pos = CountTrailingZeroes(word); + return wordIndex * kBitsPerWord + pos; + } + + size_t FindLast() const { return FindPrev(size() - 1); } + + // Return the position of the previous bit set starting from |aFromPos| + // inclusive, or SIZE_MAX if none. + size_t FindPrev(size_t aFromPos) const { + MOZ_ASSERT(aFromPos < N); + size_t wordIndex = aFromPos / kBitsPerWord; + size_t bitIndex = aFromPos % kBitsPerWord; + + Word word = mStorage[wordIndex]; + // Mask word containing |aFromPos|. + word &= Word(-1) >> (kBitsPerWord - 1 - bitIndex); + while (word == 0) { + if (wordIndex == 0) { + return SIZE_MAX; + } + wordIndex--; + word = mStorage[wordIndex]; + } + + uint_fast8_t pos = FindMostSignificantBit(word); + return wordIndex * kBitsPerWord + pos; + } + + Span Storage() { return mStorage; } + + Span Storage() const { return mStorage; } }; } // namespace mozilla diff --git a/src/third_party/mozjs/include/mozilla/Buffer.h b/src/third_party/mozjs/include/mozilla/Buffer.h index c4e0a4be92e..12156e58e07 100644 --- a/src/third_party/mozjs/include/mozilla/Buffer.h +++ b/src/third_party/mozjs/include/mozilla/Buffer.h @@ -39,7 +39,7 @@ class Buffer final { * Construct zero-lenth Buffer (without actually pointing to a heap * allocation). */ - Buffer() : mData(nullptr), mLength(0){}; + Buffer() : mData(nullptr), mLength(0) {}; /** * Construct from raw parts. diff --git a/src/third_party/mozjs/include/mozilla/Casting.h b/src/third_party/mozjs/include/mozilla/Casting.h index 6247d6e9865..82d358c27a6 100644 --- a/src/third_party/mozjs/include/mozilla/Casting.h +++ b/src/third_party/mozjs/include/mozilla/Casting.h @@ -10,7 +10,11 @@ #define mozilla_Casting_h #include "mozilla/Assertions.h" +#include "mozilla/Sprintf.h" +#include "fmt/format.h" + +#include #include #include #include @@ -78,6 +82,70 @@ constexpr uint64_t safe_integer_unsigned() { return std::pow(2, std::numeric_limits::digits); } +template +const char* TypeToStringFallback(); + +template +inline constexpr const char* TypeToString() { + return TypeToStringFallback(); +} + +#define T2S(type) \ + template <> \ + inline constexpr const char* TypeToString() { \ + return #type; \ + } + +#define T2SF(type) \ + template <> \ + inline constexpr const char* TypeToStringFallback() { \ + return #type; \ + } + +T2S(uint8_t); +T2S(uint16_t); +T2S(uint32_t); +T2S(uint64_t); +T2S(int8_t); +T2S(int16_t); +T2S(int32_t); +T2S(int64_t); +T2S(char16_t); +T2S(char32_t); +T2SF(int); +T2SF(unsigned int); +T2SF(long); +T2SF(unsigned long); +T2S(float); +T2S(double); + +#undef T2S +#undef T2SF + +template +inline void DiagnosticMessage(In aIn, char aDiagnostic[1024]) { + if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) { + static_assert(sizeof(wchar_t) <= sizeof(int32_t)); + // Characters types are printed in hexadecimal for two reasons: + // - to easily debug problems with non-printable characters. + // - {fmt} refuses to format a string with mixed character type. + // It's always possible to cast them to int64_t for lossless printing of the + // value. + auto [out, size] = fmt::format_to_n( + aDiagnostic, 1023, + FMT_STRING("Cannot cast {:x} from {} to {}: out of range"), + static_cast(aIn), TypeToString(), TypeToString()); + *out = 0; + } else { + auto [out, size] = fmt::format_to_n( + aDiagnostic, 1023, + FMT_STRING("Cannot cast {} from {} to {}: out of range"), aIn, + TypeToString(), TypeToString()); + *out = 0; + } +} + // This is working around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81676, // fixed in gcc-10 // MONGODB MODIFICATION: Only enable for GCC. @@ -186,7 +254,14 @@ bool IsInBounds(In aIn) { template inline To AssertedCast(const From aFrom) { static_assert(std::is_arithmetic_v && std::is_arithmetic_v); - MOZ_ASSERT((detail::IsInBounds(aFrom))); +#ifdef DEBUG + if (!detail::IsInBounds(aFrom)) { + char buf[1024]; + detail::DiagnosticMessage(aFrom, buf); + fprintf(stderr, "AssertedCast error: %s\n", buf); + MOZ_CRASH(); + } +#endif return static_cast(aFrom); } @@ -204,6 +279,60 @@ inline To ReleaseAssertedCast(const From aFrom) { return static_cast(aFrom); } +/** + * Cast from type From to type To, clamping to minimum and maximum value of the + * destination type if needed. + */ +template +inline To SaturatingCast(const From aFrom) { + static_assert(std::is_arithmetic_v && std::is_arithmetic_v); + // This implementation works up to 64-bits integers. + static_assert(sizeof(From) <= 8 && sizeof(To) <= 8); + constexpr bool fromFloat = std::is_floating_point_v; + constexpr bool toFloat = std::is_floating_point_v; + + // It's not clear what the caller wants here, it could be round, truncate, + // closest value, etc. + static_assert((fromFloat && !toFloat) || (!fromFloat && !toFloat), + "Handle manually depending on desired behaviour"); + + // If the source is floating point and the destination isn't, it can be that + // casting changes the value unexpectedly. Casting to double and clamping to + // the max of the destination type is correct, this also handles infinity. + if constexpr (fromFloat) { + if (aFrom > static_cast(std::numeric_limits::max())) { + return std::numeric_limits::max(); + } + if (aFrom < static_cast(std::numeric_limits::lowest())) { + return std::numeric_limits::lowest(); + } + return static_cast(aFrom); + } + // Source and destination are of opposite signedness + if constexpr (std::is_signed_v != std::is_signed_v) { + // Input is negative, output is unsigned, return 0 + if (std::is_signed_v && aFrom < 0) { + return 0; + } + // At this point the input is positive, cast everything to uint64_t for + // simplicity and compare + uint64_t inflated = AssertedCast(aFrom); + if (inflated > static_cast(std::numeric_limits::max())) { + return std::numeric_limits::max(); + } + return static_cast(aFrom); + } else { + // Regular case: clamp to destination type range + if (aFrom > std::numeric_limits::max()) { + return std::numeric_limits::max(); + } + if (aFrom < std::numeric_limits::lowest()) { + return std::numeric_limits::lowest(); + } + return static_cast(aFrom); + } +} + namespace detail { template diff --git a/src/third_party/mozjs/include/mozilla/ChaosMode.h b/src/third_party/mozjs/include/mozilla/ChaosMode.h index faf7acddf39..722a665d9a5 100644 --- a/src/third_party/mozjs/include/mozilla/ChaosMode.h +++ b/src/third_party/mozjs/include/mozilla/ChaosMode.h @@ -15,7 +15,7 @@ namespace mozilla { -enum ChaosFeature { +enum class ChaosFeature : uint32_t { None = 0x0, // Altering thread scheduling. ThreadScheduling = 0x1, @@ -37,7 +37,7 @@ enum ChaosFeature { }; namespace detail { -extern MFBT_DATA Atomic gChaosModeCounter; +extern MFBT_DATA Atomic gChaosModeCounter; extern MFBT_DATA ChaosFeature gChaosFeatures; } // namespace detail @@ -53,17 +53,14 @@ class ChaosMode { } static bool isActive(ChaosFeature aFeature) { - if (detail::gChaosModeCounter > 0) { - return true; - } - return detail::gChaosFeatures & aFeature; + return detail::gChaosModeCounter > 0 && + (uint32_t(detail::gChaosFeatures) & uint32_t(aFeature)); } /** * Increase the chaos mode activation level. An equivalent number of * calls to leaveChaosMode must be made in order to restore the original - * chaos mode state. If the activation level is nonzero all chaos mode - * features are activated. + * chaos mode state. */ static void enterChaosMode() { detail::gChaosModeCounter++; } @@ -83,6 +80,15 @@ class ChaosMode { MOZ_ASSERT(aBound != 0); return uint32_t(rand()) % aBound; } + + /** + * Returns a somewhat (but not uniformly) random int32_t <= aLow and >= aHigh. + * Not to be used for anything except ChaosMode, since it's not very random. + */ + static int32_t randomInt32InRange(int32_t aLow, int32_t aHigh) { + MOZ_ASSERT(aHigh >= aLow); + return (int32_t(rand()) % (aHigh - aLow + 1)) + aLow; + } }; } /* namespace mozilla */ diff --git a/src/third_party/mozjs/include/mozilla/Compression.h b/src/third_party/mozjs/include/mozilla/Compression.h index d9f787c0b46..60b783afa1d 100644 --- a/src/third_party/mozjs/include/mozilla/Compression.h +++ b/src/third_party/mozjs/include/mozilla/Compression.h @@ -42,8 +42,7 @@ class LZ4 { * @param aInputSize is the input size. Max supported value is ~1.9GB * @return the number of bytes written in buffer |aDest| */ - static MFBT_API size_t compress(const char* aSource, size_t aInputSize, - char* aDest); + static size_t compress(const char* aSource, size_t aInputSize, char* aDest); /** * Compress |aInputSize| bytes from |aSource| into an output buffer @@ -60,9 +59,8 @@ class LZ4 { * @return the number of bytes written in buffer |aDest| or 0 if the * compression fails */ - static MFBT_API size_t compressLimitedOutput(const char* aSource, - size_t aInputSize, char* aDest, - size_t aMaxOutputSize); + static size_t compressLimitedOutput(const char* aSource, size_t aInputSize, + char* aDest, size_t aMaxOutputSize); /** * If the source stream is malformed, the function will stop decoding @@ -81,10 +79,9 @@ class LZ4 { * buffer (necessarily <= aMaxOutputSize) * @return true on success, false on failure */ - [[nodiscard]] static MFBT_API bool decompress(const char* aSource, - size_t aInputSize, char* aDest, - size_t aMaxOutputSize, - size_t* aOutputSize); + [[nodiscard]] static bool decompress(const char* aSource, size_t aInputSize, + char* aDest, size_t aMaxOutputSize, + size_t* aOutputSize); /** * If the source stream is malformed, the function will stop decoding @@ -105,11 +102,10 @@ class LZ4 { * buffer (necessarily <= aMaxOutputSize) * @return true on success, false on failure */ - [[nodiscard]] static MFBT_API bool decompressPartial(const char* aSource, - size_t aInputSize, - char* aDest, - size_t aMaxOutputSize, - size_t* aOutputSize); + [[nodiscard]] static bool decompressPartial(const char* aSource, + size_t aInputSize, char* aDest, + size_t aMaxOutputSize, + size_t* aOutputSize); /* * Provides the maximum size that LZ4 may output in a "worst case" @@ -134,10 +130,10 @@ class LZ4 { */ class LZ4FrameCompressionContext final { public: - MFBT_API LZ4FrameCompressionContext(int aCompressionLevel, size_t aMaxSrcSize, - bool aChecksum, bool aStableSrc = false); + LZ4FrameCompressionContext(int aCompressionLevel, size_t aMaxSrcSize, + bool aChecksum, bool aStableSrc = false); - MFBT_API ~LZ4FrameCompressionContext(); + ~LZ4FrameCompressionContext(); size_t GetRequiredWriteBufferLength() { return mWriteBufLen; } @@ -147,8 +143,7 @@ class LZ4FrameCompressionContext final { * @return a Result with a Span containing the frame header, or an lz4 error * code (size_t). */ - MFBT_API Result, size_t> BeginCompressing( - Span aWriteBuffer); + Result, size_t> BeginCompressing(Span aWriteBuffer); /** * Continue streaming frame-based compression with the provided input. @@ -157,8 +152,7 @@ class LZ4FrameCompressionContext final { * @return a Result with a Span containing compressed output, or an lz4 error * code (size_t). */ - MFBT_API Result, size_t> ContinueCompressing( - Span aInput); + Result, size_t> ContinueCompressing(Span aInput); /** * Finalize streaming frame-based compression with the provided input. @@ -166,7 +160,7 @@ class LZ4FrameCompressionContext final { * @return a Result with a Span containing compressed output and the frame * footer, or an lz4 error code (size_t). */ - MFBT_API Result, size_t> EndCompressing(); + Result, size_t> EndCompressing(); private: LZ4F_cctx_s* mContext; @@ -191,8 +185,8 @@ struct LZ4FrameDecompressionResult { */ class LZ4FrameDecompressionContext final { public: - explicit MFBT_API LZ4FrameDecompressionContext(bool aStableDest = false); - MFBT_API ~LZ4FrameDecompressionContext(); + explicit LZ4FrameDecompressionContext(bool aStableDest = false); + ~LZ4FrameDecompressionContext(); /** * Decompress a buffer/part of a buffer compressed with @@ -204,7 +198,7 @@ class LZ4FrameDecompressionContext final { * completely decompressed the input into the output, or an lz4 error code * (size_t). */ - MFBT_API Result Decompress( + Result Decompress( Span aOutput, Span aInput); private: diff --git a/src/third_party/mozjs/include/mozilla/DefineEnum.h b/src/third_party/mozjs/include/mozilla/DefineEnum.h index afcff10e521..e5a6aaeaf20 100644 --- a/src/third_party/mozjs/include/mozilla/DefineEnum.h +++ b/src/third_party/mozjs/include/mozilla/DefineEnum.h @@ -10,6 +10,7 @@ #define mozilla_DefineEnum_h #include // for size_t +#include // for std::ostream #include "mozilla/MacroArgs.h" // for MOZ_ARG_COUNT #include "mozilla/MacroForEach.h" // for MOZ_FOR_EACH @@ -84,6 +85,14 @@ * and have names prefixed with "s" instead of "k" as per * naming convention. * + * - A |_TOSTRING| variant, which generates an EnumValueToString function, + * converting the enum items to strings, and implements an "operator<<", + * providing a consistent way to convert enums to strings by + * mozilla::ToString function regardless of their definition context. + * For users needing C-string compatibility for logging in restricted + * contexts or performance sensitive applications, EnumValueToString is + * preferred. + * * (and combinations of these). */ @@ -150,7 +159,61 @@ #define MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AT_CLASS_SCOPE(aEnumName, aBaseName, \ aEnumerators) \ - MOZ_DEFINE_ENUM_AT_CLASS_SCOPE_IMPL(aEnumName, class, \ - : aBaseName, aEnumerators) + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE_IMPL(aEnumName, class, : aBaseName, \ + aEnumerators) + +#define MOZ_DEFINE_ENUM_TO_ENUM_TEXT(aEnumeratorDecl) #aEnumeratorDecl + +#define MOZ_DEFINE_ENUM_TOSTRING_FUNC_IMPL(aEnumName, aEnumerators, aFriend) \ + inline static const char* EnumValueToString(const aEnumName& aEnum) { \ + static constexpr const char* kMappedStrings[] = {MOZ_FOR_EACH_SEPARATED( \ + MOZ_DEFINE_ENUM_TO_ENUM_TEXT, (, ), (), aEnumerators)}; \ + return kMappedStrings[static_cast(aEnum)]; \ + } \ + aFriend inline std::ostream& operator<<(std::ostream& aStream, \ + const aEnumName& aEnum) { \ + aStream << EnumValueToString(aEnum); \ + return aStream; \ + } + +#define MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IMPL(aEnumName, aEnumerators, ) + +#define MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IMPL(aEnumName, aEnumerators, friend) + +#define MOZ_DEFINE_ENUM_WITH_BASE_AND_TOSTRING(aEnumName, aBaseName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_WITH_BASE(aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(aEnumName, aBaseName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS_WITH_BASE(aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_WITH_TOSTRING_AT_CLASS_SCOPE(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_WITH_BASE_AND_TOSTRING_AT_CLASS_SCOPE( \ + aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(aEnumName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS_AT_CLASS_SCOPE(aEnumName, aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) + +#define MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING_AT_CLASS_SCOPE( \ + aEnumName, aBaseName, aEnumerators) \ + MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AT_CLASS_SCOPE(aEnumName, aBaseName, \ + aEnumerators) \ + MOZ_DEFINE_ENUM_TOSTRING_FUNC_IN_CLASS(aEnumName, aEnumerators) #endif // mozilla_DefineEnum_h diff --git a/src/third_party/mozjs/include/mozilla/DoublyLinkedList.h b/src/third_party/mozjs/include/mozilla/DoublyLinkedList.h index df178440d2d..ed7b8e66ccc 100644 --- a/src/third_party/mozjs/include/mozilla/DoublyLinkedList.h +++ b/src/third_party/mozjs/include/mozilla/DoublyLinkedList.h @@ -368,6 +368,38 @@ class DoublyLinkedList final { } return !ElementNotInList(aElm); } + + /** + * Returns whether an element is linked correctly to its predecessor and/or + * successor, if any. Used for internal sanity checks. + */ + bool ElementIsLinkedWell(T* aElm) { + MOZ_ASSERT(aElm); + if (!ElementProbablyInList(aElm)) { + return false; + } + T* next = ElementAccess::Get(aElm).mNext; + if (next) { + if (ElementAccess::Get(next).mPrev != aElm) { + return false; + } + } else { + if (aElm != mTail) { + return false; + } + } + T* prev = ElementAccess::Get(aElm).mPrev; + if (prev) { + if (ElementAccess::Get(prev).mNext != aElm) { + return false; + } + } else { + if (aElm != mHead) { + return false; + } + } + return true; + } }; /** diff --git a/src/third_party/mozjs/include/mozilla/EnumSet.h b/src/third_party/mozjs/include/mozilla/EnumSet.h index 712e03d3f3d..c9bc82d1da7 100644 --- a/src/third_party/mozjs/include/mozilla/EnumSet.h +++ b/src/third_party/mozjs/include/mozilla/EnumSet.h @@ -52,6 +52,8 @@ class EnumSet { } } + constexpr explicit EnumSet(Serialized aValue) : mBitField(aValue) {} + #ifdef DEBUG constexpr EnumSet(const EnumSet& aEnumSet) : mBitField(aEnumSet.mBitField) {} @@ -82,7 +84,7 @@ class EnumSet { /** * Union */ - void operator+=(const EnumSet& aEnumSet) { + constexpr void operator+=(const EnumSet& aEnumSet) { IncVersion(); mBitField |= aEnumSet.mBitField; } @@ -90,7 +92,7 @@ class EnumSet { /** * Union */ - EnumSet operator+(const EnumSet& aEnumSet) const { + constexpr EnumSet operator+(const EnumSet& aEnumSet) const { EnumSet result(*this); result += aEnumSet; return result; @@ -99,7 +101,7 @@ class EnumSet { /** * Remove an element */ - void operator-=(T aEnum) { + constexpr void operator-=(T aEnum) { IncVersion(); mBitField &= ~(BitFor(aEnum)); } @@ -107,7 +109,7 @@ class EnumSet { /** * Remove an element */ - EnumSet operator-(T aEnum) const { + constexpr EnumSet operator-(T aEnum) const { EnumSet result(*this); result -= aEnum; return result; @@ -116,7 +118,7 @@ class EnumSet { /** * Remove a set of elements */ - void operator-=(const EnumSet& aEnumSet) { + constexpr void operator-=(const EnumSet& aEnumSet) { IncVersion(); mBitField &= ~(aEnumSet.mBitField); } @@ -124,7 +126,7 @@ class EnumSet { /** * Remove a set of elements */ - EnumSet operator-(const EnumSet& aEnumSet) const { + constexpr EnumSet operator-(const EnumSet& aEnumSet) const { EnumSet result(*this); result -= aEnumSet; return result; @@ -133,7 +135,7 @@ class EnumSet { /** * Clear */ - void clear() { + constexpr void clear() { IncVersion(); mBitField = Serialized(); } @@ -141,7 +143,7 @@ class EnumSet { /** * Intersection */ - void operator&=(const EnumSet& aEnumSet) { + constexpr void operator&=(const EnumSet& aEnumSet) { IncVersion(); mBitField &= aEnumSet.mBitField; } @@ -149,7 +151,7 @@ class EnumSet { /** * Intersection */ - EnumSet operator&(const EnumSet& aEnumSet) const { + constexpr EnumSet operator&(const EnumSet& aEnumSet) const { EnumSet result(*this); result &= aEnumSet; return result; @@ -158,36 +160,38 @@ class EnumSet { /** * Equality */ - bool operator==(const EnumSet& aEnumSet) const { + constexpr bool operator==(const EnumSet& aEnumSet) const { return mBitField == aEnumSet.mBitField; } /** * Equality */ - bool operator==(T aEnum) const { return mBitField == BitFor(aEnum); } + constexpr bool operator==(T aEnum) const { + return mBitField == BitFor(aEnum); + } /** * Not equal */ - bool operator!=(const EnumSet& aEnumSet) const { + constexpr bool operator!=(const EnumSet& aEnumSet) const { return !operator==(aEnumSet); } /** * Not equal */ - bool operator!=(T aEnum) const { return !operator==(aEnum); } + constexpr bool operator!=(T aEnum) const { return !operator==(aEnum); } /** * Test is an element is contained in the set. */ - bool contains(T aEnum) const { return HasBitFor(aEnum); } + constexpr bool contains(T aEnum) const { return HasBitFor(aEnum); } /** * Test if a set is contained in the set. */ - bool contains(const EnumSet& aEnumSet) const { + constexpr bool contains(const EnumSet& aEnumSet) const { return (mBitField & aEnumSet.mBitField) == aEnumSet.mBitField; } @@ -206,7 +210,7 @@ class EnumSet { } } - bool isEmpty() const { + constexpr bool isEmpty() const { if constexpr (std::is_unsigned_v) { return mBitField == 0; } else { @@ -319,7 +323,12 @@ class EnumSet { } constexpr bool HasBitAt(size_t aPos) const { - return static_cast(mBitField & BitAt(aPos)); + if constexpr (std::is_unsigned_v) { + return mBitField & BitAt(aPos); + } else { + // for std::bitset and mozilla::BitSet + return mBitField.test(aPos); + } } constexpr void IncVersion() { @@ -332,7 +341,7 @@ class EnumSet { if constexpr (std::is_unsigned_v) { return sizeof(Serialized) * 8; } else { - return Serialized::Size(); + return Serialized().size(); } } diff --git a/src/third_party/mozjs/include/mozilla/EnumTypeTraits.h b/src/third_party/mozjs/include/mozilla/EnumTypeTraits.h index 09ead3d0e96..84ad19c607b 100644 --- a/src/third_party/mozjs/include/mozilla/EnumTypeTraits.h +++ b/src/third_party/mozjs/include/mozilla/EnumTypeTraits.h @@ -63,6 +63,7 @@ struct EnumTypeFitsWithin /** * Get the underlying value of an enum, but typesafe. + * TODO: Replace with std::to_underlying when available. * * example: * diff --git a/src/third_party/mozjs/include/mozilla/EnumeratedArray.h b/src/third_party/mozjs/include/mozilla/EnumeratedArray.h index c1e7eeccddd..cb9b326d7f0 100644 --- a/src/third_party/mozjs/include/mozilla/EnumeratedArray.h +++ b/src/third_party/mozjs/include/mozilla/EnumeratedArray.h @@ -61,9 +61,11 @@ class EnumeratedArray { MOZ_IMPLICIT constexpr EnumeratedArray(Args&&... aArgs) : mArray{std::forward(aArgs)...} {} - ValueType& operator[](Enum aIndex) { return mArray[size_t(aIndex)]; } + constexpr ValueType& operator[](Enum aIndex) { + return mArray[size_t(aIndex)]; + } - const ValueType& operator[](Enum aIndex) const { + constexpr const ValueType& operator[](Enum aIndex) const { return mArray[size_t(aIndex)]; } @@ -80,6 +82,9 @@ class EnumeratedArray { const_iterator end() const { return mArray.end(); } const_iterator cend() const { return mArray.cend(); } + // Method for std::size. + constexpr size_t size() const { return mArray.size(); } + // Methods for reverse iterating. reverse_iterator rbegin() { return mArray.rbegin(); } const_reverse_iterator rbegin() const { return mArray.rbegin(); } diff --git a/src/third_party/mozjs/include/mozilla/FailureLatch.h b/src/third_party/mozjs/include/mozilla/FailureLatch.h new file mode 100644 index 00000000000..10205e009bd --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/FailureLatch.h @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This header contains an interface `FailureLatch`, and some implementation +// helpers that may be used across a range of classes and functions to handle +// failures at any point during a process, and share that failure state so that +// the process may gracefully stop quickly and report the first error. +// +// It could be thought as a replacement for C++ exceptions, but it's less strong +// (cancellations may be delayed). +// Now, if possible, mozilla::Result may be a better option as C++ exceptions +// replacement, as it is more visible in all affected functions. +// Consider FailureLatch if failures may happen in different places, but where +// `return`ing this potential failure from all functions would be too arduous. + +#ifndef mozilla_FailureLatch_h +#define mozilla_FailureLatch_h + +#include + +#include + +namespace mozilla { + +// ---------------------------------------------------------------------------- +// Main interface +// ---------------------------------------------------------------------------- + +// Interface handling a failure latch (starting in a successful state, the first +// failure gets recorded, subsequent failures are ignored.) +class FailureLatch { + public: + virtual ~FailureLatch() = default; + + // Can this ever fail? (This may influence how some code deals with + // failures, e.g., if infallible, OOMs should assert&crash.) + [[nodiscard]] virtual bool Fallible() const = 0; + + // Set latch in its failed state because of an external cause. + // The first call sets the reason, subsequent calls are ignored. + virtual void SetFailure(std::string aReason) = 0; + + // Has there been any failure so far? + [[nodiscard]] virtual bool Failed() const = 0; + + // Return first failure string, may be null if not failed yet. + [[nodiscard]] virtual const char* GetFailure() const = 0; + + // Retrieve the one source FailureLatch. It could reference `*this`! + // This may be used by dependent proxy FailureLatch'es to find where to + // redirect calls. + [[nodiscard]] virtual const FailureLatch& SourceFailureLatch() const = 0; + [[nodiscard]] virtual FailureLatch& SourceFailureLatch() = 0; + + // Non-virtual helpers. + + // Transfer any failure from another FailureLatch. + void SetFailureFrom(const FailureLatch& aOther) { + if (Failed()) { + return; + } + if (const char* otherFailure = aOther.GetFailure(); otherFailure) { + SetFailure(otherFailure); + } + } +}; + +// ---------------------------------------------------------------------------- +// Concrete implementations +// ---------------------------------------------------------------------------- + +// Concrete infallible FailureLatch class. +// Any `SetFailure` leads to an assert-crash, so the final runtime result can +// always be assumed to be succesful. +class FailureLatchInfallibleSource final : public FailureLatch { + public: + [[nodiscard]] bool Fallible() const final { return false; } + + void SetFailure(std::string aReason) final { + MOZ_RELEASE_ASSERT(false, + "SetFailure in infallible FailureLatchInfallibleSource"); + } + + [[nodiscard]] bool Failed() const final { return false; } + + [[nodiscard]] const char* GetFailure() const final { return nullptr; } + + [[nodiscard]] const ::mozilla::FailureLatch& SourceFailureLatch() + const final { + return *this; + } + + [[nodiscard]] ::mozilla::FailureLatch& SourceFailureLatch() final { + return *this; + } + + // Singleton FailureLatchInfallibleSource that may be used as default + // FailureLatch proxy. + static FailureLatchInfallibleSource& Singleton() { + static FailureLatchInfallibleSource singleton; + return singleton; + } +}; + +// Concrete FailureLatch class, intended to be intantiated as an object shared +// between classes and functions that are part of a long operation, so that +// failures can happen anywhere and be visible everywhere. +// Not thread-safe. +class FailureLatchSource final : public FailureLatch { + public: + [[nodiscard]] bool Fallible() const final { return true; } + + void SetFailure(std::string aReason) final { + if (!mFailed) { + mFailed = true; + mReason = std::move(aReason); + } + } + + [[nodiscard]] bool Failed() const final { return mFailed; } + + [[nodiscard]] const char* GetFailure() const final { + return mFailed ? mReason.c_str() : nullptr; + } + + [[nodiscard]] const FailureLatch& SourceFailureLatch() const final { + return *this; + } + + [[nodiscard]] FailureLatch& SourceFailureLatch() final { return *this; } + + private: + bool mFailed = false; + std::string mReason; +}; + +// ---------------------------------------------------------------------------- +// Helper macros, to be used in FailureLatch-derived classes +// ---------------------------------------------------------------------------- + +// Classes deriving from FailureLatch can use this to forward virtual calls to +// another FailureLatch. +#define FAILURELATCH_IMPL_PROXY(FAILURELATCH_REF) \ + [[nodiscard]] bool Fallible() const final { \ + return static_cast(FAILURELATCH_REF) \ + .Fallible(); \ + } \ + void SetFailure(std::string aReason) final { \ + static_cast<::mozilla::FailureLatch&>(FAILURELATCH_REF) \ + .SetFailure(std::move(aReason)); \ + } \ + [[nodiscard]] bool Failed() const final { \ + return static_cast(FAILURELATCH_REF) \ + .Failed(); \ + } \ + [[nodiscard]] const char* GetFailure() const final { \ + return static_cast(FAILURELATCH_REF) \ + .GetFailure(); \ + } \ + [[nodiscard]] const FailureLatch& SourceFailureLatch() const final { \ + return static_cast(FAILURELATCH_REF) \ + .SourceFailureLatch(); \ + } \ + [[nodiscard]] FailureLatch& SourceFailureLatch() final { \ + return static_cast<::mozilla::FailureLatch&>(FAILURELATCH_REF) \ + .SourceFailureLatch(); \ + } + +// Classes deriving from FailureLatch can use this to forward virtual calls to +// another FailureLatch through a pointer, unless it's null in which case act +// like an infallible FailureLatch. +#define FAILURELATCH_IMPL_PROXY_OR_INFALLIBLE(FAILURELATCH_PTR, CLASS_NAME) \ + [[nodiscard]] bool Fallible() const final { \ + return FAILURELATCH_PTR \ + ? static_cast(FAILURELATCH_PTR) \ + ->Fallible() \ + : false; \ + } \ + void SetFailure(std::string aReason) final { \ + if (FAILURELATCH_PTR) { \ + static_cast<::mozilla::FailureLatch*>(FAILURELATCH_PTR) \ + ->SetFailure(std::move(aReason)); \ + } else { \ + MOZ_RELEASE_ASSERT(false, "SetFailure in infallible " #CLASS_NAME); \ + } \ + } \ + [[nodiscard]] bool Failed() const final { \ + return FAILURELATCH_PTR \ + ? static_cast(FAILURELATCH_PTR) \ + ->Failed() \ + : false; \ + } \ + [[nodiscard]] const char* GetFailure() const final { \ + return FAILURELATCH_PTR \ + ? static_cast(FAILURELATCH_PTR) \ + ->GetFailure() \ + : nullptr; \ + } \ + [[nodiscard]] const FailureLatch& SourceFailureLatch() const final { \ + return FAILURELATCH_PTR \ + ? static_cast(FAILURELATCH_PTR) \ + ->SourceFailureLatch() \ + : ::mozilla::FailureLatchInfallibleSource::Singleton(); \ + } \ + [[nodiscard]] FailureLatch& SourceFailureLatch() final { \ + return FAILURELATCH_PTR \ + ? static_cast<::mozilla::FailureLatch*>(FAILURELATCH_PTR) \ + ->SourceFailureLatch() \ + : ::mozilla::FailureLatchInfallibleSource::Singleton(); \ + } + +} // namespace mozilla + +#endif /* mozilla_FailureLatch_h */ diff --git a/src/third_party/mozjs/include/mozilla/FloatingPoint.h b/src/third_party/mozjs/include/mozilla/FloatingPoint.h index f4ae36257bb..ad9362152ae 100644 --- a/src/third_party/mozjs/include/mozilla/FloatingPoint.h +++ b/src/third_party/mozjs/include/mozilla/FloatingPoint.h @@ -151,7 +151,7 @@ struct FloatingPoint final : private detail::FloatingPointTrait { static_assert((kExponentBits & kSignificandBits) == 0, "exponent bits shouldn't overlap significand bits"); - static_assert((kSignBit | kExponentBits | kSignificandBits) == ~Bits(0), + static_assert((kSignBit | kExponentBits | kSignificandBits) == Bits(~0), "all bits accounted for"); }; @@ -216,24 +216,14 @@ static MOZ_ALWAYS_INLINE int_fast16_t ExponentComponent(T aValue) { /** Returns +Infinity. */ template -static MOZ_ALWAYS_INLINE T PositiveInfinity() { - /* - * Positive infinity has all exponent bits set, sign bit set to 0, and no - * significand. - */ - typedef FloatingPoint Traits; - return BitwiseCast(Traits::kExponentBits); +static constexpr MOZ_ALWAYS_INLINE T PositiveInfinity() { + return std::numeric_limits::infinity(); } /** Returns -Infinity. */ template -static MOZ_ALWAYS_INLINE T NegativeInfinity() { - /* - * Negative infinity has all exponent bits set, sign bit set to 1, and no - * significand. - */ - typedef FloatingPoint Traits; - return BitwiseCast(Traits::kSignBit | Traits::kExponentBits); +static constexpr MOZ_ALWAYS_INLINE T NegativeInfinity() { + return -std::numeric_limits::infinity(); } /** @@ -306,10 +296,14 @@ SpecificNaN(int signbit, typename FloatingPoint::Bits significand) { /** Computes the smallest non-zero positive float/double value. */ template -static MOZ_ALWAYS_INLINE T MinNumberValue() { - typedef FloatingPoint Traits; - typedef typename Traits::Bits Bits; - return BitwiseCast(Bits(1)); +static constexpr MOZ_ALWAYS_INLINE T MinNumberValue() { + return std::numeric_limits::denorm_min(); +} + +/** Computes the largest positive float/double value. */ +template +static constexpr MOZ_ALWAYS_INLINE T MaxNumberValue() { + return std::numeric_limits::max(); } namespace detail { diff --git a/src/third_party/mozjs/include/mozilla/Flow.h b/src/third_party/mozjs/include/mozilla/Flow.h new file mode 100644 index 00000000000..a30cd5c151f --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/Flow.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Flow_h +#define Flow_h + +// We use a Flow for connecting markers over time. It's a +// global (cross-process) 64bit id that will connect any markers that have the +// same id until we see a terminating-flow with that id. +// +// With these semanatics we can derive a flow from a pointer by xoring it with +// gProcessUUID and using a terminating-flow when we're done with +// that pointer e.g. destructor. This doesn't ensure that the flow is globally +// unique but makes colluisions unlikely enough that it mostly works. + +// The following code for Flow is derived from Perfetto + +#include +#include "mozilla/ProfileBufferEntrySerialization.h" + +extern uint64_t MFBT_DATA gProcessUUID; + +// This class is used as a marker field type and is used in the marker schema. +// To create a Flow, use Flow::FromPointer, Flow::ProcessScoped or Flow::Global. +class Flow { + public: + // |aFlow| which is local within a given process (e.g. atomic counter xor'ed + // with feature-specific value). This value is xor'ed with processUUID + // to attempt to ensure that it's globally-unique. + static inline Flow ProcessScoped(uint64_t aFlowId) { + return Global(aFlowId ^ gProcessUUID); + } + + // Same as above, but construct an id from a pointer. + // NOTE: After the object is destroyed, the value of |aPtr| can be reused for + // a different object (in particular if the object is allocated on a stack) + // but it needs to be emitted as terminating flow first. + static inline Flow FromPointer(void* aPtr) { + return ProcessScoped(reinterpret_cast(aPtr)); + } + + // The caller is responsible for ensuring that it's + // globally-unique (e.g. by generating a random value). This should be used + // only for flow events which cross the process boundary (e.g. IPCs). + static inline Flow Global(uint64_t aFlowId) { return Flow(aFlowId); } + + uint64_t Id() const { return mFlowId; } + + static MFBT_API void Init(); + + private: + explicit Flow(uint64_t aFlowId) : mFlowId(aFlowId) {} + const uint64_t mFlowId; +}; + +template <> +struct mozilla::ProfileBufferEntryWriter::Serializer { + static constexpr Length Bytes(const Flow& aFlow) { return sizeof(Flow); } + + static void Write(ProfileBufferEntryWriter& aEW, const Flow& aFlow) { + aEW.WriteBytes(&aFlow, sizeof(Flow)); + } +}; + +template <> +struct mozilla::ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, uint64_t& aFlow) { + aER.ReadBytes(&aFlow, sizeof(Flow)); + } + + static Flow Read(ProfileBufferEntryReader& aER) { + uint64_t flow; + ReadInto(aER, flow); + return Flow::Global(flow); + } +}; + +#endif // Flow_h diff --git a/src/third_party/mozjs/include/mozilla/HashTable.h b/src/third_party/mozjs/include/mozilla/HashTable.h index 9f3f42b40ec..6ef91045177 100644 --- a/src/third_party/mozjs/include/mozilla/HashTable.h +++ b/src/third_party/mozjs/include/mozilla/HashTable.h @@ -180,6 +180,9 @@ class HashMap { HashMap(HashMap&& aRhs) = default; HashMap& operator=(HashMap&& aRhs) = default; + // Swap the contents of this hash map with another. + void swap(HashMap& aOther) { mImpl.swap(aOther.mImpl); } + // -- Status and sizing ---------------------------------------------------- // The map's current generation. @@ -477,6 +480,9 @@ class HashSet { HashSet(HashSet&& aRhs) = default; HashSet& operator=(HashSet&& aRhs) = default; + // Swap the contents of this hash set with another. + void swap(HashSet& aOther) { mImpl.swap(aOther.mImpl); } + // -- Status and sizing ---------------------------------------------------- // The set's current generation. @@ -1558,6 +1564,29 @@ class HashTable : private AllocPolicy { return *this; } + void swap(HashTable& aOther) { + ReentrancyGuard g1(*this); + ReentrancyGuard g2(aOther); + + // Manual swap of generation because it's a bitfield + uint64_t generation = mGen; + mGen = aOther.mGen; + aOther.mGen = generation; + + // Manual swap of hashShift because it's a bitfield + uint64_t hashShift = mHashShift; + mHashShift = aOther.mHashShift; + aOther.mHashShift = hashShift; + + std::swap(mTable, aOther.mTable); + std::swap(mEntryCount, aOther.mEntryCount); + std::swap(mRemovedCount, aOther.mRemovedCount); +#ifdef DEBUG + std::swap(mMutationCount, aOther.mMutationCount); + std::swap(mEntered, aOther.mEntered); +#endif + } + private: void moveFrom(HashTable& aRhs) { mGen = aRhs.mGen; diff --git a/src/third_party/mozjs/include/mozilla/JSONWriter.h b/src/third_party/mozjs/include/mozilla/JSONWriter.h index f779ee98378..7e37e3ce6ad 100644 --- a/src/third_party/mozjs/include/mozilla/JSONWriter.h +++ b/src/third_party/mozjs/include/mozilla/JSONWriter.h @@ -250,8 +250,8 @@ class JSONWriter { static constexpr Span scTopObjectEndString = MakeStringSpan("}"); static constexpr Span scTrueString = MakeStringSpan("true"); - JSONWriteFunc& mWriter; const UniquePtr mMaybeOwnedWriter; + JSONWriteFunc& mWriter; Vector mNeedComma; // do we need a comma at depth N? Vector mNeedNewlines; // do we need newlines at depth N? size_t mDepth; // the current nesting depth @@ -352,8 +352,8 @@ class JSONWriter { explicit JSONWriter(UniquePtr aWriter, CollectionStyle aStyle = MultiLineStyle) - : mWriter(*aWriter), - mMaybeOwnedWriter(std::move(aWriter)), + : mMaybeOwnedWriter(std::move(aWriter)), + mWriter(*mMaybeOwnedWriter), mNeedComma(), mNeedNewlines(), mDepth(0) { @@ -365,7 +365,7 @@ class JSONWriter { // Returns the JSONWriteFunc passed in at creation, for temporary use. The // JSONWriter object still owns the JSONWriteFunc. - JSONWriteFunc& WriteFunc() const { return mWriter; } + JSONWriteFunc& WriteFunc() const MOZ_LIFETIME_BOUND { return mWriter; } // For all the following functions, the "Prints:" comment indicates what the // basic output looks like. However, it doesn't indicate the whitespace and diff --git a/src/third_party/mozjs/include/mozilla/LinkedList.h b/src/third_party/mozjs/include/mozilla/LinkedList.h index 850b8594c75..15e53e80c1d 100644 --- a/src/third_party/mozjs/include/mozilla/LinkedList.h +++ b/src/third_party/mozjs/include/mozilla/LinkedList.h @@ -409,13 +409,13 @@ class LinkedListElement { template class LinkedList { private: - typedef typename detail::LinkedListElementTraits Traits; - typedef typename Traits::RawType RawType; - typedef typename Traits::ConstRawType ConstRawType; - typedef typename Traits::ClientType ClientType; - typedef typename Traits::ConstClientType ConstClientType; - typedef LinkedListElement* ElementType; - typedef const LinkedListElement* ConstElementType; + using Traits = typename detail::LinkedListElementTraits; + using RawType = typename Traits::RawType; + using ConstRawType = typename Traits::ConstRawType; + using ClientType = typename Traits::ClientType; + using ConstClientType = typename Traits::ConstClientType; + using ElementType = LinkedListElement*; + using ConstElementType = const LinkedListElement*; LinkedListElement sentinel; @@ -445,6 +445,9 @@ class LinkedList { } }; + using const_iterator = Iterator; + using iterator = Iterator; + LinkedList() : sentinel(LinkedListElement::NodeKind::Sentinel) {} LinkedList(LinkedList&& aOther) : sentinel(std::move(aOther.sentinel)) {} @@ -701,6 +704,11 @@ class LinkedList { LinkedList(const LinkedList& aOther) = delete; }; +template +size_t RangeSizeEstimate(const LinkedList&) { + return 0; +} + template inline void ImplCycleCollectionUnlink(LinkedList>& aField) { aField.clear(); diff --git a/src/third_party/mozjs/include/mozilla/Literals.h b/src/third_party/mozjs/include/mozilla/Literals.h new file mode 100644 index 00000000000..97f24af8003 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/Literals.h @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Helpers for units on integer literals. */ + +#ifndef mozilla_Literals_h +#define mozilla_Literals_h + +#include + +// User-defined literals to make constants more legible. Use them by +// appending them to literals such as: +// +// size_t page_size = 4_KiB; +// +constexpr size_t operator""_KiB(unsigned long long int aNum) { + return size_t(aNum) * 1024; +} + +constexpr size_t operator""_KiB(long double aNum) { + return size_t(aNum * 1024); +} + +constexpr size_t operator""_MiB(unsigned long long int aNum) { + return size_t(aNum) * 1024_KiB; +} + +constexpr size_t operator""_MiB(long double aNum) { + return size_t(aNum * 1024_KiB); +} + +constexpr double operator""_percent(long double aPercent) { + return double(aPercent) / 100; +} + +#endif /* ! mozilla_Literals_h */ diff --git a/src/third_party/mozjs/include/mozilla/LoggingCore.h b/src/third_party/mozjs/include/mozilla/LoggingCore.h new file mode 100644 index 00000000000..4cc14f90488 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/LoggingCore.h @@ -0,0 +1,49 @@ +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Shared logging infrastructure across different binaries. + +#ifndef _mozilla_LoggingCore_h +#define _mozilla_LoggingCore_h + +#include "mozilla/Atomics.h" +#include "mozilla/Types.h" + +namespace mozilla { +// While not a 100% mapping to PR_LOG's numeric values, mozilla::LogLevel does +// maintain a direct mapping for the Disabled, Debug and Verbose levels. +// +// Mappings of LogLevel to PR_LOG's numeric values: +// +// +---------+------------------+-----------------+ +// | Numeric | NSPR Logging | Mozilla Logging | +// +---------+------------------+-----------------+ +// | 0 | PR_LOG_NONE | Disabled | +// | 1 | PR_LOG_ALWAYS | Error | +// | 2 | PR_LOG_ERROR | Warning | +// | 3 | PR_LOG_WARNING | Info | +// | 4 | PR_LOG_DEBUG | Debug | +// | 5 | PR_LOG_DEBUG + 1 | Verbose | +// +---------+------------------+-----------------+ +// +enum class LogLevel { + Disabled = 0, + Error, + Warning, + Info, + Debug, + Verbose, +}; + +/** + * Safely converts an integer into a valid LogLevel. + */ +MFBT_API LogLevel ToLogLevel(int32_t aLevel); + +using AtomicLogLevel = Atomic; + +} // namespace mozilla + +#endif /* _mozilla_LoggingCore_h */ diff --git a/src/third_party/mozjs/include/mozilla/MPSCQueue.h b/src/third_party/mozjs/include/mozilla/MPSCQueue.h new file mode 100644 index 00000000000..a413fd63bcc --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/MPSCQueue.h @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Multiple Producer Single Consumer lock-free queue. + * Allocation-free is guaranteed outside of the constructor. + * + * This is a direct C++ port from + * https://docs.rs/signal-hook/0.3.17/src/signal_hook/low_level/channel.rs.html#1-235 + * with the exception we are using atomic uint64t to have 15 slots in the ring + * buffer (Rust implem is 5 slots, we want a bit more). + * */ + +#ifndef mozilla_MPSCQueue_h +#define mozilla_MPSCQueue_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/PodOperations.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mozilla { + +namespace detail { +template ::value> +struct MemoryOperations { + /** + * This allows either moving (if T supports it) or copying a number of + * elements from a `aSource` pointer to a `aDestination` pointer. + * If it is safe to do so and this call copies, this uses PodCopy. Otherwise, + * constructors and destructors are called in a loop. + */ + static void MoveOrCopy(T* aDestination, T* aSource, size_t aCount); +}; + +template +struct MemoryOperations { + static void MoveOrCopy(T* aDestination, T* aSource, size_t aCount) { + PodCopy(aDestination, aSource, aCount); + } +}; + +template +struct MemoryOperations { + static void MoveOrCopy(T* aDestination, T* aSource, size_t aCount) { + std::move(aSource, aSource + aCount, aDestination); + } +}; +} // namespace detail + +static const bool MPSC_DEBUG = false; + +static const size_t kMaxCapacity = 16; + +/** + * This data structure allows producing data from several threads, and consuming + * it on one thread, safely and without performing memory allocations or + * locking. + * + * The role for the producers and the consumer must be constant, i.e., the + * producer should always be on one thread and the consumer should always be on + * another thread. + * + * Some words about the inner workings of this class: + * - Capacity is fixed. Only one allocation is performed, in the constructor. + * - Maximum capacity is 15 elements, with 0 being used to denote an empty set. + * This is a hard limitation from encoding indexes within the atomic uint64_t. + * - This is lock-free but not wait-free, it might spin a little until + * compare/exchange succeeds. + * - There is no guarantee of forward progression for individual threads. + * - This should be safe to use from a signal handler context. + */ +template +class MPSCRingBufferBase { + public: + explicit MPSCRingBufferBase(size_t aCapacity) + : mFree(0), mOccupied(0), mCapacity(aCapacity + 1) { + MOZ_RELEASE_ASSERT(aCapacity < kMaxCapacity); + + if constexpr (MPSC_DEBUG) { + fprintf(stderr, + "[%s] this=%p { mCapacity=%zu, mBits=%" PRIu64 + ", mMask=0x%" PRIx64 " }\n", + __PRETTY_FUNCTION__, this, mCapacity, mBits, mMask); + } + + // Leave one empty space in the queue, used to distinguish an empty queue + // from a full one, as in the SPSCQueue. + // https://docs.rs/signal-hook/0.3.17/src/signal_hook/low_level/channel.rs.html#126 + for (uint64_t i = 1; i < StorageCapacity(); ++i) { + MarkSlot(mFree, i); + } + + // This should be the only allocation performed, thus it cannot be performed + // in a restricted context (e.g., signal handler, real-time thread) + mData = std::make_unique(Capacity()); + + std::atomic_thread_fence(std::memory_order_seq_cst); + } + + /** + * @brief Put an element in the queue. The caller MUST check the return value + * and maybe loop to try again (or drop if acceptable). + * + * First it attempts to acuire a slot (storage index) that is known to be + * non used. If that is not successfull then 0 is returned. If that is + * successfull, the slot is ours (it has been exclusively acquired) and data + * can be copied into the ring buffer at that index. + * + * @param aElement The element to put in the queue. + * + * @return 0 if insertion could not be performed, inserted index otherwise + */ + [[nodiscard]] int Send(T& aElement) { + std::optional empty_idx = UnmarkSlot(mFree); + if (empty_idx.has_value()) { + detail::MemoryOperations::MoveOrCopy(&mData[*empty_idx - 1], &aElement, + 1); + MarkSlot(mOccupied, *empty_idx); + return *empty_idx; + } + return 0; + } + + /** + * Retrieve one element from the ring buffer, and copy it to + * `aElement`, if non-null. + * + * It attempts to acquire a slot from the list of used ones. If that is not + * successfull, then 0 is returned. Once a slot has been exclusively acquired, + * data is copied from it into the non-null pointer passed in parameter. + * + * @param aElement A pointer to a `T` where data will be copied. + * + * @return The index from which data was copied, 0 if there was nothing in the + * ring buffer. + */ + [[nodiscard]] int Recv(T* aElement) { + std::optional idx = UnmarkSlot(mOccupied); + if (idx.has_value()) { + if (aElement) { + detail::MemoryOperations::MoveOrCopy(aElement, &mData[*idx - 1], 1); + } + MarkSlot(mFree, *idx); + return *idx; + } + return 0; + } + + size_t Capacity() const { return StorageCapacity() - 1; } + + private: + /* + * Get/Set manipulates the encoding within `aNumber` by storing the index as a + * number and shifting it to the left (set) or right (get). + * + * Initial `aNumber` value is 0. + * + * Set() with first index value (1), we store the index on mBits and we shift + * it to the left, e.g., as follows: + * + * aNumber=0b00000000000000000000000000000000000000000000000000000000000000 + * aIndex=0 aValue=1 + * aNumber=0b00000000000000000000000000000000000000000000000000000000000001 + * aIndex=1 aValue=33 + * aNumber=0b00000000000000000000000000000000000000000000000000000000100001 + * aIndex=2 aValue=801 + * aNumber=0b00000000000000000000000000000000000000000000000000001100100001 + * aIndex=3 aValue=17185 + * aNumber=0b00000000000000000000000000000000000000000000000100001100100001 + * aIndex=4 aValue=344865 + * aNumber=0b00000000000000000000000000000000000000000001010100001100100001 + * aIndex=5 aValue=6636321 + * aNumber=0b00000000000000000000000000000000000000011001010100001100100001 + * aIndex=6 aValue=124076833 + * aNumber=0b00000000000000000000000000000000000111011001010100001100100001 + * aIndex=7 aValue=2271560481 + * aNumber=0b00000000000000000000000000000010000111011001010100001100100001 + * aIndex=8 aValue=40926266145 + * aNumber=0b00000000000000000000000000100110000111011001010100001100100001 + * aIndex=9 aValue=728121033505 + * aNumber=0b00000000000000000000001010100110000111011001010100001100100001 + * aIndex=10 aValue=12822748939041 + * aNumber=0b00000000000000000010111010100110000111011001010100001100100001 + * aIndex=11 aValue=223928981472033 + * aNumber=0b00000000000000110010111010100110000111011001010100001100100001 + * aIndex=12 aValue=3883103678710561 + * aNumber=0b00000000001101110010111010100110000111011001010100001100100001 + * aIndex=13 aValue=66933498461897505 + * aNumber=0b00000011101101110010111010100110000111011001010100001100100001 + * aIndex=14 aValue=1147797409030816545 + */ + [[nodiscard]] uint64_t Get(uint64_t aNumber, uint64_t aIndex) { + return (aNumber >> (mBits * aIndex)) & mMask; + } + + [[nodiscard]] uint64_t Set(uint64_t aNumber, uint64_t aIndex, + uint64_t aValue) { + return (aNumber & ~(mMask << (mBits * aIndex))) | + (aValue << (mBits * aIndex)); + } + + /* + * Enqueue a value in the ring buffer at aIndex. + * + * Takes the current uint64_t value from the atomic and try to acquire a non + * used slot in the ring buffer. If unsucessfull, 0 is returned, otherwise + * compute the new atomic value that holds the new state of usage of the + * slots, and use compare/exchange to perform lock-free synchronization: + * compare/exchanges succeeds when the current value and the modified one are + * equal, reflecting an acquired lock. If another thread was concurrent to + * this one, then it would fail to that operation, and go into the next + * iteration of the loop to read the new state value from the atomic, and + * acquire a different slot. + * + * @param aSlotStatus a uint64_t atomic that is used to perform lock-free + * thread exclusions + * + * @param aIndex the index where we want to enqueue. It should come from the + * empty queue + * */ + void MarkSlot(std::atomic& aSlotStatus, uint64_t aIndex) { + uint64_t current = aSlotStatus.load(std::memory_order_relaxed); + do { + // Attempts to find a slot that is available to enqueue, without + // cross-thread synchronization + auto empty = [&]() -> std::optional { + for (uint64_t i = 0; i < Capacity(); ++i) { + if (Get(current, i) == 0) { + return i; + } + } + return {}; + }(); + if (!empty.has_value()) { + // Rust does expect() which would panic: + // https://docs.rs/signal-hook/0.3.17/src/signal_hook/low_level/channel.rs.html#62 + // If there's no empty place, then it would be up to the caller to deal + // with that + MOZ_CRASH("No empty slot available"); + } + uint64_t modified = Set(current, *empty, aIndex); + // This is where the lock-free synchronization happens ; if `current` + // matches the content of `aSlotStatus`, then store `modified` in + // aSlotStatus and succeeds. Upon success it means no other thread has + // tried to change the same value at the same time, so the lock was safely + // acquired. + // + // Upon failure, it means another thread tried at the same time to use the + // same slot, so a new iteration of the loop needs to be executed to try + // another slot. + // + // In case of success (`aSlotStatus`'s content is equal to `current`), we + // require memory_order_release for the read-modify-write operation + // because we want to make sure when acquiring a slot that any concurrent + // thread performing a write had a chance to do it. + // + // In case of failure we require memory_order_relaxed for the load + // operation because we dont need synchronization at that point. + if (aSlotStatus.compare_exchange_weak(current, modified, + std::memory_order_release, + std::memory_order_relaxed)) { + if constexpr (MPSC_DEBUG) { + fprintf(stderr, + "[enqueue] modified=0x%" PRIx64 " => index=%" PRIu64 "\n", + modified, aIndex); + } + return; + } + } while (true); + } + + /* + * Dequeue a value from the ring buffer. + * + * Takes the current value from the uint64_t atomic and read the current index + * out of it. If that index is 0 then we are facing a lack of slots and we + * return, the caller MUST check this and deal with the situation. If the + * index is non null we can try to acquire the matching slot in the ring + * buffer thanks to the compare/exchange loop. When the compare/exchange call + * succeeds, then the slot was acquired. + * + * @param aSlotStatus a uint64_t atomic that is used to perform lock-free + * thread exclusions + * */ + [[nodiscard]] std::optional UnmarkSlot( + std::atomic& aSlotStatus) { + uint64_t current = aSlotStatus.load(std::memory_order_relaxed); + do { + uint64_t index = current & mMask; + if (index == 0) { + // Return a None + // https://docs.rs/signal-hook/0.3.17/src/signal_hook/low_level/channel.rs.html#77 + // If we return None while dequeuing on mFree then we are full and the + // caller needs to deal with that. + return {}; + } + uint64_t modified = current >> mBits; + // See the comment in MarkSlot for details + // + // In case of success (`aSlotStatus`'s content is equal to `current`), we + // require memory_order_acquire for the read-modify-write operation + // because we want to make sure when unmarking a slot that any concurrent + // thread performing a read will see the value we are writing. + // + // In case of failure we require memory_order_relaxed for the load + // operation because we dont need synchronization at that point. + if (aSlotStatus.compare_exchange_weak(current, modified, + std::memory_order_acquire, + std::memory_order_relaxed)) { + if constexpr (MPSC_DEBUG) { + fprintf(stderr, + "[dequeue] current=0x%" PRIx64 " => index=%" PRIu64 "\n", + current, index); + } + return index; + } + } while (true); + return {}; + } + + // Return the number of elements we can store within the ring buffer, whereas + // Capacity() will return the amount of elements in mData, including the 0 + // value. + [[nodiscard]] size_t StorageCapacity() const { return mCapacity; } + + // For the atomics below they are manipulated by Get()/Set(), and we are using + // them to store the IDs of the ring buffer usage (empty/full). + // + // We use mBits bits to store an ID (so we are limited to 16 and 0 is + // reserved) and append each of them to the atomics. + // + // A 0 value in one of those denotes we are full for the atomic, i.e., + // mFree=0 means we are full and mOccupied=0 means we are empty. + + // Holds the IDs of the free slots in the ring buffer + std::atomic mFree; + + // Holds the IDs of the occupied slots in the ring buffer + std::atomic mOccupied; + + const size_t mCapacity; + + // The actual ring buffer + std::unique_ptr mData; + + // How we are using the uint64_t atomic above to store the IDs of the ring + // buffer. + static const uint64_t mBits = 4; + static const uint64_t mMask = 0b1111; +}; + +/** + * Instantiation of the `MPSCRingBufferBase` type. This is safe to use from + * several producers threads and one one consumer (that never changes role), + * without explicit synchronization nor allocation (outside of the constructor). + */ +template +using MPSCQueue = MPSCRingBufferBase; + +} // namespace mozilla + +#endif // mozilla_MPSCQueue_h diff --git a/src/third_party/mozjs/include/mozilla/MathAlgorithms.h b/src/third_party/mozjs/include/mozilla/MathAlgorithms.h index 5ac810c22c1..a94de1fd4c0 100644 --- a/src/third_party/mozjs/include/mozilla/MathAlgorithms.h +++ b/src/third_party/mozjs/include/mozilla/MathAlgorithms.h @@ -310,28 +310,24 @@ inline uint_fast8_t CeilingLog2Size(size_t aValue) { return CeilingLog2(aValue); } -namespace detail { - -template -class FloorLog2; - +/** + * Compute the bit position of the most significant bit set in + * |aValue|. Requires that |aValue| is non-zero. + */ template -class FloorLog2 { - public: - static uint_fast8_t compute(const T aValue) { - return 31u - CountLeadingZeroes32(aValue | 1); +inline uint_fast8_t FindMostSignificantBit(T aValue) { + static_assert(sizeof(T) <= 8); + static_assert(std::is_integral_v); + MOZ_ASSERT(aValue != 0); + // This casts to 32-bits + if constexpr (sizeof(T) <= 4) { + return 31u - CountLeadingZeroes32(aValue); } -}; - -template -class FloorLog2 { - public: - static uint_fast8_t compute(const T aValue) { - return 63u - CountLeadingZeroes64(aValue | 1); + // This doesn't + if constexpr (sizeof(T) == 8) { + return 63u - CountLeadingZeroes64(aValue); } -}; - -} // namespace detail +} /** * Compute the log of the greatest power of 2 less than or equal to |aValue|. @@ -343,7 +339,7 @@ class FloorLog2 { */ template inline constexpr uint_fast8_t FloorLog2(const T aValue) { - return detail::FloorLog2::compute(aValue); + return FindMostSignificantBit(aValue | 1); } /** A FloorLog2 variant that accepts only size_t. */ @@ -405,21 +401,6 @@ constexpr bool IsPowerOfTwo(T x) { return x && (x & (x - 1)) == 0; } -template -inline T Clamp(const T aValue, const T aMin, const T aMax) { - static_assert(std::is_integral_v, - "Clamp accepts only integral types, so that it doesn't have" - " to distinguish differently-signed zeroes (which users may" - " or may not care to distinguish, likely at a perf cost) or" - " to decide how to clamp NaN or a range with a NaN" - " endpoint."); - MOZ_ASSERT(aMin <= aMax); - - if (aValue <= aMin) return aMin; - if (aValue >= aMax) return aMax; - return aValue; -} - template inline uint_fast8_t CountTrailingZeroes(T aValue) { static_assert(sizeof(T) <= 8); diff --git a/src/third_party/mozjs/include/mozilla/Maybe.h b/src/third_party/mozjs/include/mozilla/Maybe.h index e938356b9fc..79d1c1052ca 100644 --- a/src/third_party/mozjs/include/mozilla/Maybe.h +++ b/src/third_party/mozjs/include/mozilla/Maybe.h @@ -249,7 +249,7 @@ struct MaybeStorage : MaybeStorageBase { protected: char mIsSome = false; // not bool -- guarantees minimal space consumption - MaybeStorage() = default; + constexpr MaybeStorage() = default; explicit MaybeStorage(const T& aVal) : MaybeStorageBase{aVal}, mIsSome{true} {} explicit MaybeStorage(T&& aVal) @@ -364,7 +364,7 @@ constexpr Maybe Some(T&& aValue); * functions |Some()| and |Nothing()|. */ template -class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe +class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_GSL_OWNER Maybe : private detail::MaybeStorage, public detail::Maybe_CopyMove_Enabler { template @@ -579,23 +579,24 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe constexpr const T* operator->() const; /* Returns the contents of this Maybe by ref. Unsafe unless |isSome()|. */ - constexpr T& ref() &; - constexpr const T& ref() const&; - constexpr T&& ref() &&; - constexpr const T&& ref() const&&; + constexpr T& ref() & MOZ_LIFETIME_BOUND; + constexpr const T& ref() const& MOZ_LIFETIME_BOUND; + constexpr T&& ref() && MOZ_LIFETIME_BOUND; + constexpr const T&& ref() const&& MOZ_LIFETIME_BOUND; /* * Returns the contents of this Maybe by ref. If |isNothing()|, returns * the default value provided. */ - constexpr T& refOr(T& aDefault) { + constexpr T& refOr(T& aDefault MOZ_LIFETIME_BOUND) MOZ_LIFETIME_BOUND { if (isSome()) { return ref(); } return aDefault; } - constexpr const T& refOr(const T& aDefault) const { + constexpr const T& refOr(const T& aDefault MOZ_LIFETIME_BOUND) const + MOZ_LIFETIME_BOUND { if (isSome()) { return ref(); } @@ -622,10 +623,10 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe return aFunc(); } - constexpr T& operator*() &; - constexpr const T& operator*() const&; - constexpr T&& operator*() &&; - constexpr const T&& operator*() const&&; + constexpr T& operator*() & MOZ_LIFETIME_BOUND; + constexpr const T& operator*() const& MOZ_LIFETIME_BOUND; + constexpr T&& operator*() && MOZ_LIFETIME_BOUND; + constexpr const T&& operator*() const&& MOZ_LIFETIME_BOUND; /* If |isSome()|, runs the provided function or functor on the contents of * this Maybe. */ diff --git a/src/third_party/mozjs/include/mozilla/MaybeStorageBase.h b/src/third_party/mozjs/include/mozilla/MaybeStorageBase.h index 2732d78d053..9469d427eb3 100644 --- a/src/third_party/mozjs/include/mozilla/MaybeStorageBase.h +++ b/src/third_party/mozjs/include/mozilla/MaybeStorageBase.h @@ -46,7 +46,7 @@ struct MaybeStorageBase { } mStorage; public: - MaybeStorageBase() = default; + constexpr MaybeStorageBase() = default; explicit MaybeStorageBase(const T& aVal) : mStorage{aVal} {} explicit MaybeStorageBase(T&& aVal) : mStorage{std::move(aVal)} {} template @@ -63,7 +63,7 @@ struct MaybeStorageBase { using NonConstT = std::remove_const_t; union Union { - constexpr Union() : dummy() {} + constexpr Union() : empty() {} constexpr explicit Union(const T& aVal) : val{aVal} {} constexpr explicit Union(T&& aVal) : val{std::move(aVal)} {} template @@ -71,7 +71,7 @@ struct MaybeStorageBase { : val{std::forward(aArgs)...} {} NonConstT val; - char dummy; + char empty; } mStorage; public: diff --git a/src/third_party/mozjs/include/mozilla/ModuloBuffer.h b/src/third_party/mozjs/include/mozilla/ModuloBuffer.h new file mode 100644 index 00000000000..80e765279e3 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ModuloBuffer.h @@ -0,0 +1,618 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ModuloBuffer_h +#define ModuloBuffer_h + +#include "mozilla/leb128iterator.h" +#include "mozilla/Maybe.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/NotNull.h" +#include "mozilla/PowerOfTwo.h" +#include "mozilla/ProfileBufferEntrySerialization.h" +#include "mozilla/UniquePtr.h" + +#include +#include +#include +#include + +namespace mozilla { + +// The ModuloBuffer class is a circular buffer that holds raw byte values, with +// data-read/write helpers. +// +// OffsetT: Type of the internal offset into the buffer of bytes, it should be +// large enough to access all bytes of the buffer. It will also be used as +// Length (in bytes) of the buffer and of any subset. Default uint32_t +// IndexT: Type of the external index, it should be large enough that overflows +// should not happen during the lifetime of the ModuloBuffer. +// +// The basic usage is to create an iterator-like object with `ReaderAt(Index)` +// or `WriterAt(Index)`, and use it to read/write data blobs. Iterators +// automatically manage the wrap-around (through "Modulo", which is effectively +// an AND-masking with the PowerOfTwo buffer size.) +// +// There is zero safety: No thread safety, no checks that iterators may be +// overwriting data that's still to be read, etc. It's up to the caller to add +// adequate checks. +// The intended use is as an underlying buffer for a safer container. +template +class ModuloBuffer { + public: + using Byte = uint8_t; + static_assert(sizeof(Byte) == 1, "ModuloBuffer::Byte must be 1 byte"); + using Offset = OffsetT; + static_assert(!std::numeric_limits::is_signed, + "ModuloBuffer::Offset must be an unsigned integral type"); + using Length = Offset; + using Index = IndexT; + static_assert(!std::numeric_limits::is_signed, + "ModuloBuffer::Index must be an unsigned integral type"); + static_assert(sizeof(Index) >= sizeof(Offset), + "ModuloBuffer::Index size must >= Offset"); + + // Create a buffer of the given length. + explicit ModuloBuffer(PowerOfTwo aLength) + : mMask(aLength.Mask()), + mBuffer(WrapNotNull(new Byte[aLength.Value()])), + mBufferDeleter([](Byte* aBuffer) { delete[] aBuffer; }) {} + + // Take ownership of an existing buffer. Existing contents is ignored. + // Done by extracting the raw pointer from UniquePtr, and adding + // an equivalent `delete[]` in `mBufferDeleter`. + ModuloBuffer(UniquePtr aExistingBuffer, PowerOfTwo aLength) + : mMask(aLength.Mask()), + mBuffer(WrapNotNull(aExistingBuffer.release())), + mBufferDeleter([](Byte* aBuffer) { delete[] aBuffer; }) {} + + // Use an externally-owned buffer. Existing contents is ignored. + ModuloBuffer(Byte* aExternalBuffer, PowerOfTwo aLength) + : mMask(aLength.Mask()), mBuffer(WrapNotNull(aExternalBuffer)) {} + + // Disallow copying, as we may uniquely own the resource. + ModuloBuffer(const ModuloBuffer& aOther) = delete; + ModuloBuffer& operator=(const ModuloBuffer& aOther) = delete; + + // Allow move-construction. Stealing ownership if the original had it. + // This effectively prevents copy construction, and all assignments; needed so + // that a ModuloBuffer may be initialized from a separate construction. + // The moved-from ModuloBuffer still points at the resource but doesn't own + // it, so it won't try to free it; but accesses are not guaranteed, so it + // should not be used anymore. + ModuloBuffer(ModuloBuffer&& aOther) + : mMask(std::move(aOther.mMask)), + mBuffer(std::move(aOther.mBuffer)), + mBufferDeleter(std::move(aOther.mBufferDeleter)) { + // The above move leaves `aOther.mBufferDeleter` in a valid state but with + // an unspecified value, so it could theoretically still contain the + // original function, which would be bad because we don't want aOther to + // delete the resource that `this` now owns. + if (aOther.mBufferDeleter) { + // `aOther` still had a non-empty deleter, reset it. + aOther.mBufferDeleter = nullptr; + } + } + + // Disallow assignment, as we have some `const` members. + ModuloBuffer& operator=(ModuloBuffer&& aOther) = delete; + + // Destructor, deletes the resource if we uniquely own it. + ~ModuloBuffer() { + if (mBufferDeleter) { + mBufferDeleter(mBuffer); + } + } + + PowerOfTwo BufferLength() const { + return PowerOfTwo(mMask.MaskValue() + 1); + } + + // Size of external resources. + // Note: `mBufferDeleter`'s potential external data (for its captures) is not + // included, as it's hidden in the `std::function` implementation. + size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { + if (!mBufferDeleter) { + // If we don't have a buffer deleter, assume we don't own the data, so + // it's probably on the stack, or should be reported by its owner. + return 0; + } + return aMallocSizeOf(mBuffer); + } + + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + + ProfileBufferEntryReader EntryReaderFromTo( + Index aStart, Index aEnd, ProfileBufferBlockIndex aBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) const { + using EntrySpan = Span; + if (aStart == aEnd) { + return ProfileBufferEntryReader{}; + } + // Don't allow over-wrapping. + MOZ_ASSERT(aEnd - aStart <= mMask.MaskValue() + 1); + // Start offset in 0 .. (buffer size - 1) + Offset start = static_cast(aStart) & mMask; + // End offset in 1 .. (buffer size) + Offset end = (static_cast(aEnd - 1) & mMask) + 1; + if (start < end) { + // Segment doesn't cross buffer threshold, one span is enough. + return ProfileBufferEntryReader{EntrySpan(&mBuffer[start], end - start), + aBlockIndex, aNextBlockIndex}; + } + // Segment crosses buffer threshold, we need one span until the end and one + // span restarting at the beginning of the buffer. + return ProfileBufferEntryReader{ + EntrySpan(&mBuffer[start], mMask.MaskValue() + 1 - start), + EntrySpan(&mBuffer[0], end), aBlockIndex, aNextBlockIndex}; + } + + // Return an entry writer for the given range. + ProfileBufferEntryWriter EntryWriterFromTo(Index aStart, Index aEnd) const { + using EntrySpan = Span; + if (aStart == aEnd) { + return ProfileBufferEntryWriter{}; + } + MOZ_ASSERT(aEnd - aStart <= mMask.MaskValue() + 1); + // Start offset in 0 .. (buffer size - 1) + Offset start = static_cast(aStart) & mMask; + // End offset in 1 .. (buffer size) + Offset end = (static_cast(aEnd - 1) & mMask) + 1; + if (start < end) { + // Segment doesn't cross buffer threshold, one span is enough. + return ProfileBufferEntryWriter{ + EntrySpan(&mBuffer[start], end - start), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aStart), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aEnd)}; + } + // Segment crosses buffer threshold, we need one span until the end and one + // span restarting at the beginning of the buffer. + return ProfileBufferEntryWriter{ + EntrySpan(&mBuffer[start], mMask.MaskValue() + 1 - start), + EntrySpan(&mBuffer[0], end), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aStart), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aEnd)}; + } + + // Emplace an entry writer into `aMaybeEntryWriter` for the given range. + void EntryWriterFromTo(Maybe& aMaybeEntryWriter, + Index aStart, Index aEnd) const { + MOZ_ASSERT(aMaybeEntryWriter.isNothing(), + "Reference entry writer should be Nothing."); + using EntrySpan = Span; + if (aStart == aEnd) { + return; + } + MOZ_ASSERT(aEnd - aStart <= mMask.MaskValue() + 1); + // Start offset in 0 .. (buffer size - 1) + Offset start = static_cast(aStart) & mMask; + // End offset in 1 .. (buffer size) + Offset end = (static_cast(aEnd - 1) & mMask) + 1; + if (start < end) { + // Segment doesn't cross buffer threshold, one span is enough. + aMaybeEntryWriter.emplace( + EntrySpan(&mBuffer[start], end - start), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aStart), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aEnd)); + } else { + // Segment crosses buffer threshold, we need one span until the end and + // one span restarting at the beginning of the buffer. + aMaybeEntryWriter.emplace( + EntrySpan(&mBuffer[start], mMask.MaskValue() + 1 - start), + EntrySpan(&mBuffer[0], end), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aStart), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex(aEnd)); + } + } + + // All ModuloBuffer operations should be done through this iterator, which has + // an effectively infinite range. The underlying wrapping-around is hidden. + // Use `ReaderAt(Index)` or `WriterAt(Index)` to create it. + // + // `const Iterator<...>` means the iterator itself cannot change, i.e., it + // cannot move, and only its const methods are available. Note that these + // const methods may still be used to modify the buffer contents (e.g.: + // `operator*()`, `Poke()`). + // + // `Iterator` means the buffer contents cannot be + // modified, i.e., write operations are forbidden, but the iterator may still + // move if non-const itself. + template + class Iterator { + // Alias to const- or mutable-`ModuloBuffer` depending on `IsBufferConst`. + using ConstOrMutableBuffer = + std::conditional_t; + + // Implementation note about the strange enable-if's below: + // `template enable_if_t` + // which intuitively could be simplified to: + // `enable_if_t` + // The former extra-templated syntax is in fact necessary to delay + // instantiation of these functions until they are actually needed. + // + // If we were just doing `enable_if_t`, this would only + // depend on the *class* (`ModuloBuffer<...>::Iterator`), which gets + // instantiated when a `ModuloBuffer` is created with some template + // arguments; at that point, all non-templated methods get instantiated, so + // there's no "SFINAE" happening, and `enable_if_t<...>` is actually doing + // `typename enable_if<...>::type` on the spot, but there is no `type` if + // `IsBufferConst` is true, so it just fails right away. E.g.: + // error: no type named 'type' in 'std::enable_if'; + // 'enable_if' cannot be used to disable this declaration + // note: in instantiation of template type alias 'enable_if_t' + // > std::enable_if_t WriteObject(const T& aObject) { + // in instantiation of template class + // 'mozilla::ModuloBuffer<...>::Iterator' + // > auto it = mb.ReaderAt(1); + // + // By adding another template level `template `, the instantiation is delayed until the function is + // actually invoked somewhere, e.g. `it.Poke(...);`. + // So at that invocation point, the compiler looks for a "Poke" name in it, + // and considers potential template instantiations that could work. The + // `enable_if_t` is *now* attempted, with `NotIsBufferConst` taking its + // value from `!IsBufferConst`: + // - If `IsBufferConst` is false, `NotIsBufferConst` is true, + // `enable_if` does define a `type` (`void` by default), + // so `enable_if_t` happily becomes `void`, the function exists and may be + // called. + // - Otherwise if `IsBufferConst` is true, `NotIsBufferConst` is false, + // `enable_if` does *not* define a `type`, therefore + // `enable_if_t` produces an error because there is no `type`. Now "SFINAE" + // happens: This "Substitution Failure Is Not An Error" (by itself)... But + // then, there are no other functions named "Poke" as requested in the + // `it.Poke(...);` call, so we are now getting an error (can't find + // function), as expected because `it` had `IsBufferConst`==true. (But at + // least the compiler waited until this invocation attempt before outputting + // an error.) + // + // C++ is fun! + + public: + // These definitions are expected by std functions, to recognize this as an + // iterator. See https://en.cppreference.com/w/cpp/iterator/iterator_traits + using difference_type = Index; + using value_type = Byte; + using pointer = std::conditional_t; + using reference = std::conditional_t; + using iterator_category = std::random_access_iterator_tag; + + // Can always copy/assign from the same kind of iterator. + Iterator(const Iterator& aRhs) = default; + Iterator& operator=(const Iterator& aRhs) = default; + + // Can implicitly copy an Iterator-to-mutable (reader+writer) to + // Iterator-to-const (reader-only), but not the reverse. + template > + MOZ_IMPLICIT Iterator(const Iterator& aRhs) + : mModuloBuffer(aRhs.mModuloBuffer), mIndex(aRhs.mIndex) {} + + // Can implicitly assign from an Iterator-to-mutable (reader+writer) to + // Iterator-to-const (reader-only), but not the reverse. + template > + Iterator& operator=(const Iterator& aRhs) { + mModuloBuffer = aRhs.mModuloBuffer; + mIndex = aRhs.mIndex; + return *this; + } + + // Current location of the iterator in the `Index` range. + // Note that due to wrapping, multiple indices may effectively point at the + // same byte in the buffer. + Index CurrentIndex() const { return mIndex; } + + // Location comparison in the `Index` range. I.e., two `Iterator`s may look + // unequal, but refer to the same buffer location. + // Must be on the same buffer. + bool operator==(const Iterator& aRhs) const { + MOZ_ASSERT(mModuloBuffer == aRhs.mModuloBuffer); + return mIndex == aRhs.mIndex; + } + bool operator!=(const Iterator& aRhs) const { + MOZ_ASSERT(mModuloBuffer == aRhs.mModuloBuffer); + return mIndex != aRhs.mIndex; + } + bool operator<(const Iterator& aRhs) const { + MOZ_ASSERT(mModuloBuffer == aRhs.mModuloBuffer); + return mIndex < aRhs.mIndex; + } + bool operator<=(const Iterator& aRhs) const { + MOZ_ASSERT(mModuloBuffer == aRhs.mModuloBuffer); + return mIndex <= aRhs.mIndex; + } + bool operator>(const Iterator& aRhs) const { + MOZ_ASSERT(mModuloBuffer == aRhs.mModuloBuffer); + return mIndex > aRhs.mIndex; + } + bool operator>=(const Iterator& aRhs) const { + MOZ_ASSERT(mModuloBuffer == aRhs.mModuloBuffer); + return mIndex >= aRhs.mIndex; + } + + // Movement in the `Index` range. + Iterator& operator++() { + ++mIndex; + return *this; + } + Iterator operator++(int) { + Iterator here(*mModuloBuffer, mIndex); + ++mIndex; + return here; + } + Iterator& operator--() { + --mIndex; + return *this; + } + Iterator operator--(int) { + Iterator here(*mModuloBuffer, mIndex); + --mIndex; + return here; + } + Iterator& operator+=(Length aLength) { + mIndex += aLength; + return *this; + } + Iterator operator+(Length aLength) const { + return Iterator(*mModuloBuffer, mIndex + aLength); + } + friend Iterator operator+(Length aLength, const Iterator& aIt) { + return aIt + aLength; + } + Iterator& operator-=(Length aLength) { + mIndex -= aLength; + return *this; + } + Iterator operator-(Length aLength) const { + return Iterator(*mModuloBuffer, mIndex - aLength); + } + + // Distance from `aRef` to here in the `Index` range. + // May be negative (as 2's complement) if `aRef > *this`. + Index operator-(const Iterator& aRef) const { + MOZ_ASSERT(mModuloBuffer == aRef.mModuloBuffer); + return mIndex - aRef.mIndex; + } + + // Dereference a single byte (read-only if `IsBufferConst` is true). + reference operator*() const { + return mModuloBuffer->mBuffer[OffsetInBuffer()]; + } + + // Random-access dereference. + reference operator[](Length aLength) const { return *(*this + aLength); } + + // Write data (if `IsBufferConst` is false) but don't move iterator. + template + std::enable_if_t Poke(const void* aSrc, + Length aLength) const { + // Don't allow data larger than the buffer. + MOZ_ASSERT(aLength <= mModuloBuffer->BufferLength().Value()); + // Offset inside the buffer (corresponding to our Index). + Offset offset = OffsetInBuffer(); + // Compute remaining bytes between this offset and the end of the buffer. + Length remaining = mModuloBuffer->BufferLength().Value() - offset; + if (MOZ_LIKELY(remaining >= aLength)) { + // Enough space to write everything before the end. + memcpy(&mModuloBuffer->mBuffer[offset], aSrc, aLength); + } else { + // Not enough space. Write as much as possible before the end. + memcpy(&mModuloBuffer->mBuffer[offset], aSrc, remaining); + // And then continue from the beginning of the buffer. + memcpy(&mModuloBuffer->mBuffer[0], + static_cast(aSrc) + remaining, + (aLength - remaining)); + } + } + + // Write object data (if `IsBufferConst` is false) but don't move iterator. + // Note that this copies bytes from the object, with the intent to read them + // back later. Restricted to trivially-copyable types, which support this + // without Undefined Behavior! + template + std::enable_if_t PokeObject(const T& aObject) const { + static_assert(std::is_trivially_copyable::value, + "PokeObject - T must be trivially copyable"); + return Poke(&aObject, sizeof(T)); + } + + // Write data (if `IsBufferConst` is false) and move iterator ahead. + template + std::enable_if_t Write(const void* aSrc, Length aLength) { + Poke(aSrc, aLength); + mIndex += aLength; + } + + // Write object data (if `IsBufferConst` is false) and move iterator ahead. + // Note that this copies bytes from the object, with the intent to read them + // back later. Restricted to trivially-copyable types, which support this + // without Undefined Behavior! + template + std::enable_if_t WriteObject(const T& aObject) { + static_assert(std::is_trivially_copyable::value, + "WriteObject - T must be trivially copyable"); + return Write(&aObject, sizeof(T)); + } + + // Number of bytes needed to represent `aValue` in unsigned LEB128. + template + static unsigned ULEB128Size(T aValue) { + return ::mozilla::ULEB128Size(aValue); + } + + // Write number as unsigned LEB128 (if `IsBufferConst` is false) and move + // iterator ahead. + template + std::enable_if_t WriteULEB128(T aValue) { + ::mozilla::WriteULEB128(aValue, *this); + } + + // Read data but don't move iterator. + void Peek(void* aDst, Length aLength) const { + // Don't allow data larger than the buffer. + MOZ_ASSERT(aLength <= mModuloBuffer->BufferLength().Value()); + // Offset inside the buffer (corresponding to our Index). + Offset offset = OffsetInBuffer(); + // Compute remaining bytes between this offset and the end of the buffer. + Length remaining = mModuloBuffer->BufferLength().Value() - offset; + if (MOZ_LIKELY(remaining >= aLength)) { + // Can read everything we need before the end of the buffer. + memcpy(aDst, &mModuloBuffer->mBuffer[offset], aLength); + } else { + // Read as much as possible before the end of the buffer. + memcpy(aDst, &mModuloBuffer->mBuffer[offset], remaining); + // And then continue from the beginning of the buffer. + memcpy(static_cast(aDst) + remaining, &mModuloBuffer->mBuffer[0], + (aLength - remaining)); + } + } + + // Read data into an object but don't move iterator. + // Note that this overwrites `aObject` with bytes from the buffer. + // Restricted to trivially-copyable types, which support this without + // Undefined Behavior! + template + void PeekIntoObject(T& aObject) const { + static_assert(std::is_trivially_copyable::value, + "PeekIntoObject - T must be trivially copyable"); + Peek(&aObject, sizeof(T)); + } + + // Read data as an object but don't move iterator. + // Note that this creates an default `T` first, and then overwrites it with + // bytes from the buffer. Restricted to trivially-copyable types, which + // support this without Undefined Behavior! + template + T PeekObject() const { + static_assert(std::is_trivially_copyable::value, + "PeekObject - T must be trivially copyable"); + T object; + PeekIntoObject(object); + return object; + } + + // Read data and move iterator ahead. + void Read(void* aDst, Length aLength) { + Peek(aDst, aLength); + mIndex += aLength; + } + + // Read data into a mutable iterator and move both iterators ahead. + void ReadInto(Iterator& aDst, Length aLength) { + // Don't allow data larger than the buffer. + MOZ_ASSERT(aLength <= mModuloBuffer->BufferLength().Value()); + MOZ_ASSERT(aLength <= aDst.mModuloBuffer->BufferLength().Value()); + // Offset inside the buffer (corresponding to our Index). + Offset offset = OffsetInBuffer(); + // Compute remaining bytes between this offset and the end of the buffer. + Length remaining = mModuloBuffer->BufferLength().Value() - offset; + if (MOZ_LIKELY(remaining >= aLength)) { + // Can read everything we need before the end of the buffer. + aDst.Write(&mModuloBuffer->mBuffer[offset], aLength); + } else { + // Read as much as possible before the end of the buffer. + aDst.Write(&mModuloBuffer->mBuffer[offset], remaining); + // And then continue from the beginning of the buffer. + aDst.Write(&mModuloBuffer->mBuffer[0], (aLength - remaining)); + } + mIndex += aLength; + } + + // Read data into an object and move iterator ahead. + // Note that this overwrites `aObject` with bytes from the buffer. + // Restricted to trivially-copyable types, which support this without + // Undefined Behavior! + template + void ReadIntoObject(T& aObject) { + static_assert(std::is_trivially_copyable::value, + "ReadIntoObject - T must be trivially copyable"); + Read(&aObject, sizeof(T)); + } + + // Read data as an object and move iterator ahead. + // Note that this creates an default `T` first, and then overwrites it with + // bytes from the buffer. Restricted to trivially-copyable types, which + // support this without Undefined Behavior! + template + T ReadObject() { + static_assert(std::is_trivially_copyable::value, + "ReadObject - T must be trivially copyable"); + T object; + ReadIntoObject(object); + return object; + } + + // Read an unsigned LEB128 number and move iterator ahead. + template + T ReadULEB128() { + return ::mozilla::ReadULEB128(*this); + } + + private: + // Only a ModuloBuffer can instantiate its iterator. + friend class ModuloBuffer; + + Iterator(ConstOrMutableBuffer& aBuffer, Index aIndex) + : mModuloBuffer(WrapNotNull(&aBuffer)), mIndex(aIndex) {} + + // Convert the Iterator's mIndex into an offset inside the byte buffer. + Offset OffsetInBuffer() const { + return static_cast(mIndex) & mModuloBuffer->mMask; + } + + // ModuloBuffer that this Iterator operates on. + // Using a non-null pointer instead of a reference, to allow re-assignment + // of an Iterator variable. + NotNull mModuloBuffer; + + // Position of this iterator in the wider `Index` range. (Will be wrapped + // around as needed when actually accessing bytes from the buffer.) + Index mIndex; + }; + + // Shortcut to iterator to const (read-only) data. + using Reader = Iterator; + // Shortcut to iterator to non-const (read/write) data. + using Writer = Iterator; + + // Create an iterator to const data at the given index. + Reader ReaderAt(Index aIndex) const { return Reader(*this, aIndex); } + + // Create an iterator to non-const data at the given index. + Writer WriterAt(Index aIndex) { return Writer(*this, aIndex); } + +#ifdef DEBUG + void Dump() const { + Length len = BufferLength().Value(); + if (len > 128) { + len = 128; + } + for (Length i = 0; i < len; ++i) { + printf("%02x ", mBuffer[i]); + } + printf("\n"); + } +#endif // DEBUG + + private: + // Mask used to convert an index to an offset in `mBuffer` + const PowerOfTwoMask mMask; + + // Buffer data. `const NotNull<...>` shows that `mBuffer is `const`, and + // `Byte* const` shows that the pointer cannot be changed to point at + // something else, but the pointed-at `Byte`s are writable. + const NotNull mBuffer; + + // Function used to release the buffer resource (if needed). + std::function mBufferDeleter; +}; + +} // namespace mozilla + +#endif // ModuloBuffer_h diff --git a/src/third_party/mozjs/include/mozilla/NativeNt.h b/src/third_party/mozjs/include/mozilla/NativeNt.h index 932dcd0a7b0..e28ad0f2914 100644 --- a/src/third_party/mozjs/include/mozilla/NativeNt.h +++ b/src/third_party/mozjs/include/mozilla/NativeNt.h @@ -554,7 +554,7 @@ class MOZ_RAII PEHeaders final { WORD wLength; WORD wValueLength; WORD wType; - WCHAR szKey[16]; // ArrayLength(L"VS_VERSION_INFO") + WCHAR szKey[16]; // std::size(L"VS_VERSION_INFO") // Additional data goes here, aligned on a 4-byte boundary }; @@ -913,6 +913,12 @@ class MOZ_RAII PEHeaders final { IMAGE_SCN_MEM_READ); } + // There may be other data sections in the binary besides .data + Maybe> GetDataSectionInfo() const { + return FindSection(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE); + } + static bool IsValid(PIMAGE_IMPORT_DESCRIPTOR aImpDesc) { return aImpDesc && aImpDesc->OriginalFirstThunk != 0; } @@ -1024,8 +1030,8 @@ class MOZ_RAII PEHeaders final { const wchar_t kVersionInfoKey[] = L"VS_VERSION_INFO"; if (::RtlCompareMemory(aVerInfo->szKey, kVersionInfoKey, - ArrayLength(kVersionInfoKey)) != - ArrayLength(kVersionInfoKey)) { + std::size(kVersionInfoKey)) != + std::size(kVersionInfoKey)) { return nullptr; } diff --git a/src/third_party/mozjs/include/mozilla/NeverDestroyed.h b/src/third_party/mozjs/include/mozilla/NeverDestroyed.h new file mode 100644 index 00000000000..dcb8a007cd8 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/NeverDestroyed.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_NeverDestroyed_h +#define mozilla_NeverDestroyed_h + +#include +#include +#include +#include "mozilla/Attributes.h" + +namespace mozilla { + +// Helper type for creating a local static member of type `T` when `T` has a +// non-trivial static destructor. When used for the local static value, this +// type will avoid introducing a static destructor for these types, as they +// will survive until shutdown. +// +// This can be very useful to avoid static destructors, which are heavily +// discouraged. Using this type is unnecessary if `T` already has a trivial +// destructor, and may introduce unnecessary extra overhead. +// +// This type must only be used with static local members within a function, +// which will be enforced by the clang static analysis. +template +class MOZ_STATIC_LOCAL_CLASS +MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS NeverDestroyed { + public: + static_assert( + !std::is_trivially_destructible_v, + "NeverDestroyed is unnecessary for trivially destructable types"); + + // Allow constructing the inner type. + // This isn't constexpr, as it requires invoking placement-new. See the + // comment on `mStorage`. + template + explicit NeverDestroyed(U&&... aArgs) { + new (mStorage) T(std::forward(aArgs)...); + } + + const T& operator*() const { return *get(); } + T& operator*() { return *get(); } + + const T* operator->() const { return get(); } + T* operator->() { return get(); } + + const T* get() const { return reinterpret_cast(mStorage); } + T* get() { return reinterpret_cast(mStorage); } + + // Block copy & move constructor, as the type is not safe to copy. + NeverDestroyed(const NeverDestroyed&) = delete; + NeverDestroyed& operator=(const NeverDestroyed&) = delete; + + private: + // Correctly aligned storage for the type. We unfortunately can't use a union + // for alignment & constexpr initialization as that would require an explicit + // destructor declaration, making `NeverDestroyed` non-trivially destructable. + alignas(T) char mStorage[sizeof(T)]; +}; + +}; // namespace mozilla + +#endif // mozilla_NeverDestroyed_h diff --git a/src/third_party/mozjs/include/mozilla/Now.h b/src/third_party/mozjs/include/mozilla/Now.h new file mode 100644 index 00000000000..cafc69f761a --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/Now.h @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_Now_h +#define mozilla_Now_h + +#include + +#include "mozilla/Maybe.h" + +namespace mozilla { + +// Returns monotonic milliseconds elapsed since an arbitrary reference point, +// excluding time when the system was suspended. +MFBT_API Maybe NowExcludingSuspendMs(); +// Returns monotonic milliseconds elapsed since an arbitrary reference point, +// including time when the system was suspended. +MFBT_API Maybe NowIncludingSuspendMs(); + +}; // namespace mozilla + +#endif // mozilla_Now_h diff --git a/src/third_party/mozjs/include/mozilla/PodOperations.h b/src/third_party/mozjs/include/mozilla/PodOperations.h index f4e5da4c799..3c10090eede 100644 --- a/src/third_party/mozjs/include/mozilla/PodOperations.h +++ b/src/third_party/mozjs/include/mozilla/PodOperations.h @@ -32,12 +32,16 @@ class NotNull; /** Set the contents of |aT| to 0. */ template static MOZ_ALWAYS_INLINE void PodZero(T* aT) { + static_assert(std::is_trivially_copyable_v, + "PodZero requires trivially copyable types"); memset(aT, 0, sizeof(T)); } /** Set the contents of |aNElem| elements starting at |aT| to 0. */ template static MOZ_ALWAYS_INLINE void PodZero(T* aT, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodZero requires trivially copyable types"); /* * This function is often called with 'aNElem' small; we use an inline loop * instead of calling 'memset' with a non-constant length. The compiler @@ -69,50 +73,50 @@ static void PodZero(T (&aT)[N], size_t aNElem) = delete; /** Set the contents of the array |aT| to zero. */ template static MOZ_ALWAYS_INLINE void PodArrayZero(T (&aT)[N]) { + static_assert(std::is_trivially_copyable_v, + "PodArrayZero requires trivially copyable types"); memset(aT, 0, N * sizeof(T)); } template static MOZ_ALWAYS_INLINE void PodArrayZero(Array& aArr) { + static_assert(std::is_trivially_copyable_v, + "PodArrayZero requires trivially copyable types"); memset(&aArr[0], 0, N * sizeof(T)); } -/** - * Assign |*aSrc| to |*aDst|. The locations must not be the same and must not - * overlap. - */ -template -static MOZ_ALWAYS_INLINE void PodAssign(T* aDst, const T* aSrc) { - MOZ_ASSERT(aDst + 1 <= aSrc || aSrc + 1 <= aDst, - "destination and source must not overlap"); - memcpy(reinterpret_cast(aDst), reinterpret_cast(aSrc), - sizeof(T)); -} - /** * Copy |aNElem| T elements from |aSrc| to |aDst|. The two memory ranges must * not overlap! */ template static MOZ_ALWAYS_INLINE void PodCopy(T* aDst, const T* aSrc, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodCopy requires trivially copyable types"); MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst, "destination and source must not overlap"); + +// Linux memcpy for small sizes seems slower than on other +// platforms. So we use a loop for small sizes there only. +// +// See Bug 1967062 for details. +#if defined(XP_LINUX) if (aNElem < 128) { - /* - * Avoid using operator= in this loop, as it may have been - * intentionally deleted by the POD type. - */ for (const T* srcend = aSrc + aNElem; aSrc < srcend; aSrc++, aDst++) { - PodAssign(aDst, aSrc); + *aDst = *aSrc; } - } else { - memcpy(aDst, aSrc, aNElem * sizeof(T)); + return; } +#endif + + memcpy(aDst, aSrc, aNElem * sizeof(T)); } template static MOZ_ALWAYS_INLINE void PodCopy(volatile T* aDst, const volatile T* aSrc, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodCopy requires trivially copyable types"); MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst, "destination and source must not overlap"); @@ -145,6 +149,8 @@ static MOZ_ALWAYS_INLINE void PodArrayCopy(T (&aDst)[N], const T (&aSrc)[N]) { */ template static MOZ_ALWAYS_INLINE void PodMove(T* aDst, const T* aSrc, size_t aNElem) { + static_assert(std::is_trivially_copyable_v, + "PodMove requires trivially copyable types"); MOZ_ASSERT(aNElem <= SIZE_MAX / sizeof(T), "trying to move an impossible number of elements"); memmove(aDst, aSrc, aNElem * sizeof(T)); diff --git a/src/third_party/mozjs/include/mozilla/PowerOfTwo.h b/src/third_party/mozjs/include/mozilla/PowerOfTwo.h new file mode 100644 index 00000000000..7d396c15e67 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/PowerOfTwo.h @@ -0,0 +1,322 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// PowerOfTwo is a value type that always hold a power of 2. +// It has the same size as their underlying unsigned type, but offer the +// guarantee of being a power of 2, which permits some optimizations when +// involved in modulo operations (using masking instead of actual modulo). +// +// PowerOfTwoMask contains a mask corresponding to a power of 2. +// E.g., 2^8 is 256 or 0x100, the corresponding mask is 2^8-1 or 255 or 0xFF. +// It should be used instead of PowerOfTwo in situations where most operations +// would be modulo, this saves having to recompute the mask from the stored +// power of 2. +// +// One common use would be for ring-buffer containers with a power-of-2 size, +// where an index is usually converted to an in-buffer offset by `i % size`. +// Instead, the container could store a PowerOfTwo or PowerOfTwoMask, and do +// `i % p2` or `i & p2m`, which is more efficient than for arbitrary sizes. +// +// Shortcuts for common 32- and 64-bit values: PowerOfTwo32, etc. +// +// To create constexpr constants, use MakePowerOfTwo(), etc. + +#ifndef PowerOfTwo_h +#define PowerOfTwo_h + +#include "mozilla/MathAlgorithms.h" + +#include + +namespace mozilla { + +// Compute the smallest power of 2 greater than or equal to aInput, except if +// that would overflow in which case the highest possible power of 2 if chosen. +// 0->1, 1->1, 2->2, 3->4, ... 2^31->2^31, 2^31+1->2^31 (for uint32_t), etc. +template +T FriendlyRoundUpPow2(T aInput) { + // This is the same code as `RoundUpPow2()`, except we handle any type (that + // CeilingLog2 supports) and allow the greater-than-max-power case. + constexpr T max = T(1) << (sizeof(T) * CHAR_BIT - 1); + if (aInput >= max) { + return max; + } + return T(1) << CeilingLog2(aInput); +} + +namespace detail { +// Same function name `CountLeadingZeroes` with uint32_t and uint64_t overloads. +inline uint_fast8_t CountLeadingZeroes(uint32_t aValue) { + MOZ_ASSERT(aValue != 0); + return detail::CountLeadingZeroes32(aValue); +} +inline uint_fast8_t CountLeadingZeroes(uint64_t aValue) { + MOZ_ASSERT(aValue != 0); + return detail::CountLeadingZeroes64(aValue); +} +// Refuse anything else. +template +inline uint_fast8_t CountLeadingZeroes(T aValue) = delete; +} // namespace detail + +// Compute the smallest 2^N-1 mask where aInput can fit. +// I.e., `x & mask == x`, but `x & (mask >> 1) != x`. +// Or looking at binary, we want a mask with as many leading zeroes as the +// input, by right-shifting a full mask: (8-bit examples) +// input: 00000000 00000001 00000010 00010110 01111111 10000000 +// N leading 0s: ^^^^^^^^ 8 ^^^^^^^ 7 ^^^^^^ 6 ^^^ 3 ^ 1 0 +// full mask: 11111111 11111111 11111111 11111111 11111111 11111111 +// full mask >> N: 00000000 00000001 00000011 00011111 01111111 11111111 +template +T RoundUpPow2Mask(T aInput) { + // Special case, as CountLeadingZeroes(0) is undefined. (And even if that was + // defined, shifting by the full type size is also undefined!) + if (aInput == 0) { + return 0; + } + return T(-1) >> detail::CountLeadingZeroes(aInput); +} + +template +class PowerOfTwoMask; + +template +constexpr PowerOfTwoMask MakePowerOfTwoMask(); + +template +class PowerOfTwo; + +template +constexpr PowerOfTwo MakePowerOfTwo(); + +// PowerOfTwoMask will always contain a mask for a power of 2, which is useful +// for power-of-2 modulo operations (e.g., to keep an index inside a power-of-2 +// container). +// Use this instead of PowerOfTwo if masking is the primary use of the value. +// +// Note that this class can store a "full" mask where all bits are set, so it +// works for mask corresponding to the power of 2 that would overflow `T` +// (e.g., 2^32 for uint32_t gives a mask of 2^32-1, which fits in a uint32_t). +// For this reason there is no API that computes the power of 2 corresponding to +// the mask; But this can be done explicitly with `MaskValue() + 1`, which may +// be useful for computing things like distance-to-the-end by doing +// `MaskValue() + 1 - offset`, which works fine with unsigned number types. +template +class PowerOfTwoMask { + static_assert(!std::numeric_limits::is_signed, + "PowerOfTwoMask must use an unsigned type"); + + public: + // Construct a power of 2 mask where the given value can fit. + // Cannot be constexpr because of `RoundUpPow2Mask()`. + explicit PowerOfTwoMask(T aInput) : mMask(RoundUpPow2Mask(aInput)) {} + + // Compute the mask corresponding to a PowerOfTwo. + // This saves having to compute the nearest 2^N-1. + // Not a conversion constructor, as that could be ambiguous whether we'd want + // the mask corresponding to the power of 2 (2^N -> 2^N-1), or the mask that + // can *contain* the PowerOfTwo value (2^N -> 2^(N+1)-1). + // Note: Not offering reverse PowerOfTwoMark-to-PowerOfTwo conversion, because + // that could result in an unexpected 0 result for the largest possible mask. + template + static constexpr PowerOfTwoMask MaskForPowerOfTwo( + const PowerOfTwo& aP2) { + return PowerOfTwoMask(aP2); + } + + // Allow smaller unsigned types as input. + // Bigger or signed types must be explicitly converted by the caller. + template + explicit constexpr PowerOfTwoMask(U aInput) + : mMask(RoundUpPow2Mask(static_cast(aInput))) { + static_assert(!std::numeric_limits::is_signed, + "PowerOfTwoMask does not accept signed types"); + static_assert(sizeof(U) <= sizeof(T), + "PowerOfTwoMask does not accept bigger types"); + } + + constexpr T MaskValue() const { return mMask; } + + // `x & aPowerOfTwoMask` just works. + template + friend U operator&(U aNumber, PowerOfTwoMask aP2M) { + return static_cast(aNumber & aP2M.MaskValue()); + } + + // `aPowerOfTwoMask & x` just works. + template + friend constexpr U operator&(PowerOfTwoMask aP2M, U aNumber) { + return static_cast(aP2M.MaskValue() & aNumber); + } + + // `x % aPowerOfTwoMask(2^N-1)` is equivalent to `x % 2^N` but is more + // optimal by doing `x & (2^N-1)`. + // Useful for templated code doing modulo with a template argument type. + template + friend constexpr U operator%(U aNumerator, PowerOfTwoMask aDenominator) { + return aNumerator & aDenominator.MaskValue(); + } + + constexpr bool operator==(const PowerOfTwoMask& aRhs) const { + return mMask == aRhs.mMask; + } + constexpr bool operator!=(const PowerOfTwoMask& aRhs) const { + return mMask != aRhs.mMask; + } + + private: + // Trust `PowerOfTwo` to call the private Trusted constructor below. + friend class PowerOfTwo; + + // Trust `MakePowerOfTwoMask()` to call the private Trusted constructor below. + template + friend constexpr PowerOfTwoMask MakePowerOfTwoMask(); + + struct Trusted { + T mMask; + }; + // Construct the mask corresponding to a PowerOfTwo. + // This saves having to compute the nearest 2^N-1. + // Note: Not a public PowerOfTwo->PowerOfTwoMask conversion constructor, as + // that could be ambiguous whether we'd want the mask corresponding to the + // power of 2 (2^N -> 2^N-1), or the mask that can *contain* the PowerOfTwo + // value (2^N -> 2^(N+1)-1). + explicit constexpr PowerOfTwoMask(const Trusted& aP2) : mMask(aP2.mMask) {} + + T mMask = 0; +}; + +// Make a PowerOfTwoMask constant, statically-checked. +template +constexpr PowerOfTwoMask MakePowerOfTwoMask() { + static_assert(Mask == T(-1) || IsPowerOfTwo(Mask + 1), + "MakePowerOfTwoMask: Mask must be 2^N-1"); + using Trusted = typename PowerOfTwoMask::Trusted; + return PowerOfTwoMask(Trusted{Mask}); +} + +// PowerOfTwo will always contain a power of 2. +template +class PowerOfTwo { + static_assert(!std::numeric_limits::is_signed, + "PowerOfTwo must use an unsigned type"); + + public: + // Construct a power of 2 that can fit the given value, or the highest power + // of 2 possible. + // Caller should explicitly check/assert `Value() <= aInput` if they want to. + // Cannot be constexpr because of `FriendlyRoundUpPow2()`. + explicit PowerOfTwo(T aInput) : mValue(FriendlyRoundUpPow2(aInput)) {} + + // Allow smaller unsigned types as input. + // Bigger or signed types must be explicitly converted by the caller. + template + explicit PowerOfTwo(U aInput) + : mValue(FriendlyRoundUpPow2(static_cast(aInput))) { + static_assert(!std::numeric_limits::is_signed, + "PowerOfTwo does not accept signed types"); + static_assert(sizeof(U) <= sizeof(T), + "PowerOfTwo does not accept bigger types"); + } + + constexpr T Value() const { return mValue; } + + // Binary mask corresponding to the power of 2, useful for modulo. + // E.g., `x & powerOfTwo(y).Mask()` == `x % powerOfTwo(y)`. + // Consider PowerOfTwoMask class instead of PowerOfTwo if masking is the + // primary use case. + constexpr T MaskValue() const { return mValue - 1; } + + // PowerOfTwoMask corresponding to this power of 2, useful for modulo. + constexpr PowerOfTwoMask Mask() const { + using Trusted = typename PowerOfTwoMask::Trusted; + return PowerOfTwoMask(Trusted{MaskValue()}); + } + + // `x % aPowerOfTwo` works optimally. + // Useful for templated code doing modulo with a template argument type. + // Use PowerOfTwoMask class instead if masking is the primary use case. + template + friend constexpr U operator%(U aNumerator, PowerOfTwo aDenominator) { + return aNumerator & aDenominator.MaskValue(); + } + + constexpr bool operator==(const PowerOfTwo& aRhs) const { + return mValue == aRhs.mValue; + } + constexpr bool operator!=(const PowerOfTwo& aRhs) const { + return mValue != aRhs.mValue; + } + constexpr bool operator<(const PowerOfTwo& aRhs) const { + return mValue < aRhs.mValue; + } + constexpr bool operator<=(const PowerOfTwo& aRhs) const { + return mValue <= aRhs.mValue; + } + constexpr bool operator>(const PowerOfTwo& aRhs) const { + return mValue > aRhs.mValue; + } + constexpr bool operator>=(const PowerOfTwo& aRhs) const { + return mValue >= aRhs.mValue; + } + + private: + // Trust `MakePowerOfTwo()` to call the private Trusted constructor below. + template + friend constexpr PowerOfTwo MakePowerOfTwo(); + + struct Trusted { + T mValue; + }; + // Construct a PowerOfTwo with the given trusted value. + // This saves having to compute the nearest 2^N. + // Note: Not offering PowerOfTwoMark-to-PowerOfTwo conversion, because that + // could result in an unexpected 0 result for the largest possible mask. + explicit constexpr PowerOfTwo(const Trusted& aP2) : mValue(aP2.mValue) {} + + // The smallest power of 2 is 2^0 == 1. + T mValue = 1; +}; + +// Make a PowerOfTwo constant, statically-checked. +template +constexpr PowerOfTwo MakePowerOfTwo() { + static_assert(IsPowerOfTwo(Value), + "MakePowerOfTwo: Value must be 2^N"); + using Trusted = typename PowerOfTwo::Trusted; + return PowerOfTwo(Trusted{Value}); +} + +// Shortcuts for the most common types and functions. + +using PowerOfTwoMask32 = PowerOfTwoMask; +using PowerOfTwo32 = PowerOfTwo; +using PowerOfTwoMask64 = PowerOfTwoMask; +using PowerOfTwo64 = PowerOfTwo; + +template +constexpr PowerOfTwoMask32 MakePowerOfTwoMask32() { + return MakePowerOfTwoMask(); +} + +template +constexpr PowerOfTwo32 MakePowerOfTwo32() { + return MakePowerOfTwo(); +} + +template +constexpr PowerOfTwoMask64 MakePowerOfTwoMask64() { + return MakePowerOfTwoMask(); +} + +template +constexpr PowerOfTwo64 MakePowerOfTwo64() { + return MakePowerOfTwo(); +} + +} // namespace mozilla + +#endif // PowerOfTwo_h diff --git a/src/third_party/mozjs/include/mozilla/PreXULSkeletonUI.h b/src/third_party/mozjs/include/mozilla/PreXULSkeletonUI.h index c0549cd4e62..8f0c9b1a65b 100644 --- a/src/third_party/mozjs/include/mozilla/PreXULSkeletonUI.h +++ b/src/third_party/mozjs/include/mozilla/PreXULSkeletonUI.h @@ -21,8 +21,8 @@ namespace mozilla { // to not vary based off of any user settings for the initial toplevel window, // so we're safe here for now. static const DWORD kPreXULSkeletonUIWindowStyle = - WS_CLIPCHILDREN | WS_DLGFRAME | WS_BORDER | WS_MAXIMIZEBOX | - WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU; + WS_OVERLAPPED | WS_CLIPCHILDREN | WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | + WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU; static const DWORD kPreXULSkeletonUIWindowStyleEx = WS_EX_WINDOWEDGE; struct CSSPixelSpan { @@ -50,6 +50,7 @@ struct SkeletonUISettings { bool menubarShown; bool bookmarksToolbarShown; bool rtlEnabled; + bool verticalTabs; SkeletonUIDensity uiDensity; }; @@ -61,12 +62,13 @@ enum class SkeletonUIFlag : uint8_t { RtlEnabled, TouchDensity, CompactDensity, + VerticalTabs }; struct ThemeColors { uint32_t backgroundColor; uint32_t toolbarForegroundColor; - uint32_t tabBarColor; + uint32_t titlebarColor; uint32_t tabColor; uint32_t tabOutlineColor; uint32_t chromeContentDividerColor; @@ -101,61 +103,6 @@ enum class PreXULSkeletonUIError : uint32_t { Unknown, }; -inline const wchar_t* GetPreXULSkeletonUIErrorString( - PreXULSkeletonUIError error) { - switch (error) { - case PreXULSkeletonUIError::None: - return L"None"; - case PreXULSkeletonUIError::Disabled: - return L"Disabled"; - case PreXULSkeletonUIError::OOM: - return L"OOM"; - case PreXULSkeletonUIError::Cmdline: - return L"Cmdline"; - case PreXULSkeletonUIError::EnvVars: - return L"EnvVars"; - case PreXULSkeletonUIError::FailedToOpenRegistryKey: - return L"FailedToOpenRegistryKey"; - case PreXULSkeletonUIError::RegistryError: - return L"RegistryError"; - case PreXULSkeletonUIError::FailedLoadingDynamicProcs: - return L"FailedLoadingDynamicProcs"; - case PreXULSkeletonUIError::FailedGettingLock: - return L"FailedGettingLock"; - case PreXULSkeletonUIError::FilesystemFailure: - return L"FilesystemFailure"; - case PreXULSkeletonUIError::NoStartWithLastProfile: - return L"NoStartWithLastProfile"; - case PreXULSkeletonUIError::FailedRegisteringWindowClass: - return L"FailedRegisteringWindowClass"; - case PreXULSkeletonUIError::CorruptData: - return L"CorruptData"; - case PreXULSkeletonUIError::BadWindowDimensions: - return L"BadWindowDimensions"; - case PreXULSkeletonUIError::FailedGettingMonitorInfo: - return L"FailedGettingMonitorInfo"; - case PreXULSkeletonUIError::EnabledKeyDoesNotExist: - return L"EnabledKeyDoesNotExist"; - case PreXULSkeletonUIError::CreateWindowFailed: - return L"CreateWindowFailed"; - case PreXULSkeletonUIError::FailedGettingDC: - return L"FailedGettingDC"; - case PreXULSkeletonUIError::FailedBlitting: - return L"FailedBlitting"; - case PreXULSkeletonUIError::FailedFillingBottomRect: - return L"FailedFillingBottomRect"; - case PreXULSkeletonUIError::CrashedOnce: - return L"CrashedOnce"; - case PreXULSkeletonUIError::BadUIDensity: - return L"BadUIDensity"; - case PreXULSkeletonUIError::Unknown: - return L"Unknown"; - } - - MOZ_ASSERT_UNREACHABLE(); - return L"Unknown"; -} - enum class PreXULSkeletonUIProgress : uint32_t { Started, Completed, @@ -166,7 +113,6 @@ MFBT_API void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc, MFBT_API void CleanupProcessRuntime(); MFBT_API bool GetPreXULSkeletonUIWasShown(); MFBT_API HWND ConsumePreXULSkeletonUIHandle(); -MFBT_API Maybe GetPreXULSkeletonUIErrorReason(); MFBT_API bool WasPreXULSkeletonUIMaximized(); MFBT_API Result PersistPreXULSkeletonUIValues( const SkeletonUISettings& settings); diff --git a/src/third_party/mozjs/include/mozilla/ProcessType.h b/src/third_party/mozjs/include/mozilla/ProcessType.h index 890ed4faacf..012cd046e61 100644 --- a/src/third_party/mozjs/include/mozilla/ProcessType.h +++ b/src/third_party/mozjs/include/mozilla/ProcessType.h @@ -22,9 +22,16 @@ enum GeckoProcessType { GeckoProcessType_Invalid = GeckoProcessType_End }; +// Integral type used for GeckoChildIDs. A ChildID of -1 is used as the invalid +// sentinel, and 0 indicates the parent process. +using GeckoChildID = int32_t; + +inline constexpr GeckoChildID kInvalidGeckoChildID = -1; + namespace mozilla { namespace startup { extern MFBT_DATA GeckoProcessType sChildProcessType; +extern MFBT_DATA GeckoChildID sGeckoChildID; } // namespace startup /** @@ -39,6 +46,18 @@ MOZ_ALWAYS_INLINE GeckoProcessType GetGeckoProcessType() { */ MFBT_API void SetGeckoProcessType(const char* aProcessTypeString); +/** + * @return the GeckoChildID of the current process. + */ +MOZ_ALWAYS_INLINE GeckoChildID GetGeckoChildID() { + return startup::sGeckoChildID; +} + +/** + * Set the gecko child id based on a null-terminated byte string. + */ +MFBT_API void SetGeckoChildID(const char* aGeckoChildIDString); + } // namespace mozilla #endif // IPC_PROCESSTYPE_H_ diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferChunk.h b/src/third_party/mozjs/include/mozilla/ProfileBufferChunk.h new file mode 100644 index 00000000000..9ba2483372e --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferChunk.h @@ -0,0 +1,547 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferChunk_h +#define ProfileBufferChunk_h + +#include "mozilla/MemoryReporting.h" +#include "mozilla/ProfileBufferIndex.h" +#include "mozilla/Span.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/UniquePtr.h" + +#if defined(MOZ_MEMORY) +# include "mozmemory.h" +#endif + +#include +#include +#include + +#ifdef DEBUG +# include +#endif + +namespace mozilla { + +// Represents a single chunk of memory, with a link to the next chunk (or null). +// +// A chunk is made of an internal header (which contains a public part) followed +// by user-accessible bytes. +// +// +---------------+---------+----------------------------------------------+ +// | public Header | private | memory containing user blocks | +// +---------------+---------+----------------------------------------------+ +// <---------------BufferBytes()------------------> +// <------------------------------ChunkBytes()------------------------------> +// +// The chunk can reserve "blocks", but doesn't know the internal contents of +// each block, it only knows where the first one starts, and where the last one +// ends (which is where the next one will begin, if not already out of range). +// It is up to the user to add structure to each block so that they can be +// distinguished when later read. +// +// +---------------+---------+----------------------------------------------+ +// | public Header | private | [1st block]...[last full block] | +// +---------------+---------+----------------------------------------------+ +// ChunkHeader().mOffsetFirstBlock ^ ^ +// ChunkHeader().mOffsetPastLastBlock --' +// +// It is possible to attempt to reserve more than the remaining space, in which +// case only what is available is returned. The caller is responsible for using +// another chunk, reserving a block "tail" in it, and using both parts to +// constitute a full block. (This initial tail may be empty in some chunks.) +// +// +---------------+---------+----------------------------------------------+ +// | public Header | private | tail][1st block]...[last full block][head... | +// +---------------+---------+----------------------------------------------+ +// ChunkHeader().mOffsetFirstBlock ^ ^ +// ChunkHeader().mOffsetPastLastBlock --' +// +// Each Chunk has an internal state (checked in DEBUG builds) that directs how +// to use it during creation, initialization, use, end of life, recycling, and +// destruction. See `State` below for details. +// In particular: +// - `ReserveInitialBlockAsTail()` must be called before the first `Reserve()` +// after construction or recycling, even with a size of 0 (no actual tail), +// - `MarkDone()` and `MarkRecycled()` must be called as appropriate. +class ProfileBufferChunk { + public: + using Byte = uint8_t; + using Length = uint32_t; + + using SpanOfBytes = Span; + + // Hint about the size of the metadata (public and private headers). + // `Create()` below takes the minimum *buffer* size, so the minimum total + // Chunk size is at least `SizeofChunkMetadata() + aMinBufferBytes`. + [[nodiscard]] static constexpr Length SizeofChunkMetadata() { + return static_cast(sizeof(InternalHeader)); + } + + // Allocate space for a chunk with a given minimum size, and construct it. + // The actual size may be higher, to match the actual space taken in the + // memory pool. + [[nodiscard]] static UniquePtr Create( + Length aMinBufferBytes) { + // We need at least one byte, to cover the always-present `mBuffer` byte. + aMinBufferBytes = std::max(aMinBufferBytes, Length(1)); + // Trivial struct with the same alignment as `ProfileBufferChunk`, and size + // equal to that alignment, because typically the sizeof of an object is + // a multiple of its alignment. + struct alignas(alignof(InternalHeader)) ChunkStruct { + Byte c[alignof(InternalHeader)]; + }; + static_assert(std::is_trivial_v, + "ChunkStruct must be trivial to avoid any construction"); + // Allocate an array of that struct, enough to contain the expected + // `ProfileBufferChunk` (with its header+buffer). + size_t count = (sizeof(InternalHeader) + aMinBufferBytes + + (alignof(InternalHeader) - 1)) / + alignof(InternalHeader); +#if defined(MOZ_MEMORY) + // Potentially expand the array to use more of the effective allocation. + count = (malloc_good_size(count * sizeof(ChunkStruct)) + + (sizeof(ChunkStruct) - 1)) / + sizeof(ChunkStruct); +#endif + auto chunkStorage = MakeUnique(count); + MOZ_ASSERT(reinterpret_cast(chunkStorage.get()) % + alignof(InternalHeader) == + 0); + // After the allocation, compute the actual chunk size (including header). + const size_t chunkBytes = count * sizeof(ChunkStruct); + MOZ_ASSERT(chunkBytes >= sizeof(ProfileBufferChunk), + "Not enough space to construct a ProfileBufferChunk"); + MOZ_ASSERT(chunkBytes <= + static_cast(std::numeric_limits::max())); + // Compute the size of the user-accessible buffer inside the chunk. + const Length bufferBytes = + static_cast(chunkBytes - sizeof(InternalHeader)); + MOZ_ASSERT(bufferBytes >= aMinBufferBytes, + "Not enough space for minimum buffer size"); + // Construct the header at the beginning of the allocated array, with the + // known buffer size. + new (chunkStorage.get()) ProfileBufferChunk(bufferBytes); + // We now have a proper `ProfileBufferChunk` object, create the appropriate + // UniquePtr for it. + UniquePtr chunk{ + reinterpret_cast(chunkStorage.release())}; + MOZ_ASSERT( + size_t(reinterpret_cast( + &chunk.get()->BufferSpan()[bufferBytes - 1]) - + reinterpret_cast(chunk.get())) == chunkBytes - 1, + "Buffer span spills out of chunk allocation"); + return chunk; + } + +#ifdef DEBUG + ~ProfileBufferChunk() { + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::InUse); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Full); + MOZ_ASSERT(mInternalHeader.mState == InternalHeader::State::Created || + mInternalHeader.mState == InternalHeader::State::Done || + mInternalHeader.mState == InternalHeader::State::Recycled); + } +#endif + + // Must be called with the first block tail (may be empty), which will be + // skipped if the reader starts with this ProfileBufferChunk. + [[nodiscard]] SpanOfBytes ReserveInitialBlockAsTail(Length aTailSize) { +#ifdef DEBUG + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::InUse); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Full); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Done); + MOZ_ASSERT(mInternalHeader.mState == InternalHeader::State::Created || + mInternalHeader.mState == InternalHeader::State::Recycled); + mInternalHeader.mState = InternalHeader::State::InUse; +#endif + mInternalHeader.mHeader.mOffsetFirstBlock = aTailSize; + mInternalHeader.mHeader.mOffsetPastLastBlock = aTailSize; + mInternalHeader.mHeader.mStartTimeStamp = TimeStamp::Now(); + return SpanOfBytes(&mBuffer, aTailSize); + } + + struct ReserveReturn { + SpanOfBytes mSpan; + ProfileBufferBlockIndex mBlockRangeIndex; + }; + + // Reserve a block of up to `aBlockSize` bytes, and return a Span to it, and + // its starting index. The actual size may be smaller, if the block cannot fit + // in the remaining space. + [[nodiscard]] ReserveReturn ReserveBlock(Length aBlockSize) { + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Created); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Full); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Done); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Recycled); + MOZ_ASSERT(mInternalHeader.mState == InternalHeader::State::InUse); + MOZ_ASSERT(RangeStart() != 0, + "Expected valid range start before first Reserve()"); + const Length blockOffset = mInternalHeader.mHeader.mOffsetPastLastBlock; + Length reservedSize = aBlockSize; + if (MOZ_UNLIKELY(aBlockSize >= RemainingBytes())) { + reservedSize = RemainingBytes(); +#ifdef DEBUG + mInternalHeader.mState = InternalHeader::State::Full; +#endif + } + mInternalHeader.mHeader.mOffsetPastLastBlock += reservedSize; + mInternalHeader.mHeader.mBlockCount += 1; + return {SpanOfBytes(&mBuffer + blockOffset, reservedSize), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mInternalHeader.mHeader.mRangeStart + blockOffset)}; + } + + // When a chunk will not be used to store more blocks (because it is full, or + // because the profiler will not add more data), it should be marked "done". + // Access to its content is still allowed. + void MarkDone() { +#ifdef DEBUG + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Created); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Done); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Recycled); + MOZ_ASSERT(mInternalHeader.mState == InternalHeader::State::InUse || + mInternalHeader.mState == InternalHeader::State::Full); + mInternalHeader.mState = InternalHeader::State::Done; +#endif + mInternalHeader.mHeader.mDoneTimeStamp = TimeStamp::Now(); + } + + // A "Done" chunk may be recycled, to avoid allocating a new one. + void MarkRecycled() { +#ifdef DEBUG + // We also allow Created and already-Recycled chunks to be recycled, this + // way it's easier to recycle chunks when their state is not easily + // trackable. + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::InUse); + MOZ_ASSERT(mInternalHeader.mState != InternalHeader::State::Full); + MOZ_ASSERT(mInternalHeader.mState == InternalHeader::State::Created || + mInternalHeader.mState == InternalHeader::State::Done || + mInternalHeader.mState == InternalHeader::State::Recycled); + mInternalHeader.mState = InternalHeader::State::Recycled; +#endif + // Reset all header fields, in case this recycled chunk gets read. + mInternalHeader.mHeader.Reset(); + } + + // Public header, meant to uniquely identify a chunk, it may be shared with + // other processes to coordinate global memory handling. + struct Header { + explicit Header(Length aBufferBytes) : mBufferBytes(aBufferBytes) {} + + // Reset all members to their as-new values (apart from the buffer size, + // which cannot change), ready for re-use. + void Reset() { + mOffsetFirstBlock = 0; + mOffsetPastLastBlock = 0; + mStartTimeStamp = TimeStamp{}; + mDoneTimeStamp = TimeStamp{}; + mBlockCount = 0; + mRangeStart = 0; + mProcessId = 0; + } + + // Note: Part of the ordering of members below is to avoid unnecessary + // padding. + + // Members managed by the ProfileBufferChunk. + + // Offset of the first block (past the initial tail block, which may be 0). + Length mOffsetFirstBlock = 0; + // Offset past the last byte of the last reserved block + // It may be past mBufferBytes when last block continues in the next + // ProfileBufferChunk. It may be before mBufferBytes if ProfileBufferChunk + // is marked "Done" before the end is reached. + Length mOffsetPastLastBlock = 0; + // Timestamp when the buffer becomes in-use, ready to record data. + TimeStamp mStartTimeStamp; + // Timestamp when the buffer is "Done" (which happens when the last block is + // written). This will be used to find and discard the oldest + // ProfileBufferChunk. + TimeStamp mDoneTimeStamp; + // Number of bytes in the buffer, set once at construction time. + const Length mBufferBytes; + // Number of reserved blocks (including final one even if partial, but + // excluding initial tail). + Length mBlockCount = 0; + + // Meta-data set by the user. + + // Index of the first byte of this ProfileBufferChunk, relative to all + // Chunks for this process. Index 0 is reserved as nullptr-like index, + // mRangeStart should be set to a non-0 value before the first `Reserve()`. + ProfileBufferIndex mRangeStart = 0; + // Process writing to this ProfileBufferChunk. + int mProcessId = 0; + + // A bit of spare space (necessary here because of the alignment due to + // other members), may be later repurposed for extra data. + const int mPADDING = 0; + }; + + [[nodiscard]] const Header& ChunkHeader() const { + return mInternalHeader.mHeader; + } + + [[nodiscard]] Length BufferBytes() const { + return ChunkHeader().mBufferBytes; + } + + // Total size of the chunk (buffer + header). + [[nodiscard]] Length ChunkBytes() const { + return static_cast(sizeof(InternalHeader)) + BufferBytes(); + } + + // Size of external resources, in this case all the following chunks. + [[nodiscard]] size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { + const ProfileBufferChunk* const next = GetNext(); + return next ? next->SizeOfIncludingThis(aMallocSizeOf) : 0; + } + + // Size of this chunk and all following ones. + [[nodiscard]] size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { + // Just in case `aMallocSizeOf` falls back on just `sizeof`, make sure we + // account for at least the actual Chunk requested allocation size. + return std::max(aMallocSizeOf(this), ChunkBytes()) + + SizeOfExcludingThis(aMallocSizeOf); + } + + [[nodiscard]] Length RemainingBytes() const { + return BufferBytes() - OffsetPastLastBlock(); + } + + [[nodiscard]] Length OffsetFirstBlock() const { + return ChunkHeader().mOffsetFirstBlock; + } + + [[nodiscard]] Length OffsetPastLastBlock() const { + return ChunkHeader().mOffsetPastLastBlock; + } + + [[nodiscard]] Length BlockCount() const { return ChunkHeader().mBlockCount; } + + [[nodiscard]] int ProcessId() const { return ChunkHeader().mProcessId; } + + void SetProcessId(int aProcessId) { + mInternalHeader.mHeader.mProcessId = aProcessId; + } + + // Global range index at the start of this Chunk. + [[nodiscard]] ProfileBufferIndex RangeStart() const { + return ChunkHeader().mRangeStart; + } + + void SetRangeStart(ProfileBufferIndex aRangeStart) { + mInternalHeader.mHeader.mRangeStart = aRangeStart; + } + + // Get a read-only Span to the buffer. It is up to the caller to decypher the + // contents, based on known offsets and the internal block structure. + [[nodiscard]] Span BufferSpan() const { + return Span(&mBuffer, BufferBytes()); + } + + [[nodiscard]] Byte ByteAt(Length aOffset) const { + MOZ_ASSERT(aOffset < OffsetPastLastBlock()); + return *(&mBuffer + aOffset); + } + + [[nodiscard]] ProfileBufferChunk* GetNext() { + return mInternalHeader.mNext.get(); + } + [[nodiscard]] const ProfileBufferChunk* GetNext() const { + return mInternalHeader.mNext.get(); + } + + [[nodiscard]] UniquePtr ReleaseNext() { + return std::move(mInternalHeader.mNext); + } + + void InsertNext(UniquePtr&& aChunk) { + if (!aChunk) { + return; + } + aChunk->SetLast(ReleaseNext()); + mInternalHeader.mNext = std::move(aChunk); + } + + // Find the last chunk in this chain (it may be `this`). + [[nodiscard]] ProfileBufferChunk* Last() { + ProfileBufferChunk* chunk = this; + for (;;) { + ProfileBufferChunk* next = chunk->GetNext(); + if (!next) { + return chunk; + } + chunk = next; + } + } + [[nodiscard]] const ProfileBufferChunk* Last() const { + const ProfileBufferChunk* chunk = this; + for (;;) { + const ProfileBufferChunk* next = chunk->GetNext(); + if (!next) { + return chunk; + } + chunk = next; + } + } + + void SetLast(UniquePtr&& aChunk) { + if (!aChunk) { + return; + } + Last()->mInternalHeader.mNext = std::move(aChunk); + } + + // Join two possibly-null chunk lists. + [[nodiscard]] static UniquePtr Join( + UniquePtr&& aFirst, + UniquePtr&& aLast) { + if (aFirst) { + aFirst->SetLast(std::move(aLast)); + return std::move(aFirst); + } + return std::move(aLast); + } + +#ifdef DEBUG + void Dump(std::FILE* aFile = stdout) const { + fprintf(aFile, + "Chunk[%p] chunkSize=%u bufferSize=%u state=%s rangeStart=%u " + "firstBlockOffset=%u offsetPastLastBlock=%u blockCount=%u", + this, unsigned(ChunkBytes()), unsigned(BufferBytes()), + mInternalHeader.StateString(), unsigned(RangeStart()), + unsigned(OffsetFirstBlock()), unsigned(OffsetPastLastBlock()), + unsigned(BlockCount())); + const auto len = OffsetPastLastBlock(); + constexpr unsigned columns = 16; + unsigned char ascii[columns + 1]; + ascii[columns] = '\0'; + for (Length i = 0; i < len; ++i) { + if (i % columns == 0) { + fprintf(aFile, "\n %4u=0x%03x:", unsigned(i), unsigned(i)); + for (unsigned a = 0; a < columns; ++a) { + ascii[a] = ' '; + } + } + unsigned char sep = ' '; + if (i == OffsetFirstBlock()) { + if (i == OffsetPastLastBlock()) { + sep = '#'; + } else { + sep = '['; + } + } else if (i == OffsetPastLastBlock()) { + sep = ']'; + } + unsigned char c = *(&mBuffer + i); + fprintf(aFile, "%c%02x", sep, c); + + if (i == len - 1) { + if (i + 1 == OffsetPastLastBlock()) { + // Special case when last block ends right at the end. + fprintf(aFile, "]"); + } else { + fprintf(aFile, " "); + } + } else if (i % columns == columns - 1) { + fprintf(aFile, " "); + } + + ascii[i % columns] = (c >= ' ' && c <= '~') ? c : '.'; + + if (i % columns == columns - 1) { + fprintf(aFile, " %s", ascii); + } + } + + if (len % columns < columns - 1) { + for (Length i = len % columns; i < columns; ++i) { + fprintf(aFile, " "); + } + fprintf(aFile, " %s", ascii); + } + + fprintf(aFile, "\n"); + } +#endif // DEBUG + + private: + // ProfileBufferChunk constructor. Use static `Create()` to allocate and + // construct a ProfileBufferChunk. + explicit ProfileBufferChunk(Length aBufferBytes) + : mInternalHeader(aBufferBytes) {} + + // This internal header starts with the public `Header`, and adds some data + // only necessary for local handling. + // This encapsulation is also necessary to perform placement-new in + // `Create()`. + struct InternalHeader { + explicit InternalHeader(Length aBufferBytes) : mHeader(aBufferBytes) {} + + Header mHeader; + UniquePtr mNext; + +#ifdef DEBUG + enum class State { + Created, // Self-set. Just constructed, waiting for initial block tail. + InUse, // Ready to accept blocks. + Full, // Self-set. Blocks reach the end (or further). + Done, // Blocks won't be added anymore. + Recycled // Still full of data, but expecting an initial block tail. + }; + + State mState = State::Created; + // Transition table: (X=unexpected) + // Method \ State Created InUse Full Done Recycled + // ReserveInitialBlockAsTail InUse X X X InUse + // Reserve X InUse/Full X X X + // MarkDone X Done Done X X + // MarkRecycled X X X Recycled X + // destructor ok X X ok ok + + const char* StateString() const { + switch (mState) { + case State::Created: + return "Created"; + case State::InUse: + return "InUse"; + case State::Full: + return "Full"; + case State::Done: + return "Done"; + case State::Recycled: + return "Recycled"; + default: + return "?"; + } + } +#else // DEBUG + const char* StateString() const { return "(non-DEBUG)"; } +#endif + }; + + InternalHeader mInternalHeader; + + // KEEP THIS LAST! + // First byte of the buffer. Note that ProfileBufferChunk::Create allocates a + // bigger block, such that `mBuffer` is the first of `mBufferBytes` available + // bytes. + // The initialization is not strictly needed, because bytes should only be + // read after they have been written and `mOffsetPastLastBlock` has been + // updated. However: + // - Reviewbot complains that it's not initialized. + // - It's cheap to initialize one byte. + // - In the worst case (reading does happen), zero is not a valid entry size + // and should get caught in entry readers. + Byte mBuffer = '\0'; +}; + +} // namespace mozilla + +#endif // ProfileBufferChunk_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManager.h b/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManager.h new file mode 100644 index 00000000000..e7f12bf21f4 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManager.h @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferChunkManager_h +#define ProfileBufferChunkManager_h + +#include "mozilla/ProfileBufferChunk.h" +#include "mozilla/ScopeExit.h" + +#include + +namespace mozilla { + +// Manages the ProfileBufferChunks for this process. +// The main user of this class is the buffer that needs chunks to store its +// data. +// The main ProfileBufferChunks responsibilities are: +// - It can create new chunks, they are called "unreleased". +// - Later these chunks are returned here, and become "released". +// - The manager is free to destroy or recycle the oldest released chunks +// (usually to reclaim memory), and will inform the user through a provided +// callback. +// - The user may access still-alive released chunks. +class ProfileBufferChunkManager { + public: + virtual ~ProfileBufferChunkManager() +#ifdef DEBUG + { + MOZ_ASSERT(!mUser, "Still registered when being destroyed"); + } +#else + = default; +#endif + + // Expected maximum size needed to store one stack sample. + // Most ChunkManager sub-classes will require chunk sizes, this can serve as + // a minimum recommendation to hold most backtraces. + constexpr static ProfileBufferChunk::Length scExpectedMaximumStackSize = + 128 * 1024; + + // Estimated maximum buffer size. + [[nodiscard]] virtual size_t MaxTotalSize() const = 0; + + // Create or recycle a chunk right now. May return null in case of allocation + // failure. + // Note that the chunk-destroyed callback may be invoked during this call; + // user should be careful with reentrancy issues. + [[nodiscard]] virtual UniquePtr GetChunk() = 0; + + // `aChunkReceiver` may be called with a new or recycled chunk, or nullptr. + // (See `FulfillChunkRequests()` regarding when the callback may happen.) + virtual void RequestChunk( + std::function)>&& aChunkReceiver) = 0; + + // This method may be invoked at any time on any thread (and not necessarily + // by the main user of this class), to do the work necessary to respond to a + // previous `RequestChunk()`. + // It is optional: If it is never called, or called too late, the user is + // responsible for directly calling `GetChunk()` when a chunk is really + // needed (or it should at least fail gracefully). + // The idea is to fulfill chunk request on a separate thread, and most + // importantly outside of profiler calls, to avoid doing expensive memory + // allocations during these calls. + virtual void FulfillChunkRequests() = 0; + + // One chunk is released by the user, the ProfileBufferChunkManager should + // keep it as long as possible (depending on local or global memory/time + // limits). Note that the chunk-destroyed callback may be invoked during this + // call; user should be careful with reentrancy issues. + virtual void ReleaseChunk(UniquePtr aChunk) = 0; + + // `aChunkDestroyedCallback` will be called whenever the contents of a + // previously-released chunk is about to be destroyed or recycled. + // Note that it may be called during other functions above, or at other times + // from the same or other threads; user should be careful with reentrancy + // issues. + virtual void SetChunkDestroyedCallback( + std::function&& + aChunkDestroyedCallback) = 0; + + // Give away all released chunks that have not yet been destroyed. + [[nodiscard]] virtual UniquePtr + GetExtantReleasedChunks() = 0; + + // Let a callback see all released chunks that have not yet been destroyed, if + // any. Return whatever the callback returns. + template + [[nodiscard]] auto PeekExtantReleasedChunks(Callback&& aCallback) { + const ProfileBufferChunk* chunks = PeekExtantReleasedChunksAndLock(); + auto unlock = + MakeScopeExit([&]() { UnlockAfterPeekExtantReleasedChunks(); }); + return std::forward(aCallback)(chunks); + } + + // Chunks that were still unreleased will never be released. + virtual void ForgetUnreleasedChunks() = 0; + + [[nodiscard]] virtual size_t SizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const = 0; + [[nodiscard]] virtual size_t SizeOfIncludingThis( + MallocSizeOf aMallocSizeOf) const = 0; + + protected: + // Derived classes to implement `PeekExtantReleasedChunks` through these: + virtual const ProfileBufferChunk* PeekExtantReleasedChunksAndLock() = 0; + virtual void UnlockAfterPeekExtantReleasedChunks() = 0; + +#ifdef DEBUG + public: + // DEBUG checks ensuring that this manager and its users avoid UAFs. + // Derived classes should assert that mUser is not null in their functions. + + void RegisteredWith(const void* aUser) { + MOZ_ASSERT(!mUser); + MOZ_ASSERT(aUser); + mUser = aUser; + } + + void DeregisteredFrom(const void* aUser) { + MOZ_ASSERT(mUser == aUser); + mUser = nullptr; + } + + protected: + const void* mUser = nullptr; +#endif // DEBUG +}; + +} // namespace mozilla + +#endif // ProfileBufferChunkManager_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerSingle.h b/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerSingle.h new file mode 100644 index 00000000000..c91b38cbdbe --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerSingle.h @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferChunkManagerSingle_h +#define ProfileBufferChunkManagerSingle_h + +#include "mozilla/ProfileBufferChunkManager.h" + +#ifdef DEBUG +# include "mozilla/Atomics.h" +#endif // DEBUG + +namespace mozilla { + +// Manages only one Chunk. +// The first call to `Get`/`RequestChunk()` will retrieve the one chunk, and all +// subsequent calls will return nullptr. That chunk may still be released, but +// it will never be destroyed or recycled. +// Unlike others, this manager may be `Reset()`, to allow another round of +// small-data gathering. +// The main use is with short-lived ProfileChunkedBuffers that collect little +// data that can fit in one chunk, e.g., capturing one stack. +// It is not thread-safe. +class ProfileBufferChunkManagerSingle final : public ProfileBufferChunkManager { + public: + using Length = ProfileBufferChunk::Length; + + // Use a preallocated chunk. (Accepting null to gracefully handle OOM.) + explicit ProfileBufferChunkManagerSingle(UniquePtr aChunk) + : mInitialChunk(std::move(aChunk)), + mBufferBytes(mInitialChunk ? mInitialChunk->BufferBytes() : 0) { + MOZ_ASSERT(!mInitialChunk || !mInitialChunk->GetNext(), + "Expected at most one chunk"); + } + + // ChunkMinBufferBytes: Minimum number of user-available bytes in the Chunk. + // Note that Chunks use a bit more memory for their header. + explicit ProfileBufferChunkManagerSingle(Length aChunkMinBufferBytes) + : mInitialChunk(ProfileBufferChunk::Create(aChunkMinBufferBytes)), + mBufferBytes(mInitialChunk ? mInitialChunk->BufferBytes() : 0) {} + +#ifdef DEBUG + ~ProfileBufferChunkManagerSingle() { MOZ_ASSERT(mVirtuallyLocked == false); } +#endif // DEBUG + + // Reset this manager, using the provided chunk (probably coming from the + // ProfileChunkedBuffer that just used it); if null, fallback on current or + // released chunk. + void Reset(UniquePtr aPossibleChunk) { + if (aPossibleChunk) { + mInitialChunk = std::move(aPossibleChunk); + mReleasedChunk = nullptr; + } else if (!mInitialChunk) { + MOZ_ASSERT(!!mReleasedChunk, "Can't reset properly!"); + mInitialChunk = std::move(mReleasedChunk); + } + + if (mInitialChunk) { + mInitialChunk->MarkRecycled(); + mBufferBytes = mInitialChunk->BufferBytes(); + } else { + mBufferBytes = 0; + } + } + + [[nodiscard]] size_t MaxTotalSize() const final { return mBufferBytes; } + + // One of `GetChunk` and `RequestChunk` will only work the very first time (if + // there's even a chunk). + [[nodiscard]] UniquePtr GetChunk() final { + MOZ_ASSERT(mUser, "Not registered yet"); + return std::move(mInitialChunk); + } + + void RequestChunk(std::function)>&& + aChunkReceiver) final { + MOZ_ASSERT(mUser, "Not registered yet"); + // Simple retrieval. + std::move(aChunkReceiver)(GetChunk()); + } + + void FulfillChunkRequests() final { + // Nothing to do here. + } + + void ReleaseChunk(UniquePtr aChunk) final { + MOZ_ASSERT(mUser, "Not registered yet"); + if (!aChunk) { + return; + } + MOZ_ASSERT(!mReleasedChunk, "Unexpected 2nd released chunk"); + MOZ_ASSERT(!aChunk->GetNext(), "Only expected one released chunk"); + mReleasedChunk = std::move(aChunk); + } + + void SetChunkDestroyedCallback( + std::function&& aChunkDestroyedCallback) + final { + MOZ_ASSERT(mUser, "Not registered yet"); + // The chunk-destroyed callback will never actually be called, but we keep + // the callback here in case the caller expects it to live as long as this + // manager. + mChunkDestroyedCallback = std::move(aChunkDestroyedCallback); + } + + [[nodiscard]] UniquePtr GetExtantReleasedChunks() final { + MOZ_ASSERT(mUser, "Not registered yet"); + return std::move(mReleasedChunk); + } + + void ForgetUnreleasedChunks() final { + MOZ_ASSERT(mUser, "Not registered yet"); + } + + [[nodiscard]] size_t SizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const final { + MOZ_ASSERT(mUser, "Not registered yet"); + size_t size = 0; + if (mInitialChunk) { + size += mInitialChunk->SizeOfIncludingThis(aMallocSizeOf); + } + if (mReleasedChunk) { + size += mReleasedChunk->SizeOfIncludingThis(aMallocSizeOf); + } + // Note: Missing size of std::function external resources (if any). + return size; + } + + [[nodiscard]] size_t SizeOfIncludingThis( + MallocSizeOf aMallocSizeOf) const final { + MOZ_ASSERT(mUser, "Not registered yet"); + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + + protected: + // This manager is not thread-safe, so there's not actual locking needed. + const ProfileBufferChunk* PeekExtantReleasedChunksAndLock() final { + MOZ_ASSERT(mVirtuallyLocked.compareExchange(false, true)); + MOZ_ASSERT(mUser, "Not registered yet"); + return mReleasedChunk.get(); + } + void UnlockAfterPeekExtantReleasedChunks() final { + MOZ_ASSERT(mVirtuallyLocked.compareExchange(true, false)); + } + + private: + // Initial chunk created with this manager, given away at first Get/Request. + UniquePtr mInitialChunk; + + // Storage for the released chunk (which should probably not happen, as it + // means the chunk is full). + UniquePtr mReleasedChunk; + + // Size of the one chunk we're managing. Stored here, because the chunk may + // be moved out and inaccessible from here. + Length mBufferBytes; + + // The chunk-destroyed callback will never actually be called, but we keep it + // here in case the caller expects it to live as long as this manager. + std::function mChunkDestroyedCallback; + +#ifdef DEBUG + mutable Atomic mVirtuallyLocked{false}; +#endif // DEBUG +}; + +} // namespace mozilla + +#endif // ProfileBufferChunkManagerSingle_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerWithLocalLimit.h b/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerWithLocalLimit.h new file mode 100644 index 00000000000..034279809de --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferChunkManagerWithLocalLimit.h @@ -0,0 +1,444 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferChunkManagerWithLocalLimit_h +#define ProfileBufferChunkManagerWithLocalLimit_h + +#include "BaseProfiler.h" +#include "mozilla/BaseProfilerDetail.h" +#include "mozilla/ProfileBufferChunkManager.h" +#include "mozilla/ProfileBufferControlledChunkManager.h" +#include "mozilla/mozalloc.h" + +#include + +namespace mozilla { + +// Manages the Chunks for this process in a thread-safe manner, with a maximum +// size per process. +// +// "Unreleased" chunks are not owned here, only "released" chunks can be +// destroyed or recycled when reaching the memory limit, so it is theoretically +// possible to break that limit, if: +// - The user of this class doesn't release their chunks, AND/OR +// - The limit is too small (e.g., smaller than 2 or 3 chunks, which should be +// the usual number of unreleased chunks in flight). +// In this case, it just means that we will use more memory than allowed, +// potentially risking OOMs. Hopefully this shouldn't happen in real code, +// assuming that the user is doing the right thing and releasing chunks ASAP, +// and that the memory limit is reasonably large. +class ProfileBufferChunkManagerWithLocalLimit final + : public ProfileBufferChunkManager, + public ProfileBufferControlledChunkManager { + public: + using Length = ProfileBufferChunk::Length; + + // MaxTotalBytes: Maximum number of bytes allocated in all local Chunks. + // ChunkMinBufferBytes: Minimum number of user-available bytes in each Chunk. + // Note that Chunks use a bit more memory for their header. + explicit ProfileBufferChunkManagerWithLocalLimit(size_t aMaxTotalBytes, + Length aChunkMinBufferBytes) + : mMaxTotalBytes(aMaxTotalBytes), + mChunkMinBufferBytes(aChunkMinBufferBytes) {} + + ~ProfileBufferChunkManagerWithLocalLimit() { + if (mUpdateCallback) { + // Signal the end of this callback. + std::move(mUpdateCallback)(Update(nullptr)); + } + } + + [[nodiscard]] size_t MaxTotalSize() const final { + // `mMaxTotalBytes` is `const` so there is no need to lock the mutex. + return mMaxTotalBytes; + } + + [[nodiscard]] size_t TotalSize() const { return mTotalBytes; } + + [[nodiscard]] UniquePtr GetChunk() final { + AUTO_PROFILER_STATS(Local_GetChunk); + + ChunkAndUpdate chunkAndUpdate = [&]() { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + return GetChunk(lock); + }(); + + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + if (mUpdateCallback && !chunkAndUpdate.second.IsNotUpdate()) { + mUpdateCallback(std::move(chunkAndUpdate.second)); + } + + return std::move(chunkAndUpdate.first); + } + + void RequestChunk(std::function)>&& + aChunkReceiver) final { + AUTO_PROFILER_STATS(Local_RequestChunk); + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + if (mChunkReceiver) { + // We already have a chunk receiver, meaning a request is pending. + return; + } + // Store the chunk receiver. This indicates that a request is pending, and + // it will be handled in the next `FulfillChunkRequests()` call. + mChunkReceiver = std::move(aChunkReceiver); + } + + void FulfillChunkRequests() final { + AUTO_PROFILER_STATS(Local_FulfillChunkRequests); + std::function)> chunkReceiver; + ChunkAndUpdate chunkAndUpdate = [&]() -> ChunkAndUpdate { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + if (!mChunkReceiver) { + // No receiver means no pending request, we're done. + return {}; + } + // Otherwise there is a request, extract the receiver to call below. + std::swap(chunkReceiver, mChunkReceiver); + MOZ_ASSERT(!mChunkReceiver, "mChunkReceiver should have been emptied"); + // And allocate the requested chunk. This may fail, it's fine, we're + // letting the receiver know about it. + AUTO_PROFILER_STATS(Local_FulfillChunkRequests_GetChunk); + return GetChunk(lock); + }(); + + if (chunkReceiver) { + { + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + if (mUpdateCallback && !chunkAndUpdate.second.IsNotUpdate()) { + mUpdateCallback(std::move(chunkAndUpdate.second)); + } + } + + // Invoke callback outside of lock, so that it can use other chunk manager + // functions if needed. + // Note that this means there could be a race, where another request + // happens now and even gets fulfilled before this one is! It should be + // rare, and shouldn't be a problem anyway, the user will still get their + // requested chunks, new/recycled chunks look the same so their order + // doesn't matter. + std::move(chunkReceiver)(std::move(chunkAndUpdate.first)); + } + } + + void ReleaseChunk(UniquePtr aChunk) final { + if (!aChunk) { + return; + } + + MOZ_RELEASE_ASSERT(!aChunk->GetNext(), "ReleaseChunk only accepts 1 chunk"); + MOZ_RELEASE_ASSERT(!aChunk->ChunkHeader().mDoneTimeStamp.IsNull(), + "Released chunk should have a 'Done' timestamp"); + + Update update = [&]() { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + MOZ_ASSERT(mUser, "Not registered yet"); + // Keep a pointer to the first newly-released chunk, so we can use it to + // prepare an update (after `aChunk` is moved-from). + const ProfileBufferChunk* const newlyReleasedChunk = aChunk.get(); + // Transfer the chunk size from the unreleased bucket to the released one. + mUnreleasedBufferBytes -= aChunk->BufferBytes(); + mReleasedBufferBytes += aChunk->BufferBytes(); + if (!mReleasedChunks) { + // No other released chunks at the moment, we're starting the list. + MOZ_ASSERT(mReleasedBufferBytes == aChunk->BufferBytes()); + mReleasedChunks = std::move(aChunk); + } else { + // Insert aChunk in mReleasedChunks to keep done-timestamp order. + const TimeStamp& releasedChunkDoneTimeStamp = + aChunk->ChunkHeader().mDoneTimeStamp; + if (releasedChunkDoneTimeStamp < + mReleasedChunks->ChunkHeader().mDoneTimeStamp) { + // aChunk is the oldest -> Insert at the beginning. + aChunk->SetLast(std::move(mReleasedChunks)); + mReleasedChunks = std::move(aChunk); + } else { + // Go through the already-released chunk list, and insert aChunk + // before the first younger released chunk, or at the end. + ProfileBufferChunk* chunk = mReleasedChunks.get(); + for (;;) { + ProfileBufferChunk* const nextChunk = chunk->GetNext(); + if (!nextChunk || releasedChunkDoneTimeStamp < + nextChunk->ChunkHeader().mDoneTimeStamp) { + // Either we're at the last released chunk, or the next released + // chunk is younger -> Insert right after this released chunk. + chunk->InsertNext(std::move(aChunk)); + break; + } + chunk = nextChunk; + } + } + } + + return Update(mUnreleasedBufferBytes, mReleasedBufferBytes, + mReleasedChunks.get(), newlyReleasedChunk); + }(); + + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + if (mUpdateCallback && !update.IsNotUpdate()) { + mUpdateCallback(std::move(update)); + } + } + + void SetChunkDestroyedCallback( + std::function&& aChunkDestroyedCallback) + final { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + MOZ_ASSERT(mUser, "Not registered yet"); + mChunkDestroyedCallback = std::move(aChunkDestroyedCallback); + } + + [[nodiscard]] UniquePtr GetExtantReleasedChunks() final { + UniquePtr chunks; + size_t unreleasedBufferBytes = [&]() { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + MOZ_ASSERT(mUser, "Not registered yet"); + mReleasedBufferBytes = 0; + chunks = std::move(mReleasedChunks); + return mUnreleasedBufferBytes; + }(); + + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + if (mUpdateCallback) { + mUpdateCallback(Update(unreleasedBufferBytes, 0, nullptr, nullptr)); + } + + return chunks; + } + + void ForgetUnreleasedChunks() final { + Update update = [&]() { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + MOZ_ASSERT(mUser, "Not registered yet"); + mUnreleasedBufferBytes = 0; + return Update(0, mReleasedBufferBytes, mReleasedChunks.get(), nullptr); + }(); + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + if (mUpdateCallback) { + mUpdateCallback(std::move(update)); + } + } + + [[nodiscard]] size_t SizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const final { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + return SizeOfExcludingThis(aMallocSizeOf, lock); + } + + [[nodiscard]] size_t SizeOfIncludingThis( + MallocSizeOf aMallocSizeOf) const final { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + MOZ_ASSERT(mUser, "Not registered yet"); + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf, lock); + } + + void SetUpdateCallback(UpdateCallback&& aUpdateCallback) final { + { + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + if (mUpdateCallback) { + // Signal the end of the previous callback. + std::move(mUpdateCallback)(Update(nullptr)); + mUpdateCallback = nullptr; + } + } + + if (aUpdateCallback) { + Update initialUpdate = [&]() { + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + return Update(mUnreleasedBufferBytes, mReleasedBufferBytes, + mReleasedChunks.get(), nullptr); + }(); + + baseprofiler::detail::BaseProfilerAutoLock lock(mUpdateCallbackMutex); + MOZ_ASSERT(!mUpdateCallback, "Only one update callback allowed"); + mUpdateCallback = std::move(aUpdateCallback); + mUpdateCallback(std::move(initialUpdate)); + } + } + + void DestroyChunksAtOrBefore(TimeStamp aDoneTimeStamp) final { + MOZ_ASSERT(!aDoneTimeStamp.IsNull()); + baseprofiler::detail::BaseProfilerAutoLock lock(mMutex); + for (;;) { + if (!mReleasedChunks) { + // We don't own any released chunks (anymore), we're done. + break; + } + if (mReleasedChunks->ChunkHeader().mDoneTimeStamp > aDoneTimeStamp) { + // The current chunk is strictly after the given timestamp, we're done. + break; + } + // We've found a chunk at or before the timestamp, discard it. + DiscardOldestReleasedChunk(lock); + } + } + + protected: + const ProfileBufferChunk* PeekExtantReleasedChunksAndLock() final + MOZ_CAPABILITY_ACQUIRE(mMutex) { + mMutex.Lock(); + MOZ_ASSERT(mUser, "Not registered yet"); + return mReleasedChunks.get(); + } + void UnlockAfterPeekExtantReleasedChunks() final + MOZ_CAPABILITY_RELEASE(mMutex) { + mMutex.Unlock(); + } + + private: + size_t MaybeRecycleChunkAndGetDeallocatedSize( + UniquePtr&& chunk, + const baseprofiler::detail::BaseProfilerAutoLock& aLock) { + // Try to recycle big-enough chunks. (All chunks should have the same size, + // but it's a cheap test and may allow future adjustments based on actual + // data rate.) + if (chunk->BufferBytes() >= mChunkMinBufferBytes) { + // We keep up to two recycled chunks at any time. + if (!mRecycledChunks) { + mRecycledChunks = std::move(chunk); + return 0; + } else if (!mRecycledChunks->GetNext()) { + mRecycledChunks->InsertNext(std::move(chunk)); + return 0; + } + } + return moz_malloc_usable_size(chunk.get()); + } + + UniquePtr TakeRecycledChunk( + const baseprofiler::detail::BaseProfilerAutoLock& aLock) { + UniquePtr recycled; + if (mRecycledChunks) { + recycled = std::exchange(mRecycledChunks, mRecycledChunks->ReleaseNext()); + recycled->MarkRecycled(); + } + return recycled; + } + + void DiscardOldestReleasedChunk( + const baseprofiler::detail::BaseProfilerAutoLock& aLock) { + MOZ_ASSERT(!!mReleasedChunks); + UniquePtr oldest = + std::exchange(mReleasedChunks, mReleasedChunks->ReleaseNext()); + mReleasedBufferBytes -= oldest->BufferBytes(); + if (mChunkDestroyedCallback) { + // Inform the user that we're going to destroy this chunk. + mChunkDestroyedCallback(*oldest); + } + + mTotalBytes -= + MaybeRecycleChunkAndGetDeallocatedSize(std::move(oldest), aLock); + } + + using ChunkAndUpdate = std::pair, Update>; + [[nodiscard]] ChunkAndUpdate GetChunk( + const baseprofiler::detail::BaseProfilerAutoLock& aLock) { + MOZ_ASSERT(mUser, "Not registered yet"); + // After this function, the total memory consumption will be the sum of: + // - Bytes from released (i.e., full) chunks, + // - Bytes from unreleased (still in use) chunks, + // - Bytes from the chunk we want to create/recycle. (Note that we don't + // count the extra bytes of chunk header, and of extra allocation ability, + // for the new chunk, as it's assumed to be negligible compared to the + // total memory limit.) + // If this total is higher than the local limit, we'll want to destroy + // the oldest released chunks until we're under the limit; if any, we may + // recycle one of them to avoid a deallocation followed by an allocation. + while (mReleasedBufferBytes + mUnreleasedBufferBytes + + mChunkMinBufferBytes >= + mMaxTotalBytes && + !!mReleasedChunks) { + // We have reached the local limit, discard the oldest released chunk. + DiscardOldestReleasedChunk(aLock); + } + + // Extract the recycled chunk, if any. + ChunkAndUpdate chunkAndUpdate{TakeRecycledChunk(aLock), Update()}; + UniquePtr& chunk = chunkAndUpdate.first; + + if (!chunk) { + // No recycled chunk -> Create a chunk now. (This could still fail.) + chunk = ProfileBufferChunk::Create(mChunkMinBufferBytes); + mTotalBytes += moz_malloc_usable_size(chunk.get()); + } + + if (chunk) { + // We do have a chunk (recycled or new), record its size as "unreleased". + mUnreleasedBufferBytes += chunk->BufferBytes(); + + chunkAndUpdate.second = + Update(mUnreleasedBufferBytes, mReleasedBufferBytes, + mReleasedChunks.get(), nullptr); + } + + return chunkAndUpdate; + } + + [[nodiscard]] size_t SizeOfExcludingThis( + MallocSizeOf aMallocSizeOf, + const baseprofiler::detail::BaseProfilerAutoLock&) const { + MOZ_ASSERT(mUser, "Not registered yet"); + size_t size = 0; + if (mReleasedChunks) { + size += mReleasedChunks->SizeOfIncludingThis(aMallocSizeOf); + } + if (mRecycledChunks) { + size += mRecycledChunks->SizeOfIncludingThis(aMallocSizeOf); + } + // Note: Missing size of std::function external resources (if any). + return size; + } + + // Maxumum number of bytes that should be used by all unreleased and released + // chunks. Note that only released chunks can be destroyed here, so it is the + // responsibility of the user to properly release their chunks when possible. + const size_t mMaxTotalBytes; + + // Minimum number of bytes that new chunks should be able to store. + // Used when calling `ProfileBufferChunk::Create()`. + const Length mChunkMinBufferBytes; + + // Mutex guarding the following members. + mutable baseprofiler::detail::BaseProfilerMutex mMutex; + + // Number of bytes currently held in chunks that have been given away (through + // `GetChunk` or `RequestChunk`) and not released yet. + size_t mUnreleasedBufferBytes = 0; + + // Number of bytes currently held in chunks that have been released and stored + // in `mReleasedChunks` below. + size_t mReleasedBufferBytes = 0; + + // Total allocated size (used to substract it from memory counters). + size_t mTotalBytes = 0; + + // List of all released chunks. The oldest one should be at the start of the + // list, and may be destroyed or recycled when the memory limit is reached. + UniquePtr mReleasedChunks; + + // This may hold chunks that were released then slated for destruction, they + // will be reused next time an allocation would have been needed. + UniquePtr mRecycledChunks; + + // Optional callback used to notify the user when a chunk is about to be + // destroyed or recycled. (The data content is always destroyed, but the chunk + // container may be reused.) + std::function mChunkDestroyedCallback; + + // Callback set from `RequestChunk()`, until it is serviced in + // `FulfillChunkRequests()`. There can only be one request in flight. + std::function)> mChunkReceiver; + + // Separate mutex guarding mUpdateCallback, so that it may be invoked outside + // of the main buffer `mMutex`. + mutable baseprofiler::detail::BaseProfilerMutex mUpdateCallbackMutex; + + UpdateCallback mUpdateCallback; +}; + +} // namespace mozilla + +#endif // ProfileBufferChunkManagerWithLocalLimit_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferControlledChunkManager.h b/src/third_party/mozjs/include/mozilla/ProfileBufferControlledChunkManager.h new file mode 100644 index 00000000000..45b39b163c8 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferControlledChunkManager.h @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferControlledChunkManager_h +#define ProfileBufferControlledChunkManager_h + +#include "mozilla/ProfileBufferChunk.h" + +#include +#include + +namespace mozilla { + +// A "Controlled" chunk manager will provide updates about chunks that it +// creates, releases, and destroys; and it can destroy released chunks as +// requested. +class ProfileBufferControlledChunkManager { + public: + using Length = ProfileBufferChunk::Length; + + virtual ~ProfileBufferControlledChunkManager() = default; + + // Minimum amount of chunk metadata to be transferred between processes. + struct ChunkMetadata { + // Timestamp when chunk was marked "done", which is used to: + // - determine its age, so the oldest one will be destroyed first, + // - uniquely identify this chunk in this process. (The parent process is + // responsible for associating this timestamp to its process id.) + TimeStamp mDoneTimeStamp; + // Size of this chunk's buffer. + Length mBufferBytes; + + ChunkMetadata(TimeStamp aDoneTimeStamp, Length aBufferBytes) + : mDoneTimeStamp(aDoneTimeStamp), mBufferBytes(aBufferBytes) {} + }; + + // Class collecting all information necessary to describe updates that + // happened in a chunk manager. + // An update can be folded into a previous update. + class Update { + public: + // Construct a "not-an-Update" object, which should only be used after a + // real update is folded into it. + Update() = default; + + // Construct a "final" Update, which marks the end of all updates from a + // chunk manager. + explicit Update(decltype(nullptr)) : mUnreleasedBytes(FINAL) {} + + // Construct an Update from the given data and released chunks. + // The chunk pointers may be null, and it doesn't matter if + // `aNewlyReleasedChunks` is already linked to `aExistingReleasedChunks` or + // not. + Update(size_t aUnreleasedBytes, size_t aReleasedBytes, + const ProfileBufferChunk* aExistingReleasedChunks, + const ProfileBufferChunk* aNewlyReleasedChunks) + : mUnreleasedBytes(aUnreleasedBytes), + mReleasedBytes(aReleasedBytes), + mOldestDoneTimeStamp( + aExistingReleasedChunks + ? aExistingReleasedChunks->ChunkHeader().mDoneTimeStamp + : TimeStamp{}) { + MOZ_RELEASE_ASSERT( + !IsNotUpdate(), + "Empty update should only be constructed with default constructor"); + MOZ_RELEASE_ASSERT( + !IsFinal(), + "Final update should only be constructed with nullptr constructor"); + for (const ProfileBufferChunk* chunk = aNewlyReleasedChunks; chunk; + chunk = chunk->GetNext()) { + mNewlyReleasedChunks.emplace_back(ChunkMetadata{ + chunk->ChunkHeader().mDoneTimeStamp, chunk->BufferBytes()}); + } + } + + // Construct an Update from raw data. + // This may be used to re-construct an Update that was previously + // serialized. + Update(size_t aUnreleasedBytes, size_t aReleasedBytes, + TimeStamp aOldestDoneTimeStamp, + std::vector&& aNewlyReleasedChunks) + : mUnreleasedBytes(aUnreleasedBytes), + mReleasedBytes(aReleasedBytes), + mOldestDoneTimeStamp(aOldestDoneTimeStamp), + mNewlyReleasedChunks(std::move(aNewlyReleasedChunks)) {} + + // Clear the Update completely and return it to a "not-an-Update" state. + void Clear() { + mUnreleasedBytes = NO_UPDATE; + mReleasedBytes = 0; + mOldestDoneTimeStamp = TimeStamp{}; + mNewlyReleasedChunks.clear(); + } + + bool IsNotUpdate() const { return mUnreleasedBytes == NO_UPDATE; } + + bool IsFinal() const { return mUnreleasedBytes == FINAL; } + + size_t UnreleasedBytes() const { + MOZ_RELEASE_ASSERT(!IsNotUpdate(), + "Cannot access UnreleasedBytes from empty update"); + MOZ_RELEASE_ASSERT(!IsFinal(), + "Cannot access UnreleasedBytes from final update"); + return mUnreleasedBytes; + } + + size_t ReleasedBytes() const { + MOZ_RELEASE_ASSERT(!IsNotUpdate(), + "Cannot access ReleasedBytes from empty update"); + MOZ_RELEASE_ASSERT(!IsFinal(), + "Cannot access ReleasedBytes from final update"); + return mReleasedBytes; + } + + TimeStamp OldestDoneTimeStamp() const { + MOZ_RELEASE_ASSERT(!IsNotUpdate(), + "Cannot access OldestDoneTimeStamp from empty update"); + MOZ_RELEASE_ASSERT(!IsFinal(), + "Cannot access OldestDoneTimeStamp from final update"); + return mOldestDoneTimeStamp; + } + + const std::vector& NewlyReleasedChunksRef() const { + MOZ_RELEASE_ASSERT( + !IsNotUpdate(), + "Cannot access NewlyReleasedChunksRef from empty update"); + MOZ_RELEASE_ASSERT( + !IsFinal(), "Cannot access NewlyReleasedChunksRef from final update"); + return mNewlyReleasedChunks; + } + + // Fold a later update into this one. + void Fold(Update&& aNewUpdate) { + MOZ_ASSERT( + !IsFinal() || aNewUpdate.IsFinal(), + "There shouldn't be another non-final update after the final update"); + + if (IsNotUpdate() || aNewUpdate.IsFinal()) { + // We were empty, or the new update is the final update, we just switch + // to that new update. + *this = std::move(aNewUpdate); + return; + } + + mUnreleasedBytes = aNewUpdate.mUnreleasedBytes; + mReleasedBytes = aNewUpdate.mReleasedBytes; + if (!aNewUpdate.mOldestDoneTimeStamp.IsNull()) { + MOZ_ASSERT(mOldestDoneTimeStamp.IsNull() || + mOldestDoneTimeStamp <= aNewUpdate.mOldestDoneTimeStamp); + mOldestDoneTimeStamp = aNewUpdate.mOldestDoneTimeStamp; + auto it = mNewlyReleasedChunks.begin(); + while (it != mNewlyReleasedChunks.end() && + it->mDoneTimeStamp < mOldestDoneTimeStamp) { + it = mNewlyReleasedChunks.erase(it); + } + } + if (!aNewUpdate.mNewlyReleasedChunks.empty()) { + mNewlyReleasedChunks.reserve(mNewlyReleasedChunks.size() + + aNewUpdate.mNewlyReleasedChunks.size()); + mNewlyReleasedChunks.insert(mNewlyReleasedChunks.end(), + aNewUpdate.mNewlyReleasedChunks.begin(), + aNewUpdate.mNewlyReleasedChunks.end()); + } + } + + private: + static const size_t NO_UPDATE = size_t(-1); + static const size_t FINAL = size_t(-2); + + size_t mUnreleasedBytes = NO_UPDATE; + size_t mReleasedBytes = 0; + TimeStamp mOldestDoneTimeStamp; + std::vector mNewlyReleasedChunks; + }; + + using UpdateCallback = std::function; + + // This *may* be set (or reset) by an object that needs to know about all + // chunk updates that happen in this manager. The main use will be to + // coordinate the global memory usage of Firefox. + // If a non-empty callback is given, it will be immediately invoked with the + // current state. + // When the callback is about to be destroyed (by overwriting it here, or in + // the class destructor), it will be invoked one last time with an empty + // update. + // Note that the callback (even the first current-state callback) will be + // invoked from inside a locked scope, so it should *not* call other functions + // of the chunk manager. A side benefit of this locking is that it guarantees + // that no two invocations can overlap. + virtual void SetUpdateCallback(UpdateCallback&& aUpdateCallback) = 0; + + // This is a request to destroy all chunks before the given timestamp. + // This timestamp should be one that was given in a previous UpdateCallback + // call. Obviously, only released chunks can be destroyed. + virtual void DestroyChunksAtOrBefore(TimeStamp aDoneTimeStamp) = 0; +}; + +} // namespace mozilla + +#endif // ProfileBufferControlledChunkManager_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferEntryKinds.h b/src/third_party/mozjs/include/mozilla/ProfileBufferEntryKinds.h new file mode 100644 index 00000000000..bffe5cfac5e --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferEntryKinds.h @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferEntryKinds_h +#define ProfileBufferEntryKinds_h + +#include "mozilla/BaseProfilerUtils.h" + +#include + +namespace mozilla { + +// This is equal to sizeof(double), which is the largest non-char variant in +// |u|. +static constexpr size_t ProfileBufferEntryNumChars = 8; + +// NOTE! If you add entries, you need to verify if they need to be added to the +// switch statement in DuplicateLastSample! +// This will evaluate the MACRO with (KIND, TYPE, SIZE) +#define FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(MACRO) \ + MACRO(CategoryPair, int, sizeof(int)) \ + MACRO(CollectionStart, double, sizeof(double)) \ + MACRO(CollectionEnd, double, sizeof(double)) \ + MACRO(Label, const char*, sizeof(const char*)) \ + MACRO(FrameFlags, uint64_t, sizeof(uint64_t)) \ + MACRO(DynamicStringFragment, char*, ProfileBufferEntryNumChars) \ + MACRO(JitReturnAddr, void*, sizeof(void*)) \ + MACRO(InnerWindowID, uint64_t, sizeof(uint64_t)) \ + MACRO(LineNumber, int, sizeof(int)) \ + MACRO(ColumnNumber, int, sizeof(int)) \ + MACRO(NativeLeafAddr, void*, sizeof(void*)) \ + MACRO(Pause, double, sizeof(double)) \ + MACRO(Resume, double, sizeof(double)) \ + MACRO(PauseSampling, double, sizeof(double)) \ + MACRO(ResumeSampling, double, sizeof(double)) \ + MACRO(Responsiveness, double, sizeof(double)) \ + MACRO(ThreadId, ::mozilla::baseprofiler::BaseProfilerThreadId, \ + sizeof(::mozilla::baseprofiler::BaseProfilerThreadId)) \ + MACRO(Time, double, sizeof(double)) \ + MACRO(TimeBeforeCompactStack, double, sizeof(double)) \ + MACRO(TimeBeforeSameSample, double, sizeof(double)) \ + MACRO(CounterId, void*, sizeof(void*)) \ + MACRO(Number, uint64_t, sizeof(uint64_t)) \ + MACRO(Count, int64_t, sizeof(int64_t)) \ + MACRO(ProfilerOverheadTime, double, sizeof(double)) \ + MACRO(ProfilerOverheadDuration, double, sizeof(double)) + +// The `Kind` is a single byte identifying the type of data that is actually +// stored in a `ProfileBufferEntry`, as per the list in +// `FOR_EACH_PROFILE_BUFFER_ENTRY_KIND`. +// +// This byte is also used to identify entries in ProfileChunkedBuffer blocks, +// for both "legacy" entries that do contain a `ProfileBufferEntry`, and for +// new types of entries that may carry more data of different types. +// TODO: Eventually each type of "legacy" entry should be replaced with newer, +// more efficient kinds of entries (e.g., stack frames could be stored in one +// bigger entry, instead of multiple `ProfileBufferEntry`s); then we could +// discard `ProfileBufferEntry` and move this enum to a more appropriate spot. +enum class ProfileBufferEntryKind : uint8_t { + INVALID = 0, +#define KIND(KIND, TYPE, SIZE) KIND, + FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(KIND) +#undef KIND + + // Any value under `LEGACY_LIMIT` represents a `ProfileBufferEntry`. + LEGACY_LIMIT, + + // Any value starting here does *not* represent a `ProfileBufferEntry` and + // requires separate decoding and handling. + + // Markers and their data. + Marker = LEGACY_LIMIT, + + // Entry with "running times", such as CPU usage measurements. + // Optional between TimeBeforeX and X. + RunningTimes, + + // Optional between TimeBeforeX and X. + UnresponsiveDurationMs, + + // Collection of legacy stack entries, must follow a ThreadId and + // TimeBeforeCompactStack (which are not included in the CompactStack; + // TimeBeforeCompactStack is equivalent to Time, but indicates that a + // CompactStack follows shortly afterwards). + CompactStack, + + // Indicates that this sample is identical to the previous one, must follow a + // ThreadId and TimeBeforeSameSample. + SameSample, + + MODERN_LIMIT +}; + +enum class MarkerPayloadType : uint8_t { + Cpp, + Rust, +}; + +} // namespace mozilla + +#endif // ProfileBufferEntryKinds_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferEntrySerialization.h b/src/third_party/mozjs/include/mozilla/ProfileBufferEntrySerialization.h new file mode 100644 index 00000000000..4daec91ac50 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferEntrySerialization.h @@ -0,0 +1,1184 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferEntrySerialization_h +#define ProfileBufferEntrySerialization_h + +#include "mozilla/Assertions.h" +#include "mozilla/leb128iterator.h" +#include "mozilla/Likely.h" +#include "mozilla/Maybe.h" +#include "mozilla/ProfileBufferIndex.h" +#include "mozilla/Span.h" +#include "mozilla/UniquePtrExtensions.h" +#include "mozilla/Unused.h" +#include "mozilla/Variant.h" + +#include +#include + +namespace mozilla { + +class ProfileBufferEntryWriter; + +// Iterator-like class used to read from an entry. +// An entry may be split in two memory segments (e.g., the ends of a ring +// buffer, or two chunks of a chunked buffer); it doesn't deal with this +// underlying buffer, but only with one or two spans pointing at the space +// where the entry lives. +class ProfileBufferEntryReader { + public: + using Byte = uint8_t; + using Length = uint32_t; + + using SpanOfConstBytes = Span; + + // Class to be specialized for types to be read from a profile buffer entry. + // See common specializations at the bottom of this header. + // The following static functions must be provided: + // static void ReadInto(EntryReader aER&, T& aT) + // { + // /* Call `aER.ReadX(...)` function to deserialize into aT, be sure to + // read exactly `Bytes(aT)`! */ + // } + // static T Read(EntryReader& aER) { + // /* Call `aER.ReadX(...)` function to deserialize and return a `T`, be + // sure to read exactly `Bytes(returned value)`! */ + // } + template + struct Deserializer; + + ProfileBufferEntryReader() = default; + + // Reader over one Span. + ProfileBufferEntryReader(SpanOfConstBytes aSpan, + ProfileBufferBlockIndex aCurrentBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) + : mCurrentSpan(aSpan), + mNextSpanOrEmpty(aSpan.Last(0)), + mCurrentBlockIndex(aCurrentBlockIndex), + mNextBlockIndex(aNextBlockIndex) { + // 2nd internal Span points at the end of the 1st internal Span, to enforce + // invariants. + CheckInvariants(); + } + + // Reader over two Spans, the second one must not be empty. + ProfileBufferEntryReader(SpanOfConstBytes aSpanHead, + SpanOfConstBytes aSpanTail, + ProfileBufferBlockIndex aCurrentBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) + : mCurrentSpan(aSpanHead), + mNextSpanOrEmpty(aSpanTail), + mCurrentBlockIndex(aCurrentBlockIndex), + mNextBlockIndex(aNextBlockIndex) { + MOZ_RELEASE_ASSERT(!mNextSpanOrEmpty.IsEmpty()); + if (MOZ_UNLIKELY(mCurrentSpan.IsEmpty())) { + // First span is already empty, skip it. + mCurrentSpan = mNextSpanOrEmpty; + mNextSpanOrEmpty = mNextSpanOrEmpty.Last(0); + } + CheckInvariants(); + } + + // Allow copying, which is needed when used as an iterator in some std + // functions (e.g., string assignment), and to occasionally backtrack. + // Be aware that the main profile buffer APIs give a reference to an entry + // reader, and expect that reader to advance to the end of the entry, so don't + // just advance copies! + ProfileBufferEntryReader(const ProfileBufferEntryReader&) = default; + ProfileBufferEntryReader& operator=(const ProfileBufferEntryReader&) = + default; + + // Don't =default moving, as it doesn't bring any benefit in this class. + + [[nodiscard]] Length RemainingBytes() const { + return mCurrentSpan.LengthBytes() + mNextSpanOrEmpty.LengthBytes(); + } + + void SetRemainingBytes(Length aBytes) { + MOZ_RELEASE_ASSERT(aBytes <= RemainingBytes()); + if (aBytes <= mCurrentSpan.LengthBytes()) { + mCurrentSpan = mCurrentSpan.First(aBytes); + mNextSpanOrEmpty = mCurrentSpan.Last(0); + } else { + mNextSpanOrEmpty = + mNextSpanOrEmpty.First(aBytes - mCurrentSpan.LengthBytes()); + } + } + + [[nodiscard]] ProfileBufferBlockIndex CurrentBlockIndex() const { + return mCurrentBlockIndex; + } + + [[nodiscard]] ProfileBufferBlockIndex NextBlockIndex() const { + return mNextBlockIndex; + } + + // Create a reader of size zero, pointing at aOffset past the current position + // of this Reader, so it can be used as end iterator. + [[nodiscard]] ProfileBufferEntryReader EmptyIteratorAtOffset( + Length aOffset) const { + MOZ_RELEASE_ASSERT(aOffset <= RemainingBytes()); + if (MOZ_LIKELY(aOffset < mCurrentSpan.LengthBytes())) { + // aOffset is before the end of mCurrentSpan. + return ProfileBufferEntryReader(mCurrentSpan.Subspan(aOffset, 0), + mCurrentBlockIndex, mNextBlockIndex); + } + // aOffset is right at the end of mCurrentSpan, or inside mNextSpanOrEmpty. + return ProfileBufferEntryReader( + mNextSpanOrEmpty.Subspan(aOffset - mCurrentSpan.LengthBytes(), 0), + mCurrentBlockIndex, mNextBlockIndex); + } + + // Be like a limited input iterator, with only `*`, prefix-`++`, `==`, `!=`. + // These definitions are expected by std functions, to recognize this as an + // iterator. See https://en.cppreference.com/w/cpp/iterator/iterator_traits + using difference_type = std::make_signed_t; + using value_type = Byte; + using pointer = const Byte*; + using reference = const Byte&; + using iterator_category = std::input_iterator_tag; + + [[nodiscard]] const Byte& operator*() { + // Assume the caller will read from the returned reference (and not just + // take the address). + MOZ_RELEASE_ASSERT(mCurrentSpan.LengthBytes() >= 1); + return *(mCurrentSpan.Elements()); + } + + ProfileBufferEntryReader& operator++() { + MOZ_RELEASE_ASSERT(mCurrentSpan.LengthBytes() >= 1); + if (MOZ_LIKELY(mCurrentSpan.LengthBytes() > 1)) { + // More than 1 byte left in mCurrentSpan, just eat it. + mCurrentSpan = mCurrentSpan.From(1); + } else { + // mCurrentSpan will be empty, move mNextSpanOrEmpty to mCurrentSpan. + mCurrentSpan = mNextSpanOrEmpty; + mNextSpanOrEmpty = mNextSpanOrEmpty.Last(0); + } + CheckInvariants(); + return *this; + } + + ProfileBufferEntryReader& operator+=(Length aBytes) { + MOZ_RELEASE_ASSERT(aBytes <= RemainingBytes()); + if (MOZ_LIKELY(aBytes <= mCurrentSpan.LengthBytes())) { + // All bytes are in mCurrentSpan. + // Update mCurrentSpan past the read bytes. + mCurrentSpan = mCurrentSpan.From(aBytes); + if (mCurrentSpan.IsEmpty() && !mNextSpanOrEmpty.IsEmpty()) { + // Don't leave mCurrentSpan empty, move non-empty mNextSpanOrEmpty into + // mCurrentSpan. + mCurrentSpan = mNextSpanOrEmpty; + mNextSpanOrEmpty = mNextSpanOrEmpty.Last(0); + } + } else { + // mCurrentSpan does not hold enough bytes. + // This should only happen at most once: Only for double spans, and when + // data crosses the gap. + const Length tail = + aBytes - static_cast(mCurrentSpan.LengthBytes()); + // Move mNextSpanOrEmpty to mCurrentSpan, past the data. So the next call + // will go back to the true case above. + mCurrentSpan = mNextSpanOrEmpty.From(tail); + mNextSpanOrEmpty = mNextSpanOrEmpty.Last(0); + } + CheckInvariants(); + return *this; + } + + [[nodiscard]] bool operator==(const ProfileBufferEntryReader& aOther) const { + return mCurrentSpan.Elements() == aOther.mCurrentSpan.Elements(); + } + [[nodiscard]] bool operator!=(const ProfileBufferEntryReader& aOther) const { + return mCurrentSpan.Elements() != aOther.mCurrentSpan.Elements(); + } + + // Read an unsigned LEB128 number and move iterator ahead. + template + [[nodiscard]] T ReadULEB128() { + return ::mozilla::ReadULEB128(*this); + } + + // This struct points at a number of bytes through either one span, or two + // separate spans (in the rare cases when it is split between two chunks). + // So the possibilities are: + // - Totally empty: { [] [] } + // - First span is not empty: { [content] [] } (Most common case.) + // - Both spans are not empty: { [cont] [ent] } + // But something like { [] [content] } is not possible. + // + // Recommended usage patterns: + // - Call a utility function like `CopyBytesTo` if you always need to copy the + // data to an outside buffer, e.g., to deserialize an aligned object. + // - Access both spans one after the other; Note that the second one may be + // empty; and the fist could be empty as well if there is no data at all. + // - Check is the second span is empty, in which case you only need to read + // the first one; and since its part of a chunk, it may be directly passed + // as an unaligned pointer or reference, thereby saving one copy. But + // remember to always handle the double-span case as well. + // + // Reminder: An empty span still has a non-null pointer, so it's safe to use + // with functions like memcpy. + struct DoubleSpanOfConstBytes { + SpanOfConstBytes mFirstOrOnly; + SpanOfConstBytes mSecondOrEmpty; + + void CheckInvariants() const { + MOZ_ASSERT(mFirstOrOnly.IsEmpty() ? mSecondOrEmpty.IsEmpty() : true, + "mSecondOrEmpty should not be the only span to contain data"); + } + + DoubleSpanOfConstBytes() : mFirstOrOnly(), mSecondOrEmpty() { + CheckInvariants(); + } + + DoubleSpanOfConstBytes(const Byte* aOnlyPointer, size_t aOnlyLength) + : mFirstOrOnly(aOnlyPointer, aOnlyLength), mSecondOrEmpty() { + CheckInvariants(); + } + + DoubleSpanOfConstBytes(const Byte* aFirstPointer, size_t aFirstLength, + const Byte* aSecondPointer, size_t aSecondLength) + : mFirstOrOnly(aFirstPointer, aFirstLength), + mSecondOrEmpty(aSecondPointer, aSecondLength) { + CheckInvariants(); + } + + // Is there no data at all? + [[nodiscard]] bool IsEmpty() const { + // We only need to check the first span, because if it's empty, the second + // one must be empty as well. + return mFirstOrOnly.IsEmpty(); + } + + // Total length (in bytes) pointed at by both spans. + [[nodiscard]] size_t LengthBytes() const { + return mFirstOrOnly.LengthBytes() + mSecondOrEmpty.LengthBytes(); + } + + // Utility functions to copy all `LengthBytes()` to a given buffer. + void CopyBytesTo(void* aDest) const { + memcpy(aDest, mFirstOrOnly.Elements(), mFirstOrOnly.LengthBytes()); + if (MOZ_UNLIKELY(!mSecondOrEmpty.IsEmpty())) { + memcpy(static_cast(aDest) + mFirstOrOnly.LengthBytes(), + mSecondOrEmpty.Elements(), mSecondOrEmpty.LengthBytes()); + } + } + + // If the second span is empty, only the first span may point at data. + [[nodiscard]] bool IsSingleSpan() const { return mSecondOrEmpty.IsEmpty(); } + }; + + // Get Span(s) to a sequence of bytes, see `DoubleSpanOfConstBytes` for usage. + // Note that the reader location is *not* updated, do `+=` on it afterwards. + [[nodiscard]] DoubleSpanOfConstBytes PeekSpans(Length aBytes) const { + MOZ_RELEASE_ASSERT(aBytes <= RemainingBytes()); + if (MOZ_LIKELY(aBytes <= mCurrentSpan.LengthBytes())) { + // All `aBytes` are in the current chunk, only one span is needed. + return DoubleSpanOfConstBytes{mCurrentSpan.Elements(), aBytes}; + } + // Otherwise the first span covers then end of the current chunk, and the + // second span starts in the next chunk. + return DoubleSpanOfConstBytes{ + mCurrentSpan.Elements(), mCurrentSpan.LengthBytes(), + mNextSpanOrEmpty.Elements(), aBytes - mCurrentSpan.LengthBytes()}; + } + + // Get Span(s) to a sequence of bytes, see `DoubleSpanOfConstBytes` for usage, + // and move the reader forward. + [[nodiscard]] DoubleSpanOfConstBytes ReadSpans(Length aBytes) { + DoubleSpanOfConstBytes spans = PeekSpans(aBytes); + (*this) += aBytes; + return spans; + } + + // Read a sequence of bytes, like memcpy. + void ReadBytes(void* aDest, Length aBytes) { + DoubleSpanOfConstBytes spans = ReadSpans(aBytes); + MOZ_ASSERT(spans.LengthBytes() == aBytes); + spans.CopyBytesTo(aDest); + } + + template + void ReadIntoObject(T& aObject) { + Deserializer::ReadInto(*this, aObject); + } + + // Read into one or more objects, sequentially. + // `EntryReader::ReadIntoObjects()` with nothing is implicitly allowed, this + // could be useful for generic programming. + template + void ReadIntoObjects(Ts&... aTs) { + (ReadIntoObject(aTs), ...); + } + + // Read data as an object and move iterator ahead. + template + [[nodiscard]] T ReadObject() { + T ob = Deserializer::Read(*this); + return ob; + } + + private: + friend class ProfileBufferEntryWriter; + + // Invariants: + // - mCurrentSpan cannot be empty unless mNextSpanOrEmpty is also empty. So + // mCurrentSpan always points at the next byte to read or the end. + // - If mNextSpanOrEmpty is empty, it points at the end of mCurrentSpan. So + // when reaching the end of mCurrentSpan, we can blindly move + // mNextSpanOrEmpty to mCurrentSpan and keep the invariants. + SpanOfConstBytes mCurrentSpan; + SpanOfConstBytes mNextSpanOrEmpty; + ProfileBufferBlockIndex mCurrentBlockIndex; + ProfileBufferBlockIndex mNextBlockIndex; + + void CheckInvariants() const { + MOZ_ASSERT(!mCurrentSpan.IsEmpty() || mNextSpanOrEmpty.IsEmpty()); + MOZ_ASSERT(!mNextSpanOrEmpty.IsEmpty() || + (mNextSpanOrEmpty == mCurrentSpan.Last(0))); + } +}; + +// Iterator-like class used to write into an entry. +// An entry may be split in two memory segments (e.g., the ends of a ring +// buffer, or two chunks of a chunked buffer); it doesn't deal with this +// underlying buffer, but only with one or two spans pointing at the space +// reserved for the entry. +class ProfileBufferEntryWriter { + public: + using Byte = uint8_t; + using Length = uint32_t; + + using SpanOfBytes = Span; + + // Class to be specialized for types to be written in an entry. + // See common specializations at the bottom of this header. + // The following static functions must be provided: + // static Length Bytes(const T& aT) { + // /* Return number of bytes that will be written. */ + // } + // static void Write(ProfileBufferEntryWriter& aEW, + // const T& aT) { + // /* Call `aEW.WriteX(...)` functions to serialize aT, be sure to write + // exactly `Bytes(aT)` bytes! */ + // } + template + struct Serializer; + + ProfileBufferEntryWriter() = default; + + ProfileBufferEntryWriter(SpanOfBytes aSpan, + ProfileBufferBlockIndex aCurrentBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) + : mCurrentSpan(aSpan), + mCurrentBlockIndex(aCurrentBlockIndex), + mNextBlockIndex(aNextBlockIndex) {} + + ProfileBufferEntryWriter(SpanOfBytes aSpanHead, SpanOfBytes aSpanTail, + ProfileBufferBlockIndex aCurrentBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) + : mCurrentSpan(aSpanHead), + mNextSpanOrEmpty(aSpanTail), + mCurrentBlockIndex(aCurrentBlockIndex), + mNextBlockIndex(aNextBlockIndex) { + // Either: + // - mCurrentSpan is not empty, OR + // - mNextSpanOrEmpty is empty if mNextSpanOrEmpty is empty as well. + MOZ_RELEASE_ASSERT(!mCurrentSpan.IsEmpty() || mNextSpanOrEmpty.IsEmpty()); + } + + // Disable copying and moving, so we can't have multiple writing heads. + ProfileBufferEntryWriter(const ProfileBufferEntryWriter&) = delete; + ProfileBufferEntryWriter& operator=(const ProfileBufferEntryWriter&) = delete; + ProfileBufferEntryWriter(ProfileBufferEntryWriter&&) = delete; + ProfileBufferEntryWriter& operator=(ProfileBufferEntryWriter&&) = delete; + + void Set() { + mCurrentSpan = SpanOfBytes{}; + mNextSpanOrEmpty = SpanOfBytes{}; + mCurrentBlockIndex = nullptr; + mNextBlockIndex = nullptr; + } + + void Set(SpanOfBytes aSpan, ProfileBufferBlockIndex aCurrentBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) { + mCurrentSpan = aSpan; + mNextSpanOrEmpty = SpanOfBytes{}; + mCurrentBlockIndex = aCurrentBlockIndex; + mNextBlockIndex = aNextBlockIndex; + } + + void Set(SpanOfBytes aSpan0, SpanOfBytes aSpan1, + ProfileBufferBlockIndex aCurrentBlockIndex, + ProfileBufferBlockIndex aNextBlockIndex) { + mCurrentSpan = aSpan0; + mNextSpanOrEmpty = aSpan1; + mCurrentBlockIndex = aCurrentBlockIndex; + mNextBlockIndex = aNextBlockIndex; + // Either: + // - mCurrentSpan is not empty, OR + // - mNextSpanOrEmpty is empty if mNextSpanOrEmpty is empty as well. + MOZ_RELEASE_ASSERT(!mCurrentSpan.IsEmpty() || mNextSpanOrEmpty.IsEmpty()); + } + + [[nodiscard]] Length RemainingBytes() const { + return mCurrentSpan.LengthBytes() + mNextSpanOrEmpty.LengthBytes(); + } + + [[nodiscard]] ProfileBufferBlockIndex CurrentBlockIndex() const { + return mCurrentBlockIndex; + } + + [[nodiscard]] ProfileBufferBlockIndex NextBlockIndex() const { + return mNextBlockIndex; + } + + // Be like a limited output iterator, with only `*` and prefix-`++`. + // These definitions are expected by std functions, to recognize this as an + // iterator. See https://en.cppreference.com/w/cpp/iterator/iterator_traits + using value_type = Byte; + using pointer = Byte*; + using reference = Byte&; + using iterator_category = std::output_iterator_tag; + + [[nodiscard]] Byte& operator*() { + MOZ_RELEASE_ASSERT(RemainingBytes() >= 1); + return *( + (MOZ_LIKELY(!mCurrentSpan.IsEmpty()) ? mCurrentSpan : mNextSpanOrEmpty) + .Elements()); + } + + ProfileBufferEntryWriter& operator++() { + if (MOZ_LIKELY(mCurrentSpan.LengthBytes() >= 1)) { + // There is at least 1 byte in mCurrentSpan, eat it. + mCurrentSpan = mCurrentSpan.From(1); + } else { + // mCurrentSpan is empty, move mNextSpanOrEmpty (past the first byte) to + // mCurrentSpan. + MOZ_RELEASE_ASSERT(mNextSpanOrEmpty.LengthBytes() >= 1); + mCurrentSpan = mNextSpanOrEmpty.From(1); + mNextSpanOrEmpty = mNextSpanOrEmpty.First(0); + } + return *this; + } + + ProfileBufferEntryWriter& operator+=(Length aBytes) { + // Note: This is a rare operation. The code below is a copy of `WriteBytes` + // but without the `memcpy`s. + MOZ_RELEASE_ASSERT(aBytes <= RemainingBytes()); + if (MOZ_LIKELY(aBytes <= mCurrentSpan.LengthBytes())) { + // Data fits in mCurrentSpan. + // Update mCurrentSpan. It may become empty, so in case of a double span, + // the next call will go to the false case below. + mCurrentSpan = mCurrentSpan.From(aBytes); + } else { + // Data does not fully fit in mCurrentSpan. + // This should only happen at most once: Only for double spans, and when + // data crosses the gap or starts there. + const Length tail = + aBytes - static_cast(mCurrentSpan.LengthBytes()); + // Move mNextSpanOrEmpty to mCurrentSpan, past the data. So the next call + // will go back to the true case above. + mCurrentSpan = mNextSpanOrEmpty.From(tail); + mNextSpanOrEmpty = mNextSpanOrEmpty.First(0); + } + return *this; + } + + // Number of bytes needed to represent `aValue` in unsigned LEB128. + template + [[nodiscard]] static unsigned ULEB128Size(T aValue) { + return ::mozilla::ULEB128Size(aValue); + } + + // Write number as unsigned LEB128 and move iterator ahead. + template + void WriteULEB128(T aValue) { + ::mozilla::WriteULEB128(aValue, *this); + } + + // Number of bytes needed to serialize objects. + template + [[nodiscard]] static Length SumBytes(const Ts&... aTs) { + return (0 + ... + Serializer::Bytes(aTs)); + } + + // Write a sequence of bytes, like memcpy. + void WriteBytes(const void* aSrc, Length aBytes) { + MOZ_RELEASE_ASSERT(aBytes <= RemainingBytes()); + if (MOZ_LIKELY(aBytes <= mCurrentSpan.LengthBytes())) { + // Data fits in mCurrentSpan. + memcpy(mCurrentSpan.Elements(), aSrc, aBytes); + // Update mCurrentSpan. It may become empty, so in case of a double span, + // the next call will go to the false case below. + mCurrentSpan = mCurrentSpan.From(aBytes); + } else { + // Data does not fully fit in mCurrentSpan. + // This should only happen at most once: Only for double spans, and when + // data crosses the gap or starts there. + // Split data between the end of mCurrentSpan and the beginning of + // mNextSpanOrEmpty. (mCurrentSpan could be empty, it's ok to do a memcpy + // because Span::Elements() is never null.) + memcpy(mCurrentSpan.Elements(), aSrc, mCurrentSpan.LengthBytes()); + const Length tail = + aBytes - static_cast(mCurrentSpan.LengthBytes()); + memcpy(mNextSpanOrEmpty.Elements(), + reinterpret_cast(aSrc) + mCurrentSpan.LengthBytes(), + tail); + // Move mNextSpanOrEmpty to mCurrentSpan, past the data. So the next call + // will go back to the true case above. + mCurrentSpan = mNextSpanOrEmpty.From(tail); + mNextSpanOrEmpty = mNextSpanOrEmpty.First(0); + } + } + + void WriteFromReader(ProfileBufferEntryReader& aReader, Length aBytes) { + MOZ_RELEASE_ASSERT(aBytes <= RemainingBytes()); + MOZ_RELEASE_ASSERT(aBytes <= aReader.RemainingBytes()); + Length read0 = std::min( + aBytes, static_cast(aReader.mCurrentSpan.LengthBytes())); + if (read0 != 0) { + WriteBytes(aReader.mCurrentSpan.Elements(), read0); + } + Length read1 = aBytes - read0; + if (read1 != 0) { + WriteBytes(aReader.mNextSpanOrEmpty.Elements(), read1); + } + aReader += aBytes; + } + + // Write a single object by using the appropriate Serializer. + template + void WriteObject(const T& aObject) { + Serializer::Write(*this, aObject); + } + + // Write one or more objects, sequentially. + // Allow `EntryWrite::WriteObjects()` with nothing, this could be useful + // for generic programming. + template + void WriteObjects(const Ts&... aTs) { + (WriteObject(aTs), ...); + } + + private: + // The two spans covering the memory still to be written. + SpanOfBytes mCurrentSpan; + SpanOfBytes mNextSpanOrEmpty; + ProfileBufferBlockIndex mCurrentBlockIndex; + ProfileBufferBlockIndex mNextBlockIndex; +}; + +// ============================================================================ +// Serializer and Deserializer ready-to-use specializations. + +// ---------------------------------------------------------------------------- +// Trivially-copyable types (default) + +// The default implementation works for all trivially-copyable types (e.g., +// PODs). +// +// Usage: `aEW.WriteObject(123);`. +// +// Raw pointers, though trivially-copyable, are explicitly forbidden when +// writing (to avoid unexpected leaks/UAFs), instead use one of +// `WrapProfileBufferLiteralCStringPointer`, `WrapProfileBufferUnownedCString`, +// or `WrapProfileBufferRawPointer` as needed. +template +struct ProfileBufferEntryWriter::Serializer { + static_assert(std::is_trivially_copyable_v, + "Serializer only works with trivially-copyable types by " + "default, use/add specialization for other types."); + + static constexpr Length Bytes(const T&) { return sizeof(T); } + + static void Write(ProfileBufferEntryWriter& aEW, const T& aT) { + static_assert(!std::is_pointer::value, + "Serializer won't write raw pointers by default, use " + "WrapProfileBufferRawPointer or other."); + aEW.WriteBytes(&aT, sizeof(T)); + } +}; + +// Usage: `aER.ReadObject();` or `int x; aER.ReadIntoObject(x);`. +template +struct ProfileBufferEntryReader::Deserializer { + static_assert(std::is_trivially_copyable_v, + "Deserializer only works with trivially-copyable types by " + "default, use/add specialization for other types."); + + static void ReadInto(ProfileBufferEntryReader& aER, T& aT) { + aER.ReadBytes(&aT, sizeof(T)); + } + + static T Read(ProfileBufferEntryReader& aER) { + // Note that this creates a default `T` first, and then overwrites it with + // bytes from the buffer. Trivially-copyable types support this without UB. + T ob; + ReadInto(aER, ob); + return ob; + } +}; + +// ---------------------------------------------------------------------------- +// Strip const/volatile/reference from types. + +// Automatically strip `const`. +template +struct ProfileBufferEntryWriter::Serializer + : public ProfileBufferEntryWriter::Serializer {}; + +template +struct ProfileBufferEntryReader::Deserializer + : public ProfileBufferEntryReader::Deserializer {}; + +// Automatically strip `volatile`. +template +struct ProfileBufferEntryWriter::Serializer + : public ProfileBufferEntryWriter::Serializer {}; + +template +struct ProfileBufferEntryReader::Deserializer + : public ProfileBufferEntryReader::Deserializer {}; + +// Automatically strip `lvalue-reference`. +template +struct ProfileBufferEntryWriter::Serializer + : public ProfileBufferEntryWriter::Serializer {}; + +template +struct ProfileBufferEntryReader::Deserializer + : public ProfileBufferEntryReader::Deserializer {}; + +// Automatically strip `rvalue-reference`. +template +struct ProfileBufferEntryWriter::Serializer + : public ProfileBufferEntryWriter::Serializer {}; + +template +struct ProfileBufferEntryReader::Deserializer + : public ProfileBufferEntryReader::Deserializer {}; + +// ---------------------------------------------------------------------------- +// ProfileBufferBlockIndex + +// ProfileBufferBlockIndex, serialized as the underlying value. +template <> +struct ProfileBufferEntryWriter::Serializer { + static constexpr Length Bytes(const ProfileBufferBlockIndex& aBlockIndex) { + return sizeof(ProfileBufferBlockIndex); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const ProfileBufferBlockIndex& aBlockIndex) { + aEW.WriteBytes(&aBlockIndex, sizeof(aBlockIndex)); + } +}; + +template <> +struct ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, + ProfileBufferBlockIndex& aBlockIndex) { + aER.ReadBytes(&aBlockIndex, sizeof(aBlockIndex)); + } + + static ProfileBufferBlockIndex Read(ProfileBufferEntryReader& aER) { + ProfileBufferBlockIndex blockIndex; + ReadInto(aER, blockIndex); + return blockIndex; + } +}; + +// ---------------------------------------------------------------------------- +// Literal C string pointer + +// Wrapper around a pointer to a literal C string. +template +struct ProfileBufferLiteralCStringPointer { + const char* mCString; +}; + +// Wrap a pointer to a literal C string. +template +ProfileBufferLiteralCStringPointer +WrapProfileBufferLiteralCStringPointer( + const char (&aCString)[CharactersIncludingTerminal]) { + return {aCString}; +} + +// Literal C strings, serialized as the raw pointer because it is unique and +// valid for the whole program lifetime. +// +// Usage: `aEW.WriteObject(WrapProfileBufferLiteralCStringPointer("hi"));`. +// +// No deserializer is provided for this type, instead it must be deserialized as +// a raw pointer: `aER.ReadObject();` +template +struct ProfileBufferEntryReader::Deserializer< + ProfileBufferLiteralCStringPointer> { + static constexpr Length Bytes( + const ProfileBufferLiteralCStringPointer&) { + // We're only storing a pointer, its size is independent from the pointer + // value. + return sizeof(const char*); + } + + static void Write( + ProfileBufferEntryWriter& aEW, + const ProfileBufferLiteralCStringPointer& + aWrapper) { + // Write the pointer *value*, not the string contents. + aEW.WriteBytes(aWrapper.mCString, sizeof(aWrapper.mCString)); + } +}; + +// ---------------------------------------------------------------------------- +// C string contents + +// Wrapper around a pointer to a C string whose contents will be serialized. +struct ProfileBufferUnownedCString { + const char* mCString; +}; + +// Wrap a pointer to a C string whose contents will be serialized. +inline ProfileBufferUnownedCString WrapProfileBufferUnownedCString( + const char* aCString) { + return {aCString}; +} + +// The contents of a (probably) unowned C string are serialized as the number of +// characters (encoded as ULEB128) and all the characters in the string. The +// terminal '\0' is omitted. +// +// Usage: `aEW.WriteObject(WrapProfileBufferUnownedCString(str.c_str()))`. +// +// No deserializer is provided for this pointer type, instead it must be +// deserialized as one of the other string types that manages its contents, +// e.g.: `aER.ReadObject();` +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(const ProfileBufferUnownedCString& aS) { + const auto len = strlen(aS.mCString); + return ULEB128Size(len) + len; + } + + static void Write(ProfileBufferEntryWriter& aEW, + const ProfileBufferUnownedCString& aS) { + const auto len = strlen(aS.mCString); + aEW.WriteULEB128(len); + aEW.WriteBytes(aS.mCString, len); + } +}; + +// ---------------------------------------------------------------------------- +// Raw pointers + +// Wrapper around a pointer to be serialized as the raw pointer value. +template +struct ProfileBufferRawPointer { + T* mRawPointer; +}; + +// Wrap a pointer to be serialized as the raw pointer value. +template +ProfileBufferRawPointer WrapProfileBufferRawPointer(T* aRawPointer) { + return {aRawPointer}; +} + +// Raw pointers are serialized as the raw pointer value. +// +// Usage: `aEW.WriteObject(WrapProfileBufferRawPointer(ptr));` +// +// The wrapper is compulsory when writing pointers (to avoid unexpected +// leaks/UAFs), but reading can be done straight into a raw pointer object, +// e.g.: `aER.ReadObject;`. +template +struct ProfileBufferEntryWriter::Serializer> { + template + static constexpr Length Bytes(const U&) { + return sizeof(T*); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const ProfileBufferRawPointer& aWrapper) { + aEW.WriteBytes(&aWrapper.mRawPointer, sizeof(aWrapper.mRawPointer)); + } +}; + +// Usage: `aER.ReadObject;` or `Foo* p; aER.ReadIntoObject(p);`, no +// wrapper necessary. +template +struct ProfileBufferEntryReader::Deserializer> { + static void ReadInto(ProfileBufferEntryReader& aER, + ProfileBufferRawPointer& aPtr) { + aER.ReadBytes(&aPtr.mRawPointer, sizeof(aPtr)); + } + + static ProfileBufferRawPointer Read(ProfileBufferEntryReader& aER) { + ProfileBufferRawPointer rawPointer; + ReadInto(aER, rawPointer); + return rawPointer; + } +}; + +// ---------------------------------------------------------------------------- +// std::string contents + +// std::string contents are serialized as the number of characters (encoded as +// ULEB128) and all the characters in the string. The terminal '\0' is omitted. +// +// Usage: `std::string s = ...; aEW.WriteObject(s);` +template +struct ProfileBufferEntryWriter::Serializer> { + static Length Bytes(const std::basic_string& aS) { + const Length len = static_cast(aS.length()); + return ULEB128Size(len) + len; + } + + static void Write(ProfileBufferEntryWriter& aEW, + const std::basic_string& aS) { + const Length len = static_cast(aS.length()); + aEW.WriteULEB128(len); + aEW.WriteBytes(aS.c_str(), len * sizeof(CHAR)); + } +}; + +// Usage: `std::string s = aEW.ReadObject(s);` or +// `std::string s; aER.ReadIntoObject(s);` +template +struct ProfileBufferEntryReader::Deserializer> { + static void ReadCharsInto(ProfileBufferEntryReader& aER, + std::basic_string& aS, size_t aLength) { + // Assign to `aS` by using iterators. + // (`aER+0` so we get the same iterator type as `aER+len`.) + aS.assign(aER, aER.EmptyIteratorAtOffset(aLength)); + aER += aLength; + } + + static void ReadInto(ProfileBufferEntryReader& aER, + std::basic_string& aS) { + ReadCharsInto( + aER, aS, + aER.ReadULEB128::size_type>()); + } + + static std::basic_string ReadChars(ProfileBufferEntryReader& aER, + size_t aLength) { + // Construct a string by using iterators. + // (`aER+0` so we get the same iterator type as `aER+len`.) + std::basic_string s(aER, aER.EmptyIteratorAtOffset(aLength)); + aER += aLength; + return s; + } + + static std::basic_string Read(ProfileBufferEntryReader& aER) { + return ReadChars( + aER, aER.ReadULEB128::size_type>()); + } +}; + +// ---------------------------------------------------------------------------- +// mozilla::UniqueFreePtr + +// UniqueFreePtr, which points at a string allocated with `malloc` +// (typically generated by `strdup()`), is serialized as the number of +// *bytes* (encoded as ULEB128) and all the characters in the string. The +// null terminator is omitted. +// `CHAR` can be any type that has a specialization for +// `std::char_traits::length(const CHAR*)`. +// +// Note: A nullptr pointer will be serialized like an empty string, so when +// deserializing it will result in an allocated buffer only containing a +// single null terminator. +template +struct ProfileBufferEntryWriter::Serializer> { + static Length Bytes(const UniqueFreePtr& aS) { + if (!aS) { + // Null pointer, store it as if it was an empty string (so: 0 bytes). + return ULEB128Size(0u); + } + // Note that we store the size in *bytes*, not in number of characters. + const auto bytes = std::char_traits::length(aS.get()) * sizeof(CHAR); + return ULEB128Size(bytes) + bytes; + } + + static void Write(ProfileBufferEntryWriter& aEW, + const UniqueFreePtr& aS) { + if (!aS) { + // Null pointer, store it as if it was an empty string (so we write a + // length of 0 bytes). + aEW.WriteULEB128(0u); + return; + } + // Note that we store the size in *bytes*, not in number of characters. + const auto bytes = std::char_traits::length(aS.get()) * sizeof(CHAR); + aEW.WriteULEB128(bytes); + aEW.WriteBytes(aS.get(), bytes); + } +}; + +template +struct ProfileBufferEntryReader::Deserializer> { + static void ReadInto(ProfileBufferEntryReader& aER, UniqueFreePtr& aS) { + aS = Read(aER); + } + + static UniqueFreePtr Read(ProfileBufferEntryReader& aER) { + // Read the number of *bytes* that follow. + const auto bytes = aER.ReadULEB128(); + // We need a buffer of the non-const character type. + using NC_CHAR = std::remove_const_t; + // We allocate the required number of bytes, plus one extra character for + // the null terminator. + NC_CHAR* buffer = static_cast(malloc(bytes + sizeof(NC_CHAR))); + // Copy the characters into the buffer. + aER.ReadBytes(buffer, bytes); + // And append a null terminator. + buffer[bytes / sizeof(NC_CHAR)] = NC_CHAR(0); + return UniqueFreePtr(buffer); + } +}; + +// ---------------------------------------------------------------------------- +// std::tuple + +// std::tuple is serialized as a sequence of each recursively-serialized item. +// +// This is equivalent to manually serializing each item, so reading/writing +// tuples is equivalent to reading/writing their elements in order, e.g.: +// ``` +// std::tuple is = ...; +// aEW.WriteObject(is); // Write the tuple, equivalent to: +// aEW.WriteObject(/* int */ std::get<0>(is), /* string */ std::get<1>(is)); +// ... +// // Reading back can be done directly into a tuple: +// auto is = aER.ReadObject>(); +// // Or each item could be read separately: +// auto i = aER.ReadObject(); auto s = aER.ReadObject(); +// ``` +template +struct ProfileBufferEntryWriter::Serializer> { + private: + template + static Length TupleBytes(const std::tuple& aTuple, + std::index_sequence) { + return (0 + ... + SumBytes(std::get(aTuple))); + } + + template + static void TupleWrite(ProfileBufferEntryWriter& aEW, + const std::tuple& aTuple, + std::index_sequence) { + (aEW.WriteObject(std::get(aTuple)), ...); + } + + public: + static Length Bytes(const std::tuple& aTuple) { + // Generate a 0..N-1 index pack, we'll add the sizes of each item. + return TupleBytes(aTuple, std::index_sequence_for()); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const std::tuple& aTuple) { + // Generate a 0..N-1 index pack, we'll write each item. + TupleWrite(aEW, aTuple, std::index_sequence_for()); + } +}; + +template +struct ProfileBufferEntryReader::Deserializer> { + template + static void TupleIReadInto(ProfileBufferEntryReader& aER, + std::tuple& aTuple) { + aER.ReadIntoObject(std::get(aTuple)); + } + + template + static void TupleReadInto(ProfileBufferEntryReader& aER, + std::tuple& aTuple, + std::index_sequence) { + (TupleIReadInto(aER, aTuple), ...); + } + + static void ReadInto(ProfileBufferEntryReader& aER, + std::tuple& aTuple) { + TupleReadInto(aER, aTuple, std::index_sequence_for()); + } + + static std::tuple Read(ProfileBufferEntryReader& aER) { + // Note that this creates default `Ts` first, and then overwrites them. + std::tuple ob; + ReadInto(aER, ob); + return ob; + } +}; +// ---------------------------------------------------------------------------- +// mozilla::Span + +// Span. All elements are serialized in sequence. +// The caller is assumed to know the number of elements (they may manually +// write&read it before the span if needed). +// Similar to tuples, reading/writing spans is equivalent to reading/writing +// their elements in order. +template +struct ProfileBufferEntryWriter::Serializer> { + static Length Bytes(const Span& aSpan) { + Length bytes = 0; + for (const T& element : aSpan) { + bytes += SumBytes(element); + } + return bytes; + } + + static void Write(ProfileBufferEntryWriter& aEW, const Span& aSpan) { + for (const T& element : aSpan) { + aEW.WriteObject(element); + } + } +}; + +template +struct ProfileBufferEntryReader::Deserializer> { + // Read elements back into span pointing at a pre-allocated buffer. + static void ReadInto(ProfileBufferEntryReader& aER, Span& aSpan) { + for (T& element : aSpan) { + aER.ReadIntoObject(element); + } + } + + // A Span does not own its data, this would probably leak so we forbid this. + static Span Read(ProfileBufferEntryReader& aER) = delete; +}; + +// ---------------------------------------------------------------------------- +// mozilla::Maybe + +// Maybe is serialized as one byte containing either 'm' (Nothing), +// or 'M' followed by the recursively-serialized `T` object. +template +struct ProfileBufferEntryWriter::Serializer> { + static Length Bytes(const Maybe& aMaybe) { + // 1 byte to store nothing/something flag, then object size if present. + return aMaybe.isNothing() ? 1 : (1 + SumBytes(aMaybe.ref())); + } + + static void Write(ProfileBufferEntryWriter& aEW, const Maybe& aMaybe) { + // 'm'/'M' is just an arbitrary 1-byte value to distinguish states. + if (aMaybe.isNothing()) { + aEW.WriteObject('m'); + } else { + aEW.WriteObject('M'); + // Use the Serializer for the contained type. + aEW.WriteObject(aMaybe.ref()); + } + } +}; + +template +struct ProfileBufferEntryReader::Deserializer> { + static void ReadInto(ProfileBufferEntryReader& aER, Maybe& aMaybe) { + char c = aER.ReadObject(); + if (c == 'm') { + aMaybe.reset(); + } else { + MOZ_ASSERT(c == 'M'); + // If aMaybe is empty, create a default `T` first, to be overwritten. + // Otherwise we'll just overwrite whatever was already there. + if (aMaybe.isNothing()) { + aMaybe.emplace(); + } + // Use the Deserializer for the contained type. + aER.ReadIntoObject(aMaybe.ref()); + } + } + + static Maybe Read(ProfileBufferEntryReader& aER) { + Maybe maybe; + char c = aER.ReadObject(); + MOZ_ASSERT(c == 'M' || c == 'm'); + if (c == 'M') { + // Note that this creates a default `T` inside the Maybe first, and then + // overwrites it. + maybe = Some(T{}); + // Use the Deserializer for the contained type. + aER.ReadIntoObject(maybe.ref()); + } + return maybe; + } +}; + +// ---------------------------------------------------------------------------- +// mozilla::Variant + +// Variant is serialized as the tag (0-based index of the stored type, encoded +// as ULEB128), and the recursively-serialized object. +template +struct ProfileBufferEntryWriter::Serializer> { + public: + static Length Bytes(const Variant& aVariantTs) { + return aVariantTs.match([](auto aIndex, const auto& aAlternative) { + return ULEB128Size(aIndex) + SumBytes(aAlternative); + }); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const Variant& aVariantTs) { + aVariantTs.match([&aEW](auto aIndex, const auto& aAlternative) { + aEW.WriteULEB128(aIndex); + aEW.WriteObject(aAlternative); + }); + } +}; + +template +struct ProfileBufferEntryReader::Deserializer> { + private: + // Called from the fold expression in `VariantReadInto()`, only the selected + // variant will deserialize the object. + template + static void VariantIReadInto(ProfileBufferEntryReader& aER, + Variant& aVariantTs, unsigned aTag) { + if (I == aTag) { + // Ensure the variant contains the target type. Note that this may create + // a default object. + if (!aVariantTs.template is()) { + aVariantTs = Variant(VariantIndex{}); + } + aER.ReadIntoObject(aVariantTs.template as()); + } + } + + template + static void VariantReadInto(ProfileBufferEntryReader& aER, + Variant& aVariantTs, + std::index_sequence) { + unsigned tag = aER.ReadULEB128(); + (VariantIReadInto(aER, aVariantTs, tag), ...); + } + + public: + static void ReadInto(ProfileBufferEntryReader& aER, + Variant& aVariantTs) { + // Generate a 0..N-1 index pack, the selected variant will deserialize + // itself. + VariantReadInto(aER, aVariantTs, std::index_sequence_for()); + } + + static Variant Read(ProfileBufferEntryReader& aER) { + // Note that this creates a default `Variant` of the first type, and then + // overwrites it. Consider using `ReadInto` for more control if needed. + Variant variant(VariantIndex<0>{}); + ReadInto(aER, variant); + return variant; + } +}; + +} // namespace mozilla + +#endif // ProfileBufferEntrySerialization_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileBufferIndex.h b/src/third_party/mozjs/include/mozilla/ProfileBufferIndex.h new file mode 100644 index 00000000000..5cda6bd89eb --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileBufferIndex.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileBufferIndex_h +#define ProfileBufferIndex_h + +#include "mozilla/Attributes.h" + +#include +#include + +namespace mozilla { + +// Generic index into a Profiler buffer, mostly for internal usage. +// Intended to appear infinite (it should effectively never wrap). +// 0 (zero) is reserved as nullptr-like value; it may indicate failure result, +// or it may point at the earliest available block. +using ProfileBufferIndex = uint64_t; + +// Externally-opaque class encapsulating a block index, i.e. a +// ProfileBufferIndex that is guaranteed to point at the start of a Profile +// buffer block (until it is destroyed, but then that index cannot be reused and +// functions should gracefully handle expired blocks). +// Users may get these from Profile buffer functions, to later access previous +// blocks; they should avoid converting and operating on their value. +class ProfileBufferBlockIndex { + public: + // Default constructor with internal 0 value, for which Profile buffers must + // guarantee that it is before any valid entries; All public APIs should + // fail gracefully, doing and/or returning Nothing. + ProfileBufferBlockIndex() : mBlockIndex(0) {} + + // Implicit conversion from literal `nullptr` to internal 0 value, to allow + // convenient init/reset/comparison with 0 index. + MOZ_IMPLICIT ProfileBufferBlockIndex(std::nullptr_t) : mBlockIndex(0) {} + + // Explicit conversion to bool, works in `if` and other tests. + // Only returns false for default `ProfileBufferBlockIndex{}` value. + explicit operator bool() const { return mBlockIndex != 0; } + + // Comparison operators. Default `ProfileBufferBlockIndex{}` value is always + // the lowest. + [[nodiscard]] bool operator==(const ProfileBufferBlockIndex& aRhs) const { + return mBlockIndex == aRhs.mBlockIndex; + } + [[nodiscard]] bool operator!=(const ProfileBufferBlockIndex& aRhs) const { + return mBlockIndex != aRhs.mBlockIndex; + } + [[nodiscard]] bool operator<(const ProfileBufferBlockIndex& aRhs) const { + return mBlockIndex < aRhs.mBlockIndex; + } + [[nodiscard]] bool operator<=(const ProfileBufferBlockIndex& aRhs) const { + return mBlockIndex <= aRhs.mBlockIndex; + } + [[nodiscard]] bool operator>(const ProfileBufferBlockIndex& aRhs) const { + return mBlockIndex > aRhs.mBlockIndex; + } + [[nodiscard]] bool operator>=(const ProfileBufferBlockIndex& aRhs) const { + return mBlockIndex >= aRhs.mBlockIndex; + } + + // Explicit conversion to ProfileBufferIndex, mostly used by internal Profile + // buffer code. + [[nodiscard]] ProfileBufferIndex ConvertToProfileBufferIndex() const { + return mBlockIndex; + } + + // Explicit creation from ProfileBufferIndex, mostly used by internal + // Profile buffer code. + [[nodiscard]] static ProfileBufferBlockIndex CreateFromProfileBufferIndex( + ProfileBufferIndex aIndex) { + return ProfileBufferBlockIndex(aIndex); + } + + private: + // Private to prevent easy construction from any value. Use + // `CreateFromProfileBufferIndex()` instead. + // The main reason for this indirection is to make it harder to create these + // objects, because only the profiler code should need to do it. Ideally, this + // class should be used wherever a block index should be stored, but there is + // so much code that uses `uint64_t` that it would be a big task to change + // them all. So for now we allow conversions to/from numbers, but it's as ugly + // as possible to make sure it doesn't get too common; and if one day we want + // to tackle a global change, it should be easy to find all these locations + // thanks to the explicit conversion functions. + explicit ProfileBufferBlockIndex(ProfileBufferIndex aBlockIndex) + : mBlockIndex(aBlockIndex) {} + + ProfileBufferIndex mBlockIndex; +}; + +} // namespace mozilla + +#endif // ProfileBufferIndex_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileChunkedBuffer.h b/src/third_party/mozjs/include/mozilla/ProfileChunkedBuffer.h new file mode 100644 index 00000000000..ded7fbd08b4 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileChunkedBuffer.h @@ -0,0 +1,1560 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileChunkedBuffer_h +#define ProfileChunkedBuffer_h + +#include "mozilla/Attributes.h" +#include "mozilla/BaseProfilerDetail.h" +#include "mozilla/NotNull.h" +#include "mozilla/ProfileBufferChunkManager.h" +#include "mozilla/ProfileBufferChunkManagerSingle.h" +#include "mozilla/ProfileBufferEntrySerialization.h" +#include "mozilla/ProfileChunkedBufferDetail.h" +#include "mozilla/RefPtr.h" +#include "mozilla/ScopeExit.h" +#include "mozilla/Unused.h" + +#include + +#ifdef DEBUG +# include +#endif + +namespace mozilla { + +// Thread-safe buffer that can store blocks of different sizes during defined +// sessions, using Chunks (from a ChunkManager) as storage. +// +// Each *block* contains an *entry* and the entry size: +// [ entry_size | entry ] [ entry_size | entry ] ... +// +// *In-session* is a period of time during which `ProfileChunkedBuffer` allows +// reading and writing. +// *Out-of-session*, the `ProfileChunkedBuffer` object is still valid, but +// contains no data, and gracefully denies accesses. +// +// To write an entry, the buffer reserves a block of sufficient size (to contain +// user data of predetermined size), writes the entry size, and lets the caller +// fill the entry contents using a ProfileBufferEntryWriter. E.g.: +// ``` +// ProfileChunkedBuffer cb(...); +// cb.ReserveAndPut([]() { return sizeof(123); }, +// [&](Maybe& aEW) { +// if (aEW) { aEW->WriteObject(123); } +// }); +// ``` +// Other `Put...` functions may be used as shortcuts for simple entries. +// The objects given to the caller's callbacks should only be used inside the +// callbacks and not stored elsewhere, because they keep their own references to +// chunk memory and therefore should not live longer. +// Different type of objects may be serialized into an entry, see +// `ProfileBufferEntryWriter::Serializer` for more information. +// +// When reading data, the buffer iterates over blocks (it knows how to read the +// entry size, and therefore move to the next block), and lets the caller read +// the entry inside of each block. E.g.: +// ``` +// cb.ReadEach([](ProfileBufferEntryReader& aER) { +// /* Use ProfileBufferEntryReader functions to read serialized objects. */ +// int n = aER.ReadObject(); +// }); +// ``` +// Different type of objects may be deserialized from an entry, see +// `ProfileBufferEntryReader::Deserializer` for more information. +// +// Writers may retrieve the block index corresponding to an entry +// (`ProfileBufferBlockIndex` is an opaque type preventing the user from easily +// modifying it). That index may later be used with `ReadAt` to get back to the +// entry in that particular block -- if it still exists. +class ProfileChunkedBuffer { + public: + using Byte = ProfileBufferChunk::Byte; + using Length = ProfileBufferChunk::Length; + + enum class ThreadSafety { WithoutMutex, WithMutex }; + + // Default constructor starts out-of-session (nothing to read or write). + explicit ProfileChunkedBuffer(ThreadSafety aThreadSafety) + : mMutex(aThreadSafety != ThreadSafety::WithoutMutex) {} + + // Start in-session with external chunk manager. + ProfileChunkedBuffer(ThreadSafety aThreadSafety, + ProfileBufferChunkManager& aChunkManager) + : mMutex(aThreadSafety != ThreadSafety::WithoutMutex) { + SetChunkManager(aChunkManager); + } + + // Start in-session with owned chunk manager. + ProfileChunkedBuffer(ThreadSafety aThreadSafety, + UniquePtr&& aChunkManager) + : mMutex(aThreadSafety != ThreadSafety::WithoutMutex) { + SetChunkManager(std::move(aChunkManager)); + } + + ~ProfileChunkedBuffer() { + // Do proper clean-up by resetting the chunk manager. + ResetChunkManager(); + } + + // This cannot change during the lifetime of this buffer, so there's no need + // to lock. + [[nodiscard]] bool IsThreadSafe() const { return mMutex.IsActivated(); } + + [[nodiscard]] bool IsInSession() const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return !!mChunkManager; + } + + // Stop using the current chunk manager. + // If we own the current chunk manager, it will be destroyed. + // This will always clear currently-held chunks, if any. + void ResetChunkManager() { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + Unused << ResetChunkManager(lock); + } + + // Set the current chunk manager. + // The caller is responsible for keeping the chunk manager alive as along as + // it's used here (until the next (Re)SetChunkManager, or + // ~ProfileChunkedBuffer). + void SetChunkManager(ProfileBufferChunkManager& aChunkManager) { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + Unused << ResetChunkManager(lock); + SetChunkManager(aChunkManager, lock); + } + + // Set the current chunk manager, and keep ownership of it. + void SetChunkManager(UniquePtr&& aChunkManager) { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + Unused << ResetChunkManager(lock); + mOwnedChunkManager = std::move(aChunkManager); + if (mOwnedChunkManager) { + SetChunkManager(*mOwnedChunkManager, lock); + } + } + + // Set the current chunk manager, except if it's already the one provided. + // The caller is responsible for keeping the chunk manager alive as along as + // it's used here (until the next (Re)SetChunkManager, or + // ~ProfileChunkedBuffer). + void SetChunkManagerIfDifferent(ProfileBufferChunkManager& aChunkManager) { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (!mChunkManager || mChunkManager != &aChunkManager) { + Unused << ResetChunkManager(lock); + SetChunkManager(aChunkManager, lock); + } + } + + // Clear the contents of this buffer, ready to receive new chunks. + // Note that memory is not freed: No chunks are destroyed, they are all + // receycled. + // Also the range doesn't reset, instead it continues at some point after the + // previous range. This may be useful if the caller may be keeping indexes + // into old chunks that have now been cleared, using these indexes will fail + // gracefully (instead of potentially pointing into new data). + void Clear() { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return; + } + + mRangeStart = mRangeEnd = mNextChunkRangeStart; + mPushedBlockCount = 0; + mClearedBlockCount = 0; + mFailedPutBytes = 0; + + // Recycle all released chunks as "next" chunks. This will reduce the number + // of future allocations. Also, when using ProfileBufferChunkManagerSingle, + // this retrieves the one chunk if it was released. + UniquePtr releasedChunks = + mChunkManager->GetExtantReleasedChunks(); + if (releasedChunks) { + // Released chunks should be in the "Done" state, they need to be marked + // "recycled" before they can be reused. + for (ProfileBufferChunk* chunk = releasedChunks.get(); chunk; + chunk = chunk->GetNext()) { + chunk->MarkRecycled(); + } + mNextChunks = ProfileBufferChunk::Join(std::move(mNextChunks), + std::move(releasedChunks)); + } + + if (mCurrentChunk) { + // We already have a current chunk (empty or in-use), mark it "done" and + // then "recycled", ready to be reused. + mCurrentChunk->MarkDone(); + mCurrentChunk->MarkRecycled(); + } else { + if (!mNextChunks) { + // No current chunk, and no next chunks to recycle, nothing more to do. + // The next "Put" operation will try to allocate a chunk as needed. + return; + } + + // No current chunk, take a next chunk. + mCurrentChunk = std::exchange(mNextChunks, mNextChunks->ReleaseNext()); + } + + // Here, there was already a current chunk, or one has just been taken. + // Make sure it's ready to receive new entries. + InitializeCurrentChunk(lock); + } + + // Buffer maximum length in bytes. + Maybe BufferLength() const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (!mChunkManager) { + return Nothing{}; + } + return Some(mChunkManager->MaxTotalSize()); + } + + [[nodiscard]] size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return SizeOfExcludingThis(aMallocSizeOf, lock); + } + + [[nodiscard]] size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf, lock); + } + + // Snapshot of the buffer state. + struct State { + // Index to/before the first block. + ProfileBufferIndex mRangeStart = 1; + + // Index past the last block. Equals mRangeStart if empty. + ProfileBufferIndex mRangeEnd = 1; + + // Number of blocks that have been pushed into this buffer. + uint64_t mPushedBlockCount = 0; + + // Number of blocks that have been removed from this buffer. + // Note: Live entries = pushed - cleared. + uint64_t mClearedBlockCount = 0; + + // Number of bytes that could not be put into this buffer. + uint64_t mFailedPutBytes = 0; + }; + + // Get a snapshot of the current state. + // When out-of-session, mFirstReadIndex==mNextWriteIndex, and + // mPushedBlockCount==mClearedBlockCount==0. + // Note that these may change right after this thread-safe call, so they + // should only be used for statistical purposes. + [[nodiscard]] State GetState() const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return {mRangeStart, mRangeEnd, mPushedBlockCount, mClearedBlockCount, + mFailedPutBytes}; + } + + // In in-session, return the start TimeStamp of the earliest chunk. + // If out-of-session, return a null TimeStamp. + [[nodiscard]] TimeStamp GetEarliestChunkStartTimeStamp() const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return {}; + } + return mChunkManager->PeekExtantReleasedChunks( + [&](const ProfileBufferChunk* aOldestChunk) -> TimeStamp { + if (aOldestChunk) { + return aOldestChunk->ChunkHeader().mStartTimeStamp; + } + if (mCurrentChunk) { + return mCurrentChunk->ChunkHeader().mStartTimeStamp; + } + return {}; + }); + } + + [[nodiscard]] bool IsEmpty() const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return mRangeStart == mRangeEnd; + } + + // True if this buffer is already locked on this thread. + // This should be used if some functions may call an already-locked buffer, + // e.g.: Put -> memory hook -> profiler_add_native_allocation_marker -> Put. + [[nodiscard]] bool IsThreadSafeAndLockedOnCurrentThread() const { + return mMutex.IsActivatedAndLockedOnCurrentThread(); + } + + // Lock the buffer mutex and run the provided callback. + // This can be useful when the caller needs to explicitly lock down this + // buffer, but not do anything else with it. + template + auto LockAndRun(Callback&& aCallback) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return std::forward(aCallback)(); + } + + // Reserve a block that can hold an entry of the given `aCallbackEntryBytes()` + // size, write the entry size (ULEB128-encoded), and invoke and return + // `aCallback(Maybe&)`. + // Note: `aCallbackEntryBytes` is a callback instead of a simple value, to + // delay this potentially-expensive computation until after we're checked that + // we're in-session; use `Put(Length, Callback)` below if you know the size + // already. + template + auto ReserveAndPut(CallbackEntryBytes&& aCallbackEntryBytes, + Callback&& aCallback) + -> decltype(std::forward(aCallback)( + std::declval&>())) { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + + // This can only be read in the 2nd lambda below after it has been written + // by the first lambda. + Length entryBytes; + + return ReserveAndPutRaw( + [&]() { + entryBytes = std::forward(aCallbackEntryBytes)(); + MOZ_ASSERT(entryBytes != 0, "Empty entries are not allowed"); + return ULEB128Size(entryBytes) + entryBytes; + }, + [&](Maybe& aMaybeEntryWriter) { + if (aMaybeEntryWriter.isSome()) { + aMaybeEntryWriter->WriteULEB128(entryBytes); + MOZ_ASSERT(aMaybeEntryWriter->RemainingBytes() == entryBytes); + } + return std::forward(aCallback)(aMaybeEntryWriter); + }, + lock); + } + + template + auto Put(Length aEntryBytes, Callback&& aCallback) { + return ReserveAndPut([aEntryBytes]() { return aEntryBytes; }, + std::forward(aCallback)); + } + + // Add a new entry copied from the given buffer, return block index. + ProfileBufferBlockIndex PutFrom(const void* aSrc, Length aBytes) { + return ReserveAndPut( + [aBytes]() { return aBytes; }, + [aSrc, aBytes](Maybe& aMaybeEntryWriter) { + if (aMaybeEntryWriter.isNothing()) { + return ProfileBufferBlockIndex{}; + } + aMaybeEntryWriter->WriteBytes(aSrc, aBytes); + return aMaybeEntryWriter->CurrentBlockIndex(); + }); + } + + // Add a new single entry with *all* given object (using a Serializer for + // each), return block index. + template + ProfileBufferBlockIndex PutObjects(const Ts&... aTs) { + static_assert(sizeof...(Ts) > 0, + "PutObjects must be given at least one object."); + return ReserveAndPut( + [&]() { return ProfileBufferEntryWriter::SumBytes(aTs...); }, + [&](Maybe& aMaybeEntryWriter) { + if (aMaybeEntryWriter.isNothing()) { + return ProfileBufferBlockIndex{}; + } + aMaybeEntryWriter->WriteObjects(aTs...); + return aMaybeEntryWriter->CurrentBlockIndex(); + }); + } + + // Add a new entry copied from the given object, return block index. + template + ProfileBufferBlockIndex PutObject(const T& aOb) { + return PutObjects(aOb); + } + + // Get *all* chunks related to this buffer, including extant chunks in its + // ChunkManager, and yet-unused new/recycled chunks. + // We don't expect this buffer to be used again, though it's still possible + // and will allocate the first buffer when needed. + [[nodiscard]] UniquePtr GetAllChunks() { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return nullptr; + } + UniquePtr chunks = + mChunkManager->GetExtantReleasedChunks(); + Unused << HandleRequestedChunk_IsPending(lock); + if (MOZ_LIKELY(!!mCurrentChunk)) { + mCurrentChunk->MarkDone(); + chunks = + ProfileBufferChunk::Join(std::move(chunks), std::move(mCurrentChunk)); + } + chunks = + ProfileBufferChunk::Join(std::move(chunks), std::move(mNextChunks)); + mChunkManager->ForgetUnreleasedChunks(); + mRangeStart = mRangeEnd = mNextChunkRangeStart; + return chunks; + } + + // True if the given index points inside the current chunk (up to the last + // written byte). + // This could be used to check if an index written now would have a good + // chance of referring to a previous block that has not been destroyed yet. + // But use with extreme care: This information may become incorrect right + // after this function returns, because new writes could start a new chunk. + [[nodiscard]] bool IsIndexInCurrentChunk(ProfileBufferIndex aIndex) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager || !mCurrentChunk)) { + // Out-of-session, or no current chunk. + return false; + } + return (mCurrentChunk->RangeStart() <= aIndex) && + (aIndex < (mCurrentChunk->RangeStart() + + mCurrentChunk->OffsetPastLastBlock())); + } + + class Reader; + + // Class that can iterate through blocks and provide + // `ProfileBufferEntryReader`s. + // Created through `Reader`, lives within a lock guard lifetime. + class BlockIterator { + public: +#ifdef DEBUG + ~BlockIterator() { + // No BlockIterator should live outside of a mutexed call. + mBuffer->mMutex.AssertCurrentThreadOwns(); + } +#endif // DEBUG + + // Comparison with other iterator, mostly used in range-for loops. + [[nodiscard]] bool operator==(const BlockIterator& aRhs) const { + MOZ_ASSERT(mBuffer == aRhs.mBuffer); + return mCurrentBlockIndex == aRhs.mCurrentBlockIndex; + } + [[nodiscard]] bool operator!=(const BlockIterator& aRhs) const { + MOZ_ASSERT(mBuffer == aRhs.mBuffer); + return mCurrentBlockIndex != aRhs.mCurrentBlockIndex; + } + + // Advance to next BlockIterator. + BlockIterator& operator++() { + mBuffer->mMutex.AssertCurrentThreadOwns(); + mCurrentBlockIndex = + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mNextBlockPointer.GlobalRangePosition()); + mCurrentEntry = + mNextBlockPointer.EntryReader(mNextBlockPointer.ReadEntrySize()); + return *this; + } + + // Dereferencing creates a `ProfileBufferEntryReader` object for the entry + // inside this block. + // (Note: It would be possible to return a `const + // ProfileBufferEntryReader&`, but not useful in practice, because in most + // case the user will want to read, which is non-const.) + [[nodiscard]] ProfileBufferEntryReader operator*() const { + return mCurrentEntry; + } + + // True if this iterator is just past the last entry. + [[nodiscard]] bool IsAtEnd() const { + return mCurrentEntry.RemainingBytes() == 0; + } + + // Can be used as reference to come back to this entry with `GetEntryAt()`. + [[nodiscard]] ProfileBufferBlockIndex CurrentBlockIndex() const { + return mCurrentBlockIndex; + } + + // Index past the end of this block, which is the start of the next block. + [[nodiscard]] ProfileBufferBlockIndex NextBlockIndex() const { + MOZ_ASSERT(!IsAtEnd()); + return ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mNextBlockPointer.GlobalRangePosition()); + } + + // Index of the first block in the whole buffer. + [[nodiscard]] ProfileBufferBlockIndex BufferRangeStart() const { + mBuffer->mMutex.AssertCurrentThreadOwns(); + return ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mBuffer->mRangeStart); + } + + // Index past the last block in the whole buffer. + [[nodiscard]] ProfileBufferBlockIndex BufferRangeEnd() const { + mBuffer->mMutex.AssertCurrentThreadOwns(); + return ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mBuffer->mRangeEnd); + } + + private: + // Only a Reader can instantiate a BlockIterator. + friend class Reader; + + BlockIterator(const ProfileChunkedBuffer& aBuffer, + const ProfileBufferChunk* aChunks0, + const ProfileBufferChunk* aChunks1, + ProfileBufferBlockIndex aBlockIndex) + : mNextBlockPointer(aChunks0, aChunks1, aBlockIndex), + mCurrentBlockIndex( + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mNextBlockPointer.GlobalRangePosition())), + mCurrentEntry( + mNextBlockPointer.EntryReader(mNextBlockPointer.ReadEntrySize())), + mBuffer(WrapNotNull(&aBuffer)) { + // No BlockIterator should live outside of a mutexed call. + mBuffer->mMutex.AssertCurrentThreadOwns(); + } + + profiler::detail::InChunkPointer mNextBlockPointer; + + ProfileBufferBlockIndex mCurrentBlockIndex; + + ProfileBufferEntryReader mCurrentEntry; + + // Using a non-null pointer instead of a reference, to allow copying. + // This BlockIterator should only live inside one of the thread-safe + // ProfileChunkedBuffer functions, for this reference to stay valid. + NotNull mBuffer; + }; + + // Class that can create `BlockIterator`s (e.g., for range-for), or just + // iterate through entries; lives within a lock guard lifetime. + class MOZ_RAII Reader { + public: + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + Reader(Reader&&) = delete; + Reader& operator=(Reader&&) = delete; + +#ifdef DEBUG + ~Reader() { + // No Reader should live outside of a mutexed call. + mBuffer.mMutex.AssertCurrentThreadOwns(); + } +#endif // DEBUG + + // Index of the first block in the whole buffer. + [[nodiscard]] ProfileBufferBlockIndex BufferRangeStart() const { + mBuffer.mMutex.AssertCurrentThreadOwns(); + return ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mBuffer.mRangeStart); + } + + // Index past the last block in the whole buffer. + [[nodiscard]] ProfileBufferBlockIndex BufferRangeEnd() const { + mBuffer.mMutex.AssertCurrentThreadOwns(); + return ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + mBuffer.mRangeEnd); + } + + // Iterators to the first and past-the-last blocks. + // Compatible with range-for (see `ForEach` below as example). + [[nodiscard]] BlockIterator begin() const { + return BlockIterator(mBuffer, mChunks0, mChunks1, nullptr); + } + // Note that a `BlockIterator` at the `end()` should not be dereferenced, as + // there is no actual block there! + [[nodiscard]] BlockIterator end() const { + return BlockIterator(mBuffer, nullptr, nullptr, nullptr); + } + + // Get a `BlockIterator` at the given `ProfileBufferBlockIndex`, clamped to + // the stored range. Note that a `BlockIterator` at the `end()` should not + // be dereferenced, as there is no actual block there! + [[nodiscard]] BlockIterator At(ProfileBufferBlockIndex aBlockIndex) const { + if (aBlockIndex < BufferRangeStart()) { + // Anything before the range (including null ProfileBufferBlockIndex) is + // clamped at the beginning. + return begin(); + } + // Otherwise we at least expect the index to be valid (pointing exactly at + // a live block, or just past the end.) + return BlockIterator(mBuffer, mChunks0, mChunks1, aBlockIndex); + } + + // Run `aCallback(ProfileBufferEntryReader&)` on each entry from first to + // last. Callback should not store `ProfileBufferEntryReader`, as it may + // become invalid after this thread-safe call. + template + void ForEach(Callback&& aCallback) const { + for (ProfileBufferEntryReader reader : *this) { + aCallback(reader); + } + } + + // If this reader only points at one chunk with some data, this data will be + // exposed as a single entry. + [[nodiscard]] ProfileBufferEntryReader SingleChunkDataAsEntry() { + const ProfileBufferChunk* onlyNonEmptyChunk = nullptr; + for (const ProfileBufferChunk* chunkList : {mChunks0, mChunks1}) { + for (const ProfileBufferChunk* chunk = chunkList; chunk; + chunk = chunk->GetNext()) { + if (chunk->OffsetFirstBlock() != chunk->OffsetPastLastBlock()) { + if (onlyNonEmptyChunk) { + // More than one non-empty chunk. + return ProfileBufferEntryReader(); + } + onlyNonEmptyChunk = chunk; + } + } + } + if (!onlyNonEmptyChunk) { + // No non-empty chunks. + return ProfileBufferEntryReader(); + } + // Here, we have found one chunk that had some data. + return ProfileBufferEntryReader( + onlyNonEmptyChunk->BufferSpan().FromTo( + onlyNonEmptyChunk->OffsetFirstBlock(), + onlyNonEmptyChunk->OffsetPastLastBlock()), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + onlyNonEmptyChunk->RangeStart()), + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + onlyNonEmptyChunk->RangeStart() + + (onlyNonEmptyChunk->OffsetPastLastBlock() - + onlyNonEmptyChunk->OffsetFirstBlock()))); + } + + private: + friend class ProfileChunkedBuffer; + + explicit Reader(const ProfileChunkedBuffer& aBuffer, + const ProfileBufferChunk* aChunks0, + const ProfileBufferChunk* aChunks1) + : mBuffer(aBuffer), mChunks0(aChunks0), mChunks1(aChunks1) { + // No Reader should live outside of a mutexed call. + mBuffer.mMutex.AssertCurrentThreadOwns(); + } + + // This Reader should only live inside one of the thread-safe + // ProfileChunkedBuffer functions, for this reference to stay valid. + const ProfileChunkedBuffer& mBuffer; + const ProfileBufferChunk* mChunks0; + const ProfileBufferChunk* mChunks1; + }; + + // In in-session, call `aCallback(ProfileChunkedBuffer::Reader&)` and return + // true. Callback should not store `Reader`, because it may become invalid + // after this call. + // If out-of-session, return false (callback is not invoked). + template + [[nodiscard]] auto Read(Callback&& aCallback) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return std::forward(aCallback)(static_cast(nullptr)); + } + return mChunkManager->PeekExtantReleasedChunks( + [&](const ProfileBufferChunk* aOldestChunk) { + Reader reader(*this, aOldestChunk, mCurrentChunk.get()); + return std::forward(aCallback)(&reader); + }); + } + + // Invoke `aCallback(ProfileBufferEntryReader& [, ProfileBufferBlockIndex])` + // on each entry, it must read or at least skip everything. Either/both chunk + // pointers may be null. + template + static void ReadEach(const ProfileBufferChunk* aChunks0, + const ProfileBufferChunk* aChunks1, + Callback&& aCallback) { + static_assert(std::is_invocable_v || + std::is_invocable_v, + "ReadEach callback must take ProfileBufferEntryReader& and " + "optionally a ProfileBufferBlockIndex"); + profiler::detail::InChunkPointer p{aChunks0, aChunks1}; + while (!p.IsNull()) { + // The position right before an entry size *is* a block index. + const ProfileBufferBlockIndex blockIndex = + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + p.GlobalRangePosition()); + Length entrySize = p.ReadEntrySize(); + if (entrySize == 0) { + return; + } + ProfileBufferEntryReader entryReader = p.EntryReader(entrySize); + if (entryReader.RemainingBytes() == 0) { + return; + } + MOZ_ASSERT(entryReader.RemainingBytes() == entrySize); + if constexpr (std::is_invocable_v) { + aCallback(entryReader, blockIndex); + } else { + Unused << blockIndex; + aCallback(entryReader); + } + MOZ_ASSERT(entryReader.RemainingBytes() == 0); + } + } + + // Invoke `aCallback(ProfileBufferEntryReader& [, ProfileBufferBlockIndex])` + // on each entry, it must read or at least skip everything. + template + void ReadEach(Callback&& aCallback) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return; + } + mChunkManager->PeekExtantReleasedChunks( + [&](const ProfileBufferChunk* aOldestChunk) { + ReadEach(aOldestChunk, mCurrentChunk.get(), + std::forward(aCallback)); + }); + } + + // Call `aCallback(Maybe&&)` on the entry at + // the given ProfileBufferBlockIndex; The `Maybe` will be `Nothing` if + // out-of-session, or if that entry doesn't exist anymore, or if we've reached + // just past the last entry. Return whatever `aCallback` returns. Callback + // should not store `ProfileBufferEntryReader`, because it may become invalid + // after this call. + // Either/both chunk pointers may be null. + template + [[nodiscard]] static auto ReadAt(ProfileBufferBlockIndex aMinimumBlockIndex, + const ProfileBufferChunk* aChunks0, + const ProfileBufferChunk* aChunks1, + Callback&& aCallback) { + static_assert( + std::is_invocable_v&&>, + "ReadAt callback must take a Maybe&&"); + Maybe maybeEntryReader; + if (profiler::detail::InChunkPointer p{aChunks0, aChunks1}; !p.IsNull()) { + // If the pointer position is before the given position, try to advance. + if (p.GlobalRangePosition() >= + aMinimumBlockIndex.ConvertToProfileBufferIndex() || + p.AdvanceToGlobalRangePosition( + aMinimumBlockIndex.ConvertToProfileBufferIndex())) { + MOZ_ASSERT(p.GlobalRangePosition() >= + aMinimumBlockIndex.ConvertToProfileBufferIndex()); + // Here we're pointing at the start of a block, try to read the entry + // size. (Entries cannot be empty, so 0 means failure.) + if (Length entrySize = p.ReadEntrySize(); entrySize != 0) { + maybeEntryReader.emplace(p.EntryReader(entrySize)); + if (maybeEntryReader->RemainingBytes() == 0) { + // An empty entry reader means there was no complete block at the + // given index. + maybeEntryReader.reset(); + } else { + MOZ_ASSERT(maybeEntryReader->RemainingBytes() == entrySize); + } + } + } + } +#ifdef DEBUG + auto assertAllRead = MakeScopeExit([&]() { + MOZ_ASSERT(!maybeEntryReader || maybeEntryReader->RemainingBytes() == 0); + }); +#endif // DEBUG + return std::forward(aCallback)(std::move(maybeEntryReader)); + } + + // Call `aCallback(Maybe&&)` on the entry at + // the given ProfileBufferBlockIndex; The `Maybe` will be `Nothing` if + // out-of-session, or if that entry doesn't exist anymore, or if we've reached + // just past the last entry. Return whatever `aCallback` returns. Callback + // should not store `ProfileBufferEntryReader`, because it may become invalid + // after this call. + template + [[nodiscard]] auto ReadAt(ProfileBufferBlockIndex aBlockIndex, + Callback&& aCallback) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return std::forward(aCallback)(Nothing{}); + } + return mChunkManager->PeekExtantReleasedChunks( + [&](const ProfileBufferChunk* aOldestChunk) { + return ReadAt(aBlockIndex, aOldestChunk, mCurrentChunk.get(), + std::forward(aCallback)); + }); + } + + // Append the contents of another ProfileChunkedBuffer to this one. + ProfileBufferBlockIndex AppendContents(const ProfileChunkedBuffer& aSrc) { + ProfileBufferBlockIndex firstBlockIndex; + // If we start failing, we'll stop writing. + bool failed = false; + aSrc.ReadEach([&](ProfileBufferEntryReader& aER) { + if (failed) { + return; + } + failed = + !Put(aER.RemainingBytes(), [&](Maybe& aEW) { + if (aEW.isNothing()) { + return false; + } + if (!firstBlockIndex) { + firstBlockIndex = aEW->CurrentBlockIndex(); + } + aEW->WriteFromReader(aER, aER.RemainingBytes()); + return true; + }); + }); + return failed ? nullptr : firstBlockIndex; + } + +#ifdef DEBUG + void Dump(std::FILE* aFile = stdout) const { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + fprintf(aFile, + "ProfileChunkedBuffer[%p] State: range %u-%u pushed=%u cleared=%u " + "(live=%u) failed-puts=%u bytes", + this, unsigned(mRangeStart), unsigned(mRangeEnd), + unsigned(mPushedBlockCount), unsigned(mClearedBlockCount), + unsigned(mPushedBlockCount) - unsigned(mClearedBlockCount), + unsigned(mFailedPutBytes)); + if (MOZ_UNLIKELY(!mChunkManager)) { + fprintf(aFile, " - Out-of-session\n"); + return; + } + fprintf(aFile, " - chunks:\n"); + bool hasChunks = false; + mChunkManager->PeekExtantReleasedChunks( + [&](const ProfileBufferChunk* aOldestChunk) { + for (const ProfileBufferChunk* chunk = aOldestChunk; chunk; + chunk = chunk->GetNext()) { + fprintf(aFile, "R "); + chunk->Dump(aFile); + hasChunks = true; + } + }); + if (mCurrentChunk) { + fprintf(aFile, "C "); + mCurrentChunk->Dump(aFile); + hasChunks = true; + } + for (const ProfileBufferChunk* chunk = mNextChunks.get(); chunk; + chunk = chunk->GetNext()) { + fprintf(aFile, "N "); + chunk->Dump(aFile); + hasChunks = true; + } + switch (mRequestedChunkHolder->GetState()) { + case RequestedChunkRefCountedHolder::State::Unused: + fprintf(aFile, " - No request pending.\n"); + break; + case RequestedChunkRefCountedHolder::State::Requested: + fprintf(aFile, " - Request pending.\n"); + break; + case RequestedChunkRefCountedHolder::State::Fulfilled: + fprintf(aFile, " - Request fulfilled.\n"); + break; + } + if (!hasChunks) { + fprintf(aFile, " No chunks.\n"); + } + } +#endif // DEBUG + + private: + // Used to de/serialize a ProfileChunkedBuffer (e.g., containing a backtrace). + friend ProfileBufferEntryWriter::Serializer; + friend ProfileBufferEntryReader::Deserializer; + friend ProfileBufferEntryWriter::Serializer>; + friend ProfileBufferEntryReader::Deserializer< + UniquePtr>; + + [[nodiscard]] UniquePtr ResetChunkManager( + const baseprofiler::detail::BaseProfilerMaybeAutoLock&) { + UniquePtr chunkManager; + if (mChunkManager) { + mRequestedChunkHolder = nullptr; + mChunkManager->ForgetUnreleasedChunks(); +#ifdef DEBUG + mChunkManager->DeregisteredFrom(this); +#endif + mChunkManager = nullptr; + chunkManager = std::move(mOwnedChunkManager); + if (mCurrentChunk) { + mCurrentChunk->MarkDone(); + mCurrentChunk = nullptr; + } + mNextChunks = nullptr; + mNextChunkRangeStart = mRangeEnd; + mRangeStart = mRangeEnd; + mPushedBlockCount = 0; + mClearedBlockCount = 0; + mFailedPutBytes = 0; + } + return chunkManager; + } + + void SetChunkManager( + ProfileBufferChunkManager& aChunkManager, + const baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock) { + MOZ_ASSERT(!mChunkManager); + mChunkManager = &aChunkManager; +#ifdef DEBUG + mChunkManager->RegisteredWith(this); +#endif + + mChunkManager->SetChunkDestroyedCallback( + [this](const ProfileBufferChunk& aChunk) { + for (;;) { + ProfileBufferIndex rangeStart = mRangeStart; + if (MOZ_LIKELY(rangeStart <= aChunk.RangeStart())) { + if (MOZ_LIKELY(mRangeStart.compareExchange( + rangeStart, + aChunk.RangeStart() + aChunk.BufferBytes()))) { + break; + } + } + } + mClearedBlockCount += aChunk.BlockCount(); + }); + + // We start with one chunk right away, and request a following one now + // so it should be available before the current chunk is full. + SetAndInitializeCurrentChunk(mChunkManager->GetChunk(), aLock); + mRequestedChunkHolder = MakeRefPtr(); + RequestChunk(aLock); + } + + [[nodiscard]] size_t SizeOfExcludingThis( + MallocSizeOf aMallocSizeOf, + const baseprofiler::detail::BaseProfilerMaybeAutoLock&) const { + if (MOZ_UNLIKELY(!mChunkManager)) { + // Out-of-session. + return 0; + } + size_t size = mChunkManager->SizeOfIncludingThis(aMallocSizeOf); + if (mCurrentChunk) { + size += mCurrentChunk->SizeOfIncludingThis(aMallocSizeOf); + } + if (mNextChunks) { + size += mNextChunks->SizeOfIncludingThis(aMallocSizeOf); + } + return size; + } + + void InitializeCurrentChunk( + const baseprofiler::detail::BaseProfilerMaybeAutoLock&) { + MOZ_ASSERT(!!mCurrentChunk); + mCurrentChunk->SetRangeStart(mNextChunkRangeStart); + mNextChunkRangeStart += mCurrentChunk->BufferBytes(); + Unused << mCurrentChunk->ReserveInitialBlockAsTail(0); + } + + void SetAndInitializeCurrentChunk( + UniquePtr&& aChunk, + const baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock) { + mCurrentChunk = std::move(aChunk); + if (mCurrentChunk) { + InitializeCurrentChunk(aLock); + } + } + + void RequestChunk( + const baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock) { + if (HandleRequestedChunk_IsPending(aLock)) { + // There is already a pending request, don't start a new one. + return; + } + + // Ensure the `RequestedChunkHolder` knows we're starting a request. + mRequestedChunkHolder->StartRequest(); + + // Request a chunk, the callback carries a `RefPtr` of the + // `RequestedChunkHolder`, so it's guaranteed to live until it's invoked, + // even if this `ProfileChunkedBuffer` changes its `ChunkManager` or is + // destroyed. + mChunkManager->RequestChunk( + [requestedChunkHolder = RefPtr( + mRequestedChunkHolder)](UniquePtr aChunk) { + requestedChunkHolder->AddRequestedChunk(std::move(aChunk)); + }); + } + + [[nodiscard]] bool HandleRequestedChunk_IsPending( + const baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock) { + MOZ_ASSERT(!!mChunkManager); + MOZ_ASSERT(!!mRequestedChunkHolder); + + if (mRequestedChunkHolder->GetState() == + RequestedChunkRefCountedHolder::State::Unused) { + return false; + } + + // A request is either in-flight or fulfilled. + Maybe> maybeChunk = + mRequestedChunkHolder->GetChunkIfFulfilled(); + if (maybeChunk.isNothing()) { + // Request is still pending. + return true; + } + + // Since we extracted the provided chunk, the holder should now be unused. + MOZ_ASSERT(mRequestedChunkHolder->GetState() == + RequestedChunkRefCountedHolder::State::Unused); + + // Request has been fulfilled. + UniquePtr& chunk = *maybeChunk; + if (chunk) { + // Try to use as current chunk if needed. + if (!mCurrentChunk) { + SetAndInitializeCurrentChunk(std::move(chunk), aLock); + // We've just received a chunk and made it current, request a next chunk + // for later. + MOZ_ASSERT(!mNextChunks); + RequestChunk(aLock); + return true; + } + + if (!mNextChunks) { + mNextChunks = std::move(chunk); + } else { + mNextChunks->InsertNext(std::move(chunk)); + } + } + + return false; + } + + // Get a pointer to the next chunk available + [[nodiscard]] ProfileBufferChunk* GetOrCreateCurrentChunk( + const baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock) { + ProfileBufferChunk* current = mCurrentChunk.get(); + if (MOZ_UNLIKELY(!current)) { + // No current chunk ready. + MOZ_ASSERT(!mNextChunks, + "There shouldn't be next chunks when there is no current one"); + // See if a request has recently been fulfilled, ignore pending status. + Unused << HandleRequestedChunk_IsPending(aLock); + current = mCurrentChunk.get(); + if (MOZ_UNLIKELY(!current)) { + // There was no pending chunk, try to get one right now. + // This may still fail, but we can't do anything else about it, the + // caller must handle the nullptr case. + // Attempt a request for later. + SetAndInitializeCurrentChunk(mChunkManager->GetChunk(), aLock); + current = mCurrentChunk.get(); + } + } + return current; + } + + // Get a pointer to the next chunk available + [[nodiscard]] ProfileBufferChunk* GetOrCreateNextChunk( + const baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock) { + MOZ_ASSERT(!!mCurrentChunk, + "Why ask for a next chunk when there isn't even a current one?"); + ProfileBufferChunk* next = mNextChunks.get(); + if (MOZ_UNLIKELY(!next)) { + // No next chunk ready, see if a request has recently been fulfilled, + // ignore pending status. + Unused << HandleRequestedChunk_IsPending(aLock); + next = mNextChunks.get(); + if (MOZ_UNLIKELY(!next)) { + // There was no pending chunk, try to get one right now. + mNextChunks = mChunkManager->GetChunk(); + next = mNextChunks.get(); + // This may still fail, but we can't do anything else about it, the + // caller must handle the nullptr case. + if (MOZ_UNLIKELY(!next)) { + // Attempt a request for later. + RequestChunk(aLock); + } + } + } + return next; + } + + // Reserve a block of `aCallbackBlockBytes()` size, and invoke and return + // `aCallback(Maybe&)`. Note that this is the "raw" + // version that doesn't write the entry size at the beginning of the block. + // Note: `aCallbackBlockBytes` is a callback instead of a simple value, to + // delay this potentially-expensive computation until after we're checked that + // we're in-session; use `Put(Length, Callback)` below if you know the size + // already. + template + auto ReserveAndPutRaw(CallbackBlockBytes&& aCallbackBlockBytes, + Callback&& aCallback, + baseprofiler::detail::BaseProfilerMaybeAutoLock& aLock, + uint64_t aBlockCount = 1) { + // The entry writer that will point into one or two chunks to write + // into, empty by default (failure). + Maybe maybeEntryWriter; + + // The current chunk will be filled if we need to write more than its + // remaining space. + bool currentChunkFilled = false; + + // If the current chunk gets filled, we may or may not initialize the next + // chunk! + bool nextChunkInitialized = false; + + if (MOZ_LIKELY(mChunkManager)) { + // In-session. + + const Length blockBytes = + std::forward(aCallbackBlockBytes)(); + + if (ProfileBufferChunk* current = GetOrCreateCurrentChunk(aLock); + MOZ_LIKELY(current)) { + if (blockBytes <= current->RemainingBytes()) { + // Block fits in current chunk with only one span. + currentChunkFilled = blockBytes == current->RemainingBytes(); + const auto [mem0, blockIndex] = current->ReserveBlock(blockBytes); + MOZ_ASSERT(mem0.LengthBytes() == blockBytes); + maybeEntryWriter.emplace( + mem0, blockIndex, + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + blockIndex.ConvertToProfileBufferIndex() + blockBytes)); + MOZ_ASSERT(maybeEntryWriter->RemainingBytes() == blockBytes); + mRangeEnd += blockBytes; + mPushedBlockCount += aBlockCount; + } else if (blockBytes >= current->BufferBytes()) { + // Currently only two buffer chunks are held at a time and it is not + // possible to write an object that takes up more space than this. In + // this scenario, silently discard this block of data if it is unable + // to fit into the two reserved profiler chunks. + mFailedPutBytes += blockBytes; + } else { + // Block doesn't fit fully in current chunk, it needs to overflow into + // the next one. + // Whether or not we can write this entry, the current chunk is now + // considered full, so it will be released. (Otherwise we could refuse + // this entry, but later accept a smaller entry into this chunk, which + // would be somewhat inconsistent.) + currentChunkFilled = true; + // Make sure the next chunk is available (from a previous request), + // otherwise create one on the spot. + if (ProfileBufferChunk* next = GetOrCreateNextChunk(aLock); + MOZ_LIKELY(next)) { + // Here, we know we have a current and a next chunk. + // Reserve head of block at the end of the current chunk. + const auto [mem0, blockIndex] = + current->ReserveBlock(current->RemainingBytes()); + MOZ_ASSERT(mem0.LengthBytes() < blockBytes); + MOZ_ASSERT(current->RemainingBytes() == 0); + // Set the next chunk range, and reserve the needed space for the + // tail of the block. + next->SetRangeStart(mNextChunkRangeStart); + mNextChunkRangeStart += next->BufferBytes(); + const auto mem1 = next->ReserveInitialBlockAsTail( + blockBytes - mem0.LengthBytes()); + MOZ_ASSERT(next->RemainingBytes() != 0); + nextChunkInitialized = true; + // Block is split in two spans. + maybeEntryWriter.emplace( + mem0, mem1, blockIndex, + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + blockIndex.ConvertToProfileBufferIndex() + blockBytes)); + MOZ_ASSERT(maybeEntryWriter->RemainingBytes() == blockBytes); + mRangeEnd += blockBytes; + mPushedBlockCount += aBlockCount; + } else { + // Cannot get a new chunk. Record put failure. + mFailedPutBytes += blockBytes; + } + } + } else { + // Cannot get a current chunk. Record put failure. + mFailedPutBytes += blockBytes; + } + } // end of `if (MOZ_LIKELY(mChunkManager))` + + // Here, we either have a `Nothing` (failure), or a non-empty entry writer + // pointing at the start of the block. + + // After we invoke the callback and return, we may need to handle the + // current chunk being filled. + auto handleFilledChunk = MakeScopeExit([&]() { + // If the entry writer was not already empty, the callback *must* have + // filled the full entry. + MOZ_ASSERT(!maybeEntryWriter || maybeEntryWriter->RemainingBytes() == 0); + + if (currentChunkFilled) { + // Extract current (now filled) chunk. + UniquePtr filled = std::move(mCurrentChunk); + + if (mNextChunks) { + // Cycle to the next chunk. + mCurrentChunk = + std::exchange(mNextChunks, mNextChunks->ReleaseNext()); + + // Make sure it is initialized (it is now the current chunk). + if (!nextChunkInitialized) { + InitializeCurrentChunk(aLock); + } + } + + // And finally mark filled chunk done and release it. + filled->MarkDone(); + mChunkManager->ReleaseChunk(std::move(filled)); + + // Request another chunk if needed. + // In most cases, here we should have one current chunk and no next + // chunk, so we want to do a request so there hopefully will be a next + // chunk available when the current one gets filled. + // But we also for a request if we don't even have a current chunk (if + // it's too late, it's ok because the next `ReserveAndPutRaw` wil just + // allocate one on the spot.) + // And if we already have a next chunk, there's no need for more now. + if (!mCurrentChunk || !mNextChunks) { + RequestChunk(aLock); + } + } + }); + + return std::forward(aCallback)(maybeEntryWriter); + } + + // Reserve a block of `aBlockBytes` size, and invoke and return + // `aCallback(Maybe&)`. Note that this is the "raw" + // version that doesn't write the entry size at the beginning of the block. + template + auto ReserveAndPutRaw(Length aBlockBytes, Callback&& aCallback, + uint64_t aBlockCount) { + baseprofiler::detail::BaseProfilerMaybeAutoLock lock(mMutex); + return ReserveAndPutRaw([aBlockBytes]() { return aBlockBytes; }, + std::forward(aCallback), lock, + aBlockCount); + } + + // Mutex guarding the following members. + mutable baseprofiler::detail::BaseProfilerMaybeMutex mMutex; + + // Pointer to the current Chunk Manager (or null when out-of-session.) + // It may be owned locally (see below) or externally. + ProfileBufferChunkManager* mChunkManager = nullptr; + + // Only non-null when we own the current Chunk Manager. + UniquePtr mOwnedChunkManager; + + UniquePtr mCurrentChunk; + + UniquePtr mNextChunks; + + // Class used to transfer requested chunks from a `ChunkManager` to a + // `ProfileChunkedBuffer`. + // It needs to be ref-counted because the request may be fulfilled + // asynchronously, and either side may be destroyed during the request. + // It cannot use the `ProfileChunkedBuffer` mutex, because that buffer and its + // mutex could be destroyed during the request. + class RequestedChunkRefCountedHolder { + public: + enum class State { Unused, Requested, Fulfilled }; + + // Get the current state. Note that it may change after the function + // returns, so it should be used carefully, e.g., `ProfileChunkedBuffer` can + // see if a request is pending or fulfilled, to avoid starting another + // request. + [[nodiscard]] State GetState() const { + baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex); + return mState; + } + + // Must be called by `ProfileChunkedBuffer` when it requests a chunk. + // There cannot be more than one request in-flight. + void StartRequest() { + baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex); + MOZ_ASSERT(mState == State::Unused, "Already requested or fulfilled"); + mState = State::Requested; + } + + // Must be called by the `ChunkManager` with a chunk. + // If the `ChunkManager` cannot provide a chunk (because of memory limits, + // or it gets destroyed), it must call this anyway with a nullptr. + void AddRequestedChunk(UniquePtr&& aChunk) { + baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex); + MOZ_ASSERT(mState == State::Requested); + mState = State::Fulfilled; + mRequestedChunk = std::move(aChunk); + } + + // The `ProfileChunkedBuffer` can try to extract the provided chunk after a + // request: + // - Nothing -> Request is not fulfilled yet. + // - Some(nullptr) -> The `ChunkManager` was not able to provide a chunk. + // - Some(chunk) -> Requested chunk. + [[nodiscard]] Maybe> GetChunkIfFulfilled() { + Maybe> maybeChunk; + baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex); + MOZ_ASSERT(mState == State::Requested || mState == State::Fulfilled); + if (mState == State::Fulfilled) { + mState = State::Unused; + maybeChunk.emplace(std::move(mRequestedChunk)); + } + return maybeChunk; + } + + // Ref-counting implementation. Hand-rolled, because mozilla::RefCounted + // logs AddRefs and Releases in xpcom, but this object could be AddRef'd + // by the Base Profiler before xpcom starts, then Release'd by the Gecko + // Profiler in xpcom, leading to apparent negative leaks. + + void AddRef() { + baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex); + ++mRefCount; + } + + void Release() { + { + baseprofiler::detail::BaseProfilerAutoLock lock(mRequestMutex); + if (--mRefCount > 0) { + return; + } + } + delete this; + } + + private: + ~RequestedChunkRefCountedHolder() = default; + + // Mutex guarding the following members. + mutable baseprofiler::detail::BaseProfilerMutex mRequestMutex; + int mRefCount = 0; + State mState = State::Unused; + UniquePtr mRequestedChunk; + }; + + // Requested-chunk holder, kept alive when in-session, but may also live + // longer if a request is in-flight. + RefPtr mRequestedChunkHolder; + + // Range start of the next chunk to become current. Starting at 1 because + // 0 is a reserved index similar to nullptr. + ProfileBufferIndex mNextChunkRangeStart = 1; + + // Index to the first block. + // Atomic because it may be increased when a Chunk is destroyed, and the + // callback may be invoked from anywhere, including from inside one of our + // locked section, so we cannot protect it with a mutex. + Atomic mRangeStart{1}; + + // Index past the last block. Equals mRangeStart if empty. + ProfileBufferIndex mRangeEnd = 1; + + // Number of blocks that have been pushed into this buffer. + uint64_t mPushedBlockCount = 0; + + // Number of blocks that have been removed from this buffer. + // Note: Live entries = pushed - cleared. + // Atomic because it may be updated when a Chunk is destroyed, and the + // callback may be invoked from anywhere, including from inside one of our + // locked section, so we cannot protect it with a mutex. + Atomic mClearedBlockCount{0}; + + // Number of bytes that could not be put into this buffer. + uint64_t mFailedPutBytes = 0; +}; + +// ---------------------------------------------------------------------------- +// ProfileChunkedBuffer serialization + +// A ProfileChunkedBuffer can hide another one! +// This will be used to store marker backtraces; They can be read back into a +// UniquePtr. +// Format: len (ULEB128) | start | end | buffer (len bytes) | pushed | cleared +// len==0 marks an out-of-session buffer, or empty buffer. +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(const ProfileChunkedBuffer& aBuffer) { + return aBuffer.Read([&](ProfileChunkedBuffer::Reader* aReader) { + if (!aReader) { + // Out-of-session, we only need 1 byte to store a length of 0. + return ULEB128Size(0); + } + ProfileBufferEntryReader reader = aReader->SingleChunkDataAsEntry(); + const ProfileBufferIndex start = + reader.CurrentBlockIndex().ConvertToProfileBufferIndex(); + const ProfileBufferIndex end = + reader.NextBlockIndex().ConvertToProfileBufferIndex(); + MOZ_ASSERT(end - start <= std::numeric_limits::max()); + const Length len = static_cast(end - start); + if (len == 0) { + // In-session but empty, also store a length of 0. + return ULEB128Size(0); + } + // In-session. + return static_cast(ULEB128Size(len) + sizeof(start) + len + + sizeof(aBuffer.mPushedBlockCount) + + sizeof(aBuffer.mClearedBlockCount)); + }); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const ProfileChunkedBuffer& aBuffer) { + aBuffer.Read([&](ProfileChunkedBuffer::Reader* aReader) { + if (!aReader) { + // Out-of-session, only store a length of 0. + aEW.WriteULEB128(0); + return; + } + ProfileBufferEntryReader reader = aReader->SingleChunkDataAsEntry(); + const ProfileBufferIndex start = + reader.CurrentBlockIndex().ConvertToProfileBufferIndex(); + const ProfileBufferIndex end = + reader.NextBlockIndex().ConvertToProfileBufferIndex(); + MOZ_ASSERT(end - start <= std::numeric_limits::max()); + const Length len = static_cast(end - start); + MOZ_ASSERT(len <= aEW.RemainingBytes()); + if (len == 0) { + // In-session but empty, only store a length of 0. + aEW.WriteULEB128(0); + return; + } + // In-session. + // Store buffer length, and start index. + aEW.WriteULEB128(len); + aEW.WriteObject(start); + // Write all the bytes. + aEW.WriteFromReader(reader, reader.RemainingBytes()); + // And write stats. + aEW.WriteObject(static_cast(aBuffer.mPushedBlockCount)); + aEW.WriteObject(static_cast(aBuffer.mClearedBlockCount)); + // Note: Failed pushes are not important to serialize. + }); + } +}; + +// A serialized ProfileChunkedBuffer can be read into an empty buffer (either +// out-of-session, or in-session with enough room). +template <> +struct ProfileBufferEntryReader::Deserializer { + static void ReadInto(ProfileBufferEntryReader& aER, + ProfileChunkedBuffer& aBuffer) { + // Expect an empty buffer, as we're going to overwrite it. + MOZ_ASSERT(aBuffer.GetState().mRangeStart == aBuffer.GetState().mRangeEnd); + // Read the stored buffer length. + const auto len = aER.ReadULEB128(); + if (len == 0) { + // 0-length means an "uninteresting" buffer, just return now. + return; + } + // We have a non-empty buffer to read. + + // Read start and end indices. + const auto start = aER.ReadObject(); + aBuffer.mRangeStart = start; + // For now, set the end to be the start (the buffer is still empty). It will + // be updated in `ReserveAndPutRaw()` below. + aBuffer.mRangeEnd = start; + + if (aBuffer.IsInSession()) { + // Output buffer is in-session (i.e., it already has a memory buffer + // attached). Make sure the caller allocated enough space. + MOZ_RELEASE_ASSERT(aBuffer.BufferLength().value() >= len); + } else { + // Output buffer is out-of-session, set a new chunk manager that will + // provide a single chunk of just the right size. + aBuffer.SetChunkManager(MakeUnique(len)); + MOZ_ASSERT(aBuffer.BufferLength().value() >= len); + } + + // Copy bytes into the buffer. + aBuffer.ReserveAndPutRaw( + len, + [&](Maybe& aEW) { + MOZ_RELEASE_ASSERT(aEW.isSome()); + aEW->WriteFromReader(aER, len); + }, + 0); + // Finally copy stats. + aBuffer.mPushedBlockCount = aER.ReadObject(); + aBuffer.mClearedBlockCount = aER.ReadObject(); + // Failed puts are not important to keep. + aBuffer.mFailedPutBytes = 0; + } + + // We cannot output a ProfileChunkedBuffer object (not copyable), use + // `ReadInto()` or `aER.ReadObject>()` instead. + static ProfileChunkedBuffer Read(ProfileBufferEntryReader& aER) = delete; +}; + +// A ProfileChunkedBuffer is usually refererenced through a UniquePtr, for +// convenience we support (de)serializing that UniquePtr directly. +// This is compatible with the non-UniquePtr serialization above, with a null +// pointer being treated like an out-of-session or empty buffer; and any of +// these would be deserialized into a null pointer. +template <> +struct ProfileBufferEntryWriter::Serializer> { + static Length Bytes(const UniquePtr& aBufferUPtr) { + if (!aBufferUPtr) { + // Null pointer, treat it like an empty buffer, i.e., write length of 0. + return ULEB128Size(0); + } + // Otherwise write the pointed-at ProfileChunkedBuffer (which could be + // out-of-session or empty.) + return SumBytes(*aBufferUPtr); + } + + static void Write(ProfileBufferEntryWriter& aEW, + const UniquePtr& aBufferUPtr) { + if (!aBufferUPtr) { + // Null pointer, treat it like an empty buffer, i.e., write length of 0. + aEW.WriteULEB128(0); + return; + } + // Otherwise write the pointed-at ProfileChunkedBuffer (which could be + // out-of-session or empty.) + aEW.WriteObject(*aBufferUPtr); + } +}; + +// Serialization of a raw pointer to ProfileChunkedBuffer. +// Use Deserializer> to read it back. +template <> +struct ProfileBufferEntryWriter::Serializer { + static Length Bytes(ProfileChunkedBuffer* aBufferUPtr) { + if (!aBufferUPtr) { + // Null pointer, treat it like an empty buffer, i.e., write length of 0. + return ULEB128Size(0); + } + // Otherwise write the pointed-at ProfileChunkedBuffer (which could be + // out-of-session or empty.) + return SumBytes(*aBufferUPtr); + } + + static void Write(ProfileBufferEntryWriter& aEW, + ProfileChunkedBuffer* aBufferUPtr) { + if (!aBufferUPtr) { + // Null pointer, treat it like an empty buffer, i.e., write length of 0. + aEW.WriteULEB128(0); + return; + } + // Otherwise write the pointed-at ProfileChunkedBuffer (which could be + // out-of-session or empty.) + aEW.WriteObject(*aBufferUPtr); + } +}; + +template <> +struct ProfileBufferEntryReader::Deserializer> { + static void ReadInto(ProfileBufferEntryReader& aER, + UniquePtr& aBuffer) { + aBuffer = Read(aER); + } + + static UniquePtr Read(ProfileBufferEntryReader& aER) { + UniquePtr bufferUPtr; + // Keep a copy of the reader before reading the length, so we can restart + // from here below. + ProfileBufferEntryReader readerBeforeLen = aER; + // Read the stored buffer length. + const auto len = aER.ReadULEB128(); + if (len == 0) { + // 0-length means an "uninteresting" buffer, just return nullptr. + return bufferUPtr; + } + // We have a non-empty buffer. + // allocate an empty ProfileChunkedBuffer without mutex. + bufferUPtr = MakeUnique( + ProfileChunkedBuffer::ThreadSafety::WithoutMutex); + // Rewind the reader before the length and deserialize the contents, using + // the non-UniquePtr Deserializer. + aER = readerBeforeLen; + aER.ReadIntoObject(*bufferUPtr); + return bufferUPtr; + } +}; + +} // namespace mozilla + +#endif // ProfileChunkedBuffer_h diff --git a/src/third_party/mozjs/include/mozilla/ProfileChunkedBufferDetail.h b/src/third_party/mozjs/include/mozilla/ProfileChunkedBufferDetail.h new file mode 100644 index 00000000000..75e461cd40d --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfileChunkedBufferDetail.h @@ -0,0 +1,401 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfileChunkedBufferDetail_h +#define ProfileChunkedBufferDetail_h + +#include "mozilla/Assertions.h" +#include "mozilla/Likely.h" +#include "mozilla/ProfileBufferChunk.h" +#include "mozilla/ProfileBufferEntrySerialization.h" + +namespace mozilla::profiler::detail { + +// Internal accessor pointing at a position inside a chunk. +// It can handle two groups of chunks (typically the extant chunks stored in +// the store manager, and the current chunk). +// The main operations are: +// - ReadEntrySize() to read an entry size, 0 means failure. +// - operator+=(Length) to skip a number of bytes. +// - EntryReader() creates an entry reader at the current position for a given +// size (it may fail with an empty reader), and skips the entry. +// Note that there is no "past-the-end" position -- as soon as InChunkPointer +// reaches the end, it becomes effectively null. +class InChunkPointer { + public: + using Byte = ProfileBufferChunk::Byte; + using Length = ProfileBufferChunk::Length; + + // Nullptr-like InChunkPointer, may be used as end iterator. + InChunkPointer() + : mChunk(nullptr), mNextChunkGroup(nullptr), mOffsetInChunk(0) {} + + // InChunkPointer over one or two chunk groups, pointing at the given + // block index (if still in range). + // This constructor should only be used with *trusted* block index values! + InChunkPointer(const ProfileBufferChunk* aChunk, + const ProfileBufferChunk* aNextChunkGroup, + ProfileBufferBlockIndex aBlockIndex) + : mChunk(aChunk), mNextChunkGroup(aNextChunkGroup) { + if (mChunk) { + mOffsetInChunk = mChunk->OffsetFirstBlock(); + Adjust(); + } else if (mNextChunkGroup) { + mChunk = mNextChunkGroup; + mNextChunkGroup = nullptr; + mOffsetInChunk = mChunk->OffsetFirstBlock(); + Adjust(); + } else { + mOffsetInChunk = 0; + } + + // Try to advance to given position. + if (!AdvanceToGlobalRangePosition(aBlockIndex)) { + // Block does not exist anymore (or block doesn't look valid), reset the + // in-chunk pointer. + mChunk = nullptr; + mNextChunkGroup = nullptr; + } + } + + // InChunkPointer over one or two chunk groups, will start at the first + // block (if any). This may be slow, so avoid using it too much. + InChunkPointer(const ProfileBufferChunk* aChunk, + const ProfileBufferChunk* aNextChunkGroup, + ProfileBufferIndex aIndex = ProfileBufferIndex(0)) + : mChunk(aChunk), mNextChunkGroup(aNextChunkGroup) { + if (mChunk) { + mOffsetInChunk = mChunk->OffsetFirstBlock(); + Adjust(); + } else if (mNextChunkGroup) { + mChunk = mNextChunkGroup; + mNextChunkGroup = nullptr; + mOffsetInChunk = mChunk->OffsetFirstBlock(); + Adjust(); + } else { + mOffsetInChunk = 0; + } + + // Try to advance to given position. + if (!AdvanceToGlobalRangePosition(aIndex)) { + // Block does not exist anymore, reset the in-chunk pointer. + mChunk = nullptr; + mNextChunkGroup = nullptr; + } + } + + // Compute the current position in the global range. + // 0 if null (including if we're reached the end). + [[nodiscard]] ProfileBufferIndex GlobalRangePosition() const { + if (IsNull()) { + return 0; + } + return mChunk->RangeStart() + mOffsetInChunk; + } + + // Move InChunkPointer forward to the block at the given global block + // position, which is assumed to be valid exactly -- but it may be obsolete. + // 0 stays where it is (if valid already). + // MOZ_ASSERTs if the index is invalid. + [[nodiscard]] bool AdvanceToGlobalRangePosition( + ProfileBufferBlockIndex aBlockIndex) { + if (IsNull()) { + // Pointer is null already. (Not asserting because it's acceptable.) + return false; + } + if (!aBlockIndex) { + // Special null position, just stay where we are. + return ShouldPointAtValidBlock(); + } + if (aBlockIndex.ConvertToProfileBufferIndex() < GlobalRangePosition()) { + // Past the requested position, stay where we are (assuming the current + // position was valid). + return ShouldPointAtValidBlock(); + } + for (;;) { + if (aBlockIndex.ConvertToProfileBufferIndex() < + mChunk->RangeStart() + mChunk->OffsetPastLastBlock()) { + // Target position is in this chunk's written space, move to it. + mOffsetInChunk = + aBlockIndex.ConvertToProfileBufferIndex() - mChunk->RangeStart(); + return ShouldPointAtValidBlock(); + } + // Position is after this chunk, try next chunk. + GoToNextChunk(); + if (IsNull()) { + return false; + } + // Skip whatever block tail there is, we don't allow pointing in the + // middle of a block. + mOffsetInChunk = mChunk->OffsetFirstBlock(); + if (aBlockIndex.ConvertToProfileBufferIndex() < GlobalRangePosition()) { + // Past the requested position, meaning that the given position was in- + // between blocks -> Failure. + MOZ_ASSERT(false, "AdvanceToGlobalRangePosition - In-between blocks"); + return false; + } + } + } + + // Move InChunkPointer forward to the block at or after the given global + // range position. + // 0 stays where it is (if valid already). + [[nodiscard]] bool AdvanceToGlobalRangePosition( + ProfileBufferIndex aPosition) { + if (aPosition == 0) { + // Special position '0', just stay where we are. + // Success if this position is already valid. + return !IsNull(); + } + for (;;) { + ProfileBufferIndex currentPosition = GlobalRangePosition(); + if (currentPosition == 0) { + // Pointer is null. + return false; + } + if (aPosition <= currentPosition) { + // At or past the requested position, stay where we are. + return true; + } + if (aPosition < mChunk->RangeStart() + mChunk->OffsetPastLastBlock()) { + // Target position is in this chunk's written space, move to it. + for (;;) { + // Skip the current block. + mOffsetInChunk += ReadEntrySize(); + if (mOffsetInChunk >= mChunk->OffsetPastLastBlock()) { + // Reached the end of the chunk, this can happen for the last + // block, let's just continue to the next chunk. + break; + } + if (aPosition <= mChunk->RangeStart() + mOffsetInChunk) { + // We're at or after the position, return at this block position. + return true; + } + } + } + // Position is after this chunk, try next chunk. + GoToNextChunk(); + if (IsNull()) { + return false; + } + // Skip whatever block tail there is, we don't allow pointing in the + // middle of a block. + mOffsetInChunk = mChunk->OffsetFirstBlock(); + } + } + + [[nodiscard]] Byte ReadByte() { + MOZ_ASSERT(!IsNull()); + MOZ_ASSERT(mOffsetInChunk < mChunk->OffsetPastLastBlock()); + Byte byte = mChunk->ByteAt(mOffsetInChunk); + if (MOZ_UNLIKELY(++mOffsetInChunk == mChunk->OffsetPastLastBlock())) { + Adjust(); + } + return byte; + } + + // Read and skip a ULEB128-encoded size. + // 0 means failure (0-byte entries are not allowed.) + // Note that this doesn't guarantee that there are actually that many bytes + // available to read! (EntryReader() below may gracefully fail.) + [[nodiscard]] Length ReadEntrySize() { + ULEB128Reader reader; + if (IsNull()) { + return 0; + } + for (;;) { + const bool isComplete = reader.FeedByteIsComplete(ReadByte()); + if (MOZ_UNLIKELY(IsNull())) { + // End of chunks, so there's no actual entry after this anyway. + return 0; + } + if (MOZ_LIKELY(isComplete)) { + if (MOZ_UNLIKELY(reader.Value() > mChunk->BufferBytes())) { + // Don't allow entries larger than a chunk. + return 0; + } + return reader.Value(); + } + } + } + + InChunkPointer& operator+=(Length aLength) { + MOZ_ASSERT(!IsNull()); + mOffsetInChunk += aLength; + Adjust(); + return *this; + } + + [[nodiscard]] ProfileBufferEntryReader EntryReader(Length aLength) { + if (IsNull() || aLength == 0) { + return ProfileBufferEntryReader(); + } + + MOZ_ASSERT(mOffsetInChunk < mChunk->OffsetPastLastBlock()); + + // We should be pointing at the entry, past the entry size. + const ProfileBufferIndex entryIndex = GlobalRangePosition(); + // Verify that there's enough space before for the size (starting at index + // 1 at least). + MOZ_ASSERT(entryIndex >= 1u + ULEB128Size(aLength)); + + const Length remaining = mChunk->OffsetPastLastBlock() - mOffsetInChunk; + Span mem0 = mChunk->BufferSpan(); + mem0 = mem0.From(mOffsetInChunk); + if (aLength <= remaining) { + // Move to the end of this block, which could make this null if we have + // reached the end of all buffers. + *this += aLength; + return ProfileBufferEntryReader( + mem0.To(aLength), + // Block starts before the entry size. + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + entryIndex - ULEB128Size(aLength)), + // Block ends right after the entry (could be null for last entry). + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + GlobalRangePosition())); + } + + // We need to go to the next chunk for the 2nd part of this block. + GoToNextChunk(); + if (IsNull()) { + return ProfileBufferEntryReader(); + } + + Span mem1 = mChunk->BufferSpan(); + const Length tail = aLength - remaining; + MOZ_ASSERT(tail <= mChunk->BufferBytes()); + MOZ_ASSERT(tail == mChunk->OffsetFirstBlock()); + // We are in the correct chunk, move the offset to the end of the block. + mOffsetInChunk = tail; + // And adjust as needed, which could make this null if we have reached the + // end of all buffers. + Adjust(); + return ProfileBufferEntryReader( + mem0, mem1.To(tail), + // Block starts before the entry size. + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + entryIndex - ULEB128Size(aLength)), + // Block ends right after the entry (could be null for last entry). + ProfileBufferBlockIndex::CreateFromProfileBufferIndex( + GlobalRangePosition())); + } + + [[nodiscard]] bool IsNull() const { return !mChunk; } + + [[nodiscard]] bool operator==(const InChunkPointer& aOther) const { + if (IsNull() || aOther.IsNull()) { + return IsNull() && aOther.IsNull(); + } + return mChunk == aOther.mChunk && mOffsetInChunk == aOther.mOffsetInChunk; + } + + [[nodiscard]] bool operator!=(const InChunkPointer& aOther) const { + return !(*this == aOther); + } + + [[nodiscard]] Byte operator*() const { + MOZ_ASSERT(!IsNull()); + MOZ_ASSERT(mOffsetInChunk < mChunk->OffsetPastLastBlock()); + return mChunk->ByteAt(mOffsetInChunk); + } + + InChunkPointer& operator++() { + MOZ_ASSERT(!IsNull()); + MOZ_ASSERT(mOffsetInChunk < mChunk->OffsetPastLastBlock()); + if (MOZ_UNLIKELY(++mOffsetInChunk == mChunk->OffsetPastLastBlock())) { + mOffsetInChunk = 0; + GoToNextChunk(); + Adjust(); + } + return *this; + } + + private: + void GoToNextChunk() { + MOZ_ASSERT(!IsNull()); + const ProfileBufferIndex expectedNextRangeStart = + mChunk->RangeStart() + mChunk->BufferBytes(); + + mChunk = mChunk->GetNext(); + if (!mChunk) { + // Reached the end of the current chunk group, try the next one (which + // may be null too, especially on the 2nd try). + mChunk = mNextChunkGroup; + mNextChunkGroup = nullptr; + } + + if (mChunk && mChunk->RangeStart() == 0) { + // Reached a chunk without a valid (non-null) range start, assume there + // are only unused chunks from here on. + mChunk = nullptr; + } + + MOZ_ASSERT(!mChunk || mChunk->RangeStart() == expectedNextRangeStart, + "We don't handle discontinuous buffers (yet)"); + // Non-DEBUG fallback: Stop reading past discontinuities. + // (They should be rare, only happening on temporary OOMs.) + // TODO: Handle discontinuities (by skipping over incomplete blocks). + if (mChunk && mChunk->RangeStart() != expectedNextRangeStart) { + mChunk = nullptr; + } + } + + // We want `InChunkPointer` to always point at a valid byte (or be null). + // After some operations, `mOffsetInChunk` may point past the end of the + // current `mChunk`, in which case we need to adjust our position to be inside + // the appropriate chunk. E.g., if we're 10 bytes after the end of the current + // chunk, we should end up at offset 10 in the next chunk. + // Note that we may "fall off" the last chunk and make this `InChunkPointer` + // effectively null. + void Adjust() { + while (mChunk && mOffsetInChunk >= mChunk->OffsetPastLastBlock()) { + // TODO: Try to adjust offset between chunks relative to mRangeStart + // differences. But we don't handle discontinuities yet. + if (mOffsetInChunk < mChunk->BufferBytes()) { + mOffsetInChunk -= mChunk->BufferBytes(); + } else { + mOffsetInChunk -= mChunk->OffsetPastLastBlock(); + } + GoToNextChunk(); + } + } + + // Check if the current position is likely to point at a valid block. + // (Size should be reasonable, and block should fully fit inside buffer.) + // MOZ_ASSERTs on failure, to catch incorrect uses of block indices (which + // should only point at valid blocks if still in range). Non-asserting build + // fallback should still be handled. + [[nodiscard]] bool ShouldPointAtValidBlock() const { + if (IsNull()) { + // Pointer is null, no blocks here. + MOZ_ASSERT(false, "ShouldPointAtValidBlock - null pointer"); + return false; + } + // Use a copy, so we don't modify `*this`. + InChunkPointer pointer = *this; + // Try to read the entry size. + Length entrySize = pointer.ReadEntrySize(); + if (entrySize == 0) { + // Entry size of zero means we read 0 or a way-too-big value. + MOZ_ASSERT(false, "ShouldPointAtValidBlock - invalid size"); + return false; + } + // See if the last byte of the entry is still inside the buffer. + pointer += entrySize - 1; + MOZ_ASSERT(!pointer.IsNull(), + "ShouldPointAtValidBlock - past end of buffer"); + return !pointer.IsNull(); + } + + const ProfileBufferChunk* mChunk; + const ProfileBufferChunk* mNextChunkGroup; + Length mOffsetInChunk; +}; + +} // namespace mozilla::profiler::detail + +#endif // ProfileChunkedBufferDetail_h diff --git a/src/third_party/mozjs/include/mozilla/ProfilerBufferSize.h b/src/third_party/mozjs/include/mozilla/ProfilerBufferSize.h new file mode 100644 index 00000000000..d77d869a68f --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProfilerBufferSize.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProfilerBufferSize_h +#define ProfilerBufferSize_h + +#include "mozilla/ProfileBufferChunkManager.h" + +// We need to decide how many chunks of what size we want to fit in the given +// total maximum capacity for this process, in the (likely) context of +// multiple processes doing the same choice and having an inter-process +// mechanism to control the overall memory limit. + +// The buffer size is provided as a number of "entries", this is their size in +// bytes. +constexpr static uint32_t scBytesPerEntry = 8; + +// Minimum chunk size allowed, enough for at least one stack. +constexpr static uint32_t scMinimumChunkSize = + 2 * mozilla::ProfileBufferChunkManager::scExpectedMaximumStackSize; + +// Ideally we want at least 2 unreleased chunks to work with (1 current and 1 +// next), and 2 released chunks (so that one can be recycled when old, leaving +// one with some data). +constexpr static uint32_t scMinimumNumberOfChunks = 4; + +// And we want to limit chunks to a maximum size, which is a compromise +// between: +// - A big size, which helps with reducing the rate of allocations and IPCs. +// - A small size, which helps with equalizing the duration of recorded data +// (as the inter-process controller will discard the oldest chunks in all +// Firefox processes). +constexpr static uint32_t scMaximumChunkSize = 1024 * 1024; + +// Limit to 128MiB as a lower buffer size usually isn't enough. +constexpr static uint32_t scMinimumBufferSize = 128u * 1024u * 1024u; +// Note: Keep in sync with GeckoThread.maybeStartGeckoProfiler: +// https://searchfox.org/mozilla-central/source/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java +constexpr static uint32_t scMinimumBufferEntries = + scMinimumBufferSize / scBytesPerEntry; + +// Limit to 2GiB. +constexpr static uint32_t scMaximumBufferSize = 2u * 1024u * 1024u * 1024u; +constexpr static uint32_t scMaximumBufferEntries = + scMaximumBufferSize / scBytesPerEntry; + +constexpr static uint32_t ClampToAllowedEntries(uint32_t aEntries) { + if (aEntries <= scMinimumBufferEntries) { + return scMinimumBufferEntries; + } + if (aEntries >= scMaximumBufferEntries) { + return scMaximumBufferEntries; + } + return aEntries; +} + +#endif // ProfilerBufferSize_h diff --git a/src/third_party/mozjs/include/mozilla/ProgressLogger.h b/src/third_party/mozjs/include/mozilla/ProgressLogger.h new file mode 100644 index 00000000000..e15095faaab --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProgressLogger.h @@ -0,0 +1,500 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProgressLogger_h +#define ProgressLogger_h + +#include "mozilla/Assertions.h" +#include "mozilla/ProportionValue.h" +#include "mozilla/RefCounted.h" +#include "mozilla/RefPtr.h" + +#include + +// Uncomment to printf ProcessLogger updates. +// #define DEBUG_PROCESSLOGGER + +#ifdef DEBUG_PROCESSLOGGER +# include "mozilla/BaseProfilerUtils.h" +# include +#endif // DEBUG_PROCESSLOGGER + +namespace mozilla { + +// A `ProgressLogger` is used to update a referenced atomic `ProportionValue`, +// and can recursively create a sub-logger corresponding to a subset of their +// own range, but that sub-logger's updates are done in its local 0%-100% range. +// The typical usage is for multi-level tasks, where each level can estimate its +// own work and the work delegated to a next-level function, without knowing how +// this local work relates to the higher-level total work. See +// `CreateSubLoggerFromTo` for details. +// Note that this implementation is single-threaded, it does not support logging +// progress from multiple threads at the same time. +class ProgressLogger { + public: + // An RefPtr'd object of this class is used as the target of all + // ProgressLogger updates, and it may be shared to make these updates visible + // from other code in any thread. + class SharedProgress : public external::AtomicRefCounted { + public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(SharedProgress) + + SharedProgress() = default; + + SharedProgress(const SharedProgress&) = delete; + SharedProgress& operator=(const SharedProgress&) = delete; + + // This constant is used to indicate that an update may change the progress + // value, but should not modify the previously-recorded location. + static constexpr const char* NO_LOCATION_UPDATE = nullptr; + + // Set the current progress and location, but the previous location is not + // overwritten if the new one is null or empty. + // The location and then the progress are atomically "released", so that all + // preceding writes on this thread will be visible to other threads reading + // these values; most importantly when reaching 100% progress, the reader + // can be confident that the location is final and the operation being + // watched has completed. + void SetProgress( + ProportionValue aProgress, + const char* aLocationOrNullEmptyToIgnore = NO_LOCATION_UPDATE) { + if (aLocationOrNullEmptyToIgnore && + *aLocationOrNullEmptyToIgnore != '\0') { + mLastLocation.store(aLocationOrNullEmptyToIgnore, + std::memory_order_release); + } + mProgress.store(aProgress, std::memory_order_release); + } + + // Read the current progress value. Atomically "acquired", so that writes + // from the thread that stored this value are all visible to the reader + // here; most importantly when reaching 100%, we can be confident that the + // location is final and the operation being watched has completed. + [[nodiscard]] ProportionValue Progress() const { + return mProgress.load(std::memory_order_acquire); + } + + // Read the current progress value. Atomically "acquired". + [[nodiscard]] const char* LastLocation() const { + return mLastLocation.load(std::memory_order_acquire); + } + + private: + friend mozilla::detail::RefCounted; + ~SharedProgress() = default; + + // Progress and last-known location. + // Beware that these two values are not strongly tied: Reading one then the + // other may give mismatched information; but it should be fine for + // informational usage. + // They are stored using atomic acquire-release ordering, to guarantee that + // when read, all writes preceding these values are visible. + std::atomic mProgress = ProportionValue{0.0}; + std::atomic mLastLocation = nullptr; + }; + + static constexpr const char* NO_LOCATION_UPDATE = + SharedProgress::NO_LOCATION_UPDATE; + + ProgressLogger() = default; + + // Construct a top-level logger, starting at 0% and expected to end at 100%. + explicit ProgressLogger( + RefPtr aGlobalProgressOrNull, + const char* aLocationOrNullEmptyToIgnoreAtStart = NO_LOCATION_UPDATE, + const char* aLocationOrNullEmptyToIgnoreAtEnd = NO_LOCATION_UPDATE) + : ProgressLogger{std::move(aGlobalProgressOrNull), + /* Start */ ProportionValue{0.0}, + /* Multiplier */ ProportionValue{1.0}, + aLocationOrNullEmptyToIgnoreAtStart, + aLocationOrNullEmptyToIgnoreAtEnd} {} + + // Don't make copies, it would be confusing! + // TODO: Copies could one day be allowed to track multi-threaded work, but it + // is outside the scope of this implementation; Please update if needed. + ProgressLogger(const ProgressLogger&) = delete; + ProgressLogger& operator&(const ProgressLogger&) = delete; + + // Move-construct is allowed, to return from CreateSubLoggerFromTo, and + // forward straight into a function. Note that moved-from ProgressLoggers must + // not be used anymore! Use `CreateSubLoggerFromTo` to pass a sub-logger to + // functions. + ProgressLogger(ProgressLogger&& aOther) + : mGlobalProgressOrNull(std::move(aOther.mGlobalProgressOrNull)), + mLocalStartInGlobalSpace(aOther.mLocalStartInGlobalSpace), + mLocalToGlobalMultiplier(aOther.mLocalToGlobalMultiplier), + mLocationAtDestruction(aOther.mLocationAtDestruction) { + aOther.MarkMovedFrom(); +#ifdef DEBUG_PROCESSLOGGER + if (mGlobalProgressOrNull) { + printf("[%d] Moved (staying globally at %.2f in [%.2f, %.2f])\n", + int(baseprofiler::profiler_current_process_id().ToNumber()), + GetGlobalProgress().ToDouble() * 100.0, + mLocalStartInGlobalSpace.ToDouble() * 100.0, + (mLocalStartInGlobalSpace + mLocalToGlobalMultiplier).ToDouble() * + 100.0); + } +#endif // DEBUG_PROCESSLOGGER + } + + // Move-assign. This may be useful when starting with a default (empty) logger + // and later assigning it a progress value to start updating. + ProgressLogger& operator=(ProgressLogger&& aOther) { + mGlobalProgressOrNull = std::move(aOther.mGlobalProgressOrNull); + mLocalStartInGlobalSpace = aOther.mLocalStartInGlobalSpace; + mLocalToGlobalMultiplier = aOther.mLocalToGlobalMultiplier; + mLocationAtDestruction = aOther.mLocationAtDestruction; + aOther.MarkMovedFrom(); +#ifdef DEBUG_PROCESSLOGGER + if (mGlobalProgressOrNull) { + printf("[%d] Re-assigned (globally at %.2f in [%.2f, %.2f])\n", + int(baseprofiler::profiler_current_process_id().ToNumber()), + GetGlobalProgress().ToDouble() * 100.0, + mLocalStartInGlobalSpace.ToDouble() * 100.0, + (mLocalStartInGlobalSpace + mLocalToGlobalMultiplier).ToDouble() * + 100.0); + } +#endif // DEBUG_PROCESSLOGGER + return *this; + } + + // Destruction sets the local update value to 100% unless empty or moved-from. + ~ProgressLogger() { + if (!IsMovedFrom()) { +#ifdef DEBUG_PROCESSLOGGER + if (mGlobalProgressOrNull) { + printf("[%d] Destruction:\n", + int(baseprofiler::profiler_current_process_id().ToNumber())); + } +#endif // DEBUG_PROCESSLOGGER + SetLocalProgress(ProportionValue{1.0}, mLocationAtDestruction); + } + } + + // Retrieve the current progress in the global space. May be invalid. + [[nodiscard]] ProportionValue GetGlobalProgress() const { + return mGlobalProgressOrNull ? mGlobalProgressOrNull->Progress() + : ProportionValue::MakeInvalid(); + } + + // Retrieve the last known global location. May be null. + [[nodiscard]] const char* GetLastGlobalLocation() const { + return mGlobalProgressOrNull ? mGlobalProgressOrNull->LastLocation() + : nullptr; + } + + // Set the current progress in the local space. + void SetLocalProgress(ProportionValue aLocalProgress, + const char* aLocationOrNullEmptyToIgnore) { + MOZ_ASSERT(!IsMovedFrom()); + if (mGlobalProgressOrNull && !mLocalToGlobalMultiplier.IsExactlyZero()) { + mGlobalProgressOrNull->SetProgress(LocalToGlobal(aLocalProgress), + aLocationOrNullEmptyToIgnore); +#ifdef DEBUG_PROCESSLOGGER + printf("[%d] - local %.0f%% ~ global %.2f%% \"%s\"\n", + int(baseprofiler::profiler_current_process_id().ToNumber()), + aLocalProgress.ToDouble() * 100.0, + LocalToGlobal(aLocalProgress).ToDouble() * 100.0, + aLocationOrNullEmptyToIgnore ? aLocationOrNullEmptyToIgnore + : ""); +#endif // DEBUG_PROCESSLOGGER + } + } + + // Create a sub-logger that will record progress in the given local range. + // E.g.: `f(pl.CreateSubLoggerFromTo(0.2, "f...", 0.4, "f done"));` expects + // that `f` will produce work in the local range 0.2 (when starting) to 0.4 + // (when returning); `f` itself will update this provided logger from 0.0 + // to 1.0 (local to that `f` function), which will effectively be converted to + // 0.2-0.4 (local to the calling function). + // This can cascade multiple levels, each deeper level affecting a smaller and + // smaller range in the global output. + [[nodiscard]] ProgressLogger CreateSubLoggerFromTo( + ProportionValue aSubStartInLocalSpace, + const char* aLocationOrNullEmptyToIgnoreAtStart, + ProportionValue aSubEndInLocalSpace, + const char* aLocationOrNullEmptyToIgnoreAtEnd = NO_LOCATION_UPDATE) { + MOZ_ASSERT(!IsMovedFrom()); + if (!mGlobalProgressOrNull) { + return ProgressLogger{}; + } + const ProportionValue subStartInGlobalSpace = + LocalToGlobal(aSubStartInLocalSpace); + const ProportionValue subEndInGlobalSpace = + LocalToGlobal(aSubEndInLocalSpace); + if (subStartInGlobalSpace.IsInvalid() || subEndInGlobalSpace.IsInvalid()) { + return ProgressLogger{mGlobalProgressOrNull, + /* Start */ ProportionValue::MakeInvalid(), + /* Multiplier */ ProportionValue{0.0}, + aLocationOrNullEmptyToIgnoreAtStart, + aLocationOrNullEmptyToIgnoreAtEnd}; + } +#ifdef DEBUG_PROCESSLOGGER + if (mGlobalProgressOrNull) { + printf("[%d] * Sub: local [%.0f%%, %.0f%%] ~ global [%.2f%%, %.2f%%]\n", + int(baseprofiler::profiler_current_process_id().ToNumber()), + aSubStartInLocalSpace.ToDouble() * 100.0, + aSubEndInLocalSpace.ToDouble() * 100.0, + subStartInGlobalSpace.ToDouble() * 100.0, + subEndInGlobalSpace.ToDouble() * 100.0); + } +#endif // DEBUG_PROCESSLOGGER + return ProgressLogger{ + mGlobalProgressOrNull, + /* Start */ subStartInGlobalSpace, + /* Multipler */ subEndInGlobalSpace - subStartInGlobalSpace, + aLocationOrNullEmptyToIgnoreAtStart, aLocationOrNullEmptyToIgnoreAtEnd}; + } + + // Helper with no start location. + [[nodiscard]] ProgressLogger CreateSubLoggerFromTo( + ProportionValue aSubStartInLocalSpace, + ProportionValue aSubEndInLocalSpace, + const char* aLocationOrNullEmptyToIgnoreAtEnd = NO_LOCATION_UPDATE) { + return CreateSubLoggerFromTo(aSubStartInLocalSpace, NO_LOCATION_UPDATE, + aSubEndInLocalSpace, + aLocationOrNullEmptyToIgnoreAtEnd); + } + + // Helper using the current progress as start. + [[nodiscard]] ProgressLogger CreateSubLoggerTo( + const char* aLocationOrNullEmptyToIgnoreAtStart, + ProportionValue aSubEndInLocalSpace, + const char* aLocationOrNullEmptyToIgnoreAtEnd = NO_LOCATION_UPDATE) { + MOZ_ASSERT(!IsMovedFrom()); + if (!mGlobalProgressOrNull) { + return ProgressLogger{}; + } + const ProportionValue subStartInGlobalSpace = GetGlobalProgress(); + const ProportionValue subEndInGlobalSpace = + LocalToGlobal(aSubEndInLocalSpace); + if (subStartInGlobalSpace.IsInvalid() || subEndInGlobalSpace.IsInvalid()) { + return ProgressLogger{mGlobalProgressOrNull, + /* Start */ ProportionValue::MakeInvalid(), + /* Multiplier */ ProportionValue{0.0}, + aLocationOrNullEmptyToIgnoreAtStart, + aLocationOrNullEmptyToIgnoreAtEnd}; + } +#ifdef DEBUG_PROCESSLOGGER + if (mGlobalProgressOrNull) { + printf("[%d] * Sub: local [(here), %.0f%%] ~ global [%.2f%%, %.2f%%]\n", + int(baseprofiler::profiler_current_process_id().ToNumber()), + aSubEndInLocalSpace.ToDouble() * 100.0, + subStartInGlobalSpace.ToDouble() * 100.0, + subEndInGlobalSpace.ToDouble() * 100.0); + } +#endif // DEBUG_PROCESSLOGGER + return ProgressLogger{ + mGlobalProgressOrNull, + /* Start */ subStartInGlobalSpace, + /* Multiplier */ subEndInGlobalSpace - subStartInGlobalSpace, + aLocationOrNullEmptyToIgnoreAtStart, aLocationOrNullEmptyToIgnoreAtEnd}; + } + + // Helper using the current progress as start, no start location. + [[nodiscard]] ProgressLogger CreateSubLoggerTo( + ProportionValue aSubEndInLocalSpace, + const char* aLocationOrNullEmptyToIgnoreAtEnd = NO_LOCATION_UPDATE) { + return CreateSubLoggerTo(NO_LOCATION_UPDATE, aSubEndInLocalSpace, + aLocationOrNullEmptyToIgnoreAtEnd); + } + + class IndexAndProgressLoggerRange; + + [[nodiscard]] inline IndexAndProgressLoggerRange CreateLoopSubLoggersFromTo( + ProportionValue aLoopStartInLocalSpace, + ProportionValue aLoopEndInLocalSpace, uint32_t aLoopCount, + const char* aLocationOrNullEmptyToIgnoreAtEdges = + ProgressLogger::NO_LOCATION_UPDATE); + [[nodiscard]] inline IndexAndProgressLoggerRange CreateLoopSubLoggersTo( + ProportionValue aLoopEndInLocalSpace, uint32_t aLoopCount, + const char* aLocationOrNullEmptyToIgnoreAtEdges = + ProgressLogger::NO_LOCATION_UPDATE); + + private: + // All constructions start at the local 0%. + ProgressLogger(RefPtr aGlobalProgressOrNull, + ProportionValue aLocalStartInGlobalSpace, + ProportionValue aLocalToGlobalMultiplier, + const char* aLocationOrNullEmptyToIgnoreAtConstruction, + const char* aLocationOrNullEmptyToIgnoreAtDestruction) + : mGlobalProgressOrNull(std::move(aGlobalProgressOrNull)), + mLocalStartInGlobalSpace(aLocalStartInGlobalSpace), + mLocalToGlobalMultiplier(aLocalToGlobalMultiplier), + mLocationAtDestruction(aLocationOrNullEmptyToIgnoreAtDestruction) { + MOZ_ASSERT(!IsMovedFrom(), "Don't construct a moved-from object!"); + SetLocalProgress(ProportionValue{0.0}, + aLocationOrNullEmptyToIgnoreAtConstruction); + } + + void MarkMovedFrom() { + mLocalToGlobalMultiplier = ProportionValue::MakeInvalid(); + } + [[nodiscard]] bool IsMovedFrom() const { + return mLocalToGlobalMultiplier.IsInvalid(); + } + + [[nodiscard]] ProportionValue LocalToGlobal( + ProportionValue aLocalProgress) const { + return aLocalProgress * mLocalToGlobalMultiplier + mLocalStartInGlobalSpace; + } + + // Global progress value to update from local changes. + RefPtr mGlobalProgressOrNull; + + // How much to multiply and add to a local [0, 100%] value, to get the + // corresponding value in the global space. + // If mLocalToGlobalMultiplier is invalid, this ProgressLogger is moved-from, + // functions should not be used, and destructor won't update progress. + ProportionValue mLocalStartInGlobalSpace; + ProportionValue mLocalToGlobalMultiplier; + + const char* mLocationAtDestruction = nullptr; +}; + +// Helper class for range-for loop, e.g., with `aProgressLogger`: +// for (auto [index, loopProgressLogger] : +// IndexAndProgressLoggerRange{aProgressLogger, 30_pc, 50_pc, 10, +// "looping..."}) { +// // This will loop 10 times. +// // `index` is the loop index, from 0 to 9. +// // The overall loop will start at 30% and end at 50% of aProgressLogger. +// // `loopProgressLogger` is the progress logger for each iteration, +// // covering 1/10th of the range, therefore: [30%,32%], then [32%,34%], +// // etc. until [48%,50%]. +// // Progress is automatically updated before/after each loop. +// } +// Note that this implementation is single-threaded, it does not support logging +// progress from parallel loops. +class ProgressLogger::IndexAndProgressLoggerRange { + public: + struct IndexAndProgressLogger { + uint32_t index; + ProgressLogger progressLogger; + }; + + class IndexAndProgressLoggerEndIterator { + public: + explicit IndexAndProgressLoggerEndIterator(uint32_t aIndex) + : mIndex(aIndex) {} + + [[nodiscard]] uint32_t Index() const { return mIndex; } + + private: + uint32_t mIndex; + }; + + class IndexAndProgressLoggerIterator { + public: + IndexAndProgressLoggerIterator( + RefPtr aGlobalProgressOrNull, + ProportionValue aLoopStartInGlobalSpace, + ProportionValue aLoopIncrementInGlobalSpace, + const char* aLocationOrNullEmptyToIgnoreAtEdges) + : mGlobalProgressOrNull(aGlobalProgressOrNull), + mLoopStartInGlobalSpace(aLoopStartInGlobalSpace), + mLoopIncrementInGlobalSpace(aLoopIncrementInGlobalSpace), + mIndex(0u), + mLocationOrNullEmptyToIgnoreAtEdges( + aLocationOrNullEmptyToIgnoreAtEdges) { + if (mGlobalProgressOrNull) { + mGlobalProgressOrNull->SetProgress(mLoopStartInGlobalSpace, + mLocationOrNullEmptyToIgnoreAtEdges); + } + } + + [[nodiscard]] IndexAndProgressLogger operator*() { + return IndexAndProgressLogger{ + mIndex, + mGlobalProgressOrNull + ? ProgressLogger{mGlobalProgressOrNull, mLoopStartInGlobalSpace, + mLoopIncrementInGlobalSpace, + ProgressLogger::NO_LOCATION_UPDATE, + ProgressLogger::NO_LOCATION_UPDATE} + : ProgressLogger{}}; + } + + [[nodiscard]] bool operator!=( + const IndexAndProgressLoggerEndIterator& aEnd) const { + return mIndex != aEnd.Index(); + } + + IndexAndProgressLoggerIterator& operator++() { + ++mIndex; + mLoopStartInGlobalSpace = + mLoopStartInGlobalSpace + mLoopIncrementInGlobalSpace; + if (mGlobalProgressOrNull) { + mGlobalProgressOrNull->SetProgress(mLoopStartInGlobalSpace, + mLocationOrNullEmptyToIgnoreAtEdges); + } + return *this; + } + + private: + RefPtr mGlobalProgressOrNull; + ProportionValue mLoopStartInGlobalSpace; + ProportionValue mLoopIncrementInGlobalSpace; + uint32_t mIndex; + const char* mLocationOrNullEmptyToIgnoreAtEdges; + }; + + [[nodiscard]] IndexAndProgressLoggerIterator begin() { + return IndexAndProgressLoggerIterator{ + mGlobalProgressOrNull, mLoopStartInGlobalSpace, + mLoopIncrementInGlobalSpace, mLocationOrNullEmptyToIgnoreAtEdges}; + } + + [[nodiscard]] IndexAndProgressLoggerEndIterator end() { + return IndexAndProgressLoggerEndIterator{mLoopCount}; + } + + private: + friend class ProgressLogger; + IndexAndProgressLoggerRange(ProgressLogger& aProgressLogger, + ProportionValue aLoopStartInGlobalSpace, + ProportionValue aLoopEndInGlobalSpace, + uint32_t aLoopCount, + const char* aLocationOrNullEmptyToIgnoreAtEdges = + ProgressLogger::NO_LOCATION_UPDATE) + : mGlobalProgressOrNull(aProgressLogger.mGlobalProgressOrNull), + mLoopStartInGlobalSpace(aLoopStartInGlobalSpace), + mLoopIncrementInGlobalSpace( + (aLoopEndInGlobalSpace - aLoopStartInGlobalSpace) / aLoopCount), + mLoopCount(aLoopCount), + mLocationOrNullEmptyToIgnoreAtEdges( + aLocationOrNullEmptyToIgnoreAtEdges) {} + + RefPtr mGlobalProgressOrNull; + ProportionValue mLoopStartInGlobalSpace; + ProportionValue mLoopIncrementInGlobalSpace; + uint32_t mLoopCount; + const char* mLocationOrNullEmptyToIgnoreAtEdges; +}; + +[[nodiscard]] ProgressLogger::IndexAndProgressLoggerRange +ProgressLogger::CreateLoopSubLoggersFromTo( + ProportionValue aLoopStartInLocalSpace, + ProportionValue aLoopEndInLocalSpace, uint32_t aLoopCount, + const char* aLocationOrNullEmptyToIgnoreAtEdges) { + return IndexAndProgressLoggerRange{ + *this, LocalToGlobal(aLoopStartInLocalSpace), + LocalToGlobal(aLoopEndInLocalSpace), aLoopCount, + aLocationOrNullEmptyToIgnoreAtEdges}; +} + +[[nodiscard]] ProgressLogger::IndexAndProgressLoggerRange +ProgressLogger::CreateLoopSubLoggersTo( + ProportionValue aLoopEndInLocalSpace, uint32_t aLoopCount, + const char* aLocationOrNullEmptyToIgnoreAtEdges) { + return IndexAndProgressLoggerRange{ + *this, GetGlobalProgress(), LocalToGlobal(aLoopEndInLocalSpace), + aLoopCount, aLocationOrNullEmptyToIgnoreAtEdges}; +} + +} // namespace mozilla + +#endif // ProgressLogger_h diff --git a/src/third_party/mozjs/include/mozilla/ProportionValue.h b/src/third_party/mozjs/include/mozilla/ProportionValue.h new file mode 100644 index 00000000000..61eb2766ec8 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/ProportionValue.h @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ProportionValue_h +#define ProportionValue_h + +#include "mozilla/Attributes.h" + +#include +#include + +namespace mozilla { + +// Class storing a proportion value between 0 and 1, effectively 0% to 100%. +// The public interface deals with doubles, but internally the value is encoded +// in an integral type, so arithmetic operations are fast. +// It also supports an invalid value: Use MakeInvalid() to construct, it infects +// any operation, and gets converted to a signaling NaN. +class ProportionValue { + public: + using UnderlyingType = uint32_t; + + // Default-construct at 0%. + constexpr ProportionValue() + // This `noexcept` is necessary to avoid a build error when encapsulating + // `ProportionValue` in `std::Atomic`: + // "use of deleted function + // 'constexpr std::atomic::atomic()" + // because the default `std::atomic::atomic()` constructor is marked: + // `noexcept(std::is_nothrow_default_constructible_v)` + // and therefore this default constructor here must be explicitly marked + // `noexcept` as well. + noexcept + : mIntegralValue(0u) {} + + // Construct a ProportionValue with the given value, clamped to 0..1. + // Note that it's constexpr, so construction from literal numbers should incur + // no runtime costs. + // If `aValue` is NaN, behavior is undefined! Use `MakeInvalid()` instead. + constexpr explicit ProportionValue(double aValue) + : mIntegralValue(UnderlyingType(std::clamp(aValue, 0.0, 1.0) * scMaxD)) {} + + [[nodiscard]] static constexpr ProportionValue MakeInvalid() { + return ProportionValue(scInvalidU, Internal{}); + } + + [[nodiscard]] constexpr double ToDouble() const { + return IsInvalid() ? std::numeric_limits::signaling_NaN() + : (double(mIntegralValue) * scInvMaxD); + } + + // Retrieve the underlying integral value, for storage or testing purposes. + [[nodiscard]] constexpr UnderlyingType ToUnderlyingType() const { + return mIntegralValue; + }; + + // Re-construct a ProportionValue from an underlying integral value. + [[nodiscard]] static constexpr ProportionValue FromUnderlyingType( + UnderlyingType aUnderlyingType) { + return ProportionValue( + (aUnderlyingType <= scMaxU) ? aUnderlyingType : scInvalidU, Internal{}); + } + + [[nodiscard]] constexpr bool IsExactlyZero() const { + return mIntegralValue == 0u; + } + + [[nodiscard]] constexpr bool IsExactlyOne() const { + return mIntegralValue == scMaxU; + } + + [[nodiscard]] constexpr bool IsValid() const { + // Compare to the maximum value, not just exactly scInvalidU, to catch any + // kind of invalid state. + return mIntegralValue <= scMaxU; + } + [[nodiscard]] constexpr bool IsInvalid() const { + // Compare to the maximum value, not just exactly scInvalidU, to catch any + // kind of invalid state. + return mIntegralValue > scMaxU; + } + + // Strict comparisons based on the underlying integral value. Use + // `CompareWithin` instead to make fuzzy comparisons. + // `ProportionValue::MakeInvalid()`s are equal, and greater than anything + // else; Best to avoid comparisons, and first use IsInvalid() instead. +#define OPERATOR_COMPARISON(CMP) \ + [[nodiscard]] constexpr friend bool operator CMP( \ + const ProportionValue& aLHS, const ProportionValue& aRHS) { \ + return aLHS.mIntegralValue CMP aRHS.mIntegralValue; \ + } + OPERATOR_COMPARISON(==) + OPERATOR_COMPARISON(!=) + OPERATOR_COMPARISON(<) + OPERATOR_COMPARISON(<=) + OPERATOR_COMPARISON(>) + OPERATOR_COMPARISON(>=) +#undef OPERATOR_COMPARISON + + // Arithmetic operations + - *, all working on the underlying integral values + // (i.e, no expensive floating-point operations are used), and always clamping + // to 0..1 range. Invalid values are poisonous. + + [[nodiscard]] constexpr ProportionValue operator+( + ProportionValue aRHS) const { + return ProportionValue( + (IsInvalid() || aRHS.IsInvalid()) + ? scInvalidU + // Adding fixed-point values keep the same scale, so there is no + // adjustment needed for that. [0,1]+[0,1]=[0,2], so we only need to + // ensure that the result is capped at max 1, aka scMaxU: + // a+b<=max <=> b<=max-a, so b is at maximum max-a. + : (mIntegralValue + + std::min(aRHS.mIntegralValue, scMaxU - mIntegralValue)), + Internal{}); + } + + [[nodiscard]] constexpr ProportionValue operator-( + ProportionValue aRHS) const { + return ProportionValue( + (IsInvalid() || aRHS.IsInvalid()) + ? scInvalidU + // Subtracting fixed-point values keep the same scale, so there is + // no adjustment needed for that. [0,1]-[0,1]=[-1,1], so we only + // need to ensure that the value is positive: + // a-b>=0 <=> b<=a, so b is at maximum a. + : (mIntegralValue - std::min(aRHS.mIntegralValue, mIntegralValue)), + Internal{}); + } + + [[nodiscard]] constexpr ProportionValue operator*( + ProportionValue aRHS) const { + // Type to hold the full result of multiplying two maximum numbers. + using DoublePrecisionType = uint64_t; + static_assert(sizeof(DoublePrecisionType) >= 2 * sizeof(UnderlyingType)); + return ProportionValue( + (IsInvalid() || aRHS.IsInvalid()) + ? scInvalidU + // Multiplying fixed-point values doubles the scale (2^31 -> 2^62), + // so we need to adjust the result by dividing it by one scale + // (which is optimized into a binary right-shift). + : (UnderlyingType((DoublePrecisionType(mIntegralValue) * + DoublePrecisionType(aRHS.mIntegralValue)) / + DoublePrecisionType(scMaxU))), + Internal{}); + } + + // Explicitly forbid divisions, they make little sense, and would almost + // always return a clamped 100% (E.g.: 50% / 10% = 0.5 / 0.1 = 5 = 500%). + [[nodiscard]] constexpr ProportionValue operator/( + ProportionValue aRHS) const = delete; + + // Division by a positive integer value, useful to split an interval in equal + // parts (with maybe some spare space at the end, because it is rounded down). + // Division by 0 produces an invalid value. + [[nodiscard]] constexpr ProportionValue operator/(uint32_t aDivisor) const { + return ProportionValue((IsInvalid() || aDivisor == 0u) + ? scInvalidU + : (mIntegralValue / aDivisor), + Internal{}); + } + + // Multiplication by a positive integer value, useful as inverse of the + // integer division above. But it may be lossy because the division is rounded + // down, therefore: PV - u < (PV / u) * u <= PV. + // Clamped to 100% max. + [[nodiscard]] constexpr ProportionValue operator*( + uint32_t aMultiplier) const { + return ProportionValue(IsInvalid() + ? scInvalidU + : ((aMultiplier > scMaxU / mIntegralValue) + ? scMaxU + : (mIntegralValue * aMultiplier)), + Internal{}); + } + + private: + // Tagged constructor for internal construction from the UnderlyingType, so + // that it is never ambiguously considered in constructions from one number. + struct Internal {}; + constexpr ProportionValue(UnderlyingType aIntegralValue, Internal) + : mIntegralValue(aIntegralValue) {} + + // Use all but 1 bit for the fractional part. + // Valid values can go from 0b0 (0%) up to 0b1000...00 (scMaxU aka 100%). + static constexpr unsigned scFractionalBits = sizeof(UnderlyingType) * 8 - 1; + // Maximum value corresponding to 1.0 or 100%. + static constexpr UnderlyingType scMaxU = UnderlyingType(1u) + << scFractionalBits; + // This maximum value corresponding to 1.0 can also be seen as the scaling + // factor from any [0,1] `double` value to the internal integral value. + static constexpr double scMaxD = double(scMaxU); + // The inverse can be used to convert the internal value back to [0,1]. + static constexpr double scInvMaxD = 1.0 / scMaxD; + + // Special value outside [0,max], used to construct invalid values. + static constexpr UnderlyingType scInvalidU = ~UnderlyingType(0u); + + // Internal integral value, guaranteed to always be <= scMaxU, or scInvalidU. + // This is effectively a fixed-point value using 1 bit for the integer part + // and 31 bits for the fractional part. + // It is roughly equal to the `double` value [0,1] multiplied by scMaxD. + UnderlyingType mIntegralValue; +}; + +namespace literals { +inline namespace ProportionValue_literals { + +// User-defined literal for integer percentages, e.g.: `10_pc`, `100_pc` +// (equivalent to `ProportionValue{0.1}` and `ProportionValue{1.0}`). +// Clamped to [0, 100]_pc. +[[nodiscard]] constexpr ProportionValue operator""_pc( + unsigned long long int aPercentage) { + return ProportionValue{ + double(std::clamp(aPercentage, 0u, 100u)) / + 100.0}; +} + +// User-defined literal for non-integer percentages, e.g.: `12.3_pc`, `100.0_pc` +// (equivalent to `ProportionValue{0.123}` and `ProportionValue{1.0}`). +// Clamped to [0.0, 100.0]_pc. +[[nodiscard]] constexpr ProportionValue operator""_pc(long double aPercentage) { + return ProportionValue{ + double(std::clamp(aPercentage, 0.0, 100.0)) / 100.0}; +} + +} // namespace ProportionValue_literals +} // namespace literals + +} // namespace mozilla + +#endif // ProportionValue_h diff --git a/src/third_party/mozjs/include/mozilla/RefCounted.h b/src/third_party/mozjs/include/mozilla/RefCounted.h index 5c083f3524f..a0686919822 100644 --- a/src/third_party/mozjs/include/mozilla/RefCounted.h +++ b/src/third_party/mozjs/include/mozilla/RefCounted.h @@ -24,11 +24,7 @@ # include #endif // __wasi__ -#if defined(MOZILLA_INTERNAL_API) -# include "nsXPCOM.h" -#endif - -#if defined(MOZILLA_INTERNAL_API) && defined(NS_BUILD_REFCNT_LOGGING) +#if defined(MOZ_SUPPORT_LEAKCHECKING) && defined(NS_BUILD_REFCNT_LOGGING) # define MOZ_REFCOUNTED_LEAK_CHECKING #endif @@ -58,13 +54,26 @@ namespace mozilla { * Note that when deriving from RefCounted or AtomicRefCounted, you * should add MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public * section of your class, where ClassName is the name of your class. - * - * Note: SpiderMonkey should use js::RefCounted instead since that type - * will use appropriate js_delete and also not break ref-count logging. */ namespace detail { const MozRefCountType DEAD = 0xffffdead; +#ifdef MOZ_REFCOUNTED_LEAK_CHECKING +// When this header is included in SpiderMonkey code, NS_LogAddRef and +// NS_LogRelease are not available. To work around this, we call these +// functions through a function pointer set by SetLeakCheckingFunctions. +// Note: these are globals because GCC on Linux reports undefined-reference +// errors when they're static members of the RefCountLogger class. +using LogAddRefFunc = void (*)(void* aPtr, MozRefCountType aNewRefCnt, + const char* aTypeName, uint32_t aClassSize); +using LogReleaseFunc = void (*)(void* aPtr, MozRefCountType aNewRefCnt, + const char* aTypeName); +extern MFBT_DATA LogAddRefFunc gLogAddRefFunc; +extern MFBT_DATA LogReleaseFunc gLogReleaseFunc; +extern MFBT_DATA size_t gNumStaticCtors; +extern MFBT_DATA const char* gLastStaticCtorTypeName; +#endif + // When building code that gets compiled into Gecko, try to use the // trace-refcount leak logging facilities. class RefCountLogger { @@ -78,10 +87,20 @@ class RefCountLogger { const void* pointer = aPointer; const char* typeName = aPointer->typeName(); uint32_t typeSize = aPointer->typeSize(); - NS_LogAddRef(const_cast(pointer), aRefCount, typeName, typeSize); + if (gLogAddRefFunc) { + gLogAddRefFunc(const_cast(pointer), aRefCount, typeName, typeSize); + } else { + gNumStaticCtors++; + gLastStaticCtorTypeName = typeName; + } #endif } +#ifdef MOZ_REFCOUNTED_LEAK_CHECKING + static MFBT_API void SetLeakCheckingFunctions(LogAddRefFunc aLogAddRefFunc, + LogReleaseFunc aLogReleaseFunc); +#endif + // Created by `RefCounted`-like classes to log a successful Release call in // the Gecko leak-logging system. The constructor should be invoked before the // refcount is decremented to avoid invoking `typeName()` with a zero @@ -100,7 +119,12 @@ class RefCountLogger { void logRelease(MozRefCountType aRefCount) { #ifdef MOZ_REFCOUNTED_LEAK_CHECKING MOZ_ASSERT(aRefCount != DEAD); - NS_LogRelease(const_cast(mPointer), aRefCount, mTypeName); + if (gLogReleaseFunc) { + gLogReleaseFunc(const_cast(mPointer), aRefCount, mTypeName); + } else { + gNumStaticCtors++; + gLastStaticCtorTypeName = mTypeName; + } #endif } diff --git a/src/third_party/mozjs/include/mozilla/RefPtr.h b/src/third_party/mozjs/include/mozilla/RefPtr.h index 27f22356bab..80257d8bd64 100644 --- a/src/third_party/mozjs/include/mozilla/RefPtr.h +++ b/src/third_party/mozjs/include/mozilla/RefPtr.h @@ -83,7 +83,7 @@ class MOZ_IS_REFPTR RefPtr { // Constructors - RefPtr() + constexpr RefPtr() : mRawPtr(nullptr) // default constructor {} @@ -431,7 +431,7 @@ inline void ImplCycleCollectionUnlink(RefPtr& aField) { template inline void ImplCycleCollectionTraverse( - nsCycleCollectionTraversalCallback& aCallback, RefPtr& aField, + nsCycleCollectionTraversalCallback& aCallback, const RefPtr& aField, const char* aName, uint32_t aFlags = 0) { CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); } diff --git a/src/third_party/mozjs/include/mozilla/SIMD.h b/src/third_party/mozjs/include/mozilla/SIMD.h index 3d171856567..18b78fbcdb5 100644 --- a/src/third_party/mozjs/include/mozilla/SIMD.h +++ b/src/third_party/mozjs/include/mozilla/SIMD.h @@ -54,6 +54,15 @@ class SIMD { static MFBT_API const char16_t* memchr16AVX2(const char16_t* ptr, char16_t value, size_t length); + // Search through `ptr[0..length]` for the first occurrence of `value` and + // return the pointer to it, or nullptr if it cannot be found. + static MFBT_API const uint32_t* memchr32(const uint32_t* ptr, uint32_t value, + size_t length); + + // This function just restricts our execution to the AVX2 path + static MFBT_API const uint32_t* memchr32AVX2(const uint32_t* ptr, + uint32_t value, size_t length); + // Search through `ptr[0..length]` for the first occurrence of `value` and // return the pointer to it, or nullptr if it cannot be found. static MFBT_API const uint64_t* memchr64(const uint64_t* ptr, uint64_t value, diff --git a/src/third_party/mozjs/include/mozilla/SegmentedVector.h b/src/third_party/mozjs/include/mozilla/SegmentedVector.h index c22c3e8d1f5..0198d81e9e6 100644 --- a/src/third_party/mozjs/include/mozilla/SegmentedVector.h +++ b/src/third_party/mozjs/include/mozilla/SegmentedVector.h @@ -224,10 +224,8 @@ class SegmentedVector : private AllocPolicy { } // Equivalent to calling |PopLast| |aNumElements| times, but potentially - // more efficient. + // more efficient. It is safe to call this even when aNumElements > Length(). void PopLastN(uint32_t aNumElements) { - MOZ_ASSERT(aNumElements <= Length()); - Segment* last; // Pop full segments for as long as we can. Note that this loop diff --git a/src/third_party/mozjs/include/mozilla/Span.h b/src/third_party/mozjs/include/mozilla/Span.h index ca754f3810f..132349bf7e4 100644 --- a/src/third_party/mozjs/include/mozilla/Span.h +++ b/src/third_party/mozjs/include/mozilla/Span.h @@ -365,7 +365,7 @@ class extent_type { * Subspan etc. */ template -class Span { +class MOZ_GSL_POINTER Span { public: // constants and types using element_type = ElementType; @@ -405,12 +405,14 @@ class Span { /** * Constructor for pointer and length. */ - constexpr Span(pointer aPtr, index_type aLength) : storage_(aPtr, aLength) {} + constexpr Span(pointer aPtr MOZ_LIFETIME_BOUND, index_type aLength) + : storage_(aPtr, aLength) {} /** * Constructor for start pointer and pointer past end. */ - constexpr Span(pointer aStartPtr, pointer aEndPtr) + constexpr Span(pointer aStartPtr MOZ_LIFETIME_BOUND, + pointer aEndPtr MOZ_LIFETIME_BOUND) : storage_(aStartPtr, std::distance(aStartPtr, aEndPtr)) {} /** @@ -438,7 +440,7 @@ class Span { * Constructor for C array. */ template - constexpr MOZ_IMPLICIT Span(element_type (&aArr)[N]) + constexpr MOZ_IMPLICIT Span(element_type (&aArr MOZ_LIFETIME_BOUND)[N]) : storage_(&aArr[0], span_details::extent_type()) {} // Implicit constructors for char* and char16_t* pointers are deleted in order @@ -463,7 +465,8 @@ class Span { */ template > - constexpr MOZ_IMPLICIT Span(std::array& aArr) + constexpr MOZ_IMPLICIT Span( + std::array& aArr MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -471,7 +474,8 @@ class Span { */ template constexpr MOZ_IMPLICIT Span( - const std::array, N>& aArr) + const std::array, N>& aArr + MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -479,7 +483,8 @@ class Span { */ template > - constexpr MOZ_IMPLICIT Span(mozilla::Array& aArr) + constexpr MOZ_IMPLICIT Span( + mozilla::Array& aArr MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -487,7 +492,8 @@ class Span { */ template constexpr MOZ_IMPLICIT Span( - const mozilla::Array, N>& aArr) + const mozilla::Array, N>& aArr + MOZ_LIFETIME_BOUND) : storage_(&aArr[0], span_details::extent_type()) {} /** @@ -496,15 +502,17 @@ class Span { template > constexpr MOZ_IMPLICIT Span( - mozilla::EnumeratedArray& aArr) + mozilla::EnumeratedArray& aArr + MOZ_LIFETIME_BOUND) : storage_(&aArr[Enum(0)], span_details::extent_type()) {} /** * Constructor for const mozilla::EnumeratedArray. */ template - constexpr MOZ_IMPLICIT Span(const mozilla::EnumeratedArray< - Enum, std::remove_const_t, N>& aArr) + constexpr MOZ_IMPLICIT Span( + const mozilla::EnumeratedArray, + N>& aArr MOZ_LIFETIME_BOUND) : storage_(&aArr[Enum(0)], span_details::extent_type()) {} /** @@ -512,7 +520,8 @@ class Span { */ template , class DeleterType> - constexpr Span(const mozilla::UniquePtr& aPtr, + constexpr Span(const mozilla::UniquePtr& aPtr + MOZ_LIFETIME_BOUND, index_type aLength) : storage_(aPtr.get(), aLength) {} diff --git a/src/third_party/mozjs/include/mozilla/StackWalk_windows.h b/src/third_party/mozjs/include/mozilla/StackWalk_windows.h index 81c81257810..ddc86b398a5 100644 --- a/src/third_party/mozjs/include/mozilla/StackWalk_windows.h +++ b/src/third_party/mozjs/include/mozilla/StackWalk_windows.h @@ -7,12 +7,30 @@ #ifndef mozilla_StackWalk_windows_h #define mozilla_StackWalk_windows_h +#include "mozilla/Array.h" #include "mozilla/Types.h" #if defined(_M_AMD64) || defined(_M_ARM64) /** - * Allow stack walkers to work around the egregious win64 dynamic lookup table - * list API by locking around SuspendThread to avoid deadlock. + * This function enables strategy (1) for avoiding deadlocks between the stack + * walking thread and the suspended thread. In aStackWalkLocks the caller must + * provide pointers to the two ntdll-internal SRW locks acquired by + * RtlLookupFunctionEntry. These locks are LdrpInvertedFunctionTableSRWLock and + * RtlpDynamicFunctionTableLock -- we don't need to know which one is which. + * Until InitializeStackWalkLocks function is called, strategy (2) is used. + * + * See comment in StackWalk.cpp + */ +MFBT_API +void InitializeStackWalkLocks(const mozilla::Array& aStackWalkLocks); + +/** + * As part of strategy (2) for avoiding deadlocks between the stack walking + * thread and the suspended thread, we mark stack walk suppression paths by + * putting them under the scope of a AutoSuppressStackWalking object. Any code + * path that may do an exclusive acquire of LdrpInvertedFunctionTableSRWLock or + * RtlpDynamicFunctionTableLock should be marked this way, to ensure that + * strategy (2) can properly mitigate all deadlock scenarios. * * See comment in StackWalk.cpp */ diff --git a/src/third_party/mozjs/include/mozilla/StringBuffer.h b/src/third_party/mozjs/include/mozilla/StringBuffer.h new file mode 100644 index 00000000000..eb75d5b3611 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/StringBuffer.h @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef StringBuffer_h__ +#define StringBuffer_h__ + +#include +#include +#include "mozilla/CheckedInt.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/Assertions.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Maybe.h" +#include "mozilla/RefCounted.h" +#include "mozmemory.h" + +namespace mozilla { + +/** + * This structure precedes the string buffers "we" allocate. It may be the + * case that nsTAString::mData does not point to one of these special + * buffers. The mDataFlags member variable distinguishes the buffer type. + * + * When this header is in use, it enables reference counting, and capacity + * tracking. NOTE: A string buffer can be modified only if its reference + * count is 1. + */ +class StringBuffer { + private: + std::atomic mRefCount; + uint32_t mStorageSize; + + public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(StringBuffer) + + /** + * Allocates a new string buffer, with given size in bytes and a + * reference count of one. When the string buffer is no longer needed, + * it should be released via Release. + * + * It is up to the caller to set the bytes corresponding to the string + * buffer by calling the Data method to fetch the raw data pointer. Care + * must be taken to properly null terminate the character array. The + * storage size can be greater than the length of the actual string + * (i.e., it is not required that the null terminator appear in the last + * storage unit of the string buffer's data). + * + * This guarantees that StorageSize() returns aSize if the returned + * buffer is non-null. Some callers like nsAttrValue rely on it. + * + * @return new string buffer or null if out of memory. + */ + static already_AddRefed Alloc( + size_t aSize, mozilla::Maybe aArena = mozilla::Nothing()) { + MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed"); + MOZ_ASSERT(sizeof(StringBuffer) + aSize <= size_t(uint32_t(-1)) && + sizeof(StringBuffer) + aSize > aSize, + "mStorageSize will truncate"); + + size_t bytes = sizeof(StringBuffer) + aSize; + //MONGODB Modification: We must use our custom arena_malloc function instead of the mozJS one. + void* hdr = aArena ? js_arena_malloc(*aArena, bytes) : malloc(bytes); + if (!hdr) { + return nullptr; + } + return ConstructInPlace(hdr, aSize); + } + + /** + * Like Alloc, but use aBuffer instead of allocating a new buffer. This can + * be used when the caller already has a malloced buffer of the right size and + * allocating a new one would be too expensive. + * + * aStorageSize must be the string's length in bytes (including the null + * terminator). The caller must initialize all of these bytes either before or + * after calling this function. + * + * @return the new StringBuffer header. + */ + static already_AddRefed ConstructInPlace(void* aBuffer, + size_t aStorageSize) { + MOZ_ASSERT(aBuffer, "must have a valid buffer"); + MOZ_ASSERT(aStorageSize != 0, "zero capacity StringBuffer not allowed"); + auto* hdr = new (aBuffer) StringBuffer(); + hdr->mRefCount = 1; + hdr->mStorageSize = aStorageSize; + detail::RefCountLogger::logAddRef(hdr, 1); + return already_AddRefed(hdr); + } + + /** + * Returns true if (aLength + 1) * sizeof(CharT) is a valid allocation size + * for Alloc. Adds +1 to aLength for the null-terminator. + */ + template + static constexpr bool IsValidLength(size_t aLength) { + auto checkedSize = + (CheckedUint32(aLength) + 1) * sizeof(CharT) + sizeof(StringBuffer); + return checkedSize.isValid(); + } + + /** + * Returns a string buffer initialized with the given string on it, or null on + * OOM. + * Note that this will allocate extra space for the trailing null byte, which + * this method will add. + */ + static already_AddRefed Create(const char16_t* aData, + size_t aLength) { + return DoCreate(aData, aLength); + } + static already_AddRefed Create(const char* aData, + size_t aLength) { + return DoCreate(aData, aLength); + } + static already_AddRefed Create(const unsigned char* aData, + size_t aLength) { + return DoCreate(aData, aLength); + } + + /** + * Resizes the given string buffer to the specified storage size. This + * method must not be called on a readonly string buffer. Use this API + * carefully!! + * + * This method behaves like the ANSI-C realloc function. (i.e., If the + * allocation fails, null will be returned and the given string buffer + * will remain unmodified.) + * + * @see IsReadonly + */ + static StringBuffer* Realloc( + StringBuffer* aHdr, size_t aSize, + mozilla::Maybe aArena = mozilla::Nothing()) { + MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed"); + MOZ_ASSERT(sizeof(StringBuffer) + aSize <= size_t(uint32_t(-1)) && + sizeof(StringBuffer) + aSize > aSize, + "mStorageSize will truncate"); + + // no point in trying to save ourselves if we hit this assertion + MOZ_ASSERT(!aHdr->IsReadonly(), "|Realloc| attempted on readonly string"); + + // Treat this as a release and addref for refcounting purposes, since we + // just asserted that the refcount is 1. If we don't do that, refcount + // logging will claim we've leaked all sorts of stuff. + { + detail::RefCountLogger::ReleaseLogger logger(aHdr); + logger.logRelease(0); + } + + size_t bytes = sizeof(StringBuffer) + aSize; + //MONGODB Modification: We must use our custom arena_realloc function instead of the mozJS one. + aHdr = aArena ? (StringBuffer*)js_arena_realloc(*aArena, aHdr, bytes) + : (StringBuffer*)realloc(aHdr, bytes); + if (aHdr) { + detail::RefCountLogger::logAddRef(aHdr, 1); + aHdr->mStorageSize = aSize; + } + + return aHdr; + } + + void AddRef() { + // Memory synchronization is not required when incrementing a + // reference count. The first increment of a reference count on a + // thread is not important, since the first use of the object on a + // thread can happen before it. What is important is the transfer + // of the pointer to that thread, which may happen prior to the + // first increment on that thread. The necessary memory + // synchronization is done by the mechanism that transfers the + // pointer between threads. + uint32_t count = mRefCount.fetch_add(1, std::memory_order_relaxed) + 1; + detail::RefCountLogger::logAddRef(this, count); + } + + void Release() { + // Since this may be the last release on this thread, we need release + // semantics so that prior writes on this thread are visible to the thread + // that destroys the object when it reads mValue with acquire semantics. + detail::RefCountLogger::ReleaseLogger logger(this); + uint32_t count = mRefCount.fetch_sub(1, std::memory_order_release) - 1; + logger.logRelease(count); + if (count == 0) { + // We're going to destroy the object on this thread, so we need acquire + // semantics to synchronize with the memory released by the last release + // on other threads, that is, to ensure that writes prior to that release + // are now visible on this thread. + count = mRefCount.load(std::memory_order_acquire); + free(this); // We were allocated with malloc. + } + } + + /** + * This method returns the string buffer corresponding to the given data + * pointer. The data pointer must have been returned previously by a + * call to the StringBuffer::Data method. + */ + static StringBuffer* FromData(void* aData) { + return reinterpret_cast(aData) - 1; + } + + /** + * This method returns the data pointer for this string buffer. + */ + void* Data() const { + return const_cast(reinterpret_cast(this + 1)); + } + + /** + * This function returns the storage size of a string buffer in bytes. + * This value is the same value that was originally passed to Alloc (or + * Realloc). + */ + uint32_t StorageSize() const { return mStorageSize; } + + /** + * This function returns the allocation size of a string buffer in bytes. + * This includes the size of the StringBuffer header. + */ + uint32_t AllocationSize() const { + return sizeof(StringBuffer) + StorageSize(); + } + + /** + * If this method returns false, then the caller can be sure that their + * reference to the string buffer is the only reference to the string + * buffer, and therefore it has exclusive access to the string buffer and + * associated data. However, if this function returns true, then other + * consumers may rely on the data in this buffer being immutable and + * other threads may access this buffer simultaneously. + */ + bool IsReadonly() const { + // This doesn't lead to the destruction of the buffer, so we don't + // need to perform acquire memory synchronization for the normal + // reason that a reference count needs acquire synchronization + // (ensuring that all writes to the object made on other threads are + // visible to the thread destroying the object). + // + // We then need to consider the possibility that there were prior + // writes to the buffer on a different thread: one that has either + // since released its reference count, or one that also has access + // to this buffer through the same reference. There are two ways + // for that to happen: either the buffer pointer or a data structure + // (e.g., string object) pointing to the buffer was transferred from + // one thread to another, or the data structure pointing to the + // buffer was already visible on both threads. In the first case + // (transfer), the transfer of data from one thread to another would + // have handled the memory synchronization. In the latter case + // (data structure visible on both threads), the caller needed some + // sort of higher level memory synchronization to protect against + // the string object being mutated at the same time on multiple + // threads. + + // See bug 1603504. TSan might complain about a race when using + // memory_order_relaxed, so use memory_order_acquire for making TSan + // happy. +#if defined(MOZ_TSAN) + return mRefCount.load(std::memory_order_acquire) > 1; +#else + return mRefCount.load(std::memory_order_relaxed) > 1; +#endif + } + + /** + * Alias for IsReadOnly. + */ + bool HasMultipleReferences() const { return IsReadonly(); } + +#ifdef DEBUG + /** + * Returns the buffer's reference count. This is only exposed for logging and + * testing purposes. + */ + uint32_t RefCount() const { + return mRefCount.load(std::memory_order_acquire); + } +#endif + + /** + * This measures the size only if the StringBuffer is unshared. + */ + size_t SizeOfIncludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const { + return IsReadonly() ? 0 : aMallocSizeOf(this); + } + + /** + * This measures the size regardless of whether the StringBuffer is + * unshared. + * + * WARNING: Only use this if you really know what you are doing, because + * it can easily lead to double-counting strings. If you do use them, + * please explain clearly in a comment why it's safe and won't lead to + * double-counting. + */ + size_t SizeOfIncludingThisEvenIfShared(MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(this); + } + + private: + template + static already_AddRefed DoCreate(const CharT* aData, + size_t aLength) { + StringBuffer* buffer = Alloc((aLength + 1) * sizeof(CharT)).take(); + if (MOZ_LIKELY(buffer)) { + auto* data = reinterpret_cast(buffer->Data()); + memcpy(data, aData, aLength * sizeof(CharT)); + data[aLength] = 0; + } + return already_AddRefed(buffer); + } +}; + +} // namespace mozilla + +#endif diff --git a/src/third_party/mozjs/include/mozilla/TimeStamp.h b/src/third_party/mozjs/include/mozilla/TimeStamp.h index 635b62cf137..81e7515a956 100644 --- a/src/third_party/mozjs/include/mozilla/TimeStamp.h +++ b/src/third_party/mozjs/include/mozilla/TimeStamp.h @@ -387,6 +387,7 @@ static_assert(sizeof(TimeStampValue) > 8); */ class TimeStamp { public: + using DurationType = TimeDuration; /** * Initialize to the "null" moment */ diff --git a/src/third_party/mozjs/include/mozilla/Try.h b/src/third_party/mozjs/include/mozilla/Try.h index a650a33ea27..fa6ec09fb77 100644 --- a/src/third_party/mozjs/include/mozilla/Try.h +++ b/src/third_party/mozjs/include/mozilla/Try.h @@ -10,10 +10,41 @@ #include "mozilla/Result.h" /** - * MOZ_TRY(expr) is the C++ equivalent of Rust's `try!(expr);`. First, it - * evaluates expr, which must produce a Result value. On success, it - * discards the result altogether. On error, it immediately returns an error - * Result from the enclosing function. + * MOZ_TRY(expr) is the C++ equivalent of Rust's `target = try!(expr);`, using + * gcc's statement expressions [0]. First, it evaluates expr, which must produce + * a Result value. On success, the result's success value is 'returned' as + * rvalue. On error, immediately returns the error result. This pattern allows + * to directly assign the success value: + * + * ``` + * SuccessValue val = MOZ_TRY(Func()); + * ``` + * + * Where `Func()` returns a `Result` and is called in a + * function that returns `Result`. + * + * [0]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html + */ +#ifndef _MSC_VER + +#define MOZ_TRY(expr) \ + __extension__({ \ + auto mozTryVarTempResult = ::mozilla::ToResult(expr); \ + if (MOZ_UNLIKELY(mozTryVarTempResult.isErr())) { \ + return mozTryVarTempResult.propagateErr(); \ + } \ + mozTryVarTempResult.unwrap(); \ + }) + +#else + +/** + * MONGODB MODIFICATION: statement expressions are a gcc extension + * unsupported by MSVC, reimplement with standard C++. + * + * This implementation doesn't return the result of expr, + * so MOZ_TRY_VAR should be used instead. If this is necessary + * behavior, consider implementing using a lambda */ #define MOZ_TRY(expr) \ do { \ @@ -23,12 +54,34 @@ } \ } while (0) +#endif // _MSC_VER + /** * MOZ_TRY_VAR(target, expr) is the C++ equivalent of Rust's `target = * try!(expr);`. First, it evaluates expr, which must produce a Result value. On * success, the result's success value is assigned to target. On error, * immediately returns the error result. |target| must be an lvalue. + * + * This macro is obsolete and its usages should be replaced with `MOZ_TRY`. */ +#ifndef _MSC_VER + +#define MOZ_TRY_VAR(target, expr) (target) = MOZ_TRY(expr); + +#else + +/** + * MONGODB MODIFICATION: statement expressions are a gcc extension + * unsupported by MSVC, reimplement with standard C++. + */ +#define MOZ_TRY(expr) \ + do { \ + auto mozTryTempResult_ = ::mozilla::ToResult(expr); \ + if (MOZ_UNLIKELY(mozTryTempResult_.isErr())) { \ + return mozTryTempResult_.propagateErr(); \ + } \ + } while (0) + #define MOZ_TRY_VAR(target, expr) \ do { \ auto mozTryVarTempResult_ = (expr); \ @@ -38,4 +91,6 @@ (target) = mozTryVarTempResult_.unwrap(); \ } while (0) +#endif // _MSC_VER + #endif // mozilla_Try_h diff --git a/src/third_party/mozjs/include/mozilla/UniquePtr.h b/src/third_party/mozjs/include/mozilla/UniquePtr.h index 9b51e58db31..b7b41520366 100644 --- a/src/third_party/mozjs/include/mozilla/UniquePtr.h +++ b/src/third_party/mozjs/include/mozilla/UniquePtr.h @@ -187,7 +187,7 @@ struct PointerType { * |UniquePtr&&| argument. */ template -class UniquePtr { +class MOZ_GSL_OWNER UniquePtr { public: typedef T ElementType; typedef D DeleterType; @@ -214,12 +214,13 @@ class UniquePtr { /** * Construct a UniquePtr containing |aPtr|. */ - explicit UniquePtr(Pointer aPtr) : mTuple(aPtr, DeleterType()) { + explicit UniquePtr(Pointer aPtr MOZ_LIFETIME_BOUND) + : mTuple(aPtr, DeleterType()) { static_assert(!std::is_pointer_v, "must provide a deleter instance"); static_assert(!std::is_reference_v, "must provide a deleter instance"); } - UniquePtr(Pointer aPtr, + UniquePtr(Pointer aPtr MOZ_LIFETIME_BOUND, std::conditional_t, D, const D&> aD1) : mTuple(aPtr, aD1) {} @@ -273,21 +274,21 @@ class UniquePtr { return *this; } - std::add_lvalue_reference_t operator*() const { + std::add_lvalue_reference_t operator*() const MOZ_LIFETIME_BOUND { MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr with *"); return *get(); } - Pointer operator->() const { + Pointer operator->() const MOZ_LIFETIME_BOUND { MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr with ->"); return get(); } explicit operator bool() const { return get() != nullptr; } - Pointer get() const { return ptr(); } + Pointer get() const MOZ_LIFETIME_BOUND { return ptr(); } - DeleterType& get_deleter() { return del(); } - const DeleterType& get_deleter() const { return del(); } + DeleterType& get_deleter() MOZ_LIFETIME_BOUND { return del(); } + const DeleterType& get_deleter() const MOZ_LIFETIME_BOUND { return del(); } [[nodiscard]] Pointer release() { Pointer p = ptr(); diff --git a/src/third_party/mozjs/include/mozilla/UniquePtrExtensions.h b/src/third_party/mozjs/include/mozilla/UniquePtrExtensions.h index 2679440e501..565d4bf1fce 100644 --- a/src/third_party/mozjs/include/mozilla/UniquePtrExtensions.h +++ b/src/third_party/mozjs/include/mozilla/UniquePtrExtensions.h @@ -93,28 +93,29 @@ struct FreePolicy { void operator()(const void* ptr) { free(const_cast(ptr)); } }; -#if defined(XP_WIN) +#if !defined(RUST_BINDGEN) +# if defined(XP_WIN) // Can't include to get the actual definition of HANDLE // because of namespace pollution. typedef void* FileHandleType; -#elif defined(XP_UNIX) +# elif defined(XP_UNIX) typedef int FileHandleType; -#else -# error "Unsupported OS?" -#endif +# else +# error "Unsupported OS?" +# endif struct FileHandleHelper { MOZ_IMPLICIT FileHandleHelper(FileHandleType aHandle) : mHandle(aHandle) { -#if defined(XP_UNIX) && (defined(DEBUG) || defined(FUZZING)) +# if defined(XP_UNIX) && (defined(DEBUG) || defined(FUZZING)) MOZ_RELEASE_ASSERT(aHandle == kInvalidHandle || aHandle > 2); -#endif +# endif } MOZ_IMPLICIT constexpr FileHandleHelper(std::nullptr_t) : mHandle(kInvalidHandle) {} bool operator!=(std::nullptr_t) const { -#ifdef XP_WIN +# ifdef XP_WIN // Windows uses both nullptr and INVALID_HANDLE_VALUE (-1 cast to // HANDLE) in different situations, but nullptr is more reliably // null while -1 is also valid input to some calls that take @@ -123,20 +124,20 @@ struct FileHandleHelper { if (mHandle == (void*)-1) { return false; } -#endif +# endif return mHandle != kInvalidHandle; } operator FileHandleType() const { return mHandle; } -#ifdef XP_WIN +# ifdef XP_WIN // NSPR uses an integer type for PROsfd, so this conversion is // provided for working with it without needing reinterpret casts // everywhere. operator std::intptr_t() const { return reinterpret_cast(mHandle); } -#endif +# endif // When there's only one user-defined conversion operator, the // compiler will use that to derive equality, but that doesn't work @@ -148,13 +149,13 @@ struct FileHandleHelper { private: FileHandleType mHandle; -#ifdef XP_WIN +# ifdef XP_WIN // See above for why this is nullptr. (Also, INVALID_HANDLE_VALUE // can't be expressed as a constexpr.) static constexpr FileHandleType kInvalidHandle = nullptr; -#else +# else static constexpr FileHandleType kInvalidHandle = -1; -#endif +# endif }; struct FileHandleDeleter { @@ -162,6 +163,7 @@ struct FileHandleDeleter { using receiver = FileHandleType; MFBT_API void operator()(FileHandleHelper aHelper); }; +#endif #if defined(XP_DARWIN) && !defined(RUST_BINDGEN) struct MachPortHelper { @@ -215,11 +217,21 @@ struct MachPortSetDeleter { template using UniqueFreePtr = UniquePtr>; +#if !defined(RUST_BINDGEN) // A RAII class for the OS construct used for open files and similar // objects: a file descriptor on Unix or a handle on Windows. using UniqueFileHandle = UniquePtr; +# ifndef __wasm__ +// WASI does not have `dup` +MFBT_API UniqueFileHandle DuplicateFileHandle(detail::FileHandleType aFile); +inline UniqueFileHandle DuplicateFileHandle(const UniqueFileHandle& aFile) { + return DuplicateFileHandle(aFile.get()); +} +# endif +#endif + #if defined(XP_DARWIN) && !defined(RUST_BINDGEN) // A RAII class for a Mach port that names a send right. using UniqueMachSendRight = diff --git a/src/third_party/mozjs/include/mozilla/Variant.h b/src/third_party/mozjs/include/mozilla/Variant.h index d1db3a2cc92..848499f81d9 100644 --- a/src/third_party/mozjs/include/mozilla/Variant.h +++ b/src/third_party/mozjs/include/mozilla/Variant.h @@ -567,7 +567,8 @@ struct VariantIndex { * instead. */ template -class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { +class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS +MOZ_NON_PARAM MOZ_GSL_OWNER Variant { friend struct IPC::ParamTraits>; friend struct mozilla::ipc::IPDLParamTraits>; @@ -739,7 +740,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Mutable lvalue-reference. */ template - T& as() & { + T& as() & MOZ_LIFETIME_BOUND { static_assert( detail::SelectVariantType::count == 1, "provided a type not uniquely found in this Variant's type list"); @@ -748,7 +749,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - typename detail::Nth::Type& as() & { + typename detail::Nth::Type& as() & MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -757,7 +758,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Immutable const lvalue-reference. */ template - const T& as() const& { + const T& as() const& MOZ_LIFETIME_BOUND { static_assert(detail::SelectVariantType::count == 1, "provided a type not found in this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -765,7 +766,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - const typename detail::Nth::Type& as() const& { + const typename detail::Nth::Type& as() const& MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -774,7 +775,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Mutable rvalue-reference. */ template - T&& as() && { + T&& as() && MOZ_LIFETIME_BOUND { static_assert( detail::SelectVariantType::count == 1, "provided a type not uniquely found in this Variant's type list"); @@ -783,7 +784,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - typename detail::Nth::Type&& as() && { + typename detail::Nth::Type&& as() && MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -793,7 +794,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { /** Immutable const rvalue-reference. */ template - const T&& as() const&& { + const T&& as() const&& MOZ_LIFETIME_BOUND { static_assert(detail::SelectVariantType::count == 1, "provided a type not found in this Variant's type list"); MOZ_RELEASE_ASSERT(is()); @@ -801,7 +802,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant { } template - const typename detail::Nth::Type&& as() const&& { + const typename detail::Nth::Type&& as() const&& MOZ_LIFETIME_BOUND { static_assert(N < sizeof...(Ts), "provided an index outside of this Variant's type list"); MOZ_RELEASE_ASSERT(is()); diff --git a/src/third_party/mozjs/include/mozilla/Vector.h b/src/third_party/mozjs/include/mozilla/Vector.h index 380e2725486..84e5845de66 100644 --- a/src/third_party/mozjs/include/mozilla/Vector.h +++ b/src/third_party/mozjs/include/mozilla/Vector.h @@ -339,7 +339,7 @@ struct VectorTesting; */ template -class MOZ_NON_PARAM Vector final : private AllocPolicy { +class MOZ_NON_PARAM MOZ_GSL_OWNER Vector final : private AllocPolicy { /* utilities */ static constexpr bool kElemIsPod = std::is_trivial_v && std::is_standard_layout_v; diff --git a/src/third_party/mozjs/include/mozilla/WindowsDiagnostics.h b/src/third_party/mozjs/include/mozilla/WindowsDiagnostics.h index 09bc314e893..d9a03ef10c2 100644 --- a/src/third_party/mozjs/include/mozilla/WindowsDiagnostics.h +++ b/src/third_party/mozjs/include/mozilla/WindowsDiagnostics.h @@ -86,9 +86,7 @@ struct WinErrorState { bool operator!=(WinErrorState const& that) const { return !operator==(that); } }; -// TODO This code does not have tests. Only use it on paths that are already -// known to crash. Add tests before using it in release builds. -#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && defined(_M_X64) +#if defined(_M_AMD64) using OnSingleStepCallback = std::function; @@ -108,9 +106,6 @@ MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void EnableTrapFlag(); MFBT_API MOZ_NEVER_INLINE __attribute__((naked)) void DisableTrapFlag(); MFBT_API LONG SingleStepExceptionHandler(_EXCEPTION_POINTERS* aExceptionInfo); -// This block uses nt::PEHeaders and thus depends on NativeNt.h. -# if !defined(IMPL_MFBT) - // Run aCallbackToRun instruction by instruction, and between each instruction // call aOnSingleStepCallback. Single-stepping ends when aOnSingleStepCallback // returns false (in which case aCallbackToRun will continue to run @@ -140,6 +135,9 @@ CollectSingleStepData(CallbackToRun aCallbackToRun, return WindowsDiagnosticsError::None; } +// This block uses nt::PEHeaders and thus depends on NativeNt.h. +# if !defined(IMPL_MFBT) + template struct ModuleSingleStepData { uint32_t mStepsLog[NMaxSteps]{}; @@ -288,7 +286,7 @@ WindowsDiagnosticsError CollectModuleSingleStepData( # endif // !IMPL_MFBT -#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED && _M_X64 +#endif // _M_AMD64 } // namespace mozilla diff --git a/src/third_party/mozjs/include/mozilla/WindowsDpiAwareness.h b/src/third_party/mozjs/include/mozilla/WindowsDpiAwareness.h index 589415da6d0..4ba641cc95a 100644 --- a/src/third_party/mozjs/include/mozilla/WindowsDpiAwareness.h +++ b/src/third_party/mozjs/include/mozilla/WindowsDpiAwareness.h @@ -21,9 +21,9 @@ typedef enum DPI_AWARENESS { DPI_AWARENESS_PER_MONITOR_AWARE = 2 } DPI_AWARENESS; -# define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1) -# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2) -# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) +# define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT) - 1) +# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT) - 2) +# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT) - 3) # define DPI_AWARENESS_CONTEXT_DECLARED #endif // (DPI_AWARENESS_CONTEXT_DECLARED) diff --git a/src/third_party/mozjs/include/mozilla/WindowsUnwindInfo.h b/src/third_party/mozjs/include/mozilla/WindowsUnwindInfo.h index 3667b5f2bc8..be76670d2d9 100644 --- a/src/third_party/mozjs/include/mozilla/WindowsUnwindInfo.h +++ b/src/third_party/mozjs/include/mozilla/WindowsUnwindInfo.h @@ -290,7 +290,7 @@ class IterableUnwindInfo { : mInfo(aInfo), mIndex(aIndex), mSlotsCount(aSlotsCount), - mIsValid(aIsValid){}; + mIsValid(aIsValid) {}; UnwindInfo& mInfo; uint8_t mIndex; diff --git a/src/third_party/mozjs/include/mozilla/WrappingOperations.h b/src/third_party/mozjs/include/mozilla/WrappingOperations.h index bd67ac34f18..99d28f68f41 100644 --- a/src/third_party/mozjs/include/mozilla/WrappingOperations.h +++ b/src/third_party/mozjs/include/mozilla/WrappingOperations.h @@ -17,8 +17,9 @@ * 2) They implement this functionality *safely*, without invoking signed * integer overflow that has undefined behavior in C++. * 3) They play nice with compiler-based integer-overflow sanitizers (see - * build/autoconf/sanitize.m4), that in appropriately configured builds - * verify at runtime that integral arithmetic doesn't overflow. + * build/moz.configure/toolchain.configure), that in appropriately + * configured builds verify at runtime that integral arithmetic doesn't + * overflow. */ #ifndef mozilla_WrappingOperations_h diff --git a/src/third_party/mozjs/include/mozilla/leb128iterator.h b/src/third_party/mozjs/include/mozilla/leb128iterator.h new file mode 100644 index 00000000000..636baf916f0 --- /dev/null +++ b/src/third_party/mozjs/include/mozilla/leb128iterator.h @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// LEB128 utilities that can read/write unsigned LEB128 numbers from/to +// iterators. +// +// LEB128 = Little Endian Base 128, where small numbers take few bytes, but +// large numbers are still allowed, which is ideal when serializing numbers that +// are likely to be small. +// Each byte contains 7 bits from the number, starting at the "little end", the +// top bit is 0 for the last byte, 1 otherwise. +// Numbers 0-127 only take 1 byte. 128-16383 take 2 bytes. Etc. +// +// Iterators only need to provide: +// - `*it` to return a reference to the next byte to be read from or written to. +// - `++it` to advance the iterator after a byte is written. +// +// The caller must always provide sufficient space to write any number, by: +// - pre-allocating a large enough buffer, or +// - allocating more space when `++it` reaches the end and/or `*it` is invoked +// after the end, or +// - moving the underlying pointer to an appropriate location (e.g., wrapping +// around a circular buffer). +// The caller must also provide enough bytes to read a full value (i.e., at +// least one byte should have its top bit unset), and a type large enough to +// hold the stored value. +// +// Note: There are insufficient checks for validity! These functions are +// intended to be used together, i.e., the user should only `ReadULEB128()` from +// a sufficiently-large buffer that the same user filled with `WriteULEB128()`. +// Using with externally-sourced data (e.g., DWARF) is *not* recommended. +// +// https://en.wikipedia.org/wiki/LEB128 + +#ifndef leb128iterator_h +#define leb128iterator_h + +#include "mozilla/Assertions.h" +#include "mozilla/Likely.h" + +#include +#include +#include +#include + +namespace mozilla { + +// Number of bytes needed to represent `aValue`. +template +constexpr uint_fast8_t ULEB128Size(T aValue) { + static_assert(!std::numeric_limits::is_signed, + "ULEB128Size only takes unsigned types"); + // We need one output byte per 7 bits of non-zero value. So we just remove + // 7 least significant bits at a time until the value becomes zero. + // Note the special case of 0, which still needs 1 output byte; this is done + // by starting the first loop before we check for 0. + uint_fast8_t size = 0; + for (;;) { + size += 1; + aValue >>= 7; + // Expecting small values, so it should be more likely that `aValue == 0`. + if (MOZ_LIKELY(aValue == 0)) { + return size; + } + } +} + +// Maximum number of bytes needed to represent any value of type `T`. +template +constexpr uint_fast8_t ULEB128MaxSize() { + return ULEB128Size(std::numeric_limits::max()); +} + +// Write `aValue` in LEB128 to `aIterator`. +// The iterator will be moved past the last byte. +template +void WriteULEB128(T aValue, It& aIterator) { + static_assert(!std::numeric_limits::is_signed, + "WriteULEB128 only takes unsigned types"); + using IteratorValue = std::remove_reference_t; + static_assert(sizeof(IteratorValue) == 1, + "WriteULEB128 expects an iterator to single bytes"); + // 0. Don't test for 0 yet, as we want to output one byte for it. + for (;;) { + // 1. Extract the 7 least significant bits. + const uint_fast8_t byte = aValue & 0x7Fu; + // 2. Remove them from `aValue`. + aValue >>= 7; + // 3. Write the 7 bits, and set the 8th bit if `aValue` is not 0 yet + // (meaning there will be more bytes after this one.) + // Expecting small values, so it should be more likely that `aValue == 0`. + // Note: No absolute need to force-cast to IteratorValue, because we have + // only changed the bottom 8 bits above. However the compiler could warn + // about a narrowing conversion from potentially-multibyte uint_fast8_t down + // to whatever single-byte type `*iterator* expects, so we make it explicit. + *aIterator = static_cast( + MOZ_LIKELY(aValue == 0) ? byte : (byte | 0x80u)); + // 4. Always advance the iterator to the next byte. + ++aIterator; + // 5. We're done if `aValue` is 0. + // Expecting small values, so it should be more likely that `aValue == 0`. + if (MOZ_LIKELY(aValue == 0)) { + return; + } + } +} + +// Read an LEB128 value from `aIterator`. +// The iterator will be moved past the last byte. +template +T ReadULEB128(It& aIterator) { + static_assert(!std::numeric_limits::is_signed, + "ReadULEB128 must return an unsigned type"); + using IteratorValue = std::remove_reference_t; + static_assert(sizeof(IteratorValue) == 1, + "ReadULEB128 expects an iterator to single bytes"); + // Incoming bits will be added to `result`... + T result = 0; + // ... starting with the least significant bits. + uint_fast8_t shift = 0; + for (;;) { + // 1. Read one byte from the iterator. + // `static_cast` just in case IteratorValue is not implicitly convertible to + // uint_fast8_t. It wouldn't matter if the sign was extended, we're only + // dealing with the bottom 8 bits below. + const uint_fast8_t byte = static_cast(*aIterator); + // 2. Always advance the iterator. + ++aIterator; + // 3. Extract the 7 bits of value, and shift them in place into `result`. + result |= static_cast(byte & 0x7fu) << shift; + // 4. If the 8th bit is *not* set, this was the last byte. + // Expecting small values, so it should be more likely that the bit is off. + if (MOZ_LIKELY((byte & 0x80u) == 0)) { + return result; + } + // There are more bytes to read. + // 5. Next byte will contain more significant bits above the past 7. + shift += 7; + // Safety check that we're not going to shift by >= than the type size, + // which is Undefined Behavior in C++. + MOZ_ASSERT(shift < CHAR_BIT * sizeof(T)); + } +} + +// constexpr ULEB128 reader class. +// Mostly useful when dealing with non-trivial byte feeds. +template +class ULEB128Reader { + static_assert(!std::numeric_limits::is_signed, + "ULEB128Reader must handle an unsigned type"); + + public: + constexpr ULEB128Reader() = default; + + // Don't allow copy/assignment, it doesn't make sense for a stateful parser. + constexpr ULEB128Reader(const ULEB128Reader&) = delete; + constexpr ULEB128Reader& operator=(const ULEB128Reader&) = delete; + + // Feed a byte into the parser. + // Returns true if this was the last byte. + [[nodiscard]] constexpr bool FeedByteIsComplete(unsigned aByte) { + MOZ_ASSERT(!IsComplete()); + // Extract the 7 bits of value, and shift them in place into the value. + mValue |= static_cast(aByte & 0x7fu) << mShift; + // If the 8th bit is *not* set, this was the last byte. + // Expecting small values, so it should be more likely that the bit is off. + if (MOZ_LIKELY((aByte & 0x80u) == 0)) { + mShift = mCompleteShift; + return true; + } + // There are more bytes to read. + // Next byte will contain more significant bits above the past 7. + mShift += 7; + // Safety check that we're not going to shift by >= than the type size, + // which is Undefined Behavior in C++. + MOZ_ASSERT(mShift < CHAR_BIT * sizeof(T)); + return false; + } + + constexpr void Reset() { + mValue = 0; + mShift = 0; + } + + [[nodiscard]] constexpr bool IsComplete() const { + return mShift == mCompleteShift; + } + + [[nodiscard]] constexpr T Value() const { + MOZ_ASSERT(IsComplete()); + return mValue; + } + + private: + // Special value of `mShift` indicating that parsing is complete. + constexpr static unsigned mCompleteShift = 0x10000u; + + T mValue = 0; + unsigned mShift = 0; +}; + +} // namespace mozilla + +#endif // leb128iterator_h diff --git a/src/third_party/mozjs/include/mozjemalloc_types.h b/src/third_party/mozjs/include/mozjemalloc_types.h index 5f8872ff405..1a0ad44a210 100644 --- a/src/third_party/mozjs/include/mozjemalloc_types.h +++ b/src/third_party/mozjs/include/mozjemalloc_types.h @@ -92,22 +92,23 @@ typedef struct arena_params_s { } arena_params_t; // jemalloc_stats() is not a stable interface. When using jemalloc_stats_t, be -// sure that the compiled results of jemalloc.c are in sync with this header -// file. +// sure that the compiled results of mozjemalloc.cpp are in sync with this +// header file. typedef struct { // Run-time configuration settings. - bool opt_junk; // Fill allocated memory with kAllocJunk? - bool opt_zero; // Fill allocated memory with 0x0? - size_t narenas; // Number of arenas. - size_t quantum; // Allocation quantum. - size_t quantum_max; // Max quantum-spaced allocation size. - size_t quantum_wide; // Allocation quantum (QuantuWide). - size_t quantum_wide_max; // Max quantum-wide-spaced allocation size. - size_t subpage_max; // Max subpage allocation size. - size_t large_max; // Max sub-chunksize allocation size. - size_t chunksize; // Size of each virtual memory mapping. - size_t page_size; // Size of pages. - size_t dirty_max; // Max dirty pages per arena. + bool opt_junk; // Fill allocated memory with kAllocJunk? + bool opt_randomize_small; // Randomization of small allocations? + bool opt_zero; // Fill allocated memory with 0x0? + size_t narenas; // Number of arenas. + size_t quantum; // Allocation quantum. + size_t quantum_max; // Max quantum-spaced allocation size. + size_t quantum_wide; // Allocation quantum (QuantuWide). + size_t quantum_wide_max; // Max quantum-wide-spaced allocation size. + size_t subpage_max; // Max subpage allocation size. + size_t large_max; // Max sub-chunksize allocation size. + size_t chunksize; // Size of each virtual memory mapping. + size_t page_size; // Size of pages. + size_t dirty_max; // Max dirty pages per arena. // Current memory usage statistics. size_t mapped; // Bytes mapped (not necessarily committed). @@ -121,6 +122,13 @@ typedef struct { size_t bookkeeping; // Committed bytes used internally by the // allocator. size_t bin_unused; // Bytes committed to a bin but currently unused. + + size_t num_operations; // The number of malloc()+free() calls. Note that + // realloc calls + // count as 0, 1 or 2 operations depending on internal + // operations. Which internal operations (eg in place + // or move, or different size classes) require + // different internal operations is unspecified. } jemalloc_stats_t; typedef struct { @@ -131,8 +139,21 @@ typedef struct { size_t bytes_unused; // The unallocated bytes across all these bins size_t bytes_total; // The total storage area for runs in this bin, size_t bytes_per_run; // The number of bytes per run, including headers. + size_t regions_per_run; // The number of regions (aka cells) per run. } jemalloc_bin_stats_t; +// jemalloc_stats_lite() is not a stable interface. When using +// jemalloc_stats_lite_t, be sure that the compiled results of mozjemalloc.cpp +// are in sync with this header file. +typedef struct { + size_t allocated_bytes; + + // The number of malloc()+free() calls. realloc calls count as 0, 1 or 2 + // operations depending on whether they do nothing, resize in-place, or move + // the memory. + uint64_t num_operations; +} jemalloc_stats_lite_t; + enum PtrInfoTag { // The pointer is not currently known to the allocator. // 'addr', 'size', and 'arenaId' are always 0. @@ -194,6 +215,22 @@ static inline bool jemalloc_ptr_is_freed_page(jemalloc_ptr_info_t* info) { return info->tag == TagFreedPage; } +// The result of a purge step. +enum purge_result_t { + // Done: No more purge requests are pending. + Done, + + // There may be one or more arenas whose reuse grace period expired and + // needs purging asap. + NeedsMore, + + // There is at least one arena that waits either for its reuse grace to + // expire or for significant reuse to happen. As we cannot foresee the + // future, whatever schedules the purges should come back later to check + // if we need a purge. + WantsLater, +}; + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/third_party/mozjs/include/mozmemory.h b/src/third_party/mozjs/include/mozmemory.h index bd009052a02..f5d14e39ecd 100644 --- a/src/third_party/mozjs/include/mozmemory.h +++ b/src/third_party/mozjs/include/mozmemory.h @@ -20,10 +20,12 @@ #ifdef MALLOC_H # include MALLOC_H #endif + #include "mozmemory_wrap.h" #include "mozilla/Attributes.h" #include "mozilla/Types.h" #include "mozjemalloc_types.h" +#include "malloc_decls.h" #include "stdbool.h" #ifdef MOZ_MEMORY diff --git a/src/third_party/mozjs/include/mozmemory_wrap.h b/src/third_party/mozjs/include/mozmemory_wrap.h index 92d0a1176a6..6d7fc33fd25 100644 --- a/src/third_party/mozjs/include/mozmemory_wrap.h +++ b/src/third_party/mozjs/include/mozmemory_wrap.h @@ -106,6 +106,7 @@ #ifdef MOZ_MEMORY_IMPL # define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API +# define MOZ_JEMALLOC_API_NODISCARD MOZ_EXTERN_C [[nodiscard]] MFBT_API # if defined(XP_WIN) # define mozmem_malloc_impl(a) je_##a # else @@ -119,6 +120,7 @@ #if !defined(MOZ_MEMORY_IMPL) # define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API # define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API +# define MOZ_JEMALLOC_API_NODISCARD MOZ_EXTERN_C [[nodiscard]] MFBT_API #endif #ifndef MOZ_MEMORY_API @@ -126,6 +128,7 @@ #endif #ifndef MOZ_JEMALLOC_API # define MOZ_JEMALLOC_API MOZ_EXTERN_C +# define MOZ_JEMALLOC_API_NODISCARD MOZ_EXTERN_C [[nodiscard]] #endif #ifndef mozmem_malloc_impl diff --git a/src/third_party/mozjs/include/wasm/WasmBuiltinModuleGenerated.h b/src/third_party/mozjs/include/wasm/WasmBuiltinModuleGenerated.h index 379113c1b86..b59222d6a02 100644 --- a/src/third_party/mozjs/include/wasm/WasmBuiltinModuleGenerated.h +++ b/src/third_party/mozjs/include/wasm/WasmBuiltinModuleGenerated.h @@ -8,113 +8,113 @@ /* This file is generated by wasm/GenerateBuiltinModules.py. Do not edit! */ #define FOR_EACH_BUILTIN_MODULE_FUNC(M) \ - M(I8VecMul, "i8vecmul", IntrI8VecMul, Args_Int32_GeneralInt32Int32Int32Int32General, Instance::intrI8VecMul, true, 0)\ - M(StringTest, "test", StringTest, Args_Int32_GeneralGeneral, Instance::stringTest, false, 1)\ - M(StringCast, "cast", StringCast, Args_General2, Instance::stringCast, false, 2)\ - M(StringFromCharCodeArray, "fromCharCodeArray", StringFromCharCodeArray, Args_General_GeneralGeneralInt32Int32, Instance::stringFromCharCodeArray, false, 3)\ - M(StringIntoCharCodeArray, "intoCharCodeArray", StringIntoCharCodeArray, Args_Int32_GeneralGeneralGeneralInt32, Instance::stringIntoCharCodeArray, false, 4)\ - M(StringFromCharCode, "fromCharCode", StringFromCharCode, Args_General_GeneralInt32, Instance::stringFromCharCode, false, 5)\ - M(StringFromCodePoint, "fromCodePoint", StringFromCodePoint, Args_General_GeneralInt32, Instance::stringFromCodePoint, false, 6)\ - M(StringCharCodeAt, "charCodeAt", StringCharCodeAt, Args_Int32_GeneralGeneralInt32, Instance::stringCharCodeAt, false, 7)\ - M(StringCodePointAt, "codePointAt", StringCodePointAt, Args_Int32_GeneralGeneralInt32, Instance::stringCodePointAt, false, 8)\ - M(StringLength, "length", StringLength, Args_Int32_GeneralGeneral, Instance::stringLength, false, 9)\ - M(StringConcat, "concat", StringConcat, Args_General3, Instance::stringConcat, false, 10)\ - M(StringSubstring, "substring", StringSubstring, Args_General_GeneralGeneralInt32Int32, Instance::stringSubstring, false, 11)\ - M(StringEquals, "equals", StringEquals, Args_Int32_GeneralGeneralGeneral, Instance::stringEquals, false, 12)\ - M(StringCompare, "compare", StringCompare, Args_Int32_GeneralGeneralGeneral, Instance::stringCompare, false, 13)\ + M(I8VecMul, "i8vecmul", IntrI8VecMul, Args_Int32_GeneralInt32Int32Int32Int32General, Instance::intrI8VecMul, true, BuiltinInlineOp::None, 0)\ + M(StringTest, "test", StringTest, Args_Int32_GeneralGeneral, Instance::stringTest, false, BuiltinInlineOp::StringTest, 1)\ + M(StringCast, "cast", StringCast, Args_General2, Instance::stringCast, false, BuiltinInlineOp::StringCast, 2)\ + M(StringFromCharCodeArray, "fromCharCodeArray", StringFromCharCodeArray, Args_General_GeneralGeneralInt32Int32, Instance::stringFromCharCodeArray, false, BuiltinInlineOp::None, 3)\ + M(StringIntoCharCodeArray, "intoCharCodeArray", StringIntoCharCodeArray, Args_Int32_GeneralGeneralGeneralInt32, Instance::stringIntoCharCodeArray, false, BuiltinInlineOp::None, 4)\ + M(StringFromCharCode, "fromCharCode", StringFromCharCode, Args_General_GeneralInt32, Instance::stringFromCharCode, false, BuiltinInlineOp::None, 5)\ + M(StringFromCodePoint, "fromCodePoint", StringFromCodePoint, Args_General_GeneralInt32, Instance::stringFromCodePoint, false, BuiltinInlineOp::None, 6)\ + M(StringCharCodeAt, "charCodeAt", StringCharCodeAt, Args_Int32_GeneralGeneralInt32, Instance::stringCharCodeAt, false, BuiltinInlineOp::None, 7)\ + M(StringCodePointAt, "codePointAt", StringCodePointAt, Args_Int32_GeneralGeneralInt32, Instance::stringCodePointAt, false, BuiltinInlineOp::None, 8)\ + M(StringLength, "length", StringLength, Args_Int32_GeneralGeneral, Instance::stringLength, false, BuiltinInlineOp::StringLength, 9)\ + M(StringConcat, "concat", StringConcat, Args_General3, Instance::stringConcat, false, BuiltinInlineOp::None, 10)\ + M(StringSubstring, "substring", StringSubstring, Args_General_GeneralGeneralInt32Int32, Instance::stringSubstring, false, BuiltinInlineOp::None, 11)\ + M(StringEquals, "equals", StringEquals, Args_Int32_GeneralGeneralGeneral, Instance::stringEquals, false, BuiltinInlineOp::None, 12)\ + M(StringCompare, "compare", StringCompare, Args_Int32_GeneralGeneralGeneral, Instance::stringCompare, false, BuiltinInlineOp::None, 13)\ #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_I8VecMul {ValType::i32(), ValType::i32(), ValType::i32(), ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_I8VecMul 6, {MIRType::Pointer, ValType::i32().toMIRType(), ValType::i32().toMIRType(), ValType::i32().toMIRType(), ValType::i32().toMIRType(), MIRType::Pointer, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_I8VecMul Nothing() +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_I8VecMul mozilla::Nothing() #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_I8VecMul MIRType::None #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_I8VecMul FailureMode::FailOnNegI32 #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringTest {ValType(RefType::extern_())} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringTest 2, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringTest Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringTest mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringTest ValType::i32().toMIRType() #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringTest FailureMode::Infallible #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringCast {ValType(RefType::extern_())} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringCast 2, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCast Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCast mozilla::Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringCast MIRType::WasmAnyRef #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringCast FailureMode::FailOnNullPtr #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringFromCharCodeArray {ValType(RefType::fromTypeDef(StaticTypeDefs::arrayMutI16, true)), ValType::i32(), ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringFromCharCodeArray 4, {MIRType::Pointer, MIRType::WasmAnyRef, ValType::i32().toMIRType(), ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringFromCharCodeArray Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringFromCharCodeArray mozilla::Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringFromCharCodeArray MIRType::WasmAnyRef #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringFromCharCodeArray FailureMode::FailOnNullPtr #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringIntoCharCodeArray {ValType(RefType::extern_()), ValType(RefType::fromTypeDef(StaticTypeDefs::arrayMutI16, true)), ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringIntoCharCodeArray 4, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::WasmAnyRef, ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringIntoCharCodeArray Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringIntoCharCodeArray mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringIntoCharCodeArray ValType::i32().toMIRType() #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringIntoCharCodeArray FailureMode::FailOnNegI32 #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringFromCharCode {ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringFromCharCode 2, {MIRType::Pointer, ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringFromCharCode Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringFromCharCode mozilla::Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringFromCharCode MIRType::WasmAnyRef #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringFromCharCode FailureMode::FailOnNullPtr #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringFromCodePoint {ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringFromCodePoint 2, {MIRType::Pointer, ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringFromCodePoint Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringFromCodePoint mozilla::Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringFromCodePoint MIRType::WasmAnyRef #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringFromCodePoint FailureMode::FailOnNullPtr #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringCharCodeAt {ValType(RefType::extern_()), ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringCharCodeAt 3, {MIRType::Pointer, MIRType::WasmAnyRef, ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCharCodeAt Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCharCodeAt mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringCharCodeAt ValType::i32().toMIRType() #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringCharCodeAt FailureMode::FailOnNegI32 #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringCodePointAt {ValType(RefType::extern_()), ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringCodePointAt 3, {MIRType::Pointer, MIRType::WasmAnyRef, ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCodePointAt Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCodePointAt mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringCodePointAt ValType::i32().toMIRType() #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringCodePointAt FailureMode::FailOnNegI32 #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringLength {ValType(RefType::extern_())} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringLength 2, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringLength Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringLength mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringLength ValType::i32().toMIRType() #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringLength FailureMode::FailOnNegI32 #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringConcat {ValType(RefType::extern_()), ValType(RefType::extern_())} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringConcat 3, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::WasmAnyRef, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringConcat Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringConcat mozilla::Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringConcat MIRType::WasmAnyRef #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringConcat FailureMode::FailOnNullPtr #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringSubstring {ValType(RefType::extern_()), ValType::i32(), ValType::i32()} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringSubstring 4, {MIRType::Pointer, MIRType::WasmAnyRef, ValType::i32().toMIRType(), ValType::i32().toMIRType(), MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringSubstring Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringSubstring mozilla::Some(ValType(RefType::fromTypeCode(TypeCode(RefType::Extern), false))) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringSubstring MIRType::WasmAnyRef #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringSubstring FailureMode::FailOnNullPtr #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringEquals {ValType(RefType::extern_()), ValType(RefType::extern_())} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringEquals 3, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::WasmAnyRef, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringEquals Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringEquals mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringEquals ValType::i32().toMIRType() #define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_StringEquals FailureMode::FailOnNegI32 #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_StringCompare {ValType(RefType::extern_()), ValType(RefType::extern_())} #define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_StringCompare 3, {MIRType::Pointer, MIRType::WasmAnyRef, MIRType::WasmAnyRef, MIRType::None} -#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCompare Some(ValType::i32()) +#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_StringCompare mozilla::Some(ValType::i32()) #define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_StringCompare ValType::i32().toMIRType() diff --git a/src/third_party/mozjs/mongo_sources/jscustomallocator.h b/src/third_party/mozjs/mongo_sources/jscustomallocator.h index dad165f5915..c09cbee4ffb 100644 --- a/src/third_party/mozjs/mongo_sources/jscustomallocator.h +++ b/src/third_party/mozjs/mongo_sources/jscustomallocator.h @@ -30,15 +30,20 @@ #include #include -#include - #include "jscustomallocator_oom.h" +#include namespace mongo { namespace sm { +JS_PUBLIC_API void reset(size_t max_bytes, bool track_mmap); JS_PUBLIC_API size_t get_total_bytes(); -JS_PUBLIC_API void reset(size_t max_bytes); JS_PUBLIC_API size_t get_max_bytes(); + +JS_PUBLIC_API void check_oom_on_mmap_allocation(size_t bytes); + +size_t get_malloc_bytes(); +size_t get_mmap_bytes(); +void signal_oom(); } // namespace sm } // namespace mongo @@ -60,6 +65,7 @@ JS_PUBLIC_API void* js_arena_realloc(arena_id_t arena, void* p, size_t bytes); namespace js { extern JS_PUBLIC_DATA arena_id_t MallocArena; +extern JS_PUBLIC_DATA arena_id_t BackgroundMallocArena; extern JS_PUBLIC_DATA arena_id_t ArrayBufferContentsArena; extern JS_PUBLIC_DATA arena_id_t StringBufferArena; @@ -89,15 +95,24 @@ struct MOZ_RAII JS_PUBLIC_DATA AutoEnterOOMUnsafeRegion { annotateOOMSizeCallback = callback; } + /* Returns true if there's an AutoEnterOOMUnsafeRegion scope on the current callstack */ + static bool isInOOMUnsafeRegion() { + return isInOomUnsafeRegion_ > 0; + } + #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) AutoEnterOOMUnsafeRegion() : oomEnabled_(oom::simulator.isThreadSimulatingAny()) { if (oomEnabled_) { MOZ_ALWAYS_TRUE(owner_.compareExchange(nullptr, this)); oom::simulator.setInUnsafeRegion(true); } + + ++isInOomUnsafeRegion_; } ~AutoEnterOOMUnsafeRegion() { + --isInOomUnsafeRegion_; + if (oomEnabled_) { oom::simulator.setInUnsafeRegion(false); MOZ_ALWAYS_TRUE(owner_.compareExchange(this, nullptr)); @@ -109,9 +124,20 @@ private: static mozilla::Atomic owner_; bool oomEnabled_; +#else + AutoEnterOOMUnsafeRegion() { + ++isInOomUnsafeRegion_; + } + + ~AutoEnterOOMUnsafeRegion() { + --isInOomUnsafeRegion_; + } #endif private: + // Tracks whether the current thread is inside an AutoEnterOOMUnsafeRegion + static thread_local size_t isInOomUnsafeRegion_; + static MOZ_NORETURN MOZ_COLD void crash_impl(const char* reason); static MOZ_NORETURN MOZ_COLD void crash_impl(size_t size, const char* reason); }; diff --git a/src/third_party/mozjs/mongo_sources/jscustomallocator_oom.h b/src/third_party/mozjs/mongo_sources/jscustomallocator_oom.h index ac09b1028b4..07f20854651 100644 --- a/src/third_party/mozjs/mongo_sources/jscustomallocator_oom.h +++ b/src/third_party/mozjs/mongo_sources/jscustomallocator_oom.h @@ -25,21 +25,22 @@ namespace js { * adding new thread types. */ enum ThreadType { - THREAD_TYPE_NONE = 0, // 0 - THREAD_TYPE_MAIN, // 1 - THREAD_TYPE_WASM_COMPILE_TIER1, // 2 - THREAD_TYPE_WASM_COMPILE_TIER2, // 3 - THREAD_TYPE_ION, // 4 - THREAD_TYPE_PARSE, // 5 - THREAD_TYPE_COMPRESS, // 6 - THREAD_TYPE_GCPARALLEL, // 7 - THREAD_TYPE_PROMISE_TASK, // 8 - THREAD_TYPE_ION_FREE, // 9 - THREAD_TYPE_WASM_GENERATOR_TIER2, // 10 - THREAD_TYPE_WORKER, // 11 - THREAD_TYPE_DELAZIFY, // 12 - THREAD_TYPE_DELAZIFY_FREE, // 13 - THREAD_TYPE_MAX // Used to check shell function arguments + THREAD_TYPE_NONE = 0, // 0 + THREAD_TYPE_MAIN, // 1 + THREAD_TYPE_WASM_COMPILE_TIER1, // 2 + THREAD_TYPE_WASM_COMPILE_TIER2, // 3 + THREAD_TYPE_BASELINE, // 4 + THREAD_TYPE_ION, // 5 + THREAD_TYPE_COMPRESS, // 6 + THREAD_TYPE_GCPARALLEL, // 7 + THREAD_TYPE_PROMISE_TASK, // 8 + THREAD_TYPE_ION_FREE, // 9 + THREAD_TYPE_WASM_GENERATOR_COMPLETE_TIER2, // 10 + THREAD_TYPE_WASM_COMPILE_PARTIAL_TIER2, // 11 + THREAD_TYPE_WORKER, // 12 + THREAD_TYPE_DELAZIFY, // 13 + THREAD_TYPE_DELAZIFY_FREE, // 14 + THREAD_TYPE_MAX // Used to check shell function arguments }; namespace oom { @@ -58,7 +59,7 @@ namespace oom { // Define the range of threads tested by simulated OOM testing and the // like. Testing worker threads is not supported. const ThreadType FirstThreadTypeToTest = THREAD_TYPE_MAIN; -const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_GENERATOR_TIER2; +const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_COMPILE_PARTIAL_TIER2; extern bool InitThreadType(void); extern void SetThreadType(ThreadType); diff --git a/src/third_party/mozjs/mongo_sources/mongoErrorReportToString.cpp b/src/third_party/mozjs/mongo_sources/mongoErrorReportToString.cpp index 3999e88d26c..b95c42155e8 100644 --- a/src/third_party/mozjs/mongo_sources/mongoErrorReportToString.cpp +++ b/src/third_party/mozjs/mongo_sources/mongoErrorReportToString.cpp @@ -42,7 +42,7 @@ #include "gc/Marking.h" #include "js/CharacterEncoding.h" #include "js/Wrapper.h" -#include "util/StringBuffer.h" +#include "mozilla/StringBuffer.h" #include "vm/ErrorObject.h" #include "vm/GlobalObject.h" #include "vm/JSContext.h" diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/js-confdefs.h b/src/third_party/mozjs/platform/aarch64/linux/build/js-confdefs.h index d63af5ed56c..6a9f5099286 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/aarch64/linux/build/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -23,11 +27,9 @@ #define HAVE_GETC_UNLOCKED 1 #define HAVE_GETOPT_H 1 #define HAVE_GETPAGESIZE 1 -#define HAVE_GETTID 1 #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -39,7 +41,6 @@ #define HAVE_NETINET_IN_H 1 #define HAVE_NL_TYPES_H 1 #define HAVE_POSIX_MEMALIGN 1 -#define HAVE_PTHREAD_GETNAME_NP 1 #define HAVE_PTHREAD_H 1 #define HAVE_RES_NINIT 1 #define HAVE_SETPRIORITY 1 @@ -69,12 +70,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -83,6 +82,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "aarch64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_LINUX 1 diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/aarch64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/aarch64/linux/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/aarch64/linux/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/jit/AtomicOperationsGenerated.h b/src/third_party/mozjs/platform/aarch64/linux/include/jit/AtomicOperationsGenerated.h index e598860de3f..c27f32d6aa2 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/jit/AtomicOperationsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/jit/AtomicOperationsGenerated.h @@ -548,6 +548,9 @@ namespace jit { : "memory", "cc"); return res; } + inline void AtomicPause() { + asm volatile ("isb" ::: "memory"); + } inline void AtomicCopyUnalignedBlockDownUnsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); @@ -933,7 +936,29 @@ namespace jit { : [dst] "r" (dst_), [src] "r"(src_) : "memory"); } - inline void AtomicCopyByteUnsynchronized(uint8_t* dst, const uint8_t* src) { + inline void AtomicCopy32Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint32_t* dst_ = reinterpret_cast(dst); + const uint32_t* src_ = reinterpret_cast(src); + uint32_t scratch; + asm volatile ("ldr %w[scratch], [%x[src], 0]\n\t" +"str %w[scratch], [%x[dst], 0]\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy16Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint16_t* dst_ = reinterpret_cast(dst); + const uint16_t* src_ = reinterpret_cast(src); + uint16_t scratch; + asm volatile ("ldrh %w[scratch], [%x[src], 0]\n\t" +"strh %w[scratch], [%x[dst], 0]\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy8Unsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); uint8_t scratch; diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/aarch64/linux/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/aarch64/linux/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/aarch64/linux/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/js-confdefs.h b/src/third_party/mozjs/platform/aarch64/linux/include/js-confdefs.h index d63af5ed56c..6a9f5099286 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -23,11 +27,9 @@ #define HAVE_GETC_UNLOCKED 1 #define HAVE_GETOPT_H 1 #define HAVE_GETPAGESIZE 1 -#define HAVE_GETTID 1 #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -39,7 +41,6 @@ #define HAVE_NETINET_IN_H 1 #define HAVE_NL_TYPES_H 1 #define HAVE_POSIX_MEMALIGN 1 -#define HAVE_PTHREAD_GETNAME_NP 1 #define HAVE_PTHREAD_H 1 #define HAVE_RES_NINIT 1 #define HAVE_SETPRIORITY 1 @@ -69,12 +70,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -83,6 +82,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "aarch64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_LINUX 1 diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/js-config.h b/src/third_party/mozjs/platform/aarch64/linux/include/js-config.h index e6a4e862c32..75330b2452d 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/js-config.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +/* #undef XP_WIN */ +#define XP_UNIX 1 +/* #undef XP_DARWIN */ + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/aarch64/linux/include/selfhosted.out.h b/src/third_party/mozjs/platform/aarch64/linux/include/selfhosted.out.h index 61dcac32173..f92431e839c 100644 --- a/src/third_party/mozjs/platform/aarch64/linux/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/aarch64/linux/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 237, 125, 253, 119, 27, 55, 174, 232, 239, 254, 43, 38, 58, 189, 173, 188, 150, 189, 150, 147, 126, 108, 236, 164, 235, 186, 73, 215, 111, 147, 56, 199, 78, 119, 207, 185, 126, 57, 185, 19, 105, 236, 204, 90, 214, 168, 51, 82, 28, 183, 205, 251, 219, 31, 65, 130, 36, 192, 143, 153, 145, 44, 39, 182, 111, 114, 78, 235, 209, 12, 9, 130, 32, 0, 130, 32, 8, 158, 204, 198, 131, 105, 94, 140, 147, 113, 118, 241, 230, 48, 27, 20, 229, 176, 187, 154, 252, 177, 146, 36, 101, 54, 157, 149, 227, 164, 154, 14, 223, 28, 188, 253, 79, 54, 152, 190, 25, 148, 89, 58, 205, 186, 227, 217, 104, 180, 186, 189, 242, 113, 229, 68, 215, 125, 85, 252, 84, 20, 163, 44, 29, 119, 223, 179, 186, 247, 238, 189, 119, 202, 189, 152, 157, 191, 205, 74, 167, 216, 26, 47, 117, 148, 158, 103, 255, 74, 71, 179, 236, 191, 179, 178, 232, 126, 232, 37, 151, 172, 244, 135, 228, 209, 163, 71, 201, 101, 242, 231, 159, 73, 247, 67, 114, 79, 60, 127, 72, 190, 254, 90, 188, 128, 199, 75, 142, 216, 47, 217, 244, 121, 54, 125, 87, 12, 187, 255, 234, 37, 47, 21, 152, 237, 109, 241, 191, 247, 105, 153, 64, 169, 228, 81, 242, 175, 227, 151, 175, 225, 85, 126, 146, 116, 247, 171, 23, 162, 115, 7, 229, 175, 227, 97, 118, 146, 143, 179, 97, 23, 10, 173, 170, 138, 6, 131, 153, 254, 10, 213, 62, 98, 213, 123, 251, 213, 94, 58, 26, 165, 111, 71, 25, 175, 244, 234, 93, 89, 92, 188, 186, 156, 100, 79, 202, 178, 40, 187, 253, 173, 94, 50, 21, 191, 138, 19, 137, 192, 170, 134, 129, 176, 225, 29, 235, 194, 126, 245, 178, 44, 38, 89, 57, 189, 252, 103, 118, 217, 77, 203, 211, 217, 121, 54, 158, 42, 224, 208, 11, 128, 37, 122, 129, 32, 245, 247, 109, 11, 81, 21, 16, 180, 233, 84, 211, 50, 31, 159, 118, 128, 114, 228, 229, 229, 249, 219, 98, 212, 225, 35, 48, 201, 6, 121, 86, 237, 21, 99, 81, 101, 54, 152, 10, 180, 139, 183, 255, 233, 37, 162, 219, 233, 108, 52, 37, 239, 29, 146, 194, 43, 129, 140, 40, 188, 49, 176, 133, 52, 117, 213, 87, 209, 168, 33, 160, 67, 88, 31, 190, 67, 97, 197, 136, 18, 80, 140, 190, 223, 126, 215, 75, 58, 133, 44, 247, 77, 149, 124, 67, 208, 248, 38, 153, 32, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 154, 229, 163, 105, 62, 62, 146, 68, 233, 118, 42, 69, 136, 206, 106, 13, 135, 84, 46, 123, 212, 247, 98, 159, 145, 213, 86, 134, 111, 149, 228, 97, 75, 87, 248, 119, 152, 77, 138, 114, 250, 107, 149, 158, 102, 123, 197, 108, 60, 21, 210, 227, 55, 208, 75, 238, 203, 46, 169, 102, 172, 236, 234, 134, 29, 26, 201, 50, 253, 7, 61, 249, 183, 243, 247, 191, 99, 55, 13, 125, 18, 193, 73, 134, 132, 132, 130, 29, 81, 193, 19, 48, 11, 118, 99, 99, 67, 240, 95, 165, 112, 159, 150, 151, 216, 135, 129, 16, 139, 167, 88, 161, 11, 234, 68, 255, 120, 147, 78, 38, 163, 203, 158, 131, 93, 207, 178, 71, 47, 145, 240, 100, 47, 4, 152, 233, 224, 93, 210, 205, 28, 106, 103, 186, 143, 219, 46, 98, 187, 167, 167, 101, 118, 42, 52, 214, 18, 176, 227, 176, 150, 134, 226, 62, 140, 231, 56, 29, 45, 1, 67, 6, 106, 57, 8, 2, 167, 155, 134, 69, 21, 242, 105, 175, 152, 92, 254, 156, 78, 83, 212, 77, 130, 121, 186, 83, 209, 78, 54, 237, 37, 85, 49, 43, 7, 89, 47, 201, 62, 12, 70, 179, 97, 54, 220, 159, 102, 231, 21, 209, 19, 219, 53, 162, 36, 171, 58, 242, 68, 69, 245, 164, 44, 206, 133, 180, 190, 42, 80, 17, 96, 5, 173, 126, 206, 178, 75, 16, 102, 31, 185, 131, 82, 16, 251, 224, 98, 44, 84, 168, 69, 20, 128, 185, 104, 106, 220, 20, 36, 33, 140, 114, 178, 11, 226, 115, 34, 148, 89, 23, 90, 205, 5, 254, 98, 82, 74, 54, 183, 241, 113, 71, 34, 178, 49, 202, 198, 167, 211, 119, 248, 114, 109, 77, 67, 65, 68, 69, 5, 40, 117, 44, 191, 190, 222, 54, 58, 0, 197, 254, 222, 187, 180, 18, 8, 3, 34, 30, 41, 191, 254, 26, 11, 121, 156, 129, 19, 181, 150, 227, 253, 234, 201, 88, 76, 7, 37, 76, 74, 186, 191, 2, 224, 170, 172, 110, 85, 204, 207, 146, 252, 132, 98, 151, 134, 70, 178, 121, 168, 120, 44, 158, 94, 19, 29, 243, 113, 165, 150, 27, 126, 29, 159, 8, 69, 154, 149, 98, 80, 57, 95, 16, 70, 184, 57, 60, 128, 22, 205, 231, 30, 250, 69, 135, 115, 137, 35, 89, 204, 96, 130, 97, 246, 150, 249, 150, 143, 199, 230, 155, 249, 218, 57, 41, 138, 142, 164, 11, 83, 29, 187, 101, 153, 94, 62, 121, 159, 149, 151, 178, 87, 111, 211, 193, 217, 201, 56, 177, 86, 203, 1, 29, 193, 233, 187, 188, 50, 227, 39, 72, 39, 191, 61, 147, 36, 236, 30, 32, 45, 205, 240, 236, 162, 133, 83, 97, 129, 85, 57, 86, 155, 49, 107, 224, 219, 94, 178, 41, 12, 2, 137, 207, 134, 32, 228, 180, 0, 211, 103, 35, 3, 212, 172, 25, 224, 26, 112, 22, 231, 58, 51, 238, 103, 97, 46, 159, 79, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 68, 135, 124, 180, 31, 39, 253, 228, 71, 57, 79, 225, 167, 110, 127, 53, 121, 200, 141, 75, 195, 104, 103, 138, 201, 206, 4, 131, 9, 122, 136, 7, 203, 84, 146, 103, 197, 224, 36, 7, 150, 15, 100, 127, 0, 29, 97, 35, 76, 5, 104, 195, 85, 22, 69, 49, 109, 244, 146, 131, 227, 179, 215, 130, 53, 196, 3, 97, 34, 59, 242, 233, 168, 202, 182, 241, 237, 71, 194, 48, 214, 182, 44, 103, 25, 140, 251, 145, 152, 202, 170, 253, 241, 40, 31, 3, 249, 158, 1, 203, 153, 38, 45, 43, 8, 162, 112, 6, 57, 42, 206, 179, 155, 201, 31, 149, 192, 236, 110, 179, 199, 149, 185, 67, 141, 125, 13, 115, 32, 251, 180, 224, 14, 224, 3, 143, 57, 158, 22, 229, 147, 116, 240, 238, 102, 242, 199, 137, 66, 238, 238, 178, 200, 124, 236, 177, 29, 26, 127, 130, 71, 11, 30, 192, 225, 246, 216, 224, 121, 58, 185, 153, 44, 112, 158, 78, 110, 254, 240, 67, 237, 93, 89, 27, 196, 12, 151, 245, 202, 141, 115, 208, 3, 66, 173, 94, 133, 73, 160, 138, 32, 195, 36, 27, 74, 127, 13, 172, 163, 23, 96, 155, 160, 217, 178, 43, 139, 16, 224, 97, 30, 219, 109, 197, 91, 130, 135, 124, 245, 34, 237, 211, 155, 201, 90, 202, 118, 190, 237, 220, 181, 25, 224, 173, 94, 50, 45, 230, 231, 177, 51, 205, 94, 192, 59, 154, 105, 90, 78, 98, 170, 110, 96, 26, 11, 51, 221, 180, 88, 91, 211, 149, 12, 127, 6, 167, 183, 118, 172, 167, 216, 204, 227, 190, 195, 108, 56, 27, 220, 80, 219, 167, 148, 184, 125, 42, 238, 83, 42, 7, 127, 164, 131, 193, 236, 124, 54, 74, 137, 211, 48, 200, 153, 186, 93, 82, 94, 128, 225, 204, 170, 60, 30, 153, 176, 65, 8, 119, 73, 10, 82, 154, 36, 201, 20, 112, 247, 104, 179, 197, 252, 105, 18, 209, 151, 101, 86, 9, 208, 162, 33, 98, 24, 15, 11, 102, 85, 185, 220, 155, 208, 106, 212, 98, 74, 146, 183, 66, 80, 206, 28, 14, 75, 46, 222, 9, 138, 37, 221, 181, 53, 20, 143, 85, 187, 58, 188, 167, 33, 205, 135, 58, 39, 145, 16, 160, 181, 181, 215, 108, 29, 219, 94, 20, 57, 168, 144, 236, 153, 206, 17, 33, 52, 239, 172, 75, 202, 188, 34, 16, 237, 75, 57, 65, 88, 250, 145, 15, 248, 20, 158, 10, 24, 239, 184, 75, 81, 37, 111, 135, 249, 233, 187, 233, 23, 161, 83, 66, 7, 253, 90, 79, 250, 95, 68, 143, 139, 222, 250, 250, 89, 242, 248, 17, 78, 94, 203, 149, 188, 245, 117, 95, 242, 30, 171, 201, 112, 125, 253, 142, 10, 222, 211, 124, 60, 236, 78, 4, 119, 231, 3, 97, 22, 220, 32, 129, 19, 4, 25, 198, 197, 205, 96, 60, 143, 180, 145, 74, 159, 110, 241, 22, 177, 143, 98, 214, 145, 193, 177, 206, 56, 194, 129, 85, 95, 151, 177, 182, 19, 180, 14, 24, 224, 227, 225, 62, 120, 64, 191, 176, 199, 53, 175, 237, 155, 249, 32, 232, 233, 209, 92, 16, 100, 128, 245, 126, 235, 145, 151, 131, 236, 13, 63, 56, 232, 255, 157, 139, 145, 29, 219, 29, 2, 241, 32, 254, 100, 227, 97, 226, 237, 17, 47, 206, 19, 240, 189, 204, 132, 122, 202, 223, 103, 175, 100, 75, 178, 40, 236, 151, 157, 138, 5, 160, 106, 220, 148, 132, 229, 201, 138, 234, 61, 171, 178, 147, 108, 34, 89, 126, 148, 33, 17, 207, 211, 233, 187, 55, 231, 233, 7, 57, 173, 173, 57, 165, 97, 237, 131, 165, 31, 146, 210, 162, 171, 110, 57, 109, 226, 81, 36, 143, 128, 12, 12, 71, 73, 24, 83, 78, 109, 128, 48, 36, 85, 149, 150, 56, 30, 41, 50, 55, 161, 136, 197, 66, 24, 62, 145, 35, 36, 199, 137, 238, 230, 139, 102, 161, 165, 135, 4, 243, 76, 10, 62, 226, 45, 184, 100, 228, 32, 14, 144, 90, 162, 45, 138, 54, 35, 45, 11, 81, 148, 7, 176, 103, 46, 144, 101, 165, 21, 38, 235, 184, 133, 162, 12, 161, 105, 97, 52, 136, 36, 240, 14, 176, 194, 215, 95, 195, 255, 119, 20, 201, 215, 20, 48, 45, 32, 184, 15, 69, 63, 105, 123, 42, 81, 171, 92, 241, 63, 239, 3, 90, 25, 234, 237, 99, 106, 12, 153, 150, 93, 51, 230, 224, 120, 90, 188, 150, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 202, 226, 220, 184, 81, 200, 174, 175, 235, 183, 211, 194, 62, 75, 76, 244, 207, 143, 174, 225, 246, 25, 209, 93, 91, 179, 232, 218, 103, 31, 93, 171, 147, 14, 66, 230, 199, 104, 36, 84, 164, 156, 228, 42, 148, 171, 205, 107, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 89, 153, 202, 182, 217, 156, 6, 179, 149, 232, 196, 123, 109, 157, 68, 89, 64, 249, 162, 36, 35, 236, 79, 179, 50, 53, 129, 76, 103, 96, 144, 152, 65, 207, 229, 183, 108, 168, 134, 157, 114, 128, 40, 108, 104, 144, 35, 4, 241, 253, 69, 118, 193, 129, 202, 66, 191, 142, 171, 244, 36, 19, 83, 226, 161, 88, 44, 148, 239, 179, 225, 209, 168, 152, 118, 117, 53, 105, 102, 240, 150, 90, 213, 234, 107, 71, 90, 83, 193, 45, 236, 214, 182, 165, 134, 254, 232, 203, 133, 198, 252, 69, 246, 97, 218, 181, 148, 16, 253, 5, 189, 37, 248, 94, 235, 66, 27, 116, 5, 180, 144, 65, 119, 170, 208, 47, 179, 180, 28, 190, 42, 60, 226, 174, 174, 70, 54, 207, 121, 180, 2, 242, 2, 88, 84, 12, 132, 10, 215, 219, 63, 249, 119, 41, 93, 191, 122, 13, 2, 40, 233, 231, 142, 215, 131, 142, 252, 194, 172, 170, 84, 160, 168, 40, 246, 139, 67, 49, 201, 0, 155, 68, 48, 170, 217, 8, 6, 253, 15, 197, 80, 15, 105, 232, 204, 176, 24, 139, 23, 114, 205, 9, 27, 220, 138, 36, 105, 160, 131, 0, 99, 3, 74, 179, 181, 38, 118, 92, 125, 166, 216, 233, 184, 129, 26, 12, 251, 148, 241, 206, 255, 153, 75, 185, 53, 229, 133, 144, 222, 223, 122, 42, 180, 164, 95, 113, 139, 170, 44, 141, 243, 126, 245, 178, 168, 170, 252, 237, 232, 18, 9, 11, 166, 234, 80, 18, 178, 155, 26, 155, 79, 233, 184, 104, 73, 84, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 31, 105, 245, 115, 54, 77, 7, 239, 178, 225, 79, 179, 147, 19, 161, 102, 82, 230, 148, 117, 173, 243, 239, 127, 8, 57, 97, 233, 84, 226, 232, 229, 148, 234, 101, 109, 186, 43, 114, 63, 150, 62, 15, 221, 90, 88, 156, 20, 115, 144, 136, 144, 57, 7, 183, 6, 170, 16, 100, 133, 199, 26, 142, 173, 196, 204, 140, 173, 32, 98, 223, 225, 167, 247, 184, 170, 75, 89, 164, 72, 176, 93, 15, 214, 22, 93, 31, 78, 210, 28, 212, 150, 2, 211, 51, 240, 94, 111, 135, 90, 131, 194, 53, 45, 109, 43, 253, 194, 170, 72, 112, 68, 239, 232, 26, 45, 22, 8, 84, 140, 233, 26, 225, 43, 249, 85, 46, 64, 43, 30, 143, 18, 82, 234, 82, 61, 72, 178, 202, 38, 247, 210, 113, 49, 22, 171, 155, 209, 139, 244, 60, 235, 82, 80, 98, 165, 39, 145, 174, 58, 222, 130, 228, 201, 120, 90, 230, 237, 27, 219, 90, 245, 181, 170, 12, 45, 106, 89, 127, 51, 80, 31, 4, 122, 183, 186, 28, 15, 186, 41, 252, 95, 134, 123, 201, 77, 176, 147, 49, 53, 87, 122, 82, 29, 138, 133, 97, 216, 134, 217, 35, 42, 92, 175, 23, 36, 212, 189, 81, 81, 205, 74, 201, 81, 240, 51, 129, 165, 241, 99, 194, 38, 176, 219, 150, 143, 1, 170, 106, 242, 30, 181, 16, 172, 204, 235, 98, 194, 56, 166, 107, 98, 89, 135, 8, 115, 96, 69, 252, 170, 56, 146, 193, 90, 186, 172, 235, 231, 155, 85, 2, 238, 46, 118, 93, 79, 182, 150, 20, 129, 0, 221, 148, 22, 198, 48, 93, 133, 101, 8, 150, 163, 182, 147, 112, 131, 78, 151, 29, 244, 142, 106, 11, 71, 90, 190, 23, 10, 122, 246, 221, 10, 126, 205, 58, 229, 248, 125, 159, 80, 212, 82, 105, 213, 213, 152, 220, 240, 14, 117, 162, 150, 196, 185, 75, 93, 210, 203, 163, 122, 242, 134, 91, 115, 72, 102, 173, 254, 48, 216, 8, 237, 34, 212, 59, 138, 17, 111, 126, 242, 89, 196, 62, 18, 70, 104, 51, 194, 96, 38, 181, 238, 136, 222, 68, 229, 129, 225, 123, 171, 201, 143, 6, 143, 110, 32, 8, 124, 175, 151, 116, 187, 253, 100, 103, 39, 233, 127, 39, 236, 50, 161, 143, 86, 123, 54, 86, 219, 117, 247, 136, 210, 123, 171, 224, 64, 58, 54, 131, 200, 54, 223, 224, 31, 216, 220, 233, 69, 154, 79, 149, 83, 105, 44, 52, 178, 242, 43, 194, 185, 130, 209, 168, 184, 64, 160, 208, 33, 240, 220, 88, 167, 51, 209, 86, 124, 228, 25, 141, 122, 113, 174, 192, 47, 108, 192, 252, 224, 2, 131, 209, 54, 227, 1, 212, 71, 124, 176, 155, 195, 18, 164, 14, 50, 170, 180, 103, 161, 11, 59, 154, 240, 128, 11, 74, 81, 136, 188, 243, 217, 101, 174, 128, 6, 248, 7, 195, 112, 6, 118, 129, 43, 17, 187, 104, 205, 192, 119, 253, 205, 110, 63, 219, 146, 210, 226, 149, 38, 90, 126, 150, 209, 5, 12, 225, 235, 109, 83, 210, 53, 153, 116, 69, 106, 58, 213, 241, 229, 146, 248, 81, 173, 246, 86, 113, 61, 168, 108, 81, 187, 229, 233, 176, 39, 58, 34, 244, 182, 104, 56, 60, 64, 141, 141, 233, 15, 9, 22, 240, 153, 9, 185, 198, 140, 193, 143, 88, 187, 13, 171, 24, 183, 249, 170, 169, 254, 144, 121, 203, 231, 228, 0, 103, 252, 213, 152, 146, 177, 71, 67, 158, 143, 253, 71, 98, 112, 185, 83, 124, 55, 98, 92, 72, 27, 113, 9, 38, 69, 163, 165, 208, 218, 78, 104, 242, 155, 247, 17, 89, 223, 103, 142, 8, 107, 148, 164, 78, 33, 179, 76, 222, 110, 58, 195, 73, 196, 141, 66, 103, 208, 216, 25, 29, 111, 198, 9, 204, 54, 129, 153, 198, 221, 12, 200, 233, 92, 243, 241, 211, 8, 28, 155, 0, 28, 249, 50, 123, 9, 205, 106, 31, 121, 40, 214, 249, 54, 162, 86, 35, 100, 175, 28, 77, 76, 36, 204, 211, 255, 17, 33, 131, 8, 158, 112, 228, 88, 72, 163, 50, 153, 90, 169, 209, 165, 185, 81, 163, 109, 149, 104, 108, 68, 87, 20, 21, 150, 170, 70, 87, 20, 141, 124, 85, 58, 247, 38, 162, 146, 156, 51, 194, 39, 117, 195, 217, 52, 152, 158, 174, 228, 154, 178, 181, 158, 132, 161, 241, 85, 34, 141, 197, 226, 234, 78, 152, 118, 242, 184, 35, 241, 110, 201, 49, 138, 58, 120, 241, 56, 168, 44, 180, 241, 159, 34, 31, 19, 245, 16, 62, 217, 25, 242, 107, 145, 99, 27, 83, 196, 160, 167, 96, 186, 39, 61, 67, 100, 3, 240, 182, 184, 223, 165, 103, 133, 168, 149, 97, 199, 70, 242, 135, 144, 196, 98, 2, 101, 232, 25, 43, 218, 91, 170, 183, 67, 76, 235, 238, 159, 122, 46, 29, 125, 210, 163, 67, 37, 228, 36, 47, 171, 233, 147, 81, 118, 174, 226, 43, 36, 164, 227, 205, 215, 186, 161, 67, 235, 120, 242, 78, 212, 146, 154, 134, 148, 135, 2, 6, 54, 64, 151, 43, 135, 18, 91, 236, 47, 242, 79, 144, 110, 4, 230, 198, 148, 145, 169, 199, 80, 197, 163, 79, 180, 39, 85, 54, 73, 245, 164, 209, 233, 117, 60, 145, 233, 199, 69, 6, 20, 146, 75, 3, 45, 55, 135, 201, 218, 35, 11, 219, 174, 14, 3, 147, 13, 1, 67, 244, 168, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 205, 108, 171, 16, 9, 63, 30, 50, 134, 251, 138, 198, 116, 114, 159, 134, 98, 168, 168, 163, 5, 235, 244, 146, 14, 236, 155, 30, 171, 121, 119, 3, 143, 152, 190, 246, 253, 46, 60, 110, 180, 40, 243, 83, 112, 248, 203, 79, 82, 181, 1, 111, 90, 206, 222, 38, 108, 42, 53, 129, 224, 212, 117, 195, 170, 70, 61, 108, 82, 199, 152, 32, 185, 82, 137, 12, 184, 43, 198, 76, 115, 82, 15, 162, 54, 128, 88, 237, 208, 249, 102, 111, 226, 22, 150, 143, 120, 87, 22, 85, 117, 152, 165, 163, 115, 220, 247, 166, 69, 218, 226, 160, 192, 163, 218, 178, 213, 0, 173, 189, 198, 115, 203, 170, 250, 158, 164, 149, 45, 75, 17, 81, 46, 245, 142, 191, 249, 31, 68, 136, 46, 133, 247, 2, 203, 254, 230, 186, 186, 75, 123, 181, 199, 193, 107, 169, 113, 207, 165, 118, 204, 162, 124, 32, 56, 145, 12, 86, 224, 16, 120, 139, 105, 248, 254, 42, 221, 87, 105, 158, 143, 21, 182, 158, 9, 62, 74, 167, 112, 158, 65, 206, 109, 165, 174, 213, 42, 234, 69, 157, 114, 124, 214, 16, 251, 226, 216, 217, 164, 145, 121, 2, 85, 220, 154, 174, 229, 125, 125, 193, 226, 64, 32, 65, 208, 253, 241, 84, 109, 44, 129, 45, 112, 208, 179, 157, 151, 190, 249, 190, 139, 161, 176, 51, 232, 232, 4, 140, 1, 128, 219, 93, 18, 157, 161, 212, 48, 155, 76, 223, 189, 152, 157, 203, 233, 97, 37, 22, 119, 36, 196, 159, 146, 68, 104, 169, 160, 11, 136, 0, 179, 187, 175, 188, 34, 27, 130, 165, 16, 81, 55, 26, 39, 156, 7, 70, 20, 196, 72, 29, 241, 132, 167, 188, 205, 19, 192, 133, 31, 114, 231, 121, 5, 59, 5, 15, 206, 80, 173, 36, 122, 225, 182, 98, 135, 67, 129, 221, 199, 77, 49, 9, 131, 77, 195, 170, 9, 253, 93, 216, 176, 244, 197, 142, 197, 128, 125, 224, 49, 80, 180, 70, 62, 102, 135, 145, 245, 108, 158, 153, 153, 92, 125, 61, 38, 117, 152, 235, 211, 145, 15, 226, 119, 218, 182, 62, 29, 11, 173, 54, 94, 51, 68, 32, 253, 79, 251, 27, 200, 43, 132, 74, 95, 17, 44, 253, 215, 230, 133, 227, 20, 70, 102, 127, 87, 204, 70, 67, 28, 104, 30, 92, 171, 122, 42, 71, 145, 199, 125, 36, 94, 45, 61, 187, 34, 110, 94, 75, 146, 252, 180, 142, 235, 229, 195, 138, 142, 208, 225, 91, 238, 148, 146, 100, 97, 220, 18, 98, 83, 94, 178, 129, 126, 182, 245, 158, 87, 213, 163, 170, 34, 200, 122, 210, 15, 16, 214, 13, 112, 129, 126, 83, 92, 33, 212, 247, 67, 255, 132, 254, 171, 117, 80, 127, 251, 125, 63, 224, 139, 174, 61, 228, 77, 177, 78, 220, 241, 96, 157, 178, 17, 53, 225, 131, 189, 182, 164, 175, 77, 119, 167, 106, 71, 117, 153, 97, 51, 122, 56, 173, 6, 204, 49, 108, 16, 87, 167, 90, 205, 242, 10, 143, 201, 58, 5, 140, 117, 246, 213, 91, 78, 232, 176, 247, 181, 64, 185, 21, 29, 122, 189, 147, 108, 130, 255, 254, 204, 217, 47, 142, 229, 254, 209, 129, 39, 210, 240, 111, 177, 225, 185, 59, 245, 44, 224, 87, 197, 33, 156, 71, 175, 178, 97, 119, 25, 36, 221, 197, 112, 183, 197, 220, 0, 24, 214, 166, 130, 226, 206, 108, 224, 154, 254, 102, 67, 141, 73, 120, 87, 116, 21, 111, 106, 184, 171, 223, 240, 138, 93, 152, 97, 130, 8, 96, 141, 164, 101, 118, 130, 180, 151, 33, 172, 250, 149, 179, 209, 226, 248, 22, 109, 205, 136, 185, 243, 61, 155, 73, 23, 167, 177, 244, 145, 44, 76, 231, 0, 185, 208, 169, 118, 166, 98, 113, 153, 165, 11, 184, 236, 176, 232, 0, 29, 220, 115, 94, 57, 84, 245, 92, 17, 18, 183, 55, 85, 1, 225, 96, 216, 132, 165, 81, 56, 90, 255, 89, 90, 77, 111, 108, 72, 54, 32, 247, 105, 194, 178, 173, 63, 124, 9, 193, 217, 250, 172, 77, 232, 192, 199, 226, 1, 252, 254, 126, 196, 245, 135, 241, 195, 0, 4, 67, 249, 225, 195, 205, 14, 231, 55, 24, 222, 49, 6, 154, 135, 83, 174, 53, 208, 223, 16, 152, 49, 8, 108, 75, 233, 178, 50, 220, 240, 125, 58, 34, 14, 29, 18, 50, 116, 158, 253, 146, 141, 89, 144, 140, 40, 42, 6, 19, 92, 88, 29, 71, 91, 81, 168, 114, 140, 230, 7, 43, 207, 112, 133, 224, 234, 77, 141, 253, 161, 32, 103, 46, 148, 115, 208, 253, 197, 235, 152, 38, 150, 219, 69, 83, 122, 217, 125, 52, 197, 15, 37, 144, 249, 33, 171, 34, 10, 180, 10, 39, 10, 19, 17, 118, 36, 51, 19, 166, 170, 50, 76, 246, 84, 168, 165, 27, 129, 171, 247, 237, 72, 201, 13, 27, 194, 170, 237, 69, 104, 86, 69, 137, 146, 210, 27, 54, 65, 83, 196, 201, 74, 43, 174, 82, 221, 107, 2, 64, 227, 251, 191, 180, 110, 207, 180, 73, 79, 8, 26, 223, 156, 130, 22, 223, 11, 132, 244, 132, 174, 2, 209, 117, 130, 242, 135, 81, 206, 78, 222, 56, 68, 225, 231, 188, 52, 161, 185, 127, 172, 184, 184, 168, 104, 220, 176, 158, 12, 160, 33, 139, 83, 13, 6, 76, 105, 40, 13, 57, 29, 225, 69, 200, 213, 100, 11, 206, 163, 55, 105, 45, 199, 142, 65, 197, 134, 189, 124, 8, 141, 171, 85, 152, 173, 163, 126, 147, 0, 93, 120, 241, 209, 37, 20, 99, 69, 69, 45, 21, 147, 90, 46, 72, 52, 29, 17, 126, 77, 52, 34, 165, 130, 36, 105, 17, 2, 247, 48, 34, 136, 152, 8, 213, 83, 251, 122, 127, 72, 180, 102, 105, 220, 37, 2, 74, 202, 198, 54, 31, 180, 104, 200, 64, 215, 247, 116, 211, 85, 129, 84, 10, 162, 52, 170, 102, 230, 184, 94, 28, 169, 6, 58, 90, 129, 38, 66, 214, 74, 168, 27, 240, 229, 194, 236, 97, 108, 87, 218, 154, 240, 200, 100, 16, 249, 139, 69, 85, 236, 5, 246, 238, 99, 124, 2, 249, 71, 54, 18, 156, 246, 194, 161, 167, 182, 135, 194, 97, 246, 7, 42, 200, 254, 128, 132, 216, 251, 32, 187, 7, 11, 132, 217, 251, 96, 90, 4, 219, 171, 179, 51, 248, 163, 19, 233, 93, 32, 254, 254, 84, 79, 26, 209, 40, 119, 89, 231, 64, 129, 134, 83, 36, 204, 193, 78, 251, 176, 15, 129, 185, 227, 42, 31, 248, 19, 109, 207, 182, 99, 71, 177, 126, 52, 14, 61, 38, 188, 91, 227, 161, 250, 247, 89, 70, 68, 53, 189, 192, 152, 24, 227, 230, 110, 14, 137, 236, 222, 103, 25, 17, 217, 242, 92, 3, 98, 183, 167, 252, 243, 81, 201, 163, 128, 237, 97, 22, 115, 225, 253, 167, 249, 247, 157, 184, 13, 146, 51, 74, 226, 217, 171, 192, 104, 155, 245, 36, 37, 170, 219, 51, 107, 201, 234, 46, 153, 70, 161, 250, 2, 90, 167, 230, 100, 22, 51, 97, 20, 150, 56, 144, 234, 143, 129, 225, 140, 43, 175, 226, 155, 215, 127, 153, 167, 91, 102, 12, 71, 98, 109, 102, 252, 0, 202, 112, 201, 134, 210, 54, 39, 135, 90, 108, 206, 225, 203, 60, 27, 97, 124, 54, 45, 72, 54, 8, 228, 242, 148, 76, 225, 96, 6, 24, 35, 154, 29, 47, 179, 72, 25, 36, 204, 92, 123, 15, 170, 201, 179, 53, 250, 205, 124, 112, 148, 80, 49, 91, 66, 31, 74, 145, 144, 223, 211, 112, 177, 80, 151, 225, 159, 1, 39, 222, 203, 142, 199, 66, 154, 96, 8, 105, 204, 36, 183, 27, 34, 132, 82, 39, 150, 228, 41, 198, 145, 38, 47, 200, 138, 41, 110, 209, 143, 46, 156, 178, 33, 91, 28, 196, 132, 23, 115, 154, 97, 234, 221, 43, 75, 176, 129, 51, 135, 12, 219, 58, 215, 35, 197, 170, 139, 33, 142, 55, 45, 223, 90, 81, 110, 209, 183, 47, 242, 220, 66, 158, 229, 33, 205, 232, 98, 94, 211, 50, 32, 201, 116, 5, 225, 43, 5, 214, 246, 199, 0, 14, 159, 71, 232, 95, 165, 103, 89, 119, 148, 159, 231, 211, 121, 229, 93, 173, 188, 206, 211, 124, 172, 98, 185, 237, 222, 155, 2, 167, 117, 130, 45, 179, 227, 56, 94, 15, 211, 241, 41, 42, 131, 239, 254, 214, 191, 38, 145, 135, 14, 134, 132, 194, 160, 117, 123, 37, 190, 185, 107, 215, 44, 240, 219, 132, 1, 30, 131, 95, 217, 252, 180, 254, 229, 171, 232, 3, 197, 243, 168, 18, 2, 11, 244, 232, 89, 176, 101, 205, 228, 209, 106, 75, 23, 86, 162, 79, 194, 158, 188, 214, 117, 99, 146, 254, 115, 89, 76, 238, 180, 164, 67, 7, 239, 168, 164, 55, 119, 205, 12, 233, 141, 19, 236, 182, 210, 204, 101, 216, 30, 106, 97, 170, 235, 78, 89, 26, 159, 83, 223, 180, 50, 14, 118, 43, 185, 33, 151, 13, 95, 166, 121, 89, 117, 23, 209, 27, 203, 19, 111, 142, 140, 47, 13, 183, 87, 186, 27, 123, 182, 52, 225, 94, 186, 60, 245, 200, 37, 38, 75, 18, 173, 158, 190, 247, 228, 154, 100, 76, 231, 177, 144, 213, 95, 223, 28, 97, 227, 225, 221, 119, 205, 127, 134, 189, 187, 139, 62, 180, 230, 174, 45, 119, 114, 94, 108, 246, 93, 68, 44, 151, 51, 205, 217, 51, 128, 181, 219, 228, 141, 30, 50, 39, 195, 128, 188, 80, 40, 122, 214, 84, 129, 227, 219, 122, 74, 254, 109, 189, 207, 185, 26, 175, 11, 122, 192, 244, 238, 42, 169, 115, 153, 196, 84, 65, 205, 238, 116, 84, 45, 32, 204, 121, 244, 130, 169, 66, 21, 67, 171, 124, 207, 44, 43, 145, 199, 174, 33, 30, 208, 29, 148, 251, 224, 54, 225, 89, 48, 86, 2, 138, 204, 23, 41, 161, 106, 216, 113, 136, 154, 164, 46, 44, 126, 61, 34, 207, 167, 204, 229, 128, 5, 12, 55, 38, 185, 94, 241, 152, 250, 125, 148, 159, 13, 45, 86, 131, 208, 227, 52, 197, 62, 225, 48, 234, 157, 38, 47, 171, 115, 32, 167, 179, 68, 70, 169, 0, 141, 110, 56, 105, 115, 29, 51, 99, 146, 183, 176, 241, 248, 71, 187, 144, 4, 149, 106, 8, 152, 90, 237, 157, 211, 24, 218, 99, 115, 106, 148, 89, 34, 139, 211, 53, 30, 94, 139, 118, 9, 213, 75, 132, 38, 185, 138, 168, 173, 167, 134, 190, 150, 72, 71, 39, 47, 71, 170, 231, 75, 235, 78, 211, 33, 92, 129, 253, 226, 46, 210, 113, 68, 137, 55, 233, 61, 121, 161, 215, 237, 167, 76, 131, 3, 57, 68, 29, 63, 172, 166, 140, 196, 220, 154, 107, 177, 234, 8, 169, 174, 206, 187, 27, 148, 188, 55, 55, 45, 61, 98, 186, 115, 249, 138, 67, 230, 6, 145, 133, 28, 244, 119, 131, 150, 87, 229, 74, 98, 238, 121, 107, 25, 137, 127, 32, 109, 66, 83, 82, 208, 8, 33, 238, 247, 146, 142, 124, 234, 64, 28, 42, 130, 237, 232, 4, 124, 252, 10, 230, 113, 122, 158, 233, 248, 57, 241, 8, 159, 240, 149, 250, 227, 164, 170, 69, 184, 50, 93, 45, 162, 11, 229, 204, 26, 230, 188, 58, 69, 104, 231, 89, 5, 199, 122, 225, 131, 122, 41, 255, 239, 130, 99, 144, 68, 9, 51, 228, 166, 245, 78, 199, 9, 33, 17, 165, 116, 7, 228, 145, 64, 4, 235, 149, 211, 221, 33, 44, 43, 129, 174, 37, 157, 135, 73, 71, 252, 145, 128, 98, 163, 0, 249, 86, 94, 149, 105, 62, 18, 207, 98, 225, 38, 254, 100, 60, 24, 185, 241, 110, 96, 6, 78, 5, 130, 247, 196, 140, 187, 10, 8, 252, 223, 113, 199, 137, 151, 12, 198, 48, 227, 136, 31, 205, 170, 73, 38, 168, 54, 228, 241, 192, 110, 114, 28, 26, 227, 15, 97, 58, 226, 149, 169, 64, 191, 5, 99, 11, 253, 243, 145, 32, 113, 166, 126, 36, 24, 135, 135, 227, 72, 171, 199, 254, 232, 176, 94, 117, 240, 189, 103, 67, 58, 56, 10, 81, 7, 219, 127, 24, 193, 53, 158, 43, 22, 244, 145, 9, 15, 244, 161, 239, 87, 135, 179, 49, 120, 97, 93, 192, 142, 240, 60, 248, 206, 217, 67, 176, 107, 204, 57, 162, 201, 147, 192, 149, 207, 114, 152, 90, 246, 214, 20, 131, 84, 15, 164, 4, 237, 158, 186, 9, 37, 211, 214, 129, 207, 76, 78, 228, 250, 93, 225, 38, 18, 212, 181, 56, 59, 41, 226, 137, 22, 62, 51, 195, 152, 99, 2, 55, 130, 99, 220, 35, 9, 119, 133, 101, 104, 104, 230, 242, 84, 144, 28, 193, 79, 165, 124, 228, 70, 226, 123, 200, 5, 223, 136, 64, 45, 219, 149, 238, 33, 146, 207, 201, 120, 176, 23, 90, 78, 4, 46, 100, 164, 0, 233, 238, 41, 36, 75, 144, 152, 218, 132, 241, 194, 126, 131, 211, 246, 88, 67, 123, 78, 229, 209, 97, 157, 123, 25, 245, 111, 189, 248, 89, 216, 84, 93, 123, 160, 80, 50, 91, 195, 162, 146, 188, 82, 127, 154, 135, 212, 162, 135, 121, 44, 89, 208, 36, 110, 121, 12, 42, 224, 127, 140, 158, 247, 209, 103, 110, 100, 167, 124, 183, 211, 78, 178, 133, 195, 26, 206, 46, 198, 161, 111, 208, 19, 8, 206, 39, 253, 211, 38, 31, 107, 200, 198, 16, 7, 29, 47, 164, 127, 210, 34, 214, 243, 98, 100, 189, 246, 160, 80, 192, 249, 133, 37, 28, 235, 209, 230, 214, 14, 29, 8, 82, 169, 198, 243, 74, 174, 105, 122, 201, 185, 58, 25, 97, 181, 40, 125, 129, 89, 195, 85, 89, 43, 73, 231, 250, 20, 134, 0, 139, 103, 70, 36, 208, 70, 55, 15, 219, 38, 118, 90, 210, 186, 3, 106, 60, 111, 221, 64, 238, 195, 182, 96, 246, 217, 32, 240, 189, 21, 5, 80, 29, 11, 34, 109, 18, 40, 60, 63, 183, 60, 77, 88, 22, 231, 52, 39, 109, 215, 111, 196, 142, 116, 0, 3, 194, 43, 206, 81, 18, 39, 51, 68, 123, 2, 123, 253, 215, 10, 217, 57, 51, 23, 116, 198, 219, 3, 46, 1, 238, 51, 114, 17, 225, 63, 72, 89, 41, 215, 125, 24, 64, 15, 171, 36, 248, 11, 43, 37, 56, 80, 43, 22, 172, 181, 39, 161, 52, 124, 115, 28, 138, 98, 108, 70, 76, 53, 253, 230, 141, 60, 167, 251, 230, 205, 67, 217, 148, 146, 34, 46, 83, 205, 199, 190, 188, 173, 31, 213, 72, 76, 78, 48, 107, 136, 92, 203, 75, 226, 151, 25, 208, 69, 45, 147, 104, 38, 189, 248, 114, 87, 197, 203, 144, 90, 96, 108, 88, 218, 200, 68, 5, 157, 74, 173, 122, 107, 157, 220, 45, 233, 204, 71, 255, 156, 156, 149, 106, 206, 114, 74, 169, 175, 123, 229, 159, 166, 58, 231, 231, 168, 8, 131, 137, 70, 212, 20, 77, 239, 116, 156, 143, 255, 62, 206, 205, 131, 64, 27, 219, 72, 156, 64, 6, 142, 239, 206, 45, 181, 127, 219, 155, 165, 100, 54, 220, 131, 224, 9, 212, 8, 155, 28, 160, 66, 49, 94, 134, 102, 134, 127, 151, 86, 251, 227, 106, 154, 142, 7, 58, 9, 53, 159, 114, 72, 178, 200, 188, 122, 169, 15, 171, 31, 156, 40, 38, 183, 163, 106, 62, 117, 59, 86, 221, 114, 57, 89, 33, 147, 12, 105, 214, 49, 28, 40, 15, 104, 78, 186, 80, 190, 46, 181, 53, 12, 134, 237, 211, 2, 54, 215, 242, 161, 81, 132, 77, 27, 180, 8, 129, 237, 204, 186, 120, 181, 173, 222, 119, 5, 126, 133, 239, 236, 98, 97, 54, 166, 33, 164, 157, 139, 109, 230, 57, 76, 20, 164, 193, 2, 167, 137, 66, 112, 218, 92, 111, 19, 235, 78, 224, 4, 17, 225, 218, 240, 1, 162, 3, 122, 213, 13, 99, 216, 104, 249, 190, 123, 200, 168, 238, 192, 39, 145, 189, 134, 1, 193, 69, 221, 221, 25, 146, 232, 65, 187, 246, 131, 98, 114, 181, 182, 59, 213, 222, 242, 252, 43, 59, 48, 156, 248, 158, 42, 124, 79, 78, 181, 170, 217, 197, 81, 159, 115, 29, 132, 15, 104, 88, 114, 248, 117, 177, 65, 119, 34, 84, 22, 24, 110, 14, 161, 205, 64, 251, 200, 47, 116, 110, 207, 140, 112, 8, 193, 248, 9, 214, 72, 16, 48, 71, 234, 74, 130, 244, 249, 105, 122, 133, 243, 169, 237, 168, 26, 56, 133, 218, 64, 215, 120, 204, 150, 68, 38, 76, 219, 107, 179, 94, 174, 39, 14, 172, 217, 88, 49, 121, 48, 132, 25, 208, 38, 56, 140, 80, 207, 13, 156, 2, 154, 211, 89, 130, 196, 135, 213, 216, 1, 10, 129, 250, 248, 174, 86, 130, 68, 121, 196, 95, 46, 255, 101, 1, 204, 45, 91, 84, 138, 189, 246, 4, 193, 71, 153, 228, 162, 134, 56, 176, 96, 13, 179, 159, 25, 138, 74, 242, 107, 216, 229, 67, 40, 50, 201, 100, 34, 161, 235, 131, 129, 74, 100, 75, 131, 41, 234, 247, 27, 97, 171, 137, 185, 110, 120, 130, 14, 226, 255, 51, 145, 96, 243, 196, 128, 245, 52, 70, 136, 171, 138, 228, 82, 160, 212, 27, 141, 241, 26, 230, 84, 253, 24, 52, 219, 213, 9, 71, 155, 114, 233, 6, 10, 236, 50, 147, 72, 93, 159, 216, 134, 15, 27, 186, 252, 111, 209, 186, 105, 194, 59, 47, 254, 95, 68, 152, 136, 112, 149, 141, 132, 72, 68, 133, 152, 100, 14, 107, 146, 99, 153, 220, 21, 161, 217, 62, 122, 103, 33, 62, 182, 23, 241, 248, 121, 198, 207, 33, 220, 42, 44, 77, 158, 149, 122, 6, 56, 37, 228, 42, 105, 193, 52, 227, 129, 115, 130, 234, 94, 151, 149, 150, 249, 73, 219, 30, 164, 186, 62, 97, 15, 157, 51, 116, 69, 133, 226, 125, 227, 164, 189, 77, 7, 2, 71, 169, 110, 133, 172, 243, 131, 119, 44, 187, 97, 109, 125, 187, 56, 212, 113, 69, 203, 80, 15, 158, 232, 2, 122, 235, 235, 17, 4, 147, 228, 109, 153, 165, 44, 115, 96, 64, 164, 227, 7, 23, 191, 136, 244, 162, 34, 29, 58, 80, 120, 171, 68, 186, 77, 7, 110, 171, 72, 47, 75, 24, 153, 106, 88, 95, 135, 52, 192, 155, 13, 179, 108, 216, 108, 174, 61, 153, 116, 19, 140, 230, 155, 190, 202, 141, 28, 17, 186, 37, 43, 221, 249, 176, 191, 93, 178, 118, 27, 86, 187, 230, 180, 211, 190, 21, 184, 200, 54, 147, 106, 175, 39, 201, 28, 171, 253, 130, 177, 57, 253, 98, 120, 157, 16, 161, 254, 152, 149, 165, 4, 133, 211, 139, 53, 184, 234, 170, 31, 247, 48, 214, 28, 150, 126, 195, 41, 169, 155, 160, 150, 150, 117, 218, 170, 89, 49, 57, 231, 177, 8, 87, 235, 238, 55, 28, 207, 178, 50, 176, 174, 72, 62, 207, 65, 166, 196, 21, 161, 101, 207, 98, 26, 252, 14, 157, 192, 56, 86, 236, 40, 162, 69, 71, 95, 138, 202, 131, 40, 120, 213, 240, 94, 133, 58, 46, 69, 133, 147, 30, 145, 114, 36, 117, 109, 45, 96, 150, 7, 176, 14, 159, 44, 139, 159, 172, 242, 215, 183, 145, 227, 84, 159, 203, 20, 174, 103, 77, 236, 212, 241, 198, 198, 198, 124, 131, 255, 58, 188, 237, 30, 61, 61, 117, 19, 164, 125, 241, 83, 29, 237, 100, 252, 154, 166, 169, 182, 199, 65, 92, 94, 15, 42, 101, 121, 132, 235, 139, 127, 245, 186, 199, 172, 69, 210, 254, 186, 225, 91, 224, 184, 153, 55, 210, 234, 140, 217, 151, 161, 254, 20, 67, 125, 111, 153, 99, 221, 124, 26, 46, 176, 111, 50, 30, 126, 25, 234, 91, 39, 213, 117, 107, 123, 177, 158, 35, 23, 96, 238, 143, 115, 196, 77, 16, 211, 142, 175, 88, 77, 144, 161, 149, 118, 230, 112, 40, 251, 45, 190, 108, 84, 89, 48, 85, 189, 44, 82, 55, 12, 56, 166, 170, 156, 103, 45, 2, 93, 4, 201, 206, 227, 167, 26, 1, 197, 240, 169, 13, 93, 183, 230, 112, 194, 183, 189, 164, 35, 250, 222, 97, 161, 253, 33, 162, 75, 244, 228, 162, 182, 103, 112, 58, 222, 124, 77, 126, 244, 95, 251, 243, 224, 115, 25, 233, 35, 141, 20, 0, 250, 54, 29, 156, 193, 92, 106, 111, 115, 113, 238, 111, 132, 30, 63, 143, 138, 207, 115, 21, 129, 241, 220, 70, 96, 8, 248, 230, 219, 220, 193, 23, 162, 114, 139, 136, 11, 130, 55, 249, 74, 110, 18, 236, 216, 78, 58, 129, 24, 46, 43, 88, 80, 243, 136, 37, 173, 69, 229, 50, 131, 124, 48, 89, 229, 198, 66, 42, 239, 235, 228, 13, 126, 238, 37, 207, 237, 73, 206, 116, 162, 84, 152, 40, 119, 40, 29, 28, 144, 97, 73, 0, 56, 29, 21, 111, 83, 160, 71, 224, 51, 84, 190, 120, 39, 208, 73, 186, 114, 21, 77, 86, 243, 16, 244, 164, 22, 64, 114, 73, 155, 78, 158, 136, 54, 47, 5, 45, 180, 162, 236, 26, 36, 194, 77, 147, 109, 47, 158, 113, 194, 241, 131, 171, 230, 206, 178, 75, 37, 106, 1, 72, 120, 91, 54, 207, 201, 18, 41, 218, 199, 162, 81, 72, 137, 98, 163, 218, 82, 125, 94, 42, 36, 50, 1, 142, 55, 106, 74, 244, 69, 143, 12, 8, 140, 116, 148, 213, 12, 130, 104, 75, 5, 215, 135, 63, 131, 183, 141, 202, 28, 245, 52, 44, 24, 219, 68, 160, 44, 18, 216, 68, 170, 183, 137, 106, 114, 112, 14, 4, 52, 45, 204, 187, 24, 17, 248, 47, 126, 204, 170, 230, 168, 105, 59, 206, 62, 168, 229, 105, 73, 93, 202, 210, 58, 69, 199, 63, 229, 89, 36, 27, 146, 181, 63, 158, 222, 223, 130, 240, 105, 55, 54, 107, 139, 184, 171, 180, 51, 82, 203, 138, 5, 196, 119, 143, 140, 59, 182, 65, 70, 112, 245, 239, 129, 234, 183, 7, 213, 231, 160, 116, 53, 115, 101, 171, 169, 127, 28, 197, 37, 70, 64, 1, 251, 53, 21, 253, 101, 138, 169, 98, 132, 13, 173, 32, 40, 97, 241, 19, 142, 188, 245, 178, 174, 16, 159, 48, 148, 224, 23, 187, 11, 214, 152, 243, 90, 119, 91, 163, 205, 165, 238, 224, 103, 46, 139, 217, 228, 39, 147, 117, 133, 76, 7, 230, 36, 146, 31, 203, 42, 11, 199, 102, 25, 28, 163, 111, 31, 104, 249, 115, 167, 28, 85, 91, 127, 205, 85, 106, 153, 128, 57, 218, 49, 98, 180, 252, 153, 175, 31, 159, 249, 246, 146, 232, 213, 235, 198, 150, 177, 246, 218, 56, 187, 72, 246, 236, 126, 196, 89, 123, 51, 213, 161, 226, 182, 149, 72, 53, 21, 53, 41, 125, 223, 58, 61, 35, 82, 141, 55, 202, 70, 39, 112, 121, 7, 173, 180, 183, 68, 107, 100, 166, 180, 245, 66, 247, 95, 39, 97, 96, 21, 5, 214, 75, 142, 85, 182, 191, 213, 160, 16, 7, 50, 254, 232, 54, 205, 61, 184, 21, 222, 44, 232, 92, 80, 36, 255, 127, 70, 28, 213, 54, 197, 67, 58, 97, 146, 243, 98, 118, 254, 54, 43, 223, 228, 149, 88, 76, 9, 50, 119, 199, 179, 115, 203, 207, 104, 18, 139, 119, 234, 224, 207, 88, 22, 118, 15, 110, 134, 100, 20, 170, 172, 203, 255, 75, 221, 24, 110, 242, 69, 250, 98, 153, 237, 221, 147, 146, 113, 30, 110, 75, 167, 6, 86, 32, 67, 77, 138, 215, 173, 91, 37, 187, 237, 254, 70, 59, 54, 177, 205, 176, 3, 232, 235, 182, 78, 156, 40, 71, 98, 66, 250, 60, 200, 202, 220, 32, 46, 166, 247, 232, 212, 86, 51, 0, 235, 221, 238, 86, 242, 151, 191, 36, 223, 222, 95, 133, 59, 29, 87, 97, 87, 87, 195, 248, 250, 107, 243, 40, 222, 178, 114, 252, 40, 155, 52, 33, 44, 99, 152, 190, 99, 27, 140, 113, 94, 21, 234, 167, 46, 184, 26, 6, 101, 217, 58, 10, 13, 139, 212, 3, 84, 6, 154, 208, 118, 7, 23, 99, 45, 142, 63, 103, 213, 160, 204, 39, 66, 225, 85, 244, 212, 149, 74, 45, 99, 46, 6, 61, 176, 42, 47, 187, 212, 215, 235, 30, 102, 39, 16, 94, 246, 166, 184, 24, 255, 83, 188, 237, 234, 3, 101, 210, 232, 177, 96, 193, 84, 250, 200, 148, 164, 201, 38, 214, 195, 75, 70, 1, 40, 42, 129, 109, 252, 138, 119, 243, 230, 252, 194, 120, 171, 47, 161, 138, 74, 55, 74, 140, 117, 104, 85, 124, 171, 239, 167, 58, 86, 200, 245, 32, 50, 165, 172, 47, 89, 210, 78, 70, 171, 117, 186, 140, 116, 19, 181, 33, 188, 113, 246, 43, 112, 172, 72, 217, 240, 168, 144, 115, 102, 246, 14, 60, 172, 76, 233, 125, 202, 139, 154, 65, 194, 107, 2, 61, 208, 251, 213, 147, 15, 98, 94, 169, 114, 60, 83, 201, 0, 179, 19, 148, 192, 229, 180, 165, 220, 173, 25, 128, 254, 102, 90, 60, 43, 196, 60, 145, 121, 233, 137, 232, 18, 161, 230, 232, 202, 193, 198, 212, 100, 193, 57, 8, 182, 32, 167, 5, 209, 83, 134, 184, 123, 105, 173, 95, 237, 93, 90, 17, 6, 232, 254, 139, 85, 87, 31, 187, 255, 82, 203, 41, 94, 255, 43, 5, 64, 18, 89, 140, 11, 204, 222, 115, 15, 134, 202, 130, 16, 54, 219, 60, 240, 104, 189, 153, 243, 182, 204, 108, 163, 197, 143, 20, 54, 178, 24, 67, 201, 155, 168, 145, 6, 21, 162, 167, 19, 12, 169, 154, 141, 104, 29, 105, 180, 170, 40, 90, 170, 180, 146, 9, 68, 11, 242, 39, 245, 146, 74, 254, 96, 170, 68, 20, 76, 66, 215, 12, 187, 166, 29, 86, 141, 152, 117, 247, 239, 43, 132, 166, 48, 87, 208, 137, 65, 105, 4, 51, 179, 64, 22, 39, 122, 198, 23, 184, 218, 251, 134, 115, 78, 240, 91, 37, 141, 232, 142, 176, 78, 95, 21, 154, 125, 132, 134, 83, 169, 172, 132, 169, 106, 82, 90, 169, 222, 27, 14, 147, 72, 171, 238, 42, 123, 23, 52, 130, 124, 216, 252, 176, 181, 185, 153, 252, 41, 254, 110, 246, 213, 159, 45, 60, 78, 105, 206, 85, 171, 142, 169, 103, 88, 64, 174, 72, 19, 216, 227, 106, 213, 228, 47, 148, 224, 167, 139, 19, 252, 180, 153, 224, 167, 119, 139, 224, 167, 132, 204, 150, 248, 53, 4, 127, 86, 20, 103, 179, 9, 225, 240, 86, 132, 254, 172, 84, 26, 22, 212, 177, 166, 230, 196, 216, 108, 168, 55, 189, 145, 138, 206, 188, 40, 103, 51, 51, 1, 234, 55, 176, 94, 254, 90, 145, 152, 166, 145, 32, 243, 220, 241, 150, 201, 254, 173, 51, 0, 135, 239, 21, 249, 72, 134, 208, 49, 43, 78, 189, 25, 81, 188, 85, 108, 168, 157, 136, 88, 239, 158, 246, 39, 69, 135, 239, 151, 47, 195, 55, 215, 240, 245, 111, 202, 240, 213, 27, 113, 19, 75, 70, 59, 172, 237, 41, 198, 1, 88, 95, 27, 161, 90, 168, 219, 38, 81, 243, 116, 90, 86, 187, 227, 33, 250, 225, 144, 180, 26, 12, 251, 10, 228, 238, 111, 186, 107, 16, 77, 123, 244, 35, 34, 229, 181, 171, 228, 162, 204, 167, 160, 164, 31, 38, 247, 238, 249, 208, 54, 31, 24, 159, 74, 38, 184, 78, 237, 221, 68, 138, 246, 77, 209, 65, 49, 62, 201, 79, 103, 117, 133, 183, 86, 157, 83, 199, 52, 83, 209, 31, 90, 135, 58, 216, 86, 230, 205, 22, 190, 105, 141, 84, 107, 148, 62, 6, 216, 227, 160, 68, 118, 115, 38, 6, 119, 112, 123, 114, 176, 242, 183, 179, 41, 184, 202, 64, 130, 7, 83, 187, 36, 93, 206, 197, 220, 164, 57, 162, 55, 232, 219, 136, 250, 240, 138, 248, 90, 196, 135, 18, 81, 38, 76, 34, 30, 134, 249, 219, 244, 214, 210, 164, 201, 187, 247, 67, 208, 187, 183, 69, 201, 138, 9, 237, 61, 1, 209, 46, 50, 76, 187, 161, 47, 140, 48, 235, 111, 227, 53, 211, 63, 212, 12, 77, 92, 173, 234, 92, 148, 243, 18, 122, 210, 177, 76, 214, 17, 43, 69, 138, 140, 142, 174, 147, 24, 252, 249, 136, 124, 218, 176, 149, 4, 245, 164, 125, 240, 16, 254, 252, 64, 253, 141, 29, 202, 149, 115, 192, 166, 213, 20, 244, 45, 9, 189, 191, 201, 160, 171, 68, 171, 13, 96, 165, 198, 208, 107, 91, 69, 52, 210, 18, 217, 128, 38, 84, 213, 193, 38, 166, 37, 173, 68, 230, 104, 44, 212, 47, 13, 70, 245, 233, 129, 236, 211, 22, 239, 147, 24, 182, 230, 70, 182, 116, 35, 102, 144, 73, 35, 167, 25, 217, 151, 8, 88, 169, 32, 15, 88, 239, 94, 216, 93, 233, 112, 239, 119, 63, 40, 251, 181, 227, 44, 200, 37, 190, 213, 92, 248, 86, 1, 124, 171, 24, 190, 149, 197, 183, 154, 27, 223, 42, 140, 175, 66, 202, 153, 182, 249, 135, 62, 157, 207, 93, 208, 91, 4, 166, 81, 231, 173, 180, 102, 165, 87, 24, 122, 105, 103, 20, 40, 29, 127, 205, 132, 20, 53, 170, 103, 245, 59, 99, 110, 24, 196, 187, 196, 70, 87, 127, 30, 168, 61, 66, 91, 52, 80, 2, 63, 82, 3, 38, 224, 159, 241, 123, 196, 239, 189, 8, 68, 105, 153, 220, 96, 139, 16, 10, 93, 243, 114, 97, 225, 82, 105, 78, 80, 196, 225, 79, 30, 13, 204, 200, 194, 176, 213, 12, 72, 102, 190, 171, 76, 163, 114, 11, 223, 49, 105, 180, 122, 38, 29, 150, 41, 170, 60, 116, 97, 159, 242, 137, 218, 209, 151, 161, 39, 174, 235, 209, 113, 25, 78, 96, 131, 54, 22, 182, 18, 9, 89, 129, 58, 13, 225, 42, 170, 228, 198, 137, 69, 134, 71, 175, 68, 89, 74, 111, 59, 78, 212, 198, 160, 59, 200, 225, 62, 255, 67, 249, 156, 14, 122, 201, 203, 6, 79, 43, 119, 82, 189, 212, 201, 186, 124, 243, 248, 203, 126, 158, 179, 159, 167, 200, 73, 60, 96, 3, 25, 235, 208, 197, 5, 198, 13, 218, 183, 227, 235, 203, 179, 184, 125, 120, 22, 183, 11, 207, 154, 236, 193, 51, 101, 7, 218, 101, 161, 179, 91, 8, 73, 234, 196, 199, 215, 118, 34, 107, 218, 18, 140, 137, 196, 103, 218, 11, 116, 37, 77, 128, 62, 207, 171, 236, 13, 158, 103, 234, 22, 227, 167, 234, 201, 74, 220, 68, 21, 137, 6, 176, 224, 247, 186, 244, 249, 216, 10, 36, 205, 199, 134, 34, 249, 243, 97, 123, 25, 183, 232, 233, 222, 50, 54, 209, 139, 109, 61, 107, 248, 138, 183, 77, 54, 170, 233, 187, 76, 119, 167, 167, 146, 242, 226, 175, 144, 111, 207, 246, 92, 119, 132, 84, 135, 161, 31, 147, 202, 9, 3, 231, 126, 101, 3, 217, 37, 96, 86, 193, 146, 215, 108, 255, 158, 206, 255, 206, 161, 190, 144, 152, 20, 182, 47, 238, 5, 173, 238, 64, 33, 61, 14, 179, 170, 24, 189, 207, 186, 123, 44, 7, 43, 153, 126, 194, 33, 158, 178, 238, 6, 160, 221, 75, 12, 229, 13, 218, 1, 31, 8, 191, 80, 90, 51, 161, 250, 211, 165, 132, 98, 253, 23, 138, 166, 162, 135, 228, 110, 35, 1, 84, 38, 102, 213, 147, 32, 1, 26, 242, 144, 69, 218, 138, 50, 46, 159, 212, 84, 92, 218, 179, 188, 146, 230, 129, 244, 211, 60, 203, 207, 178, 167, 69, 41, 180, 126, 101, 247, 174, 140, 64, 168, 237, 195, 87, 5, 30, 188, 18, 5, 80, 127, 152, 213, 46, 148, 120, 156, 116, 191, 221, 220, 76, 254, 146, 8, 11, 57, 126, 66, 188, 223, 255, 27, 19, 221, 145, 64, 3, 167, 18, 229, 49, 18, 160, 86, 217, 164, 145, 203, 105, 68, 252, 209, 155, 149, 118, 163, 50, 160, 235, 0, 158, 152, 62, 229, 92, 126, 156, 123, 38, 3, 124, 102, 196, 208, 142, 52, 121, 95, 68, 119, 154, 150, 50, 136, 3, 131, 255, 228, 17, 49, 97, 142, 153, 147, 103, 162, 54, 115, 104, 24, 53, 160, 42, 206, 19, 36, 170, 107, 56, 19, 182, 118, 26, 176, 38, 27, 172, 136, 239, 77, 84, 222, 255, 176, 122, 255, 211, 49, 31, 176, 155, 27, 178, 155, 230, 245, 171, 226, 168, 152, 149, 131, 204, 105, 142, 91, 18, 109, 175, 218, 104, 67, 59, 220, 18, 219, 175, 246, 199, 163, 92, 30, 248, 124, 6, 181, 12, 92, 54, 26, 116, 31, 76, 127, 24, 104, 253, 109, 134, 138, 53, 144, 240, 209, 33, 202, 190, 97, 128, 30, 52, 15, 144, 138, 237, 190, 120, 37, 95, 107, 198, 247, 15, 37, 62, 78, 182, 116, 35, 166, 180, 115, 230, 80, 175, 18, 3, 104, 154, 42, 113, 147, 218, 195, 117, 171, 151, 144, 106, 100, 81, 75, 231, 19, 138, 203, 212, 116, 225, 211, 49, 158, 25, 184, 249, 152, 79, 58, 184, 132, 86, 194, 92, 233, 251, 213, 75, 97, 241, 101, 67, 165, 42, 28, 185, 20, 6, 27, 123, 131, 74, 74, 70, 146, 16, 205, 132, 205, 255, 200, 11, 227, 219, 135, 77, 218, 209, 229, 231, 36, 169, 46, 114, 153, 183, 31, 208, 212, 122, 209, 156, 76, 19, 244, 223, 124, 232, 76, 30, 154, 18, 174, 86, 215, 28, 109, 7, 115, 219, 66, 233, 47, 12, 69, 138, 72, 37, 214, 81, 20, 220, 214, 213, 193, 225, 67, 159, 193, 189, 191, 68, 184, 248, 176, 197, 26, 120, 112, 29, 13, 224, 195, 125, 214, 210, 183, 215, 218, 18, 62, 60, 96, 77, 126, 247, 105, 154, 196, 135, 111, 89, 219, 223, 127, 226, 182, 241, 225, 59, 134, 196, 15, 159, 11, 9, 124, 248, 158, 97, 243, 183, 207, 142, 13, 62, 252, 192, 208, 234, 47, 174, 81, 150, 142, 23, 62, 252, 141, 35, 184, 4, 101, 181, 116, 4, 53, 64, 174, 7, 251, 203, 84, 132, 203, 71, 85, 63, 25, 37, 43, 214, 47, 169, 88, 144, 56, 72, 27, 11, 162, 9, 91, 255, 188, 151, 54, 172, 134, 243, 58, 54, 177, 233, 171, 184, 54, 117, 62, 249, 0, 58, 167, 177, 29, 105, 221, 49, 111, 83, 218, 185, 254, 136, 27, 81, 45, 118, 25, 93, 115, 143, 245, 47, 186, 65, 30, 66, 39, 216, 161, 119, 105, 181, 28, 220, 3, 182, 151, 170, 16, 48, 186, 68, 163, 190, 185, 133, 224, 131, 70, 62, 221, 1, 205, 199, 198, 80, 12, 15, 80, 168, 63, 201, 245, 118, 8, 182, 153, 218, 117, 168, 209, 56, 199, 30, 171, 0, 10, 137, 254, 209, 76, 222, 121, 233, 119, 170, 231, 88, 239, 46, 213, 84, 149, 99, 82, 131, 103, 127, 248, 234, 48, 59, 125, 242, 97, 242, 116, 148, 158, 86, 44, 210, 17, 172, 219, 195, 168, 135, 236, 176, 142, 125, 15, 235, 78, 27, 31, 50, 251, 217, 120, 71, 58, 29, 221, 200, 225, 134, 188, 36, 97, 152, 15, 236, 134, 28, 22, 91, 19, 229, 134, 29, 74, 198, 195, 13, 117, 98, 43, 80, 240, 212, 41, 152, 159, 142, 139, 50, 219, 75, 171, 44, 80, 56, 119, 10, 159, 139, 15, 112, 181, 99, 168, 236, 185, 83, 118, 88, 76, 119, 71, 33, 12, 42, 167, 224, 108, 156, 15, 138, 97, 8, 228, 44, 92, 82, 44, 71, 67, 36, 120, 239, 148, 174, 166, 249, 224, 236, 50, 80, 240, 178, 227, 112, 131, 77, 68, 229, 7, 127, 122, 140, 128, 49, 169, 39, 240, 134, 199, 163, 170, 162, 129, 251, 72, 175, 159, 97, 38, 144, 142, 169, 84, 62, 31, 108, 94, 16, 64, 10, 155, 113, 238, 75, 140, 121, 9, 249, 138, 110, 172, 116, 254, 10, 55, 124, 106, 104, 107, 248, 91, 22, 171, 35, 143, 189, 174, 211, 222, 155, 74, 73, 179, 59, 124, 15, 119, 123, 168, 47, 251, 16, 156, 222, 61, 194, 187, 173, 137, 227, 202, 120, 175, 170, 217, 100, 162, 220, 222, 105, 41, 247, 2, 212, 218, 27, 227, 223, 143, 244, 42, 241, 235, 175, 209, 42, 112, 220, 28, 170, 153, 55, 192, 42, 47, 139, 124, 60, 221, 21, 186, 193, 54, 247, 56, 217, 252, 112, 34, 254, 173, 240, 107, 58, 20, 244, 181, 164, 47, 254, 99, 237, 59, 186, 20, 186, 251, 28, 28, 117, 93, 181, 33, 97, 71, 185, 252, 16, 29, 230, 242, 67, 237, 181, 89, 31, 234, 6, 90, 212, 165, 35, 125, 68, 71, 16, 81, 208, 13, 238, 87, 136, 159, 60, 13, 122, 48, 153, 230, 231, 249, 239, 42, 43, 148, 69, 128, 178, 66, 195, 17, 201, 242, 3, 63, 35, 169, 148, 138, 168, 119, 239, 94, 87, 129, 192, 48, 36, 235, 28, 225, 122, 7, 91, 19, 29, 250, 85, 137, 174, 91, 183, 191, 233, 58, 106, 85, 15, 126, 193, 3, 167, 130, 206, 162, 27, 18, 145, 163, 30, 5, 20, 218, 181, 87, 85, 113, 219, 224, 201, 135, 108, 160, 234, 185, 186, 159, 140, 161, 232, 229, 197, 203, 84, 204, 51, 186, 96, 120, 168, 157, 98, 102, 196, 61, 137, 42, 63, 16, 145, 50, 89, 52, 66, 204, 153, 143, 7, 163, 217, 80, 154, 84, 80, 1, 148, 74, 199, 221, 51, 86, 24, 4, 58, 226, 19, 181, 125, 51, 51, 181, 15, 35, 48, 29, 165, 213, 116, 159, 222, 95, 15, 96, 119, 19, 122, 189, 253, 88, 127, 138, 28, 78, 55, 243, 84, 16, 85, 157, 13, 82, 149, 113, 206, 54, 219, 157, 113, 117, 96, 74, 112, 190, 20, 128, 135, 201, 46, 29, 90, 117, 196, 16, 198, 96, 90, 50, 74, 75, 168, 214, 69, 18, 240, 43, 239, 10, 91, 186, 103, 42, 19, 140, 44, 60, 118, 255, 49, 122, 183, 9, 85, 140, 255, 156, 82, 203, 50, 44, 39, 33, 25, 16, 44, 0, 30, 171, 176, 230, 179, 192, 76, 209, 135, 164, 229, 53, 147, 66, 76, 254, 127, 188, 182, 22, 88, 4, 180, 19, 19, 195, 171, 222, 104, 207, 201, 1, 184, 171, 32, 168, 1, 26, 72, 235, 224, 26, 222, 152, 20, 85, 142, 233, 20, 21, 178, 71, 89, 90, 14, 222, 9, 75, 10, 209, 116, 41, 10, 67, 99, 43, 61, 130, 172, 112, 115, 50, 11, 237, 15, 111, 243, 153, 248, 34, 147, 202, 118, 143, 136, 62, 35, 140, 117, 52, 123, 171, 148, 41, 12, 143, 198, 130, 224, 152, 172, 155, 183, 203, 228, 184, 235, 102, 32, 220, 235, 49, 31, 30, 235, 49, 12, 108, 238, 237, 234, 42, 31, 27, 120, 175, 118, 154, 161, 139, 9, 85, 204, 159, 3, 99, 7, 25, 85, 121, 25, 29, 205, 78, 31, 147, 219, 196, 84, 145, 14, 157, 185, 149, 117, 64, 234, 202, 200, 106, 130, 21, 249, 180, 170, 141, 6, 245, 78, 95, 58, 198, 251, 208, 75, 226, 53, 228, 187, 141, 76, 40, 58, 57, 150, 234, 165, 58, 7, 4, 205, 190, 1, 21, 184, 226, 30, 152, 80, 165, 14, 179, 201, 40, 21, 139, 159, 10, 77, 165, 82, 253, 38, 209, 97, 159, 223, 138, 136, 75, 185, 154, 115, 84, 135, 210, 17, 246, 69, 148, 97, 169, 39, 73, 135, 76, 157, 188, 172, 166, 63, 23, 162, 72, 169, 25, 93, 101, 123, 148, 125, 243, 32, 90, 22, 177, 176, 184, 222, 119, 218, 208, 147, 140, 125, 173, 205, 195, 199, 52, 215, 66, 0, 13, 193, 95, 79, 157, 183, 33, 240, 52, 216, 240, 6, 26, 88, 240, 46, 74, 69, 163, 0, 112, 72, 31, 39, 223, 110, 242, 195, 13, 54, 240, 229, 167, 180, 194, 116, 28, 79, 240, 215, 211, 66, 232, 205, 243, 183, 195, 52, 68, 22, 11, 220, 240, 167, 134, 178, 202, 27, 8, 154, 118, 136, 168, 32, 161, 110, 173, 203, 170, 192, 252, 212, 115, 222, 28, 185, 47, 176, 91, 238, 107, 138, 173, 251, 77, 153, 65, 206, 75, 141, 56, 123, 205, 250, 249, 113, 197, 127, 170, 237, 21, 24, 99, 102, 162, 67, 52, 57, 98, 137, 181, 20, 41, 92, 57, 158, 46, 179, 222, 115, 102, 195, 134, 198, 229, 100, 70, 233, 201, 105, 201, 8, 22, 160, 97, 140, 126, 30, 237, 92, 60, 205, 39, 175, 87, 245, 232, 230, 144, 72, 121, 14, 106, 125, 52, 210, 80, 195, 249, 172, 73, 121, 18, 119, 142, 209, 241, 27, 106, 26, 146, 186, 230, 156, 241, 160, 163, 65, 8, 239, 141, 68, 120, 28, 34, 68, 143, 47, 136, 92, 100, 154, 169, 29, 94, 49, 33, 8, 179, 24, 90, 161, 125, 65, 180, 89, 31, 124, 252, 189, 225, 194, 215, 126, 151, 106, 38, 80, 138, 128, 106, 94, 182, 71, 154, 118, 27, 14, 54, 235, 53, 218, 118, 93, 199, 20, 245, 92, 235, 59, 59, 143, 210, 181, 155, 49, 131, 124, 245, 126, 197, 69, 94, 216, 200, 231, 78, 198, 74, 101, 111, 121, 3, 155, 227, 54, 129, 11, 166, 247, 169, 174, 115, 253, 231, 229, 31, 11, 88, 212, 136, 99, 207, 32, 180, 182, 230, 68, 120, 73, 51, 194, 157, 20, 131, 169, 205, 218, 44, 35, 111, 223, 242, 208, 132, 92, 232, 36, 206, 217, 240, 144, 123, 143, 117, 134, 67, 229, 123, 127, 105, 151, 101, 60, 210, 151, 4, 109, 105, 98, 179, 200, 45, 51, 214, 56, 38, 199, 57, 73, 48, 49, 222, 75, 39, 66, 85, 100, 58, 5, 134, 76, 66, 114, 158, 126, 232, 90, 26, 201, 90, 38, 218, 98, 61, 233, 235, 187, 17, 201, 232, 200, 180, 245, 209, 193, 49, 197, 20, 72, 153, 56, 75, 86, 34, 102, 170, 183, 246, 100, 216, 32, 57, 237, 187, 124, 44, 48, 212, 25, 89, 16, 69, 229, 39, 52, 170, 209, 132, 116, 111, 174, 16, 61, 171, 184, 95, 42, 19, 240, 19, 90, 238, 241, 109, 228, 63, 255, 244, 173, 79, 127, 246, 48, 160, 140, 52, 9, 75, 76, 93, 49, 240, 225, 208, 126, 37, 179, 8, 185, 146, 1, 254, 33, 45, 130, 83, 139, 89, 208, 154, 55, 102, 192, 26, 167, 155, 176, 202, 142, 168, 109, 66, 33, 39, 200, 217, 38, 219, 76, 32, 88, 89, 252, 217, 121, 100, 177, 216, 134, 133, 38, 181, 111, 100, 202, 211, 116, 242, 194, 240, 219, 241, 216, 28, 189, 213, 89, 75, 197, 215, 200, 249, 33, 248, 103, 216, 8, 10, 18, 99, 78, 155, 36, 250, 175, 196, 41, 61, 207, 134, 132, 133, 145, 19, 78, 225, 20, 65, 69, 87, 210, 188, 96, 180, 117, 115, 106, 129, 149, 15, 88, 69, 116, 212, 41, 253, 93, 243, 195, 48, 244, 227, 71, 1, 89, 182, 77, 251, 90, 96, 205, 30, 23, 98, 62, 14, 31, 138, 245, 123, 64, 118, 167, 64, 35, 107, 46, 171, 88, 206, 79, 194, 26, 198, 0, 92, 163, 130, 235, 175, 171, 2, 149, 69, 71, 29, 87, 133, 155, 173, 94, 119, 209, 49, 86, 148, 132, 4, 8, 177, 210, 138, 6, 122, 169, 20, 36, 65, 196, 48, 137, 74, 170, 149, 81, 34, 157, 82, 46, 169, 68, 50, 89, 188, 170, 237, 50, 176, 92, 236, 79, 235, 250, 163, 81, 160, 114, 10, 8, 204, 187, 186, 96, 207, 169, 2, 211, 47, 118, 133, 135, 252, 54, 75, 117, 92, 162, 155, 164, 25, 107, 133, 4, 58, 106, 56, 212, 117, 192, 212, 55, 49, 162, 77, 226, 95, 187, 212, 240, 245, 66, 228, 132, 136, 14, 59, 52, 244, 161, 42, 131, 7, 30, 18, 126, 55, 221, 38, 159, 194, 185, 80, 89, 129, 250, 101, 176, 119, 183, 182, 133, 171, 80, 131, 32, 25, 231, 147, 63, 137, 160, 90, 97, 191, 87, 201, 47, 162, 117, 121, 68, 228, 141, 232, 158, 253, 209, 191, 134, 190, 110, 221, 220, 190, 218, 31, 91, 215, 208, 241, 251, 183, 164, 227, 246, 199, 253, 107, 160, 194, 131, 219, 72, 5, 251, 227, 193, 50, 73, 66, 247, 19, 230, 84, 213, 205, 123, 46, 117, 181, 233, 50, 180, 149, 229, 54, 39, 252, 144, 117, 199, 28, 48, 238, 136, 55, 158, 200, 224, 62, 47, 114, 70, 82, 55, 30, 136, 153, 106, 209, 51, 119, 130, 171, 177, 79, 61, 183, 143, 48, 110, 164, 209, 148, 79, 103, 150, 55, 13, 85, 148, 81, 165, 254, 112, 22, 9, 120, 127, 28, 171, 165, 231, 227, 22, 55, 176, 158, 186, 211, 175, 180, 177, 208, 192, 74, 216, 166, 157, 191, 177, 98, 34, 75, 198, 254, 44, 143, 187, 5, 235, 106, 81, 221, 218, 28, 104, 49, 227, 215, 204, 247, 238, 108, 95, 163, 33, 26, 245, 67, 92, 59, 68, 116, 131, 89, 87, 243, 215, 97, 9, 167, 242, 109, 165, 219, 200, 182, 59, 175, 127, 166, 142, 232, 71, 119, 38, 95, 188, 79, 91, 55, 169, 79, 250, 209, 157, 175, 23, 239, 222, 253, 27, 218, 61, 253, 232, 206, 201, 139, 247, 244, 193, 205, 239, 169, 126, 116, 103, 221, 5, 58, 77, 93, 130, 209, 165, 32, 91, 181, 109, 214, 174, 218, 182, 91, 76, 188, 99, 211, 129, 177, 61, 189, 89, 95, 195, 40, 206, 53, 240, 3, 178, 89, 190, 117, 197, 45, 61, 193, 183, 156, 4, 91, 3, 190, 31, 154, 217, 201, 188, 200, 249, 103, 57, 115, 122, 112, 214, 91, 124, 159, 204, 110, 101, 52, 198, 222, 205, 21, 28, 180, 168, 151, 249, 147, 196, 8, 121, 94, 255, 121, 226, 129, 106, 60, 103, 203, 242, 155, 249, 14, 190, 32, 193, 12, 214, 182, 203, 164, 35, 143, 172, 87, 237, 134, 133, 17, 17, 242, 83, 155, 255, 174, 248, 248, 66, 27, 252, 43, 173, 119, 32, 213, 214, 249, 181, 201, 101, 81, 230, 167, 144, 56, 64, 245, 133, 6, 158, 168, 17, 15, 70, 158, 244, 87, 221, 234, 79, 113, 227, 19, 3, 190, 77, 114, 58, 212, 132, 50, 171, 78, 101, 132, 233, 31, 206, 7, 178, 245, 119, 13, 186, 194, 243, 57, 59, 219, 65, 100, 59, 208, 197, 152, 111, 225, 205, 173, 116, 26, 212, 78, 144, 243, 231, 83, 62, 238, 22, 216, 252, 209, 136, 73, 139, 157, 49, 119, 195, 193, 183, 131, 26, 172, 160, 152, 13, 20, 180, 128, 188, 253, 168, 176, 61, 99, 173, 25, 147, 186, 140, 238, 31, 201, 71, 58, 122, 206, 150, 179, 140, 125, 109, 26, 186, 232, 22, 116, 100, 232, 182, 195, 163, 98, 44, 186, 54, 36, 135, 124, 108, 219, 97, 174, 163, 251, 140, 180, 24, 229, 152, 186, 157, 147, 232, 118, 97, 120, 141, 76, 204, 95, 190, 99, 88, 187, 65, 72, 199, 218, 25, 152, 79, 60, 95, 90, 137, 111, 59, 93, 178, 113, 225, 215, 55, 221, 212, 153, 146, 98, 246, 231, 35, 205, 19, 118, 3, 16, 11, 181, 83, 235, 96, 255, 154, 198, 156, 169, 225, 207, 63, 93, 80, 117, 161, 137, 210, 146, 102, 179, 131, 172, 77, 54, 174, 173, 122, 51, 71, 90, 15, 211, 139, 46, 111, 181, 199, 97, 4, 34, 43, 239, 152, 117, 64, 131, 26, 231, 178, 16, 72, 48, 226, 173, 52, 22, 62, 203, 164, 255, 101, 126, 112, 230, 135, 230, 176, 92, 204, 162, 53, 81, 17, 191, 106, 220, 189, 12, 116, 80, 139, 239, 247, 90, 240, 178, 114, 77, 248, 197, 246, 54, 249, 193, 231, 43, 168, 106, 191, 58, 113, 34, 240, 143, 132, 35, 59, 121, 213, 233, 40, 208, 136, 217, 123, 245, 189, 93, 108, 190, 244, 103, 76, 39, 118, 54, 100, 207, 4, 230, 205, 200, 86, 200, 151, 25, 244, 203, 12, 154, 124, 153, 65, 155, 98, 216, 231, 156, 62, 253, 77, 166, 219, 226, 12, 251, 50, 215, 45, 52, 215, 93, 71, 252, 222, 28, 251, 165, 148, 86, 145, 105, 198, 223, 62, 85, 133, 23, 92, 141, 197, 3, 48, 123, 225, 14, 224, 219, 47, 203, 183, 207, 49, 249, 220, 17, 245, 28, 62, 68, 210, 82, 61, 135, 79, 33, 199, 195, 231, 23, 58, 65, 103, 143, 101, 28, 148, 71, 50, 245, 7, 215, 241, 93, 155, 37, 255, 135, 85, 179, 111, 196, 107, 208, 144, 190, 90, 38, 136, 87, 149, 195, 24, 152, 48, 184, 158, 144, 195, 120, 68, 184, 132, 26, 193, 209, 19, 27, 115, 122, 46, 107, 188, 150, 117, 248, 135, 177, 103, 113, 45, 71, 20, 171, 160, 88, 215, 123, 60, 227, 205, 59, 141, 251, 176, 105, 203, 142, 134, 169, 15, 167, 142, 205, 216, 76, 92, 54, 201, 102, 164, 208, 10, 78, 3, 119, 79, 142, 231, 217, 197, 248, 34, 197, 203, 145, 226, 121, 172, 182, 26, 139, 109, 89, 34, 108, 98, 163, 34, 198, 93, 155, 83, 55, 53, 70, 93, 173, 57, 28, 183, 236, 62, 133, 134, 104, 227, 7, 160, 86, 90, 99, 152, 219, 10, 26, 89, 95, 84, 77, 221, 33, 216, 150, 11, 186, 248, 17, 135, 47, 234, 231, 139, 250, 185, 149, 234, 103, 193, 224, 210, 229, 132, 244, 182, 92, 154, 206, 165, 240, 230, 140, 235, 253, 162, 25, 169, 89, 124, 195, 18, 200, 169, 29, 129, 236, 125, 94, 204, 170, 103, 132, 195, 41, 195, 123, 46, 178, 253, 234, 191, 179, 18, 146, 245, 28, 137, 209, 150, 44, 209, 245, 96, 232, 115, 190, 178, 71, 78, 205, 136, 84, 177, 27, 244, 234, 211, 13, 125, 253, 181, 77, 8, 184, 35, 244, 242, 247, 39, 39, 39, 53, 71, 212, 221, 21, 147, 62, 130, 92, 135, 156, 135, 158, 215, 69, 84, 112, 124, 39, 99, 193, 60, 48, 120, 218, 44, 56, 225, 196, 167, 135, 8, 74, 124, 199, 193, 73, 119, 25, 8, 246, 87, 228, 225, 249, 238, 122, 62, 240, 56, 83, 55, 87, 181, 236, 94, 155, 60, 64, 6, 176, 206, 202, 82, 72, 125, 29, 55, 202, 113, 179, 204, 231, 214, 8, 33, 16, 225, 185, 32, 5, 53, 15, 70, 38, 65, 164, 221, 186, 123, 249, 18, 159, 129, 2, 169, 179, 142, 38, 163, 124, 234, 102, 157, 218, 91, 66, 242, 172, 189, 105, 81, 38, 143, 98, 215, 39, 209, 236, 89, 208, 204, 158, 156, 91, 108, 205, 249, 18, 116, 217, 122, 27, 38, 1, 214, 182, 171, 88, 111, 126, 94, 46, 57, 22, 38, 43, 215, 8, 220, 20, 55, 73, 39, 71, 110, 202, 2, 114, 52, 140, 178, 221, 177, 183, 100, 52, 183, 114, 212, 243, 33, 210, 182, 43, 169, 193, 79, 183, 64, 62, 3, 236, 133, 253, 170, 175, 96, 227, 150, 55, 68, 59, 75, 255, 172, 52, 50, 37, 121, 43, 104, 112, 154, 149, 154, 156, 4, 53, 147, 244, 100, 126, 157, 233, 52, 19, 217, 220, 225, 154, 85, 106, 84, 166, 172, 171, 249, 227, 33, 224, 159, 238, 82, 120, 27, 175, 194, 237, 59, 221, 236, 255, 147, 237, 6, 39, 12, 2, 168, 212, 83, 138, 107, 214, 215, 167, 166, 9, 81, 98, 129, 172, 49, 202, 96, 190, 120, 170, 3, 59, 244, 17, 237, 182, 128, 46, 59, 100, 170, 210, 128, 104, 164, 136, 215, 117, 183, 16, 164, 30, 86, 105, 154, 245, 220, 69, 136, 19, 77, 248, 191, 39, 120, 23, 36, 175, 103, 224, 49, 41, 227, 153, 45, 149, 205, 176, 75, 55, 244, 4, 63, 107, 190, 12, 48, 190, 238, 146, 248, 4, 149, 100, 18, 97, 248, 183, 237, 45, 189, 100, 1, 5, 225, 241, 227, 199, 142, 15, 87, 55, 136, 173, 240, 29, 14, 154, 138, 81, 215, 168, 242, 223, 129, 41, 105, 50, 62, 121, 137, 172, 124, 77, 43, 71, 228, 9, 243, 97, 115, 243, 71, 147, 19, 141, 160, 120, 134, 49, 55, 43, 36, 31, 55, 11, 89, 78, 223, 4, 234, 170, 189, 190, 190, 25, 168, 252, 127, 56, 161, 230, 166, 61, 198, 25, 34, 206, 111, 48, 115, 7, 244, 220, 139, 130, 172, 141, 168, 254, 19, 246, 226, 189, 72, 248, 50, 197, 30, 64, 226, 62, 237, 111, 194, 174, 4, 98, 83, 171, 82, 8, 244, 239, 219, 33, 162, 219, 118, 109, 183, 127, 243, 173, 79, 70, 254, 223, 152, 229, 247, 27, 186, 234, 65, 207, 254, 6, 203, 26, 218, 54, 252, 11, 110, 63, 101, 173, 162, 140, 127, 79, 236, 69, 225, 102, 44, 163, 108, 243, 187, 231, 36, 168, 65, 251, 247, 246, 91, 202, 64, 143, 223, 237, 242, 220, 118, 124, 158, 206, 254, 38, 84, 196, 239, 199, 155, 175, 89, 132, 115, 68, 161, 50, 59, 239, 183, 109, 175, 123, 30, 239, 54, 119, 236, 55, 25, 155, 196, 117, 109, 108, 243, 241, 55, 184, 105, 244, 55, 186, 201, 152, 128, 14, 19, 211, 182, 123, 183, 178, 234, 154, 241, 105, 249, 248, 123, 121, 233, 148, 10, 152, 112, 102, 91, 28, 49, 142, 86, 157, 92, 162, 250, 236, 57, 177, 234, 2, 40, 4, 167, 235, 75, 205, 176, 148, 74, 34, 75, 115, 81, 238, 74, 188, 133, 254, 243, 50, 232, 177, 140, 190, 160, 45, 51, 91, 247, 247, 128, 82, 145, 147, 149, 180, 62, 14, 78, 26, 179, 80, 253, 30, 78, 64, 165, 160, 64, 6, 44, 67, 9, 20, 254, 92, 30, 141, 115, 192, 83, 70, 104, 160, 206, 239, 250, 70, 67, 100, 40, 77, 137, 0, 113, 26, 9, 228, 19, 137, 114, 14, 85, 165, 70, 43, 234, 245, 203, 196, 149, 173, 6, 180, 59, 120, 91, 43, 149, 167, 57, 249, 64, 206, 79, 134, 21, 200, 226, 104, 55, 96, 131, 59, 150, 186, 231, 26, 169, 187, 65, 1, 20, 165, 187, 94, 58, 116, 151, 75, 204, 120, 65, 138, 65, 226, 90, 234, 90, 216, 63, 249, 119, 153, 78, 38, 246, 204, 194, 161, 126, 192, 197, 1, 254, 234, 4, 113, 118, 110, 115, 174, 51, 235, 163, 249, 234, 15, 35, 89, 232, 95, 101, 213, 116, 46, 154, 212, 44, 76, 230, 184, 85, 162, 21, 254, 128, 248, 211, 162, 148, 40, 250, 248, 127, 165, 215, 25, 114, 1, 131, 119, 98, 232, 75, 88, 36, 242, 241, 91, 37, 176, 18, 94, 184, 113, 124, 36, 175, 114, 222, 168, 212, 219, 215, 236, 130, 9, 227, 35, 2, 149, 183, 59, 26, 125, 89, 90, 95, 101, 105, 189, 18, 94, 40, 107, 226, 126, 38, 199, 101, 197, 83, 55, 46, 127, 153, 204, 150, 106, 58, 238, 185, 236, 37, 158, 195, 169, 153, 219, 76, 10, 136, 69, 150, 148, 11, 44, 128, 17, 87, 178, 114, 108, 183, 73, 198, 20, 188, 65, 182, 211, 225, 136, 196, 22, 155, 182, 213, 22, 75, 178, 64, 197, 141, 118, 72, 26, 68, 80, 255, 206, 177, 18, 61, 237, 172, 10, 198, 146, 62, 212, 135, 176, 204, 249, 115, 126, 16, 51, 4, 209, 223, 148, 32, 124, 234, 174, 111, 57, 19, 156, 186, 143, 20, 117, 152, 178, 184, 132, 17, 151, 2, 211, 25, 158, 18, 212, 234, 185, 12, 55, 10, 187, 87, 107, 192, 149, 217, 105, 246, 97, 210, 211, 243, 83, 28, 160, 28, 97, 123, 201, 14, 191, 110, 39, 71, 112, 162, 47, 47, 178, 139, 96, 67, 178, 219, 138, 31, 133, 182, 102, 108, 168, 107, 203, 165, 154, 66, 168, 85, 233, 190, 70, 187, 85, 233, 45, 221, 185, 86, 165, 239, 107, 127, 203, 159, 56, 98, 225, 10, 202, 174, 212, 181, 228, 175, 7, 61, 62, 190, 43, 206, 45, 65, 88, 56, 236, 212, 101, 52, 123, 145, 125, 96, 158, 53, 50, 113, 127, 234, 107, 14, 174, 226, 28, 245, 250, 68, 58, 82, 188, 253, 79, 84, 241, 203, 59, 201, 133, 101, 214, 85, 133, 126, 153, 165, 229, 240, 85, 17, 100, 46, 40, 186, 26, 243, 173, 215, 27, 110, 28, 82, 196, 140, 3, 4, 29, 219, 205, 239, 86, 192, 124, 51, 27, 20, 127, 36, 242, 226, 251, 135, 52, 121, 195, 176, 24, 139, 23, 114, 26, 87, 23, 192, 187, 145, 9, 70, 123, 251, 44, 7, 119, 44, 42, 110, 211, 236, 229, 31, 242, 183, 206, 24, 220, 76, 128, 6, 129, 218, 165, 94, 157, 5, 119, 115, 20, 222, 32, 132, 20, 5, 53, 38, 222, 12, 194, 145, 217, 92, 33, 155, 180, 74, 52, 91, 76, 92, 28, 70, 159, 194, 104, 57, 143, 113, 8, 247, 41, 132, 218, 251, 16, 218, 69, 244, 59, 81, 24, 196, 93, 134, 145, 237, 115, 121, 126, 145, 139, 12, 182, 73, 178, 101, 249, 134, 157, 51, 105, 171, 20, 80, 80, 91, 28, 76, 65, 93, 223, 87, 162, 130, 40, 251, 213, 35, 198, 2, 214, 222, 82, 181, 79, 2, 7, 81, 98, 177, 47, 102, 165, 137, 180, 53, 191, 217, 222, 36, 190, 101, 174, 147, 123, 241, 232, 150, 218, 208, 22, 19, 243, 97, 166, 124, 90, 97, 231, 17, 114, 39, 174, 229, 77, 17, 8, 255, 118, 130, 90, 156, 249, 49, 16, 6, 14, 129, 224, 214, 37, 70, 2, 208, 131, 110, 159, 154, 121, 196, 227, 12, 248, 247, 128, 254, 88, 239, 155, 31, 196, 37, 16, 19, 111, 245, 205, 17, 113, 74, 165, 208, 109, 32, 209, 120, 25, 215, 83, 230, 142, 129, 44, 132, 199, 48, 130, 199, 44, 26, 67, 243, 93, 136, 161, 240, 124, 53, 70, 1, 103, 84, 237, 0, 69, 99, 245, 45, 45, 174, 56, 50, 116, 186, 119, 6, 200, 59, 158, 184, 116, 22, 176, 1, 93, 146, 17, 222, 227, 149, 55, 146, 212, 219, 230, 155, 199, 8, 122, 75, 31, 117, 125, 211, 214, 147, 241, 161, 67, 121, 102, 120, 59, 39, 48, 194, 253, 147, 215, 2, 115, 3, 175, 129, 20, 132, 12, 134, 4, 235, 68, 91, 234, 217, 10, 133, 141, 69, 1, 48, 177, 53, 106, 60, 44, 150, 243, 35, 209, 167, 42, 123, 174, 217, 213, 23, 57, 211, 3, 231, 98, 1, 45, 116, 100, 98, 208, 197, 116, 180, 138, 35, 63, 0, 9, 44, 21, 127, 61, 228, 12, 25, 243, 89, 66, 208, 209, 220, 7, 98, 180, 180, 153, 230, 232, 169, 24, 139, 3, 145, 180, 0, 219, 152, 150, 45, 59, 50, 89, 185, 210, 184, 168, 213, 84, 88, 30, 188, 75, 91, 61, 67, 188, 155, 226, 205, 191, 204, 235, 131, 134, 169, 249, 214, 228, 145, 177, 171, 91, 93, 229, 216, 218, 234, 202, 25, 213, 237, 200, 66, 157, 213, 215, 140, 71, 69, 165, 96, 204, 30, 182, 116, 239, 30, 150, 114, 214, 141, 251, 213, 203, 162, 170, 242, 183, 163, 75, 52, 96, 153, 159, 202, 224, 205, 186, 172, 134, 85, 26, 248, 255, 72, 171, 23, 133, 186, 154, 212, 154, 232, 170, 114, 237, 90, 67, 21, 177, 91, 247, 4, 100, 172, 202, 145, 185, 226, 21, 169, 171, 96, 8, 12, 108, 33, 2, 166, 71, 209, 168, 165, 187, 166, 80, 55, 74, 105, 184, 228, 154, 128, 94, 117, 24, 64, 125, 210, 55, 34, 222, 150, 197, 87, 160, 70, 13, 175, 17, 56, 178, 163, 43, 238, 210, 77, 122, 218, 246, 199, 112, 91, 122, 58, 21, 252, 148, 169, 133, 145, 12, 13, 85, 82, 255, 94, 17, 196, 113, 201, 137, 101, 179, 30, 90, 149, 2, 175, 103, 21, 154, 170, 21, 98, 190, 55, 18, 47, 84, 83, 86, 226, 246, 171, 23, 66, 31, 29, 148, 191, 106, 41, 144, 32, 184, 55, 48, 128, 35, 246, 82, 161, 201, 38, 138, 188, 122, 169, 238, 37, 62, 210, 107, 19, 237, 39, 196, 57, 16, 226, 80, 148, 106, 235, 104, 198, 148, 77, 221, 235, 186, 85, 33, 104, 48, 44, 56, 102, 240, 238, 249, 248, 99, 15, 87, 172, 209, 204, 213, 132, 24, 49, 236, 132, 158, 192, 162, 99, 232, 78, 11, 49, 141, 193, 150, 193, 174, 111, 205, 56, 147, 116, 115, 134, 100, 60, 15, 36, 115, 227, 155, 50, 208, 118, 128, 46, 113, 17, 162, 157, 22, 38, 197, 212, 4, 239, 62, 21, 63, 72, 165, 238, 145, 99, 38, 96, 212, 141, 174, 80, 223, 81, 91, 208, 239, 8, 61, 42, 47, 157, 98, 93, 210, 142, 226, 185, 38, 228, 253, 59, 128, 221, 88, 80, 162, 134, 66, 68, 39, 131, 252, 161, 110, 128, 149, 211, 243, 40, 46, 48, 224, 72, 95, 170, 204, 8, 128, 174, 216, 224, 204, 23, 97, 100, 26, 55, 98, 166, 78, 231, 27, 95, 201, 163, 25, 64, 226, 120, 98, 120, 43, 155, 147, 174, 14, 28, 93, 211, 239, 247, 61, 11, 88, 162, 219, 236, 153, 53, 188, 172, 26, 225, 119, 39, 7, 155, 218, 18, 101, 12, 141, 130, 201, 56, 22, 148, 100, 9, 239, 147, 10, 179, 113, 204, 248, 18, 93, 39, 34, 246, 2, 178, 26, 28, 100, 99, 173, 24, 92, 245, 27, 15, 4, 96, 192, 191, 194, 204, 155, 140, 112, 248, 38, 233, 80, 244, 241, 131, 178, 105, 197, 154, 36, 31, 141, 142, 208, 12, 21, 159, 158, 140, 135, 87, 150, 2, 5, 6, 246, 145, 212, 19, 236, 36, 193, 227, 209, 52, 45, 167, 161, 9, 197, 217, 80, 98, 116, 204, 199, 211, 231, 26, 91, 106, 140, 155, 46, 80, 79, 153, 120, 35, 35, 14, 74, 39, 68, 139, 1, 81, 110, 11, 241, 195, 81, 69, 226, 165, 70, 202, 120, 228, 129, 58, 25, 67, 206, 210, 203, 40, 59, 93, 136, 221, 82, 230, 3, 245, 16, 121, 156, 116, 187, 253, 100, 103, 39, 185, 191, 9, 97, 16, 91, 156, 176, 135, 233, 248, 212, 200, 205, 38, 163, 23, 52, 168, 186, 202, 224, 173, 99, 191, 52, 242, 98, 13, 53, 30, 192, 65, 10, 116, 100, 233, 190, 248, 158, 92, 100, 141, 50, 155, 8, 78, 213, 103, 73, 160, 180, 122, 238, 234, 6, 255, 138, 175, 77, 240, 198, 159, 214, 89, 25, 110, 109, 141, 30, 41, 65, 152, 176, 124, 213, 16, 255, 203, 129, 168, 105, 138, 60, 4, 52, 165, 233, 57, 44, 85, 197, 162, 40, 216, 162, 51, 115, 68, 176, 82, 227, 18, 20, 142, 55, 21, 176, 105, 88, 68, 96, 75, 46, 233, 176, 189, 115, 70, 76, 11, 69, 113, 57, 236, 93, 6, 37, 77, 218, 218, 49, 241, 124, 147, 141, 35, 34, 186, 180, 246, 37, 77, 107, 215, 47, 250, 146, 228, 187, 184, 130, 193, 131, 76, 13, 107, 24, 203, 183, 114, 143, 240, 164, 44, 206, 117, 148, 77, 112, 27, 79, 31, 168, 211, 213, 254, 41, 204, 185, 108, 212, 213, 42, 89, 235, 102, 18, 13, 165, 64, 110, 74, 49, 10, 124, 30, 225, 192, 109, 18, 57, 243, 25, 166, 212, 183, 89, 203, 112, 67, 76, 62, 237, 223, 188, 112, 21, 171, 70, 211, 43, 96, 212, 160, 93, 143, 11, 0, 130, 3, 91, 5, 132, 236, 124, 195, 96, 117, 150, 62, 1, 232, 154, 251, 136, 20, 183, 18, 24, 17, 106, 6, 158, 88, 10, 6, 206, 252, 166, 130, 174, 218, 75, 88, 187, 74, 242, 106, 110, 176, 110, 97, 62, 40, 128, 71, 94, 33, 74, 16, 45, 50, 102, 245, 69, 111, 234, 38, 212, 119, 164, 68, 65, 210, 119, 184, 210, 24, 142, 30, 107, 54, 114, 21, 45, 154, 178, 225, 203, 198, 23, 110, 42, 124, 175, 56, 155, 245, 38, 69, 85, 27, 69, 63, 204, 62, 28, 156, 144, 45, 120, 2, 223, 78, 43, 69, 229, 109, 234, 233, 25, 69, 148, 163, 205, 1, 34, 142, 47, 81, 86, 168, 97, 4, 63, 179, 60, 239, 164, 104, 221, 248, 82, 87, 200, 238, 218, 52, 205, 71, 47, 101, 239, 0, 191, 53, 86, 203, 57, 93, 59, 206, 46, 142, 12, 170, 180, 71, 198, 129, 105, 74, 152, 248, 17, 230, 13, 164, 159, 153, 134, 147, 24, 170, 19, 159, 134, 236, 182, 240, 218, 35, 77, 144, 109, 198, 192, 198, 48, 171, 92, 108, 37, 103, 98, 199, 118, 88, 105, 31, 211, 181, 16, 46, 88, 185, 199, 91, 90, 215, 239, 221, 53, 34, 161, 76, 84, 73, 202, 152, 169, 107, 215, 147, 237, 215, 127, 84, 154, 131, 139, 192, 80, 1, 190, 18, 36, 37, 110, 231, 114, 144, 16, 45, 186, 32, 252, 162, 235, 183, 87, 174, 160, 121, 119, 181, 225, 183, 184, 242, 85, 21, 172, 180, 199, 53, 84, 170, 182, 57, 126, 186, 116, 99, 191, 251, 61, 6, 197, 116, 95, 88, 187, 7, 39, 112, 72, 226, 57, 110, 64, 153, 99, 64, 38, 238, 195, 38, 243, 35, 217, 5, 234, 82, 248, 193, 158, 8, 201, 47, 16, 138, 93, 9, 204, 29, 230, 139, 36, 139, 254, 69, 73, 133, 239, 52, 22, 242, 39, 225, 47, 214, 236, 78, 224, 126, 8, 239, 102, 12, 210, 31, 90, 121, 219, 101, 253, 72, 166, 248, 218, 60, 241, 225, 92, 117, 129, 28, 241, 161, 46, 134, 146, 223, 25, 199, 130, 236, 54, 237, 188, 229, 242, 163, 81, 46, 3, 56, 172, 62, 15, 82, 149, 15, 186, 75, 87, 161, 229, 121, 1, 218, 86, 169, 211, 228, 177, 22, 189, 244, 4, 110, 27, 9, 75, 51, 65, 57, 113, 155, 143, 132, 0, 108, 120, 152, 234, 111, 7, 220, 14, 159, 242, 120, 144, 80, 120, 70, 115, 58, 205, 1, 120, 125, 118, 39, 184, 192, 62, 155, 107, 83, 99, 62, 131, 187, 184, 102, 83, 3, 214, 114, 219, 73, 209, 225, 206, 237, 59, 105, 26, 208, 141, 39, 213, 213, 216, 226, 80, 213, 88, 154, 123, 27, 17, 248, 228, 123, 66, 154, 175, 231, 223, 20, 170, 240, 16, 94, 75, 95, 178, 166, 48, 209, 233, 6, 194, 252, 54, 131, 174, 122, 21, 95, 114, 195, 238, 80, 128, 211, 91, 108, 15, 177, 188, 39, 205, 155, 68, 235, 91, 203, 219, 29, 186, 170, 215, 219, 140, 208, 28, 62, 111, 194, 72, 50, 197, 192, 157, 212, 143, 208, 179, 38, 143, 22, 42, 5, 149, 103, 33, 155, 164, 24, 165, 77, 82, 45, 92, 73, 59, 72, 20, 2, 43, 31, 84, 5, 240, 62, 232, 152, 128, 50, 145, 145, 226, 103, 167, 141, 155, 9, 81, 15, 66, 211, 133, 107, 78, 142, 51, 86, 70, 145, 128, 246, 136, 240, 245, 108, 43, 36, 70, 208, 63, 227, 23, 115, 132, 133, 48, 12, 170, 54, 221, 207, 58, 39, 152, 70, 196, 85, 110, 246, 40, 62, 93, 22, 153, 113, 141, 114, 9, 85, 111, 26, 198, 2, 234, 205, 28, 212, 37, 109, 42, 218, 41, 142, 242, 85, 67, 120, 7, 92, 78, 203, 90, 88, 212, 176, 5, 177, 193, 212, 0, 254, 153, 254, 68, 158, 193, 35, 11, 39, 62, 114, 193, 19, 254, 166, 107, 199, 175, 169, 65, 174, 84, 62, 29, 189, 56, 81, 142, 143, 88, 213, 24, 63, 225, 225, 239, 94, 114, 40, 9, 99, 68, 163, 6, 231, 22, 88, 112, 28, 136, 118, 240, 249, 25, 154, 14, 107, 2, 98, 162, 166, 229, 84, 90, 168, 75, 208, 3, 26, 234, 188, 123, 125, 163, 192, 246, 29, 238, 1, 202, 189, 67, 89, 113, 95, 48, 225, 41, 28, 129, 135, 55, 116, 155, 80, 238, 23, 65, 15, 156, 52, 41, 63, 74, 184, 15, 73, 85, 232, 165, 174, 120, 34, 83, 251, 35, 116, 187, 94, 205, 149, 143, 195, 44, 94, 53, 10, 224, 141, 151, 187, 0, 28, 128, 106, 187, 182, 186, 40, 18, 168, 92, 22, 231, 110, 69, 139, 81, 207, 0, 183, 174, 194, 194, 93, 86, 71, 139, 71, 246, 35, 204, 102, 134, 220, 117, 16, 58, 181, 16, 43, 15, 248, 189, 138, 135, 116, 228, 57, 208, 253, 106, 127, 60, 18, 208, 196, 176, 62, 75, 203, 211, 204, 221, 98, 50, 99, 188, 186, 29, 225, 42, 205, 82, 116, 121, 116, 117, 174, 90, 96, 251, 184, 137, 117, 48, 173, 135, 207, 118, 146, 149, 18, 18, 36, 74, 121, 74, 214, 162, 76, 229, 108, 96, 154, 134, 119, 72, 94, 16, 139, 76, 144, 185, 96, 93, 42, 192, 154, 0, 24, 234, 183, 13, 214, 21, 220, 98, 25, 83, 158, 42, 231, 30, 108, 176, 207, 136, 135, 54, 198, 157, 153, 102, 77, 60, 42, 174, 97, 74, 104, 117, 123, 91, 146, 151, 12, 102, 127, 170, 184, 100, 210, 232, 220, 12, 21, 224, 166, 65, 1, 27, 184, 16, 117, 217, 191, 58, 19, 41, 96, 243, 48, 17, 180, 182, 139, 17, 159, 120, 227, 124, 119, 53, 152, 43, 166, 226, 91, 253, 225, 74, 129, 125, 7, 49, 234, 166, 89, 49, 99, 235, 122, 221, 205, 213, 213, 102, 120, 91, 115, 193, 139, 125, 234, 175, 6, 24, 71, 201, 4, 188, 55, 215, 20, 231, 210, 237, 38, 254, 236, 36, 30, 58, 219, 144, 83, 193, 245, 193, 249, 78, 77, 218, 108, 174, 13, 17, 235, 52, 177, 149, 218, 122, 63, 222, 84, 224, 255, 89, 238, 4, 6, 16, 111, 197, 228, 37, 167, 15, 174, 31, 118, 228, 86, 49, 252, 251, 209, 219, 78, 22, 227, 79, 39, 50, 44, 247, 48, 166, 81, 232, 76, 5, 19, 143, 110, 8, 144, 21, 205, 68, 27, 192, 169, 46, 0, 88, 126, 161, 96, 171, 73, 58, 118, 213, 161, 153, 145, 180, 34, 108, 55, 147, 73, 80, 243, 104, 28, 24, 229, 128, 194, 81, 81, 48, 221, 65, 49, 27, 47, 97, 81, 164, 160, 133, 152, 41, 110, 11, 143, 25, 175, 40, 68, 180, 46, 26, 211, 9, 197, 11, 20, 194, 140, 102, 102, 203, 73, 20, 255, 11, 73, 203, 249, 200, 139, 56, 106, 19, 114, 100, 67, 28, 164, 155, 26, 146, 97, 58, 96, 224, 132, 130, 193, 254, 149, 113, 216, 75, 189, 177, 189, 77, 151, 121, 80, 155, 100, 183, 122, 37, 29, 165, 212, 136, 30, 11, 171, 222, 100, 127, 145, 53, 108, 233, 35, 90, 154, 31, 7, 114, 28, 235, 68, 113, 188, 10, 233, 140, 220, 156, 167, 158, 107, 128, 237, 222, 21, 54, 107, 206, 76, 152, 112, 109, 243, 91, 37, 201, 208, 13, 153, 15, 124, 196, 229, 203, 150, 92, 193, 79, 135, 171, 18, 115, 159, 11, 63, 106, 85, 176, 239, 72, 94, 240, 180, 53, 199, 224, 202, 39, 146, 157, 14, 45, 116, 22, 153, 195, 104, 115, 10, 217, 239, 68, 36, 125, 76, 211, 169, 80, 117, 46, 139, 168, 116, 231, 240, 113, 248, 52, 168, 172, 101, 69, 39, 144, 97, 110, 254, 243, 207, 202, 250, 196, 67, 182, 52, 213, 208, 220, 231, 151, 225, 0, 211, 203, 34, 151, 59, 79, 177, 237, 95, 83, 102, 119, 42, 99, 183, 115, 150, 247, 125, 240, 46, 45, 247, 64, 127, 9, 8, 125, 161, 37, 186, 22, 228, 99, 204, 220, 87, 195, 144, 138, 58, 8, 83, 212, 54, 208, 144, 55, 217, 177, 164, 24, 130, 48, 65, 236, 233, 86, 123, 146, 155, 122, 182, 103, 148, 203, 173, 137, 209, 60, 123, 80, 142, 9, 45, 129, 166, 98, 22, 24, 188, 41, 211, 11, 153, 224, 226, 72, 8, 80, 98, 133, 99, 80, 20, 103, 50, 193, 186, 201, 21, 174, 11, 217, 240, 225, 244, 130, 125, 151, 53, 54, 196, 91, 107, 111, 72, 161, 28, 29, 101, 167, 210, 12, 99, 7, 213, 210, 11, 55, 158, 210, 43, 29, 48, 96, 49, 90, 164, 166, 134, 107, 189, 218, 141, 227, 244, 66, 159, 177, 227, 70, 164, 111, 0, 146, 162, 198, 174, 164, 135, 231, 250, 219, 228, 231, 142, 219, 77, 242, 209, 90, 155, 122, 235, 85, 215, 241, 108, 83, 234, 185, 33, 88, 173, 69, 236, 82, 3, 75, 219, 167, 31, 87, 106, 235, 66, 151, 76, 29, 75, 5, 198, 86, 218, 168, 245, 231, 162, 183, 249, 233, 156, 211, 80, 200, 206, 16, 80, 92, 35, 67, 15, 235, 142, 248, 246, 184, 67, 109, 127, 89, 12, 82, 123, 238, 252, 85, 126, 11, 162, 37, 184, 255, 108, 25, 136, 1, 156, 56, 106, 240, 53, 142, 156, 250, 26, 68, 175, 24, 13, 151, 129, 157, 0, 19, 71, 46, 142, 88, 24, 169, 147, 252, 67, 182, 12, 172, 36, 156, 40, 90, 211, 105, 20, 47, 248, 20, 182, 119, 82, 97, 237, 86, 75, 64, 13, 33, 69, 145, 203, 163, 184, 229, 97, 212, 170, 115, 161, 251, 150, 128, 152, 132, 19, 69, 75, 126, 141, 162, 134, 95, 131, 232, 137, 63, 103, 217, 50, 240, 147, 128, 226, 8, 202, 207, 113, 12, 241, 115, 196, 139, 187, 12, 252, 102, 111, 227, 200, 205, 226, 162, 32, 191, 133, 209, 154, 44, 5, 173, 73, 13, 90, 147, 26, 180, 38, 14, 90, 79, 170, 65, 58, 201, 118, 167, 162, 232, 219, 217, 20, 243, 212, 191, 183, 179, 114, 62, 158, 204, 64, 77, 211, 201, 234, 61, 91, 127, 78, 131, 49, 85, 186, 94, 47, 249, 166, 243, 77, 47, 233, 124, 253, 219, 172, 152, 110, 119, 130, 14, 247, 116, 60, 120, 39, 140, 91, 56, 210, 121, 117, 210, 40, 96, 237, 151, 150, 216, 141, 111, 118, 82, 121, 166, 244, 81, 231, 27, 65, 170, 32, 85, 20, 126, 107, 162, 67, 143, 161, 204, 145, 34, 105, 26, 81, 122, 197, 120, 58, 40, 70, 5, 172, 84, 71, 58, 191, 222, 149, 180, 159, 6, 184, 64, 215, 160, 110, 34, 43, 215, 116, 15, 241, 116, 251, 7, 117, 227, 93, 4, 75, 186, 107, 205, 233, 171, 118, 16, 32, 45, 218, 63, 168, 91, 211, 61, 133, 100, 251, 222, 201, 137, 126, 86, 142, 174, 222, 177, 208, 84, 223, 138, 31, 223, 149, 217, 73, 77, 143, 36, 114, 141, 236, 152, 77, 73, 90, 193, 253, 113, 142, 43, 90, 147, 74, 89, 197, 131, 76, 201, 186, 84, 197, 43, 14, 229, 14, 170, 248, 178, 33, 158, 201, 114, 213, 4, 90, 202, 34, 49, 79, 0, 4, 177, 226, 174, 175, 42, 167, 59, 206, 172, 91, 21, 149, 15, 101, 70, 163, 226, 2, 119, 82, 97, 17, 97, 113, 212, 240, 67, 91, 173, 18, 50, 236, 179, 78, 123, 22, 28, 182, 196, 73, 240, 180, 40, 159, 164, 131, 119, 114, 69, 241, 54, 29, 156, 157, 140, 213, 120, 8, 227, 54, 241, 118, 17, 245, 216, 132, 215, 233, 71, 106, 149, 126, 68, 214, 232, 58, 131, 149, 248, 54, 255, 226, 92, 111, 81, 215, 174, 200, 9, 222, 228, 171, 192, 222, 46, 217, 77, 39, 157, 165, 186, 59, 108, 22, 84, 221, 216, 253, 156, 1, 31, 231, 163, 76, 180, 209, 221, 236, 37, 180, 22, 229, 97, 185, 206, 12, 159, 64, 200, 166, 111, 212, 87, 122, 103, 138, 24, 43, 181, 72, 20, 197, 76, 8, 142, 202, 89, 114, 228, 125, 130, 74, 145, 80, 86, 92, 174, 139, 245, 9, 172, 53, 69, 213, 39, 227, 105, 121, 41, 40, 96, 92, 37, 186, 109, 191, 69, 178, 255, 13, 96, 106, 226, 80, 77, 15, 149, 36, 56, 112, 204, 245, 210, 193, 79, 9, 205, 101, 30, 226, 222, 0, 47, 246, 84, 107, 230, 207, 145, 207, 204, 95, 137, 190, 206, 153, 174, 214, 214, 168, 201, 85, 107, 211, 107, 249, 227, 32, 186, 162, 66, 150, 252, 79, 93, 182, 204, 215, 159, 61, 199, 215, 65, 84, 156, 14, 148, 56, 29, 48, 113, 50, 131, 120, 176, 144, 64, 205, 229, 234, 226, 56, 7, 252, 92, 115, 179, 172, 90, 231, 131, 54, 170, 117, 78, 1, 75, 219, 220, 124, 205, 12, 125, 16, 229, 101, 73, 81, 202, 202, 232, 24, 61, 255, 103, 46, 55, 80, 26, 220, 109, 7, 54, 81, 171, 117, 81, 88, 25, 177, 128, 168, 175, 195, 108, 79, 213, 74, 134, 227, 143, 54, 183, 181, 155, 186, 199, 193, 202, 161, 158, 138, 215, 44, 174, 164, 89, 232, 212, 24, 24, 87, 24, 237, 23, 126, 66, 162, 135, 162, 201, 84, 9, 54, 149, 130, 155, 19, 124, 113, 131, 162, 28, 42, 119, 237, 31, 30, 59, 43, 7, 109, 80, 173, 66, 70, 97, 233, 219, 141, 167, 20, 134, 218, 204, 91, 148, 94, 28, 41, 231, 167, 248, 178, 1, 22, 140, 102, 151, 241, 236, 28, 191, 172, 97, 33, 205, 8, 250, 139, 74, 69, 47, 159, 169, 71, 200, 128, 12, 199, 240, 184, 56, 63, 16, 42, 3, 141, 178, 142, 41, 174, 143, 164, 56, 163, 91, 87, 247, 69, 250, 194, 212, 34, 29, 132, 93, 53, 213, 13, 187, 179, 163, 145, 182, 94, 91, 85, 166, 102, 135, 231, 187, 191, 109, 49, 186, 189, 75, 43, 164, 153, 120, 10, 217, 46, 226, 117, 116, 246, 131, 52, 51, 226, 123, 135, 65, 60, 203, 46, 53, 72, 120, 12, 193, 132, 247, 181, 64, 161, 64, 199, 93, 175, 253, 1, 140, 252, 80, 102, 156, 146, 22, 236, 67, 77, 147, 30, 244, 162, 167, 26, 254, 232, 242, 161, 86, 10, 32, 203, 38, 194, 13, 88, 211, 170, 92, 168, 184, 63, 53, 71, 219, 253, 40, 92, 40, 46, 59, 35, 165, 13, 126, 136, 63, 244, 72, 13, 178, 180, 6, 212, 176, 233, 35, 216, 27, 159, 108, 203, 113, 78, 215, 101, 184, 186, 69, 154, 232, 143, 174, 33, 251, 235, 24, 48, 47, 166, 239, 178, 114, 225, 169, 197, 124, 107, 55, 177, 68, 76, 52, 12, 232, 147, 168, 244, 228, 36, 34, 113, 227, 60, 35, 191, 30, 66, 128, 187, 163, 58, 100, 7, 182, 253, 113, 10, 15, 172, 6, 227, 213, 128, 137, 66, 212, 210, 63, 55, 192, 4, 182, 243, 143, 190, 186, 18, 236, 255, 201, 165, 232, 176, 231, 91, 142, 90, 223, 255, 206, 167, 239, 228, 4, 174, 65, 247, 88, 155, 204, 38, 247, 108, 62, 97, 148, 235, 120, 23, 223, 42, 175, 13, 92, 144, 243, 83, 86, 86, 153, 2, 120, 51, 199, 153, 162, 184, 200, 112, 31, 201, 165, 86, 36, 231, 187, 248, 104, 67, 170, 205, 16, 142, 179, 11, 168, 214, 181, 81, 7, 2, 41, 84, 155, 193, 33, 80, 225, 82, 7, 70, 150, 77, 249, 157, 71, 6, 203, 13, 247, 206, 160, 118, 150, 252, 1, 49, 20, 230, 54, 140, 130, 214, 252, 210, 236, 249, 144, 69, 31, 185, 161, 167, 165, 93, 223, 198, 200, 80, 173, 134, 52, 172, 161, 180, 212, 227, 150, 238, 176, 90, 125, 239, 156, 93, 109, 35, 75, 239, 201, 57, 74, 22, 107, 77, 103, 225, 249, 53, 202, 18, 148, 130, 212, 60, 78, 80, 122, 176, 63, 146, 18, 7, 84, 45, 204, 71, 2, 174, 78, 28, 50, 52, 41, 151, 159, 243, 147, 147, 172, 204, 198, 131, 236, 134, 170, 22, 139, 224, 34, 138, 37, 162, 241, 63, 179, 190, 40, 169, 132, 126, 81, 26, 159, 66, 105, 12, 179, 81, 54, 205, 110, 163, 222, 104, 213, 29, 87, 7, 180, 146, 253, 163, 203, 243, 243, 108, 90, 230, 131, 207, 165, 4, 176, 135, 237, 61, 126, 74, 47, 224, 143, 78, 184, 11, 1, 103, 197, 157, 183, 57, 23, 154, 91, 22, 99, 44, 190, 186, 157, 127, 118, 106, 197, 153, 251, 21, 4, 112, 10, 126, 58, 185, 161, 179, 146, 69, 112, 145, 89, 105, 225, 169, 231, 113, 120, 230, 137, 101, 67, 158, 199, 122, 253, 95, 236, 135, 54, 57, 75, 174, 50, 239, 184, 99, 224, 113, 186, 10, 162, 243, 249, 124, 2, 43, 167, 155, 205, 233, 26, 197, 79, 202, 235, 59, 243, 241, 250, 124, 218, 123, 201, 179, 116, 36, 235, 77, 131, 2, 94, 144, 101, 126, 206, 171, 255, 64, 60, 34, 244, 237, 182, 205, 215, 28, 251, 133, 167, 234, 47, 107, 253, 187, 103, 182, 251, 210, 112, 179, 237, 242, 5, 215, 243, 13, 221, 172, 17, 254, 127, 229, 217, 69, 54, 220, 45, 203, 244, 242, 167, 25, 88, 187, 251, 39, 135, 89, 126, 146, 67, 200, 69, 10, 111, 85, 51, 38, 33, 237, 219, 217, 73, 18, 187, 210, 74, 85, 208, 81, 232, 244, 220, 158, 81, 24, 162, 58, 92, 162, 7, 80, 244, 109, 59, 44, 125, 202, 207, 217, 52, 29, 188, 203, 134, 10, 23, 40, 126, 146, 145, 136, 30, 245, 59, 166, 86, 152, 250, 222, 214, 98, 106, 42, 105, 21, 69, 58, 171, 27, 136, 106, 42, 111, 70, 104, 121, 149, 149, 130, 219, 75, 238, 211, 64, 19, 114, 39, 213, 15, 234, 86, 244, 77, 119, 183, 97, 119, 170, 250, 79, 113, 164, 227, 128, 67, 160, 250, 211, 60, 118, 154, 6, 49, 194, 198, 246, 207, 190, 183, 199, 120, 16, 119, 85, 161, 5, 186, 40, 40, 108, 195, 60, 214, 49, 21, 136, 67, 67, 228, 198, 213, 172, 204, 0, 17, 85, 16, 36, 135, 214, 72, 203, 83, 26, 36, 100, 47, 196, 88, 85, 57, 73, 108, 77, 249, 82, 119, 47, 210, 62, 20, 217, 38, 163, 173, 187, 236, 79, 79, 48, 57, 89, 216, 193, 57, 42, 213, 17, 34, 157, 58, 186, 192, 228, 196, 187, 108, 193, 6, 46, 45, 53, 91, 159, 70, 254, 6, 234, 0, 14, 236, 142, 13, 108, 65, 61, 206, 131, 166, 211, 250, 4, 56, 92, 213, 107, 201, 69, 247, 67, 249, 28, 15, 101, 235, 54, 90, 59, 133, 44, 247, 77, 149, 124, 67, 48, 250, 38, 153, 224, 221, 208, 220, 190, 147, 83, 161, 248, 30, 202, 46, 164, 250, 79, 238, 80, 9, 164, 162, 112, 211, 147, 180, 238, 208, 62, 35, 172, 133, 115, 152, 77, 138, 114, 250, 107, 149, 158, 102, 242, 104, 7, 28, 142, 236, 9, 173, 113, 31, 206, 151, 245, 191, 131, 67, 233, 247, 87, 87, 105, 147, 149, 6, 27, 218, 157, 235, 227, 137, 172, 206, 223, 255, 142, 253, 49, 132, 72, 212, 182, 179, 162, 21, 33, 149, 207, 19, 66, 193, 231, 195, 116, 154, 57, 221, 241, 57, 159, 238, 129, 171, 15, 78, 21, 59, 73, 68, 100, 64, 147, 137, 75, 1, 77, 70, 225, 93, 70, 19, 109, 2, 74, 71, 203, 254, 35, 117, 117, 16, 175, 28, 85, 66, 212, 194, 112, 49, 12, 140, 194, 183, 127, 251, 46, 38, 96, 42, 178, 6, 116, 10, 158, 203, 32, 131, 192, 243, 4, 168, 41, 253, 194, 86, 77, 106, 110, 182, 149, 216, 80, 80, 225, 23, 230, 142, 58, 217, 171, 192, 16, 179, 6, 237, 49, 27, 121, 172, 55, 74, 86, 236, 137, 95, 87, 30, 161, 201, 224, 180, 38, 207, 15, 231, 145, 235, 123, 221, 117, 123, 48, 150, 103, 53, 181, 128, 27, 233, 138, 35, 203, 232, 170, 167, 194, 183, 151, 211, 236, 224, 228, 68, 26, 106, 215, 77, 107, 108, 83, 61, 219, 118, 23, 29, 135, 249, 169, 191, 16, 245, 132, 5, 161, 114, 104, 181, 35, 227, 167, 38, 223, 205, 33, 153, 158, 41, 93, 121, 206, 62, 100, 231, 147, 81, 26, 16, 102, 184, 20, 188, 118, 166, 213, 85, 41, 42, 53, 154, 99, 207, 52, 209, 22, 69, 28, 83, 1, 221, 96, 185, 66, 41, 205, 217, 20, 153, 244, 26, 58, 128, 120, 236, 213, 10, 102, 219, 78, 185, 28, 219, 162, 119, 215, 209, 39, 23, 141, 96, 231, 98, 157, 130, 37, 177, 13, 241, 116, 253, 29, 77, 22, 233, 65, 43, 110, 63, 160, 61, 80, 120, 203, 207, 52, 226, 112, 43, 138, 224, 251, 172, 188, 36, 49, 172, 201, 85, 48, 109, 63, 165, 88, 71, 71, 67, 250, 17, 119, 70, 249, 86, 30, 244, 238, 252, 151, 133, 248, 95, 27, 38, 219, 228, 70, 6, 189, 233, 184, 182, 230, 53, 197, 76, 219, 192, 115, 191, 15, 143, 147, 190, 88, 137, 242, 44, 36, 9, 9, 30, 101, 30, 189, 179, 68, 38, 30, 57, 83, 211, 169, 120, 224, 169, 70, 206, 48, 233, 125, 114, 112, 124, 246, 218, 186, 114, 166, 89, 101, 179, 31, 182, 14, 76, 62, 195, 212, 206, 103, 214, 47, 36, 169, 100, 161, 45, 224, 237, 59, 170, 57, 81, 236, 176, 26, 141, 51, 182, 159, 224, 230, 146, 46, 6, 75, 87, 152, 79, 100, 179, 135, 57, 138, 156, 229, 6, 95, 64, 168, 67, 81, 127, 254, 9, 169, 229, 200, 156, 193, 78, 116, 52, 56, 6, 27, 214, 94, 220, 63, 248, 158, 230, 27, 86, 105, 89, 240, 7, 228, 25, 194, 199, 14, 239, 89, 192, 105, 72, 101, 139, 45, 187, 235, 87, 179, 84, 196, 34, 50, 37, 57, 70, 197, 11, 11, 88, 182, 16, 132, 254, 18, 177, 59, 211, 145, 192, 127, 3, 226, 153, 95, 253, 77, 203, 121, 138, 233, 94, 21, 63, 229, 167, 251, 130, 129, 237, 254, 179, 227, 217, 210, 229, 94, 204, 206, 223, 102, 37, 45, 183, 162, 55, 20, 71, 233, 52, 127, 159, 53, 101, 138, 57, 195, 36, 44, 188, 124, 67, 202, 23, 86, 56, 158, 247, 197, 41, 70, 179, 180, 232, 79, 87, 72, 177, 230, 32, 142, 41, 100, 218, 160, 141, 217, 100, 234, 145, 102, 137, 101, 106, 92, 85, 109, 156, 55, 7, 206, 194, 117, 97, 223, 77, 45, 23, 34, 85, 2, 185, 223, 108, 71, 84, 2, 21, 169, 246, 228, 23, 166, 248, 64, 215, 137, 250, 146, 153, 156, 85, 195, 65, 100, 42, 19, 162, 6, 11, 236, 187, 50, 151, 157, 200, 238, 124, 170, 201, 236, 213, 194, 211, 152, 114, 109, 79, 48, 194, 241, 205, 179, 188, 34, 33, 142, 131, 116, 34, 198, 76, 166, 131, 216, 188, 226, 156, 23, 243, 217, 211, 105, 238, 149, 51, 193, 217, 185, 12, 48, 60, 214, 216, 172, 173, 1, 111, 169, 146, 124, 98, 131, 182, 119, 131, 150, 163, 107, 164, 31, 244, 76, 231, 156, 253, 57, 213, 51, 88, 28, 235, 2, 226, 151, 237, 222, 238, 241, 88, 182, 14, 8, 141, 221, 244, 150, 187, 237, 167, 83, 197, 238, 177, 249, 84, 40, 251, 137, 104, 57, 135, 235, 193, 110, 187, 28, 140, 135, 113, 41, 48, 157, 156, 71, 8, 72, 165, 27, 98, 208, 197, 152, 219, 96, 26, 51, 225, 60, 107, 45, 196, 213, 248, 137, 32, 219, 158, 201, 228, 84, 23, 97, 49, 117, 207, 247, 109, 225, 51, 164, 147, 96, 55, 124, 218, 52, 246, 90, 13, 235, 201, 62, 54, 156, 197, 188, 109, 76, 56, 15, 183, 1, 143, 70, 121, 45, 200, 102, 235, 253, 249, 248, 75, 95, 55, 31, 98, 50, 239, 188, 239, 13, 231, 49, 173, 203, 44, 64, 202, 78, 120, 176, 247, 14, 173, 79, 91, 175, 59, 9, 27, 57, 83, 222, 34, 90, 73, 17, 50, 204, 51, 251, 234, 190, 27, 188, 159, 224, 201, 72, 222, 153, 162, 82, 41, 234, 44, 76, 155, 55, 97, 37, 201, 241, 195, 151, 6, 203, 192, 82, 18, 59, 230, 232, 162, 54, 11, 70, 119, 181, 89, 107, 186, 107, 223, 126, 40, 137, 214, 122, 159, 50, 24, 207, 228, 104, 80, 183, 27, 244, 58, 107, 40, 89, 3, 136, 87, 61, 175, 229, 255, 206, 202, 226, 96, 124, 48, 155, 30, 156, 252, 84, 8, 126, 168, 32, 190, 199, 64, 81, 153, 21, 31, 203, 100, 197, 181, 248, 156, 177, 210, 6, 119, 96, 223, 177, 183, 110, 133, 183, 106, 41, 54, 182, 83, 240, 25, 61, 157, 152, 32, 227, 51, 29, 71, 22, 45, 174, 44, 108, 91, 56, 106, 245, 242, 232, 17, 31, 228, 185, 244, 103, 128, 179, 255, 79, 1, 185, 141, 77, 42, 245, 27, 193, 195, 58, 53, 190, 207, 174, 128, 237, 117, 243, 170, 10, 105, 154, 200, 144, 160, 96, 62, 121, 56, 178, 216, 235, 200, 197, 123, 52, 21, 125, 140, 217, 109, 198, 56, 137, 135, 186, 112, 225, 42, 220, 204, 239, 109, 112, 155, 11, 221, 117, 139, 119, 22, 67, 239, 228, 186, 57, 89, 199, 124, 138, 38, 8, 5, 80, 203, 20, 123, 109, 74, 139, 82, 5, 66, 153, 111, 44, 13, 191, 46, 200, 23, 44, 192, 229, 125, 100, 105, 192, 206, 179, 87, 177, 26, 51, 88, 145, 217, 15, 229, 77, 85, 98, 4, 214, 188, 86, 216, 44, 167, 186, 189, 67, 69, 88, 86, 109, 217, 105, 123, 227, 2, 145, 147, 195, 136, 152, 252, 51, 187, 252, 252, 14, 247, 205, 152, 195, 29, 110, 192, 10, 78, 81, 201, 162, 2, 29, 182, 82, 30, 243, 51, 254, 81, 153, 111, 41, 245, 92, 238, 35, 179, 87, 226, 88, 20, 246, 125, 39, 72, 128, 14, 126, 39, 129, 246, 159, 96, 142, 173, 195, 229, 166, 76, 171, 49, 139, 205, 78, 183, 78, 134, 115, 161, 226, 80, 63, 44, 111, 226, 213, 202, 65, 77, 167, 204, 143, 41, 0, 142, 173, 70, 194, 198, 113, 42, 53, 83, 228, 99, 101, 54, 174, 175, 127, 178, 25, 242, 121, 58, 185, 125, 107, 133, 200, 226, 243, 60, 157, 220, 14, 231, 95, 107, 127, 25, 115, 252, 182, 240, 147, 156, 75, 122, 107, 103, 73, 11, 223, 159, 179, 200, 0, 95, 155, 244, 34, 19, 64, 139, 251, 219, 4, 111, 133, 23, 28, 135, 217, 112, 54, 200, 238, 12, 223, 149, 178, 59, 159, 130, 245, 152, 74, 132, 24, 203, 134, 91, 37, 220, 126, 240, 100, 33, 198, 88, 135, 31, 233, 96, 48, 59, 159, 141, 48, 163, 120, 107, 222, 22, 12, 180, 182, 246, 154, 41, 49, 159, 53, 57, 236, 154, 75, 74, 253, 108, 95, 222, 245, 164, 4, 150, 126, 37, 153, 88, 47, 64, 204, 75, 62, 59, 33, 247, 146, 218, 17, 133, 168, 120, 243, 48, 63, 125, 55, 189, 61, 12, 138, 125, 158, 195, 81, 87, 218, 110, 126, 178, 180, 105, 203, 231, 94, 50, 129, 95, 141, 135, 215, 215, 57, 15, 123, 19, 241, 237, 98, 225, 247, 112, 152, 171, 123, 19, 214, 187, 29, 15, 173, 79, 177, 194, 61, 207, 135, 195, 81, 70, 13, 186, 147, 81, 81, 200, 75, 153, 146, 191, 98, 206, 47, 51, 167, 142, 138, 11, 185, 5, 44, 6, 92, 61, 194, 81, 0, 5, 1, 223, 240, 73, 118, 38, 250, 90, 26, 230, 83, 85, 214, 245, 21, 21, 6, 160, 221, 177, 144, 63, 73, 24, 138, 172, 111, 63, 203, 159, 248, 89, 23, 134, 24, 14, 83, 74, 127, 82, 5, 161, 97, 3, 223, 97, 141, 216, 62, 239, 81, 240, 74, 156, 54, 103, 201, 56, 151, 28, 44, 141, 69, 14, 230, 8, 8, 145, 216, 183, 227, 26, 87, 223, 214, 176, 200, 151, 16, 139, 101, 134, 88, 200, 157, 107, 188, 216, 193, 191, 142, 78, 136, 199, 25, 189, 13, 163, 253, 126, 49, 187, 235, 70, 53, 240, 56, 217, 164, 210, 40, 175, 237, 25, 50, 128, 63, 229, 211, 139, 188, 202, 20, 215, 11, 40, 187, 210, 194, 181, 176, 144, 213, 85, 77, 187, 128, 170, 139, 192, 8, 48, 146, 137, 134, 183, 91, 216, 248, 2, 207, 255, 153, 48, 13, 26, 85, 191, 123, 60, 86, 123, 233, 214, 112, 130, 127, 193, 211, 97, 187, 49, 113, 46, 206, 239, 142, 241, 92, 137, 206, 220, 165, 253, 157, 79, 21, 127, 88, 19, 126, 104, 175, 114, 113, 24, 10, 227, 18, 219, 174, 223, 128, 207, 194, 11, 184, 87, 197, 179, 66, 32, 155, 161, 255, 114, 36, 127, 84, 52, 242, 176, 151, 20, 19, 168, 196, 94, 90, 70, 77, 49, 52, 190, 45, 179, 166, 38, 46, 189, 61, 195, 218, 58, 237, 125, 214, 39, 121, 89, 77, 159, 24, 239, 173, 4, 81, 235, 32, 150, 160, 66, 99, 73, 33, 109, 76, 25, 189, 122, 172, 25, 121, 139, 175, 134, 77, 156, 242, 224, 134, 143, 122, 157, 29, 166, 211, 78, 229, 20, 175, 101, 50, 106, 41, 251, 224, 245, 134, 6, 80, 176, 239, 225, 188, 152, 3, 209, 175, 124, 76, 25, 138, 187, 178, 13, 37, 66, 68, 32, 240, 61, 26, 144, 111, 171, 174, 141, 27, 115, 84, 31, 205, 222, 202, 78, 116, 223, 102, 167, 249, 216, 177, 101, 218, 220, 49, 117, 47, 122, 36, 107, 153, 70, 175, 194, 174, 222, 168, 193, 158, 4, 34, 93, 219, 196, 36, 234, 115, 98, 109, 66, 27, 201, 196, 200, 15, 153, 153, 67, 128, 229, 224, 153, 190, 21, 180, 217, 223, 169, 107, 99, 205, 159, 76, 68, 63, 111, 202, 188, 102, 21, 180, 241, 240, 19, 80, 136, 89, 93, 146, 102, 166, 156, 252, 133, 155, 207, 204, 138, 81, 21, 163, 118, 140, 237, 202, 26, 175, 210, 108, 207, 96, 49, 3, 193, 224, 130, 187, 51, 58, 93, 171, 141, 206, 182, 239, 89, 31, 37, 238, 140, 44, 156, 76, 107, 180, 119, 127, 161, 224, 245, 136, 250, 230, 158, 88, 44, 147, 109, 237, 106, 119, 54, 213, 151, 59, 5, 120, 184, 198, 180, 10, 156, 16, 129, 127, 144, 132, 85, 243, 46, 57, 108, 148, 184, 125, 241, 153, 181, 217, 78, 181, 67, 18, 179, 86, 51, 140, 104, 153, 199, 96, 13, 13, 116, 123, 179, 213, 31, 228, 113, 118, 97, 100, 192, 189, 12, 87, 33, 183, 78, 134, 205, 185, 15, 175, 134, 224, 148, 206, 134, 202, 236, 64, 23, 167, 176, 122, 105, 176, 89, 137, 159, 79, 222, 157, 170, 107, 221, 110, 138, 2, 36, 60, 148, 71, 226, 49, 118, 93, 95, 83, 195, 41, 216, 154, 133, 92, 72, 169, 232, 96, 21, 203, 101, 252, 246, 57, 19, 237, 192, 43, 184, 145, 15, 236, 171, 196, 52, 28, 5, 225, 151, 91, 33, 49, 17, 242, 144, 64, 56, 6, 131, 217, 148, 100, 214, 19, 125, 146, 179, 115, 91, 251, 108, 119, 26, 182, 206, 32, 68, 12, 246, 233, 110, 77, 156, 97, 139, 120, 86, 232, 207, 45, 140, 105, 213, 14, 202, 144, 75, 241, 22, 6, 182, 194, 40, 212, 243, 220, 255, 134, 0, 87, 211, 207, 219, 26, 228, 90, 199, 149, 55, 43, 210, 213, 144, 154, 114, 221, 87, 182, 140, 228, 240, 207, 31, 187, 210, 95, 13, 95, 64, 226, 34, 42, 116, 156, 202, 240, 212, 137, 69, 98, 14, 70, 179, 161, 232, 208, 29, 12, 197, 84, 61, 251, 156, 65, 35, 94, 246, 160, 198, 112, 204, 79, 21, 35, 73, 60, 134, 196, 92, 128, 186, 71, 130, 143, 36, 239, 192, 66, 204, 101, 11, 144, 63, 95, 242, 184, 251, 39, 1, 63, 129, 99, 104, 24, 63, 80, 104, 137, 45, 175, 170, 149, 121, 231, 170, 98, 86, 14, 132, 188, 159, 167, 147, 147, 49, 119, 238, 212, 94, 33, 181, 231, 91, 161, 244, 24, 249, 94, 84, 29, 62, 48, 87, 103, 237, 49, 229, 7, 209, 8, 242, 182, 84, 5, 79, 225, 115, 47, 228, 175, 112, 85, 176, 44, 74, 72, 212, 164, 128, 251, 216, 91, 126, 211, 43, 182, 159, 216, 91, 146, 217, 160, 219, 207, 30, 135, 189, 66, 82, 8, 216, 154, 159, 102, 21, 185, 47, 24, 86, 27, 146, 202, 129, 4, 60, 230, 174, 112, 155, 129, 135, 215, 189, 231, 46, 17, 253, 207, 212, 33, 224, 210, 134, 149, 142, 211, 232, 251, 190, 63, 73, 41, 156, 57, 145, 36, 120, 77, 10, 39, 253, 19, 31, 126, 245, 21, 53, 151, 6, 101, 154, 7, 56, 248, 152, 184, 196, 18, 61, 242, 116, 170, 128, 102, 138, 51, 229, 135, 144, 233, 119, 166, 184, 95, 234, 73, 253, 96, 50, 205, 207, 213, 178, 184, 171, 87, 143, 212, 103, 31, 81, 82, 8, 127, 219, 148, 171, 81, 78, 193, 178, 83, 152, 248, 32, 63, 99, 82, 147, 35, 100, 175, 151, 236, 217, 125, 22, 84, 180, 45, 252, 208, 168, 179, 117, 19, 42, 172, 7, 121, 237, 236, 181, 133, 245, 209, 60, 105, 245, 161, 171, 232, 50, 31, 91, 14, 76, 116, 76, 94, 166, 131, 179, 165, 15, 202, 156, 4, 84, 237, 210, 107, 176, 145, 217, 201, 12, 149, 203, 132, 149, 20, 91, 211, 128, 97, 249, 237, 150, 228, 114, 210, 215, 130, 27, 124, 31, 111, 246, 123, 85, 200, 19, 159, 90, 187, 114, 49, 180, 190, 91, 197, 73, 170, 54, 185, 0, 222, 200, 113, 76, 186, 44, 145, 2, 185, 180, 246, 156, 92, 90, 91, 92, 134, 93, 162, 146, 54, 194, 41, 87, 176, 118, 59, 134, 100, 11, 30, 213, 49, 194, 138, 126, 252, 26, 42, 19, 67, 241, 31, 131, 142, 118, 169, 175, 249, 65, 214, 85, 83, 229, 33, 91, 4, 121, 242, 224, 132, 185, 57, 1, 181, 108, 104, 181, 70, 151, 94, 219, 103, 249, 153, 58, 193, 207, 149, 152, 99, 161, 104, 23, 157, 169, 66, 217, 175, 253, 224, 44, 54, 40, 115, 239, 85, 25, 44, 217, 158, 85, 221, 136, 204, 61, 30, 124, 52, 234, 199, 130, 38, 205, 176, 227, 80, 99, 178, 28, 156, 116, 201, 106, 83, 13, 129, 183, 86, 210, 244, 92, 186, 137, 50, 206, 46, 150, 61, 58, 10, 164, 34, 14, 93, 220, 157, 185, 187, 37, 170, 32, 35, 14, 153, 37, 231, 188, 51, 209, 171, 88, 115, 117, 162, 205, 20, 202, 85, 27, 92, 156, 39, 234, 157, 203, 117, 132, 106, 215, 152, 211, 185, 181, 124, 130, 220, 35, 235, 244, 228, 37, 126, 213, 42, 25, 30, 148, 180, 220, 181, 87, 92, 107, 229, 190, 51, 44, 31, 48, 135, 177, 104, 79, 215, 101, 185, 251, 141, 122, 62, 126, 109, 80, 212, 6, 122, 36, 245, 249, 88, 93, 5, 16, 219, 240, 122, 110, 187, 64, 117, 58, 239, 135, 147, 104, 214, 237, 5, 220, 32, 7, 69, 58, 158, 137, 5, 111, 55, 26, 178, 166, 255, 44, 77, 194, 159, 211, 105, 250, 18, 147, 29, 154, 196, 194, 249, 218, 154, 218, 122, 219, 224, 89, 71, 144, 47, 84, 49, 198, 74, 196, 228, 89, 60, 142, 136, 230, 164, 230, 75, 240, 185, 179, 82, 147, 234, 109, 22, 170, 177, 248, 34, 183, 91, 1, 95, 142, 151, 234, 227, 32, 198, 117, 52, 203, 7, 213, 62, 166, 9, 112, 240, 47, 28, 130, 36, 119, 139, 191, 132, 33, 181, 12, 67, 82, 123, 39, 177, 56, 36, 73, 75, 26, 139, 132, 25, 92, 3, 233, 206, 14, 122, 177, 219, 202, 200, 192, 118, 86, 105, 195, 111, 234, 12, 81, 149, 56, 80, 253, 95, 33, 105, 170, 230, 21, 178, 48, 93, 67, 34, 204, 159, 48, 213, 47, 166, 79, 54, 111, 194, 2, 5, 72, 172, 174, 6, 215, 126, 30, 59, 27, 80, 113, 69, 100, 179, 126, 126, 116, 87, 189, 20, 17, 104, 149, 105, 57, 236, 142, 131, 89, 115, 107, 15, 184, 190, 35, 100, 177, 94, 13, 178, 14, 137, 31, 207, 106, 214, 18, 164, 7, 228, 212, 149, 75, 164, 87, 66, 151, 152, 67, 87, 74, 69, 180, 164, 213, 138, 214, 215, 134, 76, 98, 76, 14, 162, 10, 228, 91, 166, 64, 210, 193, 116, 150, 142, 158, 133, 156, 223, 97, 173, 98, 169, 171, 57, 197, 130, 216, 209, 236, 22, 107, 251, 59, 205, 144, 61, 219, 240, 146, 52, 225, 96, 86, 150, 66, 8, 158, 53, 42, 68, 104, 70, 41, 186, 29, 82, 137, 78, 187, 126, 124, 33, 156, 169, 66, 188, 73, 59, 40, 228, 250, 64, 139, 109, 19, 174, 230, 129, 73, 209, 18, 75, 110, 59, 29, 244, 180, 86, 144, 45, 244, 44, 219, 5, 12, 45, 45, 141, 53, 105, 210, 129, 101, 184, 181, 229, 145, 207, 79, 181, 253, 21, 157, 143, 230, 179, 216, 252, 154, 109, 76, 182, 175, 142, 222, 165, 37, 227, 166, 121, 47, 215, 142, 212, 111, 211, 184, 95, 119, 41, 150, 133, 7, 118, 161, 91, 47, 92, 32, 87, 177, 50, 194, 29, 13, 4, 253, 40, 139, 193, 43, 254, 197, 110, 184, 75, 118, 131, 55, 188, 215, 111, 61, 160, 247, 66, 155, 14, 106, 141, 26, 21, 23, 180, 30, 92, 137, 225, 147, 122, 180, 90, 100, 94, 252, 110, 179, 205, 172, 110, 144, 211, 182, 4, 153, 64, 15, 240, 242, 240, 3, 16, 120, 175, 249, 234, 121, 118, 94, 148, 151, 176, 83, 130, 133, 233, 134, 164, 135, 76, 235, 137, 182, 78, 24, 85, 59, 243, 207, 181, 223, 109, 214, 206, 181, 94, 147, 116, 202, 146, 29, 99, 243, 149, 6, 196, 39, 172, 184, 87, 192, 245, 77, 0, 201, 224, 93, 36, 83, 179, 189, 229, 192, 50, 177, 32, 83, 52, 199, 255, 156, 73, 155, 67, 233, 222, 35, 232, 190, 42, 240, 240, 208, 240, 166, 29, 106, 178, 152, 125, 138, 115, 77, 252, 224, 132, 51, 136, 11, 156, 23, 134, 45, 79, 19, 15, 112, 198, 79, 49, 193, 55, 27, 157, 2, 191, 208, 45, 136, 71, 132, 205, 119, 199, 72, 138, 157, 90, 128, 145, 87, 1, 89, 250, 102, 160, 27, 48, 146, 44, 82, 141, 101, 170, 237, 112, 204, 63, 197, 232, 182, 141, 99, 83, 122, 195, 132, 157, 213, 71, 180, 145, 194, 141, 177, 109, 188, 108, 77, 148, 155, 100, 173, 155, 149, 50, 151, 45, 52, 154, 163, 152, 15, 236, 38, 191, 85, 224, 170, 231, 24, 188, 71, 95, 9, 130, 250, 107, 18, 169, 218, 15, 211, 241, 169, 89, 250, 240, 3, 170, 215, 33, 172, 90, 32, 207, 36, 33, 41, 138, 63, 34, 145, 30, 146, 80, 178, 5, 37, 85, 88, 6, 69, 57, 21, 186, 22, 54, 125, 197, 132, 116, 50, 182, 162, 106, 94, 181, 219, 127, 183, 16, 218, 239, 193, 195, 1, 30, 91, 141, 175, 168, 63, 77, 32, 217, 178, 71, 15, 199, 65, 15, 12, 61, 11, 77, 146, 206, 120, 23, 141, 217, 230, 223, 84, 5, 88, 216, 187, 148, 50, 181, 131, 249, 239, 44, 61, 123, 158, 78, 200, 84, 13, 219, 155, 202, 123, 46, 198, 197, 46, 175, 206, 211, 137, 163, 166, 210, 225, 80, 250, 116, 196, 23, 184, 198, 141, 172, 187, 204, 168, 202, 34, 117, 65, 109, 184, 69, 162, 202, 105, 68, 217, 237, 108, 251, 211, 236, 60, 116, 57, 155, 69, 209, 97, 41, 226, 55, 135, 186, 113, 126, 122, 240, 173, 88, 129, 98, 255, 185, 251, 60, 228, 176, 151, 40, 202, 160, 143, 158, 193, 235, 120, 243, 53, 249, 209, 127, 141, 61, 112, 200, 43, 239, 250, 109, 34, 175, 138, 255, 15, 145, 87, 124, 217, 16, 207, 215, 68, 222, 232, 229, 119, 62, 125, 107, 168, 34, 239, 160, 224, 151, 251, 10, 50, 252, 127, 27, 8, 248, 46 }; + static const unsigned char data[] = { 120, 156, 237, 125, 107, 83, 28, 71, 178, 232, 119, 126, 69, 51, 225, 99, 15, 102, 224, 48, 72, 246, 122, 133, 36, 47, 198, 146, 151, 176, 36, 20, 140, 118, 55, 226, 112, 21, 58, 173, 153, 6, 122, 25, 186, 199, 221, 61, 2, 108, 235, 252, 246, 91, 89, 207, 204, 122, 244, 99, 24, 36, 96, 165, 8, 155, 158, 238, 170, 172, 172, 172, 204, 172, 172, 172, 172, 172, 227, 121, 54, 174, 210, 60, 139, 178, 228, 226, 221, 97, 50, 206, 139, 73, 127, 45, 250, 99, 37, 138, 138, 164, 154, 23, 89, 84, 86, 147, 119, 7, 239, 255, 157, 140, 171, 119, 227, 34, 137, 171, 164, 159, 205, 167, 211, 181, 157, 149, 143, 43, 199, 170, 238, 155, 252, 167, 60, 159, 38, 113, 214, 255, 64, 234, 174, 174, 126, 176, 202, 189, 154, 159, 191, 79, 10, 171, 216, 58, 45, 53, 138, 207, 147, 127, 198, 211, 121, 242, 63, 73, 145, 247, 47, 7, 209, 21, 41, 125, 25, 61, 121, 242, 36, 186, 138, 254, 252, 51, 234, 95, 70, 171, 236, 249, 50, 250, 250, 107, 246, 2, 30, 175, 40, 98, 191, 36, 213, 203, 164, 58, 205, 39, 253, 127, 14, 162, 215, 2, 204, 206, 14, 251, 223, 135, 184, 136, 160, 84, 244, 36, 250, 231, 209, 235, 183, 240, 42, 61, 142, 250, 251, 229, 43, 214, 185, 131, 226, 31, 217, 36, 57, 78, 179, 100, 210, 135, 66, 107, 162, 162, 198, 96, 174, 190, 66, 181, 143, 178, 234, 234, 126, 185, 23, 79, 167, 241, 251, 105, 66, 43, 189, 57, 45, 242, 139, 55, 87, 179, 228, 89, 81, 228, 69, 127, 184, 61, 136, 42, 246, 43, 63, 230, 8, 172, 41, 24, 18, 54, 188, 35, 93, 216, 47, 95, 23, 249, 44, 41, 170, 171, 95, 147, 171, 126, 92, 156, 204, 207, 147, 172, 18, 192, 161, 23, 0, 139, 245, 66, 130, 84, 223, 119, 12, 68, 81, 128, 209, 166, 87, 86, 69, 154, 157, 244, 128, 114, 232, 229, 213, 249, 251, 124, 218, 163, 35, 48, 75, 198, 105, 82, 238, 229, 25, 171, 50, 31, 87, 12, 237, 252, 253, 191, 7, 17, 235, 118, 60, 159, 86, 232, 189, 69, 82, 120, 197, 144, 97, 133, 55, 199, 166, 144, 162, 174, 248, 202, 26, 213, 4, 180, 8, 235, 194, 183, 40, 44, 24, 145, 3, 10, 209, 247, 187, 239, 7, 81, 47, 231, 229, 190, 41, 163, 111, 16, 26, 223, 68, 51, 73, 201, 158, 166, 58, 32, 93, 50, 140, 225, 251, 17, 227, 150, 159, 230, 233, 180, 74, 179, 17, 39, 74, 191, 87, 10, 66, 244, 214, 106, 56, 164, 180, 217, 163, 190, 23, 251, 132, 172, 78, 229, 82, 149, 181, 186, 197, 203, 12, 31, 14, 248, 223, 222, 223, 254, 38, 49, 211, 93, 138, 216, 224, 235, 94, 163, 78, 247, 88, 5, 71, 38, 12, 216, 205, 205, 77, 198, 50, 165, 64, 162, 42, 174, 36, 50, 99, 198, 201, 207, 101, 133, 62, 104, 0, 245, 227, 93, 60, 155, 77, 175, 6, 22, 118, 3, 51, 162, 131, 136, 195, 227, 189, 96, 96, 170, 241, 105, 212, 79, 172, 62, 38, 170, 143, 59, 54, 98, 187, 39, 39, 69, 114, 194, 148, 204, 18, 176, 163, 176, 150, 134, 226, 126, 86, 37, 69, 22, 79, 151, 128, 33, 1, 181, 28, 4, 129, 57, 117, 195, 172, 10, 250, 180, 151, 207, 174, 126, 142, 171, 88, 170, 19, 198, 60, 253, 138, 181, 147, 84, 131, 168, 204, 231, 197, 56, 25, 68, 201, 229, 120, 58, 159, 36, 147, 253, 42, 57, 47, 145, 104, 239, 212, 112, 63, 175, 106, 113, 49, 150, 174, 227, 34, 63, 103, 2, 246, 38, 151, 178, 43, 43, 40, 141, 113, 150, 92, 129, 252, 185, 200, 29, 20, 140, 216, 7, 23, 25, 211, 122, 6, 81, 0, 102, 163, 169, 112, 19, 144, 152, 118, 225, 243, 147, 23, 159, 99, 166, 127, 250, 208, 106, 202, 240, 103, 243, 72, 180, 181, 35, 31, 31, 115, 68, 54, 167, 73, 118, 82, 157, 202, 151, 235, 235, 10, 138, 68, 148, 85, 128, 82, 71, 252, 43, 215, 8, 162, 101, 254, 16, 69, 171, 167, 113, 201, 16, 6, 68, 28, 82, 126, 253, 181, 44, 228, 112, 134, 156, 91, 149, 28, 239, 151, 207, 50, 166, 193, 11, 152, 71, 84, 127, 25, 192, 53, 94, 93, 225, 19, 69, 63, 115, 242, 35, 138, 93, 105, 26, 241, 230, 161, 226, 17, 123, 122, 187, 38, 208, 252, 200, 41, 80, 203, 13, 255, 200, 142, 153, 238, 75, 10, 54, 168, 148, 47, 16, 35, 220, 30, 30, 144, 70, 200, 231, 30, 250, 69, 135, 115, 137, 35, 153, 207, 217, 160, 81, 155, 77, 127, 75, 179, 76, 127, 211, 95, 123, 199, 121, 222, 227, 116, 33, 170, 99, 183, 40, 226, 171, 103, 31, 146, 226, 138, 247, 234, 125, 60, 62, 59, 206, 34, 99, 104, 28, 224, 17, 172, 78, 211, 82, 143, 31, 35, 29, 255, 246, 130, 147, 176, 127, 32, 105, 169, 135, 103, 87, 26, 37, 165, 44, 176, 198, 199, 106, 43, 52, 129, 127, 55, 136, 182, 216, 28, 206, 241, 217, 100, 132, 172, 114, 176, 86, 54, 19, 64, 205, 204, 220, 182, 205, 101, 112, 174, 179, 188, 126, 102, 22, 238, 249, 44, 157, 38, 12, 167, 62, 107, 5, 215, 194, 28, 251, 134, 117, 200, 69, 251, 105, 52, 140, 126, 228, 243, 148, 252, 212, 31, 174, 69, 143, 168, 61, 168, 25, 237, 76, 48, 217, 25, 99, 48, 70, 15, 246, 96, 152, 138, 243, 44, 27, 156, 232, 192, 240, 1, 239, 15, 160, 195, 204, 131, 138, 129, 214, 92, 101, 80, 100, 211, 198, 32, 58, 56, 58, 123, 203, 88, 131, 61, 32, 38, 50, 35, 31, 79, 203, 100, 71, 190, 253, 136, 24, 198, 152, 131, 197, 60, 129, 113, 31, 177, 169, 172, 220, 207, 166, 105, 6, 228, 123, 1, 44, 167, 155, 52, 172, 192, 136, 66, 25, 100, 148, 159, 39, 183, 147, 63, 74, 134, 217, 253, 102, 143, 107, 115, 135, 24, 251, 26, 230, 144, 236, 211, 130, 59, 128, 15, 28, 230, 120, 158, 23, 207, 226, 241, 233, 237, 228, 143, 99, 129, 220, 253, 101, 145, 110, 236, 177, 227, 27, 127, 132, 71, 11, 30, 144, 195, 237, 176, 193, 203, 120, 118, 59, 89, 224, 60, 158, 221, 254, 225, 135, 218, 187, 96, 14, 197, 217, 193, 172, 74, 207, 211, 223, 19, 33, 113, 98, 197, 215, 103, 35, 254, 35, 247, 202, 240, 183, 125, 70, 40, 0, 129, 139, 236, 9, 63, 205, 193, 0, 200, 186, 118, 29, 150, 130, 42, 140, 104, 179, 100, 194, 29, 50, 176, 80, 94, 128, 201, 188, 70, 206, 46, 47, 130, 128, 251, 57, 114, 183, 21, 39, 50, 142, 115, 149, 17, 183, 102, 111, 39, 35, 10, 75, 251, 158, 240, 226, 209, 219, 32, 255, 109, 121, 184, 111, 16, 85, 121, 119, 46, 60, 83, 12, 8, 220, 165, 216, 170, 229, 164, 40, 234, 122, 166, 69, 63, 91, 86, 249, 250, 186, 170, 164, 57, 216, 59, 93, 182, 99, 78, 193, 136, 14, 127, 30, 38, 147, 249, 248, 150, 218, 82, 5, 199, 237, 83, 241, 167, 80, 74, 242, 71, 60, 30, 207, 207, 231, 211, 24, 249, 13, 189, 188, 171, 218, 69, 229, 25, 24, 202, 206, 194, 131, 146, 48, 155, 6, 113, 23, 167, 32, 166, 73, 20, 85, 128, 187, 67, 155, 109, 164, 145, 36, 162, 175, 139, 164, 100, 160, 89, 67, 200, 208, 158, 228, 196, 74, 179, 185, 55, 194, 213, 176, 5, 22, 69, 239, 153, 160, 156, 89, 28, 22, 93, 156, 50, 138, 69, 253, 245, 117, 41, 30, 107, 102, 181, 185, 170, 32, 117, 67, 157, 146, 136, 9, 208, 250, 250, 91, 178, 46, 110, 47, 138, 20, 148, 79, 246, 116, 231, 144, 16, 234, 119, 198, 197, 165, 95, 33, 136, 230, 37, 159, 66, 12, 253, 208, 7, 249, 228, 159, 44, 8, 239, 216, 75, 91, 33, 111, 135, 233, 201, 105, 245, 69, 232, 132, 208, 65, 191, 54, 162, 225, 23, 209, 163, 162, 183, 177, 113, 22, 61, 125, 34, 39, 175, 229, 74, 222, 198, 134, 43, 121, 79, 197, 100, 184, 177, 113, 79, 5, 239, 121, 154, 77, 250, 51, 198, 221, 233, 152, 153, 5, 183, 72, 224, 24, 65, 38, 97, 113, 211, 24, 119, 145, 54, 84, 233, 211, 45, 6, 3, 246, 81, 200, 58, 210, 56, 214, 25, 71, 114, 96, 197, 215, 101, 172, 21, 25, 173, 61, 38, 122, 54, 217, 7, 143, 234, 23, 246, 184, 97, 95, 65, 51, 31, 120, 61, 71, 138, 11, 188, 12, 176, 49, 108, 61, 242, 124, 144, 157, 225, 7, 135, 255, 191, 82, 54, 178, 153, 217, 113, 96, 15, 236, 79, 146, 77, 34, 103, 155, 120, 113, 158, 128, 239, 69, 194, 212, 83, 250, 33, 121, 195, 91, 226, 69, 97, 255, 237, 132, 45, 17, 69, 227, 186, 36, 44, 79, 86, 68, 239, 73, 149, 199, 209, 150, 36, 139, 88, 127, 191, 140, 171, 211, 119, 231, 241, 37, 159, 214, 214, 173, 210, 176, 246, 145, 165, 31, 161, 210, 172, 171, 118, 57, 101, 226, 97, 36, 71, 64, 6, 130, 35, 39, 140, 46, 39, 54, 84, 8, 146, 162, 74, 75, 28, 71, 130, 204, 77, 40, 202, 98, 62, 12, 159, 241, 17, 226, 227, 132, 55, 244, 89, 179, 208, 210, 35, 132, 121, 194, 5, 95, 226, 205, 184, 100, 106, 33, 14, 144, 90, 162, 205, 138, 54, 35, 205, 11, 97, 148, 199, 249, 156, 27, 0, 164, 180, 192, 100, 67, 110, 201, 8, 67, 168, 202, 181, 6, 225, 4, 126, 12, 172, 240, 245, 215, 240, 255, 199, 130, 228, 235, 2, 152, 18, 16, 185, 175, 133, 63, 41, 123, 42, 18, 171, 92, 246, 63, 231, 131, 180, 50, 196, 219, 167, 216, 24, 210, 45, 219, 102, 204, 193, 81, 149, 191, 229, 202, 29, 62, 235, 245, 47, 49, 176, 224, 223, 36, 153, 38, 76, 135, 242, 226, 212, 184, 17, 200, 110, 108, 168, 183, 85, 110, 158, 57, 38, 234, 231, 71, 219, 112, 251, 140, 232, 174, 175, 27, 116, 205, 179, 139, 174, 209, 73, 7, 62, 243, 99, 58, 101, 42, 146, 79, 114, 165, 148, 171, 173, 27, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 90, 153, 242, 182, 201, 156, 6, 179, 21, 235, 196, 7, 101, 157, 4, 89, 64, 248, 162, 56, 35, 236, 87, 73, 17, 235, 88, 166, 51, 48, 72, 244, 160, 167, 252, 91, 50, 17, 195, 142, 57, 128, 21, 214, 52, 72, 37, 4, 246, 253, 85, 114, 65, 129, 242, 66, 255, 200, 202, 248, 56, 97, 83, 226, 33, 91, 44, 20, 31, 146, 201, 104, 154, 87, 125, 85, 141, 155, 25, 180, 165, 86, 181, 134, 202, 145, 214, 84, 112, 91, 118, 107, 199, 80, 67, 125, 116, 229, 66, 97, 254, 42, 185, 172, 250, 134, 18, 172, 191, 160, 183, 24, 223, 43, 93, 104, 226, 174, 128, 22, 60, 238, 78, 20, 250, 101, 30, 23, 147, 55, 185, 67, 220, 181, 181, 192, 102, 60, 141, 126, 144, 188, 0, 22, 21, 1, 33, 34, 246, 246, 143, 255, 85, 112, 231, 176, 90, 131, 0, 74, 234, 185, 231, 244, 160, 199, 191, 16, 171, 42, 102, 40, 10, 138, 253, 98, 81, 140, 51, 192, 22, 18, 140, 114, 62, 133, 65, 255, 67, 48, 212, 35, 28, 138, 51, 201, 51, 246, 130, 175, 57, 97, 195, 92, 144, 36, 246, 116, 16, 96, 108, 66, 105, 178, 214, 148, 29, 23, 159, 49, 118, 42, 14, 161, 6, 195, 33, 102, 188, 243, 95, 83, 46, 183, 186, 60, 19, 210, 7, 219, 207, 153, 150, 116, 43, 110, 99, 149, 165, 112, 222, 47, 95, 231, 101, 153, 190, 159, 94, 73, 194, 130, 169, 58, 17, 155, 8, 177, 182, 249, 132, 142, 11, 150, 148, 170, 47, 70, 75, 99, 207, 162, 30, 94, 7, 65, 252, 61, 46, 127, 78, 170, 120, 124, 154, 76, 126, 154, 31, 31, 51, 53, 19, 19, 167, 172, 101, 70, 127, 191, 165, 150, 212, 196, 9, 139, 167, 18, 75, 47, 199, 88, 47, 43, 211, 93, 144, 251, 41, 247, 121, 168, 214, 252, 226, 36, 152, 3, 69, 152, 116, 28, 220, 26, 168, 76, 144, 5, 30, 235, 114, 108, 57, 102, 122, 108, 25, 17, 135, 22, 63, 125, 144, 171, 186, 152, 68, 158, 120, 219, 117, 96, 109, 227, 245, 225, 44, 78, 65, 109, 9, 48, 3, 13, 239, 237, 142, 175, 53, 40, 92, 211, 210, 142, 208, 47, 164, 10, 7, 135, 244, 142, 170, 209, 98, 129, 128, 197, 24, 175, 17, 190, 226, 95, 249, 2, 180, 164, 241, 45, 62, 165, 206, 213, 3, 39, 43, 111, 114, 47, 206, 242, 140, 173, 110, 166, 175, 226, 243, 164, 143, 65, 177, 149, 30, 71, 186, 236, 57, 11, 146, 103, 89, 85, 164, 237, 27, 219, 94, 115, 181, 42, 15, 85, 106, 89, 127, 203, 83, 31, 4, 122, 183, 188, 202, 198, 253, 24, 254, 207, 195, 199, 248, 54, 217, 113, 134, 205, 149, 1, 87, 135, 108, 97, 232, 183, 97, 246, 144, 10, 87, 235, 5, 14, 117, 111, 154, 151, 243, 130, 115, 20, 252, 140, 96, 105, 252, 20, 177, 9, 236, 199, 165, 25, 64, 21, 77, 174, 98, 11, 193, 200, 188, 42, 198, 140, 99, 188, 38, 230, 117, 144, 48, 123, 86, 196, 111, 242, 17, 15, 254, 82, 101, 109, 63, 223, 188, 100, 112, 119, 101, 215, 213, 100, 107, 72, 225, 137, 209, 141, 113, 97, 25, 169, 43, 176, 244, 193, 178, 212, 118, 228, 111, 208, 234, 178, 133, 222, 168, 182, 112, 160, 229, 85, 95, 220, 179, 235, 86, 112, 107, 214, 41, 199, 191, 12, 17, 69, 13, 149, 214, 108, 141, 73, 13, 111, 95, 39, 106, 73, 156, 218, 212, 69, 189, 28, 213, 147, 215, 223, 154, 69, 50, 99, 245, 251, 193, 6, 104, 23, 160, 222, 40, 68, 188, 238, 228, 51, 136, 125, 68, 140, 208, 102, 132, 193, 76, 106, 221, 17, 181, 205, 74, 99, 195, 247, 96, 115, 85, 135, 114, 219, 222, 155, 189, 65, 180, 7, 238, 160, 35, 61, 36, 100, 43, 13, 254, 129, 5, 29, 95, 196, 105, 37, 92, 68, 25, 211, 175, 194, 75, 8, 7, 5, 166, 211, 252, 66, 194, 4, 244, 192, 15, 99, 92, 200, 72, 247, 208, 113, 36, 61, 30, 132, 199, 88, 126, 33, 228, 119, 131, 9, 52, 70, 59, 100, 68, 165, 118, 161, 67, 215, 28, 134, 192, 53, 138, 86, 140, 3, 3, 157, 89, 197, 104, 68, 109, 80, 130, 66, 232, 157, 59, 248, 157, 2, 24, 224, 31, 12, 195, 25, 204, 242, 54, 127, 239, 74, 219, 4, 190, 171, 111, 102, 51, 217, 148, 228, 246, 43, 55, 184, 210, 179, 4, 47, 71, 16, 151, 238, 232, 146, 182, 1, 164, 42, 98, 67, 104, 113, 46, 19, 75, 50, 185, 102, 51, 65, 39, 6, 40, 98, 58, 233, 44, 80, 91, 151, 254, 45, 124, 65, 113, 141, 37, 218, 208, 119, 89, 68, 242, 130, 166, 236, 143, 178, 118, 27, 6, 208, 174, 237, 53, 93, 253, 17, 241, 104, 119, 28, 87, 107, 84, 197, 72, 161, 17, 149, 198, 54, 29, 209, 143, 200, 40, 178, 167, 225, 126, 192, 0, 224, 118, 220, 18, 166, 253, 198, 217, 188, 245, 92, 222, 228, 219, 30, 74, 100, 93, 191, 182, 68, 88, 161, 196, 53, 5, 154, 9, 210, 118, 83, 142, 84, 244, 118, 228, 57, 129, 166, 145, 245, 206, 10, 158, 25, 193, 51, 27, 216, 14, 251, 20, 207, 7, 31, 175, 37, 70, 88, 89, 91, 82, 163, 189, 248, 205, 42, 90, 114, 70, 168, 75, 109, 4, 168, 70, 116, 222, 88, 90, 19, 201, 141, 163, 171, 3, 162, 3, 177, 51, 254, 168, 46, 159, 246, 35, 146, 178, 82, 163, 247, 82, 173, 242, 218, 42, 188, 208, 56, 173, 72, 42, 52, 171, 188, 21, 209, 115, 87, 237, 117, 222, 148, 19, 92, 126, 134, 70, 191, 110, 144, 154, 134, 200, 209, 107, 84, 171, 181, 214, 105, 64, 112, 87, 125, 225, 216, 38, 170, 154, 152, 169, 196, 79, 16, 34, 111, 17, 167, 124, 208, 97, 42, 79, 88, 242, 66, 155, 255, 206, 211, 12, 137, 178, 255, 176, 164, 207, 79, 132, 142, 85, 84, 18, 131, 129, 128, 105, 31, 158, 244, 145, 13, 192, 155, 226, 110, 151, 94, 228, 172, 86, 34, 59, 54, 229, 63, 152, 124, 229, 51, 40, 131, 207, 64, 225, 222, 98, 29, 235, 99, 69, 123, 63, 210, 113, 145, 168, 147, 24, 61, 204, 247, 199, 105, 81, 86, 207, 166, 201, 185, 136, 87, 224, 144, 142, 182, 222, 170, 134, 14, 141, 35, 199, 57, 164, 138, 106, 106, 82, 30, 50, 24, 178, 1, 108, 254, 31, 114, 108, 101, 127, 37, 255, 120, 233, 134, 96, 110, 86, 132, 76, 3, 130, 170, 60, 154, 132, 123, 82, 38, 179, 88, 41, 248, 222, 160, 231, 136, 204, 48, 44, 50, 160, 102, 108, 26, 40, 185, 57, 140, 214, 159, 24, 216, 102, 181, 229, 153, 24, 16, 24, 164, 29, 57, 0, 187, 243, 254, 238, 35, 0, 78, 239, 49, 112, 101, 232, 26, 53, 135, 248, 241, 144, 48, 220, 87, 36, 116, 146, 248, 8, 4, 67, 5, 29, 23, 178, 206, 32, 234, 193, 62, 228, 145, 152, 35, 55, 229, 17, 208, 183, 174, 31, 131, 198, 97, 230, 69, 122, 2, 14, 116, 254, 137, 107, 54, 224, 77, 195, 217, 59, 136, 77, 185, 38, 96, 156, 186, 161, 89, 85, 171, 135, 45, 236, 104, 98, 36, 23, 42, 145, 0, 119, 14, 179, 98, 205, 137, 61, 114, 220, 209, 44, 107, 34, 237, 204, 90, 33, 240, 236, 67, 196, 202, 198, 241, 84, 53, 194, 97, 205, 202, 204, 172, 97, 239, 138, 188, 44, 15, 147, 120, 122, 46, 55, 158, 113, 145, 182, 72, 11, 240, 82, 207, 153, 106, 128, 208, 94, 227, 217, 97, 81, 125, 143, 19, 215, 148, 197, 136, 8, 159, 118, 207, 221, 125, 247, 34, 132, 215, 162, 123, 158, 117, 119, 115, 93, 213, 165, 189, 218, 35, 217, 181, 212, 88, 181, 169, 29, 50, 23, 31, 50, 214, 69, 99, 233, 57, 136, 173, 52, 120, 227, 172, 44, 112, 112, 172, 230, 105, 92, 193, 177, 3, 62, 197, 21, 170, 86, 171, 96, 18, 113, 24, 241, 69, 67, 72, 137, 101, 26, 163, 70, 186, 196, 127, 216, 53, 109, 99, 249, 115, 70, 105, 3, 9, 25, 201, 247, 179, 74, 236, 232, 128, 209, 112, 48, 48, 228, 225, 78, 241, 161, 221, 7, 102, 144, 224, 237, 38, 143, 213, 0, 112, 251, 75, 26, 9, 40, 53, 73, 102, 213, 233, 171, 249, 57, 159, 71, 86, 66, 1, 63, 76, 236, 49, 209, 152, 58, 243, 250, 94, 16, 48, 179, 237, 73, 43, 146, 65, 250, 68, 100, 86, 104, 133, 73, 235, 128, 97, 5, 101, 16, 13, 123, 146, 7, 186, 245, 19, 192, 133, 31, 124, 83, 120, 69, 118, 27, 30, 172, 193, 92, 137, 212, 122, 109, 197, 12, 152, 0, 187, 47, 247, 171, 56, 12, 50, 163, 139, 38, 212, 119, 102, 14, 227, 23, 143, 13, 6, 228, 3, 13, 79, 194, 53, 210, 140, 156, 59, 86, 134, 65, 162, 141, 2, 241, 245, 8, 213, 33, 94, 73, 75, 198, 144, 19, 105, 199, 56, 104, 12, 180, 218, 80, 74, 31, 129, 212, 63, 229, 102, 64, 175, 36, 84, 252, 10, 97, 233, 190, 214, 47, 44, 127, 173, 20, 135, 211, 124, 62, 157, 200, 129, 166, 113, 175, 162, 167, 124, 20, 105, 72, 70, 228, 212, 82, 19, 181, 196, 205, 105, 137, 147, 31, 215, 177, 93, 118, 178, 162, 37, 150, 242, 45, 245, 48, 113, 178, 16, 110, 241, 177, 41, 45, 217, 64, 63, 211, 250, 192, 169, 234, 80, 85, 16, 100, 35, 26, 122, 8, 107, 199, 158, 64, 191, 49, 174, 16, 133, 123, 57, 60, 198, 255, 106, 125, 199, 223, 253, 245, 59, 143, 155, 184, 246, 60, 55, 198, 58, 178, 199, 131, 116, 202, 4, 187, 248, 207, 240, 154, 146, 174, 190, 221, 173, 196, 102, 231, 50, 35, 90, 212, 112, 26, 29, 153, 202, 136, 62, 185, 208, 85, 138, 152, 86, 120, 138, 150, 60, 96, 247, 147, 175, 206, 202, 68, 69, 164, 175, 123, 202, 173, 168, 168, 232, 199, 209, 22, 184, 214, 207, 172, 173, 220, 80, 102, 30, 21, 19, 194, 215, 16, 45, 246, 34, 119, 43, 199, 152, 126, 147, 31, 194, 209, 243, 50, 153, 244, 151, 65, 210, 93, 25, 137, 182, 152, 71, 65, 70, 156, 137, 120, 181, 51, 19, 83, 166, 190, 153, 40, 96, 20, 121, 21, 116, 8, 232, 26, 182, 25, 230, 95, 252, 231, 69, 197, 136, 0, 22, 77, 92, 36, 199, 146, 246, 60, 186, 84, 189, 178, 246, 64, 44, 151, 162, 169, 25, 48, 153, 254, 66, 230, 218, 197, 105, 204, 221, 45, 11, 211, 217, 67, 46, 233, 117, 59, 19, 97, 178, 196, 6, 6, 92, 30, 147, 141, 123, 21, 119, 115, 94, 90, 84, 117, 188, 26, 28, 183, 119, 101, 14, 145, 90, 178, 9, 67, 35, 127, 32, 253, 139, 184, 172, 110, 109, 180, 52, 32, 247, 105, 34, 166, 141, 27, 124, 9, 113, 211, 234, 24, 140, 239, 44, 198, 226, 177, 245, 238, 54, 196, 205, 71, 216, 195, 0, 120, 163, 236, 225, 195, 237, 142, 180, 215, 24, 222, 51, 6, 234, 194, 41, 55, 26, 131, 175, 9, 76, 24, 4, 118, 163, 84, 89, 30, 9, 248, 33, 158, 34, 223, 16, 138, 230, 57, 79, 126, 73, 50, 18, 191, 194, 138, 178, 193, 4, 111, 88, 207, 210, 86, 24, 42, 31, 163, 238, 96, 249, 241, 42, 31, 92, 181, 235, 177, 63, 97, 228, 76, 153, 114, 246, 122, 210, 104, 29, 221, 196, 114, 187, 168, 75, 47, 187, 143, 186, 248, 33, 7, 210, 29, 178, 40, 34, 64, 139, 72, 31, 63, 17, 97, 35, 50, 209, 17, 164, 34, 255, 227, 64, 68, 65, 218, 193, 177, 106, 187, 14, 149, 220, 52, 209, 165, 202, 94, 132, 102, 69, 0, 39, 42, 189, 105, 114, 49, 5, 252, 181, 184, 226, 26, 214, 189, 58, 54, 51, 188, 237, 139, 235, 14, 116, 155, 248, 240, 158, 246, 218, 9, 104, 225, 45, 64, 72, 30, 104, 43, 16, 85, 199, 43, 127, 50, 0, 217, 74, 17, 39, 81, 248, 57, 45, 116, 212, 236, 31, 43, 54, 46, 34, 80, 214, 175, 39, 61, 104, 240, 226, 88, 131, 1, 83, 106, 74, 67, 198, 69, 120, 225, 115, 87, 153, 130, 93, 244, 38, 174, 101, 217, 49, 82, 177, 201, 94, 62, 130, 198, 197, 42, 204, 212, 17, 191, 81, 236, 44, 188, 248, 104, 19, 138, 176, 162, 160, 150, 8, 23, 45, 22, 36, 154, 10, 214, 190, 33, 26, 161, 82, 94, 146, 180, 136, 78, 123, 20, 16, 68, 153, 166, 212, 81, 251, 106, 171, 137, 181, 102, 104, 220, 71, 2, 138, 202, 134, 246, 49, 148, 104, 240, 24, 212, 15, 120, 87, 86, 128, 20, 10, 162, 208, 170, 102, 110, 185, 94, 44, 169, 6, 58, 26, 129, 70, 66, 214, 74, 168, 27, 240, 165, 194, 236, 96, 108, 86, 218, 138, 240, 146, 201, 32, 40, 87, 22, 21, 33, 23, 178, 119, 31, 195, 19, 200, 223, 147, 41, 227, 180, 87, 22, 61, 149, 61, 228, 143, 128, 63, 16, 241, 239, 7, 40, 250, 221, 5, 217, 63, 88, 32, 2, 222, 5, 211, 34, 14, 94, 28, 107, 145, 63, 122, 129, 222, 121, 66, 227, 79, 212, 164, 17, 12, 64, 231, 117, 14, 4, 104, 56, 224, 129, 61, 145, 164, 15, 251, 16, 51, 155, 149, 233, 216, 157, 104, 7, 166, 29, 51, 138, 245, 163, 113, 232, 48, 225, 253, 26, 15, 209, 191, 207, 50, 34, 162, 233, 5, 198, 68, 27, 55, 247, 115, 72, 120, 247, 62, 203, 136, 240, 150, 59, 13, 136, 217, 226, 114, 143, 46, 69, 79, 60, 182, 135, 94, 204, 249, 247, 176, 186, 239, 93, 81, 27, 36, 37, 148, 148, 199, 162, 60, 163, 173, 215, 147, 152, 168, 118, 207, 140, 37, 171, 186, 164, 27, 133, 234, 11, 104, 157, 154, 67, 83, 196, 132, 17, 88, 202, 129, 20, 127, 52, 12, 107, 92, 105, 21, 215, 188, 254, 182, 75, 183, 244, 24, 78, 217, 218, 76, 251, 1, 132, 225, 146, 76, 184, 109, 142, 206, 155, 152, 244, 194, 87, 105, 50, 149, 161, 211, 184, 32, 218, 32, 224, 203, 83, 52, 133, 131, 25, 160, 141, 104, 114, 242, 203, 32, 165, 145, 208, 115, 237, 42, 84, 227, 199, 94, 212, 155, 110, 112, 132, 80, 17, 91, 66, 157, 23, 225, 144, 63, 224, 120, 50, 95, 151, 225, 159, 6, 199, 222, 243, 142, 135, 162, 163, 96, 8, 113, 168, 36, 181, 27, 2, 132, 18, 135, 137, 248, 1, 195, 169, 34, 47, 200, 138, 46, 110, 208, 15, 46, 156, 146, 9, 89, 28, 132, 132, 87, 38, 36, 147, 89, 118, 175, 45, 193, 26, 78, 7, 25, 54, 117, 110, 70, 138, 69, 23, 125, 28, 175, 91, 190, 179, 162, 220, 162, 111, 95, 228, 185, 133, 60, 243, 243, 147, 193, 197, 188, 162, 165, 71, 146, 241, 10, 194, 85, 10, 164, 237, 143, 30, 28, 62, 143, 208, 191, 137, 207, 146, 254, 52, 61, 79, 171, 174, 242, 46, 86, 94, 231, 113, 154, 137, 16, 110, 179, 247, 38, 192, 41, 157, 96, 202, 60, 182, 28, 175, 135, 113, 118, 162, 78, 81, 254, 245, 135, 27, 18, 121, 232, 160, 79, 40, 52, 90, 119, 87, 226, 155, 187, 118, 195, 2, 191, 131, 24, 224, 41, 248, 149, 245, 79, 227, 95, 190, 142, 62, 16, 60, 47, 85, 130, 103, 129, 30, 60, 166, 181, 172, 153, 60, 88, 109, 233, 194, 138, 244, 137, 223, 147, 215, 186, 110, 72, 210, 127, 46, 242, 217, 189, 150, 116, 232, 224, 61, 149, 244, 230, 174, 233, 33, 189, 117, 130, 221, 86, 154, 169, 12, 155, 179, 44, 68, 117, 221, 43, 75, 227, 115, 234, 155, 86, 198, 193, 110, 201, 55, 228, 146, 201, 235, 56, 45, 202, 254, 34, 122, 99, 121, 226, 77, 145, 113, 165, 225, 238, 74, 119, 99, 207, 150, 38, 220, 75, 151, 167, 1, 186, 175, 100, 73, 162, 53, 80, 87, 156, 220, 144, 140, 169, 20, 19, 188, 250, 219, 219, 35, 108, 52, 68, 252, 190, 249, 207, 100, 239, 238, 163, 15, 173, 185, 107, 203, 157, 156, 23, 155, 125, 23, 17, 203, 229, 76, 115, 230, 56, 97, 237, 54, 121, 163, 135, 204, 74, 23, 192, 239, 14, 10, 30, 70, 21, 224, 232, 182, 158, 144, 127, 83, 239, 115, 174, 198, 235, 130, 30, 100, 230, 117, 145, 111, 185, 136, 66, 170, 160, 102, 119, 58, 168, 22, 36, 204, 46, 122, 65, 87, 193, 138, 161, 85, 42, 102, 146, 48, 200, 97, 87, 31, 15, 168, 14, 242, 125, 112, 147, 139, 204, 27, 43, 1, 69, 186, 69, 74, 136, 26, 102, 28, 130, 38, 169, 13, 235, 1, 169, 68, 83, 29, 83, 57, 32, 1, 195, 141, 249, 167, 87, 28, 166, 254, 16, 228, 103, 77, 139, 53, 47, 244, 48, 77, 101, 159, 228, 48, 170, 157, 38, 39, 225, 178, 39, 221, 50, 71, 70, 168, 0, 133, 174, 63, 159, 114, 29, 51, 203, 252, 107, 126, 227, 241, 143, 118, 33, 9, 34, 11, 16, 48, 181, 216, 59, 199, 49, 180, 71, 250, 0, 42, 177, 68, 22, 167, 107, 56, 188, 86, 218, 37, 88, 47, 33, 154, 164, 34, 162, 182, 158, 26, 234, 6, 34, 21, 157, 188, 28, 169, 238, 150, 113, 29, 103, 65, 184, 6, 251, 133, 93, 164, 89, 64, 137, 55, 233, 61, 126, 119, 215, 221, 167, 76, 131, 3, 217, 71, 29, 55, 172, 166, 8, 196, 220, 234, 27, 176, 234, 8, 41, 110, 201, 187, 31, 148, 92, 237, 76, 75, 135, 152, 246, 92, 190, 98, 145, 185, 65, 100, 33, 61, 252, 253, 160, 229, 117, 185, 18, 153, 123, 206, 90, 134, 227, 239, 201, 192, 208, 148, 175, 51, 64, 136, 7, 131, 168, 199, 159, 122, 16, 135, 42, 193, 246, 84, 110, 60, 122, 65, 114, 22, 159, 39, 42, 126, 142, 61, 194, 39, 249, 74, 252, 177, 178, 200, 74, 184, 60, 147, 172, 68, 23, 202, 233, 53, 204, 121, 121, 34, 161, 157, 39, 101, 25, 159, 112, 128, 226, 37, 255, 191, 13, 142, 64, 98, 37, 244, 144, 235, 214, 123, 61, 43, 132, 132, 149, 82, 29, 224, 71, 2, 37, 88, 167, 156, 234, 14, 98, 89, 14, 116, 61, 234, 61, 138, 122, 236, 15, 7, 20, 26, 5, 72, 200, 242, 166, 136, 211, 41, 123, 102, 11, 55, 246, 39, 161, 193, 200, 141, 215, 0, 19, 112, 34, 16, 124, 192, 102, 220, 53, 64, 224, 255, 101, 61, 43, 94, 210, 27, 195, 44, 71, 124, 52, 47, 103, 9, 163, 218, 132, 198, 3, 219, 57, 113, 112, 140, 63, 132, 233, 176, 87, 186, 2, 254, 230, 141, 45, 116, 207, 71, 130, 196, 233, 250, 129, 96, 28, 26, 142, 195, 173, 30, 243, 163, 71, 122, 213, 147, 239, 29, 27, 210, 194, 145, 137, 58, 216, 254, 147, 0, 174, 225, 52, 174, 160, 143, 116, 120, 160, 11, 125, 191, 60, 156, 103, 224, 133, 181, 1, 91, 194, 243, 240, 123, 107, 15, 193, 172, 49, 59, 68, 147, 71, 158, 219, 157, 249, 48, 181, 236, 173, 46, 6, 89, 35, 80, 9, 220, 61, 113, 73, 73, 162, 172, 3, 151, 153, 172, 200, 245, 251, 194, 77, 40, 168, 107, 113, 118, 18, 196, 99, 45, 124, 102, 134, 209, 199, 4, 110, 5, 199, 216, 71, 18, 238, 11, 203, 224, 208, 204, 229, 169, 32, 62, 130, 159, 74, 249, 240, 141, 196, 15, 144, 166, 189, 17, 129, 90, 182, 43, 236, 67, 36, 159, 147, 241, 96, 47, 180, 152, 49, 92, 208, 72, 1, 210, 253, 19, 72, 150, 192, 49, 53, 185, 220, 153, 253, 6, 167, 237, 101, 13, 229, 57, 229, 71, 135, 85, 90, 100, 169, 127, 235, 197, 207, 192, 198, 234, 218, 1, 37, 37, 179, 53, 44, 44, 201, 43, 245, 167, 121, 80, 45, 124, 152, 199, 144, 69, 154, 196, 45, 143, 65, 121, 252, 143, 193, 243, 62, 234, 204, 13, 239, 148, 235, 118, 122, 28, 109, 203, 97, 245, 39, 42, 163, 208, 55, 241, 9, 4, 235, 147, 250, 105, 242, 152, 213, 102, 99, 8, 3, 14, 21, 81, 63, 137, 240, 207, 85, 222, 5, 188, 118, 240, 31, 16, 242, 56, 189, 100, 9, 203, 106, 52, 233, 174, 125, 7, 129, 68, 246, 239, 180, 228, 107, 153, 65, 116, 46, 78, 68, 24, 237, 137, 95, 200, 68, 222, 162, 172, 145, 160, 115, 117, 250, 130, 129, 149, 103, 69, 56, 208, 70, 247, 14, 217, 30, 182, 90, 82, 58, 3, 106, 188, 108, 221, 64, 234, 194, 54, 96, 246, 201, 0, 208, 61, 21, 1, 80, 28, 7, 66, 109, 34, 40, 52, 101, 54, 63, 69, 88, 228, 231, 56, 177, 108, 223, 109, 196, 140, 178, 7, 3, 196, 37, 214, 17, 18, 43, 35, 68, 123, 2, 59, 253, 87, 138, 216, 58, 43, 231, 117, 194, 155, 131, 45, 30, 238, 211, 242, 16, 224, 63, 200, 80, 201, 215, 123, 50, 112, 30, 86, 71, 240, 23, 86, 72, 112, 144, 150, 45, 84, 107, 79, 64, 41, 248, 250, 24, 20, 198, 88, 143, 152, 104, 250, 221, 59, 126, 62, 247, 221, 187, 71, 188, 41, 33, 65, 84, 158, 154, 143, 123, 57, 91, 62, 162, 145, 144, 156, 200, 108, 33, 124, 13, 207, 137, 95, 36, 64, 23, 177, 60, 194, 201, 248, 194, 203, 92, 17, 39, 131, 106, 129, 145, 97, 104, 195, 19, 20, 244, 74, 177, 218, 173, 117, 110, 183, 164, 51, 29, 253, 115, 116, 70, 170, 57, 169, 41, 166, 190, 234, 149, 123, 138, 234, 156, 158, 159, 66, 12, 198, 26, 17, 83, 51, 190, 102, 177, 27, 255, 125, 236, 204, 131, 64, 27, 211, 72, 152, 64, 26, 142, 235, 198, 45, 148, 95, 219, 153, 157, 120, 242, 219, 3, 239, 201, 211, 0, 155, 28, 72, 133, 162, 189, 11, 205, 12, 127, 26, 151, 251, 89, 89, 197, 217, 88, 101, 146, 166, 83, 13, 202, 55, 153, 150, 175, 213, 33, 245, 131, 99, 193, 228, 102, 84, 245, 167, 126, 207, 168, 91, 42, 39, 43, 104, 146, 65, 205, 90, 6, 3, 230, 1, 197, 73, 23, 194, 199, 37, 182, 132, 193, 160, 125, 158, 195, 166, 90, 58, 209, 138, 176, 105, 99, 86, 66, 32, 59, 178, 54, 94, 109, 171, 15, 109, 129, 95, 161, 59, 186, 178, 48, 25, 83, 31, 210, 214, 93, 51, 93, 14, 17, 121, 105, 176, 192, 41, 34, 31, 156, 54, 55, 206, 132, 186, 227, 57, 57, 132, 184, 214, 127, 112, 232, 0, 223, 62, 67, 24, 54, 88, 126, 104, 31, 46, 170, 59, 232, 137, 100, 175, 97, 64, 228, 98, 238, 254, 12, 73, 240, 128, 93, 251, 65, 209, 233, 94, 219, 157, 102, 111, 121, 238, 149, 28, 20, 142, 92, 15, 149, 124, 143, 78, 179, 138, 217, 197, 82, 159, 157, 14, 192, 123, 52, 44, 58, 244, 186, 216, 160, 91, 145, 41, 11, 12, 55, 133, 208, 102, 160, 93, 228, 23, 58, 175, 167, 71, 216, 135, 96, 248, 228, 106, 32, 248, 151, 34, 117, 45, 65, 250, 252, 52, 189, 198, 185, 212, 118, 84, 245, 156, 62, 109, 160, 107, 56, 86, 139, 35, 227, 167, 237, 141, 89, 47, 55, 19, 255, 213, 108, 172, 232, 252, 23, 204, 12, 104, 19, 20, 134, 168, 103, 7, 76, 1, 205, 241, 44, 129, 226, 194, 106, 236, 0, 129, 64, 125, 92, 87, 43, 65, 194, 60, 226, 46, 151, 191, 93, 0, 115, 195, 22, 165, 96, 175, 61, 70, 240, 105, 194, 185, 168, 33, 254, 203, 91, 67, 239, 99, 250, 162, 145, 220, 26, 102, 249, 224, 139, 72, 210, 25, 72, 240, 250, 128, 95, 93, 201, 173, 58, 29, 68, 81, 191, 207, 8, 91, 76, 196, 101, 67, 19, 115, 32, 191, 159, 142, 0, 235, 18, 251, 53, 80, 24, 73, 92, 69, 4, 151, 0, 37, 222, 40, 140, 215, 101, 182, 213, 143, 94, 179, 93, 156, 108, 52, 169, 150, 110, 161, 192, 46, 51, 121, 212, 205, 137, 173, 255, 144, 161, 205, 255, 6, 173, 219, 38, 188, 93, 241, 255, 34, 194, 72, 132, 203, 100, 202, 68, 34, 40, 196, 40, 99, 88, 147, 28, 243, 164, 174, 18, 154, 233, 163, 115, 6, 226, 99, 123, 17, 15, 159, 99, 252, 28, 194, 45, 194, 209, 248, 25, 169, 23, 128, 83, 132, 110, 119, 102, 76, 147, 141, 173, 147, 83, 171, 125, 82, 154, 231, 37, 109, 123, 128, 234, 230, 132, 221, 119, 190, 208, 22, 21, 140, 247, 173, 147, 246, 54, 29, 240, 28, 161, 186, 19, 178, 78, 15, 220, 145, 172, 134, 181, 245, 205, 226, 80, 197, 19, 45, 67, 61, 56, 162, 11, 232, 109, 108, 4, 16, 140, 162, 247, 69, 18, 147, 140, 129, 30, 145, 14, 31, 88, 252, 34, 210, 139, 138, 180, 239, 32, 225, 157, 18, 233, 54, 29, 184, 171, 34, 189, 44, 97, 36, 170, 97, 99, 3, 210, 255, 110, 53, 204, 178, 126, 179, 185, 246, 68, 210, 109, 48, 154, 111, 251, 42, 55, 112, 52, 232, 142, 172, 116, 187, 97, 127, 183, 100, 237, 46, 172, 118, 245, 41, 167, 125, 35, 112, 129, 109, 38, 209, 222, 128, 147, 57, 84, 251, 21, 97, 115, 252, 69, 243, 58, 34, 66, 253, 241, 42, 67, 9, 12, 103, 16, 106, 112, 205, 86, 63, 246, 33, 172, 14, 150, 126, 195, 233, 168, 219, 160, 150, 150, 117, 202, 170, 89, 49, 89, 231, 176, 16, 87, 171, 238, 55, 28, 203, 50, 50, 176, 33, 72, 222, 229, 0, 83, 100, 139, 208, 178, 103, 49, 5, 254, 49, 158, 192, 40, 86, 228, 8, 162, 65, 71, 221, 129, 74, 131, 40, 104, 85, 255, 94, 133, 56, 38, 133, 133, 19, 31, 141, 178, 36, 117, 125, 221, 99, 150, 123, 176, 246, 159, 40, 11, 159, 168, 114, 215, 183, 129, 99, 84, 159, 203, 20, 174, 103, 77, 217, 169, 163, 205, 205, 205, 110, 131, 255, 214, 191, 237, 30, 60, 53, 117, 27, 164, 125, 241, 211, 28, 237, 100, 252, 134, 166, 169, 182, 199, 64, 108, 94, 247, 42, 101, 126, 116, 235, 139, 127, 245, 166, 199, 172, 69, 178, 254, 186, 225, 91, 224, 152, 153, 51, 210, 226, 108, 217, 151, 161, 254, 20, 67, 189, 186, 204, 177, 110, 62, 5, 231, 217, 55, 201, 38, 95, 134, 250, 206, 73, 117, 221, 218, 158, 173, 231, 208, 149, 152, 251, 89, 42, 113, 99, 196, 52, 227, 203, 86, 19, 104, 104, 185, 157, 57, 153, 240, 126, 179, 47, 155, 101, 226, 77, 81, 207, 139, 212, 13, 131, 28, 83, 81, 206, 177, 22, 129, 46, 140, 100, 231, 225, 211, 140, 128, 162, 255, 180, 134, 170, 91, 115, 40, 225, 187, 65, 212, 99, 125, 239, 145, 144, 126, 31, 209, 57, 122, 124, 81, 59, 208, 56, 29, 109, 189, 69, 63, 134, 111, 221, 121, 240, 37, 143, 244, 225, 70, 10, 0, 125, 31, 143, 207, 96, 46, 53, 183, 184, 88, 55, 59, 66, 143, 95, 6, 197, 231, 165, 136, 192, 120, 105, 34, 48, 24, 124, 253, 173, 115, 240, 5, 171, 220, 34, 226, 2, 225, 141, 190, 162, 27, 4, 123, 166, 147, 86, 32, 134, 205, 10, 6, 84, 23, 177, 196, 181, 176, 92, 38, 144, 7, 38, 41, 237, 88, 72, 225, 125, 157, 189, 147, 159, 7, 209, 75, 115, 130, 51, 158, 9, 21, 198, 202, 29, 114, 7, 7, 100, 86, 98, 0, 78, 166, 249, 251, 24, 232, 225, 249, 12, 149, 47, 78, 25, 58, 81, 159, 175, 162, 209, 106, 30, 130, 158, 196, 2, 136, 47, 105, 227, 217, 51, 214, 230, 21, 163, 133, 82, 148, 125, 141, 132, 191, 105, 180, 237, 69, 51, 77, 88, 126, 112, 209, 220, 89, 114, 37, 68, 205, 3, 73, 94, 184, 77, 115, 177, 4, 138, 14, 101, 209, 32, 164, 72, 176, 81, 109, 169, 33, 45, 229, 19, 25, 15, 199, 107, 53, 197, 250, 162, 70, 6, 4, 134, 59, 202, 106, 6, 129, 181, 37, 130, 235, 253, 159, 193, 219, 134, 101, 14, 123, 26, 22, 140, 109, 66, 80, 22, 9, 108, 66, 213, 219, 68, 53, 89, 56, 123, 2, 154, 22, 230, 93, 25, 17, 248, 79, 122, 188, 170, 230, 136, 105, 59, 206, 62, 168, 229, 105, 78, 93, 204, 210, 42, 53, 199, 175, 252, 12, 146, 9, 201, 218, 207, 170, 7, 219, 16, 62, 237, 15, 28, 197, 110, 86, 35, 43, 6, 16, 221, 61, 210, 238, 216, 6, 25, 145, 171, 127, 7, 212, 176, 61, 168, 33, 5, 165, 170, 233, 171, 90, 117, 253, 163, 32, 46, 33, 2, 50, 216, 111, 177, 232, 47, 83, 76, 5, 35, 108, 42, 5, 129, 9, 43, 63, 201, 145, 55, 94, 214, 21, 228, 19, 134, 18, 244, 110, 120, 198, 26, 29, 111, 134, 55, 53, 218, 220, 11, 15, 126, 230, 34, 159, 207, 126, 210, 217, 86, 208, 116, 160, 79, 34, 185, 177, 172, 188, 112, 104, 150, 145, 99, 244, 221, 67, 37, 127, 246, 148, 35, 106, 171, 175, 169, 72, 41, 227, 49, 71, 123, 90, 140, 150, 63, 243, 13, 195, 51, 223, 94, 20, 188, 140, 93, 219, 50, 198, 94, 203, 146, 139, 104, 207, 236, 71, 156, 181, 55, 83, 45, 42, 238, 24, 137, 20, 83, 81, 147, 210, 119, 173, 211, 51, 36, 213, 242, 38, 217, 224, 4, 206, 239, 158, 229, 246, 22, 107, 13, 205, 148, 166, 158, 239, 102, 236, 200, 15, 172, 196, 192, 6, 209, 145, 200, 242, 183, 230, 21, 98, 79, 166, 31, 213, 166, 190, 255, 182, 148, 55, 10, 90, 23, 19, 241, 255, 159, 33, 71, 181, 73, 237, 16, 207, 136, 228, 188, 154, 159, 191, 79, 138, 119, 105, 201, 22, 83, 140, 204, 253, 108, 126, 110, 248, 89, 154, 196, 236, 157, 56, 248, 147, 241, 194, 246, 129, 77, 159, 140, 66, 149, 13, 254, 127, 174, 27, 253, 77, 190, 138, 95, 45, 179, 189, 85, 46, 25, 231, 254, 182, 84, 74, 96, 1, 210, 215, 36, 123, 221, 186, 85, 180, 219, 238, 110, 180, 203, 38, 118, 8, 118, 0, 125, 195, 212, 9, 19, 101, 196, 38, 164, 207, 131, 44, 207, 9, 98, 99, 186, 138, 167, 182, 154, 1, 216, 232, 247, 183, 163, 111, 191, 141, 190, 123, 176, 6, 119, 57, 174, 193, 174, 174, 130, 241, 245, 215, 250, 145, 189, 37, 229, 232, 81, 54, 110, 66, 24, 198, 208, 125, 151, 109, 16, 198, 121, 147, 139, 159, 170, 224, 154, 31, 148, 97, 235, 32, 52, 89, 164, 30, 160, 48, 208, 152, 182, 59, 184, 200, 148, 56, 254, 156, 148, 227, 34, 157, 49, 133, 87, 226, 83, 87, 34, 165, 140, 190, 16, 244, 192, 168, 188, 228, 74, 93, 171, 123, 152, 28, 67, 120, 217, 187, 252, 34, 251, 149, 189, 237, 171, 3, 101, 220, 232, 49, 96, 193, 84, 250, 72, 148, 164, 206, 34, 54, 144, 151, 139, 2, 80, 169, 4, 118, 228, 87, 121, 39, 111, 74, 47, 138, 55, 250, 18, 170, 136, 52, 163, 200, 88, 135, 86, 217, 183, 250, 126, 138, 99, 133, 84, 15, 74, 166, 228, 245, 57, 75, 154, 201, 104, 173, 78, 151, 161, 110, 74, 109, 8, 111, 172, 253, 10, 57, 86, 168, 172, 127, 84, 208, 57, 51, 115, 247, 157, 172, 140, 233, 125, 66, 139, 234, 65, 146, 215, 3, 58, 160, 247, 203, 103, 151, 108, 94, 41, 83, 121, 166, 146, 0, 38, 39, 40, 129, 203, 113, 75, 169, 93, 211, 3, 253, 93, 149, 191, 200, 217, 60, 145, 56, 105, 137, 240, 18, 161, 230, 232, 202, 193, 102, 165, 179, 223, 28, 120, 91, 224, 211, 2, 235, 41, 65, 220, 190, 172, 214, 173, 118, 26, 151, 136, 1, 250, 255, 36, 213, 197, 199, 254, 63, 197, 114, 138, 214, 255, 74, 0, 224, 68, 102, 227, 2, 179, 119, 231, 193, 16, 217, 15, 252, 102, 155, 3, 94, 90, 111, 250, 188, 45, 49, 219, 112, 241, 145, 192, 134, 23, 35, 40, 57, 19, 181, 164, 65, 41, 209, 83, 137, 133, 68, 205, 70, 180, 70, 10, 173, 50, 136, 150, 40, 45, 100, 66, 162, 5, 121, 147, 6, 81, 201, 127, 16, 85, 194, 10, 70, 190, 235, 133, 109, 211, 78, 86, 13, 152, 117, 15, 30, 8, 132, 42, 152, 43, 240, 196, 32, 52, 130, 158, 89, 32, 123, 19, 62, 227, 11, 92, 237, 124, 147, 115, 142, 247, 91, 201, 141, 232, 30, 179, 78, 223, 228, 138, 125, 152, 134, 19, 41, 172, 152, 169, 170, 83, 89, 137, 222, 107, 14, 227, 72, 139, 238, 10, 123, 23, 52, 2, 127, 216, 186, 220, 222, 218, 138, 254, 100, 127, 183, 134, 226, 207, 182, 60, 78, 169, 207, 85, 139, 142, 137, 103, 88, 64, 174, 112, 19, 216, 225, 106, 209, 228, 47, 152, 224, 39, 139, 19, 252, 164, 153, 224, 39, 247, 139, 224, 39, 136, 204, 134, 248, 53, 4, 127, 145, 231, 103, 243, 25, 226, 240, 86, 132, 254, 172, 84, 154, 228, 216, 177, 38, 230, 196, 208, 108, 168, 54, 189, 37, 21, 173, 121, 145, 207, 102, 122, 2, 84, 111, 96, 189, 252, 181, 32, 49, 78, 35, 129, 230, 185, 163, 109, 157, 245, 91, 101, 254, 245, 223, 39, 242, 17, 13, 161, 101, 86, 156, 56, 51, 34, 123, 43, 216, 80, 57, 17, 101, 189, 85, 229, 79, 10, 14, 223, 47, 95, 134, 175, 211, 240, 13, 111, 203, 240, 213, 27, 113, 51, 67, 70, 51, 172, 237, 41, 70, 1, 24, 95, 27, 162, 154, 175, 219, 58, 65, 115, 85, 21, 229, 110, 54, 145, 126, 56, 73, 90, 5, 134, 124, 5, 114, 15, 183, 236, 53, 136, 162, 189, 244, 35, 74, 202, 43, 87, 201, 69, 145, 86, 160, 164, 31, 69, 171, 171, 46, 180, 173, 135, 218, 167, 146, 48, 174, 19, 123, 55, 129, 162, 67, 93, 116, 156, 103, 199, 233, 201, 188, 174, 240, 246, 154, 117, 234, 24, 103, 40, 250, 67, 233, 80, 11, 219, 82, 191, 217, 150, 111, 90, 35, 213, 26, 165, 143, 30, 246, 56, 40, 36, 187, 89, 19, 131, 61, 184, 3, 62, 88, 233, 251, 121, 5, 174, 50, 144, 224, 113, 101, 150, 164, 203, 185, 144, 27, 53, 135, 244, 6, 126, 27, 80, 31, 78, 17, 87, 139, 184, 80, 2, 202, 132, 72, 196, 35, 63, 127, 235, 222, 26, 154, 52, 121, 247, 126, 240, 122, 247, 182, 49, 89, 101, 34, 123, 71, 64, 148, 139, 76, 166, 221, 80, 23, 69, 232, 245, 183, 246, 154, 169, 31, 98, 134, 70, 174, 86, 113, 46, 202, 122, 9, 61, 233, 25, 38, 235, 177, 149, 34, 70, 70, 69, 215, 113, 12, 254, 124, 130, 62, 109, 154, 74, 140, 122, 220, 62, 120, 4, 127, 126, 192, 254, 198, 30, 230, 202, 14, 176, 113, 53, 1, 125, 155, 67, 31, 110, 17, 232, 34, 193, 106, 3, 88, 174, 49, 212, 218, 86, 16, 13, 181, 132, 54, 160, 17, 85, 85, 176, 137, 110, 73, 41, 145, 14, 141, 249, 250, 165, 192, 136, 62, 61, 228, 125, 218, 166, 125, 98, 195, 214, 220, 200, 182, 106, 68, 15, 50, 106, 228, 36, 65, 251, 18, 30, 43, 21, 228, 65, 214, 91, 245, 187, 43, 45, 238, 253, 254, 7, 97, 191, 246, 172, 5, 57, 199, 183, 236, 132, 111, 233, 193, 183, 12, 225, 91, 26, 124, 203, 206, 248, 150, 126, 124, 5, 82, 214, 180, 77, 63, 12, 241, 124, 110, 131, 222, 38, 110, 85, 169, 206, 91, 105, 205, 82, 173, 48, 212, 210, 78, 43, 80, 60, 254, 138, 9, 49, 106, 88, 207, 170, 119, 218, 220, 208, 136, 247, 145, 141, 46, 254, 60, 20, 123, 132, 166, 168, 167, 132, 252, 136, 13, 24, 143, 127, 198, 237, 17, 189, 239, 194, 19, 165, 165, 115, 131, 45, 66, 40, 233, 154, 231, 11, 11, 155, 74, 29, 65, 33, 135, 63, 122, 212, 48, 3, 11, 195, 86, 51, 32, 154, 249, 174, 51, 141, 242, 45, 124, 203, 164, 81, 234, 25, 117, 152, 167, 168, 114, 208, 133, 125, 202, 103, 98, 71, 159, 135, 158, 216, 174, 71, 203, 101, 56, 131, 13, 218, 80, 216, 74, 32, 100, 5, 234, 52, 132, 171, 136, 146, 155, 199, 6, 25, 26, 189, 18, 100, 41, 181, 237, 56, 19, 27, 131, 246, 32, 251, 251, 252, 119, 225, 115, 58, 24, 68, 175, 27, 60, 173, 212, 73, 245, 90, 37, 235, 114, 205, 227, 47, 251, 121, 214, 126, 158, 32, 39, 242, 128, 141, 121, 172, 67, 95, 46, 48, 110, 209, 190, 29, 93, 95, 158, 133, 237, 195, 179, 176, 93, 120, 214, 100, 15, 158, 9, 59, 208, 44, 11, 173, 221, 66, 72, 82, 199, 62, 190, 53, 19, 89, 211, 150, 96, 72, 36, 62, 211, 94, 160, 45, 105, 12, 244, 121, 90, 38, 239, 228, 121, 166, 126, 158, 61, 23, 79, 70, 226, 102, 162, 72, 48, 128, 69, 126, 175, 75, 155, 47, 91, 129, 100, 249, 178, 161, 64, 222, 124, 216, 94, 150, 91, 244, 120, 111, 89, 54, 49, 8, 109, 61, 43, 248, 130, 183, 117, 54, 170, 234, 52, 81, 221, 25, 136, 100, 188, 242, 151, 207, 183, 103, 122, 174, 58, 130, 170, 195, 208, 103, 168, 114, 68, 192, 217, 95, 201, 64, 246, 17, 152, 53, 176, 228, 21, 219, 127, 192, 243, 191, 117, 168, 207, 39, 38, 185, 233, 139, 125, 49, 171, 61, 80, 146, 30, 135, 73, 153, 79, 63, 36, 253, 61, 146, 131, 21, 77, 63, 254, 16, 79, 94, 119, 19, 208, 30, 68, 154, 242, 26, 109, 143, 15, 132, 94, 36, 173, 152, 80, 252, 233, 99, 66, 145, 254, 51, 69, 83, 226, 67, 114, 119, 145, 0, 34, 3, 179, 232, 137, 151, 0, 13, 121, 200, 2, 109, 5, 25, 151, 78, 106, 34, 46, 237, 69, 90, 114, 243, 128, 251, 105, 94, 164, 103, 201, 243, 188, 96, 90, 191, 52, 123, 87, 90, 32, 196, 246, 225, 155, 92, 30, 188, 98, 5, 164, 254, 208, 171, 93, 40, 241, 52, 234, 127, 183, 181, 21, 125, 27, 49, 11, 57, 124, 66, 124, 56, 252, 43, 17, 221, 41, 67, 67, 78, 37, 194, 99, 196, 64, 173, 145, 73, 35, 229, 211, 8, 251, 163, 54, 43, 205, 70, 165, 71, 215, 1, 60, 54, 125, 242, 185, 252, 40, 117, 76, 6, 248, 76, 136, 161, 28, 105, 252, 158, 136, 126, 21, 23, 60, 136, 67, 6, 255, 241, 35, 98, 204, 28, 211, 39, 207, 88, 109, 226, 208, 208, 106, 64, 84, 236, 18, 36, 170, 106, 88, 19, 182, 114, 26, 144, 38, 27, 172, 136, 191, 232, 168, 188, 255, 37, 245, 254, 183, 167, 63, 200, 110, 110, 242, 110, 234, 215, 111, 242, 81, 62, 47, 198, 137, 213, 28, 181, 36, 218, 94, 177, 209, 134, 118, 114, 75, 108, 191, 220, 207, 166, 41, 63, 240, 249, 2, 106, 105, 184, 100, 52, 240, 62, 152, 250, 48, 86, 250, 91, 15, 21, 105, 32, 162, 163, 131, 148, 125, 195, 0, 61, 108, 30, 32, 17, 219, 125, 241, 134, 191, 86, 140, 239, 30, 74, 124, 26, 109, 171, 70, 116, 105, 235, 204, 161, 90, 37, 122, 208, 212, 85, 194, 38, 181, 131, 235, 246, 32, 66, 213, 208, 162, 22, 207, 39, 24, 151, 74, 119, 225, 211, 49, 158, 30, 184, 110, 204, 199, 29, 92, 76, 43, 201, 28, 233, 251, 229, 107, 102, 241, 37, 19, 161, 42, 44, 185, 100, 6, 27, 121, 35, 149, 20, 143, 36, 65, 154, 73, 54, 255, 35, 45, 44, 223, 62, 106, 210, 142, 54, 63, 71, 81, 121, 145, 242, 124, 253, 128, 166, 210, 139, 250, 100, 26, 163, 255, 214, 35, 107, 242, 80, 148, 176, 181, 186, 226, 104, 51, 152, 59, 6, 202, 112, 97, 40, 92, 68, 74, 182, 142, 194, 224, 182, 175, 15, 78, 62, 12, 9, 220, 7, 75, 132, 43, 31, 182, 73, 3, 15, 111, 162, 1, 249, 240, 128, 180, 244, 221, 141, 182, 36, 31, 30, 146, 38, 191, 255, 52, 77, 202, 135, 239, 72, 219, 127, 249, 196, 109, 203, 135, 239, 9, 18, 63, 124, 46, 36, 228, 195, 95, 8, 54, 127, 253, 236, 216, 200, 135, 31, 8, 90, 195, 197, 53, 202, 210, 241, 146, 15, 127, 165, 8, 46, 65, 89, 45, 29, 65, 5, 144, 234, 193, 225, 50, 21, 225, 242, 81, 85, 79, 90, 201, 178, 245, 75, 204, 22, 36, 22, 210, 218, 130, 104, 194, 214, 61, 239, 165, 12, 171, 73, 87, 199, 166, 108, 250, 58, 174, 77, 149, 79, 222, 131, 206, 73, 104, 71, 90, 117, 204, 217, 148, 182, 174, 61, 162, 70, 84, 139, 93, 70, 219, 220, 35, 253, 11, 110, 144, 251, 208, 241, 118, 232, 52, 46, 151, 131, 187, 199, 246, 18, 21, 60, 70, 23, 107, 212, 53, 183, 36, 120, 175, 145, 143, 119, 64, 211, 76, 27, 138, 254, 1, 242, 245, 39, 186, 217, 14, 193, 54, 83, 187, 14, 53, 26, 231, 178, 199, 34, 128, 130, 163, 63, 154, 243, 187, 46, 221, 78, 13, 44, 235, 221, 166, 154, 168, 114, 132, 106, 208, 236, 15, 95, 29, 38, 39, 207, 46, 103, 207, 167, 241, 73, 73, 34, 29, 193, 186, 61, 12, 122, 200, 14, 235, 216, 247, 176, 238, 180, 241, 33, 177, 159, 181, 119, 164, 215, 83, 141, 28, 110, 242, 75, 18, 38, 233, 216, 108, 200, 201, 98, 235, 172, 220, 164, 135, 201, 120, 184, 41, 78, 108, 121, 10, 158, 88, 5, 211, 147, 44, 47, 146, 189, 184, 76, 60, 133, 83, 171, 240, 57, 251, 0, 87, 58, 250, 202, 158, 91, 101, 39, 121, 181, 59, 245, 97, 80, 90, 5, 231, 89, 58, 206, 39, 62, 144, 115, 127, 73, 182, 28, 245, 145, 224, 131, 85, 186, 172, 210, 241, 217, 149, 167, 224, 85, 207, 226, 6, 147, 136, 202, 13, 254, 116, 24, 65, 198, 164, 30, 195, 27, 26, 143, 42, 138, 122, 238, 33, 189, 121, 134, 153, 65, 58, 166, 66, 248, 124, 100, 243, 140, 0, 92, 216, 180, 115, 159, 99, 76, 75, 240, 87, 120, 99, 165, 247, 223, 112, 179, 167, 130, 182, 46, 127, 243, 98, 117, 228, 49, 215, 116, 154, 251, 82, 49, 105, 118, 39, 31, 224, 110, 15, 241, 101, 31, 130, 211, 251, 35, 121, 167, 53, 114, 92, 105, 239, 85, 57, 159, 205, 132, 219, 59, 46, 248, 94, 128, 88, 123, 203, 248, 247, 145, 90, 37, 126, 253, 181, 180, 10, 44, 55, 135, 104, 230, 29, 176, 202, 235, 60, 205, 170, 93, 166, 27, 76, 115, 79, 163, 173, 203, 99, 246, 111, 133, 94, 211, 33, 160, 175, 71, 67, 246, 31, 105, 223, 210, 165, 208, 221, 151, 224, 168, 235, 139, 13, 9, 51, 202, 197, 101, 112, 152, 139, 203, 218, 107, 179, 46, 235, 6, 154, 213, 197, 35, 61, 194, 35, 40, 81, 80, 13, 178, 246, 102, 85, 122, 158, 254, 14, 110, 26, 129, 170, 139, 0, 102, 133, 134, 35, 146, 197, 229, 32, 82, 158, 15, 115, 122, 150, 213, 91, 93, 237, 11, 16, 50, 12, 201, 56, 71, 168, 222, 145, 173, 177, 14, 253, 67, 136, 174, 93, 119, 184, 37, 110, 58, 196, 239, 126, 216, 178, 157, 183, 162, 43, 191, 200, 67, 168, 140, 246, 172, 155, 28, 185, 209, 0, 3, 247, 237, 228, 139, 170, 114, 43, 225, 217, 101, 50, 22, 245, 236, 249, 0, 141, 43, 235, 249, 197, 235, 152, 205, 61, 170, 160, 127, 248, 173, 98, 154, 11, 28, 41, 43, 46, 145, 152, 233, 204, 26, 62, 134, 77, 179, 241, 116, 62, 225, 102, 22, 84, 0, 69, 211, 179, 247, 145, 5, 6, 158, 142, 184, 132, 110, 223, 204, 188, 199, 71, 161, 125, 133, 15, 98, 51, 135, 117, 109, 26, 151, 213, 190, 58, 182, 162, 228, 119, 23, 206, 164, 234, 107, 156, 50, 245, 41, 112, 194, 93, 79, 118, 222, 190, 169, 148, 146, 162, 140, 117, 64, 218, 108, 175, 139, 83, 87, 76, 124, 184, 20, 61, 138, 118, 49, 47, 136, 115, 138, 48, 104, 85, 65, 134, 134, 67, 53, 126, 22, 143, 115, 122, 151, 25, 228, 3, 93, 25, 97, 100, 224, 145, 203, 147, 165, 139, 28, 81, 69, 59, 225, 49, 181, 12, 135, 83, 18, 162, 17, 148, 5, 192, 237, 229, 87, 159, 6, 152, 46, 250, 8, 181, 188, 174, 243, 144, 241, 255, 103, 235, 235, 158, 149, 68, 59, 185, 210, 204, 237, 140, 118, 71, 14, 144, 91, 19, 140, 26, 160, 198, 148, 34, 175, 225, 141, 89, 94, 166, 50, 39, 163, 64, 118, 148, 196, 197, 248, 148, 153, 99, 18, 77, 155, 162, 48, 52, 166, 210, 19, 72, 45, 215, 145, 89, 112, 127, 104, 155, 47, 216, 23, 158, 153, 182, 63, 66, 74, 17, 49, 214, 104, 254, 94, 104, 100, 24, 30, 133, 5, 194, 49, 218, 208, 111, 151, 201, 113, 55, 205, 64, 114, 195, 72, 127, 120, 170, 198, 208, 179, 67, 184, 171, 170, 124, 108, 197, 123, 135, 201, 108, 26, 179, 5, 65, 41, 205, 135, 66, 252, 70, 17, 83, 159, 127, 102, 13, 51, 173, 208, 185, 162, 67, 241, 84, 246, 133, 149, 33, 233, 24, 81, 135, 116, 157, 180, 40, 171, 159, 115, 86, 164, 80, 227, 38, 50, 32, 242, 190, 57, 16, 205, 20, 96, 96, 81, 53, 102, 181, 161, 116, 166, 121, 173, 76, 166, 167, 56, 255, 128, 7, 13, 102, 10, 60, 183, 222, 250, 192, 227, 0, 188, 91, 104, 116, 192, 187, 32, 21, 53, 63, 203, 33, 125, 26, 125, 183, 69, 3, 254, 77, 48, 200, 79, 113, 41, 83, 84, 60, 147, 191, 158, 231, 76, 13, 156, 191, 159, 196, 62, 178, 24, 224, 154, 63, 21, 148, 53, 218, 128, 215, 180, 145, 136, 50, 114, 170, 214, 250, 164, 10, 168, 219, 129, 245, 102, 100, 191, 144, 221, 178, 95, 99, 108, 237, 111, 98, 86, 183, 94, 42, 196, 201, 107, 210, 207, 143, 43, 238, 83, 109, 175, 192, 182, 208, 122, 91, 162, 73, 17, 139, 140, 165, 132, 225, 242, 241, 180, 153, 117, 213, 82, 238, 13, 141, 115, 221, 140, 233, 73, 105, 73, 8, 230, 161, 97, 136, 126, 14, 237, 108, 60, 245, 39, 167, 87, 245, 232, 166, 144, 92, 184, 3, 181, 62, 106, 105, 168, 225, 124, 210, 36, 63, 157, 218, 97, 116, 220, 134, 154, 134, 164, 174, 57, 107, 60, 240, 104, 32, 194, 59, 35, 225, 31, 135, 0, 209, 195, 11, 2, 27, 153, 102, 106, 251, 87, 12, 18, 132, 94, 12, 172, 224, 190, 72, 180, 73, 31, 92, 252, 157, 225, 146, 175, 221, 46, 249, 214, 34, 30, 4, 68, 243, 188, 61, 212, 180, 221, 176, 183, 89, 167, 209, 182, 235, 26, 162, 168, 59, 173, 111, 204, 60, 138, 215, 46, 250, 20, 132, 171, 222, 63, 245, 34, 199, 111, 228, 82, 79, 93, 41, 82, 160, 188, 131, 29, 102, 147, 5, 69, 230, 200, 41, 111, 114, 253, 227, 36, 241, 242, 88, 148, 18, 199, 129, 70, 104, 125, 221, 10, 147, 226, 118, 135, 61, 139, 122, 243, 131, 181, 89, 70, 221, 189, 229, 145, 142, 91, 80, 153, 144, 147, 201, 33, 117, 193, 170, 52, 129, 194, 129, 253, 218, 44, 75, 104, 184, 44, 138, 124, 82, 196, 38, 225, 79, 122, 172, 229, 152, 28, 165, 40, 75, 67, 182, 23, 207, 152, 110, 73, 84, 30, 9, 158, 201, 227, 60, 190, 236, 27, 26, 241, 90, 58, 100, 97, 35, 26, 170, 11, 6, 209, 232, 240, 220, 239, 193, 193, 209, 197, 4, 72, 158, 125, 138, 87, 66, 118, 173, 179, 246, 34, 216, 72, 114, 154, 119, 105, 198, 48, 84, 105, 77, 36, 138, 194, 217, 166, 117, 169, 142, 139, 222, 90, 65, 138, 89, 112, 63, 215, 62, 224, 108, 51, 220, 227, 26, 213, 76, 114, 91, 76, 55, 26, 148, 150, 38, 102, 186, 137, 60, 253, 151, 135, 230, 43, 154, 118, 208, 189, 6, 240, 79, 210, 194, 59, 23, 233, 5, 157, 126, 163, 7, 172, 113, 126, 242, 235, 248, 128, 158, 71, 20, 178, 34, 133, 77, 198, 202, 8, 34, 126, 217, 159, 199, 79, 12, 22, 59, 176, 208, 194, 6, 17, 207, 27, 26, 207, 94, 105, 126, 59, 202, 244, 249, 85, 149, 250, 147, 125, 13, 28, 194, 129, 127, 154, 141, 160, 32, 178, 254, 148, 13, 163, 254, 114, 156, 226, 243, 100, 130, 88, 88, 114, 194, 9, 132, 226, 151, 120, 37, 73, 11, 6, 91, 215, 161, 255, 164, 188, 199, 140, 194, 163, 142, 233, 111, 219, 43, 154, 161, 159, 62, 241, 200, 178, 105, 218, 213, 2, 235, 230, 204, 13, 89, 227, 187, 80, 204, 186, 31, 82, 36, 121, 26, 89, 183, 89, 197, 112, 126, 228, 215, 48, 26, 224, 58, 22, 92, 119, 33, 230, 169, 204, 58, 106, 45, 213, 237, 148, 239, 170, 139, 150, 117, 35, 36, 196, 67, 136, 149, 86, 52, 80, 107, 43, 47, 9, 2, 150, 76, 80, 82, 141, 140, 34, 233, 228, 114, 137, 37, 146, 200, 226, 117, 141, 157, 177, 225, 98, 119, 90, 87, 31, 181, 2, 229, 83, 128, 103, 222, 85, 5, 7, 86, 21, 152, 126, 101, 87, 104, 220, 108, 179, 84, 135, 37, 186, 73, 154, 101, 45, 159, 64, 7, 13, 135, 186, 14, 232, 250, 58, 208, 178, 73, 252, 107, 215, 38, 174, 94, 8, 28, 179, 80, 177, 123, 154, 62, 88, 101, 208, 232, 61, 196, 239, 186, 219, 232, 147, 63, 161, 40, 41, 80, 191, 110, 118, 46, 168, 54, 112, 5, 106, 16, 105, 98, 125, 114, 39, 17, 169, 86, 200, 239, 53, 244, 11, 105, 93, 26, 86, 120, 43, 186, 103, 126, 12, 111, 160, 175, 219, 183, 183, 175, 230, 199, 246, 13, 116, 252, 193, 29, 233, 184, 249, 241, 224, 6, 168, 240, 240, 46, 82, 193, 252, 120, 184, 76, 146, 96, 127, 122, 71, 85, 221, 188, 231, 80, 87, 27, 47, 67, 91, 89, 110, 29, 225, 251, 172, 59, 226, 177, 177, 71, 188, 241, 88, 3, 117, 146, 161, 131, 134, 170, 113, 79, 224, 81, 139, 158, 217, 19, 92, 141, 125, 234, 248, 137, 152, 113, 195, 141, 166, 180, 154, 27, 222, 212, 84, 17, 70, 149, 248, 67, 89, 196, 227, 46, 178, 172, 150, 129, 139, 91, 216, 192, 122, 110, 79, 191, 220, 198, 146, 6, 86, 68, 54, 173, 220, 157, 24, 29, 158, 145, 185, 179, 188, 220, 94, 216, 16, 139, 234, 214, 230, 64, 139, 25, 191, 102, 190, 183, 103, 251, 26, 13, 209, 168, 31, 194, 218, 33, 160, 27, 244, 186, 154, 190, 246, 75, 56, 150, 111, 35, 221, 90, 182, 237, 121, 253, 51, 117, 68, 61, 218, 51, 249, 226, 125, 218, 190, 77, 125, 82, 143, 246, 124, 189, 120, 247, 30, 220, 210, 238, 169, 71, 123, 78, 94, 188, 167, 15, 111, 127, 79, 213, 163, 61, 235, 46, 208, 105, 236, 18, 12, 46, 5, 201, 170, 109, 171, 118, 213, 182, 211, 98, 226, 205, 116, 7, 50, 115, 4, 178, 190, 134, 86, 156, 235, 224, 7, 36, 179, 124, 235, 138, 219, 106, 130, 111, 57, 9, 182, 6, 252, 192, 55, 179, 163, 121, 145, 242, 207, 114, 230, 116, 239, 172, 183, 248, 198, 154, 217, 251, 88, 40, 128, 173, 83, 192, 204, 162, 158, 231, 79, 18, 55, 227, 236, 4, 116, 137, 145, 169, 241, 166, 45, 203, 151, 230, 58, 253, 188, 4, 211, 88, 155, 46, 163, 142, 60, 49, 158, 182, 91, 22, 90, 131, 200, 143, 215, 1, 247, 197, 239, 231, 139, 18, 88, 105, 189, 141, 41, 246, 223, 219, 202, 106, 103, 185, 204, 139, 244, 4, 78, 228, 139, 190, 224, 232, 21, 49, 226, 222, 240, 149, 225, 154, 93, 253, 185, 220, 61, 149, 145, 212, 58, 235, 155, 212, 142, 60, 93, 77, 169, 133, 233, 239, 214, 7, 180, 29, 120, 3, 186, 194, 241, 67, 91, 91, 68, 104, 139, 208, 198, 152, 110, 235, 117, 86, 58, 13, 106, 199, 203, 249, 221, 148, 143, 189, 45, 214, 61, 66, 47, 106, 177, 91, 102, 111, 66, 184, 182, 81, 131, 101, 20, 178, 139, 188, 86, 145, 179, 71, 229, 183, 113, 140, 133, 163, 115, 130, 225, 61, 37, 254, 136, 71, 207, 218, 134, 230, 241, 160, 77, 67, 23, 220, 150, 14, 12, 221, 142, 127, 84, 180, 149, 215, 134, 228, 144, 232, 108, 199, 207, 117, 120, 239, 17, 23, 195, 28, 83, 183, 155, 18, 220, 66, 244, 175, 155, 145, 73, 76, 119, 17, 107, 55, 13, 241, 88, 91, 3, 243, 137, 231, 75, 35, 241, 109, 167, 75, 50, 46, 244, 94, 164, 219, 58, 83, 98, 204, 254, 124, 162, 120, 194, 108, 10, 202, 66, 237, 212, 58, 216, 196, 186, 49, 107, 106, 248, 243, 79, 27, 84, 93, 124, 35, 183, 174, 201, 236, 192, 107, 163, 205, 108, 163, 222, 244, 89, 209, 195, 248, 162, 79, 91, 29, 80, 24, 158, 240, 204, 123, 102, 29, 224, 200, 200, 78, 22, 2, 138, 104, 188, 147, 198, 194, 103, 153, 244, 191, 204, 15, 214, 252, 208, 28, 219, 43, 211, 83, 205, 68, 216, 176, 24, 119, 39, 181, 27, 212, 162, 123, 192, 6, 60, 175, 92, 19, 146, 177, 179, 131, 126, 208, 249, 10, 170, 154, 175, 86, 236, 8, 252, 67, 49, 205, 86, 194, 114, 60, 10, 56, 236, 118, 181, 190, 183, 139, 205, 151, 238, 140, 105, 5, 224, 250, 236, 25, 207, 188, 25, 216, 30, 249, 50, 131, 126, 153, 65, 163, 47, 51, 104, 83, 32, 124, 199, 233, 211, 221, 120, 186, 177, 121, 244, 203, 92, 119, 27, 230, 186, 155, 136, 233, 235, 176, 135, 138, 105, 21, 152, 102, 220, 45, 85, 81, 120, 193, 213, 88, 56, 40, 115, 224, 239, 128, 124, 251, 101, 249, 246, 57, 38, 159, 123, 162, 158, 253, 39, 81, 90, 170, 103, 255, 201, 220, 112, 72, 253, 66, 199, 240, 204, 217, 142, 131, 98, 196, 115, 106, 80, 29, 223, 55, 233, 231, 127, 88, 211, 123, 73, 180, 6, 14, 243, 171, 101, 130, 112, 85, 62, 140, 158, 9, 131, 234, 9, 62, 140, 35, 196, 37, 216, 8, 14, 158, 226, 232, 232, 185, 172, 241, 90, 214, 225, 239, 199, 158, 196, 186, 140, 48, 86, 94, 177, 174, 247, 120, 134, 155, 183, 26, 119, 97, 227, 150, 45, 13, 83, 31, 98, 29, 154, 177, 137, 184, 108, 161, 13, 74, 166, 21, 172, 6, 238, 159, 28, 119, 217, 197, 248, 34, 197, 203, 145, 226, 46, 86, 91, 141, 197, 182, 44, 17, 214, 241, 82, 1, 227, 174, 205, 73, 156, 26, 163, 174, 214, 28, 14, 91, 118, 159, 66, 67, 180, 241, 3, 96, 43, 173, 49, 244, 109, 69, 26, 89, 95, 84, 77, 221, 73, 218, 150, 11, 186, 240, 177, 135, 47, 234, 231, 139, 250, 185, 147, 234, 103, 193, 128, 211, 229, 132, 249, 182, 92, 154, 118, 82, 120, 29, 99, 125, 191, 104, 70, 108, 22, 223, 178, 204, 108, 98, 71, 32, 249, 144, 230, 243, 242, 5, 226, 112, 204, 240, 142, 139, 108, 191, 252, 159, 164, 200, 97, 0, 217, 104, 115, 150, 232, 59, 48, 212, 217, 95, 222, 35, 171, 102, 64, 170, 200, 213, 116, 181, 153, 91, 32, 55, 187, 206, 180, 247, 152, 233, 229, 191, 28, 31, 31, 215, 28, 91, 183, 87, 76, 234, 88, 114, 29, 114, 14, 122, 78, 23, 165, 130, 163, 59, 25, 11, 38, 147, 145, 39, 208, 188, 19, 78, 120, 122, 8, 160, 68, 119, 28, 172, 60, 146, 158, 3, 0, 130, 60, 52, 105, 220, 192, 5, 30, 102, 234, 230, 170, 134, 221, 107, 19, 10, 240, 160, 214, 121, 81, 48, 169, 175, 227, 70, 62, 110, 134, 249, 236, 26, 62, 4, 2, 60, 231, 165, 160, 226, 193, 192, 36, 40, 105, 183, 97, 223, 106, 68, 103, 32, 151, 84, 179, 41, 91, 10, 171, 100, 82, 83, 88, 24, 223, 38, 45, 240, 94, 222, 104, 84, 229, 133, 216, 30, 244, 93, 113, 36, 122, 98, 18, 99, 4, 110, 74, 130, 1, 69, 240, 204, 38, 178, 17, 105, 125, 3, 67, 189, 152, 243, 66, 123, 188, 139, 24, 65, 249, 161, 207, 169, 72, 207, 102, 64, 196, 171, 236, 189, 249, 170, 110, 225, 162, 54, 34, 196, 234, 114, 79, 34, 55, 135, 248, 176, 148, 48, 72, 85, 82, 168, 97, 64, 24, 235, 28, 31, 221, 165, 219, 106, 38, 176, 13, 65, 117, 0, 151, 125, 162, 86, 202, 238, 59, 247, 240, 79, 117, 201, 191, 225, 84, 202, 141, 38, 213, 236, 255, 241, 118, 189, 170, 13, 1, 42, 148, 242, 179, 13, 208, 250, 76, 44, 62, 74, 116, 74, 146, 178, 163, 53, 124, 150, 92, 60, 87, 33, 8, 234, 128, 113, 91, 64, 87, 61, 164, 84, 21, 32, 28, 211, 224, 116, 221, 46, 4, 217, 103, 69, 166, 94, 165, 101, 17, 113, 130, 57, 223, 247, 6, 17, 220, 1, 117, 57, 208, 240, 136, 116, 210, 188, 132, 98, 118, 219, 197, 91, 79, 140, 159, 21, 95, 122, 24, 95, 117, 137, 125, 130, 74, 60, 143, 44, 252, 219, 113, 22, 9, 188, 128, 128, 240, 244, 233, 83, 203, 219, 168, 26, 148, 173, 80, 95, 60, 78, 164, 167, 106, 148, 233, 239, 192, 148, 56, 247, 28, 191, 71, 148, 191, 198, 149, 3, 242, 36, 83, 34, 211, 137, 90, 145, 83, 78, 215, 225, 132, 90, 118, 78, 63, 58, 110, 6, 50, 159, 104, 16, 212, 53, 115, 131, 121, 51, 80, 254, 127, 127, 58, 196, 45, 115, 8, 209, 71, 156, 223, 96, 142, 241, 168, 191, 87, 57, 178, 226, 177, 90, 100, 150, 205, 106, 32, 208, 22, 99, 15, 32, 229, 142, 226, 111, 204, 2, 2, 98, 99, 251, 135, 9, 244, 239, 59, 62, 162, 155, 118, 77, 183, 127, 115, 237, 36, 66, 254, 223, 136, 141, 242, 155, 116, 42, 131, 158, 253, 13, 12, 112, 220, 54, 252, 243, 110, 148, 36, 173, 226, 97, 127, 143, 204, 93, 209, 122, 44, 131, 108, 243, 187, 179, 156, 173, 65, 251, 247, 246, 155, 159, 64, 143, 223, 205, 66, 210, 116, 188, 75, 103, 127, 99, 42, 226, 119, 182, 154, 37, 177, 184, 1, 133, 74, 44, 146, 223, 118, 156, 238, 57, 188, 219, 220, 177, 223, 120, 20, 13, 213, 181, 161, 109, 178, 223, 224, 178, 201, 223, 240, 118, 24, 191, 224, 157, 205, 181, 246, 245, 186, 162, 107, 218, 251, 226, 226, 239, 164, 97, 19, 42, 96, 70, 153, 109, 113, 196, 40, 90, 117, 114, 41, 213, 231, 192, 138, 170, 102, 64, 33, 140, 90, 221, 107, 37, 75, 137, 20, 160, 56, 245, 226, 46, 199, 155, 233, 63, 39, 97, 28, 201, 199, 10, 218, 50, 49, 117, 127, 247, 40, 21, 62, 89, 113, 235, 227, 224, 184, 49, 135, 210, 239, 254, 244, 73, 2, 10, 228, 111, 210, 148, 144, 194, 159, 242, 131, 93, 22, 120, 204, 8, 13, 212, 249, 93, 93, 106, 39, 25, 74, 81, 194, 67, 156, 70, 2, 185, 68, 194, 156, 131, 85, 169, 214, 138, 202, 210, 158, 217, 178, 213, 128, 118, 79, 94, 216, 137, 229, 169, 35, 31, 240, 249, 73, 179, 2, 50, 227, 119, 61, 182, 251, 187, 89, 145, 87, 57, 152, 149, 239, 132, 48, 90, 139, 248, 186, 36, 250, 252, 8, 214, 126, 73, 140, 219, 67, 59, 117, 54, 49, 94, 36, 197, 32, 79, 171, 212, 111, 73, 117, 154, 79, 246, 143, 255, 85, 196, 179, 153, 137, 174, 63, 84, 15, 114, 81, 33, 127, 245, 188, 56, 91, 23, 250, 214, 45, 7, 130, 233, 201, 15, 3, 73, 199, 223, 36, 101, 213, 137, 38, 53, 11, 154, 14, 23, 11, 180, 194, 31, 16, 127, 158, 23, 28, 69, 23, 255, 175, 212, 218, 140, 175, 97, 228, 181, 8, 234, 30, 14, 142, 124, 248, 98, 1, 89, 73, 222, 185, 112, 52, 226, 183, 249, 110, 150, 226, 237, 91, 114, 199, 0, 154, 166, 118, 167, 211, 207, 228, 3, 42, 105, 102, 188, 207, 176, 254, 35, 139, 13, 21, 99, 90, 12, 34, 103, 113, 223, 232, 253, 113, 150, 132, 250, 72, 254, 34, 139, 164, 5, 150, 116, 18, 119, 180, 22, 106, 183, 65, 65, 84, 150, 70, 182, 215, 163, 136, 132, 150, 79, 166, 213, 22, 139, 12, 79, 197, 205, 118, 72, 106, 68, 164, 70, 233, 176, 182, 58, 233, 173, 49, 78, 228, 254, 171, 71, 96, 184, 255, 217, 29, 196, 92, 130, 24, 110, 113, 16, 46, 117, 55, 182, 45, 149, 45, 46, 89, 148, 82, 41, 108, 8, 102, 150, 196, 192, 138, 154, 199, 24, 181, 6, 54, 3, 78, 253, 174, 173, 26, 112, 69, 114, 146, 92, 206, 6, 74, 227, 134, 1, 154, 172, 20, 214, 255, 248, 76, 46, 193, 177, 190, 188, 74, 46, 188, 13, 241, 110, 11, 126, 100, 250, 135, 176, 161, 170, 205, 23, 31, 2, 161, 86, 165, 135, 10, 237, 86, 165, 183, 85, 231, 90, 149, 126, 160, 60, 8, 127, 202, 17, 243, 87, 16, 150, 146, 170, 197, 127, 201, 59, 235, 53, 229, 86, 172, 171, 79, 100, 97, 159, 67, 141, 80, 236, 85, 114, 89, 161, 107, 109, 196, 149, 242, 126, 157, 202, 175, 36, 102, 179, 114, 95, 20, 250, 101, 30, 23, 147, 55, 185, 119, 24, 160, 232, 90, 200, 3, 88, 63, 105, 83, 72, 129, 41, 28, 16, 180, 230, 109, 183, 91, 158, 169, 91, 187, 81, 255, 136, 248, 189, 215, 143, 240, 177, 243, 73, 158, 177, 23, 60, 77, 173, 184, 255, 217, 222, 63, 213, 122, 206, 29, 28, 184, 98, 77, 140, 139, 26, 8, 247, 40, 178, 89, 136, 75, 151, 39, 52, 8, 212, 46, 148, 101, 238, 245, 57, 11, 188, 129, 93, 49, 10, 98, 76, 28, 93, 75, 145, 217, 90, 65, 91, 73, 130, 137, 91, 168, 120, 10, 99, 136, 97, 180, 212, 248, 20, 194, 3, 12, 161, 54, 245, 251, 226, 7, 243, 173, 253, 99, 228, 62, 145, 49, 185, 157, 60, 129, 146, 179, 116, 15, 162, 104, 219, 240, 18, 137, 144, 87, 6, 234, 107, 101, 52, 162, 9, 184, 175, 61, 177, 45, 34, 233, 165, 130, 28, 10, 169, 145, 152, 186, 213, 3, 51, 172, 172, 189, 45, 106, 31, 123, 34, 231, 67, 155, 245, 122, 193, 33, 73, 170, 127, 147, 205, 20, 249, 150, 172, 160, 87, 195, 219, 241, 181, 123, 241, 122, 147, 90, 207, 147, 184, 194, 227, 39, 146, 81, 229, 146, 14, 45, 146, 126, 180, 119, 225, 173, 73, 197, 19, 183, 10, 145, 171, 198, 51, 130, 34, 102, 189, 171, 255, 26, 229, 235, 48, 4, 252, 123, 136, 127, 108, 12, 245, 15, 180, 50, 12, 73, 186, 248, 102, 73, 59, 166, 146, 239, 14, 132, 224, 6, 191, 237, 48, 177, 199, 128, 23, 146, 113, 227, 222, 184, 240, 198, 88, 98, 27, 162, 47, 158, 88, 140, 145, 199, 39, 81, 59, 64, 193, 224, 98, 67, 139, 107, 142, 12, 158, 35, 173, 1, 114, 206, 83, 45, 157, 5, 76, 4, 10, 103, 132, 15, 242, 162, 15, 78, 234, 29, 253, 205, 97, 4, 181, 7, 41, 213, 126, 211, 14, 132, 118, 165, 66, 121, 98, 173, 90, 33, 227, 254, 254, 241, 11, 66, 169, 85, 212, 64, 10, 68, 6, 77, 130, 13, 164, 36, 213, 196, 37, 133, 141, 108, 91, 18, 177, 213, 218, 219, 47, 150, 221, 145, 24, 98, 77, 221, 105, 162, 117, 69, 78, 247, 192, 202, 142, 174, 132, 14, 205, 7, 170, 152, 218, 94, 183, 228, 7, 32, 129, 209, 226, 46, 34, 172, 33, 35, 174, 43, 136, 146, 232, 28, 193, 175, 164, 77, 55, 135, 195, 248, 13, 14, 72, 210, 60, 108, 163, 91, 54, 236, 72, 100, 229, 90, 227, 34, 150, 32, 126, 121, 112, 174, 111, 212, 214, 171, 154, 106, 245, 229, 239, 130, 186, 212, 70, 213, 223, 44, 155, 83, 95, 62, 64, 24, 147, 47, 9, 85, 149, 35, 179, 120, 23, 62, 137, 126, 143, 23, 234, 173, 189, 37, 60, 202, 42, 121, 131, 140, 100, 75, 171, 171, 178, 148, 181, 216, 218, 47, 95, 231, 101, 153, 190, 159, 94, 73, 91, 150, 172, 207, 53, 222, 164, 203, 220, 117, 177, 159, 193, 21, 185, 113, 197, 170, 38, 194, 28, 230, 97, 75, 98, 128, 63, 136, 214, 45, 31, 7, 91, 86, 244, 4, 75, 244, 68, 202, 166, 129, 225, 93, 81, 139, 182, 35, 215, 148, 28, 113, 201, 145, 134, 184, 251, 229, 43, 198, 122, 7, 197, 63, 84, 135, 57, 8, 234, 94, 241, 224, 40, 137, 39, 208, 36, 58, 33, 45, 95, 139, 203, 40, 71, 202, 34, 85, 142, 23, 169, 238, 96, 231, 89, 112, 113, 79, 81, 158, 55, 181, 218, 183, 171, 130, 75, 35, 206, 164, 205, 37, 165, 128, 155, 98, 98, 4, 95, 228, 249, 217, 124, 214, 95, 211, 134, 216, 170, 219, 25, 217, 221, 21, 99, 44, 145, 3, 193, 138, 26, 172, 165, 26, 239, 138, 40, 228, 56, 189, 201, 74, 7, 25, 47, 74, 211, 34, 226, 40, 149, 79, 121, 147, 177, 164, 36, 167, 170, 16, 100, 82, 91, 23, 133, 216, 212, 241, 148, 217, 184, 71, 106, 157, 200, 225, 115, 106, 142, 243, 233, 65, 246, 186, 128, 109, 167, 244, 67, 178, 151, 207, 51, 126, 123, 174, 59, 199, 233, 94, 219, 238, 21, 237, 79, 8, 116, 220, 235, 155, 212, 101, 0, 99, 207, 208, 215, 27, 223, 88, 137, 179, 73, 178, 210, 241, 115, 207, 217, 15, 1, 68, 92, 250, 57, 178, 38, 62, 25, 78, 160, 42, 4, 168, 168, 20, 139, 46, 232, 118, 6, 159, 86, 229, 190, 145, 62, 106, 71, 112, 89, 155, 14, 184, 247, 89, 218, 33, 89, 72, 205, 248, 136, 143, 184, 232, 178, 142, 131, 132, 255, 107, 20, 214, 13, 224, 132, 93, 170, 122, 96, 0, 109, 13, 33, 185, 51, 32, 166, 84, 70, 229, 132, 224, 176, 48, 94, 170, 202, 201, 13, 5, 41, 132, 240, 22, 150, 20, 22, 4, 75, 173, 14, 135, 67, 135, 231, 57, 186, 205, 78, 58, 205, 211, 162, 17, 122, 15, 168, 183, 169, 109, 86, 70, 211, 200, 123, 38, 254, 230, 245, 20, 107, 122, 249, 170, 138, 247, 231, 126, 104, 43, 237, 82, 113, 85, 86, 157, 252, 155, 91, 146, 106, 112, 224, 141, 181, 146, 92, 65, 80, 25, 112, 44, 3, 138, 5, 102, 43, 118, 72, 173, 228, 203, 89, 60, 97, 125, 188, 20, 38, 40, 91, 66, 164, 211, 233, 72, 90, 141, 236, 211, 179, 108, 114, 109, 241, 22, 96, 96, 115, 69, 60, 193, 246, 10, 60, 142, 170, 184, 168, 124, 70, 129, 181, 203, 66, 232, 152, 102, 213, 75, 133, 45, 182, 157, 117, 23, 176, 143, 139, 189, 225, 251, 196, 133, 21, 88, 67, 128, 8, 47, 3, 251, 97, 233, 88, 246, 82, 33, 165, 189, 206, 64, 157, 132, 32, 103, 232, 165, 53, 185, 42, 68, 110, 70, 114, 129, 58, 136, 60, 141, 250, 253, 97, 244, 248, 113, 244, 96, 11, 54, 175, 183, 41, 97, 15, 227, 236, 68, 43, 132, 45, 66, 47, 104, 80, 116, 149, 192, 219, 144, 253, 82, 200, 179, 37, 79, 54, 134, 64, 109, 233, 119, 82, 125, 113, 125, 176, 146, 53, 138, 100, 198, 56, 85, 197, 170, 67, 105, 241, 220, 87, 13, 254, 183, 124, 173, 183, 220, 255, 52, 110, 70, 127, 107, 235, 56, 100, 93, 194, 132, 213, 166, 130, 248, 95, 22, 68, 69, 83, 201, 67, 64, 83, 124, 252, 223, 80, 149, 173, 97, 188, 45, 90, 83, 98, 0, 43, 49, 46, 94, 225, 120, 87, 2, 155, 250, 69, 4, 182, 157, 162, 30, 217, 241, 36, 196, 52, 80, 4, 151, 195, 126, 157, 87, 210, 248, 146, 36, 36, 158, 239, 146, 44, 32, 162, 75, 107, 159, 211, 148, 54, 175, 71, 137, 239, 250, 28, 23, 249, 185, 138, 4, 240, 110, 204, 168, 227, 41, 170, 218, 175, 204, 58, 75, 166, 125, 165, 128, 148, 38, 66, 17, 27, 2, 228, 22, 103, 26, 207, 231, 169, 68, 115, 11, 113, 149, 75, 158, 66, 93, 48, 203, 67, 162, 100, 122, 87, 55, 183, 249, 117, 140, 19, 9, 205, 103, 155, 200, 149, 136, 92, 178, 32, 28, 200, 186, 101, 25, 43, 19, 4, 59, 184, 60, 193, 101, 234, 231, 126, 92, 178, 141, 1, 160, 110, 213, 137, 8, 153, 5, 71, 5, 175, 144, 68, 231, 120, 168, 77, 64, 128, 184, 243, 152, 162, 55, 182, 11, 52, 156, 86, 134, 129, 191, 123, 55, 98, 29, 40, 196, 186, 144, 166, 165, 197, 32, 0, 142, 156, 66, 184, 119, 74, 61, 234, 69, 51, 190, 65, 24, 177, 160, 165, 47, 5, 36, 117, 183, 36, 142, 101, 24, 144, 102, 3, 87, 100, 74, 106, 251, 47, 65, 94, 184, 41, 255, 125, 199, 100, 162, 155, 229, 101, 109, 184, 243, 36, 185, 60, 56, 70, 59, 203, 8, 190, 153, 73, 242, 210, 217, 129, 83, 147, 8, 43, 135, 155, 3, 68, 44, 111, 31, 175, 80, 195, 8, 110, 2, 107, 218, 73, 214, 186, 246, 118, 174, 160, 173, 176, 42, 78, 167, 175, 121, 239, 0, 191, 117, 82, 203, 58, 176, 151, 37, 23, 35, 141, 42, 238, 145, 118, 49, 234, 18, 58, 44, 130, 248, 235, 240, 103, 162, 230, 57, 134, 226, 16, 153, 38, 187, 41, 188, 254, 68, 17, 100, 135, 48, 176, 182, 197, 74, 27, 91, 206, 153, 178, 99, 143, 73, 105, 23, 211, 117, 31, 46, 178, 242, 128, 182, 180, 161, 222, 219, 235, 93, 68, 153, 224, 76, 193, 99, 135, 110, 124, 178, 104, 191, 150, 245, 233, 42, 178, 160, 245, 43, 51, 188, 170, 69, 37, 238, 230, 210, 22, 17, 173, 121, 113, 251, 101, 150, 251, 143, 157, 229, 22, 154, 115, 118, 149, 149, 187, 248, 180, 35, 42, 24, 61, 23, 214, 205, 177, 216, 130, 249, 233, 202, 14, 79, 30, 14, 8, 20, 221, 125, 102, 218, 31, 28, 67, 28, 255, 75, 185, 57, 166, 79, 170, 232, 240, 20, 147, 25, 13, 29, 213, 174, 203, 135, 6, 251, 53, 232, 176, 182, 47, 196, 198, 51, 107, 234, 47, 56, 14, 150, 144, 74, 190, 83, 88, 240, 159, 136, 123, 73, 179, 143, 61, 201, 246, 157, 107, 6, 80, 127, 112, 229, 29, 91, 176, 2, 105, 183, 107, 147, 110, 251, 19, 127, 121, 18, 110, 251, 186, 232, 203, 36, 166, 189, 40, 188, 219, 184, 243, 134, 203, 71, 211, 148, 199, 148, 152, 153, 204, 75, 85, 58, 232, 54, 93, 217, 252, 70, 11, 224, 182, 10, 149, 115, 140, 180, 232, 156, 245, 182, 219, 136, 200, 153, 125, 204, 137, 59, 116, 36, 24, 96, 205, 195, 120, 230, 178, 192, 61, 166, 147, 61, 141, 101, 242, 207, 229, 86, 167, 41, 0, 167, 207, 246, 212, 238, 217, 3, 148, 252, 43, 58, 179, 52, 87, 180, 0, 247, 101, 171, 202, 154, 27, 197, 145, 163, 6, 7, 112, 41, 207, 37, 181, 244, 0, 75, 82, 227, 25, 80, 67, 184, 69, 14, 96, 133, 211, 117, 60, 192, 55, 181, 105, 69, 18, 34, 52, 111, 93, 109, 108, 47, 111, 207, 234, 186, 238, 106, 61, 250, 93, 156, 213, 165, 56, 0, 158, 204, 98, 25, 52, 139, 206, 128, 95, 75, 234, 1, 174, 207, 98, 151, 34, 14, 239, 189, 11, 106, 40, 211, 78, 148, 49, 11, 107, 135, 145, 236, 135, 23, 180, 42, 92, 115, 78, 149, 140, 164, 228, 8, 232, 9, 98, 191, 129, 105, 5, 133, 162, 185, 39, 138, 66, 46, 45, 31, 134, 203, 113, 104, 41, 172, 66, 42, 204, 148, 104, 50, 243, 85, 185, 86, 138, 12, 232, 131, 136, 162, 172, 88, 193, 72, 142, 70, 51, 71, 146, 177, 101, 175, 235, 122, 216, 154, 115, 18, 209, 105, 10, 70, 75, 171, 222, 237, 205, 205, 168, 53, 125, 24, 178, 145, 22, 245, 27, 242, 252, 160, 146, 82, 114, 130, 89, 189, 61, 149, 199, 175, 221, 115, 211, 17, 63, 231, 132, 44, 127, 202, 175, 222, 83, 212, 186, 107, 71, 111, 241, 152, 137, 57, 4, 243, 108, 120, 183, 254, 104, 68, 170, 134, 164, 72, 30, 176, 29, 68, 135, 156, 48, 90, 59, 212, 224, 220, 2, 11, 138, 3, 50, 116, 92, 41, 134, 166, 253, 202, 16, 217, 88, 113, 81, 113, 19, 107, 9, 170, 80, 65, 237, 186, 51, 55, 245, 108, 182, 201, 29, 59, 190, 211, 199, 43, 238, 51, 38, 60, 129, 99, 198, 240, 6, 111, 234, 241, 221, 29, 232, 129, 149, 138, 226, 71, 14, 247, 17, 170, 10, 189, 84, 21, 143, 121, 162, 111, 9, 221, 44, 184, 82, 225, 158, 208, 171, 47, 133, 2, 236, 38, 240, 93, 12, 10, 64, 180, 93, 91, 157, 21, 241, 84, 46, 242, 115, 187, 162, 193, 104, 160, 129, 27, 47, 95, 110, 175, 11, 131, 197, 3, 251, 41, 122, 51, 134, 239, 154, 176, 153, 36, 103, 166, 51, 252, 94, 147, 199, 70, 248, 89, 187, 253, 114, 63, 155, 50, 104, 108, 88, 95, 196, 197, 73, 98, 111, 8, 233, 49, 198, 7, 236, 200, 55, 197, 82, 216, 190, 191, 62, 87, 45, 176, 217, 219, 196, 58, 50, 117, 130, 203, 118, 156, 149, 34, 20, 129, 137, 121, 138, 215, 194, 76, 101, 109, 55, 234, 134, 31, 163, 220, 11, 6, 25, 47, 115, 193, 194, 138, 129, 213, 113, 56, 216, 229, 234, 173, 203, 184, 197, 48, 38, 63, 185, 75, 157, 207, 96, 148, 33, 231, 106, 136, 59, 19, 197, 154, 242, 56, 174, 130, 201, 161, 213, 237, 205, 113, 94, 210, 152, 253, 41, 130, 126, 81, 163, 157, 25, 202, 195, 77, 227, 28, 182, 91, 33, 164, 113, 120, 125, 38, 18, 192, 186, 48, 17, 180, 182, 43, 195, 41, 229, 157, 212, 253, 53, 111, 62, 142, 146, 110, 204, 251, 43, 121, 182, 12, 216, 168, 235, 102, 153, 53, 160, 234, 245, 183, 214, 214, 154, 225, 109, 119, 130, 23, 250, 52, 92, 243, 48, 142, 144, 9, 120, 175, 47, 50, 77, 185, 223, 136, 253, 121, 28, 57, 232, 236, 192, 185, 117, 219, 137, 228, 122, 229, 112, 179, 169, 50, 114, 204, 170, 223, 84, 106, 191, 124, 7, 7, 198, 114, 39, 48, 128, 120, 39, 38, 47, 62, 125, 80, 253, 240, 152, 111, 117, 195, 191, 31, 157, 237, 112, 54, 254, 120, 34, 147, 229, 30, 133, 52, 10, 158, 169, 96, 226, 81, 13, 1, 178, 172, 153, 96, 3, 114, 170, 243, 0, 230, 95, 48, 216, 114, 22, 103, 182, 58, 212, 51, 146, 82, 132, 237, 102, 50, 14, 170, 139, 198, 129, 81, 246, 40, 28, 17, 179, 210, 31, 131, 69, 188, 148, 237, 156, 196, 175, 113, 194, 182, 112, 70, 120, 69, 32, 162, 116, 81, 134, 39, 20, 39, 172, 71, 102, 141, 210, 187, 69, 172, 248, 183, 40, 73, 223, 19, 39, 62, 168, 77, 128, 144, 9, 209, 224, 126, 86, 72, 141, 103, 129, 129, 240, 127, 141, 253, 27, 237, 113, 230, 122, 99, 103, 7, 175, 205, 160, 54, 202, 32, 244, 134, 123, 250, 176, 17, 157, 49, 171, 94, 103, 216, 224, 53, 76, 233, 17, 46, 77, 207, 218, 88, 158, 97, 164, 56, 222, 248, 116, 70, 170, 79, 248, 118, 26, 96, 179, 237, 36, 155, 213, 7, 18, 116, 128, 188, 254, 45, 18, 17, 168, 134, 244, 7, 58, 226, 252, 101, 75, 174, 160, 231, 149, 69, 137, 206, 39, 149, 71, 173, 10, 14, 45, 201, 243, 158, 255, 165, 24, 92, 251, 228, 175, 213, 161, 133, 206, 252, 82, 24, 109, 78, 251, 186, 157, 8, 164, 232, 104, 58, 114, 41, 14, 61, 33, 149, 110, 29, 242, 245, 31, 181, 228, 181, 140, 232, 120, 178, 120, 117, 63, 103, 44, 172, 79, 121, 112, 21, 167, 115, 233, 124, 78, 24, 78, 7, 189, 206, 83, 190, 117, 18, 218, 185, 213, 101, 118, 43, 30, 66, 158, 146, 44, 208, 227, 211, 184, 224, 174, 5, 6, 97, 200, 180, 68, 223, 128, 124, 42, 179, 163, 213, 48, 164, 160, 142, 132, 201, 106, 107, 104, 146, 55, 201, 153, 159, 16, 130, 48, 65, 236, 169, 86, 7, 156, 155, 6, 166, 103, 152, 203, 141, 137, 209, 60, 123, 96, 142, 241, 45, 129, 42, 54, 11, 140, 223, 21, 241, 5, 79, 185, 48, 98, 2, 20, 25, 225, 24, 231, 249, 25, 79, 183, 172, 51, 7, 171, 66, 38, 216, 55, 190, 32, 223, 121, 141, 77, 246, 214, 216, 27, 92, 40, 167, 163, 228, 132, 155, 97, 228, 20, 88, 124, 97, 71, 63, 58, 165, 61, 6, 172, 12, 244, 168, 169, 97, 91, 175, 102, 231, 51, 190, 80, 7, 216, 168, 17, 233, 26, 128, 168, 168, 182, 43, 241, 201, 180, 225, 14, 250, 249, 216, 238, 38, 250, 104, 172, 77, 181, 119, 168, 234, 56, 182, 41, 246, 220, 32, 172, 214, 3, 118, 169, 134, 165, 236, 211, 143, 43, 181, 117, 161, 75, 186, 142, 161, 2, 97, 171, 112, 88, 201, 251, 244, 164, 227, 52, 228, 179, 51, 24, 20, 219, 200, 80, 195, 250, 152, 125, 123, 218, 195, 182, 63, 47, 6, 233, 19, 31, 255, 55, 255, 230, 69, 139, 113, 255, 217, 50, 16, 3, 56, 97, 212, 224, 107, 24, 57, 241, 213, 139, 94, 62, 157, 44, 3, 59, 6, 38, 140, 92, 24, 49, 63, 82, 199, 233, 101, 178, 12, 172, 56, 156, 32, 90, 85, 21, 196, 11, 62, 249, 237, 157, 152, 89, 187, 229, 18, 80, 147, 144, 130, 200, 165, 65, 220, 82, 63, 106, 229, 57, 211, 125, 75, 64, 140, 195, 9, 162, 197, 191, 6, 81, 147, 95, 189, 232, 177, 63, 103, 201, 50, 240, 227, 128, 194, 8, 242, 207, 97, 12, 229, 231, 128, 23, 119, 25, 248, 205, 223, 135, 145, 155, 135, 69, 129, 127, 243, 163, 53, 91, 10, 90, 179, 26, 180, 102, 53, 104, 205, 44, 180, 158, 149, 227, 120, 150, 236, 86, 172, 232, 251, 121, 37, 179, 86, 127, 48, 179, 114, 154, 205, 230, 160, 166, 241, 100, 245, 129, 172, 63, 253, 65, 65, 170, 222, 32, 250, 166, 247, 205, 32, 234, 125, 253, 219, 60, 175, 118, 122, 94, 135, 123, 156, 141, 79, 153, 113, 11, 135, 104, 175, 79, 26, 1, 172, 253, 210, 82, 118, 227, 155, 199, 49, 63, 197, 251, 164, 247, 13, 35, 149, 151, 42, 2, 191, 117, 214, 161, 167, 80, 102, 36, 72, 26, 7, 148, 94, 158, 85, 227, 124, 154, 195, 74, 117, 170, 114, 128, 93, 75, 251, 41, 128, 11, 116, 13, 234, 70, 188, 114, 77, 247, 36, 158, 118, 255, 160, 110, 184, 139, 96, 73, 247, 141, 57, 125, 221, 14, 2, 164, 69, 251, 7, 117, 107, 186, 39, 144, 108, 223, 59, 62, 209, 207, 139, 233, 245, 59, 230, 155, 234, 91, 241, 227, 105, 145, 28, 215, 244, 136, 35, 215, 200, 142, 73, 133, 210, 223, 237, 103, 169, 92, 209, 234, 116, 181, 34, 192, 164, 66, 235, 82, 17, 112, 55, 225, 187, 179, 236, 203, 38, 123, 70, 203, 85, 29, 41, 200, 139, 132, 60, 1, 16, 127, 42, 247, 186, 69, 57, 213, 113, 98, 221, 138, 128, 122, 40, 51, 157, 230, 23, 114, 39, 21, 22, 17, 6, 71, 5, 223, 183, 213, 202, 33, 195, 62, 107, 53, 48, 224, 100, 75, 148, 4, 207, 243, 226, 89, 60, 62, 229, 43, 138, 247, 241, 248, 236, 56, 19, 227, 193, 140, 219, 200, 217, 69, 84, 99, 227, 95, 167, 143, 196, 42, 125, 132, 214, 232, 42, 83, 20, 251, 214, 125, 113, 174, 182, 191, 107, 87, 228, 8, 111, 244, 149, 97, 111, 150, 236, 186, 147, 214, 82, 221, 30, 54, 3, 170, 110, 236, 126, 78, 128, 143, 211, 105, 194, 218, 232, 111, 13, 34, 92, 11, 243, 48, 95, 103, 250, 15, 15, 36, 213, 59, 241, 21, 223, 160, 192, 198, 74, 44, 18, 89, 49, 29, 119, 35, 18, 130, 140, 156, 79, 80, 41, 16, 139, 41, 151, 235, 108, 125, 2, 107, 77, 86, 245, 89, 86, 21, 87, 140, 2, 218, 85, 162, 218, 118, 91, 68, 251, 223, 0, 166, 38, 144, 82, 247, 80, 72, 130, 5, 71, 95, 54, 235, 253, 20, 225, 124, 209, 62, 238, 245, 240, 226, 64, 180, 166, 255, 140, 92, 102, 254, 138, 245, 181, 99, 74, 80, 83, 163, 38, 31, 168, 201, 93, 229, 142, 3, 235, 138, 136, 83, 114, 63, 245, 201, 50, 95, 125, 118, 28, 95, 7, 65, 113, 58, 16, 226, 116, 64, 196, 73, 15, 226, 193, 66, 2, 213, 201, 213, 69, 113, 246, 248, 185, 58, 179, 172, 88, 231, 131, 54, 170, 117, 78, 1, 75, 155, 28, 120, 205, 12, 125, 16, 228, 101, 78, 81, 204, 202, 210, 49, 122, 254, 107, 202, 55, 80, 26, 220, 109, 7, 38, 219, 168, 113, 81, 24, 25, 49, 128, 176, 175, 67, 111, 79, 213, 74, 134, 229, 143, 214, 119, 55, 235, 186, 71, 222, 202, 190, 158, 178, 215, 36, 174, 164, 89, 232, 196, 24, 104, 87, 24, 238, 151, 252, 36, 137, 78, 18, 215, 104, 255, 4, 148, 32, 83, 41, 184, 57, 193, 23, 55, 206, 139, 137, 112, 215, 254, 225, 176, 179, 112, 208, 122, 213, 42, 36, 197, 229, 190, 221, 112, 86, 92, 168, 77, 188, 69, 241, 197, 72, 56, 63, 217, 151, 77, 176, 96, 20, 187, 100, 243, 115, 249, 101, 93, 22, 82, 140, 160, 190, 136, 116, 223, 252, 25, 123, 132, 52, 72, 127, 12, 143, 141, 243, 67, 166, 50, 164, 81, 214, 211, 197, 213, 105, 18, 107, 116, 235, 234, 190, 138, 95, 233, 90, 168, 131, 176, 171, 38, 186, 97, 118, 118, 20, 210, 198, 107, 43, 202, 212, 236, 240, 124, 255, 215, 191, 18, 186, 157, 198, 165, 164, 25, 123, 242, 217, 46, 236, 117, 112, 246, 131, 196, 62, 236, 123, 143, 64, 60, 75, 174, 20, 72, 120, 244, 193, 132, 247, 181, 64, 161, 64, 207, 94, 175, 253, 1, 140, 252, 136, 167, 115, 226, 22, 236, 35, 69, 147, 1, 244, 98, 32, 26, 254, 104, 243, 161, 82, 10, 32, 203, 58, 122, 14, 88, 211, 168, 92, 168, 184, 95, 233, 131, 232, 110, 244, 45, 20, 231, 157, 225, 210, 6, 63, 216, 31, 124, 38, 68, 178, 180, 2, 212, 176, 233, 195, 216, 91, 62, 153, 150, 195, 156, 174, 202, 80, 117, 43, 105, 162, 62, 218, 134, 236, 63, 50, 192, 60, 175, 78, 147, 98, 225, 169, 69, 127, 107, 55, 177, 4, 76, 52, 25, 208, 199, 81, 25, 240, 73, 132, 227, 70, 121, 134, 127, 101, 116, 21, 106, 29, 169, 14, 222, 129, 29, 119, 156, 252, 3, 171, 192, 56, 53, 96, 162, 96, 181, 212, 207, 77, 48, 129, 205, 252, 163, 46, 178, 3, 251, 127, 118, 197, 58, 236, 248, 150, 131, 214, 247, 191, 210, 234, 148, 79, 224, 10, 244, 128, 180, 73, 108, 114, 199, 230, 99, 70, 185, 138, 119, 113, 173, 242, 218, 192, 5, 62, 63, 37, 69, 153, 8, 128, 183, 115, 156, 49, 138, 139, 12, 247, 136, 47, 181, 2, 57, 204, 217, 71, 147, 192, 92, 15, 97, 150, 92, 64, 181, 190, 137, 58, 96, 72, 73, 181, 233, 29, 2, 17, 46, 117, 160, 101, 89, 151, 127, 252, 68, 99, 185, 105, 223, 203, 210, 206, 146, 63, 64, 134, 66, 103, 195, 200, 107, 205, 47, 205, 158, 247, 89, 244, 129, 91, 80, 90, 218, 245, 109, 140, 12, 209, 170, 79, 195, 106, 74, 115, 61, 110, 232, 14, 171, 213, 15, 206, 233, 194, 102, 89, 250, 128, 14, 2, 146, 8, 115, 60, 11, 119, 215, 40, 75, 80, 10, 92, 243, 88, 161, 248, 222, 254, 112, 74, 28, 96, 181, 208, 141, 4, 84, 157, 88, 100, 104, 82, 46, 63, 167, 199, 199, 73, 145, 100, 227, 228, 150, 170, 22, 131, 224, 34, 138, 37, 160, 241, 63, 179, 190, 40, 176, 132, 126, 81, 26, 159, 66, 105, 76, 146, 105, 82, 37, 119, 81, 111, 180, 234, 142, 173, 3, 90, 201, 254, 232, 234, 252, 60, 169, 138, 116, 252, 185, 148, 128, 236, 97, 123, 143, 159, 208, 11, 242, 71, 207, 223, 5, 143, 179, 226, 222, 219, 156, 11, 205, 45, 139, 49, 22, 93, 221, 118, 159, 157, 90, 113, 230, 126, 9, 1, 156, 140, 159, 142, 111, 233, 172, 100, 16, 92, 100, 86, 90, 120, 234, 121, 234, 159, 121, 66, 169, 134, 187, 88, 175, 255, 193, 126, 104, 157, 110, 228, 58, 243, 142, 61, 6, 14, 167, 139, 32, 58, 151, 207, 103, 176, 114, 186, 221, 156, 174, 80, 252, 164, 188, 254, 184, 27, 175, 119, 211, 222, 75, 158, 165, 3, 9, 107, 26, 20, 240, 130, 44, 243, 115, 90, 254, 27, 226, 17, 161, 111, 119, 109, 190, 166, 216, 47, 60, 85, 127, 89, 235, 223, 63, 179, 221, 149, 134, 219, 109, 151, 47, 184, 158, 111, 232, 102, 141, 240, 255, 51, 77, 46, 146, 201, 110, 81, 196, 87, 63, 205, 193, 218, 221, 63, 62, 76, 210, 227, 20, 66, 46, 98, 120, 43, 154, 209, 233, 99, 223, 207, 143, 163, 208, 213, 81, 162, 130, 138, 66, 199, 231, 246, 180, 194, 96, 213, 225, 90, 55, 128, 162, 174, 178, 33, 119, 34, 252, 156, 84, 241, 248, 52, 153, 8, 92, 160, 248, 113, 130, 34, 122, 196, 239, 144, 90, 33, 234, 123, 71, 137, 169, 174, 164, 84, 20, 234, 172, 106, 32, 168, 169, 156, 25, 161, 229, 149, 81, 2, 238, 32, 122, 128, 3, 77, 240, 61, 79, 226, 230, 233, 45, 123, 183, 97, 183, 18, 253, 199, 56, 226, 113, 144, 67, 32, 250, 211, 60, 118, 138, 6, 33, 194, 6, 246, 25, 190, 151, 23, 88, 33, 198, 17, 21, 90, 160, 43, 5, 133, 108, 152, 135, 58, 38, 2, 113, 112, 136, 92, 86, 206, 139, 4, 16, 17, 5, 65, 114, 112, 141, 184, 56, 193, 65, 66, 230, 182, 9, 153, 96, 193, 212, 228, 47, 85, 247, 2, 237, 67, 145, 29, 52, 218, 170, 203, 238, 244, 4, 147, 147, 129, 237, 157, 163, 98, 21, 33, 210, 171, 163, 11, 76, 78, 180, 203, 6, 172, 231, 10, 77, 189, 245, 169, 229, 111, 44, 14, 224, 192, 238, 216, 216, 20, 84, 227, 60, 110, 58, 173, 143, 128, 195, 117, 168, 134, 92, 120, 63, 148, 206, 241, 99, 156, 201, 193, 179, 209, 218, 203, 121, 185, 111, 202, 232, 27, 132, 209, 55, 209, 76, 222, 191, 75, 237, 59, 62, 21, 178, 239, 158, 235, 73, 100, 140, 4, 186, 160, 196, 147, 115, 195, 78, 148, 214, 186, 67, 251, 132, 176, 14, 156, 82, 149, 245, 109, 185, 13, 229, 49, 171, 222, 223, 254, 38, 145, 212, 189, 139, 196, 94, 178, 32, 0, 234, 191, 59, 208, 76, 107, 167, 147, 184, 74, 44, 28, 93, 118, 198, 27, 219, 226, 131, 85, 197, 104, 254, 0, 99, 171, 190, 83, 214, 198, 25, 38, 156, 235, 91, 130, 77, 64, 233, 96, 217, 191, 199, 182, 98, 161, 149, 131, 154, 5, 155, 13, 54, 134, 158, 81, 248, 126, 123, 43, 36, 53, 34, 92, 6, 20, 133, 60, 108, 129, 6, 129, 30, 254, 23, 243, 244, 133, 169, 26, 213, 92, 160, 202, 177, 193, 160, 252, 47, 244, 173, 110, 188, 87, 158, 33, 38, 13, 154, 179, 51, 252, 172, 110, 144, 172, 178, 39, 110, 93, 126, 46, 38, 129, 35, 152, 52, 107, 153, 67, 174, 161, 234, 186, 57, 237, 138, 148, 57, 1, 220, 72, 87, 57, 178, 132, 174, 106, 126, 123, 127, 85, 37, 7, 199, 199, 220, 250, 186, 105, 90, 203, 54, 197, 179, 105, 119, 209, 113, 232, 78, 253, 133, 168, 199, 204, 2, 145, 241, 167, 29, 25, 63, 53, 249, 110, 15, 201, 212, 244, 103, 203, 115, 114, 153, 156, 207, 166, 177, 71, 152, 225, 222, 233, 218, 233, 83, 85, 197, 168, 212, 104, 142, 61, 221, 68, 91, 20, 229, 152, 50, 232, 26, 203, 21, 76, 105, 202, 166, 146, 73, 111, 160, 3, 18, 143, 189, 90, 193, 108, 219, 41, 155, 99, 91, 244, 238, 38, 250, 100, 163, 225, 237, 92, 168, 83, 176, 206, 53, 113, 155, 182, 19, 163, 201, 204, 60, 104, 197, 237, 7, 184, 7, 2, 111, 254, 25, 135, 17, 110, 7, 17, 252, 144, 20, 87, 40, 48, 53, 186, 14, 166, 237, 167, 20, 227, 189, 104, 200, 41, 98, 27, 122, 223, 241, 211, 219, 189, 255, 50, 16, 255, 107, 115, 166, 114, 254, 109, 38, 208, 155, 158, 109, 64, 222, 80, 32, 180, 137, 38, 119, 251, 240, 52, 26, 178, 229, 37, 77, 45, 18, 161, 136, 80, 226, 166, 59, 139, 120, 54, 145, 51, 49, 157, 178, 7, 154, 63, 228, 76, 38, 161, 143, 14, 142, 206, 222, 26, 255, 76, 149, 148, 38, 143, 97, 235, 104, 227, 51, 153, 112, 248, 204, 56, 123, 56, 149, 12, 180, 5, 92, 120, 163, 154, 99, 194, 22, 171, 225, 224, 97, 243, 233, 57, 51, 192, 97, 78, 186, 39, 108, 120, 204, 187, 243, 169, 248, 240, 205, 194, 28, 40, 92, 77, 51, 25, 113, 244, 238, 69, 90, 162, 144, 163, 113, 60, 99, 131, 204, 143, 103, 111, 93, 147, 93, 67, 62, 52, 204, 161, 111, 44, 222, 52, 108, 8, 24, 30, 41, 108, 214, 215, 193, 65, 39, 74, 82, 158, 132, 182, 119, 189, 74, 223, 158, 95, 15, 6, 186, 115, 150, 191, 92, 244, 12, 236, 90, 85, 128, 253, 50, 221, 219, 61, 202, 120, 235, 128, 80, 102, 167, 155, 219, 109, 47, 9, 130, 221, 67, 162, 144, 77, 250, 51, 214, 114, 10, 151, 235, 220, 117, 57, 200, 38, 97, 41, 208, 157, 236, 34, 4, 168, 210, 45, 209, 197, 33, 230, 214, 152, 134, 180, 175, 163, 104, 125, 92, 45, 63, 33, 100, 219, 51, 25, 79, 144, 20, 96, 49, 113, 169, 237, 93, 225, 51, 73, 39, 198, 110, 242, 105, 75, 239, 187, 212, 176, 30, 239, 99, 195, 217, 168, 187, 198, 132, 93, 184, 13, 120, 52, 200, 107, 94, 54, 219, 24, 118, 227, 47, 117, 183, 178, 143, 201, 156, 243, 119, 183, 156, 199, 148, 46, 51, 0, 49, 59, 201, 131, 118, 247, 200, 180, 108, 109, 50, 34, 54, 178, 166, 188, 69, 180, 146, 32, 164, 159, 103, 126, 77, 174, 62, 255, 82, 41, 232, 225, 123, 25, 207, 238, 30, 55, 7, 212, 227, 121, 60, 187, 27, 230, 105, 107, 139, 78, 185, 23, 219, 206, 228, 231, 156, 222, 106, 58, 111, 97, 157, 90, 98, 0, 214, 224, 25, 88, 131, 8, 208, 226, 22, 33, 227, 45, 191, 72, 28, 38, 147, 249, 56, 185, 55, 124, 87, 240, 238, 124, 10, 214, 83, 46, 106, 142, 44, 236, 202, 53, 228, 33, 181, 251, 177, 77, 152, 248, 44, 66, 247, 201, 196, 227, 241, 252, 124, 62, 149, 57, 232, 90, 243, 54, 99, 32, 182, 122, 209, 60, 234, 103, 77, 10, 187, 230, 94, 22, 247, 124, 184, 115, 35, 11, 130, 165, 94, 113, 38, 86, 235, 42, 253, 146, 154, 72, 146, 123, 81, 237, 128, 66, 20, 188, 121, 152, 158, 156, 86, 119, 135, 65, 187, 155, 146, 133, 233, 230, 39, 59, 104, 191, 124, 238, 5, 104, 27, 34, 159, 228, 245, 120, 120, 99, 131, 242, 240, 83, 161, 102, 55, 54, 238, 34, 11, 143, 188, 57, 115, 219, 4, 155, 173, 146, 237, 208, 3, 123, 31, 55, 20, 90, 214, 176, 123, 207, 122, 98, 174, 143, 2, 164, 228, 15, 200, 76, 173, 216, 212, 194, 222, 226, 201, 192, 86, 172, 45, 94, 1, 121, 18, 65, 221, 140, 98, 233, 135, 164, 41, 91, 239, 153, 76, 132, 75, 203, 55, 164, 221, 37, 133, 195, 185, 119, 173, 98, 56, 83, 174, 250, 116, 141, 52, 247, 22, 226, 50, 141, 111, 27, 180, 101, 70, 223, 122, 164, 157, 228, 190, 99, 153, 249, 209, 205, 87, 207, 68, 242, 12, 167, 203, 108, 239, 192, 34, 201, 112, 69, 3, 79, 141, 210, 227, 33, 14, 192, 29, 19, 2, 240, 167, 180, 186, 72, 203, 68, 112, 61, 131, 178, 203, 13, 26, 3, 75, 178, 186, 168, 105, 214, 140, 146, 104, 158, 244, 252, 3, 31, 35, 233, 157, 117, 227, 83, 147, 47, 100, 128, 32, 76, 124, 188, 58, 222, 161, 223, 61, 202, 132, 115, 207, 204, 147, 240, 207, 27, 62, 182, 27, 18, 231, 252, 252, 254, 216, 74, 37, 235, 204, 125, 90, 112, 126, 170, 189, 140, 154, 173, 12, 147, 235, 213, 98, 40, 185, 199, 209, 214, 92, 7, 62, 243, 219, 235, 111, 242, 23, 57, 67, 86, 221, 207, 59, 229, 63, 32, 216, 8, 37, 3, 201, 103, 80, 137, 188, 52, 140, 26, 203, 109, 246, 182, 204, 106, 2, 236, 218, 51, 44, 13, 202, 211, 118, 134, 53, 133, 153, 52, 168, 66, 113, 22, 101, 245, 108, 170, 110, 16, 228, 32, 100, 40, 173, 14, 10, 35, 23, 185, 172, 168, 41, 222, 30, 75, 12, 105, 179, 34, 244, 26, 144, 102, 200, 181, 190, 232, 22, 152, 168, 55, 232, 57, 76, 55, 244, 51, 221, 33, 191, 224, 79, 213, 53, 28, 7, 241, 171, 118, 111, 176, 71, 151, 124, 247, 39, 206, 24, 179, 126, 165, 25, 102, 40, 157, 238, 228, 144, 164, 69, 245, 17, 1, 193, 119, 104, 128, 190, 173, 217, 38, 205, 97, 72, 243, 205, 223, 243, 78, 244, 223, 39, 39, 105, 102, 217, 50, 109, 146, 80, 175, 6, 195, 187, 174, 107, 209, 224, 152, 121, 129, 93, 189, 81, 35, 123, 226, 137, 159, 111, 19, 113, 170, 98, 206, 106, 194, 116, 53, 24, 52, 49, 210, 128, 53, 29, 37, 88, 140, 245, 181, 33, 182, 20, 253, 79, 82, 228, 7, 217, 193, 188, 58, 56, 254, 137, 77, 160, 147, 82, 215, 150, 53, 127, 210, 209, 1, 180, 41, 253, 154, 84, 80, 198, 195, 79, 64, 33, 98, 117, 113, 154, 233, 114, 252, 151, 204, 17, 76, 172, 24, 81, 49, 104, 199, 152, 174, 172, 211, 42, 205, 246, 140, 44, 166, 33, 104, 92, 18, 193, 164, 42, 159, 139, 217, 233, 53, 239, 73, 31, 57, 238, 132, 44, 148, 76, 235, 184, 119, 223, 98, 240, 106, 68, 93, 115, 143, 173, 141, 76, 195, 251, 229, 238, 188, 82, 217, 159, 61, 60, 220, 45, 218, 4, 254, 65, 150, 22, 197, 187, 40, 112, 41, 178, 251, 226, 50, 107, 179, 157, 106, 134, 36, 100, 173, 38, 210, 197, 222, 197, 96, 245, 13, 116, 123, 179, 213, 29, 228, 44, 185, 240, 92, 157, 35, 110, 203, 17, 200, 109, 160, 97, 179, 18, 230, 183, 138, 89, 66, 84, 38, 193, 97, 148, 194, 226, 165, 198, 102, 37, 28, 192, 188, 91, 137, 188, 239, 183, 69, 1, 34, 30, 226, 120, 121, 148, 222, 174, 237, 90, 104, 136, 168, 173, 89, 200, 249, 148, 138, 202, 41, 110, 184, 140, 166, 167, 63, 83, 100, 161, 21, 158, 34, 163, 0, 230, 88, 242, 149, 99, 138, 15, 174, 40, 47, 195, 186, 167, 156, 4, 127, 198, 175, 75, 97, 196, 230, 110, 3, 88, 34, 81, 18, 19, 155, 18, 205, 122, 172, 79, 124, 118, 110, 107, 159, 237, 86, 126, 235, 12, 246, 172, 224, 98, 220, 59, 179, 241, 217, 98, 131, 29, 250, 115, 7, 55, 217, 149, 63, 202, 231, 65, 186, 131, 59, 237, 48, 10, 245, 60, 247, 159, 176, 227, 174, 251, 121, 87, 119, 221, 235, 184, 242, 118, 109, 189, 107, 82, 99, 174, 251, 202, 148, 225, 28, 254, 249, 119, 83, 135, 107, 254, 12, 165, 54, 162, 76, 199, 137, 35, 160, 61, 191, 20, 141, 248, 69, 34, 252, 84, 112, 153, 207, 139, 49, 35, 246, 121, 60, 59, 206, 232, 202, 186, 54, 193, 239, 158, 107, 2, 224, 120, 224, 189, 32, 47, 62, 212, 137, 141, 247, 8, 231, 193, 206, 159, 188, 160, 13, 224, 9, 124, 188, 23, 182, 218, 252, 207, 139, 34, 206, 104, 226, 254, 161, 236, 45, 189, 135, 67, 182, 31, 153, 59, 108, 200, 124, 108, 62, 59, 167, 7, 223, 72, 82, 48, 216, 74, 157, 204, 75, 116, 155, 11, 152, 122, 156, 202, 158, 227, 81, 250, 38, 39, 115, 62, 138, 214, 93, 181, 237, 115, 247, 51, 94, 141, 217, 180, 33, 165, 195, 52, 250, 203, 208, 213, 16, 2, 103, 74, 36, 14, 94, 145, 194, 58, 156, 71, 135, 95, 222, 141, 44, 47, 15, 150, 160, 200, 249, 35, 249, 24, 217, 196, 98, 61, 114, 24, 90, 93, 216, 12, 255, 136, 101, 41, 33, 227, 239, 68, 106, 252, 55, 152, 203, 178, 216, 97, 26, 48, 17, 37, 252, 29, 93, 174, 198, 86, 244, 150, 173, 64, 235, 192, 233, 249, 186, 195, 30, 123, 131, 104, 207, 56, 185, 197, 191, 54, 78, 64, 241, 79, 55, 33, 182, 208, 37, 175, 157, 189, 53, 176, 62, 234, 39, 229, 186, 83, 85, 168, 99, 184, 121, 96, 130, 99, 242, 58, 30, 159, 45, 125, 80, 58, 18, 80, 180, 139, 47, 41, 146, 204, 110, 150, 180, 89, 202, 211, 9, 96, 108, 117, 3, 154, 229, 119, 90, 146, 203, 74, 46, 2, 62, 200, 125, 153, 119, 253, 77, 206, 227, 127, 149, 118, 165, 98, 104, 28, 103, 130, 147, 68, 109, 116, 61, 151, 219, 115, 36, 102, 254, 3, 46, 18, 104, 59, 174, 33, 38, 161, 104, 29, 241, 139, 27, 208, 33, 37, 94, 147, 229, 71, 175, 43, 146, 43, 85, 26, 123, 188, 166, 171, 60, 34, 102, 162, 195, 180, 86, 220, 135, 162, 173, 143, 254, 74, 237, 114, 191, 214, 139, 244, 76, 100, 191, 165, 154, 198, 90, 213, 41, 39, 134, 174, 130, 121, 100, 49, 82, 119, 246, 209, 235, 182, 137, 175, 190, 142, 206, 157, 169, 76, 105, 92, 79, 97, 124, 240, 192, 80, 215, 239, 13, 229, 214, 194, 193, 113, 31, 89, 217, 130, 176, 238, 117, 173, 55, 101, 29, 100, 201, 197, 178, 71, 71, 128, 20, 196, 193, 70, 237, 153, 237, 37, 22, 5, 9, 113, 208, 4, 213, 49, 153, 188, 83, 177, 38, 167, 188, 73, 161, 64, 181, 10, 100, 20, 103, 245, 206, 185, 131, 196, 58, 74, 142, 238, 115, 244, 114, 15, 175, 51, 224, 217, 205, 205, 85, 196, 198, 127, 147, 218, 166, 130, 109, 40, 60, 176, 134, 229, 82, 38, 119, 97, 237, 169, 186, 36, 169, 153, 214, 140, 71, 111, 53, 138, 106, 19, 51, 144, 19, 42, 19, 57, 210, 66, 142, 254, 151, 166, 11, 88, 157, 210, 126, 88, 25, 56, 236, 94, 64, 106, 109, 40, 210, 115, 172, 27, 120, 187, 217, 144, 78, 234, 103, 110, 141, 253, 28, 87, 241, 107, 121, 96, 92, 103, 92, 73, 215, 215, 197, 150, 195, 166, 73, 27, 136, 88, 73, 20, 163, 172, 132, 204, 141, 142, 188, 228, 214, 108, 195, 76, 95, 141, 78, 227, 130, 88, 57, 93, 239, 67, 8, 212, 111, 211, 184, 45, 190, 35, 6, 17, 222, 5, 14, 132, 154, 12, 9, 70, 123, 48, 214, 8, 230, 7, 232, 120, 54, 212, 119, 170, 60, 160, 4, 223, 228, 163, 188, 168, 146, 73, 159, 223, 79, 83, 36, 199, 153, 57, 228, 175, 95, 181, 91, 175, 24, 8, 237, 215, 44, 176, 219, 108, 170, 209, 53, 239, 167, 241, 122, 184, 1, 21, 214, 8, 118, 12, 27, 149, 1, 159, 202, 33, 133, 227, 180, 158, 154, 80, 44, 39, 109, 142, 105, 254, 93, 153, 67, 52, 203, 46, 166, 140, 37, 110, 52, 178, 225, 95, 76, 140, 95, 198, 179, 230, 235, 124, 216, 84, 137, 200, 201, 109, 13, 121, 157, 15, 251, 2, 73, 137, 240, 180, 22, 47, 239, 58, 31, 166, 230, 207, 219, 221, 230, 227, 42, 59, 168, 27, 230, 167, 135, 223, 49, 225, 148, 253, 167, 58, 207, 167, 101, 229, 189, 64, 172, 179, 3, 141, 23, 191, 85, 66, 255, 24, 170, 251, 40, 45, 242, 142, 254, 83, 111, 75, 250, 255, 46, 4, 227, 16 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 20960; + return 19520; } uint32_t GetRawScriptsSize() { - return 144873; + return 134068; } } // selfhosted } // js diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/js-confdefs.h b/src/third_party/mozjs/platform/aarch64/macOS/build/js-confdefs.h index 48975428e0e..c3f50598c6e 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_CLOCK_MONOTONIC 1 @@ -56,12 +60,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR const -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 1 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".dylib" @@ -70,6 +72,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "aarch64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_DARWIN 1 diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/aarch64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/aarch64/macOS/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/AtomicOperationsGenerated.h b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/AtomicOperationsGenerated.h index e598860de3f..c27f32d6aa2 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/AtomicOperationsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/AtomicOperationsGenerated.h @@ -548,6 +548,9 @@ namespace jit { : "memory", "cc"); return res; } + inline void AtomicPause() { + asm volatile ("isb" ::: "memory"); + } inline void AtomicCopyUnalignedBlockDownUnsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); @@ -933,7 +936,29 @@ namespace jit { : [dst] "r" (dst_), [src] "r"(src_) : "memory"); } - inline void AtomicCopyByteUnsynchronized(uint8_t* dst, const uint8_t* src) { + inline void AtomicCopy32Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint32_t* dst_ = reinterpret_cast(dst); + const uint32_t* src_ = reinterpret_cast(src); + uint32_t scratch; + asm volatile ("ldr %w[scratch], [%x[src], 0]\n\t" +"str %w[scratch], [%x[dst], 0]\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy16Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint16_t* dst_ = reinterpret_cast(dst); + const uint16_t* src_ = reinterpret_cast(src); + uint16_t scratch; + asm volatile ("ldrh %w[scratch], [%x[src], 0]\n\t" +"strh %w[scratch], [%x[dst], 0]\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy8Unsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); uint8_t scratch; diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/js-confdefs.h b/src/third_party/mozjs/platform/aarch64/macOS/include/js-confdefs.h index 48975428e0e..c3f50598c6e 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_CLOCK_MONOTONIC 1 @@ -56,12 +60,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR const -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 1 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".dylib" @@ -70,6 +72,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "aarch64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_DARWIN 1 diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/js-config.h b/src/third_party/mozjs/platform/aarch64/macOS/include/js-config.h index e6a4e862c32..77afa830384 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/js-config.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +/* #undef XP_WIN */ +#define XP_UNIX 1 +#define XP_DARWIN 1 + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/aarch64/macOS/include/selfhosted.out.h b/src/third_party/mozjs/platform/aarch64/macOS/include/selfhosted.out.h index 61dcac32173..f92431e839c 100644 --- a/src/third_party/mozjs/platform/aarch64/macOS/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/aarch64/macOS/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 237, 125, 253, 119, 27, 55, 174, 232, 239, 254, 43, 38, 58, 189, 173, 188, 150, 189, 150, 147, 126, 108, 236, 164, 235, 186, 73, 215, 111, 147, 56, 199, 78, 119, 207, 185, 126, 57, 185, 19, 105, 236, 204, 90, 214, 168, 51, 82, 28, 183, 205, 251, 219, 31, 65, 130, 36, 192, 143, 153, 145, 44, 39, 182, 111, 114, 78, 235, 209, 12, 9, 130, 32, 0, 130, 32, 8, 158, 204, 198, 131, 105, 94, 140, 147, 113, 118, 241, 230, 48, 27, 20, 229, 176, 187, 154, 252, 177, 146, 36, 101, 54, 157, 149, 227, 164, 154, 14, 223, 28, 188, 253, 79, 54, 152, 190, 25, 148, 89, 58, 205, 186, 227, 217, 104, 180, 186, 189, 242, 113, 229, 68, 215, 125, 85, 252, 84, 20, 163, 44, 29, 119, 223, 179, 186, 247, 238, 189, 119, 202, 189, 152, 157, 191, 205, 74, 167, 216, 26, 47, 117, 148, 158, 103, 255, 74, 71, 179, 236, 191, 179, 178, 232, 126, 232, 37, 151, 172, 244, 135, 228, 209, 163, 71, 201, 101, 242, 231, 159, 73, 247, 67, 114, 79, 60, 127, 72, 190, 254, 90, 188, 128, 199, 75, 142, 216, 47, 217, 244, 121, 54, 125, 87, 12, 187, 255, 234, 37, 47, 21, 152, 237, 109, 241, 191, 247, 105, 153, 64, 169, 228, 81, 242, 175, 227, 151, 175, 225, 85, 126, 146, 116, 247, 171, 23, 162, 115, 7, 229, 175, 227, 97, 118, 146, 143, 179, 97, 23, 10, 173, 170, 138, 6, 131, 153, 254, 10, 213, 62, 98, 213, 123, 251, 213, 94, 58, 26, 165, 111, 71, 25, 175, 244, 234, 93, 89, 92, 188, 186, 156, 100, 79, 202, 178, 40, 187, 253, 173, 94, 50, 21, 191, 138, 19, 137, 192, 170, 134, 129, 176, 225, 29, 235, 194, 126, 245, 178, 44, 38, 89, 57, 189, 252, 103, 118, 217, 77, 203, 211, 217, 121, 54, 158, 42, 224, 208, 11, 128, 37, 122, 129, 32, 245, 247, 109, 11, 81, 21, 16, 180, 233, 84, 211, 50, 31, 159, 118, 128, 114, 228, 229, 229, 249, 219, 98, 212, 225, 35, 48, 201, 6, 121, 86, 237, 21, 99, 81, 101, 54, 152, 10, 180, 139, 183, 255, 233, 37, 162, 219, 233, 108, 52, 37, 239, 29, 146, 194, 43, 129, 140, 40, 188, 49, 176, 133, 52, 117, 213, 87, 209, 168, 33, 160, 67, 88, 31, 190, 67, 97, 197, 136, 18, 80, 140, 190, 223, 126, 215, 75, 58, 133, 44, 247, 77, 149, 124, 67, 208, 248, 38, 153, 32, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 154, 229, 163, 105, 62, 62, 146, 68, 233, 118, 42, 69, 136, 206, 106, 13, 135, 84, 46, 123, 212, 247, 98, 159, 145, 213, 86, 134, 111, 149, 228, 97, 75, 87, 248, 119, 152, 77, 138, 114, 250, 107, 149, 158, 102, 123, 197, 108, 60, 21, 210, 227, 55, 208, 75, 238, 203, 46, 169, 102, 172, 236, 234, 134, 29, 26, 201, 50, 253, 7, 61, 249, 183, 243, 247, 191, 99, 55, 13, 125, 18, 193, 73, 134, 132, 132, 130, 29, 81, 193, 19, 48, 11, 118, 99, 99, 67, 240, 95, 165, 112, 159, 150, 151, 216, 135, 129, 16, 139, 167, 88, 161, 11, 234, 68, 255, 120, 147, 78, 38, 163, 203, 158, 131, 93, 207, 178, 71, 47, 145, 240, 100, 47, 4, 152, 233, 224, 93, 210, 205, 28, 106, 103, 186, 143, 219, 46, 98, 187, 167, 167, 101, 118, 42, 52, 214, 18, 176, 227, 176, 150, 134, 226, 62, 140, 231, 56, 29, 45, 1, 67, 6, 106, 57, 8, 2, 167, 155, 134, 69, 21, 242, 105, 175, 152, 92, 254, 156, 78, 83, 212, 77, 130, 121, 186, 83, 209, 78, 54, 237, 37, 85, 49, 43, 7, 89, 47, 201, 62, 12, 70, 179, 97, 54, 220, 159, 102, 231, 21, 209, 19, 219, 53, 162, 36, 171, 58, 242, 68, 69, 245, 164, 44, 206, 133, 180, 190, 42, 80, 17, 96, 5, 173, 126, 206, 178, 75, 16, 102, 31, 185, 131, 82, 16, 251, 224, 98, 44, 84, 168, 69, 20, 128, 185, 104, 106, 220, 20, 36, 33, 140, 114, 178, 11, 226, 115, 34, 148, 89, 23, 90, 205, 5, 254, 98, 82, 74, 54, 183, 241, 113, 71, 34, 178, 49, 202, 198, 167, 211, 119, 248, 114, 109, 77, 67, 65, 68, 69, 5, 40, 117, 44, 191, 190, 222, 54, 58, 0, 197, 254, 222, 187, 180, 18, 8, 3, 34, 30, 41, 191, 254, 26, 11, 121, 156, 129, 19, 181, 150, 227, 253, 234, 201, 88, 76, 7, 37, 76, 74, 186, 191, 2, 224, 170, 172, 110, 85, 204, 207, 146, 252, 132, 98, 151, 134, 70, 178, 121, 168, 120, 44, 158, 94, 19, 29, 243, 113, 165, 150, 27, 126, 29, 159, 8, 69, 154, 149, 98, 80, 57, 95, 16, 70, 184, 57, 60, 128, 22, 205, 231, 30, 250, 69, 135, 115, 137, 35, 89, 204, 96, 130, 97, 246, 150, 249, 150, 143, 199, 230, 155, 249, 218, 57, 41, 138, 142, 164, 11, 83, 29, 187, 101, 153, 94, 62, 121, 159, 149, 151, 178, 87, 111, 211, 193, 217, 201, 56, 177, 86, 203, 1, 29, 193, 233, 187, 188, 50, 227, 39, 72, 39, 191, 61, 147, 36, 236, 30, 32, 45, 205, 240, 236, 162, 133, 83, 97, 129, 85, 57, 86, 155, 49, 107, 224, 219, 94, 178, 41, 12, 2, 137, 207, 134, 32, 228, 180, 0, 211, 103, 35, 3, 212, 172, 25, 224, 26, 112, 22, 231, 58, 51, 238, 103, 97, 46, 159, 79, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 68, 135, 124, 180, 31, 39, 253, 228, 71, 57, 79, 225, 167, 110, 127, 53, 121, 200, 141, 75, 195, 104, 103, 138, 201, 206, 4, 131, 9, 122, 136, 7, 203, 84, 146, 103, 197, 224, 36, 7, 150, 15, 100, 127, 0, 29, 97, 35, 76, 5, 104, 195, 85, 22, 69, 49, 109, 244, 146, 131, 227, 179, 215, 130, 53, 196, 3, 97, 34, 59, 242, 233, 168, 202, 182, 241, 237, 71, 194, 48, 214, 182, 44, 103, 25, 140, 251, 145, 152, 202, 170, 253, 241, 40, 31, 3, 249, 158, 1, 203, 153, 38, 45, 43, 8, 162, 112, 6, 57, 42, 206, 179, 155, 201, 31, 149, 192, 236, 110, 179, 199, 149, 185, 67, 141, 125, 13, 115, 32, 251, 180, 224, 14, 224, 3, 143, 57, 158, 22, 229, 147, 116, 240, 238, 102, 242, 199, 137, 66, 238, 238, 178, 200, 124, 236, 177, 29, 26, 127, 130, 71, 11, 30, 192, 225, 246, 216, 224, 121, 58, 185, 153, 44, 112, 158, 78, 110, 254, 240, 67, 237, 93, 89, 27, 196, 12, 151, 245, 202, 141, 115, 208, 3, 66, 173, 94, 133, 73, 160, 138, 32, 195, 36, 27, 74, 127, 13, 172, 163, 23, 96, 155, 160, 217, 178, 43, 139, 16, 224, 97, 30, 219, 109, 197, 91, 130, 135, 124, 245, 34, 237, 211, 155, 201, 90, 202, 118, 190, 237, 220, 181, 25, 224, 173, 94, 50, 45, 230, 231, 177, 51, 205, 94, 192, 59, 154, 105, 90, 78, 98, 170, 110, 96, 26, 11, 51, 221, 180, 88, 91, 211, 149, 12, 127, 6, 167, 183, 118, 172, 167, 216, 204, 227, 190, 195, 108, 56, 27, 220, 80, 219, 167, 148, 184, 125, 42, 238, 83, 42, 7, 127, 164, 131, 193, 236, 124, 54, 74, 137, 211, 48, 200, 153, 186, 93, 82, 94, 128, 225, 204, 170, 60, 30, 153, 176, 65, 8, 119, 73, 10, 82, 154, 36, 201, 20, 112, 247, 104, 179, 197, 252, 105, 18, 209, 151, 101, 86, 9, 208, 162, 33, 98, 24, 15, 11, 102, 85, 185, 220, 155, 208, 106, 212, 98, 74, 146, 183, 66, 80, 206, 28, 14, 75, 46, 222, 9, 138, 37, 221, 181, 53, 20, 143, 85, 187, 58, 188, 167, 33, 205, 135, 58, 39, 145, 16, 160, 181, 181, 215, 108, 29, 219, 94, 20, 57, 168, 144, 236, 153, 206, 17, 33, 52, 239, 172, 75, 202, 188, 34, 16, 237, 75, 57, 65, 88, 250, 145, 15, 248, 20, 158, 10, 24, 239, 184, 75, 81, 37, 111, 135, 249, 233, 187, 233, 23, 161, 83, 66, 7, 253, 90, 79, 250, 95, 68, 143, 139, 222, 250, 250, 89, 242, 248, 17, 78, 94, 203, 149, 188, 245, 117, 95, 242, 30, 171, 201, 112, 125, 253, 142, 10, 222, 211, 124, 60, 236, 78, 4, 119, 231, 3, 97, 22, 220, 32, 129, 19, 4, 25, 198, 197, 205, 96, 60, 143, 180, 145, 74, 159, 110, 241, 22, 177, 143, 98, 214, 145, 193, 177, 206, 56, 194, 129, 85, 95, 151, 177, 182, 19, 180, 14, 24, 224, 227, 225, 62, 120, 64, 191, 176, 199, 53, 175, 237, 155, 249, 32, 232, 233, 209, 92, 16, 100, 128, 245, 126, 235, 145, 151, 131, 236, 13, 63, 56, 232, 255, 157, 139, 145, 29, 219, 29, 2, 241, 32, 254, 100, 227, 97, 226, 237, 17, 47, 206, 19, 240, 189, 204, 132, 122, 202, 223, 103, 175, 100, 75, 178, 40, 236, 151, 157, 138, 5, 160, 106, 220, 148, 132, 229, 201, 138, 234, 61, 171, 178, 147, 108, 34, 89, 126, 148, 33, 17, 207, 211, 233, 187, 55, 231, 233, 7, 57, 173, 173, 57, 165, 97, 237, 131, 165, 31, 146, 210, 162, 171, 110, 57, 109, 226, 81, 36, 143, 128, 12, 12, 71, 73, 24, 83, 78, 109, 128, 48, 36, 85, 149, 150, 56, 30, 41, 50, 55, 161, 136, 197, 66, 24, 62, 145, 35, 36, 199, 137, 238, 230, 139, 102, 161, 165, 135, 4, 243, 76, 10, 62, 226, 45, 184, 100, 228, 32, 14, 144, 90, 162, 45, 138, 54, 35, 45, 11, 81, 148, 7, 176, 103, 46, 144, 101, 165, 21, 38, 235, 184, 133, 162, 12, 161, 105, 97, 52, 136, 36, 240, 14, 176, 194, 215, 95, 195, 255, 119, 20, 201, 215, 20, 48, 45, 32, 184, 15, 69, 63, 105, 123, 42, 81, 171, 92, 241, 63, 239, 3, 90, 25, 234, 237, 99, 106, 12, 153, 150, 93, 51, 230, 224, 120, 90, 188, 150, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 202, 226, 220, 184, 81, 200, 174, 175, 235, 183, 211, 194, 62, 75, 76, 244, 207, 143, 174, 225, 246, 25, 209, 93, 91, 179, 232, 218, 103, 31, 93, 171, 147, 14, 66, 230, 199, 104, 36, 84, 164, 156, 228, 42, 148, 171, 205, 107, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 89, 153, 202, 182, 217, 156, 6, 179, 149, 232, 196, 123, 109, 157, 68, 89, 64, 249, 162, 36, 35, 236, 79, 179, 50, 53, 129, 76, 103, 96, 144, 152, 65, 207, 229, 183, 108, 168, 134, 157, 114, 128, 40, 108, 104, 144, 35, 4, 241, 253, 69, 118, 193, 129, 202, 66, 191, 142, 171, 244, 36, 19, 83, 226, 161, 88, 44, 148, 239, 179, 225, 209, 168, 152, 118, 117, 53, 105, 102, 240, 150, 90, 213, 234, 107, 71, 90, 83, 193, 45, 236, 214, 182, 165, 134, 254, 232, 203, 133, 198, 252, 69, 246, 97, 218, 181, 148, 16, 253, 5, 189, 37, 248, 94, 235, 66, 27, 116, 5, 180, 144, 65, 119, 170, 208, 47, 179, 180, 28, 190, 42, 60, 226, 174, 174, 70, 54, 207, 121, 180, 2, 242, 2, 88, 84, 12, 132, 10, 215, 219, 63, 249, 119, 41, 93, 191, 122, 13, 2, 40, 233, 231, 142, 215, 131, 142, 252, 194, 172, 170, 84, 160, 168, 40, 246, 139, 67, 49, 201, 0, 155, 68, 48, 170, 217, 8, 6, 253, 15, 197, 80, 15, 105, 232, 204, 176, 24, 139, 23, 114, 205, 9, 27, 220, 138, 36, 105, 160, 131, 0, 99, 3, 74, 179, 181, 38, 118, 92, 125, 166, 216, 233, 184, 129, 26, 12, 251, 148, 241, 206, 255, 153, 75, 185, 53, 229, 133, 144, 222, 223, 122, 42, 180, 164, 95, 113, 139, 170, 44, 141, 243, 126, 245, 178, 168, 170, 252, 237, 232, 18, 9, 11, 166, 234, 80, 18, 178, 155, 26, 155, 79, 233, 184, 104, 73, 84, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 31, 105, 245, 115, 54, 77, 7, 239, 178, 225, 79, 179, 147, 19, 161, 102, 82, 230, 148, 117, 173, 243, 239, 127, 8, 57, 97, 233, 84, 226, 232, 229, 148, 234, 101, 109, 186, 43, 114, 63, 150, 62, 15, 221, 90, 88, 156, 20, 115, 144, 136, 144, 57, 7, 183, 6, 170, 16, 100, 133, 199, 26, 142, 173, 196, 204, 140, 173, 32, 98, 223, 225, 167, 247, 184, 170, 75, 89, 164, 72, 176, 93, 15, 214, 22, 93, 31, 78, 210, 28, 212, 150, 2, 211, 51, 240, 94, 111, 135, 90, 131, 194, 53, 45, 109, 43, 253, 194, 170, 72, 112, 68, 239, 232, 26, 45, 22, 8, 84, 140, 233, 26, 225, 43, 249, 85, 46, 64, 43, 30, 143, 18, 82, 234, 82, 61, 72, 178, 202, 38, 247, 210, 113, 49, 22, 171, 155, 209, 139, 244, 60, 235, 82, 80, 98, 165, 39, 145, 174, 58, 222, 130, 228, 201, 120, 90, 230, 237, 27, 219, 90, 245, 181, 170, 12, 45, 106, 89, 127, 51, 80, 31, 4, 122, 183, 186, 28, 15, 186, 41, 252, 95, 134, 123, 201, 77, 176, 147, 49, 53, 87, 122, 82, 29, 138, 133, 97, 216, 134, 217, 35, 42, 92, 175, 23, 36, 212, 189, 81, 81, 205, 74, 201, 81, 240, 51, 129, 165, 241, 99, 194, 38, 176, 219, 150, 143, 1, 170, 106, 242, 30, 181, 16, 172, 204, 235, 98, 194, 56, 166, 107, 98, 89, 135, 8, 115, 96, 69, 252, 170, 56, 146, 193, 90, 186, 172, 235, 231, 155, 85, 2, 238, 46, 118, 93, 79, 182, 150, 20, 129, 0, 221, 148, 22, 198, 48, 93, 133, 101, 8, 150, 163, 182, 147, 112, 131, 78, 151, 29, 244, 142, 106, 11, 71, 90, 190, 23, 10, 122, 246, 221, 10, 126, 205, 58, 229, 248, 125, 159, 80, 212, 82, 105, 213, 213, 152, 220, 240, 14, 117, 162, 150, 196, 185, 75, 93, 210, 203, 163, 122, 242, 134, 91, 115, 72, 102, 173, 254, 48, 216, 8, 237, 34, 212, 59, 138, 17, 111, 126, 242, 89, 196, 62, 18, 70, 104, 51, 194, 96, 38, 181, 238, 136, 222, 68, 229, 129, 225, 123, 171, 201, 143, 6, 143, 110, 32, 8, 124, 175, 151, 116, 187, 253, 100, 103, 39, 233, 127, 39, 236, 50, 161, 143, 86, 123, 54, 86, 219, 117, 247, 136, 210, 123, 171, 224, 64, 58, 54, 131, 200, 54, 223, 224, 31, 216, 220, 233, 69, 154, 79, 149, 83, 105, 44, 52, 178, 242, 43, 194, 185, 130, 209, 168, 184, 64, 160, 208, 33, 240, 220, 88, 167, 51, 209, 86, 124, 228, 25, 141, 122, 113, 174, 192, 47, 108, 192, 252, 224, 2, 131, 209, 54, 227, 1, 212, 71, 124, 176, 155, 195, 18, 164, 14, 50, 170, 180, 103, 161, 11, 59, 154, 240, 128, 11, 74, 81, 136, 188, 243, 217, 101, 174, 128, 6, 248, 7, 195, 112, 6, 118, 129, 43, 17, 187, 104, 205, 192, 119, 253, 205, 110, 63, 219, 146, 210, 226, 149, 38, 90, 126, 150, 209, 5, 12, 225, 235, 109, 83, 210, 53, 153, 116, 69, 106, 58, 213, 241, 229, 146, 248, 81, 173, 246, 86, 113, 61, 168, 108, 81, 187, 229, 233, 176, 39, 58, 34, 244, 182, 104, 56, 60, 64, 141, 141, 233, 15, 9, 22, 240, 153, 9, 185, 198, 140, 193, 143, 88, 187, 13, 171, 24, 183, 249, 170, 169, 254, 144, 121, 203, 231, 228, 0, 103, 252, 213, 152, 146, 177, 71, 67, 158, 143, 253, 71, 98, 112, 185, 83, 124, 55, 98, 92, 72, 27, 113, 9, 38, 69, 163, 165, 208, 218, 78, 104, 242, 155, 247, 17, 89, 223, 103, 142, 8, 107, 148, 164, 78, 33, 179, 76, 222, 110, 58, 195, 73, 196, 141, 66, 103, 208, 216, 25, 29, 111, 198, 9, 204, 54, 129, 153, 198, 221, 12, 200, 233, 92, 243, 241, 211, 8, 28, 155, 0, 28, 249, 50, 123, 9, 205, 106, 31, 121, 40, 214, 249, 54, 162, 86, 35, 100, 175, 28, 77, 76, 36, 204, 211, 255, 17, 33, 131, 8, 158, 112, 228, 88, 72, 163, 50, 153, 90, 169, 209, 165, 185, 81, 163, 109, 149, 104, 108, 68, 87, 20, 21, 150, 170, 70, 87, 20, 141, 124, 85, 58, 247, 38, 162, 146, 156, 51, 194, 39, 117, 195, 217, 52, 152, 158, 174, 228, 154, 178, 181, 158, 132, 161, 241, 85, 34, 141, 197, 226, 234, 78, 152, 118, 242, 184, 35, 241, 110, 201, 49, 138, 58, 120, 241, 56, 168, 44, 180, 241, 159, 34, 31, 19, 245, 16, 62, 217, 25, 242, 107, 145, 99, 27, 83, 196, 160, 167, 96, 186, 39, 61, 67, 100, 3, 240, 182, 184, 223, 165, 103, 133, 168, 149, 97, 199, 70, 242, 135, 144, 196, 98, 2, 101, 232, 25, 43, 218, 91, 170, 183, 67, 76, 235, 238, 159, 122, 46, 29, 125, 210, 163, 67, 37, 228, 36, 47, 171, 233, 147, 81, 118, 174, 226, 43, 36, 164, 227, 205, 215, 186, 161, 67, 235, 120, 242, 78, 212, 146, 154, 134, 148, 135, 2, 6, 54, 64, 151, 43, 135, 18, 91, 236, 47, 242, 79, 144, 110, 4, 230, 198, 148, 145, 169, 199, 80, 197, 163, 79, 180, 39, 85, 54, 73, 245, 164, 209, 233, 117, 60, 145, 233, 199, 69, 6, 20, 146, 75, 3, 45, 55, 135, 201, 218, 35, 11, 219, 174, 14, 3, 147, 13, 1, 67, 244, 168, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 205, 108, 171, 16, 9, 63, 30, 50, 134, 251, 138, 198, 116, 114, 159, 134, 98, 168, 168, 163, 5, 235, 244, 146, 14, 236, 155, 30, 171, 121, 119, 3, 143, 152, 190, 246, 253, 46, 60, 110, 180, 40, 243, 83, 112, 248, 203, 79, 82, 181, 1, 111, 90, 206, 222, 38, 108, 42, 53, 129, 224, 212, 117, 195, 170, 70, 61, 108, 82, 199, 152, 32, 185, 82, 137, 12, 184, 43, 198, 76, 115, 82, 15, 162, 54, 128, 88, 237, 208, 249, 102, 111, 226, 22, 150, 143, 120, 87, 22, 85, 117, 152, 165, 163, 115, 220, 247, 166, 69, 218, 226, 160, 192, 163, 218, 178, 213, 0, 173, 189, 198, 115, 203, 170, 250, 158, 164, 149, 45, 75, 17, 81, 46, 245, 142, 191, 249, 31, 68, 136, 46, 133, 247, 2, 203, 254, 230, 186, 186, 75, 123, 181, 199, 193, 107, 169, 113, 207, 165, 118, 204, 162, 124, 32, 56, 145, 12, 86, 224, 16, 120, 139, 105, 248, 254, 42, 221, 87, 105, 158, 143, 21, 182, 158, 9, 62, 74, 167, 112, 158, 65, 206, 109, 165, 174, 213, 42, 234, 69, 157, 114, 124, 214, 16, 251, 226, 216, 217, 164, 145, 121, 2, 85, 220, 154, 174, 229, 125, 125, 193, 226, 64, 32, 65, 208, 253, 241, 84, 109, 44, 129, 45, 112, 208, 179, 157, 151, 190, 249, 190, 139, 161, 176, 51, 232, 232, 4, 140, 1, 128, 219, 93, 18, 157, 161, 212, 48, 155, 76, 223, 189, 152, 157, 203, 233, 97, 37, 22, 119, 36, 196, 159, 146, 68, 104, 169, 160, 11, 136, 0, 179, 187, 175, 188, 34, 27, 130, 165, 16, 81, 55, 26, 39, 156, 7, 70, 20, 196, 72, 29, 241, 132, 167, 188, 205, 19, 192, 133, 31, 114, 231, 121, 5, 59, 5, 15, 206, 80, 173, 36, 122, 225, 182, 98, 135, 67, 129, 221, 199, 77, 49, 9, 131, 77, 195, 170, 9, 253, 93, 216, 176, 244, 197, 142, 197, 128, 125, 224, 49, 80, 180, 70, 62, 102, 135, 145, 245, 108, 158, 153, 153, 92, 125, 61, 38, 117, 152, 235, 211, 145, 15, 226, 119, 218, 182, 62, 29, 11, 173, 54, 94, 51, 68, 32, 253, 79, 251, 27, 200, 43, 132, 74, 95, 17, 44, 253, 215, 230, 133, 227, 20, 70, 102, 127, 87, 204, 70, 67, 28, 104, 30, 92, 171, 122, 42, 71, 145, 199, 125, 36, 94, 45, 61, 187, 34, 110, 94, 75, 146, 252, 180, 142, 235, 229, 195, 138, 142, 208, 225, 91, 238, 148, 146, 100, 97, 220, 18, 98, 83, 94, 178, 129, 126, 182, 245, 158, 87, 213, 163, 170, 34, 200, 122, 210, 15, 16, 214, 13, 112, 129, 126, 83, 92, 33, 212, 247, 67, 255, 132, 254, 171, 117, 80, 127, 251, 125, 63, 224, 139, 174, 61, 228, 77, 177, 78, 220, 241, 96, 157, 178, 17, 53, 225, 131, 189, 182, 164, 175, 77, 119, 167, 106, 71, 117, 153, 97, 51, 122, 56, 173, 6, 204, 49, 108, 16, 87, 167, 90, 205, 242, 10, 143, 201, 58, 5, 140, 117, 246, 213, 91, 78, 232, 176, 247, 181, 64, 185, 21, 29, 122, 189, 147, 108, 130, 255, 254, 204, 217, 47, 142, 229, 254, 209, 129, 39, 210, 240, 111, 177, 225, 185, 59, 245, 44, 224, 87, 197, 33, 156, 71, 175, 178, 97, 119, 25, 36, 221, 197, 112, 183, 197, 220, 0, 24, 214, 166, 130, 226, 206, 108, 224, 154, 254, 102, 67, 141, 73, 120, 87, 116, 21, 111, 106, 184, 171, 223, 240, 138, 93, 152, 97, 130, 8, 96, 141, 164, 101, 118, 130, 180, 151, 33, 172, 250, 149, 179, 209, 226, 248, 22, 109, 205, 136, 185, 243, 61, 155, 73, 23, 167, 177, 244, 145, 44, 76, 231, 0, 185, 208, 169, 118, 166, 98, 113, 153, 165, 11, 184, 236, 176, 232, 0, 29, 220, 115, 94, 57, 84, 245, 92, 17, 18, 183, 55, 85, 1, 225, 96, 216, 132, 165, 81, 56, 90, 255, 89, 90, 77, 111, 108, 72, 54, 32, 247, 105, 194, 178, 173, 63, 124, 9, 193, 217, 250, 172, 77, 232, 192, 199, 226, 1, 252, 254, 126, 196, 245, 135, 241, 195, 0, 4, 67, 249, 225, 195, 205, 14, 231, 55, 24, 222, 49, 6, 154, 135, 83, 174, 53, 208, 223, 16, 152, 49, 8, 108, 75, 233, 178, 50, 220, 240, 125, 58, 34, 14, 29, 18, 50, 116, 158, 253, 146, 141, 89, 144, 140, 40, 42, 6, 19, 92, 88, 29, 71, 91, 81, 168, 114, 140, 230, 7, 43, 207, 112, 133, 224, 234, 77, 141, 253, 161, 32, 103, 46, 148, 115, 208, 253, 197, 235, 152, 38, 150, 219, 69, 83, 122, 217, 125, 52, 197, 15, 37, 144, 249, 33, 171, 34, 10, 180, 10, 39, 10, 19, 17, 118, 36, 51, 19, 166, 170, 50, 76, 246, 84, 168, 165, 27, 129, 171, 247, 237, 72, 201, 13, 27, 194, 170, 237, 69, 104, 86, 69, 137, 146, 210, 27, 54, 65, 83, 196, 201, 74, 43, 174, 82, 221, 107, 2, 64, 227, 251, 191, 180, 110, 207, 180, 73, 79, 8, 26, 223, 156, 130, 22, 223, 11, 132, 244, 132, 174, 2, 209, 117, 130, 242, 135, 81, 206, 78, 222, 56, 68, 225, 231, 188, 52, 161, 185, 127, 172, 184, 184, 168, 104, 220, 176, 158, 12, 160, 33, 139, 83, 13, 6, 76, 105, 40, 13, 57, 29, 225, 69, 200, 213, 100, 11, 206, 163, 55, 105, 45, 199, 142, 65, 197, 134, 189, 124, 8, 141, 171, 85, 152, 173, 163, 126, 147, 0, 93, 120, 241, 209, 37, 20, 99, 69, 69, 45, 21, 147, 90, 46, 72, 52, 29, 17, 126, 77, 52, 34, 165, 130, 36, 105, 17, 2, 247, 48, 34, 136, 152, 8, 213, 83, 251, 122, 127, 72, 180, 102, 105, 220, 37, 2, 74, 202, 198, 54, 31, 180, 104, 200, 64, 215, 247, 116, 211, 85, 129, 84, 10, 162, 52, 170, 102, 230, 184, 94, 28, 169, 6, 58, 90, 129, 38, 66, 214, 74, 168, 27, 240, 229, 194, 236, 97, 108, 87, 218, 154, 240, 200, 100, 16, 249, 139, 69, 85, 236, 5, 246, 238, 99, 124, 2, 249, 71, 54, 18, 156, 246, 194, 161, 167, 182, 135, 194, 97, 246, 7, 42, 200, 254, 128, 132, 216, 251, 32, 187, 7, 11, 132, 217, 251, 96, 90, 4, 219, 171, 179, 51, 248, 163, 19, 233, 93, 32, 254, 254, 84, 79, 26, 209, 40, 119, 89, 231, 64, 129, 134, 83, 36, 204, 193, 78, 251, 176, 15, 129, 185, 227, 42, 31, 248, 19, 109, 207, 182, 99, 71, 177, 126, 52, 14, 61, 38, 188, 91, 227, 161, 250, 247, 89, 70, 68, 53, 189, 192, 152, 24, 227, 230, 110, 14, 137, 236, 222, 103, 25, 17, 217, 242, 92, 3, 98, 183, 167, 252, 243, 81, 201, 163, 128, 237, 97, 22, 115, 225, 253, 167, 249, 247, 157, 184, 13, 146, 51, 74, 226, 217, 171, 192, 104, 155, 245, 36, 37, 170, 219, 51, 107, 201, 234, 46, 153, 70, 161, 250, 2, 90, 167, 230, 100, 22, 51, 97, 20, 150, 56, 144, 234, 143, 129, 225, 140, 43, 175, 226, 155, 215, 127, 153, 167, 91, 102, 12, 71, 98, 109, 102, 252, 0, 202, 112, 201, 134, 210, 54, 39, 135, 90, 108, 206, 225, 203, 60, 27, 97, 124, 54, 45, 72, 54, 8, 228, 242, 148, 76, 225, 96, 6, 24, 35, 154, 29, 47, 179, 72, 25, 36, 204, 92, 123, 15, 170, 201, 179, 53, 250, 205, 124, 112, 148, 80, 49, 91, 66, 31, 74, 145, 144, 223, 211, 112, 177, 80, 151, 225, 159, 1, 39, 222, 203, 142, 199, 66, 154, 96, 8, 105, 204, 36, 183, 27, 34, 132, 82, 39, 150, 228, 41, 198, 145, 38, 47, 200, 138, 41, 110, 209, 143, 46, 156, 178, 33, 91, 28, 196, 132, 23, 115, 154, 97, 234, 221, 43, 75, 176, 129, 51, 135, 12, 219, 58, 215, 35, 197, 170, 139, 33, 142, 55, 45, 223, 90, 81, 110, 209, 183, 47, 242, 220, 66, 158, 229, 33, 205, 232, 98, 94, 211, 50, 32, 201, 116, 5, 225, 43, 5, 214, 246, 199, 0, 14, 159, 71, 232, 95, 165, 103, 89, 119, 148, 159, 231, 211, 121, 229, 93, 173, 188, 206, 211, 124, 172, 98, 185, 237, 222, 155, 2, 167, 117, 130, 45, 179, 227, 56, 94, 15, 211, 241, 41, 42, 131, 239, 254, 214, 191, 38, 145, 135, 14, 134, 132, 194, 160, 117, 123, 37, 190, 185, 107, 215, 44, 240, 219, 132, 1, 30, 131, 95, 217, 252, 180, 254, 229, 171, 232, 3, 197, 243, 168, 18, 2, 11, 244, 232, 89, 176, 101, 205, 228, 209, 106, 75, 23, 86, 162, 79, 194, 158, 188, 214, 117, 99, 146, 254, 115, 89, 76, 238, 180, 164, 67, 7, 239, 168, 164, 55, 119, 205, 12, 233, 141, 19, 236, 182, 210, 204, 101, 216, 30, 106, 97, 170, 235, 78, 89, 26, 159, 83, 223, 180, 50, 14, 118, 43, 185, 33, 151, 13, 95, 166, 121, 89, 117, 23, 209, 27, 203, 19, 111, 142, 140, 47, 13, 183, 87, 186, 27, 123, 182, 52, 225, 94, 186, 60, 245, 200, 37, 38, 75, 18, 173, 158, 190, 247, 228, 154, 100, 76, 231, 177, 144, 213, 95, 223, 28, 97, 227, 225, 221, 119, 205, 127, 134, 189, 187, 139, 62, 180, 230, 174, 45, 119, 114, 94, 108, 246, 93, 68, 44, 151, 51, 205, 217, 51, 128, 181, 219, 228, 141, 30, 50, 39, 195, 128, 188, 80, 40, 122, 214, 84, 129, 227, 219, 122, 74, 254, 109, 189, 207, 185, 26, 175, 11, 122, 192, 244, 238, 42, 169, 115, 153, 196, 84, 65, 205, 238, 116, 84, 45, 32, 204, 121, 244, 130, 169, 66, 21, 67, 171, 124, 207, 44, 43, 145, 199, 174, 33, 30, 208, 29, 148, 251, 224, 54, 225, 89, 48, 86, 2, 138, 204, 23, 41, 161, 106, 216, 113, 136, 154, 164, 46, 44, 126, 61, 34, 207, 167, 204, 229, 128, 5, 12, 55, 38, 185, 94, 241, 152, 250, 125, 148, 159, 13, 45, 86, 131, 208, 227, 52, 197, 62, 225, 48, 234, 157, 38, 47, 171, 115, 32, 167, 179, 68, 70, 169, 0, 141, 110, 56, 105, 115, 29, 51, 99, 146, 183, 176, 241, 248, 71, 187, 144, 4, 149, 106, 8, 152, 90, 237, 157, 211, 24, 218, 99, 115, 106, 148, 89, 34, 139, 211, 53, 30, 94, 139, 118, 9, 213, 75, 132, 38, 185, 138, 168, 173, 167, 134, 190, 150, 72, 71, 39, 47, 71, 170, 231, 75, 235, 78, 211, 33, 92, 129, 253, 226, 46, 210, 113, 68, 137, 55, 233, 61, 121, 161, 215, 237, 167, 76, 131, 3, 57, 68, 29, 63, 172, 166, 140, 196, 220, 154, 107, 177, 234, 8, 169, 174, 206, 187, 27, 148, 188, 55, 55, 45, 61, 98, 186, 115, 249, 138, 67, 230, 6, 145, 133, 28, 244, 119, 131, 150, 87, 229, 74, 98, 238, 121, 107, 25, 137, 127, 32, 109, 66, 83, 82, 208, 8, 33, 238, 247, 146, 142, 124, 234, 64, 28, 42, 130, 237, 232, 4, 124, 252, 10, 230, 113, 122, 158, 233, 248, 57, 241, 8, 159, 240, 149, 250, 227, 164, 170, 69, 184, 50, 93, 45, 162, 11, 229, 204, 26, 230, 188, 58, 69, 104, 231, 89, 5, 199, 122, 225, 131, 122, 41, 255, 239, 130, 99, 144, 68, 9, 51, 228, 166, 245, 78, 199, 9, 33, 17, 165, 116, 7, 228, 145, 64, 4, 235, 149, 211, 221, 33, 44, 43, 129, 174, 37, 157, 135, 73, 71, 252, 145, 128, 98, 163, 0, 249, 86, 94, 149, 105, 62, 18, 207, 98, 225, 38, 254, 100, 60, 24, 185, 241, 110, 96, 6, 78, 5, 130, 247, 196, 140, 187, 10, 8, 252, 223, 113, 199, 137, 151, 12, 198, 48, 227, 136, 31, 205, 170, 73, 38, 168, 54, 228, 241, 192, 110, 114, 28, 26, 227, 15, 97, 58, 226, 149, 169, 64, 191, 5, 99, 11, 253, 243, 145, 32, 113, 166, 126, 36, 24, 135, 135, 227, 72, 171, 199, 254, 232, 176, 94, 117, 240, 189, 103, 67, 58, 56, 10, 81, 7, 219, 127, 24, 193, 53, 158, 43, 22, 244, 145, 9, 15, 244, 161, 239, 87, 135, 179, 49, 120, 97, 93, 192, 142, 240, 60, 248, 206, 217, 67, 176, 107, 204, 57, 162, 201, 147, 192, 149, 207, 114, 152, 90, 246, 214, 20, 131, 84, 15, 164, 4, 237, 158, 186, 9, 37, 211, 214, 129, 207, 76, 78, 228, 250, 93, 225, 38, 18, 212, 181, 56, 59, 41, 226, 137, 22, 62, 51, 195, 152, 99, 2, 55, 130, 99, 220, 35, 9, 119, 133, 101, 104, 104, 230, 242, 84, 144, 28, 193, 79, 165, 124, 228, 70, 226, 123, 200, 5, 223, 136, 64, 45, 219, 149, 238, 33, 146, 207, 201, 120, 176, 23, 90, 78, 4, 46, 100, 164, 0, 233, 238, 41, 36, 75, 144, 152, 218, 132, 241, 194, 126, 131, 211, 246, 88, 67, 123, 78, 229, 209, 97, 157, 123, 25, 245, 111, 189, 248, 89, 216, 84, 93, 123, 160, 80, 50, 91, 195, 162, 146, 188, 82, 127, 154, 135, 212, 162, 135, 121, 44, 89, 208, 36, 110, 121, 12, 42, 224, 127, 140, 158, 247, 209, 103, 110, 100, 167, 124, 183, 211, 78, 178, 133, 195, 26, 206, 46, 198, 161, 111, 208, 19, 8, 206, 39, 253, 211, 38, 31, 107, 200, 198, 16, 7, 29, 47, 164, 127, 210, 34, 214, 243, 98, 100, 189, 246, 160, 80, 192, 249, 133, 37, 28, 235, 209, 230, 214, 14, 29, 8, 82, 169, 198, 243, 74, 174, 105, 122, 201, 185, 58, 25, 97, 181, 40, 125, 129, 89, 195, 85, 89, 43, 73, 231, 250, 20, 134, 0, 139, 103, 70, 36, 208, 70, 55, 15, 219, 38, 118, 90, 210, 186, 3, 106, 60, 111, 221, 64, 238, 195, 182, 96, 246, 217, 32, 240, 189, 21, 5, 80, 29, 11, 34, 109, 18, 40, 60, 63, 183, 60, 77, 88, 22, 231, 52, 39, 109, 215, 111, 196, 142, 116, 0, 3, 194, 43, 206, 81, 18, 39, 51, 68, 123, 2, 123, 253, 215, 10, 217, 57, 51, 23, 116, 198, 219, 3, 46, 1, 238, 51, 114, 17, 225, 63, 72, 89, 41, 215, 125, 24, 64, 15, 171, 36, 248, 11, 43, 37, 56, 80, 43, 22, 172, 181, 39, 161, 52, 124, 115, 28, 138, 98, 108, 70, 76, 53, 253, 230, 141, 60, 167, 251, 230, 205, 67, 217, 148, 146, 34, 46, 83, 205, 199, 190, 188, 173, 31, 213, 72, 76, 78, 48, 107, 136, 92, 203, 75, 226, 151, 25, 208, 69, 45, 147, 104, 38, 189, 248, 114, 87, 197, 203, 144, 90, 96, 108, 88, 218, 200, 68, 5, 157, 74, 173, 122, 107, 157, 220, 45, 233, 204, 71, 255, 156, 156, 149, 106, 206, 114, 74, 169, 175, 123, 229, 159, 166, 58, 231, 231, 168, 8, 131, 137, 70, 212, 20, 77, 239, 116, 156, 143, 255, 62, 206, 205, 131, 64, 27, 219, 72, 156, 64, 6, 142, 239, 206, 45, 181, 127, 219, 155, 165, 100, 54, 220, 131, 224, 9, 212, 8, 155, 28, 160, 66, 49, 94, 134, 102, 134, 127, 151, 86, 251, 227, 106, 154, 142, 7, 58, 9, 53, 159, 114, 72, 178, 200, 188, 122, 169, 15, 171, 31, 156, 40, 38, 183, 163, 106, 62, 117, 59, 86, 221, 114, 57, 89, 33, 147, 12, 105, 214, 49, 28, 40, 15, 104, 78, 186, 80, 190, 46, 181, 53, 12, 134, 237, 211, 2, 54, 215, 242, 161, 81, 132, 77, 27, 180, 8, 129, 237, 204, 186, 120, 181, 173, 222, 119, 5, 126, 133, 239, 236, 98, 97, 54, 166, 33, 164, 157, 139, 109, 230, 57, 76, 20, 164, 193, 2, 167, 137, 66, 112, 218, 92, 111, 19, 235, 78, 224, 4, 17, 225, 218, 240, 1, 162, 3, 122, 213, 13, 99, 216, 104, 249, 190, 123, 200, 168, 238, 192, 39, 145, 189, 134, 1, 193, 69, 221, 221, 25, 146, 232, 65, 187, 246, 131, 98, 114, 181, 182, 59, 213, 222, 242, 252, 43, 59, 48, 156, 248, 158, 42, 124, 79, 78, 181, 170, 217, 197, 81, 159, 115, 29, 132, 15, 104, 88, 114, 248, 117, 177, 65, 119, 34, 84, 22, 24, 110, 14, 161, 205, 64, 251, 200, 47, 116, 110, 207, 140, 112, 8, 193, 248, 9, 214, 72, 16, 48, 71, 234, 74, 130, 244, 249, 105, 122, 133, 243, 169, 237, 168, 26, 56, 133, 218, 64, 215, 120, 204, 150, 68, 38, 76, 219, 107, 179, 94, 174, 39, 14, 172, 217, 88, 49, 121, 48, 132, 25, 208, 38, 56, 140, 80, 207, 13, 156, 2, 154, 211, 89, 130, 196, 135, 213, 216, 1, 10, 129, 250, 248, 174, 86, 130, 68, 121, 196, 95, 46, 255, 101, 1, 204, 45, 91, 84, 138, 189, 246, 4, 193, 71, 153, 228, 162, 134, 56, 176, 96, 13, 179, 159, 25, 138, 74, 242, 107, 216, 229, 67, 40, 50, 201, 100, 34, 161, 235, 131, 129, 74, 100, 75, 131, 41, 234, 247, 27, 97, 171, 137, 185, 110, 120, 130, 14, 226, 255, 51, 145, 96, 243, 196, 128, 245, 52, 70, 136, 171, 138, 228, 82, 160, 212, 27, 141, 241, 26, 230, 84, 253, 24, 52, 219, 213, 9, 71, 155, 114, 233, 6, 10, 236, 50, 147, 72, 93, 159, 216, 134, 15, 27, 186, 252, 111, 209, 186, 105, 194, 59, 47, 254, 95, 68, 152, 136, 112, 149, 141, 132, 72, 68, 133, 152, 100, 14, 107, 146, 99, 153, 220, 21, 161, 217, 62, 122, 103, 33, 62, 182, 23, 241, 248, 121, 198, 207, 33, 220, 42, 44, 77, 158, 149, 122, 6, 56, 37, 228, 42, 105, 193, 52, 227, 129, 115, 130, 234, 94, 151, 149, 150, 249, 73, 219, 30, 164, 186, 62, 97, 15, 157, 51, 116, 69, 133, 226, 125, 227, 164, 189, 77, 7, 2, 71, 169, 110, 133, 172, 243, 131, 119, 44, 187, 97, 109, 125, 187, 56, 212, 113, 69, 203, 80, 15, 158, 232, 2, 122, 235, 235, 17, 4, 147, 228, 109, 153, 165, 44, 115, 96, 64, 164, 227, 7, 23, 191, 136, 244, 162, 34, 29, 58, 80, 120, 171, 68, 186, 77, 7, 110, 171, 72, 47, 75, 24, 153, 106, 88, 95, 135, 52, 192, 155, 13, 179, 108, 216, 108, 174, 61, 153, 116, 19, 140, 230, 155, 190, 202, 141, 28, 17, 186, 37, 43, 221, 249, 176, 191, 93, 178, 118, 27, 86, 187, 230, 180, 211, 190, 21, 184, 200, 54, 147, 106, 175, 39, 201, 28, 171, 253, 130, 177, 57, 253, 98, 120, 157, 16, 161, 254, 152, 149, 165, 4, 133, 211, 139, 53, 184, 234, 170, 31, 247, 48, 214, 28, 150, 126, 195, 41, 169, 155, 160, 150, 150, 117, 218, 170, 89, 49, 57, 231, 177, 8, 87, 235, 238, 55, 28, 207, 178, 50, 176, 174, 72, 62, 207, 65, 166, 196, 21, 161, 101, 207, 98, 26, 252, 14, 157, 192, 56, 86, 236, 40, 162, 69, 71, 95, 138, 202, 131, 40, 120, 213, 240, 94, 133, 58, 46, 69, 133, 147, 30, 145, 114, 36, 117, 109, 45, 96, 150, 7, 176, 14, 159, 44, 139, 159, 172, 242, 215, 183, 145, 227, 84, 159, 203, 20, 174, 103, 77, 236, 212, 241, 198, 198, 198, 124, 131, 255, 58, 188, 237, 30, 61, 61, 117, 19, 164, 125, 241, 83, 29, 237, 100, 252, 154, 166, 169, 182, 199, 65, 92, 94, 15, 42, 101, 121, 132, 235, 139, 127, 245, 186, 199, 172, 69, 210, 254, 186, 225, 91, 224, 184, 153, 55, 210, 234, 140, 217, 151, 161, 254, 20, 67, 125, 111, 153, 99, 221, 124, 26, 46, 176, 111, 50, 30, 126, 25, 234, 91, 39, 213, 117, 107, 123, 177, 158, 35, 23, 96, 238, 143, 115, 196, 77, 16, 211, 142, 175, 88, 77, 144, 161, 149, 118, 230, 112, 40, 251, 45, 190, 108, 84, 89, 48, 85, 189, 44, 82, 55, 12, 56, 166, 170, 156, 103, 45, 2, 93, 4, 201, 206, 227, 167, 26, 1, 197, 240, 169, 13, 93, 183, 230, 112, 194, 183, 189, 164, 35, 250, 222, 97, 161, 253, 33, 162, 75, 244, 228, 162, 182, 103, 112, 58, 222, 124, 77, 126, 244, 95, 251, 243, 224, 115, 25, 233, 35, 141, 20, 0, 250, 54, 29, 156, 193, 92, 106, 111, 115, 113, 238, 111, 132, 30, 63, 143, 138, 207, 115, 21, 129, 241, 220, 70, 96, 8, 248, 230, 219, 220, 193, 23, 162, 114, 139, 136, 11, 130, 55, 249, 74, 110, 18, 236, 216, 78, 58, 129, 24, 46, 43, 88, 80, 243, 136, 37, 173, 69, 229, 50, 131, 124, 48, 89, 229, 198, 66, 42, 239, 235, 228, 13, 126, 238, 37, 207, 237, 73, 206, 116, 162, 84, 152, 40, 119, 40, 29, 28, 144, 97, 73, 0, 56, 29, 21, 111, 83, 160, 71, 224, 51, 84, 190, 120, 39, 208, 73, 186, 114, 21, 77, 86, 243, 16, 244, 164, 22, 64, 114, 73, 155, 78, 158, 136, 54, 47, 5, 45, 180, 162, 236, 26, 36, 194, 77, 147, 109, 47, 158, 113, 194, 241, 131, 171, 230, 206, 178, 75, 37, 106, 1, 72, 120, 91, 54, 207, 201, 18, 41, 218, 199, 162, 81, 72, 137, 98, 163, 218, 82, 125, 94, 42, 36, 50, 1, 142, 55, 106, 74, 244, 69, 143, 12, 8, 140, 116, 148, 213, 12, 130, 104, 75, 5, 215, 135, 63, 131, 183, 141, 202, 28, 245, 52, 44, 24, 219, 68, 160, 44, 18, 216, 68, 170, 183, 137, 106, 114, 112, 14, 4, 52, 45, 204, 187, 24, 17, 248, 47, 126, 204, 170, 230, 168, 105, 59, 206, 62, 168, 229, 105, 73, 93, 202, 210, 58, 69, 199, 63, 229, 89, 36, 27, 146, 181, 63, 158, 222, 223, 130, 240, 105, 55, 54, 107, 139, 184, 171, 180, 51, 82, 203, 138, 5, 196, 119, 143, 140, 59, 182, 65, 70, 112, 245, 239, 129, 234, 183, 7, 213, 231, 160, 116, 53, 115, 101, 171, 169, 127, 28, 197, 37, 70, 64, 1, 251, 53, 21, 253, 101, 138, 169, 98, 132, 13, 173, 32, 40, 97, 241, 19, 142, 188, 245, 178, 174, 16, 159, 48, 148, 224, 23, 187, 11, 214, 152, 243, 90, 119, 91, 163, 205, 165, 238, 224, 103, 46, 139, 217, 228, 39, 147, 117, 133, 76, 7, 230, 36, 146, 31, 203, 42, 11, 199, 102, 25, 28, 163, 111, 31, 104, 249, 115, 167, 28, 85, 91, 127, 205, 85, 106, 153, 128, 57, 218, 49, 98, 180, 252, 153, 175, 31, 159, 249, 246, 146, 232, 213, 235, 198, 150, 177, 246, 218, 56, 187, 72, 246, 236, 126, 196, 89, 123, 51, 213, 161, 226, 182, 149, 72, 53, 21, 53, 41, 125, 223, 58, 61, 35, 82, 141, 55, 202, 70, 39, 112, 121, 7, 173, 180, 183, 68, 107, 100, 166, 180, 245, 66, 247, 95, 39, 97, 96, 21, 5, 214, 75, 142, 85, 182, 191, 213, 160, 16, 7, 50, 254, 232, 54, 205, 61, 184, 21, 222, 44, 232, 92, 80, 36, 255, 127, 70, 28, 213, 54, 197, 67, 58, 97, 146, 243, 98, 118, 254, 54, 43, 223, 228, 149, 88, 76, 9, 50, 119, 199, 179, 115, 203, 207, 104, 18, 139, 119, 234, 224, 207, 88, 22, 118, 15, 110, 134, 100, 20, 170, 172, 203, 255, 75, 221, 24, 110, 242, 69, 250, 98, 153, 237, 221, 147, 146, 113, 30, 110, 75, 167, 6, 86, 32, 67, 77, 138, 215, 173, 91, 37, 187, 237, 254, 70, 59, 54, 177, 205, 176, 3, 232, 235, 182, 78, 156, 40, 71, 98, 66, 250, 60, 200, 202, 220, 32, 46, 166, 247, 232, 212, 86, 51, 0, 235, 221, 238, 86, 242, 151, 191, 36, 223, 222, 95, 133, 59, 29, 87, 97, 87, 87, 195, 248, 250, 107, 243, 40, 222, 178, 114, 252, 40, 155, 52, 33, 44, 99, 152, 190, 99, 27, 140, 113, 94, 21, 234, 167, 46, 184, 26, 6, 101, 217, 58, 10, 13, 139, 212, 3, 84, 6, 154, 208, 118, 7, 23, 99, 45, 142, 63, 103, 213, 160, 204, 39, 66, 225, 85, 244, 212, 149, 74, 45, 99, 46, 6, 61, 176, 42, 47, 187, 212, 215, 235, 30, 102, 39, 16, 94, 246, 166, 184, 24, 255, 83, 188, 237, 234, 3, 101, 210, 232, 177, 96, 193, 84, 250, 200, 148, 164, 201, 38, 214, 195, 75, 70, 1, 40, 42, 129, 109, 252, 138, 119, 243, 230, 252, 194, 120, 171, 47, 161, 138, 74, 55, 74, 140, 117, 104, 85, 124, 171, 239, 167, 58, 86, 200, 245, 32, 50, 165, 172, 47, 89, 210, 78, 70, 171, 117, 186, 140, 116, 19, 181, 33, 188, 113, 246, 43, 112, 172, 72, 217, 240, 168, 144, 115, 102, 246, 14, 60, 172, 76, 233, 125, 202, 139, 154, 65, 194, 107, 2, 61, 208, 251, 213, 147, 15, 98, 94, 169, 114, 60, 83, 201, 0, 179, 19, 148, 192, 229, 180, 165, 220, 173, 25, 128, 254, 102, 90, 60, 43, 196, 60, 145, 121, 233, 137, 232, 18, 161, 230, 232, 202, 193, 198, 212, 100, 193, 57, 8, 182, 32, 167, 5, 209, 83, 134, 184, 123, 105, 173, 95, 237, 93, 90, 17, 6, 232, 254, 139, 85, 87, 31, 187, 255, 82, 203, 41, 94, 255, 43, 5, 64, 18, 89, 140, 11, 204, 222, 115, 15, 134, 202, 130, 16, 54, 219, 60, 240, 104, 189, 153, 243, 182, 204, 108, 163, 197, 143, 20, 54, 178, 24, 67, 201, 155, 168, 145, 6, 21, 162, 167, 19, 12, 169, 154, 141, 104, 29, 105, 180, 170, 40, 90, 170, 180, 146, 9, 68, 11, 242, 39, 245, 146, 74, 254, 96, 170, 68, 20, 76, 66, 215, 12, 187, 166, 29, 86, 141, 152, 117, 247, 239, 43, 132, 166, 48, 87, 208, 137, 65, 105, 4, 51, 179, 64, 22, 39, 122, 198, 23, 184, 218, 251, 134, 115, 78, 240, 91, 37, 141, 232, 142, 176, 78, 95, 21, 154, 125, 132, 134, 83, 169, 172, 132, 169, 106, 82, 90, 169, 222, 27, 14, 147, 72, 171, 238, 42, 123, 23, 52, 130, 124, 216, 252, 176, 181, 185, 153, 252, 41, 254, 110, 246, 213, 159, 45, 60, 78, 105, 206, 85, 171, 142, 169, 103, 88, 64, 174, 72, 19, 216, 227, 106, 213, 228, 47, 148, 224, 167, 139, 19, 252, 180, 153, 224, 167, 119, 139, 224, 167, 132, 204, 150, 248, 53, 4, 127, 86, 20, 103, 179, 9, 225, 240, 86, 132, 254, 172, 84, 26, 22, 212, 177, 166, 230, 196, 216, 108, 168, 55, 189, 145, 138, 206, 188, 40, 103, 51, 51, 1, 234, 55, 176, 94, 254, 90, 145, 152, 166, 145, 32, 243, 220, 241, 150, 201, 254, 173, 51, 0, 135, 239, 21, 249, 72, 134, 208, 49, 43, 78, 189, 25, 81, 188, 85, 108, 168, 157, 136, 88, 239, 158, 246, 39, 69, 135, 239, 151, 47, 195, 55, 215, 240, 245, 111, 202, 240, 213, 27, 113, 19, 75, 70, 59, 172, 237, 41, 198, 1, 88, 95, 27, 161, 90, 168, 219, 38, 81, 243, 116, 90, 86, 187, 227, 33, 250, 225, 144, 180, 26, 12, 251, 10, 228, 238, 111, 186, 107, 16, 77, 123, 244, 35, 34, 229, 181, 171, 228, 162, 204, 167, 160, 164, 31, 38, 247, 238, 249, 208, 54, 31, 24, 159, 74, 38, 184, 78, 237, 221, 68, 138, 246, 77, 209, 65, 49, 62, 201, 79, 103, 117, 133, 183, 86, 157, 83, 199, 52, 83, 209, 31, 90, 135, 58, 216, 86, 230, 205, 22, 190, 105, 141, 84, 107, 148, 62, 6, 216, 227, 160, 68, 118, 115, 38, 6, 119, 112, 123, 114, 176, 242, 183, 179, 41, 184, 202, 64, 130, 7, 83, 187, 36, 93, 206, 197, 220, 164, 57, 162, 55, 232, 219, 136, 250, 240, 138, 248, 90, 196, 135, 18, 81, 38, 76, 34, 30, 134, 249, 219, 244, 214, 210, 164, 201, 187, 247, 67, 208, 187, 183, 69, 201, 138, 9, 237, 61, 1, 209, 46, 50, 76, 187, 161, 47, 140, 48, 235, 111, 227, 53, 211, 63, 212, 12, 77, 92, 173, 234, 92, 148, 243, 18, 122, 210, 177, 76, 214, 17, 43, 69, 138, 140, 142, 174, 147, 24, 252, 249, 136, 124, 218, 176, 149, 4, 245, 164, 125, 240, 16, 254, 252, 64, 253, 141, 29, 202, 149, 115, 192, 166, 213, 20, 244, 45, 9, 189, 191, 201, 160, 171, 68, 171, 13, 96, 165, 198, 208, 107, 91, 69, 52, 210, 18, 217, 128, 38, 84, 213, 193, 38, 166, 37, 173, 68, 230, 104, 44, 212, 47, 13, 70, 245, 233, 129, 236, 211, 22, 239, 147, 24, 182, 230, 70, 182, 116, 35, 102, 144, 73, 35, 167, 25, 217, 151, 8, 88, 169, 32, 15, 88, 239, 94, 216, 93, 233, 112, 239, 119, 63, 40, 251, 181, 227, 44, 200, 37, 190, 213, 92, 248, 86, 1, 124, 171, 24, 190, 149, 197, 183, 154, 27, 223, 42, 140, 175, 66, 202, 153, 182, 249, 135, 62, 157, 207, 93, 208, 91, 4, 166, 81, 231, 173, 180, 102, 165, 87, 24, 122, 105, 103, 20, 40, 29, 127, 205, 132, 20, 53, 170, 103, 245, 59, 99, 110, 24, 196, 187, 196, 70, 87, 127, 30, 168, 61, 66, 91, 52, 80, 2, 63, 82, 3, 38, 224, 159, 241, 123, 196, 239, 189, 8, 68, 105, 153, 220, 96, 139, 16, 10, 93, 243, 114, 97, 225, 82, 105, 78, 80, 196, 225, 79, 30, 13, 204, 200, 194, 176, 213, 12, 72, 102, 190, 171, 76, 163, 114, 11, 223, 49, 105, 180, 122, 38, 29, 150, 41, 170, 60, 116, 97, 159, 242, 137, 218, 209, 151, 161, 39, 174, 235, 209, 113, 25, 78, 96, 131, 54, 22, 182, 18, 9, 89, 129, 58, 13, 225, 42, 170, 228, 198, 137, 69, 134, 71, 175, 68, 89, 74, 111, 59, 78, 212, 198, 160, 59, 200, 225, 62, 255, 67, 249, 156, 14, 122, 201, 203, 6, 79, 43, 119, 82, 189, 212, 201, 186, 124, 243, 248, 203, 126, 158, 179, 159, 167, 200, 73, 60, 96, 3, 25, 235, 208, 197, 5, 198, 13, 218, 183, 227, 235, 203, 179, 184, 125, 120, 22, 183, 11, 207, 154, 236, 193, 51, 101, 7, 218, 101, 161, 179, 91, 8, 73, 234, 196, 199, 215, 118, 34, 107, 218, 18, 140, 137, 196, 103, 218, 11, 116, 37, 77, 128, 62, 207, 171, 236, 13, 158, 103, 234, 22, 227, 167, 234, 201, 74, 220, 68, 21, 137, 6, 176, 224, 247, 186, 244, 249, 216, 10, 36, 205, 199, 134, 34, 249, 243, 97, 123, 25, 183, 232, 233, 222, 50, 54, 209, 139, 109, 61, 107, 248, 138, 183, 77, 54, 170, 233, 187, 76, 119, 167, 167, 146, 242, 226, 175, 144, 111, 207, 246, 92, 119, 132, 84, 135, 161, 31, 147, 202, 9, 3, 231, 126, 101, 3, 217, 37, 96, 86, 193, 146, 215, 108, 255, 158, 206, 255, 206, 161, 190, 144, 152, 20, 182, 47, 238, 5, 173, 238, 64, 33, 61, 14, 179, 170, 24, 189, 207, 186, 123, 44, 7, 43, 153, 126, 194, 33, 158, 178, 238, 6, 160, 221, 75, 12, 229, 13, 218, 1, 31, 8, 191, 80, 90, 51, 161, 250, 211, 165, 132, 98, 253, 23, 138, 166, 162, 135, 228, 110, 35, 1, 84, 38, 102, 213, 147, 32, 1, 26, 242, 144, 69, 218, 138, 50, 46, 159, 212, 84, 92, 218, 179, 188, 146, 230, 129, 244, 211, 60, 203, 207, 178, 167, 69, 41, 180, 126, 101, 247, 174, 140, 64, 168, 237, 195, 87, 5, 30, 188, 18, 5, 80, 127, 152, 213, 46, 148, 120, 156, 116, 191, 221, 220, 76, 254, 146, 8, 11, 57, 126, 66, 188, 223, 255, 27, 19, 221, 145, 64, 3, 167, 18, 229, 49, 18, 160, 86, 217, 164, 145, 203, 105, 68, 252, 209, 155, 149, 118, 163, 50, 160, 235, 0, 158, 152, 62, 229, 92, 126, 156, 123, 38, 3, 124, 102, 196, 208, 142, 52, 121, 95, 68, 119, 154, 150, 50, 136, 3, 131, 255, 228, 17, 49, 97, 142, 153, 147, 103, 162, 54, 115, 104, 24, 53, 160, 42, 206, 19, 36, 170, 107, 56, 19, 182, 118, 26, 176, 38, 27, 172, 136, 239, 77, 84, 222, 255, 176, 122, 255, 211, 49, 31, 176, 155, 27, 178, 155, 230, 245, 171, 226, 168, 152, 149, 131, 204, 105, 142, 91, 18, 109, 175, 218, 104, 67, 59, 220, 18, 219, 175, 246, 199, 163, 92, 30, 248, 124, 6, 181, 12, 92, 54, 26, 116, 31, 76, 127, 24, 104, 253, 109, 134, 138, 53, 144, 240, 209, 33, 202, 190, 97, 128, 30, 52, 15, 144, 138, 237, 190, 120, 37, 95, 107, 198, 247, 15, 37, 62, 78, 182, 116, 35, 166, 180, 115, 230, 80, 175, 18, 3, 104, 154, 42, 113, 147, 218, 195, 117, 171, 151, 144, 106, 100, 81, 75, 231, 19, 138, 203, 212, 116, 225, 211, 49, 158, 25, 184, 249, 152, 79, 58, 184, 132, 86, 194, 92, 233, 251, 213, 75, 97, 241, 101, 67, 165, 42, 28, 185, 20, 6, 27, 123, 131, 74, 74, 70, 146, 16, 205, 132, 205, 255, 200, 11, 227, 219, 135, 77, 218, 209, 229, 231, 36, 169, 46, 114, 153, 183, 31, 208, 212, 122, 209, 156, 76, 19, 244, 223, 124, 232, 76, 30, 154, 18, 174, 86, 215, 28, 109, 7, 115, 219, 66, 233, 47, 12, 69, 138, 72, 37, 214, 81, 20, 220, 214, 213, 193, 225, 67, 159, 193, 189, 191, 68, 184, 248, 176, 197, 26, 120, 112, 29, 13, 224, 195, 125, 214, 210, 183, 215, 218, 18, 62, 60, 96, 77, 126, 247, 105, 154, 196, 135, 111, 89, 219, 223, 127, 226, 182, 241, 225, 59, 134, 196, 15, 159, 11, 9, 124, 248, 158, 97, 243, 183, 207, 142, 13, 62, 252, 192, 208, 234, 47, 174, 81, 150, 142, 23, 62, 252, 141, 35, 184, 4, 101, 181, 116, 4, 53, 64, 174, 7, 251, 203, 84, 132, 203, 71, 85, 63, 25, 37, 43, 214, 47, 169, 88, 144, 56, 72, 27, 11, 162, 9, 91, 255, 188, 151, 54, 172, 134, 243, 58, 54, 177, 233, 171, 184, 54, 117, 62, 249, 0, 58, 167, 177, 29, 105, 221, 49, 111, 83, 218, 185, 254, 136, 27, 81, 45, 118, 25, 93, 115, 143, 245, 47, 186, 65, 30, 66, 39, 216, 161, 119, 105, 181, 28, 220, 3, 182, 151, 170, 16, 48, 186, 68, 163, 190, 185, 133, 224, 131, 70, 62, 221, 1, 205, 199, 198, 80, 12, 15, 80, 168, 63, 201, 245, 118, 8, 182, 153, 218, 117, 168, 209, 56, 199, 30, 171, 0, 10, 137, 254, 209, 76, 222, 121, 233, 119, 170, 231, 88, 239, 46, 213, 84, 149, 99, 82, 131, 103, 127, 248, 234, 48, 59, 125, 242, 97, 242, 116, 148, 158, 86, 44, 210, 17, 172, 219, 195, 168, 135, 236, 176, 142, 125, 15, 235, 78, 27, 31, 50, 251, 217, 120, 71, 58, 29, 221, 200, 225, 134, 188, 36, 97, 152, 15, 236, 134, 28, 22, 91, 19, 229, 134, 29, 74, 198, 195, 13, 117, 98, 43, 80, 240, 212, 41, 152, 159, 142, 139, 50, 219, 75, 171, 44, 80, 56, 119, 10, 159, 139, 15, 112, 181, 99, 168, 236, 185, 83, 118, 88, 76, 119, 71, 33, 12, 42, 167, 224, 108, 156, 15, 138, 97, 8, 228, 44, 92, 82, 44, 71, 67, 36, 120, 239, 148, 174, 166, 249, 224, 236, 50, 80, 240, 178, 227, 112, 131, 77, 68, 229, 7, 127, 122, 140, 128, 49, 169, 39, 240, 134, 199, 163, 170, 162, 129, 251, 72, 175, 159, 97, 38, 144, 142, 169, 84, 62, 31, 108, 94, 16, 64, 10, 155, 113, 238, 75, 140, 121, 9, 249, 138, 110, 172, 116, 254, 10, 55, 124, 106, 104, 107, 248, 91, 22, 171, 35, 143, 189, 174, 211, 222, 155, 74, 73, 179, 59, 124, 15, 119, 123, 168, 47, 251, 16, 156, 222, 61, 194, 187, 173, 137, 227, 202, 120, 175, 170, 217, 100, 162, 220, 222, 105, 41, 247, 2, 212, 218, 27, 227, 223, 143, 244, 42, 241, 235, 175, 209, 42, 112, 220, 28, 170, 153, 55, 192, 42, 47, 139, 124, 60, 221, 21, 186, 193, 54, 247, 56, 217, 252, 112, 34, 254, 173, 240, 107, 58, 20, 244, 181, 164, 47, 254, 99, 237, 59, 186, 20, 186, 251, 28, 28, 117, 93, 181, 33, 97, 71, 185, 252, 16, 29, 230, 242, 67, 237, 181, 89, 31, 234, 6, 90, 212, 165, 35, 125, 68, 71, 16, 81, 208, 13, 238, 87, 136, 159, 60, 13, 122, 48, 153, 230, 231, 249, 239, 42, 43, 148, 69, 128, 178, 66, 195, 17, 201, 242, 3, 63, 35, 169, 148, 138, 168, 119, 239, 94, 87, 129, 192, 48, 36, 235, 28, 225, 122, 7, 91, 19, 29, 250, 85, 137, 174, 91, 183, 191, 233, 58, 106, 85, 15, 126, 193, 3, 167, 130, 206, 162, 27, 18, 145, 163, 30, 5, 20, 218, 181, 87, 85, 113, 219, 224, 201, 135, 108, 160, 234, 185, 186, 159, 140, 161, 232, 229, 197, 203, 84, 204, 51, 186, 96, 120, 168, 157, 98, 102, 196, 61, 137, 42, 63, 16, 145, 50, 89, 52, 66, 204, 153, 143, 7, 163, 217, 80, 154, 84, 80, 1, 148, 74, 199, 221, 51, 86, 24, 4, 58, 226, 19, 181, 125, 51, 51, 181, 15, 35, 48, 29, 165, 213, 116, 159, 222, 95, 15, 96, 119, 19, 122, 189, 253, 88, 127, 138, 28, 78, 55, 243, 84, 16, 85, 157, 13, 82, 149, 113, 206, 54, 219, 157, 113, 117, 96, 74, 112, 190, 20, 128, 135, 201, 46, 29, 90, 117, 196, 16, 198, 96, 90, 50, 74, 75, 168, 214, 69, 18, 240, 43, 239, 10, 91, 186, 103, 42, 19, 140, 44, 60, 118, 255, 49, 122, 183, 9, 85, 140, 255, 156, 82, 203, 50, 44, 39, 33, 25, 16, 44, 0, 30, 171, 176, 230, 179, 192, 76, 209, 135, 164, 229, 53, 147, 66, 76, 254, 127, 188, 182, 22, 88, 4, 180, 19, 19, 195, 171, 222, 104, 207, 201, 1, 184, 171, 32, 168, 1, 26, 72, 235, 224, 26, 222, 152, 20, 85, 142, 233, 20, 21, 178, 71, 89, 90, 14, 222, 9, 75, 10, 209, 116, 41, 10, 67, 99, 43, 61, 130, 172, 112, 115, 50, 11, 237, 15, 111, 243, 153, 248, 34, 147, 202, 118, 143, 136, 62, 35, 140, 117, 52, 123, 171, 148, 41, 12, 143, 198, 130, 224, 152, 172, 155, 183, 203, 228, 184, 235, 102, 32, 220, 235, 49, 31, 30, 235, 49, 12, 108, 238, 237, 234, 42, 31, 27, 120, 175, 118, 154, 161, 139, 9, 85, 204, 159, 3, 99, 7, 25, 85, 121, 25, 29, 205, 78, 31, 147, 219, 196, 84, 145, 14, 157, 185, 149, 117, 64, 234, 202, 200, 106, 130, 21, 249, 180, 170, 141, 6, 245, 78, 95, 58, 198, 251, 208, 75, 226, 53, 228, 187, 141, 76, 40, 58, 57, 150, 234, 165, 58, 7, 4, 205, 190, 1, 21, 184, 226, 30, 152, 80, 165, 14, 179, 201, 40, 21, 139, 159, 10, 77, 165, 82, 253, 38, 209, 97, 159, 223, 138, 136, 75, 185, 154, 115, 84, 135, 210, 17, 246, 69, 148, 97, 169, 39, 73, 135, 76, 157, 188, 172, 166, 63, 23, 162, 72, 169, 25, 93, 101, 123, 148, 125, 243, 32, 90, 22, 177, 176, 184, 222, 119, 218, 208, 147, 140, 125, 173, 205, 195, 199, 52, 215, 66, 0, 13, 193, 95, 79, 157, 183, 33, 240, 52, 216, 240, 6, 26, 88, 240, 46, 74, 69, 163, 0, 112, 72, 31, 39, 223, 110, 242, 195, 13, 54, 240, 229, 167, 180, 194, 116, 28, 79, 240, 215, 211, 66, 232, 205, 243, 183, 195, 52, 68, 22, 11, 220, 240, 167, 134, 178, 202, 27, 8, 154, 118, 136, 168, 32, 161, 110, 173, 203, 170, 192, 252, 212, 115, 222, 28, 185, 47, 176, 91, 238, 107, 138, 173, 251, 77, 153, 65, 206, 75, 141, 56, 123, 205, 250, 249, 113, 197, 127, 170, 237, 21, 24, 99, 102, 162, 67, 52, 57, 98, 137, 181, 20, 41, 92, 57, 158, 46, 179, 222, 115, 102, 195, 134, 198, 229, 100, 70, 233, 201, 105, 201, 8, 22, 160, 97, 140, 126, 30, 237, 92, 60, 205, 39, 175, 87, 245, 232, 230, 144, 72, 121, 14, 106, 125, 52, 210, 80, 195, 249, 172, 73, 121, 18, 119, 142, 209, 241, 27, 106, 26, 146, 186, 230, 156, 241, 160, 163, 65, 8, 239, 141, 68, 120, 28, 34, 68, 143, 47, 136, 92, 100, 154, 169, 29, 94, 49, 33, 8, 179, 24, 90, 161, 125, 65, 180, 89, 31, 124, 252, 189, 225, 194, 215, 126, 151, 106, 38, 80, 138, 128, 106, 94, 182, 71, 154, 118, 27, 14, 54, 235, 53, 218, 118, 93, 199, 20, 245, 92, 235, 59, 59, 143, 210, 181, 155, 49, 131, 124, 245, 126, 197, 69, 94, 216, 200, 231, 78, 198, 74, 101, 111, 121, 3, 155, 227, 54, 129, 11, 166, 247, 169, 174, 115, 253, 231, 229, 31, 11, 88, 212, 136, 99, 207, 32, 180, 182, 230, 68, 120, 73, 51, 194, 157, 20, 131, 169, 205, 218, 44, 35, 111, 223, 242, 208, 132, 92, 232, 36, 206, 217, 240, 144, 123, 143, 117, 134, 67, 229, 123, 127, 105, 151, 101, 60, 210, 151, 4, 109, 105, 98, 179, 200, 45, 51, 214, 56, 38, 199, 57, 73, 48, 49, 222, 75, 39, 66, 85, 100, 58, 5, 134, 76, 66, 114, 158, 126, 232, 90, 26, 201, 90, 38, 218, 98, 61, 233, 235, 187, 17, 201, 232, 200, 180, 245, 209, 193, 49, 197, 20, 72, 153, 56, 75, 86, 34, 102, 170, 183, 246, 100, 216, 32, 57, 237, 187, 124, 44, 48, 212, 25, 89, 16, 69, 229, 39, 52, 170, 209, 132, 116, 111, 174, 16, 61, 171, 184, 95, 42, 19, 240, 19, 90, 238, 241, 109, 228, 63, 255, 244, 173, 79, 127, 246, 48, 160, 140, 52, 9, 75, 76, 93, 49, 240, 225, 208, 126, 37, 179, 8, 185, 146, 1, 254, 33, 45, 130, 83, 139, 89, 208, 154, 55, 102, 192, 26, 167, 155, 176, 202, 142, 168, 109, 66, 33, 39, 200, 217, 38, 219, 76, 32, 88, 89, 252, 217, 121, 100, 177, 216, 134, 133, 38, 181, 111, 100, 202, 211, 116, 242, 194, 240, 219, 241, 216, 28, 189, 213, 89, 75, 197, 215, 200, 249, 33, 248, 103, 216, 8, 10, 18, 99, 78, 155, 36, 250, 175, 196, 41, 61, 207, 134, 132, 133, 145, 19, 78, 225, 20, 65, 69, 87, 210, 188, 96, 180, 117, 115, 106, 129, 149, 15, 88, 69, 116, 212, 41, 253, 93, 243, 195, 48, 244, 227, 71, 1, 89, 182, 77, 251, 90, 96, 205, 30, 23, 98, 62, 14, 31, 138, 245, 123, 64, 118, 167, 64, 35, 107, 46, 171, 88, 206, 79, 194, 26, 198, 0, 92, 163, 130, 235, 175, 171, 2, 149, 69, 71, 29, 87, 133, 155, 173, 94, 119, 209, 49, 86, 148, 132, 4, 8, 177, 210, 138, 6, 122, 169, 20, 36, 65, 196, 48, 137, 74, 170, 149, 81, 34, 157, 82, 46, 169, 68, 50, 89, 188, 170, 237, 50, 176, 92, 236, 79, 235, 250, 163, 81, 160, 114, 10, 8, 204, 187, 186, 96, 207, 169, 2, 211, 47, 118, 133, 135, 252, 54, 75, 117, 92, 162, 155, 164, 25, 107, 133, 4, 58, 106, 56, 212, 117, 192, 212, 55, 49, 162, 77, 226, 95, 187, 212, 240, 245, 66, 228, 132, 136, 14, 59, 52, 244, 161, 42, 131, 7, 30, 18, 126, 55, 221, 38, 159, 194, 185, 80, 89, 129, 250, 101, 176, 119, 183, 182, 133, 171, 80, 131, 32, 25, 231, 147, 63, 137, 160, 90, 97, 191, 87, 201, 47, 162, 117, 121, 68, 228, 141, 232, 158, 253, 209, 191, 134, 190, 110, 221, 220, 190, 218, 31, 91, 215, 208, 241, 251, 183, 164, 227, 246, 199, 253, 107, 160, 194, 131, 219, 72, 5, 251, 227, 193, 50, 73, 66, 247, 19, 230, 84, 213, 205, 123, 46, 117, 181, 233, 50, 180, 149, 229, 54, 39, 252, 144, 117, 199, 28, 48, 238, 136, 55, 158, 200, 224, 62, 47, 114, 70, 82, 55, 30, 136, 153, 106, 209, 51, 119, 130, 171, 177, 79, 61, 183, 143, 48, 110, 164, 209, 148, 79, 103, 150, 55, 13, 85, 148, 81, 165, 254, 112, 22, 9, 120, 127, 28, 171, 165, 231, 227, 22, 55, 176, 158, 186, 211, 175, 180, 177, 208, 192, 74, 216, 166, 157, 191, 177, 98, 34, 75, 198, 254, 44, 143, 187, 5, 235, 106, 81, 221, 218, 28, 104, 49, 227, 215, 204, 247, 238, 108, 95, 163, 33, 26, 245, 67, 92, 59, 68, 116, 131, 89, 87, 243, 215, 97, 9, 167, 242, 109, 165, 219, 200, 182, 59, 175, 127, 166, 142, 232, 71, 119, 38, 95, 188, 79, 91, 55, 169, 79, 250, 209, 157, 175, 23, 239, 222, 253, 27, 218, 61, 253, 232, 206, 201, 139, 247, 244, 193, 205, 239, 169, 126, 116, 103, 221, 5, 58, 77, 93, 130, 209, 165, 32, 91, 181, 109, 214, 174, 218, 182, 91, 76, 188, 99, 211, 129, 177, 61, 189, 89, 95, 195, 40, 206, 53, 240, 3, 178, 89, 190, 117, 197, 45, 61, 193, 183, 156, 4, 91, 3, 190, 31, 154, 217, 201, 188, 200, 249, 103, 57, 115, 122, 112, 214, 91, 124, 159, 204, 110, 101, 52, 198, 222, 205, 21, 28, 180, 168, 151, 249, 147, 196, 8, 121, 94, 255, 121, 226, 129, 106, 60, 103, 203, 242, 155, 249, 14, 190, 32, 193, 12, 214, 182, 203, 164, 35, 143, 172, 87, 237, 134, 133, 17, 17, 242, 83, 155, 255, 174, 248, 248, 66, 27, 252, 43, 173, 119, 32, 213, 214, 249, 181, 201, 101, 81, 230, 167, 144, 56, 64, 245, 133, 6, 158, 168, 17, 15, 70, 158, 244, 87, 221, 234, 79, 113, 227, 19, 3, 190, 77, 114, 58, 212, 132, 50, 171, 78, 101, 132, 233, 31, 206, 7, 178, 245, 119, 13, 186, 194, 243, 57, 59, 219, 65, 100, 59, 208, 197, 152, 111, 225, 205, 173, 116, 26, 212, 78, 144, 243, 231, 83, 62, 238, 22, 216, 252, 209, 136, 73, 139, 157, 49, 119, 195, 193, 183, 131, 26, 172, 160, 152, 13, 20, 180, 128, 188, 253, 168, 176, 61, 99, 173, 25, 147, 186, 140, 238, 31, 201, 71, 58, 122, 206, 150, 179, 140, 125, 109, 26, 186, 232, 22, 116, 100, 232, 182, 195, 163, 98, 44, 186, 54, 36, 135, 124, 108, 219, 97, 174, 163, 251, 140, 180, 24, 229, 152, 186, 157, 147, 232, 118, 97, 120, 141, 76, 204, 95, 190, 99, 88, 187, 65, 72, 199, 218, 25, 152, 79, 60, 95, 90, 137, 111, 59, 93, 178, 113, 225, 215, 55, 221, 212, 153, 146, 98, 246, 231, 35, 205, 19, 118, 3, 16, 11, 181, 83, 235, 96, 255, 154, 198, 156, 169, 225, 207, 63, 93, 80, 117, 161, 137, 210, 146, 102, 179, 131, 172, 77, 54, 174, 173, 122, 51, 71, 90, 15, 211, 139, 46, 111, 181, 199, 97, 4, 34, 43, 239, 152, 117, 64, 131, 26, 231, 178, 16, 72, 48, 226, 173, 52, 22, 62, 203, 164, 255, 101, 126, 112, 230, 135, 230, 176, 92, 204, 162, 53, 81, 17, 191, 106, 220, 189, 12, 116, 80, 139, 239, 247, 90, 240, 178, 114, 77, 248, 197, 246, 54, 249, 193, 231, 43, 168, 106, 191, 58, 113, 34, 240, 143, 132, 35, 59, 121, 213, 233, 40, 208, 136, 217, 123, 245, 189, 93, 108, 190, 244, 103, 76, 39, 118, 54, 100, 207, 4, 230, 205, 200, 86, 200, 151, 25, 244, 203, 12, 154, 124, 153, 65, 155, 98, 216, 231, 156, 62, 253, 77, 166, 219, 226, 12, 251, 50, 215, 45, 52, 215, 93, 71, 252, 222, 28, 251, 165, 148, 86, 145, 105, 198, 223, 62, 85, 133, 23, 92, 141, 197, 3, 48, 123, 225, 14, 224, 219, 47, 203, 183, 207, 49, 249, 220, 17, 245, 28, 62, 68, 210, 82, 61, 135, 79, 33, 199, 195, 231, 23, 58, 65, 103, 143, 101, 28, 148, 71, 50, 245, 7, 215, 241, 93, 155, 37, 255, 135, 85, 179, 111, 196, 107, 208, 144, 190, 90, 38, 136, 87, 149, 195, 24, 152, 48, 184, 158, 144, 195, 120, 68, 184, 132, 26, 193, 209, 19, 27, 115, 122, 46, 107, 188, 150, 117, 248, 135, 177, 103, 113, 45, 71, 20, 171, 160, 88, 215, 123, 60, 227, 205, 59, 141, 251, 176, 105, 203, 142, 134, 169, 15, 167, 142, 205, 216, 76, 92, 54, 201, 102, 164, 208, 10, 78, 3, 119, 79, 142, 231, 217, 197, 248, 34, 197, 203, 145, 226, 121, 172, 182, 26, 139, 109, 89, 34, 108, 98, 163, 34, 198, 93, 155, 83, 55, 53, 70, 93, 173, 57, 28, 183, 236, 62, 133, 134, 104, 227, 7, 160, 86, 90, 99, 152, 219, 10, 26, 89, 95, 84, 77, 221, 33, 216, 150, 11, 186, 248, 17, 135, 47, 234, 231, 139, 250, 185, 149, 234, 103, 193, 224, 210, 229, 132, 244, 182, 92, 154, 206, 165, 240, 230, 140, 235, 253, 162, 25, 169, 89, 124, 195, 18, 200, 169, 29, 129, 236, 125, 94, 204, 170, 103, 132, 195, 41, 195, 123, 46, 178, 253, 234, 191, 179, 18, 146, 245, 28, 137, 209, 150, 44, 209, 245, 96, 232, 115, 190, 178, 71, 78, 205, 136, 84, 177, 27, 244, 234, 211, 13, 125, 253, 181, 77, 8, 184, 35, 244, 242, 247, 39, 39, 39, 53, 71, 212, 221, 21, 147, 62, 130, 92, 135, 156, 135, 158, 215, 69, 84, 112, 124, 39, 99, 193, 60, 48, 120, 218, 44, 56, 225, 196, 167, 135, 8, 74, 124, 199, 193, 73, 119, 25, 8, 246, 87, 228, 225, 249, 238, 122, 62, 240, 56, 83, 55, 87, 181, 236, 94, 155, 60, 64, 6, 176, 206, 202, 82, 72, 125, 29, 55, 202, 113, 179, 204, 231, 214, 8, 33, 16, 225, 185, 32, 5, 53, 15, 70, 38, 65, 164, 221, 186, 123, 249, 18, 159, 129, 2, 169, 179, 142, 38, 163, 124, 234, 102, 157, 218, 91, 66, 242, 172, 189, 105, 81, 38, 143, 98, 215, 39, 209, 236, 89, 208, 204, 158, 156, 91, 108, 205, 249, 18, 116, 217, 122, 27, 38, 1, 214, 182, 171, 88, 111, 126, 94, 46, 57, 22, 38, 43, 215, 8, 220, 20, 55, 73, 39, 71, 110, 202, 2, 114, 52, 140, 178, 221, 177, 183, 100, 52, 183, 114, 212, 243, 33, 210, 182, 43, 169, 193, 79, 183, 64, 62, 3, 236, 133, 253, 170, 175, 96, 227, 150, 55, 68, 59, 75, 255, 172, 52, 50, 37, 121, 43, 104, 112, 154, 149, 154, 156, 4, 53, 147, 244, 100, 126, 157, 233, 52, 19, 217, 220, 225, 154, 85, 106, 84, 166, 172, 171, 249, 227, 33, 224, 159, 238, 82, 120, 27, 175, 194, 237, 59, 221, 236, 255, 147, 237, 6, 39, 12, 2, 168, 212, 83, 138, 107, 214, 215, 167, 166, 9, 81, 98, 129, 172, 49, 202, 96, 190, 120, 170, 3, 59, 244, 17, 237, 182, 128, 46, 59, 100, 170, 210, 128, 104, 164, 136, 215, 117, 183, 16, 164, 30, 86, 105, 154, 245, 220, 69, 136, 19, 77, 248, 191, 39, 120, 23, 36, 175, 103, 224, 49, 41, 227, 153, 45, 149, 205, 176, 75, 55, 244, 4, 63, 107, 190, 12, 48, 190, 238, 146, 248, 4, 149, 100, 18, 97, 248, 183, 237, 45, 189, 100, 1, 5, 225, 241, 227, 199, 142, 15, 87, 55, 136, 173, 240, 29, 14, 154, 138, 81, 215, 168, 242, 223, 129, 41, 105, 50, 62, 121, 137, 172, 124, 77, 43, 71, 228, 9, 243, 97, 115, 243, 71, 147, 19, 141, 160, 120, 134, 49, 55, 43, 36, 31, 55, 11, 89, 78, 223, 4, 234, 170, 189, 190, 190, 25, 168, 252, 127, 56, 161, 230, 166, 61, 198, 25, 34, 206, 111, 48, 115, 7, 244, 220, 139, 130, 172, 141, 168, 254, 19, 246, 226, 189, 72, 248, 50, 197, 30, 64, 226, 62, 237, 111, 194, 174, 4, 98, 83, 171, 82, 8, 244, 239, 219, 33, 162, 219, 118, 109, 183, 127, 243, 173, 79, 70, 254, 223, 152, 229, 247, 27, 186, 234, 65, 207, 254, 6, 203, 26, 218, 54, 252, 11, 110, 63, 101, 173, 162, 140, 127, 79, 236, 69, 225, 102, 44, 163, 108, 243, 187, 231, 36, 168, 65, 251, 247, 246, 91, 202, 64, 143, 223, 237, 242, 220, 118, 124, 158, 206, 254, 38, 84, 196, 239, 199, 155, 175, 89, 132, 115, 68, 161, 50, 59, 239, 183, 109, 175, 123, 30, 239, 54, 119, 236, 55, 25, 155, 196, 117, 109, 108, 243, 241, 55, 184, 105, 244, 55, 186, 201, 152, 128, 14, 19, 211, 182, 123, 183, 178, 234, 154, 241, 105, 249, 248, 123, 121, 233, 148, 10, 152, 112, 102, 91, 28, 49, 142, 86, 157, 92, 162, 250, 236, 57, 177, 234, 2, 40, 4, 167, 235, 75, 205, 176, 148, 74, 34, 75, 115, 81, 238, 74, 188, 133, 254, 243, 50, 232, 177, 140, 190, 160, 45, 51, 91, 247, 247, 128, 82, 145, 147, 149, 180, 62, 14, 78, 26, 179, 80, 253, 30, 78, 64, 165, 160, 64, 6, 44, 67, 9, 20, 254, 92, 30, 141, 115, 192, 83, 70, 104, 160, 206, 239, 250, 70, 67, 100, 40, 77, 137, 0, 113, 26, 9, 228, 19, 137, 114, 14, 85, 165, 70, 43, 234, 245, 203, 196, 149, 173, 6, 180, 59, 120, 91, 43, 149, 167, 57, 249, 64, 206, 79, 134, 21, 200, 226, 104, 55, 96, 131, 59, 150, 186, 231, 26, 169, 187, 65, 1, 20, 165, 187, 94, 58, 116, 151, 75, 204, 120, 65, 138, 65, 226, 90, 234, 90, 216, 63, 249, 119, 153, 78, 38, 246, 204, 194, 161, 126, 192, 197, 1, 254, 234, 4, 113, 118, 110, 115, 174, 51, 235, 163, 249, 234, 15, 35, 89, 232, 95, 101, 213, 116, 46, 154, 212, 44, 76, 230, 184, 85, 162, 21, 254, 128, 248, 211, 162, 148, 40, 250, 248, 127, 165, 215, 25, 114, 1, 131, 119, 98, 232, 75, 88, 36, 242, 241, 91, 37, 176, 18, 94, 184, 113, 124, 36, 175, 114, 222, 168, 212, 219, 215, 236, 130, 9, 227, 35, 2, 149, 183, 59, 26, 125, 89, 90, 95, 101, 105, 189, 18, 94, 40, 107, 226, 126, 38, 199, 101, 197, 83, 55, 46, 127, 153, 204, 150, 106, 58, 238, 185, 236, 37, 158, 195, 169, 153, 219, 76, 10, 136, 69, 150, 148, 11, 44, 128, 17, 87, 178, 114, 108, 183, 73, 198, 20, 188, 65, 182, 211, 225, 136, 196, 22, 155, 182, 213, 22, 75, 178, 64, 197, 141, 118, 72, 26, 68, 80, 255, 206, 177, 18, 61, 237, 172, 10, 198, 146, 62, 212, 135, 176, 204, 249, 115, 126, 16, 51, 4, 209, 223, 148, 32, 124, 234, 174, 111, 57, 19, 156, 186, 143, 20, 117, 152, 178, 184, 132, 17, 151, 2, 211, 25, 158, 18, 212, 234, 185, 12, 55, 10, 187, 87, 107, 192, 149, 217, 105, 246, 97, 210, 211, 243, 83, 28, 160, 28, 97, 123, 201, 14, 191, 110, 39, 71, 112, 162, 47, 47, 178, 139, 96, 67, 178, 219, 138, 31, 133, 182, 102, 108, 168, 107, 203, 165, 154, 66, 168, 85, 233, 190, 70, 187, 85, 233, 45, 221, 185, 86, 165, 239, 107, 127, 203, 159, 56, 98, 225, 10, 202, 174, 212, 181, 228, 175, 7, 61, 62, 190, 43, 206, 45, 65, 88, 56, 236, 212, 101, 52, 123, 145, 125, 96, 158, 53, 50, 113, 127, 234, 107, 14, 174, 226, 28, 245, 250, 68, 58, 82, 188, 253, 79, 84, 241, 203, 59, 201, 133, 101, 214, 85, 133, 126, 153, 165, 229, 240, 85, 17, 100, 46, 40, 186, 26, 243, 173, 215, 27, 110, 28, 82, 196, 140, 3, 4, 29, 219, 205, 239, 86, 192, 124, 51, 27, 20, 127, 36, 242, 226, 251, 135, 52, 121, 195, 176, 24, 139, 23, 114, 26, 87, 23, 192, 187, 145, 9, 70, 123, 251, 44, 7, 119, 44, 42, 110, 211, 236, 229, 31, 242, 183, 206, 24, 220, 76, 128, 6, 129, 218, 165, 94, 157, 5, 119, 115, 20, 222, 32, 132, 20, 5, 53, 38, 222, 12, 194, 145, 217, 92, 33, 155, 180, 74, 52, 91, 76, 92, 28, 70, 159, 194, 104, 57, 143, 113, 8, 247, 41, 132, 218, 251, 16, 218, 69, 244, 59, 81, 24, 196, 93, 134, 145, 237, 115, 121, 126, 145, 139, 12, 182, 73, 178, 101, 249, 134, 157, 51, 105, 171, 20, 80, 80, 91, 28, 76, 65, 93, 223, 87, 162, 130, 40, 251, 213, 35, 198, 2, 214, 222, 82, 181, 79, 2, 7, 81, 98, 177, 47, 102, 165, 137, 180, 53, 191, 217, 222, 36, 190, 101, 174, 147, 123, 241, 232, 150, 218, 208, 22, 19, 243, 97, 166, 124, 90, 97, 231, 17, 114, 39, 174, 229, 77, 17, 8, 255, 118, 130, 90, 156, 249, 49, 16, 6, 14, 129, 224, 214, 37, 70, 2, 208, 131, 110, 159, 154, 121, 196, 227, 12, 248, 247, 128, 254, 88, 239, 155, 31, 196, 37, 16, 19, 111, 245, 205, 17, 113, 74, 165, 208, 109, 32, 209, 120, 25, 215, 83, 230, 142, 129, 44, 132, 199, 48, 130, 199, 44, 26, 67, 243, 93, 136, 161, 240, 124, 53, 70, 1, 103, 84, 237, 0, 69, 99, 245, 45, 45, 174, 56, 50, 116, 186, 119, 6, 200, 59, 158, 184, 116, 22, 176, 1, 93, 146, 17, 222, 227, 149, 55, 146, 212, 219, 230, 155, 199, 8, 122, 75, 31, 117, 125, 211, 214, 147, 241, 161, 67, 121, 102, 120, 59, 39, 48, 194, 253, 147, 215, 2, 115, 3, 175, 129, 20, 132, 12, 134, 4, 235, 68, 91, 234, 217, 10, 133, 141, 69, 1, 48, 177, 53, 106, 60, 44, 150, 243, 35, 209, 167, 42, 123, 174, 217, 213, 23, 57, 211, 3, 231, 98, 1, 45, 116, 100, 98, 208, 197, 116, 180, 138, 35, 63, 0, 9, 44, 21, 127, 61, 228, 12, 25, 243, 89, 66, 208, 209, 220, 7, 98, 180, 180, 153, 230, 232, 169, 24, 139, 3, 145, 180, 0, 219, 152, 150, 45, 59, 50, 89, 185, 210, 184, 168, 213, 84, 88, 30, 188, 75, 91, 61, 67, 188, 155, 226, 205, 191, 204, 235, 131, 134, 169, 249, 214, 228, 145, 177, 171, 91, 93, 229, 216, 218, 234, 202, 25, 213, 237, 200, 66, 157, 213, 215, 140, 71, 69, 165, 96, 204, 30, 182, 116, 239, 30, 150, 114, 214, 141, 251, 213, 203, 162, 170, 242, 183, 163, 75, 52, 96, 153, 159, 202, 224, 205, 186, 172, 134, 85, 26, 248, 255, 72, 171, 23, 133, 186, 154, 212, 154, 232, 170, 114, 237, 90, 67, 21, 177, 91, 247, 4, 100, 172, 202, 145, 185, 226, 21, 169, 171, 96, 8, 12, 108, 33, 2, 166, 71, 209, 168, 165, 187, 166, 80, 55, 74, 105, 184, 228, 154, 128, 94, 117, 24, 64, 125, 210, 55, 34, 222, 150, 197, 87, 160, 70, 13, 175, 17, 56, 178, 163, 43, 238, 210, 77, 122, 218, 246, 199, 112, 91, 122, 58, 21, 252, 148, 169, 133, 145, 12, 13, 85, 82, 255, 94, 17, 196, 113, 201, 137, 101, 179, 30, 90, 149, 2, 175, 103, 21, 154, 170, 21, 98, 190, 55, 18, 47, 84, 83, 86, 226, 246, 171, 23, 66, 31, 29, 148, 191, 106, 41, 144, 32, 184, 55, 48, 128, 35, 246, 82, 161, 201, 38, 138, 188, 122, 169, 238, 37, 62, 210, 107, 19, 237, 39, 196, 57, 16, 226, 80, 148, 106, 235, 104, 198, 148, 77, 221, 235, 186, 85, 33, 104, 48, 44, 56, 102, 240, 238, 249, 248, 99, 15, 87, 172, 209, 204, 213, 132, 24, 49, 236, 132, 158, 192, 162, 99, 232, 78, 11, 49, 141, 193, 150, 193, 174, 111, 205, 56, 147, 116, 115, 134, 100, 60, 15, 36, 115, 227, 155, 50, 208, 118, 128, 46, 113, 17, 162, 157, 22, 38, 197, 212, 4, 239, 62, 21, 63, 72, 165, 238, 145, 99, 38, 96, 212, 141, 174, 80, 223, 81, 91, 208, 239, 8, 61, 42, 47, 157, 98, 93, 210, 142, 226, 185, 38, 228, 253, 59, 128, 221, 88, 80, 162, 134, 66, 68, 39, 131, 252, 161, 110, 128, 149, 211, 243, 40, 46, 48, 224, 72, 95, 170, 204, 8, 128, 174, 216, 224, 204, 23, 97, 100, 26, 55, 98, 166, 78, 231, 27, 95, 201, 163, 25, 64, 226, 120, 98, 120, 43, 155, 147, 174, 14, 28, 93, 211, 239, 247, 61, 11, 88, 162, 219, 236, 153, 53, 188, 172, 26, 225, 119, 39, 7, 155, 218, 18, 101, 12, 141, 130, 201, 56, 22, 148, 100, 9, 239, 147, 10, 179, 113, 204, 248, 18, 93, 39, 34, 246, 2, 178, 26, 28, 100, 99, 173, 24, 92, 245, 27, 15, 4, 96, 192, 191, 194, 204, 155, 140, 112, 248, 38, 233, 80, 244, 241, 131, 178, 105, 197, 154, 36, 31, 141, 142, 208, 12, 21, 159, 158, 140, 135, 87, 150, 2, 5, 6, 246, 145, 212, 19, 236, 36, 193, 227, 209, 52, 45, 167, 161, 9, 197, 217, 80, 98, 116, 204, 199, 211, 231, 26, 91, 106, 140, 155, 46, 80, 79, 153, 120, 35, 35, 14, 74, 39, 68, 139, 1, 81, 110, 11, 241, 195, 81, 69, 226, 165, 70, 202, 120, 228, 129, 58, 25, 67, 206, 210, 203, 40, 59, 93, 136, 221, 82, 230, 3, 245, 16, 121, 156, 116, 187, 253, 100, 103, 39, 185, 191, 9, 97, 16, 91, 156, 176, 135, 233, 248, 212, 200, 205, 38, 163, 23, 52, 168, 186, 202, 224, 173, 99, 191, 52, 242, 98, 13, 53, 30, 192, 65, 10, 116, 100, 233, 190, 248, 158, 92, 100, 141, 50, 155, 8, 78, 213, 103, 73, 160, 180, 122, 238, 234, 6, 255, 138, 175, 77, 240, 198, 159, 214, 89, 25, 110, 109, 141, 30, 41, 65, 152, 176, 124, 213, 16, 255, 203, 129, 168, 105, 138, 60, 4, 52, 165, 233, 57, 44, 85, 197, 162, 40, 216, 162, 51, 115, 68, 176, 82, 227, 18, 20, 142, 55, 21, 176, 105, 88, 68, 96, 75, 46, 233, 176, 189, 115, 70, 76, 11, 69, 113, 57, 236, 93, 6, 37, 77, 218, 218, 49, 241, 124, 147, 141, 35, 34, 186, 180, 246, 37, 77, 107, 215, 47, 250, 146, 228, 187, 184, 130, 193, 131, 76, 13, 107, 24, 203, 183, 114, 143, 240, 164, 44, 206, 117, 148, 77, 112, 27, 79, 31, 168, 211, 213, 254, 41, 204, 185, 108, 212, 213, 42, 89, 235, 102, 18, 13, 165, 64, 110, 74, 49, 10, 124, 30, 225, 192, 109, 18, 57, 243, 25, 166, 212, 183, 89, 203, 112, 67, 76, 62, 237, 223, 188, 112, 21, 171, 70, 211, 43, 96, 212, 160, 93, 143, 11, 0, 130, 3, 91, 5, 132, 236, 124, 195, 96, 117, 150, 62, 1, 232, 154, 251, 136, 20, 183, 18, 24, 17, 106, 6, 158, 88, 10, 6, 206, 252, 166, 130, 174, 218, 75, 88, 187, 74, 242, 106, 110, 176, 110, 97, 62, 40, 128, 71, 94, 33, 74, 16, 45, 50, 102, 245, 69, 111, 234, 38, 212, 119, 164, 68, 65, 210, 119, 184, 210, 24, 142, 30, 107, 54, 114, 21, 45, 154, 178, 225, 203, 198, 23, 110, 42, 124, 175, 56, 155, 245, 38, 69, 85, 27, 69, 63, 204, 62, 28, 156, 144, 45, 120, 2, 223, 78, 43, 69, 229, 109, 234, 233, 25, 69, 148, 163, 205, 1, 34, 142, 47, 81, 86, 168, 97, 4, 63, 179, 60, 239, 164, 104, 221, 248, 82, 87, 200, 238, 218, 52, 205, 71, 47, 101, 239, 0, 191, 53, 86, 203, 57, 93, 59, 206, 46, 142, 12, 170, 180, 71, 198, 129, 105, 74, 152, 248, 17, 230, 13, 164, 159, 153, 134, 147, 24, 170, 19, 159, 134, 236, 182, 240, 218, 35, 77, 144, 109, 198, 192, 198, 48, 171, 92, 108, 37, 103, 98, 199, 118, 88, 105, 31, 211, 181, 16, 46, 88, 185, 199, 91, 90, 215, 239, 221, 53, 34, 161, 76, 84, 73, 202, 152, 169, 107, 215, 147, 237, 215, 127, 84, 154, 131, 139, 192, 80, 1, 190, 18, 36, 37, 110, 231, 114, 144, 16, 45, 186, 32, 252, 162, 235, 183, 87, 174, 160, 121, 119, 181, 225, 183, 184, 242, 85, 21, 172, 180, 199, 53, 84, 170, 182, 57, 126, 186, 116, 99, 191, 251, 61, 6, 197, 116, 95, 88, 187, 7, 39, 112, 72, 226, 57, 110, 64, 153, 99, 64, 38, 238, 195, 38, 243, 35, 217, 5, 234, 82, 248, 193, 158, 8, 201, 47, 16, 138, 93, 9, 204, 29, 230, 139, 36, 139, 254, 69, 73, 133, 239, 52, 22, 242, 39, 225, 47, 214, 236, 78, 224, 126, 8, 239, 102, 12, 210, 31, 90, 121, 219, 101, 253, 72, 166, 248, 218, 60, 241, 225, 92, 117, 129, 28, 241, 161, 46, 134, 146, 223, 25, 199, 130, 236, 54, 237, 188, 229, 242, 163, 81, 46, 3, 56, 172, 62, 15, 82, 149, 15, 186, 75, 87, 161, 229, 121, 1, 218, 86, 169, 211, 228, 177, 22, 189, 244, 4, 110, 27, 9, 75, 51, 65, 57, 113, 155, 143, 132, 0, 108, 120, 152, 234, 111, 7, 220, 14, 159, 242, 120, 144, 80, 120, 70, 115, 58, 205, 1, 120, 125, 118, 39, 184, 192, 62, 155, 107, 83, 99, 62, 131, 187, 184, 102, 83, 3, 214, 114, 219, 73, 209, 225, 206, 237, 59, 105, 26, 208, 141, 39, 213, 213, 216, 226, 80, 213, 88, 154, 123, 27, 17, 248, 228, 123, 66, 154, 175, 231, 223, 20, 170, 240, 16, 94, 75, 95, 178, 166, 48, 209, 233, 6, 194, 252, 54, 131, 174, 122, 21, 95, 114, 195, 238, 80, 128, 211, 91, 108, 15, 177, 188, 39, 205, 155, 68, 235, 91, 203, 219, 29, 186, 170, 215, 219, 140, 208, 28, 62, 111, 194, 72, 50, 197, 192, 157, 212, 143, 208, 179, 38, 143, 22, 42, 5, 149, 103, 33, 155, 164, 24, 165, 77, 82, 45, 92, 73, 59, 72, 20, 2, 43, 31, 84, 5, 240, 62, 232, 152, 128, 50, 145, 145, 226, 103, 167, 141, 155, 9, 81, 15, 66, 211, 133, 107, 78, 142, 51, 86, 70, 145, 128, 246, 136, 240, 245, 108, 43, 36, 70, 208, 63, 227, 23, 115, 132, 133, 48, 12, 170, 54, 221, 207, 58, 39, 152, 70, 196, 85, 110, 246, 40, 62, 93, 22, 153, 113, 141, 114, 9, 85, 111, 26, 198, 2, 234, 205, 28, 212, 37, 109, 42, 218, 41, 142, 242, 85, 67, 120, 7, 92, 78, 203, 90, 88, 212, 176, 5, 177, 193, 212, 0, 254, 153, 254, 68, 158, 193, 35, 11, 39, 62, 114, 193, 19, 254, 166, 107, 199, 175, 169, 65, 174, 84, 62, 29, 189, 56, 81, 142, 143, 88, 213, 24, 63, 225, 225, 239, 94, 114, 40, 9, 99, 68, 163, 6, 231, 22, 88, 112, 28, 136, 118, 240, 249, 25, 154, 14, 107, 2, 98, 162, 166, 229, 84, 90, 168, 75, 208, 3, 26, 234, 188, 123, 125, 163, 192, 246, 29, 238, 1, 202, 189, 67, 89, 113, 95, 48, 225, 41, 28, 129, 135, 55, 116, 155, 80, 238, 23, 65, 15, 156, 52, 41, 63, 74, 184, 15, 73, 85, 232, 165, 174, 120, 34, 83, 251, 35, 116, 187, 94, 205, 149, 143, 195, 44, 94, 53, 10, 224, 141, 151, 187, 0, 28, 128, 106, 187, 182, 186, 40, 18, 168, 92, 22, 231, 110, 69, 139, 81, 207, 0, 183, 174, 194, 194, 93, 86, 71, 139, 71, 246, 35, 204, 102, 134, 220, 117, 16, 58, 181, 16, 43, 15, 248, 189, 138, 135, 116, 228, 57, 208, 253, 106, 127, 60, 18, 208, 196, 176, 62, 75, 203, 211, 204, 221, 98, 50, 99, 188, 186, 29, 225, 42, 205, 82, 116, 121, 116, 117, 174, 90, 96, 251, 184, 137, 117, 48, 173, 135, 207, 118, 146, 149, 18, 18, 36, 74, 121, 74, 214, 162, 76, 229, 108, 96, 154, 134, 119, 72, 94, 16, 139, 76, 144, 185, 96, 93, 42, 192, 154, 0, 24, 234, 183, 13, 214, 21, 220, 98, 25, 83, 158, 42, 231, 30, 108, 176, 207, 136, 135, 54, 198, 157, 153, 102, 77, 60, 42, 174, 97, 74, 104, 117, 123, 91, 146, 151, 12, 102, 127, 170, 184, 100, 210, 232, 220, 12, 21, 224, 166, 65, 1, 27, 184, 16, 117, 217, 191, 58, 19, 41, 96, 243, 48, 17, 180, 182, 139, 17, 159, 120, 227, 124, 119, 53, 152, 43, 166, 226, 91, 253, 225, 74, 129, 125, 7, 49, 234, 166, 89, 49, 99, 235, 122, 221, 205, 213, 213, 102, 120, 91, 115, 193, 139, 125, 234, 175, 6, 24, 71, 201, 4, 188, 55, 215, 20, 231, 210, 237, 38, 254, 236, 36, 30, 58, 219, 144, 83, 193, 245, 193, 249, 78, 77, 218, 108, 174, 13, 17, 235, 52, 177, 149, 218, 122, 63, 222, 84, 224, 255, 89, 238, 4, 6, 16, 111, 197, 228, 37, 167, 15, 174, 31, 118, 228, 86, 49, 252, 251, 209, 219, 78, 22, 227, 79, 39, 50, 44, 247, 48, 166, 81, 232, 76, 5, 19, 143, 110, 8, 144, 21, 205, 68, 27, 192, 169, 46, 0, 88, 126, 161, 96, 171, 73, 58, 118, 213, 161, 153, 145, 180, 34, 108, 55, 147, 73, 80, 243, 104, 28, 24, 229, 128, 194, 81, 81, 48, 221, 65, 49, 27, 47, 97, 81, 164, 160, 133, 152, 41, 110, 11, 143, 25, 175, 40, 68, 180, 46, 26, 211, 9, 197, 11, 20, 194, 140, 102, 102, 203, 73, 20, 255, 11, 73, 203, 249, 200, 139, 56, 106, 19, 114, 100, 67, 28, 164, 155, 26, 146, 97, 58, 96, 224, 132, 130, 193, 254, 149, 113, 216, 75, 189, 177, 189, 77, 151, 121, 80, 155, 100, 183, 122, 37, 29, 165, 212, 136, 30, 11, 171, 222, 100, 127, 145, 53, 108, 233, 35, 90, 154, 31, 7, 114, 28, 235, 68, 113, 188, 10, 233, 140, 220, 156, 167, 158, 107, 128, 237, 222, 21, 54, 107, 206, 76, 152, 112, 109, 243, 91, 37, 201, 208, 13, 153, 15, 124, 196, 229, 203, 150, 92, 193, 79, 135, 171, 18, 115, 159, 11, 63, 106, 85, 176, 239, 72, 94, 240, 180, 53, 199, 224, 202, 39, 146, 157, 14, 45, 116, 22, 153, 195, 104, 115, 10, 217, 239, 68, 36, 125, 76, 211, 169, 80, 117, 46, 139, 168, 116, 231, 240, 113, 248, 52, 168, 172, 101, 69, 39, 144, 97, 110, 254, 243, 207, 202, 250, 196, 67, 182, 52, 213, 208, 220, 231, 151, 225, 0, 211, 203, 34, 151, 59, 79, 177, 237, 95, 83, 102, 119, 42, 99, 183, 115, 150, 247, 125, 240, 46, 45, 247, 64, 127, 9, 8, 125, 161, 37, 186, 22, 228, 99, 204, 220, 87, 195, 144, 138, 58, 8, 83, 212, 54, 208, 144, 55, 217, 177, 164, 24, 130, 48, 65, 236, 233, 86, 123, 146, 155, 122, 182, 103, 148, 203, 173, 137, 209, 60, 123, 80, 142, 9, 45, 129, 166, 98, 22, 24, 188, 41, 211, 11, 153, 224, 226, 72, 8, 80, 98, 133, 99, 80, 20, 103, 50, 193, 186, 201, 21, 174, 11, 217, 240, 225, 244, 130, 125, 151, 53, 54, 196, 91, 107, 111, 72, 161, 28, 29, 101, 167, 210, 12, 99, 7, 213, 210, 11, 55, 158, 210, 43, 29, 48, 96, 49, 90, 164, 166, 134, 107, 189, 218, 141, 227, 244, 66, 159, 177, 227, 70, 164, 111, 0, 146, 162, 198, 174, 164, 135, 231, 250, 219, 228, 231, 142, 219, 77, 242, 209, 90, 155, 122, 235, 85, 215, 241, 108, 83, 234, 185, 33, 88, 173, 69, 236, 82, 3, 75, 219, 167, 31, 87, 106, 235, 66, 151, 76, 29, 75, 5, 198, 86, 218, 168, 245, 231, 162, 183, 249, 233, 156, 211, 80, 200, 206, 16, 80, 92, 35, 67, 15, 235, 142, 248, 246, 184, 67, 109, 127, 89, 12, 82, 123, 238, 252, 85, 126, 11, 162, 37, 184, 255, 108, 25, 136, 1, 156, 56, 106, 240, 53, 142, 156, 250, 26, 68, 175, 24, 13, 151, 129, 157, 0, 19, 71, 46, 142, 88, 24, 169, 147, 252, 67, 182, 12, 172, 36, 156, 40, 90, 211, 105, 20, 47, 248, 20, 182, 119, 82, 97, 237, 86, 75, 64, 13, 33, 69, 145, 203, 163, 184, 229, 97, 212, 170, 115, 161, 251, 150, 128, 152, 132, 19, 69, 75, 126, 141, 162, 134, 95, 131, 232, 137, 63, 103, 217, 50, 240, 147, 128, 226, 8, 202, 207, 113, 12, 241, 115, 196, 139, 187, 12, 252, 102, 111, 227, 200, 205, 226, 162, 32, 191, 133, 209, 154, 44, 5, 173, 73, 13, 90, 147, 26, 180, 38, 14, 90, 79, 170, 65, 58, 201, 118, 167, 162, 232, 219, 217, 20, 243, 212, 191, 183, 179, 114, 62, 158, 204, 64, 77, 211, 201, 234, 61, 91, 127, 78, 131, 49, 85, 186, 94, 47, 249, 166, 243, 77, 47, 233, 124, 253, 219, 172, 152, 110, 119, 130, 14, 247, 116, 60, 120, 39, 140, 91, 56, 210, 121, 117, 210, 40, 96, 237, 151, 150, 216, 141, 111, 118, 82, 121, 166, 244, 81, 231, 27, 65, 170, 32, 85, 20, 126, 107, 162, 67, 143, 161, 204, 145, 34, 105, 26, 81, 122, 197, 120, 58, 40, 70, 5, 172, 84, 71, 58, 191, 222, 149, 180, 159, 6, 184, 64, 215, 160, 110, 34, 43, 215, 116, 15, 241, 116, 251, 7, 117, 227, 93, 4, 75, 186, 107, 205, 233, 171, 118, 16, 32, 45, 218, 63, 168, 91, 211, 61, 133, 100, 251, 222, 201, 137, 126, 86, 142, 174, 222, 177, 208, 84, 223, 138, 31, 223, 149, 217, 73, 77, 143, 36, 114, 141, 236, 152, 77, 73, 90, 193, 253, 113, 142, 43, 90, 147, 74, 89, 197, 131, 76, 201, 186, 84, 197, 43, 14, 229, 14, 170, 248, 178, 33, 158, 201, 114, 213, 4, 90, 202, 34, 49, 79, 0, 4, 177, 226, 174, 175, 42, 167, 59, 206, 172, 91, 21, 149, 15, 101, 70, 163, 226, 2, 119, 82, 97, 17, 97, 113, 212, 240, 67, 91, 173, 18, 50, 236, 179, 78, 123, 22, 28, 182, 196, 73, 240, 180, 40, 159, 164, 131, 119, 114, 69, 241, 54, 29, 156, 157, 140, 213, 120, 8, 227, 54, 241, 118, 17, 245, 216, 132, 215, 233, 71, 106, 149, 126, 68, 214, 232, 58, 131, 149, 248, 54, 255, 226, 92, 111, 81, 215, 174, 200, 9, 222, 228, 171, 192, 222, 46, 217, 77, 39, 157, 165, 186, 59, 108, 22, 84, 221, 216, 253, 156, 1, 31, 231, 163, 76, 180, 209, 221, 236, 37, 180, 22, 229, 97, 185, 206, 12, 159, 64, 200, 166, 111, 212, 87, 122, 103, 138, 24, 43, 181, 72, 20, 197, 76, 8, 142, 202, 89, 114, 228, 125, 130, 74, 145, 80, 86, 92, 174, 139, 245, 9, 172, 53, 69, 213, 39, 227, 105, 121, 41, 40, 96, 92, 37, 186, 109, 191, 69, 178, 255, 13, 96, 106, 226, 80, 77, 15, 149, 36, 56, 112, 204, 245, 210, 193, 79, 9, 205, 101, 30, 226, 222, 0, 47, 246, 84, 107, 230, 207, 145, 207, 204, 95, 137, 190, 206, 153, 174, 214, 214, 168, 201, 85, 107, 211, 107, 249, 227, 32, 186, 162, 66, 150, 252, 79, 93, 182, 204, 215, 159, 61, 199, 215, 65, 84, 156, 14, 148, 56, 29, 48, 113, 50, 131, 120, 176, 144, 64, 205, 229, 234, 226, 56, 7, 252, 92, 115, 179, 172, 90, 231, 131, 54, 170, 117, 78, 1, 75, 219, 220, 124, 205, 12, 125, 16, 229, 101, 73, 81, 202, 202, 232, 24, 61, 255, 103, 46, 55, 80, 26, 220, 109, 7, 54, 81, 171, 117, 81, 88, 25, 177, 128, 168, 175, 195, 108, 79, 213, 74, 134, 227, 143, 54, 183, 181, 155, 186, 199, 193, 202, 161, 158, 138, 215, 44, 174, 164, 89, 232, 212, 24, 24, 87, 24, 237, 23, 126, 66, 162, 135, 162, 201, 84, 9, 54, 149, 130, 155, 19, 124, 113, 131, 162, 28, 42, 119, 237, 31, 30, 59, 43, 7, 109, 80, 173, 66, 70, 97, 233, 219, 141, 167, 20, 134, 218, 204, 91, 148, 94, 28, 41, 231, 167, 248, 178, 1, 22, 140, 102, 151, 241, 236, 28, 191, 172, 97, 33, 205, 8, 250, 139, 74, 69, 47, 159, 169, 71, 200, 128, 12, 199, 240, 184, 56, 63, 16, 42, 3, 141, 178, 142, 41, 174, 143, 164, 56, 163, 91, 87, 247, 69, 250, 194, 212, 34, 29, 132, 93, 53, 213, 13, 187, 179, 163, 145, 182, 94, 91, 85, 166, 102, 135, 231, 187, 191, 109, 49, 186, 189, 75, 43, 164, 153, 120, 10, 217, 46, 226, 117, 116, 246, 131, 52, 51, 226, 123, 135, 65, 60, 203, 46, 53, 72, 120, 12, 193, 132, 247, 181, 64, 161, 64, 199, 93, 175, 253, 1, 140, 252, 80, 102, 156, 146, 22, 236, 67, 77, 147, 30, 244, 162, 167, 26, 254, 232, 242, 161, 86, 10, 32, 203, 38, 194, 13, 88, 211, 170, 92, 168, 184, 63, 53, 71, 219, 253, 40, 92, 40, 46, 59, 35, 165, 13, 126, 136, 63, 244, 72, 13, 178, 180, 6, 212, 176, 233, 35, 216, 27, 159, 108, 203, 113, 78, 215, 101, 184, 186, 69, 154, 232, 143, 174, 33, 251, 235, 24, 48, 47, 166, 239, 178, 114, 225, 169, 197, 124, 107, 55, 177, 68, 76, 52, 12, 232, 147, 168, 244, 228, 36, 34, 113, 227, 60, 35, 191, 30, 66, 128, 187, 163, 58, 100, 7, 182, 253, 113, 10, 15, 172, 6, 227, 213, 128, 137, 66, 212, 210, 63, 55, 192, 4, 182, 243, 143, 190, 186, 18, 236, 255, 201, 165, 232, 176, 231, 91, 142, 90, 223, 255, 206, 167, 239, 228, 4, 174, 65, 247, 88, 155, 204, 38, 247, 108, 62, 97, 148, 235, 120, 23, 223, 42, 175, 13, 92, 144, 243, 83, 86, 86, 153, 2, 120, 51, 199, 153, 162, 184, 200, 112, 31, 201, 165, 86, 36, 231, 187, 248, 104, 67, 170, 205, 16, 142, 179, 11, 168, 214, 181, 81, 7, 2, 41, 84, 155, 193, 33, 80, 225, 82, 7, 70, 150, 77, 249, 157, 71, 6, 203, 13, 247, 206, 160, 118, 150, 252, 1, 49, 20, 230, 54, 140, 130, 214, 252, 210, 236, 249, 144, 69, 31, 185, 161, 167, 165, 93, 223, 198, 200, 80, 173, 134, 52, 172, 161, 180, 212, 227, 150, 238, 176, 90, 125, 239, 156, 93, 109, 35, 75, 239, 201, 57, 74, 22, 107, 77, 103, 225, 249, 53, 202, 18, 148, 130, 212, 60, 78, 80, 122, 176, 63, 146, 18, 7, 84, 45, 204, 71, 2, 174, 78, 28, 50, 52, 41, 151, 159, 243, 147, 147, 172, 204, 198, 131, 236, 134, 170, 22, 139, 224, 34, 138, 37, 162, 241, 63, 179, 190, 40, 169, 132, 126, 81, 26, 159, 66, 105, 12, 179, 81, 54, 205, 110, 163, 222, 104, 213, 29, 87, 7, 180, 146, 253, 163, 203, 243, 243, 108, 90, 230, 131, 207, 165, 4, 176, 135, 237, 61, 126, 74, 47, 224, 143, 78, 184, 11, 1, 103, 197, 157, 183, 57, 23, 154, 91, 22, 99, 44, 190, 186, 157, 127, 118, 106, 197, 153, 251, 21, 4, 112, 10, 126, 58, 185, 161, 179, 146, 69, 112, 145, 89, 105, 225, 169, 231, 113, 120, 230, 137, 101, 67, 158, 199, 122, 253, 95, 236, 135, 54, 57, 75, 174, 50, 239, 184, 99, 224, 113, 186, 10, 162, 243, 249, 124, 2, 43, 167, 155, 205, 233, 26, 197, 79, 202, 235, 59, 243, 241, 250, 124, 218, 123, 201, 179, 116, 36, 235, 77, 131, 2, 94, 144, 101, 126, 206, 171, 255, 64, 60, 34, 244, 237, 182, 205, 215, 28, 251, 133, 167, 234, 47, 107, 253, 187, 103, 182, 251, 210, 112, 179, 237, 242, 5, 215, 243, 13, 221, 172, 17, 254, 127, 229, 217, 69, 54, 220, 45, 203, 244, 242, 167, 25, 88, 187, 251, 39, 135, 89, 126, 146, 67, 200, 69, 10, 111, 85, 51, 38, 33, 237, 219, 217, 73, 18, 187, 210, 74, 85, 208, 81, 232, 244, 220, 158, 81, 24, 162, 58, 92, 162, 7, 80, 244, 109, 59, 44, 125, 202, 207, 217, 52, 29, 188, 203, 134, 10, 23, 40, 126, 146, 145, 136, 30, 245, 59, 166, 86, 152, 250, 222, 214, 98, 106, 42, 105, 21, 69, 58, 171, 27, 136, 106, 42, 111, 70, 104, 121, 149, 149, 130, 219, 75, 238, 211, 64, 19, 114, 39, 213, 15, 234, 86, 244, 77, 119, 183, 97, 119, 170, 250, 79, 113, 164, 227, 128, 67, 160, 250, 211, 60, 118, 154, 6, 49, 194, 198, 246, 207, 190, 183, 199, 120, 16, 119, 85, 161, 5, 186, 40, 40, 108, 195, 60, 214, 49, 21, 136, 67, 67, 228, 198, 213, 172, 204, 0, 17, 85, 16, 36, 135, 214, 72, 203, 83, 26, 36, 100, 47, 196, 88, 85, 57, 73, 108, 77, 249, 82, 119, 47, 210, 62, 20, 217, 38, 163, 173, 187, 236, 79, 79, 48, 57, 89, 216, 193, 57, 42, 213, 17, 34, 157, 58, 186, 192, 228, 196, 187, 108, 193, 6, 46, 45, 53, 91, 159, 70, 254, 6, 234, 0, 14, 236, 142, 13, 108, 65, 61, 206, 131, 166, 211, 250, 4, 56, 92, 213, 107, 201, 69, 247, 67, 249, 28, 15, 101, 235, 54, 90, 59, 133, 44, 247, 77, 149, 124, 67, 48, 250, 38, 153, 224, 221, 208, 220, 190, 147, 83, 161, 248, 30, 202, 46, 164, 250, 79, 238, 80, 9, 164, 162, 112, 211, 147, 180, 238, 208, 62, 35, 172, 133, 115, 152, 77, 138, 114, 250, 107, 149, 158, 102, 242, 104, 7, 28, 142, 236, 9, 173, 113, 31, 206, 151, 245, 191, 131, 67, 233, 247, 87, 87, 105, 147, 149, 6, 27, 218, 157, 235, 227, 137, 172, 206, 223, 255, 142, 253, 49, 132, 72, 212, 182, 179, 162, 21, 33, 149, 207, 19, 66, 193, 231, 195, 116, 154, 57, 221, 241, 57, 159, 238, 129, 171, 15, 78, 21, 59, 73, 68, 100, 64, 147, 137, 75, 1, 77, 70, 225, 93, 70, 19, 109, 2, 74, 71, 203, 254, 35, 117, 117, 16, 175, 28, 85, 66, 212, 194, 112, 49, 12, 140, 194, 183, 127, 251, 46, 38, 96, 42, 178, 6, 116, 10, 158, 203, 32, 131, 192, 243, 4, 168, 41, 253, 194, 86, 77, 106, 110, 182, 149, 216, 80, 80, 225, 23, 230, 142, 58, 217, 171, 192, 16, 179, 6, 237, 49, 27, 121, 172, 55, 74, 86, 236, 137, 95, 87, 30, 161, 201, 224, 180, 38, 207, 15, 231, 145, 235, 123, 221, 117, 123, 48, 150, 103, 53, 181, 128, 27, 233, 138, 35, 203, 232, 170, 167, 194, 183, 151, 211, 236, 224, 228, 68, 26, 106, 215, 77, 107, 108, 83, 61, 219, 118, 23, 29, 135, 249, 169, 191, 16, 245, 132, 5, 161, 114, 104, 181, 35, 227, 167, 38, 223, 205, 33, 153, 158, 41, 93, 121, 206, 62, 100, 231, 147, 81, 26, 16, 102, 184, 20, 188, 118, 166, 213, 85, 41, 42, 53, 154, 99, 207, 52, 209, 22, 69, 28, 83, 1, 221, 96, 185, 66, 41, 205, 217, 20, 153, 244, 26, 58, 128, 120, 236, 213, 10, 102, 219, 78, 185, 28, 219, 162, 119, 215, 209, 39, 23, 141, 96, 231, 98, 157, 130, 37, 177, 13, 241, 116, 253, 29, 77, 22, 233, 65, 43, 110, 63, 160, 61, 80, 120, 203, 207, 52, 226, 112, 43, 138, 224, 251, 172, 188, 36, 49, 172, 201, 85, 48, 109, 63, 165, 88, 71, 71, 67, 250, 17, 119, 70, 249, 86, 30, 244, 238, 252, 151, 133, 248, 95, 27, 38, 219, 228, 70, 6, 189, 233, 184, 182, 230, 53, 197, 76, 219, 192, 115, 191, 15, 143, 147, 190, 88, 137, 242, 44, 36, 9, 9, 30, 101, 30, 189, 179, 68, 38, 30, 57, 83, 211, 169, 120, 224, 169, 70, 206, 48, 233, 125, 114, 112, 124, 246, 218, 186, 114, 166, 89, 101, 179, 31, 182, 14, 76, 62, 195, 212, 206, 103, 214, 47, 36, 169, 100, 161, 45, 224, 237, 59, 170, 57, 81, 236, 176, 26, 141, 51, 182, 159, 224, 230, 146, 46, 6, 75, 87, 152, 79, 100, 179, 135, 57, 138, 156, 229, 6, 95, 64, 168, 67, 81, 127, 254, 9, 169, 229, 200, 156, 193, 78, 116, 52, 56, 6, 27, 214, 94, 220, 63, 248, 158, 230, 27, 86, 105, 89, 240, 7, 228, 25, 194, 199, 14, 239, 89, 192, 105, 72, 101, 139, 45, 187, 235, 87, 179, 84, 196, 34, 50, 37, 57, 70, 197, 11, 11, 88, 182, 16, 132, 254, 18, 177, 59, 211, 145, 192, 127, 3, 226, 153, 95, 253, 77, 203, 121, 138, 233, 94, 21, 63, 229, 167, 251, 130, 129, 237, 254, 179, 227, 217, 210, 229, 94, 204, 206, 223, 102, 37, 45, 183, 162, 55, 20, 71, 233, 52, 127, 159, 53, 101, 138, 57, 195, 36, 44, 188, 124, 67, 202, 23, 86, 56, 158, 247, 197, 41, 70, 179, 180, 232, 79, 87, 72, 177, 230, 32, 142, 41, 100, 218, 160, 141, 217, 100, 234, 145, 102, 137, 101, 106, 92, 85, 109, 156, 55, 7, 206, 194, 117, 97, 223, 77, 45, 23, 34, 85, 2, 185, 223, 108, 71, 84, 2, 21, 169, 246, 228, 23, 166, 248, 64, 215, 137, 250, 146, 153, 156, 85, 195, 65, 100, 42, 19, 162, 6, 11, 236, 187, 50, 151, 157, 200, 238, 124, 170, 201, 236, 213, 194, 211, 152, 114, 109, 79, 48, 194, 241, 205, 179, 188, 34, 33, 142, 131, 116, 34, 198, 76, 166, 131, 216, 188, 226, 156, 23, 243, 217, 211, 105, 238, 149, 51, 193, 217, 185, 12, 48, 60, 214, 216, 172, 173, 1, 111, 169, 146, 124, 98, 131, 182, 119, 131, 150, 163, 107, 164, 31, 244, 76, 231, 156, 253, 57, 213, 51, 88, 28, 235, 2, 226, 151, 237, 222, 238, 241, 88, 182, 14, 8, 141, 221, 244, 150, 187, 237, 167, 83, 197, 238, 177, 249, 84, 40, 251, 137, 104, 57, 135, 235, 193, 110, 187, 28, 140, 135, 113, 41, 48, 157, 156, 71, 8, 72, 165, 27, 98, 208, 197, 152, 219, 96, 26, 51, 225, 60, 107, 45, 196, 213, 248, 137, 32, 219, 158, 201, 228, 84, 23, 97, 49, 117, 207, 247, 109, 225, 51, 164, 147, 96, 55, 124, 218, 52, 246, 90, 13, 235, 201, 62, 54, 156, 197, 188, 109, 76, 56, 15, 183, 1, 143, 70, 121, 45, 200, 102, 235, 253, 249, 248, 75, 95, 55, 31, 98, 50, 239, 188, 239, 13, 231, 49, 173, 203, 44, 64, 202, 78, 120, 176, 247, 14, 173, 79, 91, 175, 59, 9, 27, 57, 83, 222, 34, 90, 73, 17, 50, 204, 51, 251, 234, 190, 27, 188, 159, 224, 201, 72, 222, 153, 162, 82, 41, 234, 44, 76, 155, 55, 97, 37, 201, 241, 195, 151, 6, 203, 192, 82, 18, 59, 230, 232, 162, 54, 11, 70, 119, 181, 89, 107, 186, 107, 223, 126, 40, 137, 214, 122, 159, 50, 24, 207, 228, 104, 80, 183, 27, 244, 58, 107, 40, 89, 3, 136, 87, 61, 175, 229, 255, 206, 202, 226, 96, 124, 48, 155, 30, 156, 252, 84, 8, 126, 168, 32, 190, 199, 64, 81, 153, 21, 31, 203, 100, 197, 181, 248, 156, 177, 210, 6, 119, 96, 223, 177, 183, 110, 133, 183, 106, 41, 54, 182, 83, 240, 25, 61, 157, 152, 32, 227, 51, 29, 71, 22, 45, 174, 44, 108, 91, 56, 106, 245, 242, 232, 17, 31, 228, 185, 244, 103, 128, 179, 255, 79, 1, 185, 141, 77, 42, 245, 27, 193, 195, 58, 53, 190, 207, 174, 128, 237, 117, 243, 170, 10, 105, 154, 200, 144, 160, 96, 62, 121, 56, 178, 216, 235, 200, 197, 123, 52, 21, 125, 140, 217, 109, 198, 56, 137, 135, 186, 112, 225, 42, 220, 204, 239, 109, 112, 155, 11, 221, 117, 139, 119, 22, 67, 239, 228, 186, 57, 89, 199, 124, 138, 38, 8, 5, 80, 203, 20, 123, 109, 74, 139, 82, 5, 66, 153, 111, 44, 13, 191, 46, 200, 23, 44, 192, 229, 125, 100, 105, 192, 206, 179, 87, 177, 26, 51, 88, 145, 217, 15, 229, 77, 85, 98, 4, 214, 188, 86, 216, 44, 167, 186, 189, 67, 69, 88, 86, 109, 217, 105, 123, 227, 2, 145, 147, 195, 136, 152, 252, 51, 187, 252, 252, 14, 247, 205, 152, 195, 29, 110, 192, 10, 78, 81, 201, 162, 2, 29, 182, 82, 30, 243, 51, 254, 81, 153, 111, 41, 245, 92, 238, 35, 179, 87, 226, 88, 20, 246, 125, 39, 72, 128, 14, 126, 39, 129, 246, 159, 96, 142, 173, 195, 229, 166, 76, 171, 49, 139, 205, 78, 183, 78, 134, 115, 161, 226, 80, 63, 44, 111, 226, 213, 202, 65, 77, 167, 204, 143, 41, 0, 142, 173, 70, 194, 198, 113, 42, 53, 83, 228, 99, 101, 54, 174, 175, 127, 178, 25, 242, 121, 58, 185, 125, 107, 133, 200, 226, 243, 60, 157, 220, 14, 231, 95, 107, 127, 25, 115, 252, 182, 240, 147, 156, 75, 122, 107, 103, 73, 11, 223, 159, 179, 200, 0, 95, 155, 244, 34, 19, 64, 139, 251, 219, 4, 111, 133, 23, 28, 135, 217, 112, 54, 200, 238, 12, 223, 149, 178, 59, 159, 130, 245, 152, 74, 132, 24, 203, 134, 91, 37, 220, 126, 240, 100, 33, 198, 88, 135, 31, 233, 96, 48, 59, 159, 141, 48, 163, 120, 107, 222, 22, 12, 180, 182, 246, 154, 41, 49, 159, 53, 57, 236, 154, 75, 74, 253, 108, 95, 222, 245, 164, 4, 150, 126, 37, 153, 88, 47, 64, 204, 75, 62, 59, 33, 247, 146, 218, 17, 133, 168, 120, 243, 48, 63, 125, 55, 189, 61, 12, 138, 125, 158, 195, 81, 87, 218, 110, 126, 178, 180, 105, 203, 231, 94, 50, 129, 95, 141, 135, 215, 215, 57, 15, 123, 19, 241, 237, 98, 225, 247, 112, 152, 171, 123, 19, 214, 187, 29, 15, 173, 79, 177, 194, 61, 207, 135, 195, 81, 70, 13, 186, 147, 81, 81, 200, 75, 153, 146, 191, 98, 206, 47, 51, 167, 142, 138, 11, 185, 5, 44, 6, 92, 61, 194, 81, 0, 5, 1, 223, 240, 73, 118, 38, 250, 90, 26, 230, 83, 85, 214, 245, 21, 21, 6, 160, 221, 177, 144, 63, 73, 24, 138, 172, 111, 63, 203, 159, 248, 89, 23, 134, 24, 14, 83, 74, 127, 82, 5, 161, 97, 3, 223, 97, 141, 216, 62, 239, 81, 240, 74, 156, 54, 103, 201, 56, 151, 28, 44, 141, 69, 14, 230, 8, 8, 145, 216, 183, 227, 26, 87, 223, 214, 176, 200, 151, 16, 139, 101, 134, 88, 200, 157, 107, 188, 216, 193, 191, 142, 78, 136, 199, 25, 189, 13, 163, 253, 126, 49, 187, 235, 70, 53, 240, 56, 217, 164, 210, 40, 175, 237, 25, 50, 128, 63, 229, 211, 139, 188, 202, 20, 215, 11, 40, 187, 210, 194, 181, 176, 144, 213, 85, 77, 187, 128, 170, 139, 192, 8, 48, 146, 137, 134, 183, 91, 216, 248, 2, 207, 255, 153, 48, 13, 26, 85, 191, 123, 60, 86, 123, 233, 214, 112, 130, 127, 193, 211, 97, 187, 49, 113, 46, 206, 239, 142, 241, 92, 137, 206, 220, 165, 253, 157, 79, 21, 127, 88, 19, 126, 104, 175, 114, 113, 24, 10, 227, 18, 219, 174, 223, 128, 207, 194, 11, 184, 87, 197, 179, 66, 32, 155, 161, 255, 114, 36, 127, 84, 52, 242, 176, 151, 20, 19, 168, 196, 94, 90, 70, 77, 49, 52, 190, 45, 179, 166, 38, 46, 189, 61, 195, 218, 58, 237, 125, 214, 39, 121, 89, 77, 159, 24, 239, 173, 4, 81, 235, 32, 150, 160, 66, 99, 73, 33, 109, 76, 25, 189, 122, 172, 25, 121, 139, 175, 134, 77, 156, 242, 224, 134, 143, 122, 157, 29, 166, 211, 78, 229, 20, 175, 101, 50, 106, 41, 251, 224, 245, 134, 6, 80, 176, 239, 225, 188, 152, 3, 209, 175, 124, 76, 25, 138, 187, 178, 13, 37, 66, 68, 32, 240, 61, 26, 144, 111, 171, 174, 141, 27, 115, 84, 31, 205, 222, 202, 78, 116, 223, 102, 167, 249, 216, 177, 101, 218, 220, 49, 117, 47, 122, 36, 107, 153, 70, 175, 194, 174, 222, 168, 193, 158, 4, 34, 93, 219, 196, 36, 234, 115, 98, 109, 66, 27, 201, 196, 200, 15, 153, 153, 67, 128, 229, 224, 153, 190, 21, 180, 217, 223, 169, 107, 99, 205, 159, 76, 68, 63, 111, 202, 188, 102, 21, 180, 241, 240, 19, 80, 136, 89, 93, 146, 102, 166, 156, 252, 133, 155, 207, 204, 138, 81, 21, 163, 118, 140, 237, 202, 26, 175, 210, 108, 207, 96, 49, 3, 193, 224, 130, 187, 51, 58, 93, 171, 141, 206, 182, 239, 89, 31, 37, 238, 140, 44, 156, 76, 107, 180, 119, 127, 161, 224, 245, 136, 250, 230, 158, 88, 44, 147, 109, 237, 106, 119, 54, 213, 151, 59, 5, 120, 184, 198, 180, 10, 156, 16, 129, 127, 144, 132, 85, 243, 46, 57, 108, 148, 184, 125, 241, 153, 181, 217, 78, 181, 67, 18, 179, 86, 51, 140, 104, 153, 199, 96, 13, 13, 116, 123, 179, 213, 31, 228, 113, 118, 97, 100, 192, 189, 12, 87, 33, 183, 78, 134, 205, 185, 15, 175, 134, 224, 148, 206, 134, 202, 236, 64, 23, 167, 176, 122, 105, 176, 89, 137, 159, 79, 222, 157, 170, 107, 221, 110, 138, 2, 36, 60, 148, 71, 226, 49, 118, 93, 95, 83, 195, 41, 216, 154, 133, 92, 72, 169, 232, 96, 21, 203, 101, 252, 246, 57, 19, 237, 192, 43, 184, 145, 15, 236, 171, 196, 52, 28, 5, 225, 151, 91, 33, 49, 17, 242, 144, 64, 56, 6, 131, 217, 148, 100, 214, 19, 125, 146, 179, 115, 91, 251, 108, 119, 26, 182, 206, 32, 68, 12, 246, 233, 110, 77, 156, 97, 139, 120, 86, 232, 207, 45, 140, 105, 213, 14, 202, 144, 75, 241, 22, 6, 182, 194, 40, 212, 243, 220, 255, 134, 0, 87, 211, 207, 219, 26, 228, 90, 199, 149, 55, 43, 210, 213, 144, 154, 114, 221, 87, 182, 140, 228, 240, 207, 31, 187, 210, 95, 13, 95, 64, 226, 34, 42, 116, 156, 202, 240, 212, 137, 69, 98, 14, 70, 179, 161, 232, 208, 29, 12, 197, 84, 61, 251, 156, 65, 35, 94, 246, 160, 198, 112, 204, 79, 21, 35, 73, 60, 134, 196, 92, 128, 186, 71, 130, 143, 36, 239, 192, 66, 204, 101, 11, 144, 63, 95, 242, 184, 251, 39, 1, 63, 129, 99, 104, 24, 63, 80, 104, 137, 45, 175, 170, 149, 121, 231, 170, 98, 86, 14, 132, 188, 159, 167, 147, 147, 49, 119, 238, 212, 94, 33, 181, 231, 91, 161, 244, 24, 249, 94, 84, 29, 62, 48, 87, 103, 237, 49, 229, 7, 209, 8, 242, 182, 84, 5, 79, 225, 115, 47, 228, 175, 112, 85, 176, 44, 74, 72, 212, 164, 128, 251, 216, 91, 126, 211, 43, 182, 159, 216, 91, 146, 217, 160, 219, 207, 30, 135, 189, 66, 82, 8, 216, 154, 159, 102, 21, 185, 47, 24, 86, 27, 146, 202, 129, 4, 60, 230, 174, 112, 155, 129, 135, 215, 189, 231, 46, 17, 253, 207, 212, 33, 224, 210, 134, 149, 142, 211, 232, 251, 190, 63, 73, 41, 156, 57, 145, 36, 120, 77, 10, 39, 253, 19, 31, 126, 245, 21, 53, 151, 6, 101, 154, 7, 56, 248, 152, 184, 196, 18, 61, 242, 116, 170, 128, 102, 138, 51, 229, 135, 144, 233, 119, 166, 184, 95, 234, 73, 253, 96, 50, 205, 207, 213, 178, 184, 171, 87, 143, 212, 103, 31, 81, 82, 8, 127, 219, 148, 171, 81, 78, 193, 178, 83, 152, 248, 32, 63, 99, 82, 147, 35, 100, 175, 151, 236, 217, 125, 22, 84, 180, 45, 252, 208, 168, 179, 117, 19, 42, 172, 7, 121, 237, 236, 181, 133, 245, 209, 60, 105, 245, 161, 171, 232, 50, 31, 91, 14, 76, 116, 76, 94, 166, 131, 179, 165, 15, 202, 156, 4, 84, 237, 210, 107, 176, 145, 217, 201, 12, 149, 203, 132, 149, 20, 91, 211, 128, 97, 249, 237, 150, 228, 114, 210, 215, 130, 27, 124, 31, 111, 246, 123, 85, 200, 19, 159, 90, 187, 114, 49, 180, 190, 91, 197, 73, 170, 54, 185, 0, 222, 200, 113, 76, 186, 44, 145, 2, 185, 180, 246, 156, 92, 90, 91, 92, 134, 93, 162, 146, 54, 194, 41, 87, 176, 118, 59, 134, 100, 11, 30, 213, 49, 194, 138, 126, 252, 26, 42, 19, 67, 241, 31, 131, 142, 118, 169, 175, 249, 65, 214, 85, 83, 229, 33, 91, 4, 121, 242, 224, 132, 185, 57, 1, 181, 108, 104, 181, 70, 151, 94, 219, 103, 249, 153, 58, 193, 207, 149, 152, 99, 161, 104, 23, 157, 169, 66, 217, 175, 253, 224, 44, 54, 40, 115, 239, 85, 25, 44, 217, 158, 85, 221, 136, 204, 61, 30, 124, 52, 234, 199, 130, 38, 205, 176, 227, 80, 99, 178, 28, 156, 116, 201, 106, 83, 13, 129, 183, 86, 210, 244, 92, 186, 137, 50, 206, 46, 150, 61, 58, 10, 164, 34, 14, 93, 220, 157, 185, 187, 37, 170, 32, 35, 14, 153, 37, 231, 188, 51, 209, 171, 88, 115, 117, 162, 205, 20, 202, 85, 27, 92, 156, 39, 234, 157, 203, 117, 132, 106, 215, 152, 211, 185, 181, 124, 130, 220, 35, 235, 244, 228, 37, 126, 213, 42, 25, 30, 148, 180, 220, 181, 87, 92, 107, 229, 190, 51, 44, 31, 48, 135, 177, 104, 79, 215, 101, 185, 251, 141, 122, 62, 126, 109, 80, 212, 6, 122, 36, 245, 249, 88, 93, 5, 16, 219, 240, 122, 110, 187, 64, 117, 58, 239, 135, 147, 104, 214, 237, 5, 220, 32, 7, 69, 58, 158, 137, 5, 111, 55, 26, 178, 166, 255, 44, 77, 194, 159, 211, 105, 250, 18, 147, 29, 154, 196, 194, 249, 218, 154, 218, 122, 219, 224, 89, 71, 144, 47, 84, 49, 198, 74, 196, 228, 89, 60, 142, 136, 230, 164, 230, 75, 240, 185, 179, 82, 147, 234, 109, 22, 170, 177, 248, 34, 183, 91, 1, 95, 142, 151, 234, 227, 32, 198, 117, 52, 203, 7, 213, 62, 166, 9, 112, 240, 47, 28, 130, 36, 119, 139, 191, 132, 33, 181, 12, 67, 82, 123, 39, 177, 56, 36, 73, 75, 26, 139, 132, 25, 92, 3, 233, 206, 14, 122, 177, 219, 202, 200, 192, 118, 86, 105, 195, 111, 234, 12, 81, 149, 56, 80, 253, 95, 33, 105, 170, 230, 21, 178, 48, 93, 67, 34, 204, 159, 48, 213, 47, 166, 79, 54, 111, 194, 2, 5, 72, 172, 174, 6, 215, 126, 30, 59, 27, 80, 113, 69, 100, 179, 126, 126, 116, 87, 189, 20, 17, 104, 149, 105, 57, 236, 142, 131, 89, 115, 107, 15, 184, 190, 35, 100, 177, 94, 13, 178, 14, 137, 31, 207, 106, 214, 18, 164, 7, 228, 212, 149, 75, 164, 87, 66, 151, 152, 67, 87, 74, 69, 180, 164, 213, 138, 214, 215, 134, 76, 98, 76, 14, 162, 10, 228, 91, 166, 64, 210, 193, 116, 150, 142, 158, 133, 156, 223, 97, 173, 98, 169, 171, 57, 197, 130, 216, 209, 236, 22, 107, 251, 59, 205, 144, 61, 219, 240, 146, 52, 225, 96, 86, 150, 66, 8, 158, 53, 42, 68, 104, 70, 41, 186, 29, 82, 137, 78, 187, 126, 124, 33, 156, 169, 66, 188, 73, 59, 40, 228, 250, 64, 139, 109, 19, 174, 230, 129, 73, 209, 18, 75, 110, 59, 29, 244, 180, 86, 144, 45, 244, 44, 219, 5, 12, 45, 45, 141, 53, 105, 210, 129, 101, 184, 181, 229, 145, 207, 79, 181, 253, 21, 157, 143, 230, 179, 216, 252, 154, 109, 76, 182, 175, 142, 222, 165, 37, 227, 166, 121, 47, 215, 142, 212, 111, 211, 184, 95, 119, 41, 150, 133, 7, 118, 161, 91, 47, 92, 32, 87, 177, 50, 194, 29, 13, 4, 253, 40, 139, 193, 43, 254, 197, 110, 184, 75, 118, 131, 55, 188, 215, 111, 61, 160, 247, 66, 155, 14, 106, 141, 26, 21, 23, 180, 30, 92, 137, 225, 147, 122, 180, 90, 100, 94, 252, 110, 179, 205, 172, 110, 144, 211, 182, 4, 153, 64, 15, 240, 242, 240, 3, 16, 120, 175, 249, 234, 121, 118, 94, 148, 151, 176, 83, 130, 133, 233, 134, 164, 135, 76, 235, 137, 182, 78, 24, 85, 59, 243, 207, 181, 223, 109, 214, 206, 181, 94, 147, 116, 202, 146, 29, 99, 243, 149, 6, 196, 39, 172, 184, 87, 192, 245, 77, 0, 201, 224, 93, 36, 83, 179, 189, 229, 192, 50, 177, 32, 83, 52, 199, 255, 156, 73, 155, 67, 233, 222, 35, 232, 190, 42, 240, 240, 208, 240, 166, 29, 106, 178, 152, 125, 138, 115, 77, 252, 224, 132, 51, 136, 11, 156, 23, 134, 45, 79, 19, 15, 112, 198, 79, 49, 193, 55, 27, 157, 2, 191, 208, 45, 136, 71, 132, 205, 119, 199, 72, 138, 157, 90, 128, 145, 87, 1, 89, 250, 102, 160, 27, 48, 146, 44, 82, 141, 101, 170, 237, 112, 204, 63, 197, 232, 182, 141, 99, 83, 122, 195, 132, 157, 213, 71, 180, 145, 194, 141, 177, 109, 188, 108, 77, 148, 155, 100, 173, 155, 149, 50, 151, 45, 52, 154, 163, 152, 15, 236, 38, 191, 85, 224, 170, 231, 24, 188, 71, 95, 9, 130, 250, 107, 18, 169, 218, 15, 211, 241, 169, 89, 250, 240, 3, 170, 215, 33, 172, 90, 32, 207, 36, 33, 41, 138, 63, 34, 145, 30, 146, 80, 178, 5, 37, 85, 88, 6, 69, 57, 21, 186, 22, 54, 125, 197, 132, 116, 50, 182, 162, 106, 94, 181, 219, 127, 183, 16, 218, 239, 193, 195, 1, 30, 91, 141, 175, 168, 63, 77, 32, 217, 178, 71, 15, 199, 65, 15, 12, 61, 11, 77, 146, 206, 120, 23, 141, 217, 230, 223, 84, 5, 88, 216, 187, 148, 50, 181, 131, 249, 239, 44, 61, 123, 158, 78, 200, 84, 13, 219, 155, 202, 123, 46, 198, 197, 46, 175, 206, 211, 137, 163, 166, 210, 225, 80, 250, 116, 196, 23, 184, 198, 141, 172, 187, 204, 168, 202, 34, 117, 65, 109, 184, 69, 162, 202, 105, 68, 217, 237, 108, 251, 211, 236, 60, 116, 57, 155, 69, 209, 97, 41, 226, 55, 135, 186, 113, 126, 122, 240, 173, 88, 129, 98, 255, 185, 251, 60, 228, 176, 151, 40, 202, 160, 143, 158, 193, 235, 120, 243, 53, 249, 209, 127, 141, 61, 112, 200, 43, 239, 250, 109, 34, 175, 138, 255, 15, 145, 87, 124, 217, 16, 207, 215, 68, 222, 232, 229, 119, 62, 125, 107, 168, 34, 239, 160, 224, 151, 251, 10, 50, 252, 127, 27, 8, 248, 46 }; + static const unsigned char data[] = { 120, 156, 237, 125, 107, 83, 28, 71, 178, 232, 119, 126, 69, 51, 225, 99, 15, 102, 224, 48, 72, 246, 122, 133, 36, 47, 198, 146, 151, 176, 36, 20, 140, 118, 55, 226, 112, 21, 58, 173, 153, 6, 122, 25, 186, 199, 221, 61, 2, 108, 235, 252, 246, 91, 89, 207, 204, 122, 244, 99, 24, 36, 96, 165, 8, 155, 158, 238, 170, 172, 172, 172, 204, 172, 172, 172, 172, 172, 227, 121, 54, 174, 210, 60, 139, 178, 228, 226, 221, 97, 50, 206, 139, 73, 127, 45, 250, 99, 37, 138, 138, 164, 154, 23, 89, 84, 86, 147, 119, 7, 239, 255, 157, 140, 171, 119, 227, 34, 137, 171, 164, 159, 205, 167, 211, 181, 157, 149, 143, 43, 199, 170, 238, 155, 252, 167, 60, 159, 38, 113, 214, 255, 64, 234, 174, 174, 126, 176, 202, 189, 154, 159, 191, 79, 10, 171, 216, 58, 45, 53, 138, 207, 147, 127, 198, 211, 121, 242, 63, 73, 145, 247, 47, 7, 209, 21, 41, 125, 25, 61, 121, 242, 36, 186, 138, 254, 252, 51, 234, 95, 70, 171, 236, 249, 50, 250, 250, 107, 246, 2, 30, 175, 40, 98, 191, 36, 213, 203, 164, 58, 205, 39, 253, 127, 14, 162, 215, 2, 204, 206, 14, 251, 223, 135, 184, 136, 160, 84, 244, 36, 250, 231, 209, 235, 183, 240, 42, 61, 142, 250, 251, 229, 43, 214, 185, 131, 226, 31, 217, 36, 57, 78, 179, 100, 210, 135, 66, 107, 162, 162, 198, 96, 174, 190, 66, 181, 143, 178, 234, 234, 126, 185, 23, 79, 167, 241, 251, 105, 66, 43, 189, 57, 45, 242, 139, 55, 87, 179, 228, 89, 81, 228, 69, 127, 184, 61, 136, 42, 246, 43, 63, 230, 8, 172, 41, 24, 18, 54, 188, 35, 93, 216, 47, 95, 23, 249, 44, 41, 170, 171, 95, 147, 171, 126, 92, 156, 204, 207, 147, 172, 18, 192, 161, 23, 0, 139, 245, 66, 130, 84, 223, 119, 12, 68, 81, 128, 209, 166, 87, 86, 69, 154, 157, 244, 128, 114, 232, 229, 213, 249, 251, 124, 218, 163, 35, 48, 75, 198, 105, 82, 238, 229, 25, 171, 50, 31, 87, 12, 237, 252, 253, 191, 7, 17, 235, 118, 60, 159, 86, 232, 189, 69, 82, 120, 197, 144, 97, 133, 55, 199, 166, 144, 162, 174, 248, 202, 26, 213, 4, 180, 8, 235, 194, 183, 40, 44, 24, 145, 3, 10, 209, 247, 187, 239, 7, 81, 47, 231, 229, 190, 41, 163, 111, 16, 26, 223, 68, 51, 73, 201, 158, 166, 58, 32, 93, 50, 140, 225, 251, 17, 227, 150, 159, 230, 233, 180, 74, 179, 17, 39, 74, 191, 87, 10, 66, 244, 214, 106, 56, 164, 180, 217, 163, 190, 23, 251, 132, 172, 78, 229, 82, 149, 181, 186, 197, 203, 12, 31, 14, 248, 223, 222, 223, 254, 38, 49, 211, 93, 138, 216, 224, 235, 94, 163, 78, 247, 88, 5, 71, 38, 12, 216, 205, 205, 77, 198, 50, 165, 64, 162, 42, 174, 36, 50, 99, 198, 201, 207, 101, 133, 62, 104, 0, 245, 227, 93, 60, 155, 77, 175, 6, 22, 118, 3, 51, 162, 131, 136, 195, 227, 189, 96, 96, 170, 241, 105, 212, 79, 172, 62, 38, 170, 143, 59, 54, 98, 187, 39, 39, 69, 114, 194, 148, 204, 18, 176, 163, 176, 150, 134, 226, 126, 86, 37, 69, 22, 79, 151, 128, 33, 1, 181, 28, 4, 129, 57, 117, 195, 172, 10, 250, 180, 151, 207, 174, 126, 142, 171, 88, 170, 19, 198, 60, 253, 138, 181, 147, 84, 131, 168, 204, 231, 197, 56, 25, 68, 201, 229, 120, 58, 159, 36, 147, 253, 42, 57, 47, 145, 104, 239, 212, 112, 63, 175, 106, 113, 49, 150, 174, 227, 34, 63, 103, 2, 246, 38, 151, 178, 43, 43, 40, 141, 113, 150, 92, 129, 252, 185, 200, 29, 20, 140, 216, 7, 23, 25, 211, 122, 6, 81, 0, 102, 163, 169, 112, 19, 144, 152, 118, 225, 243, 147, 23, 159, 99, 166, 127, 250, 208, 106, 202, 240, 103, 243, 72, 180, 181, 35, 31, 31, 115, 68, 54, 167, 73, 118, 82, 157, 202, 151, 235, 235, 10, 138, 68, 148, 85, 128, 82, 71, 252, 43, 215, 8, 162, 101, 254, 16, 69, 171, 167, 113, 201, 16, 6, 68, 28, 82, 126, 253, 181, 44, 228, 112, 134, 156, 91, 149, 28, 239, 151, 207, 50, 166, 193, 11, 152, 71, 84, 127, 25, 192, 53, 94, 93, 225, 19, 69, 63, 115, 242, 35, 138, 93, 105, 26, 241, 230, 161, 226, 17, 123, 122, 187, 38, 208, 252, 200, 41, 80, 203, 13, 255, 200, 142, 153, 238, 75, 10, 54, 168, 148, 47, 16, 35, 220, 30, 30, 144, 70, 200, 231, 30, 250, 69, 135, 115, 137, 35, 153, 207, 217, 160, 81, 155, 77, 127, 75, 179, 76, 127, 211, 95, 123, 199, 121, 222, 227, 116, 33, 170, 99, 183, 40, 226, 171, 103, 31, 146, 226, 138, 247, 234, 125, 60, 62, 59, 206, 34, 99, 104, 28, 224, 17, 172, 78, 211, 82, 143, 31, 35, 29, 255, 246, 130, 147, 176, 127, 32, 105, 169, 135, 103, 87, 26, 37, 165, 44, 176, 198, 199, 106, 43, 52, 129, 127, 55, 136, 182, 216, 28, 206, 241, 217, 100, 132, 172, 114, 176, 86, 54, 19, 64, 205, 204, 220, 182, 205, 101, 112, 174, 179, 188, 126, 102, 22, 238, 249, 44, 157, 38, 12, 167, 62, 107, 5, 215, 194, 28, 251, 134, 117, 200, 69, 251, 105, 52, 140, 126, 228, 243, 148, 252, 212, 31, 174, 69, 143, 168, 61, 168, 25, 237, 76, 48, 217, 25, 99, 48, 70, 15, 246, 96, 152, 138, 243, 44, 27, 156, 232, 192, 240, 1, 239, 15, 160, 195, 204, 131, 138, 129, 214, 92, 101, 80, 100, 211, 198, 32, 58, 56, 58, 123, 203, 88, 131, 61, 32, 38, 50, 35, 31, 79, 203, 100, 71, 190, 253, 136, 24, 198, 152, 131, 197, 60, 129, 113, 31, 177, 169, 172, 220, 207, 166, 105, 6, 228, 123, 1, 44, 167, 155, 52, 172, 192, 136, 66, 25, 100, 148, 159, 39, 183, 147, 63, 74, 134, 217, 253, 102, 143, 107, 115, 135, 24, 251, 26, 230, 144, 236, 211, 130, 59, 128, 15, 28, 230, 120, 158, 23, 207, 226, 241, 233, 237, 228, 143, 99, 129, 220, 253, 101, 145, 110, 236, 177, 227, 27, 127, 132, 71, 11, 30, 144, 195, 237, 176, 193, 203, 120, 118, 59, 89, 224, 60, 158, 221, 254, 225, 135, 218, 187, 96, 14, 197, 217, 193, 172, 74, 207, 211, 223, 19, 33, 113, 98, 197, 215, 103, 35, 254, 35, 247, 202, 240, 183, 125, 70, 40, 0, 129, 139, 236, 9, 63, 205, 193, 0, 200, 186, 118, 29, 150, 130, 42, 140, 104, 179, 100, 194, 29, 50, 176, 80, 94, 128, 201, 188, 70, 206, 46, 47, 130, 128, 251, 57, 114, 183, 21, 39, 50, 142, 115, 149, 17, 183, 102, 111, 39, 35, 10, 75, 251, 158, 240, 226, 209, 219, 32, 255, 109, 121, 184, 111, 16, 85, 121, 119, 46, 60, 83, 12, 8, 220, 165, 216, 170, 229, 164, 40, 234, 122, 166, 69, 63, 91, 86, 249, 250, 186, 170, 164, 57, 216, 59, 93, 182, 99, 78, 193, 136, 14, 127, 30, 38, 147, 249, 248, 150, 218, 82, 5, 199, 237, 83, 241, 167, 80, 74, 242, 71, 60, 30, 207, 207, 231, 211, 24, 249, 13, 189, 188, 171, 218, 69, 229, 25, 24, 202, 206, 194, 131, 146, 48, 155, 6, 113, 23, 167, 32, 166, 73, 20, 85, 128, 187, 67, 155, 109, 164, 145, 36, 162, 175, 139, 164, 100, 160, 89, 67, 200, 208, 158, 228, 196, 74, 179, 185, 55, 194, 213, 176, 5, 22, 69, 239, 153, 160, 156, 89, 28, 22, 93, 156, 50, 138, 69, 253, 245, 117, 41, 30, 107, 102, 181, 185, 170, 32, 117, 67, 157, 146, 136, 9, 208, 250, 250, 91, 178, 46, 110, 47, 138, 20, 148, 79, 246, 116, 231, 144, 16, 234, 119, 198, 197, 165, 95, 33, 136, 230, 37, 159, 66, 12, 253, 208, 7, 249, 228, 159, 44, 8, 239, 216, 75, 91, 33, 111, 135, 233, 201, 105, 245, 69, 232, 132, 208, 65, 191, 54, 162, 225, 23, 209, 163, 162, 183, 177, 113, 22, 61, 125, 34, 39, 175, 229, 74, 222, 198, 134, 43, 121, 79, 197, 100, 184, 177, 113, 79, 5, 239, 121, 154, 77, 250, 51, 198, 221, 233, 152, 153, 5, 183, 72, 224, 24, 65, 38, 97, 113, 211, 24, 119, 145, 54, 84, 233, 211, 45, 6, 3, 246, 81, 200, 58, 210, 56, 214, 25, 71, 114, 96, 197, 215, 101, 172, 21, 25, 173, 61, 38, 122, 54, 217, 7, 143, 234, 23, 246, 184, 97, 95, 65, 51, 31, 120, 61, 71, 138, 11, 188, 12, 176, 49, 108, 61, 242, 124, 144, 157, 225, 7, 135, 255, 191, 82, 54, 178, 153, 217, 113, 96, 15, 236, 79, 146, 77, 34, 103, 155, 120, 113, 158, 128, 239, 69, 194, 212, 83, 250, 33, 121, 195, 91, 226, 69, 97, 255, 237, 132, 45, 17, 69, 227, 186, 36, 44, 79, 86, 68, 239, 73, 149, 199, 209, 150, 36, 139, 88, 127, 191, 140, 171, 211, 119, 231, 241, 37, 159, 214, 214, 173, 210, 176, 246, 145, 165, 31, 161, 210, 172, 171, 118, 57, 101, 226, 97, 36, 71, 64, 6, 130, 35, 39, 140, 46, 39, 54, 84, 8, 146, 162, 74, 75, 28, 71, 130, 204, 77, 40, 202, 98, 62, 12, 159, 241, 17, 226, 227, 132, 55, 244, 89, 179, 208, 210, 35, 132, 121, 194, 5, 95, 226, 205, 184, 100, 106, 33, 14, 144, 90, 162, 205, 138, 54, 35, 205, 11, 97, 148, 199, 249, 156, 27, 0, 164, 180, 192, 100, 67, 110, 201, 8, 67, 168, 202, 181, 6, 225, 4, 126, 12, 172, 240, 245, 215, 240, 255, 199, 130, 228, 235, 2, 152, 18, 16, 185, 175, 133, 63, 41, 123, 42, 18, 171, 92, 246, 63, 231, 131, 180, 50, 196, 219, 167, 216, 24, 210, 45, 219, 102, 204, 193, 81, 149, 191, 229, 202, 29, 62, 235, 245, 47, 49, 176, 224, 223, 36, 153, 38, 76, 135, 242, 226, 212, 184, 17, 200, 110, 108, 168, 183, 85, 110, 158, 57, 38, 234, 231, 71, 219, 112, 251, 140, 232, 174, 175, 27, 116, 205, 179, 139, 174, 209, 73, 7, 62, 243, 99, 58, 101, 42, 146, 79, 114, 165, 148, 171, 173, 27, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 90, 153, 242, 182, 201, 156, 6, 179, 21, 235, 196, 7, 101, 157, 4, 89, 64, 248, 162, 56, 35, 236, 87, 73, 17, 235, 88, 166, 51, 48, 72, 244, 160, 167, 252, 91, 50, 17, 195, 142, 57, 128, 21, 214, 52, 72, 37, 4, 246, 253, 85, 114, 65, 129, 242, 66, 255, 200, 202, 248, 56, 97, 83, 226, 33, 91, 44, 20, 31, 146, 201, 104, 154, 87, 125, 85, 141, 155, 25, 180, 165, 86, 181, 134, 202, 145, 214, 84, 112, 91, 118, 107, 199, 80, 67, 125, 116, 229, 66, 97, 254, 42, 185, 172, 250, 134, 18, 172, 191, 160, 183, 24, 223, 43, 93, 104, 226, 174, 128, 22, 60, 238, 78, 20, 250, 101, 30, 23, 147, 55, 185, 67, 220, 181, 181, 192, 102, 60, 141, 126, 144, 188, 0, 22, 21, 1, 33, 34, 246, 246, 143, 255, 85, 112, 231, 176, 90, 131, 0, 74, 234, 185, 231, 244, 160, 199, 191, 16, 171, 42, 102, 40, 10, 138, 253, 98, 81, 140, 51, 192, 22, 18, 140, 114, 62, 133, 65, 255, 67, 48, 212, 35, 28, 138, 51, 201, 51, 246, 130, 175, 57, 97, 195, 92, 144, 36, 246, 116, 16, 96, 108, 66, 105, 178, 214, 148, 29, 23, 159, 49, 118, 42, 14, 161, 6, 195, 33, 102, 188, 243, 95, 83, 46, 183, 186, 60, 19, 210, 7, 219, 207, 153, 150, 116, 43, 110, 99, 149, 165, 112, 222, 47, 95, 231, 101, 153, 190, 159, 94, 73, 194, 130, 169, 58, 17, 155, 8, 177, 182, 249, 132, 142, 11, 150, 148, 170, 47, 70, 75, 99, 207, 162, 30, 94, 7, 65, 252, 61, 46, 127, 78, 170, 120, 124, 154, 76, 126, 154, 31, 31, 51, 53, 19, 19, 167, 172, 101, 70, 127, 191, 165, 150, 212, 196, 9, 139, 167, 18, 75, 47, 199, 88, 47, 43, 211, 93, 144, 251, 41, 247, 121, 168, 214, 252, 226, 36, 152, 3, 69, 152, 116, 28, 220, 26, 168, 76, 144, 5, 30, 235, 114, 108, 57, 102, 122, 108, 25, 17, 135, 22, 63, 125, 144, 171, 186, 152, 68, 158, 120, 219, 117, 96, 109, 227, 245, 225, 44, 78, 65, 109, 9, 48, 3, 13, 239, 237, 142, 175, 53, 40, 92, 211, 210, 142, 208, 47, 164, 10, 7, 135, 244, 142, 170, 209, 98, 129, 128, 197, 24, 175, 17, 190, 226, 95, 249, 2, 180, 164, 241, 45, 62, 165, 206, 213, 3, 39, 43, 111, 114, 47, 206, 242, 140, 173, 110, 166, 175, 226, 243, 164, 143, 65, 177, 149, 30, 71, 186, 236, 57, 11, 146, 103, 89, 85, 164, 237, 27, 219, 94, 115, 181, 42, 15, 85, 106, 89, 127, 203, 83, 31, 4, 122, 183, 188, 202, 198, 253, 24, 254, 207, 195, 199, 248, 54, 217, 113, 134, 205, 149, 1, 87, 135, 108, 97, 232, 183, 97, 246, 144, 10, 87, 235, 5, 14, 117, 111, 154, 151, 243, 130, 115, 20, 252, 140, 96, 105, 252, 20, 177, 9, 236, 199, 165, 25, 64, 21, 77, 174, 98, 11, 193, 200, 188, 42, 198, 140, 99, 188, 38, 230, 117, 144, 48, 123, 86, 196, 111, 242, 17, 15, 254, 82, 101, 109, 63, 223, 188, 100, 112, 119, 101, 215, 213, 100, 107, 72, 225, 137, 209, 141, 113, 97, 25, 169, 43, 176, 244, 193, 178, 212, 118, 228, 111, 208, 234, 178, 133, 222, 168, 182, 112, 160, 229, 85, 95, 220, 179, 235, 86, 112, 107, 214, 41, 199, 191, 12, 17, 69, 13, 149, 214, 108, 141, 73, 13, 111, 95, 39, 106, 73, 156, 218, 212, 69, 189, 28, 213, 147, 215, 223, 154, 69, 50, 99, 245, 251, 193, 6, 104, 23, 160, 222, 40, 68, 188, 238, 228, 51, 136, 125, 68, 140, 208, 102, 132, 193, 76, 106, 221, 17, 181, 205, 74, 99, 195, 247, 96, 115, 85, 135, 114, 219, 222, 155, 189, 65, 180, 7, 238, 160, 35, 61, 36, 100, 43, 13, 254, 129, 5, 29, 95, 196, 105, 37, 92, 68, 25, 211, 175, 194, 75, 8, 7, 5, 166, 211, 252, 66, 194, 4, 244, 192, 15, 99, 92, 200, 72, 247, 208, 113, 36, 61, 30, 132, 199, 88, 126, 33, 228, 119, 131, 9, 52, 70, 59, 100, 68, 165, 118, 161, 67, 215, 28, 134, 192, 53, 138, 86, 140, 3, 3, 157, 89, 197, 104, 68, 109, 80, 130, 66, 232, 157, 59, 248, 157, 2, 24, 224, 31, 12, 195, 25, 204, 242, 54, 127, 239, 74, 219, 4, 190, 171, 111, 102, 51, 217, 148, 228, 246, 43, 55, 184, 210, 179, 4, 47, 71, 16, 151, 238, 232, 146, 182, 1, 164, 42, 98, 67, 104, 113, 46, 19, 75, 50, 185, 102, 51, 65, 39, 6, 40, 98, 58, 233, 44, 80, 91, 151, 254, 45, 124, 65, 113, 141, 37, 218, 208, 119, 89, 68, 242, 130, 166, 236, 143, 178, 118, 27, 6, 208, 174, 237, 53, 93, 253, 17, 241, 104, 119, 28, 87, 107, 84, 197, 72, 161, 17, 149, 198, 54, 29, 209, 143, 200, 40, 178, 167, 225, 126, 192, 0, 224, 118, 220, 18, 166, 253, 198, 217, 188, 245, 92, 222, 228, 219, 30, 74, 100, 93, 191, 182, 68, 88, 161, 196, 53, 5, 154, 9, 210, 118, 83, 142, 84, 244, 118, 228, 57, 129, 166, 145, 245, 206, 10, 158, 25, 193, 51, 27, 216, 14, 251, 20, 207, 7, 31, 175, 37, 70, 88, 89, 91, 82, 163, 189, 248, 205, 42, 90, 114, 70, 168, 75, 109, 4, 168, 70, 116, 222, 88, 90, 19, 201, 141, 163, 171, 3, 162, 3, 177, 51, 254, 168, 46, 159, 246, 35, 146, 178, 82, 163, 247, 82, 173, 242, 218, 42, 188, 208, 56, 173, 72, 42, 52, 171, 188, 21, 209, 115, 87, 237, 117, 222, 148, 19, 92, 126, 134, 70, 191, 110, 144, 154, 134, 200, 209, 107, 84, 171, 181, 214, 105, 64, 112, 87, 125, 225, 216, 38, 170, 154, 152, 169, 196, 79, 16, 34, 111, 17, 167, 124, 208, 97, 42, 79, 88, 242, 66, 155, 255, 206, 211, 12, 137, 178, 255, 176, 164, 207, 79, 132, 142, 85, 84, 18, 131, 129, 128, 105, 31, 158, 244, 145, 13, 192, 155, 226, 110, 151, 94, 228, 172, 86, 34, 59, 54, 229, 63, 152, 124, 229, 51, 40, 131, 207, 64, 225, 222, 98, 29, 235, 99, 69, 123, 63, 210, 113, 145, 168, 147, 24, 61, 204, 247, 199, 105, 81, 86, 207, 166, 201, 185, 136, 87, 224, 144, 142, 182, 222, 170, 134, 14, 141, 35, 199, 57, 164, 138, 106, 106, 82, 30, 50, 24, 178, 1, 108, 254, 31, 114, 108, 101, 127, 37, 255, 120, 233, 134, 96, 110, 86, 132, 76, 3, 130, 170, 60, 154, 132, 123, 82, 38, 179, 88, 41, 248, 222, 160, 231, 136, 204, 48, 44, 50, 160, 102, 108, 26, 40, 185, 57, 140, 214, 159, 24, 216, 102, 181, 229, 153, 24, 16, 24, 164, 29, 57, 0, 187, 243, 254, 238, 35, 0, 78, 239, 49, 112, 101, 232, 26, 53, 135, 248, 241, 144, 48, 220, 87, 36, 116, 146, 248, 8, 4, 67, 5, 29, 23, 178, 206, 32, 234, 193, 62, 228, 145, 152, 35, 55, 229, 17, 208, 183, 174, 31, 131, 198, 97, 230, 69, 122, 2, 14, 116, 254, 137, 107, 54, 224, 77, 195, 217, 59, 136, 77, 185, 38, 96, 156, 186, 161, 89, 85, 171, 135, 45, 236, 104, 98, 36, 23, 42, 145, 0, 119, 14, 179, 98, 205, 137, 61, 114, 220, 209, 44, 107, 34, 237, 204, 90, 33, 240, 236, 67, 196, 202, 198, 241, 84, 53, 194, 97, 205, 202, 204, 172, 97, 239, 138, 188, 44, 15, 147, 120, 122, 46, 55, 158, 113, 145, 182, 72, 11, 240, 82, 207, 153, 106, 128, 208, 94, 227, 217, 97, 81, 125, 143, 19, 215, 148, 197, 136, 8, 159, 118, 207, 221, 125, 247, 34, 132, 215, 162, 123, 158, 117, 119, 115, 93, 213, 165, 189, 218, 35, 217, 181, 212, 88, 181, 169, 29, 50, 23, 31, 50, 214, 69, 99, 233, 57, 136, 173, 52, 120, 227, 172, 44, 112, 112, 172, 230, 105, 92, 193, 177, 3, 62, 197, 21, 170, 86, 171, 96, 18, 113, 24, 241, 69, 67, 72, 137, 101, 26, 163, 70, 186, 196, 127, 216, 53, 109, 99, 249, 115, 70, 105, 3, 9, 25, 201, 247, 179, 74, 236, 232, 128, 209, 112, 48, 48, 228, 225, 78, 241, 161, 221, 7, 102, 144, 224, 237, 38, 143, 213, 0, 112, 251, 75, 26, 9, 40, 53, 73, 102, 213, 233, 171, 249, 57, 159, 71, 86, 66, 1, 63, 76, 236, 49, 209, 152, 58, 243, 250, 94, 16, 48, 179, 237, 73, 43, 146, 65, 250, 68, 100, 86, 104, 133, 73, 235, 128, 97, 5, 101, 16, 13, 123, 146, 7, 186, 245, 19, 192, 133, 31, 124, 83, 120, 69, 118, 27, 30, 172, 193, 92, 137, 212, 122, 109, 197, 12, 152, 0, 187, 47, 247, 171, 56, 12, 50, 163, 139, 38, 212, 119, 102, 14, 227, 23, 143, 13, 6, 228, 3, 13, 79, 194, 53, 210, 140, 156, 59, 86, 134, 65, 162, 141, 2, 241, 245, 8, 213, 33, 94, 73, 75, 198, 144, 19, 105, 199, 56, 104, 12, 180, 218, 80, 74, 31, 129, 212, 63, 229, 102, 64, 175, 36, 84, 252, 10, 97, 233, 190, 214, 47, 44, 127, 173, 20, 135, 211, 124, 62, 157, 200, 129, 166, 113, 175, 162, 167, 124, 20, 105, 72, 70, 228, 212, 82, 19, 181, 196, 205, 105, 137, 147, 31, 215, 177, 93, 118, 178, 162, 37, 150, 242, 45, 245, 48, 113, 178, 16, 110, 241, 177, 41, 45, 217, 64, 63, 211, 250, 192, 169, 234, 80, 85, 16, 100, 35, 26, 122, 8, 107, 199, 158, 64, 191, 49, 174, 16, 133, 123, 57, 60, 198, 255, 106, 125, 199, 223, 253, 245, 59, 143, 155, 184, 246, 60, 55, 198, 58, 178, 199, 131, 116, 202, 4, 187, 248, 207, 240, 154, 146, 174, 190, 221, 173, 196, 102, 231, 50, 35, 90, 212, 112, 26, 29, 153, 202, 136, 62, 185, 208, 85, 138, 152, 86, 120, 138, 150, 60, 96, 247, 147, 175, 206, 202, 68, 69, 164, 175, 123, 202, 173, 168, 168, 232, 199, 209, 22, 184, 214, 207, 172, 173, 220, 80, 102, 30, 21, 19, 194, 215, 16, 45, 246, 34, 119, 43, 199, 152, 126, 147, 31, 194, 209, 243, 50, 153, 244, 151, 65, 210, 93, 25, 137, 182, 152, 71, 65, 70, 156, 137, 120, 181, 51, 19, 83, 166, 190, 153, 40, 96, 20, 121, 21, 116, 8, 232, 26, 182, 25, 230, 95, 252, 231, 69, 197, 136, 0, 22, 77, 92, 36, 199, 146, 246, 60, 186, 84, 189, 178, 246, 64, 44, 151, 162, 169, 25, 48, 153, 254, 66, 230, 218, 197, 105, 204, 221, 45, 11, 211, 217, 67, 46, 233, 117, 59, 19, 97, 178, 196, 6, 6, 92, 30, 147, 141, 123, 21, 119, 115, 94, 90, 84, 117, 188, 26, 28, 183, 119, 101, 14, 145, 90, 178, 9, 67, 35, 127, 32, 253, 139, 184, 172, 110, 109, 180, 52, 32, 247, 105, 34, 166, 141, 27, 124, 9, 113, 211, 234, 24, 140, 239, 44, 198, 226, 177, 245, 238, 54, 196, 205, 71, 216, 195, 0, 120, 163, 236, 225, 195, 237, 142, 180, 215, 24, 222, 51, 6, 234, 194, 41, 55, 26, 131, 175, 9, 76, 24, 4, 118, 163, 84, 89, 30, 9, 248, 33, 158, 34, 223, 16, 138, 230, 57, 79, 126, 73, 50, 18, 191, 194, 138, 178, 193, 4, 111, 88, 207, 210, 86, 24, 42, 31, 163, 238, 96, 249, 241, 42, 31, 92, 181, 235, 177, 63, 97, 228, 76, 153, 114, 246, 122, 210, 104, 29, 221, 196, 114, 187, 168, 75, 47, 187, 143, 186, 248, 33, 7, 210, 29, 178, 40, 34, 64, 139, 72, 31, 63, 17, 97, 35, 50, 209, 17, 164, 34, 255, 227, 64, 68, 65, 218, 193, 177, 106, 187, 14, 149, 220, 52, 209, 165, 202, 94, 132, 102, 69, 0, 39, 42, 189, 105, 114, 49, 5, 252, 181, 184, 226, 26, 214, 189, 58, 54, 51, 188, 237, 139, 235, 14, 116, 155, 248, 240, 158, 246, 218, 9, 104, 225, 45, 64, 72, 30, 104, 43, 16, 85, 199, 43, 127, 50, 0, 217, 74, 17, 39, 81, 248, 57, 45, 116, 212, 236, 31, 43, 54, 46, 34, 80, 214, 175, 39, 61, 104, 240, 226, 88, 131, 1, 83, 106, 74, 67, 198, 69, 120, 225, 115, 87, 153, 130, 93, 244, 38, 174, 101, 217, 49, 82, 177, 201, 94, 62, 130, 198, 197, 42, 204, 212, 17, 191, 81, 236, 44, 188, 248, 104, 19, 138, 176, 162, 160, 150, 8, 23, 45, 22, 36, 154, 10, 214, 190, 33, 26, 161, 82, 94, 146, 180, 136, 78, 123, 20, 16, 68, 153, 166, 212, 81, 251, 106, 171, 137, 181, 102, 104, 220, 71, 2, 138, 202, 134, 246, 49, 148, 104, 240, 24, 212, 15, 120, 87, 86, 128, 20, 10, 162, 208, 170, 102, 110, 185, 94, 44, 169, 6, 58, 26, 129, 70, 66, 214, 74, 168, 27, 240, 165, 194, 236, 96, 108, 86, 218, 138, 240, 146, 201, 32, 40, 87, 22, 21, 33, 23, 178, 119, 31, 195, 19, 200, 223, 147, 41, 227, 180, 87, 22, 61, 149, 61, 228, 143, 128, 63, 16, 241, 239, 7, 40, 250, 221, 5, 217, 63, 88, 32, 2, 222, 5, 211, 34, 14, 94, 28, 107, 145, 63, 122, 129, 222, 121, 66, 227, 79, 212, 164, 17, 12, 64, 231, 117, 14, 4, 104, 56, 224, 129, 61, 145, 164, 15, 251, 16, 51, 155, 149, 233, 216, 157, 104, 7, 166, 29, 51, 138, 245, 163, 113, 232, 48, 225, 253, 26, 15, 209, 191, 207, 50, 34, 162, 233, 5, 198, 68, 27, 55, 247, 115, 72, 120, 247, 62, 203, 136, 240, 150, 59, 13, 136, 217, 226, 114, 143, 46, 69, 79, 60, 182, 135, 94, 204, 249, 247, 176, 186, 239, 93, 81, 27, 36, 37, 148, 148, 199, 162, 60, 163, 173, 215, 147, 152, 168, 118, 207, 140, 37, 171, 186, 164, 27, 133, 234, 11, 104, 157, 154, 67, 83, 196, 132, 17, 88, 202, 129, 20, 127, 52, 12, 107, 92, 105, 21, 215, 188, 254, 182, 75, 183, 244, 24, 78, 217, 218, 76, 251, 1, 132, 225, 146, 76, 184, 109, 142, 206, 155, 152, 244, 194, 87, 105, 50, 149, 161, 211, 184, 32, 218, 32, 224, 203, 83, 52, 133, 131, 25, 160, 141, 104, 114, 242, 203, 32, 165, 145, 208, 115, 237, 42, 84, 227, 199, 94, 212, 155, 110, 112, 132, 80, 17, 91, 66, 157, 23, 225, 144, 63, 224, 120, 50, 95, 151, 225, 159, 6, 199, 222, 243, 142, 135, 162, 163, 96, 8, 113, 168, 36, 181, 27, 2, 132, 18, 135, 137, 248, 1, 195, 169, 34, 47, 200, 138, 46, 110, 208, 15, 46, 156, 146, 9, 89, 28, 132, 132, 87, 38, 36, 147, 89, 118, 175, 45, 193, 26, 78, 7, 25, 54, 117, 110, 70, 138, 69, 23, 125, 28, 175, 91, 190, 179, 162, 220, 162, 111, 95, 228, 185, 133, 60, 243, 243, 147, 193, 197, 188, 162, 165, 71, 146, 241, 10, 194, 85, 10, 164, 237, 143, 30, 28, 62, 143, 208, 191, 137, 207, 146, 254, 52, 61, 79, 171, 174, 242, 46, 86, 94, 231, 113, 154, 137, 16, 110, 179, 247, 38, 192, 41, 157, 96, 202, 60, 182, 28, 175, 135, 113, 118, 162, 78, 81, 254, 245, 135, 27, 18, 121, 232, 160, 79, 40, 52, 90, 119, 87, 226, 155, 187, 118, 195, 2, 191, 131, 24, 224, 41, 248, 149, 245, 79, 227, 95, 190, 142, 62, 16, 60, 47, 85, 130, 103, 129, 30, 60, 166, 181, 172, 153, 60, 88, 109, 233, 194, 138, 244, 137, 223, 147, 215, 186, 110, 72, 210, 127, 46, 242, 217, 189, 150, 116, 232, 224, 61, 149, 244, 230, 174, 233, 33, 189, 117, 130, 221, 86, 154, 169, 12, 155, 179, 44, 68, 117, 221, 43, 75, 227, 115, 234, 155, 86, 198, 193, 110, 201, 55, 228, 146, 201, 235, 56, 45, 202, 254, 34, 122, 99, 121, 226, 77, 145, 113, 165, 225, 238, 74, 119, 99, 207, 150, 38, 220, 75, 151, 167, 1, 186, 175, 100, 73, 162, 53, 80, 87, 156, 220, 144, 140, 169, 20, 19, 188, 250, 219, 219, 35, 108, 52, 68, 252, 190, 249, 207, 100, 239, 238, 163, 15, 173, 185, 107, 203, 157, 156, 23, 155, 125, 23, 17, 203, 229, 76, 115, 230, 56, 97, 237, 54, 121, 163, 135, 204, 74, 23, 192, 239, 14, 10, 30, 70, 21, 224, 232, 182, 158, 144, 127, 83, 239, 115, 174, 198, 235, 130, 30, 100, 230, 117, 145, 111, 185, 136, 66, 170, 160, 102, 119, 58, 168, 22, 36, 204, 46, 122, 65, 87, 193, 138, 161, 85, 42, 102, 146, 48, 200, 97, 87, 31, 15, 168, 14, 242, 125, 112, 147, 139, 204, 27, 43, 1, 69, 186, 69, 74, 136, 26, 102, 28, 130, 38, 169, 13, 235, 1, 169, 68, 83, 29, 83, 57, 32, 1, 195, 141, 249, 167, 87, 28, 166, 254, 16, 228, 103, 77, 139, 53, 47, 244, 48, 77, 101, 159, 228, 48, 170, 157, 38, 39, 225, 178, 39, 221, 50, 71, 70, 168, 0, 133, 174, 63, 159, 114, 29, 51, 203, 252, 107, 126, 227, 241, 143, 118, 33, 9, 34, 11, 16, 48, 181, 216, 59, 199, 49, 180, 71, 250, 0, 42, 177, 68, 22, 167, 107, 56, 188, 86, 218, 37, 88, 47, 33, 154, 164, 34, 162, 182, 158, 26, 234, 6, 34, 21, 157, 188, 28, 169, 238, 150, 113, 29, 103, 65, 184, 6, 251, 133, 93, 164, 89, 64, 137, 55, 233, 61, 126, 119, 215, 221, 167, 76, 131, 3, 217, 71, 29, 55, 172, 166, 8, 196, 220, 234, 27, 176, 234, 8, 41, 110, 201, 187, 31, 148, 92, 237, 76, 75, 135, 152, 246, 92, 190, 98, 145, 185, 65, 100, 33, 61, 252, 253, 160, 229, 117, 185, 18, 153, 123, 206, 90, 134, 227, 239, 201, 192, 208, 148, 175, 51, 64, 136, 7, 131, 168, 199, 159, 122, 16, 135, 42, 193, 246, 84, 110, 60, 122, 65, 114, 22, 159, 39, 42, 126, 142, 61, 194, 39, 249, 74, 252, 177, 178, 200, 74, 184, 60, 147, 172, 68, 23, 202, 233, 53, 204, 121, 121, 34, 161, 157, 39, 101, 25, 159, 112, 128, 226, 37, 255, 191, 13, 142, 64, 98, 37, 244, 144, 235, 214, 123, 61, 43, 132, 132, 149, 82, 29, 224, 71, 2, 37, 88, 167, 156, 234, 14, 98, 89, 14, 116, 61, 234, 61, 138, 122, 236, 15, 7, 20, 26, 5, 72, 200, 242, 166, 136, 211, 41, 123, 102, 11, 55, 246, 39, 161, 193, 200, 141, 215, 0, 19, 112, 34, 16, 124, 192, 102, 220, 53, 64, 224, 255, 101, 61, 43, 94, 210, 27, 195, 44, 71, 124, 52, 47, 103, 9, 163, 218, 132, 198, 3, 219, 57, 113, 112, 140, 63, 132, 233, 176, 87, 186, 2, 254, 230, 141, 45, 116, 207, 71, 130, 196, 233, 250, 129, 96, 28, 26, 142, 195, 173, 30, 243, 163, 71, 122, 213, 147, 239, 29, 27, 210, 194, 145, 137, 58, 216, 254, 147, 0, 174, 225, 52, 174, 160, 143, 116, 120, 160, 11, 125, 191, 60, 156, 103, 224, 133, 181, 1, 91, 194, 243, 240, 123, 107, 15, 193, 172, 49, 59, 68, 147, 71, 158, 219, 157, 249, 48, 181, 236, 173, 46, 6, 89, 35, 80, 9, 220, 61, 113, 73, 73, 162, 172, 3, 151, 153, 172, 200, 245, 251, 194, 77, 40, 168, 107, 113, 118, 18, 196, 99, 45, 124, 102, 134, 209, 199, 4, 110, 5, 199, 216, 71, 18, 238, 11, 203, 224, 208, 204, 229, 169, 32, 62, 130, 159, 74, 249, 240, 141, 196, 15, 144, 166, 189, 17, 129, 90, 182, 43, 236, 67, 36, 159, 147, 241, 96, 47, 180, 152, 49, 92, 208, 72, 1, 210, 253, 19, 72, 150, 192, 49, 53, 185, 220, 153, 253, 6, 167, 237, 101, 13, 229, 57, 229, 71, 135, 85, 90, 100, 169, 127, 235, 197, 207, 192, 198, 234, 218, 1, 37, 37, 179, 53, 44, 44, 201, 43, 245, 167, 121, 80, 45, 124, 152, 199, 144, 69, 154, 196, 45, 143, 65, 121, 252, 143, 193, 243, 62, 234, 204, 13, 239, 148, 235, 118, 122, 28, 109, 203, 97, 245, 39, 42, 163, 208, 55, 241, 9, 4, 235, 147, 250, 105, 242, 152, 213, 102, 99, 8, 3, 14, 21, 81, 63, 137, 240, 207, 85, 222, 5, 188, 118, 240, 31, 16, 242, 56, 189, 100, 9, 203, 106, 52, 233, 174, 125, 7, 129, 68, 246, 239, 180, 228, 107, 153, 65, 116, 46, 78, 68, 24, 237, 137, 95, 200, 68, 222, 162, 172, 145, 160, 115, 117, 250, 130, 129, 149, 103, 69, 56, 208, 70, 247, 14, 217, 30, 182, 90, 82, 58, 3, 106, 188, 108, 221, 64, 234, 194, 54, 96, 246, 201, 0, 208, 61, 21, 1, 80, 28, 7, 66, 109, 34, 40, 52, 101, 54, 63, 69, 88, 228, 231, 56, 177, 108, 223, 109, 196, 140, 178, 7, 3, 196, 37, 214, 17, 18, 43, 35, 68, 123, 2, 59, 253, 87, 138, 216, 58, 43, 231, 117, 194, 155, 131, 45, 30, 238, 211, 242, 16, 224, 63, 200, 80, 201, 215, 123, 50, 112, 30, 86, 71, 240, 23, 86, 72, 112, 144, 150, 45, 84, 107, 79, 64, 41, 248, 250, 24, 20, 198, 88, 143, 152, 104, 250, 221, 59, 126, 62, 247, 221, 187, 71, 188, 41, 33, 65, 84, 158, 154, 143, 123, 57, 91, 62, 162, 145, 144, 156, 200, 108, 33, 124, 13, 207, 137, 95, 36, 64, 23, 177, 60, 194, 201, 248, 194, 203, 92, 17, 39, 131, 106, 129, 145, 97, 104, 195, 19, 20, 244, 74, 177, 218, 173, 117, 110, 183, 164, 51, 29, 253, 115, 116, 70, 170, 57, 169, 41, 166, 190, 234, 149, 123, 138, 234, 156, 158, 159, 66, 12, 198, 26, 17, 83, 51, 190, 102, 177, 27, 255, 125, 236, 204, 131, 64, 27, 211, 72, 152, 64, 26, 142, 235, 198, 45, 148, 95, 219, 153, 157, 120, 242, 219, 3, 239, 201, 211, 0, 155, 28, 72, 133, 162, 189, 11, 205, 12, 127, 26, 151, 251, 89, 89, 197, 217, 88, 101, 146, 166, 83, 13, 202, 55, 153, 150, 175, 213, 33, 245, 131, 99, 193, 228, 102, 84, 245, 167, 126, 207, 168, 91, 42, 39, 43, 104, 146, 65, 205, 90, 6, 3, 230, 1, 197, 73, 23, 194, 199, 37, 182, 132, 193, 160, 125, 158, 195, 166, 90, 58, 209, 138, 176, 105, 99, 86, 66, 32, 59, 178, 54, 94, 109, 171, 15, 109, 129, 95, 161, 59, 186, 178, 48, 25, 83, 31, 210, 214, 93, 51, 93, 14, 17, 121, 105, 176, 192, 41, 34, 31, 156, 54, 55, 206, 132, 186, 227, 57, 57, 132, 184, 214, 127, 112, 232, 0, 223, 62, 67, 24, 54, 88, 126, 104, 31, 46, 170, 59, 232, 137, 100, 175, 97, 64, 228, 98, 238, 254, 12, 73, 240, 128, 93, 251, 65, 209, 233, 94, 219, 157, 102, 111, 121, 238, 149, 28, 20, 142, 92, 15, 149, 124, 143, 78, 179, 138, 217, 197, 82, 159, 157, 14, 192, 123, 52, 44, 58, 244, 186, 216, 160, 91, 145, 41, 11, 12, 55, 133, 208, 102, 160, 93, 228, 23, 58, 175, 167, 71, 216, 135, 96, 248, 228, 106, 32, 248, 151, 34, 117, 45, 65, 250, 252, 52, 189, 198, 185, 212, 118, 84, 245, 156, 62, 109, 160, 107, 56, 86, 139, 35, 227, 167, 237, 141, 89, 47, 55, 19, 255, 213, 108, 172, 232, 252, 23, 204, 12, 104, 19, 20, 134, 168, 103, 7, 76, 1, 205, 241, 44, 129, 226, 194, 106, 236, 0, 129, 64, 125, 92, 87, 43, 65, 194, 60, 226, 46, 151, 191, 93, 0, 115, 195, 22, 165, 96, 175, 61, 70, 240, 105, 194, 185, 168, 33, 254, 203, 91, 67, 239, 99, 250, 162, 145, 220, 26, 102, 249, 224, 139, 72, 210, 25, 72, 240, 250, 128, 95, 93, 201, 173, 58, 29, 68, 81, 191, 207, 8, 91, 76, 196, 101, 67, 19, 115, 32, 191, 159, 142, 0, 235, 18, 251, 53, 80, 24, 73, 92, 69, 4, 151, 0, 37, 222, 40, 140, 215, 101, 182, 213, 143, 94, 179, 93, 156, 108, 52, 169, 150, 110, 161, 192, 46, 51, 121, 212, 205, 137, 173, 255, 144, 161, 205, 255, 6, 173, 219, 38, 188, 93, 241, 255, 34, 194, 72, 132, 203, 100, 202, 68, 34, 40, 196, 40, 99, 88, 147, 28, 243, 164, 174, 18, 154, 233, 163, 115, 6, 226, 99, 123, 17, 15, 159, 99, 252, 28, 194, 45, 194, 209, 248, 25, 169, 23, 128, 83, 132, 110, 119, 102, 76, 147, 141, 173, 147, 83, 171, 125, 82, 154, 231, 37, 109, 123, 128, 234, 230, 132, 221, 119, 190, 208, 22, 21, 140, 247, 173, 147, 246, 54, 29, 240, 28, 161, 186, 19, 178, 78, 15, 220, 145, 172, 134, 181, 245, 205, 226, 80, 197, 19, 45, 67, 61, 56, 162, 11, 232, 109, 108, 4, 16, 140, 162, 247, 69, 18, 147, 140, 129, 30, 145, 14, 31, 88, 252, 34, 210, 139, 138, 180, 239, 32, 225, 157, 18, 233, 54, 29, 184, 171, 34, 189, 44, 97, 36, 170, 97, 99, 3, 210, 255, 110, 53, 204, 178, 126, 179, 185, 246, 68, 210, 109, 48, 154, 111, 251, 42, 55, 112, 52, 232, 142, 172, 116, 187, 97, 127, 183, 100, 237, 46, 172, 118, 245, 41, 167, 125, 35, 112, 129, 109, 38, 209, 222, 128, 147, 57, 84, 251, 21, 97, 115, 252, 69, 243, 58, 34, 66, 253, 241, 42, 67, 9, 12, 103, 16, 106, 112, 205, 86, 63, 246, 33, 172, 14, 150, 126, 195, 233, 168, 219, 160, 150, 150, 117, 202, 170, 89, 49, 89, 231, 176, 16, 87, 171, 238, 55, 28, 203, 50, 50, 176, 33, 72, 222, 229, 0, 83, 100, 139, 208, 178, 103, 49, 5, 254, 49, 158, 192, 40, 86, 228, 8, 162, 65, 71, 221, 129, 74, 131, 40, 104, 85, 255, 94, 133, 56, 38, 133, 133, 19, 31, 141, 178, 36, 117, 125, 221, 99, 150, 123, 176, 246, 159, 40, 11, 159, 168, 114, 215, 183, 129, 99, 84, 159, 203, 20, 174, 103, 77, 217, 169, 163, 205, 205, 205, 110, 131, 255, 214, 191, 237, 30, 60, 53, 117, 27, 164, 125, 241, 211, 28, 237, 100, 252, 134, 166, 169, 182, 199, 64, 108, 94, 247, 42, 101, 126, 116, 235, 139, 127, 245, 166, 199, 172, 69, 178, 254, 186, 225, 91, 224, 152, 153, 51, 210, 226, 108, 217, 151, 161, 254, 20, 67, 189, 186, 204, 177, 110, 62, 5, 231, 217, 55, 201, 38, 95, 134, 250, 206, 73, 117, 221, 218, 158, 173, 231, 208, 149, 152, 251, 89, 42, 113, 99, 196, 52, 227, 203, 86, 19, 104, 104, 185, 157, 57, 153, 240, 126, 179, 47, 155, 101, 226, 77, 81, 207, 139, 212, 13, 131, 28, 83, 81, 206, 177, 22, 129, 46, 140, 100, 231, 225, 211, 140, 128, 162, 255, 180, 134, 170, 91, 115, 40, 225, 187, 65, 212, 99, 125, 239, 145, 144, 126, 31, 209, 57, 122, 124, 81, 59, 208, 56, 29, 109, 189, 69, 63, 134, 111, 221, 121, 240, 37, 143, 244, 225, 70, 10, 0, 125, 31, 143, 207, 96, 46, 53, 183, 184, 88, 55, 59, 66, 143, 95, 6, 197, 231, 165, 136, 192, 120, 105, 34, 48, 24, 124, 253, 173, 115, 240, 5, 171, 220, 34, 226, 2, 225, 141, 190, 162, 27, 4, 123, 166, 147, 86, 32, 134, 205, 10, 6, 84, 23, 177, 196, 181, 176, 92, 38, 144, 7, 38, 41, 237, 88, 72, 225, 125, 157, 189, 147, 159, 7, 209, 75, 115, 130, 51, 158, 9, 21, 198, 202, 29, 114, 7, 7, 100, 86, 98, 0, 78, 166, 249, 251, 24, 232, 225, 249, 12, 149, 47, 78, 25, 58, 81, 159, 175, 162, 209, 106, 30, 130, 158, 196, 2, 136, 47, 105, 227, 217, 51, 214, 230, 21, 163, 133, 82, 148, 125, 141, 132, 191, 105, 180, 237, 69, 51, 77, 88, 126, 112, 209, 220, 89, 114, 37, 68, 205, 3, 73, 94, 184, 77, 115, 177, 4, 138, 14, 101, 209, 32, 164, 72, 176, 81, 109, 169, 33, 45, 229, 19, 25, 15, 199, 107, 53, 197, 250, 162, 70, 6, 4, 134, 59, 202, 106, 6, 129, 181, 37, 130, 235, 253, 159, 193, 219, 134, 101, 14, 123, 26, 22, 140, 109, 66, 80, 22, 9, 108, 66, 213, 219, 68, 53, 89, 56, 123, 2, 154, 22, 230, 93, 25, 17, 248, 79, 122, 188, 170, 230, 136, 105, 59, 206, 62, 168, 229, 105, 78, 93, 204, 210, 42, 53, 199, 175, 252, 12, 146, 9, 201, 218, 207, 170, 7, 219, 16, 62, 237, 15, 28, 197, 110, 86, 35, 43, 6, 16, 221, 61, 210, 238, 216, 6, 25, 145, 171, 127, 7, 212, 176, 61, 168, 33, 5, 165, 170, 233, 171, 90, 117, 253, 163, 32, 46, 33, 2, 50, 216, 111, 177, 232, 47, 83, 76, 5, 35, 108, 42, 5, 129, 9, 43, 63, 201, 145, 55, 94, 214, 21, 228, 19, 134, 18, 244, 110, 120, 198, 26, 29, 111, 134, 55, 53, 218, 220, 11, 15, 126, 230, 34, 159, 207, 126, 210, 217, 86, 208, 116, 160, 79, 34, 185, 177, 172, 188, 112, 104, 150, 145, 99, 244, 221, 67, 37, 127, 246, 148, 35, 106, 171, 175, 169, 72, 41, 227, 49, 71, 123, 90, 140, 150, 63, 243, 13, 195, 51, 223, 94, 20, 188, 140, 93, 219, 50, 198, 94, 203, 146, 139, 104, 207, 236, 71, 156, 181, 55, 83, 45, 42, 238, 24, 137, 20, 83, 81, 147, 210, 119, 173, 211, 51, 36, 213, 242, 38, 217, 224, 4, 206, 239, 158, 229, 246, 22, 107, 13, 205, 148, 166, 158, 239, 102, 236, 200, 15, 172, 196, 192, 6, 209, 145, 200, 242, 183, 230, 21, 98, 79, 166, 31, 213, 166, 190, 255, 182, 148, 55, 10, 90, 23, 19, 241, 255, 159, 33, 71, 181, 73, 237, 16, 207, 136, 228, 188, 154, 159, 191, 79, 138, 119, 105, 201, 22, 83, 140, 204, 253, 108, 126, 110, 248, 89, 154, 196, 236, 157, 56, 248, 147, 241, 194, 246, 129, 77, 159, 140, 66, 149, 13, 254, 127, 174, 27, 253, 77, 190, 138, 95, 45, 179, 189, 85, 46, 25, 231, 254, 182, 84, 74, 96, 1, 210, 215, 36, 123, 221, 186, 85, 180, 219, 238, 110, 180, 203, 38, 118, 8, 118, 0, 125, 195, 212, 9, 19, 101, 196, 38, 164, 207, 131, 44, 207, 9, 98, 99, 186, 138, 167, 182, 154, 1, 216, 232, 247, 183, 163, 111, 191, 141, 190, 123, 176, 6, 119, 57, 174, 193, 174, 174, 130, 241, 245, 215, 250, 145, 189, 37, 229, 232, 81, 54, 110, 66, 24, 198, 208, 125, 151, 109, 16, 198, 121, 147, 139, 159, 170, 224, 154, 31, 148, 97, 235, 32, 52, 89, 164, 30, 160, 48, 208, 152, 182, 59, 184, 200, 148, 56, 254, 156, 148, 227, 34, 157, 49, 133, 87, 226, 83, 87, 34, 165, 140, 190, 16, 244, 192, 168, 188, 228, 74, 93, 171, 123, 152, 28, 67, 120, 217, 187, 252, 34, 251, 149, 189, 237, 171, 3, 101, 220, 232, 49, 96, 193, 84, 250, 72, 148, 164, 206, 34, 54, 144, 151, 139, 2, 80, 169, 4, 118, 228, 87, 121, 39, 111, 74, 47, 138, 55, 250, 18, 170, 136, 52, 163, 200, 88, 135, 86, 217, 183, 250, 126, 138, 99, 133, 84, 15, 74, 166, 228, 245, 57, 75, 154, 201, 104, 173, 78, 151, 161, 110, 74, 109, 8, 111, 172, 253, 10, 57, 86, 168, 172, 127, 84, 208, 57, 51, 115, 247, 157, 172, 140, 233, 125, 66, 139, 234, 65, 146, 215, 3, 58, 160, 247, 203, 103, 151, 108, 94, 41, 83, 121, 166, 146, 0, 38, 39, 40, 129, 203, 113, 75, 169, 93, 211, 3, 253, 93, 149, 191, 200, 217, 60, 145, 56, 105, 137, 240, 18, 161, 230, 232, 202, 193, 102, 165, 179, 223, 28, 120, 91, 224, 211, 2, 235, 41, 65, 220, 190, 172, 214, 173, 118, 26, 151, 136, 1, 250, 255, 36, 213, 197, 199, 254, 63, 197, 114, 138, 214, 255, 74, 0, 224, 68, 102, 227, 2, 179, 119, 231, 193, 16, 217, 15, 252, 102, 155, 3, 94, 90, 111, 250, 188, 45, 49, 219, 112, 241, 145, 192, 134, 23, 35, 40, 57, 19, 181, 164, 65, 41, 209, 83, 137, 133, 68, 205, 70, 180, 70, 10, 173, 50, 136, 150, 40, 45, 100, 66, 162, 5, 121, 147, 6, 81, 201, 127, 16, 85, 194, 10, 70, 190, 235, 133, 109, 211, 78, 86, 13, 152, 117, 15, 30, 8, 132, 42, 152, 43, 240, 196, 32, 52, 130, 158, 89, 32, 123, 19, 62, 227, 11, 92, 237, 124, 147, 115, 142, 247, 91, 201, 141, 232, 30, 179, 78, 223, 228, 138, 125, 152, 134, 19, 41, 172, 152, 169, 170, 83, 89, 137, 222, 107, 14, 227, 72, 139, 238, 10, 123, 23, 52, 2, 127, 216, 186, 220, 222, 218, 138, 254, 100, 127, 183, 134, 226, 207, 182, 60, 78, 169, 207, 85, 139, 142, 137, 103, 88, 64, 174, 112, 19, 216, 225, 106, 209, 228, 47, 152, 224, 39, 139, 19, 252, 164, 153, 224, 39, 247, 139, 224, 39, 136, 204, 134, 248, 53, 4, 127, 145, 231, 103, 243, 25, 226, 240, 86, 132, 254, 172, 84, 154, 228, 216, 177, 38, 230, 196, 208, 108, 168, 54, 189, 37, 21, 173, 121, 145, 207, 102, 122, 2, 84, 111, 96, 189, 252, 181, 32, 49, 78, 35, 129, 230, 185, 163, 109, 157, 245, 91, 101, 254, 245, 223, 39, 242, 17, 13, 161, 101, 86, 156, 56, 51, 34, 123, 43, 216, 80, 57, 17, 101, 189, 85, 229, 79, 10, 14, 223, 47, 95, 134, 175, 211, 240, 13, 111, 203, 240, 213, 27, 113, 51, 67, 70, 51, 172, 237, 41, 70, 1, 24, 95, 27, 162, 154, 175, 219, 58, 65, 115, 85, 21, 229, 110, 54, 145, 126, 56, 73, 90, 5, 134, 124, 5, 114, 15, 183, 236, 53, 136, 162, 189, 244, 35, 74, 202, 43, 87, 201, 69, 145, 86, 160, 164, 31, 69, 171, 171, 46, 180, 173, 135, 218, 167, 146, 48, 174, 19, 123, 55, 129, 162, 67, 93, 116, 156, 103, 199, 233, 201, 188, 174, 240, 246, 154, 117, 234, 24, 103, 40, 250, 67, 233, 80, 11, 219, 82, 191, 217, 150, 111, 90, 35, 213, 26, 165, 143, 30, 246, 56, 40, 36, 187, 89, 19, 131, 61, 184, 3, 62, 88, 233, 251, 121, 5, 174, 50, 144, 224, 113, 101, 150, 164, 203, 185, 144, 27, 53, 135, 244, 6, 126, 27, 80, 31, 78, 17, 87, 139, 184, 80, 2, 202, 132, 72, 196, 35, 63, 127, 235, 222, 26, 154, 52, 121, 247, 126, 240, 122, 247, 182, 49, 89, 101, 34, 123, 71, 64, 148, 139, 76, 166, 221, 80, 23, 69, 232, 245, 183, 246, 154, 169, 31, 98, 134, 70, 174, 86, 113, 46, 202, 122, 9, 61, 233, 25, 38, 235, 177, 149, 34, 70, 70, 69, 215, 113, 12, 254, 124, 130, 62, 109, 154, 74, 140, 122, 220, 62, 120, 4, 127, 126, 192, 254, 198, 30, 230, 202, 14, 176, 113, 53, 1, 125, 155, 67, 31, 110, 17, 232, 34, 193, 106, 3, 88, 174, 49, 212, 218, 86, 16, 13, 181, 132, 54, 160, 17, 85, 85, 176, 137, 110, 73, 41, 145, 14, 141, 249, 250, 165, 192, 136, 62, 61, 228, 125, 218, 166, 125, 98, 195, 214, 220, 200, 182, 106, 68, 15, 50, 106, 228, 36, 65, 251, 18, 30, 43, 21, 228, 65, 214, 91, 245, 187, 43, 45, 238, 253, 254, 7, 97, 191, 246, 172, 5, 57, 199, 183, 236, 132, 111, 233, 193, 183, 12, 225, 91, 26, 124, 203, 206, 248, 150, 126, 124, 5, 82, 214, 180, 77, 63, 12, 241, 124, 110, 131, 222, 38, 110, 85, 169, 206, 91, 105, 205, 82, 173, 48, 212, 210, 78, 43, 80, 60, 254, 138, 9, 49, 106, 88, 207, 170, 119, 218, 220, 208, 136, 247, 145, 141, 46, 254, 60, 20, 123, 132, 166, 168, 167, 132, 252, 136, 13, 24, 143, 127, 198, 237, 17, 189, 239, 194, 19, 165, 165, 115, 131, 45, 66, 40, 233, 154, 231, 11, 11, 155, 74, 29, 65, 33, 135, 63, 122, 212, 48, 3, 11, 195, 86, 51, 32, 154, 249, 174, 51, 141, 242, 45, 124, 203, 164, 81, 234, 25, 117, 152, 167, 168, 114, 208, 133, 125, 202, 103, 98, 71, 159, 135, 158, 216, 174, 71, 203, 101, 56, 131, 13, 218, 80, 216, 74, 32, 100, 5, 234, 52, 132, 171, 136, 146, 155, 199, 6, 25, 26, 189, 18, 100, 41, 181, 237, 56, 19, 27, 131, 246, 32, 251, 251, 252, 119, 225, 115, 58, 24, 68, 175, 27, 60, 173, 212, 73, 245, 90, 37, 235, 114, 205, 227, 47, 251, 121, 214, 126, 158, 32, 39, 242, 128, 141, 121, 172, 67, 95, 46, 48, 110, 209, 190, 29, 93, 95, 158, 133, 237, 195, 179, 176, 93, 120, 214, 100, 15, 158, 9, 59, 208, 44, 11, 173, 221, 66, 72, 82, 199, 62, 190, 53, 19, 89, 211, 150, 96, 72, 36, 62, 211, 94, 160, 45, 105, 12, 244, 121, 90, 38, 239, 228, 121, 166, 126, 158, 61, 23, 79, 70, 226, 102, 162, 72, 48, 128, 69, 126, 175, 75, 155, 47, 91, 129, 100, 249, 178, 161, 64, 222, 124, 216, 94, 150, 91, 244, 120, 111, 89, 54, 49, 8, 109, 61, 43, 248, 130, 183, 117, 54, 170, 234, 52, 81, 221, 25, 136, 100, 188, 242, 151, 207, 183, 103, 122, 174, 58, 130, 170, 195, 208, 103, 168, 114, 68, 192, 217, 95, 201, 64, 246, 17, 152, 53, 176, 228, 21, 219, 127, 192, 243, 191, 117, 168, 207, 39, 38, 185, 233, 139, 125, 49, 171, 61, 80, 146, 30, 135, 73, 153, 79, 63, 36, 253, 61, 146, 131, 21, 77, 63, 254, 16, 79, 94, 119, 19, 208, 30, 68, 154, 242, 26, 109, 143, 15, 132, 94, 36, 173, 152, 80, 252, 233, 99, 66, 145, 254, 51, 69, 83, 226, 67, 114, 119, 145, 0, 34, 3, 179, 232, 137, 151, 0, 13, 121, 200, 2, 109, 5, 25, 151, 78, 106, 34, 46, 237, 69, 90, 114, 243, 128, 251, 105, 94, 164, 103, 201, 243, 188, 96, 90, 191, 52, 123, 87, 90, 32, 196, 246, 225, 155, 92, 30, 188, 98, 5, 164, 254, 208, 171, 93, 40, 241, 52, 234, 127, 183, 181, 21, 125, 27, 49, 11, 57, 124, 66, 124, 56, 252, 43, 17, 221, 41, 67, 67, 78, 37, 194, 99, 196, 64, 173, 145, 73, 35, 229, 211, 8, 251, 163, 54, 43, 205, 70, 165, 71, 215, 1, 60, 54, 125, 242, 185, 252, 40, 117, 76, 6, 248, 76, 136, 161, 28, 105, 252, 158, 136, 126, 21, 23, 60, 136, 67, 6, 255, 241, 35, 98, 204, 28, 211, 39, 207, 88, 109, 226, 208, 208, 106, 64, 84, 236, 18, 36, 170, 106, 88, 19, 182, 114, 26, 144, 38, 27, 172, 136, 191, 232, 168, 188, 255, 37, 245, 254, 183, 167, 63, 200, 110, 110, 242, 110, 234, 215, 111, 242, 81, 62, 47, 198, 137, 213, 28, 181, 36, 218, 94, 177, 209, 134, 118, 114, 75, 108, 191, 220, 207, 166, 41, 63, 240, 249, 2, 106, 105, 184, 100, 52, 240, 62, 152, 250, 48, 86, 250, 91, 15, 21, 105, 32, 162, 163, 131, 148, 125, 195, 0, 61, 108, 30, 32, 17, 219, 125, 241, 134, 191, 86, 140, 239, 30, 74, 124, 26, 109, 171, 70, 116, 105, 235, 204, 161, 90, 37, 122, 208, 212, 85, 194, 38, 181, 131, 235, 246, 32, 66, 213, 208, 162, 22, 207, 39, 24, 151, 74, 119, 225, 211, 49, 158, 30, 184, 110, 204, 199, 29, 92, 76, 43, 201, 28, 233, 251, 229, 107, 102, 241, 37, 19, 161, 42, 44, 185, 100, 6, 27, 121, 35, 149, 20, 143, 36, 65, 154, 73, 54, 255, 35, 45, 44, 223, 62, 106, 210, 142, 54, 63, 71, 81, 121, 145, 242, 124, 253, 128, 166, 210, 139, 250, 100, 26, 163, 255, 214, 35, 107, 242, 80, 148, 176, 181, 186, 226, 104, 51, 152, 59, 6, 202, 112, 97, 40, 92, 68, 74, 182, 142, 194, 224, 182, 175, 15, 78, 62, 12, 9, 220, 7, 75, 132, 43, 31, 182, 73, 3, 15, 111, 162, 1, 249, 240, 128, 180, 244, 221, 141, 182, 36, 31, 30, 146, 38, 191, 255, 52, 77, 202, 135, 239, 72, 219, 127, 249, 196, 109, 203, 135, 239, 9, 18, 63, 124, 46, 36, 228, 195, 95, 8, 54, 127, 253, 236, 216, 200, 135, 31, 8, 90, 195, 197, 53, 202, 210, 241, 146, 15, 127, 165, 8, 46, 65, 89, 45, 29, 65, 5, 144, 234, 193, 225, 50, 21, 225, 242, 81, 85, 79, 90, 201, 178, 245, 75, 204, 22, 36, 22, 210, 218, 130, 104, 194, 214, 61, 239, 165, 12, 171, 73, 87, 199, 166, 108, 250, 58, 174, 77, 149, 79, 222, 131, 206, 73, 104, 71, 90, 117, 204, 217, 148, 182, 174, 61, 162, 70, 84, 139, 93, 70, 219, 220, 35, 253, 11, 110, 144, 251, 208, 241, 118, 232, 52, 46, 151, 131, 187, 199, 246, 18, 21, 60, 70, 23, 107, 212, 53, 183, 36, 120, 175, 145, 143, 119, 64, 211, 76, 27, 138, 254, 1, 242, 245, 39, 186, 217, 14, 193, 54, 83, 187, 14, 53, 26, 231, 178, 199, 34, 128, 130, 163, 63, 154, 243, 187, 46, 221, 78, 13, 44, 235, 221, 166, 154, 168, 114, 132, 106, 208, 236, 15, 95, 29, 38, 39, 207, 46, 103, 207, 167, 241, 73, 73, 34, 29, 193, 186, 61, 12, 122, 200, 14, 235, 216, 247, 176, 238, 180, 241, 33, 177, 159, 181, 119, 164, 215, 83, 141, 28, 110, 242, 75, 18, 38, 233, 216, 108, 200, 201, 98, 235, 172, 220, 164, 135, 201, 120, 184, 41, 78, 108, 121, 10, 158, 88, 5, 211, 147, 44, 47, 146, 189, 184, 76, 60, 133, 83, 171, 240, 57, 251, 0, 87, 58, 250, 202, 158, 91, 101, 39, 121, 181, 59, 245, 97, 80, 90, 5, 231, 89, 58, 206, 39, 62, 144, 115, 127, 73, 182, 28, 245, 145, 224, 131, 85, 186, 172, 210, 241, 217, 149, 167, 224, 85, 207, 226, 6, 147, 136, 202, 13, 254, 116, 24, 65, 198, 164, 30, 195, 27, 26, 143, 42, 138, 122, 238, 33, 189, 121, 134, 153, 65, 58, 166, 66, 248, 124, 100, 243, 140, 0, 92, 216, 180, 115, 159, 99, 76, 75, 240, 87, 120, 99, 165, 247, 223, 112, 179, 167, 130, 182, 46, 127, 243, 98, 117, 228, 49, 215, 116, 154, 251, 82, 49, 105, 118, 39, 31, 224, 110, 15, 241, 101, 31, 130, 211, 251, 35, 121, 167, 53, 114, 92, 105, 239, 85, 57, 159, 205, 132, 219, 59, 46, 248, 94, 128, 88, 123, 203, 248, 247, 145, 90, 37, 126, 253, 181, 180, 10, 44, 55, 135, 104, 230, 29, 176, 202, 235, 60, 205, 170, 93, 166, 27, 76, 115, 79, 163, 173, 203, 99, 246, 111, 133, 94, 211, 33, 160, 175, 71, 67, 246, 31, 105, 223, 210, 165, 208, 221, 151, 224, 168, 235, 139, 13, 9, 51, 202, 197, 101, 112, 152, 139, 203, 218, 107, 179, 46, 235, 6, 154, 213, 197, 35, 61, 194, 35, 40, 81, 80, 13, 178, 246, 102, 85, 122, 158, 254, 14, 110, 26, 129, 170, 139, 0, 102, 133, 134, 35, 146, 197, 229, 32, 82, 158, 15, 115, 122, 150, 213, 91, 93, 237, 11, 16, 50, 12, 201, 56, 71, 168, 222, 145, 173, 177, 14, 253, 67, 136, 174, 93, 119, 184, 37, 110, 58, 196, 239, 126, 216, 178, 157, 183, 162, 43, 191, 200, 67, 168, 140, 246, 172, 155, 28, 185, 209, 0, 3, 247, 237, 228, 139, 170, 114, 43, 225, 217, 101, 50, 22, 245, 236, 249, 0, 141, 43, 235, 249, 197, 235, 152, 205, 61, 170, 160, 127, 248, 173, 98, 154, 11, 28, 41, 43, 46, 145, 152, 233, 204, 26, 62, 134, 77, 179, 241, 116, 62, 225, 102, 22, 84, 0, 69, 211, 179, 247, 145, 5, 6, 158, 142, 184, 132, 110, 223, 204, 188, 199, 71, 161, 125, 133, 15, 98, 51, 135, 117, 109, 26, 151, 213, 190, 58, 182, 162, 228, 119, 23, 206, 164, 234, 107, 156, 50, 245, 41, 112, 194, 93, 79, 118, 222, 190, 169, 148, 146, 162, 140, 117, 64, 218, 108, 175, 139, 83, 87, 76, 124, 184, 20, 61, 138, 118, 49, 47, 136, 115, 138, 48, 104, 85, 65, 134, 134, 67, 53, 126, 22, 143, 115, 122, 151, 25, 228, 3, 93, 25, 97, 100, 224, 145, 203, 147, 165, 139, 28, 81, 69, 59, 225, 49, 181, 12, 135, 83, 18, 162, 17, 148, 5, 192, 237, 229, 87, 159, 6, 152, 46, 250, 8, 181, 188, 174, 243, 144, 241, 255, 103, 235, 235, 158, 149, 68, 59, 185, 210, 204, 237, 140, 118, 71, 14, 144, 91, 19, 140, 26, 160, 198, 148, 34, 175, 225, 141, 89, 94, 166, 50, 39, 163, 64, 118, 148, 196, 197, 248, 148, 153, 99, 18, 77, 155, 162, 48, 52, 166, 210, 19, 72, 45, 215, 145, 89, 112, 127, 104, 155, 47, 216, 23, 158, 153, 182, 63, 66, 74, 17, 49, 214, 104, 254, 94, 104, 100, 24, 30, 133, 5, 194, 49, 218, 208, 111, 151, 201, 113, 55, 205, 64, 114, 195, 72, 127, 120, 170, 198, 208, 179, 67, 184, 171, 170, 124, 108, 197, 123, 135, 201, 108, 26, 179, 5, 65, 41, 205, 135, 66, 252, 70, 17, 83, 159, 127, 102, 13, 51, 173, 208, 185, 162, 67, 241, 84, 246, 133, 149, 33, 233, 24, 81, 135, 116, 157, 180, 40, 171, 159, 115, 86, 164, 80, 227, 38, 50, 32, 242, 190, 57, 16, 205, 20, 96, 96, 81, 53, 102, 181, 161, 116, 166, 121, 173, 76, 166, 167, 56, 255, 128, 7, 13, 102, 10, 60, 183, 222, 250, 192, 227, 0, 188, 91, 104, 116, 192, 187, 32, 21, 53, 63, 203, 33, 125, 26, 125, 183, 69, 3, 254, 77, 48, 200, 79, 113, 41, 83, 84, 60, 147, 191, 158, 231, 76, 13, 156, 191, 159, 196, 62, 178, 24, 224, 154, 63, 21, 148, 53, 218, 128, 215, 180, 145, 136, 50, 114, 170, 214, 250, 164, 10, 168, 219, 129, 245, 102, 100, 191, 144, 221, 178, 95, 99, 108, 237, 111, 98, 86, 183, 94, 42, 196, 201, 107, 210, 207, 143, 43, 238, 83, 109, 175, 192, 182, 208, 122, 91, 162, 73, 17, 139, 140, 165, 132, 225, 242, 241, 180, 153, 117, 213, 82, 238, 13, 141, 115, 221, 140, 233, 73, 105, 73, 8, 230, 161, 97, 136, 126, 14, 237, 108, 60, 245, 39, 167, 87, 245, 232, 166, 144, 92, 184, 3, 181, 62, 106, 105, 168, 225, 124, 210, 36, 63, 157, 218, 97, 116, 220, 134, 154, 134, 164, 174, 57, 107, 60, 240, 104, 32, 194, 59, 35, 225, 31, 135, 0, 209, 195, 11, 2, 27, 153, 102, 106, 251, 87, 12, 18, 132, 94, 12, 172, 224, 190, 72, 180, 73, 31, 92, 252, 157, 225, 146, 175, 221, 46, 249, 214, 34, 30, 4, 68, 243, 188, 61, 212, 180, 221, 176, 183, 89, 167, 209, 182, 235, 26, 162, 168, 59, 173, 111, 204, 60, 138, 215, 46, 250, 20, 132, 171, 222, 63, 245, 34, 199, 111, 228, 82, 79, 93, 41, 82, 160, 188, 131, 29, 102, 147, 5, 69, 230, 200, 41, 111, 114, 253, 227, 36, 241, 242, 88, 148, 18, 199, 129, 70, 104, 125, 221, 10, 147, 226, 118, 135, 61, 139, 122, 243, 131, 181, 89, 70, 221, 189, 229, 145, 142, 91, 80, 153, 144, 147, 201, 33, 117, 193, 170, 52, 129, 194, 129, 253, 218, 44, 75, 104, 184, 44, 138, 124, 82, 196, 38, 225, 79, 122, 172, 229, 152, 28, 165, 40, 75, 67, 182, 23, 207, 152, 110, 73, 84, 30, 9, 158, 201, 227, 60, 190, 236, 27, 26, 241, 90, 58, 100, 97, 35, 26, 170, 11, 6, 209, 232, 240, 220, 239, 193, 193, 209, 197, 4, 72, 158, 125, 138, 87, 66, 118, 173, 179, 246, 34, 216, 72, 114, 154, 119, 105, 198, 48, 84, 105, 77, 36, 138, 194, 217, 166, 117, 169, 142, 139, 222, 90, 65, 138, 89, 112, 63, 215, 62, 224, 108, 51, 220, 227, 26, 213, 76, 114, 91, 76, 55, 26, 148, 150, 38, 102, 186, 137, 60, 253, 151, 135, 230, 43, 154, 118, 208, 189, 6, 240, 79, 210, 194, 59, 23, 233, 5, 157, 126, 163, 7, 172, 113, 126, 242, 235, 248, 128, 158, 71, 20, 178, 34, 133, 77, 198, 202, 8, 34, 126, 217, 159, 199, 79, 12, 22, 59, 176, 208, 194, 6, 17, 207, 27, 26, 207, 94, 105, 126, 59, 202, 244, 249, 85, 149, 250, 147, 125, 13, 28, 194, 129, 127, 154, 141, 160, 32, 178, 254, 148, 13, 163, 254, 114, 156, 226, 243, 100, 130, 88, 88, 114, 194, 9, 132, 226, 151, 120, 37, 73, 11, 6, 91, 215, 161, 255, 164, 188, 199, 140, 194, 163, 142, 233, 111, 219, 43, 154, 161, 159, 62, 241, 200, 178, 105, 218, 213, 2, 235, 230, 204, 13, 89, 227, 187, 80, 204, 186, 31, 82, 36, 121, 26, 89, 183, 89, 197, 112, 126, 228, 215, 48, 26, 224, 58, 22, 92, 119, 33, 230, 169, 204, 58, 106, 45, 213, 237, 148, 239, 170, 139, 150, 117, 35, 36, 196, 67, 136, 149, 86, 52, 80, 107, 43, 47, 9, 2, 150, 76, 80, 82, 141, 140, 34, 233, 228, 114, 137, 37, 146, 200, 226, 117, 141, 157, 177, 225, 98, 119, 90, 87, 31, 181, 2, 229, 83, 128, 103, 222, 85, 5, 7, 86, 21, 152, 126, 101, 87, 104, 220, 108, 179, 84, 135, 37, 186, 73, 154, 101, 45, 159, 64, 7, 13, 135, 186, 14, 232, 250, 58, 208, 178, 73, 252, 107, 215, 38, 174, 94, 8, 28, 179, 80, 177, 123, 154, 62, 88, 101, 208, 232, 61, 196, 239, 186, 219, 232, 147, 63, 161, 40, 41, 80, 191, 110, 118, 46, 168, 54, 112, 5, 106, 16, 105, 98, 125, 114, 39, 17, 169, 86, 200, 239, 53, 244, 11, 105, 93, 26, 86, 120, 43, 186, 103, 126, 12, 111, 160, 175, 219, 183, 183, 175, 230, 199, 246, 13, 116, 252, 193, 29, 233, 184, 249, 241, 224, 6, 168, 240, 240, 46, 82, 193, 252, 120, 184, 76, 146, 96, 127, 122, 71, 85, 221, 188, 231, 80, 87, 27, 47, 67, 91, 89, 110, 29, 225, 251, 172, 59, 226, 177, 177, 71, 188, 241, 88, 3, 117, 146, 161, 131, 134, 170, 113, 79, 224, 81, 139, 158, 217, 19, 92, 141, 125, 234, 248, 137, 152, 113, 195, 141, 166, 180, 154, 27, 222, 212, 84, 17, 70, 149, 248, 67, 89, 196, 227, 46, 178, 172, 150, 129, 139, 91, 216, 192, 122, 110, 79, 191, 220, 198, 146, 6, 86, 68, 54, 173, 220, 157, 24, 29, 158, 145, 185, 179, 188, 220, 94, 216, 16, 139, 234, 214, 230, 64, 139, 25, 191, 102, 190, 183, 103, 251, 26, 13, 209, 168, 31, 194, 218, 33, 160, 27, 244, 186, 154, 190, 246, 75, 56, 150, 111, 35, 221, 90, 182, 237, 121, 253, 51, 117, 68, 61, 218, 51, 249, 226, 125, 218, 190, 77, 125, 82, 143, 246, 124, 189, 120, 247, 30, 220, 210, 238, 169, 71, 123, 78, 94, 188, 167, 15, 111, 127, 79, 213, 163, 61, 235, 46, 208, 105, 236, 18, 12, 46, 5, 201, 170, 109, 171, 118, 213, 182, 211, 98, 226, 205, 116, 7, 50, 115, 4, 178, 190, 134, 86, 156, 235, 224, 7, 36, 179, 124, 235, 138, 219, 106, 130, 111, 57, 9, 182, 6, 252, 192, 55, 179, 163, 121, 145, 242, 207, 114, 230, 116, 239, 172, 183, 248, 198, 154, 217, 251, 88, 40, 128, 173, 83, 192, 204, 162, 158, 231, 79, 18, 55, 227, 236, 4, 116, 137, 145, 169, 241, 166, 45, 203, 151, 230, 58, 253, 188, 4, 211, 88, 155, 46, 163, 142, 60, 49, 158, 182, 91, 22, 90, 131, 200, 143, 215, 1, 247, 197, 239, 231, 139, 18, 88, 105, 189, 141, 41, 246, 223, 219, 202, 106, 103, 185, 204, 139, 244, 4, 78, 228, 139, 190, 224, 232, 21, 49, 226, 222, 240, 149, 225, 154, 93, 253, 185, 220, 61, 149, 145, 212, 58, 235, 155, 212, 142, 60, 93, 77, 169, 133, 233, 239, 214, 7, 180, 29, 120, 3, 186, 194, 241, 67, 91, 91, 68, 104, 139, 208, 198, 152, 110, 235, 117, 86, 58, 13, 106, 199, 203, 249, 221, 148, 143, 189, 45, 214, 61, 66, 47, 106, 177, 91, 102, 111, 66, 184, 182, 81, 131, 101, 20, 178, 139, 188, 86, 145, 179, 71, 229, 183, 113, 140, 133, 163, 115, 130, 225, 61, 37, 254, 136, 71, 207, 218, 134, 230, 241, 160, 77, 67, 23, 220, 150, 14, 12, 221, 142, 127, 84, 180, 149, 215, 134, 228, 144, 232, 108, 199, 207, 117, 120, 239, 17, 23, 195, 28, 83, 183, 155, 18, 220, 66, 244, 175, 155, 145, 73, 76, 119, 17, 107, 55, 13, 241, 88, 91, 3, 243, 137, 231, 75, 35, 241, 109, 167, 75, 50, 46, 244, 94, 164, 219, 58, 83, 98, 204, 254, 124, 162, 120, 194, 108, 10, 202, 66, 237, 212, 58, 216, 196, 186, 49, 107, 106, 248, 243, 79, 27, 84, 93, 124, 35, 183, 174, 201, 236, 192, 107, 163, 205, 108, 163, 222, 244, 89, 209, 195, 248, 162, 79, 91, 29, 80, 24, 158, 240, 204, 123, 102, 29, 224, 200, 200, 78, 22, 2, 138, 104, 188, 147, 198, 194, 103, 153, 244, 191, 204, 15, 214, 252, 208, 28, 219, 43, 211, 83, 205, 68, 216, 176, 24, 119, 39, 181, 27, 212, 162, 123, 192, 6, 60, 175, 92, 19, 146, 177, 179, 131, 126, 208, 249, 10, 170, 154, 175, 86, 236, 8, 252, 67, 49, 205, 86, 194, 114, 60, 10, 56, 236, 118, 181, 190, 183, 139, 205, 151, 238, 140, 105, 5, 224, 250, 236, 25, 207, 188, 25, 216, 30, 249, 50, 131, 126, 153, 65, 163, 47, 51, 104, 83, 32, 124, 199, 233, 211, 221, 120, 186, 177, 121, 244, 203, 92, 119, 27, 230, 186, 155, 136, 233, 235, 176, 135, 138, 105, 21, 152, 102, 220, 45, 85, 81, 120, 193, 213, 88, 56, 40, 115, 224, 239, 128, 124, 251, 101, 249, 246, 57, 38, 159, 123, 162, 158, 253, 39, 81, 90, 170, 103, 255, 201, 220, 112, 72, 253, 66, 199, 240, 204, 217, 142, 131, 98, 196, 115, 106, 80, 29, 223, 55, 233, 231, 127, 88, 211, 123, 73, 180, 6, 14, 243, 171, 101, 130, 112, 85, 62, 140, 158, 9, 131, 234, 9, 62, 140, 35, 196, 37, 216, 8, 14, 158, 226, 232, 232, 185, 172, 241, 90, 214, 225, 239, 199, 158, 196, 186, 140, 48, 86, 94, 177, 174, 247, 120, 134, 155, 183, 26, 119, 97, 227, 150, 45, 13, 83, 31, 98, 29, 154, 177, 137, 184, 108, 161, 13, 74, 166, 21, 172, 6, 238, 159, 28, 119, 217, 197, 248, 34, 197, 203, 145, 226, 46, 86, 91, 141, 197, 182, 44, 17, 214, 241, 82, 1, 227, 174, 205, 73, 156, 26, 163, 174, 214, 28, 14, 91, 118, 159, 66, 67, 180, 241, 3, 96, 43, 173, 49, 244, 109, 69, 26, 89, 95, 84, 77, 221, 73, 218, 150, 11, 186, 240, 177, 135, 47, 234, 231, 139, 250, 185, 147, 234, 103, 193, 128, 211, 229, 132, 249, 182, 92, 154, 118, 82, 120, 29, 99, 125, 191, 104, 70, 108, 22, 223, 178, 204, 108, 98, 71, 32, 249, 144, 230, 243, 242, 5, 226, 112, 204, 240, 142, 139, 108, 191, 252, 159, 164, 200, 97, 0, 217, 104, 115, 150, 232, 59, 48, 212, 217, 95, 222, 35, 171, 102, 64, 170, 200, 213, 116, 181, 153, 91, 32, 55, 187, 206, 180, 247, 152, 233, 229, 191, 28, 31, 31, 215, 28, 91, 183, 87, 76, 234, 88, 114, 29, 114, 14, 122, 78, 23, 165, 130, 163, 59, 25, 11, 38, 147, 145, 39, 208, 188, 19, 78, 120, 122, 8, 160, 68, 119, 28, 172, 60, 146, 158, 3, 0, 130, 60, 52, 105, 220, 192, 5, 30, 102, 234, 230, 170, 134, 221, 107, 19, 10, 240, 160, 214, 121, 81, 48, 169, 175, 227, 70, 62, 110, 134, 249, 236, 26, 62, 4, 2, 60, 231, 165, 160, 226, 193, 192, 36, 40, 105, 183, 97, 223, 106, 68, 103, 32, 151, 84, 179, 41, 91, 10, 171, 100, 82, 83, 88, 24, 223, 38, 45, 240, 94, 222, 104, 84, 229, 133, 216, 30, 244, 93, 113, 36, 122, 98, 18, 99, 4, 110, 74, 130, 1, 69, 240, 204, 38, 178, 17, 105, 125, 3, 67, 189, 152, 243, 66, 123, 188, 139, 24, 65, 249, 161, 207, 169, 72, 207, 102, 64, 196, 171, 236, 189, 249, 170, 110, 225, 162, 54, 34, 196, 234, 114, 79, 34, 55, 135, 248, 176, 148, 48, 72, 85, 82, 168, 97, 64, 24, 235, 28, 31, 221, 165, 219, 106, 38, 176, 13, 65, 117, 0, 151, 125, 162, 86, 202, 238, 59, 247, 240, 79, 117, 201, 191, 225, 84, 202, 141, 38, 213, 236, 255, 241, 118, 189, 170, 13, 1, 42, 148, 242, 179, 13, 208, 250, 76, 44, 62, 74, 116, 74, 146, 178, 163, 53, 124, 150, 92, 60, 87, 33, 8, 234, 128, 113, 91, 64, 87, 61, 164, 84, 21, 32, 28, 211, 224, 116, 221, 46, 4, 217, 103, 69, 166, 94, 165, 101, 17, 113, 130, 57, 223, 247, 6, 17, 220, 1, 117, 57, 208, 240, 136, 116, 210, 188, 132, 98, 118, 219, 197, 91, 79, 140, 159, 21, 95, 122, 24, 95, 117, 137, 125, 130, 74, 60, 143, 44, 252, 219, 113, 22, 9, 188, 128, 128, 240, 244, 233, 83, 203, 219, 168, 26, 148, 173, 80, 95, 60, 78, 164, 167, 106, 148, 233, 239, 192, 148, 56, 247, 28, 191, 71, 148, 191, 198, 149, 3, 242, 36, 83, 34, 211, 137, 90, 145, 83, 78, 215, 225, 132, 90, 118, 78, 63, 58, 110, 6, 50, 159, 104, 16, 212, 53, 115, 131, 121, 51, 80, 254, 127, 127, 58, 196, 45, 115, 8, 209, 71, 156, 223, 96, 142, 241, 168, 191, 87, 57, 178, 226, 177, 90, 100, 150, 205, 106, 32, 208, 22, 99, 15, 32, 229, 142, 226, 111, 204, 2, 2, 98, 99, 251, 135, 9, 244, 239, 59, 62, 162, 155, 118, 77, 183, 127, 115, 237, 36, 66, 254, 223, 136, 141, 242, 155, 116, 42, 131, 158, 253, 13, 12, 112, 220, 54, 252, 243, 110, 148, 36, 173, 226, 97, 127, 143, 204, 93, 209, 122, 44, 131, 108, 243, 187, 179, 156, 173, 65, 251, 247, 246, 155, 159, 64, 143, 223, 205, 66, 210, 116, 188, 75, 103, 127, 99, 42, 226, 119, 182, 154, 37, 177, 184, 1, 133, 74, 44, 146, 223, 118, 156, 238, 57, 188, 219, 220, 177, 223, 120, 20, 13, 213, 181, 161, 109, 178, 223, 224, 178, 201, 223, 240, 118, 24, 191, 224, 157, 205, 181, 246, 245, 186, 162, 107, 218, 251, 226, 226, 239, 164, 97, 19, 42, 96, 70, 153, 109, 113, 196, 40, 90, 117, 114, 41, 213, 231, 192, 138, 170, 102, 64, 33, 140, 90, 221, 107, 37, 75, 137, 20, 160, 56, 245, 226, 46, 199, 155, 233, 63, 39, 97, 28, 201, 199, 10, 218, 50, 49, 117, 127, 247, 40, 21, 62, 89, 113, 235, 227, 224, 184, 49, 135, 210, 239, 254, 244, 73, 2, 10, 228, 111, 210, 148, 144, 194, 159, 242, 131, 93, 22, 120, 204, 8, 13, 212, 249, 93, 93, 106, 39, 25, 74, 81, 194, 67, 156, 70, 2, 185, 68, 194, 156, 131, 85, 169, 214, 138, 202, 210, 158, 217, 178, 213, 128, 118, 79, 94, 216, 137, 229, 169, 35, 31, 240, 249, 73, 179, 2, 50, 227, 119, 61, 182, 251, 187, 89, 145, 87, 57, 152, 149, 239, 132, 48, 90, 139, 248, 186, 36, 250, 252, 8, 214, 126, 73, 140, 219, 67, 59, 117, 54, 49, 94, 36, 197, 32, 79, 171, 212, 111, 73, 117, 154, 79, 246, 143, 255, 85, 196, 179, 153, 137, 174, 63, 84, 15, 114, 81, 33, 127, 245, 188, 56, 91, 23, 250, 214, 45, 7, 130, 233, 201, 15, 3, 73, 199, 223, 36, 101, 213, 137, 38, 53, 11, 154, 14, 23, 11, 180, 194, 31, 16, 127, 158, 23, 28, 69, 23, 255, 175, 212, 218, 140, 175, 97, 228, 181, 8, 234, 30, 14, 142, 124, 248, 98, 1, 89, 73, 222, 185, 112, 52, 226, 183, 249, 110, 150, 226, 237, 91, 114, 199, 0, 154, 166, 118, 167, 211, 207, 228, 3, 42, 105, 102, 188, 207, 176, 254, 35, 139, 13, 21, 99, 90, 12, 34, 103, 113, 223, 232, 253, 113, 150, 132, 250, 72, 254, 34, 139, 164, 5, 150, 116, 18, 119, 180, 22, 106, 183, 65, 65, 84, 150, 70, 182, 215, 163, 136, 132, 150, 79, 166, 213, 22, 139, 12, 79, 197, 205, 118, 72, 106, 68, 164, 70, 233, 176, 182, 58, 233, 173, 49, 78, 228, 254, 171, 71, 96, 184, 255, 217, 29, 196, 92, 130, 24, 110, 113, 16, 46, 117, 55, 182, 45, 149, 45, 46, 89, 148, 82, 41, 108, 8, 102, 150, 196, 192, 138, 154, 199, 24, 181, 6, 54, 3, 78, 253, 174, 173, 26, 112, 69, 114, 146, 92, 206, 6, 74, 227, 134, 1, 154, 172, 20, 214, 255, 248, 76, 46, 193, 177, 190, 188, 74, 46, 188, 13, 241, 110, 11, 126, 100, 250, 135, 176, 161, 170, 205, 23, 31, 2, 161, 86, 165, 135, 10, 237, 86, 165, 183, 85, 231, 90, 149, 126, 160, 60, 8, 127, 202, 17, 243, 87, 16, 150, 146, 170, 197, 127, 201, 59, 235, 53, 229, 86, 172, 171, 79, 100, 97, 159, 67, 141, 80, 236, 85, 114, 89, 161, 107, 109, 196, 149, 242, 126, 157, 202, 175, 36, 102, 179, 114, 95, 20, 250, 101, 30, 23, 147, 55, 185, 119, 24, 160, 232, 90, 200, 3, 88, 63, 105, 83, 72, 129, 41, 28, 16, 180, 230, 109, 183, 91, 158, 169, 91, 187, 81, 255, 136, 248, 189, 215, 143, 240, 177, 243, 73, 158, 177, 23, 60, 77, 173, 184, 255, 217, 222, 63, 213, 122, 206, 29, 28, 184, 98, 77, 140, 139, 26, 8, 247, 40, 178, 89, 136, 75, 151, 39, 52, 8, 212, 46, 148, 101, 238, 245, 57, 11, 188, 129, 93, 49, 10, 98, 76, 28, 93, 75, 145, 217, 90, 65, 91, 73, 130, 137, 91, 168, 120, 10, 99, 136, 97, 180, 212, 248, 20, 194, 3, 12, 161, 54, 245, 251, 226, 7, 243, 173, 253, 99, 228, 62, 145, 49, 185, 157, 60, 129, 146, 179, 116, 15, 162, 104, 219, 240, 18, 137, 144, 87, 6, 234, 107, 101, 52, 162, 9, 184, 175, 61, 177, 45, 34, 233, 165, 130, 28, 10, 169, 145, 152, 186, 213, 3, 51, 172, 172, 189, 45, 106, 31, 123, 34, 231, 67, 155, 245, 122, 193, 33, 73, 170, 127, 147, 205, 20, 249, 150, 172, 160, 87, 195, 219, 241, 181, 123, 241, 122, 147, 90, 207, 147, 184, 194, 227, 39, 146, 81, 229, 146, 14, 45, 146, 126, 180, 119, 225, 173, 73, 197, 19, 183, 10, 145, 171, 198, 51, 130, 34, 102, 189, 171, 255, 26, 229, 235, 48, 4, 252, 123, 136, 127, 108, 12, 245, 15, 180, 50, 12, 73, 186, 248, 102, 73, 59, 166, 146, 239, 14, 132, 224, 6, 191, 237, 48, 177, 199, 128, 23, 146, 113, 227, 222, 184, 240, 198, 88, 98, 27, 162, 47, 158, 88, 140, 145, 199, 39, 81, 59, 64, 193, 224, 98, 67, 139, 107, 142, 12, 158, 35, 173, 1, 114, 206, 83, 45, 157, 5, 76, 4, 10, 103, 132, 15, 242, 162, 15, 78, 234, 29, 253, 205, 97, 4, 181, 7, 41, 213, 126, 211, 14, 132, 118, 165, 66, 121, 98, 173, 90, 33, 227, 254, 254, 241, 11, 66, 169, 85, 212, 64, 10, 68, 6, 77, 130, 13, 164, 36, 213, 196, 37, 133, 141, 108, 91, 18, 177, 213, 218, 219, 47, 150, 221, 145, 24, 98, 77, 221, 105, 162, 117, 69, 78, 247, 192, 202, 142, 174, 132, 14, 205, 7, 170, 152, 218, 94, 183, 228, 7, 32, 129, 209, 226, 46, 34, 172, 33, 35, 174, 43, 136, 146, 232, 28, 193, 175, 164, 77, 55, 135, 195, 248, 13, 14, 72, 210, 60, 108, 163, 91, 54, 236, 72, 100, 229, 90, 227, 34, 150, 32, 126, 121, 112, 174, 111, 212, 214, 171, 154, 106, 245, 229, 239, 130, 186, 212, 70, 213, 223, 44, 155, 83, 95, 62, 64, 24, 147, 47, 9, 85, 149, 35, 179, 120, 23, 62, 137, 126, 143, 23, 234, 173, 189, 37, 60, 202, 42, 121, 131, 140, 100, 75, 171, 171, 178, 148, 181, 216, 218, 47, 95, 231, 101, 153, 190, 159, 94, 73, 91, 150, 172, 207, 53, 222, 164, 203, 220, 117, 177, 159, 193, 21, 185, 113, 197, 170, 38, 194, 28, 230, 97, 75, 98, 128, 63, 136, 214, 45, 31, 7, 91, 86, 244, 4, 75, 244, 68, 202, 166, 129, 225, 93, 81, 139, 182, 35, 215, 148, 28, 113, 201, 145, 134, 184, 251, 229, 43, 198, 122, 7, 197, 63, 84, 135, 57, 8, 234, 94, 241, 224, 40, 137, 39, 208, 36, 58, 33, 45, 95, 139, 203, 40, 71, 202, 34, 85, 142, 23, 169, 238, 96, 231, 89, 112, 113, 79, 81, 158, 55, 181, 218, 183, 171, 130, 75, 35, 206, 164, 205, 37, 165, 128, 155, 98, 98, 4, 95, 228, 249, 217, 124, 214, 95, 211, 134, 216, 170, 219, 25, 217, 221, 21, 99, 44, 145, 3, 193, 138, 26, 172, 165, 26, 239, 138, 40, 228, 56, 189, 201, 74, 7, 25, 47, 74, 211, 34, 226, 40, 149, 79, 121, 147, 177, 164, 36, 167, 170, 16, 100, 82, 91, 23, 133, 216, 212, 241, 148, 217, 184, 71, 106, 157, 200, 225, 115, 106, 142, 243, 233, 65, 246, 186, 128, 109, 167, 244, 67, 178, 151, 207, 51, 126, 123, 174, 59, 199, 233, 94, 219, 238, 21, 237, 79, 8, 116, 220, 235, 155, 212, 101, 0, 99, 207, 208, 215, 27, 223, 88, 137, 179, 73, 178, 210, 241, 115, 207, 217, 15, 1, 68, 92, 250, 57, 178, 38, 62, 25, 78, 160, 42, 4, 168, 168, 20, 139, 46, 232, 118, 6, 159, 86, 229, 190, 145, 62, 106, 71, 112, 89, 155, 14, 184, 247, 89, 218, 33, 89, 72, 205, 248, 136, 143, 184, 232, 178, 142, 131, 132, 255, 107, 20, 214, 13, 224, 132, 93, 170, 122, 96, 0, 109, 13, 33, 185, 51, 32, 166, 84, 70, 229, 132, 224, 176, 48, 94, 170, 202, 201, 13, 5, 41, 132, 240, 22, 150, 20, 22, 4, 75, 173, 14, 135, 67, 135, 231, 57, 186, 205, 78, 58, 205, 211, 162, 17, 122, 15, 168, 183, 169, 109, 86, 70, 211, 200, 123, 38, 254, 230, 245, 20, 107, 122, 249, 170, 138, 247, 231, 126, 104, 43, 237, 82, 113, 85, 86, 157, 252, 155, 91, 146, 106, 112, 224, 141, 181, 146, 92, 65, 80, 25, 112, 44, 3, 138, 5, 102, 43, 118, 72, 173, 228, 203, 89, 60, 97, 125, 188, 20, 38, 40, 91, 66, 164, 211, 233, 72, 90, 141, 236, 211, 179, 108, 114, 109, 241, 22, 96, 96, 115, 69, 60, 193, 246, 10, 60, 142, 170, 184, 168, 124, 70, 129, 181, 203, 66, 232, 152, 102, 213, 75, 133, 45, 182, 157, 117, 23, 176, 143, 139, 189, 225, 251, 196, 133, 21, 88, 67, 128, 8, 47, 3, 251, 97, 233, 88, 246, 82, 33, 165, 189, 206, 64, 157, 132, 32, 103, 232, 165, 53, 185, 42, 68, 110, 70, 114, 129, 58, 136, 60, 141, 250, 253, 97, 244, 248, 113, 244, 96, 11, 54, 175, 183, 41, 97, 15, 227, 236, 68, 43, 132, 45, 66, 47, 104, 80, 116, 149, 192, 219, 144, 253, 82, 200, 179, 37, 79, 54, 134, 64, 109, 233, 119, 82, 125, 113, 125, 176, 146, 53, 138, 100, 198, 56, 85, 197, 170, 67, 105, 241, 220, 87, 13, 254, 183, 124, 173, 183, 220, 255, 52, 110, 70, 127, 107, 235, 56, 100, 93, 194, 132, 213, 166, 130, 248, 95, 22, 68, 69, 83, 201, 67, 64, 83, 124, 252, 223, 80, 149, 173, 97, 188, 45, 90, 83, 98, 0, 43, 49, 46, 94, 225, 120, 87, 2, 155, 250, 69, 4, 182, 157, 162, 30, 217, 241, 36, 196, 52, 80, 4, 151, 195, 126, 157, 87, 210, 248, 146, 36, 36, 158, 239, 146, 44, 32, 162, 75, 107, 159, 211, 148, 54, 175, 71, 137, 239, 250, 28, 23, 249, 185, 138, 4, 240, 110, 204, 168, 227, 41, 170, 218, 175, 204, 58, 75, 166, 125, 165, 128, 148, 38, 66, 17, 27, 2, 228, 22, 103, 26, 207, 231, 169, 68, 115, 11, 113, 149, 75, 158, 66, 93, 48, 203, 67, 162, 100, 122, 87, 55, 183, 249, 117, 140, 19, 9, 205, 103, 155, 200, 149, 136, 92, 178, 32, 28, 200, 186, 101, 25, 43, 19, 4, 59, 184, 60, 193, 101, 234, 231, 126, 92, 178, 141, 1, 160, 110, 213, 137, 8, 153, 5, 71, 5, 175, 144, 68, 231, 120, 168, 77, 64, 128, 184, 243, 152, 162, 55, 182, 11, 52, 156, 86, 134, 129, 191, 123, 55, 98, 29, 40, 196, 186, 144, 166, 165, 197, 32, 0, 142, 156, 66, 184, 119, 74, 61, 234, 69, 51, 190, 65, 24, 177, 160, 165, 47, 5, 36, 117, 183, 36, 142, 101, 24, 144, 102, 3, 87, 100, 74, 106, 251, 47, 65, 94, 184, 41, 255, 125, 199, 100, 162, 155, 229, 101, 109, 184, 243, 36, 185, 60, 56, 70, 59, 203, 8, 190, 153, 73, 242, 210, 217, 129, 83, 147, 8, 43, 135, 155, 3, 68, 44, 111, 31, 175, 80, 195, 8, 110, 2, 107, 218, 73, 214, 186, 246, 118, 174, 160, 173, 176, 42, 78, 167, 175, 121, 239, 0, 191, 117, 82, 203, 58, 176, 151, 37, 23, 35, 141, 42, 238, 145, 118, 49, 234, 18, 58, 44, 130, 248, 235, 240, 103, 162, 230, 57, 134, 226, 16, 153, 38, 187, 41, 188, 254, 68, 17, 100, 135, 48, 176, 182, 197, 74, 27, 91, 206, 153, 178, 99, 143, 73, 105, 23, 211, 117, 31, 46, 178, 242, 128, 182, 180, 161, 222, 219, 235, 93, 68, 153, 224, 76, 193, 99, 135, 110, 124, 178, 104, 191, 150, 245, 233, 42, 178, 160, 245, 43, 51, 188, 170, 69, 37, 238, 230, 210, 22, 17, 173, 121, 113, 251, 101, 150, 251, 143, 157, 229, 22, 154, 115, 118, 149, 149, 187, 248, 180, 35, 42, 24, 61, 23, 214, 205, 177, 216, 130, 249, 233, 202, 14, 79, 30, 14, 8, 20, 221, 125, 102, 218, 31, 28, 67, 28, 255, 75, 185, 57, 166, 79, 170, 232, 240, 20, 147, 25, 13, 29, 213, 174, 203, 135, 6, 251, 53, 232, 176, 182, 47, 196, 198, 51, 107, 234, 47, 56, 14, 150, 144, 74, 190, 83, 88, 240, 159, 136, 123, 73, 179, 143, 61, 201, 246, 157, 107, 6, 80, 127, 112, 229, 29, 91, 176, 2, 105, 183, 107, 147, 110, 251, 19, 127, 121, 18, 110, 251, 186, 232, 203, 36, 166, 189, 40, 188, 219, 184, 243, 134, 203, 71, 211, 148, 199, 148, 152, 153, 204, 75, 85, 58, 232, 54, 93, 217, 252, 70, 11, 224, 182, 10, 149, 115, 140, 180, 232, 156, 245, 182, 219, 136, 200, 153, 125, 204, 137, 59, 116, 36, 24, 96, 205, 195, 120, 230, 178, 192, 61, 166, 147, 61, 141, 101, 242, 207, 229, 86, 167, 41, 0, 167, 207, 246, 212, 238, 217, 3, 148, 252, 43, 58, 179, 52, 87, 180, 0, 247, 101, 171, 202, 154, 27, 197, 145, 163, 6, 7, 112, 41, 207, 37, 181, 244, 0, 75, 82, 227, 25, 80, 67, 184, 69, 14, 96, 133, 211, 117, 60, 192, 55, 181, 105, 69, 18, 34, 52, 111, 93, 109, 108, 47, 111, 207, 234, 186, 238, 106, 61, 250, 93, 156, 213, 165, 56, 0, 158, 204, 98, 25, 52, 139, 206, 128, 95, 75, 234, 1, 174, 207, 98, 151, 34, 14, 239, 189, 11, 106, 40, 211, 78, 148, 49, 11, 107, 135, 145, 236, 135, 23, 180, 42, 92, 115, 78, 149, 140, 164, 228, 8, 232, 9, 98, 191, 129, 105, 5, 133, 162, 185, 39, 138, 66, 46, 45, 31, 134, 203, 113, 104, 41, 172, 66, 42, 204, 148, 104, 50, 243, 85, 185, 86, 138, 12, 232, 131, 136, 162, 172, 88, 193, 72, 142, 70, 51, 71, 146, 177, 101, 175, 235, 122, 216, 154, 115, 18, 209, 105, 10, 70, 75, 171, 222, 237, 205, 205, 168, 53, 125, 24, 178, 145, 22, 245, 27, 242, 252, 160, 146, 82, 114, 130, 89, 189, 61, 149, 199, 175, 221, 115, 211, 17, 63, 231, 132, 44, 127, 202, 175, 222, 83, 212, 186, 107, 71, 111, 241, 152, 137, 57, 4, 243, 108, 120, 183, 254, 104, 68, 170, 134, 164, 72, 30, 176, 29, 68, 135, 156, 48, 90, 59, 212, 224, 220, 2, 11, 138, 3, 50, 116, 92, 41, 134, 166, 253, 202, 16, 217, 88, 113, 81, 113, 19, 107, 9, 170, 80, 65, 237, 186, 51, 55, 245, 108, 182, 201, 29, 59, 190, 211, 199, 43, 238, 51, 38, 60, 129, 99, 198, 240, 6, 111, 234, 241, 221, 29, 232, 129, 149, 138, 226, 71, 14, 247, 17, 170, 10, 189, 84, 21, 143, 121, 162, 111, 9, 221, 44, 184, 82, 225, 158, 208, 171, 47, 133, 2, 236, 38, 240, 93, 12, 10, 64, 180, 93, 91, 157, 21, 241, 84, 46, 242, 115, 187, 162, 193, 104, 160, 129, 27, 47, 95, 110, 175, 11, 131, 197, 3, 251, 41, 122, 51, 134, 239, 154, 176, 153, 36, 103, 166, 51, 252, 94, 147, 199, 70, 248, 89, 187, 253, 114, 63, 155, 50, 104, 108, 88, 95, 196, 197, 73, 98, 111, 8, 233, 49, 198, 7, 236, 200, 55, 197, 82, 216, 190, 191, 62, 87, 45, 176, 217, 219, 196, 58, 50, 117, 130, 203, 118, 156, 149, 34, 20, 129, 137, 121, 138, 215, 194, 76, 101, 109, 55, 234, 134, 31, 163, 220, 11, 6, 25, 47, 115, 193, 194, 138, 129, 213, 113, 56, 216, 229, 234, 173, 203, 184, 197, 48, 38, 63, 185, 75, 157, 207, 96, 148, 33, 231, 106, 136, 59, 19, 197, 154, 242, 56, 174, 130, 201, 161, 213, 237, 205, 113, 94, 210, 152, 253, 41, 130, 126, 81, 163, 157, 25, 202, 195, 77, 227, 28, 182, 91, 33, 164, 113, 120, 125, 38, 18, 192, 186, 48, 17, 180, 182, 43, 195, 41, 229, 157, 212, 253, 53, 111, 62, 142, 146, 110, 204, 251, 43, 121, 182, 12, 216, 168, 235, 102, 153, 53, 160, 234, 245, 183, 214, 214, 154, 225, 109, 119, 130, 23, 250, 52, 92, 243, 48, 142, 144, 9, 120, 175, 47, 50, 77, 185, 223, 136, 253, 121, 28, 57, 232, 236, 192, 185, 117, 219, 137, 228, 122, 229, 112, 179, 169, 50, 114, 204, 170, 223, 84, 106, 191, 124, 7, 7, 198, 114, 39, 48, 128, 120, 39, 38, 47, 62, 125, 80, 253, 240, 152, 111, 117, 195, 191, 31, 157, 237, 112, 54, 254, 120, 34, 147, 229, 30, 133, 52, 10, 158, 169, 96, 226, 81, 13, 1, 178, 172, 153, 96, 3, 114, 170, 243, 0, 230, 95, 48, 216, 114, 22, 103, 182, 58, 212, 51, 146, 82, 132, 237, 102, 50, 14, 170, 139, 198, 129, 81, 246, 40, 28, 17, 179, 210, 31, 131, 69, 188, 148, 237, 156, 196, 175, 113, 194, 182, 112, 70, 120, 69, 32, 162, 116, 81, 134, 39, 20, 39, 172, 71, 102, 141, 210, 187, 69, 172, 248, 183, 40, 73, 223, 19, 39, 62, 168, 77, 128, 144, 9, 209, 224, 126, 86, 72, 141, 103, 129, 129, 240, 127, 141, 253, 27, 237, 113, 230, 122, 99, 103, 7, 175, 205, 160, 54, 202, 32, 244, 134, 123, 250, 176, 17, 157, 49, 171, 94, 103, 216, 224, 53, 76, 233, 17, 46, 77, 207, 218, 88, 158, 97, 164, 56, 222, 248, 116, 70, 170, 79, 248, 118, 26, 96, 179, 237, 36, 155, 213, 7, 18, 116, 128, 188, 254, 45, 18, 17, 168, 134, 244, 7, 58, 226, 252, 101, 75, 174, 160, 231, 149, 69, 137, 206, 39, 149, 71, 173, 10, 14, 45, 201, 243, 158, 255, 165, 24, 92, 251, 228, 175, 213, 161, 133, 206, 252, 82, 24, 109, 78, 251, 186, 157, 8, 164, 232, 104, 58, 114, 41, 14, 61, 33, 149, 110, 29, 242, 245, 31, 181, 228, 181, 140, 232, 120, 178, 120, 117, 63, 103, 44, 172, 79, 121, 112, 21, 167, 115, 233, 124, 78, 24, 78, 7, 189, 206, 83, 190, 117, 18, 218, 185, 213, 101, 118, 43, 30, 66, 158, 146, 44, 208, 227, 211, 184, 224, 174, 5, 6, 97, 200, 180, 68, 223, 128, 124, 42, 179, 163, 213, 48, 164, 160, 142, 132, 201, 106, 107, 104, 146, 55, 201, 153, 159, 16, 130, 48, 65, 236, 169, 86, 7, 156, 155, 6, 166, 103, 152, 203, 141, 137, 209, 60, 123, 96, 142, 241, 45, 129, 42, 54, 11, 140, 223, 21, 241, 5, 79, 185, 48, 98, 2, 20, 25, 225, 24, 231, 249, 25, 79, 183, 172, 51, 7, 171, 66, 38, 216, 55, 190, 32, 223, 121, 141, 77, 246, 214, 216, 27, 92, 40, 167, 163, 228, 132, 155, 97, 228, 20, 88, 124, 97, 71, 63, 58, 165, 61, 6, 172, 12, 244, 168, 169, 97, 91, 175, 102, 231, 51, 190, 80, 7, 216, 168, 17, 233, 26, 128, 168, 168, 182, 43, 241, 201, 180, 225, 14, 250, 249, 216, 238, 38, 250, 104, 172, 77, 181, 119, 168, 234, 56, 182, 41, 246, 220, 32, 172, 214, 3, 118, 169, 134, 165, 236, 211, 143, 43, 181, 117, 161, 75, 186, 142, 161, 2, 97, 171, 112, 88, 201, 251, 244, 164, 227, 52, 228, 179, 51, 24, 20, 219, 200, 80, 195, 250, 152, 125, 123, 218, 195, 182, 63, 47, 6, 233, 19, 31, 255, 55, 255, 230, 69, 139, 113, 255, 217, 50, 16, 3, 56, 97, 212, 224, 107, 24, 57, 241, 213, 139, 94, 62, 157, 44, 3, 59, 6, 38, 140, 92, 24, 49, 63, 82, 199, 233, 101, 178, 12, 172, 56, 156, 32, 90, 85, 21, 196, 11, 62, 249, 237, 157, 152, 89, 187, 229, 18, 80, 147, 144, 130, 200, 165, 65, 220, 82, 63, 106, 229, 57, 211, 125, 75, 64, 140, 195, 9, 162, 197, 191, 6, 81, 147, 95, 189, 232, 177, 63, 103, 201, 50, 240, 227, 128, 194, 8, 242, 207, 97, 12, 229, 231, 128, 23, 119, 25, 248, 205, 223, 135, 145, 155, 135, 69, 129, 127, 243, 163, 53, 91, 10, 90, 179, 26, 180, 102, 53, 104, 205, 44, 180, 158, 149, 227, 120, 150, 236, 86, 172, 232, 251, 121, 37, 179, 86, 127, 48, 179, 114, 154, 205, 230, 160, 166, 241, 100, 245, 129, 172, 63, 253, 65, 65, 170, 222, 32, 250, 166, 247, 205, 32, 234, 125, 253, 219, 60, 175, 118, 122, 94, 135, 123, 156, 141, 79, 153, 113, 11, 135, 104, 175, 79, 26, 1, 172, 253, 210, 82, 118, 227, 155, 199, 49, 63, 197, 251, 164, 247, 13, 35, 149, 151, 42, 2, 191, 117, 214, 161, 167, 80, 102, 36, 72, 26, 7, 148, 94, 158, 85, 227, 124, 154, 195, 74, 117, 170, 114, 128, 93, 75, 251, 41, 128, 11, 116, 13, 234, 70, 188, 114, 77, 247, 36, 158, 118, 255, 160, 110, 184, 139, 96, 73, 247, 141, 57, 125, 221, 14, 2, 164, 69, 251, 7, 117, 107, 186, 39, 144, 108, 223, 59, 62, 209, 207, 139, 233, 245, 59, 230, 155, 234, 91, 241, 227, 105, 145, 28, 215, 244, 136, 35, 215, 200, 142, 73, 133, 210, 223, 237, 103, 169, 92, 209, 234, 116, 181, 34, 192, 164, 66, 235, 82, 17, 112, 55, 225, 187, 179, 236, 203, 38, 123, 70, 203, 85, 29, 41, 200, 139, 132, 60, 1, 16, 127, 42, 247, 186, 69, 57, 213, 113, 98, 221, 138, 128, 122, 40, 51, 157, 230, 23, 114, 39, 21, 22, 17, 6, 71, 5, 223, 183, 213, 202, 33, 195, 62, 107, 53, 48, 224, 100, 75, 148, 4, 207, 243, 226, 89, 60, 62, 229, 43, 138, 247, 241, 248, 236, 56, 19, 227, 193, 140, 219, 200, 217, 69, 84, 99, 227, 95, 167, 143, 196, 42, 125, 132, 214, 232, 42, 83, 20, 251, 214, 125, 113, 174, 182, 191, 107, 87, 228, 8, 111, 244, 149, 97, 111, 150, 236, 186, 147, 214, 82, 221, 30, 54, 3, 170, 110, 236, 126, 78, 128, 143, 211, 105, 194, 218, 232, 111, 13, 34, 92, 11, 243, 48, 95, 103, 250, 15, 15, 36, 213, 59, 241, 21, 223, 160, 192, 198, 74, 44, 18, 89, 49, 29, 119, 35, 18, 130, 140, 156, 79, 80, 41, 16, 139, 41, 151, 235, 108, 125, 2, 107, 77, 86, 245, 89, 86, 21, 87, 140, 2, 218, 85, 162, 218, 118, 91, 68, 251, 223, 0, 166, 38, 144, 82, 247, 80, 72, 130, 5, 71, 95, 54, 235, 253, 20, 225, 124, 209, 62, 238, 245, 240, 226, 64, 180, 166, 255, 140, 92, 102, 254, 138, 245, 181, 99, 74, 80, 83, 163, 38, 31, 168, 201, 93, 229, 142, 3, 235, 138, 136, 83, 114, 63, 245, 201, 50, 95, 125, 118, 28, 95, 7, 65, 113, 58, 16, 226, 116, 64, 196, 73, 15, 226, 193, 66, 2, 213, 201, 213, 69, 113, 246, 248, 185, 58, 179, 172, 88, 231, 131, 54, 170, 117, 78, 1, 75, 155, 28, 120, 205, 12, 125, 16, 228, 101, 78, 81, 204, 202, 210, 49, 122, 254, 107, 202, 55, 80, 26, 220, 109, 7, 38, 219, 168, 113, 81, 24, 25, 49, 128, 176, 175, 67, 111, 79, 213, 74, 134, 229, 143, 214, 119, 55, 235, 186, 71, 222, 202, 190, 158, 178, 215, 36, 174, 164, 89, 232, 196, 24, 104, 87, 24, 238, 151, 252, 36, 137, 78, 18, 215, 104, 255, 4, 148, 32, 83, 41, 184, 57, 193, 23, 55, 206, 139, 137, 112, 215, 254, 225, 176, 179, 112, 208, 122, 213, 42, 36, 197, 229, 190, 221, 112, 86, 92, 168, 77, 188, 69, 241, 197, 72, 56, 63, 217, 151, 77, 176, 96, 20, 187, 100, 243, 115, 249, 101, 93, 22, 82, 140, 160, 190, 136, 116, 223, 252, 25, 123, 132, 52, 72, 127, 12, 143, 141, 243, 67, 166, 50, 164, 81, 214, 211, 197, 213, 105, 18, 107, 116, 235, 234, 190, 138, 95, 233, 90, 168, 131, 176, 171, 38, 186, 97, 118, 118, 20, 210, 198, 107, 43, 202, 212, 236, 240, 124, 255, 215, 191, 18, 186, 157, 198, 165, 164, 25, 123, 242, 217, 46, 236, 117, 112, 246, 131, 196, 62, 236, 123, 143, 64, 60, 75, 174, 20, 72, 120, 244, 193, 132, 247, 181, 64, 161, 64, 207, 94, 175, 253, 1, 140, 252, 136, 167, 115, 226, 22, 236, 35, 69, 147, 1, 244, 98, 32, 26, 254, 104, 243, 161, 82, 10, 32, 203, 58, 122, 14, 88, 211, 168, 92, 168, 184, 95, 233, 131, 232, 110, 244, 45, 20, 231, 157, 225, 210, 6, 63, 216, 31, 124, 38, 68, 178, 180, 2, 212, 176, 233, 195, 216, 91, 62, 153, 150, 195, 156, 174, 202, 80, 117, 43, 105, 162, 62, 218, 134, 236, 63, 50, 192, 60, 175, 78, 147, 98, 225, 169, 69, 127, 107, 55, 177, 4, 76, 52, 25, 208, 199, 81, 25, 240, 73, 132, 227, 70, 121, 134, 127, 101, 116, 21, 106, 29, 169, 14, 222, 129, 29, 119, 156, 252, 3, 171, 192, 56, 53, 96, 162, 96, 181, 212, 207, 77, 48, 129, 205, 252, 163, 46, 178, 3, 251, 127, 118, 197, 58, 236, 248, 150, 131, 214, 247, 191, 210, 234, 148, 79, 224, 10, 244, 128, 180, 73, 108, 114, 199, 230, 99, 70, 185, 138, 119, 113, 173, 242, 218, 192, 5, 62, 63, 37, 69, 153, 8, 128, 183, 115, 156, 49, 138, 139, 12, 247, 136, 47, 181, 2, 57, 204, 217, 71, 147, 192, 92, 15, 97, 150, 92, 64, 181, 190, 137, 58, 96, 72, 73, 181, 233, 29, 2, 17, 46, 117, 160, 101, 89, 151, 127, 252, 68, 99, 185, 105, 223, 203, 210, 206, 146, 63, 64, 134, 66, 103, 195, 200, 107, 205, 47, 205, 158, 247, 89, 244, 129, 91, 80, 90, 218, 245, 109, 140, 12, 209, 170, 79, 195, 106, 74, 115, 61, 110, 232, 14, 171, 213, 15, 206, 233, 194, 102, 89, 250, 128, 14, 2, 146, 8, 115, 60, 11, 119, 215, 40, 75, 80, 10, 92, 243, 88, 161, 248, 222, 254, 112, 74, 28, 96, 181, 208, 141, 4, 84, 157, 88, 100, 104, 82, 46, 63, 167, 199, 199, 73, 145, 100, 227, 228, 150, 170, 22, 131, 224, 34, 138, 37, 160, 241, 63, 179, 190, 40, 176, 132, 126, 81, 26, 159, 66, 105, 76, 146, 105, 82, 37, 119, 81, 111, 180, 234, 142, 173, 3, 90, 201, 254, 232, 234, 252, 60, 169, 138, 116, 252, 185, 148, 128, 236, 97, 123, 143, 159, 208, 11, 242, 71, 207, 223, 5, 143, 179, 226, 222, 219, 156, 11, 205, 45, 139, 49, 22, 93, 221, 118, 159, 157, 90, 113, 230, 126, 9, 1, 156, 140, 159, 142, 111, 233, 172, 100, 16, 92, 100, 86, 90, 120, 234, 121, 234, 159, 121, 66, 169, 134, 187, 88, 175, 255, 193, 126, 104, 157, 110, 228, 58, 243, 142, 61, 6, 14, 167, 139, 32, 58, 151, 207, 103, 176, 114, 186, 221, 156, 174, 80, 252, 164, 188, 254, 184, 27, 175, 119, 211, 222, 75, 158, 165, 3, 9, 107, 26, 20, 240, 130, 44, 243, 115, 90, 254, 27, 226, 17, 161, 111, 119, 109, 190, 166, 216, 47, 60, 85, 127, 89, 235, 223, 63, 179, 221, 149, 134, 219, 109, 151, 47, 184, 158, 111, 232, 102, 141, 240, 255, 51, 77, 46, 146, 201, 110, 81, 196, 87, 63, 205, 193, 218, 221, 63, 62, 76, 210, 227, 20, 66, 46, 98, 120, 43, 154, 209, 233, 99, 223, 207, 143, 163, 208, 213, 81, 162, 130, 138, 66, 199, 231, 246, 180, 194, 96, 213, 225, 90, 55, 128, 162, 174, 178, 33, 119, 34, 252, 156, 84, 241, 248, 52, 153, 8, 92, 160, 248, 113, 130, 34, 122, 196, 239, 144, 90, 33, 234, 123, 71, 137, 169, 174, 164, 84, 20, 234, 172, 106, 32, 168, 169, 156, 25, 161, 229, 149, 81, 2, 238, 32, 122, 128, 3, 77, 240, 61, 79, 226, 230, 233, 45, 123, 183, 97, 183, 18, 253, 199, 56, 226, 113, 144, 67, 32, 250, 211, 60, 118, 138, 6, 33, 194, 6, 246, 25, 190, 151, 23, 88, 33, 198, 17, 21, 90, 160, 43, 5, 133, 108, 152, 135, 58, 38, 2, 113, 112, 136, 92, 86, 206, 139, 4, 16, 17, 5, 65, 114, 112, 141, 184, 56, 193, 65, 66, 230, 182, 9, 153, 96, 193, 212, 228, 47, 85, 247, 2, 237, 67, 145, 29, 52, 218, 170, 203, 238, 244, 4, 147, 147, 129, 237, 157, 163, 98, 21, 33, 210, 171, 163, 11, 76, 78, 180, 203, 6, 172, 231, 10, 77, 189, 245, 169, 229, 111, 44, 14, 224, 192, 238, 216, 216, 20, 84, 227, 60, 110, 58, 173, 143, 128, 195, 117, 168, 134, 92, 120, 63, 148, 206, 241, 99, 156, 201, 193, 179, 209, 218, 203, 121, 185, 111, 202, 232, 27, 132, 209, 55, 209, 76, 222, 191, 75, 237, 59, 62, 21, 178, 239, 158, 235, 73, 100, 140, 4, 186, 160, 196, 147, 115, 195, 78, 148, 214, 186, 67, 251, 132, 176, 14, 156, 82, 149, 245, 109, 185, 13, 229, 49, 171, 222, 223, 254, 38, 145, 212, 189, 139, 196, 94, 178, 32, 0, 234, 191, 59, 208, 76, 107, 167, 147, 184, 74, 44, 28, 93, 118, 198, 27, 219, 226, 131, 85, 197, 104, 254, 0, 99, 171, 190, 83, 214, 198, 25, 38, 156, 235, 91, 130, 77, 64, 233, 96, 217, 191, 199, 182, 98, 161, 149, 131, 154, 5, 155, 13, 54, 134, 158, 81, 248, 126, 123, 43, 36, 53, 34, 92, 6, 20, 133, 60, 108, 129, 6, 129, 30, 254, 23, 243, 244, 133, 169, 26, 213, 92, 160, 202, 177, 193, 160, 252, 47, 244, 173, 110, 188, 87, 158, 33, 38, 13, 154, 179, 51, 252, 172, 110, 144, 172, 178, 39, 110, 93, 126, 46, 38, 129, 35, 152, 52, 107, 153, 67, 174, 161, 234, 186, 57, 237, 138, 148, 57, 1, 220, 72, 87, 57, 178, 132, 174, 106, 126, 123, 127, 85, 37, 7, 199, 199, 220, 250, 186, 105, 90, 203, 54, 197, 179, 105, 119, 209, 113, 232, 78, 253, 133, 168, 199, 204, 2, 145, 241, 167, 29, 25, 63, 53, 249, 110, 15, 201, 212, 244, 103, 203, 115, 114, 153, 156, 207, 166, 177, 71, 152, 225, 222, 233, 218, 233, 83, 85, 197, 168, 212, 104, 142, 61, 221, 68, 91, 20, 229, 152, 50, 232, 26, 203, 21, 76, 105, 202, 166, 146, 73, 111, 160, 3, 18, 143, 189, 90, 193, 108, 219, 41, 155, 99, 91, 244, 238, 38, 250, 100, 163, 225, 237, 92, 168, 83, 176, 206, 53, 113, 155, 182, 19, 163, 201, 204, 60, 104, 197, 237, 7, 184, 7, 2, 111, 254, 25, 135, 17, 110, 7, 17, 252, 144, 20, 87, 40, 48, 53, 186, 14, 166, 237, 167, 20, 227, 189, 104, 200, 41, 98, 27, 122, 223, 241, 211, 219, 189, 255, 50, 16, 255, 107, 115, 166, 114, 254, 109, 38, 208, 155, 158, 109, 64, 222, 80, 32, 180, 137, 38, 119, 251, 240, 52, 26, 178, 229, 37, 77, 45, 18, 161, 136, 80, 226, 166, 59, 139, 120, 54, 145, 51, 49, 157, 178, 7, 154, 63, 228, 76, 38, 161, 143, 14, 142, 206, 222, 26, 255, 76, 149, 148, 38, 143, 97, 235, 104, 227, 51, 153, 112, 248, 204, 56, 123, 56, 149, 12, 180, 5, 92, 120, 163, 154, 99, 194, 22, 171, 225, 224, 97, 243, 233, 57, 51, 192, 97, 78, 186, 39, 108, 120, 204, 187, 243, 169, 248, 240, 205, 194, 28, 40, 92, 77, 51, 25, 113, 244, 238, 69, 90, 162, 144, 163, 113, 60, 99, 131, 204, 143, 103, 111, 93, 147, 93, 67, 62, 52, 204, 161, 111, 44, 222, 52, 108, 8, 24, 30, 41, 108, 214, 215, 193, 65, 39, 74, 82, 158, 132, 182, 119, 189, 74, 223, 158, 95, 15, 6, 186, 115, 150, 191, 92, 244, 12, 236, 90, 85, 128, 253, 50, 221, 219, 61, 202, 120, 235, 128, 80, 102, 167, 155, 219, 109, 47, 9, 130, 221, 67, 162, 144, 77, 250, 51, 214, 114, 10, 151, 235, 220, 117, 57, 200, 38, 97, 41, 208, 157, 236, 34, 4, 168, 210, 45, 209, 197, 33, 230, 214, 152, 134, 180, 175, 163, 104, 125, 92, 45, 63, 33, 100, 219, 51, 25, 79, 144, 20, 96, 49, 113, 169, 237, 93, 225, 51, 73, 39, 198, 110, 242, 105, 75, 239, 187, 212, 176, 30, 239, 99, 195, 217, 168, 187, 198, 132, 93, 184, 13, 120, 52, 200, 107, 94, 54, 219, 24, 118, 227, 47, 117, 183, 178, 143, 201, 156, 243, 119, 183, 156, 199, 148, 46, 51, 0, 49, 59, 201, 131, 118, 247, 200, 180, 108, 109, 50, 34, 54, 178, 166, 188, 69, 180, 146, 32, 164, 159, 103, 126, 77, 174, 62, 255, 82, 41, 232, 225, 123, 25, 207, 238, 30, 55, 7, 212, 227, 121, 60, 187, 27, 230, 105, 107, 139, 78, 185, 23, 219, 206, 228, 231, 156, 222, 106, 58, 111, 97, 157, 90, 98, 0, 214, 224, 25, 88, 131, 8, 208, 226, 22, 33, 227, 45, 191, 72, 28, 38, 147, 249, 56, 185, 55, 124, 87, 240, 238, 124, 10, 214, 83, 46, 106, 142, 44, 236, 202, 53, 228, 33, 181, 251, 177, 77, 152, 248, 44, 66, 247, 201, 196, 227, 241, 252, 124, 62, 149, 57, 232, 90, 243, 54, 99, 32, 182, 122, 209, 60, 234, 103, 77, 10, 187, 230, 94, 22, 247, 124, 184, 115, 35, 11, 130, 165, 94, 113, 38, 86, 235, 42, 253, 146, 154, 72, 146, 123, 81, 237, 128, 66, 20, 188, 121, 152, 158, 156, 86, 119, 135, 65, 187, 155, 146, 133, 233, 230, 39, 59, 104, 191, 124, 238, 5, 104, 27, 34, 159, 228, 245, 120, 120, 99, 131, 242, 240, 83, 161, 102, 55, 54, 238, 34, 11, 143, 188, 57, 115, 219, 4, 155, 173, 146, 237, 208, 3, 123, 31, 55, 20, 90, 214, 176, 123, 207, 122, 98, 174, 143, 2, 164, 228, 15, 200, 76, 173, 216, 212, 194, 222, 226, 201, 192, 86, 172, 45, 94, 1, 121, 18, 65, 221, 140, 98, 233, 135, 164, 41, 91, 239, 153, 76, 132, 75, 203, 55, 164, 221, 37, 133, 195, 185, 119, 173, 98, 56, 83, 174, 250, 116, 141, 52, 247, 22, 226, 50, 141, 111, 27, 180, 101, 70, 223, 122, 164, 157, 228, 190, 99, 153, 249, 209, 205, 87, 207, 68, 242, 12, 167, 203, 108, 239, 192, 34, 201, 112, 69, 3, 79, 141, 210, 227, 33, 14, 192, 29, 19, 2, 240, 167, 180, 186, 72, 203, 68, 112, 61, 131, 178, 203, 13, 26, 3, 75, 178, 186, 168, 105, 214, 140, 146, 104, 158, 244, 252, 3, 31, 35, 233, 157, 117, 227, 83, 147, 47, 100, 128, 32, 76, 124, 188, 58, 222, 161, 223, 61, 202, 132, 115, 207, 204, 147, 240, 207, 27, 62, 182, 27, 18, 231, 252, 252, 254, 216, 74, 37, 235, 204, 125, 90, 112, 126, 170, 189, 140, 154, 173, 12, 147, 235, 213, 98, 40, 185, 199, 209, 214, 92, 7, 62, 243, 219, 235, 111, 242, 23, 57, 67, 86, 221, 207, 59, 229, 63, 32, 216, 8, 37, 3, 201, 103, 80, 137, 188, 52, 140, 26, 203, 109, 246, 182, 204, 106, 2, 236, 218, 51, 44, 13, 202, 211, 118, 134, 53, 133, 153, 52, 168, 66, 113, 22, 101, 245, 108, 170, 110, 16, 228, 32, 100, 40, 173, 14, 10, 35, 23, 185, 172, 168, 41, 222, 30, 75, 12, 105, 179, 34, 244, 26, 144, 102, 200, 181, 190, 232, 22, 152, 168, 55, 232, 57, 76, 55, 244, 51, 221, 33, 191, 224, 79, 213, 53, 28, 7, 241, 171, 118, 111, 176, 71, 151, 124, 247, 39, 206, 24, 179, 126, 165, 25, 102, 40, 157, 238, 228, 144, 164, 69, 245, 17, 1, 193, 119, 104, 128, 190, 173, 217, 38, 205, 97, 72, 243, 205, 223, 243, 78, 244, 223, 39, 39, 105, 102, 217, 50, 109, 146, 80, 175, 6, 195, 187, 174, 107, 209, 224, 152, 121, 129, 93, 189, 81, 35, 123, 226, 137, 159, 111, 19, 113, 170, 98, 206, 106, 194, 116, 53, 24, 52, 49, 210, 128, 53, 29, 37, 88, 140, 245, 181, 33, 182, 20, 253, 79, 82, 228, 7, 217, 193, 188, 58, 56, 254, 137, 77, 160, 147, 82, 215, 150, 53, 127, 210, 209, 1, 180, 41, 253, 154, 84, 80, 198, 195, 79, 64, 33, 98, 117, 113, 154, 233, 114, 252, 151, 204, 17, 76, 172, 24, 81, 49, 104, 199, 152, 174, 172, 211, 42, 205, 246, 140, 44, 166, 33, 104, 92, 18, 193, 164, 42, 159, 139, 217, 233, 53, 239, 73, 31, 57, 238, 132, 44, 148, 76, 235, 184, 119, 223, 98, 240, 106, 68, 93, 115, 143, 173, 141, 76, 195, 251, 229, 238, 188, 82, 217, 159, 61, 60, 220, 45, 218, 4, 254, 65, 150, 22, 197, 187, 40, 112, 41, 178, 251, 226, 50, 107, 179, 157, 106, 134, 36, 100, 173, 38, 210, 197, 222, 197, 96, 245, 13, 116, 123, 179, 213, 29, 228, 44, 185, 240, 92, 157, 35, 110, 203, 17, 200, 109, 160, 97, 179, 18, 230, 183, 138, 89, 66, 84, 38, 193, 97, 148, 194, 226, 165, 198, 102, 37, 28, 192, 188, 91, 137, 188, 239, 183, 69, 1, 34, 30, 226, 120, 121, 148, 222, 174, 237, 90, 104, 136, 168, 173, 89, 200, 249, 148, 138, 202, 41, 110, 184, 140, 166, 167, 63, 83, 100, 161, 21, 158, 34, 163, 0, 230, 88, 242, 149, 99, 138, 15, 174, 40, 47, 195, 186, 167, 156, 4, 127, 198, 175, 75, 97, 196, 230, 110, 3, 88, 34, 81, 18, 19, 155, 18, 205, 122, 172, 79, 124, 118, 110, 107, 159, 237, 86, 126, 235, 12, 246, 172, 224, 98, 220, 59, 179, 241, 217, 98, 131, 29, 250, 115, 7, 55, 217, 149, 63, 202, 231, 65, 186, 131, 59, 237, 48, 10, 245, 60, 247, 159, 176, 227, 174, 251, 121, 87, 119, 221, 235, 184, 242, 118, 109, 189, 107, 82, 99, 174, 251, 202, 148, 225, 28, 254, 249, 119, 83, 135, 107, 254, 12, 165, 54, 162, 76, 199, 137, 35, 160, 61, 191, 20, 141, 248, 69, 34, 252, 84, 112, 153, 207, 139, 49, 35, 246, 121, 60, 59, 206, 232, 202, 186, 54, 193, 239, 158, 107, 2, 224, 120, 224, 189, 32, 47, 62, 212, 137, 141, 247, 8, 231, 193, 206, 159, 188, 160, 13, 224, 9, 124, 188, 23, 182, 218, 252, 207, 139, 34, 206, 104, 226, 254, 161, 236, 45, 189, 135, 67, 182, 31, 153, 59, 108, 200, 124, 108, 62, 59, 167, 7, 223, 72, 82, 48, 216, 74, 157, 204, 75, 116, 155, 11, 152, 122, 156, 202, 158, 227, 81, 250, 38, 39, 115, 62, 138, 214, 93, 181, 237, 115, 247, 51, 94, 141, 217, 180, 33, 165, 195, 52, 250, 203, 208, 213, 16, 2, 103, 74, 36, 14, 94, 145, 194, 58, 156, 71, 135, 95, 222, 141, 44, 47, 15, 150, 160, 200, 249, 35, 249, 24, 217, 196, 98, 61, 114, 24, 90, 93, 216, 12, 255, 136, 101, 41, 33, 227, 239, 68, 106, 252, 55, 152, 203, 178, 216, 97, 26, 48, 17, 37, 252, 29, 93, 174, 198, 86, 244, 150, 173, 64, 235, 192, 233, 249, 186, 195, 30, 123, 131, 104, 207, 56, 185, 197, 191, 54, 78, 64, 241, 79, 55, 33, 182, 208, 37, 175, 157, 189, 53, 176, 62, 234, 39, 229, 186, 83, 85, 168, 99, 184, 121, 96, 130, 99, 242, 58, 30, 159, 45, 125, 80, 58, 18, 80, 180, 139, 47, 41, 146, 204, 110, 150, 180, 89, 202, 211, 9, 96, 108, 117, 3, 154, 229, 119, 90, 146, 203, 74, 46, 2, 62, 200, 125, 153, 119, 253, 77, 206, 227, 127, 149, 118, 165, 98, 104, 28, 103, 130, 147, 68, 109, 116, 61, 151, 219, 115, 36, 102, 254, 3, 46, 18, 104, 59, 174, 33, 38, 161, 104, 29, 241, 139, 27, 208, 33, 37, 94, 147, 229, 71, 175, 43, 146, 43, 85, 26, 123, 188, 166, 171, 60, 34, 102, 162, 195, 180, 86, 220, 135, 162, 173, 143, 254, 74, 237, 114, 191, 214, 139, 244, 76, 100, 191, 165, 154, 198, 90, 213, 41, 39, 134, 174, 130, 121, 100, 49, 82, 119, 246, 209, 235, 182, 137, 175, 190, 142, 206, 157, 169, 76, 105, 92, 79, 97, 124, 240, 192, 80, 215, 239, 13, 229, 214, 194, 193, 113, 31, 89, 217, 130, 176, 238, 117, 173, 55, 101, 29, 100, 201, 197, 178, 71, 71, 128, 20, 196, 193, 70, 237, 153, 237, 37, 22, 5, 9, 113, 208, 4, 213, 49, 153, 188, 83, 177, 38, 167, 188, 73, 161, 64, 181, 10, 100, 20, 103, 245, 206, 185, 131, 196, 58, 74, 142, 238, 115, 244, 114, 15, 175, 51, 224, 217, 205, 205, 85, 196, 198, 127, 147, 218, 166, 130, 109, 40, 60, 176, 134, 229, 82, 38, 119, 97, 237, 169, 186, 36, 169, 153, 214, 140, 71, 111, 53, 138, 106, 19, 51, 144, 19, 42, 19, 57, 210, 66, 142, 254, 151, 166, 11, 88, 157, 210, 126, 88, 25, 56, 236, 94, 64, 106, 109, 40, 210, 115, 172, 27, 120, 187, 217, 144, 78, 234, 103, 110, 141, 253, 28, 87, 241, 107, 121, 96, 92, 103, 92, 73, 215, 215, 197, 150, 195, 166, 73, 27, 136, 88, 73, 20, 163, 172, 132, 204, 141, 142, 188, 228, 214, 108, 195, 76, 95, 141, 78, 227, 130, 88, 57, 93, 239, 67, 8, 212, 111, 211, 184, 45, 190, 35, 6, 17, 222, 5, 14, 132, 154, 12, 9, 70, 123, 48, 214, 8, 230, 7, 232, 120, 54, 212, 119, 170, 60, 160, 4, 223, 228, 163, 188, 168, 146, 73, 159, 223, 79, 83, 36, 199, 153, 57, 228, 175, 95, 181, 91, 175, 24, 8, 237, 215, 44, 176, 219, 108, 170, 209, 53, 239, 167, 241, 122, 184, 1, 21, 214, 8, 118, 12, 27, 149, 1, 159, 202, 33, 133, 227, 180, 158, 154, 80, 44, 39, 109, 142, 105, 254, 93, 153, 67, 52, 203, 46, 166, 140, 37, 110, 52, 178, 225, 95, 76, 140, 95, 198, 179, 230, 235, 124, 216, 84, 137, 200, 201, 109, 13, 121, 157, 15, 251, 2, 73, 137, 240, 180, 22, 47, 239, 58, 31, 166, 230, 207, 219, 221, 230, 227, 42, 59, 168, 27, 230, 167, 135, 223, 49, 225, 148, 253, 167, 58, 207, 167, 101, 229, 189, 64, 172, 179, 3, 141, 23, 191, 85, 66, 255, 24, 170, 251, 40, 45, 242, 142, 254, 83, 111, 75, 250, 255, 46, 4, 227, 16 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 20960; + return 19520; } uint32_t GetRawScriptsSize() { - return 144873; + return 134068; } } // selfhosted } // js diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/js-confdefs.h b/src/third_party/mozjs/platform/ppc64le/linux/build/js-confdefs.h index c255df145ef..c8b0f3821f8 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/js-confdefs.h @@ -9,9 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -26,7 +31,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -68,12 +72,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -82,6 +84,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "ppc64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_LINUX 1 diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/ppc64le/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/ppc64le/linux/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/js-confdefs.h b/src/third_party/mozjs/platform/ppc64le/linux/include/js-confdefs.h index c255df145ef..c8b0f3821f8 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/js-confdefs.h @@ -9,9 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -26,7 +31,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -68,12 +72,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -82,6 +84,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "ppc64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_LINUX 1 diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/js-config.h b/src/third_party/mozjs/platform/ppc64le/linux/include/js-config.h index e6a4e862c32..75330b2452d 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/js-config.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +/* #undef XP_WIN */ +#define XP_UNIX 1 +/* #undef XP_DARWIN */ + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/ppc64le/linux/include/selfhosted.out.h b/src/third_party/mozjs/platform/ppc64le/linux/include/selfhosted.out.h index 61dcac32173..f92431e839c 100644 --- a/src/third_party/mozjs/platform/ppc64le/linux/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/ppc64le/linux/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 237, 125, 253, 119, 27, 55, 174, 232, 239, 254, 43, 38, 58, 189, 173, 188, 150, 189, 150, 147, 126, 108, 236, 164, 235, 186, 73, 215, 111, 147, 56, 199, 78, 119, 207, 185, 126, 57, 185, 19, 105, 236, 204, 90, 214, 168, 51, 82, 28, 183, 205, 251, 219, 31, 65, 130, 36, 192, 143, 153, 145, 44, 39, 182, 111, 114, 78, 235, 209, 12, 9, 130, 32, 0, 130, 32, 8, 158, 204, 198, 131, 105, 94, 140, 147, 113, 118, 241, 230, 48, 27, 20, 229, 176, 187, 154, 252, 177, 146, 36, 101, 54, 157, 149, 227, 164, 154, 14, 223, 28, 188, 253, 79, 54, 152, 190, 25, 148, 89, 58, 205, 186, 227, 217, 104, 180, 186, 189, 242, 113, 229, 68, 215, 125, 85, 252, 84, 20, 163, 44, 29, 119, 223, 179, 186, 247, 238, 189, 119, 202, 189, 152, 157, 191, 205, 74, 167, 216, 26, 47, 117, 148, 158, 103, 255, 74, 71, 179, 236, 191, 179, 178, 232, 126, 232, 37, 151, 172, 244, 135, 228, 209, 163, 71, 201, 101, 242, 231, 159, 73, 247, 67, 114, 79, 60, 127, 72, 190, 254, 90, 188, 128, 199, 75, 142, 216, 47, 217, 244, 121, 54, 125, 87, 12, 187, 255, 234, 37, 47, 21, 152, 237, 109, 241, 191, 247, 105, 153, 64, 169, 228, 81, 242, 175, 227, 151, 175, 225, 85, 126, 146, 116, 247, 171, 23, 162, 115, 7, 229, 175, 227, 97, 118, 146, 143, 179, 97, 23, 10, 173, 170, 138, 6, 131, 153, 254, 10, 213, 62, 98, 213, 123, 251, 213, 94, 58, 26, 165, 111, 71, 25, 175, 244, 234, 93, 89, 92, 188, 186, 156, 100, 79, 202, 178, 40, 187, 253, 173, 94, 50, 21, 191, 138, 19, 137, 192, 170, 134, 129, 176, 225, 29, 235, 194, 126, 245, 178, 44, 38, 89, 57, 189, 252, 103, 118, 217, 77, 203, 211, 217, 121, 54, 158, 42, 224, 208, 11, 128, 37, 122, 129, 32, 245, 247, 109, 11, 81, 21, 16, 180, 233, 84, 211, 50, 31, 159, 118, 128, 114, 228, 229, 229, 249, 219, 98, 212, 225, 35, 48, 201, 6, 121, 86, 237, 21, 99, 81, 101, 54, 152, 10, 180, 139, 183, 255, 233, 37, 162, 219, 233, 108, 52, 37, 239, 29, 146, 194, 43, 129, 140, 40, 188, 49, 176, 133, 52, 117, 213, 87, 209, 168, 33, 160, 67, 88, 31, 190, 67, 97, 197, 136, 18, 80, 140, 190, 223, 126, 215, 75, 58, 133, 44, 247, 77, 149, 124, 67, 208, 248, 38, 153, 32, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 154, 229, 163, 105, 62, 62, 146, 68, 233, 118, 42, 69, 136, 206, 106, 13, 135, 84, 46, 123, 212, 247, 98, 159, 145, 213, 86, 134, 111, 149, 228, 97, 75, 87, 248, 119, 152, 77, 138, 114, 250, 107, 149, 158, 102, 123, 197, 108, 60, 21, 210, 227, 55, 208, 75, 238, 203, 46, 169, 102, 172, 236, 234, 134, 29, 26, 201, 50, 253, 7, 61, 249, 183, 243, 247, 191, 99, 55, 13, 125, 18, 193, 73, 134, 132, 132, 130, 29, 81, 193, 19, 48, 11, 118, 99, 99, 67, 240, 95, 165, 112, 159, 150, 151, 216, 135, 129, 16, 139, 167, 88, 161, 11, 234, 68, 255, 120, 147, 78, 38, 163, 203, 158, 131, 93, 207, 178, 71, 47, 145, 240, 100, 47, 4, 152, 233, 224, 93, 210, 205, 28, 106, 103, 186, 143, 219, 46, 98, 187, 167, 167, 101, 118, 42, 52, 214, 18, 176, 227, 176, 150, 134, 226, 62, 140, 231, 56, 29, 45, 1, 67, 6, 106, 57, 8, 2, 167, 155, 134, 69, 21, 242, 105, 175, 152, 92, 254, 156, 78, 83, 212, 77, 130, 121, 186, 83, 209, 78, 54, 237, 37, 85, 49, 43, 7, 89, 47, 201, 62, 12, 70, 179, 97, 54, 220, 159, 102, 231, 21, 209, 19, 219, 53, 162, 36, 171, 58, 242, 68, 69, 245, 164, 44, 206, 133, 180, 190, 42, 80, 17, 96, 5, 173, 126, 206, 178, 75, 16, 102, 31, 185, 131, 82, 16, 251, 224, 98, 44, 84, 168, 69, 20, 128, 185, 104, 106, 220, 20, 36, 33, 140, 114, 178, 11, 226, 115, 34, 148, 89, 23, 90, 205, 5, 254, 98, 82, 74, 54, 183, 241, 113, 71, 34, 178, 49, 202, 198, 167, 211, 119, 248, 114, 109, 77, 67, 65, 68, 69, 5, 40, 117, 44, 191, 190, 222, 54, 58, 0, 197, 254, 222, 187, 180, 18, 8, 3, 34, 30, 41, 191, 254, 26, 11, 121, 156, 129, 19, 181, 150, 227, 253, 234, 201, 88, 76, 7, 37, 76, 74, 186, 191, 2, 224, 170, 172, 110, 85, 204, 207, 146, 252, 132, 98, 151, 134, 70, 178, 121, 168, 120, 44, 158, 94, 19, 29, 243, 113, 165, 150, 27, 126, 29, 159, 8, 69, 154, 149, 98, 80, 57, 95, 16, 70, 184, 57, 60, 128, 22, 205, 231, 30, 250, 69, 135, 115, 137, 35, 89, 204, 96, 130, 97, 246, 150, 249, 150, 143, 199, 230, 155, 249, 218, 57, 41, 138, 142, 164, 11, 83, 29, 187, 101, 153, 94, 62, 121, 159, 149, 151, 178, 87, 111, 211, 193, 217, 201, 56, 177, 86, 203, 1, 29, 193, 233, 187, 188, 50, 227, 39, 72, 39, 191, 61, 147, 36, 236, 30, 32, 45, 205, 240, 236, 162, 133, 83, 97, 129, 85, 57, 86, 155, 49, 107, 224, 219, 94, 178, 41, 12, 2, 137, 207, 134, 32, 228, 180, 0, 211, 103, 35, 3, 212, 172, 25, 224, 26, 112, 22, 231, 58, 51, 238, 103, 97, 46, 159, 79, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 68, 135, 124, 180, 31, 39, 253, 228, 71, 57, 79, 225, 167, 110, 127, 53, 121, 200, 141, 75, 195, 104, 103, 138, 201, 206, 4, 131, 9, 122, 136, 7, 203, 84, 146, 103, 197, 224, 36, 7, 150, 15, 100, 127, 0, 29, 97, 35, 76, 5, 104, 195, 85, 22, 69, 49, 109, 244, 146, 131, 227, 179, 215, 130, 53, 196, 3, 97, 34, 59, 242, 233, 168, 202, 182, 241, 237, 71, 194, 48, 214, 182, 44, 103, 25, 140, 251, 145, 152, 202, 170, 253, 241, 40, 31, 3, 249, 158, 1, 203, 153, 38, 45, 43, 8, 162, 112, 6, 57, 42, 206, 179, 155, 201, 31, 149, 192, 236, 110, 179, 199, 149, 185, 67, 141, 125, 13, 115, 32, 251, 180, 224, 14, 224, 3, 143, 57, 158, 22, 229, 147, 116, 240, 238, 102, 242, 199, 137, 66, 238, 238, 178, 200, 124, 236, 177, 29, 26, 127, 130, 71, 11, 30, 192, 225, 246, 216, 224, 121, 58, 185, 153, 44, 112, 158, 78, 110, 254, 240, 67, 237, 93, 89, 27, 196, 12, 151, 245, 202, 141, 115, 208, 3, 66, 173, 94, 133, 73, 160, 138, 32, 195, 36, 27, 74, 127, 13, 172, 163, 23, 96, 155, 160, 217, 178, 43, 139, 16, 224, 97, 30, 219, 109, 197, 91, 130, 135, 124, 245, 34, 237, 211, 155, 201, 90, 202, 118, 190, 237, 220, 181, 25, 224, 173, 94, 50, 45, 230, 231, 177, 51, 205, 94, 192, 59, 154, 105, 90, 78, 98, 170, 110, 96, 26, 11, 51, 221, 180, 88, 91, 211, 149, 12, 127, 6, 167, 183, 118, 172, 167, 216, 204, 227, 190, 195, 108, 56, 27, 220, 80, 219, 167, 148, 184, 125, 42, 238, 83, 42, 7, 127, 164, 131, 193, 236, 124, 54, 74, 137, 211, 48, 200, 153, 186, 93, 82, 94, 128, 225, 204, 170, 60, 30, 153, 176, 65, 8, 119, 73, 10, 82, 154, 36, 201, 20, 112, 247, 104, 179, 197, 252, 105, 18, 209, 151, 101, 86, 9, 208, 162, 33, 98, 24, 15, 11, 102, 85, 185, 220, 155, 208, 106, 212, 98, 74, 146, 183, 66, 80, 206, 28, 14, 75, 46, 222, 9, 138, 37, 221, 181, 53, 20, 143, 85, 187, 58, 188, 167, 33, 205, 135, 58, 39, 145, 16, 160, 181, 181, 215, 108, 29, 219, 94, 20, 57, 168, 144, 236, 153, 206, 17, 33, 52, 239, 172, 75, 202, 188, 34, 16, 237, 75, 57, 65, 88, 250, 145, 15, 248, 20, 158, 10, 24, 239, 184, 75, 81, 37, 111, 135, 249, 233, 187, 233, 23, 161, 83, 66, 7, 253, 90, 79, 250, 95, 68, 143, 139, 222, 250, 250, 89, 242, 248, 17, 78, 94, 203, 149, 188, 245, 117, 95, 242, 30, 171, 201, 112, 125, 253, 142, 10, 222, 211, 124, 60, 236, 78, 4, 119, 231, 3, 97, 22, 220, 32, 129, 19, 4, 25, 198, 197, 205, 96, 60, 143, 180, 145, 74, 159, 110, 241, 22, 177, 143, 98, 214, 145, 193, 177, 206, 56, 194, 129, 85, 95, 151, 177, 182, 19, 180, 14, 24, 224, 227, 225, 62, 120, 64, 191, 176, 199, 53, 175, 237, 155, 249, 32, 232, 233, 209, 92, 16, 100, 128, 245, 126, 235, 145, 151, 131, 236, 13, 63, 56, 232, 255, 157, 139, 145, 29, 219, 29, 2, 241, 32, 254, 100, 227, 97, 226, 237, 17, 47, 206, 19, 240, 189, 204, 132, 122, 202, 223, 103, 175, 100, 75, 178, 40, 236, 151, 157, 138, 5, 160, 106, 220, 148, 132, 229, 201, 138, 234, 61, 171, 178, 147, 108, 34, 89, 126, 148, 33, 17, 207, 211, 233, 187, 55, 231, 233, 7, 57, 173, 173, 57, 165, 97, 237, 131, 165, 31, 146, 210, 162, 171, 110, 57, 109, 226, 81, 36, 143, 128, 12, 12, 71, 73, 24, 83, 78, 109, 128, 48, 36, 85, 149, 150, 56, 30, 41, 50, 55, 161, 136, 197, 66, 24, 62, 145, 35, 36, 199, 137, 238, 230, 139, 102, 161, 165, 135, 4, 243, 76, 10, 62, 226, 45, 184, 100, 228, 32, 14, 144, 90, 162, 45, 138, 54, 35, 45, 11, 81, 148, 7, 176, 103, 46, 144, 101, 165, 21, 38, 235, 184, 133, 162, 12, 161, 105, 97, 52, 136, 36, 240, 14, 176, 194, 215, 95, 195, 255, 119, 20, 201, 215, 20, 48, 45, 32, 184, 15, 69, 63, 105, 123, 42, 81, 171, 92, 241, 63, 239, 3, 90, 25, 234, 237, 99, 106, 12, 153, 150, 93, 51, 230, 224, 120, 90, 188, 150, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 202, 226, 220, 184, 81, 200, 174, 175, 235, 183, 211, 194, 62, 75, 76, 244, 207, 143, 174, 225, 246, 25, 209, 93, 91, 179, 232, 218, 103, 31, 93, 171, 147, 14, 66, 230, 199, 104, 36, 84, 164, 156, 228, 42, 148, 171, 205, 107, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 89, 153, 202, 182, 217, 156, 6, 179, 149, 232, 196, 123, 109, 157, 68, 89, 64, 249, 162, 36, 35, 236, 79, 179, 50, 53, 129, 76, 103, 96, 144, 152, 65, 207, 229, 183, 108, 168, 134, 157, 114, 128, 40, 108, 104, 144, 35, 4, 241, 253, 69, 118, 193, 129, 202, 66, 191, 142, 171, 244, 36, 19, 83, 226, 161, 88, 44, 148, 239, 179, 225, 209, 168, 152, 118, 117, 53, 105, 102, 240, 150, 90, 213, 234, 107, 71, 90, 83, 193, 45, 236, 214, 182, 165, 134, 254, 232, 203, 133, 198, 252, 69, 246, 97, 218, 181, 148, 16, 253, 5, 189, 37, 248, 94, 235, 66, 27, 116, 5, 180, 144, 65, 119, 170, 208, 47, 179, 180, 28, 190, 42, 60, 226, 174, 174, 70, 54, 207, 121, 180, 2, 242, 2, 88, 84, 12, 132, 10, 215, 219, 63, 249, 119, 41, 93, 191, 122, 13, 2, 40, 233, 231, 142, 215, 131, 142, 252, 194, 172, 170, 84, 160, 168, 40, 246, 139, 67, 49, 201, 0, 155, 68, 48, 170, 217, 8, 6, 253, 15, 197, 80, 15, 105, 232, 204, 176, 24, 139, 23, 114, 205, 9, 27, 220, 138, 36, 105, 160, 131, 0, 99, 3, 74, 179, 181, 38, 118, 92, 125, 166, 216, 233, 184, 129, 26, 12, 251, 148, 241, 206, 255, 153, 75, 185, 53, 229, 133, 144, 222, 223, 122, 42, 180, 164, 95, 113, 139, 170, 44, 141, 243, 126, 245, 178, 168, 170, 252, 237, 232, 18, 9, 11, 166, 234, 80, 18, 178, 155, 26, 155, 79, 233, 184, 104, 73, 84, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 31, 105, 245, 115, 54, 77, 7, 239, 178, 225, 79, 179, 147, 19, 161, 102, 82, 230, 148, 117, 173, 243, 239, 127, 8, 57, 97, 233, 84, 226, 232, 229, 148, 234, 101, 109, 186, 43, 114, 63, 150, 62, 15, 221, 90, 88, 156, 20, 115, 144, 136, 144, 57, 7, 183, 6, 170, 16, 100, 133, 199, 26, 142, 173, 196, 204, 140, 173, 32, 98, 223, 225, 167, 247, 184, 170, 75, 89, 164, 72, 176, 93, 15, 214, 22, 93, 31, 78, 210, 28, 212, 150, 2, 211, 51, 240, 94, 111, 135, 90, 131, 194, 53, 45, 109, 43, 253, 194, 170, 72, 112, 68, 239, 232, 26, 45, 22, 8, 84, 140, 233, 26, 225, 43, 249, 85, 46, 64, 43, 30, 143, 18, 82, 234, 82, 61, 72, 178, 202, 38, 247, 210, 113, 49, 22, 171, 155, 209, 139, 244, 60, 235, 82, 80, 98, 165, 39, 145, 174, 58, 222, 130, 228, 201, 120, 90, 230, 237, 27, 219, 90, 245, 181, 170, 12, 45, 106, 89, 127, 51, 80, 31, 4, 122, 183, 186, 28, 15, 186, 41, 252, 95, 134, 123, 201, 77, 176, 147, 49, 53, 87, 122, 82, 29, 138, 133, 97, 216, 134, 217, 35, 42, 92, 175, 23, 36, 212, 189, 81, 81, 205, 74, 201, 81, 240, 51, 129, 165, 241, 99, 194, 38, 176, 219, 150, 143, 1, 170, 106, 242, 30, 181, 16, 172, 204, 235, 98, 194, 56, 166, 107, 98, 89, 135, 8, 115, 96, 69, 252, 170, 56, 146, 193, 90, 186, 172, 235, 231, 155, 85, 2, 238, 46, 118, 93, 79, 182, 150, 20, 129, 0, 221, 148, 22, 198, 48, 93, 133, 101, 8, 150, 163, 182, 147, 112, 131, 78, 151, 29, 244, 142, 106, 11, 71, 90, 190, 23, 10, 122, 246, 221, 10, 126, 205, 58, 229, 248, 125, 159, 80, 212, 82, 105, 213, 213, 152, 220, 240, 14, 117, 162, 150, 196, 185, 75, 93, 210, 203, 163, 122, 242, 134, 91, 115, 72, 102, 173, 254, 48, 216, 8, 237, 34, 212, 59, 138, 17, 111, 126, 242, 89, 196, 62, 18, 70, 104, 51, 194, 96, 38, 181, 238, 136, 222, 68, 229, 129, 225, 123, 171, 201, 143, 6, 143, 110, 32, 8, 124, 175, 151, 116, 187, 253, 100, 103, 39, 233, 127, 39, 236, 50, 161, 143, 86, 123, 54, 86, 219, 117, 247, 136, 210, 123, 171, 224, 64, 58, 54, 131, 200, 54, 223, 224, 31, 216, 220, 233, 69, 154, 79, 149, 83, 105, 44, 52, 178, 242, 43, 194, 185, 130, 209, 168, 184, 64, 160, 208, 33, 240, 220, 88, 167, 51, 209, 86, 124, 228, 25, 141, 122, 113, 174, 192, 47, 108, 192, 252, 224, 2, 131, 209, 54, 227, 1, 212, 71, 124, 176, 155, 195, 18, 164, 14, 50, 170, 180, 103, 161, 11, 59, 154, 240, 128, 11, 74, 81, 136, 188, 243, 217, 101, 174, 128, 6, 248, 7, 195, 112, 6, 118, 129, 43, 17, 187, 104, 205, 192, 119, 253, 205, 110, 63, 219, 146, 210, 226, 149, 38, 90, 126, 150, 209, 5, 12, 225, 235, 109, 83, 210, 53, 153, 116, 69, 106, 58, 213, 241, 229, 146, 248, 81, 173, 246, 86, 113, 61, 168, 108, 81, 187, 229, 233, 176, 39, 58, 34, 244, 182, 104, 56, 60, 64, 141, 141, 233, 15, 9, 22, 240, 153, 9, 185, 198, 140, 193, 143, 88, 187, 13, 171, 24, 183, 249, 170, 169, 254, 144, 121, 203, 231, 228, 0, 103, 252, 213, 152, 146, 177, 71, 67, 158, 143, 253, 71, 98, 112, 185, 83, 124, 55, 98, 92, 72, 27, 113, 9, 38, 69, 163, 165, 208, 218, 78, 104, 242, 155, 247, 17, 89, 223, 103, 142, 8, 107, 148, 164, 78, 33, 179, 76, 222, 110, 58, 195, 73, 196, 141, 66, 103, 208, 216, 25, 29, 111, 198, 9, 204, 54, 129, 153, 198, 221, 12, 200, 233, 92, 243, 241, 211, 8, 28, 155, 0, 28, 249, 50, 123, 9, 205, 106, 31, 121, 40, 214, 249, 54, 162, 86, 35, 100, 175, 28, 77, 76, 36, 204, 211, 255, 17, 33, 131, 8, 158, 112, 228, 88, 72, 163, 50, 153, 90, 169, 209, 165, 185, 81, 163, 109, 149, 104, 108, 68, 87, 20, 21, 150, 170, 70, 87, 20, 141, 124, 85, 58, 247, 38, 162, 146, 156, 51, 194, 39, 117, 195, 217, 52, 152, 158, 174, 228, 154, 178, 181, 158, 132, 161, 241, 85, 34, 141, 197, 226, 234, 78, 152, 118, 242, 184, 35, 241, 110, 201, 49, 138, 58, 120, 241, 56, 168, 44, 180, 241, 159, 34, 31, 19, 245, 16, 62, 217, 25, 242, 107, 145, 99, 27, 83, 196, 160, 167, 96, 186, 39, 61, 67, 100, 3, 240, 182, 184, 223, 165, 103, 133, 168, 149, 97, 199, 70, 242, 135, 144, 196, 98, 2, 101, 232, 25, 43, 218, 91, 170, 183, 67, 76, 235, 238, 159, 122, 46, 29, 125, 210, 163, 67, 37, 228, 36, 47, 171, 233, 147, 81, 118, 174, 226, 43, 36, 164, 227, 205, 215, 186, 161, 67, 235, 120, 242, 78, 212, 146, 154, 134, 148, 135, 2, 6, 54, 64, 151, 43, 135, 18, 91, 236, 47, 242, 79, 144, 110, 4, 230, 198, 148, 145, 169, 199, 80, 197, 163, 79, 180, 39, 85, 54, 73, 245, 164, 209, 233, 117, 60, 145, 233, 199, 69, 6, 20, 146, 75, 3, 45, 55, 135, 201, 218, 35, 11, 219, 174, 14, 3, 147, 13, 1, 67, 244, 168, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 205, 108, 171, 16, 9, 63, 30, 50, 134, 251, 138, 198, 116, 114, 159, 134, 98, 168, 168, 163, 5, 235, 244, 146, 14, 236, 155, 30, 171, 121, 119, 3, 143, 152, 190, 246, 253, 46, 60, 110, 180, 40, 243, 83, 112, 248, 203, 79, 82, 181, 1, 111, 90, 206, 222, 38, 108, 42, 53, 129, 224, 212, 117, 195, 170, 70, 61, 108, 82, 199, 152, 32, 185, 82, 137, 12, 184, 43, 198, 76, 115, 82, 15, 162, 54, 128, 88, 237, 208, 249, 102, 111, 226, 22, 150, 143, 120, 87, 22, 85, 117, 152, 165, 163, 115, 220, 247, 166, 69, 218, 226, 160, 192, 163, 218, 178, 213, 0, 173, 189, 198, 115, 203, 170, 250, 158, 164, 149, 45, 75, 17, 81, 46, 245, 142, 191, 249, 31, 68, 136, 46, 133, 247, 2, 203, 254, 230, 186, 186, 75, 123, 181, 199, 193, 107, 169, 113, 207, 165, 118, 204, 162, 124, 32, 56, 145, 12, 86, 224, 16, 120, 139, 105, 248, 254, 42, 221, 87, 105, 158, 143, 21, 182, 158, 9, 62, 74, 167, 112, 158, 65, 206, 109, 165, 174, 213, 42, 234, 69, 157, 114, 124, 214, 16, 251, 226, 216, 217, 164, 145, 121, 2, 85, 220, 154, 174, 229, 125, 125, 193, 226, 64, 32, 65, 208, 253, 241, 84, 109, 44, 129, 45, 112, 208, 179, 157, 151, 190, 249, 190, 139, 161, 176, 51, 232, 232, 4, 140, 1, 128, 219, 93, 18, 157, 161, 212, 48, 155, 76, 223, 189, 152, 157, 203, 233, 97, 37, 22, 119, 36, 196, 159, 146, 68, 104, 169, 160, 11, 136, 0, 179, 187, 175, 188, 34, 27, 130, 165, 16, 81, 55, 26, 39, 156, 7, 70, 20, 196, 72, 29, 241, 132, 167, 188, 205, 19, 192, 133, 31, 114, 231, 121, 5, 59, 5, 15, 206, 80, 173, 36, 122, 225, 182, 98, 135, 67, 129, 221, 199, 77, 49, 9, 131, 77, 195, 170, 9, 253, 93, 216, 176, 244, 197, 142, 197, 128, 125, 224, 49, 80, 180, 70, 62, 102, 135, 145, 245, 108, 158, 153, 153, 92, 125, 61, 38, 117, 152, 235, 211, 145, 15, 226, 119, 218, 182, 62, 29, 11, 173, 54, 94, 51, 68, 32, 253, 79, 251, 27, 200, 43, 132, 74, 95, 17, 44, 253, 215, 230, 133, 227, 20, 70, 102, 127, 87, 204, 70, 67, 28, 104, 30, 92, 171, 122, 42, 71, 145, 199, 125, 36, 94, 45, 61, 187, 34, 110, 94, 75, 146, 252, 180, 142, 235, 229, 195, 138, 142, 208, 225, 91, 238, 148, 146, 100, 97, 220, 18, 98, 83, 94, 178, 129, 126, 182, 245, 158, 87, 213, 163, 170, 34, 200, 122, 210, 15, 16, 214, 13, 112, 129, 126, 83, 92, 33, 212, 247, 67, 255, 132, 254, 171, 117, 80, 127, 251, 125, 63, 224, 139, 174, 61, 228, 77, 177, 78, 220, 241, 96, 157, 178, 17, 53, 225, 131, 189, 182, 164, 175, 77, 119, 167, 106, 71, 117, 153, 97, 51, 122, 56, 173, 6, 204, 49, 108, 16, 87, 167, 90, 205, 242, 10, 143, 201, 58, 5, 140, 117, 246, 213, 91, 78, 232, 176, 247, 181, 64, 185, 21, 29, 122, 189, 147, 108, 130, 255, 254, 204, 217, 47, 142, 229, 254, 209, 129, 39, 210, 240, 111, 177, 225, 185, 59, 245, 44, 224, 87, 197, 33, 156, 71, 175, 178, 97, 119, 25, 36, 221, 197, 112, 183, 197, 220, 0, 24, 214, 166, 130, 226, 206, 108, 224, 154, 254, 102, 67, 141, 73, 120, 87, 116, 21, 111, 106, 184, 171, 223, 240, 138, 93, 152, 97, 130, 8, 96, 141, 164, 101, 118, 130, 180, 151, 33, 172, 250, 149, 179, 209, 226, 248, 22, 109, 205, 136, 185, 243, 61, 155, 73, 23, 167, 177, 244, 145, 44, 76, 231, 0, 185, 208, 169, 118, 166, 98, 113, 153, 165, 11, 184, 236, 176, 232, 0, 29, 220, 115, 94, 57, 84, 245, 92, 17, 18, 183, 55, 85, 1, 225, 96, 216, 132, 165, 81, 56, 90, 255, 89, 90, 77, 111, 108, 72, 54, 32, 247, 105, 194, 178, 173, 63, 124, 9, 193, 217, 250, 172, 77, 232, 192, 199, 226, 1, 252, 254, 126, 196, 245, 135, 241, 195, 0, 4, 67, 249, 225, 195, 205, 14, 231, 55, 24, 222, 49, 6, 154, 135, 83, 174, 53, 208, 223, 16, 152, 49, 8, 108, 75, 233, 178, 50, 220, 240, 125, 58, 34, 14, 29, 18, 50, 116, 158, 253, 146, 141, 89, 144, 140, 40, 42, 6, 19, 92, 88, 29, 71, 91, 81, 168, 114, 140, 230, 7, 43, 207, 112, 133, 224, 234, 77, 141, 253, 161, 32, 103, 46, 148, 115, 208, 253, 197, 235, 152, 38, 150, 219, 69, 83, 122, 217, 125, 52, 197, 15, 37, 144, 249, 33, 171, 34, 10, 180, 10, 39, 10, 19, 17, 118, 36, 51, 19, 166, 170, 50, 76, 246, 84, 168, 165, 27, 129, 171, 247, 237, 72, 201, 13, 27, 194, 170, 237, 69, 104, 86, 69, 137, 146, 210, 27, 54, 65, 83, 196, 201, 74, 43, 174, 82, 221, 107, 2, 64, 227, 251, 191, 180, 110, 207, 180, 73, 79, 8, 26, 223, 156, 130, 22, 223, 11, 132, 244, 132, 174, 2, 209, 117, 130, 242, 135, 81, 206, 78, 222, 56, 68, 225, 231, 188, 52, 161, 185, 127, 172, 184, 184, 168, 104, 220, 176, 158, 12, 160, 33, 139, 83, 13, 6, 76, 105, 40, 13, 57, 29, 225, 69, 200, 213, 100, 11, 206, 163, 55, 105, 45, 199, 142, 65, 197, 134, 189, 124, 8, 141, 171, 85, 152, 173, 163, 126, 147, 0, 93, 120, 241, 209, 37, 20, 99, 69, 69, 45, 21, 147, 90, 46, 72, 52, 29, 17, 126, 77, 52, 34, 165, 130, 36, 105, 17, 2, 247, 48, 34, 136, 152, 8, 213, 83, 251, 122, 127, 72, 180, 102, 105, 220, 37, 2, 74, 202, 198, 54, 31, 180, 104, 200, 64, 215, 247, 116, 211, 85, 129, 84, 10, 162, 52, 170, 102, 230, 184, 94, 28, 169, 6, 58, 90, 129, 38, 66, 214, 74, 168, 27, 240, 229, 194, 236, 97, 108, 87, 218, 154, 240, 200, 100, 16, 249, 139, 69, 85, 236, 5, 246, 238, 99, 124, 2, 249, 71, 54, 18, 156, 246, 194, 161, 167, 182, 135, 194, 97, 246, 7, 42, 200, 254, 128, 132, 216, 251, 32, 187, 7, 11, 132, 217, 251, 96, 90, 4, 219, 171, 179, 51, 248, 163, 19, 233, 93, 32, 254, 254, 84, 79, 26, 209, 40, 119, 89, 231, 64, 129, 134, 83, 36, 204, 193, 78, 251, 176, 15, 129, 185, 227, 42, 31, 248, 19, 109, 207, 182, 99, 71, 177, 126, 52, 14, 61, 38, 188, 91, 227, 161, 250, 247, 89, 70, 68, 53, 189, 192, 152, 24, 227, 230, 110, 14, 137, 236, 222, 103, 25, 17, 217, 242, 92, 3, 98, 183, 167, 252, 243, 81, 201, 163, 128, 237, 97, 22, 115, 225, 253, 167, 249, 247, 157, 184, 13, 146, 51, 74, 226, 217, 171, 192, 104, 155, 245, 36, 37, 170, 219, 51, 107, 201, 234, 46, 153, 70, 161, 250, 2, 90, 167, 230, 100, 22, 51, 97, 20, 150, 56, 144, 234, 143, 129, 225, 140, 43, 175, 226, 155, 215, 127, 153, 167, 91, 102, 12, 71, 98, 109, 102, 252, 0, 202, 112, 201, 134, 210, 54, 39, 135, 90, 108, 206, 225, 203, 60, 27, 97, 124, 54, 45, 72, 54, 8, 228, 242, 148, 76, 225, 96, 6, 24, 35, 154, 29, 47, 179, 72, 25, 36, 204, 92, 123, 15, 170, 201, 179, 53, 250, 205, 124, 112, 148, 80, 49, 91, 66, 31, 74, 145, 144, 223, 211, 112, 177, 80, 151, 225, 159, 1, 39, 222, 203, 142, 199, 66, 154, 96, 8, 105, 204, 36, 183, 27, 34, 132, 82, 39, 150, 228, 41, 198, 145, 38, 47, 200, 138, 41, 110, 209, 143, 46, 156, 178, 33, 91, 28, 196, 132, 23, 115, 154, 97, 234, 221, 43, 75, 176, 129, 51, 135, 12, 219, 58, 215, 35, 197, 170, 139, 33, 142, 55, 45, 223, 90, 81, 110, 209, 183, 47, 242, 220, 66, 158, 229, 33, 205, 232, 98, 94, 211, 50, 32, 201, 116, 5, 225, 43, 5, 214, 246, 199, 0, 14, 159, 71, 232, 95, 165, 103, 89, 119, 148, 159, 231, 211, 121, 229, 93, 173, 188, 206, 211, 124, 172, 98, 185, 237, 222, 155, 2, 167, 117, 130, 45, 179, 227, 56, 94, 15, 211, 241, 41, 42, 131, 239, 254, 214, 191, 38, 145, 135, 14, 134, 132, 194, 160, 117, 123, 37, 190, 185, 107, 215, 44, 240, 219, 132, 1, 30, 131, 95, 217, 252, 180, 254, 229, 171, 232, 3, 197, 243, 168, 18, 2, 11, 244, 232, 89, 176, 101, 205, 228, 209, 106, 75, 23, 86, 162, 79, 194, 158, 188, 214, 117, 99, 146, 254, 115, 89, 76, 238, 180, 164, 67, 7, 239, 168, 164, 55, 119, 205, 12, 233, 141, 19, 236, 182, 210, 204, 101, 216, 30, 106, 97, 170, 235, 78, 89, 26, 159, 83, 223, 180, 50, 14, 118, 43, 185, 33, 151, 13, 95, 166, 121, 89, 117, 23, 209, 27, 203, 19, 111, 142, 140, 47, 13, 183, 87, 186, 27, 123, 182, 52, 225, 94, 186, 60, 245, 200, 37, 38, 75, 18, 173, 158, 190, 247, 228, 154, 100, 76, 231, 177, 144, 213, 95, 223, 28, 97, 227, 225, 221, 119, 205, 127, 134, 189, 187, 139, 62, 180, 230, 174, 45, 119, 114, 94, 108, 246, 93, 68, 44, 151, 51, 205, 217, 51, 128, 181, 219, 228, 141, 30, 50, 39, 195, 128, 188, 80, 40, 122, 214, 84, 129, 227, 219, 122, 74, 254, 109, 189, 207, 185, 26, 175, 11, 122, 192, 244, 238, 42, 169, 115, 153, 196, 84, 65, 205, 238, 116, 84, 45, 32, 204, 121, 244, 130, 169, 66, 21, 67, 171, 124, 207, 44, 43, 145, 199, 174, 33, 30, 208, 29, 148, 251, 224, 54, 225, 89, 48, 86, 2, 138, 204, 23, 41, 161, 106, 216, 113, 136, 154, 164, 46, 44, 126, 61, 34, 207, 167, 204, 229, 128, 5, 12, 55, 38, 185, 94, 241, 152, 250, 125, 148, 159, 13, 45, 86, 131, 208, 227, 52, 197, 62, 225, 48, 234, 157, 38, 47, 171, 115, 32, 167, 179, 68, 70, 169, 0, 141, 110, 56, 105, 115, 29, 51, 99, 146, 183, 176, 241, 248, 71, 187, 144, 4, 149, 106, 8, 152, 90, 237, 157, 211, 24, 218, 99, 115, 106, 148, 89, 34, 139, 211, 53, 30, 94, 139, 118, 9, 213, 75, 132, 38, 185, 138, 168, 173, 167, 134, 190, 150, 72, 71, 39, 47, 71, 170, 231, 75, 235, 78, 211, 33, 92, 129, 253, 226, 46, 210, 113, 68, 137, 55, 233, 61, 121, 161, 215, 237, 167, 76, 131, 3, 57, 68, 29, 63, 172, 166, 140, 196, 220, 154, 107, 177, 234, 8, 169, 174, 206, 187, 27, 148, 188, 55, 55, 45, 61, 98, 186, 115, 249, 138, 67, 230, 6, 145, 133, 28, 244, 119, 131, 150, 87, 229, 74, 98, 238, 121, 107, 25, 137, 127, 32, 109, 66, 83, 82, 208, 8, 33, 238, 247, 146, 142, 124, 234, 64, 28, 42, 130, 237, 232, 4, 124, 252, 10, 230, 113, 122, 158, 233, 248, 57, 241, 8, 159, 240, 149, 250, 227, 164, 170, 69, 184, 50, 93, 45, 162, 11, 229, 204, 26, 230, 188, 58, 69, 104, 231, 89, 5, 199, 122, 225, 131, 122, 41, 255, 239, 130, 99, 144, 68, 9, 51, 228, 166, 245, 78, 199, 9, 33, 17, 165, 116, 7, 228, 145, 64, 4, 235, 149, 211, 221, 33, 44, 43, 129, 174, 37, 157, 135, 73, 71, 252, 145, 128, 98, 163, 0, 249, 86, 94, 149, 105, 62, 18, 207, 98, 225, 38, 254, 100, 60, 24, 185, 241, 110, 96, 6, 78, 5, 130, 247, 196, 140, 187, 10, 8, 252, 223, 113, 199, 137, 151, 12, 198, 48, 227, 136, 31, 205, 170, 73, 38, 168, 54, 228, 241, 192, 110, 114, 28, 26, 227, 15, 97, 58, 226, 149, 169, 64, 191, 5, 99, 11, 253, 243, 145, 32, 113, 166, 126, 36, 24, 135, 135, 227, 72, 171, 199, 254, 232, 176, 94, 117, 240, 189, 103, 67, 58, 56, 10, 81, 7, 219, 127, 24, 193, 53, 158, 43, 22, 244, 145, 9, 15, 244, 161, 239, 87, 135, 179, 49, 120, 97, 93, 192, 142, 240, 60, 248, 206, 217, 67, 176, 107, 204, 57, 162, 201, 147, 192, 149, 207, 114, 152, 90, 246, 214, 20, 131, 84, 15, 164, 4, 237, 158, 186, 9, 37, 211, 214, 129, 207, 76, 78, 228, 250, 93, 225, 38, 18, 212, 181, 56, 59, 41, 226, 137, 22, 62, 51, 195, 152, 99, 2, 55, 130, 99, 220, 35, 9, 119, 133, 101, 104, 104, 230, 242, 84, 144, 28, 193, 79, 165, 124, 228, 70, 226, 123, 200, 5, 223, 136, 64, 45, 219, 149, 238, 33, 146, 207, 201, 120, 176, 23, 90, 78, 4, 46, 100, 164, 0, 233, 238, 41, 36, 75, 144, 152, 218, 132, 241, 194, 126, 131, 211, 246, 88, 67, 123, 78, 229, 209, 97, 157, 123, 25, 245, 111, 189, 248, 89, 216, 84, 93, 123, 160, 80, 50, 91, 195, 162, 146, 188, 82, 127, 154, 135, 212, 162, 135, 121, 44, 89, 208, 36, 110, 121, 12, 42, 224, 127, 140, 158, 247, 209, 103, 110, 100, 167, 124, 183, 211, 78, 178, 133, 195, 26, 206, 46, 198, 161, 111, 208, 19, 8, 206, 39, 253, 211, 38, 31, 107, 200, 198, 16, 7, 29, 47, 164, 127, 210, 34, 214, 243, 98, 100, 189, 246, 160, 80, 192, 249, 133, 37, 28, 235, 209, 230, 214, 14, 29, 8, 82, 169, 198, 243, 74, 174, 105, 122, 201, 185, 58, 25, 97, 181, 40, 125, 129, 89, 195, 85, 89, 43, 73, 231, 250, 20, 134, 0, 139, 103, 70, 36, 208, 70, 55, 15, 219, 38, 118, 90, 210, 186, 3, 106, 60, 111, 221, 64, 238, 195, 182, 96, 246, 217, 32, 240, 189, 21, 5, 80, 29, 11, 34, 109, 18, 40, 60, 63, 183, 60, 77, 88, 22, 231, 52, 39, 109, 215, 111, 196, 142, 116, 0, 3, 194, 43, 206, 81, 18, 39, 51, 68, 123, 2, 123, 253, 215, 10, 217, 57, 51, 23, 116, 198, 219, 3, 46, 1, 238, 51, 114, 17, 225, 63, 72, 89, 41, 215, 125, 24, 64, 15, 171, 36, 248, 11, 43, 37, 56, 80, 43, 22, 172, 181, 39, 161, 52, 124, 115, 28, 138, 98, 108, 70, 76, 53, 253, 230, 141, 60, 167, 251, 230, 205, 67, 217, 148, 146, 34, 46, 83, 205, 199, 190, 188, 173, 31, 213, 72, 76, 78, 48, 107, 136, 92, 203, 75, 226, 151, 25, 208, 69, 45, 147, 104, 38, 189, 248, 114, 87, 197, 203, 144, 90, 96, 108, 88, 218, 200, 68, 5, 157, 74, 173, 122, 107, 157, 220, 45, 233, 204, 71, 255, 156, 156, 149, 106, 206, 114, 74, 169, 175, 123, 229, 159, 166, 58, 231, 231, 168, 8, 131, 137, 70, 212, 20, 77, 239, 116, 156, 143, 255, 62, 206, 205, 131, 64, 27, 219, 72, 156, 64, 6, 142, 239, 206, 45, 181, 127, 219, 155, 165, 100, 54, 220, 131, 224, 9, 212, 8, 155, 28, 160, 66, 49, 94, 134, 102, 134, 127, 151, 86, 251, 227, 106, 154, 142, 7, 58, 9, 53, 159, 114, 72, 178, 200, 188, 122, 169, 15, 171, 31, 156, 40, 38, 183, 163, 106, 62, 117, 59, 86, 221, 114, 57, 89, 33, 147, 12, 105, 214, 49, 28, 40, 15, 104, 78, 186, 80, 190, 46, 181, 53, 12, 134, 237, 211, 2, 54, 215, 242, 161, 81, 132, 77, 27, 180, 8, 129, 237, 204, 186, 120, 181, 173, 222, 119, 5, 126, 133, 239, 236, 98, 97, 54, 166, 33, 164, 157, 139, 109, 230, 57, 76, 20, 164, 193, 2, 167, 137, 66, 112, 218, 92, 111, 19, 235, 78, 224, 4, 17, 225, 218, 240, 1, 162, 3, 122, 213, 13, 99, 216, 104, 249, 190, 123, 200, 168, 238, 192, 39, 145, 189, 134, 1, 193, 69, 221, 221, 25, 146, 232, 65, 187, 246, 131, 98, 114, 181, 182, 59, 213, 222, 242, 252, 43, 59, 48, 156, 248, 158, 42, 124, 79, 78, 181, 170, 217, 197, 81, 159, 115, 29, 132, 15, 104, 88, 114, 248, 117, 177, 65, 119, 34, 84, 22, 24, 110, 14, 161, 205, 64, 251, 200, 47, 116, 110, 207, 140, 112, 8, 193, 248, 9, 214, 72, 16, 48, 71, 234, 74, 130, 244, 249, 105, 122, 133, 243, 169, 237, 168, 26, 56, 133, 218, 64, 215, 120, 204, 150, 68, 38, 76, 219, 107, 179, 94, 174, 39, 14, 172, 217, 88, 49, 121, 48, 132, 25, 208, 38, 56, 140, 80, 207, 13, 156, 2, 154, 211, 89, 130, 196, 135, 213, 216, 1, 10, 129, 250, 248, 174, 86, 130, 68, 121, 196, 95, 46, 255, 101, 1, 204, 45, 91, 84, 138, 189, 246, 4, 193, 71, 153, 228, 162, 134, 56, 176, 96, 13, 179, 159, 25, 138, 74, 242, 107, 216, 229, 67, 40, 50, 201, 100, 34, 161, 235, 131, 129, 74, 100, 75, 131, 41, 234, 247, 27, 97, 171, 137, 185, 110, 120, 130, 14, 226, 255, 51, 145, 96, 243, 196, 128, 245, 52, 70, 136, 171, 138, 228, 82, 160, 212, 27, 141, 241, 26, 230, 84, 253, 24, 52, 219, 213, 9, 71, 155, 114, 233, 6, 10, 236, 50, 147, 72, 93, 159, 216, 134, 15, 27, 186, 252, 111, 209, 186, 105, 194, 59, 47, 254, 95, 68, 152, 136, 112, 149, 141, 132, 72, 68, 133, 152, 100, 14, 107, 146, 99, 153, 220, 21, 161, 217, 62, 122, 103, 33, 62, 182, 23, 241, 248, 121, 198, 207, 33, 220, 42, 44, 77, 158, 149, 122, 6, 56, 37, 228, 42, 105, 193, 52, 227, 129, 115, 130, 234, 94, 151, 149, 150, 249, 73, 219, 30, 164, 186, 62, 97, 15, 157, 51, 116, 69, 133, 226, 125, 227, 164, 189, 77, 7, 2, 71, 169, 110, 133, 172, 243, 131, 119, 44, 187, 97, 109, 125, 187, 56, 212, 113, 69, 203, 80, 15, 158, 232, 2, 122, 235, 235, 17, 4, 147, 228, 109, 153, 165, 44, 115, 96, 64, 164, 227, 7, 23, 191, 136, 244, 162, 34, 29, 58, 80, 120, 171, 68, 186, 77, 7, 110, 171, 72, 47, 75, 24, 153, 106, 88, 95, 135, 52, 192, 155, 13, 179, 108, 216, 108, 174, 61, 153, 116, 19, 140, 230, 155, 190, 202, 141, 28, 17, 186, 37, 43, 221, 249, 176, 191, 93, 178, 118, 27, 86, 187, 230, 180, 211, 190, 21, 184, 200, 54, 147, 106, 175, 39, 201, 28, 171, 253, 130, 177, 57, 253, 98, 120, 157, 16, 161, 254, 152, 149, 165, 4, 133, 211, 139, 53, 184, 234, 170, 31, 247, 48, 214, 28, 150, 126, 195, 41, 169, 155, 160, 150, 150, 117, 218, 170, 89, 49, 57, 231, 177, 8, 87, 235, 238, 55, 28, 207, 178, 50, 176, 174, 72, 62, 207, 65, 166, 196, 21, 161, 101, 207, 98, 26, 252, 14, 157, 192, 56, 86, 236, 40, 162, 69, 71, 95, 138, 202, 131, 40, 120, 213, 240, 94, 133, 58, 46, 69, 133, 147, 30, 145, 114, 36, 117, 109, 45, 96, 150, 7, 176, 14, 159, 44, 139, 159, 172, 242, 215, 183, 145, 227, 84, 159, 203, 20, 174, 103, 77, 236, 212, 241, 198, 198, 198, 124, 131, 255, 58, 188, 237, 30, 61, 61, 117, 19, 164, 125, 241, 83, 29, 237, 100, 252, 154, 166, 169, 182, 199, 65, 92, 94, 15, 42, 101, 121, 132, 235, 139, 127, 245, 186, 199, 172, 69, 210, 254, 186, 225, 91, 224, 184, 153, 55, 210, 234, 140, 217, 151, 161, 254, 20, 67, 125, 111, 153, 99, 221, 124, 26, 46, 176, 111, 50, 30, 126, 25, 234, 91, 39, 213, 117, 107, 123, 177, 158, 35, 23, 96, 238, 143, 115, 196, 77, 16, 211, 142, 175, 88, 77, 144, 161, 149, 118, 230, 112, 40, 251, 45, 190, 108, 84, 89, 48, 85, 189, 44, 82, 55, 12, 56, 166, 170, 156, 103, 45, 2, 93, 4, 201, 206, 227, 167, 26, 1, 197, 240, 169, 13, 93, 183, 230, 112, 194, 183, 189, 164, 35, 250, 222, 97, 161, 253, 33, 162, 75, 244, 228, 162, 182, 103, 112, 58, 222, 124, 77, 126, 244, 95, 251, 243, 224, 115, 25, 233, 35, 141, 20, 0, 250, 54, 29, 156, 193, 92, 106, 111, 115, 113, 238, 111, 132, 30, 63, 143, 138, 207, 115, 21, 129, 241, 220, 70, 96, 8, 248, 230, 219, 220, 193, 23, 162, 114, 139, 136, 11, 130, 55, 249, 74, 110, 18, 236, 216, 78, 58, 129, 24, 46, 43, 88, 80, 243, 136, 37, 173, 69, 229, 50, 131, 124, 48, 89, 229, 198, 66, 42, 239, 235, 228, 13, 126, 238, 37, 207, 237, 73, 206, 116, 162, 84, 152, 40, 119, 40, 29, 28, 144, 97, 73, 0, 56, 29, 21, 111, 83, 160, 71, 224, 51, 84, 190, 120, 39, 208, 73, 186, 114, 21, 77, 86, 243, 16, 244, 164, 22, 64, 114, 73, 155, 78, 158, 136, 54, 47, 5, 45, 180, 162, 236, 26, 36, 194, 77, 147, 109, 47, 158, 113, 194, 241, 131, 171, 230, 206, 178, 75, 37, 106, 1, 72, 120, 91, 54, 207, 201, 18, 41, 218, 199, 162, 81, 72, 137, 98, 163, 218, 82, 125, 94, 42, 36, 50, 1, 142, 55, 106, 74, 244, 69, 143, 12, 8, 140, 116, 148, 213, 12, 130, 104, 75, 5, 215, 135, 63, 131, 183, 141, 202, 28, 245, 52, 44, 24, 219, 68, 160, 44, 18, 216, 68, 170, 183, 137, 106, 114, 112, 14, 4, 52, 45, 204, 187, 24, 17, 248, 47, 126, 204, 170, 230, 168, 105, 59, 206, 62, 168, 229, 105, 73, 93, 202, 210, 58, 69, 199, 63, 229, 89, 36, 27, 146, 181, 63, 158, 222, 223, 130, 240, 105, 55, 54, 107, 139, 184, 171, 180, 51, 82, 203, 138, 5, 196, 119, 143, 140, 59, 182, 65, 70, 112, 245, 239, 129, 234, 183, 7, 213, 231, 160, 116, 53, 115, 101, 171, 169, 127, 28, 197, 37, 70, 64, 1, 251, 53, 21, 253, 101, 138, 169, 98, 132, 13, 173, 32, 40, 97, 241, 19, 142, 188, 245, 178, 174, 16, 159, 48, 148, 224, 23, 187, 11, 214, 152, 243, 90, 119, 91, 163, 205, 165, 238, 224, 103, 46, 139, 217, 228, 39, 147, 117, 133, 76, 7, 230, 36, 146, 31, 203, 42, 11, 199, 102, 25, 28, 163, 111, 31, 104, 249, 115, 167, 28, 85, 91, 127, 205, 85, 106, 153, 128, 57, 218, 49, 98, 180, 252, 153, 175, 31, 159, 249, 246, 146, 232, 213, 235, 198, 150, 177, 246, 218, 56, 187, 72, 246, 236, 126, 196, 89, 123, 51, 213, 161, 226, 182, 149, 72, 53, 21, 53, 41, 125, 223, 58, 61, 35, 82, 141, 55, 202, 70, 39, 112, 121, 7, 173, 180, 183, 68, 107, 100, 166, 180, 245, 66, 247, 95, 39, 97, 96, 21, 5, 214, 75, 142, 85, 182, 191, 213, 160, 16, 7, 50, 254, 232, 54, 205, 61, 184, 21, 222, 44, 232, 92, 80, 36, 255, 127, 70, 28, 213, 54, 197, 67, 58, 97, 146, 243, 98, 118, 254, 54, 43, 223, 228, 149, 88, 76, 9, 50, 119, 199, 179, 115, 203, 207, 104, 18, 139, 119, 234, 224, 207, 88, 22, 118, 15, 110, 134, 100, 20, 170, 172, 203, 255, 75, 221, 24, 110, 242, 69, 250, 98, 153, 237, 221, 147, 146, 113, 30, 110, 75, 167, 6, 86, 32, 67, 77, 138, 215, 173, 91, 37, 187, 237, 254, 70, 59, 54, 177, 205, 176, 3, 232, 235, 182, 78, 156, 40, 71, 98, 66, 250, 60, 200, 202, 220, 32, 46, 166, 247, 232, 212, 86, 51, 0, 235, 221, 238, 86, 242, 151, 191, 36, 223, 222, 95, 133, 59, 29, 87, 97, 87, 87, 195, 248, 250, 107, 243, 40, 222, 178, 114, 252, 40, 155, 52, 33, 44, 99, 152, 190, 99, 27, 140, 113, 94, 21, 234, 167, 46, 184, 26, 6, 101, 217, 58, 10, 13, 139, 212, 3, 84, 6, 154, 208, 118, 7, 23, 99, 45, 142, 63, 103, 213, 160, 204, 39, 66, 225, 85, 244, 212, 149, 74, 45, 99, 46, 6, 61, 176, 42, 47, 187, 212, 215, 235, 30, 102, 39, 16, 94, 246, 166, 184, 24, 255, 83, 188, 237, 234, 3, 101, 210, 232, 177, 96, 193, 84, 250, 200, 148, 164, 201, 38, 214, 195, 75, 70, 1, 40, 42, 129, 109, 252, 138, 119, 243, 230, 252, 194, 120, 171, 47, 161, 138, 74, 55, 74, 140, 117, 104, 85, 124, 171, 239, 167, 58, 86, 200, 245, 32, 50, 165, 172, 47, 89, 210, 78, 70, 171, 117, 186, 140, 116, 19, 181, 33, 188, 113, 246, 43, 112, 172, 72, 217, 240, 168, 144, 115, 102, 246, 14, 60, 172, 76, 233, 125, 202, 139, 154, 65, 194, 107, 2, 61, 208, 251, 213, 147, 15, 98, 94, 169, 114, 60, 83, 201, 0, 179, 19, 148, 192, 229, 180, 165, 220, 173, 25, 128, 254, 102, 90, 60, 43, 196, 60, 145, 121, 233, 137, 232, 18, 161, 230, 232, 202, 193, 198, 212, 100, 193, 57, 8, 182, 32, 167, 5, 209, 83, 134, 184, 123, 105, 173, 95, 237, 93, 90, 17, 6, 232, 254, 139, 85, 87, 31, 187, 255, 82, 203, 41, 94, 255, 43, 5, 64, 18, 89, 140, 11, 204, 222, 115, 15, 134, 202, 130, 16, 54, 219, 60, 240, 104, 189, 153, 243, 182, 204, 108, 163, 197, 143, 20, 54, 178, 24, 67, 201, 155, 168, 145, 6, 21, 162, 167, 19, 12, 169, 154, 141, 104, 29, 105, 180, 170, 40, 90, 170, 180, 146, 9, 68, 11, 242, 39, 245, 146, 74, 254, 96, 170, 68, 20, 76, 66, 215, 12, 187, 166, 29, 86, 141, 152, 117, 247, 239, 43, 132, 166, 48, 87, 208, 137, 65, 105, 4, 51, 179, 64, 22, 39, 122, 198, 23, 184, 218, 251, 134, 115, 78, 240, 91, 37, 141, 232, 142, 176, 78, 95, 21, 154, 125, 132, 134, 83, 169, 172, 132, 169, 106, 82, 90, 169, 222, 27, 14, 147, 72, 171, 238, 42, 123, 23, 52, 130, 124, 216, 252, 176, 181, 185, 153, 252, 41, 254, 110, 246, 213, 159, 45, 60, 78, 105, 206, 85, 171, 142, 169, 103, 88, 64, 174, 72, 19, 216, 227, 106, 213, 228, 47, 148, 224, 167, 139, 19, 252, 180, 153, 224, 167, 119, 139, 224, 167, 132, 204, 150, 248, 53, 4, 127, 86, 20, 103, 179, 9, 225, 240, 86, 132, 254, 172, 84, 26, 22, 212, 177, 166, 230, 196, 216, 108, 168, 55, 189, 145, 138, 206, 188, 40, 103, 51, 51, 1, 234, 55, 176, 94, 254, 90, 145, 152, 166, 145, 32, 243, 220, 241, 150, 201, 254, 173, 51, 0, 135, 239, 21, 249, 72, 134, 208, 49, 43, 78, 189, 25, 81, 188, 85, 108, 168, 157, 136, 88, 239, 158, 246, 39, 69, 135, 239, 151, 47, 195, 55, 215, 240, 245, 111, 202, 240, 213, 27, 113, 19, 75, 70, 59, 172, 237, 41, 198, 1, 88, 95, 27, 161, 90, 168, 219, 38, 81, 243, 116, 90, 86, 187, 227, 33, 250, 225, 144, 180, 26, 12, 251, 10, 228, 238, 111, 186, 107, 16, 77, 123, 244, 35, 34, 229, 181, 171, 228, 162, 204, 167, 160, 164, 31, 38, 247, 238, 249, 208, 54, 31, 24, 159, 74, 38, 184, 78, 237, 221, 68, 138, 246, 77, 209, 65, 49, 62, 201, 79, 103, 117, 133, 183, 86, 157, 83, 199, 52, 83, 209, 31, 90, 135, 58, 216, 86, 230, 205, 22, 190, 105, 141, 84, 107, 148, 62, 6, 216, 227, 160, 68, 118, 115, 38, 6, 119, 112, 123, 114, 176, 242, 183, 179, 41, 184, 202, 64, 130, 7, 83, 187, 36, 93, 206, 197, 220, 164, 57, 162, 55, 232, 219, 136, 250, 240, 138, 248, 90, 196, 135, 18, 81, 38, 76, 34, 30, 134, 249, 219, 244, 214, 210, 164, 201, 187, 247, 67, 208, 187, 183, 69, 201, 138, 9, 237, 61, 1, 209, 46, 50, 76, 187, 161, 47, 140, 48, 235, 111, 227, 53, 211, 63, 212, 12, 77, 92, 173, 234, 92, 148, 243, 18, 122, 210, 177, 76, 214, 17, 43, 69, 138, 140, 142, 174, 147, 24, 252, 249, 136, 124, 218, 176, 149, 4, 245, 164, 125, 240, 16, 254, 252, 64, 253, 141, 29, 202, 149, 115, 192, 166, 213, 20, 244, 45, 9, 189, 191, 201, 160, 171, 68, 171, 13, 96, 165, 198, 208, 107, 91, 69, 52, 210, 18, 217, 128, 38, 84, 213, 193, 38, 166, 37, 173, 68, 230, 104, 44, 212, 47, 13, 70, 245, 233, 129, 236, 211, 22, 239, 147, 24, 182, 230, 70, 182, 116, 35, 102, 144, 73, 35, 167, 25, 217, 151, 8, 88, 169, 32, 15, 88, 239, 94, 216, 93, 233, 112, 239, 119, 63, 40, 251, 181, 227, 44, 200, 37, 190, 213, 92, 248, 86, 1, 124, 171, 24, 190, 149, 197, 183, 154, 27, 223, 42, 140, 175, 66, 202, 153, 182, 249, 135, 62, 157, 207, 93, 208, 91, 4, 166, 81, 231, 173, 180, 102, 165, 87, 24, 122, 105, 103, 20, 40, 29, 127, 205, 132, 20, 53, 170, 103, 245, 59, 99, 110, 24, 196, 187, 196, 70, 87, 127, 30, 168, 61, 66, 91, 52, 80, 2, 63, 82, 3, 38, 224, 159, 241, 123, 196, 239, 189, 8, 68, 105, 153, 220, 96, 139, 16, 10, 93, 243, 114, 97, 225, 82, 105, 78, 80, 196, 225, 79, 30, 13, 204, 200, 194, 176, 213, 12, 72, 102, 190, 171, 76, 163, 114, 11, 223, 49, 105, 180, 122, 38, 29, 150, 41, 170, 60, 116, 97, 159, 242, 137, 218, 209, 151, 161, 39, 174, 235, 209, 113, 25, 78, 96, 131, 54, 22, 182, 18, 9, 89, 129, 58, 13, 225, 42, 170, 228, 198, 137, 69, 134, 71, 175, 68, 89, 74, 111, 59, 78, 212, 198, 160, 59, 200, 225, 62, 255, 67, 249, 156, 14, 122, 201, 203, 6, 79, 43, 119, 82, 189, 212, 201, 186, 124, 243, 248, 203, 126, 158, 179, 159, 167, 200, 73, 60, 96, 3, 25, 235, 208, 197, 5, 198, 13, 218, 183, 227, 235, 203, 179, 184, 125, 120, 22, 183, 11, 207, 154, 236, 193, 51, 101, 7, 218, 101, 161, 179, 91, 8, 73, 234, 196, 199, 215, 118, 34, 107, 218, 18, 140, 137, 196, 103, 218, 11, 116, 37, 77, 128, 62, 207, 171, 236, 13, 158, 103, 234, 22, 227, 167, 234, 201, 74, 220, 68, 21, 137, 6, 176, 224, 247, 186, 244, 249, 216, 10, 36, 205, 199, 134, 34, 249, 243, 97, 123, 25, 183, 232, 233, 222, 50, 54, 209, 139, 109, 61, 107, 248, 138, 183, 77, 54, 170, 233, 187, 76, 119, 167, 167, 146, 242, 226, 175, 144, 111, 207, 246, 92, 119, 132, 84, 135, 161, 31, 147, 202, 9, 3, 231, 126, 101, 3, 217, 37, 96, 86, 193, 146, 215, 108, 255, 158, 206, 255, 206, 161, 190, 144, 152, 20, 182, 47, 238, 5, 173, 238, 64, 33, 61, 14, 179, 170, 24, 189, 207, 186, 123, 44, 7, 43, 153, 126, 194, 33, 158, 178, 238, 6, 160, 221, 75, 12, 229, 13, 218, 1, 31, 8, 191, 80, 90, 51, 161, 250, 211, 165, 132, 98, 253, 23, 138, 166, 162, 135, 228, 110, 35, 1, 84, 38, 102, 213, 147, 32, 1, 26, 242, 144, 69, 218, 138, 50, 46, 159, 212, 84, 92, 218, 179, 188, 146, 230, 129, 244, 211, 60, 203, 207, 178, 167, 69, 41, 180, 126, 101, 247, 174, 140, 64, 168, 237, 195, 87, 5, 30, 188, 18, 5, 80, 127, 152, 213, 46, 148, 120, 156, 116, 191, 221, 220, 76, 254, 146, 8, 11, 57, 126, 66, 188, 223, 255, 27, 19, 221, 145, 64, 3, 167, 18, 229, 49, 18, 160, 86, 217, 164, 145, 203, 105, 68, 252, 209, 155, 149, 118, 163, 50, 160, 235, 0, 158, 152, 62, 229, 92, 126, 156, 123, 38, 3, 124, 102, 196, 208, 142, 52, 121, 95, 68, 119, 154, 150, 50, 136, 3, 131, 255, 228, 17, 49, 97, 142, 153, 147, 103, 162, 54, 115, 104, 24, 53, 160, 42, 206, 19, 36, 170, 107, 56, 19, 182, 118, 26, 176, 38, 27, 172, 136, 239, 77, 84, 222, 255, 176, 122, 255, 211, 49, 31, 176, 155, 27, 178, 155, 230, 245, 171, 226, 168, 152, 149, 131, 204, 105, 142, 91, 18, 109, 175, 218, 104, 67, 59, 220, 18, 219, 175, 246, 199, 163, 92, 30, 248, 124, 6, 181, 12, 92, 54, 26, 116, 31, 76, 127, 24, 104, 253, 109, 134, 138, 53, 144, 240, 209, 33, 202, 190, 97, 128, 30, 52, 15, 144, 138, 237, 190, 120, 37, 95, 107, 198, 247, 15, 37, 62, 78, 182, 116, 35, 166, 180, 115, 230, 80, 175, 18, 3, 104, 154, 42, 113, 147, 218, 195, 117, 171, 151, 144, 106, 100, 81, 75, 231, 19, 138, 203, 212, 116, 225, 211, 49, 158, 25, 184, 249, 152, 79, 58, 184, 132, 86, 194, 92, 233, 251, 213, 75, 97, 241, 101, 67, 165, 42, 28, 185, 20, 6, 27, 123, 131, 74, 74, 70, 146, 16, 205, 132, 205, 255, 200, 11, 227, 219, 135, 77, 218, 209, 229, 231, 36, 169, 46, 114, 153, 183, 31, 208, 212, 122, 209, 156, 76, 19, 244, 223, 124, 232, 76, 30, 154, 18, 174, 86, 215, 28, 109, 7, 115, 219, 66, 233, 47, 12, 69, 138, 72, 37, 214, 81, 20, 220, 214, 213, 193, 225, 67, 159, 193, 189, 191, 68, 184, 248, 176, 197, 26, 120, 112, 29, 13, 224, 195, 125, 214, 210, 183, 215, 218, 18, 62, 60, 96, 77, 126, 247, 105, 154, 196, 135, 111, 89, 219, 223, 127, 226, 182, 241, 225, 59, 134, 196, 15, 159, 11, 9, 124, 248, 158, 97, 243, 183, 207, 142, 13, 62, 252, 192, 208, 234, 47, 174, 81, 150, 142, 23, 62, 252, 141, 35, 184, 4, 101, 181, 116, 4, 53, 64, 174, 7, 251, 203, 84, 132, 203, 71, 85, 63, 25, 37, 43, 214, 47, 169, 88, 144, 56, 72, 27, 11, 162, 9, 91, 255, 188, 151, 54, 172, 134, 243, 58, 54, 177, 233, 171, 184, 54, 117, 62, 249, 0, 58, 167, 177, 29, 105, 221, 49, 111, 83, 218, 185, 254, 136, 27, 81, 45, 118, 25, 93, 115, 143, 245, 47, 186, 65, 30, 66, 39, 216, 161, 119, 105, 181, 28, 220, 3, 182, 151, 170, 16, 48, 186, 68, 163, 190, 185, 133, 224, 131, 70, 62, 221, 1, 205, 199, 198, 80, 12, 15, 80, 168, 63, 201, 245, 118, 8, 182, 153, 218, 117, 168, 209, 56, 199, 30, 171, 0, 10, 137, 254, 209, 76, 222, 121, 233, 119, 170, 231, 88, 239, 46, 213, 84, 149, 99, 82, 131, 103, 127, 248, 234, 48, 59, 125, 242, 97, 242, 116, 148, 158, 86, 44, 210, 17, 172, 219, 195, 168, 135, 236, 176, 142, 125, 15, 235, 78, 27, 31, 50, 251, 217, 120, 71, 58, 29, 221, 200, 225, 134, 188, 36, 97, 152, 15, 236, 134, 28, 22, 91, 19, 229, 134, 29, 74, 198, 195, 13, 117, 98, 43, 80, 240, 212, 41, 152, 159, 142, 139, 50, 219, 75, 171, 44, 80, 56, 119, 10, 159, 139, 15, 112, 181, 99, 168, 236, 185, 83, 118, 88, 76, 119, 71, 33, 12, 42, 167, 224, 108, 156, 15, 138, 97, 8, 228, 44, 92, 82, 44, 71, 67, 36, 120, 239, 148, 174, 166, 249, 224, 236, 50, 80, 240, 178, 227, 112, 131, 77, 68, 229, 7, 127, 122, 140, 128, 49, 169, 39, 240, 134, 199, 163, 170, 162, 129, 251, 72, 175, 159, 97, 38, 144, 142, 169, 84, 62, 31, 108, 94, 16, 64, 10, 155, 113, 238, 75, 140, 121, 9, 249, 138, 110, 172, 116, 254, 10, 55, 124, 106, 104, 107, 248, 91, 22, 171, 35, 143, 189, 174, 211, 222, 155, 74, 73, 179, 59, 124, 15, 119, 123, 168, 47, 251, 16, 156, 222, 61, 194, 187, 173, 137, 227, 202, 120, 175, 170, 217, 100, 162, 220, 222, 105, 41, 247, 2, 212, 218, 27, 227, 223, 143, 244, 42, 241, 235, 175, 209, 42, 112, 220, 28, 170, 153, 55, 192, 42, 47, 139, 124, 60, 221, 21, 186, 193, 54, 247, 56, 217, 252, 112, 34, 254, 173, 240, 107, 58, 20, 244, 181, 164, 47, 254, 99, 237, 59, 186, 20, 186, 251, 28, 28, 117, 93, 181, 33, 97, 71, 185, 252, 16, 29, 230, 242, 67, 237, 181, 89, 31, 234, 6, 90, 212, 165, 35, 125, 68, 71, 16, 81, 208, 13, 238, 87, 136, 159, 60, 13, 122, 48, 153, 230, 231, 249, 239, 42, 43, 148, 69, 128, 178, 66, 195, 17, 201, 242, 3, 63, 35, 169, 148, 138, 168, 119, 239, 94, 87, 129, 192, 48, 36, 235, 28, 225, 122, 7, 91, 19, 29, 250, 85, 137, 174, 91, 183, 191, 233, 58, 106, 85, 15, 126, 193, 3, 167, 130, 206, 162, 27, 18, 145, 163, 30, 5, 20, 218, 181, 87, 85, 113, 219, 224, 201, 135, 108, 160, 234, 185, 186, 159, 140, 161, 232, 229, 197, 203, 84, 204, 51, 186, 96, 120, 168, 157, 98, 102, 196, 61, 137, 42, 63, 16, 145, 50, 89, 52, 66, 204, 153, 143, 7, 163, 217, 80, 154, 84, 80, 1, 148, 74, 199, 221, 51, 86, 24, 4, 58, 226, 19, 181, 125, 51, 51, 181, 15, 35, 48, 29, 165, 213, 116, 159, 222, 95, 15, 96, 119, 19, 122, 189, 253, 88, 127, 138, 28, 78, 55, 243, 84, 16, 85, 157, 13, 82, 149, 113, 206, 54, 219, 157, 113, 117, 96, 74, 112, 190, 20, 128, 135, 201, 46, 29, 90, 117, 196, 16, 198, 96, 90, 50, 74, 75, 168, 214, 69, 18, 240, 43, 239, 10, 91, 186, 103, 42, 19, 140, 44, 60, 118, 255, 49, 122, 183, 9, 85, 140, 255, 156, 82, 203, 50, 44, 39, 33, 25, 16, 44, 0, 30, 171, 176, 230, 179, 192, 76, 209, 135, 164, 229, 53, 147, 66, 76, 254, 127, 188, 182, 22, 88, 4, 180, 19, 19, 195, 171, 222, 104, 207, 201, 1, 184, 171, 32, 168, 1, 26, 72, 235, 224, 26, 222, 152, 20, 85, 142, 233, 20, 21, 178, 71, 89, 90, 14, 222, 9, 75, 10, 209, 116, 41, 10, 67, 99, 43, 61, 130, 172, 112, 115, 50, 11, 237, 15, 111, 243, 153, 248, 34, 147, 202, 118, 143, 136, 62, 35, 140, 117, 52, 123, 171, 148, 41, 12, 143, 198, 130, 224, 152, 172, 155, 183, 203, 228, 184, 235, 102, 32, 220, 235, 49, 31, 30, 235, 49, 12, 108, 238, 237, 234, 42, 31, 27, 120, 175, 118, 154, 161, 139, 9, 85, 204, 159, 3, 99, 7, 25, 85, 121, 25, 29, 205, 78, 31, 147, 219, 196, 84, 145, 14, 157, 185, 149, 117, 64, 234, 202, 200, 106, 130, 21, 249, 180, 170, 141, 6, 245, 78, 95, 58, 198, 251, 208, 75, 226, 53, 228, 187, 141, 76, 40, 58, 57, 150, 234, 165, 58, 7, 4, 205, 190, 1, 21, 184, 226, 30, 152, 80, 165, 14, 179, 201, 40, 21, 139, 159, 10, 77, 165, 82, 253, 38, 209, 97, 159, 223, 138, 136, 75, 185, 154, 115, 84, 135, 210, 17, 246, 69, 148, 97, 169, 39, 73, 135, 76, 157, 188, 172, 166, 63, 23, 162, 72, 169, 25, 93, 101, 123, 148, 125, 243, 32, 90, 22, 177, 176, 184, 222, 119, 218, 208, 147, 140, 125, 173, 205, 195, 199, 52, 215, 66, 0, 13, 193, 95, 79, 157, 183, 33, 240, 52, 216, 240, 6, 26, 88, 240, 46, 74, 69, 163, 0, 112, 72, 31, 39, 223, 110, 242, 195, 13, 54, 240, 229, 167, 180, 194, 116, 28, 79, 240, 215, 211, 66, 232, 205, 243, 183, 195, 52, 68, 22, 11, 220, 240, 167, 134, 178, 202, 27, 8, 154, 118, 136, 168, 32, 161, 110, 173, 203, 170, 192, 252, 212, 115, 222, 28, 185, 47, 176, 91, 238, 107, 138, 173, 251, 77, 153, 65, 206, 75, 141, 56, 123, 205, 250, 249, 113, 197, 127, 170, 237, 21, 24, 99, 102, 162, 67, 52, 57, 98, 137, 181, 20, 41, 92, 57, 158, 46, 179, 222, 115, 102, 195, 134, 198, 229, 100, 70, 233, 201, 105, 201, 8, 22, 160, 97, 140, 126, 30, 237, 92, 60, 205, 39, 175, 87, 245, 232, 230, 144, 72, 121, 14, 106, 125, 52, 210, 80, 195, 249, 172, 73, 121, 18, 119, 142, 209, 241, 27, 106, 26, 146, 186, 230, 156, 241, 160, 163, 65, 8, 239, 141, 68, 120, 28, 34, 68, 143, 47, 136, 92, 100, 154, 169, 29, 94, 49, 33, 8, 179, 24, 90, 161, 125, 65, 180, 89, 31, 124, 252, 189, 225, 194, 215, 126, 151, 106, 38, 80, 138, 128, 106, 94, 182, 71, 154, 118, 27, 14, 54, 235, 53, 218, 118, 93, 199, 20, 245, 92, 235, 59, 59, 143, 210, 181, 155, 49, 131, 124, 245, 126, 197, 69, 94, 216, 200, 231, 78, 198, 74, 101, 111, 121, 3, 155, 227, 54, 129, 11, 166, 247, 169, 174, 115, 253, 231, 229, 31, 11, 88, 212, 136, 99, 207, 32, 180, 182, 230, 68, 120, 73, 51, 194, 157, 20, 131, 169, 205, 218, 44, 35, 111, 223, 242, 208, 132, 92, 232, 36, 206, 217, 240, 144, 123, 143, 117, 134, 67, 229, 123, 127, 105, 151, 101, 60, 210, 151, 4, 109, 105, 98, 179, 200, 45, 51, 214, 56, 38, 199, 57, 73, 48, 49, 222, 75, 39, 66, 85, 100, 58, 5, 134, 76, 66, 114, 158, 126, 232, 90, 26, 201, 90, 38, 218, 98, 61, 233, 235, 187, 17, 201, 232, 200, 180, 245, 209, 193, 49, 197, 20, 72, 153, 56, 75, 86, 34, 102, 170, 183, 246, 100, 216, 32, 57, 237, 187, 124, 44, 48, 212, 25, 89, 16, 69, 229, 39, 52, 170, 209, 132, 116, 111, 174, 16, 61, 171, 184, 95, 42, 19, 240, 19, 90, 238, 241, 109, 228, 63, 255, 244, 173, 79, 127, 246, 48, 160, 140, 52, 9, 75, 76, 93, 49, 240, 225, 208, 126, 37, 179, 8, 185, 146, 1, 254, 33, 45, 130, 83, 139, 89, 208, 154, 55, 102, 192, 26, 167, 155, 176, 202, 142, 168, 109, 66, 33, 39, 200, 217, 38, 219, 76, 32, 88, 89, 252, 217, 121, 100, 177, 216, 134, 133, 38, 181, 111, 100, 202, 211, 116, 242, 194, 240, 219, 241, 216, 28, 189, 213, 89, 75, 197, 215, 200, 249, 33, 248, 103, 216, 8, 10, 18, 99, 78, 155, 36, 250, 175, 196, 41, 61, 207, 134, 132, 133, 145, 19, 78, 225, 20, 65, 69, 87, 210, 188, 96, 180, 117, 115, 106, 129, 149, 15, 88, 69, 116, 212, 41, 253, 93, 243, 195, 48, 244, 227, 71, 1, 89, 182, 77, 251, 90, 96, 205, 30, 23, 98, 62, 14, 31, 138, 245, 123, 64, 118, 167, 64, 35, 107, 46, 171, 88, 206, 79, 194, 26, 198, 0, 92, 163, 130, 235, 175, 171, 2, 149, 69, 71, 29, 87, 133, 155, 173, 94, 119, 209, 49, 86, 148, 132, 4, 8, 177, 210, 138, 6, 122, 169, 20, 36, 65, 196, 48, 137, 74, 170, 149, 81, 34, 157, 82, 46, 169, 68, 50, 89, 188, 170, 237, 50, 176, 92, 236, 79, 235, 250, 163, 81, 160, 114, 10, 8, 204, 187, 186, 96, 207, 169, 2, 211, 47, 118, 133, 135, 252, 54, 75, 117, 92, 162, 155, 164, 25, 107, 133, 4, 58, 106, 56, 212, 117, 192, 212, 55, 49, 162, 77, 226, 95, 187, 212, 240, 245, 66, 228, 132, 136, 14, 59, 52, 244, 161, 42, 131, 7, 30, 18, 126, 55, 221, 38, 159, 194, 185, 80, 89, 129, 250, 101, 176, 119, 183, 182, 133, 171, 80, 131, 32, 25, 231, 147, 63, 137, 160, 90, 97, 191, 87, 201, 47, 162, 117, 121, 68, 228, 141, 232, 158, 253, 209, 191, 134, 190, 110, 221, 220, 190, 218, 31, 91, 215, 208, 241, 251, 183, 164, 227, 246, 199, 253, 107, 160, 194, 131, 219, 72, 5, 251, 227, 193, 50, 73, 66, 247, 19, 230, 84, 213, 205, 123, 46, 117, 181, 233, 50, 180, 149, 229, 54, 39, 252, 144, 117, 199, 28, 48, 238, 136, 55, 158, 200, 224, 62, 47, 114, 70, 82, 55, 30, 136, 153, 106, 209, 51, 119, 130, 171, 177, 79, 61, 183, 143, 48, 110, 164, 209, 148, 79, 103, 150, 55, 13, 85, 148, 81, 165, 254, 112, 22, 9, 120, 127, 28, 171, 165, 231, 227, 22, 55, 176, 158, 186, 211, 175, 180, 177, 208, 192, 74, 216, 166, 157, 191, 177, 98, 34, 75, 198, 254, 44, 143, 187, 5, 235, 106, 81, 221, 218, 28, 104, 49, 227, 215, 204, 247, 238, 108, 95, 163, 33, 26, 245, 67, 92, 59, 68, 116, 131, 89, 87, 243, 215, 97, 9, 167, 242, 109, 165, 219, 200, 182, 59, 175, 127, 166, 142, 232, 71, 119, 38, 95, 188, 79, 91, 55, 169, 79, 250, 209, 157, 175, 23, 239, 222, 253, 27, 218, 61, 253, 232, 206, 201, 139, 247, 244, 193, 205, 239, 169, 126, 116, 103, 221, 5, 58, 77, 93, 130, 209, 165, 32, 91, 181, 109, 214, 174, 218, 182, 91, 76, 188, 99, 211, 129, 177, 61, 189, 89, 95, 195, 40, 206, 53, 240, 3, 178, 89, 190, 117, 197, 45, 61, 193, 183, 156, 4, 91, 3, 190, 31, 154, 217, 201, 188, 200, 249, 103, 57, 115, 122, 112, 214, 91, 124, 159, 204, 110, 101, 52, 198, 222, 205, 21, 28, 180, 168, 151, 249, 147, 196, 8, 121, 94, 255, 121, 226, 129, 106, 60, 103, 203, 242, 155, 249, 14, 190, 32, 193, 12, 214, 182, 203, 164, 35, 143, 172, 87, 237, 134, 133, 17, 17, 242, 83, 155, 255, 174, 248, 248, 66, 27, 252, 43, 173, 119, 32, 213, 214, 249, 181, 201, 101, 81, 230, 167, 144, 56, 64, 245, 133, 6, 158, 168, 17, 15, 70, 158, 244, 87, 221, 234, 79, 113, 227, 19, 3, 190, 77, 114, 58, 212, 132, 50, 171, 78, 101, 132, 233, 31, 206, 7, 178, 245, 119, 13, 186, 194, 243, 57, 59, 219, 65, 100, 59, 208, 197, 152, 111, 225, 205, 173, 116, 26, 212, 78, 144, 243, 231, 83, 62, 238, 22, 216, 252, 209, 136, 73, 139, 157, 49, 119, 195, 193, 183, 131, 26, 172, 160, 152, 13, 20, 180, 128, 188, 253, 168, 176, 61, 99, 173, 25, 147, 186, 140, 238, 31, 201, 71, 58, 122, 206, 150, 179, 140, 125, 109, 26, 186, 232, 22, 116, 100, 232, 182, 195, 163, 98, 44, 186, 54, 36, 135, 124, 108, 219, 97, 174, 163, 251, 140, 180, 24, 229, 152, 186, 157, 147, 232, 118, 97, 120, 141, 76, 204, 95, 190, 99, 88, 187, 65, 72, 199, 218, 25, 152, 79, 60, 95, 90, 137, 111, 59, 93, 178, 113, 225, 215, 55, 221, 212, 153, 146, 98, 246, 231, 35, 205, 19, 118, 3, 16, 11, 181, 83, 235, 96, 255, 154, 198, 156, 169, 225, 207, 63, 93, 80, 117, 161, 137, 210, 146, 102, 179, 131, 172, 77, 54, 174, 173, 122, 51, 71, 90, 15, 211, 139, 46, 111, 181, 199, 97, 4, 34, 43, 239, 152, 117, 64, 131, 26, 231, 178, 16, 72, 48, 226, 173, 52, 22, 62, 203, 164, 255, 101, 126, 112, 230, 135, 230, 176, 92, 204, 162, 53, 81, 17, 191, 106, 220, 189, 12, 116, 80, 139, 239, 247, 90, 240, 178, 114, 77, 248, 197, 246, 54, 249, 193, 231, 43, 168, 106, 191, 58, 113, 34, 240, 143, 132, 35, 59, 121, 213, 233, 40, 208, 136, 217, 123, 245, 189, 93, 108, 190, 244, 103, 76, 39, 118, 54, 100, 207, 4, 230, 205, 200, 86, 200, 151, 25, 244, 203, 12, 154, 124, 153, 65, 155, 98, 216, 231, 156, 62, 253, 77, 166, 219, 226, 12, 251, 50, 215, 45, 52, 215, 93, 71, 252, 222, 28, 251, 165, 148, 86, 145, 105, 198, 223, 62, 85, 133, 23, 92, 141, 197, 3, 48, 123, 225, 14, 224, 219, 47, 203, 183, 207, 49, 249, 220, 17, 245, 28, 62, 68, 210, 82, 61, 135, 79, 33, 199, 195, 231, 23, 58, 65, 103, 143, 101, 28, 148, 71, 50, 245, 7, 215, 241, 93, 155, 37, 255, 135, 85, 179, 111, 196, 107, 208, 144, 190, 90, 38, 136, 87, 149, 195, 24, 152, 48, 184, 158, 144, 195, 120, 68, 184, 132, 26, 193, 209, 19, 27, 115, 122, 46, 107, 188, 150, 117, 248, 135, 177, 103, 113, 45, 71, 20, 171, 160, 88, 215, 123, 60, 227, 205, 59, 141, 251, 176, 105, 203, 142, 134, 169, 15, 167, 142, 205, 216, 76, 92, 54, 201, 102, 164, 208, 10, 78, 3, 119, 79, 142, 231, 217, 197, 248, 34, 197, 203, 145, 226, 121, 172, 182, 26, 139, 109, 89, 34, 108, 98, 163, 34, 198, 93, 155, 83, 55, 53, 70, 93, 173, 57, 28, 183, 236, 62, 133, 134, 104, 227, 7, 160, 86, 90, 99, 152, 219, 10, 26, 89, 95, 84, 77, 221, 33, 216, 150, 11, 186, 248, 17, 135, 47, 234, 231, 139, 250, 185, 149, 234, 103, 193, 224, 210, 229, 132, 244, 182, 92, 154, 206, 165, 240, 230, 140, 235, 253, 162, 25, 169, 89, 124, 195, 18, 200, 169, 29, 129, 236, 125, 94, 204, 170, 103, 132, 195, 41, 195, 123, 46, 178, 253, 234, 191, 179, 18, 146, 245, 28, 137, 209, 150, 44, 209, 245, 96, 232, 115, 190, 178, 71, 78, 205, 136, 84, 177, 27, 244, 234, 211, 13, 125, 253, 181, 77, 8, 184, 35, 244, 242, 247, 39, 39, 39, 53, 71, 212, 221, 21, 147, 62, 130, 92, 135, 156, 135, 158, 215, 69, 84, 112, 124, 39, 99, 193, 60, 48, 120, 218, 44, 56, 225, 196, 167, 135, 8, 74, 124, 199, 193, 73, 119, 25, 8, 246, 87, 228, 225, 249, 238, 122, 62, 240, 56, 83, 55, 87, 181, 236, 94, 155, 60, 64, 6, 176, 206, 202, 82, 72, 125, 29, 55, 202, 113, 179, 204, 231, 214, 8, 33, 16, 225, 185, 32, 5, 53, 15, 70, 38, 65, 164, 221, 186, 123, 249, 18, 159, 129, 2, 169, 179, 142, 38, 163, 124, 234, 102, 157, 218, 91, 66, 242, 172, 189, 105, 81, 38, 143, 98, 215, 39, 209, 236, 89, 208, 204, 158, 156, 91, 108, 205, 249, 18, 116, 217, 122, 27, 38, 1, 214, 182, 171, 88, 111, 126, 94, 46, 57, 22, 38, 43, 215, 8, 220, 20, 55, 73, 39, 71, 110, 202, 2, 114, 52, 140, 178, 221, 177, 183, 100, 52, 183, 114, 212, 243, 33, 210, 182, 43, 169, 193, 79, 183, 64, 62, 3, 236, 133, 253, 170, 175, 96, 227, 150, 55, 68, 59, 75, 255, 172, 52, 50, 37, 121, 43, 104, 112, 154, 149, 154, 156, 4, 53, 147, 244, 100, 126, 157, 233, 52, 19, 217, 220, 225, 154, 85, 106, 84, 166, 172, 171, 249, 227, 33, 224, 159, 238, 82, 120, 27, 175, 194, 237, 59, 221, 236, 255, 147, 237, 6, 39, 12, 2, 168, 212, 83, 138, 107, 214, 215, 167, 166, 9, 81, 98, 129, 172, 49, 202, 96, 190, 120, 170, 3, 59, 244, 17, 237, 182, 128, 46, 59, 100, 170, 210, 128, 104, 164, 136, 215, 117, 183, 16, 164, 30, 86, 105, 154, 245, 220, 69, 136, 19, 77, 248, 191, 39, 120, 23, 36, 175, 103, 224, 49, 41, 227, 153, 45, 149, 205, 176, 75, 55, 244, 4, 63, 107, 190, 12, 48, 190, 238, 146, 248, 4, 149, 100, 18, 97, 248, 183, 237, 45, 189, 100, 1, 5, 225, 241, 227, 199, 142, 15, 87, 55, 136, 173, 240, 29, 14, 154, 138, 81, 215, 168, 242, 223, 129, 41, 105, 50, 62, 121, 137, 172, 124, 77, 43, 71, 228, 9, 243, 97, 115, 243, 71, 147, 19, 141, 160, 120, 134, 49, 55, 43, 36, 31, 55, 11, 89, 78, 223, 4, 234, 170, 189, 190, 190, 25, 168, 252, 127, 56, 161, 230, 166, 61, 198, 25, 34, 206, 111, 48, 115, 7, 244, 220, 139, 130, 172, 141, 168, 254, 19, 246, 226, 189, 72, 248, 50, 197, 30, 64, 226, 62, 237, 111, 194, 174, 4, 98, 83, 171, 82, 8, 244, 239, 219, 33, 162, 219, 118, 109, 183, 127, 243, 173, 79, 70, 254, 223, 152, 229, 247, 27, 186, 234, 65, 207, 254, 6, 203, 26, 218, 54, 252, 11, 110, 63, 101, 173, 162, 140, 127, 79, 236, 69, 225, 102, 44, 163, 108, 243, 187, 231, 36, 168, 65, 251, 247, 246, 91, 202, 64, 143, 223, 237, 242, 220, 118, 124, 158, 206, 254, 38, 84, 196, 239, 199, 155, 175, 89, 132, 115, 68, 161, 50, 59, 239, 183, 109, 175, 123, 30, 239, 54, 119, 236, 55, 25, 155, 196, 117, 109, 108, 243, 241, 55, 184, 105, 244, 55, 186, 201, 152, 128, 14, 19, 211, 182, 123, 183, 178, 234, 154, 241, 105, 249, 248, 123, 121, 233, 148, 10, 152, 112, 102, 91, 28, 49, 142, 86, 157, 92, 162, 250, 236, 57, 177, 234, 2, 40, 4, 167, 235, 75, 205, 176, 148, 74, 34, 75, 115, 81, 238, 74, 188, 133, 254, 243, 50, 232, 177, 140, 190, 160, 45, 51, 91, 247, 247, 128, 82, 145, 147, 149, 180, 62, 14, 78, 26, 179, 80, 253, 30, 78, 64, 165, 160, 64, 6, 44, 67, 9, 20, 254, 92, 30, 141, 115, 192, 83, 70, 104, 160, 206, 239, 250, 70, 67, 100, 40, 77, 137, 0, 113, 26, 9, 228, 19, 137, 114, 14, 85, 165, 70, 43, 234, 245, 203, 196, 149, 173, 6, 180, 59, 120, 91, 43, 149, 167, 57, 249, 64, 206, 79, 134, 21, 200, 226, 104, 55, 96, 131, 59, 150, 186, 231, 26, 169, 187, 65, 1, 20, 165, 187, 94, 58, 116, 151, 75, 204, 120, 65, 138, 65, 226, 90, 234, 90, 216, 63, 249, 119, 153, 78, 38, 246, 204, 194, 161, 126, 192, 197, 1, 254, 234, 4, 113, 118, 110, 115, 174, 51, 235, 163, 249, 234, 15, 35, 89, 232, 95, 101, 213, 116, 46, 154, 212, 44, 76, 230, 184, 85, 162, 21, 254, 128, 248, 211, 162, 148, 40, 250, 248, 127, 165, 215, 25, 114, 1, 131, 119, 98, 232, 75, 88, 36, 242, 241, 91, 37, 176, 18, 94, 184, 113, 124, 36, 175, 114, 222, 168, 212, 219, 215, 236, 130, 9, 227, 35, 2, 149, 183, 59, 26, 125, 89, 90, 95, 101, 105, 189, 18, 94, 40, 107, 226, 126, 38, 199, 101, 197, 83, 55, 46, 127, 153, 204, 150, 106, 58, 238, 185, 236, 37, 158, 195, 169, 153, 219, 76, 10, 136, 69, 150, 148, 11, 44, 128, 17, 87, 178, 114, 108, 183, 73, 198, 20, 188, 65, 182, 211, 225, 136, 196, 22, 155, 182, 213, 22, 75, 178, 64, 197, 141, 118, 72, 26, 68, 80, 255, 206, 177, 18, 61, 237, 172, 10, 198, 146, 62, 212, 135, 176, 204, 249, 115, 126, 16, 51, 4, 209, 223, 148, 32, 124, 234, 174, 111, 57, 19, 156, 186, 143, 20, 117, 152, 178, 184, 132, 17, 151, 2, 211, 25, 158, 18, 212, 234, 185, 12, 55, 10, 187, 87, 107, 192, 149, 217, 105, 246, 97, 210, 211, 243, 83, 28, 160, 28, 97, 123, 201, 14, 191, 110, 39, 71, 112, 162, 47, 47, 178, 139, 96, 67, 178, 219, 138, 31, 133, 182, 102, 108, 168, 107, 203, 165, 154, 66, 168, 85, 233, 190, 70, 187, 85, 233, 45, 221, 185, 86, 165, 239, 107, 127, 203, 159, 56, 98, 225, 10, 202, 174, 212, 181, 228, 175, 7, 61, 62, 190, 43, 206, 45, 65, 88, 56, 236, 212, 101, 52, 123, 145, 125, 96, 158, 53, 50, 113, 127, 234, 107, 14, 174, 226, 28, 245, 250, 68, 58, 82, 188, 253, 79, 84, 241, 203, 59, 201, 133, 101, 214, 85, 133, 126, 153, 165, 229, 240, 85, 17, 100, 46, 40, 186, 26, 243, 173, 215, 27, 110, 28, 82, 196, 140, 3, 4, 29, 219, 205, 239, 86, 192, 124, 51, 27, 20, 127, 36, 242, 226, 251, 135, 52, 121, 195, 176, 24, 139, 23, 114, 26, 87, 23, 192, 187, 145, 9, 70, 123, 251, 44, 7, 119, 44, 42, 110, 211, 236, 229, 31, 242, 183, 206, 24, 220, 76, 128, 6, 129, 218, 165, 94, 157, 5, 119, 115, 20, 222, 32, 132, 20, 5, 53, 38, 222, 12, 194, 145, 217, 92, 33, 155, 180, 74, 52, 91, 76, 92, 28, 70, 159, 194, 104, 57, 143, 113, 8, 247, 41, 132, 218, 251, 16, 218, 69, 244, 59, 81, 24, 196, 93, 134, 145, 237, 115, 121, 126, 145, 139, 12, 182, 73, 178, 101, 249, 134, 157, 51, 105, 171, 20, 80, 80, 91, 28, 76, 65, 93, 223, 87, 162, 130, 40, 251, 213, 35, 198, 2, 214, 222, 82, 181, 79, 2, 7, 81, 98, 177, 47, 102, 165, 137, 180, 53, 191, 217, 222, 36, 190, 101, 174, 147, 123, 241, 232, 150, 218, 208, 22, 19, 243, 97, 166, 124, 90, 97, 231, 17, 114, 39, 174, 229, 77, 17, 8, 255, 118, 130, 90, 156, 249, 49, 16, 6, 14, 129, 224, 214, 37, 70, 2, 208, 131, 110, 159, 154, 121, 196, 227, 12, 248, 247, 128, 254, 88, 239, 155, 31, 196, 37, 16, 19, 111, 245, 205, 17, 113, 74, 165, 208, 109, 32, 209, 120, 25, 215, 83, 230, 142, 129, 44, 132, 199, 48, 130, 199, 44, 26, 67, 243, 93, 136, 161, 240, 124, 53, 70, 1, 103, 84, 237, 0, 69, 99, 245, 45, 45, 174, 56, 50, 116, 186, 119, 6, 200, 59, 158, 184, 116, 22, 176, 1, 93, 146, 17, 222, 227, 149, 55, 146, 212, 219, 230, 155, 199, 8, 122, 75, 31, 117, 125, 211, 214, 147, 241, 161, 67, 121, 102, 120, 59, 39, 48, 194, 253, 147, 215, 2, 115, 3, 175, 129, 20, 132, 12, 134, 4, 235, 68, 91, 234, 217, 10, 133, 141, 69, 1, 48, 177, 53, 106, 60, 44, 150, 243, 35, 209, 167, 42, 123, 174, 217, 213, 23, 57, 211, 3, 231, 98, 1, 45, 116, 100, 98, 208, 197, 116, 180, 138, 35, 63, 0, 9, 44, 21, 127, 61, 228, 12, 25, 243, 89, 66, 208, 209, 220, 7, 98, 180, 180, 153, 230, 232, 169, 24, 139, 3, 145, 180, 0, 219, 152, 150, 45, 59, 50, 89, 185, 210, 184, 168, 213, 84, 88, 30, 188, 75, 91, 61, 67, 188, 155, 226, 205, 191, 204, 235, 131, 134, 169, 249, 214, 228, 145, 177, 171, 91, 93, 229, 216, 218, 234, 202, 25, 213, 237, 200, 66, 157, 213, 215, 140, 71, 69, 165, 96, 204, 30, 182, 116, 239, 30, 150, 114, 214, 141, 251, 213, 203, 162, 170, 242, 183, 163, 75, 52, 96, 153, 159, 202, 224, 205, 186, 172, 134, 85, 26, 248, 255, 72, 171, 23, 133, 186, 154, 212, 154, 232, 170, 114, 237, 90, 67, 21, 177, 91, 247, 4, 100, 172, 202, 145, 185, 226, 21, 169, 171, 96, 8, 12, 108, 33, 2, 166, 71, 209, 168, 165, 187, 166, 80, 55, 74, 105, 184, 228, 154, 128, 94, 117, 24, 64, 125, 210, 55, 34, 222, 150, 197, 87, 160, 70, 13, 175, 17, 56, 178, 163, 43, 238, 210, 77, 122, 218, 246, 199, 112, 91, 122, 58, 21, 252, 148, 169, 133, 145, 12, 13, 85, 82, 255, 94, 17, 196, 113, 201, 137, 101, 179, 30, 90, 149, 2, 175, 103, 21, 154, 170, 21, 98, 190, 55, 18, 47, 84, 83, 86, 226, 246, 171, 23, 66, 31, 29, 148, 191, 106, 41, 144, 32, 184, 55, 48, 128, 35, 246, 82, 161, 201, 38, 138, 188, 122, 169, 238, 37, 62, 210, 107, 19, 237, 39, 196, 57, 16, 226, 80, 148, 106, 235, 104, 198, 148, 77, 221, 235, 186, 85, 33, 104, 48, 44, 56, 102, 240, 238, 249, 248, 99, 15, 87, 172, 209, 204, 213, 132, 24, 49, 236, 132, 158, 192, 162, 99, 232, 78, 11, 49, 141, 193, 150, 193, 174, 111, 205, 56, 147, 116, 115, 134, 100, 60, 15, 36, 115, 227, 155, 50, 208, 118, 128, 46, 113, 17, 162, 157, 22, 38, 197, 212, 4, 239, 62, 21, 63, 72, 165, 238, 145, 99, 38, 96, 212, 141, 174, 80, 223, 81, 91, 208, 239, 8, 61, 42, 47, 157, 98, 93, 210, 142, 226, 185, 38, 228, 253, 59, 128, 221, 88, 80, 162, 134, 66, 68, 39, 131, 252, 161, 110, 128, 149, 211, 243, 40, 46, 48, 224, 72, 95, 170, 204, 8, 128, 174, 216, 224, 204, 23, 97, 100, 26, 55, 98, 166, 78, 231, 27, 95, 201, 163, 25, 64, 226, 120, 98, 120, 43, 155, 147, 174, 14, 28, 93, 211, 239, 247, 61, 11, 88, 162, 219, 236, 153, 53, 188, 172, 26, 225, 119, 39, 7, 155, 218, 18, 101, 12, 141, 130, 201, 56, 22, 148, 100, 9, 239, 147, 10, 179, 113, 204, 248, 18, 93, 39, 34, 246, 2, 178, 26, 28, 100, 99, 173, 24, 92, 245, 27, 15, 4, 96, 192, 191, 194, 204, 155, 140, 112, 248, 38, 233, 80, 244, 241, 131, 178, 105, 197, 154, 36, 31, 141, 142, 208, 12, 21, 159, 158, 140, 135, 87, 150, 2, 5, 6, 246, 145, 212, 19, 236, 36, 193, 227, 209, 52, 45, 167, 161, 9, 197, 217, 80, 98, 116, 204, 199, 211, 231, 26, 91, 106, 140, 155, 46, 80, 79, 153, 120, 35, 35, 14, 74, 39, 68, 139, 1, 81, 110, 11, 241, 195, 81, 69, 226, 165, 70, 202, 120, 228, 129, 58, 25, 67, 206, 210, 203, 40, 59, 93, 136, 221, 82, 230, 3, 245, 16, 121, 156, 116, 187, 253, 100, 103, 39, 185, 191, 9, 97, 16, 91, 156, 176, 135, 233, 248, 212, 200, 205, 38, 163, 23, 52, 168, 186, 202, 224, 173, 99, 191, 52, 242, 98, 13, 53, 30, 192, 65, 10, 116, 100, 233, 190, 248, 158, 92, 100, 141, 50, 155, 8, 78, 213, 103, 73, 160, 180, 122, 238, 234, 6, 255, 138, 175, 77, 240, 198, 159, 214, 89, 25, 110, 109, 141, 30, 41, 65, 152, 176, 124, 213, 16, 255, 203, 129, 168, 105, 138, 60, 4, 52, 165, 233, 57, 44, 85, 197, 162, 40, 216, 162, 51, 115, 68, 176, 82, 227, 18, 20, 142, 55, 21, 176, 105, 88, 68, 96, 75, 46, 233, 176, 189, 115, 70, 76, 11, 69, 113, 57, 236, 93, 6, 37, 77, 218, 218, 49, 241, 124, 147, 141, 35, 34, 186, 180, 246, 37, 77, 107, 215, 47, 250, 146, 228, 187, 184, 130, 193, 131, 76, 13, 107, 24, 203, 183, 114, 143, 240, 164, 44, 206, 117, 148, 77, 112, 27, 79, 31, 168, 211, 213, 254, 41, 204, 185, 108, 212, 213, 42, 89, 235, 102, 18, 13, 165, 64, 110, 74, 49, 10, 124, 30, 225, 192, 109, 18, 57, 243, 25, 166, 212, 183, 89, 203, 112, 67, 76, 62, 237, 223, 188, 112, 21, 171, 70, 211, 43, 96, 212, 160, 93, 143, 11, 0, 130, 3, 91, 5, 132, 236, 124, 195, 96, 117, 150, 62, 1, 232, 154, 251, 136, 20, 183, 18, 24, 17, 106, 6, 158, 88, 10, 6, 206, 252, 166, 130, 174, 218, 75, 88, 187, 74, 242, 106, 110, 176, 110, 97, 62, 40, 128, 71, 94, 33, 74, 16, 45, 50, 102, 245, 69, 111, 234, 38, 212, 119, 164, 68, 65, 210, 119, 184, 210, 24, 142, 30, 107, 54, 114, 21, 45, 154, 178, 225, 203, 198, 23, 110, 42, 124, 175, 56, 155, 245, 38, 69, 85, 27, 69, 63, 204, 62, 28, 156, 144, 45, 120, 2, 223, 78, 43, 69, 229, 109, 234, 233, 25, 69, 148, 163, 205, 1, 34, 142, 47, 81, 86, 168, 97, 4, 63, 179, 60, 239, 164, 104, 221, 248, 82, 87, 200, 238, 218, 52, 205, 71, 47, 101, 239, 0, 191, 53, 86, 203, 57, 93, 59, 206, 46, 142, 12, 170, 180, 71, 198, 129, 105, 74, 152, 248, 17, 230, 13, 164, 159, 153, 134, 147, 24, 170, 19, 159, 134, 236, 182, 240, 218, 35, 77, 144, 109, 198, 192, 198, 48, 171, 92, 108, 37, 103, 98, 199, 118, 88, 105, 31, 211, 181, 16, 46, 88, 185, 199, 91, 90, 215, 239, 221, 53, 34, 161, 76, 84, 73, 202, 152, 169, 107, 215, 147, 237, 215, 127, 84, 154, 131, 139, 192, 80, 1, 190, 18, 36, 37, 110, 231, 114, 144, 16, 45, 186, 32, 252, 162, 235, 183, 87, 174, 160, 121, 119, 181, 225, 183, 184, 242, 85, 21, 172, 180, 199, 53, 84, 170, 182, 57, 126, 186, 116, 99, 191, 251, 61, 6, 197, 116, 95, 88, 187, 7, 39, 112, 72, 226, 57, 110, 64, 153, 99, 64, 38, 238, 195, 38, 243, 35, 217, 5, 234, 82, 248, 193, 158, 8, 201, 47, 16, 138, 93, 9, 204, 29, 230, 139, 36, 139, 254, 69, 73, 133, 239, 52, 22, 242, 39, 225, 47, 214, 236, 78, 224, 126, 8, 239, 102, 12, 210, 31, 90, 121, 219, 101, 253, 72, 166, 248, 218, 60, 241, 225, 92, 117, 129, 28, 241, 161, 46, 134, 146, 223, 25, 199, 130, 236, 54, 237, 188, 229, 242, 163, 81, 46, 3, 56, 172, 62, 15, 82, 149, 15, 186, 75, 87, 161, 229, 121, 1, 218, 86, 169, 211, 228, 177, 22, 189, 244, 4, 110, 27, 9, 75, 51, 65, 57, 113, 155, 143, 132, 0, 108, 120, 152, 234, 111, 7, 220, 14, 159, 242, 120, 144, 80, 120, 70, 115, 58, 205, 1, 120, 125, 118, 39, 184, 192, 62, 155, 107, 83, 99, 62, 131, 187, 184, 102, 83, 3, 214, 114, 219, 73, 209, 225, 206, 237, 59, 105, 26, 208, 141, 39, 213, 213, 216, 226, 80, 213, 88, 154, 123, 27, 17, 248, 228, 123, 66, 154, 175, 231, 223, 20, 170, 240, 16, 94, 75, 95, 178, 166, 48, 209, 233, 6, 194, 252, 54, 131, 174, 122, 21, 95, 114, 195, 238, 80, 128, 211, 91, 108, 15, 177, 188, 39, 205, 155, 68, 235, 91, 203, 219, 29, 186, 170, 215, 219, 140, 208, 28, 62, 111, 194, 72, 50, 197, 192, 157, 212, 143, 208, 179, 38, 143, 22, 42, 5, 149, 103, 33, 155, 164, 24, 165, 77, 82, 45, 92, 73, 59, 72, 20, 2, 43, 31, 84, 5, 240, 62, 232, 152, 128, 50, 145, 145, 226, 103, 167, 141, 155, 9, 81, 15, 66, 211, 133, 107, 78, 142, 51, 86, 70, 145, 128, 246, 136, 240, 245, 108, 43, 36, 70, 208, 63, 227, 23, 115, 132, 133, 48, 12, 170, 54, 221, 207, 58, 39, 152, 70, 196, 85, 110, 246, 40, 62, 93, 22, 153, 113, 141, 114, 9, 85, 111, 26, 198, 2, 234, 205, 28, 212, 37, 109, 42, 218, 41, 142, 242, 85, 67, 120, 7, 92, 78, 203, 90, 88, 212, 176, 5, 177, 193, 212, 0, 254, 153, 254, 68, 158, 193, 35, 11, 39, 62, 114, 193, 19, 254, 166, 107, 199, 175, 169, 65, 174, 84, 62, 29, 189, 56, 81, 142, 143, 88, 213, 24, 63, 225, 225, 239, 94, 114, 40, 9, 99, 68, 163, 6, 231, 22, 88, 112, 28, 136, 118, 240, 249, 25, 154, 14, 107, 2, 98, 162, 166, 229, 84, 90, 168, 75, 208, 3, 26, 234, 188, 123, 125, 163, 192, 246, 29, 238, 1, 202, 189, 67, 89, 113, 95, 48, 225, 41, 28, 129, 135, 55, 116, 155, 80, 238, 23, 65, 15, 156, 52, 41, 63, 74, 184, 15, 73, 85, 232, 165, 174, 120, 34, 83, 251, 35, 116, 187, 94, 205, 149, 143, 195, 44, 94, 53, 10, 224, 141, 151, 187, 0, 28, 128, 106, 187, 182, 186, 40, 18, 168, 92, 22, 231, 110, 69, 139, 81, 207, 0, 183, 174, 194, 194, 93, 86, 71, 139, 71, 246, 35, 204, 102, 134, 220, 117, 16, 58, 181, 16, 43, 15, 248, 189, 138, 135, 116, 228, 57, 208, 253, 106, 127, 60, 18, 208, 196, 176, 62, 75, 203, 211, 204, 221, 98, 50, 99, 188, 186, 29, 225, 42, 205, 82, 116, 121, 116, 117, 174, 90, 96, 251, 184, 137, 117, 48, 173, 135, 207, 118, 146, 149, 18, 18, 36, 74, 121, 74, 214, 162, 76, 229, 108, 96, 154, 134, 119, 72, 94, 16, 139, 76, 144, 185, 96, 93, 42, 192, 154, 0, 24, 234, 183, 13, 214, 21, 220, 98, 25, 83, 158, 42, 231, 30, 108, 176, 207, 136, 135, 54, 198, 157, 153, 102, 77, 60, 42, 174, 97, 74, 104, 117, 123, 91, 146, 151, 12, 102, 127, 170, 184, 100, 210, 232, 220, 12, 21, 224, 166, 65, 1, 27, 184, 16, 117, 217, 191, 58, 19, 41, 96, 243, 48, 17, 180, 182, 139, 17, 159, 120, 227, 124, 119, 53, 152, 43, 166, 226, 91, 253, 225, 74, 129, 125, 7, 49, 234, 166, 89, 49, 99, 235, 122, 221, 205, 213, 213, 102, 120, 91, 115, 193, 139, 125, 234, 175, 6, 24, 71, 201, 4, 188, 55, 215, 20, 231, 210, 237, 38, 254, 236, 36, 30, 58, 219, 144, 83, 193, 245, 193, 249, 78, 77, 218, 108, 174, 13, 17, 235, 52, 177, 149, 218, 122, 63, 222, 84, 224, 255, 89, 238, 4, 6, 16, 111, 197, 228, 37, 167, 15, 174, 31, 118, 228, 86, 49, 252, 251, 209, 219, 78, 22, 227, 79, 39, 50, 44, 247, 48, 166, 81, 232, 76, 5, 19, 143, 110, 8, 144, 21, 205, 68, 27, 192, 169, 46, 0, 88, 126, 161, 96, 171, 73, 58, 118, 213, 161, 153, 145, 180, 34, 108, 55, 147, 73, 80, 243, 104, 28, 24, 229, 128, 194, 81, 81, 48, 221, 65, 49, 27, 47, 97, 81, 164, 160, 133, 152, 41, 110, 11, 143, 25, 175, 40, 68, 180, 46, 26, 211, 9, 197, 11, 20, 194, 140, 102, 102, 203, 73, 20, 255, 11, 73, 203, 249, 200, 139, 56, 106, 19, 114, 100, 67, 28, 164, 155, 26, 146, 97, 58, 96, 224, 132, 130, 193, 254, 149, 113, 216, 75, 189, 177, 189, 77, 151, 121, 80, 155, 100, 183, 122, 37, 29, 165, 212, 136, 30, 11, 171, 222, 100, 127, 145, 53, 108, 233, 35, 90, 154, 31, 7, 114, 28, 235, 68, 113, 188, 10, 233, 140, 220, 156, 167, 158, 107, 128, 237, 222, 21, 54, 107, 206, 76, 152, 112, 109, 243, 91, 37, 201, 208, 13, 153, 15, 124, 196, 229, 203, 150, 92, 193, 79, 135, 171, 18, 115, 159, 11, 63, 106, 85, 176, 239, 72, 94, 240, 180, 53, 199, 224, 202, 39, 146, 157, 14, 45, 116, 22, 153, 195, 104, 115, 10, 217, 239, 68, 36, 125, 76, 211, 169, 80, 117, 46, 139, 168, 116, 231, 240, 113, 248, 52, 168, 172, 101, 69, 39, 144, 97, 110, 254, 243, 207, 202, 250, 196, 67, 182, 52, 213, 208, 220, 231, 151, 225, 0, 211, 203, 34, 151, 59, 79, 177, 237, 95, 83, 102, 119, 42, 99, 183, 115, 150, 247, 125, 240, 46, 45, 247, 64, 127, 9, 8, 125, 161, 37, 186, 22, 228, 99, 204, 220, 87, 195, 144, 138, 58, 8, 83, 212, 54, 208, 144, 55, 217, 177, 164, 24, 130, 48, 65, 236, 233, 86, 123, 146, 155, 122, 182, 103, 148, 203, 173, 137, 209, 60, 123, 80, 142, 9, 45, 129, 166, 98, 22, 24, 188, 41, 211, 11, 153, 224, 226, 72, 8, 80, 98, 133, 99, 80, 20, 103, 50, 193, 186, 201, 21, 174, 11, 217, 240, 225, 244, 130, 125, 151, 53, 54, 196, 91, 107, 111, 72, 161, 28, 29, 101, 167, 210, 12, 99, 7, 213, 210, 11, 55, 158, 210, 43, 29, 48, 96, 49, 90, 164, 166, 134, 107, 189, 218, 141, 227, 244, 66, 159, 177, 227, 70, 164, 111, 0, 146, 162, 198, 174, 164, 135, 231, 250, 219, 228, 231, 142, 219, 77, 242, 209, 90, 155, 122, 235, 85, 215, 241, 108, 83, 234, 185, 33, 88, 173, 69, 236, 82, 3, 75, 219, 167, 31, 87, 106, 235, 66, 151, 76, 29, 75, 5, 198, 86, 218, 168, 245, 231, 162, 183, 249, 233, 156, 211, 80, 200, 206, 16, 80, 92, 35, 67, 15, 235, 142, 248, 246, 184, 67, 109, 127, 89, 12, 82, 123, 238, 252, 85, 126, 11, 162, 37, 184, 255, 108, 25, 136, 1, 156, 56, 106, 240, 53, 142, 156, 250, 26, 68, 175, 24, 13, 151, 129, 157, 0, 19, 71, 46, 142, 88, 24, 169, 147, 252, 67, 182, 12, 172, 36, 156, 40, 90, 211, 105, 20, 47, 248, 20, 182, 119, 82, 97, 237, 86, 75, 64, 13, 33, 69, 145, 203, 163, 184, 229, 97, 212, 170, 115, 161, 251, 150, 128, 152, 132, 19, 69, 75, 126, 141, 162, 134, 95, 131, 232, 137, 63, 103, 217, 50, 240, 147, 128, 226, 8, 202, 207, 113, 12, 241, 115, 196, 139, 187, 12, 252, 102, 111, 227, 200, 205, 226, 162, 32, 191, 133, 209, 154, 44, 5, 173, 73, 13, 90, 147, 26, 180, 38, 14, 90, 79, 170, 65, 58, 201, 118, 167, 162, 232, 219, 217, 20, 243, 212, 191, 183, 179, 114, 62, 158, 204, 64, 77, 211, 201, 234, 61, 91, 127, 78, 131, 49, 85, 186, 94, 47, 249, 166, 243, 77, 47, 233, 124, 253, 219, 172, 152, 110, 119, 130, 14, 247, 116, 60, 120, 39, 140, 91, 56, 210, 121, 117, 210, 40, 96, 237, 151, 150, 216, 141, 111, 118, 82, 121, 166, 244, 81, 231, 27, 65, 170, 32, 85, 20, 126, 107, 162, 67, 143, 161, 204, 145, 34, 105, 26, 81, 122, 197, 120, 58, 40, 70, 5, 172, 84, 71, 58, 191, 222, 149, 180, 159, 6, 184, 64, 215, 160, 110, 34, 43, 215, 116, 15, 241, 116, 251, 7, 117, 227, 93, 4, 75, 186, 107, 205, 233, 171, 118, 16, 32, 45, 218, 63, 168, 91, 211, 61, 133, 100, 251, 222, 201, 137, 126, 86, 142, 174, 222, 177, 208, 84, 223, 138, 31, 223, 149, 217, 73, 77, 143, 36, 114, 141, 236, 152, 77, 73, 90, 193, 253, 113, 142, 43, 90, 147, 74, 89, 197, 131, 76, 201, 186, 84, 197, 43, 14, 229, 14, 170, 248, 178, 33, 158, 201, 114, 213, 4, 90, 202, 34, 49, 79, 0, 4, 177, 226, 174, 175, 42, 167, 59, 206, 172, 91, 21, 149, 15, 101, 70, 163, 226, 2, 119, 82, 97, 17, 97, 113, 212, 240, 67, 91, 173, 18, 50, 236, 179, 78, 123, 22, 28, 182, 196, 73, 240, 180, 40, 159, 164, 131, 119, 114, 69, 241, 54, 29, 156, 157, 140, 213, 120, 8, 227, 54, 241, 118, 17, 245, 216, 132, 215, 233, 71, 106, 149, 126, 68, 214, 232, 58, 131, 149, 248, 54, 255, 226, 92, 111, 81, 215, 174, 200, 9, 222, 228, 171, 192, 222, 46, 217, 77, 39, 157, 165, 186, 59, 108, 22, 84, 221, 216, 253, 156, 1, 31, 231, 163, 76, 180, 209, 221, 236, 37, 180, 22, 229, 97, 185, 206, 12, 159, 64, 200, 166, 111, 212, 87, 122, 103, 138, 24, 43, 181, 72, 20, 197, 76, 8, 142, 202, 89, 114, 228, 125, 130, 74, 145, 80, 86, 92, 174, 139, 245, 9, 172, 53, 69, 213, 39, 227, 105, 121, 41, 40, 96, 92, 37, 186, 109, 191, 69, 178, 255, 13, 96, 106, 226, 80, 77, 15, 149, 36, 56, 112, 204, 245, 210, 193, 79, 9, 205, 101, 30, 226, 222, 0, 47, 246, 84, 107, 230, 207, 145, 207, 204, 95, 137, 190, 206, 153, 174, 214, 214, 168, 201, 85, 107, 211, 107, 249, 227, 32, 186, 162, 66, 150, 252, 79, 93, 182, 204, 215, 159, 61, 199, 215, 65, 84, 156, 14, 148, 56, 29, 48, 113, 50, 131, 120, 176, 144, 64, 205, 229, 234, 226, 56, 7, 252, 92, 115, 179, 172, 90, 231, 131, 54, 170, 117, 78, 1, 75, 219, 220, 124, 205, 12, 125, 16, 229, 101, 73, 81, 202, 202, 232, 24, 61, 255, 103, 46, 55, 80, 26, 220, 109, 7, 54, 81, 171, 117, 81, 88, 25, 177, 128, 168, 175, 195, 108, 79, 213, 74, 134, 227, 143, 54, 183, 181, 155, 186, 199, 193, 202, 161, 158, 138, 215, 44, 174, 164, 89, 232, 212, 24, 24, 87, 24, 237, 23, 126, 66, 162, 135, 162, 201, 84, 9, 54, 149, 130, 155, 19, 124, 113, 131, 162, 28, 42, 119, 237, 31, 30, 59, 43, 7, 109, 80, 173, 66, 70, 97, 233, 219, 141, 167, 20, 134, 218, 204, 91, 148, 94, 28, 41, 231, 167, 248, 178, 1, 22, 140, 102, 151, 241, 236, 28, 191, 172, 97, 33, 205, 8, 250, 139, 74, 69, 47, 159, 169, 71, 200, 128, 12, 199, 240, 184, 56, 63, 16, 42, 3, 141, 178, 142, 41, 174, 143, 164, 56, 163, 91, 87, 247, 69, 250, 194, 212, 34, 29, 132, 93, 53, 213, 13, 187, 179, 163, 145, 182, 94, 91, 85, 166, 102, 135, 231, 187, 191, 109, 49, 186, 189, 75, 43, 164, 153, 120, 10, 217, 46, 226, 117, 116, 246, 131, 52, 51, 226, 123, 135, 65, 60, 203, 46, 53, 72, 120, 12, 193, 132, 247, 181, 64, 161, 64, 199, 93, 175, 253, 1, 140, 252, 80, 102, 156, 146, 22, 236, 67, 77, 147, 30, 244, 162, 167, 26, 254, 232, 242, 161, 86, 10, 32, 203, 38, 194, 13, 88, 211, 170, 92, 168, 184, 63, 53, 71, 219, 253, 40, 92, 40, 46, 59, 35, 165, 13, 126, 136, 63, 244, 72, 13, 178, 180, 6, 212, 176, 233, 35, 216, 27, 159, 108, 203, 113, 78, 215, 101, 184, 186, 69, 154, 232, 143, 174, 33, 251, 235, 24, 48, 47, 166, 239, 178, 114, 225, 169, 197, 124, 107, 55, 177, 68, 76, 52, 12, 232, 147, 168, 244, 228, 36, 34, 113, 227, 60, 35, 191, 30, 66, 128, 187, 163, 58, 100, 7, 182, 253, 113, 10, 15, 172, 6, 227, 213, 128, 137, 66, 212, 210, 63, 55, 192, 4, 182, 243, 143, 190, 186, 18, 236, 255, 201, 165, 232, 176, 231, 91, 142, 90, 223, 255, 206, 167, 239, 228, 4, 174, 65, 247, 88, 155, 204, 38, 247, 108, 62, 97, 148, 235, 120, 23, 223, 42, 175, 13, 92, 144, 243, 83, 86, 86, 153, 2, 120, 51, 199, 153, 162, 184, 200, 112, 31, 201, 165, 86, 36, 231, 187, 248, 104, 67, 170, 205, 16, 142, 179, 11, 168, 214, 181, 81, 7, 2, 41, 84, 155, 193, 33, 80, 225, 82, 7, 70, 150, 77, 249, 157, 71, 6, 203, 13, 247, 206, 160, 118, 150, 252, 1, 49, 20, 230, 54, 140, 130, 214, 252, 210, 236, 249, 144, 69, 31, 185, 161, 167, 165, 93, 223, 198, 200, 80, 173, 134, 52, 172, 161, 180, 212, 227, 150, 238, 176, 90, 125, 239, 156, 93, 109, 35, 75, 239, 201, 57, 74, 22, 107, 77, 103, 225, 249, 53, 202, 18, 148, 130, 212, 60, 78, 80, 122, 176, 63, 146, 18, 7, 84, 45, 204, 71, 2, 174, 78, 28, 50, 52, 41, 151, 159, 243, 147, 147, 172, 204, 198, 131, 236, 134, 170, 22, 139, 224, 34, 138, 37, 162, 241, 63, 179, 190, 40, 169, 132, 126, 81, 26, 159, 66, 105, 12, 179, 81, 54, 205, 110, 163, 222, 104, 213, 29, 87, 7, 180, 146, 253, 163, 203, 243, 243, 108, 90, 230, 131, 207, 165, 4, 176, 135, 237, 61, 126, 74, 47, 224, 143, 78, 184, 11, 1, 103, 197, 157, 183, 57, 23, 154, 91, 22, 99, 44, 190, 186, 157, 127, 118, 106, 197, 153, 251, 21, 4, 112, 10, 126, 58, 185, 161, 179, 146, 69, 112, 145, 89, 105, 225, 169, 231, 113, 120, 230, 137, 101, 67, 158, 199, 122, 253, 95, 236, 135, 54, 57, 75, 174, 50, 239, 184, 99, 224, 113, 186, 10, 162, 243, 249, 124, 2, 43, 167, 155, 205, 233, 26, 197, 79, 202, 235, 59, 243, 241, 250, 124, 218, 123, 201, 179, 116, 36, 235, 77, 131, 2, 94, 144, 101, 126, 206, 171, 255, 64, 60, 34, 244, 237, 182, 205, 215, 28, 251, 133, 167, 234, 47, 107, 253, 187, 103, 182, 251, 210, 112, 179, 237, 242, 5, 215, 243, 13, 221, 172, 17, 254, 127, 229, 217, 69, 54, 220, 45, 203, 244, 242, 167, 25, 88, 187, 251, 39, 135, 89, 126, 146, 67, 200, 69, 10, 111, 85, 51, 38, 33, 237, 219, 217, 73, 18, 187, 210, 74, 85, 208, 81, 232, 244, 220, 158, 81, 24, 162, 58, 92, 162, 7, 80, 244, 109, 59, 44, 125, 202, 207, 217, 52, 29, 188, 203, 134, 10, 23, 40, 126, 146, 145, 136, 30, 245, 59, 166, 86, 152, 250, 222, 214, 98, 106, 42, 105, 21, 69, 58, 171, 27, 136, 106, 42, 111, 70, 104, 121, 149, 149, 130, 219, 75, 238, 211, 64, 19, 114, 39, 213, 15, 234, 86, 244, 77, 119, 183, 97, 119, 170, 250, 79, 113, 164, 227, 128, 67, 160, 250, 211, 60, 118, 154, 6, 49, 194, 198, 246, 207, 190, 183, 199, 120, 16, 119, 85, 161, 5, 186, 40, 40, 108, 195, 60, 214, 49, 21, 136, 67, 67, 228, 198, 213, 172, 204, 0, 17, 85, 16, 36, 135, 214, 72, 203, 83, 26, 36, 100, 47, 196, 88, 85, 57, 73, 108, 77, 249, 82, 119, 47, 210, 62, 20, 217, 38, 163, 173, 187, 236, 79, 79, 48, 57, 89, 216, 193, 57, 42, 213, 17, 34, 157, 58, 186, 192, 228, 196, 187, 108, 193, 6, 46, 45, 53, 91, 159, 70, 254, 6, 234, 0, 14, 236, 142, 13, 108, 65, 61, 206, 131, 166, 211, 250, 4, 56, 92, 213, 107, 201, 69, 247, 67, 249, 28, 15, 101, 235, 54, 90, 59, 133, 44, 247, 77, 149, 124, 67, 48, 250, 38, 153, 224, 221, 208, 220, 190, 147, 83, 161, 248, 30, 202, 46, 164, 250, 79, 238, 80, 9, 164, 162, 112, 211, 147, 180, 238, 208, 62, 35, 172, 133, 115, 152, 77, 138, 114, 250, 107, 149, 158, 102, 242, 104, 7, 28, 142, 236, 9, 173, 113, 31, 206, 151, 245, 191, 131, 67, 233, 247, 87, 87, 105, 147, 149, 6, 27, 218, 157, 235, 227, 137, 172, 206, 223, 255, 142, 253, 49, 132, 72, 212, 182, 179, 162, 21, 33, 149, 207, 19, 66, 193, 231, 195, 116, 154, 57, 221, 241, 57, 159, 238, 129, 171, 15, 78, 21, 59, 73, 68, 100, 64, 147, 137, 75, 1, 77, 70, 225, 93, 70, 19, 109, 2, 74, 71, 203, 254, 35, 117, 117, 16, 175, 28, 85, 66, 212, 194, 112, 49, 12, 140, 194, 183, 127, 251, 46, 38, 96, 42, 178, 6, 116, 10, 158, 203, 32, 131, 192, 243, 4, 168, 41, 253, 194, 86, 77, 106, 110, 182, 149, 216, 80, 80, 225, 23, 230, 142, 58, 217, 171, 192, 16, 179, 6, 237, 49, 27, 121, 172, 55, 74, 86, 236, 137, 95, 87, 30, 161, 201, 224, 180, 38, 207, 15, 231, 145, 235, 123, 221, 117, 123, 48, 150, 103, 53, 181, 128, 27, 233, 138, 35, 203, 232, 170, 167, 194, 183, 151, 211, 236, 224, 228, 68, 26, 106, 215, 77, 107, 108, 83, 61, 219, 118, 23, 29, 135, 249, 169, 191, 16, 245, 132, 5, 161, 114, 104, 181, 35, 227, 167, 38, 223, 205, 33, 153, 158, 41, 93, 121, 206, 62, 100, 231, 147, 81, 26, 16, 102, 184, 20, 188, 118, 166, 213, 85, 41, 42, 53, 154, 99, 207, 52, 209, 22, 69, 28, 83, 1, 221, 96, 185, 66, 41, 205, 217, 20, 153, 244, 26, 58, 128, 120, 236, 213, 10, 102, 219, 78, 185, 28, 219, 162, 119, 215, 209, 39, 23, 141, 96, 231, 98, 157, 130, 37, 177, 13, 241, 116, 253, 29, 77, 22, 233, 65, 43, 110, 63, 160, 61, 80, 120, 203, 207, 52, 226, 112, 43, 138, 224, 251, 172, 188, 36, 49, 172, 201, 85, 48, 109, 63, 165, 88, 71, 71, 67, 250, 17, 119, 70, 249, 86, 30, 244, 238, 252, 151, 133, 248, 95, 27, 38, 219, 228, 70, 6, 189, 233, 184, 182, 230, 53, 197, 76, 219, 192, 115, 191, 15, 143, 147, 190, 88, 137, 242, 44, 36, 9, 9, 30, 101, 30, 189, 179, 68, 38, 30, 57, 83, 211, 169, 120, 224, 169, 70, 206, 48, 233, 125, 114, 112, 124, 246, 218, 186, 114, 166, 89, 101, 179, 31, 182, 14, 76, 62, 195, 212, 206, 103, 214, 47, 36, 169, 100, 161, 45, 224, 237, 59, 170, 57, 81, 236, 176, 26, 141, 51, 182, 159, 224, 230, 146, 46, 6, 75, 87, 152, 79, 100, 179, 135, 57, 138, 156, 229, 6, 95, 64, 168, 67, 81, 127, 254, 9, 169, 229, 200, 156, 193, 78, 116, 52, 56, 6, 27, 214, 94, 220, 63, 248, 158, 230, 27, 86, 105, 89, 240, 7, 228, 25, 194, 199, 14, 239, 89, 192, 105, 72, 101, 139, 45, 187, 235, 87, 179, 84, 196, 34, 50, 37, 57, 70, 197, 11, 11, 88, 182, 16, 132, 254, 18, 177, 59, 211, 145, 192, 127, 3, 226, 153, 95, 253, 77, 203, 121, 138, 233, 94, 21, 63, 229, 167, 251, 130, 129, 237, 254, 179, 227, 217, 210, 229, 94, 204, 206, 223, 102, 37, 45, 183, 162, 55, 20, 71, 233, 52, 127, 159, 53, 101, 138, 57, 195, 36, 44, 188, 124, 67, 202, 23, 86, 56, 158, 247, 197, 41, 70, 179, 180, 232, 79, 87, 72, 177, 230, 32, 142, 41, 100, 218, 160, 141, 217, 100, 234, 145, 102, 137, 101, 106, 92, 85, 109, 156, 55, 7, 206, 194, 117, 97, 223, 77, 45, 23, 34, 85, 2, 185, 223, 108, 71, 84, 2, 21, 169, 246, 228, 23, 166, 248, 64, 215, 137, 250, 146, 153, 156, 85, 195, 65, 100, 42, 19, 162, 6, 11, 236, 187, 50, 151, 157, 200, 238, 124, 170, 201, 236, 213, 194, 211, 152, 114, 109, 79, 48, 194, 241, 205, 179, 188, 34, 33, 142, 131, 116, 34, 198, 76, 166, 131, 216, 188, 226, 156, 23, 243, 217, 211, 105, 238, 149, 51, 193, 217, 185, 12, 48, 60, 214, 216, 172, 173, 1, 111, 169, 146, 124, 98, 131, 182, 119, 131, 150, 163, 107, 164, 31, 244, 76, 231, 156, 253, 57, 213, 51, 88, 28, 235, 2, 226, 151, 237, 222, 238, 241, 88, 182, 14, 8, 141, 221, 244, 150, 187, 237, 167, 83, 197, 238, 177, 249, 84, 40, 251, 137, 104, 57, 135, 235, 193, 110, 187, 28, 140, 135, 113, 41, 48, 157, 156, 71, 8, 72, 165, 27, 98, 208, 197, 152, 219, 96, 26, 51, 225, 60, 107, 45, 196, 213, 248, 137, 32, 219, 158, 201, 228, 84, 23, 97, 49, 117, 207, 247, 109, 225, 51, 164, 147, 96, 55, 124, 218, 52, 246, 90, 13, 235, 201, 62, 54, 156, 197, 188, 109, 76, 56, 15, 183, 1, 143, 70, 121, 45, 200, 102, 235, 253, 249, 248, 75, 95, 55, 31, 98, 50, 239, 188, 239, 13, 231, 49, 173, 203, 44, 64, 202, 78, 120, 176, 247, 14, 173, 79, 91, 175, 59, 9, 27, 57, 83, 222, 34, 90, 73, 17, 50, 204, 51, 251, 234, 190, 27, 188, 159, 224, 201, 72, 222, 153, 162, 82, 41, 234, 44, 76, 155, 55, 97, 37, 201, 241, 195, 151, 6, 203, 192, 82, 18, 59, 230, 232, 162, 54, 11, 70, 119, 181, 89, 107, 186, 107, 223, 126, 40, 137, 214, 122, 159, 50, 24, 207, 228, 104, 80, 183, 27, 244, 58, 107, 40, 89, 3, 136, 87, 61, 175, 229, 255, 206, 202, 226, 96, 124, 48, 155, 30, 156, 252, 84, 8, 126, 168, 32, 190, 199, 64, 81, 153, 21, 31, 203, 100, 197, 181, 248, 156, 177, 210, 6, 119, 96, 223, 177, 183, 110, 133, 183, 106, 41, 54, 182, 83, 240, 25, 61, 157, 152, 32, 227, 51, 29, 71, 22, 45, 174, 44, 108, 91, 56, 106, 245, 242, 232, 17, 31, 228, 185, 244, 103, 128, 179, 255, 79, 1, 185, 141, 77, 42, 245, 27, 193, 195, 58, 53, 190, 207, 174, 128, 237, 117, 243, 170, 10, 105, 154, 200, 144, 160, 96, 62, 121, 56, 178, 216, 235, 200, 197, 123, 52, 21, 125, 140, 217, 109, 198, 56, 137, 135, 186, 112, 225, 42, 220, 204, 239, 109, 112, 155, 11, 221, 117, 139, 119, 22, 67, 239, 228, 186, 57, 89, 199, 124, 138, 38, 8, 5, 80, 203, 20, 123, 109, 74, 139, 82, 5, 66, 153, 111, 44, 13, 191, 46, 200, 23, 44, 192, 229, 125, 100, 105, 192, 206, 179, 87, 177, 26, 51, 88, 145, 217, 15, 229, 77, 85, 98, 4, 214, 188, 86, 216, 44, 167, 186, 189, 67, 69, 88, 86, 109, 217, 105, 123, 227, 2, 145, 147, 195, 136, 152, 252, 51, 187, 252, 252, 14, 247, 205, 152, 195, 29, 110, 192, 10, 78, 81, 201, 162, 2, 29, 182, 82, 30, 243, 51, 254, 81, 153, 111, 41, 245, 92, 238, 35, 179, 87, 226, 88, 20, 246, 125, 39, 72, 128, 14, 126, 39, 129, 246, 159, 96, 142, 173, 195, 229, 166, 76, 171, 49, 139, 205, 78, 183, 78, 134, 115, 161, 226, 80, 63, 44, 111, 226, 213, 202, 65, 77, 167, 204, 143, 41, 0, 142, 173, 70, 194, 198, 113, 42, 53, 83, 228, 99, 101, 54, 174, 175, 127, 178, 25, 242, 121, 58, 185, 125, 107, 133, 200, 226, 243, 60, 157, 220, 14, 231, 95, 107, 127, 25, 115, 252, 182, 240, 147, 156, 75, 122, 107, 103, 73, 11, 223, 159, 179, 200, 0, 95, 155, 244, 34, 19, 64, 139, 251, 219, 4, 111, 133, 23, 28, 135, 217, 112, 54, 200, 238, 12, 223, 149, 178, 59, 159, 130, 245, 152, 74, 132, 24, 203, 134, 91, 37, 220, 126, 240, 100, 33, 198, 88, 135, 31, 233, 96, 48, 59, 159, 141, 48, 163, 120, 107, 222, 22, 12, 180, 182, 246, 154, 41, 49, 159, 53, 57, 236, 154, 75, 74, 253, 108, 95, 222, 245, 164, 4, 150, 126, 37, 153, 88, 47, 64, 204, 75, 62, 59, 33, 247, 146, 218, 17, 133, 168, 120, 243, 48, 63, 125, 55, 189, 61, 12, 138, 125, 158, 195, 81, 87, 218, 110, 126, 178, 180, 105, 203, 231, 94, 50, 129, 95, 141, 135, 215, 215, 57, 15, 123, 19, 241, 237, 98, 225, 247, 112, 152, 171, 123, 19, 214, 187, 29, 15, 173, 79, 177, 194, 61, 207, 135, 195, 81, 70, 13, 186, 147, 81, 81, 200, 75, 153, 146, 191, 98, 206, 47, 51, 167, 142, 138, 11, 185, 5, 44, 6, 92, 61, 194, 81, 0, 5, 1, 223, 240, 73, 118, 38, 250, 90, 26, 230, 83, 85, 214, 245, 21, 21, 6, 160, 221, 177, 144, 63, 73, 24, 138, 172, 111, 63, 203, 159, 248, 89, 23, 134, 24, 14, 83, 74, 127, 82, 5, 161, 97, 3, 223, 97, 141, 216, 62, 239, 81, 240, 74, 156, 54, 103, 201, 56, 151, 28, 44, 141, 69, 14, 230, 8, 8, 145, 216, 183, 227, 26, 87, 223, 214, 176, 200, 151, 16, 139, 101, 134, 88, 200, 157, 107, 188, 216, 193, 191, 142, 78, 136, 199, 25, 189, 13, 163, 253, 126, 49, 187, 235, 70, 53, 240, 56, 217, 164, 210, 40, 175, 237, 25, 50, 128, 63, 229, 211, 139, 188, 202, 20, 215, 11, 40, 187, 210, 194, 181, 176, 144, 213, 85, 77, 187, 128, 170, 139, 192, 8, 48, 146, 137, 134, 183, 91, 216, 248, 2, 207, 255, 153, 48, 13, 26, 85, 191, 123, 60, 86, 123, 233, 214, 112, 130, 127, 193, 211, 97, 187, 49, 113, 46, 206, 239, 142, 241, 92, 137, 206, 220, 165, 253, 157, 79, 21, 127, 88, 19, 126, 104, 175, 114, 113, 24, 10, 227, 18, 219, 174, 223, 128, 207, 194, 11, 184, 87, 197, 179, 66, 32, 155, 161, 255, 114, 36, 127, 84, 52, 242, 176, 151, 20, 19, 168, 196, 94, 90, 70, 77, 49, 52, 190, 45, 179, 166, 38, 46, 189, 61, 195, 218, 58, 237, 125, 214, 39, 121, 89, 77, 159, 24, 239, 173, 4, 81, 235, 32, 150, 160, 66, 99, 73, 33, 109, 76, 25, 189, 122, 172, 25, 121, 139, 175, 134, 77, 156, 242, 224, 134, 143, 122, 157, 29, 166, 211, 78, 229, 20, 175, 101, 50, 106, 41, 251, 224, 245, 134, 6, 80, 176, 239, 225, 188, 152, 3, 209, 175, 124, 76, 25, 138, 187, 178, 13, 37, 66, 68, 32, 240, 61, 26, 144, 111, 171, 174, 141, 27, 115, 84, 31, 205, 222, 202, 78, 116, 223, 102, 167, 249, 216, 177, 101, 218, 220, 49, 117, 47, 122, 36, 107, 153, 70, 175, 194, 174, 222, 168, 193, 158, 4, 34, 93, 219, 196, 36, 234, 115, 98, 109, 66, 27, 201, 196, 200, 15, 153, 153, 67, 128, 229, 224, 153, 190, 21, 180, 217, 223, 169, 107, 99, 205, 159, 76, 68, 63, 111, 202, 188, 102, 21, 180, 241, 240, 19, 80, 136, 89, 93, 146, 102, 166, 156, 252, 133, 155, 207, 204, 138, 81, 21, 163, 118, 140, 237, 202, 26, 175, 210, 108, 207, 96, 49, 3, 193, 224, 130, 187, 51, 58, 93, 171, 141, 206, 182, 239, 89, 31, 37, 238, 140, 44, 156, 76, 107, 180, 119, 127, 161, 224, 245, 136, 250, 230, 158, 88, 44, 147, 109, 237, 106, 119, 54, 213, 151, 59, 5, 120, 184, 198, 180, 10, 156, 16, 129, 127, 144, 132, 85, 243, 46, 57, 108, 148, 184, 125, 241, 153, 181, 217, 78, 181, 67, 18, 179, 86, 51, 140, 104, 153, 199, 96, 13, 13, 116, 123, 179, 213, 31, 228, 113, 118, 97, 100, 192, 189, 12, 87, 33, 183, 78, 134, 205, 185, 15, 175, 134, 224, 148, 206, 134, 202, 236, 64, 23, 167, 176, 122, 105, 176, 89, 137, 159, 79, 222, 157, 170, 107, 221, 110, 138, 2, 36, 60, 148, 71, 226, 49, 118, 93, 95, 83, 195, 41, 216, 154, 133, 92, 72, 169, 232, 96, 21, 203, 101, 252, 246, 57, 19, 237, 192, 43, 184, 145, 15, 236, 171, 196, 52, 28, 5, 225, 151, 91, 33, 49, 17, 242, 144, 64, 56, 6, 131, 217, 148, 100, 214, 19, 125, 146, 179, 115, 91, 251, 108, 119, 26, 182, 206, 32, 68, 12, 246, 233, 110, 77, 156, 97, 139, 120, 86, 232, 207, 45, 140, 105, 213, 14, 202, 144, 75, 241, 22, 6, 182, 194, 40, 212, 243, 220, 255, 134, 0, 87, 211, 207, 219, 26, 228, 90, 199, 149, 55, 43, 210, 213, 144, 154, 114, 221, 87, 182, 140, 228, 240, 207, 31, 187, 210, 95, 13, 95, 64, 226, 34, 42, 116, 156, 202, 240, 212, 137, 69, 98, 14, 70, 179, 161, 232, 208, 29, 12, 197, 84, 61, 251, 156, 65, 35, 94, 246, 160, 198, 112, 204, 79, 21, 35, 73, 60, 134, 196, 92, 128, 186, 71, 130, 143, 36, 239, 192, 66, 204, 101, 11, 144, 63, 95, 242, 184, 251, 39, 1, 63, 129, 99, 104, 24, 63, 80, 104, 137, 45, 175, 170, 149, 121, 231, 170, 98, 86, 14, 132, 188, 159, 167, 147, 147, 49, 119, 238, 212, 94, 33, 181, 231, 91, 161, 244, 24, 249, 94, 84, 29, 62, 48, 87, 103, 237, 49, 229, 7, 209, 8, 242, 182, 84, 5, 79, 225, 115, 47, 228, 175, 112, 85, 176, 44, 74, 72, 212, 164, 128, 251, 216, 91, 126, 211, 43, 182, 159, 216, 91, 146, 217, 160, 219, 207, 30, 135, 189, 66, 82, 8, 216, 154, 159, 102, 21, 185, 47, 24, 86, 27, 146, 202, 129, 4, 60, 230, 174, 112, 155, 129, 135, 215, 189, 231, 46, 17, 253, 207, 212, 33, 224, 210, 134, 149, 142, 211, 232, 251, 190, 63, 73, 41, 156, 57, 145, 36, 120, 77, 10, 39, 253, 19, 31, 126, 245, 21, 53, 151, 6, 101, 154, 7, 56, 248, 152, 184, 196, 18, 61, 242, 116, 170, 128, 102, 138, 51, 229, 135, 144, 233, 119, 166, 184, 95, 234, 73, 253, 96, 50, 205, 207, 213, 178, 184, 171, 87, 143, 212, 103, 31, 81, 82, 8, 127, 219, 148, 171, 81, 78, 193, 178, 83, 152, 248, 32, 63, 99, 82, 147, 35, 100, 175, 151, 236, 217, 125, 22, 84, 180, 45, 252, 208, 168, 179, 117, 19, 42, 172, 7, 121, 237, 236, 181, 133, 245, 209, 60, 105, 245, 161, 171, 232, 50, 31, 91, 14, 76, 116, 76, 94, 166, 131, 179, 165, 15, 202, 156, 4, 84, 237, 210, 107, 176, 145, 217, 201, 12, 149, 203, 132, 149, 20, 91, 211, 128, 97, 249, 237, 150, 228, 114, 210, 215, 130, 27, 124, 31, 111, 246, 123, 85, 200, 19, 159, 90, 187, 114, 49, 180, 190, 91, 197, 73, 170, 54, 185, 0, 222, 200, 113, 76, 186, 44, 145, 2, 185, 180, 246, 156, 92, 90, 91, 92, 134, 93, 162, 146, 54, 194, 41, 87, 176, 118, 59, 134, 100, 11, 30, 213, 49, 194, 138, 126, 252, 26, 42, 19, 67, 241, 31, 131, 142, 118, 169, 175, 249, 65, 214, 85, 83, 229, 33, 91, 4, 121, 242, 224, 132, 185, 57, 1, 181, 108, 104, 181, 70, 151, 94, 219, 103, 249, 153, 58, 193, 207, 149, 152, 99, 161, 104, 23, 157, 169, 66, 217, 175, 253, 224, 44, 54, 40, 115, 239, 85, 25, 44, 217, 158, 85, 221, 136, 204, 61, 30, 124, 52, 234, 199, 130, 38, 205, 176, 227, 80, 99, 178, 28, 156, 116, 201, 106, 83, 13, 129, 183, 86, 210, 244, 92, 186, 137, 50, 206, 46, 150, 61, 58, 10, 164, 34, 14, 93, 220, 157, 185, 187, 37, 170, 32, 35, 14, 153, 37, 231, 188, 51, 209, 171, 88, 115, 117, 162, 205, 20, 202, 85, 27, 92, 156, 39, 234, 157, 203, 117, 132, 106, 215, 152, 211, 185, 181, 124, 130, 220, 35, 235, 244, 228, 37, 126, 213, 42, 25, 30, 148, 180, 220, 181, 87, 92, 107, 229, 190, 51, 44, 31, 48, 135, 177, 104, 79, 215, 101, 185, 251, 141, 122, 62, 126, 109, 80, 212, 6, 122, 36, 245, 249, 88, 93, 5, 16, 219, 240, 122, 110, 187, 64, 117, 58, 239, 135, 147, 104, 214, 237, 5, 220, 32, 7, 69, 58, 158, 137, 5, 111, 55, 26, 178, 166, 255, 44, 77, 194, 159, 211, 105, 250, 18, 147, 29, 154, 196, 194, 249, 218, 154, 218, 122, 219, 224, 89, 71, 144, 47, 84, 49, 198, 74, 196, 228, 89, 60, 142, 136, 230, 164, 230, 75, 240, 185, 179, 82, 147, 234, 109, 22, 170, 177, 248, 34, 183, 91, 1, 95, 142, 151, 234, 227, 32, 198, 117, 52, 203, 7, 213, 62, 166, 9, 112, 240, 47, 28, 130, 36, 119, 139, 191, 132, 33, 181, 12, 67, 82, 123, 39, 177, 56, 36, 73, 75, 26, 139, 132, 25, 92, 3, 233, 206, 14, 122, 177, 219, 202, 200, 192, 118, 86, 105, 195, 111, 234, 12, 81, 149, 56, 80, 253, 95, 33, 105, 170, 230, 21, 178, 48, 93, 67, 34, 204, 159, 48, 213, 47, 166, 79, 54, 111, 194, 2, 5, 72, 172, 174, 6, 215, 126, 30, 59, 27, 80, 113, 69, 100, 179, 126, 126, 116, 87, 189, 20, 17, 104, 149, 105, 57, 236, 142, 131, 89, 115, 107, 15, 184, 190, 35, 100, 177, 94, 13, 178, 14, 137, 31, 207, 106, 214, 18, 164, 7, 228, 212, 149, 75, 164, 87, 66, 151, 152, 67, 87, 74, 69, 180, 164, 213, 138, 214, 215, 134, 76, 98, 76, 14, 162, 10, 228, 91, 166, 64, 210, 193, 116, 150, 142, 158, 133, 156, 223, 97, 173, 98, 169, 171, 57, 197, 130, 216, 209, 236, 22, 107, 251, 59, 205, 144, 61, 219, 240, 146, 52, 225, 96, 86, 150, 66, 8, 158, 53, 42, 68, 104, 70, 41, 186, 29, 82, 137, 78, 187, 126, 124, 33, 156, 169, 66, 188, 73, 59, 40, 228, 250, 64, 139, 109, 19, 174, 230, 129, 73, 209, 18, 75, 110, 59, 29, 244, 180, 86, 144, 45, 244, 44, 219, 5, 12, 45, 45, 141, 53, 105, 210, 129, 101, 184, 181, 229, 145, 207, 79, 181, 253, 21, 157, 143, 230, 179, 216, 252, 154, 109, 76, 182, 175, 142, 222, 165, 37, 227, 166, 121, 47, 215, 142, 212, 111, 211, 184, 95, 119, 41, 150, 133, 7, 118, 161, 91, 47, 92, 32, 87, 177, 50, 194, 29, 13, 4, 253, 40, 139, 193, 43, 254, 197, 110, 184, 75, 118, 131, 55, 188, 215, 111, 61, 160, 247, 66, 155, 14, 106, 141, 26, 21, 23, 180, 30, 92, 137, 225, 147, 122, 180, 90, 100, 94, 252, 110, 179, 205, 172, 110, 144, 211, 182, 4, 153, 64, 15, 240, 242, 240, 3, 16, 120, 175, 249, 234, 121, 118, 94, 148, 151, 176, 83, 130, 133, 233, 134, 164, 135, 76, 235, 137, 182, 78, 24, 85, 59, 243, 207, 181, 223, 109, 214, 206, 181, 94, 147, 116, 202, 146, 29, 99, 243, 149, 6, 196, 39, 172, 184, 87, 192, 245, 77, 0, 201, 224, 93, 36, 83, 179, 189, 229, 192, 50, 177, 32, 83, 52, 199, 255, 156, 73, 155, 67, 233, 222, 35, 232, 190, 42, 240, 240, 208, 240, 166, 29, 106, 178, 152, 125, 138, 115, 77, 252, 224, 132, 51, 136, 11, 156, 23, 134, 45, 79, 19, 15, 112, 198, 79, 49, 193, 55, 27, 157, 2, 191, 208, 45, 136, 71, 132, 205, 119, 199, 72, 138, 157, 90, 128, 145, 87, 1, 89, 250, 102, 160, 27, 48, 146, 44, 82, 141, 101, 170, 237, 112, 204, 63, 197, 232, 182, 141, 99, 83, 122, 195, 132, 157, 213, 71, 180, 145, 194, 141, 177, 109, 188, 108, 77, 148, 155, 100, 173, 155, 149, 50, 151, 45, 52, 154, 163, 152, 15, 236, 38, 191, 85, 224, 170, 231, 24, 188, 71, 95, 9, 130, 250, 107, 18, 169, 218, 15, 211, 241, 169, 89, 250, 240, 3, 170, 215, 33, 172, 90, 32, 207, 36, 33, 41, 138, 63, 34, 145, 30, 146, 80, 178, 5, 37, 85, 88, 6, 69, 57, 21, 186, 22, 54, 125, 197, 132, 116, 50, 182, 162, 106, 94, 181, 219, 127, 183, 16, 218, 239, 193, 195, 1, 30, 91, 141, 175, 168, 63, 77, 32, 217, 178, 71, 15, 199, 65, 15, 12, 61, 11, 77, 146, 206, 120, 23, 141, 217, 230, 223, 84, 5, 88, 216, 187, 148, 50, 181, 131, 249, 239, 44, 61, 123, 158, 78, 200, 84, 13, 219, 155, 202, 123, 46, 198, 197, 46, 175, 206, 211, 137, 163, 166, 210, 225, 80, 250, 116, 196, 23, 184, 198, 141, 172, 187, 204, 168, 202, 34, 117, 65, 109, 184, 69, 162, 202, 105, 68, 217, 237, 108, 251, 211, 236, 60, 116, 57, 155, 69, 209, 97, 41, 226, 55, 135, 186, 113, 126, 122, 240, 173, 88, 129, 98, 255, 185, 251, 60, 228, 176, 151, 40, 202, 160, 143, 158, 193, 235, 120, 243, 53, 249, 209, 127, 141, 61, 112, 200, 43, 239, 250, 109, 34, 175, 138, 255, 15, 145, 87, 124, 217, 16, 207, 215, 68, 222, 232, 229, 119, 62, 125, 107, 168, 34, 239, 160, 224, 151, 251, 10, 50, 252, 127, 27, 8, 248, 46 }; + static const unsigned char data[] = { 120, 156, 237, 125, 107, 83, 28, 71, 178, 232, 119, 126, 69, 51, 225, 99, 15, 102, 224, 48, 72, 246, 122, 133, 36, 47, 198, 146, 151, 176, 36, 20, 140, 118, 55, 226, 112, 21, 58, 173, 153, 6, 122, 25, 186, 199, 221, 61, 2, 108, 235, 252, 246, 91, 89, 207, 204, 122, 244, 99, 24, 36, 96, 165, 8, 155, 158, 238, 170, 172, 172, 172, 204, 172, 172, 172, 172, 172, 227, 121, 54, 174, 210, 60, 139, 178, 228, 226, 221, 97, 50, 206, 139, 73, 127, 45, 250, 99, 37, 138, 138, 164, 154, 23, 89, 84, 86, 147, 119, 7, 239, 255, 157, 140, 171, 119, 227, 34, 137, 171, 164, 159, 205, 167, 211, 181, 157, 149, 143, 43, 199, 170, 238, 155, 252, 167, 60, 159, 38, 113, 214, 255, 64, 234, 174, 174, 126, 176, 202, 189, 154, 159, 191, 79, 10, 171, 216, 58, 45, 53, 138, 207, 147, 127, 198, 211, 121, 242, 63, 73, 145, 247, 47, 7, 209, 21, 41, 125, 25, 61, 121, 242, 36, 186, 138, 254, 252, 51, 234, 95, 70, 171, 236, 249, 50, 250, 250, 107, 246, 2, 30, 175, 40, 98, 191, 36, 213, 203, 164, 58, 205, 39, 253, 127, 14, 162, 215, 2, 204, 206, 14, 251, 223, 135, 184, 136, 160, 84, 244, 36, 250, 231, 209, 235, 183, 240, 42, 61, 142, 250, 251, 229, 43, 214, 185, 131, 226, 31, 217, 36, 57, 78, 179, 100, 210, 135, 66, 107, 162, 162, 198, 96, 174, 190, 66, 181, 143, 178, 234, 234, 126, 185, 23, 79, 167, 241, 251, 105, 66, 43, 189, 57, 45, 242, 139, 55, 87, 179, 228, 89, 81, 228, 69, 127, 184, 61, 136, 42, 246, 43, 63, 230, 8, 172, 41, 24, 18, 54, 188, 35, 93, 216, 47, 95, 23, 249, 44, 41, 170, 171, 95, 147, 171, 126, 92, 156, 204, 207, 147, 172, 18, 192, 161, 23, 0, 139, 245, 66, 130, 84, 223, 119, 12, 68, 81, 128, 209, 166, 87, 86, 69, 154, 157, 244, 128, 114, 232, 229, 213, 249, 251, 124, 218, 163, 35, 48, 75, 198, 105, 82, 238, 229, 25, 171, 50, 31, 87, 12, 237, 252, 253, 191, 7, 17, 235, 118, 60, 159, 86, 232, 189, 69, 82, 120, 197, 144, 97, 133, 55, 199, 166, 144, 162, 174, 248, 202, 26, 213, 4, 180, 8, 235, 194, 183, 40, 44, 24, 145, 3, 10, 209, 247, 187, 239, 7, 81, 47, 231, 229, 190, 41, 163, 111, 16, 26, 223, 68, 51, 73, 201, 158, 166, 58, 32, 93, 50, 140, 225, 251, 17, 227, 150, 159, 230, 233, 180, 74, 179, 17, 39, 74, 191, 87, 10, 66, 244, 214, 106, 56, 164, 180, 217, 163, 190, 23, 251, 132, 172, 78, 229, 82, 149, 181, 186, 197, 203, 12, 31, 14, 248, 223, 222, 223, 254, 38, 49, 211, 93, 138, 216, 224, 235, 94, 163, 78, 247, 88, 5, 71, 38, 12, 216, 205, 205, 77, 198, 50, 165, 64, 162, 42, 174, 36, 50, 99, 198, 201, 207, 101, 133, 62, 104, 0, 245, 227, 93, 60, 155, 77, 175, 6, 22, 118, 3, 51, 162, 131, 136, 195, 227, 189, 96, 96, 170, 241, 105, 212, 79, 172, 62, 38, 170, 143, 59, 54, 98, 187, 39, 39, 69, 114, 194, 148, 204, 18, 176, 163, 176, 150, 134, 226, 126, 86, 37, 69, 22, 79, 151, 128, 33, 1, 181, 28, 4, 129, 57, 117, 195, 172, 10, 250, 180, 151, 207, 174, 126, 142, 171, 88, 170, 19, 198, 60, 253, 138, 181, 147, 84, 131, 168, 204, 231, 197, 56, 25, 68, 201, 229, 120, 58, 159, 36, 147, 253, 42, 57, 47, 145, 104, 239, 212, 112, 63, 175, 106, 113, 49, 150, 174, 227, 34, 63, 103, 2, 246, 38, 151, 178, 43, 43, 40, 141, 113, 150, 92, 129, 252, 185, 200, 29, 20, 140, 216, 7, 23, 25, 211, 122, 6, 81, 0, 102, 163, 169, 112, 19, 144, 152, 118, 225, 243, 147, 23, 159, 99, 166, 127, 250, 208, 106, 202, 240, 103, 243, 72, 180, 181, 35, 31, 31, 115, 68, 54, 167, 73, 118, 82, 157, 202, 151, 235, 235, 10, 138, 68, 148, 85, 128, 82, 71, 252, 43, 215, 8, 162, 101, 254, 16, 69, 171, 167, 113, 201, 16, 6, 68, 28, 82, 126, 253, 181, 44, 228, 112, 134, 156, 91, 149, 28, 239, 151, 207, 50, 166, 193, 11, 152, 71, 84, 127, 25, 192, 53, 94, 93, 225, 19, 69, 63, 115, 242, 35, 138, 93, 105, 26, 241, 230, 161, 226, 17, 123, 122, 187, 38, 208, 252, 200, 41, 80, 203, 13, 255, 200, 142, 153, 238, 75, 10, 54, 168, 148, 47, 16, 35, 220, 30, 30, 144, 70, 200, 231, 30, 250, 69, 135, 115, 137, 35, 153, 207, 217, 160, 81, 155, 77, 127, 75, 179, 76, 127, 211, 95, 123, 199, 121, 222, 227, 116, 33, 170, 99, 183, 40, 226, 171, 103, 31, 146, 226, 138, 247, 234, 125, 60, 62, 59, 206, 34, 99, 104, 28, 224, 17, 172, 78, 211, 82, 143, 31, 35, 29, 255, 246, 130, 147, 176, 127, 32, 105, 169, 135, 103, 87, 26, 37, 165, 44, 176, 198, 199, 106, 43, 52, 129, 127, 55, 136, 182, 216, 28, 206, 241, 217, 100, 132, 172, 114, 176, 86, 54, 19, 64, 205, 204, 220, 182, 205, 101, 112, 174, 179, 188, 126, 102, 22, 238, 249, 44, 157, 38, 12, 167, 62, 107, 5, 215, 194, 28, 251, 134, 117, 200, 69, 251, 105, 52, 140, 126, 228, 243, 148, 252, 212, 31, 174, 69, 143, 168, 61, 168, 25, 237, 76, 48, 217, 25, 99, 48, 70, 15, 246, 96, 152, 138, 243, 44, 27, 156, 232, 192, 240, 1, 239, 15, 160, 195, 204, 131, 138, 129, 214, 92, 101, 80, 100, 211, 198, 32, 58, 56, 58, 123, 203, 88, 131, 61, 32, 38, 50, 35, 31, 79, 203, 100, 71, 190, 253, 136, 24, 198, 152, 131, 197, 60, 129, 113, 31, 177, 169, 172, 220, 207, 166, 105, 6, 228, 123, 1, 44, 167, 155, 52, 172, 192, 136, 66, 25, 100, 148, 159, 39, 183, 147, 63, 74, 134, 217, 253, 102, 143, 107, 115, 135, 24, 251, 26, 230, 144, 236, 211, 130, 59, 128, 15, 28, 230, 120, 158, 23, 207, 226, 241, 233, 237, 228, 143, 99, 129, 220, 253, 101, 145, 110, 236, 177, 227, 27, 127, 132, 71, 11, 30, 144, 195, 237, 176, 193, 203, 120, 118, 59, 89, 224, 60, 158, 221, 254, 225, 135, 218, 187, 96, 14, 197, 217, 193, 172, 74, 207, 211, 223, 19, 33, 113, 98, 197, 215, 103, 35, 254, 35, 247, 202, 240, 183, 125, 70, 40, 0, 129, 139, 236, 9, 63, 205, 193, 0, 200, 186, 118, 29, 150, 130, 42, 140, 104, 179, 100, 194, 29, 50, 176, 80, 94, 128, 201, 188, 70, 206, 46, 47, 130, 128, 251, 57, 114, 183, 21, 39, 50, 142, 115, 149, 17, 183, 102, 111, 39, 35, 10, 75, 251, 158, 240, 226, 209, 219, 32, 255, 109, 121, 184, 111, 16, 85, 121, 119, 46, 60, 83, 12, 8, 220, 165, 216, 170, 229, 164, 40, 234, 122, 166, 69, 63, 91, 86, 249, 250, 186, 170, 164, 57, 216, 59, 93, 182, 99, 78, 193, 136, 14, 127, 30, 38, 147, 249, 248, 150, 218, 82, 5, 199, 237, 83, 241, 167, 80, 74, 242, 71, 60, 30, 207, 207, 231, 211, 24, 249, 13, 189, 188, 171, 218, 69, 229, 25, 24, 202, 206, 194, 131, 146, 48, 155, 6, 113, 23, 167, 32, 166, 73, 20, 85, 128, 187, 67, 155, 109, 164, 145, 36, 162, 175, 139, 164, 100, 160, 89, 67, 200, 208, 158, 228, 196, 74, 179, 185, 55, 194, 213, 176, 5, 22, 69, 239, 153, 160, 156, 89, 28, 22, 93, 156, 50, 138, 69, 253, 245, 117, 41, 30, 107, 102, 181, 185, 170, 32, 117, 67, 157, 146, 136, 9, 208, 250, 250, 91, 178, 46, 110, 47, 138, 20, 148, 79, 246, 116, 231, 144, 16, 234, 119, 198, 197, 165, 95, 33, 136, 230, 37, 159, 66, 12, 253, 208, 7, 249, 228, 159, 44, 8, 239, 216, 75, 91, 33, 111, 135, 233, 201, 105, 245, 69, 232, 132, 208, 65, 191, 54, 162, 225, 23, 209, 163, 162, 183, 177, 113, 22, 61, 125, 34, 39, 175, 229, 74, 222, 198, 134, 43, 121, 79, 197, 100, 184, 177, 113, 79, 5, 239, 121, 154, 77, 250, 51, 198, 221, 233, 152, 153, 5, 183, 72, 224, 24, 65, 38, 97, 113, 211, 24, 119, 145, 54, 84, 233, 211, 45, 6, 3, 246, 81, 200, 58, 210, 56, 214, 25, 71, 114, 96, 197, 215, 101, 172, 21, 25, 173, 61, 38, 122, 54, 217, 7, 143, 234, 23, 246, 184, 97, 95, 65, 51, 31, 120, 61, 71, 138, 11, 188, 12, 176, 49, 108, 61, 242, 124, 144, 157, 225, 7, 135, 255, 191, 82, 54, 178, 153, 217, 113, 96, 15, 236, 79, 146, 77, 34, 103, 155, 120, 113, 158, 128, 239, 69, 194, 212, 83, 250, 33, 121, 195, 91, 226, 69, 97, 255, 237, 132, 45, 17, 69, 227, 186, 36, 44, 79, 86, 68, 239, 73, 149, 199, 209, 150, 36, 139, 88, 127, 191, 140, 171, 211, 119, 231, 241, 37, 159, 214, 214, 173, 210, 176, 246, 145, 165, 31, 161, 210, 172, 171, 118, 57, 101, 226, 97, 36, 71, 64, 6, 130, 35, 39, 140, 46, 39, 54, 84, 8, 146, 162, 74, 75, 28, 71, 130, 204, 77, 40, 202, 98, 62, 12, 159, 241, 17, 226, 227, 132, 55, 244, 89, 179, 208, 210, 35, 132, 121, 194, 5, 95, 226, 205, 184, 100, 106, 33, 14, 144, 90, 162, 205, 138, 54, 35, 205, 11, 97, 148, 199, 249, 156, 27, 0, 164, 180, 192, 100, 67, 110, 201, 8, 67, 168, 202, 181, 6, 225, 4, 126, 12, 172, 240, 245, 215, 240, 255, 199, 130, 228, 235, 2, 152, 18, 16, 185, 175, 133, 63, 41, 123, 42, 18, 171, 92, 246, 63, 231, 131, 180, 50, 196, 219, 167, 216, 24, 210, 45, 219, 102, 204, 193, 81, 149, 191, 229, 202, 29, 62, 235, 245, 47, 49, 176, 224, 223, 36, 153, 38, 76, 135, 242, 226, 212, 184, 17, 200, 110, 108, 168, 183, 85, 110, 158, 57, 38, 234, 231, 71, 219, 112, 251, 140, 232, 174, 175, 27, 116, 205, 179, 139, 174, 209, 73, 7, 62, 243, 99, 58, 101, 42, 146, 79, 114, 165, 148, 171, 173, 27, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 90, 153, 242, 182, 201, 156, 6, 179, 21, 235, 196, 7, 101, 157, 4, 89, 64, 248, 162, 56, 35, 236, 87, 73, 17, 235, 88, 166, 51, 48, 72, 244, 160, 167, 252, 91, 50, 17, 195, 142, 57, 128, 21, 214, 52, 72, 37, 4, 246, 253, 85, 114, 65, 129, 242, 66, 255, 200, 202, 248, 56, 97, 83, 226, 33, 91, 44, 20, 31, 146, 201, 104, 154, 87, 125, 85, 141, 155, 25, 180, 165, 86, 181, 134, 202, 145, 214, 84, 112, 91, 118, 107, 199, 80, 67, 125, 116, 229, 66, 97, 254, 42, 185, 172, 250, 134, 18, 172, 191, 160, 183, 24, 223, 43, 93, 104, 226, 174, 128, 22, 60, 238, 78, 20, 250, 101, 30, 23, 147, 55, 185, 67, 220, 181, 181, 192, 102, 60, 141, 126, 144, 188, 0, 22, 21, 1, 33, 34, 246, 246, 143, 255, 85, 112, 231, 176, 90, 131, 0, 74, 234, 185, 231, 244, 160, 199, 191, 16, 171, 42, 102, 40, 10, 138, 253, 98, 81, 140, 51, 192, 22, 18, 140, 114, 62, 133, 65, 255, 67, 48, 212, 35, 28, 138, 51, 201, 51, 246, 130, 175, 57, 97, 195, 92, 144, 36, 246, 116, 16, 96, 108, 66, 105, 178, 214, 148, 29, 23, 159, 49, 118, 42, 14, 161, 6, 195, 33, 102, 188, 243, 95, 83, 46, 183, 186, 60, 19, 210, 7, 219, 207, 153, 150, 116, 43, 110, 99, 149, 165, 112, 222, 47, 95, 231, 101, 153, 190, 159, 94, 73, 194, 130, 169, 58, 17, 155, 8, 177, 182, 249, 132, 142, 11, 150, 148, 170, 47, 70, 75, 99, 207, 162, 30, 94, 7, 65, 252, 61, 46, 127, 78, 170, 120, 124, 154, 76, 126, 154, 31, 31, 51, 53, 19, 19, 167, 172, 101, 70, 127, 191, 165, 150, 212, 196, 9, 139, 167, 18, 75, 47, 199, 88, 47, 43, 211, 93, 144, 251, 41, 247, 121, 168, 214, 252, 226, 36, 152, 3, 69, 152, 116, 28, 220, 26, 168, 76, 144, 5, 30, 235, 114, 108, 57, 102, 122, 108, 25, 17, 135, 22, 63, 125, 144, 171, 186, 152, 68, 158, 120, 219, 117, 96, 109, 227, 245, 225, 44, 78, 65, 109, 9, 48, 3, 13, 239, 237, 142, 175, 53, 40, 92, 211, 210, 142, 208, 47, 164, 10, 7, 135, 244, 142, 170, 209, 98, 129, 128, 197, 24, 175, 17, 190, 226, 95, 249, 2, 180, 164, 241, 45, 62, 165, 206, 213, 3, 39, 43, 111, 114, 47, 206, 242, 140, 173, 110, 166, 175, 226, 243, 164, 143, 65, 177, 149, 30, 71, 186, 236, 57, 11, 146, 103, 89, 85, 164, 237, 27, 219, 94, 115, 181, 42, 15, 85, 106, 89, 127, 203, 83, 31, 4, 122, 183, 188, 202, 198, 253, 24, 254, 207, 195, 199, 248, 54, 217, 113, 134, 205, 149, 1, 87, 135, 108, 97, 232, 183, 97, 246, 144, 10, 87, 235, 5, 14, 117, 111, 154, 151, 243, 130, 115, 20, 252, 140, 96, 105, 252, 20, 177, 9, 236, 199, 165, 25, 64, 21, 77, 174, 98, 11, 193, 200, 188, 42, 198, 140, 99, 188, 38, 230, 117, 144, 48, 123, 86, 196, 111, 242, 17, 15, 254, 82, 101, 109, 63, 223, 188, 100, 112, 119, 101, 215, 213, 100, 107, 72, 225, 137, 209, 141, 113, 97, 25, 169, 43, 176, 244, 193, 178, 212, 118, 228, 111, 208, 234, 178, 133, 222, 168, 182, 112, 160, 229, 85, 95, 220, 179, 235, 86, 112, 107, 214, 41, 199, 191, 12, 17, 69, 13, 149, 214, 108, 141, 73, 13, 111, 95, 39, 106, 73, 156, 218, 212, 69, 189, 28, 213, 147, 215, 223, 154, 69, 50, 99, 245, 251, 193, 6, 104, 23, 160, 222, 40, 68, 188, 238, 228, 51, 136, 125, 68, 140, 208, 102, 132, 193, 76, 106, 221, 17, 181, 205, 74, 99, 195, 247, 96, 115, 85, 135, 114, 219, 222, 155, 189, 65, 180, 7, 238, 160, 35, 61, 36, 100, 43, 13, 254, 129, 5, 29, 95, 196, 105, 37, 92, 68, 25, 211, 175, 194, 75, 8, 7, 5, 166, 211, 252, 66, 194, 4, 244, 192, 15, 99, 92, 200, 72, 247, 208, 113, 36, 61, 30, 132, 199, 88, 126, 33, 228, 119, 131, 9, 52, 70, 59, 100, 68, 165, 118, 161, 67, 215, 28, 134, 192, 53, 138, 86, 140, 3, 3, 157, 89, 197, 104, 68, 109, 80, 130, 66, 232, 157, 59, 248, 157, 2, 24, 224, 31, 12, 195, 25, 204, 242, 54, 127, 239, 74, 219, 4, 190, 171, 111, 102, 51, 217, 148, 228, 246, 43, 55, 184, 210, 179, 4, 47, 71, 16, 151, 238, 232, 146, 182, 1, 164, 42, 98, 67, 104, 113, 46, 19, 75, 50, 185, 102, 51, 65, 39, 6, 40, 98, 58, 233, 44, 80, 91, 151, 254, 45, 124, 65, 113, 141, 37, 218, 208, 119, 89, 68, 242, 130, 166, 236, 143, 178, 118, 27, 6, 208, 174, 237, 53, 93, 253, 17, 241, 104, 119, 28, 87, 107, 84, 197, 72, 161, 17, 149, 198, 54, 29, 209, 143, 200, 40, 178, 167, 225, 126, 192, 0, 224, 118, 220, 18, 166, 253, 198, 217, 188, 245, 92, 222, 228, 219, 30, 74, 100, 93, 191, 182, 68, 88, 161, 196, 53, 5, 154, 9, 210, 118, 83, 142, 84, 244, 118, 228, 57, 129, 166, 145, 245, 206, 10, 158, 25, 193, 51, 27, 216, 14, 251, 20, 207, 7, 31, 175, 37, 70, 88, 89, 91, 82, 163, 189, 248, 205, 42, 90, 114, 70, 168, 75, 109, 4, 168, 70, 116, 222, 88, 90, 19, 201, 141, 163, 171, 3, 162, 3, 177, 51, 254, 168, 46, 159, 246, 35, 146, 178, 82, 163, 247, 82, 173, 242, 218, 42, 188, 208, 56, 173, 72, 42, 52, 171, 188, 21, 209, 115, 87, 237, 117, 222, 148, 19, 92, 126, 134, 70, 191, 110, 144, 154, 134, 200, 209, 107, 84, 171, 181, 214, 105, 64, 112, 87, 125, 225, 216, 38, 170, 154, 152, 169, 196, 79, 16, 34, 111, 17, 167, 124, 208, 97, 42, 79, 88, 242, 66, 155, 255, 206, 211, 12, 137, 178, 255, 176, 164, 207, 79, 132, 142, 85, 84, 18, 131, 129, 128, 105, 31, 158, 244, 145, 13, 192, 155, 226, 110, 151, 94, 228, 172, 86, 34, 59, 54, 229, 63, 152, 124, 229, 51, 40, 131, 207, 64, 225, 222, 98, 29, 235, 99, 69, 123, 63, 210, 113, 145, 168, 147, 24, 61, 204, 247, 199, 105, 81, 86, 207, 166, 201, 185, 136, 87, 224, 144, 142, 182, 222, 170, 134, 14, 141, 35, 199, 57, 164, 138, 106, 106, 82, 30, 50, 24, 178, 1, 108, 254, 31, 114, 108, 101, 127, 37, 255, 120, 233, 134, 96, 110, 86, 132, 76, 3, 130, 170, 60, 154, 132, 123, 82, 38, 179, 88, 41, 248, 222, 160, 231, 136, 204, 48, 44, 50, 160, 102, 108, 26, 40, 185, 57, 140, 214, 159, 24, 216, 102, 181, 229, 153, 24, 16, 24, 164, 29, 57, 0, 187, 243, 254, 238, 35, 0, 78, 239, 49, 112, 101, 232, 26, 53, 135, 248, 241, 144, 48, 220, 87, 36, 116, 146, 248, 8, 4, 67, 5, 29, 23, 178, 206, 32, 234, 193, 62, 228, 145, 152, 35, 55, 229, 17, 208, 183, 174, 31, 131, 198, 97, 230, 69, 122, 2, 14, 116, 254, 137, 107, 54, 224, 77, 195, 217, 59, 136, 77, 185, 38, 96, 156, 186, 161, 89, 85, 171, 135, 45, 236, 104, 98, 36, 23, 42, 145, 0, 119, 14, 179, 98, 205, 137, 61, 114, 220, 209, 44, 107, 34, 237, 204, 90, 33, 240, 236, 67, 196, 202, 198, 241, 84, 53, 194, 97, 205, 202, 204, 172, 97, 239, 138, 188, 44, 15, 147, 120, 122, 46, 55, 158, 113, 145, 182, 72, 11, 240, 82, 207, 153, 106, 128, 208, 94, 227, 217, 97, 81, 125, 143, 19, 215, 148, 197, 136, 8, 159, 118, 207, 221, 125, 247, 34, 132, 215, 162, 123, 158, 117, 119, 115, 93, 213, 165, 189, 218, 35, 217, 181, 212, 88, 181, 169, 29, 50, 23, 31, 50, 214, 69, 99, 233, 57, 136, 173, 52, 120, 227, 172, 44, 112, 112, 172, 230, 105, 92, 193, 177, 3, 62, 197, 21, 170, 86, 171, 96, 18, 113, 24, 241, 69, 67, 72, 137, 101, 26, 163, 70, 186, 196, 127, 216, 53, 109, 99, 249, 115, 70, 105, 3, 9, 25, 201, 247, 179, 74, 236, 232, 128, 209, 112, 48, 48, 228, 225, 78, 241, 161, 221, 7, 102, 144, 224, 237, 38, 143, 213, 0, 112, 251, 75, 26, 9, 40, 53, 73, 102, 213, 233, 171, 249, 57, 159, 71, 86, 66, 1, 63, 76, 236, 49, 209, 152, 58, 243, 250, 94, 16, 48, 179, 237, 73, 43, 146, 65, 250, 68, 100, 86, 104, 133, 73, 235, 128, 97, 5, 101, 16, 13, 123, 146, 7, 186, 245, 19, 192, 133, 31, 124, 83, 120, 69, 118, 27, 30, 172, 193, 92, 137, 212, 122, 109, 197, 12, 152, 0, 187, 47, 247, 171, 56, 12, 50, 163, 139, 38, 212, 119, 102, 14, 227, 23, 143, 13, 6, 228, 3, 13, 79, 194, 53, 210, 140, 156, 59, 86, 134, 65, 162, 141, 2, 241, 245, 8, 213, 33, 94, 73, 75, 198, 144, 19, 105, 199, 56, 104, 12, 180, 218, 80, 74, 31, 129, 212, 63, 229, 102, 64, 175, 36, 84, 252, 10, 97, 233, 190, 214, 47, 44, 127, 173, 20, 135, 211, 124, 62, 157, 200, 129, 166, 113, 175, 162, 167, 124, 20, 105, 72, 70, 228, 212, 82, 19, 181, 196, 205, 105, 137, 147, 31, 215, 177, 93, 118, 178, 162, 37, 150, 242, 45, 245, 48, 113, 178, 16, 110, 241, 177, 41, 45, 217, 64, 63, 211, 250, 192, 169, 234, 80, 85, 16, 100, 35, 26, 122, 8, 107, 199, 158, 64, 191, 49, 174, 16, 133, 123, 57, 60, 198, 255, 106, 125, 199, 223, 253, 245, 59, 143, 155, 184, 246, 60, 55, 198, 58, 178, 199, 131, 116, 202, 4, 187, 248, 207, 240, 154, 146, 174, 190, 221, 173, 196, 102, 231, 50, 35, 90, 212, 112, 26, 29, 153, 202, 136, 62, 185, 208, 85, 138, 152, 86, 120, 138, 150, 60, 96, 247, 147, 175, 206, 202, 68, 69, 164, 175, 123, 202, 173, 168, 168, 232, 199, 209, 22, 184, 214, 207, 172, 173, 220, 80, 102, 30, 21, 19, 194, 215, 16, 45, 246, 34, 119, 43, 199, 152, 126, 147, 31, 194, 209, 243, 50, 153, 244, 151, 65, 210, 93, 25, 137, 182, 152, 71, 65, 70, 156, 137, 120, 181, 51, 19, 83, 166, 190, 153, 40, 96, 20, 121, 21, 116, 8, 232, 26, 182, 25, 230, 95, 252, 231, 69, 197, 136, 0, 22, 77, 92, 36, 199, 146, 246, 60, 186, 84, 189, 178, 246, 64, 44, 151, 162, 169, 25, 48, 153, 254, 66, 230, 218, 197, 105, 204, 221, 45, 11, 211, 217, 67, 46, 233, 117, 59, 19, 97, 178, 196, 6, 6, 92, 30, 147, 141, 123, 21, 119, 115, 94, 90, 84, 117, 188, 26, 28, 183, 119, 101, 14, 145, 90, 178, 9, 67, 35, 127, 32, 253, 139, 184, 172, 110, 109, 180, 52, 32, 247, 105, 34, 166, 141, 27, 124, 9, 113, 211, 234, 24, 140, 239, 44, 198, 226, 177, 245, 238, 54, 196, 205, 71, 216, 195, 0, 120, 163, 236, 225, 195, 237, 142, 180, 215, 24, 222, 51, 6, 234, 194, 41, 55, 26, 131, 175, 9, 76, 24, 4, 118, 163, 84, 89, 30, 9, 248, 33, 158, 34, 223, 16, 138, 230, 57, 79, 126, 73, 50, 18, 191, 194, 138, 178, 193, 4, 111, 88, 207, 210, 86, 24, 42, 31, 163, 238, 96, 249, 241, 42, 31, 92, 181, 235, 177, 63, 97, 228, 76, 153, 114, 246, 122, 210, 104, 29, 221, 196, 114, 187, 168, 75, 47, 187, 143, 186, 248, 33, 7, 210, 29, 178, 40, 34, 64, 139, 72, 31, 63, 17, 97, 35, 50, 209, 17, 164, 34, 255, 227, 64, 68, 65, 218, 193, 177, 106, 187, 14, 149, 220, 52, 209, 165, 202, 94, 132, 102, 69, 0, 39, 42, 189, 105, 114, 49, 5, 252, 181, 184, 226, 26, 214, 189, 58, 54, 51, 188, 237, 139, 235, 14, 116, 155, 248, 240, 158, 246, 218, 9, 104, 225, 45, 64, 72, 30, 104, 43, 16, 85, 199, 43, 127, 50, 0, 217, 74, 17, 39, 81, 248, 57, 45, 116, 212, 236, 31, 43, 54, 46, 34, 80, 214, 175, 39, 61, 104, 240, 226, 88, 131, 1, 83, 106, 74, 67, 198, 69, 120, 225, 115, 87, 153, 130, 93, 244, 38, 174, 101, 217, 49, 82, 177, 201, 94, 62, 130, 198, 197, 42, 204, 212, 17, 191, 81, 236, 44, 188, 248, 104, 19, 138, 176, 162, 160, 150, 8, 23, 45, 22, 36, 154, 10, 214, 190, 33, 26, 161, 82, 94, 146, 180, 136, 78, 123, 20, 16, 68, 153, 166, 212, 81, 251, 106, 171, 137, 181, 102, 104, 220, 71, 2, 138, 202, 134, 246, 49, 148, 104, 240, 24, 212, 15, 120, 87, 86, 128, 20, 10, 162, 208, 170, 102, 110, 185, 94, 44, 169, 6, 58, 26, 129, 70, 66, 214, 74, 168, 27, 240, 165, 194, 236, 96, 108, 86, 218, 138, 240, 146, 201, 32, 40, 87, 22, 21, 33, 23, 178, 119, 31, 195, 19, 200, 223, 147, 41, 227, 180, 87, 22, 61, 149, 61, 228, 143, 128, 63, 16, 241, 239, 7, 40, 250, 221, 5, 217, 63, 88, 32, 2, 222, 5, 211, 34, 14, 94, 28, 107, 145, 63, 122, 129, 222, 121, 66, 227, 79, 212, 164, 17, 12, 64, 231, 117, 14, 4, 104, 56, 224, 129, 61, 145, 164, 15, 251, 16, 51, 155, 149, 233, 216, 157, 104, 7, 166, 29, 51, 138, 245, 163, 113, 232, 48, 225, 253, 26, 15, 209, 191, 207, 50, 34, 162, 233, 5, 198, 68, 27, 55, 247, 115, 72, 120, 247, 62, 203, 136, 240, 150, 59, 13, 136, 217, 226, 114, 143, 46, 69, 79, 60, 182, 135, 94, 204, 249, 247, 176, 186, 239, 93, 81, 27, 36, 37, 148, 148, 199, 162, 60, 163, 173, 215, 147, 152, 168, 118, 207, 140, 37, 171, 186, 164, 27, 133, 234, 11, 104, 157, 154, 67, 83, 196, 132, 17, 88, 202, 129, 20, 127, 52, 12, 107, 92, 105, 21, 215, 188, 254, 182, 75, 183, 244, 24, 78, 217, 218, 76, 251, 1, 132, 225, 146, 76, 184, 109, 142, 206, 155, 152, 244, 194, 87, 105, 50, 149, 161, 211, 184, 32, 218, 32, 224, 203, 83, 52, 133, 131, 25, 160, 141, 104, 114, 242, 203, 32, 165, 145, 208, 115, 237, 42, 84, 227, 199, 94, 212, 155, 110, 112, 132, 80, 17, 91, 66, 157, 23, 225, 144, 63, 224, 120, 50, 95, 151, 225, 159, 6, 199, 222, 243, 142, 135, 162, 163, 96, 8, 113, 168, 36, 181, 27, 2, 132, 18, 135, 137, 248, 1, 195, 169, 34, 47, 200, 138, 46, 110, 208, 15, 46, 156, 146, 9, 89, 28, 132, 132, 87, 38, 36, 147, 89, 118, 175, 45, 193, 26, 78, 7, 25, 54, 117, 110, 70, 138, 69, 23, 125, 28, 175, 91, 190, 179, 162, 220, 162, 111, 95, 228, 185, 133, 60, 243, 243, 147, 193, 197, 188, 162, 165, 71, 146, 241, 10, 194, 85, 10, 164, 237, 143, 30, 28, 62, 143, 208, 191, 137, 207, 146, 254, 52, 61, 79, 171, 174, 242, 46, 86, 94, 231, 113, 154, 137, 16, 110, 179, 247, 38, 192, 41, 157, 96, 202, 60, 182, 28, 175, 135, 113, 118, 162, 78, 81, 254, 245, 135, 27, 18, 121, 232, 160, 79, 40, 52, 90, 119, 87, 226, 155, 187, 118, 195, 2, 191, 131, 24, 224, 41, 248, 149, 245, 79, 227, 95, 190, 142, 62, 16, 60, 47, 85, 130, 103, 129, 30, 60, 166, 181, 172, 153, 60, 88, 109, 233, 194, 138, 244, 137, 223, 147, 215, 186, 110, 72, 210, 127, 46, 242, 217, 189, 150, 116, 232, 224, 61, 149, 244, 230, 174, 233, 33, 189, 117, 130, 221, 86, 154, 169, 12, 155, 179, 44, 68, 117, 221, 43, 75, 227, 115, 234, 155, 86, 198, 193, 110, 201, 55, 228, 146, 201, 235, 56, 45, 202, 254, 34, 122, 99, 121, 226, 77, 145, 113, 165, 225, 238, 74, 119, 99, 207, 150, 38, 220, 75, 151, 167, 1, 186, 175, 100, 73, 162, 53, 80, 87, 156, 220, 144, 140, 169, 20, 19, 188, 250, 219, 219, 35, 108, 52, 68, 252, 190, 249, 207, 100, 239, 238, 163, 15, 173, 185, 107, 203, 157, 156, 23, 155, 125, 23, 17, 203, 229, 76, 115, 230, 56, 97, 237, 54, 121, 163, 135, 204, 74, 23, 192, 239, 14, 10, 30, 70, 21, 224, 232, 182, 158, 144, 127, 83, 239, 115, 174, 198, 235, 130, 30, 100, 230, 117, 145, 111, 185, 136, 66, 170, 160, 102, 119, 58, 168, 22, 36, 204, 46, 122, 65, 87, 193, 138, 161, 85, 42, 102, 146, 48, 200, 97, 87, 31, 15, 168, 14, 242, 125, 112, 147, 139, 204, 27, 43, 1, 69, 186, 69, 74, 136, 26, 102, 28, 130, 38, 169, 13, 235, 1, 169, 68, 83, 29, 83, 57, 32, 1, 195, 141, 249, 167, 87, 28, 166, 254, 16, 228, 103, 77, 139, 53, 47, 244, 48, 77, 101, 159, 228, 48, 170, 157, 38, 39, 225, 178, 39, 221, 50, 71, 70, 168, 0, 133, 174, 63, 159, 114, 29, 51, 203, 252, 107, 126, 227, 241, 143, 118, 33, 9, 34, 11, 16, 48, 181, 216, 59, 199, 49, 180, 71, 250, 0, 42, 177, 68, 22, 167, 107, 56, 188, 86, 218, 37, 88, 47, 33, 154, 164, 34, 162, 182, 158, 26, 234, 6, 34, 21, 157, 188, 28, 169, 238, 150, 113, 29, 103, 65, 184, 6, 251, 133, 93, 164, 89, 64, 137, 55, 233, 61, 126, 119, 215, 221, 167, 76, 131, 3, 217, 71, 29, 55, 172, 166, 8, 196, 220, 234, 27, 176, 234, 8, 41, 110, 201, 187, 31, 148, 92, 237, 76, 75, 135, 152, 246, 92, 190, 98, 145, 185, 65, 100, 33, 61, 252, 253, 160, 229, 117, 185, 18, 153, 123, 206, 90, 134, 227, 239, 201, 192, 208, 148, 175, 51, 64, 136, 7, 131, 168, 199, 159, 122, 16, 135, 42, 193, 246, 84, 110, 60, 122, 65, 114, 22, 159, 39, 42, 126, 142, 61, 194, 39, 249, 74, 252, 177, 178, 200, 74, 184, 60, 147, 172, 68, 23, 202, 233, 53, 204, 121, 121, 34, 161, 157, 39, 101, 25, 159, 112, 128, 226, 37, 255, 191, 13, 142, 64, 98, 37, 244, 144, 235, 214, 123, 61, 43, 132, 132, 149, 82, 29, 224, 71, 2, 37, 88, 167, 156, 234, 14, 98, 89, 14, 116, 61, 234, 61, 138, 122, 236, 15, 7, 20, 26, 5, 72, 200, 242, 166, 136, 211, 41, 123, 102, 11, 55, 246, 39, 161, 193, 200, 141, 215, 0, 19, 112, 34, 16, 124, 192, 102, 220, 53, 64, 224, 255, 101, 61, 43, 94, 210, 27, 195, 44, 71, 124, 52, 47, 103, 9, 163, 218, 132, 198, 3, 219, 57, 113, 112, 140, 63, 132, 233, 176, 87, 186, 2, 254, 230, 141, 45, 116, 207, 71, 130, 196, 233, 250, 129, 96, 28, 26, 142, 195, 173, 30, 243, 163, 71, 122, 213, 147, 239, 29, 27, 210, 194, 145, 137, 58, 216, 254, 147, 0, 174, 225, 52, 174, 160, 143, 116, 120, 160, 11, 125, 191, 60, 156, 103, 224, 133, 181, 1, 91, 194, 243, 240, 123, 107, 15, 193, 172, 49, 59, 68, 147, 71, 158, 219, 157, 249, 48, 181, 236, 173, 46, 6, 89, 35, 80, 9, 220, 61, 113, 73, 73, 162, 172, 3, 151, 153, 172, 200, 245, 251, 194, 77, 40, 168, 107, 113, 118, 18, 196, 99, 45, 124, 102, 134, 209, 199, 4, 110, 5, 199, 216, 71, 18, 238, 11, 203, 224, 208, 204, 229, 169, 32, 62, 130, 159, 74, 249, 240, 141, 196, 15, 144, 166, 189, 17, 129, 90, 182, 43, 236, 67, 36, 159, 147, 241, 96, 47, 180, 152, 49, 92, 208, 72, 1, 210, 253, 19, 72, 150, 192, 49, 53, 185, 220, 153, 253, 6, 167, 237, 101, 13, 229, 57, 229, 71, 135, 85, 90, 100, 169, 127, 235, 197, 207, 192, 198, 234, 218, 1, 37, 37, 179, 53, 44, 44, 201, 43, 245, 167, 121, 80, 45, 124, 152, 199, 144, 69, 154, 196, 45, 143, 65, 121, 252, 143, 193, 243, 62, 234, 204, 13, 239, 148, 235, 118, 122, 28, 109, 203, 97, 245, 39, 42, 163, 208, 55, 241, 9, 4, 235, 147, 250, 105, 242, 152, 213, 102, 99, 8, 3, 14, 21, 81, 63, 137, 240, 207, 85, 222, 5, 188, 118, 240, 31, 16, 242, 56, 189, 100, 9, 203, 106, 52, 233, 174, 125, 7, 129, 68, 246, 239, 180, 228, 107, 153, 65, 116, 46, 78, 68, 24, 237, 137, 95, 200, 68, 222, 162, 172, 145, 160, 115, 117, 250, 130, 129, 149, 103, 69, 56, 208, 70, 247, 14, 217, 30, 182, 90, 82, 58, 3, 106, 188, 108, 221, 64, 234, 194, 54, 96, 246, 201, 0, 208, 61, 21, 1, 80, 28, 7, 66, 109, 34, 40, 52, 101, 54, 63, 69, 88, 228, 231, 56, 177, 108, 223, 109, 196, 140, 178, 7, 3, 196, 37, 214, 17, 18, 43, 35, 68, 123, 2, 59, 253, 87, 138, 216, 58, 43, 231, 117, 194, 155, 131, 45, 30, 238, 211, 242, 16, 224, 63, 200, 80, 201, 215, 123, 50, 112, 30, 86, 71, 240, 23, 86, 72, 112, 144, 150, 45, 84, 107, 79, 64, 41, 248, 250, 24, 20, 198, 88, 143, 152, 104, 250, 221, 59, 126, 62, 247, 221, 187, 71, 188, 41, 33, 65, 84, 158, 154, 143, 123, 57, 91, 62, 162, 145, 144, 156, 200, 108, 33, 124, 13, 207, 137, 95, 36, 64, 23, 177, 60, 194, 201, 248, 194, 203, 92, 17, 39, 131, 106, 129, 145, 97, 104, 195, 19, 20, 244, 74, 177, 218, 173, 117, 110, 183, 164, 51, 29, 253, 115, 116, 70, 170, 57, 169, 41, 166, 190, 234, 149, 123, 138, 234, 156, 158, 159, 66, 12, 198, 26, 17, 83, 51, 190, 102, 177, 27, 255, 125, 236, 204, 131, 64, 27, 211, 72, 152, 64, 26, 142, 235, 198, 45, 148, 95, 219, 153, 157, 120, 242, 219, 3, 239, 201, 211, 0, 155, 28, 72, 133, 162, 189, 11, 205, 12, 127, 26, 151, 251, 89, 89, 197, 217, 88, 101, 146, 166, 83, 13, 202, 55, 153, 150, 175, 213, 33, 245, 131, 99, 193, 228, 102, 84, 245, 167, 126, 207, 168, 91, 42, 39, 43, 104, 146, 65, 205, 90, 6, 3, 230, 1, 197, 73, 23, 194, 199, 37, 182, 132, 193, 160, 125, 158, 195, 166, 90, 58, 209, 138, 176, 105, 99, 86, 66, 32, 59, 178, 54, 94, 109, 171, 15, 109, 129, 95, 161, 59, 186, 178, 48, 25, 83, 31, 210, 214, 93, 51, 93, 14, 17, 121, 105, 176, 192, 41, 34, 31, 156, 54, 55, 206, 132, 186, 227, 57, 57, 132, 184, 214, 127, 112, 232, 0, 223, 62, 67, 24, 54, 88, 126, 104, 31, 46, 170, 59, 232, 137, 100, 175, 97, 64, 228, 98, 238, 254, 12, 73, 240, 128, 93, 251, 65, 209, 233, 94, 219, 157, 102, 111, 121, 238, 149, 28, 20, 142, 92, 15, 149, 124, 143, 78, 179, 138, 217, 197, 82, 159, 157, 14, 192, 123, 52, 44, 58, 244, 186, 216, 160, 91, 145, 41, 11, 12, 55, 133, 208, 102, 160, 93, 228, 23, 58, 175, 167, 71, 216, 135, 96, 248, 228, 106, 32, 248, 151, 34, 117, 45, 65, 250, 252, 52, 189, 198, 185, 212, 118, 84, 245, 156, 62, 109, 160, 107, 56, 86, 139, 35, 227, 167, 237, 141, 89, 47, 55, 19, 255, 213, 108, 172, 232, 252, 23, 204, 12, 104, 19, 20, 134, 168, 103, 7, 76, 1, 205, 241, 44, 129, 226, 194, 106, 236, 0, 129, 64, 125, 92, 87, 43, 65, 194, 60, 226, 46, 151, 191, 93, 0, 115, 195, 22, 165, 96, 175, 61, 70, 240, 105, 194, 185, 168, 33, 254, 203, 91, 67, 239, 99, 250, 162, 145, 220, 26, 102, 249, 224, 139, 72, 210, 25, 72, 240, 250, 128, 95, 93, 201, 173, 58, 29, 68, 81, 191, 207, 8, 91, 76, 196, 101, 67, 19, 115, 32, 191, 159, 142, 0, 235, 18, 251, 53, 80, 24, 73, 92, 69, 4, 151, 0, 37, 222, 40, 140, 215, 101, 182, 213, 143, 94, 179, 93, 156, 108, 52, 169, 150, 110, 161, 192, 46, 51, 121, 212, 205, 137, 173, 255, 144, 161, 205, 255, 6, 173, 219, 38, 188, 93, 241, 255, 34, 194, 72, 132, 203, 100, 202, 68, 34, 40, 196, 40, 99, 88, 147, 28, 243, 164, 174, 18, 154, 233, 163, 115, 6, 226, 99, 123, 17, 15, 159, 99, 252, 28, 194, 45, 194, 209, 248, 25, 169, 23, 128, 83, 132, 110, 119, 102, 76, 147, 141, 173, 147, 83, 171, 125, 82, 154, 231, 37, 109, 123, 128, 234, 230, 132, 221, 119, 190, 208, 22, 21, 140, 247, 173, 147, 246, 54, 29, 240, 28, 161, 186, 19, 178, 78, 15, 220, 145, 172, 134, 181, 245, 205, 226, 80, 197, 19, 45, 67, 61, 56, 162, 11, 232, 109, 108, 4, 16, 140, 162, 247, 69, 18, 147, 140, 129, 30, 145, 14, 31, 88, 252, 34, 210, 139, 138, 180, 239, 32, 225, 157, 18, 233, 54, 29, 184, 171, 34, 189, 44, 97, 36, 170, 97, 99, 3, 210, 255, 110, 53, 204, 178, 126, 179, 185, 246, 68, 210, 109, 48, 154, 111, 251, 42, 55, 112, 52, 232, 142, 172, 116, 187, 97, 127, 183, 100, 237, 46, 172, 118, 245, 41, 167, 125, 35, 112, 129, 109, 38, 209, 222, 128, 147, 57, 84, 251, 21, 97, 115, 252, 69, 243, 58, 34, 66, 253, 241, 42, 67, 9, 12, 103, 16, 106, 112, 205, 86, 63, 246, 33, 172, 14, 150, 126, 195, 233, 168, 219, 160, 150, 150, 117, 202, 170, 89, 49, 89, 231, 176, 16, 87, 171, 238, 55, 28, 203, 50, 50, 176, 33, 72, 222, 229, 0, 83, 100, 139, 208, 178, 103, 49, 5, 254, 49, 158, 192, 40, 86, 228, 8, 162, 65, 71, 221, 129, 74, 131, 40, 104, 85, 255, 94, 133, 56, 38, 133, 133, 19, 31, 141, 178, 36, 117, 125, 221, 99, 150, 123, 176, 246, 159, 40, 11, 159, 168, 114, 215, 183, 129, 99, 84, 159, 203, 20, 174, 103, 77, 217, 169, 163, 205, 205, 205, 110, 131, 255, 214, 191, 237, 30, 60, 53, 117, 27, 164, 125, 241, 211, 28, 237, 100, 252, 134, 166, 169, 182, 199, 64, 108, 94, 247, 42, 101, 126, 116, 235, 139, 127, 245, 166, 199, 172, 69, 178, 254, 186, 225, 91, 224, 152, 153, 51, 210, 226, 108, 217, 151, 161, 254, 20, 67, 189, 186, 204, 177, 110, 62, 5, 231, 217, 55, 201, 38, 95, 134, 250, 206, 73, 117, 221, 218, 158, 173, 231, 208, 149, 152, 251, 89, 42, 113, 99, 196, 52, 227, 203, 86, 19, 104, 104, 185, 157, 57, 153, 240, 126, 179, 47, 155, 101, 226, 77, 81, 207, 139, 212, 13, 131, 28, 83, 81, 206, 177, 22, 129, 46, 140, 100, 231, 225, 211, 140, 128, 162, 255, 180, 134, 170, 91, 115, 40, 225, 187, 65, 212, 99, 125, 239, 145, 144, 126, 31, 209, 57, 122, 124, 81, 59, 208, 56, 29, 109, 189, 69, 63, 134, 111, 221, 121, 240, 37, 143, 244, 225, 70, 10, 0, 125, 31, 143, 207, 96, 46, 53, 183, 184, 88, 55, 59, 66, 143, 95, 6, 197, 231, 165, 136, 192, 120, 105, 34, 48, 24, 124, 253, 173, 115, 240, 5, 171, 220, 34, 226, 2, 225, 141, 190, 162, 27, 4, 123, 166, 147, 86, 32, 134, 205, 10, 6, 84, 23, 177, 196, 181, 176, 92, 38, 144, 7, 38, 41, 237, 88, 72, 225, 125, 157, 189, 147, 159, 7, 209, 75, 115, 130, 51, 158, 9, 21, 198, 202, 29, 114, 7, 7, 100, 86, 98, 0, 78, 166, 249, 251, 24, 232, 225, 249, 12, 149, 47, 78, 25, 58, 81, 159, 175, 162, 209, 106, 30, 130, 158, 196, 2, 136, 47, 105, 227, 217, 51, 214, 230, 21, 163, 133, 82, 148, 125, 141, 132, 191, 105, 180, 237, 69, 51, 77, 88, 126, 112, 209, 220, 89, 114, 37, 68, 205, 3, 73, 94, 184, 77, 115, 177, 4, 138, 14, 101, 209, 32, 164, 72, 176, 81, 109, 169, 33, 45, 229, 19, 25, 15, 199, 107, 53, 197, 250, 162, 70, 6, 4, 134, 59, 202, 106, 6, 129, 181, 37, 130, 235, 253, 159, 193, 219, 134, 101, 14, 123, 26, 22, 140, 109, 66, 80, 22, 9, 108, 66, 213, 219, 68, 53, 89, 56, 123, 2, 154, 22, 230, 93, 25, 17, 248, 79, 122, 188, 170, 230, 136, 105, 59, 206, 62, 168, 229, 105, 78, 93, 204, 210, 42, 53, 199, 175, 252, 12, 146, 9, 201, 218, 207, 170, 7, 219, 16, 62, 237, 15, 28, 197, 110, 86, 35, 43, 6, 16, 221, 61, 210, 238, 216, 6, 25, 145, 171, 127, 7, 212, 176, 61, 168, 33, 5, 165, 170, 233, 171, 90, 117, 253, 163, 32, 46, 33, 2, 50, 216, 111, 177, 232, 47, 83, 76, 5, 35, 108, 42, 5, 129, 9, 43, 63, 201, 145, 55, 94, 214, 21, 228, 19, 134, 18, 244, 110, 120, 198, 26, 29, 111, 134, 55, 53, 218, 220, 11, 15, 126, 230, 34, 159, 207, 126, 210, 217, 86, 208, 116, 160, 79, 34, 185, 177, 172, 188, 112, 104, 150, 145, 99, 244, 221, 67, 37, 127, 246, 148, 35, 106, 171, 175, 169, 72, 41, 227, 49, 71, 123, 90, 140, 150, 63, 243, 13, 195, 51, 223, 94, 20, 188, 140, 93, 219, 50, 198, 94, 203, 146, 139, 104, 207, 236, 71, 156, 181, 55, 83, 45, 42, 238, 24, 137, 20, 83, 81, 147, 210, 119, 173, 211, 51, 36, 213, 242, 38, 217, 224, 4, 206, 239, 158, 229, 246, 22, 107, 13, 205, 148, 166, 158, 239, 102, 236, 200, 15, 172, 196, 192, 6, 209, 145, 200, 242, 183, 230, 21, 98, 79, 166, 31, 213, 166, 190, 255, 182, 148, 55, 10, 90, 23, 19, 241, 255, 159, 33, 71, 181, 73, 237, 16, 207, 136, 228, 188, 154, 159, 191, 79, 138, 119, 105, 201, 22, 83, 140, 204, 253, 108, 126, 110, 248, 89, 154, 196, 236, 157, 56, 248, 147, 241, 194, 246, 129, 77, 159, 140, 66, 149, 13, 254, 127, 174, 27, 253, 77, 190, 138, 95, 45, 179, 189, 85, 46, 25, 231, 254, 182, 84, 74, 96, 1, 210, 215, 36, 123, 221, 186, 85, 180, 219, 238, 110, 180, 203, 38, 118, 8, 118, 0, 125, 195, 212, 9, 19, 101, 196, 38, 164, 207, 131, 44, 207, 9, 98, 99, 186, 138, 167, 182, 154, 1, 216, 232, 247, 183, 163, 111, 191, 141, 190, 123, 176, 6, 119, 57, 174, 193, 174, 174, 130, 241, 245, 215, 250, 145, 189, 37, 229, 232, 81, 54, 110, 66, 24, 198, 208, 125, 151, 109, 16, 198, 121, 147, 139, 159, 170, 224, 154, 31, 148, 97, 235, 32, 52, 89, 164, 30, 160, 48, 208, 152, 182, 59, 184, 200, 148, 56, 254, 156, 148, 227, 34, 157, 49, 133, 87, 226, 83, 87, 34, 165, 140, 190, 16, 244, 192, 168, 188, 228, 74, 93, 171, 123, 152, 28, 67, 120, 217, 187, 252, 34, 251, 149, 189, 237, 171, 3, 101, 220, 232, 49, 96, 193, 84, 250, 72, 148, 164, 206, 34, 54, 144, 151, 139, 2, 80, 169, 4, 118, 228, 87, 121, 39, 111, 74, 47, 138, 55, 250, 18, 170, 136, 52, 163, 200, 88, 135, 86, 217, 183, 250, 126, 138, 99, 133, 84, 15, 74, 166, 228, 245, 57, 75, 154, 201, 104, 173, 78, 151, 161, 110, 74, 109, 8, 111, 172, 253, 10, 57, 86, 168, 172, 127, 84, 208, 57, 51, 115, 247, 157, 172, 140, 233, 125, 66, 139, 234, 65, 146, 215, 3, 58, 160, 247, 203, 103, 151, 108, 94, 41, 83, 121, 166, 146, 0, 38, 39, 40, 129, 203, 113, 75, 169, 93, 211, 3, 253, 93, 149, 191, 200, 217, 60, 145, 56, 105, 137, 240, 18, 161, 230, 232, 202, 193, 102, 165, 179, 223, 28, 120, 91, 224, 211, 2, 235, 41, 65, 220, 190, 172, 214, 173, 118, 26, 151, 136, 1, 250, 255, 36, 213, 197, 199, 254, 63, 197, 114, 138, 214, 255, 74, 0, 224, 68, 102, 227, 2, 179, 119, 231, 193, 16, 217, 15, 252, 102, 155, 3, 94, 90, 111, 250, 188, 45, 49, 219, 112, 241, 145, 192, 134, 23, 35, 40, 57, 19, 181, 164, 65, 41, 209, 83, 137, 133, 68, 205, 70, 180, 70, 10, 173, 50, 136, 150, 40, 45, 100, 66, 162, 5, 121, 147, 6, 81, 201, 127, 16, 85, 194, 10, 70, 190, 235, 133, 109, 211, 78, 86, 13, 152, 117, 15, 30, 8, 132, 42, 152, 43, 240, 196, 32, 52, 130, 158, 89, 32, 123, 19, 62, 227, 11, 92, 237, 124, 147, 115, 142, 247, 91, 201, 141, 232, 30, 179, 78, 223, 228, 138, 125, 152, 134, 19, 41, 172, 152, 169, 170, 83, 89, 137, 222, 107, 14, 227, 72, 139, 238, 10, 123, 23, 52, 2, 127, 216, 186, 220, 222, 218, 138, 254, 100, 127, 183, 134, 226, 207, 182, 60, 78, 169, 207, 85, 139, 142, 137, 103, 88, 64, 174, 112, 19, 216, 225, 106, 209, 228, 47, 152, 224, 39, 139, 19, 252, 164, 153, 224, 39, 247, 139, 224, 39, 136, 204, 134, 248, 53, 4, 127, 145, 231, 103, 243, 25, 226, 240, 86, 132, 254, 172, 84, 154, 228, 216, 177, 38, 230, 196, 208, 108, 168, 54, 189, 37, 21, 173, 121, 145, 207, 102, 122, 2, 84, 111, 96, 189, 252, 181, 32, 49, 78, 35, 129, 230, 185, 163, 109, 157, 245, 91, 101, 254, 245, 223, 39, 242, 17, 13, 161, 101, 86, 156, 56, 51, 34, 123, 43, 216, 80, 57, 17, 101, 189, 85, 229, 79, 10, 14, 223, 47, 95, 134, 175, 211, 240, 13, 111, 203, 240, 213, 27, 113, 51, 67, 70, 51, 172, 237, 41, 70, 1, 24, 95, 27, 162, 154, 175, 219, 58, 65, 115, 85, 21, 229, 110, 54, 145, 126, 56, 73, 90, 5, 134, 124, 5, 114, 15, 183, 236, 53, 136, 162, 189, 244, 35, 74, 202, 43, 87, 201, 69, 145, 86, 160, 164, 31, 69, 171, 171, 46, 180, 173, 135, 218, 167, 146, 48, 174, 19, 123, 55, 129, 162, 67, 93, 116, 156, 103, 199, 233, 201, 188, 174, 240, 246, 154, 117, 234, 24, 103, 40, 250, 67, 233, 80, 11, 219, 82, 191, 217, 150, 111, 90, 35, 213, 26, 165, 143, 30, 246, 56, 40, 36, 187, 89, 19, 131, 61, 184, 3, 62, 88, 233, 251, 121, 5, 174, 50, 144, 224, 113, 101, 150, 164, 203, 185, 144, 27, 53, 135, 244, 6, 126, 27, 80, 31, 78, 17, 87, 139, 184, 80, 2, 202, 132, 72, 196, 35, 63, 127, 235, 222, 26, 154, 52, 121, 247, 126, 240, 122, 247, 182, 49, 89, 101, 34, 123, 71, 64, 148, 139, 76, 166, 221, 80, 23, 69, 232, 245, 183, 246, 154, 169, 31, 98, 134, 70, 174, 86, 113, 46, 202, 122, 9, 61, 233, 25, 38, 235, 177, 149, 34, 70, 70, 69, 215, 113, 12, 254, 124, 130, 62, 109, 154, 74, 140, 122, 220, 62, 120, 4, 127, 126, 192, 254, 198, 30, 230, 202, 14, 176, 113, 53, 1, 125, 155, 67, 31, 110, 17, 232, 34, 193, 106, 3, 88, 174, 49, 212, 218, 86, 16, 13, 181, 132, 54, 160, 17, 85, 85, 176, 137, 110, 73, 41, 145, 14, 141, 249, 250, 165, 192, 136, 62, 61, 228, 125, 218, 166, 125, 98, 195, 214, 220, 200, 182, 106, 68, 15, 50, 106, 228, 36, 65, 251, 18, 30, 43, 21, 228, 65, 214, 91, 245, 187, 43, 45, 238, 253, 254, 7, 97, 191, 246, 172, 5, 57, 199, 183, 236, 132, 111, 233, 193, 183, 12, 225, 91, 26, 124, 203, 206, 248, 150, 126, 124, 5, 82, 214, 180, 77, 63, 12, 241, 124, 110, 131, 222, 38, 110, 85, 169, 206, 91, 105, 205, 82, 173, 48, 212, 210, 78, 43, 80, 60, 254, 138, 9, 49, 106, 88, 207, 170, 119, 218, 220, 208, 136, 247, 145, 141, 46, 254, 60, 20, 123, 132, 166, 168, 167, 132, 252, 136, 13, 24, 143, 127, 198, 237, 17, 189, 239, 194, 19, 165, 165, 115, 131, 45, 66, 40, 233, 154, 231, 11, 11, 155, 74, 29, 65, 33, 135, 63, 122, 212, 48, 3, 11, 195, 86, 51, 32, 154, 249, 174, 51, 141, 242, 45, 124, 203, 164, 81, 234, 25, 117, 152, 167, 168, 114, 208, 133, 125, 202, 103, 98, 71, 159, 135, 158, 216, 174, 71, 203, 101, 56, 131, 13, 218, 80, 216, 74, 32, 100, 5, 234, 52, 132, 171, 136, 146, 155, 199, 6, 25, 26, 189, 18, 100, 41, 181, 237, 56, 19, 27, 131, 246, 32, 251, 251, 252, 119, 225, 115, 58, 24, 68, 175, 27, 60, 173, 212, 73, 245, 90, 37, 235, 114, 205, 227, 47, 251, 121, 214, 126, 158, 32, 39, 242, 128, 141, 121, 172, 67, 95, 46, 48, 110, 209, 190, 29, 93, 95, 158, 133, 237, 195, 179, 176, 93, 120, 214, 100, 15, 158, 9, 59, 208, 44, 11, 173, 221, 66, 72, 82, 199, 62, 190, 53, 19, 89, 211, 150, 96, 72, 36, 62, 211, 94, 160, 45, 105, 12, 244, 121, 90, 38, 239, 228, 121, 166, 126, 158, 61, 23, 79, 70, 226, 102, 162, 72, 48, 128, 69, 126, 175, 75, 155, 47, 91, 129, 100, 249, 178, 161, 64, 222, 124, 216, 94, 150, 91, 244, 120, 111, 89, 54, 49, 8, 109, 61, 43, 248, 130, 183, 117, 54, 170, 234, 52, 81, 221, 25, 136, 100, 188, 242, 151, 207, 183, 103, 122, 174, 58, 130, 170, 195, 208, 103, 168, 114, 68, 192, 217, 95, 201, 64, 246, 17, 152, 53, 176, 228, 21, 219, 127, 192, 243, 191, 117, 168, 207, 39, 38, 185, 233, 139, 125, 49, 171, 61, 80, 146, 30, 135, 73, 153, 79, 63, 36, 253, 61, 146, 131, 21, 77, 63, 254, 16, 79, 94, 119, 19, 208, 30, 68, 154, 242, 26, 109, 143, 15, 132, 94, 36, 173, 152, 80, 252, 233, 99, 66, 145, 254, 51, 69, 83, 226, 67, 114, 119, 145, 0, 34, 3, 179, 232, 137, 151, 0, 13, 121, 200, 2, 109, 5, 25, 151, 78, 106, 34, 46, 237, 69, 90, 114, 243, 128, 251, 105, 94, 164, 103, 201, 243, 188, 96, 90, 191, 52, 123, 87, 90, 32, 196, 246, 225, 155, 92, 30, 188, 98, 5, 164, 254, 208, 171, 93, 40, 241, 52, 234, 127, 183, 181, 21, 125, 27, 49, 11, 57, 124, 66, 124, 56, 252, 43, 17, 221, 41, 67, 67, 78, 37, 194, 99, 196, 64, 173, 145, 73, 35, 229, 211, 8, 251, 163, 54, 43, 205, 70, 165, 71, 215, 1, 60, 54, 125, 242, 185, 252, 40, 117, 76, 6, 248, 76, 136, 161, 28, 105, 252, 158, 136, 126, 21, 23, 60, 136, 67, 6, 255, 241, 35, 98, 204, 28, 211, 39, 207, 88, 109, 226, 208, 208, 106, 64, 84, 236, 18, 36, 170, 106, 88, 19, 182, 114, 26, 144, 38, 27, 172, 136, 191, 232, 168, 188, 255, 37, 245, 254, 183, 167, 63, 200, 110, 110, 242, 110, 234, 215, 111, 242, 81, 62, 47, 198, 137, 213, 28, 181, 36, 218, 94, 177, 209, 134, 118, 114, 75, 108, 191, 220, 207, 166, 41, 63, 240, 249, 2, 106, 105, 184, 100, 52, 240, 62, 152, 250, 48, 86, 250, 91, 15, 21, 105, 32, 162, 163, 131, 148, 125, 195, 0, 61, 108, 30, 32, 17, 219, 125, 241, 134, 191, 86, 140, 239, 30, 74, 124, 26, 109, 171, 70, 116, 105, 235, 204, 161, 90, 37, 122, 208, 212, 85, 194, 38, 181, 131, 235, 246, 32, 66, 213, 208, 162, 22, 207, 39, 24, 151, 74, 119, 225, 211, 49, 158, 30, 184, 110, 204, 199, 29, 92, 76, 43, 201, 28, 233, 251, 229, 107, 102, 241, 37, 19, 161, 42, 44, 185, 100, 6, 27, 121, 35, 149, 20, 143, 36, 65, 154, 73, 54, 255, 35, 45, 44, 223, 62, 106, 210, 142, 54, 63, 71, 81, 121, 145, 242, 124, 253, 128, 166, 210, 139, 250, 100, 26, 163, 255, 214, 35, 107, 242, 80, 148, 176, 181, 186, 226, 104, 51, 152, 59, 6, 202, 112, 97, 40, 92, 68, 74, 182, 142, 194, 224, 182, 175, 15, 78, 62, 12, 9, 220, 7, 75, 132, 43, 31, 182, 73, 3, 15, 111, 162, 1, 249, 240, 128, 180, 244, 221, 141, 182, 36, 31, 30, 146, 38, 191, 255, 52, 77, 202, 135, 239, 72, 219, 127, 249, 196, 109, 203, 135, 239, 9, 18, 63, 124, 46, 36, 228, 195, 95, 8, 54, 127, 253, 236, 216, 200, 135, 31, 8, 90, 195, 197, 53, 202, 210, 241, 146, 15, 127, 165, 8, 46, 65, 89, 45, 29, 65, 5, 144, 234, 193, 225, 50, 21, 225, 242, 81, 85, 79, 90, 201, 178, 245, 75, 204, 22, 36, 22, 210, 218, 130, 104, 194, 214, 61, 239, 165, 12, 171, 73, 87, 199, 166, 108, 250, 58, 174, 77, 149, 79, 222, 131, 206, 73, 104, 71, 90, 117, 204, 217, 148, 182, 174, 61, 162, 70, 84, 139, 93, 70, 219, 220, 35, 253, 11, 110, 144, 251, 208, 241, 118, 232, 52, 46, 151, 131, 187, 199, 246, 18, 21, 60, 70, 23, 107, 212, 53, 183, 36, 120, 175, 145, 143, 119, 64, 211, 76, 27, 138, 254, 1, 242, 245, 39, 186, 217, 14, 193, 54, 83, 187, 14, 53, 26, 231, 178, 199, 34, 128, 130, 163, 63, 154, 243, 187, 46, 221, 78, 13, 44, 235, 221, 166, 154, 168, 114, 132, 106, 208, 236, 15, 95, 29, 38, 39, 207, 46, 103, 207, 167, 241, 73, 73, 34, 29, 193, 186, 61, 12, 122, 200, 14, 235, 216, 247, 176, 238, 180, 241, 33, 177, 159, 181, 119, 164, 215, 83, 141, 28, 110, 242, 75, 18, 38, 233, 216, 108, 200, 201, 98, 235, 172, 220, 164, 135, 201, 120, 184, 41, 78, 108, 121, 10, 158, 88, 5, 211, 147, 44, 47, 146, 189, 184, 76, 60, 133, 83, 171, 240, 57, 251, 0, 87, 58, 250, 202, 158, 91, 101, 39, 121, 181, 59, 245, 97, 80, 90, 5, 231, 89, 58, 206, 39, 62, 144, 115, 127, 73, 182, 28, 245, 145, 224, 131, 85, 186, 172, 210, 241, 217, 149, 167, 224, 85, 207, 226, 6, 147, 136, 202, 13, 254, 116, 24, 65, 198, 164, 30, 195, 27, 26, 143, 42, 138, 122, 238, 33, 189, 121, 134, 153, 65, 58, 166, 66, 248, 124, 100, 243, 140, 0, 92, 216, 180, 115, 159, 99, 76, 75, 240, 87, 120, 99, 165, 247, 223, 112, 179, 167, 130, 182, 46, 127, 243, 98, 117, 228, 49, 215, 116, 154, 251, 82, 49, 105, 118, 39, 31, 224, 110, 15, 241, 101, 31, 130, 211, 251, 35, 121, 167, 53, 114, 92, 105, 239, 85, 57, 159, 205, 132, 219, 59, 46, 248, 94, 128, 88, 123, 203, 248, 247, 145, 90, 37, 126, 253, 181, 180, 10, 44, 55, 135, 104, 230, 29, 176, 202, 235, 60, 205, 170, 93, 166, 27, 76, 115, 79, 163, 173, 203, 99, 246, 111, 133, 94, 211, 33, 160, 175, 71, 67, 246, 31, 105, 223, 210, 165, 208, 221, 151, 224, 168, 235, 139, 13, 9, 51, 202, 197, 101, 112, 152, 139, 203, 218, 107, 179, 46, 235, 6, 154, 213, 197, 35, 61, 194, 35, 40, 81, 80, 13, 178, 246, 102, 85, 122, 158, 254, 14, 110, 26, 129, 170, 139, 0, 102, 133, 134, 35, 146, 197, 229, 32, 82, 158, 15, 115, 122, 150, 213, 91, 93, 237, 11, 16, 50, 12, 201, 56, 71, 168, 222, 145, 173, 177, 14, 253, 67, 136, 174, 93, 119, 184, 37, 110, 58, 196, 239, 126, 216, 178, 157, 183, 162, 43, 191, 200, 67, 168, 140, 246, 172, 155, 28, 185, 209, 0, 3, 247, 237, 228, 139, 170, 114, 43, 225, 217, 101, 50, 22, 245, 236, 249, 0, 141, 43, 235, 249, 197, 235, 152, 205, 61, 170, 160, 127, 248, 173, 98, 154, 11, 28, 41, 43, 46, 145, 152, 233, 204, 26, 62, 134, 77, 179, 241, 116, 62, 225, 102, 22, 84, 0, 69, 211, 179, 247, 145, 5, 6, 158, 142, 184, 132, 110, 223, 204, 188, 199, 71, 161, 125, 133, 15, 98, 51, 135, 117, 109, 26, 151, 213, 190, 58, 182, 162, 228, 119, 23, 206, 164, 234, 107, 156, 50, 245, 41, 112, 194, 93, 79, 118, 222, 190, 169, 148, 146, 162, 140, 117, 64, 218, 108, 175, 139, 83, 87, 76, 124, 184, 20, 61, 138, 118, 49, 47, 136, 115, 138, 48, 104, 85, 65, 134, 134, 67, 53, 126, 22, 143, 115, 122, 151, 25, 228, 3, 93, 25, 97, 100, 224, 145, 203, 147, 165, 139, 28, 81, 69, 59, 225, 49, 181, 12, 135, 83, 18, 162, 17, 148, 5, 192, 237, 229, 87, 159, 6, 152, 46, 250, 8, 181, 188, 174, 243, 144, 241, 255, 103, 235, 235, 158, 149, 68, 59, 185, 210, 204, 237, 140, 118, 71, 14, 144, 91, 19, 140, 26, 160, 198, 148, 34, 175, 225, 141, 89, 94, 166, 50, 39, 163, 64, 118, 148, 196, 197, 248, 148, 153, 99, 18, 77, 155, 162, 48, 52, 166, 210, 19, 72, 45, 215, 145, 89, 112, 127, 104, 155, 47, 216, 23, 158, 153, 182, 63, 66, 74, 17, 49, 214, 104, 254, 94, 104, 100, 24, 30, 133, 5, 194, 49, 218, 208, 111, 151, 201, 113, 55, 205, 64, 114, 195, 72, 127, 120, 170, 198, 208, 179, 67, 184, 171, 170, 124, 108, 197, 123, 135, 201, 108, 26, 179, 5, 65, 41, 205, 135, 66, 252, 70, 17, 83, 159, 127, 102, 13, 51, 173, 208, 185, 162, 67, 241, 84, 246, 133, 149, 33, 233, 24, 81, 135, 116, 157, 180, 40, 171, 159, 115, 86, 164, 80, 227, 38, 50, 32, 242, 190, 57, 16, 205, 20, 96, 96, 81, 53, 102, 181, 161, 116, 166, 121, 173, 76, 166, 167, 56, 255, 128, 7, 13, 102, 10, 60, 183, 222, 250, 192, 227, 0, 188, 91, 104, 116, 192, 187, 32, 21, 53, 63, 203, 33, 125, 26, 125, 183, 69, 3, 254, 77, 48, 200, 79, 113, 41, 83, 84, 60, 147, 191, 158, 231, 76, 13, 156, 191, 159, 196, 62, 178, 24, 224, 154, 63, 21, 148, 53, 218, 128, 215, 180, 145, 136, 50, 114, 170, 214, 250, 164, 10, 168, 219, 129, 245, 102, 100, 191, 144, 221, 178, 95, 99, 108, 237, 111, 98, 86, 183, 94, 42, 196, 201, 107, 210, 207, 143, 43, 238, 83, 109, 175, 192, 182, 208, 122, 91, 162, 73, 17, 139, 140, 165, 132, 225, 242, 241, 180, 153, 117, 213, 82, 238, 13, 141, 115, 221, 140, 233, 73, 105, 73, 8, 230, 161, 97, 136, 126, 14, 237, 108, 60, 245, 39, 167, 87, 245, 232, 166, 144, 92, 184, 3, 181, 62, 106, 105, 168, 225, 124, 210, 36, 63, 157, 218, 97, 116, 220, 134, 154, 134, 164, 174, 57, 107, 60, 240, 104, 32, 194, 59, 35, 225, 31, 135, 0, 209, 195, 11, 2, 27, 153, 102, 106, 251, 87, 12, 18, 132, 94, 12, 172, 224, 190, 72, 180, 73, 31, 92, 252, 157, 225, 146, 175, 221, 46, 249, 214, 34, 30, 4, 68, 243, 188, 61, 212, 180, 221, 176, 183, 89, 167, 209, 182, 235, 26, 162, 168, 59, 173, 111, 204, 60, 138, 215, 46, 250, 20, 132, 171, 222, 63, 245, 34, 199, 111, 228, 82, 79, 93, 41, 82, 160, 188, 131, 29, 102, 147, 5, 69, 230, 200, 41, 111, 114, 253, 227, 36, 241, 242, 88, 148, 18, 199, 129, 70, 104, 125, 221, 10, 147, 226, 118, 135, 61, 139, 122, 243, 131, 181, 89, 70, 221, 189, 229, 145, 142, 91, 80, 153, 144, 147, 201, 33, 117, 193, 170, 52, 129, 194, 129, 253, 218, 44, 75, 104, 184, 44, 138, 124, 82, 196, 38, 225, 79, 122, 172, 229, 152, 28, 165, 40, 75, 67, 182, 23, 207, 152, 110, 73, 84, 30, 9, 158, 201, 227, 60, 190, 236, 27, 26, 241, 90, 58, 100, 97, 35, 26, 170, 11, 6, 209, 232, 240, 220, 239, 193, 193, 209, 197, 4, 72, 158, 125, 138, 87, 66, 118, 173, 179, 246, 34, 216, 72, 114, 154, 119, 105, 198, 48, 84, 105, 77, 36, 138, 194, 217, 166, 117, 169, 142, 139, 222, 90, 65, 138, 89, 112, 63, 215, 62, 224, 108, 51, 220, 227, 26, 213, 76, 114, 91, 76, 55, 26, 148, 150, 38, 102, 186, 137, 60, 253, 151, 135, 230, 43, 154, 118, 208, 189, 6, 240, 79, 210, 194, 59, 23, 233, 5, 157, 126, 163, 7, 172, 113, 126, 242, 235, 248, 128, 158, 71, 20, 178, 34, 133, 77, 198, 202, 8, 34, 126, 217, 159, 199, 79, 12, 22, 59, 176, 208, 194, 6, 17, 207, 27, 26, 207, 94, 105, 126, 59, 202, 244, 249, 85, 149, 250, 147, 125, 13, 28, 194, 129, 127, 154, 141, 160, 32, 178, 254, 148, 13, 163, 254, 114, 156, 226, 243, 100, 130, 88, 88, 114, 194, 9, 132, 226, 151, 120, 37, 73, 11, 6, 91, 215, 161, 255, 164, 188, 199, 140, 194, 163, 142, 233, 111, 219, 43, 154, 161, 159, 62, 241, 200, 178, 105, 218, 213, 2, 235, 230, 204, 13, 89, 227, 187, 80, 204, 186, 31, 82, 36, 121, 26, 89, 183, 89, 197, 112, 126, 228, 215, 48, 26, 224, 58, 22, 92, 119, 33, 230, 169, 204, 58, 106, 45, 213, 237, 148, 239, 170, 139, 150, 117, 35, 36, 196, 67, 136, 149, 86, 52, 80, 107, 43, 47, 9, 2, 150, 76, 80, 82, 141, 140, 34, 233, 228, 114, 137, 37, 146, 200, 226, 117, 141, 157, 177, 225, 98, 119, 90, 87, 31, 181, 2, 229, 83, 128, 103, 222, 85, 5, 7, 86, 21, 152, 126, 101, 87, 104, 220, 108, 179, 84, 135, 37, 186, 73, 154, 101, 45, 159, 64, 7, 13, 135, 186, 14, 232, 250, 58, 208, 178, 73, 252, 107, 215, 38, 174, 94, 8, 28, 179, 80, 177, 123, 154, 62, 88, 101, 208, 232, 61, 196, 239, 186, 219, 232, 147, 63, 161, 40, 41, 80, 191, 110, 118, 46, 168, 54, 112, 5, 106, 16, 105, 98, 125, 114, 39, 17, 169, 86, 200, 239, 53, 244, 11, 105, 93, 26, 86, 120, 43, 186, 103, 126, 12, 111, 160, 175, 219, 183, 183, 175, 230, 199, 246, 13, 116, 252, 193, 29, 233, 184, 249, 241, 224, 6, 168, 240, 240, 46, 82, 193, 252, 120, 184, 76, 146, 96, 127, 122, 71, 85, 221, 188, 231, 80, 87, 27, 47, 67, 91, 89, 110, 29, 225, 251, 172, 59, 226, 177, 177, 71, 188, 241, 88, 3, 117, 146, 161, 131, 134, 170, 113, 79, 224, 81, 139, 158, 217, 19, 92, 141, 125, 234, 248, 137, 152, 113, 195, 141, 166, 180, 154, 27, 222, 212, 84, 17, 70, 149, 248, 67, 89, 196, 227, 46, 178, 172, 150, 129, 139, 91, 216, 192, 122, 110, 79, 191, 220, 198, 146, 6, 86, 68, 54, 173, 220, 157, 24, 29, 158, 145, 185, 179, 188, 220, 94, 216, 16, 139, 234, 214, 230, 64, 139, 25, 191, 102, 190, 183, 103, 251, 26, 13, 209, 168, 31, 194, 218, 33, 160, 27, 244, 186, 154, 190, 246, 75, 56, 150, 111, 35, 221, 90, 182, 237, 121, 253, 51, 117, 68, 61, 218, 51, 249, 226, 125, 218, 190, 77, 125, 82, 143, 246, 124, 189, 120, 247, 30, 220, 210, 238, 169, 71, 123, 78, 94, 188, 167, 15, 111, 127, 79, 213, 163, 61, 235, 46, 208, 105, 236, 18, 12, 46, 5, 201, 170, 109, 171, 118, 213, 182, 211, 98, 226, 205, 116, 7, 50, 115, 4, 178, 190, 134, 86, 156, 235, 224, 7, 36, 179, 124, 235, 138, 219, 106, 130, 111, 57, 9, 182, 6, 252, 192, 55, 179, 163, 121, 145, 242, 207, 114, 230, 116, 239, 172, 183, 248, 198, 154, 217, 251, 88, 40, 128, 173, 83, 192, 204, 162, 158, 231, 79, 18, 55, 227, 236, 4, 116, 137, 145, 169, 241, 166, 45, 203, 151, 230, 58, 253, 188, 4, 211, 88, 155, 46, 163, 142, 60, 49, 158, 182, 91, 22, 90, 131, 200, 143, 215, 1, 247, 197, 239, 231, 139, 18, 88, 105, 189, 141, 41, 246, 223, 219, 202, 106, 103, 185, 204, 139, 244, 4, 78, 228, 139, 190, 224, 232, 21, 49, 226, 222, 240, 149, 225, 154, 93, 253, 185, 220, 61, 149, 145, 212, 58, 235, 155, 212, 142, 60, 93, 77, 169, 133, 233, 239, 214, 7, 180, 29, 120, 3, 186, 194, 241, 67, 91, 91, 68, 104, 139, 208, 198, 152, 110, 235, 117, 86, 58, 13, 106, 199, 203, 249, 221, 148, 143, 189, 45, 214, 61, 66, 47, 106, 177, 91, 102, 111, 66, 184, 182, 81, 131, 101, 20, 178, 139, 188, 86, 145, 179, 71, 229, 183, 113, 140, 133, 163, 115, 130, 225, 61, 37, 254, 136, 71, 207, 218, 134, 230, 241, 160, 77, 67, 23, 220, 150, 14, 12, 221, 142, 127, 84, 180, 149, 215, 134, 228, 144, 232, 108, 199, 207, 117, 120, 239, 17, 23, 195, 28, 83, 183, 155, 18, 220, 66, 244, 175, 155, 145, 73, 76, 119, 17, 107, 55, 13, 241, 88, 91, 3, 243, 137, 231, 75, 35, 241, 109, 167, 75, 50, 46, 244, 94, 164, 219, 58, 83, 98, 204, 254, 124, 162, 120, 194, 108, 10, 202, 66, 237, 212, 58, 216, 196, 186, 49, 107, 106, 248, 243, 79, 27, 84, 93, 124, 35, 183, 174, 201, 236, 192, 107, 163, 205, 108, 163, 222, 244, 89, 209, 195, 248, 162, 79, 91, 29, 80, 24, 158, 240, 204, 123, 102, 29, 224, 200, 200, 78, 22, 2, 138, 104, 188, 147, 198, 194, 103, 153, 244, 191, 204, 15, 214, 252, 208, 28, 219, 43, 211, 83, 205, 68, 216, 176, 24, 119, 39, 181, 27, 212, 162, 123, 192, 6, 60, 175, 92, 19, 146, 177, 179, 131, 126, 208, 249, 10, 170, 154, 175, 86, 236, 8, 252, 67, 49, 205, 86, 194, 114, 60, 10, 56, 236, 118, 181, 190, 183, 139, 205, 151, 238, 140, 105, 5, 224, 250, 236, 25, 207, 188, 25, 216, 30, 249, 50, 131, 126, 153, 65, 163, 47, 51, 104, 83, 32, 124, 199, 233, 211, 221, 120, 186, 177, 121, 244, 203, 92, 119, 27, 230, 186, 155, 136, 233, 235, 176, 135, 138, 105, 21, 152, 102, 220, 45, 85, 81, 120, 193, 213, 88, 56, 40, 115, 224, 239, 128, 124, 251, 101, 249, 246, 57, 38, 159, 123, 162, 158, 253, 39, 81, 90, 170, 103, 255, 201, 220, 112, 72, 253, 66, 199, 240, 204, 217, 142, 131, 98, 196, 115, 106, 80, 29, 223, 55, 233, 231, 127, 88, 211, 123, 73, 180, 6, 14, 243, 171, 101, 130, 112, 85, 62, 140, 158, 9, 131, 234, 9, 62, 140, 35, 196, 37, 216, 8, 14, 158, 226, 232, 232, 185, 172, 241, 90, 214, 225, 239, 199, 158, 196, 186, 140, 48, 86, 94, 177, 174, 247, 120, 134, 155, 183, 26, 119, 97, 227, 150, 45, 13, 83, 31, 98, 29, 154, 177, 137, 184, 108, 161, 13, 74, 166, 21, 172, 6, 238, 159, 28, 119, 217, 197, 248, 34, 197, 203, 145, 226, 46, 86, 91, 141, 197, 182, 44, 17, 214, 241, 82, 1, 227, 174, 205, 73, 156, 26, 163, 174, 214, 28, 14, 91, 118, 159, 66, 67, 180, 241, 3, 96, 43, 173, 49, 244, 109, 69, 26, 89, 95, 84, 77, 221, 73, 218, 150, 11, 186, 240, 177, 135, 47, 234, 231, 139, 250, 185, 147, 234, 103, 193, 128, 211, 229, 132, 249, 182, 92, 154, 118, 82, 120, 29, 99, 125, 191, 104, 70, 108, 22, 223, 178, 204, 108, 98, 71, 32, 249, 144, 230, 243, 242, 5, 226, 112, 204, 240, 142, 139, 108, 191, 252, 159, 164, 200, 97, 0, 217, 104, 115, 150, 232, 59, 48, 212, 217, 95, 222, 35, 171, 102, 64, 170, 200, 213, 116, 181, 153, 91, 32, 55, 187, 206, 180, 247, 152, 233, 229, 191, 28, 31, 31, 215, 28, 91, 183, 87, 76, 234, 88, 114, 29, 114, 14, 122, 78, 23, 165, 130, 163, 59, 25, 11, 38, 147, 145, 39, 208, 188, 19, 78, 120, 122, 8, 160, 68, 119, 28, 172, 60, 146, 158, 3, 0, 130, 60, 52, 105, 220, 192, 5, 30, 102, 234, 230, 170, 134, 221, 107, 19, 10, 240, 160, 214, 121, 81, 48, 169, 175, 227, 70, 62, 110, 134, 249, 236, 26, 62, 4, 2, 60, 231, 165, 160, 226, 193, 192, 36, 40, 105, 183, 97, 223, 106, 68, 103, 32, 151, 84, 179, 41, 91, 10, 171, 100, 82, 83, 88, 24, 223, 38, 45, 240, 94, 222, 104, 84, 229, 133, 216, 30, 244, 93, 113, 36, 122, 98, 18, 99, 4, 110, 74, 130, 1, 69, 240, 204, 38, 178, 17, 105, 125, 3, 67, 189, 152, 243, 66, 123, 188, 139, 24, 65, 249, 161, 207, 169, 72, 207, 102, 64, 196, 171, 236, 189, 249, 170, 110, 225, 162, 54, 34, 196, 234, 114, 79, 34, 55, 135, 248, 176, 148, 48, 72, 85, 82, 168, 97, 64, 24, 235, 28, 31, 221, 165, 219, 106, 38, 176, 13, 65, 117, 0, 151, 125, 162, 86, 202, 238, 59, 247, 240, 79, 117, 201, 191, 225, 84, 202, 141, 38, 213, 236, 255, 241, 118, 189, 170, 13, 1, 42, 148, 242, 179, 13, 208, 250, 76, 44, 62, 74, 116, 74, 146, 178, 163, 53, 124, 150, 92, 60, 87, 33, 8, 234, 128, 113, 91, 64, 87, 61, 164, 84, 21, 32, 28, 211, 224, 116, 221, 46, 4, 217, 103, 69, 166, 94, 165, 101, 17, 113, 130, 57, 223, 247, 6, 17, 220, 1, 117, 57, 208, 240, 136, 116, 210, 188, 132, 98, 118, 219, 197, 91, 79, 140, 159, 21, 95, 122, 24, 95, 117, 137, 125, 130, 74, 60, 143, 44, 252, 219, 113, 22, 9, 188, 128, 128, 240, 244, 233, 83, 203, 219, 168, 26, 148, 173, 80, 95, 60, 78, 164, 167, 106, 148, 233, 239, 192, 148, 56, 247, 28, 191, 71, 148, 191, 198, 149, 3, 242, 36, 83, 34, 211, 137, 90, 145, 83, 78, 215, 225, 132, 90, 118, 78, 63, 58, 110, 6, 50, 159, 104, 16, 212, 53, 115, 131, 121, 51, 80, 254, 127, 127, 58, 196, 45, 115, 8, 209, 71, 156, 223, 96, 142, 241, 168, 191, 87, 57, 178, 226, 177, 90, 100, 150, 205, 106, 32, 208, 22, 99, 15, 32, 229, 142, 226, 111, 204, 2, 2, 98, 99, 251, 135, 9, 244, 239, 59, 62, 162, 155, 118, 77, 183, 127, 115, 237, 36, 66, 254, 223, 136, 141, 242, 155, 116, 42, 131, 158, 253, 13, 12, 112, 220, 54, 252, 243, 110, 148, 36, 173, 226, 97, 127, 143, 204, 93, 209, 122, 44, 131, 108, 243, 187, 179, 156, 173, 65, 251, 247, 246, 155, 159, 64, 143, 223, 205, 66, 210, 116, 188, 75, 103, 127, 99, 42, 226, 119, 182, 154, 37, 177, 184, 1, 133, 74, 44, 146, 223, 118, 156, 238, 57, 188, 219, 220, 177, 223, 120, 20, 13, 213, 181, 161, 109, 178, 223, 224, 178, 201, 223, 240, 118, 24, 191, 224, 157, 205, 181, 246, 245, 186, 162, 107, 218, 251, 226, 226, 239, 164, 97, 19, 42, 96, 70, 153, 109, 113, 196, 40, 90, 117, 114, 41, 213, 231, 192, 138, 170, 102, 64, 33, 140, 90, 221, 107, 37, 75, 137, 20, 160, 56, 245, 226, 46, 199, 155, 233, 63, 39, 97, 28, 201, 199, 10, 218, 50, 49, 117, 127, 247, 40, 21, 62, 89, 113, 235, 227, 224, 184, 49, 135, 210, 239, 254, 244, 73, 2, 10, 228, 111, 210, 148, 144, 194, 159, 242, 131, 93, 22, 120, 204, 8, 13, 212, 249, 93, 93, 106, 39, 25, 74, 81, 194, 67, 156, 70, 2, 185, 68, 194, 156, 131, 85, 169, 214, 138, 202, 210, 158, 217, 178, 213, 128, 118, 79, 94, 216, 137, 229, 169, 35, 31, 240, 249, 73, 179, 2, 50, 227, 119, 61, 182, 251, 187, 89, 145, 87, 57, 152, 149, 239, 132, 48, 90, 139, 248, 186, 36, 250, 252, 8, 214, 126, 73, 140, 219, 67, 59, 117, 54, 49, 94, 36, 197, 32, 79, 171, 212, 111, 73, 117, 154, 79, 246, 143, 255, 85, 196, 179, 153, 137, 174, 63, 84, 15, 114, 81, 33, 127, 245, 188, 56, 91, 23, 250, 214, 45, 7, 130, 233, 201, 15, 3, 73, 199, 223, 36, 101, 213, 137, 38, 53, 11, 154, 14, 23, 11, 180, 194, 31, 16, 127, 158, 23, 28, 69, 23, 255, 175, 212, 218, 140, 175, 97, 228, 181, 8, 234, 30, 14, 142, 124, 248, 98, 1, 89, 73, 222, 185, 112, 52, 226, 183, 249, 110, 150, 226, 237, 91, 114, 199, 0, 154, 166, 118, 167, 211, 207, 228, 3, 42, 105, 102, 188, 207, 176, 254, 35, 139, 13, 21, 99, 90, 12, 34, 103, 113, 223, 232, 253, 113, 150, 132, 250, 72, 254, 34, 139, 164, 5, 150, 116, 18, 119, 180, 22, 106, 183, 65, 65, 84, 150, 70, 182, 215, 163, 136, 132, 150, 79, 166, 213, 22, 139, 12, 79, 197, 205, 118, 72, 106, 68, 164, 70, 233, 176, 182, 58, 233, 173, 49, 78, 228, 254, 171, 71, 96, 184, 255, 217, 29, 196, 92, 130, 24, 110, 113, 16, 46, 117, 55, 182, 45, 149, 45, 46, 89, 148, 82, 41, 108, 8, 102, 150, 196, 192, 138, 154, 199, 24, 181, 6, 54, 3, 78, 253, 174, 173, 26, 112, 69, 114, 146, 92, 206, 6, 74, 227, 134, 1, 154, 172, 20, 214, 255, 248, 76, 46, 193, 177, 190, 188, 74, 46, 188, 13, 241, 110, 11, 126, 100, 250, 135, 176, 161, 170, 205, 23, 31, 2, 161, 86, 165, 135, 10, 237, 86, 165, 183, 85, 231, 90, 149, 126, 160, 60, 8, 127, 202, 17, 243, 87, 16, 150, 146, 170, 197, 127, 201, 59, 235, 53, 229, 86, 172, 171, 79, 100, 97, 159, 67, 141, 80, 236, 85, 114, 89, 161, 107, 109, 196, 149, 242, 126, 157, 202, 175, 36, 102, 179, 114, 95, 20, 250, 101, 30, 23, 147, 55, 185, 119, 24, 160, 232, 90, 200, 3, 88, 63, 105, 83, 72, 129, 41, 28, 16, 180, 230, 109, 183, 91, 158, 169, 91, 187, 81, 255, 136, 248, 189, 215, 143, 240, 177, 243, 73, 158, 177, 23, 60, 77, 173, 184, 255, 217, 222, 63, 213, 122, 206, 29, 28, 184, 98, 77, 140, 139, 26, 8, 247, 40, 178, 89, 136, 75, 151, 39, 52, 8, 212, 46, 148, 101, 238, 245, 57, 11, 188, 129, 93, 49, 10, 98, 76, 28, 93, 75, 145, 217, 90, 65, 91, 73, 130, 137, 91, 168, 120, 10, 99, 136, 97, 180, 212, 248, 20, 194, 3, 12, 161, 54, 245, 251, 226, 7, 243, 173, 253, 99, 228, 62, 145, 49, 185, 157, 60, 129, 146, 179, 116, 15, 162, 104, 219, 240, 18, 137, 144, 87, 6, 234, 107, 101, 52, 162, 9, 184, 175, 61, 177, 45, 34, 233, 165, 130, 28, 10, 169, 145, 152, 186, 213, 3, 51, 172, 172, 189, 45, 106, 31, 123, 34, 231, 67, 155, 245, 122, 193, 33, 73, 170, 127, 147, 205, 20, 249, 150, 172, 160, 87, 195, 219, 241, 181, 123, 241, 122, 147, 90, 207, 147, 184, 194, 227, 39, 146, 81, 229, 146, 14, 45, 146, 126, 180, 119, 225, 173, 73, 197, 19, 183, 10, 145, 171, 198, 51, 130, 34, 102, 189, 171, 255, 26, 229, 235, 48, 4, 252, 123, 136, 127, 108, 12, 245, 15, 180, 50, 12, 73, 186, 248, 102, 73, 59, 166, 146, 239, 14, 132, 224, 6, 191, 237, 48, 177, 199, 128, 23, 146, 113, 227, 222, 184, 240, 198, 88, 98, 27, 162, 47, 158, 88, 140, 145, 199, 39, 81, 59, 64, 193, 224, 98, 67, 139, 107, 142, 12, 158, 35, 173, 1, 114, 206, 83, 45, 157, 5, 76, 4, 10, 103, 132, 15, 242, 162, 15, 78, 234, 29, 253, 205, 97, 4, 181, 7, 41, 213, 126, 211, 14, 132, 118, 165, 66, 121, 98, 173, 90, 33, 227, 254, 254, 241, 11, 66, 169, 85, 212, 64, 10, 68, 6, 77, 130, 13, 164, 36, 213, 196, 37, 133, 141, 108, 91, 18, 177, 213, 218, 219, 47, 150, 221, 145, 24, 98, 77, 221, 105, 162, 117, 69, 78, 247, 192, 202, 142, 174, 132, 14, 205, 7, 170, 152, 218, 94, 183, 228, 7, 32, 129, 209, 226, 46, 34, 172, 33, 35, 174, 43, 136, 146, 232, 28, 193, 175, 164, 77, 55, 135, 195, 248, 13, 14, 72, 210, 60, 108, 163, 91, 54, 236, 72, 100, 229, 90, 227, 34, 150, 32, 126, 121, 112, 174, 111, 212, 214, 171, 154, 106, 245, 229, 239, 130, 186, 212, 70, 213, 223, 44, 155, 83, 95, 62, 64, 24, 147, 47, 9, 85, 149, 35, 179, 120, 23, 62, 137, 126, 143, 23, 234, 173, 189, 37, 60, 202, 42, 121, 131, 140, 100, 75, 171, 171, 178, 148, 181, 216, 218, 47, 95, 231, 101, 153, 190, 159, 94, 73, 91, 150, 172, 207, 53, 222, 164, 203, 220, 117, 177, 159, 193, 21, 185, 113, 197, 170, 38, 194, 28, 230, 97, 75, 98, 128, 63, 136, 214, 45, 31, 7, 91, 86, 244, 4, 75, 244, 68, 202, 166, 129, 225, 93, 81, 139, 182, 35, 215, 148, 28, 113, 201, 145, 134, 184, 251, 229, 43, 198, 122, 7, 197, 63, 84, 135, 57, 8, 234, 94, 241, 224, 40, 137, 39, 208, 36, 58, 33, 45, 95, 139, 203, 40, 71, 202, 34, 85, 142, 23, 169, 238, 96, 231, 89, 112, 113, 79, 81, 158, 55, 181, 218, 183, 171, 130, 75, 35, 206, 164, 205, 37, 165, 128, 155, 98, 98, 4, 95, 228, 249, 217, 124, 214, 95, 211, 134, 216, 170, 219, 25, 217, 221, 21, 99, 44, 145, 3, 193, 138, 26, 172, 165, 26, 239, 138, 40, 228, 56, 189, 201, 74, 7, 25, 47, 74, 211, 34, 226, 40, 149, 79, 121, 147, 177, 164, 36, 167, 170, 16, 100, 82, 91, 23, 133, 216, 212, 241, 148, 217, 184, 71, 106, 157, 200, 225, 115, 106, 142, 243, 233, 65, 246, 186, 128, 109, 167, 244, 67, 178, 151, 207, 51, 126, 123, 174, 59, 199, 233, 94, 219, 238, 21, 237, 79, 8, 116, 220, 235, 155, 212, 101, 0, 99, 207, 208, 215, 27, 223, 88, 137, 179, 73, 178, 210, 241, 115, 207, 217, 15, 1, 68, 92, 250, 57, 178, 38, 62, 25, 78, 160, 42, 4, 168, 168, 20, 139, 46, 232, 118, 6, 159, 86, 229, 190, 145, 62, 106, 71, 112, 89, 155, 14, 184, 247, 89, 218, 33, 89, 72, 205, 248, 136, 143, 184, 232, 178, 142, 131, 132, 255, 107, 20, 214, 13, 224, 132, 93, 170, 122, 96, 0, 109, 13, 33, 185, 51, 32, 166, 84, 70, 229, 132, 224, 176, 48, 94, 170, 202, 201, 13, 5, 41, 132, 240, 22, 150, 20, 22, 4, 75, 173, 14, 135, 67, 135, 231, 57, 186, 205, 78, 58, 205, 211, 162, 17, 122, 15, 168, 183, 169, 109, 86, 70, 211, 200, 123, 38, 254, 230, 245, 20, 107, 122, 249, 170, 138, 247, 231, 126, 104, 43, 237, 82, 113, 85, 86, 157, 252, 155, 91, 146, 106, 112, 224, 141, 181, 146, 92, 65, 80, 25, 112, 44, 3, 138, 5, 102, 43, 118, 72, 173, 228, 203, 89, 60, 97, 125, 188, 20, 38, 40, 91, 66, 164, 211, 233, 72, 90, 141, 236, 211, 179, 108, 114, 109, 241, 22, 96, 96, 115, 69, 60, 193, 246, 10, 60, 142, 170, 184, 168, 124, 70, 129, 181, 203, 66, 232, 152, 102, 213, 75, 133, 45, 182, 157, 117, 23, 176, 143, 139, 189, 225, 251, 196, 133, 21, 88, 67, 128, 8, 47, 3, 251, 97, 233, 88, 246, 82, 33, 165, 189, 206, 64, 157, 132, 32, 103, 232, 165, 53, 185, 42, 68, 110, 70, 114, 129, 58, 136, 60, 141, 250, 253, 97, 244, 248, 113, 244, 96, 11, 54, 175, 183, 41, 97, 15, 227, 236, 68, 43, 132, 45, 66, 47, 104, 80, 116, 149, 192, 219, 144, 253, 82, 200, 179, 37, 79, 54, 134, 64, 109, 233, 119, 82, 125, 113, 125, 176, 146, 53, 138, 100, 198, 56, 85, 197, 170, 67, 105, 241, 220, 87, 13, 254, 183, 124, 173, 183, 220, 255, 52, 110, 70, 127, 107, 235, 56, 100, 93, 194, 132, 213, 166, 130, 248, 95, 22, 68, 69, 83, 201, 67, 64, 83, 124, 252, 223, 80, 149, 173, 97, 188, 45, 90, 83, 98, 0, 43, 49, 46, 94, 225, 120, 87, 2, 155, 250, 69, 4, 182, 157, 162, 30, 217, 241, 36, 196, 52, 80, 4, 151, 195, 126, 157, 87, 210, 248, 146, 36, 36, 158, 239, 146, 44, 32, 162, 75, 107, 159, 211, 148, 54, 175, 71, 137, 239, 250, 28, 23, 249, 185, 138, 4, 240, 110, 204, 168, 227, 41, 170, 218, 175, 204, 58, 75, 166, 125, 165, 128, 148, 38, 66, 17, 27, 2, 228, 22, 103, 26, 207, 231, 169, 68, 115, 11, 113, 149, 75, 158, 66, 93, 48, 203, 67, 162, 100, 122, 87, 55, 183, 249, 117, 140, 19, 9, 205, 103, 155, 200, 149, 136, 92, 178, 32, 28, 200, 186, 101, 25, 43, 19, 4, 59, 184, 60, 193, 101, 234, 231, 126, 92, 178, 141, 1, 160, 110, 213, 137, 8, 153, 5, 71, 5, 175, 144, 68, 231, 120, 168, 77, 64, 128, 184, 243, 152, 162, 55, 182, 11, 52, 156, 86, 134, 129, 191, 123, 55, 98, 29, 40, 196, 186, 144, 166, 165, 197, 32, 0, 142, 156, 66, 184, 119, 74, 61, 234, 69, 51, 190, 65, 24, 177, 160, 165, 47, 5, 36, 117, 183, 36, 142, 101, 24, 144, 102, 3, 87, 100, 74, 106, 251, 47, 65, 94, 184, 41, 255, 125, 199, 100, 162, 155, 229, 101, 109, 184, 243, 36, 185, 60, 56, 70, 59, 203, 8, 190, 153, 73, 242, 210, 217, 129, 83, 147, 8, 43, 135, 155, 3, 68, 44, 111, 31, 175, 80, 195, 8, 110, 2, 107, 218, 73, 214, 186, 246, 118, 174, 160, 173, 176, 42, 78, 167, 175, 121, 239, 0, 191, 117, 82, 203, 58, 176, 151, 37, 23, 35, 141, 42, 238, 145, 118, 49, 234, 18, 58, 44, 130, 248, 235, 240, 103, 162, 230, 57, 134, 226, 16, 153, 38, 187, 41, 188, 254, 68, 17, 100, 135, 48, 176, 182, 197, 74, 27, 91, 206, 153, 178, 99, 143, 73, 105, 23, 211, 117, 31, 46, 178, 242, 128, 182, 180, 161, 222, 219, 235, 93, 68, 153, 224, 76, 193, 99, 135, 110, 124, 178, 104, 191, 150, 245, 233, 42, 178, 160, 245, 43, 51, 188, 170, 69, 37, 238, 230, 210, 22, 17, 173, 121, 113, 251, 101, 150, 251, 143, 157, 229, 22, 154, 115, 118, 149, 149, 187, 248, 180, 35, 42, 24, 61, 23, 214, 205, 177, 216, 130, 249, 233, 202, 14, 79, 30, 14, 8, 20, 221, 125, 102, 218, 31, 28, 67, 28, 255, 75, 185, 57, 166, 79, 170, 232, 240, 20, 147, 25, 13, 29, 213, 174, 203, 135, 6, 251, 53, 232, 176, 182, 47, 196, 198, 51, 107, 234, 47, 56, 14, 150, 144, 74, 190, 83, 88, 240, 159, 136, 123, 73, 179, 143, 61, 201, 246, 157, 107, 6, 80, 127, 112, 229, 29, 91, 176, 2, 105, 183, 107, 147, 110, 251, 19, 127, 121, 18, 110, 251, 186, 232, 203, 36, 166, 189, 40, 188, 219, 184, 243, 134, 203, 71, 211, 148, 199, 148, 152, 153, 204, 75, 85, 58, 232, 54, 93, 217, 252, 70, 11, 224, 182, 10, 149, 115, 140, 180, 232, 156, 245, 182, 219, 136, 200, 153, 125, 204, 137, 59, 116, 36, 24, 96, 205, 195, 120, 230, 178, 192, 61, 166, 147, 61, 141, 101, 242, 207, 229, 86, 167, 41, 0, 167, 207, 246, 212, 238, 217, 3, 148, 252, 43, 58, 179, 52, 87, 180, 0, 247, 101, 171, 202, 154, 27, 197, 145, 163, 6, 7, 112, 41, 207, 37, 181, 244, 0, 75, 82, 227, 25, 80, 67, 184, 69, 14, 96, 133, 211, 117, 60, 192, 55, 181, 105, 69, 18, 34, 52, 111, 93, 109, 108, 47, 111, 207, 234, 186, 238, 106, 61, 250, 93, 156, 213, 165, 56, 0, 158, 204, 98, 25, 52, 139, 206, 128, 95, 75, 234, 1, 174, 207, 98, 151, 34, 14, 239, 189, 11, 106, 40, 211, 78, 148, 49, 11, 107, 135, 145, 236, 135, 23, 180, 42, 92, 115, 78, 149, 140, 164, 228, 8, 232, 9, 98, 191, 129, 105, 5, 133, 162, 185, 39, 138, 66, 46, 45, 31, 134, 203, 113, 104, 41, 172, 66, 42, 204, 148, 104, 50, 243, 85, 185, 86, 138, 12, 232, 131, 136, 162, 172, 88, 193, 72, 142, 70, 51, 71, 146, 177, 101, 175, 235, 122, 216, 154, 115, 18, 209, 105, 10, 70, 75, 171, 222, 237, 205, 205, 168, 53, 125, 24, 178, 145, 22, 245, 27, 242, 252, 160, 146, 82, 114, 130, 89, 189, 61, 149, 199, 175, 221, 115, 211, 17, 63, 231, 132, 44, 127, 202, 175, 222, 83, 212, 186, 107, 71, 111, 241, 152, 137, 57, 4, 243, 108, 120, 183, 254, 104, 68, 170, 134, 164, 72, 30, 176, 29, 68, 135, 156, 48, 90, 59, 212, 224, 220, 2, 11, 138, 3, 50, 116, 92, 41, 134, 166, 253, 202, 16, 217, 88, 113, 81, 113, 19, 107, 9, 170, 80, 65, 237, 186, 51, 55, 245, 108, 182, 201, 29, 59, 190, 211, 199, 43, 238, 51, 38, 60, 129, 99, 198, 240, 6, 111, 234, 241, 221, 29, 232, 129, 149, 138, 226, 71, 14, 247, 17, 170, 10, 189, 84, 21, 143, 121, 162, 111, 9, 221, 44, 184, 82, 225, 158, 208, 171, 47, 133, 2, 236, 38, 240, 93, 12, 10, 64, 180, 93, 91, 157, 21, 241, 84, 46, 242, 115, 187, 162, 193, 104, 160, 129, 27, 47, 95, 110, 175, 11, 131, 197, 3, 251, 41, 122, 51, 134, 239, 154, 176, 153, 36, 103, 166, 51, 252, 94, 147, 199, 70, 248, 89, 187, 253, 114, 63, 155, 50, 104, 108, 88, 95, 196, 197, 73, 98, 111, 8, 233, 49, 198, 7, 236, 200, 55, 197, 82, 216, 190, 191, 62, 87, 45, 176, 217, 219, 196, 58, 50, 117, 130, 203, 118, 156, 149, 34, 20, 129, 137, 121, 138, 215, 194, 76, 101, 109, 55, 234, 134, 31, 163, 220, 11, 6, 25, 47, 115, 193, 194, 138, 129, 213, 113, 56, 216, 229, 234, 173, 203, 184, 197, 48, 38, 63, 185, 75, 157, 207, 96, 148, 33, 231, 106, 136, 59, 19, 197, 154, 242, 56, 174, 130, 201, 161, 213, 237, 205, 113, 94, 210, 152, 253, 41, 130, 126, 81, 163, 157, 25, 202, 195, 77, 227, 28, 182, 91, 33, 164, 113, 120, 125, 38, 18, 192, 186, 48, 17, 180, 182, 43, 195, 41, 229, 157, 212, 253, 53, 111, 62, 142, 146, 110, 204, 251, 43, 121, 182, 12, 216, 168, 235, 102, 153, 53, 160, 234, 245, 183, 214, 214, 154, 225, 109, 119, 130, 23, 250, 52, 92, 243, 48, 142, 144, 9, 120, 175, 47, 50, 77, 185, 223, 136, 253, 121, 28, 57, 232, 236, 192, 185, 117, 219, 137, 228, 122, 229, 112, 179, 169, 50, 114, 204, 170, 223, 84, 106, 191, 124, 7, 7, 198, 114, 39, 48, 128, 120, 39, 38, 47, 62, 125, 80, 253, 240, 152, 111, 117, 195, 191, 31, 157, 237, 112, 54, 254, 120, 34, 147, 229, 30, 133, 52, 10, 158, 169, 96, 226, 81, 13, 1, 178, 172, 153, 96, 3, 114, 170, 243, 0, 230, 95, 48, 216, 114, 22, 103, 182, 58, 212, 51, 146, 82, 132, 237, 102, 50, 14, 170, 139, 198, 129, 81, 246, 40, 28, 17, 179, 210, 31, 131, 69, 188, 148, 237, 156, 196, 175, 113, 194, 182, 112, 70, 120, 69, 32, 162, 116, 81, 134, 39, 20, 39, 172, 71, 102, 141, 210, 187, 69, 172, 248, 183, 40, 73, 223, 19, 39, 62, 168, 77, 128, 144, 9, 209, 224, 126, 86, 72, 141, 103, 129, 129, 240, 127, 141, 253, 27, 237, 113, 230, 122, 99, 103, 7, 175, 205, 160, 54, 202, 32, 244, 134, 123, 250, 176, 17, 157, 49, 171, 94, 103, 216, 224, 53, 76, 233, 17, 46, 77, 207, 218, 88, 158, 97, 164, 56, 222, 248, 116, 70, 170, 79, 248, 118, 26, 96, 179, 237, 36, 155, 213, 7, 18, 116, 128, 188, 254, 45, 18, 17, 168, 134, 244, 7, 58, 226, 252, 101, 75, 174, 160, 231, 149, 69, 137, 206, 39, 149, 71, 173, 10, 14, 45, 201, 243, 158, 255, 165, 24, 92, 251, 228, 175, 213, 161, 133, 206, 252, 82, 24, 109, 78, 251, 186, 157, 8, 164, 232, 104, 58, 114, 41, 14, 61, 33, 149, 110, 29, 242, 245, 31, 181, 228, 181, 140, 232, 120, 178, 120, 117, 63, 103, 44, 172, 79, 121, 112, 21, 167, 115, 233, 124, 78, 24, 78, 7, 189, 206, 83, 190, 117, 18, 218, 185, 213, 101, 118, 43, 30, 66, 158, 146, 44, 208, 227, 211, 184, 224, 174, 5, 6, 97, 200, 180, 68, 223, 128, 124, 42, 179, 163, 213, 48, 164, 160, 142, 132, 201, 106, 107, 104, 146, 55, 201, 153, 159, 16, 130, 48, 65, 236, 169, 86, 7, 156, 155, 6, 166, 103, 152, 203, 141, 137, 209, 60, 123, 96, 142, 241, 45, 129, 42, 54, 11, 140, 223, 21, 241, 5, 79, 185, 48, 98, 2, 20, 25, 225, 24, 231, 249, 25, 79, 183, 172, 51, 7, 171, 66, 38, 216, 55, 190, 32, 223, 121, 141, 77, 246, 214, 216, 27, 92, 40, 167, 163, 228, 132, 155, 97, 228, 20, 88, 124, 97, 71, 63, 58, 165, 61, 6, 172, 12, 244, 168, 169, 97, 91, 175, 102, 231, 51, 190, 80, 7, 216, 168, 17, 233, 26, 128, 168, 168, 182, 43, 241, 201, 180, 225, 14, 250, 249, 216, 238, 38, 250, 104, 172, 77, 181, 119, 168, 234, 56, 182, 41, 246, 220, 32, 172, 214, 3, 118, 169, 134, 165, 236, 211, 143, 43, 181, 117, 161, 75, 186, 142, 161, 2, 97, 171, 112, 88, 201, 251, 244, 164, 227, 52, 228, 179, 51, 24, 20, 219, 200, 80, 195, 250, 152, 125, 123, 218, 195, 182, 63, 47, 6, 233, 19, 31, 255, 55, 255, 230, 69, 139, 113, 255, 217, 50, 16, 3, 56, 97, 212, 224, 107, 24, 57, 241, 213, 139, 94, 62, 157, 44, 3, 59, 6, 38, 140, 92, 24, 49, 63, 82, 199, 233, 101, 178, 12, 172, 56, 156, 32, 90, 85, 21, 196, 11, 62, 249, 237, 157, 152, 89, 187, 229, 18, 80, 147, 144, 130, 200, 165, 65, 220, 82, 63, 106, 229, 57, 211, 125, 75, 64, 140, 195, 9, 162, 197, 191, 6, 81, 147, 95, 189, 232, 177, 63, 103, 201, 50, 240, 227, 128, 194, 8, 242, 207, 97, 12, 229, 231, 128, 23, 119, 25, 248, 205, 223, 135, 145, 155, 135, 69, 129, 127, 243, 163, 53, 91, 10, 90, 179, 26, 180, 102, 53, 104, 205, 44, 180, 158, 149, 227, 120, 150, 236, 86, 172, 232, 251, 121, 37, 179, 86, 127, 48, 179, 114, 154, 205, 230, 160, 166, 241, 100, 245, 129, 172, 63, 253, 65, 65, 170, 222, 32, 250, 166, 247, 205, 32, 234, 125, 253, 219, 60, 175, 118, 122, 94, 135, 123, 156, 141, 79, 153, 113, 11, 135, 104, 175, 79, 26, 1, 172, 253, 210, 82, 118, 227, 155, 199, 49, 63, 197, 251, 164, 247, 13, 35, 149, 151, 42, 2, 191, 117, 214, 161, 167, 80, 102, 36, 72, 26, 7, 148, 94, 158, 85, 227, 124, 154, 195, 74, 117, 170, 114, 128, 93, 75, 251, 41, 128, 11, 116, 13, 234, 70, 188, 114, 77, 247, 36, 158, 118, 255, 160, 110, 184, 139, 96, 73, 247, 141, 57, 125, 221, 14, 2, 164, 69, 251, 7, 117, 107, 186, 39, 144, 108, 223, 59, 62, 209, 207, 139, 233, 245, 59, 230, 155, 234, 91, 241, 227, 105, 145, 28, 215, 244, 136, 35, 215, 200, 142, 73, 133, 210, 223, 237, 103, 169, 92, 209, 234, 116, 181, 34, 192, 164, 66, 235, 82, 17, 112, 55, 225, 187, 179, 236, 203, 38, 123, 70, 203, 85, 29, 41, 200, 139, 132, 60, 1, 16, 127, 42, 247, 186, 69, 57, 213, 113, 98, 221, 138, 128, 122, 40, 51, 157, 230, 23, 114, 39, 21, 22, 17, 6, 71, 5, 223, 183, 213, 202, 33, 195, 62, 107, 53, 48, 224, 100, 75, 148, 4, 207, 243, 226, 89, 60, 62, 229, 43, 138, 247, 241, 248, 236, 56, 19, 227, 193, 140, 219, 200, 217, 69, 84, 99, 227, 95, 167, 143, 196, 42, 125, 132, 214, 232, 42, 83, 20, 251, 214, 125, 113, 174, 182, 191, 107, 87, 228, 8, 111, 244, 149, 97, 111, 150, 236, 186, 147, 214, 82, 221, 30, 54, 3, 170, 110, 236, 126, 78, 128, 143, 211, 105, 194, 218, 232, 111, 13, 34, 92, 11, 243, 48, 95, 103, 250, 15, 15, 36, 213, 59, 241, 21, 223, 160, 192, 198, 74, 44, 18, 89, 49, 29, 119, 35, 18, 130, 140, 156, 79, 80, 41, 16, 139, 41, 151, 235, 108, 125, 2, 107, 77, 86, 245, 89, 86, 21, 87, 140, 2, 218, 85, 162, 218, 118, 91, 68, 251, 223, 0, 166, 38, 144, 82, 247, 80, 72, 130, 5, 71, 95, 54, 235, 253, 20, 225, 124, 209, 62, 238, 245, 240, 226, 64, 180, 166, 255, 140, 92, 102, 254, 138, 245, 181, 99, 74, 80, 83, 163, 38, 31, 168, 201, 93, 229, 142, 3, 235, 138, 136, 83, 114, 63, 245, 201, 50, 95, 125, 118, 28, 95, 7, 65, 113, 58, 16, 226, 116, 64, 196, 73, 15, 226, 193, 66, 2, 213, 201, 213, 69, 113, 246, 248, 185, 58, 179, 172, 88, 231, 131, 54, 170, 117, 78, 1, 75, 155, 28, 120, 205, 12, 125, 16, 228, 101, 78, 81, 204, 202, 210, 49, 122, 254, 107, 202, 55, 80, 26, 220, 109, 7, 38, 219, 168, 113, 81, 24, 25, 49, 128, 176, 175, 67, 111, 79, 213, 74, 134, 229, 143, 214, 119, 55, 235, 186, 71, 222, 202, 190, 158, 178, 215, 36, 174, 164, 89, 232, 196, 24, 104, 87, 24, 238, 151, 252, 36, 137, 78, 18, 215, 104, 255, 4, 148, 32, 83, 41, 184, 57, 193, 23, 55, 206, 139, 137, 112, 215, 254, 225, 176, 179, 112, 208, 122, 213, 42, 36, 197, 229, 190, 221, 112, 86, 92, 168, 77, 188, 69, 241, 197, 72, 56, 63, 217, 151, 77, 176, 96, 20, 187, 100, 243, 115, 249, 101, 93, 22, 82, 140, 160, 190, 136, 116, 223, 252, 25, 123, 132, 52, 72, 127, 12, 143, 141, 243, 67, 166, 50, 164, 81, 214, 211, 197, 213, 105, 18, 107, 116, 235, 234, 190, 138, 95, 233, 90, 168, 131, 176, 171, 38, 186, 97, 118, 118, 20, 210, 198, 107, 43, 202, 212, 236, 240, 124, 255, 215, 191, 18, 186, 157, 198, 165, 164, 25, 123, 242, 217, 46, 236, 117, 112, 246, 131, 196, 62, 236, 123, 143, 64, 60, 75, 174, 20, 72, 120, 244, 193, 132, 247, 181, 64, 161, 64, 207, 94, 175, 253, 1, 140, 252, 136, 167, 115, 226, 22, 236, 35, 69, 147, 1, 244, 98, 32, 26, 254, 104, 243, 161, 82, 10, 32, 203, 58, 122, 14, 88, 211, 168, 92, 168, 184, 95, 233, 131, 232, 110, 244, 45, 20, 231, 157, 225, 210, 6, 63, 216, 31, 124, 38, 68, 178, 180, 2, 212, 176, 233, 195, 216, 91, 62, 153, 150, 195, 156, 174, 202, 80, 117, 43, 105, 162, 62, 218, 134, 236, 63, 50, 192, 60, 175, 78, 147, 98, 225, 169, 69, 127, 107, 55, 177, 4, 76, 52, 25, 208, 199, 81, 25, 240, 73, 132, 227, 70, 121, 134, 127, 101, 116, 21, 106, 29, 169, 14, 222, 129, 29, 119, 156, 252, 3, 171, 192, 56, 53, 96, 162, 96, 181, 212, 207, 77, 48, 129, 205, 252, 163, 46, 178, 3, 251, 127, 118, 197, 58, 236, 248, 150, 131, 214, 247, 191, 210, 234, 148, 79, 224, 10, 244, 128, 180, 73, 108, 114, 199, 230, 99, 70, 185, 138, 119, 113, 173, 242, 218, 192, 5, 62, 63, 37, 69, 153, 8, 128, 183, 115, 156, 49, 138, 139, 12, 247, 136, 47, 181, 2, 57, 204, 217, 71, 147, 192, 92, 15, 97, 150, 92, 64, 181, 190, 137, 58, 96, 72, 73, 181, 233, 29, 2, 17, 46, 117, 160, 101, 89, 151, 127, 252, 68, 99, 185, 105, 223, 203, 210, 206, 146, 63, 64, 134, 66, 103, 195, 200, 107, 205, 47, 205, 158, 247, 89, 244, 129, 91, 80, 90, 218, 245, 109, 140, 12, 209, 170, 79, 195, 106, 74, 115, 61, 110, 232, 14, 171, 213, 15, 206, 233, 194, 102, 89, 250, 128, 14, 2, 146, 8, 115, 60, 11, 119, 215, 40, 75, 80, 10, 92, 243, 88, 161, 248, 222, 254, 112, 74, 28, 96, 181, 208, 141, 4, 84, 157, 88, 100, 104, 82, 46, 63, 167, 199, 199, 73, 145, 100, 227, 228, 150, 170, 22, 131, 224, 34, 138, 37, 160, 241, 63, 179, 190, 40, 176, 132, 126, 81, 26, 159, 66, 105, 76, 146, 105, 82, 37, 119, 81, 111, 180, 234, 142, 173, 3, 90, 201, 254, 232, 234, 252, 60, 169, 138, 116, 252, 185, 148, 128, 236, 97, 123, 143, 159, 208, 11, 242, 71, 207, 223, 5, 143, 179, 226, 222, 219, 156, 11, 205, 45, 139, 49, 22, 93, 221, 118, 159, 157, 90, 113, 230, 126, 9, 1, 156, 140, 159, 142, 111, 233, 172, 100, 16, 92, 100, 86, 90, 120, 234, 121, 234, 159, 121, 66, 169, 134, 187, 88, 175, 255, 193, 126, 104, 157, 110, 228, 58, 243, 142, 61, 6, 14, 167, 139, 32, 58, 151, 207, 103, 176, 114, 186, 221, 156, 174, 80, 252, 164, 188, 254, 184, 27, 175, 119, 211, 222, 75, 158, 165, 3, 9, 107, 26, 20, 240, 130, 44, 243, 115, 90, 254, 27, 226, 17, 161, 111, 119, 109, 190, 166, 216, 47, 60, 85, 127, 89, 235, 223, 63, 179, 221, 149, 134, 219, 109, 151, 47, 184, 158, 111, 232, 102, 141, 240, 255, 51, 77, 46, 146, 201, 110, 81, 196, 87, 63, 205, 193, 218, 221, 63, 62, 76, 210, 227, 20, 66, 46, 98, 120, 43, 154, 209, 233, 99, 223, 207, 143, 163, 208, 213, 81, 162, 130, 138, 66, 199, 231, 246, 180, 194, 96, 213, 225, 90, 55, 128, 162, 174, 178, 33, 119, 34, 252, 156, 84, 241, 248, 52, 153, 8, 92, 160, 248, 113, 130, 34, 122, 196, 239, 144, 90, 33, 234, 123, 71, 137, 169, 174, 164, 84, 20, 234, 172, 106, 32, 168, 169, 156, 25, 161, 229, 149, 81, 2, 238, 32, 122, 128, 3, 77, 240, 61, 79, 226, 230, 233, 45, 123, 183, 97, 183, 18, 253, 199, 56, 226, 113, 144, 67, 32, 250, 211, 60, 118, 138, 6, 33, 194, 6, 246, 25, 190, 151, 23, 88, 33, 198, 17, 21, 90, 160, 43, 5, 133, 108, 152, 135, 58, 38, 2, 113, 112, 136, 92, 86, 206, 139, 4, 16, 17, 5, 65, 114, 112, 141, 184, 56, 193, 65, 66, 230, 182, 9, 153, 96, 193, 212, 228, 47, 85, 247, 2, 237, 67, 145, 29, 52, 218, 170, 203, 238, 244, 4, 147, 147, 129, 237, 157, 163, 98, 21, 33, 210, 171, 163, 11, 76, 78, 180, 203, 6, 172, 231, 10, 77, 189, 245, 169, 229, 111, 44, 14, 224, 192, 238, 216, 216, 20, 84, 227, 60, 110, 58, 173, 143, 128, 195, 117, 168, 134, 92, 120, 63, 148, 206, 241, 99, 156, 201, 193, 179, 209, 218, 203, 121, 185, 111, 202, 232, 27, 132, 209, 55, 209, 76, 222, 191, 75, 237, 59, 62, 21, 178, 239, 158, 235, 73, 100, 140, 4, 186, 160, 196, 147, 115, 195, 78, 148, 214, 186, 67, 251, 132, 176, 14, 156, 82, 149, 245, 109, 185, 13, 229, 49, 171, 222, 223, 254, 38, 145, 212, 189, 139, 196, 94, 178, 32, 0, 234, 191, 59, 208, 76, 107, 167, 147, 184, 74, 44, 28, 93, 118, 198, 27, 219, 226, 131, 85, 197, 104, 254, 0, 99, 171, 190, 83, 214, 198, 25, 38, 156, 235, 91, 130, 77, 64, 233, 96, 217, 191, 199, 182, 98, 161, 149, 131, 154, 5, 155, 13, 54, 134, 158, 81, 248, 126, 123, 43, 36, 53, 34, 92, 6, 20, 133, 60, 108, 129, 6, 129, 30, 254, 23, 243, 244, 133, 169, 26, 213, 92, 160, 202, 177, 193, 160, 252, 47, 244, 173, 110, 188, 87, 158, 33, 38, 13, 154, 179, 51, 252, 172, 110, 144, 172, 178, 39, 110, 93, 126, 46, 38, 129, 35, 152, 52, 107, 153, 67, 174, 161, 234, 186, 57, 237, 138, 148, 57, 1, 220, 72, 87, 57, 178, 132, 174, 106, 126, 123, 127, 85, 37, 7, 199, 199, 220, 250, 186, 105, 90, 203, 54, 197, 179, 105, 119, 209, 113, 232, 78, 253, 133, 168, 199, 204, 2, 145, 241, 167, 29, 25, 63, 53, 249, 110, 15, 201, 212, 244, 103, 203, 115, 114, 153, 156, 207, 166, 177, 71, 152, 225, 222, 233, 218, 233, 83, 85, 197, 168, 212, 104, 142, 61, 221, 68, 91, 20, 229, 152, 50, 232, 26, 203, 21, 76, 105, 202, 166, 146, 73, 111, 160, 3, 18, 143, 189, 90, 193, 108, 219, 41, 155, 99, 91, 244, 238, 38, 250, 100, 163, 225, 237, 92, 168, 83, 176, 206, 53, 113, 155, 182, 19, 163, 201, 204, 60, 104, 197, 237, 7, 184, 7, 2, 111, 254, 25, 135, 17, 110, 7, 17, 252, 144, 20, 87, 40, 48, 53, 186, 14, 166, 237, 167, 20, 227, 189, 104, 200, 41, 98, 27, 122, 223, 241, 211, 219, 189, 255, 50, 16, 255, 107, 115, 166, 114, 254, 109, 38, 208, 155, 158, 109, 64, 222, 80, 32, 180, 137, 38, 119, 251, 240, 52, 26, 178, 229, 37, 77, 45, 18, 161, 136, 80, 226, 166, 59, 139, 120, 54, 145, 51, 49, 157, 178, 7, 154, 63, 228, 76, 38, 161, 143, 14, 142, 206, 222, 26, 255, 76, 149, 148, 38, 143, 97, 235, 104, 227, 51, 153, 112, 248, 204, 56, 123, 56, 149, 12, 180, 5, 92, 120, 163, 154, 99, 194, 22, 171, 225, 224, 97, 243, 233, 57, 51, 192, 97, 78, 186, 39, 108, 120, 204, 187, 243, 169, 248, 240, 205, 194, 28, 40, 92, 77, 51, 25, 113, 244, 238, 69, 90, 162, 144, 163, 113, 60, 99, 131, 204, 143, 103, 111, 93, 147, 93, 67, 62, 52, 204, 161, 111, 44, 222, 52, 108, 8, 24, 30, 41, 108, 214, 215, 193, 65, 39, 74, 82, 158, 132, 182, 119, 189, 74, 223, 158, 95, 15, 6, 186, 115, 150, 191, 92, 244, 12, 236, 90, 85, 128, 253, 50, 221, 219, 61, 202, 120, 235, 128, 80, 102, 167, 155, 219, 109, 47, 9, 130, 221, 67, 162, 144, 77, 250, 51, 214, 114, 10, 151, 235, 220, 117, 57, 200, 38, 97, 41, 208, 157, 236, 34, 4, 168, 210, 45, 209, 197, 33, 230, 214, 152, 134, 180, 175, 163, 104, 125, 92, 45, 63, 33, 100, 219, 51, 25, 79, 144, 20, 96, 49, 113, 169, 237, 93, 225, 51, 73, 39, 198, 110, 242, 105, 75, 239, 187, 212, 176, 30, 239, 99, 195, 217, 168, 187, 198, 132, 93, 184, 13, 120, 52, 200, 107, 94, 54, 219, 24, 118, 227, 47, 117, 183, 178, 143, 201, 156, 243, 119, 183, 156, 199, 148, 46, 51, 0, 49, 59, 201, 131, 118, 247, 200, 180, 108, 109, 50, 34, 54, 178, 166, 188, 69, 180, 146, 32, 164, 159, 103, 126, 77, 174, 62, 255, 82, 41, 232, 225, 123, 25, 207, 238, 30, 55, 7, 212, 227, 121, 60, 187, 27, 230, 105, 107, 139, 78, 185, 23, 219, 206, 228, 231, 156, 222, 106, 58, 111, 97, 157, 90, 98, 0, 214, 224, 25, 88, 131, 8, 208, 226, 22, 33, 227, 45, 191, 72, 28, 38, 147, 249, 56, 185, 55, 124, 87, 240, 238, 124, 10, 214, 83, 46, 106, 142, 44, 236, 202, 53, 228, 33, 181, 251, 177, 77, 152, 248, 44, 66, 247, 201, 196, 227, 241, 252, 124, 62, 149, 57, 232, 90, 243, 54, 99, 32, 182, 122, 209, 60, 234, 103, 77, 10, 187, 230, 94, 22, 247, 124, 184, 115, 35, 11, 130, 165, 94, 113, 38, 86, 235, 42, 253, 146, 154, 72, 146, 123, 81, 237, 128, 66, 20, 188, 121, 152, 158, 156, 86, 119, 135, 65, 187, 155, 146, 133, 233, 230, 39, 59, 104, 191, 124, 238, 5, 104, 27, 34, 159, 228, 245, 120, 120, 99, 131, 242, 240, 83, 161, 102, 55, 54, 238, 34, 11, 143, 188, 57, 115, 219, 4, 155, 173, 146, 237, 208, 3, 123, 31, 55, 20, 90, 214, 176, 123, 207, 122, 98, 174, 143, 2, 164, 228, 15, 200, 76, 173, 216, 212, 194, 222, 226, 201, 192, 86, 172, 45, 94, 1, 121, 18, 65, 221, 140, 98, 233, 135, 164, 41, 91, 239, 153, 76, 132, 75, 203, 55, 164, 221, 37, 133, 195, 185, 119, 173, 98, 56, 83, 174, 250, 116, 141, 52, 247, 22, 226, 50, 141, 111, 27, 180, 101, 70, 223, 122, 164, 157, 228, 190, 99, 153, 249, 209, 205, 87, 207, 68, 242, 12, 167, 203, 108, 239, 192, 34, 201, 112, 69, 3, 79, 141, 210, 227, 33, 14, 192, 29, 19, 2, 240, 167, 180, 186, 72, 203, 68, 112, 61, 131, 178, 203, 13, 26, 3, 75, 178, 186, 168, 105, 214, 140, 146, 104, 158, 244, 252, 3, 31, 35, 233, 157, 117, 227, 83, 147, 47, 100, 128, 32, 76, 124, 188, 58, 222, 161, 223, 61, 202, 132, 115, 207, 204, 147, 240, 207, 27, 62, 182, 27, 18, 231, 252, 252, 254, 216, 74, 37, 235, 204, 125, 90, 112, 126, 170, 189, 140, 154, 173, 12, 147, 235, 213, 98, 40, 185, 199, 209, 214, 92, 7, 62, 243, 219, 235, 111, 242, 23, 57, 67, 86, 221, 207, 59, 229, 63, 32, 216, 8, 37, 3, 201, 103, 80, 137, 188, 52, 140, 26, 203, 109, 246, 182, 204, 106, 2, 236, 218, 51, 44, 13, 202, 211, 118, 134, 53, 133, 153, 52, 168, 66, 113, 22, 101, 245, 108, 170, 110, 16, 228, 32, 100, 40, 173, 14, 10, 35, 23, 185, 172, 168, 41, 222, 30, 75, 12, 105, 179, 34, 244, 26, 144, 102, 200, 181, 190, 232, 22, 152, 168, 55, 232, 57, 76, 55, 244, 51, 221, 33, 191, 224, 79, 213, 53, 28, 7, 241, 171, 118, 111, 176, 71, 151, 124, 247, 39, 206, 24, 179, 126, 165, 25, 102, 40, 157, 238, 228, 144, 164, 69, 245, 17, 1, 193, 119, 104, 128, 190, 173, 217, 38, 205, 97, 72, 243, 205, 223, 243, 78, 244, 223, 39, 39, 105, 102, 217, 50, 109, 146, 80, 175, 6, 195, 187, 174, 107, 209, 224, 152, 121, 129, 93, 189, 81, 35, 123, 226, 137, 159, 111, 19, 113, 170, 98, 206, 106, 194, 116, 53, 24, 52, 49, 210, 128, 53, 29, 37, 88, 140, 245, 181, 33, 182, 20, 253, 79, 82, 228, 7, 217, 193, 188, 58, 56, 254, 137, 77, 160, 147, 82, 215, 150, 53, 127, 210, 209, 1, 180, 41, 253, 154, 84, 80, 198, 195, 79, 64, 33, 98, 117, 113, 154, 233, 114, 252, 151, 204, 17, 76, 172, 24, 81, 49, 104, 199, 152, 174, 172, 211, 42, 205, 246, 140, 44, 166, 33, 104, 92, 18, 193, 164, 42, 159, 139, 217, 233, 53, 239, 73, 31, 57, 238, 132, 44, 148, 76, 235, 184, 119, 223, 98, 240, 106, 68, 93, 115, 143, 173, 141, 76, 195, 251, 229, 238, 188, 82, 217, 159, 61, 60, 220, 45, 218, 4, 254, 65, 150, 22, 197, 187, 40, 112, 41, 178, 251, 226, 50, 107, 179, 157, 106, 134, 36, 100, 173, 38, 210, 197, 222, 197, 96, 245, 13, 116, 123, 179, 213, 29, 228, 44, 185, 240, 92, 157, 35, 110, 203, 17, 200, 109, 160, 97, 179, 18, 230, 183, 138, 89, 66, 84, 38, 193, 97, 148, 194, 226, 165, 198, 102, 37, 28, 192, 188, 91, 137, 188, 239, 183, 69, 1, 34, 30, 226, 120, 121, 148, 222, 174, 237, 90, 104, 136, 168, 173, 89, 200, 249, 148, 138, 202, 41, 110, 184, 140, 166, 167, 63, 83, 100, 161, 21, 158, 34, 163, 0, 230, 88, 242, 149, 99, 138, 15, 174, 40, 47, 195, 186, 167, 156, 4, 127, 198, 175, 75, 97, 196, 230, 110, 3, 88, 34, 81, 18, 19, 155, 18, 205, 122, 172, 79, 124, 118, 110, 107, 159, 237, 86, 126, 235, 12, 246, 172, 224, 98, 220, 59, 179, 241, 217, 98, 131, 29, 250, 115, 7, 55, 217, 149, 63, 202, 231, 65, 186, 131, 59, 237, 48, 10, 245, 60, 247, 159, 176, 227, 174, 251, 121, 87, 119, 221, 235, 184, 242, 118, 109, 189, 107, 82, 99, 174, 251, 202, 148, 225, 28, 254, 249, 119, 83, 135, 107, 254, 12, 165, 54, 162, 76, 199, 137, 35, 160, 61, 191, 20, 141, 248, 69, 34, 252, 84, 112, 153, 207, 139, 49, 35, 246, 121, 60, 59, 206, 232, 202, 186, 54, 193, 239, 158, 107, 2, 224, 120, 224, 189, 32, 47, 62, 212, 137, 141, 247, 8, 231, 193, 206, 159, 188, 160, 13, 224, 9, 124, 188, 23, 182, 218, 252, 207, 139, 34, 206, 104, 226, 254, 161, 236, 45, 189, 135, 67, 182, 31, 153, 59, 108, 200, 124, 108, 62, 59, 167, 7, 223, 72, 82, 48, 216, 74, 157, 204, 75, 116, 155, 11, 152, 122, 156, 202, 158, 227, 81, 250, 38, 39, 115, 62, 138, 214, 93, 181, 237, 115, 247, 51, 94, 141, 217, 180, 33, 165, 195, 52, 250, 203, 208, 213, 16, 2, 103, 74, 36, 14, 94, 145, 194, 58, 156, 71, 135, 95, 222, 141, 44, 47, 15, 150, 160, 200, 249, 35, 249, 24, 217, 196, 98, 61, 114, 24, 90, 93, 216, 12, 255, 136, 101, 41, 33, 227, 239, 68, 106, 252, 55, 152, 203, 178, 216, 97, 26, 48, 17, 37, 252, 29, 93, 174, 198, 86, 244, 150, 173, 64, 235, 192, 233, 249, 186, 195, 30, 123, 131, 104, 207, 56, 185, 197, 191, 54, 78, 64, 241, 79, 55, 33, 182, 208, 37, 175, 157, 189, 53, 176, 62, 234, 39, 229, 186, 83, 85, 168, 99, 184, 121, 96, 130, 99, 242, 58, 30, 159, 45, 125, 80, 58, 18, 80, 180, 139, 47, 41, 146, 204, 110, 150, 180, 89, 202, 211, 9, 96, 108, 117, 3, 154, 229, 119, 90, 146, 203, 74, 46, 2, 62, 200, 125, 153, 119, 253, 77, 206, 227, 127, 149, 118, 165, 98, 104, 28, 103, 130, 147, 68, 109, 116, 61, 151, 219, 115, 36, 102, 254, 3, 46, 18, 104, 59, 174, 33, 38, 161, 104, 29, 241, 139, 27, 208, 33, 37, 94, 147, 229, 71, 175, 43, 146, 43, 85, 26, 123, 188, 166, 171, 60, 34, 102, 162, 195, 180, 86, 220, 135, 162, 173, 143, 254, 74, 237, 114, 191, 214, 139, 244, 76, 100, 191, 165, 154, 198, 90, 213, 41, 39, 134, 174, 130, 121, 100, 49, 82, 119, 246, 209, 235, 182, 137, 175, 190, 142, 206, 157, 169, 76, 105, 92, 79, 97, 124, 240, 192, 80, 215, 239, 13, 229, 214, 194, 193, 113, 31, 89, 217, 130, 176, 238, 117, 173, 55, 101, 29, 100, 201, 197, 178, 71, 71, 128, 20, 196, 193, 70, 237, 153, 237, 37, 22, 5, 9, 113, 208, 4, 213, 49, 153, 188, 83, 177, 38, 167, 188, 73, 161, 64, 181, 10, 100, 20, 103, 245, 206, 185, 131, 196, 58, 74, 142, 238, 115, 244, 114, 15, 175, 51, 224, 217, 205, 205, 85, 196, 198, 127, 147, 218, 166, 130, 109, 40, 60, 176, 134, 229, 82, 38, 119, 97, 237, 169, 186, 36, 169, 153, 214, 140, 71, 111, 53, 138, 106, 19, 51, 144, 19, 42, 19, 57, 210, 66, 142, 254, 151, 166, 11, 88, 157, 210, 126, 88, 25, 56, 236, 94, 64, 106, 109, 40, 210, 115, 172, 27, 120, 187, 217, 144, 78, 234, 103, 110, 141, 253, 28, 87, 241, 107, 121, 96, 92, 103, 92, 73, 215, 215, 197, 150, 195, 166, 73, 27, 136, 88, 73, 20, 163, 172, 132, 204, 141, 142, 188, 228, 214, 108, 195, 76, 95, 141, 78, 227, 130, 88, 57, 93, 239, 67, 8, 212, 111, 211, 184, 45, 190, 35, 6, 17, 222, 5, 14, 132, 154, 12, 9, 70, 123, 48, 214, 8, 230, 7, 232, 120, 54, 212, 119, 170, 60, 160, 4, 223, 228, 163, 188, 168, 146, 73, 159, 223, 79, 83, 36, 199, 153, 57, 228, 175, 95, 181, 91, 175, 24, 8, 237, 215, 44, 176, 219, 108, 170, 209, 53, 239, 167, 241, 122, 184, 1, 21, 214, 8, 118, 12, 27, 149, 1, 159, 202, 33, 133, 227, 180, 158, 154, 80, 44, 39, 109, 142, 105, 254, 93, 153, 67, 52, 203, 46, 166, 140, 37, 110, 52, 178, 225, 95, 76, 140, 95, 198, 179, 230, 235, 124, 216, 84, 137, 200, 201, 109, 13, 121, 157, 15, 251, 2, 73, 137, 240, 180, 22, 47, 239, 58, 31, 166, 230, 207, 219, 221, 230, 227, 42, 59, 168, 27, 230, 167, 135, 223, 49, 225, 148, 253, 167, 58, 207, 167, 101, 229, 189, 64, 172, 179, 3, 141, 23, 191, 85, 66, 255, 24, 170, 251, 40, 45, 242, 142, 254, 83, 111, 75, 250, 255, 46, 4, 227, 16 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 20960; + return 19520; } uint32_t GetRawScriptsSize() { - return 144873; + return 134068; } } // selfhosted } // js diff --git a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/js-confdefs.h b/src/third_party/mozjs/platform/s390x/linux/build/js-confdefs.h index ae0a63cc85c..0cb7a271056 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/s390x/linux/build/js-confdefs.h @@ -9,9 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -26,7 +31,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -68,12 +72,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -82,6 +84,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "s390x-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define WORDS_BIGENDIAN 1 diff --git a/src/third_party/mozjs/platform/s390x/linux/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/s390x/linux/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/s390x/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/s390x/linux/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/s390x/linux/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/s390x/linux/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/s390x/linux/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/s390x/linux/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/s390x/linux/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/s390x/linux/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/s390x/linux/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/s390x/linux/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/s390x/linux/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/s390x/linux/include/js-confdefs.h b/src/third_party/mozjs/platform/s390x/linux/include/js-confdefs.h index ae0a63cc85c..0cb7a271056 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/js-confdefs.h @@ -9,9 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -26,7 +31,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -68,12 +72,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -82,6 +84,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "s390x-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define WORDS_BIGENDIAN 1 diff --git a/src/third_party/mozjs/platform/s390x/linux/include/js-config.h b/src/third_party/mozjs/platform/s390x/linux/include/js-config.h index e6a4e862c32..75330b2452d 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/js-config.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +/* #undef XP_WIN */ +#define XP_UNIX 1 +/* #undef XP_DARWIN */ + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/s390x/linux/include/selfhosted.out.h b/src/third_party/mozjs/platform/s390x/linux/include/selfhosted.out.h index 52835a71bc5..95dbb85959b 100644 --- a/src/third_party/mozjs/platform/s390x/linux/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/s390x/linux/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 75, 43, 205, 75, 46, 201, 204, 207, 83, 200, 75, 45, 143, 15, 74, 77, 206, 47, 74, 209, 208, 84, 168, 230, 82, 80, 40, 74, 45, 41, 45, 202, 83, 40, 46, 73, 137, 247, 79, 202, 74, 77, 46, 137, 79, 46, 74, 77, 44, 73, 213, 200, 43, 205, 201, 209, 180, 230, 170, 229, 130, 235, 13, 201, 119, 202, 207, 207, 73, 77, 204, 211, 40, 67, 209, 171, 168, 88, 134, 166, 206, 175, 52, 55, 41, 181, 8, 77, 153, 54, 170, 170, 224, 196, 220, 212, 176, 196, 156, 210, 212, 168, 212, 162, 124, 141, 10, 29, 133, 74, 20, 213, 21, 10, 182, 182, 182, 10, 149, 10, 53, 53, 10, 26, 21, 10, 138, 64, 118, 133, 130, 154, 26, 80, 64, 17, 36, 140, 234, 48, 247, 212, 18, 223, 212, 146, 140, 252, 20, 141, 48, 29, 133, 0, 136, 49, 214, 214, 64, 162, 44, 177, 72, 1, 164, 74, 193, 86, 33, 44, 58, 32, 22, 36, 148, 153, 166, 160, 225, 89, 236, 7, 244, 156, 127, 81, 104, 94, 74, 106, 90, 102, 94, 106, 138, 6, 72, 145, 38, 68, 35, 220, 5, 165, 48, 89, 144, 182, 90, 168, 86, 69, 207, 98, 231, 196, 156, 156, 196, 164, 156, 84, 84, 77, 33, 25, 69, 249, 229, 33, 149, 5, 169, 174, 69, 69, 249, 69, 26, 134, 70, 58, 10, 37, 64, 94, 126, 26, 216, 1, 154, 80, 51, 96, 102, 131, 196, 80, 188, 224, 89, 28, 80, 148, 95, 144, 90, 84, 82, 233, 157, 90, 169, 145, 88, 148, 94, 154, 155, 154, 87, 2, 52, 28, 226, 11, 176, 89, 64, 95, 64, 141, 132, 201, 91, 195, 77, 132, 42, 0, 134, 141, 82, 113, 73, 81, 102, 94, 186, 18, 40, 228, 144, 4, 43, 115, 147, 242, 115, 148, 80, 99, 160, 32, 53, 57, 51, 181, 216, 57, 63, 15, 168, 165, 52, 185, 4, 232, 236, 252, 164, 44, 29, 5, 160, 183, 19, 75, 115, 74, 144, 196, 209, 130, 20, 36, 4, 116, 12, 80, 177, 94, 50, 66, 17, 44, 116, 65, 108, 144, 165, 136, 0, 68, 13, 88, 44, 230, 91, 163, 134, 48, 36, 33, 130, 13, 194, 21, 190, 166, 102, 58, 10, 74, 249, 73, 32, 117, 234, 197, 10, 234, 72, 206, 80, 87, 40, 128, 134, 164, 18, 60, 212, 65, 142, 46, 6, 186, 24, 228, 240, 104, 247, 212, 18, 167, 210, 204, 156, 146, 204, 188, 96, 112, 160, 104, 40, 21, 67, 2, 66, 73, 19, 103, 10, 73, 209, 40, 70, 73, 30, 232, 190, 192, 240, 133, 39, 74, 176, 194, 53, 131, 229, 138, 21, 20, 129, 161, 3, 15, 87, 48, 8, 74, 45, 200, 47, 42, 9, 45, 78, 76, 79, 117, 206, 47, 205, 43, 73, 45, 210, 192, 180, 64, 71, 193, 88, 211, 26, 172, 161, 22, 217, 37, 197, 48, 139, 209, 194, 8, 172, 198, 208, 68, 7, 76, 43, 57, 56, 64, 189, 9, 15, 31, 133, 252, 52, 5, 120, 16, 34, 133, 160, 18, 80, 3, 90, 6, 75, 45, 65, 24, 171, 167, 167, 151, 88, 148, 94, 12, 113, 123, 73, 81, 37, 212, 15, 201, 137, 57, 57, 110, 80, 13, 26, 197, 37, 41, 241, 48, 78, 124, 98, 65, 65, 78, 165, 14, 154, 235, 116, 16, 249, 75, 71, 1, 100, 30, 36, 178, 128, 198, 148, 36, 103, 40, 104, 164, 162, 133, 118, 42, 204, 143, 214, 232, 14, 115, 76, 79, 47, 74, 77, 79, 44, 161, 134, 235, 224, 102, 81, 215, 137, 158, 160, 248, 204, 75, 204, 161, 130, 11, 81, 140, 162, 142, 3, 253, 74, 145, 44, 6, 106, 65, 146, 114, 206, 47, 168, 116, 73, 44, 73, 132, 150, 77, 192, 196, 163, 81, 2, 180, 39, 181, 68, 71, 161, 56, 191, 180, 40, 57, 85, 71, 33, 181, 34, 57, 167, 52, 37, 53, 197, 179, 36, 53, 183, 88, 19, 86, 78, 64, 137, 76, 88, 86, 66, 205, 74, 96, 173, 40, 249, 169, 40, 15, 226, 54, 72, 86, 77, 43, 202, 207, 85, 176, 85, 8, 201, 135, 22, 4, 16, 13, 32, 207, 129, 165, 179, 83, 43, 139, 21, 108, 177, 56, 206, 191, 8, 24, 216, 254, 229, 121, 222, 64, 5, 48, 135, 130, 13, 67, 119, 166, 53, 212, 109, 32, 147, 192, 69, 85, 30, 208, 137, 216, 221, 147, 150, 95, 164, 160, 1, 178, 53, 19, 232, 254, 10, 160, 181, 6, 214, 80, 166, 13, 216, 33, 122, 57, 169, 121, 233, 37, 25, 80, 65, 109, 109, 136, 41, 112, 135, 42, 216, 130, 85, 69, 131, 101, 193, 21, 16, 216, 102, 96, 222, 4, 3, 197, 140, 196, 98, 160, 131, 53, 128, 106, 48, 130, 82, 77, 13, 168, 8, 154, 50, 80, 83, 6, 36, 88, 226, 97, 249, 216, 179, 216, 53, 175, 52, 55, 181, 40, 49, 41, 39, 21, 234, 95, 144, 165, 154, 96, 237, 16, 247, 128, 128, 11, 56, 248, 145, 66, 172, 18, 30, 70, 64, 213, 16, 141, 209, 64, 86, 44, 82, 25, 83, 11, 77, 40, 176, 212, 128, 22, 224, 161, 121, 105, 153, 57, 37, 169, 69, 169, 41, 104, 233, 2, 150, 16, 96, 197, 41, 122, 113, 138, 158, 6, 96, 97, 14, 75, 3, 180, 72, 3, 224, 72, 30, 4, 81, 79, 102, 116, 130, 195, 138, 74, 49, 153, 95, 10, 140, 52, 228, 6, 96, 158, 2, 92, 46, 51, 47, 15, 46, 7, 11, 17, 5, 165, 180, 252, 124, 37, 112, 184, 88, 35, 155, 227, 88, 84, 148, 88, 233, 90, 150, 90, 84, 9, 246, 85, 82, 98, 114, 118, 90, 30, 40, 201, 65, 99, 201, 31, 57, 6, 75, 50, 50, 139, 225, 241, 7, 12, 58, 176, 156, 15, 56, 8, 53, 252, 161, 97, 9, 143, 30, 71, 72, 11, 167, 164, 24, 170, 64, 19, 28, 87, 6, 48, 103, 161, 214, 37, 26, 166, 166, 58, 10, 6, 58, 10, 74, 96, 247, 232, 1, 3, 178, 36, 191, 4, 40, 169, 151, 10, 116, 26, 184, 25, 0, 116, 56, 196, 96, 148, 6, 28, 194, 205, 176, 192, 69, 55, 24, 212, 140, 115, 73, 77, 206, 207, 45, 200, 204, 73, 5, 186, 73, 195, 64, 7, 92, 80, 195, 116, 193, 76, 6, 121, 41, 4, 232, 33, 76, 103, 219, 41, 24, 42, 216, 131, 234, 41, 152, 148, 134, 161, 166, 130, 21, 172, 224, 78, 77, 177, 6, 39, 52, 104, 25, 147, 13, 78, 100, 64, 202, 6, 20, 64, 64, 6, 44, 81, 65, 211, 172, 66, 102, 158, 130, 63, 68, 4, 38, 166, 8, 114, 142, 115, 126, 94, 9, 208, 104, 120, 170, 66, 120, 76, 71, 33, 68, 71, 193, 63, 58, 59, 86, 71, 33, 27, 200, 128, 251, 19, 41, 110, 211, 18, 115, 138, 83, 173, 161, 162, 181, 144, 4, 3, 245, 22, 84, 69, 73, 81, 105, 42, 40, 222, 131, 83, 75, 60, 139, 61, 243, 114, 50, 243, 64, 193, 231, 147, 88, 148, 158, 10, 183, 18, 146, 20, 64, 225, 13, 12, 20, 212, 4, 18, 156, 159, 11, 11, 235, 65, 150, 62, 138, 129, 46, 27, 222, 201, 131, 194, 212, 1, 139, 123, 92, 137, 3, 150, 124, 96, 169, 3, 87, 234, 128, 165, 131, 84, 180, 196, 145, 88, 233, 150, 95, 228, 154, 152, 156, 49, 56, 211, 71, 26, 196, 113, 195, 55, 137, 144, 86, 120, 88, 115, 97, 198, 63, 178, 59, 106, 185, 8, 149, 16, 176, 232, 70, 79, 6, 149, 190, 137, 5, 72, 22, 43, 144, 90, 68, 208, 170, 10, 73, 213, 203, 77, 44, 24, 252, 209, 15, 10, 14, 71, 144, 110, 144, 227, 131, 11, 82, 147, 65, 221, 122, 200, 48, 142, 191, 14, 40, 160, 52, 201, 77, 36, 176, 246, 12, 48, 24, 10, 82, 83, 194, 18, 115, 74, 83, 129, 154, 147, 97, 201, 6, 45, 217, 36, 225, 74, 54, 10, 56, 26, 160, 142, 32, 37, 200, 134, 99, 79, 99, 142, 132, 106, 31, 88, 26, 66, 175, 123, 42, 221, 192, 237, 83, 13, 90, 39, 45, 178, 146, 86, 26, 216, 109, 67, 58, 117, 1, 83, 151, 1, 150, 180, 165, 163, 80, 146, 79, 122, 26, 203, 14, 75, 132, 36, 47, 255, 232, 236, 88, 107, 176, 4, 88, 49, 48, 32, 96, 201, 13, 87, 114, 131, 234, 5, 210, 58, 10, 254, 192, 208, 130, 25, 139, 146, 232, 138, 242, 11, 96, 137, 174, 36, 95, 91, 27, 164, 9, 158, 228, 160, 137, 14, 74, 214, 2, 49, 56, 233, 229, 41, 56, 130, 147, 30, 172, 88, 203, 75, 76, 2, 39, 189, 244, 84, 184, 67, 192, 161, 2, 73, 102, 154, 214, 176, 212, 7, 77, 125, 65, 169, 41, 165, 201, 200, 17, 57, 88, 82, 31, 48, 245, 21, 129, 221, 70, 167, 212, 7, 73, 22, 48, 15, 38, 38, 39, 151, 230, 150, 230, 36, 2, 199, 204, 112, 248, 9, 146, 50, 97, 246, 34, 212, 3, 7, 22, 193, 137, 21, 158, 88, 33, 150, 40, 164, 230, 20, 167, 130, 20, 67, 19, 12, 48, 192, 80, 195, 68, 65, 161, 4, 228, 118, 140, 176, 49, 66, 42, 111, 160, 14, 13, 40, 74, 45, 78, 205, 43, 81, 176, 69, 110, 24, 167, 228, 67, 12, 130, 154, 159, 141, 150, 122, 21, 144, 180, 161, 180, 152, 20, 20, 146, 138, 82, 19, 179, 209, 82, 152, 66, 121, 6, 48, 196, 20, 52, 180, 181, 161, 217, 67, 211, 26, 238, 116, 69, 176, 73, 176, 177, 95, 98, 157, 142, 22, 68, 254, 209, 217, 218, 218, 177, 64, 121, 68, 63, 22, 82, 220, 163, 21, 247, 10, 232, 158, 65, 55, 10, 189, 168, 7, 167, 109, 13, 184, 231, 146, 17, 153, 16, 38, 6, 47, 58, 82, 64, 66, 24, 38, 194, 5, 33, 21, 4, 34, 252, 144, 36, 160, 44, 36, 255, 213, 194, 243, 35, 212, 44, 104, 218, 169, 133, 149, 246, 40, 249, 45, 40, 51, 61, 163, 4, 82, 64, 192, 50, 221, 72, 205, 116, 182, 96, 127, 233, 42, 24, 210, 56, 235, 129, 20, 131, 76, 131, 101, 61, 90, 103, 61, 152, 225, 176, 172, 71, 106, 214, 211, 208, 213, 205, 86, 176, 3, 186, 18, 234, 8, 244, 156, 71, 172, 203, 49, 66, 200, 63, 58, 91, 87, 23, 51, 231, 217, 65, 42, 67, 93, 93, 168, 217, 24, 94, 65, 51, 9, 71, 27, 139, 11, 230, 53, 66, 25, 79, 129, 196, 140, 167, 0, 205, 120, 10, 208, 140, 7, 243, 30, 172, 34, 44, 130, 102, 188, 82, 180, 140, 7, 171, 232, 220, 50, 243, 82, 52, 10, 138, 82, 83, 50, 147, 19, 75, 82, 21, 52, 21, 160, 25, 78, 1, 154, 225, 146, 160, 25, 46, 19, 154, 225, 18, 161, 25, 78, 1, 154, 225, 50, 160, 25, 174, 4, 154, 225, 208, 147, 101, 9, 52, 195, 193, 146, 21, 44, 91, 192, 35, 5, 154, 225, 148, 160, 25, 14, 222, 124, 7, 6, 72, 10, 176, 253, 14, 203, 110, 104, 217, 13, 238, 98, 92, 185, 13, 61, 183, 129, 114, 27, 146, 38, 120, 102, 131, 117, 222, 208, 221, 12, 204, 74, 134, 10, 246, 10, 238, 232, 237, 43, 88, 92, 161, 15, 255, 224, 106, 151, 227, 106, 31, 225, 106, 29, 193, 221, 136, 163, 113, 4, 235, 225, 3, 35, 22, 34, 11, 205, 108, 104, 113, 94, 74, 168, 111, 7, 179, 15, 150, 8, 82, 208, 154, 64, 16, 65, 207, 188, 148, 212, 138, 17, 157, 60, 104, 157, 60, 136, 75, 7, 254, 209, 217, 177, 216, 83, 1, 48, 21, 96, 205, 244, 186, 134, 196, 197, 60, 44, 146, 49, 162, 223, 57, 191, 160, 50, 60, 19, 24, 179, 121, 240, 33, 234, 98, 32, 3, 72, 165, 230, 165, 40, 216, 34, 124, 10, 113, 16, 185, 105, 2, 44, 15, 116, 116, 78, 98, 73, 102, 89, 106, 8, 216, 38, 176, 82, 79, 96, 120, 164, 167, 22, 65, 45, 135, 171, 44, 201, 87, 176, 5, 249, 23, 93, 139, 141, 130, 1, 52, 88, 236, 129, 238, 76, 137, 247, 77, 44, 201, 136, 207, 77, 172, 0, 87, 107, 218, 104, 170, 117, 20, 12, 52, 161, 170, 173, 144, 84, 3, 189, 138, 174, 14, 232, 112, 12, 71, 6, 131, 130, 1, 197, 141, 160, 128, 65, 56, 49, 173, 40, 63, 23, 238, 72, 132, 22, 226, 220, 8, 83, 76, 200, 137, 48, 101, 88, 93, 232, 10, 138, 33, 72, 60, 217, 34, 197, 20, 208, 90, 80, 68, 88, 33, 185, 28, 168, 6, 225, 238, 204, 188, 196, 28, 52, 135, 3, 77, 34, 206, 217, 96, 165, 132, 29, 13, 84, 132, 234, 228, 228, 252, 82, 112, 3, 0, 69, 53, 196, 37, 186, 144, 41, 20, 72, 67, 8, 24, 241, 240, 18, 4, 28, 192, 54, 64, 17, 5, 53, 53, 16, 105, 3, 9, 114, 109, 136, 97, 208, 12, 2, 141, 6, 20, 41, 88, 123, 74, 1, 164, 203, 22, 68, 104, 163, 75, 64, 91, 25, 16, 81, 59, 68, 177, 132, 176, 25, 82, 247, 195, 132, 193, 213, 114, 73, 126, 44, 184, 112, 7, 73, 67, 203, 119, 88, 3, 11, 73, 93, 74, 106, 78, 106, 73, 42, 68, 57, 92, 17, 148, 6, 57, 86, 87, 23, 38, 90, 146, 15, 103, 67, 220, 167, 171, 11, 203, 228, 104, 230, 14, 160, 115, 181, 181, 17, 206, 69, 176, 209, 157, 11, 43, 147, 64, 101, 146, 63, 150, 230, 71, 102, 78, 142, 70, 25, 164, 146, 3, 231, 34, 160, 195, 12, 104, 81, 196, 192, 242, 6, 44, 247, 226, 204, 189, 217, 35, 59, 235, 18, 153, 117, 211, 96, 237, 99, 27, 136, 221, 214, 200, 117, 154, 127, 116, 118, 44, 208, 19, 224, 104, 181, 70, 173, 150, 80, 147, 128, 115, 81, 106, 98, 73, 42, 56, 33, 120, 150, 164, 22, 37, 194, 23, 50, 101, 103, 230, 33, 69, 122, 38, 88, 46, 53, 5, 28, 237, 144, 184, 243, 7, 51, 65, 138, 161, 97, 0, 83, 5, 110, 203, 251, 165, 150, 163, 26, 10, 86, 20, 154, 87, 156, 152, 150, 26, 156, 90, 18, 148, 90, 156, 90, 84, 150, 154, 18, 156, 147, 95, 162, 1, 211, 6, 12, 0, 29, 84, 155, 192, 105, 130, 160, 46, 67, 200, 64, 26, 97, 133, 70, 80, 111, 89, 195, 67, 3, 108, 29, 246, 102, 57, 204, 229, 126, 169, 21, 37, 26, 136, 144, 0, 250, 23, 232, 189, 146, 140, 76, 224, 202, 33, 72, 163, 24, 182, 232, 10, 18, 22, 224, 69, 119, 16, 69, 238, 165, 137, 69, 41, 33, 249, 24, 129, 171, 169, 9, 158, 60, 71, 95, 55, 1, 116, 13, 242, 244, 54, 172, 195, 226, 12, 20, 67, 49, 2, 178, 92, 207, 51, 45, 188, 40, 177, 160, 32, 53, 69, 7, 170, 14, 228, 36, 40, 27, 210, 86, 67, 241, 129, 18, 88, 6, 236, 243, 90, 168, 79, 18, 21, 108, 161, 33, 230, 142, 26, 98, 144, 149, 108, 6, 176, 104, 5, 58, 174, 184, 52, 7, 20, 233, 213, 64, 110, 78, 105, 42, 180, 141, 5, 89, 58, 147, 146, 159, 151, 106, 5, 25, 238, 81, 168, 133, 5, 73, 34, 22, 15, 130, 204, 208, 3, 169, 134, 245, 53, 145, 60, 14, 149, 70, 118, 29, 48, 158, 82, 43, 240, 187, 208, 16, 226, 66, 72, 194, 203, 245, 6, 234, 64, 86, 15, 92, 56, 100, 108, 228, 86, 148, 159, 139, 169, 209, 8, 172, 17, 218, 145, 130, 185, 217, 179, 56, 32, 191, 184, 56, 51, 41, 167, 18, 26, 176, 33, 149, 64, 2, 28, 144, 26, 137, 154, 80, 127, 64, 203, 56, 156, 42, 161, 69, 95, 34, 200, 2, 244, 78, 61, 204, 8, 136, 48, 78, 35, 60, 18, 139, 93, 82, 75, 18, 147, 51, 82, 83, 156, 74, 211, 210, 82, 139, 144, 108, 199, 214, 121, 51, 183, 128, 90, 6, 12, 59, 48, 141, 94, 67, 193, 202, 101, 88, 185, 156, 8, 45, 151, 97, 137, 1, 236, 28, 72, 112, 219, 129, 199, 60, 160, 182, 225, 200, 78, 144, 196, 129, 180, 34, 132, 196, 200, 197, 99, 170, 161, 14, 52, 218, 181, 65, 113, 11, 115, 25, 44, 110, 65, 129, 104, 136, 148, 158, 64, 86, 150, 65, 123, 117, 137, 192, 149, 34, 176, 69, 66, 56, 236, 205, 68, 55, 203, 8, 106, 22, 56, 33, 20, 36, 102, 22, 1, 205, 129, 24, 163, 3, 55, 15, 100, 32, 134, 109, 32, 197, 192, 17, 32, 156, 54, 89, 91, 115, 161, 107, 129, 248, 11, 34, 142, 164, 3, 220, 65, 72, 37, 208, 65, 64, 206, 198, 200, 125, 4, 21, 176, 108, 24, 200, 130, 98, 13, 160, 95, 96, 134, 99, 47, 212, 75, 50, 50, 139, 33, 89, 6, 108, 165, 115, 98, 94, 126, 94, 102, 114, 98, 142, 95, 98, 110, 170, 6, 178, 81, 58, 10, 74, 101, 96, 134, 18, 212, 50, 88, 145, 152, 88, 233, 154, 87, 82, 148, 73, 180, 101, 192, 0, 70, 41, 85, 193, 74, 188, 83, 43, 137, 214, 111, 128, 69, 191, 91, 81, 126, 174, 99, 113, 101, 94, 178, 70, 34, 136, 4, 47, 247, 2, 79, 130, 165, 229, 193, 122, 68, 153, 121, 169, 41, 58, 10, 32, 35, 28, 139, 210, 177, 180, 97, 128, 177, 237, 140, 84, 132, 131, 248, 105, 48, 83, 157, 115, 242, 139, 75, 139, 192, 41, 10, 100, 188, 2, 208, 169, 182, 118, 208, 100, 2, 155, 202, 203, 204, 3, 154, 10, 181, 82, 17, 169, 113, 159, 130, 200, 243, 48, 101, 106, 106, 10, 136, 62, 113, 42, 72, 24, 105, 112, 18, 235, 240, 100, 72, 126, 48, 104, 177, 22, 88, 45, 108, 72, 18, 146, 126, 33, 14, 40, 45, 6, 154, 235, 8, 246, 58, 52, 176, 20, 160, 110, 5, 7, 5, 104, 129, 174, 19, 234, 2, 93, 152, 36, 88, 49, 104, 153, 46, 220, 149, 216, 204, 2, 250, 7, 185, 216, 86, 192, 98, 33, 44, 72, 97, 94, 198, 112, 94, 48, 94, 197, 153, 216, 109, 70, 132, 36, 44, 166, 96, 69, 37, 108, 88, 1, 20, 132, 88, 116, 194, 195, 19, 75, 136, 154, 27, 34, 133, 40, 34, 148, 32, 193, 10, 115, 57, 90, 105, 169, 128, 238, 9, 194, 65, 12, 105, 68, 192, 66, 23, 238, 110, 52, 115, 48, 130, 23, 135, 109, 232, 65, 6, 115, 39, 46, 99, 113, 133, 29, 174, 208, 131, 105, 69, 15, 60, 82, 131, 15, 230, 48, 24, 13, 35, 137, 138, 97, 133, 154, 26, 116, 159, 227, 242, 8, 98, 138, 30, 178, 48, 28, 182, 48, 220, 89, 83, 193, 30, 238, 14, 13, 204, 69, 224, 26, 206, 58, 10, 26, 26, 134, 10, 54, 54, 10, 134, 102, 154, 10, 53, 10, 70, 154, 154, 58, 136, 181, 218, 206, 104, 195, 61, 64, 213, 206, 192, 224, 176, 82, 136, 134, 71, 34, 124, 224, 8, 34, 0, 25, 78, 74, 44, 79, 204, 44, 129, 140, 57, 230, 165, 86, 148, 128, 135, 7, 21, 242, 211, 20, 18, 115, 114, 242, 203, 161, 134, 130, 60, 20, 158, 89, 146, 161, 1, 115, 31, 82, 250, 209, 129, 137, 193, 178, 22, 44, 0, 96, 3, 205, 216, 83, 5, 84, 6, 41, 194, 96, 37, 18, 210, 226, 2, 176, 139, 96, 67, 146, 80, 144, 137, 40, 143, 80, 35, 27, 85, 39, 98, 200, 28, 30, 36, 144, 50, 72, 7, 86, 148, 234, 32, 76, 215, 81, 200, 134, 103, 33, 12, 163, 160, 33, 4, 23, 131, 57, 6, 150, 64, 208, 231, 150, 97, 115, 203, 176, 5, 13, 48, 125, 72, 179, 203, 10, 160, 104, 0, 98, 109, 208, 24, 1, 170, 73, 142, 208, 214, 140, 130, 45, 108, 24, 14, 86, 179, 40, 56, 66, 248, 181, 92, 176, 176, 74, 4, 55, 209, 50, 179, 83, 193, 29, 24, 127, 72, 7, 6, 17, 51, 80, 235, 208, 71, 203, 128, 209, 8, 215, 136, 220, 116, 194, 149, 46, 65, 233, 146, 26, 233, 17, 152, 30, 193, 189, 61, 77, 77, 104, 127, 16, 92, 1, 106, 0, 69, 32, 214, 163, 39, 79, 232, 196, 104, 182, 130, 13, 164, 17, 7, 139, 107, 216, 240, 55, 34, 110, 16, 1, 17, 13, 28, 12, 135, 41, 67, 79, 76, 96, 94, 102, 94, 58, 60, 14, 236, 33, 186, 97, 73, 5, 95, 82, 1, 89, 8, 77, 39, 112, 237, 86, 80, 65, 152, 133, 216, 87, 23, 100, 235, 192, 92, 1, 91, 95, 128, 30, 255, 176, 56, 69, 142, 123, 72, 67, 30, 61, 238, 107, 193, 13, 46, 176, 0, 70, 21, 175, 161, 137, 189, 113, 161, 145, 137, 222, 164, 0, 54, 41, 72, 106, 82, 192, 130, 18, 20, 120, 32, 197, 56, 90, 10, 153, 132, 218, 9, 176, 24, 68, 43, 148, 65, 173, 4, 151, 212, 228, 252, 92, 216, 184, 185, 33, 212, 177, 160, 98, 25, 20, 50, 240, 41, 21, 152, 131, 161, 78, 130, 148, 41, 158, 37, 208, 178, 214, 86, 33, 147, 184, 234, 12, 218, 199, 245, 67, 93, 133, 174, 1, 55, 13, 81, 143, 96, 175, 113, 208, 85, 193, 106, 26, 244, 154, 6, 125, 50, 32, 19, 90, 215, 192, 34, 156, 214, 25, 14, 189, 2, 64, 207, 95, 192, 194, 159, 168, 98, 191, 36, 3, 154, 134, 80, 3, 28, 238, 121, 226, 178, 90, 114, 34, 174, 242, 88, 33, 4, 82, 18, 163, 231, 48, 224, 176, 17, 66, 28, 150, 111, 92, 82, 211, 208, 215, 141, 129, 50, 153, 182, 54, 102, 54, 131, 5, 50, 122, 137, 10, 207, 66, 142, 214, 92, 32, 53, 184, 202, 210, 228, 18, 136, 191, 97, 157, 107, 66, 133, 40, 76, 29, 182, 24, 5, 251, 137, 202, 197, 168, 38, 23, 36, 140, 96, 69, 41, 172, 40, 133, 197, 44, 174, 89, 162, 106, 104, 98, 128, 149, 162, 176, 156, 19, 157, 29, 11, 14, 30, 66, 209, 73, 40, 50, 97, 235, 175, 96, 49, 137, 94, 82, 18, 91, 78, 2, 163, 6, 91, 145, 8, 143, 60, 88, 113, 7, 47, 238, 66, 242, 131, 75, 138, 128, 206, 212, 128, 248, 17, 30, 171, 176, 24, 69, 27, 224, 133, 109, 7, 133, 40, 210, 203, 202, 207, 4, 155, 159, 137, 150, 227, 225, 59, 59, 97, 165, 49, 250, 184, 22, 210, 182, 141, 18, 168, 11, 116, 32, 102, 66, 124, 1, 119, 51, 214, 96, 3, 25, 15, 85, 14, 45, 193, 81, 189, 228, 147, 15, 212, 149, 10, 245, 88, 14, 152, 83, 172, 163, 144, 95, 0, 82, 131, 188, 199, 170, 44, 17, 230, 91, 88, 87, 16, 87, 162, 77, 172, 68, 78, 176, 153, 105, 232, 235, 52, 16, 222, 84, 82, 2, 169, 128, 229, 144, 180, 204, 162, 226, 18, 215, 156, 212, 92, 200, 250, 10, 112, 168, 69, 27, 196, 90, 67, 165, 131, 96, 166, 161, 23, 173, 41, 26, 200, 58, 225, 65, 25, 164, 96, 11, 177, 0, 54, 184, 131, 16, 134, 71, 36, 88, 68, 1, 123, 184, 33, 153, 169, 87, 130, 18, 76, 58, 40, 78, 213, 132, 141, 20, 34, 124, 82, 156, 90, 144, 8, 174, 17, 64, 78, 208, 1, 187, 33, 45, 191, 8, 145, 101, 12, 81, 178, 12, 108, 222, 93, 1, 90, 86, 162, 135, 1, 44, 223, 0, 157, 174, 109, 139, 48, 219, 26, 86, 127, 192, 42, 27, 228, 16, 65, 50, 6, 30, 32, 80, 3, 208, 61, 175, 128, 205, 251, 200, 6, 160, 251, 30, 230, 70, 152, 231, 225, 222, 135, 4, 0, 60, 61, 230, 41, 4, 161, 36, 56, 21, 248, 154, 78, 212, 49, 145, 162, 60, 72, 130, 130, 13, 180, 160, 15, 180, 192, 245, 232, 40, 40, 165, 167, 150, 40, 68, 67, 234, 93, 61, 232, 22, 211, 88, 37, 77, 107, 148, 84, 141, 190, 110, 52, 191, 40, 51, 61, 51, 47, 49, 7, 44, 165, 163, 144, 3, 78, 155, 64, 235, 97, 41, 219, 26, 154, 76, 53, 160, 37, 129, 173, 173, 173, 130, 46, 48, 169, 130, 67, 13, 170, 92, 1, 152, 120, 97, 49, 12, 13, 114, 176, 113, 168, 134, 163, 102, 227, 60, 104, 201, 9, 45, 57, 129, 70, 107, 66, 140, 64, 52, 128, 80, 116, 235, 37, 67, 75, 116, 104, 228, 130, 236, 65, 46, 230, 193, 21, 183, 154, 154, 2, 80, 172, 40, 191, 184, 56, 40, 53, 49, 39, 23, 172, 17, 85, 9, 177, 110, 200, 4, 27, 239, 159, 148, 5, 28, 137, 71, 210, 6, 114, 150, 51, 74, 35, 7, 182, 111, 25, 182, 111, 25, 150, 240, 20, 52, 156, 193, 97, 133, 80, 139, 236, 16, 37, 176, 165, 74, 112, 115, 21, 20, 112, 57, 8, 150, 116, 80, 77, 133, 119, 251, 137, 212, 91, 203, 5, 215, 13, 109, 57, 194, 26, 156, 68, 135, 134, 34, 106, 104, 195, 194, 4, 189, 241, 165, 97, 104, 162, 163, 160, 132, 20, 89, 104, 155, 192, 65, 198, 17, 209, 184, 50, 214, 4, 170, 134, 59, 12, 104, 28, 129, 250, 56, 189, 36, 3, 181, 0, 7, 251, 195, 45, 39, 177, 196, 55, 177, 64, 3, 92, 183, 21, 65, 117, 161, 174, 66, 196, 85, 59, 65, 118, 57, 250, 164, 194, 202, 111, 216, 36, 36, 204, 42, 244, 170, 42, 21, 205, 18, 156, 193, 131, 214, 224, 214, 48, 128, 84, 189, 8, 157, 16, 159, 195, 90, 222, 184, 86, 171, 16, 90, 173, 66, 104, 43, 2, 100, 66, 6, 20, 64, 192, 0, 245, 204, 43, 201, 135, 68, 188, 163, 142, 130, 191, 14, 194, 243, 58, 10, 64, 231, 129, 187, 4, 200, 46, 212, 81, 8, 129, 199, 14, 122, 99, 0, 17, 240, 26, 84, 9, 103, 136, 170, 148, 212, 130, 146, 12, 191, 210, 92, 160, 34, 67, 72, 216, 163, 175, 59, 2, 133, 138, 154, 154, 130, 59, 82, 144, 24, 104, 34, 245, 147, 96, 169, 93, 65, 1, 217, 48, 196, 164, 49, 170, 70, 68, 20, 80, 43, 16, 97, 150, 226, 12, 56, 76, 99, 128, 10, 75, 18, 193, 203, 86, 128, 44, 136, 105, 8, 22, 208, 92, 48, 7, 168, 2, 44, 15, 54, 31, 200, 64, 143, 42, 46, 5, 88, 199, 141, 11, 30, 29, 80, 99, 61, 33, 147, 98, 16, 51, 96, 45, 87, 13, 68, 164, 192, 228, 13, 172, 81, 4, 108, 16, 46, 64, 145, 208, 214, 6, 89, 0, 43, 167, 144, 117, 100, 230, 41, 20, 195, 54, 35, 67, 91, 177, 32, 87, 164, 194, 106, 114, 168, 108, 52, 146, 30, 224, 220, 11, 68, 33, 208, 44, 148, 156, 149, 159, 135, 48, 4, 84, 59, 193, 152, 8, 211, 32, 53, 54, 172, 198, 134, 232, 209, 224, 66, 27, 94, 130, 7, 16, 108, 144, 76, 65, 1, 30, 80, 200, 66, 80, 83, 117, 184, 96, 2, 176, 240, 7, 187, 18, 83, 24, 46, 160, 9, 115, 89, 45, 146, 143, 139, 51, 242, 75, 115, 82, 160, 17, 141, 186, 184, 22, 226, 83, 112, 44, 162, 172, 251, 80, 80, 192, 208, 229, 9, 116, 100, 81, 98, 165, 6, 212, 109, 168, 54, 193, 130, 31, 73, 15, 74, 136, 33, 5, 60, 56, 211, 193, 51, 29, 204, 56, 104, 214, 131, 155, 10, 77, 132, 176, 212, 130, 158, 218, 43, 161, 65, 139, 80, 137, 18, 88, 24, 225, 7, 23, 130, 38, 96, 116, 75, 208, 66, 21, 156, 87, 21, 116, 21, 12, 209, 3, 22, 214, 112, 133, 121, 13, 234, 111, 184, 49, 144, 249, 71, 131, 10, 195, 52, 100, 128, 8, 9, 244, 154, 11, 60, 249, 105, 136, 240, 53, 44, 52, 177, 15, 45, 65, 172, 209, 65, 113, 53, 196, 99, 176, 248, 64, 247, 148, 182, 54, 106, 52, 213, 114, 65, 48, 180, 40, 64, 82, 137, 82, 40, 56, 130, 130, 216, 177, 4, 50, 163, 10, 114, 61, 161, 242, 52, 135, 64, 73, 10, 91, 253, 1, 139, 78, 88, 9, 88, 4, 181, 2, 166, 46, 27, 90, 197, 193, 151, 139, 192, 194, 20, 154, 54, 161, 163, 104, 112, 227, 96, 51, 146, 176, 88, 129, 171, 64, 93, 153, 2, 87, 7, 107, 86, 100, 43, 216, 40, 24, 40, 212, 212, 40, 100, 163, 206, 23, 195, 2, 6, 94, 165, 65, 53, 193, 196, 65, 43, 111, 65, 33, 5, 155, 240, 204, 132, 78, 120, 2, 131, 17, 146, 233, 161, 19, 158, 192, 192, 3, 183, 128, 97, 225, 9, 233, 215, 5, 165, 150, 165, 22, 21, 167, 2, 143, 94, 162, 52, 72, 161, 245, 67, 49, 172, 233, 68, 234, 48, 0, 108, 89, 27, 120, 119, 0, 80, 17, 116, 135, 128, 2, 92, 14, 58, 10, 128, 186, 188, 203, 37, 21, 61, 73, 66, 123, 241, 112, 29, 154, 104, 225, 5, 171, 164, 81, 130, 33, 56, 191, 168, 4, 24, 8, 201, 249, 185, 5, 137, 69, 169, 105, 160, 176, 135, 70, 11, 92, 8, 54, 212, 8, 137, 4, 5, 53, 228, 177, 197, 84, 36, 157, 48, 47, 161, 229, 41, 115, 152, 59, 40, 12, 227, 204, 146, 212, 220, 98, 114, 194, 25, 87, 112, 65, 7, 213, 178, 33, 107, 113, 225, 174, 204, 132, 118, 200, 109, 108, 21, 12, 81, 82, 98, 30, 196, 9, 240, 80, 69, 140, 41, 192, 147, 27, 220, 109, 241, 197, 192, 112, 133, 14, 57, 234, 40, 32, 194, 8, 57, 10, 96, 107, 178, 243, 82, 124, 18, 139, 75, 16, 203, 131, 21, 32, 182, 146, 29, 90, 56, 154, 70, 182, 182, 208, 140, 139, 30, 71, 232, 43, 246, 209, 150, 100, 131, 28, 167, 132, 28, 58, 176, 241, 88, 244, 101, 217, 232, 70, 195, 90, 187, 232, 173, 93, 244, 101, 217, 176, 180, 1, 30, 238, 6, 170, 32, 183, 185, 139, 154, 14, 114, 82, 33, 123, 109, 128, 28, 59, 160, 199, 129, 180, 174, 46, 114, 166, 203, 14, 131, 231, 170, 108, 72, 150, 82, 64, 91, 184, 13, 139, 85, 132, 31, 117, 96, 78, 4, 143, 177, 161, 47, 227, 135, 37, 148, 162, 60, 168, 172, 53, 106, 49, 15, 43, 205, 96, 46, 134, 21, 93, 184, 138, 46, 164, 212, 129, 82, 128, 161, 72, 120, 2, 141, 171, 24, 212, 105, 7, 236, 66, 228, 4, 4, 235, 51, 193, 18, 16, 44, 1, 225, 48, 31, 103, 2, 74, 166, 114, 2, 130, 181, 126, 97, 9, 8, 87, 2, 34, 49, 165, 248, 163, 31, 233, 128, 156, 78, 64, 182, 2, 221, 143, 146, 68, 20, 116, 13, 137, 170, 214, 96, 105, 3, 28, 192, 72, 9, 68, 193, 177, 184, 50, 47, 25, 166, 214, 47, 181, 162, 4, 232, 167, 28, 77, 5, 216, 128, 14, 204, 154, 162, 212, 98, 96, 64, 184, 167, 230, 33, 47, 146, 1, 134, 99, 14, 48, 50, 243, 128, 186, 148, 208, 74, 43, 100, 83, 193, 113, 68, 186, 177, 224, 61, 92, 232, 230, 194, 38, 172, 65, 170, 61, 83, 128, 193, 153, 89, 82, 169, 1, 52, 23, 102, 36, 108, 248, 11, 93, 15, 220, 10, 234, 122, 17, 110, 44, 181, 253, 8, 87, 30, 4, 54, 68, 131, 100, 147, 33, 74, 32, 70, 39, 130, 76, 84, 192, 30, 136, 206, 57, 249, 197, 169, 26, 153, 37, 48, 219, 146, 243, 139, 82, 128, 102, 128, 22, 97, 129, 44, 132, 85, 167, 176, 121, 59, 24, 19, 170, 82, 15, 198, 133, 21, 23, 16, 107, 125, 83, 75, 50, 242, 83, 144, 84, 235, 21, 65, 15, 104, 130, 13, 178, 194, 6, 89, 97, 57, 74, 3, 89, 35, 60, 237, 3, 77, 132, 46, 0, 133, 205, 30, 163, 247, 214, 64, 30, 66, 209, 171, 3, 183, 83, 19, 100, 27, 220, 62, 104, 217, 6, 49, 13, 110, 129, 2, 122, 1, 98, 106, 134, 90, 128, 104, 24, 232, 64, 93, 160, 9, 54, 15, 61, 255, 41, 148, 65, 10, 111, 88, 252, 65, 207, 141, 131, 6, 174, 75, 102, 81, 106, 50, 116, 105, 110, 53, 216, 239, 48, 183, 192, 132, 113, 148, 99, 216, 156, 1, 86, 14, 43, 193, 96, 195, 219, 176, 144, 6, 159, 233, 8, 18, 128, 6, 49, 74, 189, 139, 80, 8, 15, 89, 66, 229, 166, 129, 14, 146, 241, 8, 107, 161, 158, 6, 155, 1, 15, 104, 43, 144, 229, 144, 94, 24, 66, 15, 132, 159, 146, 159, 151, 106, 165, 144, 150, 152, 83, 156, 170, 3, 62, 132, 10, 45, 160, 28, 97, 73, 17, 17, 90, 144, 53, 169, 69, 100, 6, 26, 80, 154, 150, 97, 132, 8, 19, 236, 65, 18, 13, 27, 191, 133, 45, 129, 211, 80, 74, 68, 246, 162, 146, 102, 172, 21, 56, 35, 150, 64, 51, 34, 66, 10, 98, 172, 6, 204, 114, 168, 193, 176, 242, 12, 156, 242, 16, 97, 172, 1, 203, 160, 168, 106, 147, 19, 209, 51, 71, 30, 146, 199, 192, 161, 3, 205, 219, 176, 196, 172, 195, 5, 95, 32, 4, 53, 4, 213, 104, 244, 92, 13, 11, 71, 88, 134, 134, 42, 202, 132, 101, 106, 66, 153, 90, 129, 128, 123, 209, 51, 51, 186, 139, 161, 21, 32, 146, 159, 171, 33, 171, 192, 193, 43, 127, 33, 74, 65, 107, 193, 97, 190, 67, 79, 115, 40, 65, 238, 145, 154, 83, 144, 10, 169, 17, 96, 158, 134, 182, 122, 252, 97, 11, 42, 208, 51, 173, 134, 63, 100, 145, 61, 80, 1, 108, 137, 61, 22, 35, 53, 252, 209, 150, 217, 43, 192, 220, 11, 235, 3, 64, 61, 203, 133, 88, 102, 143, 105, 12, 40, 73, 192, 22, 219, 163, 47, 182, 135, 177, 193, 238, 134, 113, 148, 48, 205, 64, 95, 127, 15, 203, 23, 233, 169, 121, 16, 85, 208, 85, 235, 232, 171, 220, 75, 32, 78, 243, 135, 24, 109, 192, 5, 213, 94, 132, 197, 15, 158, 121, 37, 69, 153, 121, 197, 153, 201, 200, 21, 23, 164, 162, 213, 81, 128, 219, 3, 139, 69, 2, 177, 1, 171, 239, 134, 107, 124, 64, 253, 71, 247, 24, 129, 53, 37, 138, 242, 200, 136, 19, 96, 227, 38, 191, 124, 120, 70, 9, 220, 123, 116, 142, 17, 164, 86, 35, 73, 17, 130, 152, 158, 130, 132, 25, 162, 117, 150, 154, 2, 10, 111, 244, 182, 7, 172, 51, 7, 139, 35, 216, 252, 19, 108, 254, 9, 86, 42, 163, 215, 165, 134, 104, 13, 2, 196, 188, 19, 164, 49, 0, 11, 163, 76, 148, 144, 132, 236, 189, 194, 22, 219, 154, 214, 152, 129, 138, 225, 51, 120, 184, 64, 219, 163, 192, 248, 132, 89, 10, 212, 78, 84, 136, 162, 150, 58, 69, 154, 232, 59, 179, 208, 226, 14, 214, 132, 129, 184, 18, 26, 145, 96, 10, 97, 6, 106, 188, 162, 105, 193, 108, 94, 107, 145, 226, 45, 120, 28, 230, 36, 22, 67, 214, 78, 193, 194, 41, 47, 53, 53, 5, 212, 54, 71, 218, 212, 130, 116, 230, 112, 101, 102, 106, 78, 10, 184, 85, 128, 162, 48, 45, 49, 7, 58, 65, 0, 238, 158, 66, 252, 8, 51, 175, 2, 209, 136, 246, 44, 65, 132, 22, 194, 81, 8, 71, 104, 90, 67, 117, 42, 130, 180, 233, 165, 228, 231, 165, 66, 69, 72, 52, 7, 172, 9, 228, 75, 184, 67, 32, 41, 28, 232, 86, 176, 201, 101, 48, 47, 163, 251, 4, 177, 143, 71, 1, 108, 28, 108, 0, 6, 236, 113, 164, 78, 0, 172, 221, 144, 7, 77, 207, 58, 136, 78, 58, 56, 51, 193, 252, 130, 43, 160, 32, 41, 185, 86, 1, 168, 3, 104, 38, 44, 120, 51, 211, 20, 52, 96, 202, 33, 69, 30, 8, 160, 70, 44, 88, 14, 238, 105, 77, 36, 195, 176, 149, 166, 96, 45, 208, 51, 205, 32, 71, 239, 82, 150, 131, 147, 114, 82, 17, 230, 0, 13, 34, 54, 15, 35, 244, 88, 131, 157, 74, 237, 92, 12, 241, 162, 123, 42, 122, 138, 135, 217, 60, 84, 179, 50, 145, 126, 131, 199, 232, 72, 207, 207, 184, 242, 51, 44, 119, 193, 58, 243, 232, 249, 56, 15, 154, 170, 177, 229, 100, 72, 93, 5, 1, 232, 133, 66, 78, 10, 68, 13, 204, 142, 90, 34, 51, 61, 173, 51, 125, 126, 81, 72, 98, 118, 170, 70, 78, 102, 110, 102, 9, 41, 249, 29, 150, 108, 138, 82, 115, 19, 51, 243, 50, 243, 210, 161, 115, 111, 224, 185, 55, 136, 113, 96, 53, 32, 71, 35, 212, 216, 40, 192, 6, 94, 33, 101, 65, 80, 98, 94, 58, 164, 48, 208, 48, 179, 52, 164, 69, 150, 135, 122, 16, 62, 6, 133, 72, 53, 8, 167, 15, 166, 28, 15, 211, 66, 40, 199, 19, 235, 53, 244, 12, 95, 154, 10, 9, 47, 88, 134, 135, 228, 227, 146, 34, 88, 134, 175, 132, 70, 15, 145, 25, 222, 26, 97, 149, 130, 157, 130, 1, 18, 87, 87, 23, 108, 55, 185, 229, 1, 84, 103, 102, 154, 130, 6, 172, 72, 64, 74, 243, 10, 10, 208, 240, 42, 133, 141, 120, 195, 52, 212, 66, 105, 92, 57, 95, 65, 1, 123, 206, 39, 148, 105, 209, 181, 161, 103, 86, 66, 53, 52, 44, 179, 226, 170, 161, 83, 83, 224, 229, 9, 56, 223, 194, 205, 133, 165, 13, 180, 92, 139, 79, 111, 45, 87, 90, 41, 44, 167, 35, 235, 113, 41, 202, 47, 64, 207, 233, 48, 19, 96, 57, 29, 170, 18, 158, 211, 139, 53, 135, 70, 78, 135, 123, 16, 127, 118, 176, 38, 53, 167, 211, 170, 110, 39, 53, 167, 19, 242, 26, 44, 167, 39, 210, 41, 99, 43, 224, 200, 216, 37, 104, 25, 27, 94, 13, 129, 131, 41, 77, 1, 87, 110, 134, 13, 214, 193, 210, 61, 140, 68, 47, 186, 96, 238, 35, 214, 1, 232, 45, 4, 152, 91, 8, 181, 52, 8, 153, 3, 107, 105, 192, 252, 48, 212, 202, 27, 180, 66, 6, 222, 56, 128, 21, 25, 80, 45, 142, 197, 158, 121, 41, 169, 21, 169, 41, 1, 137, 153, 69, 197, 26, 136, 68, 70, 108, 185, 1, 83, 9, 75, 232, 228, 102, 111, 76, 199, 64, 114, 3, 44, 55, 192, 124, 52, 212, 114, 55, 145, 62, 131, 135, 59, 165, 153, 155, 218, 249, 73, 83, 71, 1, 188, 208, 10, 182, 19, 140, 210, 172, 133, 100, 164, 182, 54, 158, 60, 6, 50, 17, 148, 199, 208, 51, 11, 44, 100, 96, 226, 232, 117, 58, 48, 124, 96, 231, 88, 64, 204, 138, 69, 213, 63, 80, 153, 13, 164, 5, 121, 121, 55, 108, 252, 140, 216, 188, 134, 222, 251, 166, 214, 248, 25, 122, 238, 37, 55, 247, 194, 125, 231, 14, 145, 71, 74, 220, 16, 139, 209, 58, 222, 67, 37, 251, 18, 233, 53, 120, 92, 194, 146, 13, 44, 149, 146, 154, 127, 73, 205, 172, 176, 164, 7, 203, 150, 36, 102, 75, 77, 74, 179, 32, 76, 23, 36, 32, 82, 224, 182, 161, 247, 172, 51, 243, 81, 71, 200, 96, 253, 106, 120, 157, 13, 245, 60, 84, 187, 6, 56, 109, 230, 1, 195, 27, 199, 94, 211, 212, 34, 136, 113, 41, 208, 12, 160, 160, 0, 15, 95, 36, 125, 160, 2, 16, 210, 214, 160, 86, 25, 0, 75, 23, 176, 50, 0, 87, 25, 128, 158, 162, 80, 53, 6, 165, 166, 148, 38, 167, 106, 20, 165, 166, 0, 169, 34, 80, 248, 195, 178, 35, 188, 40, 128, 206, 78, 195, 244, 192, 202, 3, 216, 236, 52, 172, 88, 64, 47, 22, 96, 102, 18, 91, 46, 128, 214, 23, 128, 181, 160, 21, 12, 176, 83, 123, 97, 107, 43, 96, 75, 173, 96, 235, 148, 16, 75, 173, 12, 193, 54, 161, 39, 87, 244, 209, 21, 88, 150, 135, 121, 80, 15, 168, 18, 180, 230, 16, 53, 236, 50, 211, 144, 230, 113, 192, 251, 222, 96, 254, 64, 247, 9, 108, 137, 2, 204, 39, 136, 37, 3, 16, 111, 192, 226, 28, 214, 36, 133, 53, 73, 113, 152, 101, 140, 172, 9, 217, 239, 176, 124, 0, 203, 7, 176, 5, 195, 213, 232, 10, 161, 49, 6, 95, 175, 5, 13, 76, 244, 68, 173, 80, 134, 61, 61, 167, 194, 11, 21, 72, 138, 70, 55, 29, 87, 152, 34, 38, 13, 33, 209, 8, 43, 0, 21, 20, 74, 243, 82, 82, 211, 50, 97, 167, 58, 163, 159, 233, 12, 203, 238, 57, 165, 144, 61, 0, 48, 231, 194, 74, 72, 180, 67, 155, 19, 97, 197, 35, 44, 49, 195, 74, 71, 160, 124, 8, 116, 97, 61, 216, 217, 232, 169, 184, 26, 199, 146, 4, 152, 118, 232, 146, 4, 13, 77, 5, 91, 59, 240, 172, 153, 66, 173, 53, 200, 20, 164, 53, 180, 209, 177, 112, 17, 68, 75, 132, 220, 112, 69, 91, 94, 11, 91, 141, 12, 93, 94, 155, 153, 7, 180, 64, 91, 27, 169, 92, 130, 133, 9, 108, 69, 109, 49, 161, 208, 128, 93, 75, 148, 150, 135, 53, 60, 200, 204, 213, 105, 121, 80, 215, 163, 103, 3, 88, 134, 70, 201, 6, 64, 213, 48, 183, 147, 31, 76, 16, 93, 176, 130, 188, 4, 154, 224, 192, 5, 121, 90, 158, 14, 250, 52, 7, 44, 176, 240, 7, 78, 112, 126, 110, 234, 208, 14, 25, 120, 221, 64, 98, 232, 192, 180, 194, 18, 19, 82, 253, 89, 139, 156, 243, 242, 160, 245, 18, 129, 128, 116, 45, 75, 45, 170, 28, 38, 33, 169, 72, 106, 88, 34, 7, 38, 44, 204, 96, 117, 57, 122, 104, 2, 131, 153, 96, 96, 186, 101, 230, 165, 140, 244, 84, 9, 77, 149, 64, 97, 212, 100, 137, 212, 151, 1, 187, 31, 237, 216, 132, 50, 244, 67, 65, 209, 170, 112, 160, 28, 174, 128, 48, 214, 81, 80, 2, 179, 148, 128, 140, 18, 168, 177, 64, 54, 228, 0, 62, 37, 104, 128, 64, 172, 200, 75, 204, 77, 133, 173, 159, 75, 204, 5, 57, 16, 38, 4, 166, 144, 54, 9, 3, 35, 205, 30, 102, 174, 130, 21, 98, 127, 60, 72, 29, 200, 72, 176, 113, 185, 197, 233, 80, 211, 114, 83, 139, 139, 19, 211, 65, 6, 66, 5, 129, 36, 166, 113, 40, 38, 1, 85, 192, 163, 60, 47, 17, 106, 187, 146, 18, 212, 151, 176, 128, 4, 170, 2, 123, 0, 170, 16, 168, 9, 187, 58, 152, 119, 96, 73, 22, 42, 164, 160, 173, 160, 100, 165, 160, 164, 160, 13, 54, 8, 103, 44, 132, 103, 150, 100, 132, 20, 37, 102, 230, 0, 217, 126, 169, 229, 64, 42, 21, 26, 49, 80, 179, 146, 19, 115, 114, 192, 153, 9, 182, 225, 3, 198, 129, 221, 13, 140, 98, 156, 14, 56, 22, 117, 20, 162, 99, 53, 65, 14, 136, 201, 131, 95, 251, 13, 182, 26, 222, 255, 241, 75, 173, 128, 173, 97, 70, 196, 120, 112, 105, 113, 65, 106, 94, 74, 106, 10, 88, 25, 124, 61, 48, 52, 250, 97, 202, 96, 9, 3, 44, 165, 80, 83, 163, 160, 232, 9, 30, 15, 1, 107, 64, 146, 131, 105, 131, 133, 20, 154, 87, 160, 82, 10, 10, 206, 64, 81, 168, 126, 240, 18, 70, 244, 197, 56, 232, 203, 113, 160, 173, 30, 4, 71, 9, 197, 87, 160, 149, 106, 224, 230, 16, 44, 15, 192, 92, 142, 230, 70, 207, 98, 112, 219, 63, 5, 135, 91, 171, 33, 25, 201, 74, 161, 20, 150, 227, 116, 224, 171, 4, 33, 203, 3, 113, 152, 238, 89, 28, 84, 154, 151, 7, 140, 10, 116, 131, 209, 74, 17, 19, 51, 184, 11, 33, 184, 164, 168, 18, 37, 97, 193, 214, 102, 195, 12, 134, 173, 205, 134, 173, 38, 47, 81, 2, 27, 80, 11, 191, 242, 25, 37, 154, 136, 243, 45, 40, 65, 64, 148, 5, 167, 150, 64, 85, 192, 74, 68, 152, 247, 160, 55, 161, 164, 90, 163, 149, 38, 112, 189, 208, 197, 93, 176, 212, 52, 212, 83, 19, 76, 55, 108, 81, 23, 185, 201, 9, 102, 19, 208, 16, 144, 13, 56, 245, 123, 66, 19, 76, 58, 186, 86, 104, 130, 41, 128, 38, 24, 19, 104, 130, 81, 128, 38, 24, 5, 104, 130, 129, 135, 8, 52, 193, 160, 6, 183, 142, 66, 25, 56, 193, 128, 221, 129, 55, 197, 16, 233, 33, 138, 83, 12, 80, 47, 210, 18, 77, 220, 5, 16, 173, 147, 12, 44, 198, 9, 37, 25, 5, 104, 68, 194, 146, 12, 44, 201, 192, 56, 176, 36, 3, 243, 23, 108, 105, 38, 44, 205, 144, 154, 102, 208, 139, 32, 43, 72, 12, 210, 188, 240, 129, 170, 45, 75, 44, 82, 40, 2, 218, 168, 96, 75, 192, 1, 232, 201, 14, 37, 202, 116, 20, 138, 208, 55, 145, 16, 155, 240, 112, 133, 10, 76, 25, 44, 225, 193, 84, 16, 74, 120, 192, 184, 86, 240, 204, 43, 73, 45, 42, 0, 186, 5, 41, 166, 64, 142, 214, 72, 79, 205, 131, 230, 144, 108, 216, 129, 241, 10, 105, 249, 69, 201, 169, 112, 29, 169, 208, 145, 83, 144, 83, 179, 65, 103, 47, 219, 218, 218, 66, 203, 95, 136, 114, 92, 225, 0, 51, 27, 173, 184, 230, 66, 55, 10, 154, 51, 137, 54, 11, 150, 147, 161, 134, 89, 91, 115, 225, 215, 133, 30, 15, 200, 193, 82, 2, 84, 136, 190, 13, 10, 110, 26, 40, 116, 177, 40, 135, 141, 63, 194, 118, 241, 160, 239, 247, 129, 38, 161, 84, 200, 158, 27, 144, 167, 176, 108, 143, 179, 81, 48, 130, 70, 43, 252, 168, 56, 88, 175, 1, 54, 200, 132, 100, 58, 120, 168, 9, 182, 57, 7, 77, 10, 182, 125, 72, 19, 106, 158, 21, 186, 121, 176, 204, 14, 3, 184, 141, 198, 174, 8, 102, 9, 108, 212, 5, 6, 96, 35, 47, 176, 188, 14, 43, 198, 96, 229, 147, 6, 218, 70, 33, 180, 44, 104, 106, 6, 219, 22, 4, 141, 74, 88, 184, 195, 206, 214, 70, 14, 121, 247, 212, 18, 88, 224, 107, 128, 247, 51, 100, 22, 59, 22, 87, 230, 37, 235, 40, 228, 166, 2, 157, 14, 78, 184, 80, 235, 17, 2, 176, 12, 6, 85, 11, 19, 82, 128, 234, 1, 119, 141, 160, 94, 7, 27, 10, 61, 57, 8, 54, 204, 131, 54, 204, 147, 95, 164, 164, 9, 118, 41, 204, 88, 52, 155, 20, 20, 32, 17, 15, 210, 1, 54, 148, 144, 5, 176, 179, 26, 209, 205, 134, 25, 3, 179, 24, 22, 9, 10, 182, 24, 193, 0, 233, 53, 234, 64, 236, 132, 237, 169, 129, 153, 130, 122, 62, 55, 40, 4, 220, 138, 242, 115, 17, 103, 210, 2, 205, 64, 177, 4, 45, 166, 21, 208, 37, 97, 105, 5, 213, 30, 80, 185, 3, 25, 82, 132, 13, 41, 18, 27, 192, 232, 254, 135, 149, 99, 32, 12, 10, 3, 88, 39, 54, 191, 72, 193, 22, 148, 166, 209, 211, 180, 70, 46, 98, 131, 11, 72, 51, 90, 234, 203, 68, 63, 183, 17, 45, 253, 153, 27, 130, 117, 194, 23, 208, 43, 216, 43, 40, 129, 104, 37, 5, 43, 133, 18, 160, 170, 252, 52, 168, 193, 8, 247, 64, 188, 15, 245, 26, 204, 113, 122, 32, 81, 144, 42, 152, 139, 145, 99, 12, 106, 117, 124, 60, 120, 159, 110, 124, 188, 21, 200, 42, 104, 205, 137, 154, 167, 242, 82, 97, 102, 227, 218, 246, 5, 139, 81, 52, 75, 172, 185, 106, 185, 210, 160, 65, 2, 78, 32, 80, 89, 55, 200, 169, 33, 137, 73, 57, 169, 144, 192, 47, 74, 5, 133, 11, 164, 215, 85, 12, 9, 20, 107, 228, 96, 131, 117, 119, 179, 160, 33, 6, 145, 65, 209, 165, 80, 83, 131, 20, 54, 224, 131, 10, 148, 138, 33, 189, 94, 77, 5, 88, 228, 163, 231, 115, 51, 34, 195, 25, 61, 246, 115, 161, 33, 13, 146, 198, 178, 41, 12, 158, 114, 52, 99, 209, 67, 31, 226, 43, 244, 147, 249, 128, 93, 24, 104, 146, 129, 120, 16, 41, 10, 32, 150, 160, 141, 141, 195, 164, 137, 78, 127, 181, 168, 129, 73, 40, 13, 66, 195, 6, 110, 9, 238, 0, 130, 171, 129, 88, 131, 150, 18, 160, 227, 219, 105, 176, 90, 10, 150, 0, 192, 167, 225, 250, 3, 109, 70, 11, 29, 88, 57, 2, 75, 38, 136, 100, 226, 15, 46, 80, 138, 83, 53, 193, 1, 10, 75, 240, 176, 104, 128, 233, 215, 67, 78, 240, 25, 137, 197, 158, 121, 197, 37, 137, 121, 201, 169, 208, 80, 130, 119, 112, 193, 30, 70, 58, 44, 50, 179, 56, 160, 40, 31, 178, 89, 221, 63, 13, 156, 200, 145, 202, 3, 184, 148, 134, 18, 204, 101, 74, 154, 16, 69, 48, 123, 97, 19, 160, 160, 32, 70, 178, 22, 118, 194, 17, 70, 144, 192, 82, 82, 145, 66, 57, 120, 172, 11, 58, 53, 28, 14, 228, 184, 229, 23, 133, 37, 230, 100, 166, 192, 172, 210, 0, 25, 140, 107, 130, 22, 104, 54, 216, 4, 216, 204, 172, 130, 1, 118, 119, 17, 171, 221, 16, 66, 33, 194, 22, 106, 0, 204, 7, 80, 197, 214, 200, 113, 138, 205, 209, 224, 86, 8, 34, 122, 253, 97, 35, 88, 232, 89, 26, 125, 51, 17, 112, 127, 23, 214, 48, 128, 237, 38, 194, 181, 155, 8, 30, 175, 136, 94, 3, 54, 115, 124, 83, 209, 58, 16, 232, 221, 7, 5, 5, 37, 172, 222, 129, 143, 93, 104, 34, 199, 93, 102, 9, 44, 213, 42, 160, 109, 32, 130, 6, 176, 191, 142, 130, 1, 88, 7, 122, 130, 197, 173, 222, 16, 57, 184, 147, 209, 115, 54, 208, 139, 8, 99, 116, 224, 14, 208, 36, 20, 33, 208, 206, 143, 198, 112, 137, 18, 152, 135, 200, 143, 20, 72, 13, 3, 214, 2, 116, 54, 108, 255, 43, 172, 48, 65, 223, 213, 142, 94, 98, 163, 239, 127, 133, 149, 219, 240, 48, 128, 114, 20, 20, 80, 71, 170, 224, 30, 68, 26, 175, 130, 136, 212, 130, 253, 128, 63, 234, 17, 27, 225, 113, 69, 62, 172, 132, 133, 173, 189, 32, 55, 31, 2, 35, 29, 197, 32, 178, 162, 27, 197, 4, 162, 34, 26, 195, 241, 232, 185, 14, 182, 68, 134, 200, 24, 46, 194, 226, 64, 112, 15, 12, 150, 169, 145, 214, 193, 128, 199, 239, 97, 139, 128, 113, 134, 40, 101, 25, 105, 192, 195, 20, 54, 8, 66, 171, 80, 133, 229, 75, 98, 195, 21, 186, 133, 78, 3, 125, 157, 15, 44, 19, 227, 10, 91, 66, 45, 104, 98, 91, 47, 112, 53, 104, 141, 36, 244, 117, 96, 184, 172, 65, 159, 110, 66, 95, 7, 6, 11, 93, 88, 217, 15, 43, 95, 208, 27, 43, 176, 62, 57, 164, 25, 128, 136, 50, 244, 197, 97, 240, 56, 130, 135, 30, 100, 225, 84, 42, 116, 225, 84, 9, 52, 204, 17, 22, 194, 22, 81, 161, 174, 243, 66, 111, 7, 40, 40, 64, 29, 128, 210, 138, 128, 219, 7, 107, 70, 96, 70, 57, 52, 35, 149, 64, 35, 28, 22, 148, 176, 52, 2, 54, 20, 232, 71, 68, 180, 107, 145, 228, 114, 88, 178, 128, 37, 139, 98, 72, 242, 114, 6, 6, 120, 78, 42, 200, 56, 216, 82, 41, 232, 48, 25, 108, 29, 24, 108, 29, 24, 118, 29, 105, 137, 208, 181, 73, 181, 168, 171, 146, 20, 50, 129, 145, 143, 161, 3, 52, 115, 9, 205, 76, 48, 167, 195, 87, 38, 33, 60, 12, 137, 107, 88, 124, 39, 67, 14, 178, 85, 64, 44, 166, 128, 204, 55, 226, 154, 111, 44, 10, 207, 44, 201, 64, 26, 186, 129, 5, 4, 90, 221, 82, 6, 95, 9, 134, 214, 236, 135, 197, 9, 108, 151, 36, 162, 186, 129, 88, 169, 3, 117, 17, 204, 173, 224, 16, 2, 27, 5, 221, 251, 1, 119, 177, 182, 173, 130, 33, 56, 104, 80, 178, 42, 212, 81, 144, 45, 114, 192, 163, 141, 160, 71, 27, 193, 99, 134, 80, 134, 133, 251, 11, 45, 39, 161, 103, 88, 152, 33, 184, 50, 108, 26, 142, 12, 11, 155, 103, 71, 63, 68, 138, 216, 60, 11, 215, 4, 205, 182, 180, 206, 182, 176, 205, 134, 48, 25, 28, 233, 31, 238, 44, 66, 153, 151, 222, 153, 151, 84, 247, 195, 18, 202, 96, 203, 194, 40, 169, 9, 104, 24, 125, 178, 112, 113, 106, 78, 106, 114, 73, 42, 174, 76, 12, 15, 53, 29, 5, 88, 62, 198, 149, 143, 65, 190, 5, 155, 6, 95, 229, 14, 9, 60, 248, 94, 8, 168, 191, 136, 205, 226, 232, 251, 25, 7, 58, 115, 131, 109, 7, 58, 58, 61, 181, 200, 7, 228, 38, 232, 153, 143, 224, 219, 107, 75, 138, 128, 110, 135, 58, 21, 238, 36, 13, 20, 213, 160, 243, 73, 81, 221, 20, 148, 152, 151, 14, 116, 20, 108, 35, 21, 173, 51, 59, 250, 62, 67, 92, 89, 69, 7, 197, 151, 154, 214, 176, 220, 62, 208, 185, 157, 88, 15, 192, 118, 137, 193, 182, 82, 13, 149, 188, 206, 5, 221, 120, 7, 115, 59, 234, 233, 134, 184, 245, 195, 26, 234, 121, 214, 16, 83, 168, 85, 60, 160, 103, 93, 136, 243, 116, 117, 113, 56, 80, 65, 33, 169, 40, 53, 17, 233, 228, 64, 244, 90, 187, 8, 109, 227, 226, 112, 201, 210, 48, 55, 193, 178, 52, 189, 178, 52, 60, 76, 209, 54, 20, 162, 71, 233, 96, 207, 210, 132, 60, 48, 84, 178, 52, 44, 113, 193, 114, 0, 44, 51, 194, 50, 35, 185, 153, 17, 230, 24, 164, 162, 65, 87, 87, 193, 198, 22, 150, 245, 96, 126, 132, 101, 85, 152, 245, 232, 25, 48, 21, 186, 193, 5, 125, 103, 18, 52, 48, 75, 8, 213, 171, 180, 202, 132, 232, 141, 102, 106, 245, 114, 105, 149, 221, 96, 91, 132, 96, 82, 232, 241, 134, 218, 95, 180, 230, 26, 44, 121, 141, 84, 215, 195, 146, 199, 80, 201, 107, 148, 54, 149, 209, 3, 2, 86, 23, 82, 171, 183, 107, 13, 53, 8, 186, 219, 9, 230, 35, 5, 216, 52, 19, 250, 52, 19, 216, 72, 160, 57, 224, 96, 198, 162, 27, 150, 10, 224, 201, 28, 85, 6, 158, 214, 97, 129, 64, 104, 155, 21, 34, 36, 80, 204, 209, 193, 101, 33, 44, 108, 96, 209, 14, 51, 29, 86, 6, 193, 90, 250, 132, 90, 250, 144, 17, 244, 148, 210, 228, 84, 141, 34, 16, 5, 84, 11, 54, 25, 86, 44, 13, 146, 98, 9, 234, 54, 226, 203, 37, 244, 221, 86, 176, 130, 9, 22, 128, 232, 5, 83, 9, 180, 208, 129, 109, 200, 129, 205, 206, 33, 165, 106, 152, 247, 129, 230, 151, 230, 34, 175, 147, 1, 249, 12, 182, 61, 11, 22, 228, 160, 48, 211, 5, 6, 57, 108, 178, 22, 42, 9, 223, 27, 4, 14, 84, 247, 212, 18, 152, 97, 26, 134, 144, 68, 134, 158, 133, 106, 169, 148, 141, 96, 217, 28, 102, 188, 13, 180, 2, 131, 237, 88, 66, 184, 10, 98, 139, 53, 84, 10, 225, 28, 67, 176, 16, 204, 59, 216, 181, 98, 230, 205, 60, 104, 212, 193, 50, 39, 56, 115, 34, 235, 210, 129, 216, 167, 3, 179, 73, 91, 27, 165, 92, 193, 229, 106, 244, 148, 102, 106, 12, 137, 103, 120, 57, 140, 26, 145, 181, 232, 169, 30, 125, 59, 213, 64, 37, 119, 88, 210, 36, 148, 52, 161, 158, 138, 214, 211, 211, 35, 45, 242, 99, 177, 122, 222, 13, 182, 123, 42, 111, 128, 189, 143, 158, 219, 97, 187, 58, 112, 88, 97, 136, 222, 0, 129, 237, 234, 32, 54, 32, 97, 25, 26, 24, 122, 32, 143, 26, 128, 132, 210, 128, 206, 213, 0, 137, 151, 37, 230, 144, 155, 191, 128, 78, 197, 154, 250, 211, 242, 80, 18, 62, 188, 86, 2, 59, 64, 91, 91, 19, 86, 40, 99, 196, 80, 112, 126, 46, 242, 16, 230, 96, 139, 37, 244, 241, 85, 98, 35, 11, 125, 124, 117, 160, 227, 12, 228, 41, 108, 241, 70, 104, 232, 13, 26, 125, 48, 99, 20, 96, 25, 180, 164, 8, 82, 1, 3, 189, 134, 82, 28, 193, 26, 95, 232, 49, 13, 219, 99, 54, 210, 163, 154, 78, 81, 173, 72, 173, 184, 134, 69, 41, 122, 100, 195, 83, 1, 246, 184, 118, 203, 204, 75, 25, 209, 81, 77, 175, 168, 134, 229, 106, 88, 76, 147, 27, 211, 176, 237, 122, 57, 168, 217, 26, 41, 106, 125, 19, 11, 144, 46, 192, 244, 204, 203, 132, 186, 45, 41, 7, 41, 126, 115, 19, 11, 160, 81, 11, 243, 121, 98, 74, 10, 200, 223, 32, 25, 189, 226, 212, 18, 88, 140, 35, 71, 5, 72, 9, 174, 8, 7, 69, 3, 52, 78, 193, 70, 193, 34, 20, 22, 134, 208, 208, 7, 6, 89, 46, 182, 96, 212, 128, 57, 17, 102, 60, 204, 114, 104, 114, 131, 233, 133, 75, 99, 216, 111, 98, 170, 163, 160, 4, 244, 187, 146, 38, 34, 92, 20, 20, 146, 49, 3, 29, 226, 13, 29, 144, 71, 129, 113, 5, 53, 55, 218, 32, 22, 137, 99, 24, 171, 137, 94, 15, 130, 130, 21, 218, 72, 1, 199, 100, 82, 98, 114, 118, 90, 158, 142, 2, 252, 54, 23, 68, 4, 34, 66, 217, 23, 17, 198, 104, 254, 241, 133, 172, 192, 240, 85, 128, 173, 192, 200, 7, 154, 15, 147, 3, 45, 104, 177, 133, 46, 104, 129, 122, 23, 26, 239, 136, 149, 13, 168, 139, 47, 128, 154, 125, 81, 87, 92, 232, 64, 101, 75, 50, 32, 43, 46, 96, 129, 1, 117, 55, 23, 76, 22, 236, 122, 248, 146, 12, 223, 68, 152, 39, 149, 192, 66, 240, 72, 68, 207, 149, 240, 32, 128, 181, 140, 176, 166, 7, 151, 212, 100, 228, 108, 137, 228, 0, 77, 148, 124, 9, 140, 157, 162, 204, 212, 98, 80, 131, 29, 230, 65, 216, 190, 69, 160, 139, 226, 161, 210, 58, 10, 190, 154, 214, 80, 29, 192, 200, 131, 20, 97, 64, 117, 65, 169, 197, 165, 57, 37, 1, 137, 153, 69, 64, 3, 210, 115, 242, 147, 18, 129, 225, 129, 69, 26, 220, 97, 42, 207, 0, 58, 71, 65, 3, 212, 139, 6, 59, 28, 218, 141, 78, 201, 207, 75, 5, 119, 128, 74, 64, 93, 90, 160, 118, 87, 160, 157, 149, 192, 176, 128, 245, 116, 53, 96, 142, 192, 97, 53, 216, 101, 144, 112, 66, 57, 113, 2, 125, 28, 28, 98, 93, 118, 106, 37, 36, 171, 97, 49, 9, 114, 91, 54, 84, 97, 25, 236, 110, 117, 236, 74, 13, 161, 74, 115, 19, 113, 152, 164, 0, 73, 70, 120, 85, 25, 34, 171, 194, 158, 101, 16, 209, 13, 75, 241, 233, 176, 98, 10, 228, 23, 80, 204, 192, 50, 12, 208, 213, 248, 34, 1, 24, 71, 208, 197, 245, 216, 165, 53, 52, 173, 81, 242, 28, 44, 252, 97, 235, 197, 160, 241, 239, 143, 43, 103, 161, 175, 109, 2, 230, 44, 176, 41, 232, 107, 3, 97, 121, 139, 80, 222, 202, 129, 122, 3, 172, 221, 55, 181, 132, 80, 30, 83, 66, 115, 51, 90, 62, 42, 131, 165, 93, 44, 225, 130, 55, 216, 172, 161, 154, 129, 142, 13, 67, 222, 102, 5, 219, 106, 10, 108, 34, 128, 55, 91, 193, 55, 91, 65, 53, 16, 74, 217, 160, 48, 65, 78, 211, 48, 59, 97, 105, 26, 18, 186, 136, 36, 13, 111, 30, 228, 122, 103, 230, 165, 40, 216, 34, 150, 100, 121, 230, 149, 24, 27, 185, 21, 229, 231, 162, 140, 107, 2, 13, 55, 2, 155, 3, 117, 62, 216, 112, 32, 31, 154, 87, 224, 6, 193, 102, 143, 160, 193, 88, 4, 86, 7, 52, 30, 187, 203, 162, 13, 98, 81, 122, 255, 24, 70, 25, 18, 107, 20, 44, 15, 193, 140, 130, 107, 179, 134, 136, 34, 233, 143, 198, 233, 22, 44, 1, 8, 51, 27, 102, 56, 23, 90, 6, 132, 169, 194, 149, 77, 209, 85, 161, 103, 83, 104, 66, 208, 131, 21, 16, 176, 128, 69, 146, 130, 198, 124, 90, 34, 208, 91, 64, 9, 176, 27, 128, 82, 165, 69, 121, 80, 21, 214, 72, 245, 155, 130, 10, 48, 179, 1, 47, 14, 70, 187, 214, 189, 8, 182, 161, 11, 253, 90, 247, 220, 84, 13, 36, 29, 58, 10, 184, 46, 117, 71, 201, 204, 238, 69, 249, 165, 5, 78, 208, 83, 87, 32, 213, 1, 180, 58, 0, 90, 8, 73, 106, 232, 107, 89, 83, 32, 138, 53, 113, 212, 50, 208, 56, 50, 53, 129, 229, 63, 244, 42, 7, 162, 27, 38, 11, 230, 129, 155, 163, 232, 205, 81, 37, 120, 54, 66, 205, 177, 148, 214, 124, 32, 103, 24, 226, 174, 249, 156, 21, 108, 33, 235, 249, 209, 175, 94, 215, 128, 182, 101, 16, 101, 6, 40, 246, 83, 203, 21, 156, 53, 224, 130, 217, 64, 33, 34, 155, 169, 26, 168, 161, 104, 109, 13, 203, 145, 10, 217, 169, 149, 64, 99, 146, 209, 219, 73, 176, 66, 31, 218, 204, 129, 135, 14, 162, 216, 135, 230, 106, 164, 139, 122, 113, 86, 224, 233, 169, 37, 208, 246, 86, 118, 106, 37, 68, 31, 40, 92, 97, 87, 249, 130, 98, 4, 189, 253, 164, 0, 109, 176, 96, 26, 86, 140, 108, 152, 142, 66, 52, 216, 61, 177, 154, 208, 76, 12, 203, 196, 176, 212, 128, 126, 255, 40, 220, 78, 248, 61, 184, 197, 208, 155, 5, 145, 207, 179, 81, 80, 0, 15, 87, 3, 67, 88, 219, 86, 193, 16, 36, 130, 200, 60, 32, 187, 17, 57, 39, 63, 79, 193, 175, 52, 55, 41, 181, 40, 62, 179, 216, 45, 51, 15, 24, 204, 26, 121, 165, 185, 154, 10, 176, 244, 12, 109, 18, 231, 149, 230, 66, 54, 254, 228, 129, 21, 43, 105, 194, 234, 30, 180, 158, 91, 45, 220, 26, 176, 22, 93, 16, 9, 14, 29, 3, 236, 86, 250, 37, 250, 81, 211, 62, 160, 22, 16, 141, 221, 46, 240, 209, 192, 169, 69, 26, 16, 35, 49, 172, 132, 8, 19, 107, 43, 56, 245, 103, 66, 76, 68, 158, 104, 47, 41, 2, 218, 11, 177, 2, 92, 255, 192, 244, 66, 77, 215, 133, 233, 193, 23, 40, 193, 137, 105, 169, 244, 118, 44, 188, 178, 132, 114, 145, 92, 170, 136, 92, 181, 225, 137, 0, 93, 13, 13, 35, 5, 45, 45, 5, 83, 99, 77, 160, 110, 67, 77, 5, 27, 91, 184, 25, 106, 106, 48, 38, 72, 20, 69, 29, 74, 24, 184, 231, 228, 39, 37, 230, 32, 18, 6, 220, 239, 80, 59, 224, 97, 4, 146, 15, 201, 7, 113, 17, 129, 164, 137, 197, 40, 120, 178, 198, 97, 26, 114, 202, 39, 96, 32, 164, 129, 230, 158, 90, 226, 95, 158, 7, 203, 142, 46, 169, 197, 201, 69, 153, 5, 37, 249, 69, 197, 26, 254, 32, 179, 33, 97, 157, 159, 148, 133, 124, 49, 168, 191, 166, 53, 172, 200, 75, 173, 44, 134, 198, 64, 80, 106, 90, 14, 80, 50, 62, 191, 60, 207, 27, 40, 170, 1, 217, 80, 6, 81, 150, 2, 55, 22, 164, 186, 186, 22, 81, 72, 34, 159, 38, 166, 3, 190, 62, 211, 22, 108, 40, 180, 16, 176, 134, 202, 218, 128, 164, 192, 28, 196, 133, 241, 112, 23, 64, 181, 64, 142, 27, 133, 158, 51, 10, 179, 85, 193, 22, 191, 63, 161, 91, 80, 179, 97, 229, 32, 44, 7, 165, 230, 167, 65, 244, 43, 218, 218, 42, 0, 43, 35, 88, 101, 4, 179, 26, 107, 89, 134, 228, 77, 104, 105, 8, 50, 2, 169, 4, 67, 164, 46, 228, 32, 193, 30, 43, 240, 205, 100, 254, 105, 136, 59, 240, 160, 17, 141, 28, 222, 233, 168, 74, 97, 145, 4, 210, 131, 37, 194, 65, 59, 243, 93, 43, 74, 82, 243, 138, 51, 147, 64, 123, 42, 209, 12, 246, 132, 53, 219, 193, 18, 106, 106, 40, 54, 101, 162, 233, 196, 102, 122, 124, 73, 190, 79, 126, 114, 98, 78, 42, 234, 241, 68, 137, 168, 93, 4, 136, 109, 216, 186, 54, 26, 254, 122, 37, 249, 64, 189, 224, 83, 112, 252, 177, 218, 0, 174, 22, 252, 211, 32, 70, 195, 140, 130, 121, 27, 118, 154, 0, 166, 182, 140, 196, 98, 164, 132, 174, 17, 134, 162, 29, 34, 169, 17, 6, 236, 78, 97, 232, 87, 1, 27, 0, 9, 100, 96, 188, 148, 164, 22, 33, 89, 77, 100, 100, 128, 92, 5, 142, 13, 244, 102, 91, 170, 6, 166, 241, 144, 214, 27, 98, 191, 45, 82, 179, 13, 213, 53, 64, 179, 64, 174, 1, 43, 131, 58, 9, 189, 239, 4, 173, 168, 161, 97, 80, 12, 117, 158, 142, 2, 228, 120, 7, 176, 78, 188, 206, 130, 217, 3, 113, 86, 113, 42, 46, 103, 65, 84, 67, 242, 4, 68, 57, 248, 80, 38, 29, 133, 98, 48, 71, 19, 81, 148, 128, 21, 42, 192, 74, 19, 120, 140, 65, 155, 118, 200, 131, 26, 32, 173, 232, 3, 92, 136, 102, 157, 177, 49, 200, 65, 96, 37, 64, 151, 192, 42, 6, 88, 137, 0, 175, 6, 65, 174, 0, 102, 98, 196, 30, 95, 5, 53, 53, 224, 192, 24, 154, 28, 180, 206, 193, 42, 87, 92, 153, 155, 148, 159, 163, 164, 96, 15, 116, 50, 44, 249, 120, 167, 86, 130, 253, 167, 169, 96, 165, 0, 61, 210, 10, 82, 34, 228, 165, 194, 83, 24, 216, 209, 96, 239, 66, 150, 144, 128, 28, 6, 97, 24, 84, 24, 25, 24, 40, 212, 0, 105, 3, 67, 8, 101, 4, 221, 63, 93, 10, 219, 87, 13, 242, 24, 104, 175, 37, 184, 63, 91, 84, 154, 10, 100, 96, 75, 213, 144, 0, 7, 38, 27, 68, 128, 167, 147, 31, 224, 64, 173, 132, 2, 60, 125, 120, 5, 120, 58, 44, 152, 97, 129, 79, 40, 192, 125, 242, 243, 179, 75, 11, 130, 83, 225, 1, 78, 84, 64, 15, 104, 40, 165, 228, 3, 157, 8, 171, 19, 161, 117, 162, 59, 172, 54, 68, 171, 13, 67, 160, 147, 222, 208, 80, 84, 200, 70, 174, 23, 193, 245, 27, 52, 113, 32, 137, 68, 27, 196, 42, 168, 65, 130, 24, 33, 9, 47, 29, 193, 42, 140, 98, 173, 161, 226, 181, 80, 26, 42, 91, 10, 235, 100, 192, 234, 72, 68, 20, 66, 154, 21, 184, 74, 86, 136, 26, 176, 219, 106, 161, 131, 136, 80, 49, 112, 232, 128, 198, 147, 112, 71, 31, 82, 126, 25, 233, 209, 71, 76, 244, 129, 134, 100, 6, 58, 250, 96, 141, 85, 116, 127, 195, 26, 113, 73, 89, 58, 10, 5, 136, 96, 212, 132, 69, 43, 177, 33, 134, 110, 0, 162, 124, 68, 14, 53, 76, 111, 35, 74, 193, 196, 146, 146, 162, 98, 199, 188, 20, 232, 56, 28, 52, 104, 97, 198, 32, 203, 130, 131, 219, 16, 18, 220, 8, 83, 33, 28, 112, 60, 231, 148, 166, 90, 193, 66, 94, 7, 42, 90, 94, 148, 89, 146, 152, 148, 3, 148, 80, 84, 196, 52, 205, 192, 4, 58, 166, 162, 160, 144, 154, 87, 154, 155, 90, 132, 71, 169, 33, 92, 105, 114, 126, 94, 90, 102, 122, 41, 62, 197, 70, 80, 197, 181, 48, 175, 90, 91, 115, 33, 187, 24, 82, 134, 34, 92, 11, 171, 188, 172, 160, 25, 31, 42, 66, 180, 163, 136, 118, 82, 45, 36, 121, 160, 36, 15, 255, 162, 160, 212, 180, 28, 120, 181, 8, 141, 109, 204, 200, 213, 1, 71, 86, 102, 82, 105, 73, 106, 177, 142, 66, 49, 144, 153, 92, 2, 137, 140, 76, 216, 216, 53, 188, 17, 12, 141, 36, 244, 214, 135, 169, 25, 234, 116, 138, 6, 218, 197, 220, 8, 235, 80, 202, 13, 36, 81, 72, 49, 128, 94, 124, 160, 43, 65, 47, 69, 112, 152, 82, 137, 189, 48, 65, 82, 168, 169, 96, 133, 45, 125, 35, 249, 22, 30, 38, 160, 113, 41, 116, 79, 195, 70, 247, 192, 163, 123, 22, 152, 163, 123, 192, 16, 48, 66, 14, 86, 77, 232, 168, 29, 44, 131, 192, 50, 8, 48, 44, 12, 64, 130, 208, 99, 55, 194, 18, 115, 74, 81, 6, 69, 97, 163, 102, 48, 14, 180, 134, 86, 128, 205, 155, 64, 4, 139, 83, 209, 4, 65, 62, 81, 66, 164, 124, 37, 133, 204, 60, 100, 199, 64, 188, 3, 117, 65, 141, 45, 146, 148, 30, 66, 147, 130, 61, 164, 125, 96, 5, 162, 44, 160, 46, 135, 152, 156, 156, 15, 203, 40, 36, 153, 141, 164, 13, 106, 186, 17, 216, 116, 67, 3, 107, 100, 211, 65, 254, 37, 100, 44, 88, 23, 80, 27, 172, 128, 72, 85, 64, 177, 169, 12, 22, 100, 10, 200, 161, 90, 82, 4, 20, 68, 182, 169, 188, 40, 179, 4, 191, 31, 208, 45, 195, 234, 47, 144, 49, 8, 63, 153, 128, 253, 100, 132, 234, 39, 96, 180, 17, 176, 4, 82, 229, 88, 35, 53, 195, 80, 189, 148, 14, 153, 244, 134, 166, 82, 244, 86, 106, 145, 166, 130, 154, 26, 88, 31, 100, 68, 7, 81, 38, 67, 236, 65, 79, 189, 192, 246, 171, 153, 5, 164, 253, 10, 110, 188, 42, 64, 220, 10, 119, 111, 49, 73, 238, 45, 78, 197, 112, 47, 116, 146, 30, 221, 189, 176, 110, 12, 216, 189, 64, 125, 164, 186, 183, 24, 187, 123, 193, 142, 66, 174, 182, 97, 22, 195, 36, 96, 21, 12, 14, 163, 141, 224, 102, 34, 42, 32, 148, 230, 52, 172, 212, 132, 85, 137, 240, 82, 179, 88, 7, 26, 234, 176, 174, 29, 172, 0, 133, 228, 117, 168, 251, 50, 160, 89, 27, 217, 105, 200, 229, 172, 2, 84, 12, 202, 84, 80, 128, 59, 92, 195, 160, 194, 192, 80, 161, 6, 156, 89, 32, 148, 9, 100, 142, 16, 166, 20, 171, 10, 168, 36, 194, 112, 5, 168, 111, 96, 227, 51, 56, 124, 84, 134, 52, 196, 12, 14, 9, 196, 250, 28, 136, 32, 44, 136, 200, 8, 40, 216, 208, 60, 184, 99, 129, 30, 74, 164, 26, 5, 75, 46, 41, 40, 76, 184, 153, 181, 176, 170, 16, 86, 21, 18, 50, 23, 86, 3, 194, 18, 58, 164, 46, 240, 79, 34, 84, 141, 226, 50, 68, 7, 28, 102, 192, 152, 170, 70, 14, 40, 144, 207, 209, 60, 12, 52, 4, 139, 115, 221, 138, 242, 115, 93, 33, 51, 250, 26, 153, 200, 221, 87, 144, 122, 208, 144, 33, 108, 200, 16, 50, 175, 82, 144, 152, 89, 132, 115, 217, 10, 216, 17, 176, 140, 136, 168, 222, 128, 122, 16, 82, 10, 232, 157, 91, 240, 114, 21, 136, 74, 189, 52, 132, 99, 148, 224, 249, 4, 45, 73, 161, 134, 73, 98, 38, 104, 218, 17, 194, 128, 172, 86, 33, 194, 207, 30, 144, 49, 39, 127, 29, 133, 0, 116, 239, 34, 70, 90, 53, 173, 33, 198, 32, 13, 82, 5, 128, 91, 26, 88, 155, 199, 69, 249, 228, 206, 231, 193, 2, 6, 45, 88, 184, 208, 231, 243, 96, 53, 62, 169, 243, 121, 176, 249, 60, 244, 249, 60, 88, 36, 193, 74, 75, 216, 44, 23, 250, 124, 30, 146, 155, 12, 141, 116, 16, 206, 128, 205, 231, 161, 207, 231, 33, 130, 19, 210, 17, 137, 135, 132, 80, 124, 50, 120, 173, 131, 6, 200, 89, 96, 133, 196, 206, 219, 165, 230, 149, 120, 150, 164, 22, 105, 160, 207, 219, 193, 230, 237, 112, 205, 219, 161, 207, 219, 193, 66, 1, 86, 56, 40, 100, 107, 130, 205, 128, 245, 47, 161, 45, 188, 108, 88, 227, 15, 189, 125, 8, 147, 130, 181, 11, 97, 237, 66, 52, 93, 56, 218, 131, 217, 169, 160, 118, 32, 82, 183, 176, 12, 117, 182, 16, 24, 92, 209, 64, 73, 112, 175, 5, 18, 53, 232, 83, 130, 176, 58, 11, 86, 206, 226, 42, 101, 9, 205, 5, 162, 235, 132, 205, 5, 130, 44, 195, 55, 23, 136, 200, 140, 217, 10, 218, 182, 10, 134, 176, 200, 46, 74, 45, 41, 45, 202, 83, 200, 71, 43, 93, 128, 70, 231, 102, 22, 167, 198, 167, 129, 247, 51, 1, 221, 150, 231, 6, 97, 193, 114, 92, 145, 66, 1, 68, 9, 108, 116, 26, 154, 36, 17, 229, 6, 84, 30, 71, 106, 4, 31, 159, 15, 181, 69, 9, 200, 132, 90, 164, 132, 126, 126, 62, 98, 122, 25, 58, 69, 143, 52, 183, 12, 179, 2, 249, 104, 73, 100, 105, 184, 249, 192, 180, 13, 235, 129, 129, 76, 43, 201, 72, 205, 131, 122, 71, 7, 114, 40, 47, 148, 135, 228, 9, 88, 190, 66, 248, 28, 230, 17, 100, 237, 64, 103, 193, 229, 33, 97, 12, 51, 14, 83, 22, 45, 34, 53, 144, 140, 209, 4, 170, 132, 5, 189, 6, 36, 198, 96, 209, 141, 180, 218, 4, 107, 54, 201, 67, 56, 16, 41, 151, 104, 90, 195, 116, 35, 71, 20, 44, 86, 131, 82, 139, 243, 115, 202, 82, 53, 156, 117, 20, 138, 16, 103, 176, 66, 170, 31, 244, 249, 5, 152, 53, 176, 176, 214, 3, 57, 27, 88, 155, 193, 66, 30, 238, 108, 168, 139, 145, 141, 65, 106, 92, 43, 40, 212, 66, 45, 169, 133, 80, 26, 208, 128, 194, 244, 127, 81, 106, 98, 49, 98, 147, 220, 208, 12, 0, 200, 73, 204, 16, 159, 96, 13, 128, 90, 88, 214, 35, 197, 46, 228, 148, 7, 75, 184, 208, 0, 180, 70, 202, 188, 224, 117, 105, 37, 169, 62, 153, 197, 224, 230, 129, 99, 81, 81, 98, 165, 79, 102, 118, 170, 91, 126, 145, 99, 81, 122, 177, 6, 120, 138, 170, 26, 41, 67, 64, 167, 15, 67, 242, 33, 27, 175, 64, 10, 160, 229, 135, 166, 53, 52, 91, 131, 84, 216, 41, 104, 152, 26, 24, 40, 104, 41, 24, 26, 24, 24, 160, 102, 235, 160, 196, 188, 116, 88, 45, 99, 104, 137, 156, 117, 21, 114, 50, 139, 97, 99, 90, 96, 151, 128, 140, 2, 42, 128, 85, 26, 64, 21, 153, 224, 106, 4, 72, 217, 128, 28, 2, 100, 32, 38, 42, 49, 203, 58, 13, 144, 121, 58, 10, 153, 58, 10, 64, 87, 70, 103, 198, 194, 236, 130, 133, 38, 72, 26, 37, 48, 160, 3, 105, 144, 251, 34, 52, 74, 18, 139, 210, 83, 75, 32, 211, 56, 176, 45, 98, 58, 10, 64, 65, 232, 206, 51, 96, 152, 65, 236, 70, 47, 6, 32, 26, 49, 11, 51, 88, 213, 138, 86, 181, 26, 232, 40, 64, 116, 192, 170, 85, 152, 137, 176, 210, 17, 213, 74, 76, 99, 81, 90, 17, 230, 58, 92, 16, 150, 82, 2, 138, 190, 4, 37, 184, 4, 212, 155, 122, 96, 111, 194, 133, 67, 242, 131, 243, 75, 139, 146, 83, 81, 173, 67, 30, 99, 64, 77, 135, 110, 165, 72, 115, 95, 96, 14, 252, 170, 13, 168, 135, 8, 132, 157, 53, 100, 74, 204, 179, 216, 51, 47, 39, 51, 15, 20, 114, 62, 32, 93, 112, 115, 145, 98, 3, 156, 106, 49, 162, 41, 25, 86, 126, 67, 67, 28, 205, 2, 5, 212, 216, 201, 207, 131, 21, 246, 132, 34, 200, 132, 64, 4, 65, 83, 107, 94, 106, 121, 8, 88, 24, 215, 166, 68, 77, 5, 59, 5, 35, 168, 37, 8, 213, 10, 182, 40, 123, 14, 141, 128, 102, 66, 27, 210, 232, 206, 132, 105, 129, 185, 148, 144, 91, 161, 3, 68, 112, 155, 52, 161, 70, 131, 28, 92, 171, 144, 154, 3, 171, 79, 144, 221, 2, 245, 25, 216, 95, 240, 192, 130, 38, 60, 88, 74, 40, 129, 38, 60, 236, 193, 197, 165, 160, 0, 77, 120, 92, 208, 132, 151, 128, 162, 47, 65, 9, 38, 1, 75, 120, 122, 240, 136, 35, 45, 241, 129, 7, 184, 138, 210, 139, 21, 32, 253, 84, 207, 226, 128, 196, 228, 236, 212, 20, 112, 81, 129, 166, 81, 65, 77, 77, 33, 17, 89, 4, 90, 72, 129, 87, 146, 192, 74, 38, 3, 3, 136, 5, 10, 10, 246, 168, 138, 161, 162, 86, 4, 74, 71, 52, 59, 173, 129, 218, 138, 203, 51, 75, 146, 51, 20, 64, 50, 176, 229, 21, 176, 96, 75, 78, 4, 134, 191, 129, 21, 144, 141, 84, 123, 194, 67, 2, 185, 84, 7, 150, 234, 208, 20, 141, 28, 153, 214, 92, 112, 83, 12, 201, 54, 69, 7, 28, 128, 209, 6, 224, 178, 16, 102, 156, 17, 229, 198, 65, 24, 208, 110, 25, 204, 92, 99, 234, 153, 11, 99, 24, 161, 88, 96, 66, 11, 11, 160, 12, 99, 20, 155, 76, 105, 105, 19, 140, 97, 130, 98, 165, 25, 93, 172, 132, 49, 76, 81, 236, 54, 167, 175, 221, 48, 134, 25, 138, 35, 44, 6, 202, 17, 80, 134, 57, 138, 107, 44, 7, 220, 53, 80, 134, 5, 138, 179, 12, 13, 6, 143, 187, 160, 12, 75, 84, 7, 26, 90, 13, 58, 7, 194, 13, 52, 64, 117, 170, 209, 160, 118, 42, 204, 104, 67, 152, 163, 83, 82, 211, 18, 75, 115, 74, 208, 28, 237, 156, 15, 117, 52, 33, 215, 106, 66, 154, 195, 181, 92, 176, 134, 21, 172, 97, 21, 15, 25, 251, 12, 128, 13, 54, 192, 198, 36, 209, 199, 36, 97, 3, 155, 112, 171, 253, 147, 176, 14, 109, 18, 97, 12, 244, 60, 121, 212, 190, 9, 204, 57, 233, 208, 121, 101, 244, 121, 101, 152, 199, 144, 13, 5, 185, 7, 214, 140, 129, 53, 99, 32, 202, 52, 53, 209, 219, 47, 176, 89, 70, 66, 205, 61, 52, 255, 185, 19, 239, 28, 212, 206, 22, 220, 67, 25, 137, 197, 212, 112, 59, 214, 182, 23, 88, 3, 164, 209, 133, 218, 218, 7, 90, 138, 214, 220, 74, 78, 133, 24, 15, 107, 103, 161, 249, 22, 201, 101, 10, 153, 121, 144, 48, 193, 218, 95, 2, 70, 16, 216, 161, 232, 254, 81, 160, 173, 135, 128, 162, 144, 246, 35, 33, 15, 17, 106, 156, 195, 125, 12, 212, 9, 139, 214, 224, 210, 130, 84, 244, 24, 133, 166, 90, 119, 228, 214, 59, 40, 141, 32, 133, 26, 44, 152, 162, 145, 116, 196, 162, 132, 153, 74, 80, 106, 186, 107, 69, 129, 91, 78, 98, 122, 49, 116, 141, 12, 208, 21, 208, 214, 109, 16, 214, 17, 50, 80, 176, 5, 225, 73, 190, 10, 65, 88, 135, 131, 75, 32, 3, 150, 65, 154, 48, 23, 162, 140, 142, 40, 41, 193, 44, 9, 210, 3, 95, 146, 144, 146, 153, 156, 90, 12, 181, 4, 166, 76, 27, 168, 46, 69, 9, 166, 31, 162, 56, 61, 39, 63, 41, 49, 7, 139, 194, 116, 52, 133, 153, 233, 121, 249, 69, 169, 206, 137, 197, 169, 88, 20, 103, 162, 41, 206, 5, 74, 100, 230, 100, 130, 183, 92, 161, 171, 205, 69, 83, 155, 146, 95, 226, 152, 131, 205, 5, 197, 104, 10, 75, 243, 50, 147, 243, 83, 176, 25, 89, 138, 93, 101, 112, 106, 9, 182, 32, 40, 67, 83, 93, 92, 146, 153, 156, 93, 169, 137, 169, 176, 18, 172, 16, 150, 135, 96, 7, 81, 149, 96, 95, 252, 25, 132, 158, 16, 32, 83, 167, 10, 105, 32, 17, 208, 4, 42, 122, 154, 9, 201, 71, 93, 240, 155, 72, 32, 193, 40, 16, 72, 48, 232, 243, 7, 88, 19, 76, 65, 34, 200, 105, 224, 49, 31, 152, 245, 192, 0, 0, 103, 54, 77, 232, 152, 16, 196, 197, 168, 42, 192, 66, 154, 214, 136, 144, 80, 210, 87, 82, 208, 134, 155, 166, 13, 225, 67, 116, 226, 10, 30, 100, 63, 3, 195, 6, 182, 102, 25, 37, 104, 28, 83, 202, 18, 243, 146, 161, 43, 161, 61, 243, 82, 82, 43, 52, 130, 117, 32, 107, 216, 129, 254, 135, 12, 92, 193, 70, 175, 128, 46, 45, 46, 45, 40, 128, 12, 123, 39, 22, 85, 42, 216, 66, 38, 71, 225, 235, 223, 131, 161, 93, 54, 5, 53, 53, 144, 56, 250, 48, 71, 74, 60, 196, 154, 248, 228, 252, 148, 212, 128, 252, 204, 188, 18, 199, 18, 29, 5, 132, 117, 118, 10, 6, 21, 105, 64, 192, 5, 45, 122, 160, 62, 135, 152, 174, 173, 96, 168, 160, 141, 106, 63, 74, 185, 0, 241, 174, 111, 98, 73, 114, 6, 208, 170, 34, 228, 115, 254, 20, 138, 42, 112, 70, 115, 81, 5, 190, 120, 46, 170, 192, 23, 209, 69, 21, 40, 49, 29, 140, 20, 131, 48, 39, 192, 44, 244, 44, 6, 187, 15, 186, 227, 218, 191, 160, 36, 51, 55, 179, 10, 52, 216, 133, 236, 0, 120, 82, 192, 177, 69, 18, 182, 69, 50, 31, 228, 108, 164, 61, 146, 240, 221, 179, 64, 125, 138, 138, 26, 96, 35, 32, 203, 144, 144, 7, 71, 32, 74, 32, 118, 193, 109, 3, 122, 40, 52, 15, 156, 117, 209, 245, 26, 26, 104, 90, 67, 85, 66, 227, 1, 18, 194, 144, 45, 30, 224, 112, 246, 47, 128, 56, 36, 88, 7, 217, 32, 77, 107, 46, 232, 4, 8, 186, 86, 232, 180, 129, 107, 69, 106, 50, 68, 31, 52, 248, 208, 148, 129, 227, 16, 232, 203, 242, 128, 196, 146, 12, 136, 66, 212, 102, 0, 78, 101, 208, 24, 135, 5, 35, 114, 124, 20, 85, 232, 165, 193, 178, 20, 236, 20, 13, 236, 137, 51, 51, 47, 57, 167, 52, 5, 212, 164, 2, 105, 0, 109, 83, 76, 87, 130, 68, 17, 186, 127, 208, 61, 2, 179, 27, 17, 22, 144, 205, 109, 68, 90, 83, 170, 4, 73, 245, 21, 122, 57, 137, 197, 37, 224, 188, 8, 153, 244, 131, 24, 235, 8, 228, 68, 199, 194, 120, 121, 32, 41, 232, 230, 116, 216, 230, 116, 152, 35, 129, 242, 176, 66, 213, 22, 155, 83, 97, 41, 2, 166, 6, 154, 194, 97, 218, 21, 96, 190, 204, 3, 75, 25, 40, 216, 67, 50, 128, 149, 130, 35, 114, 212, 130, 108, 201, 5, 199, 65, 73, 17, 74, 72, 131, 77, 69, 12, 145, 32, 230, 208, 96, 227, 202, 26, 142, 58, 10, 121, 58, 112, 205, 154, 8, 23, 193, 132, 80, 239, 63, 134, 90, 6, 15, 21, 228, 241, 115, 228, 208, 130, 26, 164, 128, 30, 132, 136, 8, 129, 220, 162, 7, 30, 177, 194, 82, 242, 1, 75, 62, 132, 37, 154, 112, 165, 86, 48, 65, 72, 41, 132, 28, 6, 121, 218, 218, 224, 152, 135, 164, 78, 228, 212, 233, 158, 147, 159, 148, 152, 3, 78, 163, 254, 216, 179, 9, 48, 178, 208, 252, 5, 139, 82, 244, 20, 0, 139, 115, 88, 10, 128, 165, 0, 36, 169, 28, 112, 104, 4, 43, 216, 194, 203, 96, 60, 105, 163, 32, 191, 56, 19, 228, 84, 120, 234, 8, 78, 77, 44, 74, 206, 72, 45, 130, 58, 19, 230, 34, 88, 136, 130, 163, 6, 161, 9, 152, 38, 116, 13, 65, 230, 17, 155, 88, 20, 20, 80, 252, 136, 106, 167, 15, 80, 6, 124, 168, 172, 70, 48, 212, 54, 180, 132, 21, 92, 154, 4, 41, 76, 53, 130, 117, 224, 78, 71, 114, 163, 130, 46, 92, 20, 106, 0, 250, 172, 45, 201, 41, 14, 205, 197, 176, 104, 195, 149, 128, 138, 72, 76, 64, 80, 9, 144, 245, 8, 9, 59, 88, 28, 34, 156, 0, 11, 91, 88, 80, 194, 2, 19, 87, 218, 203, 83, 192, 91, 205, 40, 192, 59, 19, 48, 101, 208, 58, 16, 86, 5, 193, 45, 132, 46, 117, 68, 148, 105, 208, 56, 3, 175, 142, 86, 176, 69, 189, 77, 172, 36, 31, 114, 155, 24, 68, 9, 168, 12, 131, 27, 163, 1, 54, 19, 174, 23, 186, 178, 26, 201, 85, 72, 82, 154, 10, 106, 106, 72, 202, 161, 119, 157, 161, 168, 46, 170, 208, 65, 54, 12, 174, 3, 73, 76, 47, 181, 34, 53, 25, 20, 151, 80, 193, 248, 2, 152, 181, 241, 174, 21, 169, 201, 144, 150, 5, 122, 85, 82, 16, 148, 90, 144, 147, 152, 156, 10, 173, 180, 117, 20, 138, 32, 124, 216, 234, 48, 88, 43, 98, 160, 90, 17, 154, 248, 115, 57, 72, 6, 230, 161, 196, 28, 176, 95, 192, 119, 196, 121, 22, 195, 39, 214, 81, 60, 100, 13, 211, 147, 89, 84, 92, 226, 146, 15, 84, 82, 4, 78, 189, 10, 176, 211, 30, 193, 126, 195, 48, 17, 86, 130, 20, 165, 34, 204, 66, 45, 247, 209, 236, 0, 103, 48, 20, 97, 88, 243, 208, 78, 1, 169, 252, 192, 226, 12, 247, 212, 18, 55, 52, 81, 108, 198, 215, 66, 131, 13, 189, 129, 133, 158, 242, 97, 113, 3, 107, 25, 164, 67, 27, 88, 232, 13, 44, 228, 179, 117, 139, 42, 116, 20, 208, 27, 88, 137, 208, 6, 86, 26, 180, 129, 101, 0, 109, 96, 41, 64, 27, 88, 57, 208, 6, 22, 82, 254, 198, 30, 138, 80, 0, 82, 0, 139, 82, 59, 5, 83, 3, 216, 98, 72, 24, 128, 45, 124, 113, 74, 44, 78, 133, 132, 138, 43, 148, 231, 150, 95, 228, 147, 152, 155, 148, 146, 136, 45, 88, 20, 224, 134, 195, 211, 39, 204, 20, 72, 72, 192, 0, 44, 191, 195, 234, 44, 80, 157, 5, 119, 40, 48, 8, 97, 182, 105, 64, 181, 192, 53, 85, 64, 134, 13, 16, 32, 24, 77, 0, 154, 82, 209, 132, 81, 211, 14, 186, 28, 56, 98, 208, 4, 97, 222, 135, 20, 187, 48, 128, 226, 207, 90, 56, 27, 206, 194, 239, 43, 55, 96, 148, 64, 43, 58, 184, 51, 81, 29, 6, 113, 10, 220, 22, 152, 185, 160, 248, 68, 73, 172, 192, 100, 169, 160, 136, 84, 27, 18, 97, 121, 112, 105, 82, 113, 9, 44, 60, 209, 195, 18, 45, 28, 49, 194, 16, 87, 248, 161, 135, 29, 122, 166, 2, 186, 19, 44, 5, 11, 59, 152, 175, 136, 112, 110, 102, 110, 65, 78, 42, 177, 161, 5, 51, 21, 18, 82, 165, 121, 176, 148, 159, 90, 0, 73, 249, 176, 48, 66, 177, 210, 39, 63, 153, 216, 216, 129, 229, 125, 52, 139, 8, 69, 9, 78, 235, 208, 227, 3, 22, 27, 232, 113, 129, 30, 19, 184, 226, 1, 71, 160, 107, 194, 92, 76, 200, 49, 132, 66, 27, 230, 251, 90, 46, 84, 115, 96, 245, 23, 188, 51, 196, 133, 236, 23, 160, 63, 208, 252, 128, 205, 253, 232, 209, 5, 18, 198, 238, 37, 77, 107, 88, 5, 154, 153, 143, 211, 1, 16, 235, 161, 150, 195, 173, 70, 183, 24, 135, 181, 24, 150, 66, 226, 18, 94, 122, 195, 106, 29, 244, 126, 29, 88, 69, 122, 78, 62, 176, 160, 198, 218, 241, 42, 129, 118, 188, 208, 251, 119, 233, 74, 16, 221, 232, 125, 55, 88, 51, 8, 86, 188, 35, 21, 239, 40, 10, 73, 238, 228, 65, 251, 40, 72, 77, 76, 5, 3, 112, 196, 66, 92, 1, 237, 188, 21, 67, 78, 111, 137, 247, 201, 44, 46, 1, 31, 224, 2, 150, 203, 11, 74, 133, 73, 194, 250, 127, 232, 253, 63, 66, 253, 63, 88, 206, 129, 169, 65, 239, 255, 161, 159, 63, 134, 173, 69, 13, 213, 92, 172, 3, 119, 144, 182, 54, 108, 133, 23, 146, 21, 138, 200, 161, 134, 110, 52, 122, 107, 31, 87, 55, 18, 102, 26, 122, 99, 29, 102, 42, 90, 55, 74, 1, 87, 247, 208, 26, 170, 26, 45, 232, 169, 222, 186, 135, 250, 13, 22, 155, 137, 176, 67, 156, 83, 83, 32, 65, 5, 31, 61, 46, 131, 158, 112, 8, 25, 123, 15, 128, 117, 203, 208, 87, 250, 34, 22, 109, 193, 3, 27, 101, 229, 22, 44, 30, 97, 233, 38, 58, 51, 22, 236, 10, 136, 249, 206, 137, 5, 37, 165, 69, 169, 176, 35, 48, 124, 19, 75, 50, 226, 115, 19, 43, 52, 16, 97, 4, 210, 5, 91, 224, 161, 169, 160, 171, 96, 168, 163, 96, 0, 10, 44, 228, 216, 73, 77, 193, 29, 57, 72, 202, 32, 70, 42, 216, 194, 52, 33, 53, 83, 21, 20, 208, 250, 158, 200, 174, 1, 23, 89, 10, 10, 72, 98, 153, 121, 64, 23, 66, 79, 100, 129, 57, 17, 50, 78, 168, 3, 43, 80, 96, 75, 186, 21, 12, 184, 192, 229, 44, 220, 22, 88, 49, 147, 155, 154, 87, 130, 72, 61, 24, 53, 146, 66, 77, 13, 74, 89, 131, 163, 246, 40, 128, 25, 5, 207, 77, 238, 169, 37, 206, 249, 185, 5, 57, 169, 21, 96, 147, 192, 178, 192, 90, 68, 1, 10, 96, 87, 50, 192, 248, 208, 176, 128, 29, 253, 166, 0, 43, 146, 129, 0, 30, 30, 8, 17, 120, 132, 193, 133, 176, 20, 215, 224, 34, 27, 221, 63, 48, 41, 244, 18, 20, 189, 38, 130, 175, 101, 130, 42, 134, 45, 14, 204, 3, 159, 144, 14, 164, 108, 108, 17, 174, 0, 242, 97, 41, 77, 65, 1, 22, 190, 201, 137, 5, 126, 240, 244, 22, 157, 7, 77, 110, 176, 128, 6, 201, 98, 219, 63, 4, 3, 176, 60, 14, 86, 8, 116, 19, 76, 188, 22, 202, 130, 209, 96, 55, 37, 230, 166, 166, 192, 220, 2, 183, 82, 47, 189, 40, 191, 180, 160, 24, 170, 21, 108, 41, 138, 66, 156, 182, 195, 119, 45, 160, 170, 135, 56, 2, 102, 53, 122, 172, 163, 132, 63, 80, 37, 76, 29, 234, 184, 136, 157, 45, 44, 47, 35, 229, 101, 184, 213, 88, 74, 1, 109, 91, 152, 171, 80, 199, 56, 48, 77, 65, 140, 123, 40, 232, 98, 181, 68, 27, 108, 18, 154, 195, 173, 161, 130, 24, 26, 128, 241, 140, 48, 80, 91, 33, 55, 17, 158, 113, 33, 90, 96, 133, 23, 200, 123, 88, 52, 3, 61, 10, 205, 128, 80, 223, 193, 26, 35, 24, 94, 132, 54, 86, 96, 242, 26, 92, 56, 2, 130, 139, 168, 48, 200, 129, 88, 138, 61, 8, 64, 13, 19, 107, 104, 195, 164, 4, 218, 48, 193, 149, 83, 53, 184, 144, 243, 104, 110, 34, 44, 119, 130, 242, 37, 40, 71, 66, 45, 228, 66, 203, 139, 69, 16, 19, 194, 18, 161, 185, 48, 13, 61, 255, 225, 106, 187, 112, 65, 51, 13, 172, 32, 70, 171, 214, 21, 144, 37, 225, 5, 168, 129, 53, 23, 250, 72, 22, 184, 222, 133, 41, 212, 65, 211, 162, 173, 173, 3, 243, 10, 216, 208, 180, 252, 34, 98, 115, 53, 174, 28, 77, 40, 55, 43, 192, 116, 65, 51, 52, 44, 67, 195, 18, 17, 172, 225, 64, 188, 7, 224, 250, 107, 65, 193, 66, 56, 251, 67, 92, 136, 17, 17, 80, 7, 130, 37, 209, 76, 192, 230, 15, 196, 178, 67, 120, 248, 64, 164, 160, 158, 132, 45, 60, 132, 1, 88, 122, 134, 123, 27, 42, 5, 83, 158, 147, 3, 89, 239, 82, 2, 157, 251, 202, 67, 85, 160, 128, 158, 146, 144, 1, 194, 117, 8, 9, 152, 185, 16, 167, 69, 27, 192, 246, 219, 195, 0, 122, 37, 2, 7, 193, 40, 124, 77, 24, 15, 86, 19, 192, 204, 133, 173, 136, 28, 44, 222, 131, 165, 140, 212, 98, 200, 110, 125, 42, 251, 213, 104, 176, 250, 21, 153, 99, 68, 3, 143, 195, 214, 147, 14, 118, 143, 35, 56, 198, 84, 13, 5, 216, 162, 215, 33, 23, 10, 8, 14, 120, 165, 30, 181, 130, 4, 86, 72, 3, 73, 112, 81, 13, 171, 107, 2, 138, 242, 9, 22, 213, 32, 91, 9, 204, 185, 224, 214, 141, 218, 13, 133, 151, 208, 165, 69, 168, 45, 55, 88, 9, 77, 186, 249, 168, 245, 6, 172, 70, 226, 194, 17, 227, 176, 184, 134, 69, 50, 108, 71, 70, 114, 9, 98, 71, 6, 106, 76, 35, 92, 136, 176, 92, 147, 11, 22, 180, 176, 198, 19, 17, 62, 67, 117, 168, 130, 45, 190, 246, 105, 45, 23, 212, 245, 136, 198, 13, 100, 252, 42, 179, 164, 20, 146, 54, 161, 137, 11, 214, 98, 129, 245, 52, 96, 73, 36, 63, 15, 194, 131, 121, 5, 145, 104, 211, 50, 139, 138, 75, 92, 16, 173, 22, 136, 40, 138, 19, 176, 52, 176, 160, 110, 128, 133, 84, 34, 172, 95, 5, 110, 99, 1, 181, 148, 230, 64, 150, 119, 192, 108, 71, 13, 68, 77, 5, 216, 242, 18, 244, 126, 42, 172, 150, 135, 244, 72, 21, 116, 21, 12, 33, 138, 96, 205, 1, 2, 205, 1, 120, 168, 195, 106, 124, 244, 80, 199, 85, 223, 163, 215, 246, 132, 234, 122, 66, 53, 61, 174, 210, 1, 87, 217, 160, 0, 245, 15, 176, 95, 141, 34, 140, 158, 195, 209, 243, 55, 82, 238, 6, 71, 18, 204, 117, 176, 122, 125, 32, 61, 2, 138, 115, 16, 19, 185, 38, 167, 208, 79, 240, 250, 123, 224, 253, 4, 103, 162, 212, 215, 148, 121, 207, 120, 144, 122, 15, 198, 68, 212, 201, 148, 250, 20, 86, 19, 15, 90, 159, 194, 153, 168, 181, 46, 169, 158, 134, 245, 170, 17, 221, 154, 100, 112, 17, 134, 222, 21, 132, 141, 249, 193, 122, 109, 6, 120, 123, 109, 214, 64, 245, 248, 43, 70, 224, 154, 7, 176, 7, 32, 61, 58, 120, 205, 132, 79, 7, 82, 49, 172, 173, 96, 136, 86, 203, 19, 173, 209, 8, 50, 206, 140, 94, 28, 227, 170, 4, 137, 55, 216, 24, 91, 205, 14, 175, 23, 209, 211, 15, 250, 168, 60, 161, 58, 29, 230, 44, 88, 157, 158, 90, 140, 115, 88, 33, 39, 63, 41, 49, 7, 58, 164, 224, 143, 107, 158, 12, 205, 252, 52, 224, 60, 25, 184, 162, 65, 95, 38, 134, 190, 246, 174, 194, 208, 0, 236, 49, 244, 81, 109, 240, 106, 159, 162, 10, 61, 116, 49, 66, 163, 204, 137, 69, 168, 35, 38, 176, 81, 102, 244, 249, 3, 88, 116, 0, 53, 128, 35, 158, 216, 53, 66, 176, 150, 156, 6, 84, 19, 100, 41, 144, 174, 33, 204, 60, 216, 132, 2, 162, 177, 137, 226, 45, 184, 249, 232, 235, 129, 160, 38, 99, 12, 24, 193, 70, 206, 96, 227, 102, 164, 142, 155, 193, 164, 97, 227, 102, 168, 245, 155, 53, 23, 174, 65, 51, 132, 171, 33, 106, 96, 11, 120, 160, 30, 1, 250, 25, 102, 29, 196, 231, 232, 30, 37, 118, 162, 65, 3, 37, 120, 185, 20, 20, 160, 19, 13, 112, 65, 248, 68, 3, 170, 43, 208, 151, 17, 193, 116, 34, 130, 31, 18, 1, 48, 18, 214, 76, 69, 247, 43, 108, 140, 15, 110, 14, 162, 46, 66, 137, 12, 122, 141, 241, 193, 2, 149, 200, 204, 8, 154, 224, 7, 207, 64, 86, 232, 96, 159, 129, 68, 170, 23, 225, 83, 231, 200, 249, 146, 220, 124, 137, 46, 6, 86, 152, 95, 148, 153, 158, 153, 151, 152, 3, 241, 11, 120, 225, 9, 116, 225, 73, 48, 56, 36, 128, 43, 79, 80, 111, 63, 41, 170, 208, 81, 48, 4, 219, 131, 172, 221, 13, 178, 108, 5, 226, 92, 152, 100, 70, 98, 49, 180, 36, 116, 47, 202, 47, 45, 40, 134, 79, 80, 120, 160, 73, 64, 166, 254, 96, 134, 162, 71, 15, 165, 101, 69, 17, 162, 217, 15, 46, 11, 192, 130, 185, 137, 37, 168, 163, 202, 153, 105, 10, 26, 138, 232, 46, 134, 24, 131, 163, 208, 33, 84, 232, 16, 44, 118, 160, 5, 15, 106, 202, 87, 80, 128, 153, 66, 168, 240, 129, 57, 12, 234, 153, 212, 20, 180, 213, 136, 112, 247, 34, 57, 76, 65, 23, 46, 170, 9, 51, 1, 22, 20, 176, 153, 177, 146, 100, 200, 204, 24, 44, 108, 96, 37, 16, 108, 194, 193, 22, 173, 30, 195, 213, 10, 130, 73, 162, 21, 96, 58, 48, 113, 92, 45, 32, 244, 249, 40, 28, 237, 153, 96, 56, 91, 19, 202, 130, 250, 8, 50, 127, 4, 98, 162, 196, 94, 17, 44, 41, 193, 215, 103, 19, 136, 58, 216, 20, 52, 250, 20, 52, 174, 168, 131, 53, 122, 48, 98, 5, 106, 53, 244, 40, 83, 66, 65, 174, 80, 3, 73, 205, 48, 99, 224, 169, 14, 102, 14, 100, 158, 17, 161, 12, 53, 197, 192, 149, 107, 163, 167, 113, 244, 120, 132, 133, 132, 123, 42, 60, 206, 192, 229, 20, 76, 1, 44, 2, 97, 179, 17, 136, 192, 15, 6, 51, 209, 99, 6, 51, 174, 33, 145, 128, 136, 24, 236, 133, 47, 165, 245, 37, 76, 26, 189, 190, 132, 205, 50, 225, 170, 46, 97, 161, 134, 84, 93, 162, 196, 11, 48, 210, 13, 64, 49, 142, 30, 198, 176, 154, 18, 86, 83, 42, 40, 64, 106, 74, 92, 53, 37, 44, 97, 193, 148, 194, 106, 74, 176, 97, 218, 10, 134, 176, 184, 129, 213, 148, 158, 121, 168, 53, 37, 74, 162, 75, 77, 204, 70, 79, 116, 8, 61, 53, 224, 130, 16, 38, 7, 54, 17, 26, 137, 196, 20, 235, 192, 98, 93, 65, 209, 214, 150, 11, 102, 25, 90, 213, 80, 83, 131, 102, 20, 250, 210, 68, 36, 147, 140, 192, 38, 161, 214, 14, 96, 221, 8, 207, 20, 85, 192, 18, 96, 1, 124, 75, 107, 80, 98, 185, 6, 170, 173, 58, 168, 102, 128, 19, 18, 172, 117, 128, 222, 58, 128, 69, 45, 172, 117, 128, 218, 58, 40, 45, 26, 236, 173, 3, 216, 162, 70, 216, 162, 70, 88, 11, 1, 214, 66, 0, 26, 173, 3, 18, 69, 228, 47, 228, 22, 130, 130, 2, 124, 49, 34, 196, 215, 101, 137, 69, 10, 105, 165, 57, 57, 161, 132, 26, 11, 240, 36, 10, 138, 17, 3, 107, 46, 216, 10, 20, 152, 24, 173, 27, 11, 3, 85, 233, 147, 91, 63, 192, 234, 7, 88, 253, 128, 94, 63, 192, 234, 7, 244, 172, 58, 216, 235, 7, 152, 167, 96, 203, 114, 209, 151, 229, 194, 173, 4, 239, 151, 5, 26, 5, 143, 119, 148, 62, 55, 76, 151, 14, 204, 221, 176, 16, 131, 26, 15, 210, 12, 238, 103, 163, 247, 179, 21, 208, 194, 8, 173, 36, 7, 198, 12, 200, 94, 132, 44, 218, 58, 17, 160, 114, 120, 22, 80, 64, 50, 221, 26, 38, 15, 139, 5, 24, 13, 118, 141, 34, 110, 223, 162, 219, 79, 124, 125, 9, 169, 49, 115, 74, 32, 53, 38, 172, 206, 132, 113, 208, 219, 51, 48, 45, 176, 124, 13, 171, 55, 97, 53, 39, 204, 205, 48, 18, 86, 64, 37, 150, 64, 106, 208, 156, 18, 72, 13, 170, 160, 0, 169, 65, 97, 101, 20, 122, 41, 148, 153, 15, 169, 65, 51, 75, 32, 53, 40, 166, 52, 164, 6, 69, 243, 183, 53, 151, 2, 164, 6, 69, 83, 12, 76, 111, 144, 116, 5, 171, 65, 113, 213, 160, 176, 208, 132, 169, 38, 181, 6, 133, 233, 67, 239, 107, 66, 13, 211, 70, 175, 65, 97, 18, 228, 214, 160, 214, 208, 160, 134, 153, 136, 94, 237, 225, 42, 235, 96, 53, 40, 174, 26, 84, 161, 134, 58, 53, 40, 204, 51, 132, 106, 208, 224, 124, 250, 212, 160, 10, 181, 180, 173, 65, 161, 178, 196, 214, 160, 193, 176, 53, 211, 192, 96, 4, 146, 193, 58, 68, 86, 159, 105, 104, 75, 99, 116, 96, 107, 99, 168, 93, 143, 14, 151, 186, 14, 102, 32, 122, 166, 226, 66, 43, 199, 97, 174, 25, 44, 117, 29, 76, 37, 108, 198, 14, 62, 92, 11, 53, 21, 62, 99, 7, 85, 136, 62, 107, 135, 62, 76, 12, 11, 9, 244, 57, 73, 216, 124, 41, 250, 124, 105, 42, 52, 19, 194, 194, 10, 181, 184, 133, 71, 138, 59, 108, 250, 20, 54, 125, 10, 179, 3, 189, 110, 65, 239, 141, 193, 234, 21, 244, 90, 37, 21, 42, 10, 155, 80, 133, 165, 117, 216, 132, 42, 166, 7, 32, 162, 176, 74, 8, 226, 216, 196, 100, 244, 180, 59, 210, 43, 31, 164, 84, 2, 150, 32, 181, 242, 129, 233, 129, 85, 62, 176, 226, 153, 214, 197, 51, 76, 21, 172, 120, 38, 183, 120, 134, 70, 31, 23, 122, 241, 140, 190, 137, 4, 54, 21, 81, 144, 3, 233, 221, 16, 42, 158, 83, 161, 37, 48, 172, 108, 133, 197, 31, 108, 249, 60, 250, 242, 121, 88, 89, 157, 147, 136, 127, 7, 29, 172, 146, 133, 29, 81, 128, 216, 150, 225, 95, 20, 92, 146, 153, 156, 93, 137, 90, 198, 107, 32, 78, 201, 183, 208, 4, 234, 128, 237, 183, 128, 233, 128, 29, 22, 2, 107, 129, 224, 76, 4, 80, 5, 56, 180, 42, 0, 1, 178, 135, 20, 96, 169, 1, 154, 30, 20, 16, 209, 28, 140, 148, 74, 16, 141, 96, 88, 34, 71, 210, 91, 11, 241, 30, 60, 227, 129, 11, 23, 216, 200, 37, 174, 34, 31, 226, 72, 132, 22, 216, 168, 37, 204, 131, 184, 220, 143, 195, 245, 192, 180, 140, 234, 114, 152, 171, 208, 43, 58, 108, 238, 243, 1, 154, 7, 155, 110, 193, 31, 242, 168, 150, 99, 49, 27, 110, 51, 122, 141, 9, 43, 126, 97, 197, 47, 172, 200, 132, 205, 182, 192, 106, 108, 212, 44, 99, 171, 128, 146, 93, 12, 224, 195, 173, 121, 154, 10, 218, 40, 22, 64, 157, 141, 225, 34, 122, 231, 99, 170, 230, 99, 55, 160, 236, 8, 207, 197, 176, 92, 140, 208, 10, 5, 80, 15, 193, 60, 10, 205, 7, 10, 208, 156, 160, 128, 158, 139, 137, 205, 197, 132, 90, 109, 232, 89, 88, 3, 170, 30, 214, 98, 131, 57, 17, 151, 227, 73, 205, 194, 214, 208, 96, 135, 181, 217, 20, 108, 33, 46, 132, 53, 238, 96, 82, 184, 26, 119, 48, 53, 176, 194, 9, 173, 81, 7, 147, 198, 40, 37, 128, 10, 193, 122, 208, 91, 118, 37, 25, 248, 99, 21, 205, 111, 56, 75, 8, 104, 88, 227, 44, 33, 96, 225, 15, 27, 7, 64, 31, 7, 208, 128, 134, 22, 172, 149, 6, 107, 161, 161, 181, 206, 138, 32, 58, 194, 18, 65, 253, 125, 80, 79, 31, 106, 51, 188, 168, 129, 229, 106, 106, 23, 53, 176, 224, 0, 71, 39, 166, 117, 214, 208, 80, 40, 130, 21, 53, 3, 93, 212, 4, 163, 117, 232, 144, 203, 26, 144, 40, 60, 28, 161, 29, 58, 180, 182, 45, 23, 172, 248, 25, 108, 197, 15, 174, 132, 58, 210, 139, 31, 98, 139, 31, 148, 50, 38, 53, 69, 97, 184, 22, 63, 48, 135, 160, 119, 85, 113, 45, 46, 69, 239, 166, 162, 117, 83, 225, 61, 60, 88, 23, 21, 87, 23, 21, 182, 116, 9, 230, 18, 88, 212, 163, 119, 77, 243, 52, 32, 254, 35, 182, 192, 75, 204, 41, 5, 119, 69, 113, 117, 67, 209, 187, 160, 180, 42, 25, 161, 81, 72, 176, 100, 132, 89, 135, 94, 50, 106, 112, 209, 182, 100, 68, 111, 132, 193, 155, 197, 104, 7, 200, 193, 142, 126, 201, 200, 132, 36, 3, 216, 168, 54, 236, 232, 23, 152, 183, 144, 142, 126, 41, 202, 47, 210, 48, 37, 116, 244, 11, 80, 22, 28, 244, 176, 52, 25, 172, 128, 152, 249, 7, 57, 1, 118, 244, 11, 56, 19, 21, 165, 150, 101, 230, 151, 22, 251, 32, 165, 112, 228, 204, 12, 81, 135, 84, 2, 123, 22, 71, 165, 22, 229, 131, 34, 16, 24, 219, 224, 178, 91, 3, 195, 12, 96, 132, 194, 11, 19, 69, 52, 157, 88, 114, 21, 162, 192, 130, 234, 129, 158, 35, 4, 59, 116, 5, 245, 208, 21, 5, 53, 53, 133, 96, 216, 48, 147, 141, 130, 65, 133, 121, 90, 90, 26, 196, 84, 104, 160, 66, 139, 47, 5, 88, 208, 163, 246, 152, 32, 78, 195, 231, 56, 76, 231, 161, 6, 19, 44, 92, 96, 229, 47, 76, 19, 216, 246, 180, 156, 68, 210, 218, 191, 10, 10, 16, 183, 64, 52, 170, 41, 104, 24, 32, 218, 187, 208, 36, 64, 188, 147, 192, 142, 130, 149, 189, 176, 28, 145, 7, 13, 18, 180, 108, 0, 15, 158, 34, 180, 243, 238, 130, 117, 80, 13, 135, 86, 14, 181, 176, 68, 77, 170, 86, 160, 31, 176, 198, 12, 218, 225, 1, 160, 228, 152, 92, 90, 84, 148, 154, 87, 2, 209, 11, 75, 141, 168, 169, 17, 156, 168, 16, 137, 15, 93, 7, 22, 7, 192, 66, 145, 96, 8, 34, 167, 65, 160, 91, 209, 43, 65, 164, 0, 213, 53, 68, 10, 76, 88, 8, 195, 106, 32, 164, 160, 66, 28, 157, 21, 92, 144, 147, 89, 226, 15, 78, 202, 176, 164, 172, 163, 224, 12, 54, 22, 150, 243, 209, 15, 207, 66, 179, 51, 45, 49, 167, 56, 21, 100, 45, 44, 95, 67, 212, 59, 151, 228, 23, 33, 206, 206, 42, 201, 204, 115, 70, 190, 62, 9, 162, 70, 9, 158, 29, 157, 21, 20, 109, 97, 225, 15, 210, 73, 156, 29, 224, 227, 184, 224, 241, 6, 210, 167, 87, 80, 148, 15, 62, 161, 11, 168, 26, 173, 96, 133, 31, 155, 53, 88, 206, 229, 66, 47, 141, 33, 113, 161, 81, 12, 61, 149, 43, 7, 104, 97, 9, 40, 28, 96, 101, 242, 64, 151, 201, 206, 10, 168, 55, 101, 65, 227, 18, 24, 28, 132, 98, 25, 110, 68, 62, 34, 24, 21, 108, 193, 14, 246, 44, 134, 251, 29, 75, 58, 132, 135, 173, 6, 56, 52, 192, 30, 129, 55, 64, 20, 106, 106, 160, 190, 128, 132, 21, 80, 22, 126, 5, 27, 56, 101, 33, 10, 62, 29, 160, 46, 240, 248, 44, 184, 145, 9, 14, 222, 98, 144, 133, 37, 169, 69, 176, 224, 68, 114, 26, 52, 48, 73, 45, 51, 129, 58, 208, 173, 65, 105, 179, 35, 38, 119, 32, 54, 194, 132, 65, 37, 42, 200, 74, 68, 97, 93, 140, 178, 30, 2, 54, 71, 136, 107, 142, 80, 19, 90, 194, 194, 189, 4, 205, 17, 176, 105, 60, 232, 52, 94, 49, 200, 80, 208, 186, 108, 168, 181, 117, 32, 123, 65, 122, 97, 21, 70, 42, 212, 13, 40, 6, 21, 85, 88, 195, 202, 109, 152, 42, 212, 192, 129, 167, 150, 34, 216, 209, 52, 184, 66, 130, 212, 83, 99, 96, 83, 42, 169, 229, 110, 32, 113, 68, 192, 17, 111, 80, 165, 18, 48, 103, 192, 124, 5, 51, 8, 182, 82, 4, 221, 235, 88, 21, 41, 104, 131, 76, 129, 133, 1, 90, 224, 36, 131, 195, 23, 118, 224, 127, 30, 188, 251, 174, 225, 172, 163, 224, 172, 3, 12, 59, 240, 33, 250, 176, 121, 82, 88, 46, 131, 157, 108, 9, 59, 231, 18, 210, 112, 3, 137, 25, 192, 133, 50, 115, 97, 233, 50, 39, 19, 61, 225, 195, 90, 222, 32, 85, 32, 77, 21, 105, 80, 96, 141, 26, 71, 48, 5, 16, 19, 236, 236, 236, 32, 230, 195, 28, 81, 0, 179, 16, 106, 139, 2, 124, 122, 29, 90, 240, 194, 142, 98, 132, 235, 40, 206, 172, 74, 69, 58, 140, 15, 166, 23, 36, 140, 172, 25, 150, 159, 208, 243, 19, 84, 34, 8, 86, 73, 67, 154, 63, 176, 224, 132, 52, 130, 64, 179, 212, 240, 225, 97, 40, 64, 61, 21, 82, 65, 161, 22, 45, 222, 208, 76, 118, 173, 72, 77, 70, 54, 21, 104, 36, 106, 143, 17, 151, 161, 48, 18, 125, 127, 6, 244, 64, 77, 3, 88, 131, 0, 123, 224, 20, 2, 67, 166, 0, 28, 127, 168, 229, 156, 95, 62, 172, 11, 164, 96, 139, 44, 174, 160, 166, 166, 160, 8, 118, 49, 250, 242, 229, 98, 20, 215, 91, 115, 193, 231, 105, 11, 21, 108, 64, 113, 0, 11, 79, 176, 77, 169, 58, 10, 85, 208, 156, 1, 11, 116, 116, 123, 17, 222, 46, 4, 151, 12, 184, 131, 191, 16, 108, 27, 204, 176, 66, 232, 80, 189, 66, 77, 13, 80, 167, 157, 45, 204, 110, 88, 24, 162, 77, 63, 113, 65, 151, 204, 40, 160, 219, 129, 62, 230, 14, 2, 85, 64, 85, 160, 40, 1, 241, 97, 113, 137, 238, 3, 132, 85, 85, 96, 51, 97, 131, 4, 4, 156, 93, 133, 62, 66, 128, 203, 173, 144, 240, 168, 210, 131, 117, 207, 225, 38, 144, 230, 217, 66, 5, 109, 133, 170, 104, 131, 88, 120, 174, 128, 249, 8, 150, 58, 97, 101, 6, 208, 185, 40, 237, 188, 66, 168, 105, 72, 222, 115, 173, 72, 77, 198, 136, 125, 92, 30, 131, 251, 1, 173, 172, 77, 199, 49, 249, 8, 10, 40, 5, 43, 133, 66, 216, 36, 35, 4, 36, 231, 231, 149, 100, 230, 129, 102, 38, 208, 189, 134, 24, 211, 130, 56, 9, 230, 126, 216, 168, 12, 76, 53, 196, 117, 169, 10, 32, 215, 21, 32, 156, 86, 72, 174, 195, 208, 157, 5, 179, 6, 71, 190, 132, 4, 59, 144, 17, 92, 154, 84, 12, 50, 22, 220, 67, 46, 0, 26, 170, 160, 11, 116, 15, 216, 161, 224, 1, 62, 144, 42, 208, 33, 178, 48, 23, 195, 203, 93, 91, 112, 25, 9, 119, 57, 60, 123, 35, 219, 93, 0, 244, 13, 212, 49, 144, 184, 80, 196, 136, 11, 80, 118, 132, 180, 62, 252, 211, 144, 242, 124, 49, 236, 220, 39, 148, 83, 168, 170, 128, 201, 5, 237, 0, 42, 152, 41, 224, 19, 176, 16, 33, 1, 205, 252, 153, 10, 54, 182, 168, 198, 35, 101, 109, 34, 66, 167, 42, 58, 51, 22, 98, 9, 36, 157, 107, 107, 195, 56, 232, 129, 3, 203, 7, 184, 2, 8, 61, 144, 96, 34, 176, 148, 83, 11, 13, 54, 88, 34, 40, 176, 230, 2, 115, 193, 102, 22, 160, 231, 45, 2, 145, 170, 4, 105, 10, 212, 42, 164, 230, 192, 242, 19, 33, 45, 232, 233, 0, 100, 27, 34, 41, 212, 114, 33, 220, 14, 233, 17, 193, 70, 68, 96, 45, 117, 88, 75, 221, 181, 34, 53, 25, 212, 6, 70, 12, 141, 160, 222, 160, 128, 54, 50, 18, 164, 169, 80, 83, 163, 0, 228, 195, 250, 75, 176, 123, 21, 96, 221, 37, 176, 165, 72, 173, 32, 216, 64, 151, 130, 130, 51, 80, 44, 40, 21, 49, 180, 224, 153, 22, 94, 148, 88, 80, 0, 221, 179, 0, 4, 65, 48, 6, 196, 57, 48, 158, 18, 86, 55, 43, 113, 65, 22, 89, 192, 42, 39, 92, 205, 122, 88, 64, 192, 188, 142, 124, 94, 125, 16, 48, 24, 209, 251, 214, 32, 53, 33, 169, 197, 37, 196, 134, 9, 234, 173, 18, 25, 69, 232, 29, 147, 32, 104, 121, 6, 235, 151, 160, 244, 75, 130, 52, 173, 73, 117, 63, 200, 225, 110, 249, 69, 32, 39, 98, 113, 191, 74, 16, 180, 159, 145, 154, 156, 153, 90, 172, 1, 116, 23, 92, 63, 212, 241, 232, 151, 110, 192, 110, 149, 128, 105, 2, 159, 157, 152, 90, 162, 16, 29, 12, 190, 202, 89, 175, 24, 34, 26, 171, 164, 105, 13, 182, 6, 222, 175, 134, 87, 84, 142, 57, 57, 192, 46, 13, 122, 151, 166, 26, 26, 76, 176, 164, 2, 235, 90, 195, 186, 113, 176, 180, 130, 214, 237, 45, 131, 117, 173, 137, 237, 90, 67, 173, 193, 232, 90, 19, 178, 3, 214, 79, 134, 117, 173, 169, 221, 181, 134, 42, 247, 4, 186, 25, 220, 181, 198, 213, 181, 46, 201, 71, 29, 182, 132, 165, 66, 68, 224, 106, 0, 125, 157, 153, 135, 148, 59, 139, 42, 128, 78, 70, 79, 138, 232, 161, 139, 158, 22, 97, 3, 151, 176, 196, 136, 158, 24, 97, 157, 100, 120, 8, 1, 109, 197, 150, 30, 169, 213, 77, 134, 245, 255, 96, 221, 24, 232, 60, 67, 145, 142, 2, 124, 148, 8, 236, 61, 216, 136, 36, 190, 212, 6, 243, 51, 49, 93, 74, 96, 151, 18, 165, 75, 169, 0, 237, 1, 33, 233, 241, 204, 43, 49, 54, 194, 170, 197, 8, 162, 5, 226, 86, 148, 158, 35, 124, 254, 7, 214, 160, 128, 205, 209, 195, 196, 33, 97, 171, 144, 10, 43, 224, 97, 142, 133, 45, 98, 132, 57, 4, 22, 230, 232, 157, 77, 36, 91, 137, 234, 146, 97, 104, 132, 182, 107, 8, 57, 18, 238, 16, 232, 208, 133, 2, 180, 39, 10, 179, 1, 214, 19, 69, 239, 137, 194, 14, 93, 85, 176, 7, 31, 161, 173, 96, 165, 96, 160, 169, 80, 67, 186, 17, 165, 80, 35, 12, 13, 192, 70, 88, 99, 132, 174, 174, 17, 56, 36, 97, 185, 19, 118, 91, 51, 36, 137, 64, 140, 245, 44, 73, 45, 74, 44, 201, 47, 210, 128, 167, 41, 96, 104, 233, 160, 38, 56, 88, 58, 67, 31, 94, 197, 103, 92, 81, 106, 122, 106, 69, 129, 14, 180, 126, 194, 110, 32, 108, 208, 21, 58, 213, 6, 39, 96, 51, 111, 69, 10, 153, 96, 227, 192, 133, 155, 95, 106, 57, 54, 139, 192, 199, 6, 64, 211, 99, 112, 106, 9, 74, 50, 132, 233, 6, 119, 213, 32, 14, 34, 74, 181, 33, 204, 217, 68, 169, 54, 130, 121, 142, 40, 213, 198, 208, 32, 80, 168, 81, 48, 192, 163, 1, 28, 149, 48, 93, 144, 218, 221, 68, 7, 53, 126, 129, 60, 77, 68, 193, 11, 87, 140, 20, 65, 176, 202, 7, 61, 204, 252, 82, 43, 74, 64, 5, 3, 172, 96, 0, 198, 1, 56, 188, 209, 139, 122, 68, 233, 4, 22, 41, 169, 44, 72, 5, 151, 77, 176, 218, 4, 102, 53, 174, 50, 159, 80, 153, 15, 19, 67, 31, 28, 69, 107, 190, 112, 193, 202, 124, 152, 175, 112, 249, 9, 201, 35, 249, 73, 89, 10, 182, 56, 10, 126, 160, 156, 166, 66, 77, 141, 130, 6, 68, 145, 123, 105, 98, 81, 74, 72, 62, 54, 67, 193, 74, 53, 21, 96, 21, 1, 172, 162, 132, 122, 59, 25, 150, 81, 129, 110, 2, 7, 1, 172, 225, 134, 197, 36, 112, 51, 14, 189, 25, 167, 0, 118, 160, 14, 23, 172, 237, 134, 195, 91, 74, 232, 205, 183, 34, 196, 4, 69, 53, 144, 155, 83, 154, 106, 133, 24, 11, 210, 81, 72, 201, 207, 75, 181, 130, 84, 227, 10, 181, 32, 93, 64, 29, 224, 100, 3, 43, 22, 96, 165, 55, 44, 69, 35, 146, 28, 40, 220, 160, 169, 13, 20, 234, 176, 176, 131, 107, 70, 93, 171, 7, 155, 76, 0, 89, 8, 10, 237, 162, 82, 72, 135, 8, 22, 64, 176, 217, 28, 184, 187, 161, 153, 16, 217, 9, 144, 56, 65, 173, 65, 48, 28, 99, 0, 113, 12, 196, 140, 226, 18, 80, 0, 33, 155, 17, 12, 173, 184, 240, 154, 97, 136, 100, 6, 145, 245, 24, 154, 9, 198, 48, 19, 16, 75, 49, 80, 151, 96, 192, 238, 67, 64, 95, 209, 143, 174, 10, 58, 232, 139, 26, 178, 118, 136, 225, 50, 5, 107, 72, 48, 194, 106, 126, 88, 53, 77, 200, 183, 48, 215, 66, 153, 70, 176, 116, 3, 235, 190, 65, 197, 61, 139, 113, 164, 52, 180, 66, 65, 77, 13, 170, 129, 144, 213, 176, 178, 222, 16, 146, 85, 160, 78, 198, 212, 142, 163, 177, 0, 213, 109, 164, 9, 210, 13, 142, 26, 180, 141, 40, 184, 214, 190, 192, 60, 4, 171, 133, 97, 22, 42, 160, 206, 77, 66, 69, 193, 1, 1, 14, 10, 216, 185, 220, 8, 227, 32, 86, 65, 0, 34, 74, 160, 195, 161, 10, 176, 206, 43, 212, 37, 224, 53, 31, 10, 182, 88, 52, 216, 216, 66, 83, 39, 180, 47, 15, 85, 2, 2, 246, 192, 178, 13, 49, 94, 133, 90, 63, 230, 165, 67, 42, 68, 180, 101, 224, 10, 10, 86, 10, 224, 33, 49, 152, 187, 97, 11, 208, 209, 11, 36, 88, 40, 227, 170, 71, 20, 20, 80, 83, 134, 2, 180, 58, 65, 112, 116, 13, 65, 28, 88, 48, 193, 152, 184, 178, 55, 16, 128, 179, 120, 81, 30, 84, 9, 90, 40, 33, 214, 168, 160, 184, 16, 30, 118, 168, 235, 101, 162, 13, 96, 35, 101, 48, 99, 80, 227, 0, 172, 8, 50, 38, 7, 93, 13, 3, 91, 13, 3, 83, 142, 107, 105, 62, 204, 106, 116, 19, 145, 178, 38, 88, 5, 12, 96, 27, 140, 2, 53, 230, 113, 69, 16, 108, 173, 62, 204, 100, 216, 104, 21, 44, 44, 40, 141, 25, 244, 234, 30, 45, 130, 106, 97, 45, 100, 74, 45, 194, 149, 4, 96, 126, 128, 37, 4, 112, 85, 3, 141, 17, 112, 232, 67, 19, 2, 172, 172, 207, 129, 38, 132, 90, 46, 136, 4, 180, 172, 15, 74, 77, 119, 173, 40, 112, 206, 207, 67, 159, 122, 130, 181, 188, 97, 149, 6, 72, 189, 30, 82, 68, 33, 60, 15, 81, 129, 221, 127, 64, 79, 65, 27, 120, 233, 208, 6, 30, 161, 160, 128, 5, 3, 114, 16, 232, 34, 149, 150, 181, 92, 72, 137, 21, 232, 12, 196, 80, 44, 106, 182, 77, 135, 22, 227, 176, 108, 137, 158, 45, 73, 117, 4, 44, 14, 96, 1, 2, 9, 245, 148, 124, 88, 246, 75, 133, 138, 163, 135, 120, 45, 212, 21, 168, 89, 14, 238, 131, 96, 88, 239, 20, 236, 102, 136, 91, 163, 13, 98, 129, 182, 160, 228, 29, 160, 50, 104, 62, 68, 207, 63, 64, 147, 192, 45, 21, 88, 180, 192, 251, 67, 232, 81, 6, 53, 18, 162, 35, 47, 181, 2, 71, 142, 35, 148, 219, 210, 117, 32, 214, 161, 230, 54, 43, 5, 152, 32, 124, 87, 12, 142, 100, 3, 179, 25, 154, 108, 106, 209, 123, 147, 228, 198, 11, 44, 113, 192, 98, 6, 61, 63, 160, 199, 12, 122, 67, 220, 181, 162, 64, 35, 17, 122, 243, 47, 56, 116, 209, 26, 166, 112, 57, 104, 208, 195, 204, 67, 31, 245, 65, 234, 221, 194, 180, 68, 35, 218, 234, 193, 149, 185, 73, 249, 57, 26, 74, 96, 69, 74, 154, 177, 214, 92, 176, 72, 134, 104, 82, 180, 69, 95, 179, 135, 176, 73, 81, 17, 170, 10, 108, 27, 204, 71, 32, 231, 7, 228, 23, 23, 103, 38, 229, 84, 66, 27, 176, 96, 223, 192, 198, 169, 96, 142, 64, 109, 165, 67, 162, 21, 220, 192, 247, 72, 44, 246, 203, 7, 215, 124, 72, 77, 116, 136, 102, 144, 60, 172, 175, 129, 222, 215, 80, 130, 40, 81, 210, 180, 134, 104, 129, 25, 137, 79, 11, 68, 9, 68, 11, 56, 116, 33, 102, 0, 93, 128, 80, 132, 100, 140, 14, 178, 51, 112, 133, 59, 114, 72, 40, 106, 224, 12, 105, 133, 76, 20, 79, 35, 66, 3, 210, 19, 131, 72, 129, 67, 1, 181, 157, 85, 13, 245, 93, 208, 96, 235, 124, 129, 58, 95, 88, 116, 68, 227, 12, 129, 88, 168, 57, 240, 134, 14, 106, 215, 45, 63, 15, 50, 210, 230, 153, 151, 156, 159, 91, 144, 88, 146, 9, 116, 30, 164, 99, 164, 145, 151, 152, 155, 170, 3, 46, 100, 202, 64, 1, 130, 186, 110, 5, 56, 60, 108, 172, 163, 0, 139, 90, 29, 5, 176, 98, 68, 129, 6, 209, 133, 37, 241, 165, 199, 131, 221, 5, 45, 166, 52, 21, 96, 57, 206, 179, 216, 175, 52, 39, 199, 191, 40, 20, 150, 11, 192, 70, 192, 99, 63, 4, 135, 27, 161, 190, 212, 81, 0, 169, 6, 69, 1, 60, 63, 102, 22, 7, 36, 150, 148, 164, 22, 229, 65, 172, 5, 198, 30, 40, 252, 242, 211, 160, 117, 26, 56, 84, 148, 138, 33, 206, 7, 234, 67, 52, 198, 21, 53, 208, 181, 170, 169, 33, 210, 16, 106, 198, 209, 84, 128, 70, 133, 34, 134, 251, 97, 62, 4, 74, 131, 60, 1, 43, 253, 17, 197, 4, 48, 198, 192, 158, 128, 169, 212, 1, 39, 47, 44, 113, 8, 30, 115, 132, 85, 11, 48, 253, 88, 74, 12, 164, 50, 35, 57, 17, 118, 50, 83, 9, 172, 55, 12, 211, 169, 3, 13, 0, 104, 144, 193, 138, 99, 88, 192, 161, 13, 227, 151, 192, 212, 0, 237, 198, 22, 46, 56, 179, 16, 44, 230, 96, 93, 187, 146, 32, 88, 247, 216, 13, 200, 65, 210, 164, 17, 12, 115, 17, 146, 47, 17, 26, 8, 120, 52, 13, 174, 16, 205, 35, 176, 113, 102, 72, 194, 119, 46, 74, 77, 44, 73, 5, 5, 52, 204, 30, 144, 45, 248, 28, 143, 92, 232, 128, 12, 129, 117, 19, 208, 215, 130, 194, 138, 33, 28, 129, 14, 143, 100, 216, 208, 50, 142, 8, 6, 134, 65, 5, 210, 108, 72, 114, 9, 122, 134, 113, 204, 201, 161, 106, 158, 1, 25, 136, 156, 109, 106, 161, 102, 194, 18, 50, 220, 80, 104, 66, 46, 128, 26, 11, 179, 25, 18, 36, 8, 57, 88, 188, 192, 122, 242, 192, 197, 234, 208, 104, 213, 3, 115, 173, 161, 242, 216, 221, 13, 140, 239, 116, 168, 195, 161, 0, 173, 172, 49, 52, 52, 132, 36, 85, 88, 11, 88, 1, 234, 92, 216, 128, 15, 174, 193, 93, 29, 120, 90, 134, 90, 2, 189, 59, 25, 159, 85, 70, 64, 53, 240, 48, 66, 179, 182, 150, 11, 226, 75, 82, 115, 50, 204, 60, 88, 102, 166, 83, 102, 46, 46, 129, 14, 204, 192, 67, 1, 170, 16, 87, 22, 129, 153, 167, 148, 14, 241, 57, 46, 55, 192, 134, 215, 96, 126, 199, 149, 192, 145, 252, 13, 110, 185, 65, 247, 243, 40, 64, 93, 198, 133, 94, 25, 65, 163, 175, 32, 49, 5, 232, 199, 10, 72, 155, 86, 71, 33, 45, 51, 39, 7, 34, 163, 163, 0, 148, 114, 205, 75, 1, 133, 18, 40, 16, 209, 83, 19, 177, 185, 64, 3, 98, 140, 130, 189, 130, 18, 132, 165, 164, 96, 5, 102, 6, 151, 36, 22, 149, 32, 114, 6, 114, 80, 130, 226, 26, 123, 56, 102, 230, 149, 248, 194, 92, 139, 212, 24, 71, 120, 1, 174, 18, 104, 10, 80, 4, 188, 226, 0, 214, 180, 135, 21, 71, 40, 134, 216, 216, 66, 149, 66, 253, 1, 139, 8, 160, 32, 196, 81, 208, 17, 41, 160, 153, 224, 208, 73, 69, 113, 28, 34, 188, 96, 221, 33, 13, 168, 34, 216, 45, 101, 184, 12, 197, 112, 136, 157, 130, 134, 134, 161, 130, 141, 141, 130, 177, 129, 166, 130, 174, 130, 17, 106, 192, 6, 37, 230, 165, 195, 243, 141, 1, 82, 120, 65, 92, 5, 246, 42, 106, 232, 232, 66, 253, 5, 115, 124, 73, 17, 48, 234, 19, 75, 82, 83, 32, 238, 117, 131, 249, 5, 154, 177, 17, 73, 13, 150, 52, 138, 82, 11, 82, 19, 75, 192, 137, 8, 234, 115, 8, 91, 3, 102, 161, 62, 68, 24, 22, 188, 154, 10, 53, 136, 193, 74, 236, 182, 105, 219, 42, 192, 215, 35, 64, 3, 10, 212, 125, 133, 123, 65, 21, 97, 34, 44, 50, 193, 1, 85, 144, 152, 226, 154, 151, 2, 14, 83, 160, 193, 169, 152, 161, 170, 160, 141, 221, 70, 107, 46, 228, 154, 3, 151, 171, 64, 38, 192, 166, 14, 208, 50, 71, 124, 113, 73, 98, 81, 9, 34, 125, 233, 192, 178, 8, 164, 169, 163, 164, 0, 141, 226, 34, 244, 245, 12, 192, 192, 68, 152, 2, 73, 229, 58, 10, 88, 141, 209, 1, 183, 181, 83, 113, 100, 207, 148, 248, 212, 60, 80, 22, 165, 161, 253, 224, 48, 69, 183, 30, 181, 25, 22, 148, 90, 144, 147, 152, 12, 154, 45, 129, 245, 96, 208, 123, 48, 232, 13, 118, 114, 123, 48, 69, 153, 144, 30, 140, 130, 2, 164, 7, 147, 148, 5, 233, 193, 192, 20, 17, 234, 193, 192, 146, 5, 172, 7, 3, 205, 110, 208, 240, 81, 212, 64, 47, 57, 53, 148, 32, 27, 153, 82, 9, 244, 97, 96, 233, 22, 60, 195, 13, 12, 190, 162, 252, 92, 29, 5, 72, 185, 2, 182, 23, 88, 74, 160, 16, 80, 11, 225, 218, 188, 83, 139, 242, 82, 115, 32, 25, 12, 100, 2, 148, 1, 95, 13, 85, 161, 1, 49, 210, 0, 156, 141, 176, 72, 231, 64, 35, 206, 0, 146, 207, 112, 148, 231, 69, 176, 219, 172, 193, 203, 13, 195, 18, 115, 74, 83, 117, 80, 54, 113, 2, 29, 11, 13, 91, 207, 98, 191, 210, 156, 28, 82, 203, 115, 120, 120, 161, 21, 221, 200, 237, 122, 104, 7, 0, 201, 13, 10, 182, 72, 189, 0, 108, 237, 252, 32, 88, 2, 211, 4, 202, 130, 140, 129, 181, 244, 145, 220, 135, 236, 41, 77, 180, 230, 62, 212, 139, 69, 10, 182, 10, 192, 24, 6, 59, 21, 69, 189, 14, 122, 149, 137, 136, 120, 148, 150, 2, 220, 28, 82, 155, 10, 121, 112, 173, 58, 200, 30, 215, 129, 230, 60, 228, 40, 128, 90, 87, 11, 14, 56, 88, 109, 133, 214, 124, 208, 64, 174, 246, 160, 6, 130, 101, 144, 21, 33, 123, 16, 150, 101, 96, 129, 15, 179, 16, 35, 244, 161, 126, 129, 249, 4, 98, 18, 56, 248, 97, 163, 81, 26, 16, 149, 16, 127, 192, 172, 69, 247, 2, 44, 214, 33, 77, 89, 231, 68, 216, 101, 227, 72, 138, 192, 73, 137, 12, 171, 144, 154, 146, 200, 198, 65, 162, 9, 22, 98, 5, 249, 197, 40, 149, 23, 122, 171, 52, 37, 181, 194, 63, 13, 104, 46, 186, 249, 176, 170, 26, 228, 112, 144, 25, 176, 73, 61, 152, 75, 97, 53, 10, 80, 29, 178, 117, 160, 244, 133, 50, 150, 152, 14, 73, 236, 201, 176, 132, 144, 7, 77, 8, 249, 240, 132, 0, 137, 127, 68, 34, 66, 243, 36, 200, 7, 48, 247, 105, 2, 205, 130, 71, 118, 73, 98, 102, 78, 0, 200, 101, 96, 63, 106, 163, 232, 210, 203, 129, 181, 100, 160, 195, 140, 229, 193, 80, 167, 162, 250, 8, 62, 128, 9, 87, 1, 170, 44, 148, 128, 202, 96, 163, 129, 232, 210, 176, 154, 25, 57, 82, 12, 192, 142, 132, 6, 59, 178, 98, 109, 91, 5, 104, 128, 88, 195, 18, 48, 88, 2, 88, 185, 128, 27, 102, 64, 46, 154, 107, 65, 142, 131, 121, 204, 6, 69, 53, 134, 75, 81, 91, 9, 48, 183, 64, 53, 195, 66, 204, 7, 214, 200, 129, 138, 195, 29, 9, 141, 65, 184, 105, 184, 10, 73, 96, 4, 57, 230, 228, 32, 114, 80, 105, 42, 106, 10, 167, 86, 57, 153, 138, 214, 255, 131, 101, 26, 88, 241, 134, 163, 120, 211, 132, 154, 158, 137, 212, 9, 196, 170, 64, 65, 1, 185, 39, 88, 156, 10, 87, 161, 7, 22, 3, 89, 9, 54, 7, 221, 35, 232, 221, 65, 88, 31, 13, 189, 143, 70, 237, 238, 32, 46, 171, 160, 221, 65, 68, 160, 65, 59, 132, 48, 139, 161, 36, 208, 179, 144, 104, 130, 149, 245, 195, 173, 172, 135, 101, 119, 116, 69, 232, 101, 61, 44, 17, 57, 39, 162, 150, 188, 176, 212, 1, 43, 207, 96, 37, 47, 172, 228, 5, 135, 45, 144, 15, 203, 91, 232, 133, 35, 161, 194, 23, 201, 141, 224, 252, 155, 1, 77, 117, 56, 74, 168, 68, 200, 52, 135, 83, 37, 250, 218, 111, 67, 168, 181, 80, 83, 52, 97, 26, 82, 243, 82, 252, 211, 124, 18, 139, 75, 124, 33, 51, 205, 10, 6, 48, 153, 34, 240, 56, 21, 172, 28, 67, 63, 93, 192, 0, 186, 53, 4, 118, 132, 31, 44, 4, 96, 179, 49, 176, 205, 223, 176, 30, 15, 44, 38, 161, 113, 93, 12, 75, 194, 136, 186, 3, 42, 3, 13, 36, 24, 15, 230, 85, 184, 24, 98, 35, 62, 152, 139, 148, 190, 80, 172, 181, 129, 43, 131, 184, 12, 109, 23, 69, 45, 108, 75, 63, 204, 145, 48, 205, 176, 179, 11, 96, 97, 80, 0, 61, 8, 165, 4, 154, 54, 96, 85, 17, 174, 202, 8, 42, 165, 0, 211, 10, 142, 77, 160, 203, 97, 103, 196, 195, 146, 61, 76, 8, 221, 139, 48, 81, 152, 211, 96, 34, 176, 128, 225, 130, 158, 18, 15, 243, 60, 204, 165, 16, 217, 224, 156, 204, 228, 84, 5, 228, 242, 28, 91, 168, 162, 69, 58, 74, 184, 130, 15, 180, 67, 83, 128, 108, 23, 52, 85, 104, 195, 234, 28, 176, 141, 152, 199, 19, 40, 160, 39, 44, 91, 132, 241, 218, 32, 47, 195, 82, 98, 134, 53, 106, 76, 104, 219, 34, 210, 48, 72, 10, 86, 126, 163, 25, 103, 3, 181, 94, 15, 82, 229, 193, 226, 24, 225, 58, 244, 26, 77, 7, 205, 65, 176, 213, 16, 80, 3, 20, 208, 253, 172, 137, 86, 193, 161, 207, 179, 161, 119, 218, 128, 109, 106, 240, 121, 6, 232, 179, 78, 131, 173, 207, 6, 11, 40, 136, 175, 210, 18, 137, 235, 179, 129, 34, 12, 101, 218, 41, 29, 189, 203, 134, 52, 237, 4, 14, 7, 212, 113, 103, 120, 144, 4, 193, 166, 118, 112, 249, 111, 160, 231, 157, 96, 243, 78, 56, 195, 0, 58, 241, 132, 188, 203, 12, 212, 57, 68, 79, 25, 160, 118, 15, 72, 7, 250, 148, 16, 48, 194, 60, 139, 253, 74, 115, 96, 237, 2, 244, 6, 142, 2, 90, 3, 7, 214, 17, 76, 129, 57, 0, 173, 113, 131, 107, 78, 136, 90, 115, 66, 176, 116, 141, 62, 41, 132, 230, 3, 168, 31, 17, 189, 68, 120, 189, 69, 228, 88, 50, 44, 132, 209, 166, 133, 224, 38, 160, 247, 15, 113, 181, 25, 96, 37, 113, 30, 84, 43, 250, 88, 50, 212, 236, 90, 164, 208, 3, 7, 12, 172, 129, 80, 132, 210, 64, 200, 76, 131, 205, 14, 161, 207, 14, 149, 20, 65, 82, 122, 17, 116, 122, 40, 179, 10, 146, 210, 97, 78, 195, 53, 61, 4, 215, 5, 45, 151, 96, 174, 131, 249, 25, 125, 146, 200, 86, 65, 215, 8, 217, 187, 232, 179, 67, 232, 190, 193, 53, 244, 93, 0, 205, 79, 184, 130, 139, 208, 168, 55, 90, 12, 233, 224, 26, 243, 70, 207, 6, 40, 9, 169, 32, 39, 179, 4, 169, 48, 240, 79, 202, 74, 29, 38, 229, 35, 200, 103, 120, 139, 71, 68, 161, 0, 14, 132, 226, 212, 130, 68, 200, 122, 107, 133, 28, 240, 81, 11, 148, 150, 14, 80, 39, 192, 199, 247, 129, 78, 134, 26, 8, 41, 10, 192, 226, 72, 5, 65, 186, 18, 196, 68, 176, 26, 164, 240, 64, 138, 41, 88, 98, 6, 43, 66, 24, 4, 119, 58, 86, 211, 96, 138, 97, 59, 199, 97, 185, 22, 150, 107, 97, 0, 22, 154, 16, 155, 193, 246, 129, 153, 144, 214, 185, 142, 2, 220, 22, 104, 198, 128, 101, 90, 24, 13, 75, 244, 176, 194, 12, 54, 16, 134, 203, 133, 176, 97, 48, 28, 254, 84, 195, 85, 178, 33, 98, 10, 82, 184, 193, 11, 55, 232, 182, 90, 112, 225, 230, 158, 90, 2, 27, 2, 131, 169, 70, 207, 61, 240, 84, 130, 90, 188, 193, 204, 32, 185, 120, 131, 107, 69, 10, 42, 72, 228, 67, 83, 20, 212, 22, 88, 40, 193, 102, 192, 97, 101, 28, 172, 140, 131, 200, 4, 193, 10, 59, 112, 180, 97, 115, 13, 236, 104, 0, 216, 158, 126, 216, 158, 126, 176, 84, 16, 146, 193, 208, 32, 128, 197, 28, 204, 88, 216, 14, 127, 116, 175, 69, 199, 66, 221, 9, 83, 11, 213, 15, 139, 61, 220, 129, 18, 29, 140, 172, 21, 87, 122, 74, 135, 30, 184, 170, 163, 16, 4, 14, 24, 88, 214, 192, 229, 102, 88, 64, 16, 112, 69, 17, 220, 13, 104, 165, 3, 134, 253, 96, 171, 129, 198, 214, 66, 74, 130, 204, 124, 152, 154, 248, 98, 164, 38, 106, 98, 81, 137, 142, 66, 106, 94, 138, 38, 172, 28, 192, 85, 14, 192, 28, 0, 43, 7, 208, 203, 1, 37, 184, 169, 168, 13, 5, 88, 85, 87, 4, 245, 54, 172, 158, 67, 164, 129, 28, 44, 211, 119, 101, 137, 224, 57, 192, 96, 160, 251, 32, 29, 32, 207, 188, 146, 212, 244, 212, 34, 176, 139, 193, 73, 12, 166, 4, 60, 95, 4, 242, 1, 106, 120, 41, 216, 131, 205, 181, 66, 210, 10, 84, 3, 215, 8, 84, 147, 152, 3, 54, 29, 165, 191, 154, 153, 167, 129, 210, 121, 133, 57, 65, 71, 193, 64, 83, 7, 100, 32, 170, 1, 32, 187, 9, 104, 7, 58, 15, 139, 230, 162, 252, 92, 116, 141, 8, 23, 233, 64, 13, 71, 114, 110, 73, 62, 92, 57, 108, 18, 1, 151, 114, 88, 114, 64, 155, 143, 40, 134, 77, 102, 128, 103, 29, 20, 52, 74, 242, 21, 116, 193, 124, 77, 232, 38, 29, 240, 62, 80, 207, 98, 207, 188, 28, 160, 105, 192, 104, 245, 73, 44, 74, 79, 133, 103, 122, 244, 148, 163, 105, 141, 35, 85, 65, 34, 8, 232, 93, 88, 247, 8, 150, 170, 40, 74, 85, 36, 36, 41, 88, 210, 33, 148, 116, 138, 51, 171, 82, 177, 37, 59, 72, 82, 130, 186, 31, 35, 77, 129, 116, 161, 36, 170, 28, 216, 168, 6, 216, 155, 192, 24, 135, 90, 108, 3, 47, 114, 160, 142, 65, 75, 105, 137, 136, 196, 165, 160, 13, 54, 22, 186, 0, 6, 54, 110, 139, 75, 47, 56, 149, 2, 245, 194, 18, 38, 72, 43, 114, 184, 64, 59, 140, 62, 80, 247, 195, 181, 97, 166, 206, 84, 72, 210, 132, 109, 21, 135, 219, 165, 137, 50, 183, 5, 74, 75, 160, 56, 64, 79, 75, 112, 151, 213, 40, 24, 232, 160, 88, 10, 73, 80, 176, 4, 229, 9, 77, 80, 184, 18, 20, 200, 104, 44, 169, 41, 57, 63, 47, 57, 17, 188, 234, 210, 16, 18, 142, 228, 38, 34, 80, 34, 2, 27, 134, 214, 70, 129, 149, 75, 176, 68, 132, 154, 136, 64, 113, 233, 8, 93, 241, 89, 12, 241, 150, 134, 38, 74, 77, 2, 11, 28, 160, 9, 96, 3, 241, 106, 2, 250, 1, 93, 147, 130, 54, 194, 90, 247, 212, 18, 152, 62, 13, 3, 77, 136, 3, 241, 154, 103, 68, 146, 121, 184, 164, 12, 65, 86, 161, 39, 28, 5, 91, 152, 151, 210, 242, 139, 20, 52, 128, 18, 224, 131, 25, 12, 172, 129, 148, 141, 2, 134, 115, 172, 21, 50, 181, 181, 65, 174, 129, 141, 193, 229, 165, 86, 148, 64, 236, 130, 4, 44, 166, 181, 153, 96, 107, 145, 6, 77, 192, 131, 96, 80, 77, 48, 7, 21, 193, 70, 63, 208, 71, 63, 96, 9, 164, 56, 39, 51, 57, 21, 152, 167, 97, 21, 24, 185, 169, 4, 86, 212, 104, 40, 129, 77, 84, 66, 175, 188, 112, 37, 18, 90, 85, 94, 184, 42, 47, 88, 109, 0, 175, 62, 80, 203, 7, 27, 208, 84, 49, 24, 216, 67, 178, 60, 44, 151, 131, 12, 210, 134, 171, 211, 81, 48, 128, 45, 54, 183, 130, 168, 131, 21, 13, 48, 21, 176, 154, 74, 1, 90, 241, 192, 44, 2, 59, 22, 100, 13, 14, 11, 96, 85, 157, 38, 154, 193, 176, 74, 16, 197, 216, 226, 130, 196, 60, 104, 217, 4, 51, 7, 86, 35, 229, 231, 66, 10, 66, 92, 165, 15, 172, 38, 131, 213, 100, 32, 163, 64, 44, 98, 75, 28, 112, 44, 99, 41, 112, 32, 171, 96, 52, 146, 243, 75, 243, 74, 64, 73, 133, 220, 180, 4, 159, 19, 74, 197, 94, 226, 4, 227, 72, 74, 69, 10, 121, 40, 105, 5, 228, 16, 80, 90, 129, 184, 35, 79, 1, 24, 242, 40, 182, 194, 22, 10, 229, 23, 105, 24, 130, 78, 52, 67, 42, 51, 20, 129, 202, 181, 20, 130, 161, 41, 82, 193, 198, 22, 180, 226, 8, 121, 197, 17, 178, 251, 97, 38, 193, 150, 28, 193, 77, 178, 134, 85, 3, 96, 135, 229, 41, 168, 41, 104, 160, 25, 163, 160, 13, 220, 51, 15, 115, 125, 8, 124, 192, 62, 45, 191, 72, 65, 195, 218, 26, 106, 7, 212, 249, 106, 10, 134, 16, 1, 176, 181, 10, 218, 182, 10, 193, 144, 66, 0, 100, 21, 200, 10, 59, 59, 91, 5, 67, 160, 16, 76, 7, 66, 117, 48, 178, 106, 120, 229, 168, 0, 29, 88, 79, 132, 14, 172, 215, 162, 22, 28, 33, 232, 101, 6, 40, 142, 51, 97, 91, 94, 73, 136, 96, 148, 185, 43, 160, 24, 242, 158, 9, 196, 114, 109, 56, 31, 220, 227, 210, 131, 89, 4, 151, 64, 137, 113, 200, 24, 58, 52, 160, 9, 165, 10, 152, 81, 64, 5, 126, 169, 229, 193, 37, 176, 237, 140, 232, 251, 194, 209, 119, 122, 32, 237, 11, 7, 175, 131, 37, 66, 161, 33, 40, 231, 193, 114, 30, 250, 110, 107, 88, 80, 162, 186, 192, 47, 181, 162, 4, 18, 154, 96, 199, 230, 39, 101, 193, 118, 36, 195, 210, 34, 108, 71, 178, 6, 80, 78, 83, 161, 166, 6, 109, 71, 114, 48, 204, 56, 216, 94, 100, 244, 189, 200, 72, 181, 92, 114, 98, 78, 142, 27, 44, 59, 67, 3, 22, 180, 23, 25, 197, 12, 212, 93, 200, 169, 41, 232, 187, 144, 97, 209, 134, 230, 9, 248, 254, 99, 212, 56, 9, 205, 67, 223, 21, 154, 11, 13, 60, 248, 190, 44, 104, 160, 65, 139, 244, 148, 212, 10, 136, 54, 216, 110, 80, 244, 221, 160, 48, 93, 176, 172, 3, 111, 138, 66, 51, 108, 73, 6, 68, 24, 86, 31, 19, 187, 255, 25, 20, 216, 16, 235, 237, 192, 71, 13, 165, 66, 3, 15, 106, 140, 30, 250, 254, 101, 244, 26, 22, 225, 239, 228, 252, 148, 212, 128, 252, 204, 188, 18, 148, 41, 52, 216, 186, 11, 88, 243, 12, 170, 198, 177, 68, 71, 33, 88, 7, 226, 113, 184, 135, 146, 51, 18, 139, 156, 243, 75, 193, 38, 24, 42, 104, 43, 104, 32, 140, 180, 131, 158, 220, 167, 9, 75, 144, 176, 4, 137, 30, 58, 58, 208, 192, 212, 134, 154, 6, 43, 13, 209, 182, 37, 225, 114, 96, 26, 48, 204, 157, 97, 182, 234, 128, 83, 147, 14, 204, 103, 96, 147, 208, 3, 128, 80, 237, 1, 75, 99, 176, 20, 83, 130, 86, 135, 128, 235, 150, 146, 196, 146, 204, 228, 248, 162, 196, 114, 240, 1, 23, 193, 153, 37, 169, 10, 176, 204, 1, 10, 215, 252, 236, 212, 20, 216, 89, 225, 192, 44, 1, 87, 4, 15, 56, 160, 78, 100, 121, 136, 14, 61, 160, 40, 92, 69, 14, 56, 83, 230, 4, 167, 166, 131, 155, 97, 96, 213, 224, 182, 88, 134, 6, 80, 25, 48, 5, 193, 186, 35, 224, 4, 129, 161, 26, 209, 128, 133, 251, 95, 73, 9, 28, 249, 184, 116, 192, 90, 175, 72, 58, 66, 242, 33, 254, 5, 217, 24, 109, 16, 171, 137, 156, 120, 138, 64, 161, 9, 206, 45, 208, 6, 32, 186, 82, 88, 187, 18, 109, 243, 156, 161, 53, 18, 215, 6, 221, 155, 72, 146, 218, 218, 16, 215, 64, 156, 139, 208, 3, 107, 155, 34, 218, 166, 208, 66, 28, 154, 7, 16, 174, 210, 6, 59, 11, 214, 46, 133, 183, 75, 17, 102, 129, 219, 167, 10, 16, 63, 41, 224, 210, 11, 241, 18, 92, 15, 60, 20, 96, 129, 132, 172, 13, 148, 184, 208, 211, 74, 82, 102, 58, 73, 213, 16, 246, 118, 6, 208, 20, 104, 35, 3, 221, 126, 37, 27, 160, 156, 157, 146, 130, 54, 212, 193, 176, 122, 5, 40, 160, 100, 163, 15, 150, 195, 234, 172, 156, 204, 188, 108, 106, 56, 12, 100, 14, 110, 167, 129, 100, 113, 58, 14, 44, 139, 195, 121, 249, 57, 41, 212, 112, 29, 208, 24, 220, 142, 195, 237, 48, 236, 142, 74, 203, 172, 72, 77, 161, 130, 171, 192, 230, 224, 116, 86, 73, 9, 78, 119, 129, 164, 208, 29, 6, 105, 239, 36, 230, 100, 38, 23, 83, 193, 105, 80, 147, 112, 58, 46, 19, 167, 219, 50, 177, 59, 173, 56, 55, 49, 39, 135, 10, 14, 3, 155, 131, 211, 89, 96, 89, 156, 78, 3, 203, 226, 112, 94, 73, 81, 102, 118, 42, 53, 220, 7, 54, 8, 183, 3, 193, 210, 184, 93, 8, 150, 198, 225, 196, 210, 36, 106, 184, 175, 52, 9, 183, 227, 74, 147, 112, 187, 172, 52, 9, 151, 179, 10, 168, 226, 172, 2, 60, 206, 42, 192, 227, 172, 2, 52, 103, 185, 22, 39, 39, 22, 164, 58, 150, 0, 149, 38, 149, 150, 64, 22, 57, 105, 148, 105, 42, 192, 106, 229, 204, 188, 130, 210, 18, 164, 21, 159, 32, 3, 203, 128, 150, 194, 44, 132, 173, 169, 66, 95, 83, 5, 211, 167, 163, 160, 174, 164, 174, 163, 160, 164, 86, 88, 154, 95, 98, 173, 164, 137, 45, 76, 18, 243, 146, 51, 242, 139, 192, 251, 63, 9, 6, 13, 193, 160, 129, 24, 134, 30, 58, 101, 176, 78, 4, 204, 15, 48, 89, 152, 55, 212, 109, 18, 193, 123, 74, 109, 149, 212, 21, 180, 177, 134, 10, 212, 125, 218, 64, 15, 217, 129, 212, 4, 67, 130, 52, 17, 123, 60, 167, 229, 231, 149, 36, 231, 231, 0, 189, 5, 38, 41, 247, 23, 212, 64, 178, 188, 6, 210, 171, 0, 214, 140, 219, 123, 80, 119, 98, 248, 15, 164, 23, 183, 23, 139, 129, 45, 105, 240, 89, 207, 212, 241, 32, 208, 56, 104, 97, 64, 178, 255, 64, 141, 122, 60, 177, 7, 117, 36, 122, 236, 225, 246, 29, 184, 162, 47, 45, 202, 161, 220, 99, 40, 85, 61, 177, 158, 2, 165, 199, 140, 162, 212, 52, 220, 62, 130, 56, 142, 80, 114, 12, 78, 45, 1, 159, 186, 1, 57, 86, 208, 51, 47, 19, 218, 163, 77, 202, 129, 68, 25, 216, 37, 197, 169, 37, 176, 126, 41, 84, 36, 49, 37, 5, 60, 131, 10, 148, 209, 3, 178, 173, 185, 96, 221, 213, 98, 232, 66, 203, 84, 13, 176, 18, 184, 239, 209, 70, 2, 12, 141, 116, 96, 107, 93, 32, 234, 96, 30, 71, 105, 221, 130, 253, 161, 0, 82, 147, 147, 147, 95, 14, 157, 73, 245, 4, 58, 15, 225, 70, 152, 249, 232, 83, 173, 64, 191, 129, 93, 0, 158, 103, 45, 209, 81, 128, 27, 7, 181, 9, 53, 8, 220, 242, 139, 92, 19, 147, 51, 192, 61, 138, 164, 196, 228, 236, 180, 60, 72, 124, 56, 22, 165, 43, 64, 102, 48, 96, 179, 136, 176, 184, 193, 217, 79, 15, 134, 244, 210, 131, 161, 125, 244, 20, 96, 12, 166, 150, 192, 229, 48, 58, 231, 176, 248, 132, 117, 196, 208, 59, 231, 64, 205, 68, 244, 200, 147, 19, 97, 238, 134, 137, 64, 93, 15, 91, 57, 168, 132, 240, 36, 164, 171, 14, 11, 112, 244, 104, 67, 10, 2, 124, 113, 231, 146, 154, 156, 159, 91, 144, 153, 147, 10, 180, 67, 195, 64, 7, 201, 1, 154, 16, 147, 161, 225, 84, 6, 10, 242, 98, 164, 197, 164, 176, 142, 102, 60, 208, 65, 241, 16, 89, 240, 248, 10, 84, 61, 48, 174, 32, 3, 17, 64, 101, 65, 176, 14, 60, 228, 204, 146, 96, 20, 41, 88, 175, 27, 125, 41, 171, 2, 196, 156, 20, 72, 119, 221, 61, 181, 196, 15, 24, 241, 64, 173, 174, 121, 37, 69, 149, 192, 16, 128, 13, 115, 104, 64, 237, 198, 98, 35, 216, 49, 144, 128, 1, 26, 3, 53, 22, 125, 184, 12, 110, 19, 180, 39, 141, 197, 156, 104, 131, 88, 176, 98, 236, 82, 10, 144, 227, 153, 172, 161, 169, 23, 61, 245, 230, 97, 75, 139, 58, 16, 219, 160, 20, 56, 220, 208, 19, 179, 10, 208, 175, 160, 147, 103, 209, 142, 171, 205, 131, 166, 214, 90, 244, 227, 106, 83, 53, 32, 58, 8, 157, 85, 11, 59, 94, 11, 61, 30, 160, 81, 228, 12, 94, 178, 132, 41, 165, 161, 105, 141, 146, 209, 60, 225, 99, 70, 40, 3, 95, 254, 56, 179, 147, 63, 36, 59, 249, 35, 178, 19, 146, 41, 64, 89, 244, 209, 46, 152, 127, 193, 65, 10, 12, 75, 88, 134, 2, 3, 231, 196, 28, 152, 243, 113, 13, 117, 193, 50, 22, 44, 223, 160, 185, 25, 62, 206, 5, 75, 226, 184, 146, 44, 142, 160, 178, 134, 106, 2, 58, 50, 44, 49, 7, 207, 224, 148, 21, 120, 168, 73, 161, 22, 166, 129, 80, 130, 6, 134, 5, 214, 180, 12, 15, 81, 68, 82, 134, 24, 152, 89, 146, 154, 235, 157, 153, 151, 66, 96, 184, 13, 56, 220, 230, 143, 184, 169, 4, 168, 17, 58, 224, 3, 203, 35, 10, 26, 48, 131, 32, 99, 29, 48, 43, 96, 29, 127, 92, 57, 3, 125, 60, 26, 12, 172, 173, 185, 208, 244, 70, 99, 213, 140, 197, 167, 32, 97, 144, 161, 176, 188, 137, 174, 2, 150, 233, 16, 153, 14, 26, 7, 176, 161, 48, 168, 157, 200, 82, 208, 65, 63, 148, 213, 100, 176, 228, 5, 86, 1, 52, 8, 41, 235, 185, 167, 130, 226, 37, 40, 53, 57, 191, 40, 69, 35, 63, 41, 11, 28, 20, 176, 228, 140, 24, 197, 133, 20, 171, 232, 197, 106, 145, 134, 169, 153, 14, 232, 72, 74, 104, 122, 70, 63, 82, 24, 180, 64, 10, 36, 13, 75, 122, 176, 241, 174, 224, 204, 42, 144, 19, 129, 50, 122, 160, 113, 80, 107, 168, 76, 94, 105, 46, 84, 70, 27, 170, 8, 150, 16, 160, 50, 160, 181, 66, 80, 85, 224, 100, 1, 139, 77, 152, 145, 176, 153, 123, 164, 122, 15, 155, 155, 77, 116, 20, 148, 160, 141, 50, 37, 184, 114, 37, 160, 35, 209, 99, 151, 128, 94, 191, 68, 63, 184, 46, 176, 7, 225, 211, 128, 80, 111, 192, 102, 118, 138, 96, 30, 128, 166, 108, 5, 13, 168, 26, 232, 12, 15, 44, 100, 81, 230, 101, 204, 44, 141, 80, 194, 45, 35, 177, 24, 26, 102, 64, 22, 164, 204, 129, 85, 130, 144, 74, 48, 35, 17, 173, 221, 134, 112, 182, 161, 49, 208, 185, 64, 121, 37, 20, 19, 179, 83, 43, 97, 70, 2, 153, 88, 205, 4, 138, 227, 55, 20, 164, 0, 110, 42, 44, 157, 85, 43, 20, 167, 150, 88, 129, 12, 134, 44, 52, 176, 130, 133, 137, 14, 200, 23, 58, 10, 96, 139, 107, 209, 211, 161, 103, 9, 164, 80, 112, 43, 202, 207, 133, 54, 51, 139, 193, 73, 19, 104, 63, 146, 139, 129, 202, 128, 203, 224, 192, 181, 15, 122, 237, 3, 81, 14, 242, 12, 164, 142, 4, 113, 128, 148, 38, 204, 103, 176, 36, 93, 162, 1, 51, 8, 151, 223, 160, 177, 111, 106, 6, 45, 83, 225, 54, 131, 75, 110, 88, 74, 71, 75, 233, 48, 53, 92, 176, 226, 22, 41, 76, 224, 146, 200, 190, 6, 85, 46, 161, 121, 32, 151, 231, 151, 100, 0, 29, 3, 243, 39, 169, 85, 11, 76, 14, 87, 197, 130, 86, 177, 56, 99, 111, 162, 41, 148, 128, 23, 244, 129, 157, 162, 3, 174, 68, 192, 110, 67, 74, 51, 137, 69, 16, 89, 96, 184, 130, 139, 117, 88, 209, 81, 148, 2, 245, 128, 53, 70, 60, 225, 136, 88, 152, 49, 232, 58, 192, 245, 21, 80, 23, 140, 171, 151, 7, 228, 195, 212, 20, 193, 10, 88, 112, 251, 191, 160, 18, 232, 97, 200, 216, 50, 161, 214, 55, 200, 164, 240, 204, 146, 12, 160, 225, 136, 168, 215, 65, 177, 19, 156, 16, 96, 173, 82, 88, 72, 193, 219, 124, 137, 41, 41, 58, 16, 235, 81, 90, 229, 104, 81, 92, 4, 155, 85, 64, 137, 96, 79, 160, 19, 138, 138, 83, 65, 124, 92, 241, 60, 208, 241, 12, 119, 34, 153, 209, 13, 20, 7, 43, 128, 173, 65, 69, 234, 156, 105, 128, 204, 87, 130, 170, 132, 69, 33, 120, 11, 84, 57, 72, 155, 6, 88, 6, 118, 14, 95, 112, 102, 21, 214, 249, 29, 80, 20, 20, 131, 139, 15, 72, 140, 131, 130, 10, 174, 222, 198, 86, 1, 230, 74, 189, 98, 72, 197, 0, 107, 231, 162, 183, 228, 209, 140, 132, 181, 228, 129, 134, 66, 116, 192, 218, 242, 176, 26, 24, 230, 88, 88, 195, 8, 93, 202, 154, 11, 114, 109, 9, 122, 107, 30, 189, 61, 143, 214, 252, 41, 66, 111, 207, 163, 219, 10, 107, 3, 161, 183, 232, 21, 160, 0, 62, 5, 14, 157, 4, 135, 217, 8, 107, 215, 163, 155, 135, 104, 215, 67, 90, 246, 232, 146, 176, 150, 125, 78, 14, 178, 173, 201, 137, 232, 37, 108, 30, 52, 223, 2, 67, 58, 35, 17, 232, 108, 56, 15, 212, 91, 133, 88, 14, 206, 71, 48, 119, 162, 135, 58, 122, 94, 130, 233, 65, 245, 74, 45, 23, 172, 22, 134, 197, 36, 172, 124, 192, 85, 162, 160, 151, 40, 10, 68, 118, 201, 113, 21, 10, 176, 146, 7, 86, 42, 192, 66, 4, 171, 127, 192, 33, 225, 143, 220, 89, 39, 58, 8, 208, 139, 19, 244, 96, 128, 21, 46, 40, 133, 11, 87, 90, 41, 162, 112, 113, 201, 76, 75, 75, 45, 74, 205, 75, 78, 197, 86, 180, 80, 90, 133, 80, 90, 180, 160, 56, 16, 169, 96, 33, 84, 176, 192, 10, 5, 88, 137, 143, 94, 226, 15, 112, 121, 81, 4, 203, 161, 48, 109, 164, 22, 26, 180, 42, 52, 52, 161, 217, 23, 125, 24, 96, 168, 23, 26, 37, 241, 41, 169, 57, 169, 37, 169, 176, 160, 199, 85, 110, 12, 182, 114, 131, 88, 239, 160, 151, 1, 64, 175, 128, 49, 122, 222, 71, 205, 251, 193, 149, 185, 185, 169, 37, 69, 153, 201, 240, 60, 70, 231, 66, 0, 234, 67, 194, 35, 126, 48, 54, 216, 117, 64, 14, 108, 148, 2, 155, 23, 144, 71, 250, 160, 190, 200, 39, 84, 86, 144, 26, 211, 104, 58, 252, 6, 170, 205, 9, 11, 92, 92, 117, 11, 174, 186, 5, 87, 205, 66, 40, 97, 161, 229, 15, 12, 51, 96, 181, 83, 10, 14, 3, 136, 77, 153, 158, 197, 193, 165, 73, 197, 169, 37, 254, 105, 180, 77, 144, 69, 104, 9, 18, 71, 74, 84, 64, 175, 149, 144, 28, 8, 174, 149, 112, 165, 52, 28, 41, 173, 4, 189, 234, 65, 11, 192, 98, 92, 85, 143, 29, 90, 205, 3, 243, 10, 108, 255, 31, 48, 106, 144, 93, 83, 70, 168, 54, 130, 183, 94, 201, 172, 134, 208, 43, 33, 106, 85, 65, 232, 21, 16, 90, 245, 83, 11, 179, 137, 80, 213, 3, 107, 173, 162, 75, 193, 42, 30, 132, 93, 138, 40, 245, 14, 52, 164, 242, 97, 129, 77, 168, 222, 65, 143, 3, 244, 148, 14, 61, 94, 46, 213, 154, 171, 150, 43, 13, 104, 58, 114, 58, 47, 72, 45, 26, 236, 41, 29, 230, 68, 186, 165, 117, 144, 122, 27, 18, 210, 58, 169, 165, 55, 165, 197, 47, 172, 150, 134, 57, 10, 150, 130, 208, 189, 135, 171, 0, 198, 149, 100, 136, 74, 50, 46, 153, 197, 89, 249, 153, 121, 224, 171, 97, 160, 129, 77, 167, 68, 195, 69, 105, 125, 141, 230, 122, 37, 82, 171, 106, 88, 162, 130, 37, 18, 88, 1, 138, 30, 234, 184, 19, 149, 45, 214, 84, 69, 114, 105, 73, 102, 121, 169, 160, 0, 41, 49, 53, 74, 224, 37, 38, 21, 203, 76, 5, 5, 88, 169, 9, 51, 26, 214, 108, 207, 134, 41, 168, 133, 208, 196, 150, 157, 132, 74, 79, 132, 173, 228, 21, 159, 48, 119, 194, 18, 28, 44, 55, 160, 58, 183, 150, 11, 214, 238, 128, 197, 22, 44, 191, 19, 155, 223, 97, 237, 242, 178, 68, 72, 142, 15, 75, 132, 228, 120, 133, 68, 72, 142, 207, 43, 129, 228, 120, 88, 187, 188, 68, 3, 102, 60, 36, 199, 123, 150, 64, 114, 124, 9, 212, 197, 48, 95, 195, 82, 10, 44, 165, 192, 178, 188, 142, 130, 63, 214, 44, 79, 216, 155, 92, 96, 21, 88, 235, 139, 176, 204, 212, 242, 212, 20, 199, 162, 162, 196, 74, 167, 210, 180, 180, 212, 34, 207, 180, 160, 212, 204, 180, 204, 212, 20, 141, 146, 68, 144, 40, 196, 26, 107, 160, 169, 224, 16, 74, 42, 77, 67, 76, 115, 161, 44, 151, 46, 129, 106, 208, 81, 128, 236, 220, 176, 182, 70, 88, 11, 47, 48, 128, 218, 53, 21, 236, 193, 166, 88, 65, 163, 27, 238, 24, 144, 50, 151, 212, 146, 196, 228, 140, 212, 20, 136, 91, 52, 146, 64, 20, 180, 250, 2, 6, 13, 132, 15, 27, 237, 70, 47, 86, 80, 139, 111, 107, 107, 168, 30, 184, 38, 88, 17, 5, 243, 44, 194, 2, 236, 213, 27, 186, 145, 136, 99, 207, 32, 33, 128, 107, 162, 15, 24, 20, 96, 115, 65, 241, 108, 12, 12, 10, 184, 97, 26, 16, 205, 160, 59, 169, 44, 52, 193, 179, 70, 6, 40, 222, 7, 154, 230, 88, 2, 242, 63, 74, 132, 104, 192, 226, 1, 86, 28, 195, 252, 67, 56, 238, 224, 69, 21, 214, 128, 197, 53, 207, 0, 156, 79, 50, 183, 0, 106, 69, 78, 56, 80, 75, 137, 112, 46, 52, 163, 0, 77, 134, 105, 198, 165, 18, 182, 16, 7, 201, 72, 215, 188, 226, 210, 162, 84, 160, 67, 160, 10, 195, 51, 75, 50, 144, 117, 36, 22, 165, 107, 42, 192, 18, 3, 44, 81, 129, 69, 33, 103, 146, 32, 116, 130, 4, 97, 222, 195, 97, 63, 72, 9, 200, 155, 240, 216, 134, 121, 25, 154, 1, 97, 213, 19, 180, 114, 66, 152, 13, 241, 162, 103, 90, 120, 81, 98, 1, 80, 12, 82, 21, 37, 22, 65, 87, 136, 40, 225, 11, 23, 37, 160, 18, 84, 47, 35, 140, 133, 174, 28, 112, 70, 26, 166, 134, 79, 125, 90, 3, 221, 6, 142, 124, 144, 48, 116, 118, 44, 25, 161, 16, 22, 207, 96, 89, 244, 249, 70, 228, 244, 140, 100, 184, 91, 126, 17, 194, 110, 144, 77, 176, 40, 71, 171, 227, 129, 102, 98, 79, 40, 208, 137, 86, 165, 124, 176, 58, 245, 98, 5, 117, 36, 23, 169, 43, 20, 64, 239, 134, 86, 130, 153, 11, 118, 63, 48, 239, 128, 253, 16, 237, 158, 138, 126, 54, 4, 116, 141, 132, 146, 102, 44, 196, 59, 232, 203, 192, 64, 203, 192, 138, 129, 46, 33, 213, 67, 48, 179, 144, 148, 34, 153, 19, 148, 90, 144, 95, 84, 18, 90, 156, 152, 158, 10, 222, 218, 145, 90, 164, 81, 172, 163, 160, 161, 97, 172, 96, 99, 163, 96, 104, 166, 169, 80, 163, 96, 172, 169, 137, 108, 101, 49, 212, 88, 244, 192, 0, 171, 49, 52, 129, 166, 2, 7, 7, 168, 127, 20, 96, 1, 161, 0, 153, 118, 6, 135, 21, 232, 158, 84, 152, 99, 148, 128, 26, 128, 78, 173, 69, 100, 131, 176, 196, 156, 204, 148, 196, 18, 104, 70, 128, 121, 7, 61, 229, 35, 207, 129, 43, 192, 36, 144, 180, 32, 36, 113, 231, 1, 72, 48, 65, 148, 192, 114, 1, 172, 222, 128, 153, 137, 126, 25, 13, 46, 43, 192, 170, 113, 170, 245, 72, 68, 47, 131, 80, 53, 43, 40, 160, 167, 45, 104, 33, 164, 0, 115, 13, 186, 11, 177, 199, 130, 169, 165, 25, 106, 96, 134, 192, 157, 0, 89, 89, 19, 158, 89, 146, 1, 221, 151, 129, 20, 9, 58, 10, 57, 72, 231, 4, 148, 37, 22, 41, 228, 165, 150, 35, 180, 34, 223, 108, 11, 107, 145, 192, 74, 8, 144, 107, 144, 227, 83, 7, 187, 64, 14, 236, 142, 58, 144, 175, 176, 69, 49, 220, 66, 104, 209, 141, 188, 173, 23, 103, 176, 66, 124, 130, 69, 47, 48, 205, 131, 55, 196, 218, 192, 61, 134, 61, 7, 91, 154, 195, 188, 14, 166, 225, 121, 6, 18, 212, 168, 161, 64, 48, 92, 33, 49, 139, 26, 174, 224, 154, 3, 68, 87, 150, 164, 250, 167, 165, 21, 167, 194, 206, 100, 160, 93, 88, 67, 236, 132, 177, 225, 246, 146, 27, 15, 164, 134, 62, 185, 161, 23, 148, 90, 12, 57, 67, 139, 184, 96, 164, 119, 240, 13, 150, 32, 131, 213, 148, 197, 208, 144, 67, 228, 231, 212, 138, 212, 220, 130, 156, 68, 180, 204, 12, 187, 20, 28, 93, 63, 172, 166, 5, 249, 27, 174, 21, 201, 41, 184, 74, 14, 144, 77, 206, 112, 43, 172, 185, 8, 57, 17, 57, 107, 128, 98, 0, 238, 74, 46, 228, 144, 70, 132, 179, 14, 23, 60, 145, 82, 213, 3, 200, 238, 0, 121, 0, 61, 69, 193, 50, 38, 204, 83, 132, 60, 133, 158, 98, 137, 243, 29, 245, 253, 132, 238, 12, 28, 158, 211, 196, 225, 41, 215, 188, 146, 34, 240, 18, 79, 152, 187, 144, 199, 59, 176, 181, 72, 51, 144, 235, 79, 127, 77, 107, 66, 169, 189, 36, 3, 162, 10, 230, 3, 136, 187, 193, 210, 224, 30, 38, 116, 197, 161, 17, 78, 7, 150, 165, 22, 85, 34, 173, 97, 85, 32, 211, 165, 176, 42, 5, 87, 149, 130, 238, 102, 120, 53, 226, 88, 148, 94, 154, 155, 154, 7, 219, 206, 168, 1, 233, 45, 25, 224, 170, 81, 76, 117, 20, 12, 116, 20, 148, 84, 17, 38, 170, 234, 21, 0, 207, 157, 3, 159, 59, 167, 151, 10, 244, 13, 172, 77, 8, 49, 31, 182, 180, 11, 182, 102, 26, 182, 102, 26, 135, 249, 134, 132, 214, 76, 67, 77, 6, 250, 20, 177, 240, 28, 115, 75, 166, 130, 157, 130, 161, 130, 61, 168, 89, 132, 116, 10, 137, 2, 210, 226, 81, 107, 216, 136, 30, 120, 96, 0, 104, 132, 129, 181, 66, 54, 164, 58, 5, 50, 128, 155, 63, 161, 206, 3, 217, 147, 29, 6, 29, 246, 240, 143, 206, 6, 182, 94, 97, 194, 37, 169, 197, 37, 65, 169, 208, 229, 26, 201, 232, 131, 25, 249, 121, 16, 223, 162, 47, 76, 134, 24, 6, 164, 97, 227, 66, 208, 80, 66, 152, 6, 179, 26, 146, 164, 96, 221, 84, 88, 179, 8, 94, 127, 67, 59, 252, 224, 14, 127, 112, 106, 9, 250, 121, 20, 112, 87, 64, 35, 10, 150, 212, 52, 173, 33, 169, 16, 53, 21, 186, 101, 230, 228, 104, 148, 65, 92, 86, 12, 61, 79, 196, 64, 7, 116, 98, 8, 250, 178, 126, 88, 164, 194, 26, 169, 224, 110, 158, 66, 77, 141, 2, 80, 8, 97, 30, 88, 24, 28, 199, 48, 127, 192, 70, 147, 145, 42, 43, 162, 250, 94, 232, 227, 131, 96, 71, 66, 57, 96, 167, 66, 43, 126, 208, 129, 188, 112, 13, 74, 168, 62, 67, 30, 52, 68, 47, 5, 160, 252, 36, 88, 183, 27, 189, 37, 13, 205, 95, 32, 255, 128, 13, 0, 42, 6, 103, 49, 91, 104, 232, 161, 231, 41, 176, 130, 236, 204, 188, 20, 136, 89, 8, 69, 222, 64, 49, 160, 18, 88, 182, 203, 134, 174, 4, 86, 176, 4, 6, 30, 80, 3, 108, 93, 176, 1, 52, 208, 96, 99, 109, 192, 35, 117, 156, 50, 211, 61, 243, 74, 32, 209, 3, 156, 18, 67, 29, 217, 66, 82, 231, 87, 154, 155, 4, 116, 42, 68, 29, 204, 179, 144, 9, 197, 156, 196, 146, 204, 178, 84, 208, 73, 49, 37, 10, 144, 147, 98, 74, 82, 33, 39, 197, 192, 78, 138, 129, 230, 3, 104, 124, 33, 212, 19, 58, 242, 5, 85, 49, 238, 115, 95, 208, 148, 193, 15, 127, 65, 114, 30, 202, 41, 53, 176, 84, 7, 59, 165, 6, 253, 148, 26, 184, 110, 160, 154, 196, 28, 132, 195, 97, 38, 17, 235, 108, 160, 82, 188, 142, 134, 41, 130, 57, 25, 215, 80, 21, 216, 0, 160, 48, 98, 240, 6, 18, 239, 176, 193, 27, 248, 224, 141, 63, 36, 106, 40, 29, 187, 81, 192, 159, 10, 161, 161, 130, 56, 250, 6, 118, 246, 91, 14, 212, 35, 176, 242, 15, 92, 236, 65, 148, 131, 11, 62, 152, 197, 254, 209, 217, 177, 64, 253, 160, 212, 5, 46, 123, 144, 74, 29, 127, 108, 85, 25, 36, 171, 149, 164, 22, 105, 36, 39, 230, 228, 36, 37, 14, 245, 186, 44, 85, 47, 13, 236, 29, 37, 104, 120, 211, 186, 50, 11, 33, 179, 26, 131, 230, 220, 212, 2, 232, 10, 199, 120, 159, 204, 98, 164, 37, 142, 201, 137, 5, 192, 56, 75, 77, 1, 213, 112, 224, 56, 199, 85, 231, 193, 163, 30, 106, 96, 24, 180, 248, 129, 213, 121, 232, 99, 246, 216, 171, 185, 16, 29, 5, 104, 5, 167, 0, 170, 224, 224, 1, 163, 160, 0, 114, 97, 52, 204, 53, 218, 218, 177, 10, 182, 16, 149, 104, 21, 27, 40, 40, 28, 145, 147, 53, 122, 179, 20, 214, 72, 215, 240, 215, 129, 123, 14, 228, 91, 132, 207, 32, 167, 247, 3, 41, 27, 184, 2, 32, 15, 225, 61, 199, 232, 60, 160, 237, 96, 7, 1, 89, 176, 56, 128, 166, 109, 71, 88, 117, 138, 94, 157, 194, 124, 11, 115, 24, 44, 185, 163, 215, 167, 48, 185, 188, 20, 141, 2, 160, 205, 153, 201, 64, 87, 99, 203, 7, 67, 37, 31, 128, 242, 65, 94, 138, 146, 38, 174, 92, 0, 247, 36, 52, 174, 209, 77, 199, 218, 162, 67, 210, 4, 51, 183, 12, 71, 131, 14, 230, 1, 66, 57, 129, 70, 137, 27, 238, 61, 88, 19, 14, 189, 9, 7, 51, 23, 150, 130, 176, 164, 106, 152, 20, 178, 99, 107, 113, 181, 217, 208, 19, 25, 48, 240, 113, 39, 49, 79, 160, 129, 21, 67, 35, 157, 193, 134, 80, 21, 20, 76, 77, 97, 205, 52, 3, 24, 67, 73, 21, 110, 9, 122, 210, 131, 248, 81, 137, 11, 214, 130, 195, 149, 8, 135, 74, 34, 36, 53, 181, 41, 248, 71, 103, 199, 226, 76, 107, 214, 92, 232, 201, 12, 40, 170, 107, 72, 68, 33, 6, 43, 196, 96, 33, 12, 75, 100, 104, 137, 44, 31, 125, 191, 239, 32, 79, 99, 166, 208, 178, 12, 97, 32, 114, 73, 6, 241, 141, 18, 200, 108, 88, 58, 130, 165, 35, 88, 149, 14, 171, 210, 113, 152, 143, 145, 144, 208, 171, 116, 58, 167, 164, 100, 212, 84, 84, 146, 137, 86, 33, 195, 251, 157, 176, 100, 164, 224, 15, 113, 35, 172, 84, 34, 175, 84, 130, 4, 36, 182, 52, 147, 88, 9, 78, 78, 254, 105, 26, 197, 169, 137, 69, 201, 25, 174, 57, 169, 32, 239, 233, 40, 164, 21, 229, 231, 66, 142, 93, 130, 196, 30, 34, 248, 253, 147, 178, 82, 147, 209, 123, 146, 48, 211, 52, 74, 32, 61, 201, 106, 46, 212, 158, 100, 14, 220, 89, 96, 9, 5, 92, 179, 120, 69, 137, 144, 158, 164, 130, 2, 164, 39, 153, 89, 12, 97, 195, 238, 165, 129, 185, 15, 42, 152, 6, 115, 37, 122, 87, 18, 225, 49, 212, 178, 8, 189, 195, 88, 137, 214, 97, 68, 175, 245, 17, 121, 0, 18, 100, 232, 137, 30, 54, 182, 159, 135, 154, 204, 139, 96, 89, 27, 102, 45, 172, 165, 131, 232, 20, 193, 157, 14, 54, 197, 218, 26, 210, 69, 128, 245, 1, 96, 125, 0, 160, 144, 14, 134, 205, 81, 169, 69, 249, 254, 121, 254, 165, 37, 254, 105, 78, 249, 165, 121, 41, 197, 64, 167, 64, 77, 129, 58, 40, 79, 193, 14, 124, 88, 49, 94, 247, 100, 35, 169, 70, 184, 29, 156, 124, 243, 208, 251, 173, 10, 217, 144, 211, 143, 21, 180, 33, 114, 16, 141, 217, 10, 54, 48, 125, 48, 53, 6, 16, 89, 88, 25, 7, 235, 180, 96, 228, 5, 168, 99, 33, 230, 248, 71, 103, 67, 174, 49, 41, 70, 68, 50, 236, 188, 77, 132, 243, 65, 14, 198, 85, 126, 162, 167, 108, 80, 96, 121, 229, 3, 3, 16, 126, 112, 58, 196, 180, 129, 78, 195, 80, 199, 232, 160, 39, 87, 136, 107, 149, 184, 104, 155, 86, 129, 26, 64, 110, 0, 42, 64, 63, 79, 30, 209, 121, 87, 210, 81, 2, 118, 222, 97, 7, 116, 32, 194, 15, 146, 216, 113, 37, 118, 216, 137, 113, 176, 196, 14, 61, 148, 223, 22, 150, 154, 73, 77, 205, 48, 203, 96, 247, 54, 160, 91, 135, 22, 33, 193, 200, 167, 181, 234, 128, 124, 7, 238, 55, 43, 232, 42, 24, 66, 66, 19, 150, 57, 64, 78, 75, 133, 36, 47, 3, 80, 139, 50, 218, 32, 22, 156, 113, 96, 114, 65, 200, 135, 147, 192, 20, 2, 141, 64, 43, 222, 13, 161, 197, 59, 200, 147, 40, 137, 26, 201, 124, 148, 222, 24, 52, 177, 7, 41, 104, 219, 130, 99, 0, 118, 78, 17, 194, 22, 136, 59, 145, 189, 13, 178, 32, 53, 15, 98, 50, 84, 107, 50, 113, 158, 6, 185, 11, 98, 32, 82, 62, 9, 66, 30, 7, 64, 138, 5, 239, 212, 202, 98, 13, 77, 232, 128, 59, 44, 65, 161, 55, 19, 208, 155, 162, 176, 102, 2, 174, 1, 119, 244, 180, 7, 115, 5, 108, 192, 189, 8, 109, 192, 221, 64, 19, 135, 235, 124, 18, 139, 75, 32, 37, 57, 74, 21, 5, 12, 94, 162, 50, 180, 35, 90, 134, 86, 192, 209, 74, 81, 176, 83, 48, 132, 40, 192, 158, 196, 96, 121, 158, 216, 92, 15, 203, 247, 48, 30, 70, 237, 5, 93, 8, 128, 210, 162, 64, 136, 195, 203, 5, 88, 0, 192, 171, 50, 104, 101, 6, 43, 7, 113, 185, 149, 220, 242, 9, 221, 149, 4, 220, 162, 73, 171, 162, 10, 87, 73, 131, 94, 141, 1, 141, 201, 195, 211, 98, 11, 129, 87, 183, 168, 33, 13, 108, 188, 193, 202, 7, 252, 21, 47, 204, 109, 184, 138, 42, 88, 197, 11, 243, 83, 54, 208, 156, 60, 5, 59, 160, 155, 81, 198, 49, 129, 6, 230, 193, 75, 36, 144, 229, 176, 170, 20, 86, 69, 2, 155, 139, 96, 93, 64, 90, 87, 23, 232, 93, 88, 161, 1, 171, 33, 253, 163, 177, 215, 144, 104, 41, 54, 27, 150, 50, 96, 57, 31, 87, 13, 9, 77, 18, 137, 5, 208, 190, 2, 161, 190, 2, 122, 33, 128, 94, 8, 192, 34, 20, 189, 175, 128, 171, 56, 192, 145, 11, 109, 97, 177, 141, 222, 31, 69, 234, 43, 168, 130, 132, 208, 59, 159, 169, 122, 185, 137, 5, 74, 96, 147, 107, 65, 166, 163, 247, 20, 16, 195, 120, 216, 77, 39, 212, 83, 128, 153, 140, 62, 248, 71, 98, 31, 161, 12, 125, 188, 12, 215, 120, 153, 134, 63, 234, 192, 47, 174, 113, 18, 152, 111, 64, 210, 185, 224, 240, 134, 12, 150, 192, 166, 184, 112, 117, 53, 128, 99, 127, 40, 157, 12, 72, 74, 115, 140, 6, 141, 34, 35, 27, 132, 86, 135, 224, 28, 111, 131, 217, 128, 146, 182, 144, 58, 28, 72, 62, 14, 74, 77, 41, 77, 134, 69, 9, 174, 116, 55, 84, 210, 93, 170, 94, 17, 216, 59, 176, 173, 171, 180, 74, 122, 48, 147, 97, 69, 162, 129, 130, 154, 26, 150, 52, 8, 242, 135, 33, 46, 127, 24, 1, 77, 66, 36, 226, 108, 96, 144, 25, 192, 66, 48, 49, 57, 185, 52, 183, 52, 7, 212, 32, 68, 77, 219, 176, 210, 20, 123, 218, 246, 143, 206, 214, 214, 142, 5, 25, 130, 222, 206, 135, 37, 77, 5, 5, 84, 179, 97, 201, 18, 150, 44, 97, 213, 21, 172, 115, 12, 241, 179, 14, 84, 4, 158, 119, 96, 2, 112, 179, 96, 77, 104, 5, 72, 34, 134, 178, 179, 117, 96, 130, 176, 218, 9, 57, 245, 34, 235, 182, 134, 22, 136, 88, 211, 102, 80, 102, 122, 70, 9, 52, 226, 160, 9, 180, 26, 26, 80, 254, 208, 4, 106, 13, 77, 160, 69, 208, 4, 90, 4, 77, 160, 142, 208, 4, 154, 6, 77, 160, 10, 208, 4, 10, 27, 68, 201, 132, 38, 208, 2, 104, 2, 117, 132, 38, 208, 116, 104, 2, 85, 128, 38, 80, 140, 136, 133, 38, 80, 244, 136, 133, 13, 212, 193, 6, 234, 20, 160, 3, 117, 10, 120, 7, 234, 138, 82, 225, 222, 68, 171, 199, 209, 11, 78, 66, 169, 183, 8, 173, 224, 68, 79, 189, 154, 80, 147, 97, 169, 151, 90, 169, 23, 152, 122, 193, 161, 170, 11, 169, 192, 203, 8, 165, 97, 188, 105, 88, 87, 23, 145, 134, 161, 21, 177, 1, 180, 34, 134, 37, 97, 66, 73, 24, 26, 224, 112, 143, 195, 146, 48, 189, 147, 112, 98, 101, 80, 106, 89, 106, 81, 113, 170, 6, 196, 237, 176, 254, 46, 172, 121, 76, 168, 121, 140, 171, 237, 75, 108, 203, 23, 214, 158, 132, 53, 29, 209, 157, 133, 150, 220, 224, 61, 92, 106, 53, 27, 193, 245, 96, 102, 74, 74, 78, 42, 114, 131, 46, 45, 39, 63, 191, 8, 156, 250, 244, 21, 140, 192, 234, 96, 117, 170, 66, 78, 126, 121, 42, 48, 82, 129, 17, 14, 97, 130, 182, 2, 64, 77, 128, 138, 128, 75, 50, 88, 37, 171, 80, 90, 80, 0, 82, 15, 77, 124, 96, 5, 224, 68, 8, 85, 0, 53, 48, 12, 90, 9, 251, 71, 131, 185, 177, 214, 168, 250, 17, 210, 64, 46, 76, 26, 174, 24, 40, 129, 80, 5, 149, 130, 42, 4, 74, 65, 204, 71, 175, 155, 209, 231, 121, 145, 194, 39, 56, 39, 51, 57, 85, 163, 184, 4, 229, 74, 28, 244, 144, 69, 75, 40, 254, 232, 169, 4, 152, 74, 252, 169, 150, 68, 252, 97, 12, 204, 5, 33, 232, 233, 6, 236, 122, 34, 82, 13, 122, 121, 75, 32, 137, 20, 65, 215, 48, 4, 195, 150, 88, 160, 47, 177, 128, 170, 203, 86, 176, 133, 248, 24, 203, 18, 11, 5, 124, 107, 21, 112, 45, 177, 64, 95, 173, 0, 83, 6, 107, 237, 193, 156, 71, 171, 37, 22, 132, 156, 141, 107, 137, 5, 186, 163, 97, 75, 44, 224, 150, 38, 231, 151, 230, 1, 67, 18, 213, 96, 136, 75, 116, 21, 178, 129, 6, 66, 84, 162, 183, 127, 113, 181, 127, 129, 237, 95, 176, 145, 176, 187, 110, 20, 52, 32, 22, 216, 1, 13, 82, 168, 6, 10, 65, 204, 42, 206, 201, 76, 78, 5, 133, 17, 194, 64, 167, 204, 146, 242, 204, 226, 84, 72, 170, 7, 154, 226, 8, 110, 225, 34, 204, 130, 150, 137, 16, 157, 154, 80, 179, 20, 96, 129, 6, 115, 63, 242, 10, 12, 108, 9, 9, 106, 148, 2, 216, 21, 121, 64, 125, 6, 16, 1, 248, 254, 63, 248, 50, 13, 152, 21, 144, 246, 117, 30, 100, 46, 221, 31, 214, 112, 2, 131, 90, 48, 93, 139, 154, 157, 29, 177, 102, 103, 96, 128, 229, 231, 34, 53, 42, 9, 181, 77, 96, 186, 96, 109, 19, 88, 219, 4, 150, 21, 112, 181, 77, 208, 125, 12, 107, 155, 192, 218, 38, 176, 138, 149, 80, 219, 132, 64, 227, 185, 24, 232, 25, 37, 144, 209, 176, 38, 2, 174, 198, 7, 14, 227, 9, 54, 62, 96, 189, 54, 244, 249, 29, 244, 182, 1, 122, 219, 0, 189, 239, 6, 155, 223, 193, 213, 13, 131, 165, 73, 244, 233, 106, 107, 168, 48, 181, 214, 31, 66, 147, 47, 220, 48, 216, 242, 67, 88, 169, 12, 91, 100, 168, 0, 77, 80, 176, 4, 5, 91, 151, 72, 168, 255, 134, 154, 206, 52, 173, 209, 83, 32, 72, 38, 36, 223, 39, 31, 232, 216, 84, 232, 40, 105, 14, 152, 83, 172, 128, 84, 64, 233, 40, 228, 23, 128, 52, 161, 8, 34, 18, 106, 34, 200, 20, 72, 98, 69, 74, 172, 8, 11, 208, 19, 43, 88, 61, 36, 193, 38, 66, 19, 44, 172, 49, 93, 9, 77, 176, 112, 205, 208, 4, 11, 215, 3, 9, 175, 28, 216, 72, 18, 44, 184, 160, 97, 2, 31, 179, 86, 128, 20, 156, 69, 197, 37, 174, 57, 169, 185, 169, 121, 192, 72, 130, 56, 19, 58, 64, 108, 13, 181, 29, 117, 128, 152, 75, 1, 125, 78, 15, 26, 140, 200, 38, 233, 149, 160, 132, 151, 14, 138, 53, 154, 64, 35, 64, 174, 132, 13, 205, 195, 6, 229, 21, 148, 116, 192, 78, 67, 73, 116, 134, 152, 137, 14, 54, 168, 140, 208, 11, 137, 123, 216, 62, 88, 116, 223, 100, 199, 66, 228, 97, 183, 164, 192, 228, 97, 245, 11, 82, 76, 129, 253, 6, 244, 87, 102, 30, 82, 130, 66, 27, 202, 134, 135, 4, 150, 64, 64, 54, 31, 35, 12, 144, 228, 96, 185, 20, 28, 41, 176, 129, 106, 88, 186, 67, 78, 119, 193, 165, 73, 96, 79, 104, 36, 165, 166, 103, 230, 161, 182, 101, 20, 242, 147, 178, 144, 82, 84, 38, 172, 53, 3, 187, 99, 10, 214, 158, 65, 152, 166, 129, 188, 229, 9, 154, 28, 146, 19, 113, 181, 104, 96, 186, 124, 83, 75, 50, 242, 83, 60, 211, 96, 45, 26, 44, 141, 94, 176, 235, 96, 28, 244, 70, 13, 170, 79, 148, 184, 96, 237, 26, 88, 26, 68, 95, 147, 8, 86, 238, 84, 154, 134, 188, 38, 17, 228, 114, 88, 202, 214, 128, 170, 135, 45, 109, 132, 121, 8, 38, 12, 11, 62, 152, 41, 176, 77, 102, 8, 11, 139, 139, 146, 33, 89, 6, 69, 49, 174, 241, 78, 152, 110, 168, 78, 39, 216, 138, 254, 18, 84, 171, 224, 194, 40, 26, 138, 82, 115, 192, 141, 7, 39, 96, 8, 161, 78, 134, 130, 99, 20, 166, 14, 18, 130, 158, 121, 41, 169, 21, 10, 176, 86, 12, 146, 70, 220, 237, 24, 132, 87, 180, 81, 181, 232, 40, 192, 218, 51, 184, 218, 51, 80, 101, 240, 192, 128, 185, 5, 54, 153, 3, 58, 176, 2, 197, 139, 208, 196, 11, 18, 71, 246, 35, 196, 237, 200, 193, 130, 22, 76, 218, 200, 190, 211, 66, 54, 30, 22, 163, 152, 205, 61, 53, 53, 36, 139, 61, 139, 29, 75, 75, 242, 161, 165, 92, 62, 122, 26, 206, 131, 170, 68, 111, 90, 161, 111, 205, 0, 237, 105, 210, 128, 4, 9, 248, 16, 86, 40, 51, 9, 182, 73, 4, 4, 208, 253, 2, 18, 133, 37, 86, 88, 132, 18, 106, 167, 194, 3, 20, 218, 90, 69, 111, 173, 2, 3, 24, 188, 162, 5, 61, 170, 97, 13, 86, 98, 35, 154, 216, 102, 107, 94, 10, 182, 72, 206, 75, 45, 135, 154, 7, 107, 0, 66, 45, 74, 133, 57, 78, 23, 41, 218, 192, 141, 89, 104, 113, 133, 43, 192, 97, 251, 123, 96, 225, 12, 11, 101, 180, 48, 78, 130, 133, 48, 108, 183, 17, 80, 12, 236, 26, 248, 190, 56, 104, 89, 8, 43, 11, 97, 86, 57, 150, 64, 174, 117, 131, 21, 128, 69, 20, 22, 128, 69, 4, 10, 64, 184, 46, 223, 212, 146, 140, 252, 20, 79, 88, 151, 14, 150, 112, 144, 210, 16, 216, 93, 232, 133, 30, 200, 201, 200, 99, 77, 181, 64, 236, 158, 90, 226, 136, 222, 141, 131, 21, 80, 136, 198, 41, 74, 174, 243, 129, 37, 123, 152, 18, 68, 26, 132, 196, 19, 82, 161, 2, 9, 32, 184, 186, 108, 104, 176, 64, 210, 2, 92, 131, 29, 180, 81, 0, 93, 191, 128, 106, 156, 53, 23, 108, 21, 4, 76, 5, 108, 21, 4, 22, 117, 96, 227, 161, 107, 34, 64, 129, 157, 141, 188, 6, 3, 30, 196, 168, 109, 202, 90, 120, 50, 2, 133, 32, 176, 118, 38, 212, 62, 67, 14, 78, 80, 235, 12, 61, 101, 64, 150, 136, 249, 36, 22, 151, 64, 86, 167, 161, 175, 51, 68, 74, 34, 174, 121, 197, 165, 69, 169, 80, 141, 232, 173, 46, 96, 240, 249, 35, 199, 194, 64, 117, 17, 82, 245, 210, 160, 254, 81, 2, 27, 15, 11, 101, 88, 55, 1, 182, 156, 16, 109, 57, 33, 220, 6, 92, 189, 4, 244, 229, 132, 52, 232, 36, 128, 35, 31, 52, 64, 137, 109, 72, 17, 87, 79, 1, 125, 169, 33, 44, 222, 209, 151, 26, 162, 247, 13, 96, 94, 135, 101, 101, 216, 194, 86, 88, 79, 0, 57, 169, 33, 187, 152, 216, 212, 6, 75, 85, 184, 210, 92, 94, 10, 100, 158, 26, 182, 192, 21, 150, 240, 6, 75, 194, 67, 79, 22, 132, 198, 205, 113, 165, 69, 36, 127, 162, 148, 102, 195, 36, 85, 102, 18, 155, 252, 96, 75, 20, 97, 43, 93, 209, 19, 31, 122, 186, 131, 205, 67, 195, 18, 28, 161, 226, 13, 53, 73, 105, 90, 35, 82, 157, 10, 66, 77, 88, 98, 78, 41, 116, 179, 40, 185, 169, 140, 184, 180, 85, 148, 138, 107, 237, 10, 104, 237, 138, 33, 80, 77, 45, 244, 2, 146, 124, 196, 5, 36, 40, 14, 133, 28, 236, 164, 84, 6, 102, 40, 33, 251, 7, 161, 202, 51, 47, 57, 167, 52, 37, 181, 24, 121, 157, 11, 112, 25, 6, 98, 145, 35, 208, 119, 208, 180, 12, 138, 39, 69, 207, 98, 255, 36, 98, 135, 245, 97, 94, 192, 85, 193, 195, 180, 193, 42, 120, 244, 10, 94, 161, 4, 210, 195, 129, 45, 19, 65, 95, 38, 130, 107, 41, 38, 170, 207, 144, 178, 12, 180, 1, 0, 107, 0, 192, 98, 6, 117, 244, 31, 41, 74, 161, 124, 88, 139, 0, 61, 158, 96, 101, 0, 122, 87, 31, 230, 115, 216, 240, 7, 82, 166, 66, 233, 129, 192, 150, 99, 66, 27, 12, 214, 232, 173, 6, 141, 60, 72, 75, 1, 214, 14, 32, 180, 70, 18, 86, 154, 67, 219, 3, 48, 125, 10, 176, 105, 87, 228, 220, 81, 158, 145, 153, 147, 10, 81, 8, 212, 13, 81, 10, 209, 27, 156, 152, 11, 185, 244, 42, 42, 181, 40, 31, 37, 89, 148, 64, 242, 31, 70, 206, 67, 27, 254, 1, 186, 73, 91, 27, 196, 133, 229, 66, 164, 113, 32, 112, 18, 132, 37, 65, 104, 104, 6, 151, 36, 150, 100, 38, 131, 207, 157, 43, 206, 47, 45, 74, 78, 213, 81, 200, 77, 44, 72, 203, 83, 64, 234, 142, 192, 139, 0, 100, 65, 88, 30, 44, 82, 112, 70, 138, 176, 204, 52, 112, 50, 117, 206, 207, 131, 111, 35, 119, 134, 56, 25, 189, 56, 4, 22, 135, 38, 240, 171, 179, 156, 225, 41, 164, 12, 186, 172, 33, 51, 47, 29, 102, 30, 196, 61, 138, 208, 126, 6, 204, 114, 88, 144, 129, 173, 75, 204, 201, 1, 21, 193, 32, 165, 176, 161, 67, 5, 52, 27, 177, 22, 192, 134, 96, 223, 130, 199, 13, 17, 33, 8, 177, 31, 116, 109, 45, 56, 108, 209, 34, 29, 73, 26, 37, 133, 193, 214, 137, 192, 194, 10, 150, 158, 74, 139, 33, 247, 5, 195, 134, 121, 32, 161, 28, 237, 158, 138, 118, 0, 143, 82, 38, 84, 141, 146, 102, 44, 72, 47, 200, 107, 40, 122, 81, 67, 64, 65, 77, 13, 205, 104, 69, 200, 128, 64, 14, 142, 176, 65, 53, 12, 126, 164, 16, 70, 24, 153, 27, 162, 134, 17, 176, 233, 4, 117, 51, 106, 32, 129, 141, 135, 6, 5, 210, 241, 79, 142, 69, 69, 137, 149, 168, 209, 15, 145, 133, 150, 92, 48, 163, 224, 214, 131, 204, 129, 50, 21, 208, 3, 11, 232, 35, 21, 152, 169, 176, 50, 21, 104, 26, 76, 57, 138, 157, 48, 147, 145, 229, 145, 11, 238, 162, 0, 88, 165, 238, 95, 80, 146, 153, 155, 9, 238, 22, 107, 104, 66, 213, 34, 220, 163, 160, 0, 140, 26, 199, 146, 18, 244, 66, 10, 102, 190, 53, 84, 29, 190, 194, 9, 187, 218, 146, 196, 162, 244, 212, 18, 96, 56, 160, 156, 17, 130, 86, 239, 58, 235, 40, 56, 131, 231, 89, 224, 154, 209, 42, 115, 244, 113, 104, 36, 135, 43, 32, 172, 0, 46, 235, 129, 167, 53, 248, 16, 32, 56, 242, 96, 44, 88, 41, 9, 215, 2, 85, 3, 83, 65, 48, 98, 112, 198, 73, 64, 98, 114, 54, 213, 35, 133, 196, 0, 132, 164, 88, 61, 96, 40, 193, 122, 253, 96, 128, 20, 83, 158, 121, 153, 224, 3, 43, 145, 93, 11, 183, 0, 104, 0, 122, 12, 226, 15, 174, 90, 46, 152, 35, 33, 21, 62, 208, 133, 158, 208, 155, 253, 66, 242, 193, 59, 62, 33, 6, 234, 40, 192, 66, 18, 182, 196, 26, 166, 15, 156, 146, 160, 186, 161, 238, 134, 72, 66, 59, 246, 48, 151, 195, 114, 23, 122, 225, 138, 237, 44, 45, 80, 96, 192, 206, 210, 2, 157, 165, 165, 96, 132, 200, 195, 24, 129, 10, 77, 199, 232, 167, 123, 64, 83, 180, 51, 44, 81, 194, 18, 164, 6, 129, 4, 169, 128, 218, 225, 129, 120, 12, 41, 41, 162, 175, 95, 179, 133, 149, 171, 240, 16, 183, 71, 153, 52, 129, 197, 47, 80, 21, 202, 70, 86, 32, 13, 78, 47, 208, 65, 32, 136, 32, 208, 18, 244, 252, 128, 190, 204, 13, 22, 12, 56, 162, 22, 40, 131, 152, 185, 240, 201, 204, 78, 133, 221, 199, 14, 43, 196, 160, 217, 187, 12, 81, 8, 228, 67, 131, 10, 166, 5, 37, 249, 17, 29, 57, 100, 70, 10, 193, 40, 65, 143, 16, 152, 43, 97, 197, 3, 161, 24, 33, 53, 62, 208, 99, 131, 64, 92, 212, 194, 154, 43, 72, 241, 128, 210, 100, 129, 5, 3, 172, 201, 226, 159, 166, 1, 46, 32, 144, 163, 192, 177, 40, 189, 20, 185, 175, 4, 10, 25, 98, 155, 40, 213, 92, 24, 149, 33, 184, 137, 130, 222, 68, 129, 24, 152, 151, 90, 78, 229, 216, 129, 26, 9, 14, 28, 228, 33, 7, 141, 108, 136, 197, 240, 240, 129, 42, 132, 5, 14, 172, 139, 4, 115, 6, 116, 12, 88, 3, 104, 44, 82, 144, 130, 253, 142, 181, 203, 130, 174, 81, 71, 65, 9, 229, 234, 68, 136, 104, 172, 18, 172, 7, 3, 180, 14, 165, 104, 3, 22, 109, 153, 37, 169, 185, 64, 125, 185, 224, 126, 4, 208, 94, 228, 230, 116, 38, 172, 50, 135, 77, 129, 162, 229, 102, 176, 30, 29, 160, 50, 160, 17, 96, 143, 66, 163, 199, 31, 212, 92, 0, 25, 13, 209, 142, 43, 130, 204, 141, 209, 162, 165, 162, 4, 210, 157, 1, 218, 7, 179, 90, 47, 15, 233, 236, 254, 50, 88, 241, 28, 29, 11, 119, 34, 56, 78, 96, 205, 114, 216, 65, 190, 32, 235, 16, 134, 34, 102, 112, 225, 206, 135, 77, 120, 249, 66, 188, 0, 179, 14, 86, 166, 163, 250, 3, 164, 16, 234, 7, 108, 190, 48, 1, 134, 58, 80, 9, 104, 200, 11, 86, 46, 65, 141, 0, 105, 212, 75, 201, 207, 75, 133, 105, 134, 157, 254, 139, 164, 206, 5, 220, 36, 116, 73, 44, 73, 12, 128, 30, 118, 168, 1, 241, 38, 208, 81, 218, 218, 144, 169, 55, 61, 216, 169, 35, 72, 73, 41, 15, 18, 26, 224, 148, 1, 143, 91, 164, 38, 15, 120, 29, 17, 174, 117, 68, 232, 249, 9, 182, 142, 8, 253, 76, 106, 216, 129, 175, 208, 46, 184, 166, 130, 45, 106, 59, 21, 230, 20, 92, 253, 84, 36, 237, 224, 144, 198, 213, 81, 37, 176, 190, 8, 221, 91, 74, 92, 40, 29, 211, 204, 52, 244, 163, 62, 160, 174, 197, 72, 117, 176, 83, 62, 96, 58, 225, 165, 15, 114, 200, 57, 85, 150, 164, 162, 244, 83, 203, 18, 97, 227, 214, 176, 37, 72, 176, 174, 40, 250, 18, 36, 232, 164, 180, 2, 108, 114, 4, 125, 25, 18, 250, 244, 8, 108, 61, 15, 108, 98, 4, 166, 24, 54, 53, 130, 107, 106, 4, 125, 25, 18, 204, 137, 4, 166, 119, 114, 136, 93, 134, 132, 62, 171, 67, 200, 217, 196, 206, 231, 160, 45, 67, 82, 200, 75, 45, 247, 1, 5, 63, 76, 57, 108, 29, 18, 120, 29, 18, 36, 44, 193, 107, 145, 160, 202, 147, 33, 101, 81, 112, 65, 106, 114, 102, 42, 114, 63, 85, 195, 95, 7, 235, 109, 101, 69, 26, 200, 105, 71, 73, 19, 217, 226, 120, 160, 73, 201, 104, 13, 81, 88, 26, 6, 159, 220, 170, 3, 182, 79, 7, 236, 72, 36, 55, 103, 22, 67, 146, 48, 40, 144, 97, 125, 72, 152, 153, 16, 123, 172, 185, 32, 105, 82, 3, 46, 2, 84, 234, 94, 154, 88, 148, 130, 154, 161, 128, 210, 241, 154, 154, 200, 125, 63, 160, 70, 176, 86, 88, 114, 134, 39, 103, 132, 81, 208, 100, 13, 73, 216, 69, 208, 132, 93, 4, 77, 216, 154, 208, 146, 5, 189, 215, 11, 215, 13, 61, 198, 4, 185, 148, 3, 123, 7, 90, 1, 193, 92, 70, 148, 109, 38, 72, 182, 41, 160, 4, 11, 172, 231, 173, 0, 235, 135, 192, 22, 94, 192, 194, 23, 38, 70, 108, 41, 1, 243, 1, 108, 38, 14, 12, 148, 208, 3, 41, 36, 35, 19, 58, 102, 165, 160, 0, 233, 134, 16, 27, 86, 208, 8, 131, 123, 27, 60, 65, 239, 143, 179, 0, 49, 213, 68, 46, 64, 18, 147, 75, 74, 19, 115, 124, 82, 145, 6, 191, 97, 131, 223, 216, 75, 21, 68, 232, 194, 82, 10, 194, 8, 27, 104, 114, 195, 105, 183, 25, 44, 65, 234, 32, 44, 214, 68, 47, 9, 97, 161, 2, 43, 9, 113, 25, 102, 129, 226, 145, 228, 210, 162, 162, 212, 188, 18, 160, 129, 176, 2, 17, 195, 233, 254, 112, 39, 67, 10, 58, 27, 152, 38, 136, 147, 97, 213, 46, 250, 250, 66, 240, 180, 46, 208, 223, 96, 119, 35, 105, 129, 101, 114, 104, 92, 56, 34, 236, 116, 206, 47, 168, 116, 73, 44, 73, 68, 4, 150, 142, 130, 129, 142, 130, 191, 14, 180, 84, 128, 216, 160, 131, 72, 118, 96, 35, 80, 27, 90, 78, 165, 176, 131, 183, 97, 21, 164, 2, 182, 36, 163, 161, 169, 0, 111, 109, 161, 169, 128, 141, 111, 106, 162, 24, 162, 130, 228, 78, 72, 139, 141, 216, 22, 27, 186, 78, 34, 155, 108, 42, 193, 25, 137, 69, 200, 169, 137, 84, 107, 113, 233, 39, 198, 114, 76, 189, 57, 153, 232, 45, 11, 46, 5, 210, 90, 22, 41, 33, 249, 40, 198, 146, 219, 190, 64, 55, 4, 87, 249, 65, 84, 43, 3, 139, 71, 145, 219, 26, 10, 10, 181, 92, 10, 10, 240, 22, 3, 74, 184, 192, 178, 9, 106, 54, 41, 75, 132, 85, 202, 176, 118, 3, 185, 237, 6, 88, 187, 1, 87, 5, 60, 82, 218, 13, 48, 75, 113, 181, 27, 168, 213, 110, 40, 210, 64, 77, 13, 148, 182, 30, 224, 46, 135, 86, 147, 216, 91, 15, 254, 73, 89, 240, 166, 3, 132, 139, 150, 93, 144, 157, 163, 1, 114, 4, 122, 142, 193, 168, 212, 113, 104, 131, 41, 198, 168, 95, 204, 12, 144, 106, 117, 5, 5, 152, 115, 97, 181, 122, 42, 68, 46, 15, 230, 56, 144, 97, 32, 33, 88, 5, 10, 147, 0, 186, 201, 95, 161, 166, 6, 51, 143, 20, 251, 166, 230, 230, 23, 85, 6, 39, 230, 166, 66, 21, 235, 40, 248, 195, 157, 3, 175, 159, 96, 142, 49, 69, 201, 119, 152, 21, 109, 14, 180, 162, 69, 247, 39, 44, 51, 194, 170, 91, 160, 61, 96, 147, 96, 117, 45, 161, 186, 22, 106, 189, 25, 44, 250, 208, 235, 90, 160, 139, 80, 252, 6, 171, 178, 96, 85, 22, 200, 66, 80, 125, 5, 175, 175, 96, 6, 161, 85, 88, 224, 202, 170, 40, 79, 1, 125, 84, 0, 54, 100, 130, 52, 54, 1, 10, 50, 144, 24, 248, 100, 95, 216, 73, 205, 121, 233, 176, 147, 154, 173, 161, 105, 29, 210, 164, 133, 36, 98, 96, 48, 57, 67, 120, 176, 51, 254, 225, 102, 226, 56, 31, 24, 215, 112, 136, 6, 194, 84, 132, 189, 56, 156, 27, 146, 31, 148, 10, 222, 60, 148, 162, 161, 169, 80, 13, 9, 116, 88, 77, 0, 155, 253, 132, 205, 126, 194, 52, 193, 102, 63, 97, 165, 62, 254, 82, 31, 161, 13, 54, 251, 137, 171, 184, 135, 205, 107, 162, 187, 12, 86, 168, 67, 163, 18, 62, 179, 9, 139, 79, 88, 205, 15, 116, 19, 56, 92, 209, 234, 182, 50, 88, 37, 128, 228, 109, 148, 146, 31, 164, 192, 17, 73, 26, 35, 18, 253, 33, 229, 25, 250, 108, 63, 250, 240, 18, 44, 64, 192, 5, 109, 81, 126, 46, 124, 61, 64, 54, 120, 77, 0, 23, 178, 92, 88, 98, 78, 41, 100, 117, 10, 136, 7, 89, 160, 2, 219, 34, 12, 151, 135, 250, 24, 22, 194, 142, 56, 226, 16, 20, 243, 26, 153, 121, 41, 169, 21, 58, 10, 224, 177, 135, 1, 143, 73, 212, 149, 106, 10, 10, 40, 39, 213, 194, 227, 24, 226, 114, 218, 199, 46, 172, 94, 135, 45, 75, 131, 213, 235, 232, 235, 216, 96, 157, 3, 216, 178, 51, 216, 138, 54, 152, 86, 216, 138, 54, 104, 104, 193, 21, 131, 140, 68, 181, 194, 26, 220, 165, 131, 117, 233, 48, 212, 66, 219, 2, 24, 58, 160, 174, 128, 156, 128, 11, 10, 9, 136, 151, 16, 71, 230, 66, 138, 69, 216, 145, 185, 240, 35, 115, 161, 60, 216, 145, 185, 176, 16, 199, 117, 100, 46, 204, 97, 48, 117, 184, 142, 204, 229, 66, 235, 104, 160, 7, 50, 250, 42, 102, 216, 169, 13, 176, 73, 126, 88, 1, 14, 243, 57, 108, 241, 30, 76, 8, 26, 160, 112, 243, 81, 139, 246, 160, 196, 188, 116, 120, 63, 202, 8, 217, 69, 232, 153, 21, 86, 226, 194, 50, 43, 169, 153, 21, 150, 225, 64, 1, 1, 82, 106, 107, 139, 226, 68, 123, 104, 32, 89, 193, 54, 157, 144, 155, 83, 19, 43, 67, 242, 131, 243, 139, 74, 82, 83, 52, 146, 243, 115, 11, 18, 139, 82, 211, 192, 94, 6, 7, 20, 66, 8, 99, 254, 29, 214, 82, 64, 158, 127, 71, 50, 1, 62, 7, 15, 171, 18, 97, 85, 34, 250, 28, 60, 104, 126, 25, 73, 27, 124, 30, 30, 22, 174, 176, 124, 133, 107, 137, 79, 6, 82, 134, 4, 69, 51, 84, 23, 48, 68, 81, 23, 146, 1, 171, 248, 20, 144, 70, 88, 58, 65, 203, 140, 84, 139, 61, 88, 60, 32, 118, 3, 213, 130, 195, 18, 178, 78, 197, 78, 193, 16, 166, 42, 25, 24, 104, 110, 192, 216, 128, 95, 52, 134, 176, 62, 190, 56, 191, 168, 4, 184, 145, 13, 57, 100, 240, 70, 102, 120, 106, 98, 182, 111, 98, 1, 82, 85, 237, 153, 151, 9, 25, 61, 7, 197, 11, 200, 74, 136, 55, 115, 19, 11, 208, 138, 169, 196, 148, 148, 212, 34, 200, 124, 140, 94, 113, 106, 9, 44, 47, 43, 34, 197, 42, 88, 9, 44, 70, 49, 227, 19, 54, 69, 2, 49, 10, 230, 80, 88, 72, 65, 198, 207, 61, 75, 82, 115, 177, 93, 206, 134, 112, 34, 204, 120, 88, 5, 1, 27, 55, 135, 232, 133, 75, 99, 164, 39, 19, 83, 29, 5, 37, 176, 255, 33, 199, 129, 192, 146, 143, 2, 218, 128, 61, 56, 160, 32, 94, 1, 47, 250, 208, 129, 187, 43, 218, 32, 22, 137, 99, 24, 11, 241, 1, 122, 240, 6, 167, 150, 224, 13, 94, 216, 237, 129, 56, 130, 23, 40, 163, 7, 100, 211, 40, 120, 195, 18, 115, 208, 47, 191, 195, 21, 190, 120, 66, 165, 56, 21, 216, 200, 132, 25, 7, 43, 110, 107, 1, 27, 8, 248, 46 }; + static const unsigned char data[] = { 120, 156, 75, 43, 205, 75, 46, 201, 204, 207, 83, 200, 75, 45, 143, 15, 74, 77, 206, 47, 74, 209, 208, 84, 168, 230, 82, 80, 40, 74, 45, 41, 45, 202, 83, 40, 46, 73, 137, 247, 79, 202, 74, 77, 46, 137, 79, 46, 74, 77, 44, 73, 213, 200, 43, 205, 201, 209, 180, 230, 170, 229, 130, 235, 13, 201, 119, 202, 207, 207, 73, 77, 204, 211, 40, 67, 209, 171, 168, 88, 134, 166, 206, 175, 52, 55, 41, 181, 8, 77, 153, 54, 170, 170, 224, 196, 220, 212, 176, 196, 156, 210, 212, 168, 212, 162, 124, 141, 10, 29, 133, 74, 20, 213, 21, 10, 182, 182, 182, 10, 149, 10, 53, 53, 10, 26, 21, 10, 138, 64, 118, 133, 130, 154, 26, 80, 64, 17, 36, 140, 234, 48, 247, 212, 18, 223, 212, 146, 140, 252, 20, 141, 48, 29, 133, 0, 136, 49, 214, 214, 64, 162, 44, 177, 72, 1, 164, 74, 193, 86, 33, 44, 58, 32, 22, 36, 148, 153, 166, 160, 225, 89, 236, 7, 244, 156, 127, 81, 104, 94, 74, 106, 90, 102, 94, 106, 138, 6, 72, 145, 38, 68, 35, 220, 5, 165, 48, 89, 144, 182, 90, 168, 86, 69, 207, 98, 231, 196, 156, 156, 196, 164, 156, 84, 84, 77, 33, 25, 69, 249, 229, 33, 149, 5, 169, 174, 69, 69, 249, 69, 26, 134, 70, 58, 10, 37, 64, 94, 126, 26, 216, 1, 154, 80, 51, 96, 102, 131, 196, 80, 188, 224, 89, 28, 80, 148, 95, 144, 90, 84, 82, 233, 157, 90, 169, 145, 88, 148, 94, 154, 155, 154, 87, 2, 52, 28, 226, 11, 176, 89, 64, 95, 64, 141, 132, 201, 91, 195, 77, 132, 42, 0, 134, 141, 82, 113, 73, 81, 102, 94, 186, 18, 40, 228, 144, 4, 43, 115, 147, 242, 115, 148, 80, 99, 160, 32, 53, 57, 51, 181, 216, 57, 63, 15, 168, 165, 52, 185, 4, 232, 236, 252, 164, 44, 29, 5, 160, 183, 19, 75, 115, 74, 144, 196, 209, 130, 20, 36, 4, 116, 12, 80, 177, 94, 50, 66, 17, 44, 116, 65, 108, 144, 165, 136, 0, 68, 13, 88, 44, 230, 91, 163, 134, 48, 36, 33, 130, 13, 194, 21, 190, 166, 102, 58, 10, 74, 249, 73, 32, 117, 234, 197, 10, 234, 72, 206, 80, 87, 40, 128, 134, 164, 18, 60, 212, 65, 142, 46, 6, 186, 24, 228, 240, 104, 247, 212, 18, 167, 210, 204, 156, 146, 204, 188, 96, 112, 160, 104, 40, 21, 67, 2, 66, 73, 19, 103, 10, 73, 209, 40, 70, 73, 30, 4, 125, 225, 137, 18, 172, 24, 154, 139, 161, 106, 209, 189, 5, 86, 99, 104, 162, 3, 166, 149, 28, 28, 160, 46, 83, 128, 121, 73, 1, 24, 249, 112, 95, 35, 121, 90, 9, 168, 1, 57, 79, 128, 242, 68, 9, 194, 88, 61, 61, 189, 196, 162, 244, 98, 136, 35, 74, 138, 42, 21, 32, 142, 73, 78, 204, 201, 113, 131, 106, 208, 40, 46, 73, 137, 135, 113, 226, 19, 11, 10, 114, 42, 117, 208, 92, 167, 131, 136, 81, 29, 5, 176, 121, 224, 240, 5, 26, 83, 146, 156, 161, 160, 145, 138, 230, 199, 84, 152, 31, 173, 209, 29, 230, 152, 158, 94, 148, 154, 158, 88, 66, 13, 215, 161, 154, 69, 53, 39, 122, 230, 149, 164, 22, 229, 37, 230, 80, 193, 133, 200, 70, 81, 201, 129, 126, 165, 72, 22, 3, 181, 32, 73, 57, 231, 23, 84, 186, 36, 150, 36, 66, 139, 147, 204, 212, 98, 141, 18, 160, 61, 169, 37, 58, 10, 197, 249, 165, 69, 201, 169, 58, 10, 169, 21, 201, 57, 165, 41, 169, 41, 158, 37, 169, 185, 80, 63, 89, 91, 67, 8, 92, 169, 31, 162, 21, 45, 21, 3, 149, 195, 115, 87, 90, 81, 126, 46, 48, 131, 133, 228, 67, 242, 46, 76, 3, 172, 196, 200, 78, 173, 44, 6, 74, 99, 58, 206, 191, 8, 24, 216, 254, 229, 121, 222, 169, 149, 8, 135, 130, 12, 67, 119, 38, 204, 109, 16, 147, 128, 165, 11, 184, 126, 194, 234, 158, 180, 252, 34, 5, 13, 144, 173, 153, 121, 41, 169, 21, 64, 107, 13, 172, 161, 76, 27, 176, 67, 244, 114, 82, 243, 210, 75, 50, 160, 130, 218, 218, 16, 83, 224, 14, 5, 106, 0, 169, 138, 6, 203, 198, 90, 131, 165, 128, 54, 131, 243, 38, 16, 40, 102, 36, 22, 251, 151, 231, 1, 29, 2, 140, 96, 180, 160, 84, 83, 131, 42, 66, 79, 25, 176, 186, 21, 150, 143, 61, 139, 93, 243, 74, 115, 83, 139, 18, 147, 114, 82, 161, 254, 5, 89, 170, 9, 214, 14, 116, 15, 212, 24, 23, 112, 240, 35, 133, 88, 37, 60, 140, 192, 214, 131, 52, 70, 3, 89, 177, 224, 224, 1, 250, 30, 28, 2, 181, 92, 105, 184, 82, 67, 106, 113, 104, 94, 90, 102, 78, 73, 106, 81, 106, 10, 114, 186, 40, 74, 134, 166, 60, 107, 72, 56, 99, 41, 1, 161, 81, 138, 90, 12, 210, 58, 13, 64, 27, 33, 3, 29, 245, 228, 70, 39, 44, 172, 168, 16, 147, 249, 165, 192, 72, 211, 0, 25, 8, 242, 51, 172, 17, 1, 150, 3, 122, 38, 15, 42, 135, 84, 116, 40, 165, 229, 231, 43, 129, 195, 5, 169, 108, 203, 83, 112, 44, 42, 74, 172, 116, 45, 75, 45, 170, 4, 251, 42, 41, 49, 57, 59, 45, 79, 65, 19, 222, 208, 240, 71, 142, 193, 146, 140, 204, 98, 120, 252, 1, 131, 78, 1, 36, 231, 3, 14, 66, 13, 127, 104, 88, 194, 163, 199, 17, 218, 40, 41, 134, 42, 208, 4, 199, 149, 1, 216, 104, 244, 6, 82, 145, 134, 169, 169, 142, 130, 129, 142, 130, 18, 216, 61, 122, 192, 128, 44, 201, 47, 1, 74, 234, 165, 130, 156, 6, 175, 185, 209, 219, 92, 72, 110, 6, 7, 46, 142, 150, 151, 75, 106, 114, 126, 110, 65, 102, 78, 42, 208, 77, 26, 64, 91, 146, 17, 186, 32, 38, 67, 189, 20, 2, 244, 16, 166, 179, 237, 20, 12, 21, 236, 193, 245, 20, 84, 74, 195, 80, 83, 193, 10, 92, 112, 195, 218, 131, 176, 132, 86, 164, 144, 13, 78, 100, 64, 202, 6, 20, 64, 64, 6, 56, 81, 193, 82, 142, 70, 54, 48, 114, 20, 252, 225, 233, 0, 226, 31, 144, 115, 156, 243, 243, 74, 128, 70, 195, 82, 21, 146, 199, 116, 20, 66, 116, 20, 252, 163, 179, 99, 117, 20, 178, 129, 12, 164, 68, 164, 160, 0, 139, 249, 196, 156, 226, 84, 144, 51, 96, 73, 5, 150, 96, 224, 42, 74, 138, 74, 83, 65, 241, 30, 156, 90, 226, 89, 236, 153, 151, 147, 153, 7, 10, 62, 159, 196, 162, 244, 84, 184, 149, 192, 160, 135, 38, 5, 96, 160, 164, 129, 69, 97, 9, 36, 56, 63, 23, 57, 172, 7, 81, 250, 40, 6, 186, 108, 248, 38, 15, 160, 24, 216, 15, 176, 212, 65, 106, 234, 128, 197, 61, 254, 196, 145, 150, 152, 83, 76, 92, 234, 8, 6, 134, 54, 70, 226, 112, 203, 47, 114, 77, 76, 206, 64, 114, 148, 194, 96, 73, 31, 169, 122, 105, 16, 199, 13, 211, 36, 2, 4, 164, 37, 15, 107, 108, 241, 143, 112, 7, 172, 132, 240, 204, 195, 94, 66, 32, 69, 55, 70, 25, 225, 155, 88, 0, 183, 24, 86, 133, 128, 195, 196, 95, 193, 150, 222, 69, 4, 74, 21, 146, 155, 88, 48, 216, 163, 31, 162, 219, 17, 168, 219, 57, 49, 207, 191, 160, 36, 51, 55, 179, 42, 21, 236, 15, 104, 167, 92, 3, 24, 227, 246, 224, 81, 25, 176, 168, 6, 48, 160, 64, 70, 32, 43, 113, 46, 74, 77, 44, 73, 213, 240, 215, 1, 5, 171, 38, 37, 73, 10, 212, 250, 1, 6, 90, 65, 106, 74, 88, 98, 78, 105, 42, 80, 51, 200, 191, 206, 249, 121, 37, 196, 38, 50, 92, 205, 85, 13, 71, 176, 18, 36, 195, 177, 167, 72, 71, 162, 234, 42, 223, 196, 2, 180, 154, 10, 88, 24, 129, 91, 179, 131, 51, 33, 166, 101, 130, 220, 54, 28, 210, 34, 208, 136, 232, 88, 156, 233, 207, 64, 19, 61, 245, 129, 130, 163, 36, 159, 244, 84, 152, 13, 77, 128, 224, 212, 5, 50, 20, 170, 24, 28, 84, 206, 249, 121, 184, 18, 164, 66, 136, 14, 84, 47, 106, 181, 8, 75, 150, 232, 201, 210, 17, 228, 60, 109, 109, 152, 38, 77, 152, 85, 181, 200, 137, 83, 161, 40, 149, 216, 196, 9, 75, 136, 69, 64, 147, 210, 128, 194, 136, 244, 25, 148, 154, 82, 154, 12, 143, 234, 193, 149, 62, 139, 82, 129, 110, 195, 219, 154, 66, 79, 159, 228, 166, 79, 120, 178, 128, 121, 48, 49, 57, 185, 52, 183, 52, 39, 17, 58, 108, 134, 238, 39, 88, 218, 53, 132, 218, 139, 172, 30, 104, 140, 59, 114, 114, 134, 88, 162, 144, 154, 83, 156, 10, 85, 156, 153, 166, 160, 1, 14, 65, 120, 152, 128, 65, 9, 200, 237, 24, 97, 99, 4, 210, 15, 139, 122, 136, 67, 3, 138, 82, 139, 129, 70, 3, 45, 130, 53, 180, 129, 32, 37, 31, 110, 80, 102, 26, 122, 234, 5, 2, 100, 109, 240, 22, 24, 24, 36, 21, 165, 38, 102, 67, 184, 48, 107, 106, 21, 202, 51, 128, 33, 166, 160, 161, 173, 13, 45, 164, 33, 174, 128, 68, 1, 204, 36, 77, 5, 98, 157, 142, 30, 68, 224, 12, 164, 173, 29, 139, 210, 47, 182, 86, 200, 70, 175, 16, 112, 120, 6, 201, 40, 72, 101, 128, 94, 25, 104, 192, 60, 135, 20, 219, 58, 112, 49, 120, 225, 2, 23, 66, 54, 17, 33, 8, 170, 66, 16, 188, 108, 36, 9, 40, 75, 19, 230, 63, 88, 126, 44, 41, 45, 202, 67, 54, 203, 154, 171, 22, 107, 126, 11, 202, 76, 207, 40, 25, 205, 116, 224, 76, 7, 246, 151, 174, 130, 33, 45, 179, 94, 113, 42, 68, 49, 208, 52, 148, 172, 7, 75, 191, 132, 210, 47, 161, 172, 7, 51, 8, 108, 126, 54, 74, 106, 5, 103, 61, 82, 179, 30, 48, 235, 105, 232, 234, 102, 43, 216, 217, 66, 42, 47, 88, 206, 131, 25, 68, 172, 203, 97, 57, 15, 45, 231, 233, 234, 162, 229, 60, 5, 136, 85, 192, 202, 80, 87, 23, 100, 54, 46, 175, 16, 155, 241, 20, 208, 50, 158, 2, 145, 25, 15, 150, 191, 96, 25, 79, 1, 154, 241, 96, 76, 88, 198, 131, 123, 143, 64, 198, 131, 85, 116, 69, 137, 149, 110, 153, 121, 41, 26, 5, 69, 169, 41, 153, 201, 137, 37, 169, 52, 206, 112, 92, 68, 102, 56, 112, 43, 12, 232, 48, 156, 217, 13, 225, 98, 77, 108, 198, 226, 200, 109, 112, 77, 176, 204, 134, 222, 27, 64, 203, 74, 24, 45, 48, 244, 22, 24, 161, 150, 59, 174, 246, 17, 174, 214, 81, 126, 30, 194, 99, 216, 26, 71, 213, 208, 120, 134, 70, 44, 72, 22, 60, 102, 128, 17, 231, 200, 206, 172, 229, 10, 38, 212, 66, 119, 3, 134, 53, 114, 19, 8, 46, 232, 9, 52, 166, 2, 225, 166, 145, 158, 60, 168, 157, 60, 136, 77, 7, 176, 94, 27, 44, 21, 160, 166, 2, 204, 4, 0, 20, 213, 53, 36, 34, 230, 145, 34, 25, 35, 250, 157, 243, 11, 42, 195, 51, 129, 49, 155, 7, 31, 242, 46, 6, 50, 128, 84, 106, 94, 138, 130, 45, 216, 167, 176, 105, 98, 114, 211, 4, 76, 30, 232, 232, 156, 196, 146, 204, 178, 212, 16, 176, 77, 96, 165, 158, 192, 240, 72, 79, 45, 130, 90, 14, 83, 9, 238, 158, 128, 252, 139, 174, 197, 70, 193, 0, 18, 44, 208, 254, 183, 111, 98, 73, 70, 124, 110, 98, 5, 184, 90, 211, 70, 83, 173, 163, 96, 160, 9, 85, 109, 133, 164, 26, 232, 85, 84, 117, 176, 62, 58, 170, 35, 131, 129, 78, 66, 117, 35, 40, 96, 16, 78, 4, 77, 168, 160, 58, 18, 170, 133, 160, 27, 17, 138, 241, 59, 17, 174, 12, 135, 11, 93, 65, 49, 4, 137, 39, 91, 164, 152, 82, 176, 7, 169, 6, 154, 135, 112, 121, 42, 56, 227, 67, 221, 157, 153, 151, 152, 131, 226, 112, 176, 73, 68, 56, 27, 166, 148, 144, 163, 161, 138, 144, 157, 156, 156, 95, 10, 106, 0, 160, 170, 134, 184, 68, 23, 28, 146, 32, 229, 160, 134, 80, 73, 190, 166, 53, 52, 167, 167, 129, 2, 216, 6, 40, 162, 160, 166, 6, 34, 109, 192, 10, 129, 78, 1, 27, 6, 205, 32, 208, 104, 64, 145, 130, 181, 167, 20, 32, 189, 92, 32, 129, 33, 81, 158, 145, 153, 147, 170, 160, 1, 17, 181, 131, 21, 75, 208, 156, 10, 182, 25, 169, 238, 135, 214, 190, 209, 37, 249, 177, 224, 194, 29, 36, 13, 42, 223, 193, 160, 86, 33, 21, 214, 192, 130, 128, 148, 212, 156, 212, 146, 84, 176, 114, 132, 34, 48, 13, 113, 172, 174, 46, 76, 180, 36, 31, 206, 134, 184, 15, 198, 173, 133, 52, 220, 96, 230, 14, 168, 115, 181, 181, 17, 206, 133, 178, 209, 157, 139, 86, 38, 249, 163, 55, 63, 192, 221, 239, 28, 141, 178, 196, 156, 210, 84, 80, 241, 2, 201, 87, 6, 52, 43, 98, 8, 229, 94, 104, 89, 205, 5, 203, 1, 48, 245, 232, 89, 23, 87, 30, 24, 41, 89, 23, 169, 125, 108, 3, 177, 27, 82, 167, 65, 83, 143, 127, 116, 118, 172, 130, 45, 208, 97, 208, 214, 73, 45, 162, 90, 242, 7, 183, 64, 97, 73, 192, 185, 40, 53, 177, 36, 213, 177, 168, 40, 177, 210, 179, 36, 181, 40, 17, 190, 150, 41, 59, 51, 15, 41, 210, 51, 193, 114, 169, 41, 224, 104, 7, 197, 29, 172, 146, 1, 41, 6, 57, 7, 174, 10, 218, 150, 247, 75, 45, 71, 53, 20, 172, 40, 52, 175, 56, 49, 45, 53, 56, 181, 36, 40, 181, 56, 181, 168, 44, 53, 37, 56, 39, 191, 68, 3, 166, 13, 24, 0, 58, 104, 54, 17, 165, 203, 16, 168, 145, 40, 133, 70, 32, 111, 65, 226, 12, 22, 26, 48, 73, 244, 102, 57, 194, 229, 126, 169, 21, 37, 26, 154, 240, 144, 0, 250, 23, 232, 189, 146, 140, 204, 98, 112, 89, 8, 91, 119, 5, 15, 11, 208, 186, 59, 32, 3, 164, 200, 189, 52, 177, 40, 37, 36, 31, 35, 112, 53, 129, 237, 45, 196, 100, 60, 36, 197, 64, 92, 147, 156, 152, 147, 227, 6, 118, 5, 172, 195, 162, 160, 224, 12, 20, 67, 49, 2, 178, 98, 207, 51, 45, 188, 8, 56, 56, 12, 235, 177, 40, 128, 157, 4, 99, 43, 57, 162, 251, 64, 137, 11, 222, 59, 169, 133, 250, 36, 17, 232, 68, 72, 136, 185, 163, 132, 24, 216, 31, 176, 32, 133, 100, 140, 226, 210, 28, 80, 164, 87, 3, 185, 57, 165, 169, 72, 109, 44, 29, 96, 23, 51, 15, 40, 0, 238, 115, 42, 212, 194, 130, 36, 81, 1, 221, 131, 16, 51, 244, 64, 170, 81, 250, 154, 80, 143, 67, 164, 145, 92, 7, 93, 124, 128, 215, 133, 134, 72, 9, 47, 53, 215, 59, 19, 148, 99, 97, 234, 193, 11, 145, 140, 141, 220, 138, 242, 115, 49, 53, 26, 193, 53, 230, 164, 230, 193, 220, 236, 89, 28, 144, 95, 92, 156, 153, 148, 83, 9, 13, 216, 144, 74, 32, 1, 14, 72, 141, 68, 77, 152, 63, 128, 26, 128, 150, 224, 84, 233, 3, 46, 241, 128, 234, 65, 166, 130, 204, 69, 239, 212, 43, 192, 132, 113, 26, 225, 145, 88, 236, 146, 90, 146, 152, 156, 145, 154, 226, 84, 154, 150, 150, 90, 4, 182, 29, 166, 21, 189, 25, 173, 97, 102, 0, 241, 13, 180, 176, 135, 21, 249, 176, 170, 4, 230, 102, 164, 114, 57, 17, 84, 46, 3, 25, 144, 196, 0, 245, 61, 36, 184, 237, 108, 65, 138, 33, 182, 97, 207, 78, 176, 196, 1, 91, 97, 66, 106, 228, 226, 53, 213, 80, 71, 1, 226, 14, 109, 104, 220, 130, 226, 5, 18, 183, 208, 210, 216, 16, 45, 61, 149, 65, 123, 117, 137, 176, 149, 39, 184, 236, 197, 98, 150, 17, 204, 172, 178, 196, 34, 133, 130, 196, 204, 34, 160, 57, 16, 99, 116, 224, 230, 193, 13, 68, 182, 13, 172, 24, 143, 77, 214, 64, 6, 186, 22, 176, 113, 64, 113, 116, 29, 132, 186, 134, 104, 217, 24, 24, 42, 240, 82, 74, 5, 44, 11, 238, 128, 22, 107, 0, 253, 130, 48, 220, 185, 40, 21, 86, 168, 195, 203, 157, 146, 140, 204, 98, 80, 150, 129, 90, 233, 156, 152, 151, 159, 151, 153, 156, 152, 227, 151, 152, 155, 170, 129, 108, 148, 142, 130, 18, 216, 209, 197, 74, 200, 150, 129, 21, 184, 230, 149, 20, 101, 18, 111, 153, 17, 208, 0, 244, 82, 213, 59, 181, 146, 72, 253, 144, 18, 8, 93, 191, 91, 81, 126, 174, 99, 113, 101, 94, 178, 70, 34, 136, 4, 47, 31, 3, 79, 147, 165, 229, 33, 247, 136, 116, 192, 197, 161, 99, 81, 58, 122, 55, 9, 18, 219, 206, 240, 34, 28, 214, 95, 128, 154, 234, 156, 147, 95, 92, 90, 4, 138, 48, 176, 241, 10, 64, 167, 218, 218, 33, 37, 19, 160, 69, 5, 153, 121, 64, 83, 161, 86, 42, 194, 26, 247, 176, 14, 39, 36, 157, 193, 148, 169, 169, 41, 64, 71, 40, 65, 113, 11, 18, 134, 13, 78, 130, 65, 72, 70, 17, 44, 43, 195, 122, 196, 33, 249, 193, 224, 69, 101, 48, 181, 214, 92, 144, 140, 13, 115, 64, 105, 49, 208, 92, 176, 83, 97, 129, 5, 113, 43, 52, 40, 162, 209, 215, 232, 106, 40, 65, 36, 161, 138, 149, 52, 99, 17, 174, 196, 102, 22, 90, 177, 173, 128, 221, 66, 120, 144, 90, 99, 115, 94, 48, 30, 197, 184, 108, 134, 133, 36, 44, 166, 96, 214, 163, 15, 43, 96, 234, 196, 94, 56, 66, 66, 212, 220, 16, 17, 162, 72, 9, 6, 28, 172, 200, 37, 38, 162, 225, 13, 243, 50, 186, 39, 240, 6, 113, 38, 34, 116, 97, 6, 195, 124, 137, 102, 14, 70, 240, 162, 219, 134, 30, 100, 48, 119, 226, 50, 22, 87, 216, 225, 10, 61, 52, 173, 240, 192, 35, 53, 248, 96, 58, 96, 14, 171, 133, 166, 83, 98, 99, 88, 161, 166, 6, 197, 231, 56, 61, 2, 77, 89, 224, 105, 86, 160, 79, 144, 214, 134, 59, 107, 42, 216, 43, 192, 151, 114, 67, 71, 111, 224, 69, 167, 179, 142, 2, 80, 129, 149, 66, 52, 60, 74, 192, 195, 64, 176, 169, 52, 5, 5, 72, 11, 58, 177, 60, 49, 179, 4, 178, 232, 53, 47, 181, 162, 36, 12, 92, 92, 231, 167, 41, 0, 67, 44, 191, 28, 106, 38, 200, 121, 225, 153, 37, 25, 26, 112, 95, 35, 82, 3, 98, 188, 24, 213, 199, 176, 97, 99, 28, 113, 12, 149, 65, 4, 63, 172, 124, 129, 205, 247, 131, 42, 13, 132, 139, 172, 185, 96, 138, 144, 74, 23, 148, 168, 35, 180, 12, 33, 63, 15, 82, 162, 192, 10, 198, 116, 29, 132, 233, 58, 10, 217, 240, 24, 197, 48, 10, 26, 66, 48, 49, 152, 99, 16, 145, 14, 153, 41, 78, 133, 46, 96, 72, 132, 46, 96, 168, 132, 46, 96, 128, 233, 131, 205, 21, 131, 1, 56, 26, 178, 21, 180, 65, 61, 126, 84, 147, 28, 161, 125, 70, 160, 60, 100, 80, 13, 81, 199, 58, 130, 249, 72, 101, 77, 98, 81, 81, 98, 165, 79, 102, 118, 42, 82, 119, 68, 3, 17, 51, 80, 235, 208, 58, 166, 160, 214, 25, 92, 35, 208, 50, 88, 67, 8, 150, 202, 72, 77, 101, 192, 84, 166, 3, 50, 31, 180, 198, 164, 184, 36, 37, 30, 190, 232, 4, 106, 40, 90, 162, 131, 14, 22, 192, 166, 46, 21, 170, 145, 211, 38, 74, 136, 35, 188, 7, 30, 176, 134, 41, 67, 79, 34, 208, 180, 0, 15, 89, 123, 168, 238, 228, 196, 156, 28, 52, 199, 66, 170, 20, 104, 205, 88, 148, 14, 25, 218, 134, 196, 62, 92, 187, 21, 84, 16, 22, 199, 68, 199, 43, 122, 172, 194, 98, 10, 41, 70, 193, 141, 109, 88, 171, 9, 30, 163, 181, 136, 70, 17, 70, 53, 172, 1, 52, 26, 173, 1, 80, 233, 6, 84, 3, 108, 199, 161, 85, 251, 41, 176, 106, 31, 173, 218, 135, 151, 35, 232, 213, 62, 174, 218, 28, 166, 13, 84, 91, 129, 234, 42, 66, 117, 57, 52, 6, 225, 5, 39, 108, 108, 27, 109, 108, 219, 16, 234, 88, 80, 133, 14, 14, 25, 216, 184, 54, 204, 193, 48, 39, 129, 43, 80, 207, 146, 84, 88, 77, 144, 9, 173, 114, 8, 84, 57, 32, 135, 42, 34, 175, 60, 7, 123, 65, 3, 97, 26, 172, 172, 135, 213, 10, 72, 94, 65, 81, 5, 83, 133, 238, 41, 104, 109, 0, 247, 20, 116, 192, 62, 19, 86, 31, 192, 34, 156, 220, 108, 4, 47, 172, 161, 102, 192, 115, 13, 180, 160, 38, 182, 136, 134, 166, 12, 120, 48, 162, 121, 169, 12, 150, 129, 82, 32, 198, 216, 194, 50, 16, 23, 52, 255, 40, 216, 227, 203, 58, 33, 58, 168, 165, 38, 92, 151, 21, 76, 156, 96, 214, 209, 214, 198, 150, 121, 128, 65, 135, 181, 244, 43, 130, 149, 125, 176, 84, 131, 171, 220, 203, 132, 22, 121, 10, 68, 22, 120, 184, 227, 137, 11, 28, 10, 184, 226, 10, 86, 228, 1, 13, 2, 171, 132, 21, 123, 240, 98, 15, 58, 41, 167, 160, 1, 137, 67, 216, 66, 38, 216, 172, 139, 54, 52, 46, 80, 75, 188, 204, 18, 160, 235, 193, 229, 28, 161, 72, 34, 20, 69, 176, 41, 59, 88, 252, 160, 151, 106, 196, 150, 105, 176, 0, 135, 69, 9, 172, 248, 66, 138, 18, 148, 162, 9, 228, 255, 144, 252, 96, 240, 14, 66, 13, 160, 31, 145, 227, 10, 57, 158, 96, 3, 166, 10, 101, 240, 29, 150, 16, 69, 122, 89, 249, 153, 64, 243, 97, 185, 19, 145, 59, 65, 138, 52, 97, 161, 86, 132, 62, 78, 132, 186, 173, 162, 36, 31, 226, 2, 29, 5, 176, 153, 112, 95, 20, 165, 194, 180, 161, 7, 27, 216, 120, 132, 242, 90, 12, 47, 249, 228, 3, 117, 165, 66, 61, 150, 3, 230, 20, 235, 40, 228, 23, 128, 212, 20, 3, 157, 5, 237, 239, 34, 124, 139, 90, 198, 98, 77, 138, 192, 48, 133, 37, 67, 244, 117, 15, 40, 222, 84, 82, 130, 167, 123, 240, 8, 107, 81, 113, 137, 107, 78, 106, 46, 104, 189, 2, 52, 212, 162, 13, 98, 97, 22, 5, 129, 77, 67, 223, 128, 3, 46, 6, 145, 117, 194, 131, 50, 72, 193, 22, 100, 1, 218, 96, 9, 88, 24, 30, 145, 144, 244, 131, 45, 220, 80, 204, 212, 43, 201, 71, 14, 38, 29, 20, 167, 106, 162, 140, 188, 129, 157, 90, 156, 90, 144, 8, 43, 224, 149, 116, 192, 110, 64, 201, 50, 134, 184, 179, 76, 94, 106, 5, 70, 24, 100, 3, 195, 0, 226, 116, 109, 91, 132, 217, 16, 49, 28, 21, 3, 220, 24, 120, 128, 64, 13, 64, 247, 60, 46, 239, 195, 12, 192, 240, 61, 180, 97, 137, 228, 121, 184, 247, 65, 1, 128, 156, 30, 65, 81, 6, 75, 112, 176, 241, 12, 248, 210, 73, 136, 171, 160, 10, 75, 50, 50, 139, 33, 3, 23, 37, 104, 3, 23, 8, 61, 224, 145, 139, 244, 212, 18, 133, 104, 72, 29, 169, 7, 221, 2, 26, 139, 50, 142, 129, 190, 14, 19, 184, 14, 51, 191, 40, 51, 61, 51, 47, 17, 50, 200, 170, 163, 0, 73, 155, 176, 148, 13, 35, 160, 201, 20, 40, 3, 78, 169, 186, 176, 164, 170, 0, 19, 84, 48, 0, 199, 48, 44, 3, 123, 22, 67, 138, 68, 20, 195, 129, 65, 141, 156, 190, 65, 37, 39, 172, 228, 132, 101, 8, 68, 34, 129, 233, 132, 149, 206, 144, 228, 130, 98, 158, 94, 50, 66, 14, 150, 13, 156, 33, 138, 208, 181, 194, 252, 128, 94, 218, 43, 168, 169, 41, 120, 2, 67, 34, 191, 184, 56, 40, 53, 49, 39, 23, 108, 46, 138, 18, 226, 28, 13, 55, 222, 63, 41, 43, 53, 185, 4, 161, 13, 236, 32, 231, 104, 244, 22, 12, 250, 222, 97, 136, 118, 103, 5, 80, 224, 34, 212, 34, 59, 4, 50, 166, 173, 4, 53, 151, 144, 131, 128, 78, 66, 49, 21, 214, 239, 38, 86, 47, 204, 75, 48, 221, 176, 25, 220, 20, 34, 67, 3, 150, 10, 176, 7, 37, 90, 203, 202, 208, 68, 71, 65, 9, 41, 46, 129, 27, 177, 243, 209, 54, 98, 67, 173, 131, 43, 66, 47, 198, 97, 181, 50, 212, 13, 181, 104, 41, 222, 45, 39, 177, 196, 55, 177, 64, 3, 92, 197, 21, 193, 116, 41, 104, 42, 160, 207, 234, 193, 42, 169, 98, 77, 107, 136, 12, 116, 147, 163, 15, 106, 49, 14, 156, 219, 131, 88, 5, 203, 27, 72, 237, 73, 84, 75, 136, 108, 35, 131, 154, 147, 160, 26, 24, 85, 167, 53, 23, 44, 63, 144, 186, 8, 4, 22, 93, 48, 95, 80, 186, 74, 91, 65, 1, 20, 132, 192, 32, 247, 204, 43, 201, 7, 41, 3, 119, 132, 252, 117, 16, 193, 3, 84, 7, 28, 193, 70, 247, 131, 142, 66, 8, 88, 55, 122, 171, 1, 53, 106, 52, 168, 20, 19, 32, 85, 41, 169, 5, 37, 25, 126, 165, 185, 64, 69, 134, 176, 216, 193, 12, 55, 53, 53, 148, 64, 51, 208, 68, 237, 252, 192, 82, 57, 220, 48, 228, 217, 90, 20, 141, 168, 145, 68, 167, 96, 134, 57, 11, 119, 208, 98, 24, 3, 84, 8, 93, 68, 195, 165, 0, 53, 13, 196, 130, 155, 11, 230, 0, 85, 0, 229, 161, 222, 6, 49, 208, 34, 147, 75, 1, 214, 95, 227, 130, 71, 24, 212, 88, 79, 200, 124, 21, 216, 12, 224, 76, 0, 172, 70, 135, 71, 27, 84, 30, 184, 175, 22, 69, 192, 6, 225, 2, 20, 9, 216, 14, 91, 72, 252, 33, 235, 200, 204, 131, 170, 131, 40, 128, 54, 12, 20, 82, 33, 141, 2, 5, 91, 168, 108, 52, 84, 15, 124, 90, 4, 106, 22, 90, 238, 68, 24, 2, 169, 232, 160, 0, 97, 90, 114, 98, 78, 142, 115, 126, 30, 172, 176, 129, 205, 76, 194, 0, 122, 0, 193, 196, 225, 1, 5, 21, 66, 50, 21, 28, 194, 48, 128, 228, 74, 76, 97, 160, 0, 82, 243, 1, 220, 128, 64, 242, 113, 113, 70, 126, 105, 78, 10, 52, 162, 97, 235, 94, 145, 125, 10, 142, 69, 232, 146, 12, 152, 81, 24, 186, 60, 139, 193, 233, 67, 3, 234, 54, 116, 155, 192, 6, 33, 235, 129, 134, 24, 70, 192, 163, 102, 75, 152, 113, 240, 204, 9, 215, 82, 146, 88, 148, 158, 90, 226, 9, 77, 13, 110, 232, 133, 10, 76, 29, 76, 37, 44, 176, 112, 133, 31, 220, 118, 212, 176, 135, 91, 2, 15, 85, 120, 110, 86, 208, 85, 48, 196, 12, 88, 88, 27, 24, 38, 3, 246, 55, 178, 91, 237, 108, 21, 12, 42, 12, 211, 144, 1, 114, 72, 160, 21, 239, 69, 26, 166, 150, 166, 72, 190, 134, 133, 166, 2, 122, 183, 24, 105, 63, 55, 138, 171, 97, 30, 195, 30, 114, 218, 218, 168, 209, 84, 203, 133, 92, 75, 34, 171, 180, 230, 170, 229, 74, 43, 205, 75, 70, 148, 183, 142, 37, 26, 153, 32, 25, 136, 235, 97, 37, 46, 122, 137, 139, 222, 143, 6, 71, 170, 63, 114, 116, 150, 33, 45, 25, 129, 69, 39, 162, 140, 204, 132, 174, 232, 131, 168, 203, 182, 134, 86, 147, 112, 13, 176, 48, 133, 167, 205, 108, 5, 91, 100, 227, 64, 46, 71, 142, 21, 168, 138, 28, 216, 162, 17, 52, 117, 92, 16, 227, 179, 21, 108, 20, 12, 20, 106, 106, 20, 178, 97, 83, 185, 176, 214, 10, 36, 96, 74, 243, 96, 213, 34, 106, 128, 129, 22, 197, 66, 218, 215, 176, 185, 72, 28, 115, 145, 142, 192, 8, 65, 11, 207, 144, 252, 160, 212, 178, 212, 162, 226, 212, 20, 164, 126, 47, 217, 65, 10, 170, 168, 145, 27, 85, 232, 35, 10, 232, 235, 56, 209, 70, 20, 64, 19, 121, 240, 133, 251, 217, 224, 197, 251, 40, 114, 97, 137, 57, 165, 169, 64, 5, 254, 176, 149, 87, 176, 36, 137, 150, 36, 193, 131, 156, 8, 29, 240, 225, 128, 34, 244, 186, 6, 41, 24, 130, 243, 139, 74, 82, 83, 52, 146, 243, 115, 11, 18, 139, 82, 211, 32, 97, 15, 138, 22, 132, 16, 98, 132, 17, 20, 9, 200, 67, 138, 192, 224, 70, 210, 137, 99, 88, 209, 28, 238, 14, 178, 195, 24, 182, 78, 39, 183, 152, 188, 112, 198, 30, 92, 224, 81, 55, 112, 144, 129, 150, 201, 130, 76, 130, 39, 73, 144, 91, 108, 16, 19, 247, 176, 16, 4, 235, 64, 10, 85, 216, 168, 6, 60, 185, 193, 221, 22, 95, 12, 12, 87, 232, 72, 163, 142, 2, 34, 140, 80, 163, 0, 182, 92, 218, 39, 177, 184, 68, 163, 160, 40, 21, 182, 90, 26, 150, 34, 201, 12, 173, 76, 244, 198, 19, 108, 181, 52, 44, 227, 162, 199, 17, 108, 181, 52, 250, 106, 105, 189, 52, 168, 227, 148, 80, 66, 7, 41, 250, 33, 174, 134, 173, 152, 70, 55, 26, 214, 98, 70, 111, 49, 195, 52, 193, 86, 76, 67, 253, 4, 242, 32, 80, 133, 130, 45, 153, 77, 230, 52, 164, 116, 0, 14, 32, 93, 200, 160, 132, 29, 108, 47, 6, 204, 137, 176, 97, 60, 228, 181, 245, 10, 16, 191, 97, 107, 57, 20, 192, 156, 139, 62, 13, 1, 91, 97, 15, 51, 23, 150, 80, 96, 35, 119, 64, 65, 176, 239, 96, 233, 5, 86, 154, 65, 93, 92, 11, 43, 186, 112, 21, 93, 240, 212, 129, 86, 128, 33, 73, 128, 87, 218, 15, 214, 180, 131, 112, 33, 36, 1, 213, 66, 45, 128, 245, 187, 146, 160, 9, 40, 19, 154, 128, 48, 204, 135, 38, 32, 5, 104, 2, 202, 129, 38, 32, 5, 152, 38, 104, 2, 170, 133, 122, 172, 4, 154, 128, 108, 161, 9, 8, 238, 5, 104, 2, 178, 135, 38, 160, 82, 104, 2, 82, 128, 38, 160, 76, 104, 2, 74, 131, 38, 32, 5, 104, 2, 82, 128, 38, 32, 59, 104, 2, 210, 133, 58, 145, 216, 148, 2, 180, 10, 178, 6, 31, 154, 78, 48, 211, 9, 214, 36, 2, 92, 131, 143, 191, 90, 131, 165, 13, 164, 0, 6, 39, 16, 88, 2, 41, 174, 204, 75, 134, 169, 5, 173, 4, 4, 250, 41, 7, 98, 183, 181, 53, 194, 154, 162, 212, 98, 96, 64, 184, 167, 230, 165, 34, 175, 95, 1, 42, 5, 70, 102, 94, 106, 5, 48, 211, 195, 74, 43, 76, 83, 193, 113, 68, 186, 177, 224, 237, 85, 152, 230, 34, 166, 152, 61, 83, 128, 193, 153, 89, 82, 137, 125, 36, 13, 85, 15, 220, 10, 63, 106, 121, 17, 213, 88, 234, 249, 17, 205, 224, 32, 176, 33, 164, 155, 12, 81, 2, 49, 26, 60, 101, 172, 128, 61, 16, 157, 115, 242, 139, 83, 65, 43, 72, 161, 182, 37, 231, 23, 165, 128, 205, 40, 77, 133, 88, 8, 173, 78, 139, 96, 211, 117, 40, 42, 245, 96, 92, 107, 46, 176, 74, 168, 203, 124, 83, 75, 50, 242, 83, 144, 84, 235, 65, 196, 65, 170, 112, 140, 215, 34, 107, 132, 166, 125, 136, 137, 176, 181, 153, 104, 211, 190, 240, 156, 148, 159, 135, 162, 87, 7, 110, 167, 38, 180, 160, 70, 89, 192, 90, 148, 10, 50, 13, 100, 1, 180, 229, 30, 2, 43, 160, 160, 5, 148, 25, 172, 0, 129, 21, 32, 58, 80, 23, 104, 66, 205, 131, 229, 63, 104, 28, 128, 67, 10, 37, 254, 220, 83, 193, 235, 41, 64, 78, 112, 201, 44, 74, 133, 173, 154, 173, 134, 250, 29, 238, 22, 232, 66, 89, 88, 57, 70, 208, 25, 64, 229, 200, 37, 24, 100, 164, 28, 30, 210, 64, 89, 61, 144, 128, 53, 204, 26, 164, 98, 19, 172, 16, 22, 178, 232, 246, 225, 42, 55, 145, 140, 7, 91, 139, 228, 105, 136, 25, 240, 128, 182, 2, 89, 14, 238, 133, 33, 233, 209, 1, 241, 65, 107, 103, 97, 107, 103, 65, 2, 181, 232, 1, 5, 76, 138, 176, 164, 8, 11, 45, 200, 114, 209, 34, 13, 242, 2, 13, 24, 72, 180, 11, 35, 148, 48, 193, 26, 36, 88, 70, 129, 19, 161, 94, 132, 77, 102, 91, 65, 51, 98, 62, 52, 35, 194, 164, 32, 198, 106, 192, 44, 135, 21, 251, 10, 176, 169, 38, 160, 109, 208, 48, 134, 148, 96, 176, 12, 10, 83, 11, 107, 95, 162, 103, 14, 164, 40, 1, 199, 147, 66, 25, 164, 189, 15, 51, 18, 190, 218, 7, 106, 8, 186, 209, 192, 80, 132, 202, 160, 132, 35, 80, 8, 146, 161, 129, 0, 30, 154, 126, 165, 57, 57, 132, 50, 53, 33, 247, 194, 244, 224, 112, 177, 130, 66, 45, 170, 159, 171, 161, 11, 180, 75, 138, 74, 83, 33, 74, 33, 203, 180, 97, 190, 131, 165, 57, 88, 144, 35, 5, 185, 71, 106, 78, 65, 42, 172, 70, 128, 121, 26, 236, 97, 127, 5, 91, 88, 192, 163, 165, 63, 127, 200, 250, 119, 127, 5, 216, 234, 247, 124, 44, 70, 2, 85, 193, 87, 192, 231, 64, 253, 13, 115, 47, 108, 102, 19, 236, 89, 160, 4, 108, 5, 60, 22, 99, 192, 129, 128, 107, 29, 60, 44, 118, 128, 238, 134, 113, 148, 176, 249, 14, 125, 105, 60, 196, 131, 233, 169, 121, 16, 85, 10, 176, 5, 229, 176, 5, 232, 176, 245, 202, 144, 93, 22, 16, 163, 13, 128, 36, 80, 59, 118, 63, 120, 230, 149, 20, 101, 230, 21, 103, 38, 163, 86, 92, 32, 139, 117, 16, 246, 192, 99, 145, 64, 108, 192, 235, 187, 97, 26, 31, 16, 255, 13, 64, 140, 192, 154, 18, 164, 199, 9, 164, 113, 51, 92, 163, 4, 234, 61, 186, 199, 8, 188, 213, 72, 82, 132, 32, 166, 184, 16, 49, 145, 9, 150, 75, 77, 81, 176, 197, 210, 246, 128, 119, 230, 208, 43, 60, 168, 41, 154, 184, 42, 59, 244, 6, 1, 108, 222, 71, 19, 26, 70, 48, 187, 145, 66, 18, 186, 45, 10, 91, 108, 107, 90, 99, 6, 42, 134, 207, 224, 225, 2, 106, 143, 130, 189, 4, 183, 20, 168, 157, 64, 136, 162, 151, 58, 240, 54, 32, 52, 238, 96, 251, 49, 96, 113, 7, 107, 194, 32, 185, 18, 26, 145, 16, 10, 110, 6, 90, 188, 162, 106, 177, 230, 66, 107, 94, 231, 105, 17, 233, 45, 212, 56, 204, 73, 44, 46, 129, 140, 3, 64, 5, 242, 82, 83, 83, 156, 115, 242, 139, 83, 97, 251, 77, 128, 226, 37, 69, 149, 208, 216, 170, 204, 76, 205, 73, 129, 180, 10, 224, 10, 81, 39, 8, 64, 43, 202, 32, 126, 132, 55, 132, 16, 141, 104, 144, 227, 96, 161, 133, 112, 20, 194, 17, 32, 255, 130, 129, 34, 72, 155, 94, 74, 126, 30, 216, 84, 176, 117, 164, 152, 3, 90, 25, 162, 160, 0, 241, 37, 204, 33, 101, 137, 57, 176, 165, 191, 224, 205, 35, 176, 181, 191, 48, 159, 192, 188, 12, 23, 135, 26, 7, 214, 5, 241, 56, 74, 187, 1, 150, 32, 32, 33, 170, 163, 80, 154, 151, 146, 154, 150, 153, 151, 154, 2, 205, 76, 48, 191, 224, 10, 40, 112, 123, 94, 1, 168, 3, 104, 38, 40, 120, 97, 205, 25, 184, 114, 184, 243, 81, 35, 214, 25, 218, 113, 130, 120, 90, 211, 26, 97, 24, 106, 230, 69, 210, 226, 150, 153, 3, 100, 105, 64, 206, 254, 130, 197, 62, 44, 23, 129, 76, 1, 186, 204, 157, 216, 28, 156, 138, 48, 7, 108, 16, 174, 60, 140, 156, 135, 117, 128, 254, 132, 233, 161, 118, 46, 70, 246, 34, 40, 197, 163, 167, 120, 152, 205, 176, 172, 76, 237, 172, 140, 234, 7, 29, 46, 106, 103, 101, 66, 126, 131, 197, 40, 44, 63, 23, 151, 132, 37, 230, 148, 166, 194, 66, 108, 196, 231, 103, 88, 126, 134, 164, 99, 136, 125, 201, 192, 164, 140, 158, 143, 97, 97, 9, 203, 201, 176, 156, 92, 154, 10, 77, 231, 56, 10, 5, 5, 20, 187, 107, 185, 6, 75, 166, 15, 73, 204, 78, 213, 200, 201, 204, 205, 44, 33, 46, 191, 195, 106, 108, 136, 202, 162, 212, 220, 196, 204, 188, 204, 188, 116, 5, 164, 185, 55, 136, 113, 240, 50, 1, 161, 198, 6, 105, 224, 21, 84, 22, 4, 37, 230, 165, 67, 11, 3, 51, 75, 11, 77, 148, 44, 15, 181, 212, 3, 156, 179, 129, 166, 195, 178, 60, 204, 53, 16, 9, 13, 184, 75, 112, 101, 121, 176, 7, 177, 100, 10, 132, 211, 7, 38, 199, 167, 22, 81, 150, 227, 137, 243, 154, 66, 53, 52, 120, 114, 96, 25, 30, 22, 94, 176, 148, 151, 10, 12, 175, 146, 162, 210, 84, 178, 50, 188, 53, 194, 42, 5, 59, 5, 3, 36, 174, 174, 46, 52, 166, 209, 203, 3, 66, 249, 24, 165, 60, 200, 76, 83, 208, 128, 21, 9, 240, 52, 15, 109, 137, 163, 77, 64, 64, 196, 107, 185, 96, 86, 82, 90, 147, 195, 50, 45, 14, 109, 240, 144, 160, 86, 102, 133, 149, 39, 121, 104, 249, 22, 230, 87, 162, 245, 162, 229, 116, 132, 30, 151, 162, 252, 2, 141, 28, 88, 78, 135, 101, 51, 136, 9, 10, 182, 132, 114, 250, 96, 205, 233, 104, 30, 132, 55, 102, 209, 179, 3, 44, 167, 15, 150, 156, 14, 211, 66, 40, 167, 19, 235, 53, 88, 148, 194, 82, 41, 44, 99, 195, 106, 114, 74, 51, 54, 140, 11, 203, 216, 10, 56, 50, 54, 44, 252, 96, 25, 27, 150, 156, 65, 193, 148, 166, 160, 145, 135, 43, 55, 23, 229, 65, 148, 193, 242, 112, 45, 23, 196, 6, 88, 209, 5, 203, 135, 176, 150, 6, 177, 14, 64, 47, 89, 160, 58, 225, 45, 141, 84, 168, 8, 137, 230, 112, 193, 90, 26, 48, 135, 12, 181, 242, 6, 86, 200, 160, 55, 14, 80, 180, 56, 22, 123, 230, 165, 164, 86, 164, 166, 4, 36, 102, 22, 21, 107, 128, 12, 134, 101, 90, 98, 203, 13, 88, 66, 135, 101, 111, 114, 179, 55, 186, 99, 96, 185, 161, 8, 213, 71, 67, 46, 119, 19, 227, 51, 106, 100, 110, 107, 218, 228, 39, 29, 5, 240, 66, 43, 160, 6, 3, 136, 113, 148, 102, 45, 184, 145, 218, 218, 96, 221, 132, 242, 24, 122, 102, 129, 133, 12, 76, 28, 61, 143, 165, 192, 142, 152, 128, 152, 21, 59, 88, 50, 91, 126, 17, 100, 137, 56, 250, 248, 25, 177, 121, 141, 218, 227, 103, 212, 206, 189, 80, 223, 185, 163, 39, 110, 244, 49, 52, 244, 142, 247, 96, 207, 190, 132, 188, 6, 139, 75, 74, 243, 47, 185, 153, 85, 19, 150, 9, 21, 65, 106, 245, 82, 8, 101, 75, 84, 205, 92, 10, 148, 86, 115, 80, 93, 224, 128, 72, 129, 219, 134, 217, 179, 38, 52, 66, 6, 245, 60, 68, 187, 6, 208, 72, 200, 221, 65, 97, 176, 205, 168, 232, 155, 81, 193, 198, 1, 125, 0, 115, 60, 60, 124, 161, 250, 96, 14, 135, 229, 75, 92, 129, 78, 171, 50, 0, 150, 162, 96, 37, 1, 76, 35, 100, 241, 66, 74, 105, 114, 170, 70, 17, 152, 42, 130, 132, 63, 44, 59, 34, 21, 5, 40, 122, 80, 103, 167, 75, 50, 96, 197, 2, 90, 177, 0, 53, 147, 248, 114, 65, 71, 1, 162, 5, 54, 36, 7, 117, 73, 98, 114, 114, 105, 110, 105, 14, 200, 102, 136, 53, 176, 101, 122, 176, 117, 74, 176, 165, 86, 134, 80, 155, 208, 147, 43, 250, 82, 9, 112, 48, 192, 3, 75, 15, 164, 82, 7, 228, 95, 88, 216, 193, 2, 29, 62, 143, 3, 158, 18, 71, 68, 47, 186, 79, 208, 151, 40, 192, 150, 12, 104, 194, 226, 1, 106, 34, 122, 147, 20, 171, 89, 198, 200, 154, 144, 253, 174, 96, 139, 150, 15, 106, 21, 160, 11, 134, 49, 20, 162, 173, 215, 130, 5, 38, 44, 81, 151, 40, 104, 128, 115, 23, 44, 61, 163, 167, 103, 120, 208, 64, 189, 140, 110, 58, 174, 48, 133, 205, 80, 193, 162, 81, 7, 202, 133, 29, 184, 12, 155, 147, 66, 50, 14, 166, 6, 226, 24, 212, 137, 167, 34, 216, 121, 202, 48, 197, 232, 197, 35, 122, 98, 46, 10, 129, 46, 172, 135, 166, 98, 212, 84, 92, 173, 128, 107, 73, 2, 76, 59, 120, 73, 2, 80, 179, 173, 29, 120, 214, 76, 161, 22, 218, 176, 132, 175, 161, 141, 142, 133, 138, 64, 90, 34, 176, 150, 8, 185, 225, 138, 190, 26, 25, 177, 188, 22, 210, 46, 169, 208, 214, 70, 46, 151, 224, 97, 2, 91, 81, 75, 32, 52, 220, 160, 55, 16, 165, 229, 161, 133, 7, 44, 87, 147, 147, 171, 65, 166, 17, 155, 161, 13, 116, 20, 192, 167, 32, 192, 146, 31, 185, 193, 132, 43, 19, 231, 231, 1, 93, 131, 165, 16, 183, 38, 80, 238, 129, 124, 27, 156, 159, 155, 58, 212, 67, 6, 90, 168, 144, 24, 58, 48, 173, 10, 10, 208, 196, 84, 82, 4, 41, 79, 20, 20, 106, 33, 238, 129, 73, 64, 235, 37, 252, 1, 233, 90, 150, 90, 84, 57, 76, 66, 82, 145, 212, 176, 68, 13, 76, 88, 152, 161, 135, 38, 60, 152, 9, 6, 166, 91, 102, 94, 202, 104, 170, 132, 173, 38, 132, 37, 75, 88, 95, 6, 30, 102, 96, 247, 135, 228, 195, 78, 96, 128, 135, 86, 126, 82, 22, 182, 165, 24, 176, 213, 114, 184, 2, 194, 88, 71, 65, 9, 204, 82, 2, 50, 74, 160, 198, 130, 216, 96, 55, 40, 193, 3, 4, 220, 172, 72, 204, 77, 133, 173, 159, 75, 204, 5, 59, 16, 42, 4, 161, 108, 109, 17, 126, 83, 176, 135, 153, 171, 96, 133, 216, 106, 15, 84, 7, 41, 162, 64, 198, 229, 22, 167, 67, 77, 203, 77, 45, 46, 78, 76, 7, 27, 8, 22, 4, 145, 152, 198, 161, 152, 4, 84, 1, 139, 114, 176, 169, 96, 229, 74, 74, 154, 80, 95, 66, 3, 18, 104, 14, 212, 3, 32, 133, 32, 77, 216, 213, 129, 220, 15, 81, 136, 34, 164, 160, 173, 160, 100, 165, 160, 4, 164, 64, 6, 225, 140, 133, 240, 204, 146, 140, 144, 162, 196, 204, 28, 32, 219, 47, 181, 28, 72, 165, 66, 35, 166, 40, 21, 125, 17, 8, 100, 195, 7, 140, 19, 159, 8, 190, 6, 24, 213, 56, 29, 112, 44, 234, 40, 68, 199, 106, 130, 28, 16, 147, 7, 186, 148, 27, 97, 53, 188, 255, 227, 151, 90, 81, 162, 1, 91, 17, 12, 139, 241, 224, 210, 226, 130, 84, 96, 168, 165, 192, 148, 65, 179, 7, 204, 195, 168, 9, 3, 212, 173, 5, 47, 211, 1, 10, 193, 53, 32, 203, 193, 180, 41, 96, 245, 10, 80, 10, 177, 44, 7, 166, 31, 251, 250, 40, 180, 229, 56, 10, 224, 86, 15, 130, 163, 4, 211, 13, 95, 169, 6, 109, 14, 193, 218, 144, 16, 151, 163, 185, 209, 179, 216, 57, 39, 191, 56, 53, 5, 135, 91, 171, 65, 118, 148, 166, 90, 129, 146, 17, 44, 199, 193, 86, 9, 194, 150, 7, 98, 53, 221, 179, 56, 168, 52, 47, 15, 24, 21, 232, 6, 163, 149, 200, 38, 102, 72, 46, 172, 69, 233, 99, 66, 157, 80, 132, 107, 109, 54, 108, 53, 57, 36, 131, 41, 36, 195, 110, 119, 70, 142, 38, 226, 124, 11, 73, 16, 224, 122, 61, 181, 4, 73, 5, 74, 224, 149, 128, 28, 174, 0, 76, 227, 104, 165, 9, 92, 47, 216, 103, 26, 101, 137, 195, 37, 53, 193, 188, 5, 91, 212, 5, 91, 214, 69, 106, 114, 130, 7, 30, 200, 6, 156, 250, 49, 19, 12, 23, 133, 9, 6, 30, 220, 208, 4, 131, 180, 77, 0, 28, 137, 10, 201, 216, 83, 12, 33, 15, 193, 82, 76, 106, 17, 121, 41, 6, 174, 23, 186, 68, 115, 160, 147, 12, 20, 80, 45, 201, 192, 252, 5, 75, 51, 228, 166, 25, 244, 34, 8, 72, 145, 85, 248, 144, 154, 150, 184, 32, 62, 43, 82, 40, 2, 218, 8, 60, 202, 154, 144, 3, 240, 37, 59, 144, 25, 136, 77, 36, 144, 132, 135, 43, 225, 17, 23, 42, 238, 169, 121, 208, 132, 151, 10, 77, 120, 26, 208, 132, 7, 15, 12, 104, 194, 75, 133, 38, 60, 46, 104, 194, 203, 83, 240, 204, 43, 73, 45, 42, 0, 186, 5, 41, 166, 64, 142, 214, 72, 79, 205, 3, 231, 16, 200, 89, 238, 16, 203, 210, 242, 139, 146, 83, 225, 58, 32, 35, 167, 16, 167, 102, 67, 143, 69, 134, 150, 191, 48, 183, 225, 8, 7, 184, 217, 240, 226, 26, 26, 216, 168, 70, 149, 100, 0, 221, 76, 148, 89, 232, 57, 89, 161, 22, 178, 155, 135, 144, 46, 88, 60, 192, 54, 243, 32, 130, 165, 4, 172, 16, 182, 13, 170, 82, 3, 226, 10, 168, 105, 37, 192, 208, 197, 170, 28, 54, 254, 136, 216, 197, 3, 109, 142, 66, 227, 21, 121, 207, 13, 200, 83, 232, 251, 43, 129, 214, 216, 40, 24, 1, 101, 208, 14, 42, 131, 181, 117, 97, 131, 76, 136, 61, 66, 160, 240, 243, 77, 133, 109, 206, 129, 73, 161, 108, 31, 210, 132, 154, 103, 133, 105, 30, 82, 102, 71, 209, 141, 106, 48, 166, 18, 84, 11, 116, 184, 96, 10, 96, 99, 46, 176, 81, 23, 180, 114, 9, 232, 117, 200, 6, 161, 106, 46, 200, 246, 32, 88, 214, 131, 111, 49, 129, 170, 128, 69, 33, 44, 246, 96, 199, 93, 195, 67, 28, 62, 153, 0, 191, 113, 32, 179, 24, 220, 151, 209, 81, 200, 5, 57, 26, 154, 96, 193, 214, 35, 9, 64, 51, 86, 38, 68, 45, 76, 72, 65, 33, 23, 186, 251, 2, 104, 44, 212, 211, 16, 67, 9, 13, 239, 104, 106, 90, 131, 77, 64, 183, 9, 22, 32, 224, 8, 7, 233, 128, 110, 239, 32, 100, 1, 236, 104, 70, 152, 217, 232, 198, 192, 44, 6, 71, 0, 208, 56, 140, 96, 128, 244, 22, 117, 96, 118, 194, 246, 210, 40, 40, 64, 114, 16, 210, 145, 217, 224, 16, 112, 43, 202, 207, 13, 70, 50, 87, 3, 205, 18, 228, 88, 6, 25, 138, 46, 9, 75, 126, 48, 123, 96, 229, 13, 108, 40, 145, 212, 0, 70, 247, 63, 204, 188, 90, 104, 231, 21, 38, 169, 96, 11, 73, 203, 200, 105, 57, 63, 79, 3, 104, 11, 108, 99, 11, 36, 245, 193, 82, 31, 236, 144, 195, 34, 232, 129, 142, 176, 244, 7, 75, 127, 176, 19, 42, 65, 58, 225, 11, 231, 21, 236, 21, 148, 64, 180, 146, 130, 149, 66, 9, 80, 85, 126, 154, 2, 204, 96, 152, 123, 96, 222, 135, 237, 199, 3, 155, 15, 14, 20, 72, 119, 12, 230, 98, 68, 140, 65, 173, 142, 143, 7, 239, 207, 141, 143, 183, 2, 91, 165, 195, 5, 201, 129, 176, 252, 4, 228, 32, 153, 173, 195, 133, 125, 187, 151, 130, 2, 52, 70, 81, 45, 177, 230, 170, 133, 229, 19, 88, 62, 129, 205, 244, 148, 148, 164, 130, 55, 177, 130, 3, 31, 168, 27, 20, 46, 144, 238, 81, 49, 36, 80, 172, 81, 131, 13, 173, 155, 171, 0, 146, 65, 209, 165, 80, 83, 131, 20, 54, 10, 160, 3, 10, 148, 138, 193, 82, 224, 114, 91, 65, 1, 123, 62, 39, 54, 156, 81, 99, 63, 55, 21, 177, 71, 10, 117, 228, 21, 150, 114, 160, 41, 39, 22, 61, 244, 97, 190, 66, 223, 69, 149, 162, 1, 49, 19, 230, 65, 184, 6, 136, 37, 214, 232, 99, 226, 36, 166, 191, 90, 244, 192, 36, 148, 6, 65, 97, 131, 100, 9, 206, 0, 130, 171, 129, 91, 83, 148, 90, 82, 90, 148, 7, 23, 135, 150, 149, 168, 181, 147, 91, 81, 126, 174, 134, 63, 200, 102, 244, 220, 4, 75, 38, 232, 201, 196, 31, 90, 160, 104, 66, 3, 20, 61, 193, 167, 162, 37, 120, 160, 138, 140, 196, 98, 207, 188, 226, 146, 196, 188, 228, 84, 5, 91, 244, 118, 37, 16, 20, 151, 164, 196, 67, 2, 35, 62, 179, 56, 0, 118, 192, 129, 127, 154, 14, 72, 22, 169, 60, 128, 75, 105, 40, 121, 150, 192, 34, 86, 7, 37, 22, 184, 20, 16, 149, 12, 146, 181, 32, 15, 66, 139, 59, 88, 144, 192, 210, 0, 44, 37, 149, 23, 37, 22, 128, 166, 132, 193, 83, 194, 225, 64, 142, 91, 126, 81, 88, 98, 78, 102, 10, 204, 42, 13, 200, 196, 44, 250, 196, 44, 124, 93, 5, 212, 4, 216, 140, 44, 118, 119, 17, 171, 221, 16, 72, 161, 100, 120, 152, 1, 208, 236, 13, 82, 12, 89, 137, 129, 136, 83, 84, 71, 195, 134, 46, 42, 74, 52, 16, 209, 235, 175, 96, 11, 27, 185, 130, 165, 66, 104, 42, 244, 135, 109, 34, 130, 111, 34, 194, 26, 6, 136, 93, 68, 57, 57, 168, 129, 138, 30, 175, 240, 222, 2, 186, 57, 208, 142, 3, 172, 227, 0, 244, 70, 10, 200, 179, 104, 221, 6, 5, 37, 28, 222, 129, 142, 89, 104, 194, 226, 14, 45, 213, 2, 3, 24, 117, 227, 16, 40, 128, 17, 135, 129, 33, 18, 44, 180, 220, 192, 169, 222, 16, 26, 220, 48, 191, 161, 231, 108, 13, 168, 49, 176, 102, 22, 44, 239, 17, 136, 144, 32, 176, 129, 195, 40, 74, 96, 189, 56, 114, 35, 5, 86, 195, 0, 181, 64, 157, 141, 90, 152, 160, 238, 102, 207, 76, 67, 47, 177, 209, 247, 189, 194, 202, 109, 88, 24, 84, 67, 29, 95, 150, 152, 83, 154, 106, 165, 80, 10, 211, 4, 243, 20, 172, 167, 86, 154, 10, 17, 169, 133, 250, 1, 87, 212, 195, 246, 204, 194, 236, 195, 21, 249, 176, 240, 1, 175, 185, 160, 32, 31, 230, 163, 26, 164, 65, 70, 116, 163, 152, 64, 84, 68, 99, 58, 94, 9, 61, 130, 97, 11, 219, 8, 197, 48, 122, 54, 130, 57, 16, 54, 196, 136, 190, 254, 165, 8, 58, 110, 15, 91, 252, 139, 43, 68, 131, 160, 25, 105, 136, 134, 105, 16, 90, 182, 161, 122, 168, 194, 118, 159, 18, 31, 174, 168, 107, 181, 32, 174, 201, 44, 129, 57, 6, 71, 216, 102, 210, 170, 245, 2, 181, 198, 25, 182, 254, 11, 125, 253, 23, 204, 26, 216, 52, 19, 250, 52, 19, 250, 250, 47, 98, 27, 43, 176, 190, 184, 130, 95, 106, 57, 106, 148, 105, 128, 77, 66, 143, 35, 152, 26, 216, 130, 169, 68, 232, 130, 41, 104, 152, 195, 45, 68, 93, 23, 134, 187, 29, 0, 117, 128, 14, 108, 93, 23, 250, 186, 46, 144, 118, 124, 25, 9, 161, 24, 146, 70, 208, 187, 203, 176, 104, 215, 34, 209, 229, 176, 101, 95, 144, 100, 81, 28, 4, 54, 215, 25, 24, 224, 57, 169, 224, 84, 132, 190, 254, 11, 228, 238, 202, 204, 212, 28, 232, 250, 175, 76, 12, 29, 240, 53, 73, 168, 171, 145, 184, 20, 160, 61, 114, 76, 29, 176, 184, 87, 128, 56, 29, 117, 69, 18, 204, 195, 64, 195, 192, 241, 141, 116, 21, 105, 42, 40, 158, 96, 139, 40, 96, 243, 140, 56, 230, 25, 195, 51, 75, 50, 80, 134, 108, 96, 1, 129, 84, 183, 128, 141, 134, 132, 73, 138, 2, 142, 102, 63, 72, 18, 57, 203, 233, 64, 172, 212, 81, 128, 186, 8, 184, 58, 16, 30, 66, 96, 163, 96, 123, 62, 96, 46, 214, 182, 85, 48, 4, 7, 13, 52, 206, 144, 178, 42, 108, 107, 28, 226, 72, 35, 164, 152, 41, 129, 102, 88, 96, 124, 100, 100, 22, 91, 115, 161, 23, 134, 48, 5, 184, 50, 44, 122, 134, 197, 213, 221, 128, 155, 3, 205, 176, 48, 107, 96, 25, 22, 225, 56, 236, 54, 97, 207, 179, 8, 77, 48, 115, 105, 149, 109, 97, 33, 9, 219, 100, 136, 39, 253, 35, 59, 203, 26, 150, 121, 7, 58, 243, 146, 233, 126, 133, 106, 104, 96, 160, 103, 47, 244, 44, 12, 141, 179, 202, 204, 212, 28, 112, 202, 28, 110, 89, 24, 60, 126, 150, 154, 147, 154, 92, 146, 154, 2, 52, 59, 25, 61, 19, 231, 231, 33, 82, 176, 142, 66, 105, 30, 254, 124, 12, 242, 45, 196, 52, 216, 234, 118, 120, 224, 65, 52, 88, 195, 252, 5, 203, 226, 132, 178, 56, 250, 62, 198, 129, 202, 220, 136, 136, 200, 204, 3, 239, 145, 242, 1, 185, 9, 232, 2, 248, 133, 178, 37, 69, 64, 183, 107, 192, 118, 78, 65, 157, 164, 129, 172, 26, 124, 46, 41, 170, 155, 130, 18, 161, 27, 168, 138, 208, 54, 80, 209, 42, 179, 163, 239, 47, 196, 149, 85, 96, 238, 134, 121, 135, 212, 220, 78, 171, 220, 78, 172, 7, 208, 183, 80, 13, 149, 188, 174, 0, 221, 112, 7, 113, 187, 130, 45, 236, 84, 67, 66, 250, 161, 193, 102, 13, 53, 37, 141, 74, 197, 67, 37, 122, 214, 5, 57, 79, 87, 23, 211, 129, 80, 47, 38, 21, 165, 38, 102, 35, 123, 8, 61, 75, 163, 111, 88, 68, 202, 210, 224, 44, 141, 43, 75, 195, 20, 80, 154, 165, 225, 230, 64, 67, 106, 168, 103, 105, 88, 152, 194, 246, 72, 226, 202, 17, 131, 61, 75, 19, 242, 192, 96, 205, 210, 80, 135, 98, 100, 73, 88, 150, 134, 101, 70, 92, 153, 145, 216, 186, 26, 230, 24, 120, 24, 232, 234, 42, 216, 32, 101, 61, 244, 172, 10, 179, 30, 61, 3, 38, 66, 55, 182, 160, 247, 114, 97, 153, 16, 37, 19, 2, 173, 164, 79, 38, 204, 76, 163, 86, 47, 151, 214, 217, 13, 22, 130, 176, 173, 65, 169, 208, 4, 139, 30, 111, 136, 254, 34, 196, 151, 200, 121, 45, 181, 168, 44, 21, 87, 245, 73, 235, 188, 70, 170, 235, 209, 123, 187, 40, 249, 0, 24, 34, 131, 45, 175, 81, 218, 219, 69, 15, 8, 88, 246, 131, 245, 118, 73, 237, 237, 130, 91, 201, 64, 23, 193, 90, 201, 48, 131, 50, 243, 128, 129, 15, 246, 17, 36, 101, 185, 167, 150, 32, 71, 15, 208, 92, 120, 70, 0, 153, 3, 12, 102, 200, 90, 123, 44, 186, 253, 64, 78, 133, 37, 115, 152, 12, 106, 213, 162, 160, 0, 11, 4, 136, 130, 48, 130, 33, 129, 98, 142, 14, 166, 133, 104, 97, 3, 43, 126, 16, 166, 67, 163, 5, 87, 103, 30, 189, 84, 194, 181, 59, 106, 176, 20, 75, 176, 93, 86, 165, 201, 164, 149, 75, 48, 45, 112, 51, 113, 20, 76, 104, 237, 128, 68, 216, 70, 156, 252, 34, 136, 16, 60, 85, 67, 189, 143, 107, 91, 22, 204, 105, 136, 60, 160, 11, 14, 114, 216, 100, 45, 23, 218, 158, 32, 5, 180, 13, 76, 208, 236, 132, 208, 110, 0, 113, 56, 181, 178, 17, 196, 241, 48, 227, 17, 231, 73, 96, 184, 10, 94, 145, 161, 58, 7, 236, 25, 36, 239, 96, 104, 197, 209, 137, 133, 198, 131, 14, 82, 230, 68, 214, 165, 131, 214, 159, 213, 214, 70, 43, 87, 112, 184, 26, 61, 165, 25, 195, 226, 25, 86, 14, 35, 217, 129, 92, 24, 195, 83, 61, 218, 54, 170, 196, 129, 74, 238, 196, 37, 205, 162, 84, 176, 167, 162, 245, 244, 244, 72, 139, 252, 88, 116, 207, 163, 239, 154, 26, 104, 239, 163, 231, 118, 244, 221, 28, 132, 50, 186, 2, 80, 53, 9, 1, 89, 6, 203, 208, 169, 32, 143, 26, 88, 115, 81, 43, 127, 41, 96, 77, 253, 105, 121, 176, 132, 15, 171, 149, 208, 211, 58, 122, 161, 12, 181, 1, 188, 117, 171, 160, 40, 53, 5, 109, 216, 108, 208, 196, 18, 194, 113, 196, 69, 22, 108, 124, 21, 125, 124, 117, 160, 226, 12, 86, 38, 42, 104, 160, 198, 27, 108, 232, 141, 208, 208, 27, 40, 250, 160, 198, 32, 70, 1, 20, 74, 138, 74, 83, 81, 203, 47, 168, 68, 90, 98, 78, 113, 42, 182, 188, 8, 221, 91, 54, 226, 163, 154, 46, 81, 173, 72, 189, 184, 134, 69, 41, 122, 100, 195, 82, 1, 150, 184, 134, 108, 125, 27, 225, 81, 77, 175, 168, 166, 86, 76, 163, 109, 211, 3, 198, 52, 164, 192, 134, 69, 173, 111, 98, 1, 210, 149, 152, 158, 121, 153, 80, 183, 37, 229, 64, 226, 23, 214, 123, 129, 69, 45, 84, 36, 49, 37, 5, 236, 111, 160, 140, 94, 113, 42, 48, 64, 48, 163, 2, 172, 68, 19, 119, 52, 192, 226, 20, 162, 14, 22, 240, 176, 48, 4, 133, 11, 40, 200, 114, 177, 5, 35, 194, 137, 176, 88, 206, 132, 37, 55, 216, 81, 0, 96, 189, 72, 65, 129, 102, 191, 137, 169, 142, 130, 18, 208, 239, 74, 154, 208, 112, 65, 175, 2, 97, 129, 14, 246, 6, 48, 154, 128, 30, 5, 199, 21, 216, 220, 104, 131, 88, 36, 142, 97, 44, 208, 16, 204, 96, 133, 54, 82, 192, 49, 153, 148, 152, 156, 157, 150, 167, 3, 12, 66, 216, 45, 46, 240, 8, 68, 132, 178, 47, 206, 236, 227, 171, 169, 0, 90, 213, 2, 82, 0, 93, 129, 1, 52, 31, 46, 167, 9, 202, 49, 240, 197, 23, 208, 120, 135, 45, 190, 128, 251, 3, 105, 65, 11, 80, 179, 111, 106, 9, 234, 138, 11, 5, 5, 212, 21, 23, 10, 10, 112, 119, 131, 111, 178, 131, 201, 194, 110, 16, 4, 173, 103, 66, 120, 82, 9, 44, 4, 10, 6, 244, 92, 9, 138, 37, 164, 32, 128, 183, 140, 208, 211, 3, 122, 182, 52, 208, 129, 59, 0, 220, 66, 130, 154, 92, 6, 12, 39, 96, 236, 20, 101, 166, 22, 67, 26, 236, 48, 15, 66, 246, 43, 2, 93, 20, 15, 149, 214, 81, 240, 5, 233, 130, 165, 95, 112, 17, 6, 82, 23, 148, 90, 92, 154, 83, 18, 144, 152, 89, 4, 52, 32, 61, 39, 63, 41, 17, 20, 30, 152, 210, 224, 14, 83, 121, 6, 208, 57, 10, 26, 160, 94, 52, 212, 225, 96, 243, 82, 242, 243, 82, 33, 29, 32, 191, 212, 138, 18, 160, 118, 87, 160, 157, 149, 110, 249, 240, 158, 174, 6, 220, 17, 216, 173, 214, 180, 134, 167, 90, 160, 89, 32, 179, 97, 227, 224, 168, 227, 224, 10, 10, 224, 43, 123, 82, 43, 129, 182, 97, 55, 9, 122, 225, 182, 130, 2, 180, 138, 41, 77, 197, 173, 212, 16, 162, 20, 183, 73, 64, 173, 160, 100, 132, 87, 149, 33, 170, 42, 244, 44, 3, 84, 140, 45, 197, 235, 64, 220, 166, 163, 0, 244, 11, 56, 102, 160, 25, 6, 232, 106, 188, 145, 0, 140, 35, 200, 226, 122, 236, 210, 160, 209, 182, 52, 168, 181, 10, 80, 37, 176, 145, 6, 13, 68, 206, 242, 199, 153, 179, 252, 33, 57, 203, 95, 1, 150, 179, 242, 145, 76, 1, 202, 106, 146, 154, 183, 144, 180, 131, 75, 117, 92, 121, 12, 150, 133, 80, 221, 140, 88, 38, 166, 80, 11, 113, 59, 142, 104, 80, 64, 79, 187, 48, 105, 88, 218, 5, 107, 6, 57, 54, 12, 117, 123, 21, 172, 226, 72, 129, 110, 178, 66, 108, 178, 130, 164, 108, 92, 41, 27, 17, 38, 144, 52, 141, 105, 167, 38, 60, 116, 145, 147, 52, 180, 121, 144, 235, 157, 153, 135, 178, 94, 212, 51, 175, 196, 216, 200, 173, 40, 63, 23, 101, 92, 19, 190, 112, 84, 1, 234, 252, 98, 160, 225, 96, 62, 216, 100, 132, 65, 192, 205, 76, 6, 16, 43, 160, 35, 161, 64, 117, 40, 9, 31, 217, 101, 209, 6, 177, 214, 96, 149, 181, 10, 169, 192, 222, 63, 138, 81, 176, 209, 15, 98, 141, 130, 229, 33, 216, 184, 8, 84, 155, 181, 53, 186, 254, 104, 156, 110, 193, 26, 128, 16, 179, 99, 173, 97, 181, 17, 44, 3, 162, 171, 130, 101, 83, 244, 108, 138, 174, 10, 45, 155, 22, 129, 19, 130, 94, 89, 34, 176, 128, 0, 95, 108, 9, 11, 88, 184, 20, 52, 230, 97, 173, 66, 164, 246, 32, 84, 133, 53, 184, 126, 131, 214, 111, 42, 192, 10, 14, 122, 97, 48, 36, 159, 193, 212, 130, 178, 25, 72, 37, 236, 102, 120, 216, 205, 240, 26, 80, 29, 132, 238, 133, 71, 202, 204, 238, 69, 249, 165, 5, 78, 208, 211, 86, 144, 171, 3, 144, 133, 232, 187, 15, 64, 107, 89, 243, 82, 83, 32, 138, 53, 53, 21, 96, 181, 12, 114, 45, 3, 203, 167, 166, 38, 176, 252, 231, 146, 138, 90, 229, 64, 116, 67, 101, 33, 60, 172, 61, 15, 165, 82, 152, 133, 104, 57, 22, 163, 230, 131, 59, 26, 135, 155, 208, 107, 190, 116, 13, 67, 172, 53, 31, 56, 119, 58, 43, 216, 34, 173, 231, 7, 183, 219, 96, 151, 177, 195, 218, 50, 176, 246, 26, 248, 36, 162, 114, 5, 103, 13, 184, 96, 54, 74, 143, 4, 189, 153, 138, 222, 190, 130, 133, 34, 44, 113, 43, 64, 13, 73, 173, 68, 29, 40, 195, 40, 244, 161, 67, 6, 104, 173, 211, 108, 88, 174, 134, 93, 208, 155, 87, 2, 169, 192, 115, 160, 21, 120, 62, 180, 2, 79, 44, 136, 79, 79, 45, 1, 103, 17, 29, 144, 109, 80, 125, 153, 105, 10, 176, 43, 124, 33, 49, 2, 183, 2, 158, 117, 177, 27, 86, 12, 53, 12, 90, 243, 68, 131, 221, 19, 171, 105, 141, 158, 137, 21, 20, 32, 39, 253, 192, 238, 29, 205, 47, 0, 159, 244, 3, 179, 83, 7, 238, 106, 232, 141, 130, 176, 115, 108, 96, 25, 22, 68, 102, 35, 13, 84, 195, 50, 15, 200, 110, 228, 156, 163, 224, 87, 154, 155, 148, 90, 20, 159, 89, 236, 150, 153, 7, 12, 102, 141, 188, 210, 92, 144, 23, 32, 94, 44, 169, 4, 55, 137, 129, 98, 144, 141, 63, 121, 165, 32, 197, 74, 64, 5, 176, 172, 10, 50, 50, 45, 49, 167, 24, 61, 143, 130, 180, 232, 130, 73, 91, 91, 80, 60, 99, 181, 210, 47, 209, 143, 90, 246, 193, 180, 0, 105, 236, 118, 65, 143, 4, 214, 128, 24, 169, 137, 110, 37, 68, 152, 104, 91, 203, 16, 179, 237, 144, 137, 118, 216, 68, 59, 208, 94, 152, 21, 214, 200, 174, 3, 155, 174, 139, 208, 131, 59, 80, 130, 19, 211, 128, 59, 112, 233, 238, 88, 168, 13, 24, 46, 85, 132, 84, 109, 4, 35, 64, 87, 67, 195, 72, 65, 75, 75, 193, 212, 88, 19, 168, 219, 80, 83, 193, 198, 22, 110, 134, 154, 26, 156, 9, 20, 69, 81, 135, 18, 6, 238, 57, 249, 73, 137, 57, 144, 132, 129, 226, 119, 176, 29, 40, 9, 199, 79, 35, 36, 31, 196, 69, 4, 146, 38, 86, 163, 96, 201, 26, 151, 105, 176, 148, 95, 146, 74, 192, 64, 72, 3, 205, 61, 181, 196, 191, 60, 15, 150, 29, 93, 82, 139, 147, 139, 50, 11, 74, 242, 139, 128, 183, 215, 67, 204, 134, 29, 41, 3, 187, 16, 52, 185, 68, 195, 31, 20, 184, 176, 210, 170, 24, 26, 3, 65, 169, 105, 57, 64, 201, 248, 252, 242, 60, 111, 160, 168, 6, 80, 15, 92, 89, 10, 194, 88, 160, 234, 234, 90, 228, 190, 60, 226, 60, 83, 29, 240, 181, 153, 182, 32, 67, 97, 133, 128, 53, 68, 22, 114, 39, 47, 148, 3, 189, 151, 23, 81, 94, 66, 181, 64, 142, 25, 141, 133, 21, 131, 16, 91, 21, 108, 9, 248, 19, 188, 5, 21, 164, 31, 169, 28, 44, 169, 44, 72, 205, 79, 131, 232, 7, 230, 90, 228, 202, 72, 83, 1, 86, 150, 161, 151, 101, 192, 178, 12, 201, 155, 144, 210, 16, 108, 4, 172, 4, 67, 77, 93, 72, 65, 130, 61, 86, 224, 155, 201, 252, 211, 192, 97, 137, 20, 209, 40, 225, 157, 142, 170, 52, 4, 22, 73, 64, 61, 88, 35, 220, 179, 216, 181, 162, 36, 53, 175, 56, 51, 41, 39, 21, 195, 96, 96, 179, 29, 161, 91, 65, 77, 13, 197, 166, 76, 52, 157, 216, 76, 143, 47, 201, 247, 201, 79, 78, 204, 73, 13, 46, 41, 202, 204, 75, 215, 208, 84, 64, 239, 34, 88, 195, 109, 131, 12, 136, 163, 213, 114, 254, 122, 37, 240, 211, 111, 252, 177, 218, 0, 170, 22, 64, 62, 69, 113, 120, 72, 62, 212, 225, 160, 179, 34, 176, 106, 203, 72, 44, 6, 39, 116, 104, 92, 133, 161, 104, 135, 72, 106, 132, 1, 7, 16, 48, 244, 171, 64, 12, 0, 7, 50, 48, 94, 74, 82, 139, 80, 172, 38, 20, 25, 8, 87, 105, 130, 155, 109, 232, 205, 54, 76, 227, 33, 173, 55, 196, 126, 91, 148, 102, 27, 178, 107, 130, 33, 174, 1, 43, 131, 59, 9, 125, 92, 66, 3, 105, 247, 98, 49, 212, 121, 16, 111, 234, 40, 128, 117, 18, 112, 22, 204, 30, 144, 179, 138, 177, 56, 11, 57, 144, 33, 121, 2, 162, 28, 124, 24, 147, 142, 66, 49, 144, 3, 43, 166, 202, 18, 139, 20, 242, 193, 10, 145, 74, 19, 88, 140, 193, 154, 118, 136, 65, 13, 136, 86, 92, 205, 58, 99, 99, 136, 131, 128, 74, 148, 192, 218, 107, 33, 54, 64, 75, 4, 13, 88, 205, 2, 116, 133, 2, 242, 30, 95, 5, 53, 53, 5, 100, 57, 164, 106, 25, 187, 92, 49, 184, 17, 173, 164, 96, 15, 116, 50, 44, 249, 120, 167, 86, 66, 142, 176, 82, 176, 82, 128, 30, 101, 5, 43, 17, 96, 74, 52, 64, 142, 134, 120, 23, 188, 132, 68, 1, 228, 48, 8, 195, 160, 194, 200, 192, 64, 161, 6, 72, 27, 24, 66, 40, 35, 136, 68, 94, 105, 78, 14, 152, 5, 14, 54, 232, 94, 75, 112, 7, 18, 200, 64, 75, 213, 72, 1, 14, 78, 54, 176, 0, 79, 39, 63, 192, 193, 90, 241, 7, 120, 122, 234, 112, 10, 112, 80, 96, 193, 130, 25, 22, 248, 248, 3, 220, 39, 63, 63, 187, 180, 0, 148, 194, 161, 1, 174, 73, 48, 160, 7, 58, 148, 82, 242, 193, 78, 132, 213, 137, 224, 58, 209, 61, 181, 4, 86, 24, 34, 106, 67, 164, 73, 111, 136, 95, 192, 245, 34, 162, 94, 4, 215, 111, 96, 255, 130, 0, 92, 36, 218, 32, 86, 65, 13, 18, 196, 8, 73, 5, 5, 164, 122, 46, 218, 8, 92, 43, 67, 106, 65, 100, 89, 80, 39, 3, 118, 159, 8, 76, 22, 22, 133, 104, 205, 138, 116, 212, 106, 14, 226, 64, 72, 50, 132, 14, 34, 66, 197, 20, 20, 161, 227, 73, 184, 163, 15, 156, 95, 70, 122, 244, 17, 31, 125, 144, 97, 205, 129, 142, 62, 244, 70, 28, 204, 223, 136, 70, 92, 1, 34, 24, 17, 209, 74, 116, 136, 161, 25, 96, 13, 43, 31, 97, 161, 134, 203, 219, 176, 82, 48, 177, 164, 164, 168, 216, 49, 47, 5, 58, 14, 7, 14, 56, 3, 96, 192, 65, 140, 65, 150, 5, 7, 183, 33, 44, 184, 97, 166, 194, 194, 30, 54, 142, 8, 13, 121, 29, 168, 104, 121, 81, 102, 73, 98, 82, 14, 80, 66, 81, 17, 211, 52, 3, 19, 77, 152, 194, 212, 188, 210, 92, 208, 220, 13, 78, 165, 134, 112, 165, 201, 249, 121, 105, 153, 233, 165, 248, 20, 27, 105, 162, 238, 58, 86, 176, 182, 230, 66, 117, 49, 168, 12, 69, 115, 109, 49, 92, 196, 8, 40, 66, 146, 163, 136, 118, 18, 236, 26, 223, 100, 164, 228, 225, 95, 4, 74, 110, 208, 118, 8, 172, 98, 40, 193, 140, 92, 29, 112, 100, 101, 38, 149, 150, 164, 22, 235, 40, 20, 3, 153, 201, 160, 21, 239, 144, 168, 66, 140, 93, 131, 244, 105, 194, 34, 9, 94, 25, 194, 230, 83, 209, 6, 149, 12, 116, 20, 32, 45, 110, 104, 56, 193, 173, 67, 46, 55, 144, 69, 113, 21, 31, 232, 74, 208, 75, 17, 116, 37, 184, 10, 19, 160, 164, 6, 114, 130, 86, 176, 194, 158, 190, 225, 190, 69, 132, 9, 86, 79, 35, 141, 238, 89, 128, 34, 0, 54, 186, 7, 15, 1, 35, 228, 96, 133, 28, 224, 4, 178, 5, 53, 131, 0, 195, 194, 0, 82, 164, 130, 143, 221, 8, 75, 204, 1, 13, 151, 130, 250, 223, 197, 169, 16, 113, 232, 168, 25, 140, 147, 14, 46, 171, 129, 74, 96, 67, 173, 64, 65, 112, 235, 8, 46, 8, 243, 137, 82, 42, 48, 164, 82, 139, 64, 137, 76, 73, 33, 51, 15, 201, 49, 80, 239, 64, 93, 80, 99, 139, 36, 165, 135, 208, 164, 96, 15, 105, 31, 88, 129, 40, 11, 152, 203, 193, 38, 39, 231, 231, 165, 193, 82, 37, 9, 102, 35, 107, 131, 152, 110, 4, 54, 221, 16, 20, 4, 8, 211, 193, 254, 37, 100, 172, 1, 80, 23, 88, 27, 48, 4, 192, 129, 134, 108, 19, 100, 216, 25, 34, 11, 11, 85, 216, 18, 96, 100, 155, 64, 133, 8, 33, 63, 160, 89, 134, 205, 95, 96, 99, 224, 126, 50, 1, 251, 201, 8, 213, 79, 192, 104, 35, 108, 137, 17, 200, 18, 68, 51, 12, 213, 75, 64, 49, 176, 36, 44, 149, 162, 183, 82, 21, 212, 212, 96, 250, 20, 109, 109, 21, 74, 97, 101, 50, 204, 30, 244, 212, 171, 97, 102, 1, 105, 191, 66, 26, 175, 192, 218, 10, 217, 189, 197, 164, 184, 23, 156, 254, 208, 221, 91, 140, 195, 189, 176, 110, 12, 208, 189, 96, 125, 164, 185, 183, 56, 21, 221, 189, 136, 234, 4, 181, 218, 70, 151, 128, 85, 48, 88, 141, 54, 66, 152, 9, 171, 128, 242, 80, 155, 211, 149, 56, 74, 205, 98, 88, 15, 67, 7, 234, 27, 88, 1, 170, 137, 28, 255, 25, 137, 197, 224, 68, 136, 236, 52, 168, 50, 152, 155, 64, 98, 176, 18, 69, 1, 225, 112, 13, 164, 78, 17, 132, 50, 129, 204, 17, 194, 148, 98, 85, 1, 146, 132, 94, 156, 1, 83, 134, 62, 62, 131, 197, 71, 40, 67, 204, 10, 208, 144, 128, 173, 207, 129, 9, 214, 146, 27, 80, 176, 161, 121, 72, 199, 2, 61, 148, 138, 72, 51, 10, 49, 224, 143, 96, 194, 204, 196, 214, 82, 114, 73, 37, 100, 46, 44, 229, 22, 67, 2, 13, 20, 107, 138, 196, 84, 163, 216, 13, 209, 81, 0, 133, 153, 38, 208, 44, 164, 128, 2, 251, 28, 205, 195, 64, 67, 176, 56, 215, 173, 40, 63, 215, 21, 50, 163, 175, 145, 9, 206, 45, 32, 115, 96, 67, 143, 224, 33, 67, 164, 33, 67, 133, 130, 196, 204, 34, 92, 211, 42, 69, 80, 71, 160, 87, 111, 64, 61, 80, 41, 72, 142, 128, 229, 8, 164, 229, 42, 16, 149, 122, 105, 8, 199, 32, 229, 61, 92, 73, 10, 20, 38, 144, 89, 67, 8, 3, 56, 49, 136, 18, 201, 56, 253, 236, 1, 30, 144, 210, 240, 215, 81, 8, 64, 241, 46, 188, 11, 2, 25, 105, 133, 25, 3, 31, 164, 10, 208, 81, 0, 13, 190, 97, 49, 17, 60, 159, 71, 238, 124, 30, 108, 62, 15, 22, 44, 176, 26, 159, 90, 243, 121, 48, 11, 209, 231, 243, 32, 145, 228, 156, 72, 104, 62, 15, 238, 38, 67, 35, 29, 100, 103, 160, 207, 231, 193, 76, 70, 10, 78, 164, 17, 176, 228, 162, 212, 68, 240, 224, 57, 176, 131, 1, 105, 77, 80, 58, 111, 7, 155, 183, 195, 53, 111, 71, 104, 222, 14, 58, 111, 151, 141, 220, 78, 4, 241, 96, 237, 67, 244, 246, 33, 76, 10, 214, 46, 68, 151, 194, 213, 30, 4, 182, 1, 53, 178, 33, 237, 64, 16, 101, 13, 115, 57, 108, 182, 176, 24, 114, 126, 92, 52, 80, 50, 22, 34, 153, 137, 117, 74, 16, 185, 206, 82, 0, 70, 4, 246, 82, 54, 59, 21, 215, 92, 32, 46, 157, 176, 185, 64, 228, 185, 64, 208, 52, 0, 177, 115, 129, 232, 57, 13, 156, 47, 128, 70, 231, 102, 22, 167, 198, 67, 247, 51, 105, 228, 231, 185, 129, 89, 192, 96, 168, 134, 198, 126, 1, 68, 137, 2, 108, 116, 26, 189, 220, 128, 202, 195, 139, 54, 180, 212, 104, 172, 163, 160, 4, 181, 69, 9, 200, 132, 90, 132, 116, 110, 62, 204, 133, 176, 233, 101, 232, 20, 189, 51, 98, 110, 25, 102, 5, 228, 104, 73, 216, 212, 51, 66, 26, 102, 62, 228, 120, 73, 96, 15, 12, 106, 90, 73, 70, 42, 204, 59, 58, 10, 201, 137, 37, 201, 25, 80, 30, 216, 19, 104, 249, 10, 238, 115, 152, 71, 144, 181, 131, 162, 30, 198, 182, 230, 130, 76, 245, 194, 140, 67, 151, 69, 139, 72, 13, 36, 99, 52, 129, 42, 97, 65, 175, 1, 246, 62, 196, 46, 104, 74, 131, 46, 221, 64, 155, 222, 134, 169, 135, 91, 129, 148, 75, 64, 254, 133, 233, 70, 68, 20, 44, 86, 131, 82, 139, 243, 115, 202, 82, 53, 156, 81, 206, 96, 85, 80, 128, 156, 193, 138, 62, 191, 0, 181, 6, 26, 214, 122, 32, 103, 131, 107, 51, 112, 200, 35, 156, 13, 119, 49, 194, 24, 164, 198, 53, 208, 243, 176, 68, 8, 161, 52, 224, 1, 133, 238, 255, 162, 212, 196, 98, 208, 38, 185, 161, 27, 0, 176, 19, 152, 33, 62, 193, 18, 0, 224, 172, 72, 134, 93, 32, 46, 220, 175, 40, 1, 104, 205, 85, 11, 207, 188, 208, 117, 105, 62, 153, 197, 37, 110, 64, 157, 224, 113, 26, 159, 204, 236, 84, 183, 252, 34, 199, 162, 244, 98, 216, 220, 21, 44, 67, 36, 22, 65, 167, 15, 67, 242, 33, 27, 175, 64, 10, 160, 229, 7, 200, 201, 224, 28, 1, 82, 97, 167, 160, 97, 106, 96, 160, 160, 165, 96, 104, 96, 128, 101, 135, 56, 172, 150, 49, 180, 212, 68, 206, 186, 57, 153, 197, 176, 49, 45, 200, 136, 17, 208, 40, 176, 2, 196, 60, 38, 80, 218, 192, 26, 72, 193, 38, 43, 181, 181, 65, 134, 227, 40, 235, 114, 128, 230, 233, 40, 100, 130, 235, 242, 232, 204, 88, 184, 93, 208, 208, 4, 89, 135, 18, 24, 65, 208, 129, 180, 196, 130, 130, 156, 74, 141, 146, 196, 162, 244, 212, 18, 200, 114, 87, 232, 121, 204, 64, 94, 34, 148, 85, 12, 10, 51, 160, 221, 96, 79, 163, 86, 175, 16, 141, 200, 190, 198, 91, 181, 26, 232, 40, 192, 116, 160, 85, 216, 208, 86, 21, 178, 149, 216, 141, 69, 106, 69, 152, 235, 64, 89, 74, 9, 40, 250, 18, 148, 224, 18, 80, 111, 234, 129, 189, 9, 23, 14, 201, 15, 206, 47, 45, 74, 78, 69, 181, 14, 50, 198, 128, 30, 114, 160, 116, 8, 74, 236, 240, 185, 47, 40, 7, 126, 197, 6, 17, 97, 7, 155, 18, 243, 44, 246, 204, 203, 201, 204, 3, 133, 156, 15, 72, 23, 220, 92, 148, 216, 208, 180, 198, 140, 166, 228, 124, 104, 249, 173, 1, 179, 14, 197, 2, 5, 228, 216, 65, 169, 11, 8, 68, 144, 9, 193, 8, 2, 167, 214, 188, 212, 242, 144, 196, 34, 112, 23, 26, 182, 41, 17, 102, 59, 108, 83, 162, 157, 130, 17, 212, 18, 132, 106, 228, 61, 135, 192, 61, 135, 70, 96, 51, 177, 58, 19, 174, 5, 238, 82, 66, 110, 5, 13, 16, 129, 108, 130, 105, 131, 150, 34, 92, 104, 245, 9, 146, 91, 160, 62, 131, 250, 139, 80, 194, 67, 15, 46, 82, 19, 30, 36, 226, 244, 224, 17, 71, 108, 226, 131, 7, 58, 40, 134, 139, 21, 108, 193, 226, 158, 197, 1, 137, 201, 217, 169, 41, 224, 162, 2, 77, 163, 130, 154, 26, 72, 41, 66, 4, 90, 72, 41, 216, 216, 34, 151, 76, 154, 80, 235, 237, 81, 21, 67, 69, 173, 20, 8, 148, 142, 40, 118, 130, 157, 89, 92, 158, 89, 146, 156, 161, 0, 146, 1, 45, 175, 0, 89, 9, 11, 182, 228, 68, 96, 248, 27, 88, 129, 217, 176, 202, 67, 1, 30, 18, 168, 21, 85, 30, 52, 137, 34, 34, 19, 98, 60, 212, 20, 67, 178, 77, 209, 1, 7, 96, 180, 65, 44, 178, 113, 70, 148, 27, 7, 101, 24, 162, 152, 107, 76, 61, 115, 97, 12, 35, 20, 11, 76, 104, 96, 1, 140, 97, 140, 98, 147, 41, 77, 109, 130, 50, 76, 80, 172, 52, 163, 139, 149, 48, 134, 41, 138, 221, 230, 84, 182, 155, 144, 221, 80, 134, 25, 138, 35, 44, 6, 202, 17, 80, 134, 57, 138, 107, 44, 7, 218, 53, 48, 134, 5, 138, 179, 12, 81, 74, 148, 129, 117, 23, 148, 97, 137, 234, 64, 195, 65, 232, 64, 152, 129, 6, 168, 78, 53, 26, 196, 78, 69, 24, 109, 8, 115, 116, 74, 106, 90, 98, 105, 78, 9, 154, 163, 157, 161, 142, 38, 232, 90, 72, 189, 138, 210, 254, 133, 182, 184, 82, 136, 29, 147, 132, 13, 108, 66, 173, 246, 79, 202, 194, 62, 67, 72, 208, 24, 216, 121, 242, 104, 205, 113, 136, 115, 210, 83, 177, 207, 43, 67, 219, 113, 40, 134, 162, 180, 249, 160, 205, 152, 146, 68, 88, 35, 138, 11, 173, 9, 133, 107, 150, 17, 166, 3, 173, 217, 11, 241, 159, 59, 241, 206, 65, 235, 108, 193, 60, 148, 145, 88, 76, 29, 183, 163, 183, 189, 128, 109, 47, 176, 6, 88, 163, 11, 185, 209, 5, 180, 20, 46, 8, 107, 110, 193, 140, 135, 181, 179, 144, 125, 139, 236, 50, 133, 204, 60, 72, 152, 96, 239, 47, 1, 35, 8, 226, 80, 84, 255, 40, 104, 210, 212, 67, 64, 81, 34, 61, 148, 137, 171, 113, 14, 115, 5, 212, 199, 64, 157, 176, 104, 13, 46, 5, 82, 216, 98, 84, 7, 249, 196, 16, 13, 35, 212, 52, 82, 4, 11, 166, 104, 36, 29, 177, 40, 97, 166, 18, 148, 154, 238, 90, 81, 224, 150, 147, 152, 94, 12, 52, 169, 36, 181, 8, 232, 148, 106, 104, 235, 54, 8, 58, 66, 102, 141, 17, 108, 65, 248, 146, 111, 16, 182, 225, 96, 216, 128, 101, 16, 220, 133, 101, 137, 72, 163, 35, 74, 74, 48, 75, 130, 244, 50, 18, 139, 61, 243, 82, 50, 147, 83, 139, 161, 150, 192, 148, 105, 3, 213, 165, 0, 21, 194, 130, 17, 164, 56, 61, 39, 63, 41, 49, 7, 139, 194, 116, 52, 133, 153, 233, 121, 249, 69, 169, 206, 137, 192, 171, 196, 49, 21, 103, 162, 41, 206, 5, 74, 100, 230, 100, 66, 183, 92, 161, 170, 205, 69, 83, 155, 146, 95, 226, 8, 217, 202, 134, 166, 176, 24, 77, 97, 105, 94, 102, 114, 126, 10, 54, 35, 75, 177, 171, 12, 78, 45, 193, 22, 4, 101, 104, 170, 139, 75, 50, 147, 179, 65, 217, 21, 93, 97, 37, 84, 33, 44, 53, 40, 64, 15, 162, 66, 95, 252, 9, 90, 147, 10, 74, 8, 174, 40, 9, 65, 71, 1, 188, 38, 53, 13, 36, 162, 4, 238, 240, 194, 210, 12, 68, 105, 72, 126, 48, 218, 130, 95, 88, 130, 41, 134, 198, 37, 44, 159, 37, 67, 19, 12, 23, 52, 193, 192, 178, 88, 17, 52, 193, 4, 65, 19, 12, 108, 254, 32, 7, 154, 96, 10, 160, 9, 134, 11, 154, 96, 128, 54, 20, 36, 130, 156, 150, 7, 180, 7, 110, 61, 48, 0, 192, 153, 77, 211, 26, 170, 6, 236, 98, 84, 21, 96, 33, 96, 13, 3, 15, 9, 37, 125, 37, 5, 109, 184, 105, 218, 16, 62, 88, 39, 210, 78, 43, 244, 224, 65, 248, 25, 24, 54, 37, 80, 38, 74, 208, 56, 166, 148, 37, 230, 37, 67, 87, 66, 123, 130, 150, 174, 107, 4, 235, 40, 128, 215, 176, 3, 253, 15, 27, 201, 181, 134, 185, 180, 184, 180, 160, 0, 50, 236, 157, 88, 84, 169, 96, 11, 157, 28, 205, 132, 174, 127, 15, 134, 118, 217, 20, 212, 212, 160, 45, 172, 156, 28, 112, 45, 10, 27, 230, 128, 88, 19, 159, 156, 159, 146, 26, 144, 159, 153, 87, 226, 88, 162, 163, 128, 176, 206, 78, 193, 160, 34, 13, 8, 128, 122, 145, 124, 14, 53, 93, 91, 193, 80, 65, 27, 213, 126, 68, 89, 10, 244, 8, 196, 187, 190, 137, 37, 201, 25, 160, 89, 92, 148, 115, 254, 138, 42, 112, 70, 115, 81, 5, 190, 120, 46, 170, 192, 23, 209, 69, 21, 40, 49, 29, 140, 20, 131, 48, 39, 192, 44, 4, 218, 87, 80, 146, 153, 155, 89, 149, 152, 148, 147, 10, 113, 42, 166, 3, 202, 18, 97, 73, 1, 182, 69, 18, 215, 22, 73, 160, 46, 29, 5, 224, 200, 7, 76, 27, 116, 27, 168, 130, 173, 130, 162, 162, 6, 216, 8, 200, 50, 36, 228, 193, 17, 228, 114, 7, 110, 27, 208, 67, 161, 144, 172, 139, 174, 215, 16, 56, 51, 95, 83, 131, 42, 102, 97, 0, 53, 15, 22, 55, 208, 80, 119, 135, 110, 66, 5, 134, 189, 127, 1, 200, 113, 160, 88, 69, 54, 28, 54, 41, 194, 133, 161, 213, 9, 50, 149, 224, 90, 145, 154, 12, 209, 7, 86, 10, 171, 15, 96, 202, 32, 241, 10, 244, 121, 121, 64, 98, 73, 6, 92, 33, 188, 105, 128, 71, 25, 216, 195, 176, 160, 69, 205, 101, 69, 21, 176, 108, 6, 75, 22, 176, 4, 139, 158, 96, 51, 243, 146, 115, 74, 83, 82, 139, 117, 32, 134, 232, 40, 40, 165, 43, 129, 162, 13, 211, 63, 168, 30, 129, 165, 13, 180, 128, 78, 38, 218, 154, 82, 37, 112, 44, 16, 175, 161, 76, 9, 108, 47, 208, 107, 57, 137, 197, 37, 158, 176, 109, 43, 214, 80, 119, 56, 2, 57, 209, 177, 48, 94, 30, 76, 170, 60, 35, 51, 39, 85, 65, 163, 4, 182, 195, 29, 154, 60, 138, 96, 219, 96, 209, 253, 134, 148, 172, 32, 106, 96, 21, 40, 52, 125, 33, 5, 75, 30, 88, 202, 64, 193, 30, 82, 191, 90, 41, 56, 34, 165, 5, 176, 45, 185, 224, 72, 43, 41, 66, 138, 26, 168, 169, 209, 176, 254, 5, 108, 34, 46, 177, 36, 17, 214, 192, 208, 112, 212, 81, 200, 211, 129, 107, 70, 114, 17, 194, 60, 91, 216, 229, 201, 10, 10, 48, 203, 144, 67, 37, 36, 31, 218, 150, 41, 66, 10, 45, 168, 65, 232, 65, 136, 28, 131, 64, 5, 208, 97, 47, 28, 197, 39, 220, 18, 216, 248, 152, 130, 130, 21, 146, 205, 192, 162, 12, 57, 12, 242, 180, 181, 173, 185, 80, 123, 18, 232, 249, 10, 87, 190, 2, 250, 13, 28, 149, 48, 127, 193, 98, 155, 212, 20, 0, 155, 154, 0, 133, 70, 48, 80, 40, 24, 90, 144, 195, 210, 6, 122, 218, 0, 42, 46, 200, 47, 206, 4, 57, 21, 158, 58, 130, 83, 19, 139, 146, 51, 82, 139, 192, 206, 132, 6, 2, 44, 68, 97, 81, 3, 211, 4, 142, 26, 93, 67, 120, 212, 16, 151, 88, 16, 126, 68, 183, 211, 7, 40, 3, 62, 153, 86, 35, 24, 108, 27, 122, 194, 82, 8, 46, 77, 130, 148, 200, 192, 232, 129, 59, 29, 201, 141, 10, 186, 112, 81, 106, 166, 56, 244, 4, 20, 10, 77, 64, 176, 84, 97, 15, 77, 64, 169, 208, 4, 148, 7, 77, 64, 112, 125, 208, 4, 164, 0, 77, 64, 37, 208, 4, 164, 0, 77, 64, 16, 235, 17, 18, 118, 176, 56, 132, 58, 1, 41, 108, 33, 65, 9, 13, 76, 66, 105, 15, 24, 180, 65, 169, 5, 57, 137, 201, 169, 208, 138, 76, 71, 161, 8, 194, 135, 172, 152, 130, 37, 59, 66, 53, 43, 212, 21, 56, 107, 86, 92, 109, 110, 88, 205, 10, 181, 5, 87, 205, 138, 51, 209, 130, 101, 96, 30, 74, 204, 129, 250, 5, 120, 111, 26, 210, 44, 19, 178, 135, 224, 166, 165, 101, 22, 21, 151, 184, 228, 3, 149, 20, 129, 67, 20, 122, 2, 34, 212, 111, 24, 38, 194, 60, 136, 108, 22, 178, 91, 209, 237, 128, 70, 24, 178, 48, 172, 201, 100, 167, 128, 148, 29, 208, 157, 1, 153, 243, 112, 67, 19, 197, 102, 124, 45, 56, 216, 6, 91, 163, 3, 230, 49, 176, 24, 150, 80, 132, 73, 67, 211, 51, 52, 74, 237, 20, 76, 13, 32, 11, 4, 97, 178, 136, 197, 32, 78, 137, 160, 73, 102, 80, 168, 184, 66, 121, 110, 249, 69, 62, 137, 185, 73, 41, 137, 88, 130, 5, 201, 112, 88, 250, 4, 47, 228, 112, 74, 132, 44, 154, 128, 171, 129, 68, 102, 73, 105, 17, 164, 8, 134, 21, 193, 80, 135, 2, 131, 19, 102, 155, 6, 138, 22, 80, 109, 1, 234, 74, 35, 131, 96, 52, 1, 104, 74, 69, 17, 70, 79, 59, 232, 114, 224, 80, 69, 19, 132, 121, 31, 84, 138, 32, 0, 138, 63, 107, 97, 108, 24, 139, 144, 175, 220, 74, 243, 160, 53, 187, 14, 220, 153, 40, 14, 131, 54, 124, 96, 182, 192, 204, 5, 135, 40, 70, 98, 85, 180, 133, 21, 238, 68, 89, 14, 42, 155, 161, 135, 25, 163, 135, 37, 122, 56, 162, 135, 33, 174, 240, 67, 15, 59, 172, 153, 10, 40, 133, 22, 118, 48, 95, 225, 119, 110, 102, 110, 65, 78, 42, 113, 161, 5, 43, 105, 97, 33, 133, 171, 252, 64, 179, 210, 39, 63, 153, 164, 216, 209, 68, 183, 136, 80, 148, 224, 178, 14, 61, 62, 208, 99, 3, 22, 240, 232, 49, 129, 43, 30, 112, 5, 58, 44, 200, 107, 185, 240, 59, 134, 80, 104, 195, 124, 15, 50, 9, 217, 28, 68, 253, 5, 235, 12, 64, 252, 3, 243, 11, 212, 217, 112, 63, 96, 119, 63, 70, 116, 65, 133, 49, 189, 164, 105, 141, 189, 2, 69, 115, 64, 17, 208, 122, 176, 229, 72, 86, 163, 91, 140, 213, 90, 44, 150, 130, 227, 18, 86, 122, 227, 234, 215, 112, 161, 21, 212, 196, 247, 35, 210, 193, 253, 8, 244, 190, 11, 98, 23, 4, 164, 40, 71, 45, 222, 211, 74, 233, 219, 201, 81, 80, 64, 239, 230, 192, 82, 2, 162, 243, 82, 12, 57, 2, 37, 222, 39, 179, 184, 68, 67, 19, 230, 37, 232, 25, 57, 197, 48, 61, 232, 109, 92, 88, 255, 7, 87, 255, 7, 106, 61, 40, 8, 192, 106, 208, 251, 63, 240, 67, 188, 160, 25, 19, 87, 139, 18, 234, 70, 29, 184, 131, 180, 181, 81, 150, 73, 65, 172, 80, 132, 7, 51, 46, 163, 209, 90, 187, 176, 110, 148, 6, 122, 55, 10, 87, 99, 21, 86, 181, 162, 52, 88, 67, 242, 125, 208, 187, 71, 176, 198, 60, 122, 208, 83, 187, 117, 11, 243, 27, 60, 54, 161, 39, 33, 231, 36, 150, 164, 166, 64, 130, 10, 60, 4, 11, 143, 207, 212, 138, 18, 200, 0, 118, 0, 184, 135, 145, 15, 237, 215, 192, 150, 203, 194, 86, 62, 129, 87, 62, 193, 3, 27, 200, 211, 214, 134, 250, 31, 30, 215, 176, 116, 19, 157, 9, 236, 36, 193, 130, 37, 207, 57, 177, 160, 164, 20, 40, 3, 61, 201, 195, 55, 177, 36, 35, 62, 55, 177, 66, 3, 22, 70, 208, 144, 134, 47, 89, 208, 85, 48, 4, 93, 48, 8, 51, 1, 26, 59, 169, 41, 56, 34, 7, 85, 25, 196, 72, 160, 82, 168, 38, 189, 28, 88, 187, 22, 170, 10, 222, 247, 66, 115, 13, 52, 56, 139, 75, 96, 98, 153, 121, 64, 23, 66, 143, 53, 129, 57, 17, 60, 156, 166, 169, 163, 0, 49, 52, 24, 188, 46, 26, 4, 12, 128, 52, 172, 96, 6, 217, 2, 45, 151, 192, 131, 109, 214, 104, 85, 24, 82, 153, 168, 80, 83, 163, 144, 134, 86, 56, 41, 160, 85, 55, 10, 8, 163, 32, 185, 9, 92, 175, 166, 150, 56, 231, 231, 22, 228, 164, 86, 4, 165, 194, 100, 97, 213, 14, 60, 62, 96, 142, 83, 128, 132, 5, 236, 252, 52, 88, 25, 14, 5, 176, 240, 128, 139, 192, 35, 12, 218, 0, 64, 47, 223, 97, 162, 176, 194, 22, 230, 31, 120, 25, 143, 163, 156, 135, 135, 16, 218, 130, 32, 88, 58, 131, 246, 168, 13, 173, 129, 148, 141, 45, 194, 21, 64, 62, 56, 165, 193, 204, 6, 135, 111, 114, 98, 129, 31, 60, 189, 69, 231, 197, 66, 204, 133, 5, 52, 88, 22, 20, 142, 165, 64, 187, 97, 11, 154, 225, 42, 20, 224, 201, 8, 172, 80, 19, 170, 23, 86, 214, 192, 104, 88, 242, 77, 204, 77, 77, 65, 74, 194, 16, 43, 245, 210, 139, 242, 75, 11, 138, 65, 90, 97, 150, 162, 42, 196, 105, 123, 72, 62, 180, 13, 141, 162, 30, 232, 8, 152, 213, 88, 98, 29, 37, 252, 97, 197, 34, 204, 94, 248, 184, 128, 157, 45, 150, 188, 140, 176, 26, 86, 10, 32, 74, 1, 109, 240, 90, 38, 16, 64, 238, 227, 235, 160, 153, 2, 233, 237, 195, 109, 209, 197, 106, 137, 54, 220, 36, 184, 195, 97, 41, 95, 1, 77, 3, 180, 132, 129, 27, 168, 13, 201, 170, 62, 176, 124, 10, 47, 188, 160, 193, 138, 174, 25, 228, 81, 80, 6, 132, 117, 213, 33, 150, 2, 67, 49, 15, 213, 139, 176, 243, 217, 144, 90, 55, 224, 28, 130, 169, 10, 226, 122, 66, 97, 0, 207, 245, 216, 131, 128, 11, 123, 75, 198, 61, 21, 71, 78, 45, 130, 229, 81, 88, 238, 132, 53, 111, 96, 33, 3, 206, 145, 121, 206, 137, 176, 188, 136, 158, 11, 113, 228, 191, 52, 244, 156, 7, 9, 163, 178, 196, 34, 133, 100, 136, 89, 216, 171, 117, 152, 36, 36, 30, 128, 74, 12, 172, 185, 176, 142, 29, 194, 20, 234, 160, 105, 209, 214, 214, 129, 121, 5, 108, 40, 172, 246, 32, 148, 171, 113, 229, 104, 46, 180, 220, 140, 158, 159, 64, 0, 172, 11, 218, 124, 43, 66, 203, 208, 176, 134, 3, 9, 30, 0, 139, 0, 245, 131, 235, 78, 34, 179, 127, 38, 172, 96, 71, 142, 8, 144, 3, 97, 206, 71, 51, 193, 22, 139, 63, 16, 107, 247, 224, 225, 131, 144, 130, 173, 222, 131, 173, 15, 65, 164, 119, 184, 183, 193, 233, 26, 14, 208, 22, 106, 195, 206, 215, 132, 1, 92, 229, 57, 12, 192, 92, 7, 171, 46, 96, 0, 22, 90, 160, 149, 38, 168, 82, 168, 73, 22, 25, 4, 163, 240, 53, 145, 120, 154, 214, 48, 14, 218, 178, 194, 193, 224, 61, 112, 202, 0, 115, 128, 91, 222, 169, 239, 87, 200, 82, 159, 65, 232, 87, 100, 142, 17, 13, 60, 110, 60, 36, 60, 142, 204, 49, 166, 126, 40, 192, 86, 142, 14, 173, 80, 64, 112, 76, 168, 21, 36, 208, 66, 154, 220, 162, 26, 102, 43, 212, 44, 18, 117, 7, 107, 194, 42, 24, 88, 9, 13, 85, 130, 209, 114, 131, 186, 148, 68, 243, 17, 102, 194, 90, 119, 48, 111, 226, 136, 113, 80, 92, 131, 35, 25, 214, 131, 135, 113, 96, 219, 26, 80, 98, 26, 41, 110, 225, 150, 67, 2, 24, 24, 180, 144, 198, 19, 145, 62, 67, 113, 168, 130, 173, 66, 8, 174, 246, 41, 172, 37, 5, 27, 39, 130, 52, 110, 130, 75, 147, 138, 75, 50, 75, 74, 75, 50, 97, 105, 19, 30, 42, 92, 144, 158, 6, 23, 90, 47, 3, 61, 209, 114, 97, 235, 47, 0, 69, 209, 221, 134, 222, 192, 130, 187, 1, 154, 55, 96, 213, 47, 172, 141, 5, 109, 96, 41, 4, 67, 147, 10, 80, 1, 106, 32, 194, 214, 104, 64, 107, 250, 60, 148, 90, 190, 184, 20, 214, 35, 205, 80, 208, 85, 48, 4, 42, 34, 182, 57, 128, 30, 234, 182, 232, 161, 78, 160, 190, 71, 175, 237, 209, 235, 122, 152, 4, 172, 124, 192, 85, 62, 224, 42, 29, 208, 203, 6, 52, 13, 197, 144, 126, 53, 66, 24, 87, 14, 135, 229, 111, 244, 220, 13, 203, 219, 232, 245, 250, 64, 121, 4, 198, 132, 29, 94, 67, 169, 159, 96, 245, 247, 32, 241, 147, 2, 148, 105, 68, 45, 239, 193, 106, 233, 193, 230, 61, 24, 19, 189, 78, 38, 228, 83, 220, 62, 133, 212, 196, 131, 219, 167, 48, 166, 73, 44, 197, 158, 174, 133, 116, 107, 96, 189, 45, 88, 17, 134, 218, 21, 68, 233, 181, 25, 224, 235, 181, 41, 88, 67, 140, 133, 85, 219, 104, 213, 118, 41, 184, 98, 204, 131, 123, 32, 47, 22, 90, 135, 16, 210, 1, 179, 75, 65, 91, 193, 16, 84, 116, 195, 106, 121, 82, 52, 26, 1, 215, 16, 105, 66, 139, 99, 180, 226, 88, 17, 189, 56, 38, 228, 7, 20, 131, 141, 117, 20, 96, 198, 161, 215, 139, 232, 181, 58, 181, 234, 116, 236, 195, 10, 57, 249, 73, 240, 234, 206, 191, 160, 36, 56, 51, 23, 215, 84, 15, 204, 124, 232, 20, 128, 166, 66, 53, 164, 194, 83, 72, 43, 205, 201, 9, 205, 203, 76, 134, 46, 96, 131, 205, 67, 171, 65, 23, 176, 213, 64, 23, 176, 193, 196, 44, 32, 11, 216, 202, 208, 70, 186, 13, 96, 11, 102, 208, 197, 208, 71, 158, 193, 67, 45, 64, 73, 216, 200, 115, 17, 218, 184, 16, 108, 228, 25, 125, 78, 1, 182, 110, 38, 177, 8, 146, 24, 192, 202, 128, 193, 0, 91, 55, 131, 107, 221, 12, 172, 117, 7, 211, 4, 94, 30, 163, 107, 8, 51, 79, 1, 54, 201, 0, 111, 134, 162, 120, 11, 213, 124, 31, 160, 12, 98, 141, 12, 100, 52, 13, 221, 103, 176, 209, 52, 92, 99, 105, 48, 63, 34, 210, 52, 234, 64, 18, 44, 161, 43, 104, 67, 204, 129, 69, 30, 108, 208, 15, 54, 144, 134, 30, 96, 112, 87, 35, 188, 140, 228, 17, 91, 91, 184, 117, 80, 159, 163, 121, 148, 226, 201, 7, 152, 32, 124, 242, 1, 211, 21, 118, 160, 20, 9, 27, 175, 131, 233, 132, 7, 63, 52, 2, 96, 37, 20, 23, 68, 55, 134, 95, 209, 199, 253, 96, 245, 19, 250, 184, 31, 40, 50, 64, 198, 162, 143, 251, 145, 58, 238, 7, 179, 22, 150, 157, 8, 141, 251, 161, 103, 208, 124, 104, 6, 69, 204, 67, 227, 159, 198, 132, 69, 181, 14, 23, 100, 254, 189, 88, 135, 11, 236, 77, 80, 142, 67, 142, 37, 244, 188, 106, 72, 32, 95, 162, 139, 129, 143, 77, 41, 202, 76, 207, 204, 75, 204, 129, 248, 5, 178, 122, 37, 49, 45, 213, 61, 181, 4, 18, 227, 110, 69, 249, 185, 232, 107, 102, 21, 12, 33, 246, 32, 105, 119, 131, 204, 158, 66, 156, 11, 147, 204, 72, 44, 6, 151, 142, 69, 169, 238, 69, 249, 165, 5, 197, 240, 204, 228, 129, 38, 1, 157, 14, 196, 85, 86, 80, 88, 86, 20, 161, 143, 67, 163, 77, 17, 89, 115, 65, 211, 169, 134, 34, 186, 139, 33, 198, 160, 23, 58, 232, 133, 2, 174, 66, 135, 80, 177, 163, 0, 45, 120, 160, 92, 80, 209, 3, 46, 124, 96, 166, 16, 42, 124, 96, 14, 131, 120, 38, 53, 5, 125, 133, 30, 204, 98, 36, 135, 41, 232, 34, 10, 1, 152, 9, 185, 176, 160, 192, 53, 91, 6, 43, 129, 192, 97, 8, 140, 12, 180, 186, 77, 1, 189, 101, 132, 222, 6, 68, 79, 213, 48, 81, 244, 86, 17, 174, 57, 42, 244, 54, 142, 130, 2, 164, 133, 131, 222, 190, 129, 181, 110, 20, 82, 115, 32, 235, 122, 160, 33, 13, 75, 6, 197, 165, 57, 37, 160, 48, 133, 45, 114, 38, 28, 117, 16, 61, 104, 211, 210, 56, 163, 14, 214, 16, 66, 143, 21, 168, 213, 209, 6, 177, 196, 4, 185, 66, 141, 130, 1, 68, 29, 122, 170, 131, 154, 3, 153, 123, 68, 82, 134, 156, 98, 64, 202, 113, 205, 166, 160, 199, 35, 161, 126, 51, 220, 175, 69, 144, 25, 10, 56, 63, 24, 194, 68, 143, 25, 204, 184, 70, 141, 24, 72, 40, 37, 38, 39, 151, 230, 150, 230, 36, 150, 164, 18, 91, 95, 194, 242, 57, 44, 69, 19, 91, 95, 194, 102, 158, 96, 213, 37, 76, 49, 52, 52, 225, 161, 102, 205, 5, 139, 111, 148, 120, 1, 70, 186, 1, 56, 198, 209, 195, 152, 212, 154, 18, 154, 176, 184, 96, 74, 209, 107, 74, 46, 68, 130, 3, 75, 160, 215, 148, 184, 18, 29, 134, 203, 106, 32, 5, 33, 76, 14, 104, 34, 180, 194, 83, 0, 23, 235, 132, 138, 117, 67, 77, 5, 69, 91, 88, 92, 40, 192, 203, 118, 104, 213, 80, 83, 131, 110, 20, 174, 245, 141, 58, 10, 70, 96, 147, 96, 38, 64, 106, 7, 176, 110, 132, 103, 138, 42, 20, 96, 197, 27, 124, 175, 104, 80, 98, 185, 6, 170, 173, 58, 168, 102, 64, 18, 18, 174, 214, 1, 44, 106, 237, 108, 81, 195, 110, 176, 183, 14, 224, 185, 206, 31, 178, 50, 210, 41, 17, 178, 50, 18, 125, 161, 83, 70, 176, 14, 216, 173, 232, 45, 4, 232, 234, 198, 84, 216, 138, 70, 144, 175, 65, 53, 22, 161, 198, 2, 172, 13, 0, 75, 218, 176, 134, 1, 208, 98, 61, 100, 49, 74, 27, 11, 232, 218, 209, 27, 11, 180, 174, 244, 97, 130, 232, 5, 226, 72, 175, 31, 208, 235, 7, 168, 167, 60, 97, 107, 123, 209, 215, 246, 194, 172, 4, 111, 68, 5, 26, 5, 143, 119, 104, 119, 25, 220, 93, 134, 235, 210, 81, 128, 205, 1, 195, 12, 135, 24, 15, 214, 172, 8, 12, 177, 82, 88, 223, 27, 102, 60, 90, 24, 41, 160, 215, 87, 96, 123, 17, 178, 181, 176, 181, 35, 48, 1, 68, 22, 80, 64, 50, 221, 154, 11, 38, 11, 139, 5, 24, 13, 91, 105, 143, 203, 183, 232, 246, 19, 170, 47, 97, 186, 96, 53, 38, 172, 198, 4, 131, 96, 4, 7, 181, 214, 84, 80, 64, 177, 42, 44, 49, 7, 86, 111, 194, 106, 78, 152, 155, 97, 100, 98, 50, 164, 6, 133, 21, 80, 37, 10, 144, 26, 20, 189, 140, 202, 75, 133, 212, 160, 176, 82, 40, 63, 15, 82, 131, 150, 100, 66, 106, 80, 116, 105, 88, 13, 138, 171, 6, 69, 207, 128, 232, 53, 40, 174, 26, 20, 61, 21, 162, 215, 160, 176, 190, 38, 174, 26, 20, 166, 15, 86, 131, 146, 90, 131, 194, 156, 0, 203, 150, 217, 168, 129, 170, 0, 51, 12, 87, 13, 138, 86, 237, 5, 227, 42, 235, 96, 53, 40, 204, 50, 244, 242, 146, 210, 26, 148, 75, 1, 82, 131, 194, 226, 168, 66, 1, 82, 131, 86, 20, 64, 106, 208, 210, 100, 72, 13, 138, 176, 21, 82, 131, 34, 204, 128, 212, 160, 80, 223, 213, 162, 247, 175, 97, 81, 11, 171, 65, 7, 186, 6, 69, 149, 213, 228, 34, 84, 131, 194, 22, 94, 67, 23, 94, 23, 193, 170, 79, 66, 213, 39, 100, 129, 123, 90, 38, 108, 226, 9, 54, 241, 4, 242, 59, 168, 192, 35, 182, 30, 133, 37, 112, 88, 157, 137, 171, 30, 69, 15, 31, 106, 215, 117, 136, 218, 197, 7, 236, 111, 176, 32, 72, 61, 180, 0, 167, 86, 93, 7, 149, 84, 80, 72, 42, 74, 77, 4, 102, 42, 48, 27, 152, 169, 208, 202, 241, 50, 152, 107, 6, 75, 93, 135, 100, 96, 94, 98, 110, 106, 10, 108, 184, 24, 102, 42, 108, 22, 15, 166, 16, 125, 38, 175, 24, 173, 250, 66, 132, 4, 170, 121, 232, 115, 168, 48, 9, 88, 38, 132, 133, 21, 114, 113, 11, 138, 20, 88, 53, 3, 155, 82, 45, 69, 237, 78, 23, 33, 234, 22, 72, 205, 2, 99, 162, 215, 43, 232, 181, 10, 76, 20, 215, 36, 43, 134, 7, 160, 162, 80, 231, 214, 194, 242, 54, 122, 222, 30, 233, 149, 15, 172, 242, 81, 208, 64, 72, 216, 41, 228, 164, 194, 10, 80, 152, 78, 244, 124, 130, 238, 50, 88, 229, 131, 171, 120, 134, 121, 126, 168, 20, 207, 176, 157, 40, 40, 165, 115, 102, 110, 65, 14, 180, 119, 67, 168, 120, 134, 149, 192, 101, 137, 69, 40, 241, 7, 91, 46, 142, 190, 164, 30, 90, 86, 231, 64, 122, 23, 161, 121, 132, 186, 169, 208, 189, 255, 101, 240, 189, 29, 254, 69, 193, 37, 153, 201, 217, 149, 168, 101, 188, 6, 226, 248, 121, 11, 77, 144, 14, 216, 166, 13, 152, 14, 216, 41, 28, 176, 22, 8, 204, 73, 232, 45, 16, 152, 2, 116, 173, 48, 57, 5, 104, 133, 1, 243, 40, 44, 53, 192, 210, 10, 60, 26, 131, 97, 169, 4, 117, 1, 53, 44, 144, 16, 122, 107, 33, 222, 131, 103, 60, 72, 225, 130, 62, 93, 130, 94, 228, 131, 29, 137, 208, 98, 11, 27, 181, 36, 228, 126, 116, 215, 195, 92, 137, 238, 114, 152, 171, 208, 43, 58, 116, 247, 161, 79, 183, 224, 12, 121, 76, 203, 177, 152, 141, 108, 115, 81, 106, 65, 78, 98, 50, 172, 132, 129, 113, 161, 197, 111, 17, 82, 145, 9, 78, 31, 176, 26, 27, 37, 203, 216, 42, 4, 35, 103, 23, 3, 120, 233, 150, 167, 169, 160, 141, 106, 1, 196, 217, 152, 46, 26, 170, 249, 152, 208, 44, 198, 96, 205, 197, 168, 185, 88, 33, 19, 87, 82, 70, 207, 197, 131, 37, 23, 195, 90, 96, 176, 86, 27, 174, 86, 27, 204, 115, 48, 245, 176, 22, 27, 204, 119, 184, 28, 143, 203, 233, 56, 178, 176, 53, 44, 216, 113, 52, 238, 224, 82, 56, 26, 119, 48, 53, 240, 194, 9, 117, 0, 195, 154, 11, 87, 41, 161, 96, 11, 209, 3, 107, 217, 193, 173, 192, 31, 171, 69, 48, 191, 81, 90, 66, 40, 64, 27, 104, 176, 113, 0, 244, 113, 0, 46, 180, 86, 26, 172, 133, 134, 218, 58, 43, 74, 133, 181, 204, 128, 253, 125, 112, 79, 31, 98, 115, 98, 50, 122, 174, 182, 69, 205, 209, 6, 35, 172, 168, 9, 38, 212, 161, 67, 132, 35, 164, 31, 7, 235, 199, 193, 182, 61, 224, 42, 126, 168, 85, 252, 192, 52, 193, 146, 29, 122, 241, 3, 107, 68, 192, 138, 159, 145, 94, 252, 224, 42, 126, 112, 57, 125, 164, 23, 63, 80, 135, 16, 234, 170, 102, 18, 215, 77, 37, 190, 139, 10, 114, 13, 178, 75, 96, 81, 15, 235, 154, 194, 186, 166, 176, 2, 143, 216, 2, 15, 214, 21, 69, 207, 170, 208, 110, 40, 220, 129, 208, 46, 168, 38, 44, 4, 232, 93, 50, 162, 91, 71, 168, 100, 132, 58, 74, 27, 189, 17, 70, 173, 146, 17, 214, 44, 214, 128, 24, 12, 116, 46, 52, 96, 138, 42, 128, 33, 81, 146, 1, 59, 63, 6, 54, 170, 77, 233, 249, 49, 176, 243, 99, 8, 157, 31, 3, 148, 43, 40, 74, 45, 203, 204, 47, 45, 246, 65, 74, 225, 69, 176, 4, 15, 203, 77, 137, 69, 136, 82, 194, 179, 56, 42, 181, 40, 31, 20, 129, 137, 185, 144, 36, 161, 129, 97, 6, 48, 66, 225, 133, 137, 34, 154, 78, 108, 185, 10, 86, 98, 212, 66, 245, 224, 58, 185, 5, 20, 42, 224, 179, 217, 131, 161, 69, 129, 130, 141, 130, 65, 133, 121, 90, 90, 26, 196, 84, 104, 160, 166, 194, 138, 59, 120, 208, 35, 202, 59, 176, 211, 96, 197, 25, 46, 199, 97, 56, 15, 51, 152, 192, 102, 192, 202, 95, 152, 38, 144, 237, 105, 57, 137, 233, 196, 86, 64, 80, 151, 40, 128, 220, 130, 220, 222, 133, 85, 56, 22, 208, 36, 64, 138, 147, 64, 161, 136, 94, 246, 66, 131, 4, 22, 196, 80, 65, 68, 202, 68, 63, 52, 78, 7, 211, 112, 172, 137, 154, 72, 173, 10, 176, 228, 142, 22, 51, 104, 7, 10, 128, 146, 99, 114, 105, 81, 81, 106, 94, 9, 84, 47, 122, 106, 172, 128, 39, 42, 68, 226, 67, 215, 129, 205, 1, 56, 210, 28, 70, 8, 34, 167, 65, 144, 91, 209, 43, 65, 68, 128, 234, 26, 34, 7, 38, 44, 132, 97, 53, 16, 150, 160, 42, 200, 201, 44, 209, 128, 228, 61, 29, 133, 156, 204, 220, 204, 18, 164, 96, 25, 232, 82, 64, 33, 9, 114, 12, 161, 115, 73, 126, 17, 100, 122, 16, 122, 46, 161, 115, 126, 30, 80, 101, 41, 228, 138, 35, 136, 79, 148, 224, 154, 16, 55, 37, 21, 35, 212, 129, 179, 25, 178, 121, 112, 229, 249, 136, 44, 173, 0, 25, 120, 244, 36, 144, 205, 193, 138, 156, 65, 94, 68, 113, 32, 84, 66, 3, 20, 138, 144, 8, 130, 87, 149, 10, 53, 53, 80, 223, 131, 195, 24, 40, 139, 116, 11, 23, 220, 225, 105, 224, 153, 3, 160, 46, 240, 72, 162, 111, 98, 73, 114, 6, 56, 90, 138, 65, 145, 84, 146, 90, 4, 139, 6, 36, 23, 67, 35, 129, 196, 220, 13, 210, 130, 110, 13, 114, 235, 18, 105, 26, 2, 108, 35, 76, 24, 156, 247, 17, 89, 31, 84, 172, 20, 35, 207, 220, 131, 109, 134, 196, 36, 86, 171, 13, 161, 70, 42, 192, 189, 4, 201, 115, 232, 19, 78, 96, 67, 129, 171, 138, 97, 214, 214, 129, 236, 5, 234, 69, 47, 218, 80, 13, 42, 170, 128, 170, 224, 66, 83, 5, 11, 28, 120, 42, 131, 157, 196, 130, 43, 36, 208, 87, 87, 227, 58, 243, 4, 116, 72, 10, 40, 250, 96, 129, 145, 151, 90, 14, 94, 183, 136, 8, 56, 226, 13, 170, 84, 130, 231, 40, 5, 152, 65, 176, 53, 13, 197, 104, 94, 199, 174, 72, 65, 27, 118, 82, 47, 172, 148, 69, 10, 156, 100, 80, 248, 194, 206, 124, 71, 94, 84, 231, 172, 163, 0, 68, 69, 21, 224, 115, 212, 221, 32, 161, 2, 203, 157, 176, 115, 9, 99, 161, 41, 20, 218, 174, 113, 132, 213, 139, 96, 161, 204, 92, 107, 104, 245, 152, 3, 75, 218, 176, 54, 34, 124, 21, 60, 72, 21, 80, 19, 240, 28, 89, 40, 176, 70, 137, 35, 152, 2, 104, 230, 176, 179, 179, 131, 152, 15, 115, 68, 1, 212, 66, 152, 45, 10, 208, 137, 96, 120, 209, 7, 61, 72, 15, 161, 163, 56, 179, 42, 21, 113, 246, 92, 6, 76, 47, 68, 24, 174, 25, 26, 73, 249, 232, 249, 9, 38, 1, 171, 78, 160, 21, 117, 49, 52, 56, 117, 32, 213, 181, 130, 34, 108, 32, 19, 170, 69, 1, 225, 20, 168, 72, 45, 106, 188, 161, 155, 12, 170, 104, 144, 77, 5, 26, 137, 82, 172, 227, 50, 20, 70, 194, 182, 45, 192, 150, 75, 192, 142, 67, 52, 128, 86, 93, 56, 2, 167, 16, 24, 50, 5, 176, 248, 67, 242, 188, 95, 190, 115, 98, 1, 80, 121, 106, 177, 130, 45, 74, 177, 168, 166, 166, 160, 8, 114, 49, 250, 66, 219, 130, 98, 20, 215, 91, 195, 102, 20, 21, 52, 10, 21, 108, 64, 113, 0, 13, 79, 136, 77, 169, 58, 10, 85, 16, 71, 161, 5, 58, 194, 94, 132, 183, 11, 65, 37, 3, 158, 224, 47, 4, 217, 6, 15, 206, 66, 232, 160, 178, 66, 77, 13, 80, 167, 157, 45, 212, 110, 152, 97, 176, 137, 18, 120, 0, 66, 23, 119, 160, 219, 129, 58, 58, 204, 165, 0, 6, 85, 10, 182, 176, 203, 72, 225, 113, 137, 59, 217, 84, 193, 205, 244, 77, 44, 33, 228, 236, 42, 104, 53, 9, 139, 111, 92, 110, 133, 134, 71, 21, 172, 35, 137, 48, 129, 52, 207, 22, 42, 104, 43, 84, 69, 27, 196, 194, 114, 5, 204, 71, 176, 212, 137, 92, 102, 32, 183, 72, 20, 10, 33, 74, 145, 189, 231, 90, 145, 154, 140, 30, 251, 4, 60, 6, 244, 3, 106, 89, 155, 151, 142, 125, 154, 12, 28, 80, 10, 86, 64, 13, 144, 233, 48, 40, 72, 206, 207, 43, 201, 204, 3, 142, 161, 163, 123, 13, 105, 244, 5, 236, 36, 152, 251, 97, 77, 68, 46, 168, 106, 168, 235, 82, 193, 174, 43, 64, 56, 141, 92, 135, 161, 59, 11, 102, 13, 174, 124, 9, 45, 62, 117, 20, 130, 75, 147, 138, 129, 198, 66, 70, 185, 10, 128, 134, 42, 232, 2, 221, 3, 117, 104, 78, 42, 88, 149, 182, 182, 53, 220, 197, 80, 33, 176, 187, 115, 50, 115, 97, 46, 71, 205, 222, 48, 187, 11, 128, 190, 129, 56, 6, 26, 23, 138, 232, 113, 1, 206, 142, 121, 165, 185, 73, 169, 69, 254, 105, 192, 188, 7, 155, 92, 134, 157, 80, 132, 122, 134, 82, 149, 30, 236, 248, 36, 216, 241, 73, 48, 83, 160, 231, 55, 193, 67, 2, 154, 249, 51, 129, 27, 187, 80, 140, 135, 101, 109, 88, 68, 18, 8, 157, 42, 216, 165, 118, 208, 116, 14, 11, 9, 5, 244, 192, 129, 229, 3, 156, 1, 132, 22, 72, 48, 49, 88, 202, 129, 210, 192, 96, 131, 36, 2, 80, 169, 8, 226, 66, 204, 44, 80, 64, 203, 91, 4, 34, 85, 9, 216, 20, 64, 173, 214, 8, 105, 65, 79, 7, 96, 219, 16, 73, 161, 150, 11, 217, 237, 181, 92, 105, 168, 221, 156, 248, 130, 162, 252, 146, 252, 146, 202, 130, 212, 120, 72, 102, 4, 183, 157, 65, 142, 69, 191, 117, 1, 189, 245, 30, 4, 217, 130, 229, 89, 12, 109, 220, 194, 68, 97, 30, 133, 90, 154, 12, 107, 188, 192, 134, 100, 128, 192, 25, 40, 6, 209, 229, 155, 90, 146, 145, 159, 226, 153, 22, 94, 148, 88, 80, 0, 89, 93, 15, 2, 65, 48, 6, 196, 57, 48, 158, 18, 86, 55, 43, 113, 129, 151, 3, 192, 60, 139, 171, 59, 96, 13, 11, 8, 168, 215, 81, 142, 39, 15, 2, 6, 35, 90, 47, 16, 172, 38, 36, 181, 184, 132, 200, 48, 129, 249, 30, 118, 177, 0, 122, 135, 70, 33, 8, 181, 63, 131, 218, 159, 9, 210, 36, 213, 253, 224, 194, 211, 45, 191, 8, 228, 68, 44, 238, 87, 129, 118, 99, 11, 82, 147, 51, 83, 139, 53, 128, 238, 130, 235, 135, 58, 30, 122, 177, 0, 236, 98, 129, 68, 232, 197, 2, 112, 77, 224, 163, 2, 83, 75, 20, 162, 131, 193, 183, 249, 234, 21, 67, 68, 99, 149, 52, 173, 145, 131, 9, 94, 77, 57, 230, 228, 32, 7, 21, 172, 247, 135, 43, 172, 168, 213, 251, 3, 218, 2, 180, 21, 51, 192, 232, 213, 255, 67, 234, 193, 192, 26, 226, 208, 49, 221, 34, 29, 5, 96, 253, 1, 235, 125, 67, 252, 239, 89, 140, 191, 91, 8, 178, 216, 22, 165, 75, 8, 11, 36, 88, 39, 9, 209, 61, 131, 120, 23, 87, 39, 137, 80, 151, 14, 251, 178, 3, 5, 5, 168, 219, 225, 125, 33, 5, 132, 39, 192, 129, 236, 131, 99, 130, 2, 86, 100, 161, 58, 86, 73, 9, 230, 16, 92, 221, 39, 116, 91, 9, 117, 50, 42, 160, 161, 140, 170, 17, 81, 83, 227, 114, 36, 106, 136, 128, 217, 10, 216, 250, 86, 184, 250, 86, 233, 74, 154, 10, 246, 224, 51, 144, 21, 172, 20, 12, 52, 21, 106, 72, 55, 162, 20, 100, 4, 184, 91, 12, 52, 2, 214, 53, 70, 118, 184, 174, 145, 53, 23, 82, 145, 13, 189, 130, 22, 154, 78, 32, 198, 122, 150, 164, 22, 37, 150, 228, 23, 105, 192, 211, 24, 48, 180, 116, 128, 1, 142, 148, 0, 193, 233, 14, 230, 107, 88, 153, 15, 187, 209, 22, 135, 113, 69, 169, 233, 169, 21, 5, 64, 131, 192, 194, 120, 12, 84, 168, 134, 76, 115, 160, 19, 224, 124, 144, 9, 50, 14, 146, 209, 252, 82, 203, 177, 90, 4, 246, 118, 104, 94, 113, 98, 90, 106, 112, 106, 9, 34, 25, 230, 151, 104, 192, 116, 131, 59, 31, 16, 7, 17, 165, 218, 16, 228, 108, 88, 158, 39, 168, 218, 8, 230, 57, 162, 84, 27, 235, 64, 147, 76, 13, 52, 198, 176, 107, 0, 69, 37, 220, 247, 144, 250, 202, 4, 66, 193, 67, 14, 58, 105, 0, 139, 90, 152, 98, 88, 4, 193, 138, 83, 140, 16, 243, 75, 173, 40, 1, 150, 223, 176, 34, 53, 63, 41, 11, 87, 153, 10, 185, 146, 184, 166, 70, 1, 196, 0, 42, 114, 47, 77, 44, 74, 9, 201, 199, 26, 13, 32, 165, 154, 240, 50, 22, 104, 60, 172, 210, 38, 84, 105, 163, 155, 132, 163, 10, 7, 57, 16, 204, 134, 213, 219, 216, 188, 5, 170, 186, 97, 85, 55, 172, 198, 128, 14, 77, 42, 84, 3, 185, 57, 165, 169, 86, 136, 113, 0, 29, 133, 148, 252, 188, 84, 43, 133, 180, 196, 156, 226, 84, 133, 90, 104, 154, 67, 4, 48, 114, 57, 135, 25, 57, 64, 15, 67, 227, 5, 18, 17, 144, 176, 67, 104, 134, 173, 40, 130, 5, 4, 120, 200, 19, 100, 33, 40, 180, 139, 96, 45, 243, 162, 84, 216, 136, 40, 80, 26, 197, 221, 224, 228, 138, 236, 4, 72, 156, 184, 161, 151, 181, 168, 142, 49, 128, 57, 166, 44, 177, 8, 154, 136, 161, 102, 160, 23, 241, 184, 205, 48, 68, 54, 35, 13, 86, 226, 227, 42, 241, 177, 153, 96, 140, 100, 2, 236, 232, 119, 216, 68, 49, 108, 204, 206, 8, 166, 0, 186, 82, 17, 125, 221, 49, 88, 149, 161, 129, 166, 66, 77, 13, 170, 152, 133, 1, 150, 208, 182, 179, 85, 48, 128, 133, 181, 53, 56, 104, 33, 33, 144, 95, 74, 168, 146, 131, 187, 31, 234, 3, 88, 34, 51, 66, 164, 37, 176, 101, 48, 37, 176, 6, 106, 0, 172, 209, 8, 173, 128, 19, 147, 114, 82, 53, 224, 35, 177, 240, 229, 239, 56, 109, 132, 21, 144, 134, 154, 224, 26, 26, 234, 82, 76, 237, 232, 225, 141, 170, 219, 72, 19, 164, 27, 20, 75, 176, 149, 243, 208, 64, 80, 192, 53, 89, 15, 243, 7, 172, 14, 133, 89, 168, 128, 58, 123, 15, 21, 5, 251, 31, 28, 2, 176, 195, 133, 97, 198, 193, 102, 180, 21, 20, 80, 74, 37, 96, 173, 99, 0, 214, 3, 239, 118, 66, 39, 169, 19, 75, 146, 51, 64, 245, 36, 134, 6, 27, 91, 104, 66, 133, 118, 233, 160, 74, 64, 192, 30, 88, 128, 33, 134, 45, 80, 43, 149, 188, 116, 72, 45, 130, 182, 110, 85, 65, 193, 10, 50, 50, 2, 115, 55, 108, 197, 44, 172, 108, 130, 149, 77, 176, 80, 198, 85, 248, 42, 160, 37, 8, 5, 104, 25, 140, 224, 232, 26, 130, 56, 176, 96, 130, 49, 33, 89, 89, 47, 5, 150, 211, 97, 57, 29, 35, 183, 163, 133, 18, 98, 82, 29, 197, 133, 240, 176, 131, 77, 240, 67, 120, 209, 6, 177, 208, 224, 130, 25, 131, 26, 7, 96, 69, 144, 161, 25, 180, 233, 123, 152, 114, 88, 200, 192, 36, 192, 225, 99, 128, 176, 26, 221, 68, 244, 245, 196, 48, 128, 109, 76, 2, 212, 100, 198, 21, 65, 176, 197, 197, 48, 147, 97, 131, 22, 176, 176, 160, 52, 102, 96, 238, 134, 213, 145, 104, 17, 84, 11, 107, 86, 82, 106, 17, 174, 36, 0, 243, 3, 44, 33, 128, 107, 29, 104, 140, 128, 67, 31, 173, 216, 207, 129, 38, 132, 90, 46, 136, 4, 180, 216, 15, 74, 77, 119, 173, 40, 112, 206, 207, 3, 6, 101, 105, 114, 73, 80, 34, 108, 6, 2, 214, 92, 133, 213, 31, 32, 245, 122, 72, 17, 133, 240, 60, 68, 5, 118, 255, 1, 61, 133, 214, 42, 34, 20, 20, 176, 96, 64, 14, 2, 93, 35, 46, 5, 152, 215, 107, 185, 32, 25, 29, 154, 209, 161, 30, 0, 141, 200, 161, 102, 219, 116, 104, 233, 13, 203, 150, 232, 217, 146, 84, 71, 192, 226, 0, 22, 32, 176, 236, 135, 150, 253, 138, 208, 67, 188, 22, 234, 10, 212, 44, 7, 247, 1, 248, 212, 115, 133, 144, 252, 96, 176, 155, 33, 110, 133, 156, 191, 141, 146, 119, 128, 202, 160, 249, 16, 61, 255, 0, 77, 2, 55, 90, 96, 209, 2, 239, 68, 160, 71, 25, 212, 72, 5, 216, 66, 28, 104, 68, 162, 231, 56, 66, 185, 45, 93, 7, 98, 29, 106, 110, 179, 82, 128, 9, 194, 114, 154, 2, 142, 100, 3, 179, 25, 154, 108, 106, 209, 187, 96, 100, 199, 11, 52, 176, 97, 49, 131, 158, 31, 208, 99, 6, 209, 122, 133, 84, 181, 174, 21, 5, 240, 203, 223, 65, 161, 139, 222, 70, 133, 203, 65, 131, 30, 102, 94, 90, 98, 78, 49, 40, 238, 97, 9, 19, 209, 37, 132, 95, 64, 31, 141, 232, 188, 7, 87, 230, 38, 229, 231, 104, 40, 129, 21, 41, 105, 198, 90, 115, 193, 34, 25, 172, 9, 105, 145, 81, 30, 116, 2, 9, 97, 147, 162, 34, 84, 21, 216, 54, 152, 143, 64, 206, 15, 200, 47, 46, 206, 76, 202, 169, 132, 182, 101, 193, 190, 129, 245, 207, 97, 142, 64, 237, 81, 133, 100, 20, 229, 151, 123, 230, 37, 231, 231, 22, 36, 150, 0, 181, 166, 66, 154, 195, 26, 121, 137, 185, 169, 144, 8, 46, 131, 216, 142, 54, 198, 97, 172, 163, 160, 4, 41, 128, 149, 116, 20, 192, 138, 17, 105, 23, 162, 11, 213, 30, 136, 84, 60, 200, 225, 208, 20, 89, 0, 13, 92, 240, 160, 130, 95, 105, 78, 142, 127, 81, 40, 204, 195, 96, 35, 80, 135, 87, 48, 221, 8, 11, 60, 136, 51, 53, 145, 131, 62, 179, 56, 32, 17, 124, 25, 37, 208, 90, 112, 139, 20, 62, 240, 146, 154, 14, 46, 238, 128, 161, 171, 84, 12, 113, 62, 44, 228, 193, 86, 41, 106, 160, 107, 85, 83, 83, 112, 78, 204, 131, 182, 185, 64, 185, 0, 40, 8, 110, 138, 65, 98, 208, 39, 63, 63, 187, 180, 64, 3, 232, 86, 104, 75, 74, 17, 195, 51, 48, 239, 2, 165, 65, 62, 130, 101, 103, 88, 130, 130, 73, 131, 108, 194, 51, 186, 2, 86, 4, 13, 18, 164, 84, 151, 156, 152, 147, 227, 6, 13, 100, 13, 176, 14, 72, 227, 69, 71, 1, 214, 118, 129, 5, 14, 172, 230, 71, 75, 155, 238, 169, 37, 208, 224, 132, 105, 192, 145, 72, 149, 52, 81, 203, 34, 92, 201, 20, 166, 68, 17, 205, 131, 48, 183, 131, 1, 196, 165, 16, 243, 193, 161, 153, 156, 159, 227, 159, 23, 80, 4, 244, 123, 73, 102, 89, 170, 115, 126, 105, 94, 73, 42, 180, 175, 13, 117, 57, 186, 175, 97, 7, 163, 192, 60, 15, 27, 79, 192, 229, 113, 88, 218, 8, 70, 46, 102, 225, 106, 128, 121, 15, 75, 212, 131, 74, 4, 92, 141, 239, 84, 13, 136, 143, 160, 33, 154, 150, 147, 88, 18, 4, 235, 251, 185, 1, 57, 16, 67, 192, 145, 161, 17, 12, 114, 21, 180, 226, 131, 133, 15, 66, 3, 246, 80, 132, 121, 22, 201, 100, 20, 207, 192, 198, 39, 97, 53, 31, 100, 108, 68, 163, 8, 102, 15, 44, 149, 17, 242, 0, 194, 38, 136, 65, 176, 198, 47, 108, 201, 144, 129, 38, 106, 49, 131, 30, 248, 224, 192, 7, 166, 34, 88, 42, 170, 192, 151, 130, 128, 225, 80, 1, 29, 170, 134, 149, 13, 168, 101, 131, 99, 78, 14, 117, 139, 7, 160, 129, 144, 18, 162, 24, 234, 15, 136, 153, 138, 24, 134, 194, 172, 133, 25, 139, 28, 122, 152, 73, 184, 44, 17, 222, 85, 133, 70, 173, 94, 26, 108, 213, 3, 68, 55, 22, 119, 131, 59, 149, 8, 135, 99, 25, 58, 54, 52, 52, 68, 79, 243, 176, 219, 63, 97, 249, 28, 215, 56, 31, 44, 77, 67, 45, 209, 129, 221, 3, 138, 219, 42, 35, 29, 5, 68, 24, 105, 162, 90, 91, 203, 133, 171, 156, 162, 86, 57, 5, 31, 116, 167, 114, 81, 5, 243, 15, 44, 171, 225, 42, 173, 96, 78, 68, 31, 131, 66, 247, 1, 172, 180, 162, 119, 105, 133, 54, 164, 130, 81, 100, 225, 202, 255, 80, 243, 64, 177, 111, 13, 202, 180, 184, 221, 0, 182, 12, 30, 168, 184, 114, 46, 34, 64, 117, 192, 26, 138, 42, 32, 52, 196, 101, 64, 38, 214, 204, 92, 144, 152, 2, 244, 99, 5, 164, 9, 170, 163, 144, 150, 153, 147, 3, 145, 209, 81, 0, 74, 185, 230, 129, 131, 31, 28, 244, 232, 217, 132, 216, 236, 13, 49, 70, 193, 94, 65, 9, 194, 82, 82, 176, 2, 51, 131, 75, 18, 139, 74, 144, 178, 60, 44, 40, 97, 179, 44, 88, 195, 49, 51, 175, 196, 23, 230, 90, 104, 219, 25, 196, 68, 120, 1, 174, 18, 104, 10, 80, 4, 52, 79, 12, 109, 137, 151, 100, 192, 234, 15, 20, 67, 108, 108, 161, 74, 97, 254, 128, 70, 4, 80, 16, 230, 40, 107, 168, 153, 224, 208, 73, 69, 113, 28, 34, 188, 224, 189, 23, 152, 34, 216, 205, 72, 56, 12, 197, 112, 136, 157, 130, 134, 134, 161, 130, 141, 141, 130, 177, 129, 166, 130, 174, 130, 17, 106, 192, 6, 37, 230, 165, 195, 11, 4, 3, 228, 240, 2, 187, 10, 236, 85, 212, 208, 209, 133, 250, 11, 230, 248, 146, 34, 96, 212, 39, 150, 164, 166, 64, 220, 235, 6, 243, 11, 74, 142, 7, 89, 8, 75, 26, 69, 169, 5, 169, 137, 37, 58, 32, 33, 168, 207, 33, 108, 13, 152, 133, 250, 16, 97, 104, 240, 2, 167, 220, 107, 16, 195, 140, 216, 109, 211, 70, 90, 178, 174, 1, 53, 19, 56, 6, 15, 247, 130, 42, 146, 137, 176, 200, 4, 6, 20, 52, 13, 129, 195, 20, 104, 112, 42, 102, 168, 42, 104, 99, 179, 17, 165, 229, 13, 84, 137, 203, 85, 224, 120, 193, 158, 57, 226, 139, 75, 18, 139, 74, 144, 179, 8, 44, 202, 193, 185, 93, 73, 65, 9, 232, 24, 184, 5, 168, 129, 137, 48, 5, 146, 202, 117, 20, 176, 26, 163, 3, 233, 146, 224, 202, 158, 241, 169, 121, 40, 89, 148, 250, 246, 67, 194, 20, 213, 122, 120, 44, 1, 103, 133, 129, 138, 139, 242, 115, 97, 43, 1, 32, 246, 89, 91, 35, 8, 152, 245, 72, 218, 188, 83, 139, 242, 82, 115, 52, 160, 5, 16, 52, 225, 160, 172, 216, 72, 3, 26, 9, 94, 152, 86, 163, 96, 128, 69, 26, 98, 23, 72, 1, 44, 85, 161, 7, 15, 52, 137, 230, 128, 47, 152, 77, 77, 44, 74, 206, 128, 30, 239, 10, 21, 4, 242, 192, 41, 5, 86, 122, 145, 87, 122, 41, 65, 77, 67, 20, 84, 136, 236, 11, 233, 137, 104, 64, 187, 44, 72, 110, 64, 233, 183, 192, 122, 38, 5, 37, 153, 185, 153, 85, 169, 193, 164, 246, 76, 128, 78, 69, 246, 159, 38, 90, 247, 4, 94, 237, 35, 169, 193, 91, 247, 163, 170, 132, 249, 95, 65, 1, 61, 5, 193, 26, 0, 21, 5, 144, 221, 125, 169, 58, 16, 47, 194, 130, 25, 20, 28, 168, 129, 141, 84, 45, 2, 43, 69, 248, 62, 30, 180, 54, 1, 146, 33, 216, 234, 49, 88, 120, 195, 219, 5, 240, 187, 110, 161, 13, 3, 66, 13, 3, 28, 222, 83, 128, 181, 14, 168, 213, 58, 0, 134, 15, 220, 97, 164, 4, 77, 45, 23, 36, 112, 112, 181, 24, 96, 210, 96, 3, 129, 50, 104, 138, 224, 190, 131, 26, 10, 244, 59, 52, 5, 162, 88, 136, 72, 130, 121, 233, 144, 34, 2, 230, 19, 88, 230, 129, 198, 106, 48, 44, 155, 67, 167, 99, 83, 17, 214, 162, 122, 1, 150, 244, 97, 161, 237, 12, 12, 143, 196, 164, 156, 84, 88, 32, 192, 2, 156, 76, 171, 224, 30, 68, 53, 206, 154, 11, 17, 98, 5, 249, 197, 72, 245, 21, 122, 11, 27, 60, 166, 237, 159, 6, 52, 23, 213, 124, 212, 218, 25, 100, 6, 234, 12, 28, 212, 165, 16, 93, 72, 214, 129, 61, 143, 52, 218, 7, 59, 205, 26, 189, 153, 88, 2, 77, 8, 112, 71, 235, 192, 147, 104, 10, 154, 39, 65, 62, 128, 185, 79, 19, 104, 22, 60, 178, 75, 18, 51, 115, 2, 64, 46, 3, 251, 81, 27, 69, 23, 172, 241, 2, 85, 154, 151, 90, 14, 17, 71, 247, 145, 1, 212, 67, 8, 21, 144, 101, 17, 232, 227, 117, 8, 105, 72, 101, 140, 26, 41, 6, 96, 71, 66, 131, 29, 89, 177, 182, 45, 44, 64, 160, 46, 129, 250, 195, 7, 214, 22, 131, 205, 213, 192, 92, 11, 118, 28, 204, 99, 54, 40, 170, 81, 92, 10, 51, 29, 195, 45, 208, 80, 129, 133, 24, 204, 38, 93, 168, 56, 204, 145, 176, 24, 68, 152, 134, 189, 166, 0, 71, 144, 99, 78, 14, 44, 7, 129, 163, 10, 168, 23, 17, 113, 16, 103, 81, 90, 89, 0, 77, 67, 233, 203, 194, 50, 13, 122, 95, 22, 86, 176, 163, 151, 85, 10, 40, 29, 90, 76, 5, 168, 189, 90, 91, 5, 36, 21, 40, 93, 91, 116, 143, 192, 186, 182, 136, 174, 45, 4, 160, 247, 55, 97, 93, 91, 88, 17, 8, 51, 138, 220, 174, 45, 46, 171, 96, 93, 91, 88, 160, 193, 58, 183, 48, 139, 97, 36, 185, 181, 28, 246, 144, 131, 230, 118, 36, 191, 160, 215, 114, 176, 0, 69, 47, 202, 97, 169, 4, 222, 249, 131, 70, 4, 76, 18, 86, 203, 81, 187, 150, 131, 57, 29, 173, 251, 139, 225, 61, 88, 45, 55, 92, 106, 57, 152, 69, 64, 181, 112, 191, 147, 82, 231, 192, 179, 34, 212, 72, 244, 106, 129, 216, 106, 7, 170, 193, 7, 92, 114, 1, 221, 8, 211, 143, 165, 108, 78, 132, 76, 193, 56, 85, 34, 47, 79, 6, 181, 102, 13, 129, 214, 34, 153, 2, 247, 126, 106, 94, 138, 127, 154, 79, 98, 113, 9, 80, 101, 114, 6, 100, 138, 28, 150, 168, 160, 67, 148, 74, 74, 80, 33, 248, 230, 94, 168, 50, 216, 121, 104, 176, 14, 17, 44, 57, 230, 165, 86, 148, 192, 118, 210, 130, 170, 75, 88, 174, 133, 117, 239, 128, 0, 37, 243, 66, 106, 77, 184, 76, 17, 98, 29, 44, 106, 80, 65, 197, 96, 187, 154, 193, 92, 164, 212, 139, 98, 173, 13, 92, 25, 34, 105, 194, 22, 250, 195, 242, 53, 92, 9, 116, 142, 9, 166, 217, 26, 234, 19, 88, 198, 74, 205, 77, 205, 3, 5, 4, 44, 166, 96, 158, 64, 79, 169, 72, 254, 83, 0, 105, 133, 199, 38, 204, 229, 10, 176, 76, 5, 89, 255, 139, 203, 139, 48, 167, 193, 182, 110, 35, 7, 12, 136, 11, 59, 114, 27, 230, 121, 68, 42, 15, 206, 201, 4, 175, 41, 9, 46, 77, 2, 10, 192, 156, 138, 30, 170, 104, 145, 174, 131, 22, 174, 10, 186, 104, 10, 144, 236, 130, 165, 10, 109, 80, 109, 139, 176, 81, 27, 57, 164, 128, 123, 189, 81, 237, 0, 39, 44, 132, 241, 218, 176, 148, 8, 78, 137, 64, 213, 72, 118, 131, 12, 134, 167, 97, 88, 22, 0, 69, 46, 170, 113, 144, 218, 28, 81, 217, 67, 226, 24, 230, 58, 244, 186, 28, 236, 117, 116, 79, 163, 26, 128, 225, 103, 144, 119, 97, 85, 59, 250, 28, 32, 106, 189, 14, 241, 12, 104, 160, 17, 54, 20, 141, 163, 222, 35, 88, 129, 131, 123, 123, 16, 227, 80, 58, 123, 64, 140, 50, 85, 5, 157, 111, 178, 133, 77, 85, 145, 59, 85, 5, 235, 16, 6, 67, 59, 132, 249, 68, 118, 8, 97, 99, 224, 176, 169, 42, 168, 151, 50, 97, 181, 36, 108, 116, 151, 216, 33, 96, 152, 1, 176, 192, 134, 149, 24, 176, 186, 17, 177, 173, 9, 117, 16, 20, 154, 247, 107, 97, 153, 0, 154, 174, 82, 81, 235, 193, 162, 84, 244, 17, 96, 88, 21, 8, 13, 106, 77, 164, 50, 4, 34, 68, 100, 13, 136, 238, 126, 82, 7, 128, 97, 142, 71, 243, 57, 122, 229, 87, 12, 117, 19, 124, 4, 24, 221, 243, 176, 154, 174, 184, 4, 123, 77, 7, 77, 11, 153, 104, 233, 71, 13, 125, 210, 10, 125, 206, 7, 230, 47, 60, 147, 86, 40, 7, 34, 192, 28, 136, 20, 158, 96, 109, 136, 169, 43, 93, 35, 228, 184, 70, 159, 179, 66, 247, 16, 174, 49, 107, 160, 5, 224, 140, 137, 43, 196, 96, 195, 213, 184, 134, 171, 209, 98, 159, 232, 193, 106, 96, 102, 7, 111, 151, 2, 198, 72, 65, 34, 100, 249, 171, 66, 14, 40, 98, 33, 158, 202, 36, 55, 215, 167, 104, 40, 129, 205, 69, 207, 244, 176, 142, 117, 126, 26, 88, 92, 1, 150, 193, 51, 161, 29, 106, 88, 32, 163, 143, 237, 96, 207, 202, 213, 92, 176, 36, 12, 55, 21, 238, 15, 172, 70, 43, 64, 21, 231, 160, 239, 83, 77, 133, 102, 8, 24, 64, 105, 245, 4, 3, 125, 2, 77, 28, 96, 191, 235, 32, 108, 129, 38, 89, 5, 88, 178, 135, 209, 176, 56, 135, 149, 88, 176, 33, 45, 92, 46, 68, 31, 208, 34, 167, 252, 66, 196, 33, 206, 34, 172, 24, 166, 130, 64, 41, 6, 87, 7, 11, 100, 212, 236, 236, 86, 138, 90, 144, 129, 194, 7, 41, 80, 32, 113, 14, 78, 72, 153, 37, 144, 16, 130, 134, 74, 89, 98, 17, 116, 123, 33, 180, 68, 43, 241, 77, 45, 201, 200, 71, 114, 58, 52, 89, 163, 38, 235, 130, 156, 204, 18, 212, 50, 13, 102, 6, 172, 76, 67, 139, 194, 76, 88, 153, 134, 203, 55, 52, 42, 214, 10, 96, 155, 33, 9, 133, 5, 16, 67, 66, 35, 24, 107, 217, 6, 146, 9, 2, 49, 224, 137, 21, 187, 79, 129, 197, 24, 100, 223, 52, 250, 190, 105, 160, 247, 144, 13, 134, 135, 0, 44, 12, 209, 119, 81, 163, 120, 45, 58, 22, 238, 78, 88, 120, 35, 210, 44, 246, 0, 135, 233, 12, 70, 209, 90, 148, 10, 203, 69, 168, 185, 200, 39, 19, 188, 193, 86, 71, 33, 8, 28, 48, 240, 210, 1, 183, 155, 9, 185, 2, 221, 13, 32, 243, 112, 219, 15, 182, 26, 107, 97, 88, 140, 212, 198, 74, 44, 42, 1, 54, 177, 32, 147, 117, 232, 69, 33, 44, 203, 17, 89, 20, 194, 76, 85, 130, 21, 135, 176, 26, 1, 92, 197, 1, 253, 131, 35, 13, 228, 160, 79, 182, 65, 197, 51, 243, 74, 130, 65, 238, 3, 183, 224, 61, 243, 74, 82, 211, 83, 139, 32, 46, 134, 106, 5, 43, 113, 205, 75, 1, 42, 72, 5, 145, 200, 225, 165, 96, 15, 54, 215, 10, 73, 43, 80, 13, 92, 35, 80, 77, 98, 14, 204, 116, 88, 135, 43, 62, 55, 51, 79, 3, 169, 247, 85, 161, 1, 113, 2, 40, 136, 12, 52, 117, 20, 128, 6, 162, 26, 0, 177, 27, 183, 118, 136, 243, 176, 104, 46, 202, 207, 69, 215, 136, 112, 145, 14, 204, 112, 132, 115, 75, 242, 145, 149, 3, 141, 198, 173, 188, 40, 181, 4, 125, 62, 5, 56, 159, 130, 152, 140, 81, 168, 81, 48, 208, 81, 208, 0, 154, 168, 11, 230, 107, 66, 182, 141, 64, 246, 218, 121, 22, 123, 230, 229, 0, 77, 3, 70, 171, 79, 98, 81, 122, 170, 91, 105, 94, 114, 73, 38, 48, 211, 163, 164, 28, 32, 75, 211, 26, 75, 170, 2, 202, 65, 35, 8, 50, 227, 83, 146, 129, 61, 85, 17, 91, 193, 194, 82, 85, 73, 17, 105, 73, 138, 80, 210, 1, 42, 129, 28, 157, 0, 77, 118, 168, 201, 46, 53, 15, 24, 169, 80, 247, 67, 210, 20, 34, 77, 65, 116, 33, 39, 42, 168, 63, 161, 197, 24, 60, 193, 40, 216, 32, 138, 156, 76, 152, 24, 90, 20, 102, 194, 196, 181, 193, 198, 234, 40, 0, 163, 1, 101, 200, 21, 151, 222, 204, 60, 68, 194, 4, 107, 69, 9, 151, 162, 84, 80, 255, 31, 50, 92, 138, 170, 13, 45, 117, 166, 194, 146, 38, 116, 59, 46, 204, 46, 77, 216, 220, 28, 44, 45, 161, 167, 37, 80, 90, 66, 184, 12, 148, 158, 80, 45, 37, 53, 65, 21, 161, 165, 38, 144, 68, 114, 126, 94, 114, 34, 120, 73, 163, 161, 38, 165, 137, 72, 9, 98, 24, 122, 51, 173, 12, 87, 34, 130, 218, 230, 8, 93, 78, 89, 12, 241, 150, 134, 38, 172, 38, 129, 149, 196, 176, 217, 126, 152, 129, 184, 53, 65, 252, 0, 211, 4, 155, 119, 134, 91, 235, 158, 90, 2, 211, 167, 97, 160, 169, 73, 216, 60, 35, 146, 204, 195, 37, 101, 8, 181, 10, 150, 112, 96, 221, 4, 168, 151, 210, 242, 161, 23, 153, 102, 66, 46, 50, 205, 84, 176, 81, 192, 112, 14, 80, 24, 126, 159, 41, 124, 16, 9, 98, 23, 60, 96, 209, 172, 205, 212, 212, 132, 212, 159, 240, 94, 63, 84, 19, 108, 110, 2, 86, 171, 193, 186, 239, 216, 187, 239, 57, 153, 201, 169, 196, 85, 96, 68, 166, 146, 98, 144, 137, 164, 36, 18, 122, 87, 94, 48, 141, 105, 69, 249, 185, 10, 182, 92, 10, 176, 242, 1, 90, 222, 112, 193, 214, 115, 195, 74, 10, 216, 116, 184, 130, 54, 68, 29, 180, 34, 227, 130, 173, 227, 70, 168, 203, 204, 211, 64, 168, 0, 22, 221, 80, 171, 32, 21, 15, 204, 34, 160, 99, 65, 214, 224, 180, 192, 21, 82, 158, 96, 26, 12, 146, 65, 53, 182, 184, 32, 17, 24, 108, 168, 230, 0, 173, 210, 5, 123, 13, 100, 8, 222, 210, 7, 185, 38, 3, 27, 69, 160, 196, 129, 85, 97, 136, 116, 131, 90, 224, 32, 173, 89, 209, 72, 206, 47, 205, 43, 129, 150, 56, 176, 180, 68, 106, 90, 2, 78, 231, 128, 77, 67, 47, 113, 96, 109, 97, 28, 73, 41, 15, 185, 182, 130, 56, 4, 94, 22, 229, 129, 66, 30, 102, 43, 250, 178, 30, 67, 3, 11, 136, 21, 80, 197, 138, 64, 229, 90, 240, 67, 129, 20, 108, 108, 209, 214, 7, 105, 162, 186, 31, 110, 18, 108, 129, 16, 208, 36, 112, 13, 0, 35, 192, 227, 172, 10, 106, 64, 83, 80, 141, 1, 70, 187, 33, 220, 245, 33, 240, 17, 103, 112, 185, 97, 109, 13, 179, 3, 226, 124, 53, 160, 82, 168, 128, 2, 80, 173, 182, 173, 66, 176, 53, 82, 251, 59, 79, 193, 206, 206, 86, 193, 16, 34, 4, 214, 129, 80, 29, 12, 87, 141, 86, 57, 194, 70, 134, 97, 230, 192, 10, 142, 210, 162, 60, 133, 16, 96, 153, 129, 17, 199, 153, 144, 141, 157, 69, 26, 164, 69, 48, 98, 218, 9, 98, 45, 108, 67, 130, 130, 130, 18, 196, 96, 37, 56, 31, 220, 211, 202, 209, 131, 89, 4, 147, 64, 141, 113, 164, 65, 224, 90, 80, 232, 225, 77, 21, 48, 163, 128, 10, 252, 160, 211, 148, 176, 13, 170, 69, 26, 96, 85, 161, 232, 219, 40, 208, 246, 7, 27, 0, 151, 227, 18, 165, 208, 16, 154, 243, 96, 97, 8, 147, 65, 15, 74, 180, 45, 178, 26, 192, 192, 2, 59, 22, 182, 243, 23, 182, 243, 23, 214, 65, 133, 116, 80, 129, 114, 154, 144, 157, 191, 176, 157, 191, 69, 41, 16, 47, 35, 140, 3, 43, 210, 132, 237, 249, 133, 109, 224, 129, 185, 39, 57, 49, 39, 199, 13, 232, 14, 216, 88, 17, 108, 207, 47, 204, 12, 216, 110, 95, 66, 187, 125, 97, 209, 6, 211, 129, 190, 207, 23, 22, 39, 176, 77, 158, 232, 155, 60, 97, 129, 7, 219, 244, 100, 128, 136, 44, 240, 206, 23, 92, 91, 91, 81, 117, 25, 106, 194, 116, 129, 27, 149, 182, 10, 193, 176, 42, 4, 86, 31, 195, 234, 99, 244, 125, 198, 176, 125, 198, 240, 125, 198, 176, 192, 206, 132, 108, 92, 133, 29, 231, 2, 11, 60, 216, 246, 37, 180, 237, 75, 169, 72, 53, 44, 178, 191, 147, 243, 83, 82, 3, 242, 51, 243, 74, 96, 115, 64, 176, 32, 71, 154, 252, 129, 171, 113, 44, 1, 45, 33, 135, 120, 28, 238, 161, 228, 140, 196, 34, 224, 208, 2, 216, 4, 67, 5, 109, 5, 13, 132, 145, 118, 10, 144, 211, 209, 64, 106, 113, 36, 72, 72, 232, 64, 205, 4, 234, 134, 155, 6, 212, 3, 246, 14, 124, 207, 15, 30, 7, 166, 1, 195, 220, 25, 102, 171, 14, 56, 53, 233, 192, 124, 6, 51, 9, 22, 0, 176, 38, 6, 122, 123, 21, 189, 246, 128, 165, 24, 112, 178, 7, 154, 129, 158, 41, 226, 139, 75, 18, 75, 50, 147, 227, 139, 18, 203, 193, 71, 46, 4, 103, 150, 164, 42, 32, 50, 71, 114, 126, 126, 118, 106, 10, 56, 163, 67, 178, 4, 92, 17, 60, 224, 128, 58, 145, 229, 33, 58, 244, 128, 162, 112, 21, 57, 64, 229, 69, 137, 57, 193, 169, 233, 160, 102, 24, 228, 188, 10, 104, 91, 12, 168, 12, 58, 171, 168, 9, 75, 16, 24, 170, 109, 109, 21, 12, 52, 81, 115, 149, 146, 18, 44, 242, 113, 233, 48, 68, 211, 1, 203, 181, 32, 27, 163, 13, 98, 53, 97, 250, 225, 137, 22, 154, 91, 96, 101, 26, 154, 82, 112, 253, 0, 82, 11, 223, 31, 6, 84, 104, 104, 141, 196, 181, 65, 247, 38, 146, 36, 188, 181, 9, 118, 46, 178, 30, 140, 182, 41, 76, 33, 44, 15, 64, 93, 165, 13, 115, 22, 90, 187, 20, 110, 150, 166, 38, 100, 195, 90, 45, 212, 211, 56, 244, 130, 188, 4, 215, 131, 8, 5, 72, 32, 161, 104, 67, 43, 64, 193, 105, 37, 41, 51, 157, 196, 106, 8, 222, 61, 134, 181, 89, 83, 52, 148, 146, 50, 145, 134, 91, 80, 236, 87, 178, 1, 202, 217, 41, 129, 218, 254, 48, 7, 131, 149, 1, 5, 148, 108, 244, 193, 114, 88, 157, 149, 147, 153, 151, 77, 5, 135, 129, 205, 193, 233, 52, 176, 44, 78, 199, 65, 101, 177, 58, 47, 63, 39, 69, 131, 114, 215, 129, 140, 193, 237, 56, 220, 14, 195, 238, 168, 180, 204, 138, 84, 106, 184, 10, 100, 14, 110, 103, 149, 148, 224, 116, 87, 73, 9, 118, 135, 101, 150, 36, 230, 100, 38, 195, 142, 86, 162, 196, 105, 80, 147, 112, 58, 46, 19, 167, 219, 128, 50, 216, 156, 86, 156, 155, 152, 147, 67, 5, 135, 129, 205, 193, 233, 44, 176, 44, 78, 167, 65, 101, 177, 58, 15, 72, 101, 167, 82, 193, 125, 96, 131, 160, 189, 74, 44, 14, 132, 72, 227, 116, 33, 68, 26, 135, 19, 75, 147, 40, 116, 31, 116, 124, 13, 183, 227, 74, 33, 89, 1, 155, 203, 64, 114, 56, 156, 85, 64, 21, 103, 21, 224, 113, 86, 1, 78, 103, 129, 229, 80, 156, 229, 90, 156, 156, 88, 144, 234, 88, 2, 84, 154, 84, 90, 2, 89, 215, 161, 81, 6, 118, 0, 180, 201, 86, 80, 90, 18, 140, 210, 195, 7, 74, 91, 35, 44, 12, 46, 129, 45, 10, 66, 89, 20, 4, 211, 167, 163, 160, 174, 164, 174, 163, 160, 164, 86, 88, 154, 95, 98, 173, 164, 137, 45, 76, 18, 243, 146, 51, 242, 139, 52, 242, 18, 115, 83, 41, 15, 26, 136, 97, 200, 161, 3, 107, 176, 6, 67, 253, 0, 15, 20, 100, 111, 168, 219, 36, 130, 119, 241, 218, 42, 169, 43, 104, 99, 15, 21, 144, 52, 40, 28, 213, 149, 236, 64, 106, 130, 33, 65, 154, 136, 61, 158, 211, 242, 243, 74, 146, 243, 115, 128, 222, 2, 147, 148, 251, 11, 110, 32, 25, 94, 3, 233, 85, 0, 107, 198, 227, 61, 168, 59, 209, 253, 7, 210, 139, 219, 139, 197, 153, 85, 169, 26, 208, 230, 52, 165, 30, 132, 26, 135, 94, 24, 16, 235, 63, 96, 163, 30, 95, 236, 1, 29, 137, 22, 123, 248, 125, 151, 147, 153, 151, 173, 81, 90, 148, 67, 185, 199, 64, 38, 145, 149, 30, 51, 138, 82, 211, 240, 248, 8, 232, 56, 34, 146, 99, 106, 9, 210, 241, 119, 158, 121, 153, 144, 30, 45, 232, 184, 90, 68, 38, 47, 78, 45, 65, 234, 151, 66, 22, 220, 165, 164, 22, 129, 215, 228, 149, 232, 1, 217, 214, 160, 32, 64, 91, 41, 8, 86, 130, 236, 123, 216, 72, 0, 120, 164, 196, 72, 71, 1, 58, 215, 13, 54, 10, 226, 113, 200, 168, 41, 162, 117, 11, 246, 135, 2, 72, 77, 78, 78, 126, 57, 116, 38, 213, 19, 232, 60, 184, 27, 65, 230, 163, 175, 13, 119, 131, 250, 13, 228, 2, 200, 60, 107, 9, 248, 42, 140, 18, 196, 82, 201, 90, 180, 32, 112, 203, 47, 114, 77, 76, 206, 0, 247, 40, 146, 18, 147, 179, 211, 242, 32, 241, 225, 88, 148, 174, 96, 139, 62, 139, 8, 139, 27, 88, 120, 160, 246, 211, 131, 33, 189, 116, 160, 2, 88, 31, 61, 24, 122, 82, 20, 80, 14, 220, 57, 39, 173, 115, 158, 90, 226, 155, 138, 191, 71, 14, 245, 61, 212, 221, 8, 89, 144, 235, 17, 93, 118, 184, 39, 225, 93, 117, 96, 48, 96, 137, 54, 68, 16, 224, 139, 59, 151, 212, 228, 252, 220, 130, 204, 156, 84, 160, 29, 26, 6, 58, 96, 7, 192, 116, 193, 76, 6, 133, 19, 184, 159, 89, 12, 233, 104, 194, 253, 7, 233, 104, 166, 150, 196, 67, 100, 117, 20, 130, 193, 122, 160, 41, 13, 20, 191, 137, 32, 101, 65, 176, 14, 60, 228, 64, 144, 96, 12, 41, 180, 187, 105, 97, 206, 5, 154, 3, 238, 223, 67, 22, 15, 248, 1, 35, 30, 168, 213, 53, 175, 164, 168, 18, 24, 2, 176, 46, 168, 6, 204, 238, 226, 84, 116, 99, 193, 142, 129, 4, 12, 200, 24, 152, 177, 24, 195, 101, 48, 31, 130, 123, 210, 88, 204, 137, 54, 136, 5, 43, 198, 46, 165, 96, 11, 59, 21, 9, 150, 122, 209, 82, 47, 60, 34, 96, 105, 17, 24, 155, 16, 219, 160, 20, 44, 220, 96, 137, 25, 156, 152, 85, 128, 126, 133, 29, 9, 10, 113, 121, 17, 56, 129, 1, 141, 128, 29, 9, 138, 126, 36, 40, 76, 7, 174, 243, 64, 193, 231, 129, 34, 206, 174, 194, 136, 7, 96, 20, 65, 207, 29, 196, 148, 210, 64, 116, 243, 243, 20, 160, 210, 176, 17, 0, 13, 68, 118, 242, 7, 26, 81, 130, 53, 59, 249, 107, 42, 212, 212, 40, 104, 128, 20, 192, 134, 188, 16, 166, 104, 248, 99, 203, 80, 176, 12, 149, 3, 77, 112, 232, 25, 10, 166, 157, 208, 80, 23, 44, 223, 192, 148, 163, 143, 115, 193, 146, 44, 186, 167, 209, 147, 44, 122, 146, 133, 244, 243, 75, 194, 18, 115, 32, 131, 83, 56, 6, 167, 74, 138, 74, 33, 99, 83, 10, 196, 37, 104, 127, 92, 105, 25, 18, 162, 136, 164, 172, 0, 27, 24, 205, 245, 206, 204, 75, 81, 176, 37, 52, 220, 230, 15, 29, 108, 83, 128, 58, 29, 230, 17, 104, 30, 129, 27, 4, 155, 169, 131, 6, 93, 17, 44, 44, 48, 93, 21, 109, 16, 11, 212, 143, 62, 30, 13, 29, 46, 87, 64, 214, 27, 141, 85, 51, 170, 79, 225, 194, 48, 67, 161, 153, 14, 93, 5, 44, 211, 193, 50, 29, 36, 14, 244, 202, 160, 25, 24, 238, 47, 184, 20, 108, 208, 15, 229, 224, 154, 162, 84, 232, 248, 4, 72, 133, 53, 114, 214, 3, 6, 32, 120, 44, 46, 57, 191, 40, 5, 50, 92, 91, 13, 14, 124, 88, 114, 134, 141, 226, 226, 40, 86, 77, 205, 116, 32, 3, 192, 208, 244, 172, 128, 126, 42, 110, 26, 72, 26, 41, 233, 1, 163, 34, 177, 60, 24, 60, 248, 9, 146, 209, 43, 206, 172, 2, 187, 18, 36, 147, 87, 154, 11, 149, 209, 134, 42, 178, 230, 130, 184, 5, 38, 3, 92, 43, 4, 85, 5, 75, 22, 96, 105, 184, 145, 136, 153, 123, 88, 189, 135, 205, 205, 38, 58, 10, 74, 208, 70, 153, 18, 92, 185, 146, 38, 214, 216, 197, 167, 215, 47, 209, 15, 174, 11, 230, 65, 232, 52, 32, 208, 53, 40, 179, 128, 80, 15, 104, 90, 67, 61, 4, 83, 3, 159, 225, 65, 159, 151, 41, 210, 48, 179, 180, 68, 9, 183, 140, 196, 98, 104, 152, 1, 89, 214, 232, 109, 23, 96, 37, 152, 145, 136, 212, 110, 67, 171, 253, 140, 129, 206, 5, 202, 43, 105, 34, 155, 152, 157, 90, 9, 51, 18, 200, 196, 106, 38, 80, 28, 191, 161, 64, 5, 96, 83, 81, 210, 89, 181, 66, 113, 106, 137, 149, 2, 104, 80, 23, 188, 208, 192, 10, 22, 38, 58, 10, 64, 71, 232, 64, 44, 174, 69, 73, 135, 238, 176, 82, 32, 191, 200, 173, 40, 63, 215, 23, 210, 204, 4, 26, 19, 148, 154, 12, 178, 31, 225, 98, 79, 240, 18, 59, 108, 181, 15, 84, 57, 216, 51, 58, 10, 80, 78, 113, 42, 184, 60, 129, 249, 12, 154, 164, 179, 161, 6, 225, 242, 27, 52, 246, 77, 205, 96, 101, 42, 76, 3, 44, 165, 163, 167, 244, 212, 252, 52, 184, 26, 228, 182, 10, 44, 76, 224, 146, 80, 95, 195, 43, 151, 208, 60, 144, 203, 243, 75, 50, 82, 139, 64, 110, 129, 85, 45, 196, 86, 45, 176, 150, 26, 80, 14, 165, 98, 129, 249, 171, 8, 90, 177, 192, 42, 22, 144, 101, 160, 216, 69, 111, 162, 165, 166, 64, 42, 108, 29, 5, 176, 83, 128, 49, 11, 115, 27, 106, 154, 1, 203, 2, 195, 21, 104, 63, 74, 209, 1, 20, 7, 55, 136, 209, 227, 9, 71, 196, 130, 149, 131, 162, 22, 93, 7, 104, 148, 29, 168, 11, 198, 213, 203, 3, 242, 65, 106, 96, 133, 56, 168, 162, 2, 5, 155, 115, 126, 65, 37, 208, 195, 214, 196, 182, 190, 139, 194, 51, 75, 50, 128, 134, 35, 162, 30, 146, 12, 97, 118, 194, 18, 2, 44, 164, 96, 147, 11, 144, 54, 95, 98, 74, 138, 14, 196, 122, 244, 86, 57, 44, 138, 17, 195, 191, 168, 17, 12, 174, 159, 82, 139, 138, 129, 241, 51, 72, 227, 25, 213, 137, 228, 68, 55, 200, 151, 10, 182, 144, 245, 173, 153, 57, 37, 153, 121, 72, 157, 51, 13, 144, 249, 64, 51, 209, 163, 48, 47, 181, 28, 164, 77, 3, 38, 3, 118, 20, 176, 216, 132, 205, 239, 96, 68, 65, 49, 184, 248, 240, 135, 229, 101, 13, 184, 122, 27, 91, 184, 43, 245, 16, 157, 118, 5, 5, 72, 75, 158, 80, 75, 62, 181, 24, 98, 40, 76, 7, 161, 134, 17, 76, 10, 94, 239, 162, 181, 230, 129, 118, 131, 1, 200, 172, 148, 252, 188, 84, 98, 219, 243, 232, 70, 67, 157, 164, 0, 246, 43, 208, 32, 152, 209, 96, 144, 84, 148, 10, 155, 2, 7, 70, 21, 152, 70, 111, 215, 163, 155, 7, 107, 215, 163, 183, 236, 209, 27, 25, 8, 91, 193, 109, 121, 103, 88, 9, 155, 7, 77, 191, 176, 144, 206, 72, 132, 37, 33, 104, 33, 11, 109, 223, 195, 243, 17, 113, 121, 169, 12, 150, 143, 96, 94, 129, 146, 181, 176, 90, 24, 230, 51, 210, 74, 20, 5, 5, 138, 11, 5, 189, 60, 112, 169, 0, 243, 13, 44, 68, 48, 253, 3, 14, 9, 127, 88, 177, 64, 106, 16, 160, 23, 39, 104, 193, 64, 168, 112, 113, 201, 76, 75, 75, 45, 74, 205, 75, 78, 29, 164, 69, 11, 194, 129, 168, 5, 11, 44, 186, 32, 241, 25, 156, 138, 94, 176, 128, 85, 1, 173, 134, 149, 248, 176, 18, 31, 38, 53, 80, 229, 69, 106, 49, 44, 230, 32, 209, 53, 220, 11, 13, 152, 6, 116, 73, 244, 158, 9, 141, 11, 141, 148, 212, 156, 212, 146, 84, 68, 166, 41, 131, 101, 24, 244, 114, 99, 176, 149, 27, 132, 188, 3, 43, 3, 224, 101, 0, 212, 43, 132, 242, 62, 208, 148, 224, 202, 220, 220, 212, 146, 162, 204, 100, 228, 66, 128, 90, 133, 0, 161, 66, 128, 216, 17, 63, 5, 164, 129, 9, 72, 212, 195, 56, 74, 216, 189, 160, 132, 218, 122, 70, 46, 43, 64, 110, 197, 85, 86, 144, 26, 211, 48, 29, 176, 54, 167, 130, 45, 106, 12, 194, 212, 224, 40, 129, 224, 109, 78, 114, 147, 137, 31, 52, 149, 112, 65, 51, 14, 172, 110, 129, 165, 19, 88, 221, 130, 171, 110, 129, 213, 44, 4, 242, 9, 92, 35, 44, 97, 193, 242, 7, 46, 51, 8, 213, 78, 68, 165, 76, 207, 226, 224, 210, 164, 226, 212, 18, 255, 52, 104, 28, 41, 84, 115, 65, 19, 164, 2, 52, 65, 114, 65, 19, 164, 39, 52, 65, 106, 64, 19, 164, 63, 52, 65, 166, 64, 19, 100, 22, 52, 65, 194, 26, 188, 57, 208, 0, 128, 57, 0, 230, 3, 210, 106, 37, 132, 3, 97, 181, 18, 174, 148, 150, 154, 140, 154, 210, 208, 171, 30, 244, 0, 196, 91, 245, 216, 97, 214, 60, 8, 175, 160, 142, 216, 192, 106, 35, 88, 109, 132, 110, 11, 172, 54, 130, 217, 3, 171, 134, 96, 5, 56, 172, 26, 194, 83, 13, 161, 84, 66, 48, 183, 128, 204, 73, 201, 207, 75, 37, 182, 10, 66, 55, 86, 211, 26, 146, 162, 97, 21, 16, 60, 169, 37, 21, 165, 38, 102, 91, 115, 193, 10, 106, 152, 15, 9, 85, 61, 232, 82, 232, 173, 85, 168, 93, 138, 228, 214, 59, 48, 231, 161, 199, 1, 122, 74, 135, 46, 162, 171, 133, 165, 115, 120, 58, 47, 72, 45, 26, 204, 41, 29, 230, 68, 186, 167, 117, 27, 210, 210, 58, 105, 165, 119, 90, 62, 133, 197, 175, 30, 172, 150, 134, 151, 191, 138, 88, 189, 151, 145, 8, 45, 128, 97, 246, 80, 154, 100, 60, 139, 93, 50, 139, 179, 242, 51, 243, 74, 64, 126, 163, 95, 162, 161, 78, 125, 141, 234, 122, 80, 85, 173, 160, 160, 137, 28, 141, 176, 56, 167, 85, 162, 178, 197, 158, 170, 202, 18, 137, 45, 45, 253, 53, 33, 81, 5, 43, 47, 75, 82, 139, 192, 69, 11, 172, 188, 196, 91, 94, 2, 75, 204, 140, 76, 72, 137, 9, 43, 49, 97, 102, 81, 92, 102, 98, 47, 53, 21, 16, 229, 38, 164, 228, 132, 217, 8, 245, 175, 2, 158, 178, 147, 168, 210, 19, 106, 43, 217, 197, 39, 204, 157, 176, 4, 7, 43, 64, 97, 206, 69, 111, 151, 195, 92, 79, 108, 126, 135, 181, 203, 211, 242, 33, 57, 94, 33, 15, 146, 227, 75, 83, 33, 57, 62, 39, 31, 146, 227, 243, 74, 32, 57, 190, 36, 3, 146, 227, 161, 198, 235, 192, 45, 210, 67, 201, 241, 10, 48, 95, 19, 155, 229, 137, 244, 38, 23, 174, 204, 159, 167, 16, 150, 153, 90, 158, 154, 226, 88, 84, 148, 88, 233, 84, 154, 150, 150, 90, 228, 153, 22, 148, 154, 153, 150, 153, 154, 162, 81, 146, 88, 4, 20, 133, 88, 99, 13, 203, 36, 73, 165, 105, 72, 211, 92, 37, 40, 179, 91, 16, 13, 160, 85, 232, 176, 13, 27, 48, 107, 97, 5, 134, 6, 80, 187, 166, 130, 61, 200, 20, 232, 85, 54, 40, 142, 241, 44, 118, 73, 45, 73, 76, 206, 72, 77, 129, 184, 5, 164, 60, 13, 92, 18, 65, 179, 28, 136, 143, 52, 218, 173, 9, 43, 86, 208, 188, 95, 11, 179, 30, 164, 7, 170, 9, 81, 68, 33, 121, 22, 102, 1, 174, 146, 10, 102, 36, 172, 40, 129, 157, 195, 13, 11, 1, 92, 19, 125, 80, 115, 117, 20, 140, 53, 145, 66, 65, 35, 13, 113, 207, 147, 38, 120, 214, 200, 0, 197, 251, 64, 211, 28, 75, 192, 254, 71, 142, 16, 228, 120, 128, 69, 1, 216, 63, 68, 196, 29, 44, 12, 112, 5, 44, 204, 183, 104, 243, 12, 102, 6, 70, 144, 242, 19, 238, 118, 168, 165, 68, 56, 23, 154, 81, 32, 38, 67, 53, 227, 242, 88, 70, 102, 177, 38, 138, 145, 174, 121, 197, 165, 69, 169, 64, 135, 64, 21, 134, 103, 150, 100, 32, 235, 72, 44, 74, 71, 36, 6, 96, 162, 2, 39, 42, 136, 168, 154, 154, 130, 103, 49, 66, 39, 88, 16, 230, 61, 12, 251, 17, 166, 65, 114, 11, 196, 157, 48, 47, 35, 138, 106, 88, 245, 228, 12, 20, 65, 152, 237, 155, 138, 94, 71, 1, 65, 34, 104, 133, 8, 120, 125, 8, 190, 112, 81, 226, 2, 87, 77, 72, 94, 70, 24, 11, 93, 57, 224, 156, 159, 87, 12, 27, 166, 134, 77, 125, 34, 242, 31, 80, 24, 24, 245, 224, 217, 49, 224, 229, 143, 48, 133, 176, 120, 78, 70, 219, 173, 15, 155, 111, 132, 199, 4, 146, 225, 110, 249, 69, 72, 193, 133, 60, 31, 154, 153, 134, 84, 199, 131, 205, 132, 133, 36, 122, 66, 49, 53, 211, 81, 80, 2, 106, 5, 170, 83, 47, 86, 80, 71, 114, 145, 186, 66, 65, 81, 126, 65, 106, 81, 73, 37, 168, 125, 135, 200, 63, 224, 170, 16, 232, 135, 104, 148, 115, 39, 160, 231, 78, 128, 253, 143, 116, 65, 137, 39, 108, 25, 24, 204, 55, 26, 208, 53, 96, 100, 120, 200, 19, 57, 96, 49, 205, 41, 134, 168, 69, 243, 33, 116, 202, 205, 208, 4, 26, 181, 14, 14, 80, 71, 194, 125, 167, 0, 158, 75, 134, 6, 0, 236, 58, 78, 160, 13, 152, 17, 29, 150, 152, 147, 153, 146, 88, 2, 78, 221, 48, 55, 194, 162, 23, 57, 57, 131, 68, 97, 174, 131, 74, 160, 105, 129, 73, 42, 40, 224, 72, 216, 48, 191, 43, 160, 36, 109, 160, 255, 144, 204, 12, 200, 47, 46, 206, 68, 92, 223, 130, 221, 10, 168, 106, 156, 106, 61, 18, 81, 11, 150, 34, 52, 205, 232, 193, 9, 43, 89, 96, 21, 20, 166, 11, 177, 199, 130, 153, 145, 1, 214, 92, 3, 116, 2, 100, 185, 76, 120, 102, 73, 6, 116, 179, 5, 82, 36, 232, 160, 108, 254, 47, 75, 44, 82, 200, 75, 5, 155, 10, 209, 170, 96, 139, 136, 49, 212, 102, 6, 52, 219, 35, 226, 19, 218, 222, 196, 16, 128, 222, 234, 6, 109, 111, 98, 137, 98, 20, 11, 53, 97, 185, 24, 168, 13, 104, 57, 206, 96, 133, 250, 4, 83, 47, 40, 50, 64, 122, 109, 160, 22, 163, 103, 75, 120, 112, 25, 194, 188, 14, 217, 237, 10, 75, 220, 208, 196, 142, 18, 10, 4, 195, 21, 18, 179, 168, 225, 10, 171, 223, 146, 42, 75, 82, 253, 211, 210, 138, 83, 81, 15, 90, 160, 69, 88, 131, 237, 132, 54, 252, 145, 236, 37, 55, 30, 200, 8, 125, 178, 66, 47, 40, 181, 56, 179, 42, 49, 41, 39, 149, 184, 96, 164, 119, 240, 13, 142, 32, 67, 170, 254, 192, 33, 135, 156, 159, 83, 43, 82, 115, 11, 114, 18, 81, 50, 51, 252, 222, 105, 52, 253, 104, 213, 39, 76, 171, 38, 220, 41, 216, 227, 8, 106, 147, 51, 220, 10, 98, 157, 8, 141, 83, 96, 12, 192, 93, 201, 133, 28, 210, 168, 201, 20, 154, 72, 105, 224, 1, 168, 59, 156, 97, 25, 19, 150, 162, 96, 25, 147, 88, 79, 193, 82, 108, 102, 21, 36, 197, 18, 235, 59, 106, 251, 9, 221, 25, 56, 61, 135, 203, 83, 174, 121, 37, 69, 136, 117, 155, 101, 176, 65, 12, 232, 32, 134, 43, 172, 153, 137, 222, 204, 132, 90, 229, 15, 75, 237, 248, 82, 59, 72, 21, 194, 7, 16, 119, 131, 165, 129, 221, 70, 216, 50, 66, 5, 35, 156, 14, 44, 75, 45, 170, 212, 128, 45, 76, 77, 203, 83, 160, 196, 165, 56, 171, 20, 28, 110, 6, 181, 173, 28, 65, 123, 20, 97, 123, 20, 17, 103, 138, 96, 175, 81, 52, 76, 77, 117, 20, 12, 116, 20, 148, 84, 17, 38, 170, 234, 21, 192, 206, 252, 211, 75, 5, 250, 6, 169, 161, 151, 137, 182, 94, 43, 25, 238, 77, 104, 219, 0, 195, 124, 2, 11, 161, 97, 38, 195, 198, 105, 160, 171, 201, 49, 253, 96, 167, 96, 168, 96, 175, 224, 142, 180, 151, 210, 80, 83, 193, 74, 1, 222, 28, 134, 174, 204, 129, 116, 218, 179, 129, 70, 24, 88, 3, 41, 112, 117, 10, 100, 104, 195, 118, 116, 130, 237, 201, 14, 75, 132, 140, 101, 248, 71, 103, 67, 135, 46, 192, 214, 167, 22, 151, 192, 198, 177, 21, 208, 70, 40, 96, 171, 141, 209, 87, 27, 235, 64, 13, 3, 210, 144, 193, 30, 104, 203, 74, 67, 17, 97, 26, 216, 106, 104, 131, 8, 214, 247, 44, 78, 69, 109, 22, 161, 245, 226, 131, 113, 109, 19, 6, 186, 2, 28, 81, 136, 164, 166, 105, 141, 45, 21, 186, 101, 230, 148, 164, 22, 13, 155, 100, 152, 6, 246, 14, 189, 210, 97, 8, 217, 41, 176, 12, 60, 212, 84, 80, 162, 0, 94, 113, 20, 239, 147, 89, 12, 93, 114, 4, 238, 225, 37, 22, 148, 0, 3, 59, 5, 116, 68, 50, 108, 33, 25, 153, 201, 53, 19, 125, 12, 13, 61, 133, 230, 233, 40, 132, 32, 167, 77, 5, 127, 120, 192, 40, 128, 93, 24, 13, 115, 141, 182, 118, 44, 208, 104, 136, 74, 107, 46, 88, 154, 132, 5, 133, 163, 130, 45, 82, 170, 10, 46, 64, 171, 81, 96, 177, 174, 3, 247, 28, 116, 188, 28, 54, 122, 6, 246, 25, 144, 178, 129, 43, 0, 242, 16, 222, 115, 140, 206, 139, 5, 79, 133, 2, 29, 148, 7, 242, 27, 216, 226, 162, 212, 18, 80, 102, 112, 36, 62, 39, 64, 146, 59, 174, 172, 144, 151, 162, 81, 0, 180, 57, 51, 57, 177, 4, 182, 89, 126, 168, 230, 3, 160, 95, 112, 230, 2, 132, 39, 53, 53, 209, 77, 135, 101, 2, 244, 76, 160, 163, 128, 208, 4, 50, 23, 22, 241, 224, 128, 1, 170, 32, 55, 39, 144, 154, 184, 9, 37, 110, 96, 148, 34, 188, 167, 131, 89, 250, 162, 165, 240, 162, 212, 146, 210, 162, 60, 160, 44, 122, 170, 134, 73, 33, 28, 75, 92, 34, 131, 37, 36, 92, 73, 44, 47, 5, 114, 169, 237, 80, 73, 103, 208, 112, 50, 53, 213, 129, 178, 12, 96, 12, 37, 60, 73, 15, 236, 71, 228, 105, 24, 46, 244, 162, 152, 90, 137, 80, 1, 218, 32, 200, 132, 54, 8, 208, 125, 71, 173, 68, 136, 171, 40, 69, 77, 109, 25, 153, 144, 212, 230, 31, 157, 29, 139, 90, 154, 194, 210, 90, 158, 66, 54, 214, 100, 166, 107, 72, 90, 250, 2, 135, 48, 48, 12, 96, 137, 12, 41, 145, 161, 236, 191, 67, 175, 211, 7, 91, 26, 67, 46, 203, 16, 6, 34, 146, 147, 94, 26, 196, 55, 176, 194, 12, 61, 29, 165, 34, 121, 19, 20, 214, 232, 230, 227, 74, 72, 184, 170, 116, 90, 167, 36, 160, 235, 80, 154, 140, 176, 216, 133, 185, 7, 214, 100, 68, 79, 70, 48, 55, 146, 90, 42, 161, 39, 139, 12, 180, 130, 9, 42, 233, 157, 90, 89, 172, 1, 114, 31, 185, 169, 132, 184, 180, 81, 148, 138, 171, 171, 164, 225, 15, 153, 53, 170, 197, 230, 58, 223, 196, 130, 161, 150, 154, 97, 197, 35, 122, 241, 168, 151, 155, 88, 64, 143, 180, 140, 214, 60, 133, 187, 157, 184, 84, 92, 150, 8, 107, 209, 193, 188, 16, 92, 144, 154, 156, 153, 90, 236, 140, 222, 162, 243, 135, 14, 47, 162, 23, 162, 56, 146, 62, 200, 224, 92, 112, 120, 67, 187, 86, 132, 250, 79, 10, 33, 168, 217, 0, 218, 26, 204, 6, 182, 6, 145, 13, 178, 70, 205, 30, 184, 91, 132, 176, 108, 129, 156, 182, 144, 179, 4, 66, 34, 40, 53, 165, 52, 25, 30, 37, 67, 61, 221, 233, 21, 129, 189, 3, 95, 236, 140, 171, 24, 165, 52, 233, 65, 77, 6, 14, 81, 67, 28, 171, 160, 166, 134, 146, 6, 17, 254, 48, 196, 229, 15, 35, 228, 68, 12, 237, 243, 64, 67, 48, 49, 57, 185, 52, 183, 52, 39, 17, 56, 5, 6, 77, 219, 68, 165, 109, 255, 232, 108, 109, 237, 88, 120, 26, 5, 37, 77, 244, 82, 89, 1, 205, 108, 244, 100, 9, 31, 102, 85, 64, 242, 179, 14, 68, 4, 148, 119, 32, 121, 7, 38, 128, 100, 22, 84, 8, 156, 136, 97, 236, 108, 184, 32, 23, 172, 137, 132, 148, 122, 145, 117, 195, 142, 187, 43, 65, 79, 155, 160, 200, 12, 202, 76, 207, 40, 25, 34, 9, 148, 80, 83, 18, 87, 154, 133, 121, 147, 64, 99, 50, 121, 176, 166, 94, 200, 241, 205, 10, 186, 10, 134, 144, 64, 38, 55, 13, 131, 210, 176, 174, 46, 34, 13, 131, 138, 87, 59, 72, 49, 171, 171, 11, 117, 11, 178, 209, 72, 73, 24, 104, 132, 91, 233, 96, 75, 194, 149, 193, 168, 103, 230, 166, 96, 79, 187, 153, 232, 139, 205, 106, 106, 20, 20, 145, 166, 67, 43, 53, 160, 45, 108, 5, 168, 213, 176, 165, 101, 168, 254, 37, 60, 123, 15, 242, 9, 140, 1, 118, 20, 148, 3, 116, 26, 92, 129, 18, 154, 235, 145, 211, 36, 16, 163, 76, 197, 226, 42, 255, 109, 161, 65, 0, 203, 79, 176, 252, 4, 86, 80, 148, 10, 12, 177, 204, 178, 84, 224, 49, 186, 176, 211, 122, 209, 79, 235, 133, 165, 42, 168, 143, 225, 234, 97, 199, 238, 66, 143, 221, 197, 56, 21, 87, 27, 85, 177, 14, 174, 179, 119, 53, 208, 148, 193, 14, 224, 69, 118, 30, 242, 73, 193, 182, 208, 148, 3, 59, 41, 24, 118, 82, 112, 73, 42, 234, 73, 193, 208, 83, 234, 225, 14, 135, 155, 68, 164, 179, 65, 74, 65, 142, 198, 229, 104, 152, 34, 216, 225, 190, 80, 75, 147, 161, 39, 63, 194, 85, 195, 206, 171, 207, 81, 208, 85, 200, 6, 26, 8, 83, 73, 108, 115, 71, 71, 1, 233, 48, 220, 52, 5, 13, 136, 5, 118, 10, 176, 66, 15, 108, 86, 113, 78, 102, 114, 106, 10, 138, 129, 78, 153, 37, 229, 153, 197, 169, 193, 32, 25, 144, 41, 142, 58, 10, 217, 200, 102, 65, 147, 58, 72, 39, 98, 201, 134, 2, 44, 208, 16, 238, 135, 29, 207, 159, 163, 131, 45, 33, 129, 141, 2, 187, 2, 54, 166, 6, 19, 128, 46, 16, 204, 86, 176, 129, 152, 9, 179, 2, 4, 28, 163, 243, 180, 181, 129, 13, 42, 164, 122, 82, 1, 62, 59, 95, 11, 201, 216, 240, 150, 21, 52, 59, 163, 103, 231, 224, 252, 92, 170, 180, 149, 96, 209, 1, 171, 138, 208, 171, 34, 116, 31, 147, 90, 21, 193, 218, 74, 176, 182, 18, 204, 68, 148, 122, 167, 24, 232, 25, 37, 148, 26, 65, 145, 210, 70, 58, 172, 200, 133, 213, 53, 10, 208, 14, 167, 2, 180, 195, 137, 222, 156, 193, 85, 21, 192, 154, 234, 176, 14, 39, 172, 213, 77, 168, 213, 141, 62, 56, 12, 19, 70, 159, 203, 64, 175, 49, 96, 190, 133, 117, 76, 113, 205, 101, 128, 67, 9, 105, 42, 3, 150, 188, 96, 233, 6, 52, 97, 1, 86, 8, 77, 80, 112, 137, 180, 196, 156, 98, 160, 12, 161, 177, 15, 88, 52, 5, 3, 163, 6, 185, 189, 142, 144, 9, 201, 247, 201, 7, 58, 54, 21, 122, 198, 83, 14, 152, 83, 172, 0, 45, 160, 32, 135, 129, 228, 23, 128, 52, 161, 8, 34, 18, 106, 34, 200, 20, 98, 19, 43, 48, 177, 66, 23, 216, 65, 116, 19, 153, 96, 225, 122, 96, 237, 12, 88, 50, 133, 85, 97, 104, 199, 160, 150, 129, 11, 206, 162, 226, 18, 215, 28, 232, 13, 130, 16, 103, 70, 27, 196, 66, 86, 88, 66, 213, 4, 33, 31, 111, 5, 50, 10, 107, 92, 34, 155, 164, 87, 130, 18, 94, 58, 40, 214, 128, 238, 51, 130, 251, 12, 124, 11, 12, 180, 89, 172, 164, 163, 4, 105, 130, 32, 141, 114, 24, 90, 3, 41, 244, 246, 180, 2, 208, 73, 218, 182, 8, 189, 176, 20, 7, 94, 40, 139, 225, 27, 88, 138, 4, 5, 10, 138, 188, 45, 70, 76, 65, 87, 54, 148, 100, 230, 129, 19, 20, 52, 65, 41, 40, 88, 67, 56, 64, 91, 145, 66, 34, 57, 17, 35, 16, 160, 230, 99, 15, 3, 36, 183, 193, 114, 41, 60, 82, 130, 176, 150, 124, 137, 149, 193, 165, 73, 96, 79, 104, 36, 165, 166, 103, 230, 193, 218, 50, 136, 67, 168, 161, 41, 10, 26, 231, 176, 214, 12, 236, 16, 106, 244, 246, 12, 108, 249, 20, 44, 57, 160, 183, 104, 52, 160, 65, 128, 190, 30, 17, 189, 69, 131, 190, 102, 94, 1, 226, 58, 40, 7, 179, 81, 131, 236, 19, 228, 118, 13, 212, 31, 73, 165, 105, 168, 43, 78, 97, 217, 0, 182, 226, 52, 53, 5, 236, 114, 107, 168, 47, 147, 208, 151, 233, 86, 115, 33, 86, 160, 32, 87, 140, 176, 204, 4, 211, 12, 179, 176, 184, 40, 25, 146, 101, 160, 138, 97, 185, 8, 36, 20, 149, 90, 148, 239, 159, 231, 95, 90, 226, 159, 230, 148, 95, 154, 151, 82, 12, 215, 93, 150, 8, 214, 233, 4, 95, 29, 128, 162, 27, 33, 172, 145, 15, 211, 128, 212, 172, 113, 2, 133, 16, 114, 171, 11, 18, 163, 48, 117, 144, 16, 4, 31, 10, 140, 212, 138, 129, 107, 196, 209, 142, 73, 172, 208, 128, 123, 5, 169, 53, 3, 214, 130, 220, 8, 67, 111, 207, 32, 43, 67, 4, 6, 220, 45, 169, 57, 169, 185, 169, 121, 37, 193, 153, 85, 169, 40, 94, 116, 69, 136, 163, 248, 17, 236, 118, 228, 96, 65, 11, 38, 109, 100, 223, 105, 33, 27, 15, 139, 81, 104, 115, 15, 169, 185, 167, 166, 134, 100, 177, 103, 177, 99, 105, 73, 62, 196, 149, 216, 210, 48, 76, 37, 172, 105, 5, 107, 90, 161, 175, 143, 2, 134, 58, 52, 72, 128, 134, 128, 210, 40, 34, 217, 128, 121, 176, 148, 140, 112, 59, 106, 98, 133, 69, 40, 254, 118, 42, 60, 64, 21, 96, 173, 85, 88, 107, 21, 30, 192, 208, 33, 118, 180, 168, 134, 55, 88, 137, 141, 104, 160, 6, 188, 209, 12, 83, 132, 30, 201, 208, 245, 95, 62, 176, 171, 115, 144, 45, 2, 57, 20, 226, 56, 93, 164, 104, 131, 52, 102, 9, 5, 56, 108, 173, 16, 44, 156, 97, 161, 12, 15, 99, 180, 16, 134, 173, 92, 82, 128, 186, 6, 182, 198, 14, 189, 44, 132, 88, 229, 88, 2, 57, 247, 29, 24, 249, 80, 63, 228, 19, 89, 0, 194, 141, 128, 38, 30, 88, 226, 129, 21, 128, 184, 10, 192, 84, 28, 5, 160, 130, 2, 138, 239, 20, 32, 39, 184, 195, 56, 74, 72, 78, 134, 12, 45, 192, 82, 144, 130, 130, 123, 106, 137, 99, 73, 9, 122, 55, 14, 37, 55, 229, 164, 230, 193, 114, 29, 82, 177, 132, 162, 4, 22, 181, 208, 242, 66, 1, 158, 202, 160, 1, 4, 83, 151, 13, 13, 22, 88, 90, 128, 106, 176, 67, 106, 20, 100, 3, 181, 163, 24, 7, 210, 2, 219, 48, 11, 87, 1, 237, 45, 97, 168, 131, 26, 159, 173, 96, 163, 96, 0, 12, 108, 208, 176, 1, 88, 49, 90, 16, 195, 219, 148, 104, 181, 30, 208, 79, 224, 218, 153, 80, 251, 12, 17, 156, 154, 214, 160, 148, 145, 92, 2, 73, 25, 48, 113, 55, 160, 183, 125, 18, 139, 75, 16, 211, 101, 10, 96, 23, 224, 234, 34, 192, 52, 162, 183, 186, 52, 252, 81, 99, 1, 189, 197, 133, 30, 41, 132, 186, 8, 228, 118, 17, 210, 160, 254, 81, 210, 132, 4, 24, 44, 109, 195, 186, 9, 232, 243, 155, 132, 70, 164, 96, 243, 155, 232, 243, 155, 232, 179, 82, 232, 158, 32, 181, 147, 128, 24, 143, 130, 140, 32, 41, 24, 160, 140, 32, 149, 97, 239, 41, 0, 253, 134, 181, 45, 133, 152, 105, 135, 57, 17, 173, 111, 0, 94, 75, 2, 2, 176, 116, 134, 62, 211, 14, 75, 106, 176, 36, 8, 113, 113, 45, 23, 44, 181, 161, 167, 54, 88, 106, 131, 165, 42, 72, 44, 104, 90, 163, 167, 57, 100, 89, 208, 140, 123, 5, 204, 173, 208, 132, 167, 0, 77, 120, 182, 208, 132, 167, 0, 77, 120, 112, 221, 208, 132, 87, 4, 77, 120, 69, 208, 132, 87, 6, 77, 120, 182, 208, 132, 151, 3, 77, 120, 41, 48, 141, 208, 132, 151, 1, 85, 159, 9, 77, 120, 168, 113, 102, 107, 11, 203, 223, 176, 100, 1, 75, 22, 232, 195, 164, 232, 195, 164, 184, 210, 34, 204, 159, 176, 89, 247, 225, 146, 42, 73, 77, 126, 176, 201, 34, 88, 226, 67, 77, 124, 214, 92, 232, 233, 142, 208, 212, 59, 172, 120, 131, 37, 56, 88, 80, 163, 77, 191, 43, 168, 32, 212, 128, 83, 120, 177, 6, 121, 169, 12, 54, 155, 74, 168, 80, 179, 134, 186, 31, 215, 108, 170, 142, 130, 161, 38, 196, 91, 144, 19, 74, 97, 39, 148, 106, 160, 57, 20, 180, 243, 83, 9, 184, 5, 20, 200, 80, 194, 150, 139, 18, 43, 131, 75, 18, 75, 50, 147, 193, 187, 130, 139, 243, 75, 139, 146, 129, 129, 157, 155, 88, 144, 150, 135, 220, 137, 134, 135, 191, 2, 76, 16, 214, 95, 3, 7, 128, 51, 34, 0, 96, 77, 0, 228, 245, 192, 206, 192, 152, 66, 47, 33, 33, 105, 209, 68, 7, 118, 90, 163, 51, 52, 229, 33, 166, 16, 51, 243, 210, 97, 230, 65, 220, 163, 136, 220, 200, 131, 153, 8, 179, 14, 150, 254, 193, 74, 145, 82, 6, 186, 141, 232, 169, 223, 16, 234, 91, 224, 160, 13, 88, 7, 184, 179, 9, 182, 31, 114, 169, 8, 108, 92, 3, 86, 31, 163, 73, 167, 37, 230, 20, 131, 229, 97, 46, 15, 129, 6, 5, 208, 108, 112, 113, 2, 20, 42, 45, 6, 170, 133, 197, 28, 80, 26, 18, 202, 104, 219, 163, 242, 115, 52, 148, 50, 161, 106, 144, 246, 71, 161, 232, 69, 14, 1, 112, 251, 28, 201, 104, 152, 52, 172, 55, 134, 37, 108, 80, 13, 195, 29, 70, 230, 134, 72, 97, 4, 45, 33, 192, 110, 6, 21, 15, 176, 64, 130, 25, 15, 11, 10, 216, 230, 60, 104, 162, 66, 137, 126, 240, 214, 61, 88, 171, 16, 154, 200, 96, 214, 67, 205, 129, 50, 21, 20, 208, 2, 203, 214, 22, 45, 231, 149, 166, 22, 131, 47, 108, 134, 2, 100, 59, 161, 38, 195, 47, 116, 6, 15, 125, 34, 231, 154, 0, 240, 100, 41, 228, 6, 243, 204, 92, 200, 13, 230, 26, 208, 166, 187, 2, 194, 61, 224, 38, 34, 122, 19, 49, 45, 181, 8, 106, 62, 36, 12, 128, 0, 185, 178, 8, 129, 185, 2, 150, 131, 177, 170, 45, 73, 44, 74, 7, 239, 158, 87, 176, 69, 223, 236, 1, 175, 115, 65, 123, 20, 128, 8, 54, 200, 13, 2, 200, 37, 41, 108, 16, 16, 125, 60, 6, 6, 224, 86, 68, 103, 199, 130, 210, 26, 216, 25, 64, 54, 204, 44, 88, 228, 33, 74, 77, 132, 22, 144, 26, 152, 10, 98, 34, 6, 103, 156, 4, 36, 38, 103, 83, 57, 82, 72, 13, 64, 168, 207, 245, 114, 160, 93, 46, 152, 49, 72, 49, 229, 153, 151, 9, 62, 78, 0, 217, 181, 112, 11, 96, 6, 192, 116, 18, 10, 46, 40, 9, 114, 100, 25, 40, 68, 64, 7, 2, 128, 188, 8, 242, 78, 72, 190, 79, 102, 49, 44, 225, 235, 160, 134, 36, 212, 252, 50, 88, 74, 130, 234, 134, 186, 27, 33, 9, 183, 21, 154, 216, 208, 247, 82, 248, 64, 55, 184, 192, 82, 14, 177, 169, 6, 173, 73, 8, 177, 29, 41, 189, 148, 65, 23, 116, 164, 66, 23, 116, 216, 194, 10, 63, 120, 176, 216, 163, 12, 69, 194, 34, 1, 168, 42, 13, 121, 237, 49, 144, 6, 71, 42, 180, 155, 12, 17, 4, 90, 130, 158, 104, 209, 215, 125, 192, 194, 22, 71, 248, 215, 34, 143, 237, 250, 100, 102, 167, 194, 174, 180, 130, 149, 52, 208, 24, 44, 131, 133, 47, 80, 22, 26, 84, 112, 45, 208, 176, 134, 168, 35, 57, 168, 161, 13, 29, 66, 1, 141, 26, 204, 137, 69, 80, 187, 225, 57, 147, 80, 56, 147, 26, 202, 104, 97, 140, 51, 132, 97, 149, 23, 150, 208, 173, 69, 110, 45, 192, 130, 1, 210, 90, 240, 79, 211, 128, 22, 152, 176, 128, 69, 111, 35, 102, 104, 64, 194, 19, 214, 58, 160, 86, 235, 0, 58, 110, 66, 237, 216, 1, 26, 9, 11, 28, 72, 163, 22, 218, 168, 205, 134, 89, 12, 11, 31, 160, 66, 180, 192, 129, 84, 80, 176, 177, 47, 244, 195, 228, 139, 242, 32, 126, 199, 213, 84, 131, 105, 132, 157, 41, 143, 235, 76, 121, 184, 117, 208, 82, 5, 94, 170, 100, 150, 164, 230, 2, 245, 229, 166, 150, 100, 228, 167, 104, 42, 192, 182, 146, 131, 3, 10, 214, 160, 0, 122, 10, 61, 143, 130, 82, 15, 68, 143, 142, 2, 216, 8, 77, 72, 244, 32, 143, 223, 192, 180, 227, 138, 32, 115, 99, 180, 104, 169, 40, 241, 5, 27, 9, 180, 15, 166, 23, 118, 168, 25, 106, 201, 24, 29, 11, 119, 34, 116, 18, 19, 253, 132, 19, 88, 158, 0, 106, 71, 153, 185, 66, 114, 62, 216, 62, 152, 23, 80, 139, 83, 20, 127, 128, 21, 194, 252, 128, 197, 23, 38, 192, 80, 7, 41, 81, 2, 105, 134, 85, 127, 240, 169, 10, 61, 212, 131, 81, 96, 199, 162, 192, 213, 185, 128, 219, 163, 46, 137, 37, 137, 1, 208, 13, 227, 26, 16, 111, 2, 29, 165, 173, 173, 3, 246, 128, 30, 88, 4, 108, 60, 34, 41, 65, 67, 3, 53, 41, 57, 34, 154, 27, 144, 180, 68, 108, 90, 66, 215, 73, 100, 98, 82, 9, 206, 72, 44, 2, 165, 65, 114, 173, 197, 165, 159, 144, 229, 176, 82, 5, 57, 251, 6, 3, 77, 4, 137, 193, 55, 16, 234, 40, 228, 164, 66, 55, 132, 34, 37, 107, 68, 211, 41, 191, 72, 193, 86, 1, 82, 150, 160, 159, 15, 144, 88, 137, 186, 13, 17, 234, 17, 116, 43, 225, 37, 70, 134, 6, 196, 84, 216, 174, 114, 88, 149, 0, 139, 28, 20, 231, 134, 228, 7, 231, 23, 149, 164, 166, 0, 245, 228, 22, 0, 253, 159, 6, 26, 109, 131, 100, 31, 152, 16, 122, 127, 5, 150, 252, 208, 251, 43, 112, 229, 56, 18, 40, 122, 159, 5, 54, 219, 12, 215, 6, 75, 180, 208, 140, 72, 106, 127, 212, 31, 90, 76, 163, 143, 122, 192, 122, 166, 232, 237, 90, 132, 122, 71, 5, 91, 220, 49, 232, 79, 90, 241, 235, 24, 157, 29, 11, 29, 144, 130, 102, 18, 248, 252, 169, 157, 130, 33, 72, 21, 108, 85, 19, 60, 247, 23, 151, 164, 196, 35, 172, 143, 47, 6, 70, 136, 142, 130, 35, 82, 200, 160, 102, 183, 60, 5, 71, 148, 200, 12, 79, 77, 204, 246, 77, 44, 128, 39, 30, 244, 235, 124, 20, 170, 161, 222, 204, 77, 44, 64, 10, 206, 50, 216, 117, 62, 144, 74, 84, 175, 56, 181, 4, 82, 110, 194, 98, 21, 253, 58, 31, 28, 241, 137, 243, 58, 31, 13, 88, 161, 231, 89, 146, 154, 11, 60, 106, 8, 253, 168, 161, 34, 184, 19, 33, 198, 195, 146, 20, 188, 176, 131, 233, 197, 145, 158, 128, 246, 155, 152, 234, 40, 40, 65, 253, 175, 4, 75, 62, 232, 115, 202, 176, 112, 134, 221, 11, 4, 244, 44, 184, 44, 3, 155, 13, 188, 85, 2, 137, 99, 24, 11, 241, 1, 122, 240, 6, 167, 150, 16, 14, 94, 96, 0, 98, 13, 94, 244, 219, 146, 168, 29, 188, 192, 163, 156, 176, 30, 229, 132, 30, 190, 184, 66, 5, 253, 182, 36, 88, 1, 15, 10, 6, 0, 46, 4, 227, 16 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 33279; + return 30808; } uint32_t GetRawScriptsSize() { - return 144873; + return 134068; } } // selfhosted } // js diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/js-confdefs.h b/src/third_party/mozjs/platform/x86_64/linux/build/js-confdefs.h index 6fed6e945a3..9df00962038 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/x86_64/linux/build/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -28,7 +32,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -70,12 +73,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -84,6 +85,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "x86_64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_LINUX 1 diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/x86_64/linux/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/x86_64/linux/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/x86_64/linux/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/jit/AtomicOperationsGenerated.h b/src/third_party/mozjs/platform/x86_64/linux/include/jit/AtomicOperationsGenerated.h index 8502615c0f0..a74121646d4 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/jit/AtomicOperationsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/jit/AtomicOperationsGenerated.h @@ -408,6 +408,9 @@ namespace jit { : "memory", "cc"); return res; } + inline void AtomicPause() { + asm volatile ("pause" :::); + } inline void AtomicCopyUnalignedBlockDownUnsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); @@ -793,7 +796,29 @@ namespace jit { : [dst] "r" (dst_), [src] "r"(src_) : "memory"); } - inline void AtomicCopyByteUnsynchronized(uint8_t* dst, const uint8_t* src) { + inline void AtomicCopy32Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint32_t* dst_ = reinterpret_cast(dst); + const uint32_t* src_ = reinterpret_cast(src); + uint32_t scratch; + asm volatile ("movl 0(%[src]), %[scratch]\n\t" +"movl %[scratch], 0(%[dst])\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy16Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint16_t* dst_ = reinterpret_cast(dst); + const uint16_t* src_ = reinterpret_cast(src); + uint16_t scratch; + asm volatile ("movw 0(%[src]), %[scratch]\n\t" +"movw %[scratch], 0(%[dst])\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy8Unsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); uint8_t scratch; diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/linux/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/linux/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/linux/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/js-confdefs.h b/src/third_party/mozjs/platform/x86_64/linux/include/js-confdefs.h index 6fed6e945a3..9df00962038 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_BYTESWAP_H 1 @@ -28,7 +32,6 @@ #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LINUX_IF_ADDR_H 1 -#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_LINUX_QUOTA_H 1 #define HAVE_LINUX_RTNETLINK_H 1 #define HAVE_LOCALECONV 1 @@ -70,12 +73,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".so" @@ -84,6 +85,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "x86_64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_LINUX 1 diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/js-config.h b/src/third_party/mozjs/platform/x86_64/linux/include/js-config.h index e6a4e862c32..75330b2452d 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/js-config.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +/* #undef XP_WIN */ +#define XP_UNIX 1 +/* #undef XP_DARWIN */ + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/x86_64/linux/include/selfhosted.out.h b/src/third_party/mozjs/platform/x86_64/linux/include/selfhosted.out.h index 44a6a0153a0..c2add8e3354 100644 --- a/src/third_party/mozjs/platform/x86_64/linux/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/x86_64/linux/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 237, 125, 253, 119, 27, 55, 174, 232, 239, 254, 43, 38, 58, 189, 173, 188, 150, 189, 150, 147, 126, 108, 236, 164, 235, 186, 73, 215, 111, 147, 56, 199, 78, 119, 207, 185, 126, 57, 185, 19, 105, 236, 204, 90, 214, 168, 51, 82, 28, 183, 205, 251, 219, 31, 65, 130, 36, 192, 143, 153, 145, 44, 39, 182, 111, 114, 78, 235, 209, 12, 9, 130, 32, 0, 130, 32, 8, 158, 204, 198, 131, 105, 94, 140, 147, 113, 118, 241, 230, 48, 27, 20, 229, 176, 187, 154, 252, 177, 146, 36, 101, 54, 157, 149, 227, 164, 154, 14, 223, 28, 188, 253, 79, 54, 152, 190, 25, 148, 89, 58, 205, 186, 227, 217, 104, 180, 186, 189, 242, 113, 229, 68, 215, 125, 85, 252, 84, 20, 163, 44, 29, 119, 223, 179, 186, 247, 238, 189, 119, 202, 189, 152, 157, 191, 205, 74, 167, 216, 26, 47, 117, 148, 158, 103, 255, 74, 71, 179, 236, 191, 179, 178, 232, 126, 232, 37, 151, 172, 244, 135, 228, 209, 163, 71, 201, 101, 242, 231, 159, 73, 247, 67, 114, 79, 60, 127, 72, 190, 254, 90, 188, 128, 199, 75, 142, 216, 47, 217, 244, 121, 54, 125, 87, 12, 187, 255, 234, 37, 47, 21, 152, 237, 109, 241, 191, 247, 105, 153, 64, 169, 228, 81, 242, 175, 227, 151, 175, 225, 85, 126, 146, 116, 247, 171, 23, 162, 115, 7, 229, 175, 227, 97, 118, 146, 143, 179, 97, 23, 10, 173, 170, 138, 6, 131, 153, 254, 10, 213, 62, 98, 213, 123, 251, 213, 94, 58, 26, 165, 111, 71, 25, 175, 244, 234, 93, 89, 92, 188, 186, 156, 100, 79, 202, 178, 40, 187, 253, 173, 94, 50, 21, 191, 138, 19, 137, 192, 170, 134, 129, 176, 225, 29, 235, 194, 126, 245, 178, 44, 38, 89, 57, 189, 252, 103, 118, 217, 77, 203, 211, 217, 121, 54, 158, 42, 224, 208, 11, 128, 37, 122, 129, 32, 245, 247, 109, 11, 81, 21, 16, 180, 233, 84, 211, 50, 31, 159, 118, 128, 114, 228, 229, 229, 249, 219, 98, 212, 225, 35, 48, 201, 6, 121, 86, 237, 21, 99, 81, 101, 54, 152, 10, 180, 139, 183, 255, 233, 37, 162, 219, 233, 108, 52, 37, 239, 29, 146, 194, 43, 129, 140, 40, 188, 49, 176, 133, 52, 117, 213, 87, 209, 168, 33, 160, 67, 88, 31, 190, 67, 97, 197, 136, 18, 80, 140, 190, 223, 126, 215, 75, 58, 133, 44, 247, 77, 149, 124, 67, 208, 248, 38, 153, 32, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 154, 229, 163, 105, 62, 62, 146, 68, 233, 118, 42, 69, 136, 206, 106, 13, 135, 84, 46, 123, 212, 247, 98, 159, 145, 213, 86, 134, 111, 149, 228, 97, 75, 87, 248, 119, 152, 77, 138, 114, 250, 107, 149, 158, 102, 123, 197, 108, 60, 21, 210, 227, 55, 208, 75, 238, 203, 46, 169, 102, 172, 236, 234, 134, 29, 26, 201, 50, 253, 7, 61, 249, 183, 243, 247, 191, 99, 55, 13, 125, 18, 193, 73, 134, 132, 132, 130, 29, 81, 193, 19, 48, 11, 118, 99, 99, 67, 240, 95, 165, 112, 159, 150, 151, 216, 135, 129, 16, 139, 167, 88, 161, 11, 234, 68, 255, 120, 147, 78, 38, 163, 203, 158, 131, 93, 207, 178, 71, 47, 145, 240, 100, 47, 4, 152, 233, 224, 93, 210, 205, 28, 106, 103, 186, 143, 219, 46, 98, 187, 167, 167, 101, 118, 42, 52, 214, 18, 176, 227, 176, 150, 134, 226, 62, 140, 231, 56, 29, 45, 1, 67, 6, 106, 57, 8, 2, 167, 155, 134, 69, 21, 242, 105, 175, 152, 92, 254, 156, 78, 83, 212, 77, 130, 121, 186, 83, 209, 78, 54, 237, 37, 85, 49, 43, 7, 89, 47, 201, 62, 12, 70, 179, 97, 54, 220, 159, 102, 231, 21, 209, 19, 219, 53, 162, 36, 171, 58, 242, 68, 69, 245, 164, 44, 206, 133, 180, 190, 42, 80, 17, 96, 5, 173, 126, 206, 178, 75, 16, 102, 31, 185, 131, 82, 16, 251, 224, 98, 44, 84, 168, 69, 20, 128, 185, 104, 106, 220, 20, 36, 33, 140, 114, 178, 11, 226, 115, 34, 148, 89, 23, 90, 205, 5, 254, 98, 82, 74, 54, 183, 241, 113, 71, 34, 178, 49, 202, 198, 167, 211, 119, 248, 114, 109, 77, 67, 65, 68, 69, 5, 40, 117, 44, 191, 190, 222, 54, 58, 0, 197, 254, 222, 187, 180, 18, 8, 3, 34, 30, 41, 191, 254, 26, 11, 121, 156, 129, 19, 181, 150, 227, 253, 234, 201, 88, 76, 7, 37, 76, 74, 186, 191, 2, 224, 170, 172, 110, 85, 204, 207, 146, 252, 132, 98, 151, 134, 70, 178, 121, 168, 120, 44, 158, 94, 19, 29, 243, 113, 165, 150, 27, 126, 29, 159, 8, 69, 154, 149, 98, 80, 57, 95, 16, 70, 184, 57, 60, 128, 22, 205, 231, 30, 250, 69, 135, 115, 137, 35, 89, 204, 96, 130, 97, 246, 150, 249, 150, 143, 199, 230, 155, 249, 218, 57, 41, 138, 142, 164, 11, 83, 29, 187, 101, 153, 94, 62, 121, 159, 149, 151, 178, 87, 111, 211, 193, 217, 201, 56, 177, 86, 203, 1, 29, 193, 233, 187, 188, 50, 227, 39, 72, 39, 191, 61, 147, 36, 236, 30, 32, 45, 205, 240, 236, 162, 133, 83, 97, 129, 85, 57, 86, 155, 49, 107, 224, 219, 94, 178, 41, 12, 2, 137, 207, 134, 32, 228, 180, 0, 211, 103, 35, 3, 212, 172, 25, 224, 26, 112, 22, 231, 58, 51, 238, 103, 97, 46, 159, 79, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 68, 135, 124, 180, 31, 39, 253, 228, 71, 57, 79, 225, 167, 110, 127, 53, 121, 200, 141, 75, 195, 104, 103, 138, 201, 206, 4, 131, 9, 122, 136, 7, 203, 84, 146, 103, 197, 224, 36, 7, 150, 15, 100, 127, 0, 29, 97, 35, 76, 5, 104, 195, 85, 22, 69, 49, 109, 244, 146, 131, 227, 179, 215, 130, 53, 196, 3, 97, 34, 59, 242, 233, 168, 202, 182, 241, 237, 71, 194, 48, 214, 182, 44, 103, 25, 140, 251, 145, 152, 202, 170, 253, 241, 40, 31, 3, 249, 158, 1, 203, 153, 38, 45, 43, 8, 162, 112, 6, 57, 42, 206, 179, 155, 201, 31, 149, 192, 236, 110, 179, 199, 149, 185, 67, 141, 125, 13, 115, 32, 251, 180, 224, 14, 224, 3, 143, 57, 158, 22, 229, 147, 116, 240, 238, 102, 242, 199, 137, 66, 238, 238, 178, 200, 124, 236, 177, 29, 26, 127, 130, 71, 11, 30, 192, 225, 246, 216, 224, 121, 58, 185, 153, 44, 112, 158, 78, 110, 254, 240, 67, 237, 93, 89, 27, 196, 12, 151, 245, 202, 141, 115, 208, 3, 66, 173, 94, 133, 73, 160, 138, 32, 195, 36, 27, 74, 127, 13, 172, 163, 23, 96, 155, 160, 217, 178, 43, 139, 16, 224, 97, 30, 219, 109, 197, 91, 130, 135, 124, 245, 34, 237, 211, 155, 201, 90, 202, 118, 190, 237, 220, 181, 25, 224, 173, 94, 50, 45, 230, 231, 177, 51, 205, 94, 192, 59, 154, 105, 90, 78, 98, 170, 110, 96, 26, 11, 51, 221, 180, 88, 91, 211, 149, 12, 127, 6, 167, 183, 118, 172, 167, 216, 204, 227, 190, 195, 108, 56, 27, 220, 80, 219, 167, 148, 184, 125, 42, 238, 83, 42, 7, 127, 164, 131, 193, 236, 124, 54, 74, 137, 211, 48, 200, 153, 186, 93, 82, 94, 128, 225, 204, 170, 60, 30, 153, 176, 65, 8, 119, 73, 10, 82, 154, 36, 201, 20, 112, 247, 104, 179, 197, 252, 105, 18, 209, 151, 101, 86, 9, 208, 162, 33, 98, 24, 15, 11, 102, 85, 185, 220, 155, 208, 106, 212, 98, 74, 146, 183, 66, 80, 206, 28, 14, 75, 46, 222, 9, 138, 37, 221, 181, 53, 20, 143, 85, 187, 58, 188, 167, 33, 205, 135, 58, 39, 145, 16, 160, 181, 181, 215, 108, 29, 219, 94, 20, 57, 168, 144, 236, 153, 206, 17, 33, 52, 239, 172, 75, 202, 188, 34, 16, 237, 75, 57, 65, 88, 250, 145, 15, 248, 20, 158, 10, 24, 239, 184, 75, 81, 37, 111, 135, 249, 233, 187, 233, 23, 161, 83, 66, 7, 253, 90, 79, 250, 95, 68, 143, 139, 222, 250, 250, 89, 242, 248, 17, 78, 94, 203, 149, 188, 245, 117, 95, 242, 30, 171, 201, 112, 125, 253, 142, 10, 222, 211, 124, 60, 236, 78, 4, 119, 231, 3, 97, 22, 220, 32, 129, 19, 4, 25, 198, 197, 205, 96, 60, 143, 180, 145, 74, 159, 110, 241, 22, 177, 143, 98, 214, 145, 193, 177, 206, 56, 194, 129, 85, 95, 151, 177, 182, 19, 180, 14, 24, 224, 227, 225, 62, 120, 64, 191, 176, 199, 53, 175, 237, 155, 249, 32, 232, 233, 209, 92, 16, 100, 128, 245, 126, 235, 145, 151, 131, 236, 13, 63, 56, 232, 255, 157, 139, 145, 29, 219, 29, 2, 241, 32, 254, 100, 227, 97, 226, 237, 17, 47, 206, 19, 240, 189, 204, 132, 122, 202, 223, 103, 175, 100, 75, 178, 40, 236, 151, 157, 138, 5, 160, 106, 220, 148, 132, 229, 201, 138, 234, 61, 171, 178, 147, 108, 34, 89, 126, 148, 33, 17, 207, 211, 233, 187, 55, 231, 233, 7, 57, 173, 173, 57, 165, 97, 237, 131, 165, 31, 146, 210, 162, 171, 110, 57, 109, 226, 81, 36, 143, 128, 12, 12, 71, 73, 24, 83, 78, 109, 128, 48, 36, 85, 149, 150, 56, 30, 41, 50, 55, 161, 136, 197, 66, 24, 62, 145, 35, 36, 199, 137, 238, 230, 139, 102, 161, 165, 135, 4, 243, 76, 10, 62, 226, 45, 184, 100, 228, 32, 14, 144, 90, 162, 45, 138, 54, 35, 45, 11, 81, 148, 7, 176, 103, 46, 144, 101, 165, 21, 38, 235, 184, 133, 162, 12, 161, 105, 97, 52, 136, 36, 240, 14, 176, 194, 215, 95, 195, 255, 119, 20, 201, 215, 20, 48, 45, 32, 184, 15, 69, 63, 105, 123, 42, 81, 171, 92, 241, 63, 239, 3, 90, 25, 234, 237, 99, 106, 12, 153, 150, 93, 51, 230, 224, 120, 90, 188, 150, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 202, 226, 220, 184, 81, 200, 174, 175, 235, 183, 211, 194, 62, 75, 76, 244, 207, 143, 174, 225, 246, 25, 209, 93, 91, 179, 232, 218, 103, 31, 93, 171, 147, 14, 66, 230, 199, 104, 36, 84, 164, 156, 228, 42, 148, 171, 205, 107, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 89, 153, 202, 182, 217, 156, 6, 179, 149, 232, 196, 123, 109, 157, 68, 89, 64, 249, 162, 36, 35, 236, 79, 179, 50, 53, 129, 76, 103, 96, 144, 152, 65, 207, 229, 183, 108, 168, 134, 157, 114, 128, 40, 108, 104, 144, 35, 4, 241, 253, 69, 118, 193, 129, 202, 66, 191, 142, 171, 244, 36, 19, 83, 226, 161, 88, 44, 148, 239, 179, 225, 209, 168, 152, 118, 117, 53, 105, 102, 240, 150, 90, 213, 234, 107, 71, 90, 83, 193, 45, 236, 214, 182, 165, 134, 254, 232, 203, 133, 198, 252, 69, 246, 97, 218, 181, 148, 16, 253, 5, 189, 37, 248, 94, 235, 66, 27, 116, 5, 180, 144, 65, 119, 170, 208, 47, 179, 180, 28, 190, 42, 60, 226, 174, 174, 70, 54, 207, 121, 180, 2, 242, 2, 88, 84, 12, 132, 10, 215, 219, 63, 249, 119, 41, 93, 191, 122, 13, 2, 40, 233, 231, 142, 215, 131, 142, 252, 194, 172, 170, 84, 160, 168, 40, 246, 139, 67, 49, 201, 0, 155, 68, 48, 170, 217, 8, 6, 253, 15, 197, 80, 15, 105, 232, 204, 176, 24, 139, 23, 114, 205, 9, 27, 220, 138, 36, 105, 160, 131, 0, 99, 3, 74, 179, 181, 38, 118, 92, 125, 166, 216, 233, 184, 129, 26, 12, 251, 148, 241, 206, 255, 153, 75, 185, 53, 229, 133, 144, 222, 223, 122, 42, 180, 164, 95, 113, 139, 170, 44, 141, 243, 126, 245, 178, 168, 170, 252, 237, 232, 18, 9, 11, 166, 234, 80, 18, 178, 155, 26, 155, 79, 233, 184, 104, 73, 84, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 31, 105, 245, 115, 54, 77, 7, 239, 178, 225, 79, 179, 147, 19, 161, 102, 82, 230, 148, 117, 173, 243, 239, 127, 8, 57, 97, 233, 84, 226, 232, 229, 148, 234, 101, 109, 186, 43, 114, 63, 150, 62, 15, 221, 90, 88, 156, 20, 115, 144, 136, 144, 57, 7, 183, 6, 170, 16, 100, 133, 199, 26, 142, 173, 196, 204, 140, 173, 32, 98, 223, 225, 167, 247, 184, 170, 75, 89, 164, 72, 176, 93, 15, 214, 22, 93, 31, 78, 210, 28, 212, 150, 2, 211, 51, 240, 94, 111, 135, 90, 131, 194, 53, 45, 109, 43, 253, 194, 170, 72, 112, 68, 239, 232, 26, 45, 22, 8, 84, 140, 233, 26, 225, 43, 249, 85, 46, 64, 43, 30, 143, 18, 82, 234, 82, 61, 72, 178, 202, 38, 247, 210, 113, 49, 22, 171, 155, 209, 139, 244, 60, 235, 82, 80, 98, 165, 39, 145, 174, 58, 222, 130, 228, 201, 120, 90, 230, 237, 27, 219, 90, 245, 181, 170, 12, 45, 106, 89, 127, 51, 80, 31, 4, 122, 183, 186, 28, 15, 186, 41, 252, 95, 134, 123, 201, 77, 176, 147, 49, 53, 87, 122, 82, 29, 138, 133, 97, 216, 134, 217, 35, 42, 92, 175, 23, 36, 212, 189, 81, 81, 205, 74, 201, 81, 240, 51, 129, 165, 241, 99, 194, 38, 176, 219, 150, 143, 1, 170, 106, 242, 30, 181, 16, 172, 204, 235, 98, 194, 56, 166, 107, 98, 89, 135, 8, 115, 96, 69, 252, 170, 56, 146, 193, 90, 186, 172, 235, 231, 155, 85, 2, 238, 46, 118, 93, 79, 182, 150, 20, 129, 0, 221, 148, 22, 198, 48, 93, 133, 101, 8, 150, 163, 182, 147, 112, 131, 78, 151, 29, 244, 142, 106, 11, 71, 90, 190, 23, 10, 122, 246, 221, 10, 126, 205, 58, 229, 248, 125, 159, 80, 212, 82, 105, 213, 213, 152, 220, 240, 14, 117, 162, 150, 196, 185, 75, 93, 210, 203, 163, 122, 242, 134, 91, 115, 72, 102, 173, 254, 48, 216, 8, 237, 34, 212, 59, 138, 17, 111, 126, 242, 89, 196, 62, 18, 70, 104, 51, 194, 96, 38, 181, 238, 136, 222, 68, 229, 129, 225, 123, 171, 201, 143, 6, 143, 110, 32, 8, 124, 175, 151, 116, 187, 253, 100, 103, 39, 233, 127, 39, 236, 50, 161, 143, 86, 123, 54, 86, 219, 117, 247, 136, 210, 123, 171, 224, 64, 58, 54, 131, 200, 54, 223, 224, 31, 216, 220, 233, 69, 154, 79, 149, 83, 105, 44, 52, 178, 242, 43, 194, 185, 130, 209, 168, 184, 64, 160, 208, 33, 240, 220, 88, 167, 51, 209, 86, 124, 228, 25, 141, 122, 113, 174, 192, 47, 108, 192, 252, 224, 2, 131, 209, 54, 227, 1, 212, 71, 124, 176, 155, 195, 18, 164, 14, 50, 170, 180, 103, 161, 11, 59, 154, 240, 128, 11, 74, 81, 136, 188, 243, 217, 101, 174, 128, 6, 248, 7, 195, 112, 6, 118, 129, 43, 17, 187, 104, 205, 192, 119, 253, 205, 110, 63, 219, 146, 210, 226, 149, 38, 90, 126, 150, 209, 5, 12, 225, 235, 109, 83, 210, 53, 153, 116, 69, 106, 58, 213, 241, 229, 146, 248, 81, 173, 246, 86, 113, 61, 168, 108, 81, 187, 229, 233, 176, 39, 58, 34, 244, 182, 104, 56, 60, 64, 141, 141, 233, 15, 9, 22, 240, 153, 9, 185, 198, 140, 193, 143, 88, 187, 13, 171, 24, 183, 249, 170, 169, 254, 144, 121, 203, 231, 228, 0, 103, 252, 213, 152, 146, 177, 71, 67, 158, 143, 253, 71, 98, 112, 185, 83, 124, 55, 98, 92, 72, 27, 113, 9, 38, 69, 163, 165, 208, 218, 78, 104, 242, 155, 247, 17, 89, 223, 103, 142, 8, 107, 148, 164, 78, 33, 179, 76, 222, 110, 58, 195, 73, 196, 141, 66, 103, 208, 216, 25, 29, 111, 198, 9, 204, 54, 129, 153, 198, 221, 12, 200, 233, 92, 243, 241, 211, 8, 28, 155, 0, 28, 249, 50, 123, 9, 205, 106, 31, 121, 40, 214, 249, 54, 162, 86, 35, 100, 175, 28, 77, 76, 36, 204, 211, 255, 17, 33, 131, 8, 158, 112, 228, 88, 72, 163, 50, 153, 90, 169, 209, 165, 185, 81, 163, 109, 149, 104, 108, 68, 87, 20, 21, 150, 170, 70, 87, 20, 141, 124, 85, 58, 247, 38, 162, 146, 156, 51, 194, 39, 117, 195, 217, 52, 152, 158, 174, 228, 154, 178, 181, 158, 132, 161, 241, 85, 34, 141, 197, 226, 234, 78, 152, 118, 242, 184, 35, 241, 110, 201, 49, 138, 58, 120, 241, 56, 168, 44, 180, 241, 159, 34, 31, 19, 245, 16, 62, 217, 25, 242, 107, 145, 99, 27, 83, 196, 160, 167, 96, 186, 39, 61, 67, 100, 3, 240, 182, 184, 223, 165, 103, 133, 168, 149, 97, 199, 70, 242, 135, 144, 196, 98, 2, 101, 232, 25, 43, 218, 91, 170, 183, 67, 76, 235, 238, 159, 122, 46, 29, 125, 210, 163, 67, 37, 228, 36, 47, 171, 233, 147, 81, 118, 174, 226, 43, 36, 164, 227, 205, 215, 186, 161, 67, 235, 120, 242, 78, 212, 146, 154, 134, 148, 135, 2, 6, 54, 64, 151, 43, 135, 18, 91, 236, 47, 242, 79, 144, 110, 4, 230, 198, 148, 145, 169, 199, 80, 197, 163, 79, 180, 39, 85, 54, 73, 245, 164, 209, 233, 117, 60, 145, 233, 199, 69, 6, 20, 146, 75, 3, 45, 55, 135, 201, 218, 35, 11, 219, 174, 14, 3, 147, 13, 1, 67, 244, 168, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 205, 108, 171, 16, 9, 63, 30, 50, 134, 251, 138, 198, 116, 114, 159, 134, 98, 168, 168, 163, 5, 235, 244, 146, 14, 236, 155, 30, 171, 121, 119, 3, 143, 152, 190, 246, 253, 46, 60, 110, 180, 40, 243, 83, 112, 248, 203, 79, 82, 181, 1, 111, 90, 206, 222, 38, 108, 42, 53, 129, 224, 212, 117, 195, 170, 70, 61, 108, 82, 199, 152, 32, 185, 82, 137, 12, 184, 43, 198, 76, 115, 82, 15, 162, 54, 128, 88, 237, 208, 249, 102, 111, 226, 22, 150, 143, 120, 87, 22, 85, 117, 152, 165, 163, 115, 220, 247, 166, 69, 218, 226, 160, 192, 163, 218, 178, 213, 0, 173, 189, 198, 115, 203, 170, 250, 158, 164, 149, 45, 75, 17, 81, 46, 245, 142, 191, 249, 31, 68, 136, 46, 133, 247, 2, 203, 254, 230, 186, 186, 75, 123, 181, 199, 193, 107, 169, 113, 207, 165, 118, 204, 162, 124, 32, 56, 145, 12, 86, 224, 16, 120, 139, 105, 248, 254, 42, 221, 87, 105, 158, 143, 21, 182, 158, 9, 62, 74, 167, 112, 158, 65, 206, 109, 165, 174, 213, 42, 234, 69, 157, 114, 124, 214, 16, 251, 226, 216, 217, 164, 145, 121, 2, 85, 220, 154, 174, 229, 125, 125, 193, 226, 64, 32, 65, 208, 253, 241, 84, 109, 44, 129, 45, 112, 208, 179, 157, 151, 190, 249, 190, 139, 161, 176, 51, 232, 232, 4, 140, 1, 128, 219, 93, 18, 157, 161, 212, 48, 155, 76, 223, 189, 152, 157, 203, 233, 97, 37, 22, 119, 36, 196, 159, 146, 68, 104, 169, 160, 11, 136, 0, 179, 187, 175, 188, 34, 27, 130, 165, 16, 81, 55, 26, 39, 156, 7, 70, 20, 196, 72, 29, 241, 132, 167, 188, 205, 19, 192, 133, 31, 114, 231, 121, 5, 59, 5, 15, 206, 80, 173, 36, 122, 225, 182, 98, 135, 67, 129, 221, 199, 77, 49, 9, 131, 77, 195, 170, 9, 253, 93, 216, 176, 244, 197, 142, 197, 128, 125, 224, 49, 80, 180, 70, 62, 102, 135, 145, 245, 108, 158, 153, 153, 92, 125, 61, 38, 117, 152, 235, 211, 145, 15, 226, 119, 218, 182, 62, 29, 11, 173, 54, 94, 51, 68, 32, 253, 79, 251, 27, 200, 43, 132, 74, 95, 17, 44, 253, 215, 230, 133, 227, 20, 70, 102, 127, 87, 204, 70, 67, 28, 104, 30, 92, 171, 122, 42, 71, 145, 199, 125, 36, 94, 45, 61, 187, 34, 110, 94, 75, 146, 252, 180, 142, 235, 229, 195, 138, 142, 208, 225, 91, 238, 148, 146, 100, 97, 220, 18, 98, 83, 94, 178, 129, 126, 182, 245, 158, 87, 213, 163, 170, 34, 200, 122, 210, 15, 16, 214, 13, 112, 129, 126, 83, 92, 33, 212, 247, 67, 255, 132, 254, 171, 117, 80, 127, 251, 125, 63, 224, 139, 174, 61, 228, 77, 177, 78, 220, 241, 96, 157, 178, 17, 53, 225, 131, 189, 182, 164, 175, 77, 119, 167, 106, 71, 117, 153, 97, 51, 122, 56, 173, 6, 204, 49, 108, 16, 87, 167, 90, 205, 242, 10, 143, 201, 58, 5, 140, 117, 246, 213, 91, 78, 232, 176, 247, 181, 64, 185, 21, 29, 122, 189, 147, 108, 130, 255, 254, 204, 217, 47, 142, 229, 254, 209, 129, 39, 210, 240, 111, 177, 225, 185, 59, 245, 44, 224, 87, 197, 33, 156, 71, 175, 178, 97, 119, 25, 36, 221, 197, 112, 183, 197, 220, 0, 24, 214, 166, 130, 226, 206, 108, 224, 154, 254, 102, 67, 141, 73, 120, 87, 116, 21, 111, 106, 184, 171, 223, 240, 138, 93, 152, 97, 130, 8, 96, 141, 164, 101, 118, 130, 180, 151, 33, 172, 250, 149, 179, 209, 226, 248, 22, 109, 205, 136, 185, 243, 61, 155, 73, 23, 167, 177, 244, 145, 44, 76, 231, 0, 185, 208, 169, 118, 166, 98, 113, 153, 165, 11, 184, 236, 176, 232, 0, 29, 220, 115, 94, 57, 84, 245, 92, 17, 18, 183, 55, 85, 1, 225, 96, 216, 132, 165, 81, 56, 90, 255, 89, 90, 77, 111, 108, 72, 54, 32, 247, 105, 194, 178, 173, 63, 124, 9, 193, 217, 250, 172, 77, 232, 192, 199, 226, 1, 252, 254, 126, 196, 245, 135, 241, 195, 0, 4, 67, 249, 225, 195, 205, 14, 231, 55, 24, 222, 49, 6, 154, 135, 83, 174, 53, 208, 223, 16, 152, 49, 8, 108, 75, 233, 178, 50, 220, 240, 125, 138, 190, 2, 217, 30, 89, 127, 64, 216, 208, 121, 246, 75, 54, 102, 129, 50, 162, 184, 24, 80, 112, 99, 117, 28, 141, 69, 33, 203, 113, 90, 12, 180, 60, 203, 21, 130, 173, 55, 55, 246, 135, 130, 172, 185, 80, 210, 65, 55, 24, 175, 99, 154, 88, 126, 87, 77, 233, 235, 232, 171, 41, 126, 40, 129, 44, 6, 93, 21, 81, 224, 85, 136, 81, 152, 160, 176, 75, 153, 153, 208, 85, 149, 117, 178, 167, 194, 47, 221, 168, 92, 189, 151, 71, 74, 110, 216, 176, 86, 109, 67, 66, 179, 42, 114, 148, 148, 222, 176, 73, 155, 34, 142, 87, 90, 113, 149, 234, 99, 19, 20, 26, 223, 19, 166, 117, 123, 166, 77, 122, 106, 208, 248, 235, 20, 180, 248, 254, 32, 164, 44, 116, 149, 138, 174, 19, 148, 73, 140, 124, 118, 114, 201, 33, 10, 63, 231, 165, 9, 215, 253, 99, 197, 197, 69, 69, 232, 134, 117, 103, 0, 13, 89, 156, 106, 53, 96, 78, 67, 105, 200, 243, 8, 47, 66, 238, 39, 91, 112, 30, 93, 74, 107, 57, 182, 13, 42, 59, 236, 229, 67, 104, 92, 173, 204, 108, 29, 245, 155, 4, 237, 194, 139, 143, 46, 161, 24, 43, 42, 106, 169, 56, 213, 114, 65, 162, 233, 40, 241, 107, 162, 17, 41, 21, 36, 73, 139, 176, 184, 135, 17, 65, 196, 228, 168, 222, 84, 160, 247, 140, 68, 107, 150, 198, 93, 34, 160, 164, 108, 108, 67, 66, 139, 134, 12, 126, 125, 79, 55, 98, 21, 72, 165, 32, 74, 163, 110, 102, 142, 59, 198, 145, 106, 160, 163, 21, 104, 34, 100, 173, 132, 186, 1, 95, 46, 204, 30, 198, 118, 245, 173, 9, 143, 76, 6, 209, 192, 88, 84, 197, 99, 96, 239, 62, 198, 39, 147, 127, 100, 35, 193, 105, 47, 28, 122, 106, 27, 41, 28, 122, 127, 160, 2, 239, 15, 72, 216, 189, 15, 178, 123, 176, 64, 232, 189, 15, 166, 69, 0, 190, 58, 79, 131, 63, 58, 145, 222, 5, 98, 242, 79, 245, 164, 17, 141, 124, 151, 117, 14, 20, 104, 56, 89, 194, 156, 238, 180, 15, 251, 16, 172, 59, 174, 242, 129, 63, 233, 246, 108, 59, 118, 20, 235, 71, 227, 208, 99, 194, 187, 53, 30, 170, 127, 159, 101, 68, 84, 211, 11, 140, 137, 49, 114, 238, 230, 144, 200, 238, 125, 150, 17, 145, 45, 207, 53, 32, 118, 203, 202, 63, 51, 149, 60, 10, 216, 30, 102, 129, 23, 222, 147, 154, 127, 47, 138, 219, 32, 57, 163, 36, 158, 199, 10, 140, 182, 89, 99, 82, 162, 186, 61, 179, 150, 172, 238, 146, 105, 20, 170, 47, 160, 117, 106, 78, 107, 49, 19, 70, 97, 137, 3, 169, 254, 24, 24, 206, 184, 242, 42, 190, 121, 253, 151, 121, 186, 101, 198, 112, 36, 214, 107, 198, 55, 160, 12, 151, 108, 40, 109, 115, 114, 208, 197, 230, 33, 190, 204, 179, 17, 198, 108, 211, 130, 100, 211, 64, 46, 89, 201, 20, 14, 102, 128, 49, 162, 217, 145, 51, 139, 148, 65, 194, 204, 181, 247, 160, 154, 60, 111, 163, 223, 204, 7, 71, 9, 21, 179, 37, 244, 65, 21, 9, 249, 61, 13, 33, 11, 117, 25, 254, 25, 112, 226, 189, 236, 120, 44, 204, 9, 134, 144, 198, 81, 114, 187, 33, 66, 40, 117, 138, 73, 158, 108, 28, 105, 242, 130, 172, 152, 226, 22, 253, 232, 194, 41, 27, 178, 197, 65, 76, 120, 49, 207, 25, 166, 227, 189, 178, 4, 27, 56, 115, 200, 176, 173, 115, 61, 82, 172, 186, 24, 226, 120, 211, 242, 173, 21, 229, 22, 125, 251, 34, 207, 45, 228, 89, 30, 220, 140, 46, 230, 53, 45, 3, 146, 76, 87, 16, 190, 82, 96, 109, 127, 12, 224, 240, 121, 132, 254, 85, 122, 150, 117, 71, 249, 121, 62, 157, 87, 222, 213, 202, 235, 60, 205, 199, 42, 190, 219, 238, 199, 41, 112, 90, 39, 216, 50, 59, 142, 51, 246, 48, 29, 159, 162, 50, 248, 238, 111, 253, 107, 18, 121, 232, 96, 72, 40, 12, 90, 183, 87, 226, 155, 187, 118, 205, 2, 191, 77, 24, 224, 49, 248, 154, 205, 79, 235, 115, 190, 138, 62, 80, 60, 143, 42, 33, 176, 64, 143, 158, 15, 91, 214, 76, 30, 173, 182, 116, 97, 37, 250, 36, 236, 201, 107, 93, 55, 38, 233, 63, 151, 197, 228, 78, 75, 58, 116, 240, 142, 74, 122, 115, 215, 204, 144, 222, 56, 193, 110, 43, 205, 92, 134, 237, 65, 23, 166, 186, 238, 148, 165, 241, 57, 245, 77, 43, 227, 96, 183, 146, 155, 116, 217, 240, 101, 154, 151, 85, 119, 17, 189, 177, 60, 241, 230, 200, 248, 210, 112, 123, 165, 187, 177, 103, 75, 19, 238, 165, 203, 83, 143, 92, 108, 178, 36, 209, 234, 233, 187, 80, 174, 73, 198, 116, 110, 11, 89, 253, 245, 205, 17, 54, 30, 242, 125, 215, 252, 103, 216, 187, 187, 232, 67, 107, 238, 218, 114, 39, 231, 197, 102, 223, 69, 196, 114, 57, 211, 156, 61, 23, 88, 187, 77, 222, 232, 33, 115, 178, 14, 200, 75, 134, 162, 231, 79, 21, 56, 190, 173, 167, 228, 223, 214, 251, 156, 171, 241, 186, 160, 7, 76, 249, 174, 18, 61, 151, 73, 76, 21, 212, 236, 78, 71, 213, 2, 194, 156, 71, 47, 152, 42, 84, 49, 180, 202, 1, 205, 50, 21, 121, 236, 26, 226, 1, 221, 65, 185, 15, 110, 147, 160, 5, 99, 37, 160, 200, 124, 145, 18, 170, 134, 29, 135, 168, 73, 234, 194, 226, 87, 38, 242, 28, 203, 92, 14, 88, 16, 113, 99, 226, 235, 21, 143, 169, 223, 71, 249, 217, 208, 98, 53, 8, 61, 78, 83, 236, 19, 14, 163, 222, 105, 242, 50, 61, 7, 242, 60, 75, 100, 148, 10, 208, 232, 134, 19, 57, 215, 49, 51, 38, 126, 11, 27, 143, 127, 180, 11, 73, 80, 233, 135, 128, 169, 213, 222, 57, 141, 171, 61, 54, 39, 73, 153, 37, 178, 56, 93, 227, 33, 183, 104, 151, 80, 189, 68, 104, 146, 171, 40, 219, 122, 106, 232, 171, 138, 116, 196, 242, 114, 164, 122, 190, 84, 239, 52, 69, 194, 21, 216, 47, 238, 34, 29, 71, 148, 120, 147, 222, 147, 151, 124, 221, 126, 202, 52, 56, 144, 67, 212, 241, 195, 106, 202, 72, 28, 174, 185, 42, 171, 142, 144, 234, 58, 189, 187, 65, 201, 123, 115, 211, 210, 35, 166, 59, 151, 175, 56, 100, 110, 16, 89, 200, 75, 127, 55, 104, 121, 85, 174, 36, 230, 158, 183, 150, 145, 248, 7, 82, 41, 52, 37, 10, 141, 16, 226, 126, 47, 233, 200, 167, 14, 196, 162, 34, 216, 142, 78, 202, 199, 175, 101, 30, 167, 231, 153, 142, 159, 19, 143, 240, 9, 95, 169, 63, 78, 250, 90, 132, 43, 83, 216, 34, 186, 80, 206, 172, 97, 206, 171, 83, 132, 118, 158, 85, 112, 212, 23, 62, 168, 151, 242, 255, 46, 56, 6, 73, 148, 48, 67, 110, 90, 239, 116, 156, 16, 18, 81, 74, 119, 64, 30, 19, 68, 176, 94, 57, 221, 29, 194, 178, 18, 232, 90, 210, 121, 152, 116, 196, 31, 9, 40, 54, 10, 144, 131, 229, 85, 153, 230, 35, 241, 44, 22, 110, 226, 79, 198, 3, 147, 27, 239, 11, 102, 224, 84, 112, 120, 79, 204, 184, 171, 128, 192, 255, 29, 119, 156, 120, 201, 96, 60, 51, 142, 248, 209, 172, 154, 100, 130, 106, 67, 30, 15, 236, 38, 204, 161, 113, 255, 16, 166, 35, 94, 153, 10, 244, 91, 48, 182, 208, 63, 51, 9, 18, 103, 234, 71, 130, 113, 120, 56, 142, 180, 122, 236, 143, 14, 235, 85, 7, 223, 123, 54, 164, 131, 163, 16, 117, 176, 253, 135, 17, 92, 227, 249, 99, 65, 31, 153, 240, 64, 31, 250, 126, 117, 56, 27, 131, 23, 214, 5, 236, 8, 207, 131, 239, 156, 61, 4, 187, 198, 156, 35, 170, 60, 9, 92, 3, 45, 135, 169, 101, 111, 77, 49, 72, 255, 64, 74, 208, 238, 169, 219, 81, 50, 109, 29, 248, 204, 228, 68, 176, 223, 21, 110, 34, 65, 93, 139, 179, 147, 34, 158, 104, 225, 51, 51, 140, 57, 42, 112, 35, 56, 198, 61, 150, 112, 87, 88, 134, 134, 102, 46, 79, 5, 201, 17, 252, 84, 202, 71, 110, 36, 190, 135, 252, 240, 141, 8, 212, 178, 93, 233, 30, 34, 249, 156, 140, 7, 123, 161, 229, 68, 224, 66, 70, 10, 144, 238, 158, 66, 2, 5, 137, 169, 77, 34, 47, 236, 55, 56, 129, 143, 53, 180, 231, 84, 30, 39, 214, 249, 152, 81, 255, 214, 139, 159, 133, 77, 213, 181, 7, 10, 37, 179, 53, 44, 42, 201, 43, 38, 131, 115, 83, 45, 122, 152, 199, 146, 5, 77, 226, 150, 71, 162, 2, 254, 199, 232, 121, 31, 125, 230, 70, 118, 202, 119, 59, 237, 36, 91, 56, 172, 225, 140, 99, 28, 250, 6, 61, 129, 224, 124, 210, 63, 109, 66, 178, 134, 12, 13, 113, 208, 241, 66, 250, 39, 45, 98, 61, 47, 70, 214, 107, 15, 10, 5, 156, 95, 88, 194, 177, 30, 109, 190, 237, 208, 129, 32, 149, 126, 60, 175, 228, 154, 166, 151, 156, 171, 147, 17, 86, 139, 210, 23, 152, 73, 92, 149, 181, 146, 116, 174, 79, 97, 8, 176, 120, 102, 68, 2, 109, 116, 243, 176, 109, 98, 167, 37, 173, 59, 160, 198, 243, 214, 13, 228, 62, 108, 11, 102, 159, 13, 2, 223, 91, 81, 0, 213, 177, 32, 210, 38, 129, 194, 115, 118, 203, 211, 133, 101, 113, 78, 243, 212, 118, 253, 70, 236, 72, 7, 48, 32, 188, 226, 28, 37, 113, 178, 69, 180, 39, 176, 215, 127, 173, 144, 157, 51, 115, 65, 103, 188, 61, 224, 18, 224, 62, 35, 23, 17, 254, 131, 52, 150, 114, 221, 135, 1, 244, 176, 74, 130, 191, 176, 82, 130, 67, 182, 98, 193, 90, 123, 18, 74, 195, 55, 199, 161, 40, 198, 102, 196, 84, 211, 111, 222, 200, 179, 187, 111, 222, 60, 148, 77, 41, 41, 226, 50, 213, 124, 236, 203, 219, 250, 81, 141, 196, 228, 4, 51, 137, 200, 181, 188, 36, 126, 153, 1, 93, 212, 50, 137, 102, 215, 139, 47, 119, 85, 188, 12, 169, 5, 198, 134, 165, 141, 76, 94, 208, 169, 212, 170, 183, 214, 201, 221, 146, 206, 124, 244, 207, 201, 89, 169, 230, 204, 167, 148, 250, 186, 87, 254, 105, 170, 115, 126, 142, 138, 48, 152, 104, 68, 77, 209, 244, 158, 199, 249, 248, 239, 227, 220, 60, 8, 180, 177, 141, 196, 9, 100, 224, 248, 238, 220, 82, 251, 183, 189, 89, 74, 102, 200, 61, 8, 158, 64, 141, 176, 201, 1, 42, 20, 227, 101, 104, 102, 248, 119, 105, 181, 63, 174, 166, 233, 120, 160, 19, 83, 243, 41, 135, 36, 144, 204, 171, 151, 250, 0, 251, 193, 137, 98, 114, 59, 170, 230, 83, 183, 99, 213, 45, 151, 147, 21, 50, 201, 144, 102, 29, 195, 129, 242, 128, 230, 164, 11, 229, 235, 82, 91, 195, 96, 216, 62, 45, 96, 115, 45, 31, 26, 69, 216, 180, 65, 139, 16, 216, 206, 172, 139, 87, 219, 234, 125, 87, 224, 87, 248, 206, 46, 22, 102, 99, 26, 66, 218, 185, 236, 102, 158, 195, 68, 65, 26, 44, 112, 154, 40, 4, 167, 205, 149, 55, 177, 238, 4, 78, 16, 17, 174, 13, 31, 32, 58, 160, 215, 223, 48, 134, 141, 150, 239, 187, 135, 140, 234, 14, 124, 18, 217, 107, 24, 16, 92, 212, 221, 157, 33, 137, 30, 180, 107, 63, 40, 38, 127, 107, 187, 83, 237, 45, 207, 191, 178, 3, 195, 137, 239, 169, 194, 247, 228, 84, 171, 154, 93, 28, 245, 57, 215, 65, 248, 128, 134, 37, 135, 95, 23, 27, 116, 39, 66, 101, 129, 225, 230, 16, 218, 12, 180, 143, 252, 66, 231, 246, 204, 8, 135, 16, 140, 159, 96, 141, 4, 1, 115, 164, 174, 36, 72, 159, 159, 166, 87, 56, 159, 218, 142, 170, 129, 83, 168, 13, 116, 141, 199, 108, 73, 100, 194, 180, 189, 54, 235, 229, 122, 226, 192, 154, 141, 21, 147, 7, 67, 152, 1, 109, 130, 195, 8, 245, 220, 192, 41, 160, 57, 157, 37, 72, 124, 88, 141, 29, 160, 16, 168, 143, 239, 106, 37, 72, 148, 71, 252, 229, 242, 95, 22, 192, 220, 178, 69, 165, 216, 107, 79, 16, 124, 148, 73, 46, 106, 136, 3, 11, 214, 48, 251, 153, 161, 168, 36, 191, 134, 93, 62, 132, 34, 147, 76, 38, 18, 186, 62, 24, 168, 228, 182, 52, 152, 162, 126, 191, 17, 182, 154, 152, 235, 134, 39, 232, 32, 254, 63, 19, 9, 54, 79, 12, 88, 79, 99, 132, 184, 170, 72, 46, 5, 74, 189, 209, 24, 175, 97, 158, 213, 143, 65, 179, 93, 157, 112, 180, 105, 152, 110, 160, 192, 46, 51, 177, 212, 245, 137, 109, 248, 176, 161, 203, 255, 22, 173, 155, 38, 188, 243, 226, 255, 69, 132, 137, 8, 87, 217, 72, 136, 68, 84, 136, 73, 54, 177, 38, 57, 150, 9, 95, 17, 154, 237, 163, 119, 22, 226, 99, 123, 17, 143, 159, 103, 252, 28, 194, 173, 194, 210, 228, 89, 169, 103, 128, 83, 66, 174, 151, 22, 76, 51, 30, 56, 39, 168, 238, 117, 89, 105, 153, 179, 180, 237, 65, 170, 235, 19, 246, 208, 57, 67, 87, 84, 40, 222, 55, 78, 218, 219, 116, 32, 112, 148, 234, 86, 200, 58, 63, 120, 199, 50, 30, 214, 214, 183, 139, 67, 29, 87, 180, 12, 245, 224, 137, 46, 160, 183, 190, 30, 65, 48, 73, 222, 150, 89, 202, 178, 9, 6, 68, 58, 126, 112, 241, 139, 72, 47, 42, 210, 161, 3, 133, 183, 74, 164, 219, 116, 224, 182, 138, 244, 178, 132, 145, 169, 134, 245, 117, 72, 13, 188, 217, 48, 203, 134, 205, 230, 218, 147, 73, 55, 193, 104, 190, 233, 171, 220, 200, 17, 161, 91, 178, 210, 157, 15, 251, 219, 37, 107, 183, 97, 181, 107, 78, 59, 237, 91, 129, 139, 108, 51, 169, 246, 122, 146, 204, 177, 218, 47, 24, 155, 211, 47, 134, 215, 9, 17, 234, 143, 89, 89, 74, 80, 56, 189, 88, 131, 171, 174, 250, 113, 15, 99, 205, 97, 233, 55, 156, 146, 186, 9, 106, 105, 89, 167, 173, 154, 21, 147, 115, 30, 139, 112, 181, 238, 126, 195, 241, 44, 43, 3, 235, 138, 228, 243, 28, 100, 74, 92, 17, 90, 246, 44, 166, 193, 239, 208, 9, 140, 99, 197, 142, 34, 90, 116, 244, 69, 169, 60, 136, 130, 87, 13, 239, 85, 168, 227, 82, 84, 56, 233, 17, 41, 71, 82, 215, 214, 2, 102, 121, 0, 235, 240, 201, 178, 248, 201, 42, 127, 125, 27, 57, 78, 245, 185, 76, 225, 122, 214, 196, 78, 29, 111, 108, 108, 204, 55, 248, 175, 195, 219, 238, 209, 211, 83, 55, 65, 218, 23, 63, 213, 209, 78, 198, 175, 105, 154, 106, 123, 28, 196, 229, 245, 160, 82, 150, 71, 184, 190, 248, 87, 175, 123, 204, 90, 36, 242, 175, 27, 190, 5, 142, 155, 121, 35, 173, 206, 152, 125, 25, 234, 79, 49, 212, 247, 150, 57, 214, 205, 167, 225, 2, 251, 38, 227, 225, 151, 161, 190, 117, 82, 93, 183, 182, 23, 235, 57, 114, 41, 230, 254, 56, 71, 220, 4, 49, 237, 248, 138, 213, 4, 25, 90, 105, 103, 14, 135, 178, 223, 226, 203, 70, 149, 5, 83, 213, 203, 34, 117, 195, 128, 99, 170, 202, 121, 214, 34, 208, 69, 144, 236, 60, 126, 170, 17, 80, 12, 159, 218, 208, 117, 107, 14, 39, 124, 219, 75, 58, 162, 239, 29, 22, 218, 31, 34, 186, 68, 79, 46, 106, 123, 6, 167, 227, 205, 215, 228, 71, 255, 181, 63, 15, 62, 151, 145, 62, 210, 72, 1, 160, 111, 211, 193, 25, 204, 165, 246, 134, 23, 231, 78, 71, 232, 241, 243, 168, 248, 60, 87, 17, 24, 207, 109, 4, 134, 128, 111, 190, 205, 29, 124, 33, 42, 183, 136, 184, 32, 120, 147, 175, 228, 118, 193, 142, 237, 164, 19, 136, 225, 178, 130, 5, 53, 143, 88, 210, 90, 84, 46, 51, 200, 7, 147, 85, 110, 44, 164, 242, 190, 78, 222, 224, 231, 94, 242, 220, 158, 228, 76, 39, 74, 133, 137, 114, 135, 210, 193, 1, 25, 150, 4, 128, 211, 81, 241, 54, 5, 122, 4, 62, 67, 229, 139, 119, 2, 157, 164, 43, 87, 209, 100, 53, 15, 65, 79, 106, 1, 36, 151, 180, 233, 228, 137, 104, 243, 82, 208, 66, 43, 202, 174, 65, 34, 220, 52, 217, 246, 226, 25, 39, 28, 63, 184, 106, 238, 44, 187, 84, 162, 22, 128, 132, 55, 104, 243, 156, 44, 145, 162, 125, 44, 26, 133, 148, 40, 54, 170, 45, 213, 231, 165, 66, 34, 19, 224, 120, 163, 166, 68, 95, 244, 200, 128, 192, 72, 71, 89, 205, 32, 136, 182, 84, 112, 125, 248, 51, 120, 219, 168, 204, 81, 79, 195, 130, 177, 77, 4, 202, 34, 129, 77, 164, 122, 155, 168, 38, 7, 231, 64, 64, 211, 194, 188, 139, 17, 129, 255, 226, 199, 172, 106, 142, 154, 182, 227, 236, 131, 90, 158, 150, 212, 165, 44, 173, 83, 116, 252, 83, 158, 69, 178, 33, 89, 251, 227, 233, 253, 45, 8, 159, 118, 99, 179, 182, 136, 187, 74, 59, 35, 181, 172, 88, 64, 124, 247, 200, 184, 99, 27, 100, 4, 87, 255, 30, 168, 126, 123, 80, 125, 14, 74, 87, 51, 215, 184, 154, 250, 199, 81, 92, 98, 4, 20, 176, 95, 83, 209, 95, 166, 152, 42, 70, 216, 208, 10, 130, 18, 22, 63, 225, 200, 91, 47, 235, 10, 241, 9, 67, 9, 126, 217, 187, 96, 141, 57, 175, 122, 183, 53, 218, 92, 244, 14, 126, 230, 178, 152, 77, 126, 50, 89, 87, 200, 116, 96, 78, 34, 249, 177, 172, 178, 112, 108, 150, 193, 49, 250, 246, 129, 150, 63, 119, 202, 81, 181, 245, 215, 92, 165, 150, 9, 152, 163, 29, 35, 70, 203, 159, 249, 250, 241, 153, 111, 47, 137, 94, 199, 110, 108, 25, 107, 175, 141, 179, 139, 100, 207, 238, 71, 156, 181, 55, 83, 29, 42, 110, 91, 137, 84, 83, 81, 147, 210, 247, 173, 211, 51, 34, 213, 120, 203, 108, 116, 2, 151, 247, 210, 74, 123, 75, 180, 70, 102, 74, 91, 47, 116, 39, 118, 18, 6, 86, 81, 96, 189, 228, 88, 101, 251, 91, 13, 10, 113, 32, 227, 143, 110, 211, 220, 141, 91, 225, 109, 131, 206, 5, 69, 242, 255, 103, 196, 81, 109, 83, 60, 164, 19, 38, 57, 47, 102, 231, 111, 179, 242, 77, 94, 137, 197, 148, 32, 115, 119, 60, 59, 183, 252, 140, 38, 177, 120, 167, 14, 254, 140, 101, 97, 247, 224, 102, 72, 70, 161, 202, 186, 252, 191, 212, 141, 225, 38, 95, 164, 47, 150, 217, 222, 61, 41, 25, 231, 225, 182, 116, 106, 96, 5, 50, 212, 164, 120, 221, 186, 85, 178, 219, 238, 111, 180, 99, 19, 219, 12, 59, 128, 190, 110, 235, 196, 137, 114, 36, 38, 164, 207, 131, 172, 204, 13, 226, 98, 122, 143, 78, 109, 53, 3, 176, 222, 237, 110, 37, 127, 249, 75, 242, 237, 253, 85, 184, 231, 113, 21, 118, 117, 53, 140, 175, 191, 54, 143, 226, 45, 43, 199, 143, 178, 73, 19, 194, 50, 134, 233, 59, 182, 193, 24, 231, 85, 161, 126, 234, 130, 171, 97, 80, 150, 173, 163, 208, 176, 72, 61, 64, 101, 160, 9, 109, 119, 112, 49, 214, 226, 248, 115, 86, 13, 202, 124, 34, 20, 94, 69, 79, 93, 169, 212, 50, 230, 178, 208, 3, 171, 242, 178, 75, 125, 229, 238, 97, 118, 2, 225, 101, 111, 138, 139, 241, 63, 197, 219, 174, 62, 80, 38, 141, 30, 11, 22, 76, 165, 143, 76, 73, 154, 108, 98, 61, 188, 120, 20, 128, 162, 18, 216, 198, 175, 120, 95, 111, 206, 47, 145, 183, 250, 18, 170, 168, 116, 163, 196, 88, 135, 86, 197, 183, 250, 126, 170, 99, 133, 92, 15, 34, 83, 202, 250, 146, 37, 237, 100, 180, 90, 167, 203, 72, 55, 81, 27, 194, 27, 103, 191, 2, 199, 138, 148, 13, 143, 10, 57, 103, 102, 239, 192, 195, 202, 148, 222, 167, 188, 168, 25, 36, 188, 38, 208, 3, 189, 95, 61, 249, 32, 230, 149, 42, 199, 51, 149, 12, 48, 59, 65, 9, 92, 78, 91, 202, 221, 154, 1, 232, 111, 166, 197, 179, 66, 204, 19, 153, 151, 158, 136, 46, 17, 106, 142, 174, 28, 108, 76, 77, 22, 156, 131, 96, 11, 114, 90, 16, 61, 101, 136, 187, 23, 217, 250, 213, 222, 165, 21, 97, 128, 238, 191, 88, 117, 245, 177, 251, 47, 181, 156, 226, 245, 191, 82, 0, 36, 145, 197, 184, 192, 236, 61, 247, 96, 168, 44, 8, 97, 179, 205, 3, 143, 214, 155, 57, 111, 203, 204, 54, 90, 252, 72, 97, 35, 139, 49, 148, 188, 137, 26, 105, 80, 33, 122, 58, 193, 144, 170, 217, 136, 214, 145, 70, 171, 138, 162, 165, 74, 43, 153, 64, 180, 32, 127, 82, 47, 169, 228, 15, 166, 74, 68, 193, 36, 116, 245, 176, 107, 218, 97, 213, 136, 89, 119, 255, 190, 66, 104, 10, 115, 5, 157, 24, 148, 70, 48, 51, 11, 100, 113, 162, 103, 124, 129, 171, 189, 111, 56, 231, 4, 191, 85, 210, 136, 238, 8, 235, 244, 85, 161, 217, 71, 104, 56, 149, 202, 74, 152, 170, 38, 165, 149, 234, 189, 225, 48, 137, 180, 234, 174, 178, 119, 65, 35, 200, 135, 205, 15, 91, 155, 155, 201, 159, 226, 239, 102, 95, 253, 217, 194, 227, 148, 230, 92, 181, 234, 152, 122, 134, 5, 228, 138, 52, 129, 61, 174, 86, 77, 254, 66, 9, 126, 186, 56, 193, 79, 155, 9, 126, 122, 183, 8, 126, 74, 200, 108, 137, 95, 67, 240, 103, 69, 113, 54, 155, 16, 14, 111, 69, 232, 207, 74, 165, 97, 65, 29, 107, 106, 78, 140, 205, 134, 122, 211, 27, 169, 232, 204, 139, 114, 54, 51, 19, 160, 126, 3, 235, 229, 175, 21, 137, 105, 26, 9, 50, 207, 29, 111, 153, 236, 223, 58, 3, 112, 248, 94, 145, 143, 100, 8, 29, 179, 226, 212, 155, 17, 197, 91, 197, 134, 218, 137, 136, 245, 238, 105, 127, 82, 116, 248, 126, 249, 50, 124, 115, 13, 95, 255, 166, 12, 95, 189, 17, 55, 177, 100, 180, 195, 218, 158, 98, 28, 128, 245, 181, 17, 170, 133, 186, 109, 18, 53, 79, 167, 101, 181, 59, 30, 162, 31, 14, 73, 171, 193, 176, 175, 64, 238, 254, 166, 187, 6, 209, 180, 71, 63, 34, 82, 94, 187, 74, 46, 202, 124, 10, 74, 250, 97, 114, 239, 158, 15, 109, 243, 129, 241, 169, 100, 130, 235, 212, 222, 77, 164, 104, 223, 20, 29, 20, 227, 147, 252, 116, 86, 87, 120, 107, 213, 57, 117, 44, 71, 154, 216, 112, 127, 104, 61, 234, 96, 92, 153, 55, 91, 248, 166, 53, 98, 173, 209, 250, 24, 96, 145, 131, 18, 89, 206, 153, 28, 220, 1, 238, 201, 1, 203, 223, 206, 166, 224, 46, 3, 41, 30, 76, 237, 178, 116, 57, 151, 115, 147, 230, 136, 238, 160, 111, 35, 42, 196, 43, 226, 107, 18, 31, 74, 68, 161, 48, 169, 120, 24, 230, 113, 211, 91, 75, 147, 38, 15, 223, 15, 65, 15, 223, 22, 37, 43, 38, 181, 247, 132, 68, 187, 201, 48, 245, 134, 190, 52, 194, 172, 193, 141, 231, 76, 255, 80, 179, 52, 113, 183, 170, 179, 81, 206, 75, 232, 73, 199, 50, 89, 71, 172, 22, 41, 50, 58, 194, 78, 98, 240, 231, 35, 242, 105, 195, 86, 18, 212, 147, 54, 194, 67, 248, 243, 3, 245, 57, 118, 40, 87, 206, 1, 155, 86, 83, 208, 183, 36, 244, 254, 38, 131, 174, 146, 173, 54, 128, 149, 90, 67, 175, 111, 21, 209, 72, 75, 100, 19, 154, 80, 85, 7, 156, 152, 150, 180, 34, 153, 163, 177, 80, 191, 52, 24, 213, 167, 7, 178, 79, 91, 188, 79, 98, 216, 154, 27, 217, 210, 141, 152, 65, 38, 141, 156, 102, 100, 111, 34, 96, 169, 130, 60, 96, 189, 123, 97, 151, 165, 195, 189, 223, 253, 160, 108, 216, 142, 179, 40, 151, 248, 86, 115, 225, 91, 5, 240, 173, 98, 248, 86, 22, 223, 106, 110, 124, 171, 48, 190, 10, 41, 103, 234, 230, 31, 250, 116, 78, 119, 65, 111, 17, 152, 70, 157, 183, 210, 154, 149, 94, 101, 232, 229, 157, 81, 160, 116, 252, 53, 19, 82, 212, 168, 158, 213, 239, 140, 201, 97, 16, 239, 18, 59, 93, 253, 121, 160, 246, 9, 109, 209, 64, 9, 252, 72, 141, 152, 128, 143, 198, 239, 17, 191, 251, 34, 16, 169, 101, 242, 131, 45, 66, 40, 116, 207, 203, 197, 133, 75, 165, 57, 65, 17, 167, 63, 121, 52, 48, 35, 139, 195, 86, 51, 32, 153, 249, 174, 50, 141, 202, 109, 124, 199, 172, 209, 234, 153, 116, 88, 166, 169, 242, 208, 133, 189, 202, 39, 106, 87, 95, 134, 159, 184, 238, 71, 199, 109, 56, 129, 77, 218, 88, 232, 74, 36, 108, 5, 234, 52, 132, 172, 168, 146, 27, 39, 22, 25, 30, 193, 18, 101, 41, 189, 245, 56, 81, 155, 131, 238, 32, 135, 251, 252, 15, 229, 119, 58, 232, 37, 47, 27, 188, 173, 220, 81, 245, 82, 39, 236, 242, 77, 228, 47, 123, 122, 206, 158, 158, 34, 39, 241, 130, 13, 100, 188, 67, 23, 23, 25, 55, 104, 239, 142, 175, 49, 207, 226, 246, 225, 89, 220, 46, 60, 107, 178, 7, 207, 148, 29, 104, 151, 134, 206, 142, 33, 36, 170, 19, 31, 95, 219, 137, 172, 105, 91, 48, 38, 18, 159, 105, 63, 208, 149, 52, 1, 250, 60, 175, 178, 55, 120, 166, 169, 91, 140, 159, 170, 39, 43, 113, 19, 85, 36, 26, 196, 130, 223, 235, 82, 232, 99, 43, 144, 56, 31, 27, 138, 228, 208, 135, 45, 102, 220, 166, 167, 251, 203, 216, 68, 47, 182, 253, 172, 225, 43, 222, 54, 25, 169, 166, 239, 50, 221, 157, 158, 74, 204, 139, 191, 66, 254, 61, 219, 115, 221, 17, 82, 29, 134, 126, 76, 42, 39, 12, 156, 251, 149, 13, 100, 151, 128, 89, 5, 75, 94, 179, 253, 123, 58, 255, 59, 7, 251, 66, 98, 82, 216, 190, 184, 151, 180, 186, 3, 133, 244, 56, 204, 170, 98, 244, 62, 235, 238, 177, 60, 172, 100, 250, 9, 135, 121, 202, 186, 27, 128, 118, 47, 49, 148, 55, 104, 7, 252, 32, 252, 82, 105, 205, 132, 234, 79, 151, 18, 138, 245, 95, 40, 154, 138, 30, 148, 187, 141, 4, 80, 217, 152, 85, 79, 130, 4, 104, 200, 69, 22, 105, 43, 202, 184, 124, 82, 83, 177, 105, 207, 242, 74, 154, 7, 210, 87, 243, 44, 63, 203, 158, 22, 165, 208, 250, 149, 221, 191, 50, 110, 9, 32, 146, 218, 70, 124, 85, 224, 1, 44, 81, 8, 117, 136, 89, 241, 66, 137, 199, 73, 247, 219, 205, 205, 228, 47, 137, 176, 146, 227, 39, 197, 251, 253, 191, 49, 241, 29, 9, 84, 112, 58, 81, 158, 35, 1, 106, 149, 77, 28, 185, 156, 74, 196, 31, 189, 105, 105, 55, 44, 3, 250, 14, 224, 137, 41, 84, 206, 231, 199, 185, 103, 54, 192, 103, 70, 16, 237, 80, 147, 247, 70, 116, 167, 105, 41, 131, 57, 48, 8, 80, 30, 21, 19, 38, 153, 57, 129, 38, 106, 51, 167, 134, 81, 5, 170, 226, 60, 193, 162, 186, 134, 51, 105, 107, 199, 1, 107, 178, 193, 146, 248, 222, 68, 231, 253, 15, 171, 247, 63, 29, 243, 1, 187, 185, 33, 187, 105, 94, 191, 42, 142, 138, 89, 57, 200, 156, 230, 184, 53, 209, 246, 202, 141, 54, 180, 195, 173, 177, 253, 106, 127, 60, 202, 229, 193, 207, 103, 80, 203, 192, 101, 163, 65, 247, 195, 244, 135, 129, 214, 225, 102, 168, 88, 3, 9, 31, 29, 162, 240, 27, 6, 232, 65, 243, 0, 169, 24, 239, 139, 87, 242, 181, 102, 124, 255, 112, 226, 227, 100, 75, 55, 98, 74, 59, 103, 15, 245, 74, 49, 128, 166, 169, 18, 55, 171, 61, 92, 183, 122, 9, 169, 70, 22, 182, 116, 78, 161, 184, 76, 77, 23, 62, 29, 227, 153, 129, 155, 143, 249, 164, 147, 75, 104, 38, 204, 153, 190, 95, 189, 20, 86, 95, 54, 84, 170, 194, 145, 75, 97, 180, 177, 55, 168, 164, 100, 68, 9, 209, 76, 216, 252, 143, 188, 48, 190, 125, 216, 164, 33, 93, 126, 78, 146, 234, 34, 151, 249, 251, 1, 77, 173, 23, 205, 9, 53, 65, 255, 205, 135, 206, 4, 162, 41, 225, 106, 118, 205, 209, 118, 48, 183, 45, 148, 254, 194, 80, 164, 136, 84, 98, 45, 69, 193, 109, 93, 29, 28, 62, 244, 25, 220, 251, 75, 132, 139, 15, 91, 172, 129, 7, 215, 209, 0, 62, 220, 103, 45, 125, 123, 173, 45, 225, 195, 3, 214, 228, 119, 159, 166, 73, 124, 248, 150, 181, 253, 253, 39, 110, 27, 31, 190, 99, 72, 252, 240, 185, 144, 192, 135, 239, 25, 54, 127, 251, 236, 216, 224, 195, 15, 12, 173, 254, 226, 26, 101, 233, 120, 225, 195, 223, 56, 130, 75, 80, 86, 75, 71, 80, 3, 228, 122, 176, 191, 76, 69, 184, 124, 84, 245, 147, 81, 178, 98, 13, 147, 138, 69, 137, 131, 180, 177, 32, 154, 176, 245, 207, 125, 105, 195, 106, 56, 175, 115, 19, 155, 190, 138, 123, 83, 231, 149, 15, 160, 115, 26, 219, 153, 214, 29, 243, 54, 167, 157, 107, 144, 184, 17, 213, 98, 167, 209, 53, 247, 88, 255, 162, 27, 229, 33, 116, 130, 29, 122, 151, 86, 203, 193, 61, 96, 123, 169, 10, 1, 163, 75, 52, 234, 155, 91, 8, 62, 104, 228, 211, 93, 208, 124, 108, 12, 197, 240, 0, 133, 250, 147, 92, 111, 135, 96, 171, 169, 93, 135, 26, 141, 115, 236, 177, 10, 164, 144, 232, 31, 205, 228, 221, 151, 126, 167, 122, 142, 245, 238, 82, 77, 85, 57, 38, 53, 120, 22, 136, 175, 14, 179, 211, 39, 31, 38, 79, 71, 233, 105, 197, 34, 30, 193, 186, 61, 140, 122, 201, 14, 235, 216, 247, 176, 238, 212, 241, 33, 179, 159, 141, 135, 164, 211, 209, 141, 28, 110, 200, 203, 18, 134, 249, 192, 110, 202, 97, 177, 53, 81, 110, 216, 161, 100, 60, 220, 80, 39, 183, 2, 5, 79, 157, 130, 249, 233, 184, 40, 179, 189, 180, 202, 2, 133, 115, 167, 240, 185, 248, 0, 87, 60, 134, 202, 158, 59, 101, 135, 197, 116, 119, 20, 194, 160, 114, 10, 206, 198, 249, 160, 24, 134, 64, 206, 194, 37, 197, 114, 52, 68, 130, 247, 78, 233, 106, 154, 15, 206, 46, 3, 5, 47, 59, 14, 55, 216, 132, 84, 126, 16, 168, 199, 8, 24, 155, 122, 2, 111, 120, 92, 170, 42, 26, 184, 151, 244, 250, 25, 102, 2, 105, 153, 74, 229, 243, 193, 230, 5, 1, 164, 176, 25, 7, 191, 196, 152, 151, 144, 175, 232, 230, 74, 231, 175, 112, 211, 167, 134, 182, 134, 191, 101, 177, 58, 242, 216, 107, 59, 237, 253, 169, 148, 52, 187, 195, 247, 112, 199, 135, 250, 178, 15, 65, 234, 221, 35, 188, 227, 26, 157, 87, 210, 165, 11, 132, 208, 216, 86, 179, 201, 68, 185, 191, 211, 82, 238, 9, 168, 245, 55, 198, 194, 31, 233, 149, 226, 215, 95, 163, 101, 224, 184, 58, 84, 83, 111, 128, 93, 94, 22, 249, 120, 186, 43, 244, 131, 109, 242, 113, 178, 249, 225, 68, 252, 91, 225, 87, 118, 40, 232, 107, 73, 95, 252, 199, 218, 119, 244, 41, 116, 249, 57, 56, 236, 186, 106, 99, 194, 142, 116, 249, 33, 58, 212, 229, 135, 218, 43, 180, 62, 212, 13, 182, 168, 75, 71, 251, 136, 142, 34, 162, 160, 27, 220, 175, 16, 63, 121, 50, 244, 96, 50, 205, 207, 243, 223, 85, 134, 40, 139, 0, 101, 135, 134, 227, 146, 229, 7, 126, 94, 82, 41, 22, 81, 239, 222, 189, 174, 2, 129, 225, 72, 214, 65, 194, 117, 15, 182, 38, 58, 244, 171, 18, 95, 183, 110, 127, 211, 117, 216, 170, 30, 252, 130, 135, 79, 5, 157, 69, 55, 36, 34, 71, 61, 10, 40, 180, 123, 175, 170, 226, 246, 193, 147, 15, 217, 64, 213, 115, 245, 63, 25, 67, 209, 203, 139, 151, 169, 152, 107, 116, 193, 240, 80, 59, 197, 204, 136, 123, 82, 85, 126, 32, 98, 101, 50, 106, 132, 152, 51, 31, 15, 70, 179, 161, 52, 171, 160, 2, 40, 150, 142, 187, 119, 172, 48, 8, 116, 196, 39, 106, 251, 102, 102, 106, 63, 70, 96, 58, 74, 171, 233, 62, 189, 203, 30, 192, 238, 38, 244, 170, 251, 177, 254, 20, 57, 168, 110, 230, 170, 32, 170, 58, 51, 164, 42, 227, 156, 115, 182, 59, 228, 234, 240, 148, 224, 124, 41, 0, 15, 147, 93, 58, 180, 234, 184, 33, 140, 193, 180, 100, 148, 150, 80, 173, 155, 36, 224, 91, 222, 21, 246, 116, 207, 84, 38, 24, 89, 120, 236, 46, 100, 244, 112, 19, 170, 24, 31, 58, 165, 150, 101, 88, 78, 66, 50, 32, 88, 0, 188, 86, 97, 237, 103, 129, 153, 162, 15, 73, 203, 107, 38, 157, 152, 252, 255, 120, 109, 45, 176, 16, 104, 39, 38, 134, 87, 189, 209, 158, 147, 3, 112, 103, 65, 80, 3, 52, 144, 214, 193, 53, 188, 49, 41, 170, 28, 83, 43, 42, 100, 143, 178, 180, 28, 188, 19, 214, 20, 162, 233, 82, 20, 134, 198, 86, 122, 4, 25, 226, 230, 100, 22, 218, 31, 222, 230, 51, 241, 69, 38, 152, 237, 30, 17, 125, 70, 24, 235, 104, 246, 86, 41, 83, 24, 30, 141, 5, 193, 49, 89, 55, 111, 151, 201, 113, 215, 205, 64, 184, 223, 99, 62, 60, 214, 99, 24, 216, 228, 219, 213, 85, 62, 54, 240, 94, 237, 52, 67, 23, 20, 170, 152, 63, 7, 198, 14, 53, 170, 242, 50, 82, 154, 157, 68, 38, 55, 139, 169, 34, 29, 58, 115, 43, 235, 128, 212, 149, 81, 214, 4, 43, 242, 105, 85, 27, 13, 234, 157, 190, 128, 140, 247, 161, 151, 196, 107, 200, 119, 27, 153, 80, 116, 114, 44, 213, 75, 117, 38, 8, 154, 125, 3, 42, 112, 197, 61, 60, 161, 74, 29, 102, 147, 81, 42, 22, 64, 21, 154, 75, 165, 250, 77, 162, 196, 62, 191, 21, 17, 151, 114, 53, 231, 168, 14, 165, 35, 236, 139, 40, 195, 210, 80, 146, 14, 153, 58, 121, 89, 77, 127, 46, 68, 145, 82, 51, 186, 202, 252, 40, 251, 230, 65, 180, 44, 98, 97, 113, 189, 239, 180, 161, 39, 25, 251, 90, 155, 135, 143, 105, 222, 133, 0, 26, 130, 191, 158, 58, 111, 67, 224, 105, 208, 225, 13, 52, 176, 224, 93, 148, 138, 70, 1, 224, 144, 62, 78, 190, 221, 228, 7, 29, 108, 0, 204, 79, 105, 133, 169, 57, 158, 224, 175, 167, 133, 208, 155, 231, 111, 135, 105, 136, 44, 22, 184, 225, 79, 13, 101, 149, 55, 16, 52, 237, 16, 81, 65, 66, 221, 90, 151, 85, 129, 249, 169, 231, 188, 57, 114, 95, 96, 183, 220, 215, 20, 91, 247, 155, 50, 131, 156, 151, 26, 113, 246, 154, 245, 243, 227, 138, 255, 84, 219, 43, 48, 198, 204, 68, 135, 104, 114, 196, 18, 107, 41, 82, 184, 114, 60, 93, 102, 189, 231, 204, 134, 13, 141, 203, 201, 140, 210, 147, 211, 146, 17, 44, 64, 195, 24, 253, 60, 218, 185, 120, 154, 79, 94, 175, 234, 209, 205, 33, 169, 242, 28, 212, 250, 104, 164, 161, 134, 243, 89, 147, 242, 84, 238, 28, 163, 227, 55, 212, 52, 36, 117, 205, 57, 227, 65, 71, 131, 16, 222, 27, 137, 240, 56, 68, 136, 30, 95, 16, 185, 200, 52, 83, 59, 188, 98, 66, 16, 102, 49, 180, 66, 251, 130, 104, 179, 62, 248, 248, 123, 195, 133, 175, 253, 46, 213, 76, 160, 20, 1, 213, 188, 108, 143, 52, 237, 54, 28, 108, 214, 107, 180, 237, 186, 142, 41, 234, 185, 214, 119, 118, 30, 165, 107, 55, 99, 6, 249, 234, 253, 138, 139, 188, 176, 145, 207, 29, 141, 149, 202, 228, 242, 6, 54, 200, 109, 50, 23, 76, 245, 83, 93, 231, 250, 207, 203, 69, 22, 176, 168, 17, 199, 158, 65, 104, 109, 205, 137, 244, 146, 102, 132, 59, 41, 6, 211, 156, 181, 89, 70, 222, 190, 229, 161, 9, 187, 208, 9, 157, 179, 225, 33, 247, 32, 235, 108, 135, 202, 255, 254, 210, 46, 203, 120, 196, 47, 9, 220, 210, 196, 102, 209, 91, 102, 172, 113, 76, 142, 115, 146, 108, 98, 188, 151, 78, 132, 170, 200, 116, 58, 12, 153, 144, 228, 60, 253, 208, 181, 52, 146, 181, 76, 196, 197, 122, 210, 215, 247, 36, 146, 209, 145, 41, 236, 163, 131, 99, 138, 41, 144, 50, 137, 150, 172, 68, 204, 84, 111, 237, 201, 176, 65, 114, 218, 119, 249, 88, 96, 168, 179, 179, 32, 138, 202, 79, 104, 84, 163, 9, 237, 222, 92, 33, 122, 86, 113, 191, 84, 38, 224, 39, 180, 220, 227, 219, 200, 127, 254, 233, 91, 159, 254, 236, 97, 64, 25, 105, 18, 150, 152, 186, 110, 224, 195, 161, 253, 74, 102, 17, 114, 61, 3, 252, 67, 90, 4, 167, 22, 179, 160, 53, 111, 204, 128, 53, 78, 55, 97, 149, 29, 81, 219, 132, 66, 78, 176, 179, 77, 188, 153, 64, 208, 178, 248, 179, 243, 200, 98, 177, 13, 11, 77, 106, 223, 200, 244, 167, 233, 228, 133, 225, 183, 227, 177, 57, 134, 171, 51, 152, 138, 175, 145, 115, 68, 240, 207, 176, 17, 20, 36, 198, 156, 54, 73, 244, 95, 137, 83, 122, 158, 13, 9, 11, 35, 39, 156, 194, 105, 130, 138, 174, 164, 121, 193, 104, 235, 230, 244, 2, 43, 31, 176, 138, 232, 168, 83, 250, 187, 230, 135, 97, 232, 199, 143, 2, 178, 108, 155, 246, 181, 192, 154, 61, 54, 196, 124, 28, 62, 20, 235, 247, 128, 76, 79, 129, 70, 214, 92, 86, 177, 156, 159, 132, 53, 140, 1, 184, 70, 5, 215, 95, 87, 5, 42, 139, 142, 58, 174, 10, 55, 115, 189, 238, 162, 99, 172, 40, 9, 9, 16, 98, 165, 21, 13, 244, 82, 41, 72, 130, 136, 97, 18, 149, 84, 43, 163, 68, 58, 165, 92, 82, 137, 100, 178, 120, 85, 219, 101, 96, 185, 216, 159, 214, 245, 71, 163, 64, 229, 20, 16, 152, 119, 117, 193, 158, 83, 5, 166, 95, 236, 10, 15, 251, 109, 150, 234, 184, 68, 55, 73, 51, 214, 10, 9, 116, 212, 112, 168, 235, 128, 169, 111, 226, 68, 155, 196, 191, 118, 169, 225, 235, 133, 200, 73, 17, 29, 122, 104, 232, 67, 85, 6, 15, 62, 36, 252, 110, 186, 77, 62, 133, 243, 162, 178, 2, 245, 203, 96, 239, 158, 109, 11, 87, 161, 6, 129, 50, 206, 39, 127, 18, 65, 181, 194, 126, 175, 146, 95, 68, 235, 242, 168, 200, 27, 209, 61, 251, 163, 127, 13, 125, 221, 186, 185, 125, 181, 63, 182, 174, 161, 227, 247, 111, 73, 199, 237, 143, 251, 215, 64, 133, 7, 183, 145, 10, 246, 199, 131, 101, 146, 132, 238, 39, 204, 169, 170, 155, 247, 92, 234, 106, 211, 101, 104, 43, 203, 109, 78, 248, 33, 235, 142, 57, 96, 220, 17, 111, 60, 149, 193, 125, 94, 228, 172, 164, 110, 60, 16, 55, 213, 162, 103, 238, 4, 87, 99, 159, 122, 110, 31, 97, 220, 72, 163, 41, 159, 206, 44, 111, 26, 170, 40, 163, 74, 253, 225, 44, 18, 240, 254, 56, 86, 75, 207, 199, 45, 110, 96, 61, 117, 167, 95, 105, 99, 161, 129, 149, 176, 77, 59, 127, 99, 197, 28, 24, 28, 251, 179, 60, 238, 22, 172, 171, 69, 117, 107, 115, 160, 197, 140, 95, 51, 223, 187, 179, 125, 141, 134, 104, 212, 15, 113, 237, 16, 209, 13, 102, 93, 205, 95, 135, 37, 156, 202, 183, 149, 110, 35, 219, 238, 188, 254, 153, 58, 162, 31, 221, 153, 124, 241, 62, 109, 221, 164, 62, 233, 71, 119, 190, 94, 188, 123, 247, 111, 104, 247, 244, 163, 59, 39, 47, 222, 211, 7, 55, 191, 167, 250, 209, 157, 117, 23, 232, 52, 117, 9, 70, 151, 130, 108, 213, 182, 89, 187, 106, 67, 82, 182, 152, 126, 199, 166, 27, 99, 123, 142, 179, 190, 134, 81, 159, 107, 224, 13, 100, 115, 125, 235, 138, 91, 122, 154, 111, 57, 21, 182, 6, 124, 63, 52, 191, 147, 217, 145, 115, 209, 114, 102, 246, 224, 220, 183, 248, 110, 153, 221, 208, 104, 140, 192, 155, 43, 68, 104, 81, 95, 243, 39, 137, 20, 242, 124, 255, 243, 68, 5, 213, 248, 207, 150, 229, 61, 243, 221, 124, 65, 130, 25, 172, 109, 151, 73, 71, 30, 89, 223, 218, 13, 11, 38, 34, 228, 167, 150, 255, 93, 241, 244, 133, 182, 249, 87, 90, 239, 67, 170, 13, 244, 107, 147, 203, 162, 204, 79, 33, 141, 128, 234, 11, 13, 63, 81, 35, 30, 140, 63, 233, 175, 186, 213, 159, 226, 246, 39, 134, 126, 155, 84, 117, 168, 9, 101, 142, 157, 202, 8, 211, 63, 156, 15, 100, 3, 240, 26, 116, 133, 231, 121, 118, 54, 133, 200, 166, 160, 139, 49, 223, 200, 155, 91, 233, 52, 168, 157, 32, 231, 207, 167, 124, 220, 141, 176, 249, 99, 18, 147, 22, 251, 99, 238, 182, 131, 111, 13, 53, 216, 66, 49, 75, 40, 104, 7, 121, 187, 82, 97, 171, 198, 218, 52, 38, 145, 25, 221, 69, 146, 143, 116, 244, 156, 141, 103, 25, 1, 219, 52, 116, 209, 141, 232, 200, 208, 109, 135, 71, 197, 216, 117, 109, 72, 14, 217, 217, 182, 195, 92, 71, 119, 27, 105, 49, 202, 49, 117, 251, 39, 209, 77, 195, 240, 74, 153, 24, 193, 124, 223, 176, 118, 155, 144, 142, 181, 51, 48, 159, 120, 190, 180, 18, 223, 118, 186, 100, 227, 194, 47, 116, 186, 169, 51, 37, 197, 236, 207, 71, 154, 39, 236, 54, 32, 22, 106, 167, 214, 193, 254, 53, 141, 57, 83, 195, 159, 127, 186, 160, 234, 2, 20, 165, 37, 205, 102, 7, 89, 155, 108, 95, 91, 245, 102, 14, 183, 30, 166, 23, 93, 222, 106, 143, 195, 8, 196, 87, 222, 49, 235, 128, 134, 54, 206, 101, 33, 144, 144, 196, 91, 105, 44, 124, 150, 73, 255, 203, 252, 224, 204, 15, 205, 193, 185, 152, 83, 107, 162, 226, 126, 213, 184, 123, 249, 232, 160, 22, 223, 245, 181, 224, 101, 229, 154, 32, 140, 109, 242, 204, 126, 240, 185, 11, 192, 216, 175, 78, 228, 8, 252, 35, 1, 202, 78, 214, 117, 58, 34, 52, 134, 246, 94, 125, 207, 23, 155, 59, 253, 217, 211, 137, 166, 13, 217, 54, 129, 57, 52, 178, 57, 242, 101, 54, 253, 50, 155, 38, 95, 102, 211, 166, 168, 246, 57, 167, 82, 127, 219, 233, 182, 56, 198, 190, 204, 123, 11, 205, 123, 215, 17, 209, 55, 199, 14, 42, 165, 85, 100, 154, 241, 55, 84, 85, 225, 5, 87, 102, 241, 144, 204, 94, 184, 3, 248, 246, 203, 82, 238, 115, 76, 62, 119, 68, 61, 135, 143, 149, 180, 84, 207, 225, 115, 201, 241, 128, 250, 133, 206, 212, 217, 131, 26, 7, 229, 145, 76, 8, 194, 117, 124, 215, 230, 207, 255, 97, 213, 236, 33, 241, 26, 52, 200, 175, 150, 9, 226, 85, 229, 48, 6, 38, 12, 174, 39, 228, 48, 30, 17, 46, 161, 70, 112, 244, 12, 199, 156, 94, 204, 26, 15, 102, 29, 254, 97, 236, 89, 164, 203, 17, 197, 42, 40, 214, 245, 222, 207, 120, 243, 78, 227, 62, 108, 218, 178, 163, 97, 234, 3, 172, 99, 51, 54, 19, 151, 77, 178, 49, 41, 180, 130, 211, 192, 221, 147, 227, 121, 118, 52, 190, 72, 241, 114, 164, 120, 30, 171, 173, 198, 98, 91, 150, 8, 155, 104, 169, 136, 113, 215, 230, 28, 78, 141, 81, 87, 107, 14, 199, 45, 187, 79, 161, 33, 218, 248, 1, 168, 149, 214, 24, 248, 182, 130, 70, 214, 23, 85, 83, 119, 44, 182, 229, 130, 46, 126, 232, 225, 139, 250, 249, 162, 126, 110, 165, 250, 89, 48, 220, 116, 57, 65, 190, 45, 151, 166, 115, 41, 188, 57, 35, 125, 191, 104, 70, 106, 22, 223, 176, 148, 114, 106, 119, 32, 123, 159, 23, 179, 234, 25, 225, 112, 202, 240, 158, 139, 108, 191, 250, 239, 172, 132, 244, 61, 71, 98, 180, 37, 75, 116, 61, 24, 250, 228, 175, 236, 145, 83, 51, 34, 85, 236, 110, 189, 250, 4, 68, 95, 127, 109, 83, 4, 238, 8, 189, 252, 253, 201, 201, 73, 205, 161, 117, 119, 197, 164, 15, 37, 215, 33, 231, 161, 231, 117, 17, 21, 28, 223, 201, 88, 48, 51, 12, 158, 63, 11, 78, 56, 241, 233, 33, 130, 18, 223, 113, 112, 146, 96, 6, 194, 255, 21, 121, 120, 6, 188, 158, 15, 60, 206, 212, 205, 85, 45, 187, 215, 166, 19, 144, 33, 173, 179, 178, 20, 82, 95, 199, 141, 114, 220, 44, 243, 185, 53, 66, 8, 68, 120, 46, 72, 65, 205, 131, 145, 73, 16, 105, 183, 238, 94, 203, 196, 103, 160, 64, 50, 173, 163, 201, 40, 159, 186, 121, 168, 246, 150, 144, 78, 107, 111, 90, 148, 201, 163, 216, 197, 74, 52, 159, 22, 52, 179, 39, 231, 22, 91, 115, 190, 148, 93, 182, 222, 134, 73, 137, 181, 237, 42, 214, 155, 159, 169, 75, 142, 133, 201, 211, 53, 2, 55, 197, 77, 210, 201, 145, 59, 180, 128, 28, 13, 163, 108, 119, 239, 45, 25, 205, 93, 29, 245, 124, 136, 180, 237, 74, 106, 240, 243, 46, 144, 225, 0, 123, 97, 191, 234, 203, 217, 184, 229, 13, 145, 207, 210, 63, 43, 141, 76, 73, 222, 10, 26, 156, 102, 165, 38, 39, 65, 205, 164, 65, 153, 95, 103, 58, 205, 68, 54, 119, 184, 102, 149, 26, 149, 41, 235, 106, 254, 216, 8, 248, 167, 187, 20, 222, 198, 171, 112, 251, 78, 55, 251, 255, 100, 187, 193, 9, 131, 0, 42, 245, 148, 226, 154, 245, 245, 201, 106, 66, 148, 88, 32, 143, 140, 50, 152, 47, 158, 234, 32, 15, 125, 104, 187, 45, 160, 203, 14, 153, 170, 52, 32, 26, 53, 226, 117, 221, 45, 4, 9, 137, 85, 242, 102, 61, 119, 17, 226, 68, 175, 1, 216, 19, 188, 11, 146, 215, 51, 240, 152, 148, 241, 92, 151, 202, 102, 216, 165, 27, 122, 130, 159, 53, 95, 6, 24, 95, 119, 73, 124, 130, 74, 50, 173, 48, 252, 219, 246, 150, 94, 178, 128, 130, 240, 248, 241, 99, 199, 135, 171, 27, 196, 86, 248, 14, 7, 77, 206, 168, 107, 84, 249, 239, 192, 148, 52, 61, 159, 188, 94, 86, 190, 166, 149, 35, 242, 132, 89, 178, 185, 249, 163, 201, 137, 70, 80, 60, 231, 152, 155, 39, 146, 143, 155, 133, 44, 167, 111, 2, 117, 213, 94, 110, 223, 12, 84, 254, 63, 156, 98, 115, 211, 30, 236, 12, 17, 231, 55, 152, 185, 3, 122, 238, 69, 65, 214, 70, 84, 255, 9, 123, 241, 94, 36, 148, 153, 98, 15, 32, 113, 159, 246, 55, 97, 87, 2, 177, 169, 85, 41, 4, 250, 247, 237, 16, 209, 109, 187, 182, 219, 191, 249, 214, 39, 35, 255, 111, 204, 242, 251, 13, 93, 245, 160, 103, 127, 131, 101, 13, 109, 27, 254, 5, 183, 159, 178, 86, 17, 199, 191, 39, 246, 10, 113, 51, 150, 81, 182, 249, 221, 115, 18, 212, 160, 253, 123, 251, 45, 101, 160, 199, 239, 118, 121, 110, 59, 62, 79, 103, 127, 19, 42, 226, 247, 227, 205, 215, 44, 218, 57, 162, 80, 153, 157, 247, 219, 182, 215, 61, 143, 119, 155, 59, 246, 155, 140, 77, 226, 186, 54, 182, 249, 248, 27, 220, 65, 250, 27, 221, 100, 76, 64, 135, 137, 105, 219, 189, 117, 89, 117, 205, 248, 180, 124, 252, 189, 76, 117, 74, 5, 76, 56, 179, 45, 142, 24, 71, 171, 78, 46, 81, 125, 246, 156, 184, 117, 1, 20, 2, 213, 245, 85, 103, 88, 74, 165, 149, 165, 217, 41, 119, 37, 222, 66, 255, 121, 57, 245, 88, 142, 95, 208, 150, 153, 173, 251, 123, 64, 169, 200, 201, 74, 90, 31, 7, 39, 141, 121, 169, 126, 15, 167, 164, 82, 80, 32, 39, 150, 161, 4, 10, 127, 46, 15, 203, 57, 224, 41, 35, 52, 80, 231, 119, 125, 207, 33, 50, 148, 166, 68, 128, 56, 141, 4, 242, 137, 68, 57, 135, 170, 82, 163, 21, 245, 250, 101, 226, 202, 86, 3, 218, 29, 188, 199, 149, 202, 211, 156, 124, 32, 231, 39, 195, 10, 100, 113, 180, 27, 176, 193, 29, 75, 221, 115, 141, 212, 221, 171, 0, 138, 210, 93, 47, 29, 186, 203, 37, 102, 188, 32, 197, 32, 149, 45, 117, 45, 236, 159, 252, 187, 76, 39, 19, 123, 126, 225, 80, 63, 224, 226, 0, 127, 117, 130, 56, 59, 247, 60, 215, 153, 245, 209, 12, 246, 135, 145, 188, 244, 175, 178, 106, 58, 23, 77, 106, 22, 38, 115, 220, 53, 209, 10, 127, 64, 252, 105, 81, 74, 20, 125, 252, 191, 210, 235, 12, 185, 128, 193, 155, 50, 244, 213, 44, 18, 249, 248, 93, 19, 88, 9, 175, 225, 56, 62, 146, 151, 60, 111, 84, 234, 237, 107, 118, 237, 132, 241, 17, 129, 202, 219, 29, 141, 190, 44, 173, 175, 178, 180, 94, 9, 47, 148, 53, 113, 63, 147, 227, 178, 226, 201, 28, 151, 191, 76, 102, 75, 53, 29, 3, 93, 246, 18, 207, 225, 212, 204, 109, 38, 41, 196, 34, 75, 202, 5, 22, 192, 136, 43, 89, 57, 182, 219, 36, 99, 10, 222, 32, 219, 233, 112, 68, 98, 139, 77, 219, 106, 139, 37, 89, 160, 226, 70, 59, 36, 13, 34, 168, 127, 231, 88, 137, 158, 118, 86, 5, 99, 73, 31, 234, 67, 88, 230, 252, 57, 63, 136, 25, 130, 232, 111, 74, 16, 62, 117, 215, 183, 156, 9, 78, 221, 82, 138, 58, 76, 89, 92, 194, 136, 75, 129, 233, 12, 79, 9, 106, 245, 92, 134, 27, 133, 221, 171, 53, 224, 202, 236, 52, 251, 48, 233, 233, 249, 41, 14, 80, 142, 176, 186, 122, 135, 255, 79, 218, 61, 8, 78, 244, 229, 69, 118, 17, 108, 72, 118, 91, 241, 163, 208, 214, 140, 13, 117, 109, 185, 84, 83, 8, 181, 42, 221, 215, 104, 183, 42, 189, 165, 59, 215, 170, 244, 125, 237, 111, 249, 19, 71, 44, 92, 65, 217, 149, 186, 150, 252, 245, 160, 199, 199, 119, 197, 185, 55, 8, 11, 135, 157, 186, 140, 102, 47, 178, 15, 204, 179, 70, 38, 238, 79, 125, 241, 193, 85, 156, 163, 94, 159, 72, 71, 138, 183, 255, 137, 42, 126, 121, 91, 185, 176, 204, 186, 170, 208, 47, 179, 180, 28, 190, 42, 130, 204, 5, 69, 87, 99, 190, 245, 122, 195, 141, 67, 138, 152, 113, 128, 160, 99, 187, 249, 221, 10, 152, 111, 102, 131, 226, 15, 241, 115, 52, 203, 30, 210, 68, 14, 195, 98, 44, 94, 200, 105, 92, 93, 13, 239, 70, 38, 24, 237, 237, 179, 28, 220, 188, 168, 184, 77, 179, 151, 127, 224, 223, 58, 99, 112, 51, 1, 26, 4, 106, 151, 122, 117, 22, 220, 205, 81, 120, 131, 16, 82, 20, 212, 152, 120, 51, 8, 71, 102, 115, 133, 108, 210, 42, 209, 108, 49, 113, 113, 24, 125, 10, 163, 229, 60, 198, 33, 220, 167, 16, 106, 111, 72, 104, 23, 209, 239, 68, 97, 16, 119, 25, 70, 182, 207, 229, 249, 69, 46, 50, 216, 38, 201, 150, 229, 27, 118, 206, 164, 173, 82, 64, 65, 109, 113, 48, 5, 117, 125, 95, 137, 10, 162, 236, 87, 143, 24, 11, 88, 123, 75, 213, 62, 9, 28, 68, 137, 197, 190, 152, 149, 38, 210, 214, 252, 102, 123, 147, 248, 150, 185, 78, 238, 197, 163, 91, 106, 67, 91, 76, 204, 135, 153, 242, 105, 133, 157, 71, 200, 157, 184, 150, 55, 69, 32, 252, 219, 9, 106, 113, 230, 199, 64, 24, 56, 4, 130, 91, 151, 24, 9, 64, 15, 186, 125, 106, 230, 17, 143, 51, 224, 223, 3, 250, 99, 189, 111, 126, 16, 151, 64, 76, 188, 213, 55, 71, 196, 41, 149, 66, 247, 131, 68, 227, 101, 92, 79, 153, 59, 6, 178, 16, 30, 195, 8, 30, 179, 104, 12, 205, 119, 33, 134, 194, 243, 213, 24, 5, 156, 81, 181, 3, 20, 141, 213, 183, 180, 184, 226, 200, 208, 233, 222, 25, 32, 239, 120, 226, 210, 89, 192, 6, 116, 73, 70, 120, 143, 151, 224, 72, 82, 111, 155, 111, 30, 35, 232, 45, 125, 212, 245, 77, 91, 79, 198, 135, 14, 229, 153, 225, 237, 156, 192, 8, 247, 79, 94, 22, 204, 13, 188, 6, 82, 16, 50, 24, 18, 172, 19, 109, 169, 103, 43, 20, 54, 22, 5, 192, 196, 214, 168, 241, 176, 88, 206, 143, 68, 159, 170, 236, 185, 102, 87, 95, 228, 76, 15, 156, 171, 6, 180, 208, 145, 137, 65, 23, 211, 209, 42, 142, 252, 0, 36, 176, 84, 252, 245, 144, 51, 100, 204, 103, 9, 65, 71, 115, 31, 136, 209, 210, 102, 154, 163, 167, 98, 44, 14, 68, 210, 2, 108, 99, 90, 182, 236, 200, 100, 229, 74, 227, 162, 86, 83, 97, 121, 240, 174, 114, 245, 12, 241, 110, 138, 247, 1, 51, 175, 15, 26, 166, 230, 91, 147, 71, 198, 174, 110, 117, 149, 99, 107, 171, 43, 103, 84, 183, 35, 11, 117, 86, 95, 51, 30, 21, 149, 130, 49, 123, 216, 210, 189, 123, 88, 202, 89, 55, 238, 87, 47, 139, 170, 202, 223, 142, 46, 209, 128, 101, 126, 42, 131, 55, 235, 178, 26, 86, 105, 224, 255, 35, 173, 94, 20, 234, 178, 82, 107, 162, 171, 202, 181, 107, 13, 85, 196, 110, 221, 19, 144, 177, 42, 71, 230, 226, 87, 164, 174, 130, 33, 48, 176, 133, 8, 152, 30, 69, 163, 150, 238, 154, 66, 221, 40, 165, 225, 234, 107, 2, 122, 213, 97, 0, 245, 73, 223, 145, 120, 91, 22, 95, 129, 26, 53, 188, 70, 224, 200, 142, 174, 184, 75, 55, 233, 105, 219, 31, 195, 29, 234, 233, 84, 240, 83, 166, 22, 70, 50, 52, 84, 73, 253, 123, 69, 16, 199, 37, 39, 150, 205, 122, 104, 85, 58, 188, 158, 85, 104, 170, 86, 136, 249, 222, 72, 188, 80, 77, 89, 137, 219, 175, 94, 8, 125, 116, 80, 254, 170, 165, 64, 130, 224, 222, 192, 0, 142, 216, 75, 133, 38, 155, 40, 242, 234, 165, 186, 173, 248, 72, 175, 77, 180, 159, 16, 231, 64, 136, 67, 81, 170, 173, 163, 25, 83, 54, 117, 175, 235, 86, 133, 160, 193, 176, 224, 152, 193, 187, 231, 227, 143, 61, 92, 177, 70, 51, 87, 19, 98, 196, 176, 19, 122, 2, 139, 142, 161, 59, 45, 196, 52, 6, 91, 6, 187, 190, 53, 227, 76, 210, 205, 25, 146, 241, 204, 144, 204, 141, 111, 202, 64, 219, 1, 186, 196, 69, 136, 118, 90, 152, 20, 83, 19, 188, 251, 84, 252, 32, 149, 186, 71, 142, 153, 128, 81, 55, 186, 66, 125, 71, 109, 65, 191, 35, 244, 168, 188, 116, 138, 117, 73, 59, 138, 231, 154, 144, 247, 111, 5, 118, 99, 65, 137, 26, 10, 17, 157, 12, 242, 135, 186, 1, 86, 78, 207, 163, 184, 192, 128, 35, 125, 169, 50, 35, 0, 186, 98, 131, 51, 95, 132, 145, 105, 220, 136, 153, 58, 157, 111, 124, 37, 143, 102, 0, 137, 227, 137, 225, 173, 108, 78, 186, 58, 112, 116, 77, 191, 223, 247, 44, 96, 137, 110, 179, 103, 214, 240, 178, 106, 132, 223, 166, 28, 108, 106, 75, 148, 49, 52, 10, 38, 227, 88, 80, 146, 37, 188, 79, 42, 204, 198, 49, 227, 75, 116, 157, 136, 216, 43, 201, 106, 112, 144, 141, 181, 98, 112, 213, 111, 60, 16, 128, 1, 255, 10, 51, 111, 50, 194, 225, 155, 164, 67, 209, 199, 15, 202, 166, 21, 107, 146, 124, 52, 58, 66, 51, 84, 124, 122, 50, 30, 94, 89, 10, 20, 24, 216, 71, 82, 79, 176, 147, 4, 143, 71, 211, 180, 156, 134, 38, 20, 103, 67, 137, 209, 49, 31, 79, 159, 107, 108, 169, 49, 110, 186, 64, 61, 101, 226, 141, 140, 56, 40, 157, 16, 45, 6, 68, 185, 45, 196, 15, 71, 21, 137, 151, 26, 41, 227, 145, 7, 234, 100, 12, 57, 75, 47, 163, 236, 116, 33, 118, 111, 153, 15, 212, 67, 228, 113, 210, 237, 246, 147, 157, 157, 228, 254, 38, 132, 65, 108, 113, 194, 30, 166, 227, 83, 35, 55, 155, 140, 94, 208, 160, 234, 42, 131, 183, 142, 253, 210, 200, 139, 53, 212, 120, 0, 7, 41, 208, 145, 165, 251, 226, 123, 114, 145, 53, 202, 108, 34, 56, 85, 159, 37, 129, 210, 234, 185, 171, 27, 252, 43, 190, 54, 193, 27, 127, 90, 103, 101, 184, 181, 53, 122, 164, 4, 97, 194, 242, 85, 67, 252, 47, 7, 162, 166, 41, 242, 16, 208, 148, 166, 231, 176, 84, 21, 139, 162, 96, 139, 206, 204, 17, 193, 74, 141, 75, 80, 56, 222, 84, 192, 166, 97, 17, 129, 45, 185, 164, 195, 246, 206, 25, 49, 45, 20, 197, 229, 176, 119, 25, 148, 52, 105, 107, 199, 196, 243, 77, 54, 142, 136, 232, 210, 218, 151, 52, 173, 93, 191, 232, 107, 147, 239, 226, 10, 6, 15, 50, 53, 172, 97, 44, 223, 202, 61, 194, 147, 178, 56, 215, 81, 54, 116, 27, 15, 16, 96, 15, 250, 96, 157, 174, 254, 79, 97, 214, 101, 163, 174, 86, 205, 90, 71, 147, 168, 40, 5, 122, 83, 138, 83, 224, 243, 8, 7, 112, 147, 200, 155, 207, 56, 165, 190, 231, 90, 134, 29, 98, 66, 106, 255, 78, 134, 171, 88, 55, 154, 110, 1, 227, 6, 237, 123, 92, 8, 16, 28, 216, 106, 32, 100, 239, 27, 70, 171, 179, 248, 9, 64, 215, 236, 71, 164, 184, 181, 192, 136, 80, 195, 0, 196, 98, 48, 112, 230, 55, 25, 116, 213, 94, 194, 218, 85, 18, 88, 115, 183, 117, 11, 51, 66, 1, 60, 242, 10, 81, 130, 104, 209, 49, 171, 48, 122, 135, 55, 161, 190, 35, 45, 10, 146, 190, 221, 149, 198, 114, 244, 88, 179, 145, 75, 106, 209, 164, 13, 95, 67, 190, 112, 83, 225, 27, 199, 217, 236, 55, 41, 170, 218, 104, 250, 97, 246, 225, 224, 132, 108, 197, 19, 248, 118, 122, 41, 42, 111, 115, 79, 207, 44, 162, 28, 109, 14, 16, 113, 124, 138, 178, 66, 13, 35, 248, 217, 230, 121, 39, 69, 235, 198, 167, 186, 66, 118, 217, 166, 105, 62, 122, 41, 123, 7, 248, 173, 177, 90, 206, 41, 219, 113, 118, 113, 100, 80, 165, 61, 50, 142, 76, 83, 194, 196, 145, 48, 175, 32, 253, 204, 52, 157, 196, 80, 157, 252, 52, 100, 183, 133, 215, 30, 105, 130, 108, 51, 6, 54, 6, 90, 229, 98, 43, 57, 19, 59, 182, 195, 74, 251, 152, 174, 133, 112, 193, 202, 61, 222, 210, 186, 126, 239, 174, 21, 9, 101, 162, 74, 82, 198, 78, 93, 187, 158, 108, 191, 14, 164, 210, 28, 92, 12, 134, 10, 240, 21, 33, 41, 113, 59, 151, 133, 132, 104, 209, 133, 225, 23, 93, 191, 189, 114, 5, 205, 187, 171, 13, 192, 197, 149, 175, 170, 96, 165, 61, 174, 161, 82, 181, 221, 241, 211, 165, 27, 3, 222, 239, 49, 40, 166, 251, 194, 234, 61, 56, 129, 195, 18, 207, 113, 35, 202, 28, 7, 50, 241, 31, 54, 169, 31, 201, 50, 80, 151, 202, 15, 246, 70, 72, 158, 129, 80, 12, 75, 96, 238, 48, 95, 36, 89, 244, 47, 74, 42, 124, 167, 177, 144, 63, 9, 127, 177, 102, 119, 2, 119, 70, 120, 183, 101, 144, 254, 208, 202, 219, 46, 235, 71, 178, 199, 215, 230, 142, 15, 231, 172, 11, 228, 141, 15, 117, 49, 148, 4, 207, 56, 24, 100, 183, 105, 231, 45, 151, 31, 141, 114, 25, 200, 97, 245, 121, 144, 170, 124, 208, 93, 186, 10, 45, 207, 11, 208, 182, 74, 157, 46, 143, 181, 232, 165, 41, 112, 219, 72, 88, 186, 9, 202, 137, 219, 124, 36, 4, 96, 195, 195, 84, 127, 59, 224, 118, 248, 148, 199, 131, 133, 194, 51, 154, 211, 105, 14, 192, 235, 179, 59, 193, 5, 246, 219, 92, 155, 26, 243, 26, 220, 197, 181, 155, 26, 176, 150, 219, 79, 138, 14, 119, 110, 255, 73, 211, 128, 110, 64, 169, 174, 198, 22, 135, 170, 198, 210, 220, 220, 136, 192, 39, 223, 27, 210, 124, 61, 255, 230, 80, 133, 135, 241, 90, 250, 148, 53, 133, 137, 78, 55, 16, 230, 183, 25, 116, 213, 171, 248, 148, 27, 118, 137, 2, 156, 222, 98, 155, 136, 229, 63, 105, 222, 44, 90, 223, 90, 222, 46, 209, 85, 189, 223, 102, 132, 230, 240, 125, 19, 70, 146, 169, 6, 238, 164, 126, 132, 158, 53, 121, 182, 80, 41, 168, 124, 11, 217, 36, 197, 104, 109, 146, 114, 225, 74, 218, 65, 162, 16, 88, 249, 160, 42, 128, 247, 65, 199, 4, 148, 137, 140, 20, 63, 67, 109, 220, 76, 136, 122, 16, 154, 46, 92, 115, 130, 156, 177, 50, 138, 4, 180, 71, 132, 175, 103, 91, 33, 177, 130, 254, 89, 191, 152, 35, 44, 132, 97, 80, 181, 233, 126, 214, 57, 193, 52, 34, 174, 114, 179, 71, 242, 233, 178, 200, 140, 107, 148, 75, 168, 122, 211, 48, 22, 80, 111, 230, 192, 46, 105, 83, 209, 78, 113, 148, 175, 26, 194, 59, 225, 114, 90, 214, 194, 162, 134, 45, 136, 13, 166, 8, 240, 207, 246, 39, 242, 44, 30, 89, 56, 241, 145, 11, 158, 244, 55, 93, 59, 126, 77, 13, 114, 165, 242, 233, 232, 197, 137, 114, 124, 196, 170, 198, 248, 9, 15, 129, 247, 146, 67, 73, 24, 35, 26, 53, 56, 183, 192, 130, 227, 64, 180, 131, 207, 207, 208, 116, 88, 19, 16, 19, 53, 45, 167, 210, 66, 93, 130, 30, 208, 80, 231, 221, 243, 27, 5, 182, 241, 112, 47, 80, 238, 33, 202, 138, 251, 130, 9, 79, 225, 40, 60, 188, 161, 219, 133, 114, 223, 8, 122, 224, 164, 75, 249, 81, 194, 125, 72, 170, 66, 47, 117, 197, 19, 153, 226, 31, 161, 219, 245, 106, 174, 124, 28, 102, 241, 170, 81, 0, 111, 188, 220, 13, 224, 0, 84, 219, 181, 213, 69, 145, 64, 229, 178, 56, 119, 43, 90, 140, 122, 6, 184, 117, 21, 22, 238, 178, 58, 90, 60, 178, 31, 97, 54, 53, 228, 174, 131, 208, 169, 133, 88, 121, 192, 239, 85, 60, 172, 35, 207, 131, 238, 87, 251, 227, 145, 128, 38, 134, 245, 89, 90, 158, 102, 238, 86, 147, 25, 227, 213, 237, 8, 87, 105, 150, 162, 203, 163, 171, 115, 213, 2, 219, 200, 77, 172, 131, 233, 61, 124, 182, 147, 172, 148, 144, 96, 81, 202, 83, 178, 22, 101, 42, 103, 35, 211, 52, 188, 67, 242, 131, 88, 100, 130, 204, 5, 235, 82, 1, 214, 4, 194, 80, 191, 109, 176, 174, 224, 22, 203, 152, 242, 116, 57, 247, 96, 131, 125, 70, 60, 180, 49, 238, 204, 52, 107, 226, 145, 113, 13, 83, 66, 147, 26, 174, 137, 159, 12, 118, 127, 170, 24, 101, 210, 240, 220, 76, 21, 224, 168, 65, 1, 155, 185, 16, 129, 217, 191, 58, 35, 41, 96, 243, 48, 18, 180, 182, 139, 209, 159, 120, 31, 125, 119, 53, 152, 55, 166, 226, 219, 254, 225, 74, 129, 189, 7, 49, 242, 166, 89, 49, 107, 235, 122, 221, 205, 213, 213, 102, 120, 91, 115, 193, 139, 125, 234, 175, 6, 152, 71, 201, 5, 188, 55, 151, 24, 231, 210, 245, 38, 254, 236, 36, 30, 58, 219, 144, 95, 193, 245, 195, 249, 142, 77, 218, 108, 174, 141, 17, 235, 56, 177, 149, 218, 122, 64, 222, 84, 224, 3, 90, 238, 36, 6, 16, 111, 197, 4, 38, 167, 16, 174, 35, 118, 228, 118, 49, 252, 251, 209, 219, 82, 22, 227, 79, 39, 51, 44, 247, 48, 166, 85, 232, 108, 5, 147, 143, 110, 8, 144, 21, 205, 68, 27, 192, 233, 46, 0, 88, 126, 161, 96, 171, 73, 58, 118, 85, 162, 153, 149, 180, 50, 108, 55, 155, 73, 80, 243, 104, 28, 24, 229, 128, 194, 81, 17, 49, 221, 65, 49, 27, 47, 97, 97, 164, 160, 133, 152, 41, 110, 15, 143, 25, 175, 40, 68, 180, 46, 26, 211, 73, 197, 11, 26, 194, 236, 102, 102, 219, 73, 20, 255, 11, 73, 209, 249, 200, 139, 62, 106, 19, 126, 100, 102, 1, 243, 32, 93, 214, 144, 32, 211, 1, 7, 167, 22, 76, 47, 94, 25, 231, 189, 212, 31, 219, 219, 116, 201, 7, 181, 73, 198, 171, 87, 210, 105, 74, 13, 234, 177, 176, 240, 77, 70, 24, 89, 195, 150, 62, 162, 165, 249, 17, 33, 199, 201, 78, 20, 200, 171, 144, 238, 200, 205, 25, 235, 185, 6, 218, 238, 99, 97, 179, 230, 28, 133, 9, 225, 54, 191, 85, 226, 12, 221, 144, 249, 192, 71, 94, 190, 108, 201, 29, 252, 196, 184, 42, 49, 247, 89, 241, 163, 86, 5, 251, 142, 4, 6, 79, 96, 115, 12, 174, 124, 74, 217, 233, 208, 66, 231, 147, 57, 140, 54, 39, 147, 253, 78, 68, 82, 202, 52, 157, 20, 85, 103, 181, 136, 106, 119, 14, 36, 135, 79, 136, 202, 90, 86, 116, 2, 89, 231, 230, 63, 19, 173, 44, 81, 60, 120, 75, 211, 15, 205, 125, 166, 25, 14, 53, 189, 44, 114, 185, 11, 21, 219, 10, 54, 101, 118, 167, 50, 158, 59, 103, 185, 224, 7, 239, 210, 114, 15, 244, 152, 128, 208, 23, 90, 162, 107, 65, 62, 198, 108, 126, 53, 12, 169, 168, 131, 48, 69, 109, 3, 13, 121, 147, 29, 85, 138, 33, 8, 19, 197, 158, 110, 181, 39, 185, 169, 103, 123, 70, 185, 220, 154, 26, 205, 179, 8, 229, 152, 208, 114, 104, 42, 102, 131, 193, 155, 50, 189, 144, 73, 47, 142, 132, 0, 37, 86, 56, 6, 69, 113, 38, 147, 174, 155, 252, 225, 186, 144, 13, 41, 78, 47, 216, 119, 89, 99, 67, 188, 181, 118, 135, 20, 202, 209, 81, 118, 42, 205, 49, 118, 120, 45, 189, 112, 99, 44, 189, 210, 1, 67, 22, 35, 71, 106, 106, 184, 86, 172, 221, 68, 78, 47, 244, 185, 59, 110, 76, 250, 134, 32, 41, 106, 236, 75, 122, 160, 174, 191, 77, 126, 238, 184, 221, 36, 31, 173, 213, 169, 183, 97, 117, 29, 207, 70, 165, 94, 28, 130, 213, 90, 196, 62, 53, 176, 180, 157, 250, 113, 165, 182, 46, 116, 201, 212, 177, 84, 96, 108, 165, 141, 91, 127, 46, 122, 155, 159, 206, 57, 13, 133, 236, 13, 1, 197, 53, 54, 244, 176, 238, 136, 111, 143, 59, 116, 13, 32, 139, 65, 186, 207, 157, 191, 202, 111, 65, 180, 4, 247, 159, 45, 3, 49, 128, 19, 71, 13, 190, 198, 145, 83, 95, 131, 232, 21, 163, 225, 50, 176, 19, 96, 226, 200, 197, 17, 11, 35, 117, 146, 127, 200, 150, 129, 149, 132, 19, 69, 107, 58, 141, 226, 5, 159, 194, 246, 78, 42, 172, 222, 106, 9, 168, 33, 164, 40, 114, 121, 20, 183, 60, 140, 90, 117, 46, 116, 223, 18, 16, 147, 112, 162, 104, 201, 175, 81, 212, 240, 107, 16, 61, 241, 231, 44, 91, 6, 126, 18, 80, 28, 65, 249, 57, 142, 33, 126, 142, 120, 116, 151, 129, 223, 236, 109, 28, 185, 89, 92, 20, 228, 183, 48, 90, 147, 165, 160, 53, 169, 65, 107, 82, 131, 214, 196, 65, 235, 73, 53, 72, 39, 217, 238, 84, 20, 125, 59, 155, 98, 238, 250, 247, 118, 86, 206, 199, 147, 25, 168, 105, 58, 89, 189, 103, 235, 208, 105, 48, 190, 74, 215, 235, 37, 223, 116, 190, 233, 37, 157, 175, 127, 155, 21, 211, 237, 78, 208, 249, 158, 142, 7, 239, 132, 113, 11, 199, 60, 175, 78, 26, 5, 172, 253, 18, 19, 187, 241, 205, 78, 42, 207, 153, 62, 234, 124, 35, 72, 21, 164, 138, 194, 111, 77, 116, 232, 49, 148, 57, 82, 36, 77, 35, 74, 175, 24, 79, 7, 197, 168, 128, 21, 235, 72, 231, 220, 187, 146, 246, 211, 0, 23, 232, 26, 212, 77, 100, 229, 154, 238, 33, 158, 110, 255, 160, 110, 188, 139, 96, 73, 119, 173, 57, 125, 213, 14, 2, 164, 69, 251, 7, 117, 107, 186, 167, 144, 108, 223, 59, 57, 209, 207, 202, 209, 213, 59, 22, 154, 234, 91, 241, 227, 187, 50, 59, 169, 233, 145, 68, 174, 145, 29, 179, 41, 73, 53, 184, 63, 206, 113, 69, 107, 210, 43, 171, 216, 144, 41, 89, 151, 170, 216, 197, 161, 220, 77, 21, 95, 54, 196, 51, 89, 174, 154, 160, 75, 89, 36, 230, 9, 128, 128, 86, 220, 1, 86, 229, 116, 199, 153, 117, 171, 34, 244, 161, 204, 104, 84, 92, 224, 174, 42, 44, 34, 44, 142, 26, 126, 104, 219, 85, 66, 134, 61, 215, 105, 207, 130, 195, 150, 56, 9, 158, 22, 229, 147, 116, 240, 78, 174, 40, 222, 166, 131, 179, 147, 177, 26, 15, 97, 220, 38, 222, 142, 162, 30, 155, 240, 58, 253, 72, 173, 210, 143, 200, 26, 93, 103, 181, 18, 223, 230, 95, 156, 235, 237, 234, 218, 21, 57, 193, 155, 124, 21, 216, 219, 37, 187, 233, 164, 179, 84, 119, 135, 205, 130, 170, 27, 187, 159, 51, 224, 227, 124, 148, 137, 54, 186, 155, 189, 132, 214, 162, 60, 44, 215, 153, 225, 211, 8, 217, 244, 141, 250, 74, 239, 81, 17, 99, 165, 22, 137, 162, 152, 9, 199, 81, 121, 76, 142, 188, 79, 80, 41, 18, 214, 138, 203, 117, 177, 62, 129, 181, 166, 168, 250, 100, 60, 45, 47, 5, 5, 140, 171, 68, 183, 237, 183, 72, 246, 194, 1, 76, 77, 76, 170, 233, 161, 146, 4, 7, 142, 185, 114, 58, 248, 41, 161, 249, 205, 67, 220, 27, 224, 197, 158, 106, 205, 252, 57, 242, 153, 249, 43, 209, 215, 57, 83, 216, 218, 26, 53, 249, 107, 109, 202, 45, 127, 28, 68, 87, 84, 248, 146, 255, 169, 203, 150, 249, 250, 179, 231, 248, 58, 136, 138, 211, 129, 18, 167, 3, 38, 78, 102, 16, 15, 22, 18, 168, 185, 92, 93, 28, 231, 128, 159, 107, 110, 150, 85, 235, 124, 208, 70, 181, 206, 41, 96, 105, 155, 175, 175, 153, 161, 15, 162, 188, 44, 41, 74, 89, 25, 29, 163, 231, 255, 204, 229, 70, 74, 131, 187, 237, 192, 38, 111, 181, 46, 10, 43, 35, 22, 16, 245, 117, 152, 109, 170, 90, 201, 112, 252, 209, 230, 6, 119, 83, 247, 56, 88, 57, 212, 83, 241, 154, 197, 152, 52, 11, 157, 26, 3, 227, 10, 163, 253, 194, 79, 72, 244, 80, 100, 153, 42, 193, 166, 82, 112, 115, 130, 47, 110, 80, 148, 67, 229, 174, 253, 195, 99, 103, 229, 160, 13, 170, 85, 200, 50, 44, 125, 187, 241, 52, 195, 80, 155, 121, 139, 210, 139, 35, 229, 252, 20, 95, 54, 192, 130, 209, 236, 50, 158, 157, 227, 151, 53, 44, 164, 25, 65, 127, 81, 233, 233, 229, 51, 245, 8, 25, 144, 225, 120, 30, 23, 231, 7, 66, 101, 160, 81, 214, 49, 197, 245, 241, 20, 103, 116, 235, 234, 190, 72, 95, 152, 90, 164, 131, 176, 187, 166, 186, 97, 119, 120, 52, 210, 214, 107, 171, 202, 212, 236, 244, 124, 247, 183, 45, 70, 183, 119, 105, 133, 52, 19, 79, 33, 219, 69, 188, 142, 206, 126, 144, 122, 70, 124, 239, 48, 136, 103, 217, 165, 6, 9, 143, 33, 152, 240, 190, 22, 40, 20, 232, 184, 235, 181, 63, 128, 145, 31, 202, 44, 84, 210, 130, 125, 168, 105, 210, 131, 94, 244, 84, 195, 31, 93, 62, 212, 74, 1, 100, 217, 68, 187, 1, 107, 90, 149, 11, 21, 247, 167, 230, 184, 187, 31, 145, 11, 197, 101, 103, 164, 180, 193, 15, 241, 135, 30, 175, 65, 150, 214, 128, 26, 54, 125, 4, 123, 227, 147, 109, 57, 206, 233, 186, 12, 87, 183, 72, 19, 253, 209, 53, 100, 127, 29, 3, 230, 197, 244, 93, 86, 46, 60, 181, 152, 111, 237, 38, 150, 136, 137, 134, 193, 125, 18, 149, 158, 156, 68, 36, 110, 156, 103, 228, 215, 67, 8, 118, 119, 84, 135, 236, 192, 182, 63, 78, 225, 129, 213, 96, 188, 26, 48, 81, 136, 90, 250, 231, 6, 152, 192, 118, 254, 209, 215, 89, 130, 253, 63, 185, 20, 29, 246, 124, 203, 81, 235, 251, 223, 249, 244, 157, 156, 192, 53, 232, 30, 107, 147, 217, 228, 158, 205, 39, 140, 114, 29, 247, 226, 91, 229, 181, 1, 12, 114, 126, 202, 202, 42, 83, 0, 111, 230, 56, 83, 20, 23, 25, 238, 35, 185, 212, 138, 228, 129, 23, 31, 109, 120, 181, 25, 194, 113, 118, 1, 213, 186, 54, 250, 64, 32, 133, 106, 51, 56, 4, 42, 116, 234, 192, 200, 178, 41, 191, 243, 200, 96, 185, 225, 222, 35, 212, 206, 146, 63, 32, 134, 194, 220, 134, 81, 208, 154, 95, 154, 61, 31, 178, 232, 35, 183, 246, 180, 180, 235, 219, 24, 25, 170, 213, 144, 134, 53, 148, 150, 122, 220, 210, 29, 86, 171, 239, 157, 115, 172, 109, 100, 233, 61, 57, 83, 201, 226, 174, 233, 44, 60, 191, 70, 89, 130, 82, 144, 154, 199, 9, 80, 15, 246, 71, 82, 226, 128, 170, 133, 249, 72, 192, 213, 137, 67, 134, 38, 229, 242, 115, 126, 114, 146, 149, 217, 120, 144, 221, 80, 213, 98, 17, 92, 68, 177, 68, 52, 254, 103, 214, 23, 37, 149, 208, 47, 74, 227, 83, 40, 141, 97, 54, 202, 166, 217, 109, 212, 27, 173, 186, 227, 234, 128, 86, 178, 127, 116, 121, 126, 158, 77, 203, 124, 240, 185, 148, 0, 246, 176, 189, 199, 79, 233, 5, 252, 209, 9, 119, 33, 224, 172, 184, 243, 54, 231, 66, 115, 203, 98, 140, 197, 87, 183, 243, 207, 78, 173, 56, 115, 191, 130, 64, 78, 193, 79, 39, 55, 116, 86, 178, 8, 46, 50, 43, 45, 60, 245, 60, 14, 207, 60, 177, 12, 201, 243, 88, 175, 255, 139, 253, 208, 38, 127, 201, 85, 230, 29, 119, 12, 60, 78, 87, 65, 116, 62, 159, 79, 96, 229, 116, 179, 57, 93, 163, 248, 73, 121, 125, 103, 62, 94, 159, 79, 123, 47, 121, 150, 142, 100, 192, 105, 80, 192, 11, 178, 204, 207, 121, 245, 31, 136, 71, 132, 190, 221, 182, 249, 154, 99, 191, 240, 84, 253, 101, 173, 127, 247, 204, 118, 95, 26, 110, 182, 93, 190, 224, 122, 190, 161, 155, 53, 194, 255, 175, 60, 187, 200, 134, 187, 101, 153, 94, 254, 52, 3, 107, 119, 255, 228, 48, 203, 79, 114, 8, 185, 72, 225, 173, 106, 198, 36, 169, 125, 59, 59, 73, 98, 215, 92, 169, 10, 58, 10, 93, 226, 177, 109, 155, 54, 74, 67, 128, 128, 203, 245, 0, 146, 190, 133, 135, 165, 83, 249, 57, 155, 166, 131, 119, 217, 80, 225, 3, 197, 79, 50, 18, 213, 163, 126, 199, 84, 11, 83, 225, 6, 5, 168, 103, 42, 106, 85, 69, 58, 173, 27, 137, 106, 44, 111, 102, 104, 121, 205, 149, 130, 219, 75, 238, 211, 128, 19, 114, 95, 213, 15, 234, 198, 244, 77, 119, 215, 97, 119, 170, 104, 64, 113, 164, 227, 129, 67, 161, 250, 211, 60, 134, 154, 6, 49, 226, 198, 246, 209, 190, 183, 199, 122, 16, 119, 85, 161, 5, 186, 40, 48, 108, 227, 60, 214, 49, 21, 144, 67, 67, 229, 198, 213, 172, 204, 0, 17, 85, 16, 36, 136, 214, 72, 203, 83, 26, 44, 100, 47, 203, 88, 85, 121, 74, 108, 77, 249, 82, 119, 47, 210, 62, 20, 217, 38, 163, 173, 187, 236, 79, 83, 48, 73, 89, 216, 193, 185, 42, 213, 145, 34, 157, 58, 186, 192, 36, 197, 187, 108, 193, 6, 46, 52, 53, 91, 160, 70, 14, 7, 234, 32, 14, 236, 146, 13, 108, 65, 61, 206, 131, 166, 19, 252, 4, 56, 92, 227, 107, 201, 69, 247, 69, 249, 92, 15, 101, 235, 54, 92, 59, 133, 44, 247, 77, 149, 124, 67, 48, 250, 38, 153, 224, 189, 209, 220, 206, 147, 83, 162, 248, 30, 202, 56, 164, 250, 79, 238, 87, 9, 164, 167, 112, 83, 150, 180, 238, 208, 62, 35, 172, 133, 115, 152, 77, 138, 114, 250, 107, 149, 158, 102, 242, 136, 7, 28, 150, 236, 9, 173, 113, 31, 206, 153, 245, 191, 131, 131, 234, 247, 87, 87, 105, 147, 149, 6, 27, 218, 165, 235, 227, 201, 172, 206, 223, 255, 142, 253, 49, 132, 72, 212, 246, 179, 162, 21, 33, 149, 207, 19, 66, 209, 231, 195, 116, 154, 57, 221, 241, 57, 159, 238, 133, 171, 15, 78, 21, 59, 89, 68, 100, 64, 147, 137, 75, 1, 77, 80, 225, 93, 84, 19, 109, 2, 74, 71, 203, 254, 35, 117, 117, 16, 175, 28, 85, 66, 212, 210, 112, 49, 12, 140, 194, 183, 127, 251, 46, 38, 96, 42, 194, 6, 116, 10, 158, 207, 32, 131, 192, 115, 7, 168, 169, 253, 194, 86, 77, 106, 110, 189, 149, 216, 80, 80, 225, 23, 230, 254, 58, 217, 171, 192, 16, 179, 6, 237, 113, 27, 121, 204, 55, 74, 86, 236, 137, 95, 87, 30, 165, 201, 224, 244, 38, 207, 25, 231, 145, 235, 123, 221, 117, 123, 80, 150, 103, 58, 181, 128, 27, 233, 138, 35, 203, 232, 170, 167, 194, 183, 151, 211, 236, 224, 228, 68, 26, 108, 215, 77, 107, 108, 83, 61, 219, 118, 23, 29, 135, 249, 169, 191, 16, 245, 132, 5, 161, 242, 106, 181, 35, 227, 167, 38, 223, 205, 33, 153, 158, 41, 93, 121, 206, 62, 100, 231, 147, 81, 26, 16, 102, 184, 48, 188, 118, 166, 213, 85, 41, 42, 53, 154, 99, 207, 52, 209, 22, 69, 28, 83, 1, 221, 96, 185, 66, 41, 205, 217, 20, 153, 244, 26, 58, 128, 120, 236, 213, 10, 102, 219, 78, 185, 28, 219, 162, 119, 215, 209, 39, 23, 141, 96, 231, 98, 157, 130, 165, 177, 13, 245, 116, 253, 30, 77, 22, 233, 65, 43, 110, 63, 160, 61, 80, 120, 203, 207, 52, 242, 112, 43, 138, 224, 251, 172, 188, 36, 177, 172, 201, 85, 48, 109, 63, 165, 88, 135, 71, 67, 58, 18, 119, 70, 249, 86, 30, 248, 238, 252, 151, 133, 248, 95, 27, 38, 3, 229, 70, 6, 189, 233, 184, 182, 230, 53, 197, 78, 219, 0, 116, 191, 15, 143, 147, 190, 88, 141, 242, 172, 36, 9, 9, 34, 101, 158, 189, 179, 68, 38, 34, 57, 83, 211, 169, 120, 224, 169, 71, 206, 48, 17, 126, 114, 112, 124, 246, 218, 186, 116, 166, 89, 101, 51, 34, 182, 14, 80, 62, 195, 116, 207, 103, 214, 63, 36, 169, 100, 161, 45, 224, 245, 59, 170, 57, 89, 236, 176, 26, 141, 55, 182, 159, 224, 86, 147, 46, 6, 77, 87, 152, 95, 100, 179, 135, 121, 139, 156, 229, 6, 95, 64, 168, 195, 81, 127, 254, 9, 233, 230, 200, 156, 193, 78, 118, 52, 56, 8, 27, 214, 94, 220, 79, 248, 158, 230, 32, 86, 105, 90, 240, 7, 228, 30, 194, 199, 14, 239, 89, 192, 121, 72, 101, 139, 45, 187, 235, 87, 179, 84, 196, 34, 50, 37, 57, 70, 197, 13, 11, 88, 182, 16, 132, 0, 19, 177, 59, 211, 17, 193, 127, 3, 226, 153, 95, 253, 77, 203, 121, 138, 233, 94, 21, 63, 229, 167, 251, 130, 129, 237, 62, 180, 227, 225, 210, 229, 94, 204, 206, 223, 102, 37, 45, 183, 162, 55, 22, 71, 233, 52, 127, 159, 53, 101, 142, 57, 195, 164, 44, 188, 124, 67, 10, 24, 86, 56, 158, 7, 198, 41, 70, 179, 182, 232, 79, 87, 72, 187, 230, 32, 142, 41, 101, 218, 160, 141, 217, 101, 234, 145, 102, 137, 102, 106, 220, 85, 109, 156, 55, 7, 206, 194, 117, 97, 223, 77, 45, 23, 34, 85, 2, 249, 224, 108, 71, 84, 34, 21, 169, 246, 228, 23, 166, 248, 64, 215, 137, 250, 146, 153, 156, 85, 195, 65, 100, 42, 19, 162, 6, 11, 236, 187, 50, 151, 157, 200, 238, 124, 170, 201, 236, 213, 194, 211, 152, 114, 113, 79, 48, 210, 241, 205, 179, 188, 34, 161, 142, 131, 116, 34, 198, 76, 166, 133, 216, 188, 226, 156, 23, 243, 221, 211, 105, 238, 149, 51, 193, 217, 185, 12, 48, 60, 214, 216, 172, 173, 1, 111, 169, 146, 124, 98, 131, 182, 119, 131, 150, 163, 107, 164, 31, 244, 76, 231, 156, 125, 58, 213, 51, 88, 28, 235, 2, 226, 151, 237, 222, 238, 241, 88, 182, 14, 8, 141, 221, 148, 151, 187, 237, 167, 83, 197, 238, 177, 249, 84, 40, 251, 137, 104, 57, 135, 171, 195, 110, 187, 28, 140, 135, 113, 41, 48, 157, 156, 71, 8, 72, 165, 27, 98, 208, 197, 152, 219, 96, 26, 51, 225, 60, 107, 45, 196, 213, 248, 137, 32, 219, 158, 201, 228, 84, 23, 97, 49, 117, 7, 248, 109, 225, 51, 164, 147, 96, 55, 124, 218, 52, 246, 90, 13, 235, 201, 62, 54, 156, 201, 188, 109, 76, 56, 15, 183, 1, 143, 70, 121, 45, 200, 102, 235, 253, 249, 248, 75, 95, 69, 31, 98, 50, 239, 220, 239, 13, 231, 49, 173, 203, 44, 64, 202, 78, 120, 192, 247, 14, 173, 79, 91, 175, 59, 9, 27, 57, 83, 222, 34, 90, 73, 17, 50, 204, 51, 251, 234, 14, 28, 188, 179, 224, 201, 72, 222, 163, 162, 82, 43, 234, 108, 76, 155, 55, 97, 37, 201, 241, 195, 151, 6, 203, 192, 82, 18, 59, 230, 232, 162, 54, 11, 70, 119, 181, 89, 107, 186, 107, 223, 126, 40, 153, 214, 122, 159, 50, 24, 207, 236, 104, 80, 87, 27, 245, 219, 102, 137, 192, 214, 0, 226, 85, 207, 107, 249, 191, 179, 178, 56, 24, 31, 204, 166, 7, 39, 63, 21, 130, 31, 42, 136, 243, 145, 80, 160, 113, 141, 212, 24, 82, 191, 141, 188, 91, 111, 57, 78, 103, 172, 180, 193, 31, 88, 120, 236, 173, 93, 225, 173, 90, 142, 141, 237, 52, 124, 70, 79, 42, 38, 200, 252, 76, 207, 145, 133, 139, 43, 15, 219, 22, 142, 90, 193, 60, 122, 196, 7, 122, 46, 29, 26, 224, 238, 255, 83, 64, 206, 99, 147, 98, 253, 70, 240, 177, 78, 153, 239, 179, 44, 96, 123, 221, 252, 170, 194, 155, 38, 50, 60, 40, 152, 103, 30, 142, 47, 246, 58, 114, 1, 31, 77, 81, 31, 99, 120, 155, 61, 78, 226, 161, 46, 98, 184, 10, 71, 243, 251, 28, 220, 230, 66, 119, 225, 226, 157, 198, 208, 59, 185, 118, 78, 214, 49, 183, 34, 11, 70, 1, 244, 50, 197, 98, 155, 210, 178, 84, 129, 81, 102, 107, 159, 165, 232, 215, 5, 249, 194, 5, 56, 189, 143, 108, 13, 24, 122, 118, 43, 86, 99, 134, 43, 50, 252, 161, 188, 197, 74, 140, 194, 154, 215, 10, 155, 237, 84, 215, 119, 168, 24, 203, 170, 45, 59, 110, 111, 99, 32, 178, 114, 24, 17, 149, 127, 102, 151, 159, 223, 241, 190, 25, 115, 188, 195, 237, 88, 193, 169, 42, 89, 84, 168, 195, 214, 202, 99, 126, 230, 63, 42, 247, 45, 37, 159, 203, 126, 100, 22, 75, 28, 203, 194, 190, 239, 4, 9, 208, 193, 239, 36, 240, 254, 19, 204, 181, 117, 184, 220, 148, 233, 53, 102, 185, 217, 105, 215, 201, 124, 46, 212, 28, 234, 136, 229, 78, 192, 90, 65, 168, 105, 149, 249, 52, 5, 208, 177, 213, 76, 136, 0, 78, 169, 102, 170, 124, 172, 76, 200, 245, 245, 79, 54, 83, 62, 79, 39, 183, 111, 221, 16, 89, 136, 158, 167, 147, 219, 225, 8, 108, 237, 59, 99, 78, 224, 22, 62, 147, 115, 73, 111, 237, 56, 105, 225, 7, 116, 22, 28, 224, 119, 147, 30, 101, 2, 104, 113, 223, 155, 224, 173, 240, 226, 227, 48, 27, 206, 6, 217, 157, 225, 187, 82, 118, 231, 83, 176, 30, 83, 139, 16, 111, 217, 112, 227, 132, 219, 15, 158, 64, 196, 24, 237, 240, 35, 29, 12, 102, 231, 179, 17, 102, 25, 111, 205, 219, 130, 129, 214, 214, 94, 51, 37, 230, 179, 38, 135, 93, 115, 137, 169, 159, 1, 204, 187, 190, 148, 192, 210, 175, 36, 19, 235, 133, 136, 121, 201, 103, 40, 228, 94, 82, 59, 162, 16, 21, 111, 30, 230, 167, 239, 166, 183, 135, 65, 177, 207, 115, 56, 237, 74, 219, 205, 79, 150, 74, 109, 249, 220, 75, 38, 241, 171, 241, 240, 250, 58, 231, 97, 111, 34, 190, 93, 44, 252, 30, 14, 120, 117, 111, 194, 186, 183, 227, 161, 245, 41, 86, 186, 231, 249, 112, 56, 202, 168, 81, 119, 50, 42, 10, 121, 105, 83, 242, 87, 204, 3, 102, 230, 212, 81, 113, 33, 183, 131, 197, 128, 171, 71, 56, 22, 160, 32, 224, 27, 62, 201, 206, 68, 95, 75, 195, 124, 170, 202, 186, 190, 182, 194, 0, 180, 187, 23, 242, 39, 9, 73, 145, 245, 237, 103, 249, 19, 63, 235, 194, 16, 207, 97, 74, 233, 79, 170, 32, 52, 108, 224, 59, 172, 17, 219, 243, 61, 10, 94, 151, 211, 230, 124, 25, 231, 146, 131, 165, 177, 200, 193, 28, 193, 33, 18, 251, 118, 92, 227, 234, 219, 26, 22, 249, 18, 110, 177, 204, 112, 11, 185, 139, 141, 151, 61, 248, 215, 213, 9, 241, 56, 163, 55, 100, 180, 223, 59, 102, 247, 224, 168, 6, 30, 39, 155, 84, 26, 229, 149, 62, 67, 6, 240, 167, 124, 122, 145, 87, 153, 226, 122, 1, 101, 87, 90, 184, 22, 22, 178, 186, 170, 105, 23, 80, 117, 209, 24, 1, 70, 50, 145, 241, 118, 59, 27, 95, 224, 153, 64, 19, 178, 65, 35, 236, 119, 143, 199, 106, 95, 221, 26, 78, 240, 47, 120, 98, 108, 55, 38, 206, 197, 249, 221, 49, 158, 43, 209, 153, 187, 180, 215, 243, 169, 98, 17, 107, 66, 17, 237, 245, 46, 14, 67, 97, 140, 98, 219, 245, 27, 240, 89, 120, 1, 247, 170, 120, 86, 8, 100, 51, 244, 97, 142, 228, 143, 138, 70, 33, 246, 146, 98, 2, 149, 216, 75, 203, 168, 41, 134, 201, 183, 101, 214, 212, 196, 168, 183, 103, 88, 91, 167, 189, 239, 250, 36, 47, 171, 233, 19, 227, 193, 149, 32, 180, 147, 24, 106, 5, 29, 197, 18, 92, 104, 60, 41, 180, 141, 41, 163, 89, 143, 53, 37, 111, 250, 213, 176, 137, 131, 30, 92, 242, 81, 239, 179, 195, 120, 218, 185, 156, 226, 117, 77, 70, 53, 101, 31, 188, 30, 209, 128, 10, 246, 61, 156, 47, 115, 32, 250, 149, 143, 41, 83, 33, 57, 244, 159, 67, 118, 39, 74, 136, 20, 164, 21, 143, 18, 228, 219, 170, 107, 237, 198, 220, 214, 71, 179, 183, 178, 43, 221, 183, 217, 105, 62, 118, 172, 154, 54, 55, 80, 221, 139, 30, 212, 90, 166, 249, 171, 176, 171, 55, 111, 176, 39, 129, 248, 215, 54, 145, 138, 250, 244, 88, 155, 128, 71, 50, 69, 242, 163, 103, 230, 104, 96, 57, 120, 166, 239, 15, 109, 246, 126, 234, 218, 88, 243, 39, 19, 231, 207, 155, 50, 175, 89, 5, 109, 70, 252, 4, 20, 98, 246, 151, 164, 153, 41, 39, 127, 225, 150, 52, 179, 103, 84, 197, 168, 69, 99, 187, 178, 198, 171, 52, 91, 54, 88, 204, 64, 48, 184, 224, 94, 141, 78, 230, 106, 99, 182, 237, 123, 214, 71, 137, 59, 35, 11, 39, 211, 26, 237, 221, 95, 40, 120, 61, 162, 190, 225, 39, 150, 205, 100, 179, 187, 218, 157, 77, 245, 213, 79, 1, 30, 174, 49, 178, 2, 231, 70, 224, 31, 164, 104, 213, 188, 75, 142, 32, 37, 110, 95, 124, 102, 109, 182, 88, 237, 144, 196, 236, 214, 12, 227, 92, 230, 49, 93, 67, 3, 221, 222, 128, 245, 7, 121, 156, 93, 24, 25, 112, 175, 205, 85, 200, 173, 147, 97, 115, 110, 203, 171, 33, 56, 165, 179, 161, 50, 59, 230, 197, 41, 172, 94, 26, 108, 86, 226, 167, 150, 119, 167, 234, 210, 183, 155, 162, 0, 9, 15, 229, 145, 40, 141, 93, 215, 235, 212, 112, 54, 182, 102, 73, 23, 82, 42, 58, 132, 197, 114, 25, 191, 155, 206, 196, 63, 240, 10, 110, 44, 4, 251, 42, 49, 13, 199, 69, 248, 229, 86, 72, 148, 132, 60, 58, 16, 142, 202, 96, 214, 37, 153, 245, 68, 159, 228, 28, 221, 214, 82, 219, 157, 134, 237, 52, 8, 28, 131, 93, 187, 91, 19, 125, 216, 34, 202, 21, 250, 115, 11, 35, 93, 181, 171, 50, 228, 92, 188, 133, 225, 174, 48, 10, 245, 60, 247, 191, 33, 236, 213, 244, 243, 182, 134, 190, 214, 113, 229, 205, 138, 127, 53, 164, 166, 92, 247, 149, 45, 35, 57, 252, 243, 71, 178, 244, 87, 195, 215, 147, 184, 136, 10, 29, 167, 242, 63, 117, 98, 241, 153, 131, 209, 108, 40, 58, 116, 7, 3, 52, 85, 207, 62, 103, 8, 137, 151, 83, 168, 49, 72, 243, 83, 69, 77, 18, 223, 33, 49, 23, 160, 238, 145, 224, 35, 201, 59, 176, 16, 115, 217, 2, 228, 207, 151, 60, 238, 8, 74, 192, 91, 224, 24, 26, 198, 35, 20, 90, 98, 203, 139, 108, 101, 86, 186, 170, 152, 149, 3, 33, 239, 231, 233, 228, 100, 204, 221, 60, 181, 23, 76, 237, 249, 86, 40, 61, 92, 190, 23, 85, 135, 15, 204, 197, 90, 123, 76, 249, 65, 92, 130, 188, 75, 85, 193, 83, 248, 220, 11, 121, 45, 92, 21, 44, 139, 18, 18, 53, 41, 224, 62, 246, 150, 223, 3, 139, 237, 39, 246, 14, 101, 54, 232, 246, 179, 199, 97, 175, 144, 20, 2, 182, 230, 167, 89, 69, 110, 19, 134, 213, 134, 164, 114, 32, 45, 143, 185, 73, 220, 230, 229, 225, 117, 239, 185, 75, 68, 255, 51, 117, 8, 184, 180, 97, 165, 227, 52, 250, 190, 239, 79, 82, 10, 103, 78, 36, 9, 94, 147, 194, 73, 10, 197, 135, 95, 125, 69, 205, 165, 65, 153, 230, 1, 14, 62, 38, 46, 177, 68, 143, 60, 157, 42, 160, 153, 226, 76, 249, 33, 100, 250, 157, 41, 238, 151, 122, 82, 63, 152, 76, 243, 115, 181, 44, 238, 234, 213, 35, 245, 222, 71, 148, 20, 194, 223, 54, 229, 106, 148, 83, 176, 236, 20, 38, 62, 200, 222, 152, 212, 100, 14, 217, 235, 37, 123, 118, 199, 5, 21, 109, 11, 143, 52, 234, 108, 221, 132, 10, 240, 65, 94, 59, 123, 109, 97, 125, 52, 79, 90, 125, 232, 42, 186, 204, 199, 150, 3, 19, 29, 147, 151, 233, 224, 108, 233, 131, 50, 39, 1, 85, 187, 244, 146, 108, 100, 118, 50, 67, 229, 50, 157, 37, 197, 214, 52, 96, 88, 126, 187, 37, 185, 156, 228, 182, 224, 16, 223, 199, 123, 255, 94, 21, 242, 28, 168, 214, 174, 92, 12, 173, 7, 87, 113, 146, 170, 77, 174, 135, 55, 114, 28, 147, 46, 75, 164, 64, 134, 173, 61, 39, 195, 214, 22, 151, 97, 151, 168, 164, 141, 112, 34, 22, 172, 221, 142, 33, 217, 130, 71, 117, 140, 176, 162, 31, 201, 134, 202, 196, 80, 252, 199, 160, 187, 93, 234, 107, 126, 188, 117, 213, 84, 121, 200, 22, 65, 158, 60, 56, 1, 111, 78, 120, 45, 27, 90, 173, 209, 165, 215, 246, 89, 126, 166, 206, 245, 115, 37, 230, 88, 40, 218, 69, 103, 170, 80, 246, 107, 63, 56, 139, 13, 202, 220, 187, 86, 6, 75, 182, 123, 85, 55, 34, 115, 143, 7, 31, 141, 250, 177, 160, 169, 52, 236, 56, 212, 152, 44, 7, 39, 93, 178, 218, 84, 67, 224, 173, 149, 52, 61, 151, 110, 162, 140, 179, 139, 101, 143, 142, 2, 169, 136, 67, 23, 119, 103, 238, 110, 137, 42, 200, 136, 67, 102, 201, 57, 111, 84, 244, 42, 214, 92, 172, 104, 115, 136, 114, 213, 6, 215, 234, 137, 122, 231, 114, 29, 161, 218, 53, 230, 116, 110, 45, 159, 32, 247, 200, 58, 61, 121, 197, 95, 181, 74, 134, 7, 37, 45, 119, 237, 21, 215, 90, 185, 239, 12, 203, 7, 204, 112, 44, 218, 211, 117, 89, 102, 127, 163, 158, 143, 95, 27, 20, 181, 129, 30, 73, 140, 62, 86, 23, 5, 196, 54, 188, 158, 219, 46, 80, 157, 206, 251, 225, 164, 161, 117, 123, 1, 247, 203, 65, 145, 142, 103, 98, 193, 219, 141, 134, 156, 234, 63, 75, 147, 240, 231, 116, 154, 190, 196, 20, 136, 38, 237, 112, 190, 182, 166, 182, 222, 54, 120, 46, 18, 228, 11, 85, 140, 177, 18, 49, 121, 22, 143, 40, 162, 25, 171, 249, 18, 124, 238, 156, 213, 164, 122, 155, 133, 106, 44, 210, 200, 237, 86, 192, 151, 227, 37, 0, 57, 136, 113, 29, 205, 253, 65, 181, 143, 105, 2, 28, 252, 11, 7, 35, 201, 61, 227, 47, 1, 73, 45, 3, 146, 212, 222, 73, 44, 34, 73, 210, 146, 70, 37, 97, 94, 215, 64, 18, 180, 131, 94, 236, 46, 51, 50, 176, 157, 85, 218, 240, 155, 58, 67, 84, 165, 19, 84, 255, 87, 72, 154, 170, 121, 133, 44, 76, 215, 144, 8, 243, 39, 76, 0, 140, 73, 149, 205, 155, 176, 64, 1, 18, 171, 171, 193, 181, 159, 199, 206, 6, 84, 92, 17, 217, 92, 160, 31, 221, 85, 47, 69, 4, 90, 101, 90, 14, 187, 227, 96, 214, 220, 218, 3, 174, 239, 8, 89, 172, 87, 131, 172, 67, 226, 135, 181, 154, 181, 4, 233, 1, 57, 131, 229, 18, 233, 149, 208, 37, 230, 8, 150, 82, 17, 45, 105, 181, 162, 245, 181, 33, 147, 24, 147, 131, 168, 2, 249, 150, 41, 144, 116, 48, 157, 165, 163, 103, 33, 231, 119, 88, 171, 88, 234, 106, 78, 177, 32, 118, 52, 187, 197, 218, 254, 78, 51, 100, 207, 54, 188, 36, 77, 56, 152, 149, 165, 16, 130, 103, 141, 10, 17, 154, 81, 138, 110, 135, 84, 162, 211, 174, 31, 105, 8, 167, 171, 16, 111, 210, 14, 10, 185, 62, 218, 98, 219, 132, 139, 123, 96, 82, 180, 196, 146, 219, 78, 7, 61, 173, 21, 100, 11, 61, 203, 118, 1, 67, 75, 75, 99, 77, 2, 117, 96, 25, 110, 109, 121, 228, 243, 19, 112, 127, 69, 231, 163, 249, 44, 54, 191, 102, 27, 147, 237, 171, 163, 119, 105, 201, 184, 105, 222, 171, 183, 35, 245, 219, 52, 238, 215, 93, 138, 101, 225, 129, 93, 232, 78, 12, 23, 200, 85, 172, 140, 112, 71, 3, 65, 63, 202, 98, 240, 138, 127, 177, 27, 238, 146, 221, 224, 13, 239, 245, 91, 15, 232, 189, 208, 166, 131, 90, 163, 70, 197, 5, 173, 7, 87, 98, 248, 164, 30, 173, 22, 153, 23, 191, 219, 108, 51, 171, 27, 228, 180, 45, 65, 38, 208, 3, 188, 90, 252, 0, 4, 222, 107, 190, 122, 158, 157, 23, 229, 37, 236, 148, 96, 97, 186, 33, 233, 33, 211, 122, 162, 173, 19, 70, 213, 206, 252, 115, 237, 119, 155, 181, 115, 173, 215, 36, 157, 178, 100, 199, 216, 124, 165, 1, 241, 9, 43, 238, 21, 112, 125, 19, 64, 50, 120, 23, 201, 223, 44, 7, 198, 240, 187, 101, 100, 65, 170, 104, 246, 255, 57, 211, 57, 135, 18, 193, 71, 80, 126, 85, 224, 81, 162, 225, 77, 59, 226, 100, 49, 251, 20, 167, 156, 248, 49, 10, 103, 32, 23, 56, 61, 12, 219, 158, 38, 38, 224, 140, 159, 105, 130, 111, 54, 66, 5, 126, 161, 107, 16, 15, 12, 155, 239, 142, 161, 20, 59, 195, 0, 35, 175, 130, 178, 244, 221, 65, 55, 96, 36, 89, 180, 26, 203, 97, 219, 225, 152, 127, 138, 209, 109, 27, 203, 166, 116, 135, 9, 61, 171, 143, 106, 35, 133, 27, 227, 219, 120, 217, 154, 72, 55, 201, 90, 55, 43, 153, 46, 91, 108, 52, 71, 50, 43, 36, 141, 150, 179, 138, 92, 245, 30, 131, 248, 232, 43, 65, 84, 127, 109, 34, 85, 252, 97, 58, 62, 53, 75, 32, 126, 100, 245, 58, 4, 86, 11, 229, 153, 36, 38, 69, 241, 71, 36, 212, 67, 18, 82, 182, 160, 180, 10, 11, 161, 40, 167, 66, 223, 194, 230, 175, 152, 152, 78, 198, 86, 92, 205, 171, 118, 251, 240, 22, 66, 251, 189, 120, 56, 210, 99, 171, 241, 149, 245, 167, 9, 40, 91, 246, 232, 225, 56, 232, 129, 161, 167, 163, 73, 42, 26, 239, 58, 50, 219, 252, 155, 170, 0, 75, 123, 151, 82, 166, 118, 48, 255, 157, 165, 103, 207, 211, 9, 153, 174, 97, 155, 83, 121, 209, 197, 184, 216, 101, 214, 121, 58, 113, 84, 85, 58, 28, 74, 223, 142, 248, 2, 151, 189, 145, 245, 151, 25, 85, 89, 164, 46, 184, 13, 183, 74, 84, 57, 141, 40, 187, 195, 109, 127, 154, 157, 135, 174, 112, 179, 40, 58, 44, 69, 252, 231, 80, 55, 206, 79, 15, 190, 21, 43, 81, 236, 63, 119, 163, 135, 28, 247, 18, 69, 25, 252, 209, 51, 120, 29, 111, 190, 38, 63, 250, 175, 177, 7, 14, 121, 229, 141, 192, 77, 228, 85, 231, 0, 66, 228, 21, 95, 54, 196, 243, 53, 145, 55, 122, 69, 158, 79, 223, 26, 170, 200, 27, 42, 248, 21, 192, 130, 12, 255, 31, 131, 81, 3, 173 }; + static const unsigned char data[] = { 120, 156, 237, 125, 255, 83, 27, 71, 178, 248, 239, 252, 21, 139, 42, 47, 17, 135, 224, 33, 236, 228, 114, 198, 118, 142, 16, 59, 71, 157, 99, 92, 224, 187, 171, 122, 124, 92, 126, 107, 105, 129, 61, 132, 86, 217, 149, 140, 73, 226, 247, 183, 127, 166, 123, 190, 117, 207, 151, 221, 149, 16, 54, 112, 118, 85, 194, 106, 119, 166, 167, 167, 167, 187, 167, 167, 167, 167, 231, 100, 54, 30, 76, 243, 98, 156, 140, 179, 203, 183, 135, 217, 160, 40, 135, 221, 181, 228, 247, 149, 36, 41, 179, 233, 172, 28, 39, 213, 116, 248, 246, 224, 221, 191, 179, 193, 244, 237, 160, 204, 210, 105, 214, 29, 207, 70, 163, 181, 157, 149, 143, 43, 39, 186, 238, 235, 226, 199, 162, 24, 101, 233, 184, 251, 158, 213, 93, 93, 125, 239, 148, 123, 57, 187, 120, 151, 149, 78, 177, 117, 94, 234, 40, 189, 200, 254, 153, 142, 102, 217, 255, 100, 101, 209, 253, 208, 75, 174, 88, 233, 15, 201, 147, 39, 79, 146, 171, 228, 143, 63, 146, 238, 135, 100, 85, 60, 127, 72, 190, 254, 90, 188, 128, 199, 43, 142, 216, 207, 217, 244, 151, 108, 122, 86, 12, 187, 255, 236, 37, 175, 36, 152, 157, 29, 241, 191, 247, 105, 153, 64, 169, 228, 73, 242, 207, 227, 87, 111, 224, 85, 126, 146, 116, 247, 171, 151, 162, 115, 7, 229, 63, 198, 195, 236, 36, 31, 103, 195, 46, 20, 90, 147, 21, 13, 6, 51, 253, 21, 170, 125, 84, 85, 87, 247, 171, 189, 116, 52, 74, 223, 141, 50, 94, 233, 245, 89, 89, 92, 190, 190, 154, 100, 207, 202, 178, 40, 187, 253, 237, 94, 50, 21, 191, 138, 19, 68, 96, 77, 195, 80, 176, 225, 29, 235, 194, 126, 245, 170, 44, 38, 89, 57, 189, 250, 123, 118, 213, 77, 203, 211, 217, 69, 54, 158, 74, 224, 208, 11, 128, 37, 122, 161, 64, 234, 239, 59, 22, 162, 44, 32, 104, 211, 169, 166, 101, 62, 62, 237, 0, 229, 200, 203, 171, 139, 119, 197, 168, 195, 71, 96, 146, 13, 242, 172, 218, 43, 198, 162, 202, 108, 48, 21, 104, 23, 239, 254, 221, 75, 68, 183, 211, 217, 104, 74, 222, 59, 36, 133, 87, 2, 25, 81, 120, 115, 96, 11, 105, 234, 202, 175, 162, 81, 67, 64, 135, 176, 62, 124, 135, 194, 146, 17, 17, 80, 140, 190, 223, 126, 215, 75, 58, 5, 150, 251, 166, 74, 190, 33, 104, 124, 147, 76, 20, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 156, 229, 163, 105, 62, 62, 66, 162, 116, 59, 149, 36, 68, 103, 173, 134, 67, 42, 151, 61, 234, 123, 177, 207, 200, 234, 85, 174, 116, 89, 167, 91, 88, 166, 255, 176, 135, 127, 59, 127, 253, 171, 194, 204, 116, 41, 17, 131, 111, 122, 77, 58, 221, 17, 21, 60, 153, 176, 96, 55, 55, 55, 5, 203, 84, 18, 137, 105, 121, 165, 144, 25, 8, 78, 126, 174, 42, 116, 65, 3, 232, 31, 111, 211, 201, 100, 116, 213, 115, 176, 235, 217, 17, 237, 37, 8, 15, 123, 33, 192, 76, 7, 103, 73, 55, 115, 250, 152, 233, 62, 238, 184, 136, 237, 158, 158, 150, 217, 169, 80, 50, 75, 192, 142, 195, 90, 26, 138, 251, 227, 105, 86, 142, 211, 209, 18, 48, 100, 160, 150, 131, 32, 48, 167, 105, 88, 84, 33, 159, 246, 138, 201, 213, 79, 233, 52, 85, 234, 68, 48, 79, 119, 42, 218, 201, 166, 189, 164, 42, 102, 229, 32, 235, 37, 217, 135, 193, 104, 54, 204, 134, 251, 211, 236, 162, 34, 162, 189, 83, 195, 253, 88, 213, 225, 98, 42, 93, 39, 101, 113, 33, 4, 236, 117, 161, 100, 87, 85, 208, 26, 227, 60, 187, 2, 249, 243, 145, 59, 40, 5, 177, 15, 46, 199, 66, 235, 89, 68, 1, 152, 139, 166, 198, 77, 66, 18, 218, 5, 231, 167, 32, 62, 39, 66, 255, 116, 161, 213, 92, 224, 47, 230, 145, 100, 107, 71, 61, 62, 70, 68, 54, 71, 217, 248, 116, 122, 166, 94, 174, 175, 107, 40, 10, 81, 81, 1, 74, 29, 227, 87, 212, 8, 178, 101, 124, 72, 146, 213, 179, 180, 18, 8, 3, 34, 30, 41, 191, 254, 90, 21, 242, 56, 67, 205, 173, 90, 142, 247, 171, 103, 99, 161, 193, 75, 152, 71, 116, 127, 5, 192, 53, 172, 174, 241, 73, 146, 159, 144, 252, 132, 98, 87, 134, 70, 216, 60, 84, 60, 22, 79, 111, 214, 36, 154, 31, 145, 2, 181, 220, 240, 143, 241, 137, 208, 125, 89, 41, 6, 149, 243, 5, 97, 132, 219, 195, 3, 202, 8, 249, 220, 67, 191, 232, 112, 46, 113, 36, 139, 153, 24, 52, 110, 179, 153, 111, 249, 120, 108, 190, 153, 175, 157, 147, 162, 232, 32, 93, 152, 234, 216, 45, 203, 244, 234, 217, 251, 172, 188, 194, 94, 189, 75, 7, 231, 39, 227, 196, 26, 26, 7, 116, 4, 167, 103, 121, 101, 198, 79, 144, 14, 191, 189, 64, 18, 118, 15, 20, 45, 205, 240, 236, 42, 163, 164, 82, 5, 214, 112, 172, 182, 98, 19, 248, 183, 189, 100, 75, 204, 225, 136, 207, 166, 32, 228, 180, 0, 107, 101, 51, 3, 212, 236, 204, 237, 218, 92, 22, 231, 58, 203, 235, 39, 97, 225, 94, 76, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 69, 135, 124, 180, 159, 38, 253, 228, 7, 156, 167, 212, 167, 110, 127, 45, 121, 196, 237, 65, 195, 104, 231, 146, 201, 206, 5, 131, 9, 122, 136, 7, 203, 84, 200, 179, 98, 112, 146, 3, 203, 7, 216, 31, 64, 71, 152, 7, 83, 1, 218, 112, 149, 69, 81, 76, 27, 189, 228, 224, 248, 252, 141, 96, 13, 241, 64, 152, 200, 142, 124, 58, 170, 178, 29, 245, 246, 35, 97, 24, 107, 14, 150, 179, 12, 198, 253, 72, 76, 101, 213, 254, 120, 148, 143, 129, 124, 47, 128, 229, 76, 147, 150, 21, 4, 81, 56, 131, 28, 21, 23, 217, 237, 228, 143, 74, 96, 118, 191, 217, 227, 218, 220, 33, 199, 190, 134, 57, 20, 251, 180, 224, 14, 224, 3, 143, 57, 158, 23, 229, 179, 116, 112, 118, 59, 249, 227, 68, 34, 119, 127, 89, 100, 62, 246, 216, 9, 141, 63, 193, 163, 5, 15, 168, 225, 246, 216, 224, 151, 116, 114, 59, 89, 224, 34, 157, 220, 254, 225, 135, 218, 187, 96, 14, 165, 227, 131, 201, 52, 191, 200, 127, 203, 164, 196, 201, 21, 95, 87, 140, 248, 15, 232, 149, 193, 183, 93, 65, 40, 0, 65, 139, 236, 73, 63, 205, 65, 15, 200, 186, 118, 29, 150, 130, 42, 130, 104, 147, 108, 136, 14, 25, 88, 40, 47, 192, 100, 65, 35, 103, 23, 139, 16, 224, 97, 142, 220, 109, 197, 137, 130, 227, 124, 101, 132, 214, 236, 237, 100, 68, 105, 105, 223, 19, 94, 60, 126, 19, 229, 191, 173, 0, 247, 245, 146, 105, 49, 63, 23, 158, 107, 6, 4, 238, 210, 108, 213, 114, 82, 148, 117, 3, 211, 98, 152, 45, 167, 197, 250, 186, 174, 100, 56, 56, 56, 93, 182, 99, 78, 201, 136, 30, 127, 30, 102, 195, 217, 224, 150, 218, 82, 37, 226, 246, 169, 248, 83, 42, 37, 245, 35, 29, 12, 102, 23, 179, 81, 74, 252, 134, 65, 222, 213, 237, 146, 242, 2, 12, 103, 103, 233, 65, 201, 132, 77, 67, 184, 11, 41, 72, 105, 146, 36, 83, 192, 221, 163, 205, 54, 209, 72, 10, 209, 87, 101, 86, 9, 208, 162, 33, 98, 104, 15, 11, 102, 165, 185, 220, 155, 208, 106, 212, 2, 75, 146, 119, 66, 80, 206, 29, 14, 75, 46, 207, 4, 197, 146, 238, 250, 186, 18, 143, 53, 187, 218, 92, 213, 144, 230, 67, 157, 147, 72, 8, 208, 250, 250, 27, 182, 46, 110, 47, 138, 28, 84, 72, 246, 76, 231, 136, 16, 154, 119, 214, 197, 101, 94, 17, 136, 246, 37, 78, 33, 150, 126, 228, 131, 122, 10, 79, 22, 140, 119, 220, 165, 173, 148, 183, 195, 252, 244, 108, 250, 69, 232, 164, 208, 65, 191, 54, 146, 254, 23, 209, 227, 162, 183, 177, 113, 158, 60, 125, 162, 38, 175, 229, 74, 222, 198, 134, 47, 121, 79, 229, 100, 184, 177, 113, 79, 5, 239, 121, 62, 30, 118, 39, 130, 187, 243, 129, 48, 11, 110, 145, 192, 9, 130, 12, 227, 226, 102, 48, 158, 71, 218, 72, 165, 79, 183, 24, 140, 216, 71, 49, 235, 200, 224, 88, 103, 28, 169, 129, 149, 95, 151, 177, 86, 20, 180, 14, 152, 232, 227, 225, 62, 120, 84, 191, 176, 199, 13, 251, 10, 154, 249, 32, 232, 57, 210, 92, 16, 100, 128, 141, 126, 235, 145, 199, 65, 246, 134, 31, 28, 254, 255, 202, 197, 200, 142, 237, 142, 131, 120, 16, 127, 178, 241, 48, 241, 182, 137, 23, 231, 9, 248, 94, 102, 66, 61, 229, 239, 179, 215, 216, 18, 22, 133, 253, 183, 83, 177, 68, 148, 141, 155, 146, 176, 60, 89, 145, 189, 103, 85, 30, 39, 91, 138, 44, 114, 253, 253, 75, 58, 61, 123, 123, 145, 126, 192, 105, 109, 221, 41, 13, 107, 31, 85, 250, 17, 41, 45, 186, 234, 150, 211, 38, 30, 69, 242, 8, 200, 192, 112, 68, 194, 152, 114, 114, 67, 133, 33, 41, 171, 180, 196, 241, 72, 146, 185, 9, 69, 85, 44, 132, 225, 51, 28, 33, 28, 39, 186, 161, 47, 154, 133, 150, 30, 17, 204, 51, 20, 124, 133, 183, 224, 146, 145, 131, 56, 64, 106, 137, 182, 40, 218, 140, 52, 22, 162, 40, 15, 138, 25, 26, 0, 172, 180, 196, 100, 67, 109, 201, 72, 67, 104, 90, 24, 13, 130, 4, 126, 12, 172, 240, 245, 215, 240, 255, 199, 146, 228, 235, 18, 152, 22, 16, 181, 175, 69, 63, 105, 123, 42, 145, 171, 92, 241, 63, 239, 131, 178, 50, 228, 219, 167, 212, 24, 50, 45, 187, 102, 204, 193, 241, 180, 120, 131, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 98, 113, 110, 220, 72, 100, 55, 54, 244, 219, 105, 97, 159, 17, 19, 253, 243, 163, 107, 184, 125, 70, 116, 215, 215, 45, 186, 246, 217, 71, 215, 234, 164, 131, 144, 249, 49, 26, 9, 21, 137, 147, 92, 165, 228, 106, 235, 70, 85, 76, 147, 244, 158, 127, 17, 221, 22, 162, 75, 86, 166, 216, 54, 155, 211, 96, 182, 18, 157, 120, 175, 173, 147, 40, 11, 72, 95, 20, 50, 194, 254, 52, 43, 83, 19, 203, 116, 14, 6, 137, 25, 244, 28, 191, 101, 67, 57, 236, 148, 3, 68, 97, 67, 131, 92, 65, 16, 223, 95, 102, 151, 28, 40, 22, 250, 199, 184, 74, 79, 50, 49, 37, 30, 138, 197, 66, 249, 62, 27, 30, 141, 138, 105, 87, 87, 67, 51, 131, 183, 212, 170, 86, 95, 59, 210, 154, 10, 110, 171, 110, 237, 88, 106, 232, 143, 190, 92, 104, 204, 95, 102, 31, 166, 93, 75, 9, 209, 95, 208, 91, 130, 239, 181, 46, 180, 113, 87, 64, 11, 140, 187, 147, 133, 126, 158, 165, 229, 240, 117, 225, 17, 119, 109, 45, 178, 25, 207, 163, 31, 20, 47, 128, 69, 197, 64, 200, 136, 189, 253, 147, 127, 149, 232, 28, 214, 107, 16, 64, 73, 63, 119, 188, 30, 116, 240, 11, 179, 170, 82, 129, 162, 164, 216, 207, 14, 197, 144, 1, 182, 136, 96, 84, 179, 17, 12, 250, 239, 146, 161, 30, 209, 80, 156, 97, 49, 22, 47, 112, 205, 9, 27, 230, 146, 36, 105, 160, 131, 0, 99, 19, 74, 179, 181, 166, 234, 184, 252, 76, 177, 211, 113, 8, 53, 24, 246, 41, 227, 93, 252, 61, 71, 185, 53, 229, 133, 144, 62, 216, 126, 46, 180, 164, 95, 113, 155, 170, 44, 141, 243, 126, 245, 170, 168, 170, 252, 221, 232, 74, 17, 22, 76, 213, 161, 220, 68, 72, 141, 205, 39, 117, 92, 180, 164, 82, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 111, 105, 245, 83, 54, 77, 7, 103, 217, 240, 199, 217, 201, 137, 80, 51, 41, 115, 202, 58, 102, 244, 119, 91, 122, 73, 205, 156, 176, 116, 42, 113, 244, 114, 74, 245, 178, 54, 221, 37, 185, 159, 162, 207, 67, 183, 22, 22, 39, 201, 28, 36, 194, 100, 206, 193, 173, 129, 42, 4, 89, 226, 177, 174, 198, 22, 49, 51, 99, 43, 136, 216, 119, 248, 233, 189, 90, 213, 165, 44, 242, 36, 216, 174, 7, 107, 155, 174, 15, 39, 105, 14, 106, 75, 130, 233, 25, 120, 111, 118, 66, 173, 65, 225, 154, 150, 118, 164, 126, 97, 85, 16, 28, 209, 59, 186, 70, 139, 5, 2, 21, 99, 186, 70, 248, 10, 191, 226, 2, 180, 226, 241, 45, 33, 165, 142, 234, 1, 201, 138, 77, 238, 165, 227, 98, 44, 86, 55, 163, 151, 233, 69, 214, 165, 160, 196, 74, 15, 145, 174, 58, 222, 130, 228, 217, 120, 90, 230, 237, 27, 219, 94, 243, 181, 42, 134, 42, 181, 172, 191, 21, 168, 15, 2, 189, 91, 93, 141, 7, 221, 20, 254, 143, 225, 99, 184, 77, 118, 50, 166, 230, 74, 15, 213, 161, 88, 24, 134, 109, 152, 61, 162, 194, 245, 122, 1, 161, 238, 141, 138, 106, 86, 34, 71, 193, 207, 4, 150, 198, 79, 9, 155, 192, 126, 92, 62, 6, 168, 178, 201, 85, 106, 33, 88, 153, 215, 197, 132, 113, 76, 215, 196, 88, 135, 8, 115, 96, 69, 252, 186, 56, 194, 224, 47, 93, 214, 245, 243, 205, 42, 1, 119, 87, 117, 93, 79, 182, 150, 20, 129, 24, 221, 148, 22, 86, 145, 186, 18, 203, 16, 44, 71, 109, 39, 225, 6, 157, 46, 59, 232, 29, 213, 22, 142, 180, 188, 26, 138, 123, 246, 221, 10, 126, 205, 58, 229, 248, 231, 62, 161, 168, 165, 210, 154, 171, 49, 185, 225, 29, 234, 68, 45, 137, 115, 151, 186, 164, 151, 71, 245, 228, 13, 183, 230, 144, 204, 90, 253, 97, 176, 17, 218, 69, 168, 119, 20, 35, 222, 252, 228, 179, 136, 125, 36, 140, 208, 102, 132, 193, 76, 106, 221, 17, 189, 205, 202, 99, 195, 247, 96, 115, 213, 132, 114, 187, 222, 155, 189, 94, 178, 7, 238, 160, 99, 51, 36, 108, 43, 13, 254, 129, 5, 157, 94, 166, 249, 84, 186, 136, 198, 66, 191, 74, 47, 33, 28, 20, 24, 141, 138, 75, 5, 19, 208, 3, 63, 140, 117, 33, 19, 221, 195, 199, 145, 245, 184, 23, 31, 99, 245, 133, 145, 223, 15, 38, 48, 24, 237, 176, 17, 85, 218, 133, 15, 93, 115, 24, 2, 106, 20, 163, 24, 123, 22, 186, 176, 138, 201, 136, 186, 160, 36, 133, 200, 59, 127, 240, 231, 10, 96, 128, 127, 48, 12, 231, 48, 203, 187, 252, 189, 171, 108, 19, 248, 174, 191, 217, 205, 100, 91, 18, 237, 87, 52, 184, 242, 243, 140, 46, 71, 8, 151, 238, 152, 146, 174, 1, 164, 43, 82, 67, 104, 113, 46, 147, 75, 50, 181, 102, 179, 65, 39, 22, 40, 97, 58, 229, 44, 208, 91, 151, 225, 45, 124, 73, 113, 131, 37, 217, 208, 247, 89, 68, 241, 130, 161, 236, 15, 170, 118, 27, 6, 48, 174, 237, 53, 83, 253, 17, 243, 104, 207, 57, 174, 206, 168, 202, 145, 34, 35, 170, 140, 109, 62, 162, 31, 137, 81, 228, 78, 195, 221, 136, 1, 128, 118, 220, 18, 166, 253, 198, 217, 188, 245, 92, 222, 228, 219, 238, 43, 100, 125, 191, 182, 66, 88, 163, 132, 154, 130, 204, 4, 121, 187, 41, 71, 41, 122, 55, 242, 156, 65, 51, 200, 6, 103, 133, 192, 140, 16, 152, 13, 92, 135, 125, 78, 231, 131, 143, 215, 18, 35, 170, 172, 29, 169, 49, 94, 252, 102, 21, 173, 56, 35, 214, 165, 54, 2, 84, 35, 58, 175, 29, 173, 73, 228, 198, 211, 213, 17, 209, 129, 216, 153, 112, 84, 87, 72, 251, 49, 73, 89, 169, 209, 123, 185, 81, 121, 109, 21, 94, 108, 156, 86, 20, 21, 154, 85, 222, 138, 236, 185, 175, 246, 230, 222, 148, 147, 92, 126, 78, 70, 191, 110, 144, 154, 134, 200, 211, 107, 92, 171, 181, 214, 105, 64, 112, 95, 125, 209, 216, 38, 174, 154, 132, 169, 132, 39, 8, 137, 183, 8, 41, 31, 117, 152, 170, 19, 150, 88, 104, 243, 223, 69, 62, 38, 162, 28, 62, 44, 25, 242, 19, 145, 99, 21, 83, 133, 65, 79, 194, 116, 15, 79, 134, 200, 6, 224, 109, 113, 191, 75, 47, 10, 81, 43, 83, 29, 27, 225, 15, 33, 95, 197, 4, 202, 208, 51, 80, 180, 183, 84, 199, 134, 88, 209, 221, 143, 244, 92, 36, 250, 36, 70, 135, 242, 253, 73, 94, 86, 211, 103, 163, 236, 66, 198, 43, 32, 164, 227, 173, 55, 186, 161, 67, 235, 200, 241, 14, 169, 146, 154, 134, 148, 135, 2, 134, 106, 128, 154, 255, 135, 136, 173, 234, 175, 226, 159, 32, 221, 8, 204, 205, 41, 35, 83, 143, 161, 170, 142, 38, 209, 158, 84, 217, 36, 213, 10, 190, 211, 235, 120, 34, 211, 143, 139, 12, 168, 25, 151, 6, 90, 110, 14, 147, 245, 39, 22, 182, 93, 109, 5, 38, 6, 2, 134, 104, 71, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 13, 93, 171, 230, 8, 63, 30, 50, 134, 251, 138, 133, 78, 50, 31, 129, 100, 168, 168, 227, 66, 213, 233, 37, 29, 216, 135, 60, 150, 115, 228, 166, 58, 2, 250, 198, 247, 99, 240, 56, 204, 162, 204, 79, 193, 129, 142, 159, 80, 179, 1, 111, 90, 206, 222, 33, 108, 138, 154, 64, 112, 234, 134, 97, 85, 163, 30, 182, 168, 163, 73, 144, 92, 170, 68, 6, 220, 59, 204, 74, 53, 39, 245, 200, 161, 163, 89, 213, 36, 218, 89, 180, 194, 224, 185, 135, 136, 181, 141, 19, 168, 106, 133, 195, 153, 149, 133, 89, 35, 222, 149, 69, 85, 29, 102, 233, 232, 66, 109, 60, 211, 34, 109, 145, 150, 224, 149, 158, 179, 213, 0, 161, 189, 198, 179, 195, 178, 250, 30, 18, 215, 150, 165, 136, 72, 159, 118, 199, 223, 125, 15, 34, 68, 215, 162, 123, 129, 117, 119, 115, 93, 221, 165, 189, 218, 35, 217, 181, 212, 88, 117, 169, 29, 51, 23, 31, 10, 214, 37, 99, 25, 56, 136, 173, 53, 120, 227, 172, 44, 113, 240, 172, 230, 81, 58, 133, 99, 7, 56, 197, 149, 186, 86, 171, 96, 18, 121, 24, 241, 69, 67, 72, 137, 99, 26, 147, 70, 230, 137, 255, 112, 107, 186, 198, 242, 231, 140, 210, 6, 18, 10, 146, 239, 143, 167, 114, 71, 7, 140, 134, 131, 158, 37, 15, 58, 197, 251, 110, 31, 132, 65, 66, 183, 155, 2, 86, 3, 192, 237, 46, 105, 36, 160, 212, 48, 155, 76, 207, 94, 206, 46, 112, 30, 89, 137, 5, 252, 8, 177, 167, 68, 19, 234, 44, 232, 123, 33, 192, 236, 182, 39, 175, 200, 6, 233, 19, 145, 89, 163, 21, 39, 173, 7, 70, 20, 84, 65, 52, 226, 73, 29, 232, 54, 79, 0, 23, 126, 224, 166, 240, 138, 234, 54, 60, 56, 131, 185, 146, 232, 245, 218, 138, 29, 48, 9, 118, 95, 237, 87, 33, 12, 54, 163, 203, 38, 244, 119, 97, 14, 211, 23, 143, 45, 6, 236, 3, 15, 79, 162, 53, 242, 49, 59, 119, 172, 13, 131, 204, 24, 5, 242, 235, 49, 169, 195, 188, 146, 142, 140, 17, 39, 210, 142, 117, 208, 88, 104, 181, 161, 148, 33, 2, 233, 127, 218, 205, 64, 94, 41, 168, 244, 21, 193, 210, 127, 109, 94, 56, 254, 90, 37, 14, 103, 197, 108, 52, 84, 3, 205, 227, 94, 101, 79, 113, 20, 121, 72, 70, 226, 213, 210, 19, 181, 194, 205, 107, 9, 201, 79, 235, 184, 46, 59, 85, 209, 17, 75, 245, 150, 123, 152, 144, 44, 140, 91, 66, 108, 202, 75, 54, 208, 207, 182, 222, 243, 170, 122, 84, 149, 4, 217, 72, 250, 1, 194, 186, 177, 39, 208, 111, 138, 43, 68, 225, 126, 232, 159, 208, 127, 181, 190, 227, 111, 255, 242, 109, 192, 77, 92, 123, 158, 155, 98, 157, 184, 227, 193, 58, 101, 131, 93, 194, 103, 120, 109, 73, 95, 223, 238, 78, 229, 102, 231, 50, 35, 90, 244, 112, 90, 29, 153, 171, 136, 62, 181, 208, 213, 138, 152, 87, 120, 74, 150, 60, 96, 247, 179, 175, 222, 202, 68, 71, 164, 175, 7, 202, 173, 232, 168, 232, 199, 201, 22, 184, 214, 207, 157, 173, 220, 88, 102, 30, 29, 19, 130, 107, 136, 22, 123, 145, 187, 83, 207, 152, 126, 93, 28, 194, 209, 243, 42, 27, 118, 151, 65, 210, 93, 21, 137, 182, 152, 71, 65, 69, 156, 201, 120, 181, 115, 27, 83, 166, 191, 217, 40, 96, 18, 121, 21, 117, 8, 152, 26, 174, 25, 22, 94, 252, 23, 229, 84, 16, 1, 44, 154, 180, 204, 78, 20, 237, 49, 186, 84, 191, 114, 246, 64, 28, 151, 162, 173, 25, 49, 153, 254, 204, 230, 218, 197, 105, 140, 238, 150, 133, 233, 28, 32, 151, 242, 186, 157, 203, 48, 89, 102, 3, 3, 46, 143, 217, 198, 189, 142, 187, 185, 168, 28, 170, 122, 94, 13, 196, 237, 109, 85, 64, 164, 150, 106, 194, 210, 40, 28, 72, 255, 34, 173, 166, 183, 54, 90, 26, 144, 251, 52, 17, 211, 214, 13, 190, 132, 184, 105, 125, 12, 38, 116, 22, 99, 241, 216, 122, 127, 27, 226, 230, 35, 236, 97, 0, 130, 81, 246, 240, 225, 118, 71, 218, 27, 12, 239, 25, 3, 205, 195, 41, 55, 26, 131, 111, 8, 204, 24, 4, 118, 163, 116, 89, 140, 4, 124, 159, 42, 47, 2, 182, 71, 214, 31, 16, 209, 115, 145, 253, 156, 141, 89, 12, 139, 40, 46, 6, 20, 60, 98, 29, 71, 99, 81, 200, 56, 78, 139, 129, 198, 99, 86, 33, 216, 122, 247, 99, 127, 40, 200, 154, 11, 37, 29, 244, 168, 241, 58, 166, 137, 229, 119, 213, 148, 190, 137, 190, 154, 226, 135, 8, 100, 49, 232, 178, 136, 4, 47, 163, 127, 194, 4, 133, 205, 201, 204, 68, 149, 202, 156, 144, 61, 25, 25, 233, 6, 204, 234, 45, 60, 82, 114, 211, 70, 156, 106, 27, 18, 154, 149, 65, 157, 164, 244, 166, 205, 207, 20, 241, 225, 210, 138, 107, 84, 31, 155, 120, 205, 248, 86, 48, 173, 219, 51, 109, 210, 3, 125, 198, 147, 39, 161, 197, 183, 5, 33, 161, 160, 171, 84, 116, 157, 160, 76, 170, 160, 100, 39, 109, 156, 66, 225, 167, 188, 52, 145, 180, 191, 175, 184, 184, 200, 224, 217, 176, 238, 12, 160, 129, 197, 169, 86, 3, 230, 52, 148, 134, 44, 140, 240, 34, 228, 194, 178, 5, 231, 209, 165, 180, 150, 99, 219, 40, 101, 167, 122, 249, 8, 26, 151, 43, 51, 91, 71, 254, 38, 241, 180, 240, 226, 163, 75, 40, 198, 138, 146, 90, 50, 132, 180, 92, 144, 104, 58, 128, 251, 134, 104, 68, 74, 5, 73, 210, 34, 98, 237, 81, 68, 16, 85, 234, 82, 111, 42, 208, 219, 79, 162, 53, 75, 227, 46, 17, 80, 82, 54, 182, 183, 161, 69, 3, 227, 82, 223, 211, 157, 90, 9, 82, 42, 136, 210, 168, 155, 153, 227, 142, 113, 164, 26, 232, 104, 5, 154, 8, 89, 43, 161, 110, 192, 151, 11, 179, 135, 177, 93, 125, 107, 194, 43, 38, 131, 64, 93, 85, 84, 134, 97, 168, 222, 125, 140, 79, 38, 127, 203, 70, 130, 211, 94, 58, 244, 212, 54, 82, 56, 42, 254, 64, 198, 196, 31, 144, 136, 120, 31, 100, 247, 96, 129, 168, 120, 31, 76, 139, 216, 120, 121, 212, 69, 253, 232, 68, 122, 23, 8, 151, 63, 213, 147, 70, 52, 40, 29, 235, 28, 72, 208, 112, 232, 131, 122, 39, 89, 31, 246, 33, 142, 118, 92, 229, 3, 127, 210, 237, 217, 118, 236, 40, 214, 143, 198, 161, 199, 132, 247, 107, 60, 100, 255, 62, 203, 136, 200, 166, 23, 24, 19, 99, 228, 220, 207, 33, 193, 238, 125, 150, 17, 193, 150, 231, 26, 16, 187, 237, 229, 31, 103, 74, 158, 4, 108, 15, 179, 192, 11, 239, 107, 205, 191, 159, 197, 109, 144, 156, 81, 82, 29, 149, 10, 140, 182, 89, 99, 82, 162, 186, 61, 179, 150, 172, 238, 146, 105, 20, 170, 47, 160, 117, 106, 14, 82, 49, 19, 70, 98, 169, 6, 82, 254, 49, 48, 156, 113, 229, 85, 124, 243, 250, 79, 243, 116, 203, 140, 225, 72, 172, 215, 140, 111, 64, 26, 46, 217, 16, 109, 115, 114, 6, 197, 166, 28, 190, 202, 179, 145, 10, 167, 166, 5, 201, 166, 1, 46, 89, 201, 20, 14, 102, 128, 49, 162, 217, 105, 48, 139, 148, 65, 194, 204, 181, 171, 80, 13, 143, 194, 232, 55, 243, 193, 145, 66, 197, 108, 9, 125, 134, 4, 33, 191, 167, 49, 102, 161, 46, 195, 63, 3, 78, 188, 199, 142, 199, 34, 166, 96, 8, 105, 248, 36, 183, 27, 34, 132, 146, 7, 140, 240, 208, 225, 72, 147, 23, 100, 197, 20, 183, 232, 71, 23, 78, 217, 144, 45, 14, 98, 194, 171, 146, 148, 169, 204, 187, 215, 150, 96, 3, 103, 14, 25, 182, 117, 110, 70, 138, 101, 23, 67, 28, 111, 90, 190, 179, 162, 220, 162, 111, 95, 228, 185, 133, 60, 227, 153, 202, 232, 98, 94, 211, 50, 32, 201, 116, 5, 225, 43, 5, 214, 246, 199, 0, 14, 159, 71, 232, 95, 167, 231, 89, 119, 148, 95, 228, 211, 121, 229, 93, 174, 188, 46, 210, 124, 44, 195, 186, 237, 126, 156, 4, 167, 117, 130, 45, 243, 216, 113, 198, 30, 166, 227, 83, 125, 178, 242, 47, 223, 223, 144, 200, 67, 7, 67, 66, 97, 208, 186, 187, 18, 223, 220, 181, 27, 22, 248, 29, 194, 0, 79, 193, 215, 108, 126, 90, 159, 243, 117, 244, 129, 228, 121, 165, 18, 2, 11, 244, 232, 209, 173, 101, 205, 228, 209, 106, 75, 23, 86, 162, 79, 194, 158, 188, 214, 117, 99, 146, 254, 83, 89, 76, 238, 181, 164, 67, 7, 239, 169, 164, 55, 119, 205, 12, 233, 173, 19, 236, 182, 210, 204, 101, 216, 158, 111, 97, 170, 235, 94, 89, 26, 159, 83, 223, 180, 50, 14, 118, 43, 220, 164, 203, 134, 175, 210, 188, 172, 186, 139, 232, 141, 229, 137, 55, 71, 198, 151, 134, 187, 43, 221, 141, 61, 91, 154, 112, 47, 93, 158, 122, 228, 14, 147, 37, 137, 86, 79, 95, 123, 114, 67, 50, 166, 211, 78, 96, 245, 55, 183, 71, 216, 120, 216, 248, 125, 243, 159, 169, 222, 221, 71, 31, 90, 115, 215, 150, 59, 57, 47, 54, 251, 46, 34, 150, 203, 153, 230, 236, 17, 195, 218, 109, 242, 70, 15, 153, 147, 66, 0, 239, 19, 138, 30, 80, 149, 224, 248, 182, 158, 148, 127, 91, 239, 115, 174, 198, 235, 130, 30, 84, 54, 118, 153, 131, 185, 76, 98, 170, 160, 102, 119, 58, 170, 22, 20, 204, 121, 244, 130, 169, 66, 21, 67, 171, 244, 204, 44, 137, 144, 199, 174, 33, 30, 208, 29, 196, 125, 112, 155, 159, 44, 24, 43, 1, 69, 230, 139, 148, 144, 53, 236, 56, 68, 77, 82, 23, 214, 3, 86, 137, 167, 63, 230, 114, 192, 130, 136, 27, 115, 82, 175, 120, 76, 253, 62, 202, 207, 134, 22, 107, 65, 232, 113, 154, 170, 62, 169, 97, 212, 59, 77, 94, 18, 230, 64, 10, 102, 68, 70, 170, 0, 141, 110, 56, 199, 114, 29, 51, 171, 156, 108, 97, 227, 241, 247, 118, 33, 9, 50, 51, 16, 48, 181, 220, 59, 167, 113, 181, 199, 230, 80, 42, 179, 68, 22, 167, 107, 60, 228, 86, 217, 37, 84, 47, 17, 154, 228, 50, 202, 182, 158, 26, 250, 86, 34, 29, 177, 188, 28, 169, 158, 47, 11, 59, 205, 140, 112, 13, 246, 139, 187, 72, 199, 17, 37, 222, 164, 247, 240, 62, 175, 187, 79, 153, 6, 7, 114, 136, 58, 126, 88, 77, 25, 137, 195, 53, 183, 98, 213, 17, 82, 222, 156, 119, 63, 40, 185, 58, 55, 45, 61, 98, 186, 115, 249, 138, 67, 230, 6, 145, 133, 148, 241, 247, 131, 150, 215, 229, 74, 98, 238, 121, 107, 25, 196, 63, 144, 149, 161, 41, 135, 103, 132, 16, 15, 122, 73, 7, 159, 58, 16, 139, 170, 192, 118, 116, 190, 60, 126, 105, 242, 56, 189, 200, 116, 252, 156, 120, 132, 79, 234, 149, 252, 227, 100, 150, 85, 112, 49, 187, 172, 66, 23, 202, 153, 53, 204, 69, 117, 170, 160, 93, 100, 85, 149, 158, 34, 64, 249, 18, 255, 239, 130, 99, 144, 68, 9, 51, 228, 166, 245, 78, 199, 9, 33, 17, 165, 116, 7, 240, 152, 160, 2, 235, 149, 211, 221, 33, 44, 139, 64, 215, 147, 206, 163, 164, 35, 254, 32, 160, 216, 40, 64, 146, 150, 215, 101, 154, 143, 196, 179, 88, 184, 137, 63, 25, 15, 76, 110, 188, 26, 152, 129, 147, 193, 225, 61, 49, 227, 174, 1, 2, 255, 111, 220, 113, 226, 37, 131, 241, 204, 106, 196, 143, 102, 213, 36, 19, 84, 27, 242, 120, 96, 55, 79, 14, 141, 251, 135, 48, 29, 241, 202, 84, 160, 223, 130, 177, 133, 254, 153, 73, 144, 56, 83, 63, 18, 140, 195, 195, 113, 208, 234, 177, 63, 58, 172, 87, 29, 245, 222, 179, 33, 29, 28, 133, 168, 131, 237, 63, 140, 224, 26, 79, 237, 10, 250, 200, 132, 7, 250, 208, 247, 171, 195, 217, 24, 188, 176, 46, 96, 71, 120, 30, 126, 231, 236, 33, 216, 53, 230, 28, 81, 229, 73, 224, 198, 103, 28, 166, 150, 189, 53, 197, 32, 147, 4, 41, 65, 187, 39, 47, 46, 201, 180, 117, 224, 51, 147, 19, 193, 126, 95, 184, 137, 4, 117, 45, 206, 78, 146, 120, 162, 133, 207, 204, 48, 230, 168, 192, 173, 224, 24, 247, 88, 194, 125, 97, 25, 26, 154, 185, 60, 21, 132, 35, 248, 169, 148, 15, 110, 36, 190, 135, 212, 237, 141, 8, 212, 178, 93, 233, 30, 34, 249, 156, 140, 7, 123, 161, 229, 68, 224, 66, 70, 10, 144, 238, 158, 66, 2, 5, 196, 212, 230, 119, 23, 246, 27, 156, 192, 87, 53, 180, 231, 20, 143, 19, 235, 84, 201, 74, 255, 214, 139, 159, 133, 77, 213, 181, 7, 74, 73, 102, 107, 88, 84, 146, 87, 76, 114, 229, 166, 90, 244, 48, 143, 37, 139, 50, 137, 91, 30, 137, 10, 248, 31, 163, 231, 125, 244, 153, 27, 236, 148, 239, 118, 122, 156, 108, 171, 97, 13, 39, 47, 227, 208, 55, 233, 9, 4, 231, 147, 254, 105, 115, 155, 213, 102, 104, 136, 3, 142, 21, 209, 63, 153, 240, 207, 116, 46, 6, 186, 118, 8, 31, 16, 10, 56, 189, 84, 9, 199, 106, 180, 41, 176, 67, 7, 129, 100, 70, 240, 188, 194, 181, 76, 47, 185, 144, 39, 34, 172, 246, 164, 47, 84, 114, 111, 89, 214, 74, 208, 133, 62, 125, 33, 192, 170, 179, 34, 8, 180, 209, 189, 195, 182, 135, 157, 150, 180, 206, 128, 26, 191, 180, 110, 32, 247, 97, 91, 48, 251, 108, 0, 248, 158, 138, 4, 40, 143, 3, 145, 54, 9, 20, 158, 70, 27, 79, 21, 150, 197, 5, 77, 54, 219, 245, 27, 177, 163, 28, 192, 128, 112, 137, 115, 132, 196, 201, 18, 209, 158, 192, 94, 255, 181, 34, 118, 206, 202, 5, 157, 240, 246, 96, 75, 128, 251, 140, 60, 68, 248, 15, 178, 86, 226, 122, 79, 5, 206, 195, 234, 8, 254, 194, 10, 9, 14, 215, 138, 133, 106, 237, 9, 40, 13, 223, 28, 131, 162, 24, 155, 17, 147, 77, 191, 125, 139, 103, 118, 223, 190, 125, 132, 77, 73, 9, 226, 242, 212, 124, 220, 203, 219, 242, 145, 141, 196, 228, 68, 101, 16, 193, 53, 60, 18, 191, 204, 128, 46, 114, 121, 68, 19, 244, 197, 151, 185, 50, 78, 134, 212, 2, 35, 195, 210, 6, 147, 22, 116, 42, 185, 218, 173, 117, 110, 183, 164, 51, 31, 253, 11, 114, 70, 170, 57, 209, 41, 165, 190, 238, 149, 127, 138, 234, 130, 159, 159, 34, 12, 38, 26, 145, 83, 51, 189, 122, 113, 62, 254, 251, 56, 55, 15, 2, 109, 108, 35, 113, 2, 25, 56, 190, 27, 183, 212, 126, 109, 111, 118, 194, 132, 184, 7, 193, 147, 167, 17, 54, 57, 80, 10, 197, 120, 23, 154, 25, 254, 44, 173, 246, 199, 213, 52, 29, 15, 116, 118, 105, 62, 213, 144, 28, 148, 121, 245, 74, 31, 92, 63, 56, 145, 76, 110, 71, 213, 124, 234, 118, 172, 186, 229, 114, 178, 66, 38, 25, 210, 172, 99, 48, 80, 30, 208, 156, 116, 41, 125, 92, 114, 75, 24, 12, 218, 231, 5, 108, 170, 229, 67, 163, 8, 155, 54, 102, 21, 4, 182, 35, 235, 226, 213, 182, 122, 223, 21, 248, 21, 190, 163, 171, 10, 179, 49, 13, 33, 237, 220, 63, 51, 207, 33, 162, 32, 13, 22, 56, 69, 20, 130, 211, 230, 22, 154, 88, 119, 2, 39, 135, 8, 215, 134, 15, 14, 29, 208, 27, 105, 24, 195, 70, 203, 247, 221, 195, 69, 117, 7, 61, 137, 236, 53, 12, 136, 90, 204, 221, 159, 33, 137, 30, 176, 107, 63, 40, 38, 5, 108, 187, 211, 236, 45, 207, 189, 178, 131, 194, 137, 239, 161, 82, 239, 201, 105, 86, 57, 187, 56, 234, 115, 174, 3, 240, 1, 13, 75, 14, 189, 46, 54, 232, 78, 100, 202, 2, 195, 205, 33, 180, 25, 104, 31, 249, 133, 206, 235, 153, 17, 14, 33, 24, 63, 185, 26, 9, 254, 229, 72, 93, 75, 144, 62, 63, 77, 175, 113, 46, 181, 29, 85, 3, 167, 79, 27, 232, 26, 143, 213, 66, 100, 194, 180, 189, 49, 235, 229, 102, 226, 191, 154, 141, 21, 147, 255, 66, 152, 1, 109, 130, 194, 8, 245, 220, 128, 41, 160, 57, 157, 37, 72, 92, 88, 141, 29, 32, 17, 168, 143, 235, 106, 37, 72, 148, 71, 252, 229, 242, 159, 22, 192, 220, 178, 69, 37, 217, 107, 79, 16, 124, 148, 33, 23, 53, 196, 127, 5, 107, 152, 125, 204, 80, 52, 146, 95, 195, 46, 31, 66, 17, 73, 38, 3, 9, 93, 31, 224, 117, 150, 104, 213, 153, 32, 138, 250, 125, 70, 216, 98, 98, 46, 27, 158, 152, 131, 248, 253, 76, 4, 216, 60, 177, 95, 61, 141, 145, 194, 85, 70, 112, 73, 80, 242, 141, 198, 120, 93, 101, 96, 253, 24, 52, 219, 229, 201, 70, 155, 126, 233, 22, 10, 236, 50, 19, 74, 221, 156, 216, 134, 15, 25, 186, 252, 111, 209, 186, 109, 194, 59, 47, 254, 95, 68, 152, 136, 112, 149, 141, 132, 72, 68, 133, 152, 100, 17, 107, 146, 99, 76, 244, 170, 160, 217, 62, 122, 103, 32, 62, 182, 23, 241, 248, 57, 198, 207, 33, 220, 50, 28, 13, 207, 72, 189, 0, 156, 18, 114, 227, 179, 96, 154, 241, 192, 57, 57, 181, 218, 101, 165, 49, 87, 105, 219, 3, 84, 55, 39, 236, 161, 243, 133, 174, 168, 80, 188, 111, 157, 180, 183, 233, 64, 224, 8, 213, 157, 144, 117, 126, 224, 142, 101, 58, 172, 173, 111, 23, 135, 58, 158, 104, 25, 234, 193, 19, 93, 64, 111, 99, 35, 130, 96, 146, 188, 43, 179, 148, 101, 17, 12, 136, 116, 252, 192, 226, 23, 145, 94, 84, 164, 67, 7, 9, 239, 148, 72, 183, 233, 192, 93, 21, 233, 101, 9, 35, 83, 13, 27, 27, 144, 18, 120, 171, 97, 150, 13, 155, 205, 181, 39, 146, 110, 131, 209, 124, 219, 87, 185, 145, 163, 65, 119, 100, 165, 59, 31, 246, 119, 75, 214, 238, 194, 106, 215, 156, 114, 218, 183, 2, 23, 217, 102, 146, 237, 245, 144, 204, 177, 218, 47, 25, 155, 211, 47, 134, 215, 9, 17, 234, 143, 87, 89, 74, 80, 56, 189, 88, 131, 107, 174, 250, 113, 15, 97, 205, 97, 233, 55, 156, 142, 186, 13, 106, 105, 89, 167, 172, 154, 21, 147, 115, 14, 139, 112, 181, 238, 126, 195, 177, 44, 43, 3, 27, 146, 228, 243, 28, 96, 74, 92, 17, 90, 246, 44, 166, 193, 63, 166, 19, 24, 199, 138, 29, 65, 180, 232, 232, 123, 81, 121, 16, 5, 175, 26, 222, 171, 144, 199, 164, 168, 112, 210, 163, 81, 142, 164, 174, 175, 7, 204, 242, 0, 214, 225, 19, 101, 241, 19, 85, 254, 250, 54, 114, 140, 234, 115, 153, 194, 245, 172, 169, 58, 117, 188, 185, 185, 57, 223, 224, 191, 9, 111, 187, 71, 79, 77, 221, 6, 105, 95, 252, 52, 71, 59, 25, 191, 161, 105, 170, 237, 49, 16, 151, 215, 131, 74, 25, 143, 110, 125, 241, 175, 222, 244, 152, 181, 72, 224, 95, 55, 124, 11, 28, 51, 243, 70, 90, 158, 45, 251, 50, 212, 159, 98, 168, 87, 151, 57, 214, 205, 167, 224, 2, 251, 38, 227, 225, 151, 161, 190, 115, 82, 93, 183, 182, 23, 235, 57, 114, 77, 230, 254, 56, 87, 184, 9, 98, 218, 241, 21, 171, 9, 50, 180, 104, 103, 14, 135, 216, 111, 241, 101, 179, 202, 130, 41, 234, 177, 72, 221, 48, 168, 49, 149, 229, 60, 107, 17, 232, 34, 72, 118, 17, 63, 205, 8, 40, 134, 79, 107, 232, 186, 53, 135, 18, 190, 237, 37, 29, 209, 247, 14, 11, 233, 15, 17, 29, 209, 195, 69, 109, 207, 224, 116, 188, 245, 134, 252, 232, 191, 241, 231, 193, 95, 48, 210, 7, 141, 20, 0, 250, 46, 29, 156, 195, 92, 106, 111, 118, 113, 110, 123, 132, 30, 255, 18, 21, 159, 95, 100, 4, 198, 47, 54, 2, 67, 192, 55, 223, 230, 14, 190, 16, 149, 91, 68, 92, 16, 188, 201, 87, 114, 171, 96, 199, 118, 210, 9, 196, 112, 89, 193, 130, 154, 71, 44, 105, 45, 42, 151, 25, 228, 129, 201, 42, 55, 22, 82, 122, 95, 39, 111, 213, 231, 94, 242, 139, 61, 193, 153, 78, 164, 10, 19, 229, 14, 209, 193, 1, 153, 149, 4, 128, 211, 81, 241, 46, 5, 122, 4, 62, 67, 229, 203, 51, 129, 78, 210, 197, 85, 52, 89, 205, 67, 208, 147, 92, 0, 225, 146, 54, 157, 60, 19, 109, 94, 9, 90, 104, 69, 217, 53, 72, 132, 155, 38, 219, 94, 60, 211, 132, 227, 7, 151, 205, 157, 103, 87, 82, 212, 2, 144, 212, 37, 220, 60, 23, 75, 164, 104, 95, 21, 141, 66, 74, 36, 27, 213, 150, 234, 243, 82, 33, 145, 9, 112, 188, 81, 83, 162, 47, 122, 100, 64, 96, 208, 81, 86, 51, 8, 162, 45, 25, 92, 31, 254, 12, 222, 54, 42, 115, 212, 211, 176, 96, 108, 19, 129, 178, 72, 96, 19, 169, 222, 38, 170, 201, 193, 57, 16, 208, 180, 48, 239, 170, 136, 192, 127, 242, 227, 85, 53, 71, 76, 219, 113, 246, 65, 45, 79, 35, 117, 41, 75, 235, 212, 28, 127, 199, 51, 72, 54, 36, 107, 127, 60, 125, 176, 13, 225, 211, 225, 192, 81, 234, 102, 181, 178, 98, 1, 241, 221, 35, 227, 142, 109, 144, 17, 181, 250, 247, 64, 245, 219, 131, 234, 115, 80, 186, 154, 185, 190, 213, 212, 63, 142, 226, 18, 35, 160, 128, 253, 134, 138, 254, 50, 197, 84, 50, 194, 166, 86, 16, 148, 176, 234, 147, 26, 121, 235, 101, 93, 33, 62, 97, 40, 193, 239, 139, 23, 172, 49, 231, 109, 241, 182, 70, 155, 187, 226, 193, 207, 92, 22, 179, 201, 143, 38, 219, 10, 153, 14, 204, 73, 36, 63, 150, 21, 11, 199, 102, 25, 53, 70, 223, 62, 212, 242, 231, 78, 57, 178, 182, 254, 154, 203, 148, 50, 1, 115, 180, 99, 196, 104, 249, 51, 95, 63, 62, 243, 237, 37, 209, 11, 218, 141, 45, 99, 237, 181, 113, 118, 153, 236, 217, 253, 136, 243, 246, 102, 170, 67, 197, 29, 43, 145, 114, 42, 106, 82, 250, 190, 117, 122, 78, 164, 90, 221, 46, 27, 157, 192, 241, 62, 90, 180, 183, 68, 107, 100, 166, 180, 245, 66, 183, 101, 39, 97, 96, 21, 5, 214, 75, 142, 101, 150, 191, 181, 160, 16, 7, 50, 253, 232, 54, 205, 157, 184, 149, 186, 101, 208, 185, 152, 8, 255, 127, 78, 28, 213, 54, 181, 67, 58, 97, 146, 243, 114, 118, 241, 46, 43, 223, 230, 149, 88, 76, 9, 50, 119, 199, 179, 11, 203, 207, 202, 36, 22, 239, 228, 193, 159, 49, 22, 118, 15, 108, 134, 100, 20, 170, 108, 224, 255, 81, 55, 134, 155, 124, 153, 190, 92, 102, 123, 171, 40, 25, 23, 225, 182, 116, 74, 96, 9, 50, 212, 164, 120, 221, 186, 85, 178, 219, 238, 111, 180, 171, 38, 118, 24, 118, 0, 125, 195, 214, 137, 19, 229, 72, 76, 72, 159, 7, 89, 204, 9, 226, 98, 186, 74, 167, 182, 154, 1, 216, 232, 118, 183, 147, 63, 253, 41, 249, 246, 193, 26, 220, 239, 184, 6, 187, 186, 26, 198, 215, 95, 155, 71, 241, 150, 149, 227, 71, 217, 208, 132, 176, 140, 97, 250, 174, 218, 96, 140, 243, 186, 144, 63, 117, 193, 181, 48, 40, 203, 214, 81, 104, 170, 72, 61, 64, 105, 160, 9, 109, 119, 112, 57, 214, 226, 248, 83, 86, 13, 202, 124, 34, 20, 94, 69, 79, 93, 201, 148, 50, 230, 146, 208, 3, 171, 242, 178, 43, 125, 213, 238, 97, 118, 2, 225, 101, 111, 139, 203, 241, 223, 197, 219, 174, 62, 80, 134, 70, 143, 5, 11, 166, 210, 71, 166, 36, 77, 22, 177, 158, 186, 112, 20, 128, 42, 37, 176, 163, 190, 170, 123, 122, 115, 126, 121, 188, 213, 151, 80, 69, 166, 25, 37, 198, 58, 180, 42, 190, 213, 247, 83, 30, 43, 228, 122, 80, 49, 37, 214, 71, 150, 180, 147, 209, 90, 157, 46, 35, 221, 84, 218, 16, 222, 56, 251, 21, 106, 172, 72, 217, 240, 168, 144, 115, 102, 246, 238, 59, 85, 153, 210, 251, 148, 23, 53, 131, 164, 174, 7, 244, 64, 239, 87, 207, 62, 136, 121, 165, 202, 213, 153, 74, 6, 152, 157, 160, 4, 46, 167, 45, 229, 110, 205, 0, 244, 183, 211, 226, 69, 33, 230, 137, 204, 75, 75, 68, 151, 8, 53, 71, 87, 14, 54, 167, 38, 251, 205, 65, 176, 5, 156, 22, 68, 79, 25, 226, 238, 5, 182, 126, 181, 179, 180, 34, 12, 208, 253, 39, 171, 46, 63, 118, 255, 41, 151, 83, 188, 254, 87, 18, 0, 18, 89, 140, 11, 204, 222, 115, 15, 134, 204, 126, 16, 54, 219, 60, 240, 202, 122, 51, 231, 109, 153, 217, 70, 139, 31, 73, 108, 176, 24, 67, 201, 155, 168, 21, 13, 42, 133, 158, 78, 44, 36, 107, 54, 162, 117, 164, 209, 170, 162, 104, 201, 210, 82, 38, 20, 90, 144, 55, 169, 151, 84, 248, 131, 169, 18, 81, 48, 9, 93, 57, 236, 154, 118, 170, 106, 196, 172, 123, 240, 64, 34, 52, 133, 185, 130, 78, 12, 82, 35, 152, 153, 5, 178, 55, 209, 51, 190, 192, 213, 222, 55, 53, 231, 4, 191, 85, 104, 68, 119, 132, 117, 250, 186, 208, 236, 35, 52, 156, 76, 97, 37, 76, 85, 147, 202, 74, 246, 222, 112, 24, 34, 45, 187, 43, 237, 93, 208, 8, 248, 176, 245, 97, 123, 107, 43, 249, 67, 252, 221, 234, 203, 63, 219, 234, 56, 165, 57, 87, 45, 59, 38, 159, 97, 1, 185, 130, 38, 176, 199, 213, 178, 201, 159, 41, 193, 79, 23, 39, 248, 105, 51, 193, 79, 239, 23, 193, 79, 9, 153, 45, 241, 107, 8, 254, 162, 40, 206, 103, 19, 194, 225, 173, 8, 253, 89, 169, 52, 44, 168, 99, 77, 206, 137, 177, 217, 80, 111, 122, 43, 42, 58, 243, 34, 206, 102, 102, 2, 212, 111, 96, 189, 252, 181, 36, 49, 77, 35, 65, 230, 185, 227, 109, 147, 245, 91, 103, 254, 13, 223, 39, 242, 145, 12, 161, 99, 86, 156, 122, 51, 162, 120, 43, 217, 80, 59, 17, 85, 189, 85, 237, 79, 138, 14, 223, 207, 95, 134, 111, 174, 225, 235, 223, 150, 225, 171, 55, 226, 38, 150, 140, 118, 88, 219, 83, 140, 3, 176, 190, 54, 66, 181, 80, 183, 77, 130, 230, 233, 180, 172, 118, 199, 67, 229, 135, 83, 164, 213, 96, 216, 87, 32, 119, 127, 203, 93, 131, 104, 218, 43, 63, 162, 162, 188, 118, 149, 92, 150, 249, 20, 148, 244, 163, 100, 117, 213, 135, 182, 245, 208, 248, 84, 50, 193, 117, 114, 239, 38, 82, 180, 111, 138, 14, 138, 241, 73, 126, 58, 171, 43, 188, 189, 230, 156, 58, 198, 145, 38, 54, 220, 239, 90, 143, 58, 24, 87, 230, 205, 182, 122, 211, 26, 177, 214, 104, 125, 12, 176, 200, 65, 169, 88, 206, 153, 28, 220, 1, 238, 225, 128, 229, 239, 102, 83, 112, 151, 129, 20, 15, 166, 118, 89, 186, 156, 75, 185, 73, 115, 68, 119, 208, 183, 17, 21, 226, 21, 241, 53, 137, 15, 37, 162, 80, 152, 84, 60, 10, 243, 184, 233, 173, 165, 73, 147, 135, 239, 251, 160, 135, 111, 155, 146, 85, 37, 179, 247, 132, 68, 187, 201, 84, 234, 13, 125, 89, 132, 89, 131, 27, 207, 153, 254, 33, 103, 105, 226, 110, 149, 103, 163, 156, 151, 208, 147, 142, 101, 178, 142, 88, 45, 82, 100, 116, 132, 29, 98, 240, 199, 19, 242, 105, 211, 86, 18, 212, 67, 27, 225, 17, 252, 249, 158, 250, 28, 59, 148, 43, 231, 128, 77, 171, 73, 232, 219, 8, 189, 191, 197, 160, 203, 36, 171, 13, 96, 81, 107, 232, 245, 173, 36, 26, 105, 137, 108, 66, 19, 170, 234, 128, 19, 211, 146, 86, 36, 115, 52, 22, 234, 151, 6, 35, 251, 244, 16, 251, 180, 205, 251, 36, 134, 173, 185, 145, 109, 221, 136, 25, 100, 210, 200, 105, 70, 246, 38, 2, 150, 42, 200, 131, 170, 183, 26, 118, 89, 58, 220, 251, 221, 247, 210, 134, 237, 56, 139, 114, 196, 183, 154, 11, 223, 42, 128, 111, 21, 195, 183, 178, 248, 86, 115, 227, 91, 133, 241, 149, 72, 57, 83, 55, 255, 208, 167, 115, 186, 11, 122, 155, 185, 86, 149, 58, 111, 165, 53, 43, 189, 202, 208, 203, 59, 163, 64, 233, 248, 107, 38, 164, 168, 81, 61, 171, 223, 25, 147, 195, 32, 222, 37, 118, 186, 252, 243, 80, 238, 19, 218, 162, 129, 18, 234, 35, 53, 98, 2, 62, 26, 191, 71, 252, 206, 139, 64, 164, 150, 201, 15, 182, 8, 161, 148, 123, 30, 23, 23, 46, 149, 230, 4, 69, 156, 254, 228, 209, 192, 140, 44, 14, 91, 205, 128, 100, 230, 187, 206, 52, 138, 219, 248, 142, 89, 163, 213, 51, 233, 48, 166, 169, 242, 208, 133, 189, 202, 103, 114, 87, 31, 195, 79, 92, 247, 163, 227, 54, 156, 192, 38, 109, 44, 116, 37, 18, 182, 2, 117, 26, 66, 86, 100, 201, 205, 19, 139, 12, 143, 96, 137, 178, 148, 222, 122, 156, 200, 205, 65, 119, 144, 195, 125, 254, 155, 244, 59, 29, 244, 146, 87, 13, 222, 86, 238, 168, 122, 165, 19, 118, 249, 38, 242, 151, 61, 61, 103, 79, 79, 146, 147, 120, 193, 6, 24, 239, 208, 85, 139, 140, 91, 180, 119, 199, 215, 152, 231, 113, 251, 240, 60, 110, 23, 158, 55, 217, 131, 231, 210, 14, 180, 75, 67, 103, 199, 16, 18, 213, 137, 143, 111, 236, 68, 214, 180, 45, 24, 19, 137, 207, 180, 31, 232, 74, 154, 0, 125, 145, 87, 217, 91, 117, 166, 169, 91, 140, 159, 203, 39, 43, 113, 19, 89, 36, 26, 196, 162, 190, 215, 165, 206, 87, 173, 64, 194, 124, 213, 80, 36, 119, 62, 108, 49, 171, 109, 122, 186, 191, 172, 154, 232, 197, 182, 159, 53, 124, 201, 219, 38, 35, 213, 244, 44, 211, 221, 233, 201, 132, 188, 234, 87, 200, 191, 103, 123, 174, 59, 66, 170, 195, 208, 143, 73, 229, 132, 129, 115, 191, 178, 129, 236, 18, 48, 107, 96, 201, 107, 182, 127, 79, 231, 127, 231, 96, 95, 72, 76, 10, 219, 23, 247, 114, 86, 119, 160, 20, 61, 14, 179, 170, 24, 189, 207, 186, 123, 44, 15, 43, 153, 126, 194, 97, 158, 88, 119, 19, 208, 238, 37, 134, 242, 6, 237, 128, 31, 132, 95, 38, 173, 153, 80, 254, 233, 82, 66, 177, 254, 11, 69, 83, 209, 131, 114, 119, 145, 0, 50, 11, 179, 236, 73, 144, 0, 13, 185, 200, 34, 109, 69, 25, 151, 79, 106, 50, 54, 237, 69, 94, 161, 121, 128, 190, 154, 23, 249, 121, 246, 188, 40, 133, 214, 175, 236, 254, 149, 113, 75, 0, 145, 228, 54, 226, 235, 66, 29, 192, 18, 133, 148, 14, 49, 43, 94, 40, 241, 52, 233, 126, 187, 181, 149, 252, 41, 17, 86, 114, 252, 164, 120, 191, 255, 23, 38, 190, 35, 129, 138, 154, 78, 164, 231, 72, 128, 90, 99, 19, 71, 142, 83, 137, 248, 163, 55, 45, 237, 134, 101, 64, 223, 1, 60, 49, 133, 226, 124, 126, 156, 123, 102, 3, 124, 102, 4, 209, 14, 53, 188, 47, 162, 59, 77, 75, 12, 230, 80, 65, 128, 120, 84, 76, 152, 100, 230, 4, 154, 168, 205, 156, 26, 70, 21, 200, 138, 243, 4, 139, 234, 26, 206, 164, 173, 29, 7, 172, 201, 6, 75, 226, 207, 38, 58, 239, 127, 89, 189, 255, 237, 152, 15, 170, 155, 155, 216, 77, 243, 250, 117, 113, 84, 204, 202, 65, 230, 52, 199, 173, 137, 182, 87, 109, 180, 161, 157, 218, 26, 219, 175, 246, 199, 163, 28, 15, 126, 190, 128, 90, 6, 46, 27, 13, 186, 31, 166, 63, 12, 180, 14, 55, 67, 197, 26, 72, 248, 232, 16, 133, 223, 48, 64, 15, 155, 7, 72, 198, 120, 95, 190, 198, 215, 154, 241, 253, 195, 137, 79, 147, 109, 221, 136, 41, 237, 156, 61, 212, 43, 197, 0, 154, 166, 74, 220, 172, 246, 112, 221, 238, 37, 164, 26, 89, 216, 210, 57, 133, 226, 50, 53, 93, 248, 116, 140, 103, 6, 110, 62, 230, 67, 39, 151, 208, 76, 42, 87, 250, 126, 245, 74, 88, 125, 217, 80, 170, 10, 71, 46, 133, 209, 198, 222, 40, 37, 133, 17, 37, 68, 51, 169, 230, 127, 224, 133, 213, 219, 71, 77, 26, 210, 229, 231, 36, 169, 46, 115, 204, 219, 15, 104, 106, 189, 104, 78, 168, 9, 250, 111, 61, 114, 38, 16, 77, 9, 87, 179, 107, 142, 182, 131, 185, 99, 161, 244, 23, 134, 130, 34, 82, 137, 181, 20, 5, 183, 125, 125, 112, 234, 161, 207, 224, 62, 88, 34, 92, 245, 176, 205, 26, 120, 120, 19, 13, 168, 135, 7, 172, 165, 111, 111, 180, 37, 245, 240, 144, 53, 249, 221, 167, 105, 82, 61, 124, 203, 218, 254, 243, 39, 110, 91, 61, 124, 199, 144, 248, 254, 115, 33, 161, 30, 254, 204, 176, 249, 203, 103, 199, 70, 61, 124, 207, 208, 234, 47, 174, 81, 150, 142, 151, 122, 248, 11, 71, 112, 9, 202, 106, 233, 8, 106, 128, 92, 15, 246, 151, 169, 8, 151, 143, 170, 126, 50, 74, 86, 172, 97, 82, 177, 40, 113, 144, 54, 22, 68, 19, 182, 254, 185, 47, 109, 88, 13, 231, 117, 110, 170, 166, 175, 227, 222, 212, 121, 229, 3, 232, 156, 198, 118, 166, 117, 199, 188, 205, 105, 231, 250, 35, 110, 68, 181, 216, 105, 116, 205, 61, 214, 191, 232, 70, 121, 8, 157, 96, 135, 206, 210, 106, 57, 184, 7, 108, 47, 89, 33, 96, 116, 137, 70, 125, 115, 75, 129, 15, 26, 249, 116, 23, 52, 31, 27, 67, 49, 60, 64, 161, 254, 36, 55, 219, 33, 216, 106, 106, 215, 161, 70, 227, 92, 245, 88, 6, 82, 32, 250, 71, 51, 188, 243, 210, 239, 84, 207, 177, 222, 93, 170, 201, 42, 199, 164, 6, 207, 2, 241, 213, 97, 118, 250, 236, 195, 228, 249, 40, 61, 173, 88, 196, 35, 88, 183, 135, 81, 47, 217, 97, 29, 251, 30, 214, 157, 58, 62, 100, 246, 179, 241, 144, 116, 58, 186, 145, 195, 77, 188, 44, 97, 152, 15, 236, 166, 156, 42, 182, 46, 202, 13, 59, 148, 140, 135, 155, 242, 228, 86, 160, 224, 169, 83, 48, 63, 29, 23, 101, 182, 151, 86, 89, 160, 112, 238, 20, 190, 16, 31, 224, 106, 199, 80, 217, 11, 167, 236, 176, 152, 238, 142, 66, 24, 84, 78, 193, 217, 56, 31, 20, 195, 16, 200, 89, 184, 164, 88, 142, 134, 72, 240, 222, 41, 93, 77, 243, 193, 249, 85, 160, 224, 85, 199, 225, 6, 155, 144, 202, 15, 2, 245, 24, 65, 197, 166, 158, 192, 27, 30, 151, 42, 139, 6, 238, 35, 189, 121, 134, 153, 64, 90, 166, 82, 250, 124, 84, 243, 130, 0, 40, 108, 198, 193, 143, 24, 243, 18, 248, 138, 110, 174, 116, 254, 27, 110, 248, 212, 208, 214, 213, 111, 44, 86, 71, 30, 123, 93, 167, 189, 55, 149, 146, 102, 119, 248, 30, 238, 248, 144, 95, 246, 33, 72, 189, 123, 164, 238, 182, 86, 206, 43, 116, 233, 2, 33, 52, 182, 213, 108, 50, 145, 238, 239, 180, 196, 61, 1, 185, 254, 86, 177, 240, 71, 122, 165, 248, 245, 215, 202, 50, 112, 92, 29, 178, 169, 183, 192, 46, 175, 138, 124, 60, 221, 21, 250, 193, 54, 249, 52, 217, 250, 112, 34, 254, 173, 240, 43, 59, 36, 244, 245, 164, 47, 254, 99, 237, 59, 250, 20, 186, 252, 11, 56, 236, 186, 114, 99, 194, 142, 116, 249, 33, 58, 212, 229, 135, 218, 43, 180, 62, 212, 13, 182, 168, 75, 71, 251, 136, 142, 162, 66, 65, 55, 40, 218, 155, 76, 243, 139, 252, 55, 112, 213, 72, 84, 125, 4, 40, 59, 52, 28, 151, 44, 63, 244, 18, 237, 253, 176, 39, 105, 69, 189, 213, 213, 174, 4, 161, 194, 145, 172, 131, 132, 235, 30, 213, 154, 232, 208, 63, 164, 248, 186, 117, 251, 91, 242, 214, 67, 250, 238, 251, 45, 215, 137, 43, 187, 242, 179, 58, 144, 42, 104, 47, 186, 137, 200, 29, 245, 40, 240, 208, 142, 190, 172, 170, 182, 20, 158, 125, 200, 6, 178, 158, 59, 39, 144, 113, 21, 61, 191, 124, 149, 138, 249, 71, 23, 12, 15, 191, 83, 204, 112, 129, 39, 105, 229, 7, 34, 106, 38, 203, 70, 136, 97, 243, 241, 96, 52, 27, 162, 169, 5, 21, 64, 217, 116, 220, 253, 100, 137, 65, 160, 35, 62, 161, 219, 55, 51, 235, 224, 40, 180, 175, 240, 94, 110, 234, 136, 174, 141, 210, 106, 186, 175, 143, 176, 104, 249, 221, 133, 243, 169, 230, 74, 167, 177, 254, 20, 57, 237, 110, 38, 188, 96, 223, 116, 122, 73, 89, 198, 57, 44, 109, 183, 217, 229, 9, 44, 33, 62, 40, 69, 143, 146, 93, 202, 11, 242, 204, 34, 12, 218, 180, 100, 67, 131, 80, 173, 175, 37, 224, 160, 222, 21, 70, 121, 207, 84, 38, 24, 89, 120, 236, 34, 101, 229, 38, 39, 84, 49, 142, 120, 74, 45, 203, 225, 156, 132, 100, 4, 85, 1, 112, 125, 133, 85, 168, 5, 102, 138, 62, 34, 45, 175, 155, 156, 100, 248, 255, 241, 250, 122, 96, 53, 209, 78, 174, 12, 115, 123, 163, 61, 39, 7, 168, 237, 9, 65, 13, 80, 99, 90, 145, 215, 240, 198, 164, 168, 114, 149, 159, 81, 34, 123, 148, 165, 229, 224, 76, 152, 100, 10, 77, 151, 162, 48, 52, 182, 210, 19, 72, 51, 55, 39, 179, 208, 254, 240, 54, 95, 136, 47, 152, 165, 182, 123, 68, 148, 34, 97, 172, 163, 217, 59, 169, 145, 97, 120, 52, 22, 4, 199, 100, 195, 188, 93, 38, 199, 221, 52, 3, 169, 77, 35, 243, 225, 169, 30, 195, 192, 78, 225, 174, 174, 242, 177, 21, 239, 29, 102, 147, 81, 42, 22, 5, 149, 50, 33, 74, 249, 155, 68, 78, 125, 254, 153, 53, 206, 180, 82, 231, 202, 14, 165, 35, 213, 23, 81, 134, 165, 102, 36, 29, 50, 117, 242, 178, 154, 254, 84, 136, 34, 165, 30, 55, 153, 13, 17, 251, 230, 65, 180, 83, 128, 133, 197, 213, 152, 211, 134, 214, 153, 246, 181, 54, 153, 158, 210, 92, 4, 1, 52, 132, 41, 240, 220, 121, 27, 2, 79, 3, 241, 110, 161, 209, 1, 239, 162, 84, 52, 252, 172, 134, 244, 105, 242, 237, 22, 15, 254, 183, 65, 33, 63, 166, 149, 74, 87, 241, 76, 253, 122, 94, 8, 53, 112, 241, 110, 152, 134, 200, 98, 129, 27, 254, 212, 80, 214, 120, 3, 65, 211, 70, 33, 42, 200, 169, 91, 235, 178, 42, 160, 110, 123, 206, 155, 35, 247, 133, 234, 150, 251, 154, 98, 235, 126, 147, 179, 186, 243, 82, 35, 206, 94, 179, 126, 126, 92, 241, 159, 106, 123, 5, 182, 133, 209, 219, 10, 77, 142, 88, 98, 45, 37, 10, 23, 199, 211, 101, 214, 85, 71, 185, 55, 52, 142, 186, 153, 210, 147, 211, 146, 17, 44, 64, 195, 24, 253, 60, 218, 185, 120, 154, 79, 94, 175, 234, 209, 205, 33, 209, 240, 28, 212, 250, 104, 164, 161, 134, 243, 89, 147, 120, 82, 117, 142, 209, 241, 27, 106, 26, 146, 186, 230, 156, 241, 160, 163, 65, 8, 239, 141, 68, 120, 28, 34, 68, 143, 47, 8, 92, 100, 154, 169, 29, 94, 49, 40, 16, 102, 49, 176, 66, 251, 162, 208, 102, 125, 240, 241, 247, 134, 75, 189, 246, 187, 20, 90, 139, 4, 16, 144, 205, 99, 123, 164, 105, 183, 225, 96, 179, 94, 163, 109, 215, 53, 76, 81, 207, 181, 190, 177, 243, 40, 93, 187, 152, 211, 16, 190, 122, 255, 212, 139, 156, 176, 145, 203, 189, 117, 149, 76, 135, 242, 22, 118, 153, 109, 70, 20, 149, 47, 167, 186, 201, 245, 143, 151, 208, 43, 96, 81, 42, 28, 123, 6, 161, 245, 117, 39, 92, 10, 237, 14, 119, 22, 13, 230, 10, 107, 179, 140, 186, 123, 203, 35, 19, 187, 160, 179, 34, 103, 195, 67, 238, 134, 213, 41, 3, 165, 19, 251, 149, 93, 150, 240, 176, 89, 18, 253, 164, 137, 205, 66, 160, 204, 88, 171, 49, 57, 206, 73, 198, 134, 241, 94, 58, 17, 186, 37, 211, 57, 37, 48, 171, 199, 69, 250, 161, 107, 105, 132, 181, 76, 216, 194, 70, 210, 215, 151, 13, 146, 209, 193, 60, 240, 209, 193, 49, 197, 36, 72, 204, 68, 133, 149, 136, 93, 235, 173, 189, 24, 54, 138, 156, 246, 93, 62, 22, 24, 234, 20, 39, 10, 69, 233, 108, 51, 186, 212, 196, 71, 111, 173, 16, 197, 44, 185, 31, 181, 15, 56, 219, 44, 247, 248, 70, 181, 144, 220, 22, 211, 141, 1, 101, 164, 73, 152, 110, 50, 103, 255, 135, 67, 251, 149, 76, 59, 228, 142, 3, 248, 167, 104, 17, 156, 139, 204, 130, 206, 188, 49, 3, 214, 56, 63, 133, 117, 124, 68, 207, 19, 10, 57, 17, 195, 54, 123, 101, 2, 145, 191, 226, 207, 227, 39, 22, 139, 29, 88, 104, 81, 131, 8, 115, 136, 166, 147, 151, 134, 223, 142, 199, 230, 44, 171, 78, 3, 42, 190, 70, 14, 227, 192, 63, 195, 70, 80, 144, 88, 127, 218, 134, 209, 127, 17, 167, 244, 34, 27, 18, 22, 86, 156, 112, 10, 33, 249, 21, 93, 73, 242, 130, 209, 214, 205, 17, 0, 86, 62, 96, 70, 209, 81, 167, 244, 119, 237, 21, 195, 208, 79, 159, 4, 100, 217, 54, 237, 107, 129, 117, 123, 246, 134, 173, 241, 125, 40, 118, 221, 15, 233, 146, 2, 141, 172, 187, 172, 98, 57, 63, 9, 107, 24, 3, 112, 157, 10, 174, 191, 16, 11, 84, 22, 29, 117, 150, 234, 110, 250, 119, 221, 69, 199, 186, 145, 18, 18, 32, 196, 74, 43, 26, 232, 181, 85, 144, 4, 17, 75, 38, 42, 169, 86, 70, 137, 116, 162, 92, 82, 137, 100, 178, 120, 93, 99, 103, 96, 185, 216, 159, 214, 245, 71, 163, 64, 113, 10, 8, 204, 187, 186, 96, 207, 169, 2, 211, 175, 234, 10, 143, 157, 109, 150, 234, 184, 68, 55, 73, 179, 170, 21, 18, 232, 168, 225, 80, 215, 1, 83, 223, 4, 91, 54, 137, 127, 237, 218, 196, 215, 11, 145, 227, 22, 58, 126, 207, 208, 135, 170, 12, 30, 193, 71, 248, 221, 116, 155, 124, 10, 39, 23, 101, 5, 234, 215, 205, 222, 101, 213, 22, 174, 68, 13, 162, 77, 156, 79, 254, 36, 162, 212, 10, 251, 189, 70, 126, 17, 173, 203, 67, 11, 111, 69, 247, 236, 143, 254, 13, 244, 117, 251, 246, 246, 213, 254, 216, 190, 129, 142, 63, 184, 35, 29, 183, 63, 30, 220, 0, 21, 30, 222, 69, 42, 216, 31, 15, 151, 73, 18, 234, 79, 159, 83, 85, 55, 239, 57, 212, 213, 166, 203, 208, 86, 150, 219, 156, 240, 67, 214, 29, 243, 216, 184, 35, 222, 120, 180, 129, 59, 201, 200, 129, 67, 221, 120, 32, 248, 168, 69, 207, 220, 9, 174, 198, 62, 245, 252, 68, 194, 184, 65, 163, 41, 159, 206, 44, 111, 26, 170, 72, 163, 74, 254, 225, 44, 18, 112, 23, 57, 86, 75, 207, 199, 45, 110, 96, 61, 119, 167, 95, 180, 177, 148, 129, 149, 176, 77, 43, 127, 39, 198, 156, 186, 27, 251, 179, 188, 218, 94, 216, 144, 139, 234, 214, 230, 64, 139, 25, 191, 102, 190, 119, 103, 251, 26, 13, 209, 168, 31, 226, 218, 33, 162, 27, 204, 186, 154, 191, 14, 75, 56, 149, 111, 43, 221, 70, 182, 221, 121, 253, 51, 117, 68, 63, 186, 51, 249, 226, 125, 218, 190, 77, 125, 210, 143, 238, 124, 189, 120, 247, 30, 220, 210, 238, 233, 71, 119, 78, 94, 188, 167, 15, 111, 127, 79, 245, 163, 59, 235, 46, 208, 105, 234, 18, 140, 46, 5, 217, 170, 109, 171, 118, 213, 166, 72, 217, 98, 250, 29, 155, 110, 140, 237, 97, 200, 250, 26, 70, 125, 174, 131, 55, 144, 205, 245, 173, 43, 110, 235, 105, 190, 229, 84, 216, 26, 240, 131, 208, 252, 78, 102, 71, 206, 69, 203, 153, 217, 131, 115, 223, 226, 219, 107, 118, 7, 100, 161, 48, 182, 185, 194, 102, 22, 245, 63, 127, 146, 232, 25, 111, 63, 96, 158, 72, 153, 26, 159, 218, 178, 60, 106, 190, 235, 47, 72, 48, 131, 181, 237, 50, 233, 200, 19, 235, 111, 187, 101, 1, 54, 132, 252, 116, 53, 112, 95, 188, 127, 161, 88, 129, 149, 214, 155, 153, 114, 23, 190, 173, 172, 206, 45, 151, 69, 153, 159, 194, 249, 124, 217, 23, 26, 195, 34, 71, 60, 24, 196, 210, 95, 115, 171, 63, 87, 123, 168, 42, 166, 218, 228, 128, 83, 218, 17, 147, 215, 84, 70, 152, 254, 230, 124, 32, 155, 130, 55, 160, 43, 60, 111, 180, 179, 81, 68, 54, 10, 93, 140, 249, 230, 222, 220, 74, 167, 65, 237, 4, 57, 127, 62, 229, 227, 110, 142, 205, 31, 167, 151, 180, 216, 51, 115, 183, 34, 124, 11, 169, 193, 62, 138, 89, 71, 65, 219, 200, 219, 169, 10, 91, 58, 214, 206, 49, 25, 194, 232, 206, 18, 62, 210, 209, 115, 54, 163, 49, 42, 180, 105, 232, 162, 155, 211, 145, 161, 219, 9, 143, 138, 177, 245, 218, 144, 28, 210, 158, 237, 132, 185, 142, 238, 64, 210, 98, 148, 99, 234, 246, 84, 162, 27, 137, 225, 213, 51, 49, 140, 249, 94, 98, 237, 214, 33, 29, 107, 103, 96, 62, 241, 124, 105, 37, 190, 237, 116, 201, 198, 133, 223, 148, 116, 91, 103, 74, 138, 217, 31, 79, 52, 79, 216, 173, 65, 85, 168, 157, 90, 7, 155, 216, 52, 230, 76, 13, 127, 252, 225, 130, 170, 139, 114, 68, 235, 154, 205, 14, 88, 155, 108, 105, 91, 245, 102, 78, 141, 30, 166, 151, 93, 222, 106, 143, 195, 8, 4, 105, 222, 51, 235, 128, 198, 71, 206, 101, 33, 144, 184, 198, 59, 105, 44, 124, 150, 73, 255, 203, 252, 224, 204, 15, 205, 17, 190, 42, 89, 213, 68, 6, 15, 203, 113, 247, 18, 189, 65, 45, 190, 19, 108, 193, 99, 229, 154, 192, 140, 29, 242, 204, 126, 240, 185, 11, 192, 216, 175, 78, 52, 9, 252, 35, 81, 206, 78, 58, 115, 58, 34, 52, 16, 119, 181, 190, 231, 139, 205, 157, 254, 236, 233, 132, 228, 134, 108, 155, 192, 28, 26, 217, 48, 249, 50, 155, 126, 153, 77, 147, 47, 179, 105, 83, 104, 252, 156, 83, 169, 191, 21, 117, 99, 115, 234, 151, 121, 239, 54, 204, 123, 55, 17, 229, 55, 199, 174, 42, 165, 85, 100, 154, 241, 55, 89, 101, 225, 5, 87, 102, 241, 48, 205, 94, 184, 3, 234, 237, 151, 165, 220, 231, 152, 124, 238, 137, 122, 14, 159, 77, 105, 169, 158, 195, 103, 117, 227, 65, 246, 11, 29, 204, 179, 167, 61, 14, 202, 35, 204, 180, 193, 117, 124, 215, 38, 166, 255, 126, 205, 236, 43, 241, 26, 52, 240, 175, 150, 9, 226, 85, 113, 24, 3, 19, 6, 215, 19, 56, 140, 71, 132, 75, 168, 17, 28, 61, 215, 49, 167, 23, 179, 198, 131, 89, 135, 127, 24, 123, 22, 253, 114, 68, 177, 10, 138, 117, 189, 247, 51, 222, 188, 211, 184, 15, 155, 182, 236, 104, 152, 250, 160, 235, 216, 140, 205, 196, 101, 139, 108, 86, 10, 173, 224, 52, 112, 255, 228, 120, 158, 29, 141, 47, 82, 188, 28, 41, 158, 199, 106, 171, 177, 216, 150, 37, 194, 38, 130, 42, 98, 220, 181, 57, 155, 83, 99, 212, 213, 154, 195, 113, 203, 238, 83, 104, 136, 54, 126, 0, 106, 165, 53, 6, 195, 173, 40, 35, 235, 139, 170, 169, 59, 91, 219, 114, 65, 23, 63, 8, 241, 69, 253, 124, 81, 63, 119, 82, 253, 44, 24, 130, 186, 156, 192, 223, 150, 75, 211, 185, 20, 222, 156, 209, 191, 95, 52, 35, 53, 139, 111, 89, 174, 54, 185, 59, 144, 189, 207, 139, 89, 245, 130, 112, 56, 101, 120, 207, 69, 182, 95, 253, 79, 86, 22, 48, 128, 98, 180, 145, 37, 186, 30, 12, 125, 26, 24, 123, 228, 212, 140, 72, 21, 187, 180, 174, 54, 151, 11, 100, 108, 55, 185, 247, 30, 11, 189, 252, 231, 147, 147, 147, 154, 131, 236, 238, 138, 73, 31, 84, 174, 67, 206, 67, 207, 235, 162, 82, 112, 124, 39, 99, 193, 244, 50, 234, 76, 90, 112, 194, 137, 79, 15, 17, 148, 248, 142, 131, 147, 93, 50, 112, 36, 64, 146, 135, 167, 145, 235, 249, 192, 227, 76, 221, 92, 213, 178, 123, 109, 138, 1, 12, 115, 157, 149, 165, 144, 250, 58, 110, 196, 113, 179, 204, 231, 214, 8, 33, 16, 225, 185, 32, 5, 53, 15, 70, 38, 65, 69, 187, 13, 247, 190, 35, 62, 3, 249, 164, 154, 140, 196, 82, 88, 167, 151, 26, 193, 194, 248, 54, 105, 129, 119, 234, 174, 163, 105, 81, 202, 173, 194, 208, 229, 71, 178, 39, 54, 85, 70, 228, 14, 37, 24, 80, 2, 207, 110, 40, 91, 145, 54, 247, 50, 212, 139, 57, 22, 218, 195, 46, 82, 4, 213, 135, 46, 82, 145, 159, 214, 128, 232, 87, 213, 123, 251, 85, 223, 207, 197, 109, 68, 136, 219, 69, 79, 34, 154, 67, 56, 44, 21, 12, 210, 52, 43, 245, 48, 16, 140, 77, 214, 143, 249, 165, 219, 105, 38, 178, 13, 193, 117, 0, 202, 62, 83, 43, 213, 252, 187, 248, 240, 79, 119, 41, 188, 225, 84, 169, 141, 38, 221, 236, 255, 97, 187, 65, 213, 70, 0, 149, 90, 249, 185, 6, 104, 125, 110, 150, 16, 37, 230, 74, 155, 178, 99, 52, 252, 56, 187, 124, 174, 195, 17, 244, 145, 227, 182, 128, 174, 58, 68, 169, 106, 64, 52, 190, 193, 235, 186, 91, 8, 114, 210, 202, 252, 189, 90, 203, 18, 226, 68, 51, 193, 239, 245, 18, 184, 29, 234, 67, 207, 192, 99, 210, 201, 51, 21, 202, 217, 109, 151, 110, 61, 9, 126, 214, 124, 25, 96, 124, 221, 37, 241, 9, 42, 97, 102, 89, 248, 183, 227, 45, 18, 176, 128, 132, 240, 244, 233, 83, 199, 219, 168, 27, 84, 173, 112, 95, 60, 77, 173, 167, 107, 84, 249, 111, 192, 148, 52, 27, 29, 222, 48, 138, 175, 105, 229, 136, 60, 169, 68, 201, 124, 162, 214, 228, 84, 211, 117, 60, 197, 150, 155, 229, 143, 143, 155, 133, 140, 19, 13, 129, 186, 102, 239, 55, 111, 6, 138, 255, 15, 39, 72, 220, 178, 199, 18, 67, 196, 249, 21, 230, 152, 128, 250, 123, 89, 16, 43, 158, 170, 69, 97, 217, 172, 70, 130, 110, 41, 246, 0, 82, 237, 40, 254, 42, 44, 32, 32, 54, 181, 127, 132, 64, 255, 182, 19, 34, 186, 109, 215, 118, 251, 87, 223, 78, 98, 228, 255, 149, 217, 40, 191, 42, 167, 50, 232, 217, 95, 193, 0, 167, 109, 195, 191, 224, 70, 73, 214, 42, 54, 246, 183, 196, 222, 34, 109, 198, 50, 202, 54, 191, 121, 203, 217, 26, 180, 127, 107, 191, 249, 9, 244, 248, 205, 46, 36, 109, 199, 231, 233, 236, 175, 66, 69, 252, 38, 86, 179, 44, 46, 55, 162, 80, 153, 69, 242, 235, 142, 215, 61, 143, 119, 155, 59, 246, 43, 70, 209, 112, 93, 27, 219, 38, 251, 21, 174, 161, 252, 149, 110, 135, 225, 213, 239, 98, 174, 117, 47, 222, 149, 93, 51, 222, 23, 31, 127, 47, 49, 155, 84, 1, 19, 206, 108, 139, 35, 198, 209, 170, 147, 75, 165, 62, 123, 78, 132, 181, 0, 10, 33, 213, 250, 182, 43, 85, 74, 38, 5, 165, 201, 24, 119, 17, 111, 161, 255, 188, 20, 114, 44, 67, 43, 104, 203, 204, 214, 253, 45, 160, 84, 112, 178, 66, 235, 227, 224, 164, 49, 171, 210, 111, 225, 132, 74, 18, 10, 100, 116, 50, 148, 80, 194, 159, 227, 81, 47, 7, 60, 101, 132, 6, 234, 252, 166, 175, 186, 83, 12, 165, 41, 17, 32, 78, 35, 129, 124, 34, 81, 206, 161, 170, 212, 104, 69, 109, 105, 79, 92, 217, 106, 64, 187, 163, 174, 242, 164, 242, 52, 39, 31, 224, 252, 100, 88, 129, 152, 241, 187, 1, 219, 253, 237, 164, 44, 166, 5, 152, 149, 111, 165, 48, 58, 139, 248, 186, 212, 250, 120, 28, 107, 191, 98, 198, 237, 161, 155, 76, 155, 25, 47, 138, 98, 144, 185, 85, 233, 183, 108, 122, 86, 12, 247, 79, 254, 85, 166, 147, 137, 141, 180, 63, 212, 15, 106, 81, 161, 126, 117, 130, 56, 59, 87, 253, 214, 45, 7, 162, 9, 203, 15, 35, 105, 200, 95, 103, 213, 116, 46, 154, 212, 44, 104, 230, 184, 110, 160, 21, 254, 128, 248, 243, 162, 68, 20, 125, 252, 191, 210, 107, 51, 92, 195, 168, 203, 18, 244, 237, 28, 136, 124, 252, 186, 1, 85, 73, 221, 196, 112, 124, 132, 247, 252, 110, 86, 242, 237, 27, 118, 243, 0, 153, 166, 118, 71, 163, 207, 228, 3, 170, 120, 174, 188, 207, 176, 254, 99, 139, 13, 29, 111, 90, 246, 18, 111, 113, 223, 232, 253, 241, 150, 132, 230, 144, 254, 34, 139, 164, 5, 150, 116, 10, 119, 178, 22, 106, 183, 65, 193, 84, 150, 65, 182, 211, 225, 136, 196, 150, 79, 182, 213, 22, 139, 140, 64, 197, 205, 118, 72, 26, 68, 148, 70, 153, 99, 109, 117, 218, 89, 19, 156, 136, 254, 171, 71, 96, 184, 255, 49, 63, 136, 153, 2, 209, 223, 66, 16, 62, 117, 55, 182, 29, 149, 45, 175, 94, 84, 82, 41, 109, 8, 97, 150, 164, 192, 138, 134, 199, 4, 181, 122, 46, 3, 142, 194, 174, 173, 26, 112, 101, 118, 154, 125, 152, 244, 180, 198, 141, 3, 180, 121, 42, 156, 255, 225, 76, 174, 192, 137, 190, 188, 204, 46, 131, 13, 97, 183, 37, 63, 10, 253, 195, 216, 80, 215, 198, 197, 135, 68, 168, 85, 233, 190, 70, 187, 85, 233, 109, 221, 185, 86, 165, 31, 104, 15, 194, 31, 106, 196, 194, 21, 164, 165, 164, 107, 225, 47, 117, 155, 189, 161, 220, 138, 115, 25, 138, 42, 28, 114, 168, 49, 138, 189, 204, 62, 76, 201, 101, 55, 242, 178, 249, 176, 78, 197, 203, 138, 197, 172, 220, 149, 133, 126, 158, 165, 229, 240, 117, 17, 28, 6, 40, 186, 22, 243, 0, 214, 79, 218, 28, 82, 100, 10, 7, 4, 157, 121, 219, 239, 86, 96, 234, 54, 110, 212, 223, 19, 188, 17, 251, 17, 61, 130, 62, 44, 198, 226, 5, 38, 174, 149, 55, 67, 187, 251, 167, 70, 207, 249, 131, 3, 23, 175, 201, 113, 209, 3, 225, 31, 75, 182, 11, 113, 229, 242, 132, 6, 129, 218, 165, 182, 204, 131, 62, 103, 137, 55, 176, 43, 69, 65, 142, 137, 167, 107, 57, 50, 91, 43, 100, 43, 73, 50, 113, 11, 21, 207, 97, 244, 41, 140, 150, 26, 159, 67, 120, 64, 33, 212, 38, 131, 95, 252, 144, 190, 179, 127, 76, 220, 39, 42, 38, 119, 46, 79, 160, 226, 44, 211, 131, 36, 217, 182, 188, 196, 34, 228, 181, 129, 250, 74, 27, 141, 100, 2, 238, 26, 79, 108, 139, 72, 122, 165, 32, 251, 82, 106, 20, 166, 126, 245, 200, 12, 171, 106, 111, 203, 218, 39, 129, 200, 249, 216, 102, 189, 89, 112, 40, 146, 154, 223, 108, 51, 69, 189, 101, 43, 232, 213, 248, 118, 124, 237, 94, 188, 217, 164, 54, 243, 36, 173, 240, 248, 137, 98, 84, 181, 164, 35, 139, 164, 31, 220, 93, 120, 103, 82, 9, 196, 173, 66, 228, 170, 245, 140, 144, 136, 217, 224, 234, 191, 70, 249, 122, 12, 1, 255, 30, 210, 31, 27, 125, 243, 131, 172, 12, 99, 146, 46, 191, 57, 210, 78, 169, 20, 186, 21, 33, 186, 193, 239, 58, 76, 220, 49, 192, 66, 42, 110, 60, 24, 23, 222, 24, 75, 236, 66, 12, 197, 19, 203, 49, 10, 248, 36, 106, 7, 40, 26, 92, 108, 105, 113, 205, 145, 161, 115, 164, 51, 64, 222, 121, 170, 165, 179, 128, 141, 64, 65, 70, 120, 175, 174, 254, 64, 82, 239, 152, 111, 30, 35, 232, 61, 72, 165, 246, 155, 118, 32, 140, 43, 21, 202, 51, 107, 213, 9, 25, 15, 247, 15, 175, 13, 229, 86, 81, 3, 41, 8, 25, 12, 9, 54, 136, 146, 212, 19, 151, 18, 54, 182, 109, 201, 196, 214, 104, 239, 176, 88, 206, 143, 68, 159, 106, 234, 185, 38, 90, 95, 228, 76, 15, 156, 124, 233, 90, 232, 200, 124, 160, 139, 233, 237, 117, 71, 126, 0, 18, 24, 45, 254, 34, 194, 25, 50, 230, 186, 130, 40, 137, 185, 35, 248, 181, 180, 153, 230, 104, 24, 191, 197, 129, 72, 90, 128, 109, 76, 203, 150, 29, 153, 172, 92, 107, 92, 228, 18, 36, 44, 15, 222, 165, 142, 198, 122, 213, 83, 173, 185, 18, 94, 82, 151, 219, 168, 230, 155, 99, 115, 154, 235, 8, 24, 99, 226, 146, 80, 87, 57, 182, 139, 119, 233, 147, 232, 118, 176, 80, 103, 237, 13, 227, 81, 81, 41, 24, 100, 164, 90, 90, 93, 85, 165, 156, 197, 214, 126, 245, 170, 168, 170, 252, 221, 232, 74, 217, 178, 108, 125, 110, 240, 102, 93, 70, 215, 197, 254, 24, 46, 206, 77, 167, 162, 106, 38, 205, 97, 12, 91, 146, 3, 252, 94, 182, 238, 248, 56, 196, 178, 162, 35, 89, 162, 35, 211, 55, 245, 44, 239, 202, 90, 188, 29, 181, 166, 68, 196, 21, 71, 90, 226, 238, 87, 47, 5, 235, 29, 148, 255, 208, 29, 70, 16, 220, 189, 18, 192, 81, 17, 79, 162, 201, 116, 66, 94, 189, 146, 87, 84, 30, 105, 139, 84, 59, 94, 148, 186, 131, 157, 103, 201, 197, 29, 77, 121, 108, 106, 181, 235, 86, 5, 151, 70, 58, 86, 54, 151, 146, 2, 52, 197, 228, 8, 190, 40, 138, 243, 217, 164, 187, 102, 12, 177, 85, 191, 51, 170, 187, 43, 214, 88, 98, 135, 131, 53, 53, 68, 75, 53, 222, 21, 89, 200, 115, 122, 179, 149, 14, 49, 94, 180, 166, 37, 196, 209, 42, 159, 243, 166, 96, 73, 69, 78, 93, 33, 202, 164, 174, 46, 138, 177, 169, 231, 41, 115, 113, 79, 244, 58, 17, 225, 35, 53, 7, 197, 232, 96, 252, 170, 132, 109, 167, 252, 125, 182, 87, 204, 198, 120, 167, 174, 63, 199, 153, 94, 187, 238, 21, 227, 79, 136, 116, 60, 232, 155, 52, 101, 0, 227, 192, 208, 215, 27, 223, 84, 137, 139, 73, 114, 106, 226, 231, 158, 139, 31, 18, 136, 188, 6, 244, 200, 153, 248, 84, 56, 129, 174, 16, 161, 162, 86, 44, 166, 160, 223, 25, 122, 90, 21, 125, 35, 93, 210, 142, 228, 178, 54, 29, 240, 111, 184, 116, 67, 178, 136, 154, 9, 17, 159, 112, 209, 135, 58, 14, 146, 254, 175, 163, 184, 110, 0, 39, 236, 82, 213, 131, 0, 232, 106, 8, 197, 157, 17, 49, 229, 50, 170, 38, 4, 143, 133, 233, 82, 85, 77, 110, 36, 72, 33, 134, 183, 180, 164, 168, 32, 56, 106, 181, 223, 239, 123, 60, 143, 232, 54, 59, 233, 12, 79, 203, 70, 248, 205, 160, 193, 166, 182, 69, 25, 67, 163, 224, 153, 248, 155, 215, 83, 162, 233, 229, 171, 42, 236, 207, 253, 208, 86, 198, 165, 226, 171, 172, 58, 249, 183, 247, 38, 213, 224, 128, 141, 181, 146, 92, 73, 80, 21, 112, 172, 2, 138, 37, 102, 43, 110, 72, 173, 226, 203, 73, 58, 20, 125, 252, 32, 77, 80, 177, 132, 200, 71, 163, 35, 101, 53, 138, 79, 207, 198, 195, 107, 139, 183, 4, 3, 155, 43, 242, 9, 182, 87, 224, 241, 104, 154, 150, 211, 144, 81, 224, 236, 178, 48, 58, 230, 227, 233, 47, 26, 91, 106, 59, 155, 46, 80, 31, 151, 120, 131, 251, 196, 165, 19, 88, 195, 128, 72, 47, 131, 248, 225, 232, 88, 241, 82, 35, 101, 188, 206, 64, 157, 140, 33, 103, 233, 101, 52, 185, 46, 196, 238, 74, 242, 129, 122, 136, 60, 77, 186, 221, 126, 242, 248, 113, 242, 96, 11, 54, 175, 183, 57, 97, 15, 211, 241, 169, 81, 8, 91, 140, 94, 208, 160, 236, 42, 131, 183, 161, 250, 165, 145, 23, 75, 158, 241, 0, 2, 181, 149, 223, 73, 247, 197, 247, 193, 42, 214, 40, 179, 137, 224, 84, 29, 171, 14, 165, 229, 115, 87, 55, 248, 223, 234, 181, 217, 114, 255, 195, 186, 25, 195, 173, 173, 211, 144, 117, 5, 19, 86, 155, 26, 226, 127, 57, 16, 53, 77, 21, 15, 1, 77, 233, 241, 127, 75, 85, 177, 134, 9, 182, 232, 76, 137, 17, 172, 228, 184, 4, 133, 227, 109, 5, 108, 26, 22, 17, 216, 118, 74, 58, 108, 199, 147, 17, 211, 66, 145, 92, 14, 251, 117, 65, 73, 195, 37, 73, 76, 60, 223, 102, 227, 136, 136, 46, 173, 125, 164, 41, 111, 222, 140, 18, 238, 250, 156, 148, 197, 133, 142, 4, 160, 27, 51, 48, 10, 236, 65, 31, 83, 209, 213, 255, 46, 172, 180, 108, 212, 213, 138, 72, 107, 36, 18, 185, 33, 65, 111, 33, 243, 4, 62, 143, 20, 186, 91, 132, 187, 124, 50, 149, 250, 234, 89, 12, 141, 82, 41, 95, 253, 172, 231, 215, 49, 82, 20, 180, 144, 141, 162, 86, 36, 106, 233, 66, 112, 96, 235, 151, 101, 172, 80, 8, 236, 232, 50, 133, 150, 169, 183, 1, 104, 201, 54, 134, 128, 190, 111, 39, 97, 100, 150, 156, 21, 189, 92, 146, 156, 231, 225, 182, 1, 3, 226, 207, 103, 154, 222, 212, 62, 48, 112, 90, 25, 8, 225, 238, 221, 136, 149, 160, 17, 155, 135, 52, 45, 45, 7, 9, 240, 200, 43, 68, 123, 167, 213, 164, 89, 60, 211, 187, 133, 9, 11, 58, 122, 83, 66, 210, 183, 78, 210, 152, 134, 30, 107, 54, 114, 121, 166, 162, 118, 248, 122, 228, 133, 155, 10, 223, 132, 204, 38, 188, 73, 81, 213, 134, 61, 15, 179, 15, 7, 39, 100, 135, 153, 192, 183, 51, 74, 81, 121, 59, 113, 122, 50, 17, 229, 104, 115, 128, 136, 227, 245, 195, 10, 53, 140, 224, 39, 181, 230, 157, 20, 173, 27, 175, 231, 10, 217, 18, 155, 166, 249, 232, 21, 246, 14, 240, 91, 103, 181, 156, 131, 123, 227, 236, 242, 200, 160, 74, 123, 100, 92, 141, 166, 132, 9, 143, 96, 126, 59, 250, 153, 169, 123, 196, 80, 30, 38, 51, 100, 183, 133, 215, 159, 104, 130, 236, 48, 6, 54, 54, 89, 229, 98, 139, 156, 169, 58, 246, 152, 149, 246, 49, 93, 15, 225, 162, 42, 247, 120, 75, 27, 250, 189, 187, 238, 37, 148, 137, 206, 20, 24, 67, 116, 227, 147, 69, 251, 53, 109, 72, 87, 177, 133, 109, 88, 153, 209, 213, 45, 41, 113, 55, 151, 184, 132, 104, 205, 139, 220, 47, 179, 220, 127, 236, 44, 183, 208, 156, 179, 171, 173, 221, 197, 167, 29, 89, 193, 234, 185, 184, 110, 78, 229, 86, 204, 143, 87, 110, 152, 114, 191, 199, 160, 152, 238, 11, 19, 255, 224, 4, 226, 249, 127, 81, 155, 100, 230, 196, 138, 9, 83, 177, 25, 210, 200, 145, 237, 186, 188, 104, 176, 111, 67, 14, 109, 135, 66, 109, 2, 179, 166, 249, 66, 227, 97, 25, 169, 212, 59, 141, 5, 254, 36, 220, 203, 154, 125, 28, 72, 192, 239, 93, 61, 64, 250, 67, 43, 239, 184, 130, 21, 73, 197, 93, 155, 136, 59, 156, 0, 44, 144, 132, 59, 212, 197, 80, 70, 49, 227, 77, 193, 110, 211, 206, 91, 46, 63, 26, 229, 24, 91, 98, 103, 178, 32, 85, 249, 160, 187, 116, 21, 243, 27, 47, 64, 219, 42, 117, 238, 49, 214, 162, 119, 230, 219, 109, 35, 97, 103, 247, 41, 39, 238, 240, 145, 16, 128, 13, 15, 211, 153, 203, 1, 247, 152, 79, 246, 60, 166, 41, 60, 151, 59, 157, 230, 0, 188, 62, 187, 83, 123, 96, 47, 80, 241, 175, 236, 204, 210, 92, 210, 18, 220, 151, 45, 43, 103, 110, 148, 71, 143, 26, 28, 193, 149, 58, 159, 212, 210, 19, 172, 72, 77, 103, 64, 3, 225, 22, 57, 130, 53, 78, 215, 241, 4, 223, 212, 230, 21, 75, 140, 208, 188, 133, 181, 177, 189, 188, 189, 171, 235, 186, 173, 205, 232, 207, 227, 180, 174, 228, 65, 240, 108, 146, 170, 224, 89, 114, 22, 252, 90, 82, 15, 112, 67, 22, 187, 18, 113, 120, 31, 92, 80, 67, 153, 118, 162, 76, 89, 216, 56, 140, 84, 63, 130, 160, 117, 225, 154, 243, 170, 108, 36, 21, 71, 64, 79, 8, 251, 245, 108, 43, 36, 36, 205, 63, 89, 20, 115, 105, 133, 48, 92, 142, 67, 75, 99, 21, 83, 97, 182, 68, 147, 153, 175, 203, 181, 82, 100, 64, 31, 66, 20, 109, 197, 74, 70, 242, 52, 154, 61, 154, 76, 45, 123, 83, 55, 192, 214, 200, 73, 76, 167, 105, 24, 45, 173, 122, 191, 55, 55, 163, 214, 204, 161, 200, 70, 90, 212, 111, 204, 227, 129, 37, 173, 228, 36, 179, 6, 123, 170, 142, 97, 251, 231, 167, 19, 60, 239, 68, 44, 127, 206, 175, 193, 211, 212, 166, 107, 199, 111, 232, 152, 201, 57, 132, 242, 108, 124, 215, 254, 248, 136, 85, 141, 73, 145, 58, 104, 219, 75, 14, 145, 48, 70, 59, 212, 224, 220, 2, 11, 142, 3, 49, 116, 124, 41, 134, 166, 195, 202, 144, 216, 88, 105, 57, 69, 19, 107, 9, 170, 80, 67, 157, 119, 135, 110, 20, 216, 116, 83, 59, 119, 184, 227, 135, 21, 247, 5, 19, 158, 194, 113, 99, 120, 67, 55, 247, 112, 151, 7, 122, 224, 164, 164, 248, 1, 225, 62, 34, 85, 161, 151, 186, 226, 9, 38, 252, 86, 208, 237, 130, 43, 151, 238, 9, 179, 250, 210, 40, 192, 110, 2, 238, 102, 112, 0, 178, 237, 218, 234, 162, 72, 160, 114, 89, 92, 184, 21, 45, 70, 61, 3, 220, 122, 249, 10, 119, 93, 24, 45, 30, 217, 79, 49, 155, 50, 184, 107, 34, 102, 146, 66, 152, 206, 240, 123, 77, 29, 31, 193, 51, 119, 251, 213, 254, 120, 36, 160, 137, 97, 125, 145, 150, 167, 153, 187, 49, 100, 198, 152, 30, 180, 99, 223, 52, 75, 81, 251, 254, 250, 92, 181, 192, 166, 111, 19, 235, 168, 20, 10, 62, 219, 33, 43, 37, 36, 18, 147, 242, 20, 214, 162, 76, 229, 108, 59, 154, 134, 31, 147, 28, 12, 22, 153, 32, 115, 193, 194, 74, 128, 53, 241, 56, 212, 229, 26, 172, 43, 184, 197, 50, 38, 158, 224, 229, 206, 103, 48, 202, 136, 115, 53, 198, 157, 153, 102, 77, 117, 44, 87, 195, 68, 104, 168, 225, 154, 248, 201, 96, 247, 135, 12, 0, 38, 13, 207, 205, 84, 1, 142, 26, 20, 176, 245, 10, 225, 141, 253, 235, 51, 146, 4, 54, 15, 35, 65, 107, 187, 42, 180, 82, 221, 88, 221, 93, 11, 230, 230, 168, 248, 38, 125, 184, 82, 96, 219, 64, 140, 188, 105, 86, 88, 4, 186, 94, 119, 107, 109, 173, 25, 222, 246, 92, 240, 98, 159, 250, 107, 1, 230, 145, 114, 1, 239, 205, 53, 167, 57, 250, 142, 196, 159, 199, 137, 135, 206, 14, 156, 97, 119, 29, 73, 190, 103, 142, 54, 155, 107, 67, 199, 174, 252, 109, 165, 246, 75, 120, 112, 98, 44, 119, 18, 3, 136, 119, 98, 2, 195, 41, 132, 235, 136, 199, 184, 221, 13, 255, 126, 240, 182, 196, 197, 248, 211, 201, 76, 149, 123, 20, 211, 42, 116, 182, 130, 201, 71, 55, 4, 200, 138, 102, 162, 13, 168, 233, 46, 0, 24, 191, 80, 176, 213, 36, 29, 187, 42, 209, 204, 74, 90, 25, 182, 155, 205, 16, 212, 60, 26, 7, 70, 57, 160, 112, 100, 252, 74, 119, 0, 86, 241, 82, 182, 116, 178, 176, 198, 137, 219, 195, 99, 198, 43, 18, 17, 173, 139, 198, 116, 82, 241, 66, 124, 84, 6, 41, 179, 99, 36, 138, 255, 137, 36, 236, 123, 226, 197, 10, 181, 9, 22, 50, 179, 128, 121, 64, 159, 43, 164, 203, 115, 192, 193, 145, 0, 211, 139, 215, 198, 251, 140, 250, 99, 103, 135, 174, 211, 160, 54, 201, 42, 244, 26, 189, 126, 212, 160, 30, 11, 11, 223, 100, 221, 192, 26, 182, 244, 17, 45, 205, 207, 223, 56, 94, 98, 162, 64, 94, 135, 116, 71, 110, 78, 253, 206, 53, 208, 118, 11, 74, 53, 107, 14, 41, 152, 160, 121, 243, 91, 38, 39, 208, 13, 153, 15, 124, 228, 241, 101, 75, 238, 224, 103, 152, 101, 137, 185, 79, 47, 31, 181, 42, 216, 119, 36, 48, 120, 38, 152, 99, 112, 237, 211, 192, 78, 135, 22, 58, 7, 204, 97, 180, 57, 1, 236, 119, 34, 146, 182, 163, 233, 24, 166, 60, 8, 69, 84, 187, 115, 240, 55, 124, 252, 18, 107, 89, 209, 9, 100, 246, 154, 255, 236, 177, 180, 68, 213, 97, 86, 154, 226, 101, 238, 179, 195, 112, 98, 232, 85, 145, 227, 54, 74, 108, 23, 215, 148, 217, 157, 98, 88, 121, 206, 50, 67, 15, 206, 210, 18, 221, 12, 2, 66, 95, 104, 137, 174, 5, 249, 84, 101, 76, 171, 97, 72, 73, 29, 5, 83, 212, 54, 208, 20, 111, 178, 115, 64, 49, 4, 97, 162, 216, 211, 173, 246, 144, 155, 122, 182, 103, 148, 203, 173, 169, 209, 60, 139, 80, 142, 9, 45, 135, 166, 98, 54, 24, 188, 45, 211, 75, 76, 195, 112, 36, 4, 40, 177, 194, 49, 40, 138, 115, 76, 193, 108, 178, 9, 235, 66, 54, 0, 56, 189, 100, 223, 177, 198, 166, 120, 107, 237, 14, 20, 202, 209, 81, 118, 138, 230, 24, 59, 25, 150, 94, 186, 17, 145, 94, 233, 128, 33, 171, 130, 62, 106, 106, 184, 86, 172, 221, 5, 77, 47, 245, 161, 54, 110, 76, 250, 134, 32, 41, 106, 236, 75, 122, 90, 173, 191, 67, 126, 62, 118, 187, 73, 62, 90, 171, 83, 239, 35, 234, 58, 158, 141, 74, 189, 56, 4, 171, 245, 136, 125, 106, 96, 105, 59, 245, 227, 74, 109, 93, 232, 146, 169, 99, 169, 192, 216, 42, 30, 98, 242, 46, 63, 157, 115, 26, 10, 217, 27, 2, 138, 107, 108, 232, 97, 125, 44, 190, 61, 237, 208, 53, 0, 22, 131, 148, 138, 143, 255, 27, 191, 5, 209, 18, 220, 127, 190, 12, 196, 0, 78, 28, 53, 248, 26, 71, 78, 126, 13, 162, 87, 140, 134, 203, 192, 78, 128, 137, 35, 23, 71, 44, 140, 212, 73, 254, 33, 91, 6, 86, 8, 39, 138, 214, 116, 26, 197, 11, 62, 133, 237, 157, 84, 88, 189, 213, 18, 80, 83, 144, 162, 200, 229, 81, 220, 242, 48, 106, 213, 133, 208, 125, 75, 64, 12, 225, 68, 209, 194, 175, 81, 212, 212, 215, 32, 122, 226, 207, 121, 182, 12, 252, 16, 80, 28, 65, 252, 28, 199, 80, 125, 142, 120, 116, 151, 129, 223, 236, 93, 28, 185, 89, 92, 20, 240, 91, 24, 173, 201, 82, 208, 154, 212, 160, 53, 169, 65, 107, 226, 160, 245, 172, 26, 164, 147, 108, 119, 42, 138, 190, 155, 77, 85, 38, 235, 247, 118, 86, 206, 199, 147, 25, 168, 105, 58, 89, 189, 103, 235, 208, 112, 128, 144, 174, 215, 75, 190, 233, 124, 211, 75, 58, 95, 255, 58, 43, 166, 59, 157, 160, 243, 61, 29, 15, 206, 132, 113, 11, 7, 107, 175, 79, 26, 9, 172, 253, 18, 83, 117, 227, 155, 199, 41, 158, 236, 125, 210, 249, 70, 144, 42, 72, 21, 137, 223, 186, 232, 208, 83, 40, 115, 36, 73, 154, 70, 148, 94, 49, 158, 14, 138, 81, 1, 43, 214, 145, 206, 11, 118, 45, 237, 167, 1, 46, 208, 53, 168, 155, 96, 229, 154, 238, 41, 60, 221, 254, 65, 221, 120, 23, 193, 146, 238, 90, 115, 250, 186, 29, 4, 72, 139, 246, 15, 234, 214, 116, 79, 34, 217, 190, 119, 56, 209, 207, 202, 209, 245, 59, 22, 154, 234, 91, 241, 227, 89, 153, 157, 212, 244, 8, 145, 107, 100, 199, 108, 74, 82, 226, 237, 143, 115, 181, 162, 53, 41, 108, 101, 176, 201, 148, 172, 75, 101, 240, 221, 16, 119, 106, 197, 151, 77, 241, 76, 150, 171, 38, 106, 16, 139, 196, 60, 1, 16, 139, 170, 246, 189, 101, 57, 221, 113, 102, 221, 202, 224, 122, 40, 51, 26, 21, 151, 106, 87, 21, 22, 17, 22, 71, 13, 63, 180, 237, 138, 144, 97, 207, 117, 218, 179, 224, 84, 75, 156, 4, 207, 139, 242, 89, 58, 56, 195, 21, 197, 187, 116, 112, 126, 50, 150, 227, 33, 140, 219, 196, 219, 81, 212, 99, 19, 94, 167, 31, 201, 85, 250, 17, 89, 163, 235, 236, 81, 226, 219, 252, 139, 115, 189, 21, 94, 187, 34, 39, 120, 147, 175, 2, 123, 187, 100, 55, 157, 116, 150, 234, 238, 176, 89, 80, 117, 99, 247, 83, 6, 124, 156, 143, 50, 209, 70, 119, 171, 151, 208, 90, 148, 135, 113, 157, 25, 62, 72, 144, 77, 223, 202, 175, 244, 86, 5, 49, 86, 114, 145, 40, 138, 153, 24, 28, 153, 36, 228, 200, 251, 4, 149, 34, 113, 153, 106, 185, 46, 214, 39, 176, 214, 20, 85, 159, 141, 167, 229, 149, 160, 128, 113, 149, 232, 182, 253, 22, 201, 94, 56, 128, 169, 9, 170, 52, 61, 148, 146, 224, 192, 49, 23, 208, 6, 63, 37, 52, 135, 116, 136, 123, 3, 188, 216, 147, 173, 153, 63, 71, 62, 51, 127, 37, 250, 58, 103, 154, 80, 91, 163, 38, 71, 168, 205, 103, 229, 143, 131, 232, 138, 140, 89, 242, 63, 117, 217, 50, 95, 127, 246, 28, 95, 7, 81, 113, 58, 144, 226, 116, 192, 196, 201, 12, 226, 193, 66, 2, 53, 151, 171, 139, 227, 28, 240, 115, 205, 205, 178, 114, 157, 15, 218, 168, 214, 57, 5, 44, 109, 243, 226, 53, 51, 244, 65, 148, 151, 145, 162, 148, 149, 149, 99, 244, 226, 239, 57, 110, 164, 52, 184, 219, 14, 108, 6, 82, 235, 162, 176, 50, 98, 1, 81, 95, 135, 217, 166, 170, 149, 12, 199, 31, 109, 238, 115, 54, 117, 143, 131, 149, 67, 61, 21, 175, 89, 140, 73, 179, 208, 201, 49, 48, 174, 48, 218, 47, 245, 73, 17, 157, 37, 179, 49, 254, 9, 40, 193, 166, 82, 112, 115, 130, 47, 110, 80, 148, 67, 233, 174, 253, 221, 99, 103, 233, 160, 13, 170, 85, 72, 148, 139, 190, 221, 120, 166, 92, 168, 205, 188, 69, 233, 229, 145, 116, 126, 138, 47, 155, 96, 193, 104, 118, 25, 207, 46, 212, 151, 117, 85, 72, 51, 130, 254, 34, 83, 128, 227, 51, 245, 8, 25, 144, 225, 120, 30, 23, 231, 135, 66, 101, 40, 163, 172, 99, 138, 235, 147, 37, 206, 232, 214, 213, 125, 153, 190, 52, 181, 72, 7, 97, 119, 77, 118, 195, 238, 240, 104, 164, 173, 215, 86, 150, 169, 217, 233, 249, 238, 47, 127, 97, 116, 59, 75, 43, 69, 51, 241, 20, 178, 93, 196, 235, 232, 236, 7, 201, 126, 196, 247, 14, 131, 120, 158, 93, 105, 144, 240, 24, 130, 9, 239, 107, 129, 66, 129, 142, 187, 94, 251, 29, 24, 249, 17, 166, 120, 66, 11, 246, 145, 166, 73, 15, 122, 209, 147, 13, 127, 116, 249, 80, 43, 5, 144, 101, 19, 73, 7, 172, 105, 85, 46, 84, 220, 159, 154, 195, 233, 126, 36, 46, 20, 199, 206, 160, 180, 193, 15, 241, 135, 158, 15, 81, 44, 173, 1, 53, 108, 250, 8, 246, 86, 79, 182, 229, 56, 167, 235, 50, 92, 221, 42, 154, 232, 143, 174, 33, 251, 143, 49, 96, 94, 76, 207, 178, 114, 225, 169, 197, 124, 107, 55, 177, 68, 76, 52, 21, 220, 135, 168, 244, 112, 18, 65, 220, 56, 207, 224, 87, 65, 87, 169, 214, 137, 234, 192, 14, 236, 248, 227, 20, 30, 88, 13, 198, 171, 1, 19, 133, 168, 165, 127, 110, 130, 9, 108, 231, 31, 125, 185, 29, 216, 255, 147, 43, 209, 97, 207, 183, 28, 181, 190, 255, 149, 79, 207, 112, 2, 215, 160, 123, 172, 77, 102, 147, 123, 54, 159, 48, 202, 117, 220, 139, 111, 149, 215, 6, 48, 224, 252, 148, 149, 85, 38, 1, 222, 206, 113, 166, 40, 46, 50, 220, 71, 184, 212, 138, 228, 53, 23, 31, 109, 82, 115, 51, 132, 227, 236, 18, 170, 117, 109, 244, 129, 64, 74, 169, 205, 224, 16, 200, 208, 169, 3, 35, 203, 166, 252, 227, 39, 6, 203, 77, 247, 174, 150, 118, 150, 252, 1, 49, 20, 230, 54, 140, 130, 214, 252, 210, 236, 249, 144, 69, 31, 185, 25, 165, 165, 93, 223, 198, 200, 144, 173, 134, 52, 172, 161, 52, 234, 113, 75, 119, 88, 173, 190, 247, 78, 26, 54, 203, 210, 123, 114, 40, 144, 69, 155, 211, 89, 120, 126, 141, 178, 4, 165, 128, 154, 199, 9, 203, 15, 246, 7, 41, 113, 64, 213, 194, 124, 36, 224, 234, 196, 33, 67, 147, 114, 249, 41, 63, 57, 201, 202, 108, 60, 200, 110, 169, 106, 177, 8, 46, 162, 88, 34, 26, 255, 51, 235, 139, 146, 74, 232, 23, 165, 241, 41, 148, 198, 48, 27, 101, 211, 236, 46, 234, 141, 86, 221, 113, 117, 64, 43, 217, 63, 186, 186, 184, 200, 166, 101, 62, 248, 92, 74, 64, 245, 176, 189, 199, 79, 234, 5, 245, 163, 19, 238, 66, 192, 89, 113, 239, 109, 206, 133, 230, 150, 197, 24, 139, 175, 110, 231, 159, 157, 90, 113, 230, 126, 5, 129, 156, 130, 159, 78, 110, 233, 172, 100, 17, 92, 100, 86, 90, 120, 234, 121, 26, 158, 121, 98, 233, 135, 231, 177, 94, 255, 131, 253, 208, 38, 245, 200, 117, 230, 29, 119, 12, 60, 78, 151, 65, 116, 62, 159, 79, 96, 229, 116, 187, 57, 93, 163, 248, 73, 121, 253, 241, 124, 188, 62, 159, 246, 94, 242, 44, 29, 73, 94, 211, 160, 128, 23, 100, 153, 159, 242, 234, 223, 16, 143, 8, 125, 187, 107, 243, 53, 199, 126, 225, 169, 250, 203, 90, 255, 254, 153, 237, 190, 52, 220, 110, 187, 124, 193, 245, 124, 67, 55, 107, 132, 255, 159, 121, 118, 153, 13, 119, 203, 50, 189, 250, 113, 6, 214, 238, 254, 201, 97, 150, 159, 228, 16, 114, 145, 194, 91, 217, 140, 73, 41, 251, 110, 118, 146, 196, 174, 147, 146, 21, 116, 20, 58, 226, 177, 99, 155, 54, 74, 67, 128, 128, 235, 222, 0, 146, 190, 226, 134, 221, 149, 240, 83, 54, 77, 7, 103, 217, 80, 226, 3, 197, 79, 50, 18, 213, 35, 127, 199, 84, 11, 83, 225, 6, 5, 168, 103, 42, 106, 85, 69, 58, 173, 27, 137, 106, 44, 111, 102, 104, 121, 157, 148, 132, 219, 75, 30, 208, 128, 19, 122, 7, 148, 188, 149, 122, 203, 221, 117, 216, 157, 74, 26, 80, 28, 233, 120, 168, 161, 144, 253, 105, 30, 67, 77, 131, 24, 113, 35, 251, 13, 223, 169, 203, 173, 8, 3, 201, 10, 45, 208, 85, 2, 195, 54, 206, 99, 29, 147, 1, 57, 52, 84, 110, 92, 205, 202, 12, 16, 145, 5, 65, 130, 104, 141, 180, 60, 165, 193, 66, 246, 38, 10, 149, 116, 193, 214, 196, 151, 186, 123, 145, 246, 161, 200, 14, 25, 109, 221, 101, 127, 154, 130, 73, 202, 194, 14, 206, 85, 169, 142, 20, 233, 212, 209, 5, 38, 41, 222, 101, 11, 54, 112, 189, 166, 217, 2, 53, 114, 56, 144, 7, 113, 96, 151, 108, 96, 11, 234, 113, 30, 52, 157, 224, 39, 192, 225, 170, 84, 75, 46, 186, 47, 202, 231, 250, 1, 205, 238, 16, 216, 112, 237, 20, 88, 238, 155, 42, 249, 134, 96, 244, 77, 50, 81, 119, 243, 114, 59, 15, 167, 68, 241, 61, 112, 117, 137, 138, 149, 32, 151, 151, 4, 242, 112, 184, 201, 211, 90, 119, 104, 159, 17, 214, 131, 83, 233, 178, 161, 173, 183, 190, 58, 110, 213, 249, 235, 95, 21, 146, 166, 119, 137, 220, 83, 150, 4, 32, 253, 247, 7, 90, 104, 239, 124, 152, 78, 51, 7, 71, 159, 157, 233, 6, 183, 252, 224, 84, 177, 51, 64, 132, 177, 117, 223, 57, 107, 211, 172, 19, 222, 213, 46, 209, 38, 160, 116, 180, 236, 223, 82, 87, 177, 240, 202, 81, 205, 66, 205, 7, 23, 195, 192, 40, 124, 183, 189, 21, 147, 26, 25, 54, 3, 138, 66, 29, 186, 32, 131, 192, 19, 2, 200, 249, 250, 210, 86, 77, 106, 46, 87, 69, 108, 40, 168, 240, 11, 115, 227, 27, 246, 42, 48, 196, 172, 65, 123, 134, 6, 207, 238, 70, 201, 170, 122, 226, 215, 197, 243, 49, 25, 28, 201, 228, 153, 204, 60, 114, 245, 117, 215, 237, 233, 87, 162, 204, 25, 224, 70, 186, 170, 145, 101, 116, 213, 243, 219, 187, 171, 105, 118, 112, 114, 130, 86, 216, 77, 211, 90, 181, 41, 159, 109, 187, 139, 142, 195, 252, 212, 95, 136, 122, 194, 44, 144, 89, 128, 218, 145, 241, 83, 147, 239, 246, 144, 76, 79, 127, 174, 60, 103, 31, 178, 139, 201, 40, 13, 8, 51, 220, 73, 93, 59, 125, 234, 170, 20, 149, 26, 205, 177, 103, 154, 104, 139, 162, 26, 83, 1, 221, 96, 185, 66, 41, 205, 217, 84, 49, 233, 13, 116, 64, 225, 177, 87, 43, 152, 109, 59, 229, 114, 108, 139, 222, 221, 68, 159, 92, 52, 130, 157, 139, 117, 10, 214, 187, 54, 126, 211, 117, 102, 52, 153, 153, 7, 173, 184, 253, 128, 246, 64, 226, 141, 159, 105, 56, 225, 118, 20, 193, 247, 89, 121, 69, 2, 84, 147, 235, 96, 218, 126, 74, 177, 94, 140, 134, 28, 35, 174, 161, 247, 45, 158, 226, 238, 252, 151, 133, 248, 95, 155, 19, 157, 7, 112, 51, 131, 222, 116, 92, 3, 242, 134, 2, 162, 109, 84, 185, 223, 135, 167, 73, 95, 44, 49, 121, 170, 145, 132, 68, 134, 50, 119, 221, 121, 130, 217, 69, 206, 229, 116, 42, 30, 120, 62, 145, 115, 149, 152, 62, 57, 56, 62, 127, 99, 253, 52, 211, 172, 178, 185, 13, 91, 71, 29, 159, 171, 36, 196, 231, 214, 233, 131, 84, 178, 208, 22, 112, 229, 29, 213, 28, 23, 118, 88, 141, 6, 17, 219, 79, 207, 133, 1, 14, 115, 210, 61, 97, 195, 19, 236, 206, 167, 226, 195, 215, 11, 115, 160, 116, 57, 77, 84, 228, 209, 219, 23, 121, 69, 66, 143, 6, 233, 68, 12, 50, 30, 211, 222, 186, 38, 187, 198, 124, 105, 148, 67, 95, 59, 188, 105, 217, 16, 48, 60, 214, 216, 172, 175, 131, 163, 78, 150, 228, 60, 9, 109, 239, 6, 149, 190, 59, 191, 30, 244, 76, 231, 28, 191, 185, 236, 25, 216, 181, 186, 128, 248, 101, 187, 183, 123, 60, 198, 214, 1, 161, 177, 155, 130, 110, 183, 189, 36, 72, 118, 143, 137, 194, 120, 216, 157, 136, 150, 115, 184, 120, 231, 174, 203, 193, 120, 24, 151, 2, 211, 201, 121, 132, 128, 84, 186, 37, 186, 56, 198, 220, 6, 211, 152, 246, 245, 20, 109, 136, 171, 213, 39, 130, 108, 123, 38, 195, 132, 73, 17, 22, 147, 23, 222, 222, 21, 62, 83, 116, 18, 236, 166, 158, 182, 204, 254, 75, 13, 235, 97, 31, 27, 206, 72, 221, 53, 38, 156, 135, 219, 128, 71, 163, 188, 22, 100, 179, 141, 254, 124, 252, 165, 239, 93, 14, 49, 153, 119, 14, 239, 150, 243, 152, 214, 101, 22, 32, 101, 39, 117, 224, 238, 30, 153, 150, 173, 77, 70, 194, 70, 206, 148, 183, 136, 86, 146, 132, 12, 243, 204, 223, 179, 171, 207, 191, 84, 138, 122, 248, 126, 73, 39, 119, 143, 155, 35, 234, 241, 34, 157, 220, 13, 243, 180, 181, 69, 167, 221, 139, 109, 103, 242, 11, 164, 183, 158, 206, 91, 88, 167, 142, 24, 128, 53, 120, 14, 214, 32, 1, 180, 184, 69, 40, 120, 43, 44, 18, 135, 217, 112, 54, 200, 238, 13, 223, 149, 216, 157, 79, 193, 122, 218, 69, 141, 200, 194, 174, 92, 67, 94, 82, 183, 31, 219, 140, 137, 207, 19, 114, 199, 76, 58, 24, 204, 46, 102, 35, 149, 139, 174, 53, 111, 11, 6, 18, 171, 23, 195, 163, 97, 214, 228, 176, 107, 238, 106, 241, 207, 137, 123, 183, 180, 16, 88, 250, 21, 50, 177, 94, 87, 153, 151, 220, 68, 82, 220, 75, 106, 71, 20, 162, 228, 205, 195, 252, 244, 108, 122, 119, 24, 116, 126, 83, 178, 180, 221, 252, 100, 7, 238, 151, 207, 189, 0, 109, 67, 230, 149, 188, 30, 15, 111, 108, 112, 30, 126, 42, 213, 236, 198, 198, 93, 100, 225, 163, 96, 14, 221, 54, 65, 103, 171, 108, 59, 244, 192, 221, 199, 141, 133, 152, 53, 236, 222, 139, 158, 216, 43, 165, 0, 41, 245, 3, 178, 85, 107, 54, 117, 176, 119, 120, 50, 178, 21, 235, 138, 87, 68, 158, 100, 112, 183, 160, 88, 254, 62, 107, 202, 222, 123, 174, 18, 227, 242, 242, 13, 105, 120, 89, 225, 120, 46, 94, 167, 24, 205, 156, 171, 63, 93, 35, 245, 189, 131, 184, 74, 235, 219, 6, 109, 149, 225, 183, 30, 105, 47, 217, 239, 64, 101, 128, 244, 115, 216, 11, 145, 60, 167, 105, 51, 219, 59, 176, 88, 114, 92, 217, 192, 83, 171, 244, 48, 196, 1, 184, 99, 200, 0, 254, 152, 79, 47, 243, 42, 147, 92, 47, 160, 236, 162, 65, 99, 97, 41, 86, 151, 53, 237, 154, 81, 17, 45, 144, 178, 191, 23, 98, 36, 179, 179, 110, 125, 106, 234, 133, 10, 20, 132, 137, 15, 171, 211, 29, 250, 221, 227, 177, 116, 238, 217, 121, 18, 254, 5, 195, 200, 118, 99, 226, 92, 92, 220, 31, 91, 169, 18, 157, 185, 79, 11, 206, 79, 181, 151, 81, 179, 149, 97, 115, 190, 58, 12, 165, 246, 56, 218, 154, 235, 192, 103, 97, 123, 253, 117, 241, 162, 16, 200, 234, 59, 123, 71, 248, 3, 130, 141, 72, 82, 144, 98, 2, 149, 216, 75, 203, 168, 169, 218, 102, 111, 203, 172, 54, 192, 174, 61, 195, 242, 160, 60, 99, 103, 56, 83, 152, 77, 135, 42, 21, 103, 89, 77, 159, 141, 244, 173, 130, 8, 66, 133, 212, 34, 69, 53, 6, 236, 130, 151, 21, 61, 205, 187, 227, 73, 161, 109, 78, 25, 205, 122, 172, 41, 118, 221, 47, 185, 29, 38, 233, 244, 58, 30, 227, 245, 195, 140, 119, 136, 23, 255, 233, 186, 150, 235, 32, 150, 213, 237, 17, 245, 234, 178, 239, 225, 36, 26, 3, 209, 175, 124, 76, 153, 74, 145, 67, 255, 57, 100, 137, 82, 67, 164, 32, 173, 120, 148, 32, 223, 214, 92, 227, 230, 48, 166, 3, 103, 239, 176, 43, 221, 119, 217, 105, 62, 118, 172, 154, 54, 105, 169, 87, 163, 129, 94, 215, 181, 109, 104, 20, 189, 196, 174, 222, 188, 81, 61, 9, 68, 212, 183, 137, 61, 213, 209, 103, 53, 65, 187, 6, 12, 153, 34, 121, 232, 154, 137, 23, 44, 7, 230, 82, 17, 87, 158, 254, 39, 43, 139, 131, 241, 193, 108, 122, 112, 242, 163, 152, 74, 135, 149, 169, 173, 106, 254, 104, 226, 4, 120, 83, 230, 53, 171, 160, 205, 136, 31, 129, 66, 204, 254, 66, 154, 153, 114, 248, 75, 101, 13, 102, 246, 140, 172, 24, 181, 104, 108, 87, 214, 121, 149, 102, 203, 70, 21, 51, 16, 12, 46, 153, 100, 82, 157, 225, 197, 238, 249, 218, 247, 172, 143, 136, 59, 35, 11, 39, 211, 58, 237, 221, 159, 40, 120, 61, 162, 190, 225, 39, 86, 73, 182, 225, 253, 106, 119, 54, 213, 249, 160, 3, 60, 60, 95, 220, 9, 252, 131, 188, 45, 154, 119, 73, 8, 83, 226, 246, 197, 103, 214, 102, 139, 213, 14, 73, 204, 110, 205, 148, 179, 125, 30, 211, 53, 52, 208, 237, 13, 88, 127, 144, 199, 217, 101, 224, 98, 29, 121, 151, 142, 68, 110, 131, 12, 155, 147, 66, 191, 85, 244, 18, 161, 50, 11, 19, 227, 20, 150, 47, 13, 54, 43, 241, 80, 230, 221, 169, 204, 4, 127, 91, 20, 32, 225, 33, 196, 43, 160, 244, 118, 93, 39, 67, 67, 108, 109, 205, 146, 46, 164, 84, 116, 150, 113, 203, 101, 60, 97, 253, 185, 38, 11, 175, 240, 148, 152, 7, 48, 211, 178, 175, 136, 41, 61, 202, 162, 253, 13, 235, 129, 114, 10, 252, 57, 94, 164, 34, 136, 141, 14, 4, 88, 44, 113, 18, 51, 235, 146, 204, 122, 162, 79, 56, 71, 183, 181, 212, 118, 167, 97, 59, 13, 118, 175, 224, 218, 220, 59, 179, 5, 218, 98, 171, 29, 250, 115, 7, 183, 219, 181, 103, 42, 228, 75, 186, 131, 123, 238, 48, 10, 245, 60, 247, 159, 176, 247, 110, 250, 121, 87, 247, 223, 235, 184, 242, 118, 109, 194, 27, 82, 83, 174, 251, 202, 150, 65, 14, 255, 252, 251, 170, 253, 181, 112, 206, 82, 23, 81, 161, 227, 228, 161, 208, 78, 88, 138, 142, 240, 106, 17, 60, 39, 92, 21, 179, 114, 32, 136, 125, 145, 78, 78, 198, 124, 141, 93, 155, 242, 119, 207, 55, 1, 104, 100, 240, 94, 148, 23, 31, 154, 84, 199, 123, 140, 243, 96, 15, 80, 93, 221, 6, 240, 36, 62, 193, 235, 92, 93, 254, 199, 162, 132, 51, 154, 184, 191, 175, 122, 203, 111, 230, 80, 237, 39, 246, 86, 27, 54, 31, 219, 207, 222, 57, 194, 215, 138, 20, 2, 182, 86, 39, 179, 138, 220, 239, 2, 166, 30, 82, 57, 112, 80, 202, 220, 237, 100, 79, 74, 241, 186, 171, 174, 125, 238, 127, 166, 171, 49, 151, 54, 172, 116, 156, 70, 127, 238, 251, 26, 66, 226, 204, 137, 132, 224, 53, 41, 156, 99, 122, 124, 248, 213, 205, 201, 234, 106, 97, 5, 138, 157, 68, 82, 143, 137, 75, 44, 209, 35, 143, 161, 245, 117, 206, 240, 143, 89, 150, 10, 50, 253, 206, 164, 38, 124, 191, 185, 42, 75, 93, 167, 17, 19, 81, 193, 223, 49, 229, 106, 108, 197, 96, 217, 41, 104, 29, 56, 79, 95, 119, 236, 99, 175, 151, 236, 89, 119, 183, 252, 215, 198, 29, 40, 255, 153, 38, 228, 102, 186, 226, 181, 243, 55, 22, 214, 71, 243, 164, 157, 120, 186, 10, 119, 17, 55, 15, 76, 116, 76, 94, 165, 131, 243, 165, 15, 202, 156, 4, 148, 237, 210, 107, 139, 20, 179, 219, 37, 237, 56, 199, 4, 3, 20, 91, 211, 128, 97, 249, 157, 150, 228, 114, 210, 141, 128, 55, 114, 95, 101, 98, 127, 93, 96, 36, 176, 214, 174, 92, 12, 173, 251, 76, 114, 146, 172, 77, 46, 236, 242, 123, 78, 196, 44, 124, 212, 69, 1, 109, 199, 53, 204, 36, 148, 173, 19, 126, 241, 67, 59, 148, 196, 27, 178, 252, 16, 116, 72, 162, 82, 229, 81, 200, 107, 166, 202, 35, 102, 38, 122, 76, 235, 68, 128, 104, 218, 134, 232, 175, 213, 46, 250, 181, 94, 228, 231, 50, 31, 46, 215, 52, 206, 170, 78, 59, 49, 76, 21, 202, 35, 139, 145, 122, 110, 111, 189, 105, 155, 121, 237, 235, 232, 60, 55, 149, 57, 141, 235, 41, 76, 143, 32, 88, 234, 134, 189, 161, 104, 45, 28, 156, 116, 137, 149, 45, 9, 235, 95, 228, 122, 83, 214, 193, 56, 187, 92, 246, 232, 72, 144, 146, 56, 212, 168, 61, 119, 189, 196, 178, 32, 35, 14, 153, 160, 230, 76, 47, 239, 85, 172, 201, 50, 111, 19, 42, 112, 173, 2, 57, 198, 69, 189, 11, 116, 144, 56, 135, 202, 201, 13, 143, 65, 238, 193, 58, 61, 204, 119, 110, 47, 41, 182, 254, 155, 220, 53, 21, 92, 67, 225, 129, 51, 44, 31, 84, 186, 23, 209, 158, 174, 203, 210, 156, 25, 205, 120, 252, 198, 160, 168, 183, 51, 35, 89, 162, 198, 50, 107, 90, 204, 209, 255, 139, 237, 2, 85, 167, 188, 31, 78, 78, 14, 183, 23, 144, 108, 27, 138, 116, 60, 235, 6, 222, 110, 54, 36, 152, 250, 9, 173, 177, 159, 210, 105, 250, 74, 29, 29, 55, 57, 88, 242, 245, 117, 185, 229, 176, 105, 19, 9, 18, 86, 146, 197, 56, 43, 17, 115, 99, 78, 94, 242, 107, 182, 97, 166, 175, 142, 206, 210, 146, 89, 57, 243, 222, 144, 16, 169, 223, 166, 113, 87, 124, 143, 4, 68, 120, 23, 57, 26, 138, 84, 215, 124, 67, 142, 193, 10, 246, 136, 102, 11, 152, 243, 164, 104, 232, 140, 121, 68, 17, 190, 46, 142, 138, 114, 154, 13, 187, 120, 107, 77, 153, 157, 140, 237, 145, 127, 243, 170, 221, 154, 197, 66, 104, 191, 110, 129, 189, 103, 91, 141, 175, 123, 63, 141, 231, 195, 15, 175, 112, 70, 113, 206, 32, 82, 21, 254, 169, 157, 82, 52, 106, 235, 169, 13, 204, 242, 146, 233, 216, 230, 223, 86, 5, 196, 182, 236, 82, 202, 56, 34, 199, 227, 28, 254, 37, 68, 249, 151, 116, 210, 124, 201, 143, 152, 46, 9, 57, 209, 222, 80, 151, 252, 136, 47, 144, 170, 136, 78, 109, 233, 242, 46, 249, 17, 170, 254, 162, 221, 29, 63, 190, 194, 131, 186, 113, 126, 122, 248, 173, 16, 80, 213, 127, 174, 247, 66, 154, 86, 221, 22, 36, 58, 219, 51, 120, 225, 93, 19, 230, 71, 95, 223, 82, 233, 144, 247, 232, 63, 245, 14, 165, 255, 15, 151, 207, 236, 216 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 20996; + return 19546; } uint32_t GetRawScriptsSize() { - return 144981; + return 134160; } } // selfhosted } // js diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/js-confdefs.h b/src/third_party/mozjs/platform/x86_64/macOS/build/js-confdefs.h index 5cc6ab8bd13..cc206127a89 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_CLOCK_MONOTONIC 1 @@ -56,12 +60,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR const -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".dylib" @@ -70,6 +72,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "x86_64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_DARWIN 1 diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/x86_64/macOS/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/x86_64/macOS/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/AtomicOperationsGenerated.h b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/AtomicOperationsGenerated.h index 8502615c0f0..a74121646d4 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/AtomicOperationsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/AtomicOperationsGenerated.h @@ -408,6 +408,9 @@ namespace jit { : "memory", "cc"); return res; } + inline void AtomicPause() { + asm volatile ("pause" :::); + } inline void AtomicCopyUnalignedBlockDownUnsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); @@ -793,7 +796,29 @@ namespace jit { : [dst] "r" (dst_), [src] "r"(src_) : "memory"); } - inline void AtomicCopyByteUnsynchronized(uint8_t* dst, const uint8_t* src) { + inline void AtomicCopy32Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint32_t* dst_ = reinterpret_cast(dst); + const uint32_t* src_ = reinterpret_cast(src); + uint32_t scratch; + asm volatile ("movl 0(%[src]), %[scratch]\n\t" +"movl %[scratch], 0(%[dst])\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy16Unsynchronized(uint8_t* dst, const uint8_t* src) { + uint16_t* dst_ = reinterpret_cast(dst); + const uint16_t* src_ = reinterpret_cast(src); + uint16_t scratch; + asm volatile ("movw 0(%[src]), %[scratch]\n\t" +"movw %[scratch], 0(%[dst])\n\t" + + : [scratch] "=&r" (scratch) + : [dst] "r" (dst_), [src] "r"(src_) + : "memory"); + } + inline void AtomicCopy8Unsynchronized(uint8_t* dst, const uint8_t* src) { uint8_t* dst_ = reinterpret_cast(dst); const uint8_t* src_ = reinterpret_cast(src); uint8_t scratch; diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/js-confdefs.h b/src/third_party/mozjs/platform/x86_64/macOS/include/js-confdefs.h index 5cc6ab8bd13..cc206127a89 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/js-confdefs.h @@ -9,10 +9,14 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_ALLOCA_H 1 #define HAVE_CLOCK_MONOTONIC 1 @@ -56,12 +60,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR const -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "lib" #define MOZ_DLL_SUFFIX ".dylib" @@ -70,6 +72,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "x86_64-gcc3" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define XP_DARWIN 1 diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/js-config.h b/src/third_party/mozjs/platform/x86_64/macOS/include/js-config.h index e6a4e862c32..77afa830384 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/js-config.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +/* #undef XP_WIN */ +#define XP_UNIX 1 +#define XP_DARWIN 1 + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/x86_64/macOS/include/selfhosted.out.h b/src/third_party/mozjs/platform/x86_64/macOS/include/selfhosted.out.h index 61dcac32173..f92431e839c 100644 --- a/src/third_party/mozjs/platform/x86_64/macOS/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/x86_64/macOS/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 237, 125, 253, 119, 27, 55, 174, 232, 239, 254, 43, 38, 58, 189, 173, 188, 150, 189, 150, 147, 126, 108, 236, 164, 235, 186, 73, 215, 111, 147, 56, 199, 78, 119, 207, 185, 126, 57, 185, 19, 105, 236, 204, 90, 214, 168, 51, 82, 28, 183, 205, 251, 219, 31, 65, 130, 36, 192, 143, 153, 145, 44, 39, 182, 111, 114, 78, 235, 209, 12, 9, 130, 32, 0, 130, 32, 8, 158, 204, 198, 131, 105, 94, 140, 147, 113, 118, 241, 230, 48, 27, 20, 229, 176, 187, 154, 252, 177, 146, 36, 101, 54, 157, 149, 227, 164, 154, 14, 223, 28, 188, 253, 79, 54, 152, 190, 25, 148, 89, 58, 205, 186, 227, 217, 104, 180, 186, 189, 242, 113, 229, 68, 215, 125, 85, 252, 84, 20, 163, 44, 29, 119, 223, 179, 186, 247, 238, 189, 119, 202, 189, 152, 157, 191, 205, 74, 167, 216, 26, 47, 117, 148, 158, 103, 255, 74, 71, 179, 236, 191, 179, 178, 232, 126, 232, 37, 151, 172, 244, 135, 228, 209, 163, 71, 201, 101, 242, 231, 159, 73, 247, 67, 114, 79, 60, 127, 72, 190, 254, 90, 188, 128, 199, 75, 142, 216, 47, 217, 244, 121, 54, 125, 87, 12, 187, 255, 234, 37, 47, 21, 152, 237, 109, 241, 191, 247, 105, 153, 64, 169, 228, 81, 242, 175, 227, 151, 175, 225, 85, 126, 146, 116, 247, 171, 23, 162, 115, 7, 229, 175, 227, 97, 118, 146, 143, 179, 97, 23, 10, 173, 170, 138, 6, 131, 153, 254, 10, 213, 62, 98, 213, 123, 251, 213, 94, 58, 26, 165, 111, 71, 25, 175, 244, 234, 93, 89, 92, 188, 186, 156, 100, 79, 202, 178, 40, 187, 253, 173, 94, 50, 21, 191, 138, 19, 137, 192, 170, 134, 129, 176, 225, 29, 235, 194, 126, 245, 178, 44, 38, 89, 57, 189, 252, 103, 118, 217, 77, 203, 211, 217, 121, 54, 158, 42, 224, 208, 11, 128, 37, 122, 129, 32, 245, 247, 109, 11, 81, 21, 16, 180, 233, 84, 211, 50, 31, 159, 118, 128, 114, 228, 229, 229, 249, 219, 98, 212, 225, 35, 48, 201, 6, 121, 86, 237, 21, 99, 81, 101, 54, 152, 10, 180, 139, 183, 255, 233, 37, 162, 219, 233, 108, 52, 37, 239, 29, 146, 194, 43, 129, 140, 40, 188, 49, 176, 133, 52, 117, 213, 87, 209, 168, 33, 160, 67, 88, 31, 190, 67, 97, 197, 136, 18, 80, 140, 190, 223, 126, 215, 75, 58, 133, 44, 247, 77, 149, 124, 67, 208, 248, 38, 153, 32, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 154, 229, 163, 105, 62, 62, 146, 68, 233, 118, 42, 69, 136, 206, 106, 13, 135, 84, 46, 123, 212, 247, 98, 159, 145, 213, 86, 134, 111, 149, 228, 97, 75, 87, 248, 119, 152, 77, 138, 114, 250, 107, 149, 158, 102, 123, 197, 108, 60, 21, 210, 227, 55, 208, 75, 238, 203, 46, 169, 102, 172, 236, 234, 134, 29, 26, 201, 50, 253, 7, 61, 249, 183, 243, 247, 191, 99, 55, 13, 125, 18, 193, 73, 134, 132, 132, 130, 29, 81, 193, 19, 48, 11, 118, 99, 99, 67, 240, 95, 165, 112, 159, 150, 151, 216, 135, 129, 16, 139, 167, 88, 161, 11, 234, 68, 255, 120, 147, 78, 38, 163, 203, 158, 131, 93, 207, 178, 71, 47, 145, 240, 100, 47, 4, 152, 233, 224, 93, 210, 205, 28, 106, 103, 186, 143, 219, 46, 98, 187, 167, 167, 101, 118, 42, 52, 214, 18, 176, 227, 176, 150, 134, 226, 62, 140, 231, 56, 29, 45, 1, 67, 6, 106, 57, 8, 2, 167, 155, 134, 69, 21, 242, 105, 175, 152, 92, 254, 156, 78, 83, 212, 77, 130, 121, 186, 83, 209, 78, 54, 237, 37, 85, 49, 43, 7, 89, 47, 201, 62, 12, 70, 179, 97, 54, 220, 159, 102, 231, 21, 209, 19, 219, 53, 162, 36, 171, 58, 242, 68, 69, 245, 164, 44, 206, 133, 180, 190, 42, 80, 17, 96, 5, 173, 126, 206, 178, 75, 16, 102, 31, 185, 131, 82, 16, 251, 224, 98, 44, 84, 168, 69, 20, 128, 185, 104, 106, 220, 20, 36, 33, 140, 114, 178, 11, 226, 115, 34, 148, 89, 23, 90, 205, 5, 254, 98, 82, 74, 54, 183, 241, 113, 71, 34, 178, 49, 202, 198, 167, 211, 119, 248, 114, 109, 77, 67, 65, 68, 69, 5, 40, 117, 44, 191, 190, 222, 54, 58, 0, 197, 254, 222, 187, 180, 18, 8, 3, 34, 30, 41, 191, 254, 26, 11, 121, 156, 129, 19, 181, 150, 227, 253, 234, 201, 88, 76, 7, 37, 76, 74, 186, 191, 2, 224, 170, 172, 110, 85, 204, 207, 146, 252, 132, 98, 151, 134, 70, 178, 121, 168, 120, 44, 158, 94, 19, 29, 243, 113, 165, 150, 27, 126, 29, 159, 8, 69, 154, 149, 98, 80, 57, 95, 16, 70, 184, 57, 60, 128, 22, 205, 231, 30, 250, 69, 135, 115, 137, 35, 89, 204, 96, 130, 97, 246, 150, 249, 150, 143, 199, 230, 155, 249, 218, 57, 41, 138, 142, 164, 11, 83, 29, 187, 101, 153, 94, 62, 121, 159, 149, 151, 178, 87, 111, 211, 193, 217, 201, 56, 177, 86, 203, 1, 29, 193, 233, 187, 188, 50, 227, 39, 72, 39, 191, 61, 147, 36, 236, 30, 32, 45, 205, 240, 236, 162, 133, 83, 97, 129, 85, 57, 86, 155, 49, 107, 224, 219, 94, 178, 41, 12, 2, 137, 207, 134, 32, 228, 180, 0, 211, 103, 35, 3, 212, 172, 25, 224, 26, 112, 22, 231, 58, 51, 238, 103, 97, 46, 159, 79, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 68, 135, 124, 180, 31, 39, 253, 228, 71, 57, 79, 225, 167, 110, 127, 53, 121, 200, 141, 75, 195, 104, 103, 138, 201, 206, 4, 131, 9, 122, 136, 7, 203, 84, 146, 103, 197, 224, 36, 7, 150, 15, 100, 127, 0, 29, 97, 35, 76, 5, 104, 195, 85, 22, 69, 49, 109, 244, 146, 131, 227, 179, 215, 130, 53, 196, 3, 97, 34, 59, 242, 233, 168, 202, 182, 241, 237, 71, 194, 48, 214, 182, 44, 103, 25, 140, 251, 145, 152, 202, 170, 253, 241, 40, 31, 3, 249, 158, 1, 203, 153, 38, 45, 43, 8, 162, 112, 6, 57, 42, 206, 179, 155, 201, 31, 149, 192, 236, 110, 179, 199, 149, 185, 67, 141, 125, 13, 115, 32, 251, 180, 224, 14, 224, 3, 143, 57, 158, 22, 229, 147, 116, 240, 238, 102, 242, 199, 137, 66, 238, 238, 178, 200, 124, 236, 177, 29, 26, 127, 130, 71, 11, 30, 192, 225, 246, 216, 224, 121, 58, 185, 153, 44, 112, 158, 78, 110, 254, 240, 67, 237, 93, 89, 27, 196, 12, 151, 245, 202, 141, 115, 208, 3, 66, 173, 94, 133, 73, 160, 138, 32, 195, 36, 27, 74, 127, 13, 172, 163, 23, 96, 155, 160, 217, 178, 43, 139, 16, 224, 97, 30, 219, 109, 197, 91, 130, 135, 124, 245, 34, 237, 211, 155, 201, 90, 202, 118, 190, 237, 220, 181, 25, 224, 173, 94, 50, 45, 230, 231, 177, 51, 205, 94, 192, 59, 154, 105, 90, 78, 98, 170, 110, 96, 26, 11, 51, 221, 180, 88, 91, 211, 149, 12, 127, 6, 167, 183, 118, 172, 167, 216, 204, 227, 190, 195, 108, 56, 27, 220, 80, 219, 167, 148, 184, 125, 42, 238, 83, 42, 7, 127, 164, 131, 193, 236, 124, 54, 74, 137, 211, 48, 200, 153, 186, 93, 82, 94, 128, 225, 204, 170, 60, 30, 153, 176, 65, 8, 119, 73, 10, 82, 154, 36, 201, 20, 112, 247, 104, 179, 197, 252, 105, 18, 209, 151, 101, 86, 9, 208, 162, 33, 98, 24, 15, 11, 102, 85, 185, 220, 155, 208, 106, 212, 98, 74, 146, 183, 66, 80, 206, 28, 14, 75, 46, 222, 9, 138, 37, 221, 181, 53, 20, 143, 85, 187, 58, 188, 167, 33, 205, 135, 58, 39, 145, 16, 160, 181, 181, 215, 108, 29, 219, 94, 20, 57, 168, 144, 236, 153, 206, 17, 33, 52, 239, 172, 75, 202, 188, 34, 16, 237, 75, 57, 65, 88, 250, 145, 15, 248, 20, 158, 10, 24, 239, 184, 75, 81, 37, 111, 135, 249, 233, 187, 233, 23, 161, 83, 66, 7, 253, 90, 79, 250, 95, 68, 143, 139, 222, 250, 250, 89, 242, 248, 17, 78, 94, 203, 149, 188, 245, 117, 95, 242, 30, 171, 201, 112, 125, 253, 142, 10, 222, 211, 124, 60, 236, 78, 4, 119, 231, 3, 97, 22, 220, 32, 129, 19, 4, 25, 198, 197, 205, 96, 60, 143, 180, 145, 74, 159, 110, 241, 22, 177, 143, 98, 214, 145, 193, 177, 206, 56, 194, 129, 85, 95, 151, 177, 182, 19, 180, 14, 24, 224, 227, 225, 62, 120, 64, 191, 176, 199, 53, 175, 237, 155, 249, 32, 232, 233, 209, 92, 16, 100, 128, 245, 126, 235, 145, 151, 131, 236, 13, 63, 56, 232, 255, 157, 139, 145, 29, 219, 29, 2, 241, 32, 254, 100, 227, 97, 226, 237, 17, 47, 206, 19, 240, 189, 204, 132, 122, 202, 223, 103, 175, 100, 75, 178, 40, 236, 151, 157, 138, 5, 160, 106, 220, 148, 132, 229, 201, 138, 234, 61, 171, 178, 147, 108, 34, 89, 126, 148, 33, 17, 207, 211, 233, 187, 55, 231, 233, 7, 57, 173, 173, 57, 165, 97, 237, 131, 165, 31, 146, 210, 162, 171, 110, 57, 109, 226, 81, 36, 143, 128, 12, 12, 71, 73, 24, 83, 78, 109, 128, 48, 36, 85, 149, 150, 56, 30, 41, 50, 55, 161, 136, 197, 66, 24, 62, 145, 35, 36, 199, 137, 238, 230, 139, 102, 161, 165, 135, 4, 243, 76, 10, 62, 226, 45, 184, 100, 228, 32, 14, 144, 90, 162, 45, 138, 54, 35, 45, 11, 81, 148, 7, 176, 103, 46, 144, 101, 165, 21, 38, 235, 184, 133, 162, 12, 161, 105, 97, 52, 136, 36, 240, 14, 176, 194, 215, 95, 195, 255, 119, 20, 201, 215, 20, 48, 45, 32, 184, 15, 69, 63, 105, 123, 42, 81, 171, 92, 241, 63, 239, 3, 90, 25, 234, 237, 99, 106, 12, 153, 150, 93, 51, 230, 224, 120, 90, 188, 150, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 202, 226, 220, 184, 81, 200, 174, 175, 235, 183, 211, 194, 62, 75, 76, 244, 207, 143, 174, 225, 246, 25, 209, 93, 91, 179, 232, 218, 103, 31, 93, 171, 147, 14, 66, 230, 199, 104, 36, 84, 164, 156, 228, 42, 148, 171, 205, 107, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 89, 153, 202, 182, 217, 156, 6, 179, 149, 232, 196, 123, 109, 157, 68, 89, 64, 249, 162, 36, 35, 236, 79, 179, 50, 53, 129, 76, 103, 96, 144, 152, 65, 207, 229, 183, 108, 168, 134, 157, 114, 128, 40, 108, 104, 144, 35, 4, 241, 253, 69, 118, 193, 129, 202, 66, 191, 142, 171, 244, 36, 19, 83, 226, 161, 88, 44, 148, 239, 179, 225, 209, 168, 152, 118, 117, 53, 105, 102, 240, 150, 90, 213, 234, 107, 71, 90, 83, 193, 45, 236, 214, 182, 165, 134, 254, 232, 203, 133, 198, 252, 69, 246, 97, 218, 181, 148, 16, 253, 5, 189, 37, 248, 94, 235, 66, 27, 116, 5, 180, 144, 65, 119, 170, 208, 47, 179, 180, 28, 190, 42, 60, 226, 174, 174, 70, 54, 207, 121, 180, 2, 242, 2, 88, 84, 12, 132, 10, 215, 219, 63, 249, 119, 41, 93, 191, 122, 13, 2, 40, 233, 231, 142, 215, 131, 142, 252, 194, 172, 170, 84, 160, 168, 40, 246, 139, 67, 49, 201, 0, 155, 68, 48, 170, 217, 8, 6, 253, 15, 197, 80, 15, 105, 232, 204, 176, 24, 139, 23, 114, 205, 9, 27, 220, 138, 36, 105, 160, 131, 0, 99, 3, 74, 179, 181, 38, 118, 92, 125, 166, 216, 233, 184, 129, 26, 12, 251, 148, 241, 206, 255, 153, 75, 185, 53, 229, 133, 144, 222, 223, 122, 42, 180, 164, 95, 113, 139, 170, 44, 141, 243, 126, 245, 178, 168, 170, 252, 237, 232, 18, 9, 11, 166, 234, 80, 18, 178, 155, 26, 155, 79, 233, 184, 104, 73, 84, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 31, 105, 245, 115, 54, 77, 7, 239, 178, 225, 79, 179, 147, 19, 161, 102, 82, 230, 148, 117, 173, 243, 239, 127, 8, 57, 97, 233, 84, 226, 232, 229, 148, 234, 101, 109, 186, 43, 114, 63, 150, 62, 15, 221, 90, 88, 156, 20, 115, 144, 136, 144, 57, 7, 183, 6, 170, 16, 100, 133, 199, 26, 142, 173, 196, 204, 140, 173, 32, 98, 223, 225, 167, 247, 184, 170, 75, 89, 164, 72, 176, 93, 15, 214, 22, 93, 31, 78, 210, 28, 212, 150, 2, 211, 51, 240, 94, 111, 135, 90, 131, 194, 53, 45, 109, 43, 253, 194, 170, 72, 112, 68, 239, 232, 26, 45, 22, 8, 84, 140, 233, 26, 225, 43, 249, 85, 46, 64, 43, 30, 143, 18, 82, 234, 82, 61, 72, 178, 202, 38, 247, 210, 113, 49, 22, 171, 155, 209, 139, 244, 60, 235, 82, 80, 98, 165, 39, 145, 174, 58, 222, 130, 228, 201, 120, 90, 230, 237, 27, 219, 90, 245, 181, 170, 12, 45, 106, 89, 127, 51, 80, 31, 4, 122, 183, 186, 28, 15, 186, 41, 252, 95, 134, 123, 201, 77, 176, 147, 49, 53, 87, 122, 82, 29, 138, 133, 97, 216, 134, 217, 35, 42, 92, 175, 23, 36, 212, 189, 81, 81, 205, 74, 201, 81, 240, 51, 129, 165, 241, 99, 194, 38, 176, 219, 150, 143, 1, 170, 106, 242, 30, 181, 16, 172, 204, 235, 98, 194, 56, 166, 107, 98, 89, 135, 8, 115, 96, 69, 252, 170, 56, 146, 193, 90, 186, 172, 235, 231, 155, 85, 2, 238, 46, 118, 93, 79, 182, 150, 20, 129, 0, 221, 148, 22, 198, 48, 93, 133, 101, 8, 150, 163, 182, 147, 112, 131, 78, 151, 29, 244, 142, 106, 11, 71, 90, 190, 23, 10, 122, 246, 221, 10, 126, 205, 58, 229, 248, 125, 159, 80, 212, 82, 105, 213, 213, 152, 220, 240, 14, 117, 162, 150, 196, 185, 75, 93, 210, 203, 163, 122, 242, 134, 91, 115, 72, 102, 173, 254, 48, 216, 8, 237, 34, 212, 59, 138, 17, 111, 126, 242, 89, 196, 62, 18, 70, 104, 51, 194, 96, 38, 181, 238, 136, 222, 68, 229, 129, 225, 123, 171, 201, 143, 6, 143, 110, 32, 8, 124, 175, 151, 116, 187, 253, 100, 103, 39, 233, 127, 39, 236, 50, 161, 143, 86, 123, 54, 86, 219, 117, 247, 136, 210, 123, 171, 224, 64, 58, 54, 131, 200, 54, 223, 224, 31, 216, 220, 233, 69, 154, 79, 149, 83, 105, 44, 52, 178, 242, 43, 194, 185, 130, 209, 168, 184, 64, 160, 208, 33, 240, 220, 88, 167, 51, 209, 86, 124, 228, 25, 141, 122, 113, 174, 192, 47, 108, 192, 252, 224, 2, 131, 209, 54, 227, 1, 212, 71, 124, 176, 155, 195, 18, 164, 14, 50, 170, 180, 103, 161, 11, 59, 154, 240, 128, 11, 74, 81, 136, 188, 243, 217, 101, 174, 128, 6, 248, 7, 195, 112, 6, 118, 129, 43, 17, 187, 104, 205, 192, 119, 253, 205, 110, 63, 219, 146, 210, 226, 149, 38, 90, 126, 150, 209, 5, 12, 225, 235, 109, 83, 210, 53, 153, 116, 69, 106, 58, 213, 241, 229, 146, 248, 81, 173, 246, 86, 113, 61, 168, 108, 81, 187, 229, 233, 176, 39, 58, 34, 244, 182, 104, 56, 60, 64, 141, 141, 233, 15, 9, 22, 240, 153, 9, 185, 198, 140, 193, 143, 88, 187, 13, 171, 24, 183, 249, 170, 169, 254, 144, 121, 203, 231, 228, 0, 103, 252, 213, 152, 146, 177, 71, 67, 158, 143, 253, 71, 98, 112, 185, 83, 124, 55, 98, 92, 72, 27, 113, 9, 38, 69, 163, 165, 208, 218, 78, 104, 242, 155, 247, 17, 89, 223, 103, 142, 8, 107, 148, 164, 78, 33, 179, 76, 222, 110, 58, 195, 73, 196, 141, 66, 103, 208, 216, 25, 29, 111, 198, 9, 204, 54, 129, 153, 198, 221, 12, 200, 233, 92, 243, 241, 211, 8, 28, 155, 0, 28, 249, 50, 123, 9, 205, 106, 31, 121, 40, 214, 249, 54, 162, 86, 35, 100, 175, 28, 77, 76, 36, 204, 211, 255, 17, 33, 131, 8, 158, 112, 228, 88, 72, 163, 50, 153, 90, 169, 209, 165, 185, 81, 163, 109, 149, 104, 108, 68, 87, 20, 21, 150, 170, 70, 87, 20, 141, 124, 85, 58, 247, 38, 162, 146, 156, 51, 194, 39, 117, 195, 217, 52, 152, 158, 174, 228, 154, 178, 181, 158, 132, 161, 241, 85, 34, 141, 197, 226, 234, 78, 152, 118, 242, 184, 35, 241, 110, 201, 49, 138, 58, 120, 241, 56, 168, 44, 180, 241, 159, 34, 31, 19, 245, 16, 62, 217, 25, 242, 107, 145, 99, 27, 83, 196, 160, 167, 96, 186, 39, 61, 67, 100, 3, 240, 182, 184, 223, 165, 103, 133, 168, 149, 97, 199, 70, 242, 135, 144, 196, 98, 2, 101, 232, 25, 43, 218, 91, 170, 183, 67, 76, 235, 238, 159, 122, 46, 29, 125, 210, 163, 67, 37, 228, 36, 47, 171, 233, 147, 81, 118, 174, 226, 43, 36, 164, 227, 205, 215, 186, 161, 67, 235, 120, 242, 78, 212, 146, 154, 134, 148, 135, 2, 6, 54, 64, 151, 43, 135, 18, 91, 236, 47, 242, 79, 144, 110, 4, 230, 198, 148, 145, 169, 199, 80, 197, 163, 79, 180, 39, 85, 54, 73, 245, 164, 209, 233, 117, 60, 145, 233, 199, 69, 6, 20, 146, 75, 3, 45, 55, 135, 201, 218, 35, 11, 219, 174, 14, 3, 147, 13, 1, 67, 244, 168, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 205, 108, 171, 16, 9, 63, 30, 50, 134, 251, 138, 198, 116, 114, 159, 134, 98, 168, 168, 163, 5, 235, 244, 146, 14, 236, 155, 30, 171, 121, 119, 3, 143, 152, 190, 246, 253, 46, 60, 110, 180, 40, 243, 83, 112, 248, 203, 79, 82, 181, 1, 111, 90, 206, 222, 38, 108, 42, 53, 129, 224, 212, 117, 195, 170, 70, 61, 108, 82, 199, 152, 32, 185, 82, 137, 12, 184, 43, 198, 76, 115, 82, 15, 162, 54, 128, 88, 237, 208, 249, 102, 111, 226, 22, 150, 143, 120, 87, 22, 85, 117, 152, 165, 163, 115, 220, 247, 166, 69, 218, 226, 160, 192, 163, 218, 178, 213, 0, 173, 189, 198, 115, 203, 170, 250, 158, 164, 149, 45, 75, 17, 81, 46, 245, 142, 191, 249, 31, 68, 136, 46, 133, 247, 2, 203, 254, 230, 186, 186, 75, 123, 181, 199, 193, 107, 169, 113, 207, 165, 118, 204, 162, 124, 32, 56, 145, 12, 86, 224, 16, 120, 139, 105, 248, 254, 42, 221, 87, 105, 158, 143, 21, 182, 158, 9, 62, 74, 167, 112, 158, 65, 206, 109, 165, 174, 213, 42, 234, 69, 157, 114, 124, 214, 16, 251, 226, 216, 217, 164, 145, 121, 2, 85, 220, 154, 174, 229, 125, 125, 193, 226, 64, 32, 65, 208, 253, 241, 84, 109, 44, 129, 45, 112, 208, 179, 157, 151, 190, 249, 190, 139, 161, 176, 51, 232, 232, 4, 140, 1, 128, 219, 93, 18, 157, 161, 212, 48, 155, 76, 223, 189, 152, 157, 203, 233, 97, 37, 22, 119, 36, 196, 159, 146, 68, 104, 169, 160, 11, 136, 0, 179, 187, 175, 188, 34, 27, 130, 165, 16, 81, 55, 26, 39, 156, 7, 70, 20, 196, 72, 29, 241, 132, 167, 188, 205, 19, 192, 133, 31, 114, 231, 121, 5, 59, 5, 15, 206, 80, 173, 36, 122, 225, 182, 98, 135, 67, 129, 221, 199, 77, 49, 9, 131, 77, 195, 170, 9, 253, 93, 216, 176, 244, 197, 142, 197, 128, 125, 224, 49, 80, 180, 70, 62, 102, 135, 145, 245, 108, 158, 153, 153, 92, 125, 61, 38, 117, 152, 235, 211, 145, 15, 226, 119, 218, 182, 62, 29, 11, 173, 54, 94, 51, 68, 32, 253, 79, 251, 27, 200, 43, 132, 74, 95, 17, 44, 253, 215, 230, 133, 227, 20, 70, 102, 127, 87, 204, 70, 67, 28, 104, 30, 92, 171, 122, 42, 71, 145, 199, 125, 36, 94, 45, 61, 187, 34, 110, 94, 75, 146, 252, 180, 142, 235, 229, 195, 138, 142, 208, 225, 91, 238, 148, 146, 100, 97, 220, 18, 98, 83, 94, 178, 129, 126, 182, 245, 158, 87, 213, 163, 170, 34, 200, 122, 210, 15, 16, 214, 13, 112, 129, 126, 83, 92, 33, 212, 247, 67, 255, 132, 254, 171, 117, 80, 127, 251, 125, 63, 224, 139, 174, 61, 228, 77, 177, 78, 220, 241, 96, 157, 178, 17, 53, 225, 131, 189, 182, 164, 175, 77, 119, 167, 106, 71, 117, 153, 97, 51, 122, 56, 173, 6, 204, 49, 108, 16, 87, 167, 90, 205, 242, 10, 143, 201, 58, 5, 140, 117, 246, 213, 91, 78, 232, 176, 247, 181, 64, 185, 21, 29, 122, 189, 147, 108, 130, 255, 254, 204, 217, 47, 142, 229, 254, 209, 129, 39, 210, 240, 111, 177, 225, 185, 59, 245, 44, 224, 87, 197, 33, 156, 71, 175, 178, 97, 119, 25, 36, 221, 197, 112, 183, 197, 220, 0, 24, 214, 166, 130, 226, 206, 108, 224, 154, 254, 102, 67, 141, 73, 120, 87, 116, 21, 111, 106, 184, 171, 223, 240, 138, 93, 152, 97, 130, 8, 96, 141, 164, 101, 118, 130, 180, 151, 33, 172, 250, 149, 179, 209, 226, 248, 22, 109, 205, 136, 185, 243, 61, 155, 73, 23, 167, 177, 244, 145, 44, 76, 231, 0, 185, 208, 169, 118, 166, 98, 113, 153, 165, 11, 184, 236, 176, 232, 0, 29, 220, 115, 94, 57, 84, 245, 92, 17, 18, 183, 55, 85, 1, 225, 96, 216, 132, 165, 81, 56, 90, 255, 89, 90, 77, 111, 108, 72, 54, 32, 247, 105, 194, 178, 173, 63, 124, 9, 193, 217, 250, 172, 77, 232, 192, 199, 226, 1, 252, 254, 126, 196, 245, 135, 241, 195, 0, 4, 67, 249, 225, 195, 205, 14, 231, 55, 24, 222, 49, 6, 154, 135, 83, 174, 53, 208, 223, 16, 152, 49, 8, 108, 75, 233, 178, 50, 220, 240, 125, 58, 34, 14, 29, 18, 50, 116, 158, 253, 146, 141, 89, 144, 140, 40, 42, 6, 19, 92, 88, 29, 71, 91, 81, 168, 114, 140, 230, 7, 43, 207, 112, 133, 224, 234, 77, 141, 253, 161, 32, 103, 46, 148, 115, 208, 253, 197, 235, 152, 38, 150, 219, 69, 83, 122, 217, 125, 52, 197, 15, 37, 144, 249, 33, 171, 34, 10, 180, 10, 39, 10, 19, 17, 118, 36, 51, 19, 166, 170, 50, 76, 246, 84, 168, 165, 27, 129, 171, 247, 237, 72, 201, 13, 27, 194, 170, 237, 69, 104, 86, 69, 137, 146, 210, 27, 54, 65, 83, 196, 201, 74, 43, 174, 82, 221, 107, 2, 64, 227, 251, 191, 180, 110, 207, 180, 73, 79, 8, 26, 223, 156, 130, 22, 223, 11, 132, 244, 132, 174, 2, 209, 117, 130, 242, 135, 81, 206, 78, 222, 56, 68, 225, 231, 188, 52, 161, 185, 127, 172, 184, 184, 168, 104, 220, 176, 158, 12, 160, 33, 139, 83, 13, 6, 76, 105, 40, 13, 57, 29, 225, 69, 200, 213, 100, 11, 206, 163, 55, 105, 45, 199, 142, 65, 197, 134, 189, 124, 8, 141, 171, 85, 152, 173, 163, 126, 147, 0, 93, 120, 241, 209, 37, 20, 99, 69, 69, 45, 21, 147, 90, 46, 72, 52, 29, 17, 126, 77, 52, 34, 165, 130, 36, 105, 17, 2, 247, 48, 34, 136, 152, 8, 213, 83, 251, 122, 127, 72, 180, 102, 105, 220, 37, 2, 74, 202, 198, 54, 31, 180, 104, 200, 64, 215, 247, 116, 211, 85, 129, 84, 10, 162, 52, 170, 102, 230, 184, 94, 28, 169, 6, 58, 90, 129, 38, 66, 214, 74, 168, 27, 240, 229, 194, 236, 97, 108, 87, 218, 154, 240, 200, 100, 16, 249, 139, 69, 85, 236, 5, 246, 238, 99, 124, 2, 249, 71, 54, 18, 156, 246, 194, 161, 167, 182, 135, 194, 97, 246, 7, 42, 200, 254, 128, 132, 216, 251, 32, 187, 7, 11, 132, 217, 251, 96, 90, 4, 219, 171, 179, 51, 248, 163, 19, 233, 93, 32, 254, 254, 84, 79, 26, 209, 40, 119, 89, 231, 64, 129, 134, 83, 36, 204, 193, 78, 251, 176, 15, 129, 185, 227, 42, 31, 248, 19, 109, 207, 182, 99, 71, 177, 126, 52, 14, 61, 38, 188, 91, 227, 161, 250, 247, 89, 70, 68, 53, 189, 192, 152, 24, 227, 230, 110, 14, 137, 236, 222, 103, 25, 17, 217, 242, 92, 3, 98, 183, 167, 252, 243, 81, 201, 163, 128, 237, 97, 22, 115, 225, 253, 167, 249, 247, 157, 184, 13, 146, 51, 74, 226, 217, 171, 192, 104, 155, 245, 36, 37, 170, 219, 51, 107, 201, 234, 46, 153, 70, 161, 250, 2, 90, 167, 230, 100, 22, 51, 97, 20, 150, 56, 144, 234, 143, 129, 225, 140, 43, 175, 226, 155, 215, 127, 153, 167, 91, 102, 12, 71, 98, 109, 102, 252, 0, 202, 112, 201, 134, 210, 54, 39, 135, 90, 108, 206, 225, 203, 60, 27, 97, 124, 54, 45, 72, 54, 8, 228, 242, 148, 76, 225, 96, 6, 24, 35, 154, 29, 47, 179, 72, 25, 36, 204, 92, 123, 15, 170, 201, 179, 53, 250, 205, 124, 112, 148, 80, 49, 91, 66, 31, 74, 145, 144, 223, 211, 112, 177, 80, 151, 225, 159, 1, 39, 222, 203, 142, 199, 66, 154, 96, 8, 105, 204, 36, 183, 27, 34, 132, 82, 39, 150, 228, 41, 198, 145, 38, 47, 200, 138, 41, 110, 209, 143, 46, 156, 178, 33, 91, 28, 196, 132, 23, 115, 154, 97, 234, 221, 43, 75, 176, 129, 51, 135, 12, 219, 58, 215, 35, 197, 170, 139, 33, 142, 55, 45, 223, 90, 81, 110, 209, 183, 47, 242, 220, 66, 158, 229, 33, 205, 232, 98, 94, 211, 50, 32, 201, 116, 5, 225, 43, 5, 214, 246, 199, 0, 14, 159, 71, 232, 95, 165, 103, 89, 119, 148, 159, 231, 211, 121, 229, 93, 173, 188, 206, 211, 124, 172, 98, 185, 237, 222, 155, 2, 167, 117, 130, 45, 179, 227, 56, 94, 15, 211, 241, 41, 42, 131, 239, 254, 214, 191, 38, 145, 135, 14, 134, 132, 194, 160, 117, 123, 37, 190, 185, 107, 215, 44, 240, 219, 132, 1, 30, 131, 95, 217, 252, 180, 254, 229, 171, 232, 3, 197, 243, 168, 18, 2, 11, 244, 232, 89, 176, 101, 205, 228, 209, 106, 75, 23, 86, 162, 79, 194, 158, 188, 214, 117, 99, 146, 254, 115, 89, 76, 238, 180, 164, 67, 7, 239, 168, 164, 55, 119, 205, 12, 233, 141, 19, 236, 182, 210, 204, 101, 216, 30, 106, 97, 170, 235, 78, 89, 26, 159, 83, 223, 180, 50, 14, 118, 43, 185, 33, 151, 13, 95, 166, 121, 89, 117, 23, 209, 27, 203, 19, 111, 142, 140, 47, 13, 183, 87, 186, 27, 123, 182, 52, 225, 94, 186, 60, 245, 200, 37, 38, 75, 18, 173, 158, 190, 247, 228, 154, 100, 76, 231, 177, 144, 213, 95, 223, 28, 97, 227, 225, 221, 119, 205, 127, 134, 189, 187, 139, 62, 180, 230, 174, 45, 119, 114, 94, 108, 246, 93, 68, 44, 151, 51, 205, 217, 51, 128, 181, 219, 228, 141, 30, 50, 39, 195, 128, 188, 80, 40, 122, 214, 84, 129, 227, 219, 122, 74, 254, 109, 189, 207, 185, 26, 175, 11, 122, 192, 244, 238, 42, 169, 115, 153, 196, 84, 65, 205, 238, 116, 84, 45, 32, 204, 121, 244, 130, 169, 66, 21, 67, 171, 124, 207, 44, 43, 145, 199, 174, 33, 30, 208, 29, 148, 251, 224, 54, 225, 89, 48, 86, 2, 138, 204, 23, 41, 161, 106, 216, 113, 136, 154, 164, 46, 44, 126, 61, 34, 207, 167, 204, 229, 128, 5, 12, 55, 38, 185, 94, 241, 152, 250, 125, 148, 159, 13, 45, 86, 131, 208, 227, 52, 197, 62, 225, 48, 234, 157, 38, 47, 171, 115, 32, 167, 179, 68, 70, 169, 0, 141, 110, 56, 105, 115, 29, 51, 99, 146, 183, 176, 241, 248, 71, 187, 144, 4, 149, 106, 8, 152, 90, 237, 157, 211, 24, 218, 99, 115, 106, 148, 89, 34, 139, 211, 53, 30, 94, 139, 118, 9, 213, 75, 132, 38, 185, 138, 168, 173, 167, 134, 190, 150, 72, 71, 39, 47, 71, 170, 231, 75, 235, 78, 211, 33, 92, 129, 253, 226, 46, 210, 113, 68, 137, 55, 233, 61, 121, 161, 215, 237, 167, 76, 131, 3, 57, 68, 29, 63, 172, 166, 140, 196, 220, 154, 107, 177, 234, 8, 169, 174, 206, 187, 27, 148, 188, 55, 55, 45, 61, 98, 186, 115, 249, 138, 67, 230, 6, 145, 133, 28, 244, 119, 131, 150, 87, 229, 74, 98, 238, 121, 107, 25, 137, 127, 32, 109, 66, 83, 82, 208, 8, 33, 238, 247, 146, 142, 124, 234, 64, 28, 42, 130, 237, 232, 4, 124, 252, 10, 230, 113, 122, 158, 233, 248, 57, 241, 8, 159, 240, 149, 250, 227, 164, 170, 69, 184, 50, 93, 45, 162, 11, 229, 204, 26, 230, 188, 58, 69, 104, 231, 89, 5, 199, 122, 225, 131, 122, 41, 255, 239, 130, 99, 144, 68, 9, 51, 228, 166, 245, 78, 199, 9, 33, 17, 165, 116, 7, 228, 145, 64, 4, 235, 149, 211, 221, 33, 44, 43, 129, 174, 37, 157, 135, 73, 71, 252, 145, 128, 98, 163, 0, 249, 86, 94, 149, 105, 62, 18, 207, 98, 225, 38, 254, 100, 60, 24, 185, 241, 110, 96, 6, 78, 5, 130, 247, 196, 140, 187, 10, 8, 252, 223, 113, 199, 137, 151, 12, 198, 48, 227, 136, 31, 205, 170, 73, 38, 168, 54, 228, 241, 192, 110, 114, 28, 26, 227, 15, 97, 58, 226, 149, 169, 64, 191, 5, 99, 11, 253, 243, 145, 32, 113, 166, 126, 36, 24, 135, 135, 227, 72, 171, 199, 254, 232, 176, 94, 117, 240, 189, 103, 67, 58, 56, 10, 81, 7, 219, 127, 24, 193, 53, 158, 43, 22, 244, 145, 9, 15, 244, 161, 239, 87, 135, 179, 49, 120, 97, 93, 192, 142, 240, 60, 248, 206, 217, 67, 176, 107, 204, 57, 162, 201, 147, 192, 149, 207, 114, 152, 90, 246, 214, 20, 131, 84, 15, 164, 4, 237, 158, 186, 9, 37, 211, 214, 129, 207, 76, 78, 228, 250, 93, 225, 38, 18, 212, 181, 56, 59, 41, 226, 137, 22, 62, 51, 195, 152, 99, 2, 55, 130, 99, 220, 35, 9, 119, 133, 101, 104, 104, 230, 242, 84, 144, 28, 193, 79, 165, 124, 228, 70, 226, 123, 200, 5, 223, 136, 64, 45, 219, 149, 238, 33, 146, 207, 201, 120, 176, 23, 90, 78, 4, 46, 100, 164, 0, 233, 238, 41, 36, 75, 144, 152, 218, 132, 241, 194, 126, 131, 211, 246, 88, 67, 123, 78, 229, 209, 97, 157, 123, 25, 245, 111, 189, 248, 89, 216, 84, 93, 123, 160, 80, 50, 91, 195, 162, 146, 188, 82, 127, 154, 135, 212, 162, 135, 121, 44, 89, 208, 36, 110, 121, 12, 42, 224, 127, 140, 158, 247, 209, 103, 110, 100, 167, 124, 183, 211, 78, 178, 133, 195, 26, 206, 46, 198, 161, 111, 208, 19, 8, 206, 39, 253, 211, 38, 31, 107, 200, 198, 16, 7, 29, 47, 164, 127, 210, 34, 214, 243, 98, 100, 189, 246, 160, 80, 192, 249, 133, 37, 28, 235, 209, 230, 214, 14, 29, 8, 82, 169, 198, 243, 74, 174, 105, 122, 201, 185, 58, 25, 97, 181, 40, 125, 129, 89, 195, 85, 89, 43, 73, 231, 250, 20, 134, 0, 139, 103, 70, 36, 208, 70, 55, 15, 219, 38, 118, 90, 210, 186, 3, 106, 60, 111, 221, 64, 238, 195, 182, 96, 246, 217, 32, 240, 189, 21, 5, 80, 29, 11, 34, 109, 18, 40, 60, 63, 183, 60, 77, 88, 22, 231, 52, 39, 109, 215, 111, 196, 142, 116, 0, 3, 194, 43, 206, 81, 18, 39, 51, 68, 123, 2, 123, 253, 215, 10, 217, 57, 51, 23, 116, 198, 219, 3, 46, 1, 238, 51, 114, 17, 225, 63, 72, 89, 41, 215, 125, 24, 64, 15, 171, 36, 248, 11, 43, 37, 56, 80, 43, 22, 172, 181, 39, 161, 52, 124, 115, 28, 138, 98, 108, 70, 76, 53, 253, 230, 141, 60, 167, 251, 230, 205, 67, 217, 148, 146, 34, 46, 83, 205, 199, 190, 188, 173, 31, 213, 72, 76, 78, 48, 107, 136, 92, 203, 75, 226, 151, 25, 208, 69, 45, 147, 104, 38, 189, 248, 114, 87, 197, 203, 144, 90, 96, 108, 88, 218, 200, 68, 5, 157, 74, 173, 122, 107, 157, 220, 45, 233, 204, 71, 255, 156, 156, 149, 106, 206, 114, 74, 169, 175, 123, 229, 159, 166, 58, 231, 231, 168, 8, 131, 137, 70, 212, 20, 77, 239, 116, 156, 143, 255, 62, 206, 205, 131, 64, 27, 219, 72, 156, 64, 6, 142, 239, 206, 45, 181, 127, 219, 155, 165, 100, 54, 220, 131, 224, 9, 212, 8, 155, 28, 160, 66, 49, 94, 134, 102, 134, 127, 151, 86, 251, 227, 106, 154, 142, 7, 58, 9, 53, 159, 114, 72, 178, 200, 188, 122, 169, 15, 171, 31, 156, 40, 38, 183, 163, 106, 62, 117, 59, 86, 221, 114, 57, 89, 33, 147, 12, 105, 214, 49, 28, 40, 15, 104, 78, 186, 80, 190, 46, 181, 53, 12, 134, 237, 211, 2, 54, 215, 242, 161, 81, 132, 77, 27, 180, 8, 129, 237, 204, 186, 120, 181, 173, 222, 119, 5, 126, 133, 239, 236, 98, 97, 54, 166, 33, 164, 157, 139, 109, 230, 57, 76, 20, 164, 193, 2, 167, 137, 66, 112, 218, 92, 111, 19, 235, 78, 224, 4, 17, 225, 218, 240, 1, 162, 3, 122, 213, 13, 99, 216, 104, 249, 190, 123, 200, 168, 238, 192, 39, 145, 189, 134, 1, 193, 69, 221, 221, 25, 146, 232, 65, 187, 246, 131, 98, 114, 181, 182, 59, 213, 222, 242, 252, 43, 59, 48, 156, 248, 158, 42, 124, 79, 78, 181, 170, 217, 197, 81, 159, 115, 29, 132, 15, 104, 88, 114, 248, 117, 177, 65, 119, 34, 84, 22, 24, 110, 14, 161, 205, 64, 251, 200, 47, 116, 110, 207, 140, 112, 8, 193, 248, 9, 214, 72, 16, 48, 71, 234, 74, 130, 244, 249, 105, 122, 133, 243, 169, 237, 168, 26, 56, 133, 218, 64, 215, 120, 204, 150, 68, 38, 76, 219, 107, 179, 94, 174, 39, 14, 172, 217, 88, 49, 121, 48, 132, 25, 208, 38, 56, 140, 80, 207, 13, 156, 2, 154, 211, 89, 130, 196, 135, 213, 216, 1, 10, 129, 250, 248, 174, 86, 130, 68, 121, 196, 95, 46, 255, 101, 1, 204, 45, 91, 84, 138, 189, 246, 4, 193, 71, 153, 228, 162, 134, 56, 176, 96, 13, 179, 159, 25, 138, 74, 242, 107, 216, 229, 67, 40, 50, 201, 100, 34, 161, 235, 131, 129, 74, 100, 75, 131, 41, 234, 247, 27, 97, 171, 137, 185, 110, 120, 130, 14, 226, 255, 51, 145, 96, 243, 196, 128, 245, 52, 70, 136, 171, 138, 228, 82, 160, 212, 27, 141, 241, 26, 230, 84, 253, 24, 52, 219, 213, 9, 71, 155, 114, 233, 6, 10, 236, 50, 147, 72, 93, 159, 216, 134, 15, 27, 186, 252, 111, 209, 186, 105, 194, 59, 47, 254, 95, 68, 152, 136, 112, 149, 141, 132, 72, 68, 133, 152, 100, 14, 107, 146, 99, 153, 220, 21, 161, 217, 62, 122, 103, 33, 62, 182, 23, 241, 248, 121, 198, 207, 33, 220, 42, 44, 77, 158, 149, 122, 6, 56, 37, 228, 42, 105, 193, 52, 227, 129, 115, 130, 234, 94, 151, 149, 150, 249, 73, 219, 30, 164, 186, 62, 97, 15, 157, 51, 116, 69, 133, 226, 125, 227, 164, 189, 77, 7, 2, 71, 169, 110, 133, 172, 243, 131, 119, 44, 187, 97, 109, 125, 187, 56, 212, 113, 69, 203, 80, 15, 158, 232, 2, 122, 235, 235, 17, 4, 147, 228, 109, 153, 165, 44, 115, 96, 64, 164, 227, 7, 23, 191, 136, 244, 162, 34, 29, 58, 80, 120, 171, 68, 186, 77, 7, 110, 171, 72, 47, 75, 24, 153, 106, 88, 95, 135, 52, 192, 155, 13, 179, 108, 216, 108, 174, 61, 153, 116, 19, 140, 230, 155, 190, 202, 141, 28, 17, 186, 37, 43, 221, 249, 176, 191, 93, 178, 118, 27, 86, 187, 230, 180, 211, 190, 21, 184, 200, 54, 147, 106, 175, 39, 201, 28, 171, 253, 130, 177, 57, 253, 98, 120, 157, 16, 161, 254, 152, 149, 165, 4, 133, 211, 139, 53, 184, 234, 170, 31, 247, 48, 214, 28, 150, 126, 195, 41, 169, 155, 160, 150, 150, 117, 218, 170, 89, 49, 57, 231, 177, 8, 87, 235, 238, 55, 28, 207, 178, 50, 176, 174, 72, 62, 207, 65, 166, 196, 21, 161, 101, 207, 98, 26, 252, 14, 157, 192, 56, 86, 236, 40, 162, 69, 71, 95, 138, 202, 131, 40, 120, 213, 240, 94, 133, 58, 46, 69, 133, 147, 30, 145, 114, 36, 117, 109, 45, 96, 150, 7, 176, 14, 159, 44, 139, 159, 172, 242, 215, 183, 145, 227, 84, 159, 203, 20, 174, 103, 77, 236, 212, 241, 198, 198, 198, 124, 131, 255, 58, 188, 237, 30, 61, 61, 117, 19, 164, 125, 241, 83, 29, 237, 100, 252, 154, 166, 169, 182, 199, 65, 92, 94, 15, 42, 101, 121, 132, 235, 139, 127, 245, 186, 199, 172, 69, 210, 254, 186, 225, 91, 224, 184, 153, 55, 210, 234, 140, 217, 151, 161, 254, 20, 67, 125, 111, 153, 99, 221, 124, 26, 46, 176, 111, 50, 30, 126, 25, 234, 91, 39, 213, 117, 107, 123, 177, 158, 35, 23, 96, 238, 143, 115, 196, 77, 16, 211, 142, 175, 88, 77, 144, 161, 149, 118, 230, 112, 40, 251, 45, 190, 108, 84, 89, 48, 85, 189, 44, 82, 55, 12, 56, 166, 170, 156, 103, 45, 2, 93, 4, 201, 206, 227, 167, 26, 1, 197, 240, 169, 13, 93, 183, 230, 112, 194, 183, 189, 164, 35, 250, 222, 97, 161, 253, 33, 162, 75, 244, 228, 162, 182, 103, 112, 58, 222, 124, 77, 126, 244, 95, 251, 243, 224, 115, 25, 233, 35, 141, 20, 0, 250, 54, 29, 156, 193, 92, 106, 111, 115, 113, 238, 111, 132, 30, 63, 143, 138, 207, 115, 21, 129, 241, 220, 70, 96, 8, 248, 230, 219, 220, 193, 23, 162, 114, 139, 136, 11, 130, 55, 249, 74, 110, 18, 236, 216, 78, 58, 129, 24, 46, 43, 88, 80, 243, 136, 37, 173, 69, 229, 50, 131, 124, 48, 89, 229, 198, 66, 42, 239, 235, 228, 13, 126, 238, 37, 207, 237, 73, 206, 116, 162, 84, 152, 40, 119, 40, 29, 28, 144, 97, 73, 0, 56, 29, 21, 111, 83, 160, 71, 224, 51, 84, 190, 120, 39, 208, 73, 186, 114, 21, 77, 86, 243, 16, 244, 164, 22, 64, 114, 73, 155, 78, 158, 136, 54, 47, 5, 45, 180, 162, 236, 26, 36, 194, 77, 147, 109, 47, 158, 113, 194, 241, 131, 171, 230, 206, 178, 75, 37, 106, 1, 72, 120, 91, 54, 207, 201, 18, 41, 218, 199, 162, 81, 72, 137, 98, 163, 218, 82, 125, 94, 42, 36, 50, 1, 142, 55, 106, 74, 244, 69, 143, 12, 8, 140, 116, 148, 213, 12, 130, 104, 75, 5, 215, 135, 63, 131, 183, 141, 202, 28, 245, 52, 44, 24, 219, 68, 160, 44, 18, 216, 68, 170, 183, 137, 106, 114, 112, 14, 4, 52, 45, 204, 187, 24, 17, 248, 47, 126, 204, 170, 230, 168, 105, 59, 206, 62, 168, 229, 105, 73, 93, 202, 210, 58, 69, 199, 63, 229, 89, 36, 27, 146, 181, 63, 158, 222, 223, 130, 240, 105, 55, 54, 107, 139, 184, 171, 180, 51, 82, 203, 138, 5, 196, 119, 143, 140, 59, 182, 65, 70, 112, 245, 239, 129, 234, 183, 7, 213, 231, 160, 116, 53, 115, 101, 171, 169, 127, 28, 197, 37, 70, 64, 1, 251, 53, 21, 253, 101, 138, 169, 98, 132, 13, 173, 32, 40, 97, 241, 19, 142, 188, 245, 178, 174, 16, 159, 48, 148, 224, 23, 187, 11, 214, 152, 243, 90, 119, 91, 163, 205, 165, 238, 224, 103, 46, 139, 217, 228, 39, 147, 117, 133, 76, 7, 230, 36, 146, 31, 203, 42, 11, 199, 102, 25, 28, 163, 111, 31, 104, 249, 115, 167, 28, 85, 91, 127, 205, 85, 106, 153, 128, 57, 218, 49, 98, 180, 252, 153, 175, 31, 159, 249, 246, 146, 232, 213, 235, 198, 150, 177, 246, 218, 56, 187, 72, 246, 236, 126, 196, 89, 123, 51, 213, 161, 226, 182, 149, 72, 53, 21, 53, 41, 125, 223, 58, 61, 35, 82, 141, 55, 202, 70, 39, 112, 121, 7, 173, 180, 183, 68, 107, 100, 166, 180, 245, 66, 247, 95, 39, 97, 96, 21, 5, 214, 75, 142, 85, 182, 191, 213, 160, 16, 7, 50, 254, 232, 54, 205, 61, 184, 21, 222, 44, 232, 92, 80, 36, 255, 127, 70, 28, 213, 54, 197, 67, 58, 97, 146, 243, 98, 118, 254, 54, 43, 223, 228, 149, 88, 76, 9, 50, 119, 199, 179, 115, 203, 207, 104, 18, 139, 119, 234, 224, 207, 88, 22, 118, 15, 110, 134, 100, 20, 170, 172, 203, 255, 75, 221, 24, 110, 242, 69, 250, 98, 153, 237, 221, 147, 146, 113, 30, 110, 75, 167, 6, 86, 32, 67, 77, 138, 215, 173, 91, 37, 187, 237, 254, 70, 59, 54, 177, 205, 176, 3, 232, 235, 182, 78, 156, 40, 71, 98, 66, 250, 60, 200, 202, 220, 32, 46, 166, 247, 232, 212, 86, 51, 0, 235, 221, 238, 86, 242, 151, 191, 36, 223, 222, 95, 133, 59, 29, 87, 97, 87, 87, 195, 248, 250, 107, 243, 40, 222, 178, 114, 252, 40, 155, 52, 33, 44, 99, 152, 190, 99, 27, 140, 113, 94, 21, 234, 167, 46, 184, 26, 6, 101, 217, 58, 10, 13, 139, 212, 3, 84, 6, 154, 208, 118, 7, 23, 99, 45, 142, 63, 103, 213, 160, 204, 39, 66, 225, 85, 244, 212, 149, 74, 45, 99, 46, 6, 61, 176, 42, 47, 187, 212, 215, 235, 30, 102, 39, 16, 94, 246, 166, 184, 24, 255, 83, 188, 237, 234, 3, 101, 210, 232, 177, 96, 193, 84, 250, 200, 148, 164, 201, 38, 214, 195, 75, 70, 1, 40, 42, 129, 109, 252, 138, 119, 243, 230, 252, 194, 120, 171, 47, 161, 138, 74, 55, 74, 140, 117, 104, 85, 124, 171, 239, 167, 58, 86, 200, 245, 32, 50, 165, 172, 47, 89, 210, 78, 70, 171, 117, 186, 140, 116, 19, 181, 33, 188, 113, 246, 43, 112, 172, 72, 217, 240, 168, 144, 115, 102, 246, 14, 60, 172, 76, 233, 125, 202, 139, 154, 65, 194, 107, 2, 61, 208, 251, 213, 147, 15, 98, 94, 169, 114, 60, 83, 201, 0, 179, 19, 148, 192, 229, 180, 165, 220, 173, 25, 128, 254, 102, 90, 60, 43, 196, 60, 145, 121, 233, 137, 232, 18, 161, 230, 232, 202, 193, 198, 212, 100, 193, 57, 8, 182, 32, 167, 5, 209, 83, 134, 184, 123, 105, 173, 95, 237, 93, 90, 17, 6, 232, 254, 139, 85, 87, 31, 187, 255, 82, 203, 41, 94, 255, 43, 5, 64, 18, 89, 140, 11, 204, 222, 115, 15, 134, 202, 130, 16, 54, 219, 60, 240, 104, 189, 153, 243, 182, 204, 108, 163, 197, 143, 20, 54, 178, 24, 67, 201, 155, 168, 145, 6, 21, 162, 167, 19, 12, 169, 154, 141, 104, 29, 105, 180, 170, 40, 90, 170, 180, 146, 9, 68, 11, 242, 39, 245, 146, 74, 254, 96, 170, 68, 20, 76, 66, 215, 12, 187, 166, 29, 86, 141, 152, 117, 247, 239, 43, 132, 166, 48, 87, 208, 137, 65, 105, 4, 51, 179, 64, 22, 39, 122, 198, 23, 184, 218, 251, 134, 115, 78, 240, 91, 37, 141, 232, 142, 176, 78, 95, 21, 154, 125, 132, 134, 83, 169, 172, 132, 169, 106, 82, 90, 169, 222, 27, 14, 147, 72, 171, 238, 42, 123, 23, 52, 130, 124, 216, 252, 176, 181, 185, 153, 252, 41, 254, 110, 246, 213, 159, 45, 60, 78, 105, 206, 85, 171, 142, 169, 103, 88, 64, 174, 72, 19, 216, 227, 106, 213, 228, 47, 148, 224, 167, 139, 19, 252, 180, 153, 224, 167, 119, 139, 224, 167, 132, 204, 150, 248, 53, 4, 127, 86, 20, 103, 179, 9, 225, 240, 86, 132, 254, 172, 84, 26, 22, 212, 177, 166, 230, 196, 216, 108, 168, 55, 189, 145, 138, 206, 188, 40, 103, 51, 51, 1, 234, 55, 176, 94, 254, 90, 145, 152, 166, 145, 32, 243, 220, 241, 150, 201, 254, 173, 51, 0, 135, 239, 21, 249, 72, 134, 208, 49, 43, 78, 189, 25, 81, 188, 85, 108, 168, 157, 136, 88, 239, 158, 246, 39, 69, 135, 239, 151, 47, 195, 55, 215, 240, 245, 111, 202, 240, 213, 27, 113, 19, 75, 70, 59, 172, 237, 41, 198, 1, 88, 95, 27, 161, 90, 168, 219, 38, 81, 243, 116, 90, 86, 187, 227, 33, 250, 225, 144, 180, 26, 12, 251, 10, 228, 238, 111, 186, 107, 16, 77, 123, 244, 35, 34, 229, 181, 171, 228, 162, 204, 167, 160, 164, 31, 38, 247, 238, 249, 208, 54, 31, 24, 159, 74, 38, 184, 78, 237, 221, 68, 138, 246, 77, 209, 65, 49, 62, 201, 79, 103, 117, 133, 183, 86, 157, 83, 199, 52, 83, 209, 31, 90, 135, 58, 216, 86, 230, 205, 22, 190, 105, 141, 84, 107, 148, 62, 6, 216, 227, 160, 68, 118, 115, 38, 6, 119, 112, 123, 114, 176, 242, 183, 179, 41, 184, 202, 64, 130, 7, 83, 187, 36, 93, 206, 197, 220, 164, 57, 162, 55, 232, 219, 136, 250, 240, 138, 248, 90, 196, 135, 18, 81, 38, 76, 34, 30, 134, 249, 219, 244, 214, 210, 164, 201, 187, 247, 67, 208, 187, 183, 69, 201, 138, 9, 237, 61, 1, 209, 46, 50, 76, 187, 161, 47, 140, 48, 235, 111, 227, 53, 211, 63, 212, 12, 77, 92, 173, 234, 92, 148, 243, 18, 122, 210, 177, 76, 214, 17, 43, 69, 138, 140, 142, 174, 147, 24, 252, 249, 136, 124, 218, 176, 149, 4, 245, 164, 125, 240, 16, 254, 252, 64, 253, 141, 29, 202, 149, 115, 192, 166, 213, 20, 244, 45, 9, 189, 191, 201, 160, 171, 68, 171, 13, 96, 165, 198, 208, 107, 91, 69, 52, 210, 18, 217, 128, 38, 84, 213, 193, 38, 166, 37, 173, 68, 230, 104, 44, 212, 47, 13, 70, 245, 233, 129, 236, 211, 22, 239, 147, 24, 182, 230, 70, 182, 116, 35, 102, 144, 73, 35, 167, 25, 217, 151, 8, 88, 169, 32, 15, 88, 239, 94, 216, 93, 233, 112, 239, 119, 63, 40, 251, 181, 227, 44, 200, 37, 190, 213, 92, 248, 86, 1, 124, 171, 24, 190, 149, 197, 183, 154, 27, 223, 42, 140, 175, 66, 202, 153, 182, 249, 135, 62, 157, 207, 93, 208, 91, 4, 166, 81, 231, 173, 180, 102, 165, 87, 24, 122, 105, 103, 20, 40, 29, 127, 205, 132, 20, 53, 170, 103, 245, 59, 99, 110, 24, 196, 187, 196, 70, 87, 127, 30, 168, 61, 66, 91, 52, 80, 2, 63, 82, 3, 38, 224, 159, 241, 123, 196, 239, 189, 8, 68, 105, 153, 220, 96, 139, 16, 10, 93, 243, 114, 97, 225, 82, 105, 78, 80, 196, 225, 79, 30, 13, 204, 200, 194, 176, 213, 12, 72, 102, 190, 171, 76, 163, 114, 11, 223, 49, 105, 180, 122, 38, 29, 150, 41, 170, 60, 116, 97, 159, 242, 137, 218, 209, 151, 161, 39, 174, 235, 209, 113, 25, 78, 96, 131, 54, 22, 182, 18, 9, 89, 129, 58, 13, 225, 42, 170, 228, 198, 137, 69, 134, 71, 175, 68, 89, 74, 111, 59, 78, 212, 198, 160, 59, 200, 225, 62, 255, 67, 249, 156, 14, 122, 201, 203, 6, 79, 43, 119, 82, 189, 212, 201, 186, 124, 243, 248, 203, 126, 158, 179, 159, 167, 200, 73, 60, 96, 3, 25, 235, 208, 197, 5, 198, 13, 218, 183, 227, 235, 203, 179, 184, 125, 120, 22, 183, 11, 207, 154, 236, 193, 51, 101, 7, 218, 101, 161, 179, 91, 8, 73, 234, 196, 199, 215, 118, 34, 107, 218, 18, 140, 137, 196, 103, 218, 11, 116, 37, 77, 128, 62, 207, 171, 236, 13, 158, 103, 234, 22, 227, 167, 234, 201, 74, 220, 68, 21, 137, 6, 176, 224, 247, 186, 244, 249, 216, 10, 36, 205, 199, 134, 34, 249, 243, 97, 123, 25, 183, 232, 233, 222, 50, 54, 209, 139, 109, 61, 107, 248, 138, 183, 77, 54, 170, 233, 187, 76, 119, 167, 167, 146, 242, 226, 175, 144, 111, 207, 246, 92, 119, 132, 84, 135, 161, 31, 147, 202, 9, 3, 231, 126, 101, 3, 217, 37, 96, 86, 193, 146, 215, 108, 255, 158, 206, 255, 206, 161, 190, 144, 152, 20, 182, 47, 238, 5, 173, 238, 64, 33, 61, 14, 179, 170, 24, 189, 207, 186, 123, 44, 7, 43, 153, 126, 194, 33, 158, 178, 238, 6, 160, 221, 75, 12, 229, 13, 218, 1, 31, 8, 191, 80, 90, 51, 161, 250, 211, 165, 132, 98, 253, 23, 138, 166, 162, 135, 228, 110, 35, 1, 84, 38, 102, 213, 147, 32, 1, 26, 242, 144, 69, 218, 138, 50, 46, 159, 212, 84, 92, 218, 179, 188, 146, 230, 129, 244, 211, 60, 203, 207, 178, 167, 69, 41, 180, 126, 101, 247, 174, 140, 64, 168, 237, 195, 87, 5, 30, 188, 18, 5, 80, 127, 152, 213, 46, 148, 120, 156, 116, 191, 221, 220, 76, 254, 146, 8, 11, 57, 126, 66, 188, 223, 255, 27, 19, 221, 145, 64, 3, 167, 18, 229, 49, 18, 160, 86, 217, 164, 145, 203, 105, 68, 252, 209, 155, 149, 118, 163, 50, 160, 235, 0, 158, 152, 62, 229, 92, 126, 156, 123, 38, 3, 124, 102, 196, 208, 142, 52, 121, 95, 68, 119, 154, 150, 50, 136, 3, 131, 255, 228, 17, 49, 97, 142, 153, 147, 103, 162, 54, 115, 104, 24, 53, 160, 42, 206, 19, 36, 170, 107, 56, 19, 182, 118, 26, 176, 38, 27, 172, 136, 239, 77, 84, 222, 255, 176, 122, 255, 211, 49, 31, 176, 155, 27, 178, 155, 230, 245, 171, 226, 168, 152, 149, 131, 204, 105, 142, 91, 18, 109, 175, 218, 104, 67, 59, 220, 18, 219, 175, 246, 199, 163, 92, 30, 248, 124, 6, 181, 12, 92, 54, 26, 116, 31, 76, 127, 24, 104, 253, 109, 134, 138, 53, 144, 240, 209, 33, 202, 190, 97, 128, 30, 52, 15, 144, 138, 237, 190, 120, 37, 95, 107, 198, 247, 15, 37, 62, 78, 182, 116, 35, 166, 180, 115, 230, 80, 175, 18, 3, 104, 154, 42, 113, 147, 218, 195, 117, 171, 151, 144, 106, 100, 81, 75, 231, 19, 138, 203, 212, 116, 225, 211, 49, 158, 25, 184, 249, 152, 79, 58, 184, 132, 86, 194, 92, 233, 251, 213, 75, 97, 241, 101, 67, 165, 42, 28, 185, 20, 6, 27, 123, 131, 74, 74, 70, 146, 16, 205, 132, 205, 255, 200, 11, 227, 219, 135, 77, 218, 209, 229, 231, 36, 169, 46, 114, 153, 183, 31, 208, 212, 122, 209, 156, 76, 19, 244, 223, 124, 232, 76, 30, 154, 18, 174, 86, 215, 28, 109, 7, 115, 219, 66, 233, 47, 12, 69, 138, 72, 37, 214, 81, 20, 220, 214, 213, 193, 225, 67, 159, 193, 189, 191, 68, 184, 248, 176, 197, 26, 120, 112, 29, 13, 224, 195, 125, 214, 210, 183, 215, 218, 18, 62, 60, 96, 77, 126, 247, 105, 154, 196, 135, 111, 89, 219, 223, 127, 226, 182, 241, 225, 59, 134, 196, 15, 159, 11, 9, 124, 248, 158, 97, 243, 183, 207, 142, 13, 62, 252, 192, 208, 234, 47, 174, 81, 150, 142, 23, 62, 252, 141, 35, 184, 4, 101, 181, 116, 4, 53, 64, 174, 7, 251, 203, 84, 132, 203, 71, 85, 63, 25, 37, 43, 214, 47, 169, 88, 144, 56, 72, 27, 11, 162, 9, 91, 255, 188, 151, 54, 172, 134, 243, 58, 54, 177, 233, 171, 184, 54, 117, 62, 249, 0, 58, 167, 177, 29, 105, 221, 49, 111, 83, 218, 185, 254, 136, 27, 81, 45, 118, 25, 93, 115, 143, 245, 47, 186, 65, 30, 66, 39, 216, 161, 119, 105, 181, 28, 220, 3, 182, 151, 170, 16, 48, 186, 68, 163, 190, 185, 133, 224, 131, 70, 62, 221, 1, 205, 199, 198, 80, 12, 15, 80, 168, 63, 201, 245, 118, 8, 182, 153, 218, 117, 168, 209, 56, 199, 30, 171, 0, 10, 137, 254, 209, 76, 222, 121, 233, 119, 170, 231, 88, 239, 46, 213, 84, 149, 99, 82, 131, 103, 127, 248, 234, 48, 59, 125, 242, 97, 242, 116, 148, 158, 86, 44, 210, 17, 172, 219, 195, 168, 135, 236, 176, 142, 125, 15, 235, 78, 27, 31, 50, 251, 217, 120, 71, 58, 29, 221, 200, 225, 134, 188, 36, 97, 152, 15, 236, 134, 28, 22, 91, 19, 229, 134, 29, 74, 198, 195, 13, 117, 98, 43, 80, 240, 212, 41, 152, 159, 142, 139, 50, 219, 75, 171, 44, 80, 56, 119, 10, 159, 139, 15, 112, 181, 99, 168, 236, 185, 83, 118, 88, 76, 119, 71, 33, 12, 42, 167, 224, 108, 156, 15, 138, 97, 8, 228, 44, 92, 82, 44, 71, 67, 36, 120, 239, 148, 174, 166, 249, 224, 236, 50, 80, 240, 178, 227, 112, 131, 77, 68, 229, 7, 127, 122, 140, 128, 49, 169, 39, 240, 134, 199, 163, 170, 162, 129, 251, 72, 175, 159, 97, 38, 144, 142, 169, 84, 62, 31, 108, 94, 16, 64, 10, 155, 113, 238, 75, 140, 121, 9, 249, 138, 110, 172, 116, 254, 10, 55, 124, 106, 104, 107, 248, 91, 22, 171, 35, 143, 189, 174, 211, 222, 155, 74, 73, 179, 59, 124, 15, 119, 123, 168, 47, 251, 16, 156, 222, 61, 194, 187, 173, 137, 227, 202, 120, 175, 170, 217, 100, 162, 220, 222, 105, 41, 247, 2, 212, 218, 27, 227, 223, 143, 244, 42, 241, 235, 175, 209, 42, 112, 220, 28, 170, 153, 55, 192, 42, 47, 139, 124, 60, 221, 21, 186, 193, 54, 247, 56, 217, 252, 112, 34, 254, 173, 240, 107, 58, 20, 244, 181, 164, 47, 254, 99, 237, 59, 186, 20, 186, 251, 28, 28, 117, 93, 181, 33, 97, 71, 185, 252, 16, 29, 230, 242, 67, 237, 181, 89, 31, 234, 6, 90, 212, 165, 35, 125, 68, 71, 16, 81, 208, 13, 238, 87, 136, 159, 60, 13, 122, 48, 153, 230, 231, 249, 239, 42, 43, 148, 69, 128, 178, 66, 195, 17, 201, 242, 3, 63, 35, 169, 148, 138, 168, 119, 239, 94, 87, 129, 192, 48, 36, 235, 28, 225, 122, 7, 91, 19, 29, 250, 85, 137, 174, 91, 183, 191, 233, 58, 106, 85, 15, 126, 193, 3, 167, 130, 206, 162, 27, 18, 145, 163, 30, 5, 20, 218, 181, 87, 85, 113, 219, 224, 201, 135, 108, 160, 234, 185, 186, 159, 140, 161, 232, 229, 197, 203, 84, 204, 51, 186, 96, 120, 168, 157, 98, 102, 196, 61, 137, 42, 63, 16, 145, 50, 89, 52, 66, 204, 153, 143, 7, 163, 217, 80, 154, 84, 80, 1, 148, 74, 199, 221, 51, 86, 24, 4, 58, 226, 19, 181, 125, 51, 51, 181, 15, 35, 48, 29, 165, 213, 116, 159, 222, 95, 15, 96, 119, 19, 122, 189, 253, 88, 127, 138, 28, 78, 55, 243, 84, 16, 85, 157, 13, 82, 149, 113, 206, 54, 219, 157, 113, 117, 96, 74, 112, 190, 20, 128, 135, 201, 46, 29, 90, 117, 196, 16, 198, 96, 90, 50, 74, 75, 168, 214, 69, 18, 240, 43, 239, 10, 91, 186, 103, 42, 19, 140, 44, 60, 118, 255, 49, 122, 183, 9, 85, 140, 255, 156, 82, 203, 50, 44, 39, 33, 25, 16, 44, 0, 30, 171, 176, 230, 179, 192, 76, 209, 135, 164, 229, 53, 147, 66, 76, 254, 127, 188, 182, 22, 88, 4, 180, 19, 19, 195, 171, 222, 104, 207, 201, 1, 184, 171, 32, 168, 1, 26, 72, 235, 224, 26, 222, 152, 20, 85, 142, 233, 20, 21, 178, 71, 89, 90, 14, 222, 9, 75, 10, 209, 116, 41, 10, 67, 99, 43, 61, 130, 172, 112, 115, 50, 11, 237, 15, 111, 243, 153, 248, 34, 147, 202, 118, 143, 136, 62, 35, 140, 117, 52, 123, 171, 148, 41, 12, 143, 198, 130, 224, 152, 172, 155, 183, 203, 228, 184, 235, 102, 32, 220, 235, 49, 31, 30, 235, 49, 12, 108, 238, 237, 234, 42, 31, 27, 120, 175, 118, 154, 161, 139, 9, 85, 204, 159, 3, 99, 7, 25, 85, 121, 25, 29, 205, 78, 31, 147, 219, 196, 84, 145, 14, 157, 185, 149, 117, 64, 234, 202, 200, 106, 130, 21, 249, 180, 170, 141, 6, 245, 78, 95, 58, 198, 251, 208, 75, 226, 53, 228, 187, 141, 76, 40, 58, 57, 150, 234, 165, 58, 7, 4, 205, 190, 1, 21, 184, 226, 30, 152, 80, 165, 14, 179, 201, 40, 21, 139, 159, 10, 77, 165, 82, 253, 38, 209, 97, 159, 223, 138, 136, 75, 185, 154, 115, 84, 135, 210, 17, 246, 69, 148, 97, 169, 39, 73, 135, 76, 157, 188, 172, 166, 63, 23, 162, 72, 169, 25, 93, 101, 123, 148, 125, 243, 32, 90, 22, 177, 176, 184, 222, 119, 218, 208, 147, 140, 125, 173, 205, 195, 199, 52, 215, 66, 0, 13, 193, 95, 79, 157, 183, 33, 240, 52, 216, 240, 6, 26, 88, 240, 46, 74, 69, 163, 0, 112, 72, 31, 39, 223, 110, 242, 195, 13, 54, 240, 229, 167, 180, 194, 116, 28, 79, 240, 215, 211, 66, 232, 205, 243, 183, 195, 52, 68, 22, 11, 220, 240, 167, 134, 178, 202, 27, 8, 154, 118, 136, 168, 32, 161, 110, 173, 203, 170, 192, 252, 212, 115, 222, 28, 185, 47, 176, 91, 238, 107, 138, 173, 251, 77, 153, 65, 206, 75, 141, 56, 123, 205, 250, 249, 113, 197, 127, 170, 237, 21, 24, 99, 102, 162, 67, 52, 57, 98, 137, 181, 20, 41, 92, 57, 158, 46, 179, 222, 115, 102, 195, 134, 198, 229, 100, 70, 233, 201, 105, 201, 8, 22, 160, 97, 140, 126, 30, 237, 92, 60, 205, 39, 175, 87, 245, 232, 230, 144, 72, 121, 14, 106, 125, 52, 210, 80, 195, 249, 172, 73, 121, 18, 119, 142, 209, 241, 27, 106, 26, 146, 186, 230, 156, 241, 160, 163, 65, 8, 239, 141, 68, 120, 28, 34, 68, 143, 47, 136, 92, 100, 154, 169, 29, 94, 49, 33, 8, 179, 24, 90, 161, 125, 65, 180, 89, 31, 124, 252, 189, 225, 194, 215, 126, 151, 106, 38, 80, 138, 128, 106, 94, 182, 71, 154, 118, 27, 14, 54, 235, 53, 218, 118, 93, 199, 20, 245, 92, 235, 59, 59, 143, 210, 181, 155, 49, 131, 124, 245, 126, 197, 69, 94, 216, 200, 231, 78, 198, 74, 101, 111, 121, 3, 155, 227, 54, 129, 11, 166, 247, 169, 174, 115, 253, 231, 229, 31, 11, 88, 212, 136, 99, 207, 32, 180, 182, 230, 68, 120, 73, 51, 194, 157, 20, 131, 169, 205, 218, 44, 35, 111, 223, 242, 208, 132, 92, 232, 36, 206, 217, 240, 144, 123, 143, 117, 134, 67, 229, 123, 127, 105, 151, 101, 60, 210, 151, 4, 109, 105, 98, 179, 200, 45, 51, 214, 56, 38, 199, 57, 73, 48, 49, 222, 75, 39, 66, 85, 100, 58, 5, 134, 76, 66, 114, 158, 126, 232, 90, 26, 201, 90, 38, 218, 98, 61, 233, 235, 187, 17, 201, 232, 200, 180, 245, 209, 193, 49, 197, 20, 72, 153, 56, 75, 86, 34, 102, 170, 183, 246, 100, 216, 32, 57, 237, 187, 124, 44, 48, 212, 25, 89, 16, 69, 229, 39, 52, 170, 209, 132, 116, 111, 174, 16, 61, 171, 184, 95, 42, 19, 240, 19, 90, 238, 241, 109, 228, 63, 255, 244, 173, 79, 127, 246, 48, 160, 140, 52, 9, 75, 76, 93, 49, 240, 225, 208, 126, 37, 179, 8, 185, 146, 1, 254, 33, 45, 130, 83, 139, 89, 208, 154, 55, 102, 192, 26, 167, 155, 176, 202, 142, 168, 109, 66, 33, 39, 200, 217, 38, 219, 76, 32, 88, 89, 252, 217, 121, 100, 177, 216, 134, 133, 38, 181, 111, 100, 202, 211, 116, 242, 194, 240, 219, 241, 216, 28, 189, 213, 89, 75, 197, 215, 200, 249, 33, 248, 103, 216, 8, 10, 18, 99, 78, 155, 36, 250, 175, 196, 41, 61, 207, 134, 132, 133, 145, 19, 78, 225, 20, 65, 69, 87, 210, 188, 96, 180, 117, 115, 106, 129, 149, 15, 88, 69, 116, 212, 41, 253, 93, 243, 195, 48, 244, 227, 71, 1, 89, 182, 77, 251, 90, 96, 205, 30, 23, 98, 62, 14, 31, 138, 245, 123, 64, 118, 167, 64, 35, 107, 46, 171, 88, 206, 79, 194, 26, 198, 0, 92, 163, 130, 235, 175, 171, 2, 149, 69, 71, 29, 87, 133, 155, 173, 94, 119, 209, 49, 86, 148, 132, 4, 8, 177, 210, 138, 6, 122, 169, 20, 36, 65, 196, 48, 137, 74, 170, 149, 81, 34, 157, 82, 46, 169, 68, 50, 89, 188, 170, 237, 50, 176, 92, 236, 79, 235, 250, 163, 81, 160, 114, 10, 8, 204, 187, 186, 96, 207, 169, 2, 211, 47, 118, 133, 135, 252, 54, 75, 117, 92, 162, 155, 164, 25, 107, 133, 4, 58, 106, 56, 212, 117, 192, 212, 55, 49, 162, 77, 226, 95, 187, 212, 240, 245, 66, 228, 132, 136, 14, 59, 52, 244, 161, 42, 131, 7, 30, 18, 126, 55, 221, 38, 159, 194, 185, 80, 89, 129, 250, 101, 176, 119, 183, 182, 133, 171, 80, 131, 32, 25, 231, 147, 63, 137, 160, 90, 97, 191, 87, 201, 47, 162, 117, 121, 68, 228, 141, 232, 158, 253, 209, 191, 134, 190, 110, 221, 220, 190, 218, 31, 91, 215, 208, 241, 251, 183, 164, 227, 246, 199, 253, 107, 160, 194, 131, 219, 72, 5, 251, 227, 193, 50, 73, 66, 247, 19, 230, 84, 213, 205, 123, 46, 117, 181, 233, 50, 180, 149, 229, 54, 39, 252, 144, 117, 199, 28, 48, 238, 136, 55, 158, 200, 224, 62, 47, 114, 70, 82, 55, 30, 136, 153, 106, 209, 51, 119, 130, 171, 177, 79, 61, 183, 143, 48, 110, 164, 209, 148, 79, 103, 150, 55, 13, 85, 148, 81, 165, 254, 112, 22, 9, 120, 127, 28, 171, 165, 231, 227, 22, 55, 176, 158, 186, 211, 175, 180, 177, 208, 192, 74, 216, 166, 157, 191, 177, 98, 34, 75, 198, 254, 44, 143, 187, 5, 235, 106, 81, 221, 218, 28, 104, 49, 227, 215, 204, 247, 238, 108, 95, 163, 33, 26, 245, 67, 92, 59, 68, 116, 131, 89, 87, 243, 215, 97, 9, 167, 242, 109, 165, 219, 200, 182, 59, 175, 127, 166, 142, 232, 71, 119, 38, 95, 188, 79, 91, 55, 169, 79, 250, 209, 157, 175, 23, 239, 222, 253, 27, 218, 61, 253, 232, 206, 201, 139, 247, 244, 193, 205, 239, 169, 126, 116, 103, 221, 5, 58, 77, 93, 130, 209, 165, 32, 91, 181, 109, 214, 174, 218, 182, 91, 76, 188, 99, 211, 129, 177, 61, 189, 89, 95, 195, 40, 206, 53, 240, 3, 178, 89, 190, 117, 197, 45, 61, 193, 183, 156, 4, 91, 3, 190, 31, 154, 217, 201, 188, 200, 249, 103, 57, 115, 122, 112, 214, 91, 124, 159, 204, 110, 101, 52, 198, 222, 205, 21, 28, 180, 168, 151, 249, 147, 196, 8, 121, 94, 255, 121, 226, 129, 106, 60, 103, 203, 242, 155, 249, 14, 190, 32, 193, 12, 214, 182, 203, 164, 35, 143, 172, 87, 237, 134, 133, 17, 17, 242, 83, 155, 255, 174, 248, 248, 66, 27, 252, 43, 173, 119, 32, 213, 214, 249, 181, 201, 101, 81, 230, 167, 144, 56, 64, 245, 133, 6, 158, 168, 17, 15, 70, 158, 244, 87, 221, 234, 79, 113, 227, 19, 3, 190, 77, 114, 58, 212, 132, 50, 171, 78, 101, 132, 233, 31, 206, 7, 178, 245, 119, 13, 186, 194, 243, 57, 59, 219, 65, 100, 59, 208, 197, 152, 111, 225, 205, 173, 116, 26, 212, 78, 144, 243, 231, 83, 62, 238, 22, 216, 252, 209, 136, 73, 139, 157, 49, 119, 195, 193, 183, 131, 26, 172, 160, 152, 13, 20, 180, 128, 188, 253, 168, 176, 61, 99, 173, 25, 147, 186, 140, 238, 31, 201, 71, 58, 122, 206, 150, 179, 140, 125, 109, 26, 186, 232, 22, 116, 100, 232, 182, 195, 163, 98, 44, 186, 54, 36, 135, 124, 108, 219, 97, 174, 163, 251, 140, 180, 24, 229, 152, 186, 157, 147, 232, 118, 97, 120, 141, 76, 204, 95, 190, 99, 88, 187, 65, 72, 199, 218, 25, 152, 79, 60, 95, 90, 137, 111, 59, 93, 178, 113, 225, 215, 55, 221, 212, 153, 146, 98, 246, 231, 35, 205, 19, 118, 3, 16, 11, 181, 83, 235, 96, 255, 154, 198, 156, 169, 225, 207, 63, 93, 80, 117, 161, 137, 210, 146, 102, 179, 131, 172, 77, 54, 174, 173, 122, 51, 71, 90, 15, 211, 139, 46, 111, 181, 199, 97, 4, 34, 43, 239, 152, 117, 64, 131, 26, 231, 178, 16, 72, 48, 226, 173, 52, 22, 62, 203, 164, 255, 101, 126, 112, 230, 135, 230, 176, 92, 204, 162, 53, 81, 17, 191, 106, 220, 189, 12, 116, 80, 139, 239, 247, 90, 240, 178, 114, 77, 248, 197, 246, 54, 249, 193, 231, 43, 168, 106, 191, 58, 113, 34, 240, 143, 132, 35, 59, 121, 213, 233, 40, 208, 136, 217, 123, 245, 189, 93, 108, 190, 244, 103, 76, 39, 118, 54, 100, 207, 4, 230, 205, 200, 86, 200, 151, 25, 244, 203, 12, 154, 124, 153, 65, 155, 98, 216, 231, 156, 62, 253, 77, 166, 219, 226, 12, 251, 50, 215, 45, 52, 215, 93, 71, 252, 222, 28, 251, 165, 148, 86, 145, 105, 198, 223, 62, 85, 133, 23, 92, 141, 197, 3, 48, 123, 225, 14, 224, 219, 47, 203, 183, 207, 49, 249, 220, 17, 245, 28, 62, 68, 210, 82, 61, 135, 79, 33, 199, 195, 231, 23, 58, 65, 103, 143, 101, 28, 148, 71, 50, 245, 7, 215, 241, 93, 155, 37, 255, 135, 85, 179, 111, 196, 107, 208, 144, 190, 90, 38, 136, 87, 149, 195, 24, 152, 48, 184, 158, 144, 195, 120, 68, 184, 132, 26, 193, 209, 19, 27, 115, 122, 46, 107, 188, 150, 117, 248, 135, 177, 103, 113, 45, 71, 20, 171, 160, 88, 215, 123, 60, 227, 205, 59, 141, 251, 176, 105, 203, 142, 134, 169, 15, 167, 142, 205, 216, 76, 92, 54, 201, 102, 164, 208, 10, 78, 3, 119, 79, 142, 231, 217, 197, 248, 34, 197, 203, 145, 226, 121, 172, 182, 26, 139, 109, 89, 34, 108, 98, 163, 34, 198, 93, 155, 83, 55, 53, 70, 93, 173, 57, 28, 183, 236, 62, 133, 134, 104, 227, 7, 160, 86, 90, 99, 152, 219, 10, 26, 89, 95, 84, 77, 221, 33, 216, 150, 11, 186, 248, 17, 135, 47, 234, 231, 139, 250, 185, 149, 234, 103, 193, 224, 210, 229, 132, 244, 182, 92, 154, 206, 165, 240, 230, 140, 235, 253, 162, 25, 169, 89, 124, 195, 18, 200, 169, 29, 129, 236, 125, 94, 204, 170, 103, 132, 195, 41, 195, 123, 46, 178, 253, 234, 191, 179, 18, 146, 245, 28, 137, 209, 150, 44, 209, 245, 96, 232, 115, 190, 178, 71, 78, 205, 136, 84, 177, 27, 244, 234, 211, 13, 125, 253, 181, 77, 8, 184, 35, 244, 242, 247, 39, 39, 39, 53, 71, 212, 221, 21, 147, 62, 130, 92, 135, 156, 135, 158, 215, 69, 84, 112, 124, 39, 99, 193, 60, 48, 120, 218, 44, 56, 225, 196, 167, 135, 8, 74, 124, 199, 193, 73, 119, 25, 8, 246, 87, 228, 225, 249, 238, 122, 62, 240, 56, 83, 55, 87, 181, 236, 94, 155, 60, 64, 6, 176, 206, 202, 82, 72, 125, 29, 55, 202, 113, 179, 204, 231, 214, 8, 33, 16, 225, 185, 32, 5, 53, 15, 70, 38, 65, 164, 221, 186, 123, 249, 18, 159, 129, 2, 169, 179, 142, 38, 163, 124, 234, 102, 157, 218, 91, 66, 242, 172, 189, 105, 81, 38, 143, 98, 215, 39, 209, 236, 89, 208, 204, 158, 156, 91, 108, 205, 249, 18, 116, 217, 122, 27, 38, 1, 214, 182, 171, 88, 111, 126, 94, 46, 57, 22, 38, 43, 215, 8, 220, 20, 55, 73, 39, 71, 110, 202, 2, 114, 52, 140, 178, 221, 177, 183, 100, 52, 183, 114, 212, 243, 33, 210, 182, 43, 169, 193, 79, 183, 64, 62, 3, 236, 133, 253, 170, 175, 96, 227, 150, 55, 68, 59, 75, 255, 172, 52, 50, 37, 121, 43, 104, 112, 154, 149, 154, 156, 4, 53, 147, 244, 100, 126, 157, 233, 52, 19, 217, 220, 225, 154, 85, 106, 84, 166, 172, 171, 249, 227, 33, 224, 159, 238, 82, 120, 27, 175, 194, 237, 59, 221, 236, 255, 147, 237, 6, 39, 12, 2, 168, 212, 83, 138, 107, 214, 215, 167, 166, 9, 81, 98, 129, 172, 49, 202, 96, 190, 120, 170, 3, 59, 244, 17, 237, 182, 128, 46, 59, 100, 170, 210, 128, 104, 164, 136, 215, 117, 183, 16, 164, 30, 86, 105, 154, 245, 220, 69, 136, 19, 77, 248, 191, 39, 120, 23, 36, 175, 103, 224, 49, 41, 227, 153, 45, 149, 205, 176, 75, 55, 244, 4, 63, 107, 190, 12, 48, 190, 238, 146, 248, 4, 149, 100, 18, 97, 248, 183, 237, 45, 189, 100, 1, 5, 225, 241, 227, 199, 142, 15, 87, 55, 136, 173, 240, 29, 14, 154, 138, 81, 215, 168, 242, 223, 129, 41, 105, 50, 62, 121, 137, 172, 124, 77, 43, 71, 228, 9, 243, 97, 115, 243, 71, 147, 19, 141, 160, 120, 134, 49, 55, 43, 36, 31, 55, 11, 89, 78, 223, 4, 234, 170, 189, 190, 190, 25, 168, 252, 127, 56, 161, 230, 166, 61, 198, 25, 34, 206, 111, 48, 115, 7, 244, 220, 139, 130, 172, 141, 168, 254, 19, 246, 226, 189, 72, 248, 50, 197, 30, 64, 226, 62, 237, 111, 194, 174, 4, 98, 83, 171, 82, 8, 244, 239, 219, 33, 162, 219, 118, 109, 183, 127, 243, 173, 79, 70, 254, 223, 152, 229, 247, 27, 186, 234, 65, 207, 254, 6, 203, 26, 218, 54, 252, 11, 110, 63, 101, 173, 162, 140, 127, 79, 236, 69, 225, 102, 44, 163, 108, 243, 187, 231, 36, 168, 65, 251, 247, 246, 91, 202, 64, 143, 223, 237, 242, 220, 118, 124, 158, 206, 254, 38, 84, 196, 239, 199, 155, 175, 89, 132, 115, 68, 161, 50, 59, 239, 183, 109, 175, 123, 30, 239, 54, 119, 236, 55, 25, 155, 196, 117, 109, 108, 243, 241, 55, 184, 105, 244, 55, 186, 201, 152, 128, 14, 19, 211, 182, 123, 183, 178, 234, 154, 241, 105, 249, 248, 123, 121, 233, 148, 10, 152, 112, 102, 91, 28, 49, 142, 86, 157, 92, 162, 250, 236, 57, 177, 234, 2, 40, 4, 167, 235, 75, 205, 176, 148, 74, 34, 75, 115, 81, 238, 74, 188, 133, 254, 243, 50, 232, 177, 140, 190, 160, 45, 51, 91, 247, 247, 128, 82, 145, 147, 149, 180, 62, 14, 78, 26, 179, 80, 253, 30, 78, 64, 165, 160, 64, 6, 44, 67, 9, 20, 254, 92, 30, 141, 115, 192, 83, 70, 104, 160, 206, 239, 250, 70, 67, 100, 40, 77, 137, 0, 113, 26, 9, 228, 19, 137, 114, 14, 85, 165, 70, 43, 234, 245, 203, 196, 149, 173, 6, 180, 59, 120, 91, 43, 149, 167, 57, 249, 64, 206, 79, 134, 21, 200, 226, 104, 55, 96, 131, 59, 150, 186, 231, 26, 169, 187, 65, 1, 20, 165, 187, 94, 58, 116, 151, 75, 204, 120, 65, 138, 65, 226, 90, 234, 90, 216, 63, 249, 119, 153, 78, 38, 246, 204, 194, 161, 126, 192, 197, 1, 254, 234, 4, 113, 118, 110, 115, 174, 51, 235, 163, 249, 234, 15, 35, 89, 232, 95, 101, 213, 116, 46, 154, 212, 44, 76, 230, 184, 85, 162, 21, 254, 128, 248, 211, 162, 148, 40, 250, 248, 127, 165, 215, 25, 114, 1, 131, 119, 98, 232, 75, 88, 36, 242, 241, 91, 37, 176, 18, 94, 184, 113, 124, 36, 175, 114, 222, 168, 212, 219, 215, 236, 130, 9, 227, 35, 2, 149, 183, 59, 26, 125, 89, 90, 95, 101, 105, 189, 18, 94, 40, 107, 226, 126, 38, 199, 101, 197, 83, 55, 46, 127, 153, 204, 150, 106, 58, 238, 185, 236, 37, 158, 195, 169, 153, 219, 76, 10, 136, 69, 150, 148, 11, 44, 128, 17, 87, 178, 114, 108, 183, 73, 198, 20, 188, 65, 182, 211, 225, 136, 196, 22, 155, 182, 213, 22, 75, 178, 64, 197, 141, 118, 72, 26, 68, 80, 255, 206, 177, 18, 61, 237, 172, 10, 198, 146, 62, 212, 135, 176, 204, 249, 115, 126, 16, 51, 4, 209, 223, 148, 32, 124, 234, 174, 111, 57, 19, 156, 186, 143, 20, 117, 152, 178, 184, 132, 17, 151, 2, 211, 25, 158, 18, 212, 234, 185, 12, 55, 10, 187, 87, 107, 192, 149, 217, 105, 246, 97, 210, 211, 243, 83, 28, 160, 28, 97, 123, 201, 14, 191, 110, 39, 71, 112, 162, 47, 47, 178, 139, 96, 67, 178, 219, 138, 31, 133, 182, 102, 108, 168, 107, 203, 165, 154, 66, 168, 85, 233, 190, 70, 187, 85, 233, 45, 221, 185, 86, 165, 239, 107, 127, 203, 159, 56, 98, 225, 10, 202, 174, 212, 181, 228, 175, 7, 61, 62, 190, 43, 206, 45, 65, 88, 56, 236, 212, 101, 52, 123, 145, 125, 96, 158, 53, 50, 113, 127, 234, 107, 14, 174, 226, 28, 245, 250, 68, 58, 82, 188, 253, 79, 84, 241, 203, 59, 201, 133, 101, 214, 85, 133, 126, 153, 165, 229, 240, 85, 17, 100, 46, 40, 186, 26, 243, 173, 215, 27, 110, 28, 82, 196, 140, 3, 4, 29, 219, 205, 239, 86, 192, 124, 51, 27, 20, 127, 36, 242, 226, 251, 135, 52, 121, 195, 176, 24, 139, 23, 114, 26, 87, 23, 192, 187, 145, 9, 70, 123, 251, 44, 7, 119, 44, 42, 110, 211, 236, 229, 31, 242, 183, 206, 24, 220, 76, 128, 6, 129, 218, 165, 94, 157, 5, 119, 115, 20, 222, 32, 132, 20, 5, 53, 38, 222, 12, 194, 145, 217, 92, 33, 155, 180, 74, 52, 91, 76, 92, 28, 70, 159, 194, 104, 57, 143, 113, 8, 247, 41, 132, 218, 251, 16, 218, 69, 244, 59, 81, 24, 196, 93, 134, 145, 237, 115, 121, 126, 145, 139, 12, 182, 73, 178, 101, 249, 134, 157, 51, 105, 171, 20, 80, 80, 91, 28, 76, 65, 93, 223, 87, 162, 130, 40, 251, 213, 35, 198, 2, 214, 222, 82, 181, 79, 2, 7, 81, 98, 177, 47, 102, 165, 137, 180, 53, 191, 217, 222, 36, 190, 101, 174, 147, 123, 241, 232, 150, 218, 208, 22, 19, 243, 97, 166, 124, 90, 97, 231, 17, 114, 39, 174, 229, 77, 17, 8, 255, 118, 130, 90, 156, 249, 49, 16, 6, 14, 129, 224, 214, 37, 70, 2, 208, 131, 110, 159, 154, 121, 196, 227, 12, 248, 247, 128, 254, 88, 239, 155, 31, 196, 37, 16, 19, 111, 245, 205, 17, 113, 74, 165, 208, 109, 32, 209, 120, 25, 215, 83, 230, 142, 129, 44, 132, 199, 48, 130, 199, 44, 26, 67, 243, 93, 136, 161, 240, 124, 53, 70, 1, 103, 84, 237, 0, 69, 99, 245, 45, 45, 174, 56, 50, 116, 186, 119, 6, 200, 59, 158, 184, 116, 22, 176, 1, 93, 146, 17, 222, 227, 149, 55, 146, 212, 219, 230, 155, 199, 8, 122, 75, 31, 117, 125, 211, 214, 147, 241, 161, 67, 121, 102, 120, 59, 39, 48, 194, 253, 147, 215, 2, 115, 3, 175, 129, 20, 132, 12, 134, 4, 235, 68, 91, 234, 217, 10, 133, 141, 69, 1, 48, 177, 53, 106, 60, 44, 150, 243, 35, 209, 167, 42, 123, 174, 217, 213, 23, 57, 211, 3, 231, 98, 1, 45, 116, 100, 98, 208, 197, 116, 180, 138, 35, 63, 0, 9, 44, 21, 127, 61, 228, 12, 25, 243, 89, 66, 208, 209, 220, 7, 98, 180, 180, 153, 230, 232, 169, 24, 139, 3, 145, 180, 0, 219, 152, 150, 45, 59, 50, 89, 185, 210, 184, 168, 213, 84, 88, 30, 188, 75, 91, 61, 67, 188, 155, 226, 205, 191, 204, 235, 131, 134, 169, 249, 214, 228, 145, 177, 171, 91, 93, 229, 216, 218, 234, 202, 25, 213, 237, 200, 66, 157, 213, 215, 140, 71, 69, 165, 96, 204, 30, 182, 116, 239, 30, 150, 114, 214, 141, 251, 213, 203, 162, 170, 242, 183, 163, 75, 52, 96, 153, 159, 202, 224, 205, 186, 172, 134, 85, 26, 248, 255, 72, 171, 23, 133, 186, 154, 212, 154, 232, 170, 114, 237, 90, 67, 21, 177, 91, 247, 4, 100, 172, 202, 145, 185, 226, 21, 169, 171, 96, 8, 12, 108, 33, 2, 166, 71, 209, 168, 165, 187, 166, 80, 55, 74, 105, 184, 228, 154, 128, 94, 117, 24, 64, 125, 210, 55, 34, 222, 150, 197, 87, 160, 70, 13, 175, 17, 56, 178, 163, 43, 238, 210, 77, 122, 218, 246, 199, 112, 91, 122, 58, 21, 252, 148, 169, 133, 145, 12, 13, 85, 82, 255, 94, 17, 196, 113, 201, 137, 101, 179, 30, 90, 149, 2, 175, 103, 21, 154, 170, 21, 98, 190, 55, 18, 47, 84, 83, 86, 226, 246, 171, 23, 66, 31, 29, 148, 191, 106, 41, 144, 32, 184, 55, 48, 128, 35, 246, 82, 161, 201, 38, 138, 188, 122, 169, 238, 37, 62, 210, 107, 19, 237, 39, 196, 57, 16, 226, 80, 148, 106, 235, 104, 198, 148, 77, 221, 235, 186, 85, 33, 104, 48, 44, 56, 102, 240, 238, 249, 248, 99, 15, 87, 172, 209, 204, 213, 132, 24, 49, 236, 132, 158, 192, 162, 99, 232, 78, 11, 49, 141, 193, 150, 193, 174, 111, 205, 56, 147, 116, 115, 134, 100, 60, 15, 36, 115, 227, 155, 50, 208, 118, 128, 46, 113, 17, 162, 157, 22, 38, 197, 212, 4, 239, 62, 21, 63, 72, 165, 238, 145, 99, 38, 96, 212, 141, 174, 80, 223, 81, 91, 208, 239, 8, 61, 42, 47, 157, 98, 93, 210, 142, 226, 185, 38, 228, 253, 59, 128, 221, 88, 80, 162, 134, 66, 68, 39, 131, 252, 161, 110, 128, 149, 211, 243, 40, 46, 48, 224, 72, 95, 170, 204, 8, 128, 174, 216, 224, 204, 23, 97, 100, 26, 55, 98, 166, 78, 231, 27, 95, 201, 163, 25, 64, 226, 120, 98, 120, 43, 155, 147, 174, 14, 28, 93, 211, 239, 247, 61, 11, 88, 162, 219, 236, 153, 53, 188, 172, 26, 225, 119, 39, 7, 155, 218, 18, 101, 12, 141, 130, 201, 56, 22, 148, 100, 9, 239, 147, 10, 179, 113, 204, 248, 18, 93, 39, 34, 246, 2, 178, 26, 28, 100, 99, 173, 24, 92, 245, 27, 15, 4, 96, 192, 191, 194, 204, 155, 140, 112, 248, 38, 233, 80, 244, 241, 131, 178, 105, 197, 154, 36, 31, 141, 142, 208, 12, 21, 159, 158, 140, 135, 87, 150, 2, 5, 6, 246, 145, 212, 19, 236, 36, 193, 227, 209, 52, 45, 167, 161, 9, 197, 217, 80, 98, 116, 204, 199, 211, 231, 26, 91, 106, 140, 155, 46, 80, 79, 153, 120, 35, 35, 14, 74, 39, 68, 139, 1, 81, 110, 11, 241, 195, 81, 69, 226, 165, 70, 202, 120, 228, 129, 58, 25, 67, 206, 210, 203, 40, 59, 93, 136, 221, 82, 230, 3, 245, 16, 121, 156, 116, 187, 253, 100, 103, 39, 185, 191, 9, 97, 16, 91, 156, 176, 135, 233, 248, 212, 200, 205, 38, 163, 23, 52, 168, 186, 202, 224, 173, 99, 191, 52, 242, 98, 13, 53, 30, 192, 65, 10, 116, 100, 233, 190, 248, 158, 92, 100, 141, 50, 155, 8, 78, 213, 103, 73, 160, 180, 122, 238, 234, 6, 255, 138, 175, 77, 240, 198, 159, 214, 89, 25, 110, 109, 141, 30, 41, 65, 152, 176, 124, 213, 16, 255, 203, 129, 168, 105, 138, 60, 4, 52, 165, 233, 57, 44, 85, 197, 162, 40, 216, 162, 51, 115, 68, 176, 82, 227, 18, 20, 142, 55, 21, 176, 105, 88, 68, 96, 75, 46, 233, 176, 189, 115, 70, 76, 11, 69, 113, 57, 236, 93, 6, 37, 77, 218, 218, 49, 241, 124, 147, 141, 35, 34, 186, 180, 246, 37, 77, 107, 215, 47, 250, 146, 228, 187, 184, 130, 193, 131, 76, 13, 107, 24, 203, 183, 114, 143, 240, 164, 44, 206, 117, 148, 77, 112, 27, 79, 31, 168, 211, 213, 254, 41, 204, 185, 108, 212, 213, 42, 89, 235, 102, 18, 13, 165, 64, 110, 74, 49, 10, 124, 30, 225, 192, 109, 18, 57, 243, 25, 166, 212, 183, 89, 203, 112, 67, 76, 62, 237, 223, 188, 112, 21, 171, 70, 211, 43, 96, 212, 160, 93, 143, 11, 0, 130, 3, 91, 5, 132, 236, 124, 195, 96, 117, 150, 62, 1, 232, 154, 251, 136, 20, 183, 18, 24, 17, 106, 6, 158, 88, 10, 6, 206, 252, 166, 130, 174, 218, 75, 88, 187, 74, 242, 106, 110, 176, 110, 97, 62, 40, 128, 71, 94, 33, 74, 16, 45, 50, 102, 245, 69, 111, 234, 38, 212, 119, 164, 68, 65, 210, 119, 184, 210, 24, 142, 30, 107, 54, 114, 21, 45, 154, 178, 225, 203, 198, 23, 110, 42, 124, 175, 56, 155, 245, 38, 69, 85, 27, 69, 63, 204, 62, 28, 156, 144, 45, 120, 2, 223, 78, 43, 69, 229, 109, 234, 233, 25, 69, 148, 163, 205, 1, 34, 142, 47, 81, 86, 168, 97, 4, 63, 179, 60, 239, 164, 104, 221, 248, 82, 87, 200, 238, 218, 52, 205, 71, 47, 101, 239, 0, 191, 53, 86, 203, 57, 93, 59, 206, 46, 142, 12, 170, 180, 71, 198, 129, 105, 74, 152, 248, 17, 230, 13, 164, 159, 153, 134, 147, 24, 170, 19, 159, 134, 236, 182, 240, 218, 35, 77, 144, 109, 198, 192, 198, 48, 171, 92, 108, 37, 103, 98, 199, 118, 88, 105, 31, 211, 181, 16, 46, 88, 185, 199, 91, 90, 215, 239, 221, 53, 34, 161, 76, 84, 73, 202, 152, 169, 107, 215, 147, 237, 215, 127, 84, 154, 131, 139, 192, 80, 1, 190, 18, 36, 37, 110, 231, 114, 144, 16, 45, 186, 32, 252, 162, 235, 183, 87, 174, 160, 121, 119, 181, 225, 183, 184, 242, 85, 21, 172, 180, 199, 53, 84, 170, 182, 57, 126, 186, 116, 99, 191, 251, 61, 6, 197, 116, 95, 88, 187, 7, 39, 112, 72, 226, 57, 110, 64, 153, 99, 64, 38, 238, 195, 38, 243, 35, 217, 5, 234, 82, 248, 193, 158, 8, 201, 47, 16, 138, 93, 9, 204, 29, 230, 139, 36, 139, 254, 69, 73, 133, 239, 52, 22, 242, 39, 225, 47, 214, 236, 78, 224, 126, 8, 239, 102, 12, 210, 31, 90, 121, 219, 101, 253, 72, 166, 248, 218, 60, 241, 225, 92, 117, 129, 28, 241, 161, 46, 134, 146, 223, 25, 199, 130, 236, 54, 237, 188, 229, 242, 163, 81, 46, 3, 56, 172, 62, 15, 82, 149, 15, 186, 75, 87, 161, 229, 121, 1, 218, 86, 169, 211, 228, 177, 22, 189, 244, 4, 110, 27, 9, 75, 51, 65, 57, 113, 155, 143, 132, 0, 108, 120, 152, 234, 111, 7, 220, 14, 159, 242, 120, 144, 80, 120, 70, 115, 58, 205, 1, 120, 125, 118, 39, 184, 192, 62, 155, 107, 83, 99, 62, 131, 187, 184, 102, 83, 3, 214, 114, 219, 73, 209, 225, 206, 237, 59, 105, 26, 208, 141, 39, 213, 213, 216, 226, 80, 213, 88, 154, 123, 27, 17, 248, 228, 123, 66, 154, 175, 231, 223, 20, 170, 240, 16, 94, 75, 95, 178, 166, 48, 209, 233, 6, 194, 252, 54, 131, 174, 122, 21, 95, 114, 195, 238, 80, 128, 211, 91, 108, 15, 177, 188, 39, 205, 155, 68, 235, 91, 203, 219, 29, 186, 170, 215, 219, 140, 208, 28, 62, 111, 194, 72, 50, 197, 192, 157, 212, 143, 208, 179, 38, 143, 22, 42, 5, 149, 103, 33, 155, 164, 24, 165, 77, 82, 45, 92, 73, 59, 72, 20, 2, 43, 31, 84, 5, 240, 62, 232, 152, 128, 50, 145, 145, 226, 103, 167, 141, 155, 9, 81, 15, 66, 211, 133, 107, 78, 142, 51, 86, 70, 145, 128, 246, 136, 240, 245, 108, 43, 36, 70, 208, 63, 227, 23, 115, 132, 133, 48, 12, 170, 54, 221, 207, 58, 39, 152, 70, 196, 85, 110, 246, 40, 62, 93, 22, 153, 113, 141, 114, 9, 85, 111, 26, 198, 2, 234, 205, 28, 212, 37, 109, 42, 218, 41, 142, 242, 85, 67, 120, 7, 92, 78, 203, 90, 88, 212, 176, 5, 177, 193, 212, 0, 254, 153, 254, 68, 158, 193, 35, 11, 39, 62, 114, 193, 19, 254, 166, 107, 199, 175, 169, 65, 174, 84, 62, 29, 189, 56, 81, 142, 143, 88, 213, 24, 63, 225, 225, 239, 94, 114, 40, 9, 99, 68, 163, 6, 231, 22, 88, 112, 28, 136, 118, 240, 249, 25, 154, 14, 107, 2, 98, 162, 166, 229, 84, 90, 168, 75, 208, 3, 26, 234, 188, 123, 125, 163, 192, 246, 29, 238, 1, 202, 189, 67, 89, 113, 95, 48, 225, 41, 28, 129, 135, 55, 116, 155, 80, 238, 23, 65, 15, 156, 52, 41, 63, 74, 184, 15, 73, 85, 232, 165, 174, 120, 34, 83, 251, 35, 116, 187, 94, 205, 149, 143, 195, 44, 94, 53, 10, 224, 141, 151, 187, 0, 28, 128, 106, 187, 182, 186, 40, 18, 168, 92, 22, 231, 110, 69, 139, 81, 207, 0, 183, 174, 194, 194, 93, 86, 71, 139, 71, 246, 35, 204, 102, 134, 220, 117, 16, 58, 181, 16, 43, 15, 248, 189, 138, 135, 116, 228, 57, 208, 253, 106, 127, 60, 18, 208, 196, 176, 62, 75, 203, 211, 204, 221, 98, 50, 99, 188, 186, 29, 225, 42, 205, 82, 116, 121, 116, 117, 174, 90, 96, 251, 184, 137, 117, 48, 173, 135, 207, 118, 146, 149, 18, 18, 36, 74, 121, 74, 214, 162, 76, 229, 108, 96, 154, 134, 119, 72, 94, 16, 139, 76, 144, 185, 96, 93, 42, 192, 154, 0, 24, 234, 183, 13, 214, 21, 220, 98, 25, 83, 158, 42, 231, 30, 108, 176, 207, 136, 135, 54, 198, 157, 153, 102, 77, 60, 42, 174, 97, 74, 104, 117, 123, 91, 146, 151, 12, 102, 127, 170, 184, 100, 210, 232, 220, 12, 21, 224, 166, 65, 1, 27, 184, 16, 117, 217, 191, 58, 19, 41, 96, 243, 48, 17, 180, 182, 139, 17, 159, 120, 227, 124, 119, 53, 152, 43, 166, 226, 91, 253, 225, 74, 129, 125, 7, 49, 234, 166, 89, 49, 99, 235, 122, 221, 205, 213, 213, 102, 120, 91, 115, 193, 139, 125, 234, 175, 6, 24, 71, 201, 4, 188, 55, 215, 20, 231, 210, 237, 38, 254, 236, 36, 30, 58, 219, 144, 83, 193, 245, 193, 249, 78, 77, 218, 108, 174, 13, 17, 235, 52, 177, 149, 218, 122, 63, 222, 84, 224, 255, 89, 238, 4, 6, 16, 111, 197, 228, 37, 167, 15, 174, 31, 118, 228, 86, 49, 252, 251, 209, 219, 78, 22, 227, 79, 39, 50, 44, 247, 48, 166, 81, 232, 76, 5, 19, 143, 110, 8, 144, 21, 205, 68, 27, 192, 169, 46, 0, 88, 126, 161, 96, 171, 73, 58, 118, 213, 161, 153, 145, 180, 34, 108, 55, 147, 73, 80, 243, 104, 28, 24, 229, 128, 194, 81, 81, 48, 221, 65, 49, 27, 47, 97, 81, 164, 160, 133, 152, 41, 110, 11, 143, 25, 175, 40, 68, 180, 46, 26, 211, 9, 197, 11, 20, 194, 140, 102, 102, 203, 73, 20, 255, 11, 73, 203, 249, 200, 139, 56, 106, 19, 114, 100, 67, 28, 164, 155, 26, 146, 97, 58, 96, 224, 132, 130, 193, 254, 149, 113, 216, 75, 189, 177, 189, 77, 151, 121, 80, 155, 100, 183, 122, 37, 29, 165, 212, 136, 30, 11, 171, 222, 100, 127, 145, 53, 108, 233, 35, 90, 154, 31, 7, 114, 28, 235, 68, 113, 188, 10, 233, 140, 220, 156, 167, 158, 107, 128, 237, 222, 21, 54, 107, 206, 76, 152, 112, 109, 243, 91, 37, 201, 208, 13, 153, 15, 124, 196, 229, 203, 150, 92, 193, 79, 135, 171, 18, 115, 159, 11, 63, 106, 85, 176, 239, 72, 94, 240, 180, 53, 199, 224, 202, 39, 146, 157, 14, 45, 116, 22, 153, 195, 104, 115, 10, 217, 239, 68, 36, 125, 76, 211, 169, 80, 117, 46, 139, 168, 116, 231, 240, 113, 248, 52, 168, 172, 101, 69, 39, 144, 97, 110, 254, 243, 207, 202, 250, 196, 67, 182, 52, 213, 208, 220, 231, 151, 225, 0, 211, 203, 34, 151, 59, 79, 177, 237, 95, 83, 102, 119, 42, 99, 183, 115, 150, 247, 125, 240, 46, 45, 247, 64, 127, 9, 8, 125, 161, 37, 186, 22, 228, 99, 204, 220, 87, 195, 144, 138, 58, 8, 83, 212, 54, 208, 144, 55, 217, 177, 164, 24, 130, 48, 65, 236, 233, 86, 123, 146, 155, 122, 182, 103, 148, 203, 173, 137, 209, 60, 123, 80, 142, 9, 45, 129, 166, 98, 22, 24, 188, 41, 211, 11, 153, 224, 226, 72, 8, 80, 98, 133, 99, 80, 20, 103, 50, 193, 186, 201, 21, 174, 11, 217, 240, 225, 244, 130, 125, 151, 53, 54, 196, 91, 107, 111, 72, 161, 28, 29, 101, 167, 210, 12, 99, 7, 213, 210, 11, 55, 158, 210, 43, 29, 48, 96, 49, 90, 164, 166, 134, 107, 189, 218, 141, 227, 244, 66, 159, 177, 227, 70, 164, 111, 0, 146, 162, 198, 174, 164, 135, 231, 250, 219, 228, 231, 142, 219, 77, 242, 209, 90, 155, 122, 235, 85, 215, 241, 108, 83, 234, 185, 33, 88, 173, 69, 236, 82, 3, 75, 219, 167, 31, 87, 106, 235, 66, 151, 76, 29, 75, 5, 198, 86, 218, 168, 245, 231, 162, 183, 249, 233, 156, 211, 80, 200, 206, 16, 80, 92, 35, 67, 15, 235, 142, 248, 246, 184, 67, 109, 127, 89, 12, 82, 123, 238, 252, 85, 126, 11, 162, 37, 184, 255, 108, 25, 136, 1, 156, 56, 106, 240, 53, 142, 156, 250, 26, 68, 175, 24, 13, 151, 129, 157, 0, 19, 71, 46, 142, 88, 24, 169, 147, 252, 67, 182, 12, 172, 36, 156, 40, 90, 211, 105, 20, 47, 248, 20, 182, 119, 82, 97, 237, 86, 75, 64, 13, 33, 69, 145, 203, 163, 184, 229, 97, 212, 170, 115, 161, 251, 150, 128, 152, 132, 19, 69, 75, 126, 141, 162, 134, 95, 131, 232, 137, 63, 103, 217, 50, 240, 147, 128, 226, 8, 202, 207, 113, 12, 241, 115, 196, 139, 187, 12, 252, 102, 111, 227, 200, 205, 226, 162, 32, 191, 133, 209, 154, 44, 5, 173, 73, 13, 90, 147, 26, 180, 38, 14, 90, 79, 170, 65, 58, 201, 118, 167, 162, 232, 219, 217, 20, 243, 212, 191, 183, 179, 114, 62, 158, 204, 64, 77, 211, 201, 234, 61, 91, 127, 78, 131, 49, 85, 186, 94, 47, 249, 166, 243, 77, 47, 233, 124, 253, 219, 172, 152, 110, 119, 130, 14, 247, 116, 60, 120, 39, 140, 91, 56, 210, 121, 117, 210, 40, 96, 237, 151, 150, 216, 141, 111, 118, 82, 121, 166, 244, 81, 231, 27, 65, 170, 32, 85, 20, 126, 107, 162, 67, 143, 161, 204, 145, 34, 105, 26, 81, 122, 197, 120, 58, 40, 70, 5, 172, 84, 71, 58, 191, 222, 149, 180, 159, 6, 184, 64, 215, 160, 110, 34, 43, 215, 116, 15, 241, 116, 251, 7, 117, 227, 93, 4, 75, 186, 107, 205, 233, 171, 118, 16, 32, 45, 218, 63, 168, 91, 211, 61, 133, 100, 251, 222, 201, 137, 126, 86, 142, 174, 222, 177, 208, 84, 223, 138, 31, 223, 149, 217, 73, 77, 143, 36, 114, 141, 236, 152, 77, 73, 90, 193, 253, 113, 142, 43, 90, 147, 74, 89, 197, 131, 76, 201, 186, 84, 197, 43, 14, 229, 14, 170, 248, 178, 33, 158, 201, 114, 213, 4, 90, 202, 34, 49, 79, 0, 4, 177, 226, 174, 175, 42, 167, 59, 206, 172, 91, 21, 149, 15, 101, 70, 163, 226, 2, 119, 82, 97, 17, 97, 113, 212, 240, 67, 91, 173, 18, 50, 236, 179, 78, 123, 22, 28, 182, 196, 73, 240, 180, 40, 159, 164, 131, 119, 114, 69, 241, 54, 29, 156, 157, 140, 213, 120, 8, 227, 54, 241, 118, 17, 245, 216, 132, 215, 233, 71, 106, 149, 126, 68, 214, 232, 58, 131, 149, 248, 54, 255, 226, 92, 111, 81, 215, 174, 200, 9, 222, 228, 171, 192, 222, 46, 217, 77, 39, 157, 165, 186, 59, 108, 22, 84, 221, 216, 253, 156, 1, 31, 231, 163, 76, 180, 209, 221, 236, 37, 180, 22, 229, 97, 185, 206, 12, 159, 64, 200, 166, 111, 212, 87, 122, 103, 138, 24, 43, 181, 72, 20, 197, 76, 8, 142, 202, 89, 114, 228, 125, 130, 74, 145, 80, 86, 92, 174, 139, 245, 9, 172, 53, 69, 213, 39, 227, 105, 121, 41, 40, 96, 92, 37, 186, 109, 191, 69, 178, 255, 13, 96, 106, 226, 80, 77, 15, 149, 36, 56, 112, 204, 245, 210, 193, 79, 9, 205, 101, 30, 226, 222, 0, 47, 246, 84, 107, 230, 207, 145, 207, 204, 95, 137, 190, 206, 153, 174, 214, 214, 168, 201, 85, 107, 211, 107, 249, 227, 32, 186, 162, 66, 150, 252, 79, 93, 182, 204, 215, 159, 61, 199, 215, 65, 84, 156, 14, 148, 56, 29, 48, 113, 50, 131, 120, 176, 144, 64, 205, 229, 234, 226, 56, 7, 252, 92, 115, 179, 172, 90, 231, 131, 54, 170, 117, 78, 1, 75, 219, 220, 124, 205, 12, 125, 16, 229, 101, 73, 81, 202, 202, 232, 24, 61, 255, 103, 46, 55, 80, 26, 220, 109, 7, 54, 81, 171, 117, 81, 88, 25, 177, 128, 168, 175, 195, 108, 79, 213, 74, 134, 227, 143, 54, 183, 181, 155, 186, 199, 193, 202, 161, 158, 138, 215, 44, 174, 164, 89, 232, 212, 24, 24, 87, 24, 237, 23, 126, 66, 162, 135, 162, 201, 84, 9, 54, 149, 130, 155, 19, 124, 113, 131, 162, 28, 42, 119, 237, 31, 30, 59, 43, 7, 109, 80, 173, 66, 70, 97, 233, 219, 141, 167, 20, 134, 218, 204, 91, 148, 94, 28, 41, 231, 167, 248, 178, 1, 22, 140, 102, 151, 241, 236, 28, 191, 172, 97, 33, 205, 8, 250, 139, 74, 69, 47, 159, 169, 71, 200, 128, 12, 199, 240, 184, 56, 63, 16, 42, 3, 141, 178, 142, 41, 174, 143, 164, 56, 163, 91, 87, 247, 69, 250, 194, 212, 34, 29, 132, 93, 53, 213, 13, 187, 179, 163, 145, 182, 94, 91, 85, 166, 102, 135, 231, 187, 191, 109, 49, 186, 189, 75, 43, 164, 153, 120, 10, 217, 46, 226, 117, 116, 246, 131, 52, 51, 226, 123, 135, 65, 60, 203, 46, 53, 72, 120, 12, 193, 132, 247, 181, 64, 161, 64, 199, 93, 175, 253, 1, 140, 252, 80, 102, 156, 146, 22, 236, 67, 77, 147, 30, 244, 162, 167, 26, 254, 232, 242, 161, 86, 10, 32, 203, 38, 194, 13, 88, 211, 170, 92, 168, 184, 63, 53, 71, 219, 253, 40, 92, 40, 46, 59, 35, 165, 13, 126, 136, 63, 244, 72, 13, 178, 180, 6, 212, 176, 233, 35, 216, 27, 159, 108, 203, 113, 78, 215, 101, 184, 186, 69, 154, 232, 143, 174, 33, 251, 235, 24, 48, 47, 166, 239, 178, 114, 225, 169, 197, 124, 107, 55, 177, 68, 76, 52, 12, 232, 147, 168, 244, 228, 36, 34, 113, 227, 60, 35, 191, 30, 66, 128, 187, 163, 58, 100, 7, 182, 253, 113, 10, 15, 172, 6, 227, 213, 128, 137, 66, 212, 210, 63, 55, 192, 4, 182, 243, 143, 190, 186, 18, 236, 255, 201, 165, 232, 176, 231, 91, 142, 90, 223, 255, 206, 167, 239, 228, 4, 174, 65, 247, 88, 155, 204, 38, 247, 108, 62, 97, 148, 235, 120, 23, 223, 42, 175, 13, 92, 144, 243, 83, 86, 86, 153, 2, 120, 51, 199, 153, 162, 184, 200, 112, 31, 201, 165, 86, 36, 231, 187, 248, 104, 67, 170, 205, 16, 142, 179, 11, 168, 214, 181, 81, 7, 2, 41, 84, 155, 193, 33, 80, 225, 82, 7, 70, 150, 77, 249, 157, 71, 6, 203, 13, 247, 206, 160, 118, 150, 252, 1, 49, 20, 230, 54, 140, 130, 214, 252, 210, 236, 249, 144, 69, 31, 185, 161, 167, 165, 93, 223, 198, 200, 80, 173, 134, 52, 172, 161, 180, 212, 227, 150, 238, 176, 90, 125, 239, 156, 93, 109, 35, 75, 239, 201, 57, 74, 22, 107, 77, 103, 225, 249, 53, 202, 18, 148, 130, 212, 60, 78, 80, 122, 176, 63, 146, 18, 7, 84, 45, 204, 71, 2, 174, 78, 28, 50, 52, 41, 151, 159, 243, 147, 147, 172, 204, 198, 131, 236, 134, 170, 22, 139, 224, 34, 138, 37, 162, 241, 63, 179, 190, 40, 169, 132, 126, 81, 26, 159, 66, 105, 12, 179, 81, 54, 205, 110, 163, 222, 104, 213, 29, 87, 7, 180, 146, 253, 163, 203, 243, 243, 108, 90, 230, 131, 207, 165, 4, 176, 135, 237, 61, 126, 74, 47, 224, 143, 78, 184, 11, 1, 103, 197, 157, 183, 57, 23, 154, 91, 22, 99, 44, 190, 186, 157, 127, 118, 106, 197, 153, 251, 21, 4, 112, 10, 126, 58, 185, 161, 179, 146, 69, 112, 145, 89, 105, 225, 169, 231, 113, 120, 230, 137, 101, 67, 158, 199, 122, 253, 95, 236, 135, 54, 57, 75, 174, 50, 239, 184, 99, 224, 113, 186, 10, 162, 243, 249, 124, 2, 43, 167, 155, 205, 233, 26, 197, 79, 202, 235, 59, 243, 241, 250, 124, 218, 123, 201, 179, 116, 36, 235, 77, 131, 2, 94, 144, 101, 126, 206, 171, 255, 64, 60, 34, 244, 237, 182, 205, 215, 28, 251, 133, 167, 234, 47, 107, 253, 187, 103, 182, 251, 210, 112, 179, 237, 242, 5, 215, 243, 13, 221, 172, 17, 254, 127, 229, 217, 69, 54, 220, 45, 203, 244, 242, 167, 25, 88, 187, 251, 39, 135, 89, 126, 146, 67, 200, 69, 10, 111, 85, 51, 38, 33, 237, 219, 217, 73, 18, 187, 210, 74, 85, 208, 81, 232, 244, 220, 158, 81, 24, 162, 58, 92, 162, 7, 80, 244, 109, 59, 44, 125, 202, 207, 217, 52, 29, 188, 203, 134, 10, 23, 40, 126, 146, 145, 136, 30, 245, 59, 166, 86, 152, 250, 222, 214, 98, 106, 42, 105, 21, 69, 58, 171, 27, 136, 106, 42, 111, 70, 104, 121, 149, 149, 130, 219, 75, 238, 211, 64, 19, 114, 39, 213, 15, 234, 86, 244, 77, 119, 183, 97, 119, 170, 250, 79, 113, 164, 227, 128, 67, 160, 250, 211, 60, 118, 154, 6, 49, 194, 198, 246, 207, 190, 183, 199, 120, 16, 119, 85, 161, 5, 186, 40, 40, 108, 195, 60, 214, 49, 21, 136, 67, 67, 228, 198, 213, 172, 204, 0, 17, 85, 16, 36, 135, 214, 72, 203, 83, 26, 36, 100, 47, 196, 88, 85, 57, 73, 108, 77, 249, 82, 119, 47, 210, 62, 20, 217, 38, 163, 173, 187, 236, 79, 79, 48, 57, 89, 216, 193, 57, 42, 213, 17, 34, 157, 58, 186, 192, 228, 196, 187, 108, 193, 6, 46, 45, 53, 91, 159, 70, 254, 6, 234, 0, 14, 236, 142, 13, 108, 65, 61, 206, 131, 166, 211, 250, 4, 56, 92, 213, 107, 201, 69, 247, 67, 249, 28, 15, 101, 235, 54, 90, 59, 133, 44, 247, 77, 149, 124, 67, 48, 250, 38, 153, 224, 221, 208, 220, 190, 147, 83, 161, 248, 30, 202, 46, 164, 250, 79, 238, 80, 9, 164, 162, 112, 211, 147, 180, 238, 208, 62, 35, 172, 133, 115, 152, 77, 138, 114, 250, 107, 149, 158, 102, 242, 104, 7, 28, 142, 236, 9, 173, 113, 31, 206, 151, 245, 191, 131, 67, 233, 247, 87, 87, 105, 147, 149, 6, 27, 218, 157, 235, 227, 137, 172, 206, 223, 255, 142, 253, 49, 132, 72, 212, 182, 179, 162, 21, 33, 149, 207, 19, 66, 193, 231, 195, 116, 154, 57, 221, 241, 57, 159, 238, 129, 171, 15, 78, 21, 59, 73, 68, 100, 64, 147, 137, 75, 1, 77, 70, 225, 93, 70, 19, 109, 2, 74, 71, 203, 254, 35, 117, 117, 16, 175, 28, 85, 66, 212, 194, 112, 49, 12, 140, 194, 183, 127, 251, 46, 38, 96, 42, 178, 6, 116, 10, 158, 203, 32, 131, 192, 243, 4, 168, 41, 253, 194, 86, 77, 106, 110, 182, 149, 216, 80, 80, 225, 23, 230, 142, 58, 217, 171, 192, 16, 179, 6, 237, 49, 27, 121, 172, 55, 74, 86, 236, 137, 95, 87, 30, 161, 201, 224, 180, 38, 207, 15, 231, 145, 235, 123, 221, 117, 123, 48, 150, 103, 53, 181, 128, 27, 233, 138, 35, 203, 232, 170, 167, 194, 183, 151, 211, 236, 224, 228, 68, 26, 106, 215, 77, 107, 108, 83, 61, 219, 118, 23, 29, 135, 249, 169, 191, 16, 245, 132, 5, 161, 114, 104, 181, 35, 227, 167, 38, 223, 205, 33, 153, 158, 41, 93, 121, 206, 62, 100, 231, 147, 81, 26, 16, 102, 184, 20, 188, 118, 166, 213, 85, 41, 42, 53, 154, 99, 207, 52, 209, 22, 69, 28, 83, 1, 221, 96, 185, 66, 41, 205, 217, 20, 153, 244, 26, 58, 128, 120, 236, 213, 10, 102, 219, 78, 185, 28, 219, 162, 119, 215, 209, 39, 23, 141, 96, 231, 98, 157, 130, 37, 177, 13, 241, 116, 253, 29, 77, 22, 233, 65, 43, 110, 63, 160, 61, 80, 120, 203, 207, 52, 226, 112, 43, 138, 224, 251, 172, 188, 36, 49, 172, 201, 85, 48, 109, 63, 165, 88, 71, 71, 67, 250, 17, 119, 70, 249, 86, 30, 244, 238, 252, 151, 133, 248, 95, 27, 38, 219, 228, 70, 6, 189, 233, 184, 182, 230, 53, 197, 76, 219, 192, 115, 191, 15, 143, 147, 190, 88, 137, 242, 44, 36, 9, 9, 30, 101, 30, 189, 179, 68, 38, 30, 57, 83, 211, 169, 120, 224, 169, 70, 206, 48, 233, 125, 114, 112, 124, 246, 218, 186, 114, 166, 89, 101, 179, 31, 182, 14, 76, 62, 195, 212, 206, 103, 214, 47, 36, 169, 100, 161, 45, 224, 237, 59, 170, 57, 81, 236, 176, 26, 141, 51, 182, 159, 224, 230, 146, 46, 6, 75, 87, 152, 79, 100, 179, 135, 57, 138, 156, 229, 6, 95, 64, 168, 67, 81, 127, 254, 9, 169, 229, 200, 156, 193, 78, 116, 52, 56, 6, 27, 214, 94, 220, 63, 248, 158, 230, 27, 86, 105, 89, 240, 7, 228, 25, 194, 199, 14, 239, 89, 192, 105, 72, 101, 139, 45, 187, 235, 87, 179, 84, 196, 34, 50, 37, 57, 70, 197, 11, 11, 88, 182, 16, 132, 254, 18, 177, 59, 211, 145, 192, 127, 3, 226, 153, 95, 253, 77, 203, 121, 138, 233, 94, 21, 63, 229, 167, 251, 130, 129, 237, 254, 179, 227, 217, 210, 229, 94, 204, 206, 223, 102, 37, 45, 183, 162, 55, 20, 71, 233, 52, 127, 159, 53, 101, 138, 57, 195, 36, 44, 188, 124, 67, 202, 23, 86, 56, 158, 247, 197, 41, 70, 179, 180, 232, 79, 87, 72, 177, 230, 32, 142, 41, 100, 218, 160, 141, 217, 100, 234, 145, 102, 137, 101, 106, 92, 85, 109, 156, 55, 7, 206, 194, 117, 97, 223, 77, 45, 23, 34, 85, 2, 185, 223, 108, 71, 84, 2, 21, 169, 246, 228, 23, 166, 248, 64, 215, 137, 250, 146, 153, 156, 85, 195, 65, 100, 42, 19, 162, 6, 11, 236, 187, 50, 151, 157, 200, 238, 124, 170, 201, 236, 213, 194, 211, 152, 114, 109, 79, 48, 194, 241, 205, 179, 188, 34, 33, 142, 131, 116, 34, 198, 76, 166, 131, 216, 188, 226, 156, 23, 243, 217, 211, 105, 238, 149, 51, 193, 217, 185, 12, 48, 60, 214, 216, 172, 173, 1, 111, 169, 146, 124, 98, 131, 182, 119, 131, 150, 163, 107, 164, 31, 244, 76, 231, 156, 253, 57, 213, 51, 88, 28, 235, 2, 226, 151, 237, 222, 238, 241, 88, 182, 14, 8, 141, 221, 244, 150, 187, 237, 167, 83, 197, 238, 177, 249, 84, 40, 251, 137, 104, 57, 135, 235, 193, 110, 187, 28, 140, 135, 113, 41, 48, 157, 156, 71, 8, 72, 165, 27, 98, 208, 197, 152, 219, 96, 26, 51, 225, 60, 107, 45, 196, 213, 248, 137, 32, 219, 158, 201, 228, 84, 23, 97, 49, 117, 207, 247, 109, 225, 51, 164, 147, 96, 55, 124, 218, 52, 246, 90, 13, 235, 201, 62, 54, 156, 197, 188, 109, 76, 56, 15, 183, 1, 143, 70, 121, 45, 200, 102, 235, 253, 249, 248, 75, 95, 55, 31, 98, 50, 239, 188, 239, 13, 231, 49, 173, 203, 44, 64, 202, 78, 120, 176, 247, 14, 173, 79, 91, 175, 59, 9, 27, 57, 83, 222, 34, 90, 73, 17, 50, 204, 51, 251, 234, 190, 27, 188, 159, 224, 201, 72, 222, 153, 162, 82, 41, 234, 44, 76, 155, 55, 97, 37, 201, 241, 195, 151, 6, 203, 192, 82, 18, 59, 230, 232, 162, 54, 11, 70, 119, 181, 89, 107, 186, 107, 223, 126, 40, 137, 214, 122, 159, 50, 24, 207, 228, 104, 80, 183, 27, 244, 58, 107, 40, 89, 3, 136, 87, 61, 175, 229, 255, 206, 202, 226, 96, 124, 48, 155, 30, 156, 252, 84, 8, 126, 168, 32, 190, 199, 64, 81, 153, 21, 31, 203, 100, 197, 181, 248, 156, 177, 210, 6, 119, 96, 223, 177, 183, 110, 133, 183, 106, 41, 54, 182, 83, 240, 25, 61, 157, 152, 32, 227, 51, 29, 71, 22, 45, 174, 44, 108, 91, 56, 106, 245, 242, 232, 17, 31, 228, 185, 244, 103, 128, 179, 255, 79, 1, 185, 141, 77, 42, 245, 27, 193, 195, 58, 53, 190, 207, 174, 128, 237, 117, 243, 170, 10, 105, 154, 200, 144, 160, 96, 62, 121, 56, 178, 216, 235, 200, 197, 123, 52, 21, 125, 140, 217, 109, 198, 56, 137, 135, 186, 112, 225, 42, 220, 204, 239, 109, 112, 155, 11, 221, 117, 139, 119, 22, 67, 239, 228, 186, 57, 89, 199, 124, 138, 38, 8, 5, 80, 203, 20, 123, 109, 74, 139, 82, 5, 66, 153, 111, 44, 13, 191, 46, 200, 23, 44, 192, 229, 125, 100, 105, 192, 206, 179, 87, 177, 26, 51, 88, 145, 217, 15, 229, 77, 85, 98, 4, 214, 188, 86, 216, 44, 167, 186, 189, 67, 69, 88, 86, 109, 217, 105, 123, 227, 2, 145, 147, 195, 136, 152, 252, 51, 187, 252, 252, 14, 247, 205, 152, 195, 29, 110, 192, 10, 78, 81, 201, 162, 2, 29, 182, 82, 30, 243, 51, 254, 81, 153, 111, 41, 245, 92, 238, 35, 179, 87, 226, 88, 20, 246, 125, 39, 72, 128, 14, 126, 39, 129, 246, 159, 96, 142, 173, 195, 229, 166, 76, 171, 49, 139, 205, 78, 183, 78, 134, 115, 161, 226, 80, 63, 44, 111, 226, 213, 202, 65, 77, 167, 204, 143, 41, 0, 142, 173, 70, 194, 198, 113, 42, 53, 83, 228, 99, 101, 54, 174, 175, 127, 178, 25, 242, 121, 58, 185, 125, 107, 133, 200, 226, 243, 60, 157, 220, 14, 231, 95, 107, 127, 25, 115, 252, 182, 240, 147, 156, 75, 122, 107, 103, 73, 11, 223, 159, 179, 200, 0, 95, 155, 244, 34, 19, 64, 139, 251, 219, 4, 111, 133, 23, 28, 135, 217, 112, 54, 200, 238, 12, 223, 149, 178, 59, 159, 130, 245, 152, 74, 132, 24, 203, 134, 91, 37, 220, 126, 240, 100, 33, 198, 88, 135, 31, 233, 96, 48, 59, 159, 141, 48, 163, 120, 107, 222, 22, 12, 180, 182, 246, 154, 41, 49, 159, 53, 57, 236, 154, 75, 74, 253, 108, 95, 222, 245, 164, 4, 150, 126, 37, 153, 88, 47, 64, 204, 75, 62, 59, 33, 247, 146, 218, 17, 133, 168, 120, 243, 48, 63, 125, 55, 189, 61, 12, 138, 125, 158, 195, 81, 87, 218, 110, 126, 178, 180, 105, 203, 231, 94, 50, 129, 95, 141, 135, 215, 215, 57, 15, 123, 19, 241, 237, 98, 225, 247, 112, 152, 171, 123, 19, 214, 187, 29, 15, 173, 79, 177, 194, 61, 207, 135, 195, 81, 70, 13, 186, 147, 81, 81, 200, 75, 153, 146, 191, 98, 206, 47, 51, 167, 142, 138, 11, 185, 5, 44, 6, 92, 61, 194, 81, 0, 5, 1, 223, 240, 73, 118, 38, 250, 90, 26, 230, 83, 85, 214, 245, 21, 21, 6, 160, 221, 177, 144, 63, 73, 24, 138, 172, 111, 63, 203, 159, 248, 89, 23, 134, 24, 14, 83, 74, 127, 82, 5, 161, 97, 3, 223, 97, 141, 216, 62, 239, 81, 240, 74, 156, 54, 103, 201, 56, 151, 28, 44, 141, 69, 14, 230, 8, 8, 145, 216, 183, 227, 26, 87, 223, 214, 176, 200, 151, 16, 139, 101, 134, 88, 200, 157, 107, 188, 216, 193, 191, 142, 78, 136, 199, 25, 189, 13, 163, 253, 126, 49, 187, 235, 70, 53, 240, 56, 217, 164, 210, 40, 175, 237, 25, 50, 128, 63, 229, 211, 139, 188, 202, 20, 215, 11, 40, 187, 210, 194, 181, 176, 144, 213, 85, 77, 187, 128, 170, 139, 192, 8, 48, 146, 137, 134, 183, 91, 216, 248, 2, 207, 255, 153, 48, 13, 26, 85, 191, 123, 60, 86, 123, 233, 214, 112, 130, 127, 193, 211, 97, 187, 49, 113, 46, 206, 239, 142, 241, 92, 137, 206, 220, 165, 253, 157, 79, 21, 127, 88, 19, 126, 104, 175, 114, 113, 24, 10, 227, 18, 219, 174, 223, 128, 207, 194, 11, 184, 87, 197, 179, 66, 32, 155, 161, 255, 114, 36, 127, 84, 52, 242, 176, 151, 20, 19, 168, 196, 94, 90, 70, 77, 49, 52, 190, 45, 179, 166, 38, 46, 189, 61, 195, 218, 58, 237, 125, 214, 39, 121, 89, 77, 159, 24, 239, 173, 4, 81, 235, 32, 150, 160, 66, 99, 73, 33, 109, 76, 25, 189, 122, 172, 25, 121, 139, 175, 134, 77, 156, 242, 224, 134, 143, 122, 157, 29, 166, 211, 78, 229, 20, 175, 101, 50, 106, 41, 251, 224, 245, 134, 6, 80, 176, 239, 225, 188, 152, 3, 209, 175, 124, 76, 25, 138, 187, 178, 13, 37, 66, 68, 32, 240, 61, 26, 144, 111, 171, 174, 141, 27, 115, 84, 31, 205, 222, 202, 78, 116, 223, 102, 167, 249, 216, 177, 101, 218, 220, 49, 117, 47, 122, 36, 107, 153, 70, 175, 194, 174, 222, 168, 193, 158, 4, 34, 93, 219, 196, 36, 234, 115, 98, 109, 66, 27, 201, 196, 200, 15, 153, 153, 67, 128, 229, 224, 153, 190, 21, 180, 217, 223, 169, 107, 99, 205, 159, 76, 68, 63, 111, 202, 188, 102, 21, 180, 241, 240, 19, 80, 136, 89, 93, 146, 102, 166, 156, 252, 133, 155, 207, 204, 138, 81, 21, 163, 118, 140, 237, 202, 26, 175, 210, 108, 207, 96, 49, 3, 193, 224, 130, 187, 51, 58, 93, 171, 141, 206, 182, 239, 89, 31, 37, 238, 140, 44, 156, 76, 107, 180, 119, 127, 161, 224, 245, 136, 250, 230, 158, 88, 44, 147, 109, 237, 106, 119, 54, 213, 151, 59, 5, 120, 184, 198, 180, 10, 156, 16, 129, 127, 144, 132, 85, 243, 46, 57, 108, 148, 184, 125, 241, 153, 181, 217, 78, 181, 67, 18, 179, 86, 51, 140, 104, 153, 199, 96, 13, 13, 116, 123, 179, 213, 31, 228, 113, 118, 97, 100, 192, 189, 12, 87, 33, 183, 78, 134, 205, 185, 15, 175, 134, 224, 148, 206, 134, 202, 236, 64, 23, 167, 176, 122, 105, 176, 89, 137, 159, 79, 222, 157, 170, 107, 221, 110, 138, 2, 36, 60, 148, 71, 226, 49, 118, 93, 95, 83, 195, 41, 216, 154, 133, 92, 72, 169, 232, 96, 21, 203, 101, 252, 246, 57, 19, 237, 192, 43, 184, 145, 15, 236, 171, 196, 52, 28, 5, 225, 151, 91, 33, 49, 17, 242, 144, 64, 56, 6, 131, 217, 148, 100, 214, 19, 125, 146, 179, 115, 91, 251, 108, 119, 26, 182, 206, 32, 68, 12, 246, 233, 110, 77, 156, 97, 139, 120, 86, 232, 207, 45, 140, 105, 213, 14, 202, 144, 75, 241, 22, 6, 182, 194, 40, 212, 243, 220, 255, 134, 0, 87, 211, 207, 219, 26, 228, 90, 199, 149, 55, 43, 210, 213, 144, 154, 114, 221, 87, 182, 140, 228, 240, 207, 31, 187, 210, 95, 13, 95, 64, 226, 34, 42, 116, 156, 202, 240, 212, 137, 69, 98, 14, 70, 179, 161, 232, 208, 29, 12, 197, 84, 61, 251, 156, 65, 35, 94, 246, 160, 198, 112, 204, 79, 21, 35, 73, 60, 134, 196, 92, 128, 186, 71, 130, 143, 36, 239, 192, 66, 204, 101, 11, 144, 63, 95, 242, 184, 251, 39, 1, 63, 129, 99, 104, 24, 63, 80, 104, 137, 45, 175, 170, 149, 121, 231, 170, 98, 86, 14, 132, 188, 159, 167, 147, 147, 49, 119, 238, 212, 94, 33, 181, 231, 91, 161, 244, 24, 249, 94, 84, 29, 62, 48, 87, 103, 237, 49, 229, 7, 209, 8, 242, 182, 84, 5, 79, 225, 115, 47, 228, 175, 112, 85, 176, 44, 74, 72, 212, 164, 128, 251, 216, 91, 126, 211, 43, 182, 159, 216, 91, 146, 217, 160, 219, 207, 30, 135, 189, 66, 82, 8, 216, 154, 159, 102, 21, 185, 47, 24, 86, 27, 146, 202, 129, 4, 60, 230, 174, 112, 155, 129, 135, 215, 189, 231, 46, 17, 253, 207, 212, 33, 224, 210, 134, 149, 142, 211, 232, 251, 190, 63, 73, 41, 156, 57, 145, 36, 120, 77, 10, 39, 253, 19, 31, 126, 245, 21, 53, 151, 6, 101, 154, 7, 56, 248, 152, 184, 196, 18, 61, 242, 116, 170, 128, 102, 138, 51, 229, 135, 144, 233, 119, 166, 184, 95, 234, 73, 253, 96, 50, 205, 207, 213, 178, 184, 171, 87, 143, 212, 103, 31, 81, 82, 8, 127, 219, 148, 171, 81, 78, 193, 178, 83, 152, 248, 32, 63, 99, 82, 147, 35, 100, 175, 151, 236, 217, 125, 22, 84, 180, 45, 252, 208, 168, 179, 117, 19, 42, 172, 7, 121, 237, 236, 181, 133, 245, 209, 60, 105, 245, 161, 171, 232, 50, 31, 91, 14, 76, 116, 76, 94, 166, 131, 179, 165, 15, 202, 156, 4, 84, 237, 210, 107, 176, 145, 217, 201, 12, 149, 203, 132, 149, 20, 91, 211, 128, 97, 249, 237, 150, 228, 114, 210, 215, 130, 27, 124, 31, 111, 246, 123, 85, 200, 19, 159, 90, 187, 114, 49, 180, 190, 91, 197, 73, 170, 54, 185, 0, 222, 200, 113, 76, 186, 44, 145, 2, 185, 180, 246, 156, 92, 90, 91, 92, 134, 93, 162, 146, 54, 194, 41, 87, 176, 118, 59, 134, 100, 11, 30, 213, 49, 194, 138, 126, 252, 26, 42, 19, 67, 241, 31, 131, 142, 118, 169, 175, 249, 65, 214, 85, 83, 229, 33, 91, 4, 121, 242, 224, 132, 185, 57, 1, 181, 108, 104, 181, 70, 151, 94, 219, 103, 249, 153, 58, 193, 207, 149, 152, 99, 161, 104, 23, 157, 169, 66, 217, 175, 253, 224, 44, 54, 40, 115, 239, 85, 25, 44, 217, 158, 85, 221, 136, 204, 61, 30, 124, 52, 234, 199, 130, 38, 205, 176, 227, 80, 99, 178, 28, 156, 116, 201, 106, 83, 13, 129, 183, 86, 210, 244, 92, 186, 137, 50, 206, 46, 150, 61, 58, 10, 164, 34, 14, 93, 220, 157, 185, 187, 37, 170, 32, 35, 14, 153, 37, 231, 188, 51, 209, 171, 88, 115, 117, 162, 205, 20, 202, 85, 27, 92, 156, 39, 234, 157, 203, 117, 132, 106, 215, 152, 211, 185, 181, 124, 130, 220, 35, 235, 244, 228, 37, 126, 213, 42, 25, 30, 148, 180, 220, 181, 87, 92, 107, 229, 190, 51, 44, 31, 48, 135, 177, 104, 79, 215, 101, 185, 251, 141, 122, 62, 126, 109, 80, 212, 6, 122, 36, 245, 249, 88, 93, 5, 16, 219, 240, 122, 110, 187, 64, 117, 58, 239, 135, 147, 104, 214, 237, 5, 220, 32, 7, 69, 58, 158, 137, 5, 111, 55, 26, 178, 166, 255, 44, 77, 194, 159, 211, 105, 250, 18, 147, 29, 154, 196, 194, 249, 218, 154, 218, 122, 219, 224, 89, 71, 144, 47, 84, 49, 198, 74, 196, 228, 89, 60, 142, 136, 230, 164, 230, 75, 240, 185, 179, 82, 147, 234, 109, 22, 170, 177, 248, 34, 183, 91, 1, 95, 142, 151, 234, 227, 32, 198, 117, 52, 203, 7, 213, 62, 166, 9, 112, 240, 47, 28, 130, 36, 119, 139, 191, 132, 33, 181, 12, 67, 82, 123, 39, 177, 56, 36, 73, 75, 26, 139, 132, 25, 92, 3, 233, 206, 14, 122, 177, 219, 202, 200, 192, 118, 86, 105, 195, 111, 234, 12, 81, 149, 56, 80, 253, 95, 33, 105, 170, 230, 21, 178, 48, 93, 67, 34, 204, 159, 48, 213, 47, 166, 79, 54, 111, 194, 2, 5, 72, 172, 174, 6, 215, 126, 30, 59, 27, 80, 113, 69, 100, 179, 126, 126, 116, 87, 189, 20, 17, 104, 149, 105, 57, 236, 142, 131, 89, 115, 107, 15, 184, 190, 35, 100, 177, 94, 13, 178, 14, 137, 31, 207, 106, 214, 18, 164, 7, 228, 212, 149, 75, 164, 87, 66, 151, 152, 67, 87, 74, 69, 180, 164, 213, 138, 214, 215, 134, 76, 98, 76, 14, 162, 10, 228, 91, 166, 64, 210, 193, 116, 150, 142, 158, 133, 156, 223, 97, 173, 98, 169, 171, 57, 197, 130, 216, 209, 236, 22, 107, 251, 59, 205, 144, 61, 219, 240, 146, 52, 225, 96, 86, 150, 66, 8, 158, 53, 42, 68, 104, 70, 41, 186, 29, 82, 137, 78, 187, 126, 124, 33, 156, 169, 66, 188, 73, 59, 40, 228, 250, 64, 139, 109, 19, 174, 230, 129, 73, 209, 18, 75, 110, 59, 29, 244, 180, 86, 144, 45, 244, 44, 219, 5, 12, 45, 45, 141, 53, 105, 210, 129, 101, 184, 181, 229, 145, 207, 79, 181, 253, 21, 157, 143, 230, 179, 216, 252, 154, 109, 76, 182, 175, 142, 222, 165, 37, 227, 166, 121, 47, 215, 142, 212, 111, 211, 184, 95, 119, 41, 150, 133, 7, 118, 161, 91, 47, 92, 32, 87, 177, 50, 194, 29, 13, 4, 253, 40, 139, 193, 43, 254, 197, 110, 184, 75, 118, 131, 55, 188, 215, 111, 61, 160, 247, 66, 155, 14, 106, 141, 26, 21, 23, 180, 30, 92, 137, 225, 147, 122, 180, 90, 100, 94, 252, 110, 179, 205, 172, 110, 144, 211, 182, 4, 153, 64, 15, 240, 242, 240, 3, 16, 120, 175, 249, 234, 121, 118, 94, 148, 151, 176, 83, 130, 133, 233, 134, 164, 135, 76, 235, 137, 182, 78, 24, 85, 59, 243, 207, 181, 223, 109, 214, 206, 181, 94, 147, 116, 202, 146, 29, 99, 243, 149, 6, 196, 39, 172, 184, 87, 192, 245, 77, 0, 201, 224, 93, 36, 83, 179, 189, 229, 192, 50, 177, 32, 83, 52, 199, 255, 156, 73, 155, 67, 233, 222, 35, 232, 190, 42, 240, 240, 208, 240, 166, 29, 106, 178, 152, 125, 138, 115, 77, 252, 224, 132, 51, 136, 11, 156, 23, 134, 45, 79, 19, 15, 112, 198, 79, 49, 193, 55, 27, 157, 2, 191, 208, 45, 136, 71, 132, 205, 119, 199, 72, 138, 157, 90, 128, 145, 87, 1, 89, 250, 102, 160, 27, 48, 146, 44, 82, 141, 101, 170, 237, 112, 204, 63, 197, 232, 182, 141, 99, 83, 122, 195, 132, 157, 213, 71, 180, 145, 194, 141, 177, 109, 188, 108, 77, 148, 155, 100, 173, 155, 149, 50, 151, 45, 52, 154, 163, 152, 15, 236, 38, 191, 85, 224, 170, 231, 24, 188, 71, 95, 9, 130, 250, 107, 18, 169, 218, 15, 211, 241, 169, 89, 250, 240, 3, 170, 215, 33, 172, 90, 32, 207, 36, 33, 41, 138, 63, 34, 145, 30, 146, 80, 178, 5, 37, 85, 88, 6, 69, 57, 21, 186, 22, 54, 125, 197, 132, 116, 50, 182, 162, 106, 94, 181, 219, 127, 183, 16, 218, 239, 193, 195, 1, 30, 91, 141, 175, 168, 63, 77, 32, 217, 178, 71, 15, 199, 65, 15, 12, 61, 11, 77, 146, 206, 120, 23, 141, 217, 230, 223, 84, 5, 88, 216, 187, 148, 50, 181, 131, 249, 239, 44, 61, 123, 158, 78, 200, 84, 13, 219, 155, 202, 123, 46, 198, 197, 46, 175, 206, 211, 137, 163, 166, 210, 225, 80, 250, 116, 196, 23, 184, 198, 141, 172, 187, 204, 168, 202, 34, 117, 65, 109, 184, 69, 162, 202, 105, 68, 217, 237, 108, 251, 211, 236, 60, 116, 57, 155, 69, 209, 97, 41, 226, 55, 135, 186, 113, 126, 122, 240, 173, 88, 129, 98, 255, 185, 251, 60, 228, 176, 151, 40, 202, 160, 143, 158, 193, 235, 120, 243, 53, 249, 209, 127, 141, 61, 112, 200, 43, 239, 250, 109, 34, 175, 138, 255, 15, 145, 87, 124, 217, 16, 207, 215, 68, 222, 232, 229, 119, 62, 125, 107, 168, 34, 239, 160, 224, 151, 251, 10, 50, 252, 127, 27, 8, 248, 46 }; + static const unsigned char data[] = { 120, 156, 237, 125, 107, 83, 28, 71, 178, 232, 119, 126, 69, 51, 225, 99, 15, 102, 224, 48, 72, 246, 122, 133, 36, 47, 198, 146, 151, 176, 36, 20, 140, 118, 55, 226, 112, 21, 58, 173, 153, 6, 122, 25, 186, 199, 221, 61, 2, 108, 235, 252, 246, 91, 89, 207, 204, 122, 244, 99, 24, 36, 96, 165, 8, 155, 158, 238, 170, 172, 172, 172, 204, 172, 172, 172, 172, 172, 227, 121, 54, 174, 210, 60, 139, 178, 228, 226, 221, 97, 50, 206, 139, 73, 127, 45, 250, 99, 37, 138, 138, 164, 154, 23, 89, 84, 86, 147, 119, 7, 239, 255, 157, 140, 171, 119, 227, 34, 137, 171, 164, 159, 205, 167, 211, 181, 157, 149, 143, 43, 199, 170, 238, 155, 252, 167, 60, 159, 38, 113, 214, 255, 64, 234, 174, 174, 126, 176, 202, 189, 154, 159, 191, 79, 10, 171, 216, 58, 45, 53, 138, 207, 147, 127, 198, 211, 121, 242, 63, 73, 145, 247, 47, 7, 209, 21, 41, 125, 25, 61, 121, 242, 36, 186, 138, 254, 252, 51, 234, 95, 70, 171, 236, 249, 50, 250, 250, 107, 246, 2, 30, 175, 40, 98, 191, 36, 213, 203, 164, 58, 205, 39, 253, 127, 14, 162, 215, 2, 204, 206, 14, 251, 223, 135, 184, 136, 160, 84, 244, 36, 250, 231, 209, 235, 183, 240, 42, 61, 142, 250, 251, 229, 43, 214, 185, 131, 226, 31, 217, 36, 57, 78, 179, 100, 210, 135, 66, 107, 162, 162, 198, 96, 174, 190, 66, 181, 143, 178, 234, 234, 126, 185, 23, 79, 167, 241, 251, 105, 66, 43, 189, 57, 45, 242, 139, 55, 87, 179, 228, 89, 81, 228, 69, 127, 184, 61, 136, 42, 246, 43, 63, 230, 8, 172, 41, 24, 18, 54, 188, 35, 93, 216, 47, 95, 23, 249, 44, 41, 170, 171, 95, 147, 171, 126, 92, 156, 204, 207, 147, 172, 18, 192, 161, 23, 0, 139, 245, 66, 130, 84, 223, 119, 12, 68, 81, 128, 209, 166, 87, 86, 69, 154, 157, 244, 128, 114, 232, 229, 213, 249, 251, 124, 218, 163, 35, 48, 75, 198, 105, 82, 238, 229, 25, 171, 50, 31, 87, 12, 237, 252, 253, 191, 7, 17, 235, 118, 60, 159, 86, 232, 189, 69, 82, 120, 197, 144, 97, 133, 55, 199, 166, 144, 162, 174, 248, 202, 26, 213, 4, 180, 8, 235, 194, 183, 40, 44, 24, 145, 3, 10, 209, 247, 187, 239, 7, 81, 47, 231, 229, 190, 41, 163, 111, 16, 26, 223, 68, 51, 73, 201, 158, 166, 58, 32, 93, 50, 140, 225, 251, 17, 227, 150, 159, 230, 233, 180, 74, 179, 17, 39, 74, 191, 87, 10, 66, 244, 214, 106, 56, 164, 180, 217, 163, 190, 23, 251, 132, 172, 78, 229, 82, 149, 181, 186, 197, 203, 12, 31, 14, 248, 223, 222, 223, 254, 38, 49, 211, 93, 138, 216, 224, 235, 94, 163, 78, 247, 88, 5, 71, 38, 12, 216, 205, 205, 77, 198, 50, 165, 64, 162, 42, 174, 36, 50, 99, 198, 201, 207, 101, 133, 62, 104, 0, 245, 227, 93, 60, 155, 77, 175, 6, 22, 118, 3, 51, 162, 131, 136, 195, 227, 189, 96, 96, 170, 241, 105, 212, 79, 172, 62, 38, 170, 143, 59, 54, 98, 187, 39, 39, 69, 114, 194, 148, 204, 18, 176, 163, 176, 150, 134, 226, 126, 86, 37, 69, 22, 79, 151, 128, 33, 1, 181, 28, 4, 129, 57, 117, 195, 172, 10, 250, 180, 151, 207, 174, 126, 142, 171, 88, 170, 19, 198, 60, 253, 138, 181, 147, 84, 131, 168, 204, 231, 197, 56, 25, 68, 201, 229, 120, 58, 159, 36, 147, 253, 42, 57, 47, 145, 104, 239, 212, 112, 63, 175, 106, 113, 49, 150, 174, 227, 34, 63, 103, 2, 246, 38, 151, 178, 43, 43, 40, 141, 113, 150, 92, 129, 252, 185, 200, 29, 20, 140, 216, 7, 23, 25, 211, 122, 6, 81, 0, 102, 163, 169, 112, 19, 144, 152, 118, 225, 243, 147, 23, 159, 99, 166, 127, 250, 208, 106, 202, 240, 103, 243, 72, 180, 181, 35, 31, 31, 115, 68, 54, 167, 73, 118, 82, 157, 202, 151, 235, 235, 10, 138, 68, 148, 85, 128, 82, 71, 252, 43, 215, 8, 162, 101, 254, 16, 69, 171, 167, 113, 201, 16, 6, 68, 28, 82, 126, 253, 181, 44, 228, 112, 134, 156, 91, 149, 28, 239, 151, 207, 50, 166, 193, 11, 152, 71, 84, 127, 25, 192, 53, 94, 93, 225, 19, 69, 63, 115, 242, 35, 138, 93, 105, 26, 241, 230, 161, 226, 17, 123, 122, 187, 38, 208, 252, 200, 41, 80, 203, 13, 255, 200, 142, 153, 238, 75, 10, 54, 168, 148, 47, 16, 35, 220, 30, 30, 144, 70, 200, 231, 30, 250, 69, 135, 115, 137, 35, 153, 207, 217, 160, 81, 155, 77, 127, 75, 179, 76, 127, 211, 95, 123, 199, 121, 222, 227, 116, 33, 170, 99, 183, 40, 226, 171, 103, 31, 146, 226, 138, 247, 234, 125, 60, 62, 59, 206, 34, 99, 104, 28, 224, 17, 172, 78, 211, 82, 143, 31, 35, 29, 255, 246, 130, 147, 176, 127, 32, 105, 169, 135, 103, 87, 26, 37, 165, 44, 176, 198, 199, 106, 43, 52, 129, 127, 55, 136, 182, 216, 28, 206, 241, 217, 100, 132, 172, 114, 176, 86, 54, 19, 64, 205, 204, 220, 182, 205, 101, 112, 174, 179, 188, 126, 102, 22, 238, 249, 44, 157, 38, 12, 167, 62, 107, 5, 215, 194, 28, 251, 134, 117, 200, 69, 251, 105, 52, 140, 126, 228, 243, 148, 252, 212, 31, 174, 69, 143, 168, 61, 168, 25, 237, 76, 48, 217, 25, 99, 48, 70, 15, 246, 96, 152, 138, 243, 44, 27, 156, 232, 192, 240, 1, 239, 15, 160, 195, 204, 131, 138, 129, 214, 92, 101, 80, 100, 211, 198, 32, 58, 56, 58, 123, 203, 88, 131, 61, 32, 38, 50, 35, 31, 79, 203, 100, 71, 190, 253, 136, 24, 198, 152, 131, 197, 60, 129, 113, 31, 177, 169, 172, 220, 207, 166, 105, 6, 228, 123, 1, 44, 167, 155, 52, 172, 192, 136, 66, 25, 100, 148, 159, 39, 183, 147, 63, 74, 134, 217, 253, 102, 143, 107, 115, 135, 24, 251, 26, 230, 144, 236, 211, 130, 59, 128, 15, 28, 230, 120, 158, 23, 207, 226, 241, 233, 237, 228, 143, 99, 129, 220, 253, 101, 145, 110, 236, 177, 227, 27, 127, 132, 71, 11, 30, 144, 195, 237, 176, 193, 203, 120, 118, 59, 89, 224, 60, 158, 221, 254, 225, 135, 218, 187, 96, 14, 197, 217, 193, 172, 74, 207, 211, 223, 19, 33, 113, 98, 197, 215, 103, 35, 254, 35, 247, 202, 240, 183, 125, 70, 40, 0, 129, 139, 236, 9, 63, 205, 193, 0, 200, 186, 118, 29, 150, 130, 42, 140, 104, 179, 100, 194, 29, 50, 176, 80, 94, 128, 201, 188, 70, 206, 46, 47, 130, 128, 251, 57, 114, 183, 21, 39, 50, 142, 115, 149, 17, 183, 102, 111, 39, 35, 10, 75, 251, 158, 240, 226, 209, 219, 32, 255, 109, 121, 184, 111, 16, 85, 121, 119, 46, 60, 83, 12, 8, 220, 165, 216, 170, 229, 164, 40, 234, 122, 166, 69, 63, 91, 86, 249, 250, 186, 170, 164, 57, 216, 59, 93, 182, 99, 78, 193, 136, 14, 127, 30, 38, 147, 249, 248, 150, 218, 82, 5, 199, 237, 83, 241, 167, 80, 74, 242, 71, 60, 30, 207, 207, 231, 211, 24, 249, 13, 189, 188, 171, 218, 69, 229, 25, 24, 202, 206, 194, 131, 146, 48, 155, 6, 113, 23, 167, 32, 166, 73, 20, 85, 128, 187, 67, 155, 109, 164, 145, 36, 162, 175, 139, 164, 100, 160, 89, 67, 200, 208, 158, 228, 196, 74, 179, 185, 55, 194, 213, 176, 5, 22, 69, 239, 153, 160, 156, 89, 28, 22, 93, 156, 50, 138, 69, 253, 245, 117, 41, 30, 107, 102, 181, 185, 170, 32, 117, 67, 157, 146, 136, 9, 208, 250, 250, 91, 178, 46, 110, 47, 138, 20, 148, 79, 246, 116, 231, 144, 16, 234, 119, 198, 197, 165, 95, 33, 136, 230, 37, 159, 66, 12, 253, 208, 7, 249, 228, 159, 44, 8, 239, 216, 75, 91, 33, 111, 135, 233, 201, 105, 245, 69, 232, 132, 208, 65, 191, 54, 162, 225, 23, 209, 163, 162, 183, 177, 113, 22, 61, 125, 34, 39, 175, 229, 74, 222, 198, 134, 43, 121, 79, 197, 100, 184, 177, 113, 79, 5, 239, 121, 154, 77, 250, 51, 198, 221, 233, 152, 153, 5, 183, 72, 224, 24, 65, 38, 97, 113, 211, 24, 119, 145, 54, 84, 233, 211, 45, 6, 3, 246, 81, 200, 58, 210, 56, 214, 25, 71, 114, 96, 197, 215, 101, 172, 21, 25, 173, 61, 38, 122, 54, 217, 7, 143, 234, 23, 246, 184, 97, 95, 65, 51, 31, 120, 61, 71, 138, 11, 188, 12, 176, 49, 108, 61, 242, 124, 144, 157, 225, 7, 135, 255, 191, 82, 54, 178, 153, 217, 113, 96, 15, 236, 79, 146, 77, 34, 103, 155, 120, 113, 158, 128, 239, 69, 194, 212, 83, 250, 33, 121, 195, 91, 226, 69, 97, 255, 237, 132, 45, 17, 69, 227, 186, 36, 44, 79, 86, 68, 239, 73, 149, 199, 209, 150, 36, 139, 88, 127, 191, 140, 171, 211, 119, 231, 241, 37, 159, 214, 214, 173, 210, 176, 246, 145, 165, 31, 161, 210, 172, 171, 118, 57, 101, 226, 97, 36, 71, 64, 6, 130, 35, 39, 140, 46, 39, 54, 84, 8, 146, 162, 74, 75, 28, 71, 130, 204, 77, 40, 202, 98, 62, 12, 159, 241, 17, 226, 227, 132, 55, 244, 89, 179, 208, 210, 35, 132, 121, 194, 5, 95, 226, 205, 184, 100, 106, 33, 14, 144, 90, 162, 205, 138, 54, 35, 205, 11, 97, 148, 199, 249, 156, 27, 0, 164, 180, 192, 100, 67, 110, 201, 8, 67, 168, 202, 181, 6, 225, 4, 126, 12, 172, 240, 245, 215, 240, 255, 199, 130, 228, 235, 2, 152, 18, 16, 185, 175, 133, 63, 41, 123, 42, 18, 171, 92, 246, 63, 231, 131, 180, 50, 196, 219, 167, 216, 24, 210, 45, 219, 102, 204, 193, 81, 149, 191, 229, 202, 29, 62, 235, 245, 47, 49, 176, 224, 223, 36, 153, 38, 76, 135, 242, 226, 212, 184, 17, 200, 110, 108, 168, 183, 85, 110, 158, 57, 38, 234, 231, 71, 219, 112, 251, 140, 232, 174, 175, 27, 116, 205, 179, 139, 174, 209, 73, 7, 62, 243, 99, 58, 101, 42, 146, 79, 114, 165, 148, 171, 173, 27, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 90, 153, 242, 182, 201, 156, 6, 179, 21, 235, 196, 7, 101, 157, 4, 89, 64, 248, 162, 56, 35, 236, 87, 73, 17, 235, 88, 166, 51, 48, 72, 244, 160, 167, 252, 91, 50, 17, 195, 142, 57, 128, 21, 214, 52, 72, 37, 4, 246, 253, 85, 114, 65, 129, 242, 66, 255, 200, 202, 248, 56, 97, 83, 226, 33, 91, 44, 20, 31, 146, 201, 104, 154, 87, 125, 85, 141, 155, 25, 180, 165, 86, 181, 134, 202, 145, 214, 84, 112, 91, 118, 107, 199, 80, 67, 125, 116, 229, 66, 97, 254, 42, 185, 172, 250, 134, 18, 172, 191, 160, 183, 24, 223, 43, 93, 104, 226, 174, 128, 22, 60, 238, 78, 20, 250, 101, 30, 23, 147, 55, 185, 67, 220, 181, 181, 192, 102, 60, 141, 126, 144, 188, 0, 22, 21, 1, 33, 34, 246, 246, 143, 255, 85, 112, 231, 176, 90, 131, 0, 74, 234, 185, 231, 244, 160, 199, 191, 16, 171, 42, 102, 40, 10, 138, 253, 98, 81, 140, 51, 192, 22, 18, 140, 114, 62, 133, 65, 255, 67, 48, 212, 35, 28, 138, 51, 201, 51, 246, 130, 175, 57, 97, 195, 92, 144, 36, 246, 116, 16, 96, 108, 66, 105, 178, 214, 148, 29, 23, 159, 49, 118, 42, 14, 161, 6, 195, 33, 102, 188, 243, 95, 83, 46, 183, 186, 60, 19, 210, 7, 219, 207, 153, 150, 116, 43, 110, 99, 149, 165, 112, 222, 47, 95, 231, 101, 153, 190, 159, 94, 73, 194, 130, 169, 58, 17, 155, 8, 177, 182, 249, 132, 142, 11, 150, 148, 170, 47, 70, 75, 99, 207, 162, 30, 94, 7, 65, 252, 61, 46, 127, 78, 170, 120, 124, 154, 76, 126, 154, 31, 31, 51, 53, 19, 19, 167, 172, 101, 70, 127, 191, 165, 150, 212, 196, 9, 139, 167, 18, 75, 47, 199, 88, 47, 43, 211, 93, 144, 251, 41, 247, 121, 168, 214, 252, 226, 36, 152, 3, 69, 152, 116, 28, 220, 26, 168, 76, 144, 5, 30, 235, 114, 108, 57, 102, 122, 108, 25, 17, 135, 22, 63, 125, 144, 171, 186, 152, 68, 158, 120, 219, 117, 96, 109, 227, 245, 225, 44, 78, 65, 109, 9, 48, 3, 13, 239, 237, 142, 175, 53, 40, 92, 211, 210, 142, 208, 47, 164, 10, 7, 135, 244, 142, 170, 209, 98, 129, 128, 197, 24, 175, 17, 190, 226, 95, 249, 2, 180, 164, 241, 45, 62, 165, 206, 213, 3, 39, 43, 111, 114, 47, 206, 242, 140, 173, 110, 166, 175, 226, 243, 164, 143, 65, 177, 149, 30, 71, 186, 236, 57, 11, 146, 103, 89, 85, 164, 237, 27, 219, 94, 115, 181, 42, 15, 85, 106, 89, 127, 203, 83, 31, 4, 122, 183, 188, 202, 198, 253, 24, 254, 207, 195, 199, 248, 54, 217, 113, 134, 205, 149, 1, 87, 135, 108, 97, 232, 183, 97, 246, 144, 10, 87, 235, 5, 14, 117, 111, 154, 151, 243, 130, 115, 20, 252, 140, 96, 105, 252, 20, 177, 9, 236, 199, 165, 25, 64, 21, 77, 174, 98, 11, 193, 200, 188, 42, 198, 140, 99, 188, 38, 230, 117, 144, 48, 123, 86, 196, 111, 242, 17, 15, 254, 82, 101, 109, 63, 223, 188, 100, 112, 119, 101, 215, 213, 100, 107, 72, 225, 137, 209, 141, 113, 97, 25, 169, 43, 176, 244, 193, 178, 212, 118, 228, 111, 208, 234, 178, 133, 222, 168, 182, 112, 160, 229, 85, 95, 220, 179, 235, 86, 112, 107, 214, 41, 199, 191, 12, 17, 69, 13, 149, 214, 108, 141, 73, 13, 111, 95, 39, 106, 73, 156, 218, 212, 69, 189, 28, 213, 147, 215, 223, 154, 69, 50, 99, 245, 251, 193, 6, 104, 23, 160, 222, 40, 68, 188, 238, 228, 51, 136, 125, 68, 140, 208, 102, 132, 193, 76, 106, 221, 17, 181, 205, 74, 99, 195, 247, 96, 115, 85, 135, 114, 219, 222, 155, 189, 65, 180, 7, 238, 160, 35, 61, 36, 100, 43, 13, 254, 129, 5, 29, 95, 196, 105, 37, 92, 68, 25, 211, 175, 194, 75, 8, 7, 5, 166, 211, 252, 66, 194, 4, 244, 192, 15, 99, 92, 200, 72, 247, 208, 113, 36, 61, 30, 132, 199, 88, 126, 33, 228, 119, 131, 9, 52, 70, 59, 100, 68, 165, 118, 161, 67, 215, 28, 134, 192, 53, 138, 86, 140, 3, 3, 157, 89, 197, 104, 68, 109, 80, 130, 66, 232, 157, 59, 248, 157, 2, 24, 224, 31, 12, 195, 25, 204, 242, 54, 127, 239, 74, 219, 4, 190, 171, 111, 102, 51, 217, 148, 228, 246, 43, 55, 184, 210, 179, 4, 47, 71, 16, 151, 238, 232, 146, 182, 1, 164, 42, 98, 67, 104, 113, 46, 19, 75, 50, 185, 102, 51, 65, 39, 6, 40, 98, 58, 233, 44, 80, 91, 151, 254, 45, 124, 65, 113, 141, 37, 218, 208, 119, 89, 68, 242, 130, 166, 236, 143, 178, 118, 27, 6, 208, 174, 237, 53, 93, 253, 17, 241, 104, 119, 28, 87, 107, 84, 197, 72, 161, 17, 149, 198, 54, 29, 209, 143, 200, 40, 178, 167, 225, 126, 192, 0, 224, 118, 220, 18, 166, 253, 198, 217, 188, 245, 92, 222, 228, 219, 30, 74, 100, 93, 191, 182, 68, 88, 161, 196, 53, 5, 154, 9, 210, 118, 83, 142, 84, 244, 118, 228, 57, 129, 166, 145, 245, 206, 10, 158, 25, 193, 51, 27, 216, 14, 251, 20, 207, 7, 31, 175, 37, 70, 88, 89, 91, 82, 163, 189, 248, 205, 42, 90, 114, 70, 168, 75, 109, 4, 168, 70, 116, 222, 88, 90, 19, 201, 141, 163, 171, 3, 162, 3, 177, 51, 254, 168, 46, 159, 246, 35, 146, 178, 82, 163, 247, 82, 173, 242, 218, 42, 188, 208, 56, 173, 72, 42, 52, 171, 188, 21, 209, 115, 87, 237, 117, 222, 148, 19, 92, 126, 134, 70, 191, 110, 144, 154, 134, 200, 209, 107, 84, 171, 181, 214, 105, 64, 112, 87, 125, 225, 216, 38, 170, 154, 152, 169, 196, 79, 16, 34, 111, 17, 167, 124, 208, 97, 42, 79, 88, 242, 66, 155, 255, 206, 211, 12, 137, 178, 255, 176, 164, 207, 79, 132, 142, 85, 84, 18, 131, 129, 128, 105, 31, 158, 244, 145, 13, 192, 155, 226, 110, 151, 94, 228, 172, 86, 34, 59, 54, 229, 63, 152, 124, 229, 51, 40, 131, 207, 64, 225, 222, 98, 29, 235, 99, 69, 123, 63, 210, 113, 145, 168, 147, 24, 61, 204, 247, 199, 105, 81, 86, 207, 166, 201, 185, 136, 87, 224, 144, 142, 182, 222, 170, 134, 14, 141, 35, 199, 57, 164, 138, 106, 106, 82, 30, 50, 24, 178, 1, 108, 254, 31, 114, 108, 101, 127, 37, 255, 120, 233, 134, 96, 110, 86, 132, 76, 3, 130, 170, 60, 154, 132, 123, 82, 38, 179, 88, 41, 248, 222, 160, 231, 136, 204, 48, 44, 50, 160, 102, 108, 26, 40, 185, 57, 140, 214, 159, 24, 216, 102, 181, 229, 153, 24, 16, 24, 164, 29, 57, 0, 187, 243, 254, 238, 35, 0, 78, 239, 49, 112, 101, 232, 26, 53, 135, 248, 241, 144, 48, 220, 87, 36, 116, 146, 248, 8, 4, 67, 5, 29, 23, 178, 206, 32, 234, 193, 62, 228, 145, 152, 35, 55, 229, 17, 208, 183, 174, 31, 131, 198, 97, 230, 69, 122, 2, 14, 116, 254, 137, 107, 54, 224, 77, 195, 217, 59, 136, 77, 185, 38, 96, 156, 186, 161, 89, 85, 171, 135, 45, 236, 104, 98, 36, 23, 42, 145, 0, 119, 14, 179, 98, 205, 137, 61, 114, 220, 209, 44, 107, 34, 237, 204, 90, 33, 240, 236, 67, 196, 202, 198, 241, 84, 53, 194, 97, 205, 202, 204, 172, 97, 239, 138, 188, 44, 15, 147, 120, 122, 46, 55, 158, 113, 145, 182, 72, 11, 240, 82, 207, 153, 106, 128, 208, 94, 227, 217, 97, 81, 125, 143, 19, 215, 148, 197, 136, 8, 159, 118, 207, 221, 125, 247, 34, 132, 215, 162, 123, 158, 117, 119, 115, 93, 213, 165, 189, 218, 35, 217, 181, 212, 88, 181, 169, 29, 50, 23, 31, 50, 214, 69, 99, 233, 57, 136, 173, 52, 120, 227, 172, 44, 112, 112, 172, 230, 105, 92, 193, 177, 3, 62, 197, 21, 170, 86, 171, 96, 18, 113, 24, 241, 69, 67, 72, 137, 101, 26, 163, 70, 186, 196, 127, 216, 53, 109, 99, 249, 115, 70, 105, 3, 9, 25, 201, 247, 179, 74, 236, 232, 128, 209, 112, 48, 48, 228, 225, 78, 241, 161, 221, 7, 102, 144, 224, 237, 38, 143, 213, 0, 112, 251, 75, 26, 9, 40, 53, 73, 102, 213, 233, 171, 249, 57, 159, 71, 86, 66, 1, 63, 76, 236, 49, 209, 152, 58, 243, 250, 94, 16, 48, 179, 237, 73, 43, 146, 65, 250, 68, 100, 86, 104, 133, 73, 235, 128, 97, 5, 101, 16, 13, 123, 146, 7, 186, 245, 19, 192, 133, 31, 124, 83, 120, 69, 118, 27, 30, 172, 193, 92, 137, 212, 122, 109, 197, 12, 152, 0, 187, 47, 247, 171, 56, 12, 50, 163, 139, 38, 212, 119, 102, 14, 227, 23, 143, 13, 6, 228, 3, 13, 79, 194, 53, 210, 140, 156, 59, 86, 134, 65, 162, 141, 2, 241, 245, 8, 213, 33, 94, 73, 75, 198, 144, 19, 105, 199, 56, 104, 12, 180, 218, 80, 74, 31, 129, 212, 63, 229, 102, 64, 175, 36, 84, 252, 10, 97, 233, 190, 214, 47, 44, 127, 173, 20, 135, 211, 124, 62, 157, 200, 129, 166, 113, 175, 162, 167, 124, 20, 105, 72, 70, 228, 212, 82, 19, 181, 196, 205, 105, 137, 147, 31, 215, 177, 93, 118, 178, 162, 37, 150, 242, 45, 245, 48, 113, 178, 16, 110, 241, 177, 41, 45, 217, 64, 63, 211, 250, 192, 169, 234, 80, 85, 16, 100, 35, 26, 122, 8, 107, 199, 158, 64, 191, 49, 174, 16, 133, 123, 57, 60, 198, 255, 106, 125, 199, 223, 253, 245, 59, 143, 155, 184, 246, 60, 55, 198, 58, 178, 199, 131, 116, 202, 4, 187, 248, 207, 240, 154, 146, 174, 190, 221, 173, 196, 102, 231, 50, 35, 90, 212, 112, 26, 29, 153, 202, 136, 62, 185, 208, 85, 138, 152, 86, 120, 138, 150, 60, 96, 247, 147, 175, 206, 202, 68, 69, 164, 175, 123, 202, 173, 168, 168, 232, 199, 209, 22, 184, 214, 207, 172, 173, 220, 80, 102, 30, 21, 19, 194, 215, 16, 45, 246, 34, 119, 43, 199, 152, 126, 147, 31, 194, 209, 243, 50, 153, 244, 151, 65, 210, 93, 25, 137, 182, 152, 71, 65, 70, 156, 137, 120, 181, 51, 19, 83, 166, 190, 153, 40, 96, 20, 121, 21, 116, 8, 232, 26, 182, 25, 230, 95, 252, 231, 69, 197, 136, 0, 22, 77, 92, 36, 199, 146, 246, 60, 186, 84, 189, 178, 246, 64, 44, 151, 162, 169, 25, 48, 153, 254, 66, 230, 218, 197, 105, 204, 221, 45, 11, 211, 217, 67, 46, 233, 117, 59, 19, 97, 178, 196, 6, 6, 92, 30, 147, 141, 123, 21, 119, 115, 94, 90, 84, 117, 188, 26, 28, 183, 119, 101, 14, 145, 90, 178, 9, 67, 35, 127, 32, 253, 139, 184, 172, 110, 109, 180, 52, 32, 247, 105, 34, 166, 141, 27, 124, 9, 113, 211, 234, 24, 140, 239, 44, 198, 226, 177, 245, 238, 54, 196, 205, 71, 216, 195, 0, 120, 163, 236, 225, 195, 237, 142, 180, 215, 24, 222, 51, 6, 234, 194, 41, 55, 26, 131, 175, 9, 76, 24, 4, 118, 163, 84, 89, 30, 9, 248, 33, 158, 34, 223, 16, 138, 230, 57, 79, 126, 73, 50, 18, 191, 194, 138, 178, 193, 4, 111, 88, 207, 210, 86, 24, 42, 31, 163, 238, 96, 249, 241, 42, 31, 92, 181, 235, 177, 63, 97, 228, 76, 153, 114, 246, 122, 210, 104, 29, 221, 196, 114, 187, 168, 75, 47, 187, 143, 186, 248, 33, 7, 210, 29, 178, 40, 34, 64, 139, 72, 31, 63, 17, 97, 35, 50, 209, 17, 164, 34, 255, 227, 64, 68, 65, 218, 193, 177, 106, 187, 14, 149, 220, 52, 209, 165, 202, 94, 132, 102, 69, 0, 39, 42, 189, 105, 114, 49, 5, 252, 181, 184, 226, 26, 214, 189, 58, 54, 51, 188, 237, 139, 235, 14, 116, 155, 248, 240, 158, 246, 218, 9, 104, 225, 45, 64, 72, 30, 104, 43, 16, 85, 199, 43, 127, 50, 0, 217, 74, 17, 39, 81, 248, 57, 45, 116, 212, 236, 31, 43, 54, 46, 34, 80, 214, 175, 39, 61, 104, 240, 226, 88, 131, 1, 83, 106, 74, 67, 198, 69, 120, 225, 115, 87, 153, 130, 93, 244, 38, 174, 101, 217, 49, 82, 177, 201, 94, 62, 130, 198, 197, 42, 204, 212, 17, 191, 81, 236, 44, 188, 248, 104, 19, 138, 176, 162, 160, 150, 8, 23, 45, 22, 36, 154, 10, 214, 190, 33, 26, 161, 82, 94, 146, 180, 136, 78, 123, 20, 16, 68, 153, 166, 212, 81, 251, 106, 171, 137, 181, 102, 104, 220, 71, 2, 138, 202, 134, 246, 49, 148, 104, 240, 24, 212, 15, 120, 87, 86, 128, 20, 10, 162, 208, 170, 102, 110, 185, 94, 44, 169, 6, 58, 26, 129, 70, 66, 214, 74, 168, 27, 240, 165, 194, 236, 96, 108, 86, 218, 138, 240, 146, 201, 32, 40, 87, 22, 21, 33, 23, 178, 119, 31, 195, 19, 200, 223, 147, 41, 227, 180, 87, 22, 61, 149, 61, 228, 143, 128, 63, 16, 241, 239, 7, 40, 250, 221, 5, 217, 63, 88, 32, 2, 222, 5, 211, 34, 14, 94, 28, 107, 145, 63, 122, 129, 222, 121, 66, 227, 79, 212, 164, 17, 12, 64, 231, 117, 14, 4, 104, 56, 224, 129, 61, 145, 164, 15, 251, 16, 51, 155, 149, 233, 216, 157, 104, 7, 166, 29, 51, 138, 245, 163, 113, 232, 48, 225, 253, 26, 15, 209, 191, 207, 50, 34, 162, 233, 5, 198, 68, 27, 55, 247, 115, 72, 120, 247, 62, 203, 136, 240, 150, 59, 13, 136, 217, 226, 114, 143, 46, 69, 79, 60, 182, 135, 94, 204, 249, 247, 176, 186, 239, 93, 81, 27, 36, 37, 148, 148, 199, 162, 60, 163, 173, 215, 147, 152, 168, 118, 207, 140, 37, 171, 186, 164, 27, 133, 234, 11, 104, 157, 154, 67, 83, 196, 132, 17, 88, 202, 129, 20, 127, 52, 12, 107, 92, 105, 21, 215, 188, 254, 182, 75, 183, 244, 24, 78, 217, 218, 76, 251, 1, 132, 225, 146, 76, 184, 109, 142, 206, 155, 152, 244, 194, 87, 105, 50, 149, 161, 211, 184, 32, 218, 32, 224, 203, 83, 52, 133, 131, 25, 160, 141, 104, 114, 242, 203, 32, 165, 145, 208, 115, 237, 42, 84, 227, 199, 94, 212, 155, 110, 112, 132, 80, 17, 91, 66, 157, 23, 225, 144, 63, 224, 120, 50, 95, 151, 225, 159, 6, 199, 222, 243, 142, 135, 162, 163, 96, 8, 113, 168, 36, 181, 27, 2, 132, 18, 135, 137, 248, 1, 195, 169, 34, 47, 200, 138, 46, 110, 208, 15, 46, 156, 146, 9, 89, 28, 132, 132, 87, 38, 36, 147, 89, 118, 175, 45, 193, 26, 78, 7, 25, 54, 117, 110, 70, 138, 69, 23, 125, 28, 175, 91, 190, 179, 162, 220, 162, 111, 95, 228, 185, 133, 60, 243, 243, 147, 193, 197, 188, 162, 165, 71, 146, 241, 10, 194, 85, 10, 164, 237, 143, 30, 28, 62, 143, 208, 191, 137, 207, 146, 254, 52, 61, 79, 171, 174, 242, 46, 86, 94, 231, 113, 154, 137, 16, 110, 179, 247, 38, 192, 41, 157, 96, 202, 60, 182, 28, 175, 135, 113, 118, 162, 78, 81, 254, 245, 135, 27, 18, 121, 232, 160, 79, 40, 52, 90, 119, 87, 226, 155, 187, 118, 195, 2, 191, 131, 24, 224, 41, 248, 149, 245, 79, 227, 95, 190, 142, 62, 16, 60, 47, 85, 130, 103, 129, 30, 60, 166, 181, 172, 153, 60, 88, 109, 233, 194, 138, 244, 137, 223, 147, 215, 186, 110, 72, 210, 127, 46, 242, 217, 189, 150, 116, 232, 224, 61, 149, 244, 230, 174, 233, 33, 189, 117, 130, 221, 86, 154, 169, 12, 155, 179, 44, 68, 117, 221, 43, 75, 227, 115, 234, 155, 86, 198, 193, 110, 201, 55, 228, 146, 201, 235, 56, 45, 202, 254, 34, 122, 99, 121, 226, 77, 145, 113, 165, 225, 238, 74, 119, 99, 207, 150, 38, 220, 75, 151, 167, 1, 186, 175, 100, 73, 162, 53, 80, 87, 156, 220, 144, 140, 169, 20, 19, 188, 250, 219, 219, 35, 108, 52, 68, 252, 190, 249, 207, 100, 239, 238, 163, 15, 173, 185, 107, 203, 157, 156, 23, 155, 125, 23, 17, 203, 229, 76, 115, 230, 56, 97, 237, 54, 121, 163, 135, 204, 74, 23, 192, 239, 14, 10, 30, 70, 21, 224, 232, 182, 158, 144, 127, 83, 239, 115, 174, 198, 235, 130, 30, 100, 230, 117, 145, 111, 185, 136, 66, 170, 160, 102, 119, 58, 168, 22, 36, 204, 46, 122, 65, 87, 193, 138, 161, 85, 42, 102, 146, 48, 200, 97, 87, 31, 15, 168, 14, 242, 125, 112, 147, 139, 204, 27, 43, 1, 69, 186, 69, 74, 136, 26, 102, 28, 130, 38, 169, 13, 235, 1, 169, 68, 83, 29, 83, 57, 32, 1, 195, 141, 249, 167, 87, 28, 166, 254, 16, 228, 103, 77, 139, 53, 47, 244, 48, 77, 101, 159, 228, 48, 170, 157, 38, 39, 225, 178, 39, 221, 50, 71, 70, 168, 0, 133, 174, 63, 159, 114, 29, 51, 203, 252, 107, 126, 227, 241, 143, 118, 33, 9, 34, 11, 16, 48, 181, 216, 59, 199, 49, 180, 71, 250, 0, 42, 177, 68, 22, 167, 107, 56, 188, 86, 218, 37, 88, 47, 33, 154, 164, 34, 162, 182, 158, 26, 234, 6, 34, 21, 157, 188, 28, 169, 238, 150, 113, 29, 103, 65, 184, 6, 251, 133, 93, 164, 89, 64, 137, 55, 233, 61, 126, 119, 215, 221, 167, 76, 131, 3, 217, 71, 29, 55, 172, 166, 8, 196, 220, 234, 27, 176, 234, 8, 41, 110, 201, 187, 31, 148, 92, 237, 76, 75, 135, 152, 246, 92, 190, 98, 145, 185, 65, 100, 33, 61, 252, 253, 160, 229, 117, 185, 18, 153, 123, 206, 90, 134, 227, 239, 201, 192, 208, 148, 175, 51, 64, 136, 7, 131, 168, 199, 159, 122, 16, 135, 42, 193, 246, 84, 110, 60, 122, 65, 114, 22, 159, 39, 42, 126, 142, 61, 194, 39, 249, 74, 252, 177, 178, 200, 74, 184, 60, 147, 172, 68, 23, 202, 233, 53, 204, 121, 121, 34, 161, 157, 39, 101, 25, 159, 112, 128, 226, 37, 255, 191, 13, 142, 64, 98, 37, 244, 144, 235, 214, 123, 61, 43, 132, 132, 149, 82, 29, 224, 71, 2, 37, 88, 167, 156, 234, 14, 98, 89, 14, 116, 61, 234, 61, 138, 122, 236, 15, 7, 20, 26, 5, 72, 200, 242, 166, 136, 211, 41, 123, 102, 11, 55, 246, 39, 161, 193, 200, 141, 215, 0, 19, 112, 34, 16, 124, 192, 102, 220, 53, 64, 224, 255, 101, 61, 43, 94, 210, 27, 195, 44, 71, 124, 52, 47, 103, 9, 163, 218, 132, 198, 3, 219, 57, 113, 112, 140, 63, 132, 233, 176, 87, 186, 2, 254, 230, 141, 45, 116, 207, 71, 130, 196, 233, 250, 129, 96, 28, 26, 142, 195, 173, 30, 243, 163, 71, 122, 213, 147, 239, 29, 27, 210, 194, 145, 137, 58, 216, 254, 147, 0, 174, 225, 52, 174, 160, 143, 116, 120, 160, 11, 125, 191, 60, 156, 103, 224, 133, 181, 1, 91, 194, 243, 240, 123, 107, 15, 193, 172, 49, 59, 68, 147, 71, 158, 219, 157, 249, 48, 181, 236, 173, 46, 6, 89, 35, 80, 9, 220, 61, 113, 73, 73, 162, 172, 3, 151, 153, 172, 200, 245, 251, 194, 77, 40, 168, 107, 113, 118, 18, 196, 99, 45, 124, 102, 134, 209, 199, 4, 110, 5, 199, 216, 71, 18, 238, 11, 203, 224, 208, 204, 229, 169, 32, 62, 130, 159, 74, 249, 240, 141, 196, 15, 144, 166, 189, 17, 129, 90, 182, 43, 236, 67, 36, 159, 147, 241, 96, 47, 180, 152, 49, 92, 208, 72, 1, 210, 253, 19, 72, 150, 192, 49, 53, 185, 220, 153, 253, 6, 167, 237, 101, 13, 229, 57, 229, 71, 135, 85, 90, 100, 169, 127, 235, 197, 207, 192, 198, 234, 218, 1, 37, 37, 179, 53, 44, 44, 201, 43, 245, 167, 121, 80, 45, 124, 152, 199, 144, 69, 154, 196, 45, 143, 65, 121, 252, 143, 193, 243, 62, 234, 204, 13, 239, 148, 235, 118, 122, 28, 109, 203, 97, 245, 39, 42, 163, 208, 55, 241, 9, 4, 235, 147, 250, 105, 242, 152, 213, 102, 99, 8, 3, 14, 21, 81, 63, 137, 240, 207, 85, 222, 5, 188, 118, 240, 31, 16, 242, 56, 189, 100, 9, 203, 106, 52, 233, 174, 125, 7, 129, 68, 246, 239, 180, 228, 107, 153, 65, 116, 46, 78, 68, 24, 237, 137, 95, 200, 68, 222, 162, 172, 145, 160, 115, 117, 250, 130, 129, 149, 103, 69, 56, 208, 70, 247, 14, 217, 30, 182, 90, 82, 58, 3, 106, 188, 108, 221, 64, 234, 194, 54, 96, 246, 201, 0, 208, 61, 21, 1, 80, 28, 7, 66, 109, 34, 40, 52, 101, 54, 63, 69, 88, 228, 231, 56, 177, 108, 223, 109, 196, 140, 178, 7, 3, 196, 37, 214, 17, 18, 43, 35, 68, 123, 2, 59, 253, 87, 138, 216, 58, 43, 231, 117, 194, 155, 131, 45, 30, 238, 211, 242, 16, 224, 63, 200, 80, 201, 215, 123, 50, 112, 30, 86, 71, 240, 23, 86, 72, 112, 144, 150, 45, 84, 107, 79, 64, 41, 248, 250, 24, 20, 198, 88, 143, 152, 104, 250, 221, 59, 126, 62, 247, 221, 187, 71, 188, 41, 33, 65, 84, 158, 154, 143, 123, 57, 91, 62, 162, 145, 144, 156, 200, 108, 33, 124, 13, 207, 137, 95, 36, 64, 23, 177, 60, 194, 201, 248, 194, 203, 92, 17, 39, 131, 106, 129, 145, 97, 104, 195, 19, 20, 244, 74, 177, 218, 173, 117, 110, 183, 164, 51, 29, 253, 115, 116, 70, 170, 57, 169, 41, 166, 190, 234, 149, 123, 138, 234, 156, 158, 159, 66, 12, 198, 26, 17, 83, 51, 190, 102, 177, 27, 255, 125, 236, 204, 131, 64, 27, 211, 72, 152, 64, 26, 142, 235, 198, 45, 148, 95, 219, 153, 157, 120, 242, 219, 3, 239, 201, 211, 0, 155, 28, 72, 133, 162, 189, 11, 205, 12, 127, 26, 151, 251, 89, 89, 197, 217, 88, 101, 146, 166, 83, 13, 202, 55, 153, 150, 175, 213, 33, 245, 131, 99, 193, 228, 102, 84, 245, 167, 126, 207, 168, 91, 42, 39, 43, 104, 146, 65, 205, 90, 6, 3, 230, 1, 197, 73, 23, 194, 199, 37, 182, 132, 193, 160, 125, 158, 195, 166, 90, 58, 209, 138, 176, 105, 99, 86, 66, 32, 59, 178, 54, 94, 109, 171, 15, 109, 129, 95, 161, 59, 186, 178, 48, 25, 83, 31, 210, 214, 93, 51, 93, 14, 17, 121, 105, 176, 192, 41, 34, 31, 156, 54, 55, 206, 132, 186, 227, 57, 57, 132, 184, 214, 127, 112, 232, 0, 223, 62, 67, 24, 54, 88, 126, 104, 31, 46, 170, 59, 232, 137, 100, 175, 97, 64, 228, 98, 238, 254, 12, 73, 240, 128, 93, 251, 65, 209, 233, 94, 219, 157, 102, 111, 121, 238, 149, 28, 20, 142, 92, 15, 149, 124, 143, 78, 179, 138, 217, 197, 82, 159, 157, 14, 192, 123, 52, 44, 58, 244, 186, 216, 160, 91, 145, 41, 11, 12, 55, 133, 208, 102, 160, 93, 228, 23, 58, 175, 167, 71, 216, 135, 96, 248, 228, 106, 32, 248, 151, 34, 117, 45, 65, 250, 252, 52, 189, 198, 185, 212, 118, 84, 245, 156, 62, 109, 160, 107, 56, 86, 139, 35, 227, 167, 237, 141, 89, 47, 55, 19, 255, 213, 108, 172, 232, 252, 23, 204, 12, 104, 19, 20, 134, 168, 103, 7, 76, 1, 205, 241, 44, 129, 226, 194, 106, 236, 0, 129, 64, 125, 92, 87, 43, 65, 194, 60, 226, 46, 151, 191, 93, 0, 115, 195, 22, 165, 96, 175, 61, 70, 240, 105, 194, 185, 168, 33, 254, 203, 91, 67, 239, 99, 250, 162, 145, 220, 26, 102, 249, 224, 139, 72, 210, 25, 72, 240, 250, 128, 95, 93, 201, 173, 58, 29, 68, 81, 191, 207, 8, 91, 76, 196, 101, 67, 19, 115, 32, 191, 159, 142, 0, 235, 18, 251, 53, 80, 24, 73, 92, 69, 4, 151, 0, 37, 222, 40, 140, 215, 101, 182, 213, 143, 94, 179, 93, 156, 108, 52, 169, 150, 110, 161, 192, 46, 51, 121, 212, 205, 137, 173, 255, 144, 161, 205, 255, 6, 173, 219, 38, 188, 93, 241, 255, 34, 194, 72, 132, 203, 100, 202, 68, 34, 40, 196, 40, 99, 88, 147, 28, 243, 164, 174, 18, 154, 233, 163, 115, 6, 226, 99, 123, 17, 15, 159, 99, 252, 28, 194, 45, 194, 209, 248, 25, 169, 23, 128, 83, 132, 110, 119, 102, 76, 147, 141, 173, 147, 83, 171, 125, 82, 154, 231, 37, 109, 123, 128, 234, 230, 132, 221, 119, 190, 208, 22, 21, 140, 247, 173, 147, 246, 54, 29, 240, 28, 161, 186, 19, 178, 78, 15, 220, 145, 172, 134, 181, 245, 205, 226, 80, 197, 19, 45, 67, 61, 56, 162, 11, 232, 109, 108, 4, 16, 140, 162, 247, 69, 18, 147, 140, 129, 30, 145, 14, 31, 88, 252, 34, 210, 139, 138, 180, 239, 32, 225, 157, 18, 233, 54, 29, 184, 171, 34, 189, 44, 97, 36, 170, 97, 99, 3, 210, 255, 110, 53, 204, 178, 126, 179, 185, 246, 68, 210, 109, 48, 154, 111, 251, 42, 55, 112, 52, 232, 142, 172, 116, 187, 97, 127, 183, 100, 237, 46, 172, 118, 245, 41, 167, 125, 35, 112, 129, 109, 38, 209, 222, 128, 147, 57, 84, 251, 21, 97, 115, 252, 69, 243, 58, 34, 66, 253, 241, 42, 67, 9, 12, 103, 16, 106, 112, 205, 86, 63, 246, 33, 172, 14, 150, 126, 195, 233, 168, 219, 160, 150, 150, 117, 202, 170, 89, 49, 89, 231, 176, 16, 87, 171, 238, 55, 28, 203, 50, 50, 176, 33, 72, 222, 229, 0, 83, 100, 139, 208, 178, 103, 49, 5, 254, 49, 158, 192, 40, 86, 228, 8, 162, 65, 71, 221, 129, 74, 131, 40, 104, 85, 255, 94, 133, 56, 38, 133, 133, 19, 31, 141, 178, 36, 117, 125, 221, 99, 150, 123, 176, 246, 159, 40, 11, 159, 168, 114, 215, 183, 129, 99, 84, 159, 203, 20, 174, 103, 77, 217, 169, 163, 205, 205, 205, 110, 131, 255, 214, 191, 237, 30, 60, 53, 117, 27, 164, 125, 241, 211, 28, 237, 100, 252, 134, 166, 169, 182, 199, 64, 108, 94, 247, 42, 101, 126, 116, 235, 139, 127, 245, 166, 199, 172, 69, 178, 254, 186, 225, 91, 224, 152, 153, 51, 210, 226, 108, 217, 151, 161, 254, 20, 67, 189, 186, 204, 177, 110, 62, 5, 231, 217, 55, 201, 38, 95, 134, 250, 206, 73, 117, 221, 218, 158, 173, 231, 208, 149, 152, 251, 89, 42, 113, 99, 196, 52, 227, 203, 86, 19, 104, 104, 185, 157, 57, 153, 240, 126, 179, 47, 155, 101, 226, 77, 81, 207, 139, 212, 13, 131, 28, 83, 81, 206, 177, 22, 129, 46, 140, 100, 231, 225, 211, 140, 128, 162, 255, 180, 134, 170, 91, 115, 40, 225, 187, 65, 212, 99, 125, 239, 145, 144, 126, 31, 209, 57, 122, 124, 81, 59, 208, 56, 29, 109, 189, 69, 63, 134, 111, 221, 121, 240, 37, 143, 244, 225, 70, 10, 0, 125, 31, 143, 207, 96, 46, 53, 183, 184, 88, 55, 59, 66, 143, 95, 6, 197, 231, 165, 136, 192, 120, 105, 34, 48, 24, 124, 253, 173, 115, 240, 5, 171, 220, 34, 226, 2, 225, 141, 190, 162, 27, 4, 123, 166, 147, 86, 32, 134, 205, 10, 6, 84, 23, 177, 196, 181, 176, 92, 38, 144, 7, 38, 41, 237, 88, 72, 225, 125, 157, 189, 147, 159, 7, 209, 75, 115, 130, 51, 158, 9, 21, 198, 202, 29, 114, 7, 7, 100, 86, 98, 0, 78, 166, 249, 251, 24, 232, 225, 249, 12, 149, 47, 78, 25, 58, 81, 159, 175, 162, 209, 106, 30, 130, 158, 196, 2, 136, 47, 105, 227, 217, 51, 214, 230, 21, 163, 133, 82, 148, 125, 141, 132, 191, 105, 180, 237, 69, 51, 77, 88, 126, 112, 209, 220, 89, 114, 37, 68, 205, 3, 73, 94, 184, 77, 115, 177, 4, 138, 14, 101, 209, 32, 164, 72, 176, 81, 109, 169, 33, 45, 229, 19, 25, 15, 199, 107, 53, 197, 250, 162, 70, 6, 4, 134, 59, 202, 106, 6, 129, 181, 37, 130, 235, 253, 159, 193, 219, 134, 101, 14, 123, 26, 22, 140, 109, 66, 80, 22, 9, 108, 66, 213, 219, 68, 53, 89, 56, 123, 2, 154, 22, 230, 93, 25, 17, 248, 79, 122, 188, 170, 230, 136, 105, 59, 206, 62, 168, 229, 105, 78, 93, 204, 210, 42, 53, 199, 175, 252, 12, 146, 9, 201, 218, 207, 170, 7, 219, 16, 62, 237, 15, 28, 197, 110, 86, 35, 43, 6, 16, 221, 61, 210, 238, 216, 6, 25, 145, 171, 127, 7, 212, 176, 61, 168, 33, 5, 165, 170, 233, 171, 90, 117, 253, 163, 32, 46, 33, 2, 50, 216, 111, 177, 232, 47, 83, 76, 5, 35, 108, 42, 5, 129, 9, 43, 63, 201, 145, 55, 94, 214, 21, 228, 19, 134, 18, 244, 110, 120, 198, 26, 29, 111, 134, 55, 53, 218, 220, 11, 15, 126, 230, 34, 159, 207, 126, 210, 217, 86, 208, 116, 160, 79, 34, 185, 177, 172, 188, 112, 104, 150, 145, 99, 244, 221, 67, 37, 127, 246, 148, 35, 106, 171, 175, 169, 72, 41, 227, 49, 71, 123, 90, 140, 150, 63, 243, 13, 195, 51, 223, 94, 20, 188, 140, 93, 219, 50, 198, 94, 203, 146, 139, 104, 207, 236, 71, 156, 181, 55, 83, 45, 42, 238, 24, 137, 20, 83, 81, 147, 210, 119, 173, 211, 51, 36, 213, 242, 38, 217, 224, 4, 206, 239, 158, 229, 246, 22, 107, 13, 205, 148, 166, 158, 239, 102, 236, 200, 15, 172, 196, 192, 6, 209, 145, 200, 242, 183, 230, 21, 98, 79, 166, 31, 213, 166, 190, 255, 182, 148, 55, 10, 90, 23, 19, 241, 255, 159, 33, 71, 181, 73, 237, 16, 207, 136, 228, 188, 154, 159, 191, 79, 138, 119, 105, 201, 22, 83, 140, 204, 253, 108, 126, 110, 248, 89, 154, 196, 236, 157, 56, 248, 147, 241, 194, 246, 129, 77, 159, 140, 66, 149, 13, 254, 127, 174, 27, 253, 77, 190, 138, 95, 45, 179, 189, 85, 46, 25, 231, 254, 182, 84, 74, 96, 1, 210, 215, 36, 123, 221, 186, 85, 180, 219, 238, 110, 180, 203, 38, 118, 8, 118, 0, 125, 195, 212, 9, 19, 101, 196, 38, 164, 207, 131, 44, 207, 9, 98, 99, 186, 138, 167, 182, 154, 1, 216, 232, 247, 183, 163, 111, 191, 141, 190, 123, 176, 6, 119, 57, 174, 193, 174, 174, 130, 241, 245, 215, 250, 145, 189, 37, 229, 232, 81, 54, 110, 66, 24, 198, 208, 125, 151, 109, 16, 198, 121, 147, 139, 159, 170, 224, 154, 31, 148, 97, 235, 32, 52, 89, 164, 30, 160, 48, 208, 152, 182, 59, 184, 200, 148, 56, 254, 156, 148, 227, 34, 157, 49, 133, 87, 226, 83, 87, 34, 165, 140, 190, 16, 244, 192, 168, 188, 228, 74, 93, 171, 123, 152, 28, 67, 120, 217, 187, 252, 34, 251, 149, 189, 237, 171, 3, 101, 220, 232, 49, 96, 193, 84, 250, 72, 148, 164, 206, 34, 54, 144, 151, 139, 2, 80, 169, 4, 118, 228, 87, 121, 39, 111, 74, 47, 138, 55, 250, 18, 170, 136, 52, 163, 200, 88, 135, 86, 217, 183, 250, 126, 138, 99, 133, 84, 15, 74, 166, 228, 245, 57, 75, 154, 201, 104, 173, 78, 151, 161, 110, 74, 109, 8, 111, 172, 253, 10, 57, 86, 168, 172, 127, 84, 208, 57, 51, 115, 247, 157, 172, 140, 233, 125, 66, 139, 234, 65, 146, 215, 3, 58, 160, 247, 203, 103, 151, 108, 94, 41, 83, 121, 166, 146, 0, 38, 39, 40, 129, 203, 113, 75, 169, 93, 211, 3, 253, 93, 149, 191, 200, 217, 60, 145, 56, 105, 137, 240, 18, 161, 230, 232, 202, 193, 102, 165, 179, 223, 28, 120, 91, 224, 211, 2, 235, 41, 65, 220, 190, 172, 214, 173, 118, 26, 151, 136, 1, 250, 255, 36, 213, 197, 199, 254, 63, 197, 114, 138, 214, 255, 74, 0, 224, 68, 102, 227, 2, 179, 119, 231, 193, 16, 217, 15, 252, 102, 155, 3, 94, 90, 111, 250, 188, 45, 49, 219, 112, 241, 145, 192, 134, 23, 35, 40, 57, 19, 181, 164, 65, 41, 209, 83, 137, 133, 68, 205, 70, 180, 70, 10, 173, 50, 136, 150, 40, 45, 100, 66, 162, 5, 121, 147, 6, 81, 201, 127, 16, 85, 194, 10, 70, 190, 235, 133, 109, 211, 78, 86, 13, 152, 117, 15, 30, 8, 132, 42, 152, 43, 240, 196, 32, 52, 130, 158, 89, 32, 123, 19, 62, 227, 11, 92, 237, 124, 147, 115, 142, 247, 91, 201, 141, 232, 30, 179, 78, 223, 228, 138, 125, 152, 134, 19, 41, 172, 152, 169, 170, 83, 89, 137, 222, 107, 14, 227, 72, 139, 238, 10, 123, 23, 52, 2, 127, 216, 186, 220, 222, 218, 138, 254, 100, 127, 183, 134, 226, 207, 182, 60, 78, 169, 207, 85, 139, 142, 137, 103, 88, 64, 174, 112, 19, 216, 225, 106, 209, 228, 47, 152, 224, 39, 139, 19, 252, 164, 153, 224, 39, 247, 139, 224, 39, 136, 204, 134, 248, 53, 4, 127, 145, 231, 103, 243, 25, 226, 240, 86, 132, 254, 172, 84, 154, 228, 216, 177, 38, 230, 196, 208, 108, 168, 54, 189, 37, 21, 173, 121, 145, 207, 102, 122, 2, 84, 111, 96, 189, 252, 181, 32, 49, 78, 35, 129, 230, 185, 163, 109, 157, 245, 91, 101, 254, 245, 223, 39, 242, 17, 13, 161, 101, 86, 156, 56, 51, 34, 123, 43, 216, 80, 57, 17, 101, 189, 85, 229, 79, 10, 14, 223, 47, 95, 134, 175, 211, 240, 13, 111, 203, 240, 213, 27, 113, 51, 67, 70, 51, 172, 237, 41, 70, 1, 24, 95, 27, 162, 154, 175, 219, 58, 65, 115, 85, 21, 229, 110, 54, 145, 126, 56, 73, 90, 5, 134, 124, 5, 114, 15, 183, 236, 53, 136, 162, 189, 244, 35, 74, 202, 43, 87, 201, 69, 145, 86, 160, 164, 31, 69, 171, 171, 46, 180, 173, 135, 218, 167, 146, 48, 174, 19, 123, 55, 129, 162, 67, 93, 116, 156, 103, 199, 233, 201, 188, 174, 240, 246, 154, 117, 234, 24, 103, 40, 250, 67, 233, 80, 11, 219, 82, 191, 217, 150, 111, 90, 35, 213, 26, 165, 143, 30, 246, 56, 40, 36, 187, 89, 19, 131, 61, 184, 3, 62, 88, 233, 251, 121, 5, 174, 50, 144, 224, 113, 101, 150, 164, 203, 185, 144, 27, 53, 135, 244, 6, 126, 27, 80, 31, 78, 17, 87, 139, 184, 80, 2, 202, 132, 72, 196, 35, 63, 127, 235, 222, 26, 154, 52, 121, 247, 126, 240, 122, 247, 182, 49, 89, 101, 34, 123, 71, 64, 148, 139, 76, 166, 221, 80, 23, 69, 232, 245, 183, 246, 154, 169, 31, 98, 134, 70, 174, 86, 113, 46, 202, 122, 9, 61, 233, 25, 38, 235, 177, 149, 34, 70, 70, 69, 215, 113, 12, 254, 124, 130, 62, 109, 154, 74, 140, 122, 220, 62, 120, 4, 127, 126, 192, 254, 198, 30, 230, 202, 14, 176, 113, 53, 1, 125, 155, 67, 31, 110, 17, 232, 34, 193, 106, 3, 88, 174, 49, 212, 218, 86, 16, 13, 181, 132, 54, 160, 17, 85, 85, 176, 137, 110, 73, 41, 145, 14, 141, 249, 250, 165, 192, 136, 62, 61, 228, 125, 218, 166, 125, 98, 195, 214, 220, 200, 182, 106, 68, 15, 50, 106, 228, 36, 65, 251, 18, 30, 43, 21, 228, 65, 214, 91, 245, 187, 43, 45, 238, 253, 254, 7, 97, 191, 246, 172, 5, 57, 199, 183, 236, 132, 111, 233, 193, 183, 12, 225, 91, 26, 124, 203, 206, 248, 150, 126, 124, 5, 82, 214, 180, 77, 63, 12, 241, 124, 110, 131, 222, 38, 110, 85, 169, 206, 91, 105, 205, 82, 173, 48, 212, 210, 78, 43, 80, 60, 254, 138, 9, 49, 106, 88, 207, 170, 119, 218, 220, 208, 136, 247, 145, 141, 46, 254, 60, 20, 123, 132, 166, 168, 167, 132, 252, 136, 13, 24, 143, 127, 198, 237, 17, 189, 239, 194, 19, 165, 165, 115, 131, 45, 66, 40, 233, 154, 231, 11, 11, 155, 74, 29, 65, 33, 135, 63, 122, 212, 48, 3, 11, 195, 86, 51, 32, 154, 249, 174, 51, 141, 242, 45, 124, 203, 164, 81, 234, 25, 117, 152, 167, 168, 114, 208, 133, 125, 202, 103, 98, 71, 159, 135, 158, 216, 174, 71, 203, 101, 56, 131, 13, 218, 80, 216, 74, 32, 100, 5, 234, 52, 132, 171, 136, 146, 155, 199, 6, 25, 26, 189, 18, 100, 41, 181, 237, 56, 19, 27, 131, 246, 32, 251, 251, 252, 119, 225, 115, 58, 24, 68, 175, 27, 60, 173, 212, 73, 245, 90, 37, 235, 114, 205, 227, 47, 251, 121, 214, 126, 158, 32, 39, 242, 128, 141, 121, 172, 67, 95, 46, 48, 110, 209, 190, 29, 93, 95, 158, 133, 237, 195, 179, 176, 93, 120, 214, 100, 15, 158, 9, 59, 208, 44, 11, 173, 221, 66, 72, 82, 199, 62, 190, 53, 19, 89, 211, 150, 96, 72, 36, 62, 211, 94, 160, 45, 105, 12, 244, 121, 90, 38, 239, 228, 121, 166, 126, 158, 61, 23, 79, 70, 226, 102, 162, 72, 48, 128, 69, 126, 175, 75, 155, 47, 91, 129, 100, 249, 178, 161, 64, 222, 124, 216, 94, 150, 91, 244, 120, 111, 89, 54, 49, 8, 109, 61, 43, 248, 130, 183, 117, 54, 170, 234, 52, 81, 221, 25, 136, 100, 188, 242, 151, 207, 183, 103, 122, 174, 58, 130, 170, 195, 208, 103, 168, 114, 68, 192, 217, 95, 201, 64, 246, 17, 152, 53, 176, 228, 21, 219, 127, 192, 243, 191, 117, 168, 207, 39, 38, 185, 233, 139, 125, 49, 171, 61, 80, 146, 30, 135, 73, 153, 79, 63, 36, 253, 61, 146, 131, 21, 77, 63, 254, 16, 79, 94, 119, 19, 208, 30, 68, 154, 242, 26, 109, 143, 15, 132, 94, 36, 173, 152, 80, 252, 233, 99, 66, 145, 254, 51, 69, 83, 226, 67, 114, 119, 145, 0, 34, 3, 179, 232, 137, 151, 0, 13, 121, 200, 2, 109, 5, 25, 151, 78, 106, 34, 46, 237, 69, 90, 114, 243, 128, 251, 105, 94, 164, 103, 201, 243, 188, 96, 90, 191, 52, 123, 87, 90, 32, 196, 246, 225, 155, 92, 30, 188, 98, 5, 164, 254, 208, 171, 93, 40, 241, 52, 234, 127, 183, 181, 21, 125, 27, 49, 11, 57, 124, 66, 124, 56, 252, 43, 17, 221, 41, 67, 67, 78, 37, 194, 99, 196, 64, 173, 145, 73, 35, 229, 211, 8, 251, 163, 54, 43, 205, 70, 165, 71, 215, 1, 60, 54, 125, 242, 185, 252, 40, 117, 76, 6, 248, 76, 136, 161, 28, 105, 252, 158, 136, 126, 21, 23, 60, 136, 67, 6, 255, 241, 35, 98, 204, 28, 211, 39, 207, 88, 109, 226, 208, 208, 106, 64, 84, 236, 18, 36, 170, 106, 88, 19, 182, 114, 26, 144, 38, 27, 172, 136, 191, 232, 168, 188, 255, 37, 245, 254, 183, 167, 63, 200, 110, 110, 242, 110, 234, 215, 111, 242, 81, 62, 47, 198, 137, 213, 28, 181, 36, 218, 94, 177, 209, 134, 118, 114, 75, 108, 191, 220, 207, 166, 41, 63, 240, 249, 2, 106, 105, 184, 100, 52, 240, 62, 152, 250, 48, 86, 250, 91, 15, 21, 105, 32, 162, 163, 131, 148, 125, 195, 0, 61, 108, 30, 32, 17, 219, 125, 241, 134, 191, 86, 140, 239, 30, 74, 124, 26, 109, 171, 70, 116, 105, 235, 204, 161, 90, 37, 122, 208, 212, 85, 194, 38, 181, 131, 235, 246, 32, 66, 213, 208, 162, 22, 207, 39, 24, 151, 74, 119, 225, 211, 49, 158, 30, 184, 110, 204, 199, 29, 92, 76, 43, 201, 28, 233, 251, 229, 107, 102, 241, 37, 19, 161, 42, 44, 185, 100, 6, 27, 121, 35, 149, 20, 143, 36, 65, 154, 73, 54, 255, 35, 45, 44, 223, 62, 106, 210, 142, 54, 63, 71, 81, 121, 145, 242, 124, 253, 128, 166, 210, 139, 250, 100, 26, 163, 255, 214, 35, 107, 242, 80, 148, 176, 181, 186, 226, 104, 51, 152, 59, 6, 202, 112, 97, 40, 92, 68, 74, 182, 142, 194, 224, 182, 175, 15, 78, 62, 12, 9, 220, 7, 75, 132, 43, 31, 182, 73, 3, 15, 111, 162, 1, 249, 240, 128, 180, 244, 221, 141, 182, 36, 31, 30, 146, 38, 191, 255, 52, 77, 202, 135, 239, 72, 219, 127, 249, 196, 109, 203, 135, 239, 9, 18, 63, 124, 46, 36, 228, 195, 95, 8, 54, 127, 253, 236, 216, 200, 135, 31, 8, 90, 195, 197, 53, 202, 210, 241, 146, 15, 127, 165, 8, 46, 65, 89, 45, 29, 65, 5, 144, 234, 193, 225, 50, 21, 225, 242, 81, 85, 79, 90, 201, 178, 245, 75, 204, 22, 36, 22, 210, 218, 130, 104, 194, 214, 61, 239, 165, 12, 171, 73, 87, 199, 166, 108, 250, 58, 174, 77, 149, 79, 222, 131, 206, 73, 104, 71, 90, 117, 204, 217, 148, 182, 174, 61, 162, 70, 84, 139, 93, 70, 219, 220, 35, 253, 11, 110, 144, 251, 208, 241, 118, 232, 52, 46, 151, 131, 187, 199, 246, 18, 21, 60, 70, 23, 107, 212, 53, 183, 36, 120, 175, 145, 143, 119, 64, 211, 76, 27, 138, 254, 1, 242, 245, 39, 186, 217, 14, 193, 54, 83, 187, 14, 53, 26, 231, 178, 199, 34, 128, 130, 163, 63, 154, 243, 187, 46, 221, 78, 13, 44, 235, 221, 166, 154, 168, 114, 132, 106, 208, 236, 15, 95, 29, 38, 39, 207, 46, 103, 207, 167, 241, 73, 73, 34, 29, 193, 186, 61, 12, 122, 200, 14, 235, 216, 247, 176, 238, 180, 241, 33, 177, 159, 181, 119, 164, 215, 83, 141, 28, 110, 242, 75, 18, 38, 233, 216, 108, 200, 201, 98, 235, 172, 220, 164, 135, 201, 120, 184, 41, 78, 108, 121, 10, 158, 88, 5, 211, 147, 44, 47, 146, 189, 184, 76, 60, 133, 83, 171, 240, 57, 251, 0, 87, 58, 250, 202, 158, 91, 101, 39, 121, 181, 59, 245, 97, 80, 90, 5, 231, 89, 58, 206, 39, 62, 144, 115, 127, 73, 182, 28, 245, 145, 224, 131, 85, 186, 172, 210, 241, 217, 149, 167, 224, 85, 207, 226, 6, 147, 136, 202, 13, 254, 116, 24, 65, 198, 164, 30, 195, 27, 26, 143, 42, 138, 122, 238, 33, 189, 121, 134, 153, 65, 58, 166, 66, 248, 124, 100, 243, 140, 0, 92, 216, 180, 115, 159, 99, 76, 75, 240, 87, 120, 99, 165, 247, 223, 112, 179, 167, 130, 182, 46, 127, 243, 98, 117, 228, 49, 215, 116, 154, 251, 82, 49, 105, 118, 39, 31, 224, 110, 15, 241, 101, 31, 130, 211, 251, 35, 121, 167, 53, 114, 92, 105, 239, 85, 57, 159, 205, 132, 219, 59, 46, 248, 94, 128, 88, 123, 203, 248, 247, 145, 90, 37, 126, 253, 181, 180, 10, 44, 55, 135, 104, 230, 29, 176, 202, 235, 60, 205, 170, 93, 166, 27, 76, 115, 79, 163, 173, 203, 99, 246, 111, 133, 94, 211, 33, 160, 175, 71, 67, 246, 31, 105, 223, 210, 165, 208, 221, 151, 224, 168, 235, 139, 13, 9, 51, 202, 197, 101, 112, 152, 139, 203, 218, 107, 179, 46, 235, 6, 154, 213, 197, 35, 61, 194, 35, 40, 81, 80, 13, 178, 246, 102, 85, 122, 158, 254, 14, 110, 26, 129, 170, 139, 0, 102, 133, 134, 35, 146, 197, 229, 32, 82, 158, 15, 115, 122, 150, 213, 91, 93, 237, 11, 16, 50, 12, 201, 56, 71, 168, 222, 145, 173, 177, 14, 253, 67, 136, 174, 93, 119, 184, 37, 110, 58, 196, 239, 126, 216, 178, 157, 183, 162, 43, 191, 200, 67, 168, 140, 246, 172, 155, 28, 185, 209, 0, 3, 247, 237, 228, 139, 170, 114, 43, 225, 217, 101, 50, 22, 245, 236, 249, 0, 141, 43, 235, 249, 197, 235, 152, 205, 61, 170, 160, 127, 248, 173, 98, 154, 11, 28, 41, 43, 46, 145, 152, 233, 204, 26, 62, 134, 77, 179, 241, 116, 62, 225, 102, 22, 84, 0, 69, 211, 179, 247, 145, 5, 6, 158, 142, 184, 132, 110, 223, 204, 188, 199, 71, 161, 125, 133, 15, 98, 51, 135, 117, 109, 26, 151, 213, 190, 58, 182, 162, 228, 119, 23, 206, 164, 234, 107, 156, 50, 245, 41, 112, 194, 93, 79, 118, 222, 190, 169, 148, 146, 162, 140, 117, 64, 218, 108, 175, 139, 83, 87, 76, 124, 184, 20, 61, 138, 118, 49, 47, 136, 115, 138, 48, 104, 85, 65, 134, 134, 67, 53, 126, 22, 143, 115, 122, 151, 25, 228, 3, 93, 25, 97, 100, 224, 145, 203, 147, 165, 139, 28, 81, 69, 59, 225, 49, 181, 12, 135, 83, 18, 162, 17, 148, 5, 192, 237, 229, 87, 159, 6, 152, 46, 250, 8, 181, 188, 174, 243, 144, 241, 255, 103, 235, 235, 158, 149, 68, 59, 185, 210, 204, 237, 140, 118, 71, 14, 144, 91, 19, 140, 26, 160, 198, 148, 34, 175, 225, 141, 89, 94, 166, 50, 39, 163, 64, 118, 148, 196, 197, 248, 148, 153, 99, 18, 77, 155, 162, 48, 52, 166, 210, 19, 72, 45, 215, 145, 89, 112, 127, 104, 155, 47, 216, 23, 158, 153, 182, 63, 66, 74, 17, 49, 214, 104, 254, 94, 104, 100, 24, 30, 133, 5, 194, 49, 218, 208, 111, 151, 201, 113, 55, 205, 64, 114, 195, 72, 127, 120, 170, 198, 208, 179, 67, 184, 171, 170, 124, 108, 197, 123, 135, 201, 108, 26, 179, 5, 65, 41, 205, 135, 66, 252, 70, 17, 83, 159, 127, 102, 13, 51, 173, 208, 185, 162, 67, 241, 84, 246, 133, 149, 33, 233, 24, 81, 135, 116, 157, 180, 40, 171, 159, 115, 86, 164, 80, 227, 38, 50, 32, 242, 190, 57, 16, 205, 20, 96, 96, 81, 53, 102, 181, 161, 116, 166, 121, 173, 76, 166, 167, 56, 255, 128, 7, 13, 102, 10, 60, 183, 222, 250, 192, 227, 0, 188, 91, 104, 116, 192, 187, 32, 21, 53, 63, 203, 33, 125, 26, 125, 183, 69, 3, 254, 77, 48, 200, 79, 113, 41, 83, 84, 60, 147, 191, 158, 231, 76, 13, 156, 191, 159, 196, 62, 178, 24, 224, 154, 63, 21, 148, 53, 218, 128, 215, 180, 145, 136, 50, 114, 170, 214, 250, 164, 10, 168, 219, 129, 245, 102, 100, 191, 144, 221, 178, 95, 99, 108, 237, 111, 98, 86, 183, 94, 42, 196, 201, 107, 210, 207, 143, 43, 238, 83, 109, 175, 192, 182, 208, 122, 91, 162, 73, 17, 139, 140, 165, 132, 225, 242, 241, 180, 153, 117, 213, 82, 238, 13, 141, 115, 221, 140, 233, 73, 105, 73, 8, 230, 161, 97, 136, 126, 14, 237, 108, 60, 245, 39, 167, 87, 245, 232, 166, 144, 92, 184, 3, 181, 62, 106, 105, 168, 225, 124, 210, 36, 63, 157, 218, 97, 116, 220, 134, 154, 134, 164, 174, 57, 107, 60, 240, 104, 32, 194, 59, 35, 225, 31, 135, 0, 209, 195, 11, 2, 27, 153, 102, 106, 251, 87, 12, 18, 132, 94, 12, 172, 224, 190, 72, 180, 73, 31, 92, 252, 157, 225, 146, 175, 221, 46, 249, 214, 34, 30, 4, 68, 243, 188, 61, 212, 180, 221, 176, 183, 89, 167, 209, 182, 235, 26, 162, 168, 59, 173, 111, 204, 60, 138, 215, 46, 250, 20, 132, 171, 222, 63, 245, 34, 199, 111, 228, 82, 79, 93, 41, 82, 160, 188, 131, 29, 102, 147, 5, 69, 230, 200, 41, 111, 114, 253, 227, 36, 241, 242, 88, 148, 18, 199, 129, 70, 104, 125, 221, 10, 147, 226, 118, 135, 61, 139, 122, 243, 131, 181, 89, 70, 221, 189, 229, 145, 142, 91, 80, 153, 144, 147, 201, 33, 117, 193, 170, 52, 129, 194, 129, 253, 218, 44, 75, 104, 184, 44, 138, 124, 82, 196, 38, 225, 79, 122, 172, 229, 152, 28, 165, 40, 75, 67, 182, 23, 207, 152, 110, 73, 84, 30, 9, 158, 201, 227, 60, 190, 236, 27, 26, 241, 90, 58, 100, 97, 35, 26, 170, 11, 6, 209, 232, 240, 220, 239, 193, 193, 209, 197, 4, 72, 158, 125, 138, 87, 66, 118, 173, 179, 246, 34, 216, 72, 114, 154, 119, 105, 198, 48, 84, 105, 77, 36, 138, 194, 217, 166, 117, 169, 142, 139, 222, 90, 65, 138, 89, 112, 63, 215, 62, 224, 108, 51, 220, 227, 26, 213, 76, 114, 91, 76, 55, 26, 148, 150, 38, 102, 186, 137, 60, 253, 151, 135, 230, 43, 154, 118, 208, 189, 6, 240, 79, 210, 194, 59, 23, 233, 5, 157, 126, 163, 7, 172, 113, 126, 242, 235, 248, 128, 158, 71, 20, 178, 34, 133, 77, 198, 202, 8, 34, 126, 217, 159, 199, 79, 12, 22, 59, 176, 208, 194, 6, 17, 207, 27, 26, 207, 94, 105, 126, 59, 202, 244, 249, 85, 149, 250, 147, 125, 13, 28, 194, 129, 127, 154, 141, 160, 32, 178, 254, 148, 13, 163, 254, 114, 156, 226, 243, 100, 130, 88, 88, 114, 194, 9, 132, 226, 151, 120, 37, 73, 11, 6, 91, 215, 161, 255, 164, 188, 199, 140, 194, 163, 142, 233, 111, 219, 43, 154, 161, 159, 62, 241, 200, 178, 105, 218, 213, 2, 235, 230, 204, 13, 89, 227, 187, 80, 204, 186, 31, 82, 36, 121, 26, 89, 183, 89, 197, 112, 126, 228, 215, 48, 26, 224, 58, 22, 92, 119, 33, 230, 169, 204, 58, 106, 45, 213, 237, 148, 239, 170, 139, 150, 117, 35, 36, 196, 67, 136, 149, 86, 52, 80, 107, 43, 47, 9, 2, 150, 76, 80, 82, 141, 140, 34, 233, 228, 114, 137, 37, 146, 200, 226, 117, 141, 157, 177, 225, 98, 119, 90, 87, 31, 181, 2, 229, 83, 128, 103, 222, 85, 5, 7, 86, 21, 152, 126, 101, 87, 104, 220, 108, 179, 84, 135, 37, 186, 73, 154, 101, 45, 159, 64, 7, 13, 135, 186, 14, 232, 250, 58, 208, 178, 73, 252, 107, 215, 38, 174, 94, 8, 28, 179, 80, 177, 123, 154, 62, 88, 101, 208, 232, 61, 196, 239, 186, 219, 232, 147, 63, 161, 40, 41, 80, 191, 110, 118, 46, 168, 54, 112, 5, 106, 16, 105, 98, 125, 114, 39, 17, 169, 86, 200, 239, 53, 244, 11, 105, 93, 26, 86, 120, 43, 186, 103, 126, 12, 111, 160, 175, 219, 183, 183, 175, 230, 199, 246, 13, 116, 252, 193, 29, 233, 184, 249, 241, 224, 6, 168, 240, 240, 46, 82, 193, 252, 120, 184, 76, 146, 96, 127, 122, 71, 85, 221, 188, 231, 80, 87, 27, 47, 67, 91, 89, 110, 29, 225, 251, 172, 59, 226, 177, 177, 71, 188, 241, 88, 3, 117, 146, 161, 131, 134, 170, 113, 79, 224, 81, 139, 158, 217, 19, 92, 141, 125, 234, 248, 137, 152, 113, 195, 141, 166, 180, 154, 27, 222, 212, 84, 17, 70, 149, 248, 67, 89, 196, 227, 46, 178, 172, 150, 129, 139, 91, 216, 192, 122, 110, 79, 191, 220, 198, 146, 6, 86, 68, 54, 173, 220, 157, 24, 29, 158, 145, 185, 179, 188, 220, 94, 216, 16, 139, 234, 214, 230, 64, 139, 25, 191, 102, 190, 183, 103, 251, 26, 13, 209, 168, 31, 194, 218, 33, 160, 27, 244, 186, 154, 190, 246, 75, 56, 150, 111, 35, 221, 90, 182, 237, 121, 253, 51, 117, 68, 61, 218, 51, 249, 226, 125, 218, 190, 77, 125, 82, 143, 246, 124, 189, 120, 247, 30, 220, 210, 238, 169, 71, 123, 78, 94, 188, 167, 15, 111, 127, 79, 213, 163, 61, 235, 46, 208, 105, 236, 18, 12, 46, 5, 201, 170, 109, 171, 118, 213, 182, 211, 98, 226, 205, 116, 7, 50, 115, 4, 178, 190, 134, 86, 156, 235, 224, 7, 36, 179, 124, 235, 138, 219, 106, 130, 111, 57, 9, 182, 6, 252, 192, 55, 179, 163, 121, 145, 242, 207, 114, 230, 116, 239, 172, 183, 248, 198, 154, 217, 251, 88, 40, 128, 173, 83, 192, 204, 162, 158, 231, 79, 18, 55, 227, 236, 4, 116, 137, 145, 169, 241, 166, 45, 203, 151, 230, 58, 253, 188, 4, 211, 88, 155, 46, 163, 142, 60, 49, 158, 182, 91, 22, 90, 131, 200, 143, 215, 1, 247, 197, 239, 231, 139, 18, 88, 105, 189, 141, 41, 246, 223, 219, 202, 106, 103, 185, 204, 139, 244, 4, 78, 228, 139, 190, 224, 232, 21, 49, 226, 222, 240, 149, 225, 154, 93, 253, 185, 220, 61, 149, 145, 212, 58, 235, 155, 212, 142, 60, 93, 77, 169, 133, 233, 239, 214, 7, 180, 29, 120, 3, 186, 194, 241, 67, 91, 91, 68, 104, 139, 208, 198, 152, 110, 235, 117, 86, 58, 13, 106, 199, 203, 249, 221, 148, 143, 189, 45, 214, 61, 66, 47, 106, 177, 91, 102, 111, 66, 184, 182, 81, 131, 101, 20, 178, 139, 188, 86, 145, 179, 71, 229, 183, 113, 140, 133, 163, 115, 130, 225, 61, 37, 254, 136, 71, 207, 218, 134, 230, 241, 160, 77, 67, 23, 220, 150, 14, 12, 221, 142, 127, 84, 180, 149, 215, 134, 228, 144, 232, 108, 199, 207, 117, 120, 239, 17, 23, 195, 28, 83, 183, 155, 18, 220, 66, 244, 175, 155, 145, 73, 76, 119, 17, 107, 55, 13, 241, 88, 91, 3, 243, 137, 231, 75, 35, 241, 109, 167, 75, 50, 46, 244, 94, 164, 219, 58, 83, 98, 204, 254, 124, 162, 120, 194, 108, 10, 202, 66, 237, 212, 58, 216, 196, 186, 49, 107, 106, 248, 243, 79, 27, 84, 93, 124, 35, 183, 174, 201, 236, 192, 107, 163, 205, 108, 163, 222, 244, 89, 209, 195, 248, 162, 79, 91, 29, 80, 24, 158, 240, 204, 123, 102, 29, 224, 200, 200, 78, 22, 2, 138, 104, 188, 147, 198, 194, 103, 153, 244, 191, 204, 15, 214, 252, 208, 28, 219, 43, 211, 83, 205, 68, 216, 176, 24, 119, 39, 181, 27, 212, 162, 123, 192, 6, 60, 175, 92, 19, 146, 177, 179, 131, 126, 208, 249, 10, 170, 154, 175, 86, 236, 8, 252, 67, 49, 205, 86, 194, 114, 60, 10, 56, 236, 118, 181, 190, 183, 139, 205, 151, 238, 140, 105, 5, 224, 250, 236, 25, 207, 188, 25, 216, 30, 249, 50, 131, 126, 153, 65, 163, 47, 51, 104, 83, 32, 124, 199, 233, 211, 221, 120, 186, 177, 121, 244, 203, 92, 119, 27, 230, 186, 155, 136, 233, 235, 176, 135, 138, 105, 21, 152, 102, 220, 45, 85, 81, 120, 193, 213, 88, 56, 40, 115, 224, 239, 128, 124, 251, 101, 249, 246, 57, 38, 159, 123, 162, 158, 253, 39, 81, 90, 170, 103, 255, 201, 220, 112, 72, 253, 66, 199, 240, 204, 217, 142, 131, 98, 196, 115, 106, 80, 29, 223, 55, 233, 231, 127, 88, 211, 123, 73, 180, 6, 14, 243, 171, 101, 130, 112, 85, 62, 140, 158, 9, 131, 234, 9, 62, 140, 35, 196, 37, 216, 8, 14, 158, 226, 232, 232, 185, 172, 241, 90, 214, 225, 239, 199, 158, 196, 186, 140, 48, 86, 94, 177, 174, 247, 120, 134, 155, 183, 26, 119, 97, 227, 150, 45, 13, 83, 31, 98, 29, 154, 177, 137, 184, 108, 161, 13, 74, 166, 21, 172, 6, 238, 159, 28, 119, 217, 197, 248, 34, 197, 203, 145, 226, 46, 86, 91, 141, 197, 182, 44, 17, 214, 241, 82, 1, 227, 174, 205, 73, 156, 26, 163, 174, 214, 28, 14, 91, 118, 159, 66, 67, 180, 241, 3, 96, 43, 173, 49, 244, 109, 69, 26, 89, 95, 84, 77, 221, 73, 218, 150, 11, 186, 240, 177, 135, 47, 234, 231, 139, 250, 185, 147, 234, 103, 193, 128, 211, 229, 132, 249, 182, 92, 154, 118, 82, 120, 29, 99, 125, 191, 104, 70, 108, 22, 223, 178, 204, 108, 98, 71, 32, 249, 144, 230, 243, 242, 5, 226, 112, 204, 240, 142, 139, 108, 191, 252, 159, 164, 200, 97, 0, 217, 104, 115, 150, 232, 59, 48, 212, 217, 95, 222, 35, 171, 102, 64, 170, 200, 213, 116, 181, 153, 91, 32, 55, 187, 206, 180, 247, 152, 233, 229, 191, 28, 31, 31, 215, 28, 91, 183, 87, 76, 234, 88, 114, 29, 114, 14, 122, 78, 23, 165, 130, 163, 59, 25, 11, 38, 147, 145, 39, 208, 188, 19, 78, 120, 122, 8, 160, 68, 119, 28, 172, 60, 146, 158, 3, 0, 130, 60, 52, 105, 220, 192, 5, 30, 102, 234, 230, 170, 134, 221, 107, 19, 10, 240, 160, 214, 121, 81, 48, 169, 175, 227, 70, 62, 110, 134, 249, 236, 26, 62, 4, 2, 60, 231, 165, 160, 226, 193, 192, 36, 40, 105, 183, 97, 223, 106, 68, 103, 32, 151, 84, 179, 41, 91, 10, 171, 100, 82, 83, 88, 24, 223, 38, 45, 240, 94, 222, 104, 84, 229, 133, 216, 30, 244, 93, 113, 36, 122, 98, 18, 99, 4, 110, 74, 130, 1, 69, 240, 204, 38, 178, 17, 105, 125, 3, 67, 189, 152, 243, 66, 123, 188, 139, 24, 65, 249, 161, 207, 169, 72, 207, 102, 64, 196, 171, 236, 189, 249, 170, 110, 225, 162, 54, 34, 196, 234, 114, 79, 34, 55, 135, 248, 176, 148, 48, 72, 85, 82, 168, 97, 64, 24, 235, 28, 31, 221, 165, 219, 106, 38, 176, 13, 65, 117, 0, 151, 125, 162, 86, 202, 238, 59, 247, 240, 79, 117, 201, 191, 225, 84, 202, 141, 38, 213, 236, 255, 241, 118, 189, 170, 13, 1, 42, 148, 242, 179, 13, 208, 250, 76, 44, 62, 74, 116, 74, 146, 178, 163, 53, 124, 150, 92, 60, 87, 33, 8, 234, 128, 113, 91, 64, 87, 61, 164, 84, 21, 32, 28, 211, 224, 116, 221, 46, 4, 217, 103, 69, 166, 94, 165, 101, 17, 113, 130, 57, 223, 247, 6, 17, 220, 1, 117, 57, 208, 240, 136, 116, 210, 188, 132, 98, 118, 219, 197, 91, 79, 140, 159, 21, 95, 122, 24, 95, 117, 137, 125, 130, 74, 60, 143, 44, 252, 219, 113, 22, 9, 188, 128, 128, 240, 244, 233, 83, 203, 219, 168, 26, 148, 173, 80, 95, 60, 78, 164, 167, 106, 148, 233, 239, 192, 148, 56, 247, 28, 191, 71, 148, 191, 198, 149, 3, 242, 36, 83, 34, 211, 137, 90, 145, 83, 78, 215, 225, 132, 90, 118, 78, 63, 58, 110, 6, 50, 159, 104, 16, 212, 53, 115, 131, 121, 51, 80, 254, 127, 127, 58, 196, 45, 115, 8, 209, 71, 156, 223, 96, 142, 241, 168, 191, 87, 57, 178, 226, 177, 90, 100, 150, 205, 106, 32, 208, 22, 99, 15, 32, 229, 142, 226, 111, 204, 2, 2, 98, 99, 251, 135, 9, 244, 239, 59, 62, 162, 155, 118, 77, 183, 127, 115, 237, 36, 66, 254, 223, 136, 141, 242, 155, 116, 42, 131, 158, 253, 13, 12, 112, 220, 54, 252, 243, 110, 148, 36, 173, 226, 97, 127, 143, 204, 93, 209, 122, 44, 131, 108, 243, 187, 179, 156, 173, 65, 251, 247, 246, 155, 159, 64, 143, 223, 205, 66, 210, 116, 188, 75, 103, 127, 99, 42, 226, 119, 182, 154, 37, 177, 184, 1, 133, 74, 44, 146, 223, 118, 156, 238, 57, 188, 219, 220, 177, 223, 120, 20, 13, 213, 181, 161, 109, 178, 223, 224, 178, 201, 223, 240, 118, 24, 191, 224, 157, 205, 181, 246, 245, 186, 162, 107, 218, 251, 226, 226, 239, 164, 97, 19, 42, 96, 70, 153, 109, 113, 196, 40, 90, 117, 114, 41, 213, 231, 192, 138, 170, 102, 64, 33, 140, 90, 221, 107, 37, 75, 137, 20, 160, 56, 245, 226, 46, 199, 155, 233, 63, 39, 97, 28, 201, 199, 10, 218, 50, 49, 117, 127, 247, 40, 21, 62, 89, 113, 235, 227, 224, 184, 49, 135, 210, 239, 254, 244, 73, 2, 10, 228, 111, 210, 148, 144, 194, 159, 242, 131, 93, 22, 120, 204, 8, 13, 212, 249, 93, 93, 106, 39, 25, 74, 81, 194, 67, 156, 70, 2, 185, 68, 194, 156, 131, 85, 169, 214, 138, 202, 210, 158, 217, 178, 213, 128, 118, 79, 94, 216, 137, 229, 169, 35, 31, 240, 249, 73, 179, 2, 50, 227, 119, 61, 182, 251, 187, 89, 145, 87, 57, 152, 149, 239, 132, 48, 90, 139, 248, 186, 36, 250, 252, 8, 214, 126, 73, 140, 219, 67, 59, 117, 54, 49, 94, 36, 197, 32, 79, 171, 212, 111, 73, 117, 154, 79, 246, 143, 255, 85, 196, 179, 153, 137, 174, 63, 84, 15, 114, 81, 33, 127, 245, 188, 56, 91, 23, 250, 214, 45, 7, 130, 233, 201, 15, 3, 73, 199, 223, 36, 101, 213, 137, 38, 53, 11, 154, 14, 23, 11, 180, 194, 31, 16, 127, 158, 23, 28, 69, 23, 255, 175, 212, 218, 140, 175, 97, 228, 181, 8, 234, 30, 14, 142, 124, 248, 98, 1, 89, 73, 222, 185, 112, 52, 226, 183, 249, 110, 150, 226, 237, 91, 114, 199, 0, 154, 166, 118, 167, 211, 207, 228, 3, 42, 105, 102, 188, 207, 176, 254, 35, 139, 13, 21, 99, 90, 12, 34, 103, 113, 223, 232, 253, 113, 150, 132, 250, 72, 254, 34, 139, 164, 5, 150, 116, 18, 119, 180, 22, 106, 183, 65, 65, 84, 150, 70, 182, 215, 163, 136, 132, 150, 79, 166, 213, 22, 139, 12, 79, 197, 205, 118, 72, 106, 68, 164, 70, 233, 176, 182, 58, 233, 173, 49, 78, 228, 254, 171, 71, 96, 184, 255, 217, 29, 196, 92, 130, 24, 110, 113, 16, 46, 117, 55, 182, 45, 149, 45, 46, 89, 148, 82, 41, 108, 8, 102, 150, 196, 192, 138, 154, 199, 24, 181, 6, 54, 3, 78, 253, 174, 173, 26, 112, 69, 114, 146, 92, 206, 6, 74, 227, 134, 1, 154, 172, 20, 214, 255, 248, 76, 46, 193, 177, 190, 188, 74, 46, 188, 13, 241, 110, 11, 126, 100, 250, 135, 176, 161, 170, 205, 23, 31, 2, 161, 86, 165, 135, 10, 237, 86, 165, 183, 85, 231, 90, 149, 126, 160, 60, 8, 127, 202, 17, 243, 87, 16, 150, 146, 170, 197, 127, 201, 59, 235, 53, 229, 86, 172, 171, 79, 100, 97, 159, 67, 141, 80, 236, 85, 114, 89, 161, 107, 109, 196, 149, 242, 126, 157, 202, 175, 36, 102, 179, 114, 95, 20, 250, 101, 30, 23, 147, 55, 185, 119, 24, 160, 232, 90, 200, 3, 88, 63, 105, 83, 72, 129, 41, 28, 16, 180, 230, 109, 183, 91, 158, 169, 91, 187, 81, 255, 136, 248, 189, 215, 143, 240, 177, 243, 73, 158, 177, 23, 60, 77, 173, 184, 255, 217, 222, 63, 213, 122, 206, 29, 28, 184, 98, 77, 140, 139, 26, 8, 247, 40, 178, 89, 136, 75, 151, 39, 52, 8, 212, 46, 148, 101, 238, 245, 57, 11, 188, 129, 93, 49, 10, 98, 76, 28, 93, 75, 145, 217, 90, 65, 91, 73, 130, 137, 91, 168, 120, 10, 99, 136, 97, 180, 212, 248, 20, 194, 3, 12, 161, 54, 245, 251, 226, 7, 243, 173, 253, 99, 228, 62, 145, 49, 185, 157, 60, 129, 146, 179, 116, 15, 162, 104, 219, 240, 18, 137, 144, 87, 6, 234, 107, 101, 52, 162, 9, 184, 175, 61, 177, 45, 34, 233, 165, 130, 28, 10, 169, 145, 152, 186, 213, 3, 51, 172, 172, 189, 45, 106, 31, 123, 34, 231, 67, 155, 245, 122, 193, 33, 73, 170, 127, 147, 205, 20, 249, 150, 172, 160, 87, 195, 219, 241, 181, 123, 241, 122, 147, 90, 207, 147, 184, 194, 227, 39, 146, 81, 229, 146, 14, 45, 146, 126, 180, 119, 225, 173, 73, 197, 19, 183, 10, 145, 171, 198, 51, 130, 34, 102, 189, 171, 255, 26, 229, 235, 48, 4, 252, 123, 136, 127, 108, 12, 245, 15, 180, 50, 12, 73, 186, 248, 102, 73, 59, 166, 146, 239, 14, 132, 224, 6, 191, 237, 48, 177, 199, 128, 23, 146, 113, 227, 222, 184, 240, 198, 88, 98, 27, 162, 47, 158, 88, 140, 145, 199, 39, 81, 59, 64, 193, 224, 98, 67, 139, 107, 142, 12, 158, 35, 173, 1, 114, 206, 83, 45, 157, 5, 76, 4, 10, 103, 132, 15, 242, 162, 15, 78, 234, 29, 253, 205, 97, 4, 181, 7, 41, 213, 126, 211, 14, 132, 118, 165, 66, 121, 98, 173, 90, 33, 227, 254, 254, 241, 11, 66, 169, 85, 212, 64, 10, 68, 6, 77, 130, 13, 164, 36, 213, 196, 37, 133, 141, 108, 91, 18, 177, 213, 218, 219, 47, 150, 221, 145, 24, 98, 77, 221, 105, 162, 117, 69, 78, 247, 192, 202, 142, 174, 132, 14, 205, 7, 170, 152, 218, 94, 183, 228, 7, 32, 129, 209, 226, 46, 34, 172, 33, 35, 174, 43, 136, 146, 232, 28, 193, 175, 164, 77, 55, 135, 195, 248, 13, 14, 72, 210, 60, 108, 163, 91, 54, 236, 72, 100, 229, 90, 227, 34, 150, 32, 126, 121, 112, 174, 111, 212, 214, 171, 154, 106, 245, 229, 239, 130, 186, 212, 70, 213, 223, 44, 155, 83, 95, 62, 64, 24, 147, 47, 9, 85, 149, 35, 179, 120, 23, 62, 137, 126, 143, 23, 234, 173, 189, 37, 60, 202, 42, 121, 131, 140, 100, 75, 171, 171, 178, 148, 181, 216, 218, 47, 95, 231, 101, 153, 190, 159, 94, 73, 91, 150, 172, 207, 53, 222, 164, 203, 220, 117, 177, 159, 193, 21, 185, 113, 197, 170, 38, 194, 28, 230, 97, 75, 98, 128, 63, 136, 214, 45, 31, 7, 91, 86, 244, 4, 75, 244, 68, 202, 166, 129, 225, 93, 81, 139, 182, 35, 215, 148, 28, 113, 201, 145, 134, 184, 251, 229, 43, 198, 122, 7, 197, 63, 84, 135, 57, 8, 234, 94, 241, 224, 40, 137, 39, 208, 36, 58, 33, 45, 95, 139, 203, 40, 71, 202, 34, 85, 142, 23, 169, 238, 96, 231, 89, 112, 113, 79, 81, 158, 55, 181, 218, 183, 171, 130, 75, 35, 206, 164, 205, 37, 165, 128, 155, 98, 98, 4, 95, 228, 249, 217, 124, 214, 95, 211, 134, 216, 170, 219, 25, 217, 221, 21, 99, 44, 145, 3, 193, 138, 26, 172, 165, 26, 239, 138, 40, 228, 56, 189, 201, 74, 7, 25, 47, 74, 211, 34, 226, 40, 149, 79, 121, 147, 177, 164, 36, 167, 170, 16, 100, 82, 91, 23, 133, 216, 212, 241, 148, 217, 184, 71, 106, 157, 200, 225, 115, 106, 142, 243, 233, 65, 246, 186, 128, 109, 167, 244, 67, 178, 151, 207, 51, 126, 123, 174, 59, 199, 233, 94, 219, 238, 21, 237, 79, 8, 116, 220, 235, 155, 212, 101, 0, 99, 207, 208, 215, 27, 223, 88, 137, 179, 73, 178, 210, 241, 115, 207, 217, 15, 1, 68, 92, 250, 57, 178, 38, 62, 25, 78, 160, 42, 4, 168, 168, 20, 139, 46, 232, 118, 6, 159, 86, 229, 190, 145, 62, 106, 71, 112, 89, 155, 14, 184, 247, 89, 218, 33, 89, 72, 205, 248, 136, 143, 184, 232, 178, 142, 131, 132, 255, 107, 20, 214, 13, 224, 132, 93, 170, 122, 96, 0, 109, 13, 33, 185, 51, 32, 166, 84, 70, 229, 132, 224, 176, 48, 94, 170, 202, 201, 13, 5, 41, 132, 240, 22, 150, 20, 22, 4, 75, 173, 14, 135, 67, 135, 231, 57, 186, 205, 78, 58, 205, 211, 162, 17, 122, 15, 168, 183, 169, 109, 86, 70, 211, 200, 123, 38, 254, 230, 245, 20, 107, 122, 249, 170, 138, 247, 231, 126, 104, 43, 237, 82, 113, 85, 86, 157, 252, 155, 91, 146, 106, 112, 224, 141, 181, 146, 92, 65, 80, 25, 112, 44, 3, 138, 5, 102, 43, 118, 72, 173, 228, 203, 89, 60, 97, 125, 188, 20, 38, 40, 91, 66, 164, 211, 233, 72, 90, 141, 236, 211, 179, 108, 114, 109, 241, 22, 96, 96, 115, 69, 60, 193, 246, 10, 60, 142, 170, 184, 168, 124, 70, 129, 181, 203, 66, 232, 152, 102, 213, 75, 133, 45, 182, 157, 117, 23, 176, 143, 139, 189, 225, 251, 196, 133, 21, 88, 67, 128, 8, 47, 3, 251, 97, 233, 88, 246, 82, 33, 165, 189, 206, 64, 157, 132, 32, 103, 232, 165, 53, 185, 42, 68, 110, 70, 114, 129, 58, 136, 60, 141, 250, 253, 97, 244, 248, 113, 244, 96, 11, 54, 175, 183, 41, 97, 15, 227, 236, 68, 43, 132, 45, 66, 47, 104, 80, 116, 149, 192, 219, 144, 253, 82, 200, 179, 37, 79, 54, 134, 64, 109, 233, 119, 82, 125, 113, 125, 176, 146, 53, 138, 100, 198, 56, 85, 197, 170, 67, 105, 241, 220, 87, 13, 254, 183, 124, 173, 183, 220, 255, 52, 110, 70, 127, 107, 235, 56, 100, 93, 194, 132, 213, 166, 130, 248, 95, 22, 68, 69, 83, 201, 67, 64, 83, 124, 252, 223, 80, 149, 173, 97, 188, 45, 90, 83, 98, 0, 43, 49, 46, 94, 225, 120, 87, 2, 155, 250, 69, 4, 182, 157, 162, 30, 217, 241, 36, 196, 52, 80, 4, 151, 195, 126, 157, 87, 210, 248, 146, 36, 36, 158, 239, 146, 44, 32, 162, 75, 107, 159, 211, 148, 54, 175, 71, 137, 239, 250, 28, 23, 249, 185, 138, 4, 240, 110, 204, 168, 227, 41, 170, 218, 175, 204, 58, 75, 166, 125, 165, 128, 148, 38, 66, 17, 27, 2, 228, 22, 103, 26, 207, 231, 169, 68, 115, 11, 113, 149, 75, 158, 66, 93, 48, 203, 67, 162, 100, 122, 87, 55, 183, 249, 117, 140, 19, 9, 205, 103, 155, 200, 149, 136, 92, 178, 32, 28, 200, 186, 101, 25, 43, 19, 4, 59, 184, 60, 193, 101, 234, 231, 126, 92, 178, 141, 1, 160, 110, 213, 137, 8, 153, 5, 71, 5, 175, 144, 68, 231, 120, 168, 77, 64, 128, 184, 243, 152, 162, 55, 182, 11, 52, 156, 86, 134, 129, 191, 123, 55, 98, 29, 40, 196, 186, 144, 166, 165, 197, 32, 0, 142, 156, 66, 184, 119, 74, 61, 234, 69, 51, 190, 65, 24, 177, 160, 165, 47, 5, 36, 117, 183, 36, 142, 101, 24, 144, 102, 3, 87, 100, 74, 106, 251, 47, 65, 94, 184, 41, 255, 125, 199, 100, 162, 155, 229, 101, 109, 184, 243, 36, 185, 60, 56, 70, 59, 203, 8, 190, 153, 73, 242, 210, 217, 129, 83, 147, 8, 43, 135, 155, 3, 68, 44, 111, 31, 175, 80, 195, 8, 110, 2, 107, 218, 73, 214, 186, 246, 118, 174, 160, 173, 176, 42, 78, 167, 175, 121, 239, 0, 191, 117, 82, 203, 58, 176, 151, 37, 23, 35, 141, 42, 238, 145, 118, 49, 234, 18, 58, 44, 130, 248, 235, 240, 103, 162, 230, 57, 134, 226, 16, 153, 38, 187, 41, 188, 254, 68, 17, 100, 135, 48, 176, 182, 197, 74, 27, 91, 206, 153, 178, 99, 143, 73, 105, 23, 211, 117, 31, 46, 178, 242, 128, 182, 180, 161, 222, 219, 235, 93, 68, 153, 224, 76, 193, 99, 135, 110, 124, 178, 104, 191, 150, 245, 233, 42, 178, 160, 245, 43, 51, 188, 170, 69, 37, 238, 230, 210, 22, 17, 173, 121, 113, 251, 101, 150, 251, 143, 157, 229, 22, 154, 115, 118, 149, 149, 187, 248, 180, 35, 42, 24, 61, 23, 214, 205, 177, 216, 130, 249, 233, 202, 14, 79, 30, 14, 8, 20, 221, 125, 102, 218, 31, 28, 67, 28, 255, 75, 185, 57, 166, 79, 170, 232, 240, 20, 147, 25, 13, 29, 213, 174, 203, 135, 6, 251, 53, 232, 176, 182, 47, 196, 198, 51, 107, 234, 47, 56, 14, 150, 144, 74, 190, 83, 88, 240, 159, 136, 123, 73, 179, 143, 61, 201, 246, 157, 107, 6, 80, 127, 112, 229, 29, 91, 176, 2, 105, 183, 107, 147, 110, 251, 19, 127, 121, 18, 110, 251, 186, 232, 203, 36, 166, 189, 40, 188, 219, 184, 243, 134, 203, 71, 211, 148, 199, 148, 152, 153, 204, 75, 85, 58, 232, 54, 93, 217, 252, 70, 11, 224, 182, 10, 149, 115, 140, 180, 232, 156, 245, 182, 219, 136, 200, 153, 125, 204, 137, 59, 116, 36, 24, 96, 205, 195, 120, 230, 178, 192, 61, 166, 147, 61, 141, 101, 242, 207, 229, 86, 167, 41, 0, 167, 207, 246, 212, 238, 217, 3, 148, 252, 43, 58, 179, 52, 87, 180, 0, 247, 101, 171, 202, 154, 27, 197, 145, 163, 6, 7, 112, 41, 207, 37, 181, 244, 0, 75, 82, 227, 25, 80, 67, 184, 69, 14, 96, 133, 211, 117, 60, 192, 55, 181, 105, 69, 18, 34, 52, 111, 93, 109, 108, 47, 111, 207, 234, 186, 238, 106, 61, 250, 93, 156, 213, 165, 56, 0, 158, 204, 98, 25, 52, 139, 206, 128, 95, 75, 234, 1, 174, 207, 98, 151, 34, 14, 239, 189, 11, 106, 40, 211, 78, 148, 49, 11, 107, 135, 145, 236, 135, 23, 180, 42, 92, 115, 78, 149, 140, 164, 228, 8, 232, 9, 98, 191, 129, 105, 5, 133, 162, 185, 39, 138, 66, 46, 45, 31, 134, 203, 113, 104, 41, 172, 66, 42, 204, 148, 104, 50, 243, 85, 185, 86, 138, 12, 232, 131, 136, 162, 172, 88, 193, 72, 142, 70, 51, 71, 146, 177, 101, 175, 235, 122, 216, 154, 115, 18, 209, 105, 10, 70, 75, 171, 222, 237, 205, 205, 168, 53, 125, 24, 178, 145, 22, 245, 27, 242, 252, 160, 146, 82, 114, 130, 89, 189, 61, 149, 199, 175, 221, 115, 211, 17, 63, 231, 132, 44, 127, 202, 175, 222, 83, 212, 186, 107, 71, 111, 241, 152, 137, 57, 4, 243, 108, 120, 183, 254, 104, 68, 170, 134, 164, 72, 30, 176, 29, 68, 135, 156, 48, 90, 59, 212, 224, 220, 2, 11, 138, 3, 50, 116, 92, 41, 134, 166, 253, 202, 16, 217, 88, 113, 81, 113, 19, 107, 9, 170, 80, 65, 237, 186, 51, 55, 245, 108, 182, 201, 29, 59, 190, 211, 199, 43, 238, 51, 38, 60, 129, 99, 198, 240, 6, 111, 234, 241, 221, 29, 232, 129, 149, 138, 226, 71, 14, 247, 17, 170, 10, 189, 84, 21, 143, 121, 162, 111, 9, 221, 44, 184, 82, 225, 158, 208, 171, 47, 133, 2, 236, 38, 240, 93, 12, 10, 64, 180, 93, 91, 157, 21, 241, 84, 46, 242, 115, 187, 162, 193, 104, 160, 129, 27, 47, 95, 110, 175, 11, 131, 197, 3, 251, 41, 122, 51, 134, 239, 154, 176, 153, 36, 103, 166, 51, 252, 94, 147, 199, 70, 248, 89, 187, 253, 114, 63, 155, 50, 104, 108, 88, 95, 196, 197, 73, 98, 111, 8, 233, 49, 198, 7, 236, 200, 55, 197, 82, 216, 190, 191, 62, 87, 45, 176, 217, 219, 196, 58, 50, 117, 130, 203, 118, 156, 149, 34, 20, 129, 137, 121, 138, 215, 194, 76, 101, 109, 55, 234, 134, 31, 163, 220, 11, 6, 25, 47, 115, 193, 194, 138, 129, 213, 113, 56, 216, 229, 234, 173, 203, 184, 197, 48, 38, 63, 185, 75, 157, 207, 96, 148, 33, 231, 106, 136, 59, 19, 197, 154, 242, 56, 174, 130, 201, 161, 213, 237, 205, 113, 94, 210, 152, 253, 41, 130, 126, 81, 163, 157, 25, 202, 195, 77, 227, 28, 182, 91, 33, 164, 113, 120, 125, 38, 18, 192, 186, 48, 17, 180, 182, 43, 195, 41, 229, 157, 212, 253, 53, 111, 62, 142, 146, 110, 204, 251, 43, 121, 182, 12, 216, 168, 235, 102, 153, 53, 160, 234, 245, 183, 214, 214, 154, 225, 109, 119, 130, 23, 250, 52, 92, 243, 48, 142, 144, 9, 120, 175, 47, 50, 77, 185, 223, 136, 253, 121, 28, 57, 232, 236, 192, 185, 117, 219, 137, 228, 122, 229, 112, 179, 169, 50, 114, 204, 170, 223, 84, 106, 191, 124, 7, 7, 198, 114, 39, 48, 128, 120, 39, 38, 47, 62, 125, 80, 253, 240, 152, 111, 117, 195, 191, 31, 157, 237, 112, 54, 254, 120, 34, 147, 229, 30, 133, 52, 10, 158, 169, 96, 226, 81, 13, 1, 178, 172, 153, 96, 3, 114, 170, 243, 0, 230, 95, 48, 216, 114, 22, 103, 182, 58, 212, 51, 146, 82, 132, 237, 102, 50, 14, 170, 139, 198, 129, 81, 246, 40, 28, 17, 179, 210, 31, 131, 69, 188, 148, 237, 156, 196, 175, 113, 194, 182, 112, 70, 120, 69, 32, 162, 116, 81, 134, 39, 20, 39, 172, 71, 102, 141, 210, 187, 69, 172, 248, 183, 40, 73, 223, 19, 39, 62, 168, 77, 128, 144, 9, 209, 224, 126, 86, 72, 141, 103, 129, 129, 240, 127, 141, 253, 27, 237, 113, 230, 122, 99, 103, 7, 175, 205, 160, 54, 202, 32, 244, 134, 123, 250, 176, 17, 157, 49, 171, 94, 103, 216, 224, 53, 76, 233, 17, 46, 77, 207, 218, 88, 158, 97, 164, 56, 222, 248, 116, 70, 170, 79, 248, 118, 26, 96, 179, 237, 36, 155, 213, 7, 18, 116, 128, 188, 254, 45, 18, 17, 168, 134, 244, 7, 58, 226, 252, 101, 75, 174, 160, 231, 149, 69, 137, 206, 39, 149, 71, 173, 10, 14, 45, 201, 243, 158, 255, 165, 24, 92, 251, 228, 175, 213, 161, 133, 206, 252, 82, 24, 109, 78, 251, 186, 157, 8, 164, 232, 104, 58, 114, 41, 14, 61, 33, 149, 110, 29, 242, 245, 31, 181, 228, 181, 140, 232, 120, 178, 120, 117, 63, 103, 44, 172, 79, 121, 112, 21, 167, 115, 233, 124, 78, 24, 78, 7, 189, 206, 83, 190, 117, 18, 218, 185, 213, 101, 118, 43, 30, 66, 158, 146, 44, 208, 227, 211, 184, 224, 174, 5, 6, 97, 200, 180, 68, 223, 128, 124, 42, 179, 163, 213, 48, 164, 160, 142, 132, 201, 106, 107, 104, 146, 55, 201, 153, 159, 16, 130, 48, 65, 236, 169, 86, 7, 156, 155, 6, 166, 103, 152, 203, 141, 137, 209, 60, 123, 96, 142, 241, 45, 129, 42, 54, 11, 140, 223, 21, 241, 5, 79, 185, 48, 98, 2, 20, 25, 225, 24, 231, 249, 25, 79, 183, 172, 51, 7, 171, 66, 38, 216, 55, 190, 32, 223, 121, 141, 77, 246, 214, 216, 27, 92, 40, 167, 163, 228, 132, 155, 97, 228, 20, 88, 124, 97, 71, 63, 58, 165, 61, 6, 172, 12, 244, 168, 169, 97, 91, 175, 102, 231, 51, 190, 80, 7, 216, 168, 17, 233, 26, 128, 168, 168, 182, 43, 241, 201, 180, 225, 14, 250, 249, 216, 238, 38, 250, 104, 172, 77, 181, 119, 168, 234, 56, 182, 41, 246, 220, 32, 172, 214, 3, 118, 169, 134, 165, 236, 211, 143, 43, 181, 117, 161, 75, 186, 142, 161, 2, 97, 171, 112, 88, 201, 251, 244, 164, 227, 52, 228, 179, 51, 24, 20, 219, 200, 80, 195, 250, 152, 125, 123, 218, 195, 182, 63, 47, 6, 233, 19, 31, 255, 55, 255, 230, 69, 139, 113, 255, 217, 50, 16, 3, 56, 97, 212, 224, 107, 24, 57, 241, 213, 139, 94, 62, 157, 44, 3, 59, 6, 38, 140, 92, 24, 49, 63, 82, 199, 233, 101, 178, 12, 172, 56, 156, 32, 90, 85, 21, 196, 11, 62, 249, 237, 157, 152, 89, 187, 229, 18, 80, 147, 144, 130, 200, 165, 65, 220, 82, 63, 106, 229, 57, 211, 125, 75, 64, 140, 195, 9, 162, 197, 191, 6, 81, 147, 95, 189, 232, 177, 63, 103, 201, 50, 240, 227, 128, 194, 8, 242, 207, 97, 12, 229, 231, 128, 23, 119, 25, 248, 205, 223, 135, 145, 155, 135, 69, 129, 127, 243, 163, 53, 91, 10, 90, 179, 26, 180, 102, 53, 104, 205, 44, 180, 158, 149, 227, 120, 150, 236, 86, 172, 232, 251, 121, 37, 179, 86, 127, 48, 179, 114, 154, 205, 230, 160, 166, 241, 100, 245, 129, 172, 63, 253, 65, 65, 170, 222, 32, 250, 166, 247, 205, 32, 234, 125, 253, 219, 60, 175, 118, 122, 94, 135, 123, 156, 141, 79, 153, 113, 11, 135, 104, 175, 79, 26, 1, 172, 253, 210, 82, 118, 227, 155, 199, 49, 63, 197, 251, 164, 247, 13, 35, 149, 151, 42, 2, 191, 117, 214, 161, 167, 80, 102, 36, 72, 26, 7, 148, 94, 158, 85, 227, 124, 154, 195, 74, 117, 170, 114, 128, 93, 75, 251, 41, 128, 11, 116, 13, 234, 70, 188, 114, 77, 247, 36, 158, 118, 255, 160, 110, 184, 139, 96, 73, 247, 141, 57, 125, 221, 14, 2, 164, 69, 251, 7, 117, 107, 186, 39, 144, 108, 223, 59, 62, 209, 207, 139, 233, 245, 59, 230, 155, 234, 91, 241, 227, 105, 145, 28, 215, 244, 136, 35, 215, 200, 142, 73, 133, 210, 223, 237, 103, 169, 92, 209, 234, 116, 181, 34, 192, 164, 66, 235, 82, 17, 112, 55, 225, 187, 179, 236, 203, 38, 123, 70, 203, 85, 29, 41, 200, 139, 132, 60, 1, 16, 127, 42, 247, 186, 69, 57, 213, 113, 98, 221, 138, 128, 122, 40, 51, 157, 230, 23, 114, 39, 21, 22, 17, 6, 71, 5, 223, 183, 213, 202, 33, 195, 62, 107, 53, 48, 224, 100, 75, 148, 4, 207, 243, 226, 89, 60, 62, 229, 43, 138, 247, 241, 248, 236, 56, 19, 227, 193, 140, 219, 200, 217, 69, 84, 99, 227, 95, 167, 143, 196, 42, 125, 132, 214, 232, 42, 83, 20, 251, 214, 125, 113, 174, 182, 191, 107, 87, 228, 8, 111, 244, 149, 97, 111, 150, 236, 186, 147, 214, 82, 221, 30, 54, 3, 170, 110, 236, 126, 78, 128, 143, 211, 105, 194, 218, 232, 111, 13, 34, 92, 11, 243, 48, 95, 103, 250, 15, 15, 36, 213, 59, 241, 21, 223, 160, 192, 198, 74, 44, 18, 89, 49, 29, 119, 35, 18, 130, 140, 156, 79, 80, 41, 16, 139, 41, 151, 235, 108, 125, 2, 107, 77, 86, 245, 89, 86, 21, 87, 140, 2, 218, 85, 162, 218, 118, 91, 68, 251, 223, 0, 166, 38, 144, 82, 247, 80, 72, 130, 5, 71, 95, 54, 235, 253, 20, 225, 124, 209, 62, 238, 245, 240, 226, 64, 180, 166, 255, 140, 92, 102, 254, 138, 245, 181, 99, 74, 80, 83, 163, 38, 31, 168, 201, 93, 229, 142, 3, 235, 138, 136, 83, 114, 63, 245, 201, 50, 95, 125, 118, 28, 95, 7, 65, 113, 58, 16, 226, 116, 64, 196, 73, 15, 226, 193, 66, 2, 213, 201, 213, 69, 113, 246, 248, 185, 58, 179, 172, 88, 231, 131, 54, 170, 117, 78, 1, 75, 155, 28, 120, 205, 12, 125, 16, 228, 101, 78, 81, 204, 202, 210, 49, 122, 254, 107, 202, 55, 80, 26, 220, 109, 7, 38, 219, 168, 113, 81, 24, 25, 49, 128, 176, 175, 67, 111, 79, 213, 74, 134, 229, 143, 214, 119, 55, 235, 186, 71, 222, 202, 190, 158, 178, 215, 36, 174, 164, 89, 232, 196, 24, 104, 87, 24, 238, 151, 252, 36, 137, 78, 18, 215, 104, 255, 4, 148, 32, 83, 41, 184, 57, 193, 23, 55, 206, 139, 137, 112, 215, 254, 225, 176, 179, 112, 208, 122, 213, 42, 36, 197, 229, 190, 221, 112, 86, 92, 168, 77, 188, 69, 241, 197, 72, 56, 63, 217, 151, 77, 176, 96, 20, 187, 100, 243, 115, 249, 101, 93, 22, 82, 140, 160, 190, 136, 116, 223, 252, 25, 123, 132, 52, 72, 127, 12, 143, 141, 243, 67, 166, 50, 164, 81, 214, 211, 197, 213, 105, 18, 107, 116, 235, 234, 190, 138, 95, 233, 90, 168, 131, 176, 171, 38, 186, 97, 118, 118, 20, 210, 198, 107, 43, 202, 212, 236, 240, 124, 255, 215, 191, 18, 186, 157, 198, 165, 164, 25, 123, 242, 217, 46, 236, 117, 112, 246, 131, 196, 62, 236, 123, 143, 64, 60, 75, 174, 20, 72, 120, 244, 193, 132, 247, 181, 64, 161, 64, 207, 94, 175, 253, 1, 140, 252, 136, 167, 115, 226, 22, 236, 35, 69, 147, 1, 244, 98, 32, 26, 254, 104, 243, 161, 82, 10, 32, 203, 58, 122, 14, 88, 211, 168, 92, 168, 184, 95, 233, 131, 232, 110, 244, 45, 20, 231, 157, 225, 210, 6, 63, 216, 31, 124, 38, 68, 178, 180, 2, 212, 176, 233, 195, 216, 91, 62, 153, 150, 195, 156, 174, 202, 80, 117, 43, 105, 162, 62, 218, 134, 236, 63, 50, 192, 60, 175, 78, 147, 98, 225, 169, 69, 127, 107, 55, 177, 4, 76, 52, 25, 208, 199, 81, 25, 240, 73, 132, 227, 70, 121, 134, 127, 101, 116, 21, 106, 29, 169, 14, 222, 129, 29, 119, 156, 252, 3, 171, 192, 56, 53, 96, 162, 96, 181, 212, 207, 77, 48, 129, 205, 252, 163, 46, 178, 3, 251, 127, 118, 197, 58, 236, 248, 150, 131, 214, 247, 191, 210, 234, 148, 79, 224, 10, 244, 128, 180, 73, 108, 114, 199, 230, 99, 70, 185, 138, 119, 113, 173, 242, 218, 192, 5, 62, 63, 37, 69, 153, 8, 128, 183, 115, 156, 49, 138, 139, 12, 247, 136, 47, 181, 2, 57, 204, 217, 71, 147, 192, 92, 15, 97, 150, 92, 64, 181, 190, 137, 58, 96, 72, 73, 181, 233, 29, 2, 17, 46, 117, 160, 101, 89, 151, 127, 252, 68, 99, 185, 105, 223, 203, 210, 206, 146, 63, 64, 134, 66, 103, 195, 200, 107, 205, 47, 205, 158, 247, 89, 244, 129, 91, 80, 90, 218, 245, 109, 140, 12, 209, 170, 79, 195, 106, 74, 115, 61, 110, 232, 14, 171, 213, 15, 206, 233, 194, 102, 89, 250, 128, 14, 2, 146, 8, 115, 60, 11, 119, 215, 40, 75, 80, 10, 92, 243, 88, 161, 248, 222, 254, 112, 74, 28, 96, 181, 208, 141, 4, 84, 157, 88, 100, 104, 82, 46, 63, 167, 199, 199, 73, 145, 100, 227, 228, 150, 170, 22, 131, 224, 34, 138, 37, 160, 241, 63, 179, 190, 40, 176, 132, 126, 81, 26, 159, 66, 105, 76, 146, 105, 82, 37, 119, 81, 111, 180, 234, 142, 173, 3, 90, 201, 254, 232, 234, 252, 60, 169, 138, 116, 252, 185, 148, 128, 236, 97, 123, 143, 159, 208, 11, 242, 71, 207, 223, 5, 143, 179, 226, 222, 219, 156, 11, 205, 45, 139, 49, 22, 93, 221, 118, 159, 157, 90, 113, 230, 126, 9, 1, 156, 140, 159, 142, 111, 233, 172, 100, 16, 92, 100, 86, 90, 120, 234, 121, 234, 159, 121, 66, 169, 134, 187, 88, 175, 255, 193, 126, 104, 157, 110, 228, 58, 243, 142, 61, 6, 14, 167, 139, 32, 58, 151, 207, 103, 176, 114, 186, 221, 156, 174, 80, 252, 164, 188, 254, 184, 27, 175, 119, 211, 222, 75, 158, 165, 3, 9, 107, 26, 20, 240, 130, 44, 243, 115, 90, 254, 27, 226, 17, 161, 111, 119, 109, 190, 166, 216, 47, 60, 85, 127, 89, 235, 223, 63, 179, 221, 149, 134, 219, 109, 151, 47, 184, 158, 111, 232, 102, 141, 240, 255, 51, 77, 46, 146, 201, 110, 81, 196, 87, 63, 205, 193, 218, 221, 63, 62, 76, 210, 227, 20, 66, 46, 98, 120, 43, 154, 209, 233, 99, 223, 207, 143, 163, 208, 213, 81, 162, 130, 138, 66, 199, 231, 246, 180, 194, 96, 213, 225, 90, 55, 128, 162, 174, 178, 33, 119, 34, 252, 156, 84, 241, 248, 52, 153, 8, 92, 160, 248, 113, 130, 34, 122, 196, 239, 144, 90, 33, 234, 123, 71, 137, 169, 174, 164, 84, 20, 234, 172, 106, 32, 168, 169, 156, 25, 161, 229, 149, 81, 2, 238, 32, 122, 128, 3, 77, 240, 61, 79, 226, 230, 233, 45, 123, 183, 97, 183, 18, 253, 199, 56, 226, 113, 144, 67, 32, 250, 211, 60, 118, 138, 6, 33, 194, 6, 246, 25, 190, 151, 23, 88, 33, 198, 17, 21, 90, 160, 43, 5, 133, 108, 152, 135, 58, 38, 2, 113, 112, 136, 92, 86, 206, 139, 4, 16, 17, 5, 65, 114, 112, 141, 184, 56, 193, 65, 66, 230, 182, 9, 153, 96, 193, 212, 228, 47, 85, 247, 2, 237, 67, 145, 29, 52, 218, 170, 203, 238, 244, 4, 147, 147, 129, 237, 157, 163, 98, 21, 33, 210, 171, 163, 11, 76, 78, 180, 203, 6, 172, 231, 10, 77, 189, 245, 169, 229, 111, 44, 14, 224, 192, 238, 216, 216, 20, 84, 227, 60, 110, 58, 173, 143, 128, 195, 117, 168, 134, 92, 120, 63, 148, 206, 241, 99, 156, 201, 193, 179, 209, 218, 203, 121, 185, 111, 202, 232, 27, 132, 209, 55, 209, 76, 222, 191, 75, 237, 59, 62, 21, 178, 239, 158, 235, 73, 100, 140, 4, 186, 160, 196, 147, 115, 195, 78, 148, 214, 186, 67, 251, 132, 176, 14, 156, 82, 149, 245, 109, 185, 13, 229, 49, 171, 222, 223, 254, 38, 145, 212, 189, 139, 196, 94, 178, 32, 0, 234, 191, 59, 208, 76, 107, 167, 147, 184, 74, 44, 28, 93, 118, 198, 27, 219, 226, 131, 85, 197, 104, 254, 0, 99, 171, 190, 83, 214, 198, 25, 38, 156, 235, 91, 130, 77, 64, 233, 96, 217, 191, 199, 182, 98, 161, 149, 131, 154, 5, 155, 13, 54, 134, 158, 81, 248, 126, 123, 43, 36, 53, 34, 92, 6, 20, 133, 60, 108, 129, 6, 129, 30, 254, 23, 243, 244, 133, 169, 26, 213, 92, 160, 202, 177, 193, 160, 252, 47, 244, 173, 110, 188, 87, 158, 33, 38, 13, 154, 179, 51, 252, 172, 110, 144, 172, 178, 39, 110, 93, 126, 46, 38, 129, 35, 152, 52, 107, 153, 67, 174, 161, 234, 186, 57, 237, 138, 148, 57, 1, 220, 72, 87, 57, 178, 132, 174, 106, 126, 123, 127, 85, 37, 7, 199, 199, 220, 250, 186, 105, 90, 203, 54, 197, 179, 105, 119, 209, 113, 232, 78, 253, 133, 168, 199, 204, 2, 145, 241, 167, 29, 25, 63, 53, 249, 110, 15, 201, 212, 244, 103, 203, 115, 114, 153, 156, 207, 166, 177, 71, 152, 225, 222, 233, 218, 233, 83, 85, 197, 168, 212, 104, 142, 61, 221, 68, 91, 20, 229, 152, 50, 232, 26, 203, 21, 76, 105, 202, 166, 146, 73, 111, 160, 3, 18, 143, 189, 90, 193, 108, 219, 41, 155, 99, 91, 244, 238, 38, 250, 100, 163, 225, 237, 92, 168, 83, 176, 206, 53, 113, 155, 182, 19, 163, 201, 204, 60, 104, 197, 237, 7, 184, 7, 2, 111, 254, 25, 135, 17, 110, 7, 17, 252, 144, 20, 87, 40, 48, 53, 186, 14, 166, 237, 167, 20, 227, 189, 104, 200, 41, 98, 27, 122, 223, 241, 211, 219, 189, 255, 50, 16, 255, 107, 115, 166, 114, 254, 109, 38, 208, 155, 158, 109, 64, 222, 80, 32, 180, 137, 38, 119, 251, 240, 52, 26, 178, 229, 37, 77, 45, 18, 161, 136, 80, 226, 166, 59, 139, 120, 54, 145, 51, 49, 157, 178, 7, 154, 63, 228, 76, 38, 161, 143, 14, 142, 206, 222, 26, 255, 76, 149, 148, 38, 143, 97, 235, 104, 227, 51, 153, 112, 248, 204, 56, 123, 56, 149, 12, 180, 5, 92, 120, 163, 154, 99, 194, 22, 171, 225, 224, 97, 243, 233, 57, 51, 192, 97, 78, 186, 39, 108, 120, 204, 187, 243, 169, 248, 240, 205, 194, 28, 40, 92, 77, 51, 25, 113, 244, 238, 69, 90, 162, 144, 163, 113, 60, 99, 131, 204, 143, 103, 111, 93, 147, 93, 67, 62, 52, 204, 161, 111, 44, 222, 52, 108, 8, 24, 30, 41, 108, 214, 215, 193, 65, 39, 74, 82, 158, 132, 182, 119, 189, 74, 223, 158, 95, 15, 6, 186, 115, 150, 191, 92, 244, 12, 236, 90, 85, 128, 253, 50, 221, 219, 61, 202, 120, 235, 128, 80, 102, 167, 155, 219, 109, 47, 9, 130, 221, 67, 162, 144, 77, 250, 51, 214, 114, 10, 151, 235, 220, 117, 57, 200, 38, 97, 41, 208, 157, 236, 34, 4, 168, 210, 45, 209, 197, 33, 230, 214, 152, 134, 180, 175, 163, 104, 125, 92, 45, 63, 33, 100, 219, 51, 25, 79, 144, 20, 96, 49, 113, 169, 237, 93, 225, 51, 73, 39, 198, 110, 242, 105, 75, 239, 187, 212, 176, 30, 239, 99, 195, 217, 168, 187, 198, 132, 93, 184, 13, 120, 52, 200, 107, 94, 54, 219, 24, 118, 227, 47, 117, 183, 178, 143, 201, 156, 243, 119, 183, 156, 199, 148, 46, 51, 0, 49, 59, 201, 131, 118, 247, 200, 180, 108, 109, 50, 34, 54, 178, 166, 188, 69, 180, 146, 32, 164, 159, 103, 126, 77, 174, 62, 255, 82, 41, 232, 225, 123, 25, 207, 238, 30, 55, 7, 212, 227, 121, 60, 187, 27, 230, 105, 107, 139, 78, 185, 23, 219, 206, 228, 231, 156, 222, 106, 58, 111, 97, 157, 90, 98, 0, 214, 224, 25, 88, 131, 8, 208, 226, 22, 33, 227, 45, 191, 72, 28, 38, 147, 249, 56, 185, 55, 124, 87, 240, 238, 124, 10, 214, 83, 46, 106, 142, 44, 236, 202, 53, 228, 33, 181, 251, 177, 77, 152, 248, 44, 66, 247, 201, 196, 227, 241, 252, 124, 62, 149, 57, 232, 90, 243, 54, 99, 32, 182, 122, 209, 60, 234, 103, 77, 10, 187, 230, 94, 22, 247, 124, 184, 115, 35, 11, 130, 165, 94, 113, 38, 86, 235, 42, 253, 146, 154, 72, 146, 123, 81, 237, 128, 66, 20, 188, 121, 152, 158, 156, 86, 119, 135, 65, 187, 155, 146, 133, 233, 230, 39, 59, 104, 191, 124, 238, 5, 104, 27, 34, 159, 228, 245, 120, 120, 99, 131, 242, 240, 83, 161, 102, 55, 54, 238, 34, 11, 143, 188, 57, 115, 219, 4, 155, 173, 146, 237, 208, 3, 123, 31, 55, 20, 90, 214, 176, 123, 207, 122, 98, 174, 143, 2, 164, 228, 15, 200, 76, 173, 216, 212, 194, 222, 226, 201, 192, 86, 172, 45, 94, 1, 121, 18, 65, 221, 140, 98, 233, 135, 164, 41, 91, 239, 153, 76, 132, 75, 203, 55, 164, 221, 37, 133, 195, 185, 119, 173, 98, 56, 83, 174, 250, 116, 141, 52, 247, 22, 226, 50, 141, 111, 27, 180, 101, 70, 223, 122, 164, 157, 228, 190, 99, 153, 249, 209, 205, 87, 207, 68, 242, 12, 167, 203, 108, 239, 192, 34, 201, 112, 69, 3, 79, 141, 210, 227, 33, 14, 192, 29, 19, 2, 240, 167, 180, 186, 72, 203, 68, 112, 61, 131, 178, 203, 13, 26, 3, 75, 178, 186, 168, 105, 214, 140, 146, 104, 158, 244, 252, 3, 31, 35, 233, 157, 117, 227, 83, 147, 47, 100, 128, 32, 76, 124, 188, 58, 222, 161, 223, 61, 202, 132, 115, 207, 204, 147, 240, 207, 27, 62, 182, 27, 18, 231, 252, 252, 254, 216, 74, 37, 235, 204, 125, 90, 112, 126, 170, 189, 140, 154, 173, 12, 147, 235, 213, 98, 40, 185, 199, 209, 214, 92, 7, 62, 243, 219, 235, 111, 242, 23, 57, 67, 86, 221, 207, 59, 229, 63, 32, 216, 8, 37, 3, 201, 103, 80, 137, 188, 52, 140, 26, 203, 109, 246, 182, 204, 106, 2, 236, 218, 51, 44, 13, 202, 211, 118, 134, 53, 133, 153, 52, 168, 66, 113, 22, 101, 245, 108, 170, 110, 16, 228, 32, 100, 40, 173, 14, 10, 35, 23, 185, 172, 168, 41, 222, 30, 75, 12, 105, 179, 34, 244, 26, 144, 102, 200, 181, 190, 232, 22, 152, 168, 55, 232, 57, 76, 55, 244, 51, 221, 33, 191, 224, 79, 213, 53, 28, 7, 241, 171, 118, 111, 176, 71, 151, 124, 247, 39, 206, 24, 179, 126, 165, 25, 102, 40, 157, 238, 228, 144, 164, 69, 245, 17, 1, 193, 119, 104, 128, 190, 173, 217, 38, 205, 97, 72, 243, 205, 223, 243, 78, 244, 223, 39, 39, 105, 102, 217, 50, 109, 146, 80, 175, 6, 195, 187, 174, 107, 209, 224, 152, 121, 129, 93, 189, 81, 35, 123, 226, 137, 159, 111, 19, 113, 170, 98, 206, 106, 194, 116, 53, 24, 52, 49, 210, 128, 53, 29, 37, 88, 140, 245, 181, 33, 182, 20, 253, 79, 82, 228, 7, 217, 193, 188, 58, 56, 254, 137, 77, 160, 147, 82, 215, 150, 53, 127, 210, 209, 1, 180, 41, 253, 154, 84, 80, 198, 195, 79, 64, 33, 98, 117, 113, 154, 233, 114, 252, 151, 204, 17, 76, 172, 24, 81, 49, 104, 199, 152, 174, 172, 211, 42, 205, 246, 140, 44, 166, 33, 104, 92, 18, 193, 164, 42, 159, 139, 217, 233, 53, 239, 73, 31, 57, 238, 132, 44, 148, 76, 235, 184, 119, 223, 98, 240, 106, 68, 93, 115, 143, 173, 141, 76, 195, 251, 229, 238, 188, 82, 217, 159, 61, 60, 220, 45, 218, 4, 254, 65, 150, 22, 197, 187, 40, 112, 41, 178, 251, 226, 50, 107, 179, 157, 106, 134, 36, 100, 173, 38, 210, 197, 222, 197, 96, 245, 13, 116, 123, 179, 213, 29, 228, 44, 185, 240, 92, 157, 35, 110, 203, 17, 200, 109, 160, 97, 179, 18, 230, 183, 138, 89, 66, 84, 38, 193, 97, 148, 194, 226, 165, 198, 102, 37, 28, 192, 188, 91, 137, 188, 239, 183, 69, 1, 34, 30, 226, 120, 121, 148, 222, 174, 237, 90, 104, 136, 168, 173, 89, 200, 249, 148, 138, 202, 41, 110, 184, 140, 166, 167, 63, 83, 100, 161, 21, 158, 34, 163, 0, 230, 88, 242, 149, 99, 138, 15, 174, 40, 47, 195, 186, 167, 156, 4, 127, 198, 175, 75, 97, 196, 230, 110, 3, 88, 34, 81, 18, 19, 155, 18, 205, 122, 172, 79, 124, 118, 110, 107, 159, 237, 86, 126, 235, 12, 246, 172, 224, 98, 220, 59, 179, 241, 217, 98, 131, 29, 250, 115, 7, 55, 217, 149, 63, 202, 231, 65, 186, 131, 59, 237, 48, 10, 245, 60, 247, 159, 176, 227, 174, 251, 121, 87, 119, 221, 235, 184, 242, 118, 109, 189, 107, 82, 99, 174, 251, 202, 148, 225, 28, 254, 249, 119, 83, 135, 107, 254, 12, 165, 54, 162, 76, 199, 137, 35, 160, 61, 191, 20, 141, 248, 69, 34, 252, 84, 112, 153, 207, 139, 49, 35, 246, 121, 60, 59, 206, 232, 202, 186, 54, 193, 239, 158, 107, 2, 224, 120, 224, 189, 32, 47, 62, 212, 137, 141, 247, 8, 231, 193, 206, 159, 188, 160, 13, 224, 9, 124, 188, 23, 182, 218, 252, 207, 139, 34, 206, 104, 226, 254, 161, 236, 45, 189, 135, 67, 182, 31, 153, 59, 108, 200, 124, 108, 62, 59, 167, 7, 223, 72, 82, 48, 216, 74, 157, 204, 75, 116, 155, 11, 152, 122, 156, 202, 158, 227, 81, 250, 38, 39, 115, 62, 138, 214, 93, 181, 237, 115, 247, 51, 94, 141, 217, 180, 33, 165, 195, 52, 250, 203, 208, 213, 16, 2, 103, 74, 36, 14, 94, 145, 194, 58, 156, 71, 135, 95, 222, 141, 44, 47, 15, 150, 160, 200, 249, 35, 249, 24, 217, 196, 98, 61, 114, 24, 90, 93, 216, 12, 255, 136, 101, 41, 33, 227, 239, 68, 106, 252, 55, 152, 203, 178, 216, 97, 26, 48, 17, 37, 252, 29, 93, 174, 198, 86, 244, 150, 173, 64, 235, 192, 233, 249, 186, 195, 30, 123, 131, 104, 207, 56, 185, 197, 191, 54, 78, 64, 241, 79, 55, 33, 182, 208, 37, 175, 157, 189, 53, 176, 62, 234, 39, 229, 186, 83, 85, 168, 99, 184, 121, 96, 130, 99, 242, 58, 30, 159, 45, 125, 80, 58, 18, 80, 180, 139, 47, 41, 146, 204, 110, 150, 180, 89, 202, 211, 9, 96, 108, 117, 3, 154, 229, 119, 90, 146, 203, 74, 46, 2, 62, 200, 125, 153, 119, 253, 77, 206, 227, 127, 149, 118, 165, 98, 104, 28, 103, 130, 147, 68, 109, 116, 61, 151, 219, 115, 36, 102, 254, 3, 46, 18, 104, 59, 174, 33, 38, 161, 104, 29, 241, 139, 27, 208, 33, 37, 94, 147, 229, 71, 175, 43, 146, 43, 85, 26, 123, 188, 166, 171, 60, 34, 102, 162, 195, 180, 86, 220, 135, 162, 173, 143, 254, 74, 237, 114, 191, 214, 139, 244, 76, 100, 191, 165, 154, 198, 90, 213, 41, 39, 134, 174, 130, 121, 100, 49, 82, 119, 246, 209, 235, 182, 137, 175, 190, 142, 206, 157, 169, 76, 105, 92, 79, 97, 124, 240, 192, 80, 215, 239, 13, 229, 214, 194, 193, 113, 31, 89, 217, 130, 176, 238, 117, 173, 55, 101, 29, 100, 201, 197, 178, 71, 71, 128, 20, 196, 193, 70, 237, 153, 237, 37, 22, 5, 9, 113, 208, 4, 213, 49, 153, 188, 83, 177, 38, 167, 188, 73, 161, 64, 181, 10, 100, 20, 103, 245, 206, 185, 131, 196, 58, 74, 142, 238, 115, 244, 114, 15, 175, 51, 224, 217, 205, 205, 85, 196, 198, 127, 147, 218, 166, 130, 109, 40, 60, 176, 134, 229, 82, 38, 119, 97, 237, 169, 186, 36, 169, 153, 214, 140, 71, 111, 53, 138, 106, 19, 51, 144, 19, 42, 19, 57, 210, 66, 142, 254, 151, 166, 11, 88, 157, 210, 126, 88, 25, 56, 236, 94, 64, 106, 109, 40, 210, 115, 172, 27, 120, 187, 217, 144, 78, 234, 103, 110, 141, 253, 28, 87, 241, 107, 121, 96, 92, 103, 92, 73, 215, 215, 197, 150, 195, 166, 73, 27, 136, 88, 73, 20, 163, 172, 132, 204, 141, 142, 188, 228, 214, 108, 195, 76, 95, 141, 78, 227, 130, 88, 57, 93, 239, 67, 8, 212, 111, 211, 184, 45, 190, 35, 6, 17, 222, 5, 14, 132, 154, 12, 9, 70, 123, 48, 214, 8, 230, 7, 232, 120, 54, 212, 119, 170, 60, 160, 4, 223, 228, 163, 188, 168, 146, 73, 159, 223, 79, 83, 36, 199, 153, 57, 228, 175, 95, 181, 91, 175, 24, 8, 237, 215, 44, 176, 219, 108, 170, 209, 53, 239, 167, 241, 122, 184, 1, 21, 214, 8, 118, 12, 27, 149, 1, 159, 202, 33, 133, 227, 180, 158, 154, 80, 44, 39, 109, 142, 105, 254, 93, 153, 67, 52, 203, 46, 166, 140, 37, 110, 52, 178, 225, 95, 76, 140, 95, 198, 179, 230, 235, 124, 216, 84, 137, 200, 201, 109, 13, 121, 157, 15, 251, 2, 73, 137, 240, 180, 22, 47, 239, 58, 31, 166, 230, 207, 219, 221, 230, 227, 42, 59, 168, 27, 230, 167, 135, 223, 49, 225, 148, 253, 167, 58, 207, 167, 101, 229, 189, 64, 172, 179, 3, 141, 23, 191, 85, 66, 255, 24, 170, 251, 40, 45, 242, 142, 254, 83, 111, 75, 250, 255, 46, 4, 227, 16 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 20960; + return 19520; } uint32_t GetRawScriptsSize() { - return 144873; + return 134068; } } // selfhosted } // js diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src16.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src16.cpp index b5ffc558d11..b9f0515432d 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src16.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src16.cpp @@ -17,6 +17,15 @@ #error "vm/List.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "vm/Logging.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Logging.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Logging.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "vm/MemoryMetrics.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/MemoryMetrics.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/NativeObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/OffThreadPromiseRuntimeState.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src17.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src17.cpp index b08f1106daf..94b6d38fd92 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src17.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src17.cpp @@ -1,11 +1,20 @@ #define MOZ_UNIFIED_BUILD -#include "vm/PIC.cpp" +#include "vm/ObjectWithStashedPointer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "vm/PIC.cpp defines INITGUID, so it cannot be built in unified mode." +#error "vm/ObjectWithStashedPointer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "vm/OffThreadPromiseRuntimeState.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/OffThreadPromiseRuntimeState.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/OffThreadPromiseRuntimeState.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "vm/PlainObject.cpp" @@ -43,13 +52,4 @@ #ifdef INITGUID #error "vm/Probes.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "vm/PromiseLookup.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/PromiseLookup.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/PromiseLookup.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src21.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src21.cpp index 68b2f38047e..ea91f9b7a92 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src21.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src21.cpp @@ -17,15 +17,6 @@ #error "vm/StaticStrings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "vm/StencilCache.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/StencilCache.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/StencilCache.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/StencilObject.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/StencilObject.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/StructuredClone.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/SymbolType.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src22.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src22.cpp index 2f680d9080d..ff0a99efa9d 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src22.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src22.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/SymbolType.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/SymbolType.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/SymbolType.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/TaggedProto.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/TaggedProto.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/TypedArrayObject.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/UbiNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src23.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src23.cpp index b098329bf76..7479e005cf5 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src23.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src23.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/UbiNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/UbiNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/UbiNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/UbiNodeCensus.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/UbiNodeCensus.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "vm/Warnings.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "vm/Watchtower.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src24.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src24.cpp index a9cdcfb101b..67114f2db8d 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src24.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/Unified_cpp_js_src24.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "vm/Watchtower.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "vm/Watchtower.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "vm/Watchtower.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "vm/WellKnownAtom.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "vm/WellKnownAtom.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend1.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend1.cpp index 28e5df3a03a..5741f07fe09 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend1.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend1.cpp @@ -17,15 +17,6 @@ #error "frontend/CallOrNewEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "frontend/CompileScript.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/CompileScript.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/CompileScript.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/DefaultEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/DefaultEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ElemOpEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/EmitterScope.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend2.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend2.cpp index eb4c6de5412..934b87e3f3e 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend2.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend2.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/EmitterScope.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/EmitterScope.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/EmitterScope.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ExpressionStatementEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ExpressionStatementEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ForOfLoopControl.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/FrontendContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend3.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend3.cpp index 8657ff80ca7..d1ade59a71b 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend3.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend3.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/FrontendContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/FrontendContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/FrontendContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/FunctionEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/FunctionEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/LexicalScopeEmitter.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/NameFunctions.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend4.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend4.cpp index 24033ca6ae5..0b31d7b0f9d 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend4.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend4.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/NameFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/NameFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/NameFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/NameOpEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/NameOpEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/ParseContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/ParseNode.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend5.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend5.cpp index 40037b65315..d20f40b41d9 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend5.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend5.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/ParseNode.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/ParseNode.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/ParseNode.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/ParseNodeVerify.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/ParseNodeVerify.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/SharedContext.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/SourceNotes.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend6.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend6.cpp index 01dbab94a0c..8ee8ed4cd88 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend6.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend6.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/SourceNotes.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/SourceNotes.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/SourceNotes.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/Stencil.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/Stencil.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -52,4 +43,13 @@ #ifdef INITGUID #error "frontend/TokenStream.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID +#endif +#include "frontend/TryEmitter.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend7.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend7.cpp index 90b23b751e9..9d4a6fd7113 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend7.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/frontend/Unified_cpp_js_src_frontend7.cpp @@ -1,13 +1,4 @@ #define MOZ_UNIFIED_BUILD -#include "frontend/TryEmitter.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "frontend/TryEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "frontend/TryEmitter.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif #include "frontend/WhileEmitter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "frontend/WhileEmitter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc0.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc0.cpp index d3a729cf6b9..d9b29bb8842 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc0.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc0.cpp @@ -26,6 +26,15 @@ #error "gc/Barrier.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "gc/BufferAllocator.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/BufferAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/BufferAllocator.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/Compacting.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/Compacting.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/FinalizationObservers.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/GC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc1.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc1.cpp index 1277307139f..6dca73d1db2 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc1.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/gc/Unified_cpp_js_src_gc1.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "gc/GC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "gc/GC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "gc/GC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "gc/GCAPI.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "gc/GCAPI.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "gc/Marking.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "gc/Memory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "gc/Memory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "gc/Memory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit1.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit1.cpp index b6f46e4aad1..46b4dc09b71 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit1.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit1.cpp @@ -8,6 +8,15 @@ #error "jit/BaselineCodeGen.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "jit/BaselineCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BaselineDebugModeOSR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BaselineDebugModeOSR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "jit/BaselineIC.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/BaselineJIT.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit10.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit10.cpp index 53b64d16ecd..2bf8da0115b 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit10.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit10.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/PerfSpewer.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ProcessExecutableMemory.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/RangeAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ReciprocalMulConstants.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Recover.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Recover.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/RegisterAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/RematerializedFrame.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/SafepointIndex.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Safepoints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ScalarReplacement.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit11.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit11.cpp index c1d3d2b467d..14ab782f391 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit11.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit11.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/RematerializedFrame.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/RematerializedFrame.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/RematerializedFrame.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/SafepointIndex.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/SafepointIndex.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/SafepointIndex.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Safepoints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Safepoints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Safepoints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/ScalarReplacement.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/ScalarReplacement.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/ScalarReplacement.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ShuffleAnalysis.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ShuffleAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -8,48 +44,12 @@ #error "jit/ShuffleAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/Sink.cpp" +#include "jit/SimpleAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Snapshots.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/Trampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrampolineNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/TrialInlining.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/SimpleAllocator.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit12.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit12.cpp index 66e87e19520..f7408c70b9d 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit12.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit12.cpp @@ -1,4 +1,49 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Sink.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Sink.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Sink.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Snapshots.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Snapshots.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Snapshots.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/Trampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Trampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Trampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrampolineNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrampolineNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrampolineNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/TrialInlining.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/TrialInlining.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/TrialInlining.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/TypePolicy.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/TypePolicy.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -7,49 +52,4 @@ #ifdef INITGUID #error "jit/TypePolicy.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/VMFunctions.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ValueNumbering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilder.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpBuilderShared.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/WarpCacheIRTranspiler.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit13.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit13.cpp index 5cfa680afa4..333eadfd8f5 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit13.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit13.cpp @@ -1,55 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/WarpOracle.cpp" +#include "jit/UnrollLoops.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/UnrollLoops.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WarpSnapshot.cpp" +#include "jit/VMFunctions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/VMFunctions.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/WasmBCE.cpp" +#include "jit/ValueNumbering.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/ValueNumbering.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/XrayJitInfo.cpp" +#include "jit/WarpBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/none/Trampoline-none.cpp" +#include "jit/WarpBuilderShared.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpBuilderShared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Assembler-shared.cpp" +#include "jit/WarpCacheIRTranspiler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpCacheIRTranspiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit14.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit14.cpp index 8124f7f3c88..5cfa680afa4 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit14.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit14.cpp @@ -1,37 +1,55 @@ #define MOZ_UNIFIED_BUILD -#include "jit/shared/AtomicOperations-shared-jit.cpp" +#include "jit/WarpOracle.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpOracle.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/CodeGenerator-shared.cpp" +#include "jit/WarpSnapshot.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WarpSnapshot.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Disassembler-shared.cpp" +#include "jit/WasmBCE.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/WasmBCE.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/shared/Lowering-shared.cpp" +#include "jit/XrayJitInfo.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/XrayJitInfo.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/none/Trampoline-none.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/none/Trampoline-none.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/none/Trampoline-none.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Assembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Assembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Assembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit15.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit15.cpp new file mode 100644 index 00000000000..8124f7f3c88 --- /dev/null +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit15.cpp @@ -0,0 +1,37 @@ +#define MOZ_UNIFIED_BUILD +#include "jit/shared/AtomicOperations-shared-jit.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/AtomicOperations-shared-jit.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/AtomicOperations-shared-jit.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/CodeGenerator-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/CodeGenerator-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/CodeGenerator-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Disassembler-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Disassembler-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Disassembler-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/shared/Lowering-shared.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/shared/Lowering-shared.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/shared/Lowering-shared.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit2.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit2.cpp index 4ea3da2354e..3a5aa3d53f9 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit2.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit2.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "jit/BaselineJIT.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/BaselineJIT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/BaselineJIT.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/BitSet.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/BitSet.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -35,21 +44,12 @@ #error "jit/CacheIR.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "jit/CacheIRCompiler.cpp" +#include "jit/CacheIRAOT.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/CacheIRHealth.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#error "jit/CacheIRAOT.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit3.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit3.cpp index df8a8463d6b..edac4eb0663 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit3.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit3.cpp @@ -1,4 +1,22 @@ #define MOZ_UNIFIED_BUILD +#include "jit/CacheIRCompiler.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRCompiler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/CacheIRHealth.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/CacheIRHealth.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/CacheIRHealth.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/CacheIRSpewer.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/CacheIRSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -34,22 +52,4 @@ #ifdef INITGUID #error "jit/Disassemble.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/EdgeCaseAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/EffectiveAddressAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit4.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit4.cpp index a0de0def80c..ef46e97c1d6 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit4.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit4.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/DominatorTree.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/DominatorTree.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/DominatorTree.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EdgeCaseAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EdgeCaseAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EdgeCaseAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/EffectiveAddressAnalysis.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/EffectiveAddressAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/EffectiveAddressAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/ExecutableAllocator.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/ExecutableAllocator.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/FoldLinearArithConstants.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/InlinableNatives.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InstructionReordering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/InterpreterEntryTrampoline.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit5.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit5.cpp index 16e082b4b0d..8c218716c03 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit5.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit5.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/InlinableNatives.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InlinableNatives.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InlinableNatives.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InstructionReordering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InstructionReordering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InstructionReordering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/InterpreterEntryTrampoline.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/InterpreterEntryTrampoline.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/InterpreterEntryTrampoline.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/Ion.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/Ion.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/IonCacheIRCompiler.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/IonCompileTask.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonIC.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/IonOptimizationLevels.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit6.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit6.cpp index 6d22553a5ec..d332435bdb0 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit6.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit6.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/IonCompileTask.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonCompileTask.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonCompileTask.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonIC.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonIC.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonIC.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/IonOptimizationLevels.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/IonOptimizationLevels.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/IonOptimizationLevels.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JSJitFrameIter.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JSJitFrameIter.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Jit.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitContext.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitFrames.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/JitHints.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit7.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit7.cpp index 3aa269e01f8..efa541f30ed 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit7.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit7.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitContext.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitContext.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitContext.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitFrames.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitFrames.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitFrames.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/JitHints.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitHints.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitHints.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/JitOptions.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/JitOptions.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/JitSpewer.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/JitcodeMap.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/KnownClass.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/LICM.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit8.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit8.cpp index 39b6451fdb3..444ec796c50 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit8.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit8.cpp @@ -1,4 +1,31 @@ #define MOZ_UNIFIED_BUILD +#include "jit/JitcodeMap.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/JitcodeMap.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/JitcodeMap.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/KnownClass.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/KnownClass.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/KnownClass.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/LICM.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/LICM.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/LICM.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/LIR.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/LIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -25,31 +52,4 @@ #ifdef INITGUID #error "jit/Linker.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/Lowering.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIR.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/MIRGraph.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit9.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit9.cpp index 08ab8fb7345..8f87047a4db 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit9.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/jit/Unified_cpp_js_src_jit9.cpp @@ -1,4 +1,40 @@ #define MOZ_UNIFIED_BUILD +#include "jit/Lowering.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/Lowering.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/Lowering.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR-wasm.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR-wasm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR-wasm.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIR.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIR.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIR.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif +#include "jit/MIRGraph.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "jit/MIRGraph.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "jit/MIRGraph.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "jit/MacroAssembler.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "jit/MacroAssembler.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -16,40 +52,4 @@ #ifdef INITGUID #error "jit/MoveResolver.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "jit/PerfSpewer.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/PerfSpewer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/PerfSpewer.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ProcessExecutableMemory.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ProcessExecutableMemory.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ProcessExecutableMemory.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/RangeAnalysis.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/RangeAnalysis.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/RangeAnalysis.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID -#endif -#include "jit/ReciprocalMulConstants.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "jit/ReciprocalMulConstants.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "jit/ReciprocalMulConstants.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/js-confdefs.h b/src/third_party/mozjs/platform/x86_64/windows/build/js-confdefs.h index 0ecd699d685..b80bd9875a7 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/js-confdefs.h +++ b/src/third_party/mozjs/platform/x86_64/windows/build/js-confdefs.h @@ -9,20 +9,24 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_CPUID_H 1 -#define HAVE_FORCEINLINE 1 #define HAVE_INTTYPES_H 1 +#define HAVE_IO_H 1 #define HAVE_LOCALECONV 1 #define HAVE_MALLOC_H 1 +#define HAVE_SEH_EXCEPTIONS 1 #define HAVE_STDINT_H 1 #define HAVE_SYS_TYPES_H 1 #define HAVE__GETC_NOLOCK 1 -#define HAVE__MSIZE 1 #define JS_64BIT 1 #define JS_CODEGEN_NONE 1 #define JS_DEFAULT_JITREPORT_GRANULARITY 3 @@ -31,12 +35,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "" #define MOZ_DLL_SUFFIX ".dll" @@ -46,6 +48,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "x86_64-msvc" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define WIN32_LEAN_AND_MEAN 1 diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/util/Unified_cpp_js_src_util1.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/util/Unified_cpp_js_src_util1.cpp index c137de15ce2..2574715b1e2 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/util/Unified_cpp_js_src_util1.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/util/Unified_cpp_js_src_util1.cpp @@ -8,13 +8,13 @@ #error "util/Printf.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif -#include "util/StringBuffer.cpp" +#include "util/StringBuilder.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK -#error "util/StringBuffer.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." #undef PL_ARENA_CONST_ALIGN_MASK #endif #ifdef INITGUID -#error "util/StringBuffer.cpp defines INITGUID, so it cannot be built in unified mode." +#error "util/StringBuilder.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif #include "util/StructuredSpewer.cpp" diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm4.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm4.cpp index 2278e8b873d..cd452f3672f 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm4.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm4.cpp @@ -8,6 +8,15 @@ #error "wasm/WasmMemory.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID #endif +#include "wasm/WasmMetadata.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmMetadata.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmMetadata.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmModule.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmModule.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmPI.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmProcess.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm5.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm5.cpp index 4e93b981aef..990f06f579e 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm5.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm5.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmProcess.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmProcess.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmProcess.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmRealm.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmRealm.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." @@ -43,13 +52,4 @@ #ifdef INITGUID #error "wasm/WasmStubs.cpp defines INITGUID, so it cannot be built in unified mode." #undef INITGUID -#endif -#include "wasm/WasmSummarizeInsn.cpp" -#ifdef PL_ARENA_CONST_ALIGN_MASK -#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." -#undef PL_ARENA_CONST_ALIGN_MASK -#endif -#ifdef INITGUID -#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." -#undef INITGUID #endif \ No newline at end of file diff --git a/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm6.cpp b/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm6.cpp index a774ef67b0c..d4baab01086 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm6.cpp +++ b/src/third_party/mozjs/platform/x86_64/windows/build/wasm/Unified_cpp_js_src_wasm6.cpp @@ -1,4 +1,13 @@ #define MOZ_UNIFIED_BUILD +#include "wasm/WasmSummarizeInsn.cpp" +#ifdef PL_ARENA_CONST_ALIGN_MASK +#error "wasm/WasmSummarizeInsn.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." +#undef PL_ARENA_CONST_ALIGN_MASK +#endif +#ifdef INITGUID +#error "wasm/WasmSummarizeInsn.cpp defines INITGUID, so it cannot be built in unified mode." +#undef INITGUID +#endif #include "wasm/WasmTable.cpp" #ifdef PL_ARENA_CONST_ALIGN_MASK #error "wasm/WasmTable.cpp uses PL_ARENA_CONST_ALIGN_MASK, so it cannot be built in unified mode." diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/gc/StatsPhasesGenerated.h b/src/third_party/mozjs/platform/x86_64/windows/include/gc/StatsPhasesGenerated.h index 2e21df04613..b5523453c55 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/gc/StatsPhasesGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/gc/StatsPhasesGenerated.h @@ -33,7 +33,7 @@ enum class PhaseKind : uint8_t { FINALIZE_START, UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -48,8 +48,6 @@ enum class PhaseKind : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, SWEEP_COMPARTMENTS, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, @@ -131,7 +129,7 @@ enum class Phase : uint8_t { UPDATE_ATOMS_BITMAP, SWEEP_ATOMS_TABLE, SWEEP_COMPARTMENTS, - SWEEP_DISCARD_CODE, + SWEEP_JIT_SCRIPTS, SWEEP_INNER_VIEWS, SWEEP_CC_WRAPPER, SWEEP_BASE_SHAPE, @@ -146,8 +144,6 @@ enum class Phase : uint8_t { SWEEP_WEAK_CACHES, SWEEP_MISC, JOIN_PARALLEL_TASKS_4, - FINALIZE_OBJECT, - FINALIZE_NON_OBJECT, SWEEP_PROP_MAP, FINALIZE_END, DESTROY, diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/jit/ABIFunctionTypeGenerated.h b/src/third_party/mozjs/platform/x86_64/windows/include/jit/ABIFunctionTypeGenerated.h index 81df398460f..ccec0f1c071 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/jit/ABIFunctionTypeGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/jit/ABIFunctionTypeGenerated.h @@ -21,7 +21,11 @@ Args_Double_None = detail::MakeABIFunctionType(ABIType::Float64, {}),\ Args_Int_Double = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float64}),\ Args_Int_Float32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::Float32}),\ + Args_Int32_Float32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::Float32}),\ Args_Float32_Float32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float32}),\ + Args_Float32_Float64 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Float64}),\ + Args_Float32_General = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General}),\ + Args_Float32_Int32 = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::Int32}),\ Args_Float32_IntInt = detail::MakeABIFunctionType(ABIType::Float32, {ABIType::General, ABIType::General}),\ Args_Double_Double = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::Float64}),\ Args_Double_Int = detail::MakeABIFunctionType(ABIType::Float64, {ABIType::General}),\ @@ -41,16 +45,21 @@ Args_General_GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32}),\ Args_General_GeneralInt32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_General_GeneralInt32Int32General = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General}),\ Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ + Args_General_GeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_General_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::General, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ Args_Int32_General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General}),\ Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General}),\ + Args_Int32_GeneralGeneralGeneralGeneral = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::General}),\ Args_Int32_GeneralGeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General}),\ Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ + Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32}),\ Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General = detail::MakeABIFunctionType(ABIType::Int32, {ABIType::General, ABIType::Int32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Float32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::Int32, ABIType::General}),\ @@ -84,6 +93,8 @@ Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int32}),\ Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64}),\ Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(ABIType::Int64, {ABIType::General, ABIType::Int64, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32}),\ + Args_Void_GeneralInt32GeneralInt32Int32Int32 = detail::MakeABIFunctionType(ABIType::Void, {ABIType::General, ABIType::Int32, ABIType::General, ABIType::Int32, ABIType::Int32, ABIType::Int32}),\ #define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \ typedef intptr_t (*Prototype_General0)();\ @@ -99,7 +110,11 @@ typedef double (*Prototype_Double_None)();\ typedef intptr_t (*Prototype_Int_Double)(double);\ typedef intptr_t (*Prototype_Int_Float32)(float);\ + typedef int32_t (*Prototype_Int32_Float32)(float);\ typedef float (*Prototype_Float32_Float32)(float);\ + typedef float (*Prototype_Float32_Float64)(double);\ + typedef float (*Prototype_Float32_General)(intptr_t);\ + typedef float (*Prototype_Float32_Int32)(int32_t);\ typedef float (*Prototype_Float32_IntInt)(intptr_t, intptr_t);\ typedef double (*Prototype_Double_Double)(double);\ typedef double (*Prototype_Double_Int)(intptr_t);\ @@ -119,16 +134,21 @@ typedef intptr_t (*Prototype_General_GeneralInt32)(intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralInt32General)(intptr_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32)(intptr_t, int32_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32General)(intptr_t, int32_t, int32_t, intptr_t);\ typedef intptr_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(intptr_t, int32_t, int32_t, intptr_t, int32_t);\ + typedef intptr_t (*Prototype_General_GeneralInt32Int32Int32GeneralInt32)(intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef intptr_t (*Prototype_General_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_General)(intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneral)(intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralGeneral)(intptr_t, intptr_t, intptr_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralGeneralInt32)(intptr_t, intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32)(intptr_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(intptr_t, intptr_t, int32_t, intptr_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(intptr_t, intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(intptr_t, intptr_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t);\ + typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32Int32Int32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, int32_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(intptr_t, intptr_t, int32_t, int32_t, int32_t, intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32)(intptr_t, int32_t);\ typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(intptr_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t, int32_t, intptr_t);\ @@ -162,6 +182,8 @@ typedef int64_t (*Prototype_Int64_GeneralInt32)(intptr_t, int32_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64)(intptr_t, int64_t);\ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(intptr_t, int64_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t);\ + typedef void (*Prototype_Void_GeneralInt32GeneralInt32Int32Int32)(intptr_t, int32_t, intptr_t, int32_t, int32_t, int32_t);\ #define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -242,12 +264,36 @@ case js::jit::Args_Int_Float32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(s0);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(s0);\ setFP32Result(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(d0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0);\ + setFP32Result(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1);\ @@ -362,12 +408,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4);\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR64Result(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -392,6 +450,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3);\ @@ -422,6 +486,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setGPR32Result(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5);\ + setGPR32Result(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ + setGPR32Result(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(x0, x1, x2, x3, x4, x5, x6);\ @@ -620,6 +696,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setGPR64Result(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(x0, x1, x2, x3, x4, x5);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -697,7 +783,7 @@ case js::jit::Args_General8: {\ case js::jit::Args_Int64_Double: {\ auto target = reinterpret_cast(external);\ int64_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -717,7 +803,7 @@ case js::jit::Args_Double_None: {\ case js::jit::Args_Int_Double: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -729,7 +815,19 @@ case js::jit::Args_Int_Double: {\ case js::jit::Args_Int_Float32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(s0);\ + } else {\ + ret = target(mozilla::BitwiseCast(a0));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -741,7 +839,7 @@ case js::jit::Args_Int_Float32: {\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0);\ } else {\ ret = target(mozilla::BitwiseCast(a0));\ @@ -750,6 +848,34 @@ case js::jit::Args_Float32_Float32: {\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + if (ARMFlags::UseHardFpABI()) {\ + ret = target(d0);\ + } else {\ + ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ + }\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(external);\ + float ret;\ + ret = target(a0);\ + scratchVolatileRegisters((void*)target);\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(external);\ float ret;\ @@ -761,7 +887,7 @@ case js::jit::Args_Float32_IntInt: {\ case js::jit::Args_Double_Double: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)));\ @@ -789,7 +915,7 @@ case js::jit::Args_Double_IntInt: {\ case js::jit::Args_Double_DoubleInt: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -801,7 +927,7 @@ case js::jit::Args_Double_DoubleInt: {\ case js::jit::Args_Double_DoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -813,7 +939,7 @@ case js::jit::Args_Double_DoubleDouble: {\ case js::jit::Args_Float32_Float32Float32: {\ auto target = reinterpret_cast(external);\ float ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(s0, s1);\ } else {\ ret = target(mozilla::BitwiseCast(a0), mozilla::BitwiseCast(a1));\ @@ -825,7 +951,7 @@ case js::jit::Args_Float32_Float32Float32: {\ case js::jit::Args_Double_IntDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -837,7 +963,7 @@ case js::jit::Args_Double_IntDouble: {\ case js::jit::Args_Int_IntDouble: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)));\ @@ -849,7 +975,7 @@ case js::jit::Args_Int_IntDouble: {\ case js::jit::Args_Int_DoubleInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2);\ @@ -861,7 +987,7 @@ case js::jit::Args_Int_DoubleInt: {\ case js::jit::Args_Double_DoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])));\ @@ -873,7 +999,7 @@ case js::jit::Args_Double_DoubleDoubleDouble: {\ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ auto target = reinterpret_cast(external);\ double ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, d1, d2, d3);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), mozilla::BitwiseCast(MakeInt64(a2, a3)), mozilla::BitwiseCast(MakeInt64(stack_pointer[0], stack_pointer[1])), mozilla::BitwiseCast(MakeInt64(stack_pointer[2], stack_pointer[3])));\ @@ -885,7 +1011,7 @@ case js::jit::Args_Double_DoubleDoubleDoubleDouble: {\ case js::jit::Args_Int_DoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(d0, a0, a1);\ } else {\ ret = target(mozilla::BitwiseCast(MakeInt64(a0, a1)), a2, a3);\ @@ -897,7 +1023,7 @@ case js::jit::Args_Int_DoubleIntInt: {\ case js::jit::Args_Int_IntDoubleIntInt: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, d0, a1, a2);\ } else {\ ret = target(a0, mozilla::BitwiseCast(MakeInt64(a2, a3)), stack_pointer[0], stack_pointer[1]);\ @@ -946,6 +1072,14 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -954,6 +1088,14 @@ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(external);\ + intptr_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(external);\ intptr_t ret;\ @@ -986,6 +1128,14 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1026,6 +1176,22 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + int32_t ret;\ + ret = target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ + scratchVolatileRegisters((void*)target);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ @@ -1045,7 +1211,7 @@ case js::jit::Args_Int32_GeneralInt32: {\ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, s2, s3, a2, a3, stack_pointer[0], stack_pointer[1], stack_pointer[2]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), mozilla::BitwiseCast(stack_pointer[0]), mozilla::BitwiseCast(stack_pointer[1]), stack_pointer[2], stack_pointer[3], stack_pointer[4], stack_pointer[5], stack_pointer[6]);\ @@ -1057,7 +1223,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32 case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, s2, s3, a3, s4, stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3], stack_pointer[4]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], mozilla::BitwiseCast(stack_pointer[1]), mozilla::BitwiseCast(stack_pointer[2]), stack_pointer[3], mozilla::BitwiseCast(stack_pointer[4]), stack_pointer[5], stack_pointer[6], stack_pointer[7], stack_pointer[8], stack_pointer[9]);\ @@ -1069,7 +1235,7 @@ case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {\ auto target = reinterpret_cast(external);\ int32_t ret;\ - if (UseHardFpABI()) {\ + if (ARMFlags::UseHardFpABI()) {\ ret = target(a0, a1, s0, s1, a2, a3, stack_pointer[0], stack_pointer[1]);\ } else {\ ret = target(a0, a1, mozilla::BitwiseCast(a2), mozilla::BitwiseCast(a3), stack_pointer[0], stack_pointer[1], stack_pointer[2], stack_pointer[3]);\ @@ -1302,6 +1468,18 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(external);\ + target(a0, a1, a2, a3, stack_pointer[0], stack_pointer[1]);\ + scratchVolatileRegisters((void*)target);\ + break;\ +}\ #define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1382,12 +1560,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f0_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f0_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1502,12 +1704,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1532,6 +1746,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -1562,6 +1782,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -1760,6 +1992,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ #define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \ case js::jit::Args_General0: {\ @@ -1840,12 +2082,36 @@ case js::jit::Args_Int_Float32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Int32_Float32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_s);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Float32_Float32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(f12_s);\ setCallResultFloat(ret);\ break;\ }\ +case js::jit::Args_Float32_Float64: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(f12_d);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_);\ + setCallResultFloat(ret);\ + break;\ +}\ +case js::jit::Args_Float32_Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(I32(a0_));\ + setCallResultFloat(ret);\ + break;\ +}\ case js::jit::Args_Float32_IntInt: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_);\ @@ -1960,12 +2226,24 @@ case js::jit::Args_General_GeneralInt32Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32General: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), a3_);\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, I32(a1_), I32(a2_), a3_, I32(a4_));\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_General_GeneralInt32Int32Int32GeneralInt32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, I32(a1_), I32(a2_), I32(a3_), a4_, I32(a5_));\ + setCallResult(ret);\ + break;\ +}\ case js::jit::Args_General_GeneralGeneralInt32Int32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_));\ @@ -1990,6 +2268,12 @@ case js::jit::Args_Int32_GeneralGeneralGeneral: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralGeneralGeneral: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, a2_, a3_);\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralGeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, a2_, I32(a3_));\ @@ -2020,6 +2304,18 @@ case js::jit::Args_Int32_GeneralGeneralInt32Int32: {\ setCallResult(I64(ret));\ break;\ }\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_));\ + setCallResult(I64(ret));\ + break;\ +}\ +case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), I32(a5_), I32(a6_));\ + setCallResult(I64(ret));\ + break;\ +}\ case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {\ auto target = reinterpret_cast(nativeFn);\ auto ret = target(a0_, a1_, I32(a2_), I32(a3_), I32(a4_), a5_, I32(a6_));\ @@ -2218,6 +2514,16 @@ case js::jit::Args_Int64_GeneralInt64Int32: {\ setCallResult(ret);\ break;\ }\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_));\ + break;\ +}\ +case js::jit::Args_Void_GeneralInt32GeneralInt32Int32Int32: {\ + auto target = reinterpret_cast(nativeFn);\ + target(a0_, I32(a1_), a2_, I32(a3_), I32(a4_), I32(a5_));\ + break;\ +}\ diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/jit/CacheIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/windows/include/jit/CacheIROpsGenerated.h index 33f1593d8e8..5028cee95c0 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/jit/CacheIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/jit/CacheIROpsGenerated.h @@ -38,6 +38,7 @@ _(GuardFuse, 1, true, 1)\ _(GuardAnyClass, 1 + 1, true, 1)\ _(GuardGlobalGeneration, 1 + 1, true, 1)\ _(HasClassResult, 1 + 1, true, 1)\ +_(HasShapeResult, 1 + 1, true, 1)\ _(CallRegExpMatcherResult, 1 + 1 + 1 + 1, true, 5)\ _(CallRegExpSearcherResult, 1 + 1 + 1 + 1, true, 5)\ _(RegExpSearcherLastLimitResult, 0, true, 1)\ @@ -48,8 +49,6 @@ _(RegExpFlagResult, 1 + 4, true, 2)\ _(CallSubstringKernelResult, 1 + 1 + 1, true, 5)\ _(StringReplaceStringResult, 1 + 1 + 1, true, 5)\ _(StringSplitStringResult, 1 + 1, true, 5)\ -_(RegExpPrototypeOptimizableResult, 1, true, 4)\ -_(RegExpInstanceOptimizableResult, 1 + 1, true, 4)\ _(GetFirstDollarIndexResult, 1, true, 5)\ _(GuardCompartment, 1 + 1 + 1, false, 2)\ _(GuardIsExtensible, 1, true, 1)\ @@ -69,6 +68,7 @@ _(GuardFunctionScript, 1 + 1 + 1, true, 1)\ _(GuardSpecificAtom, 1 + 1, true, 4)\ _(GuardSpecificSymbol, 1 + 1, true, 1)\ _(GuardSpecificInt32, 1 + 4, true, 1)\ +_(GuardSpecificValue, 1 + 1, true, 1)\ _(GuardNoDenseElements, 1, true, 1)\ _(GuardStringToIndex, 1 + 1, true, 4)\ _(GuardStringToInt32, 1 + 1, true, 4)\ @@ -98,6 +98,7 @@ _(GuardFunctionIsConstructor, 1, true, 1)\ _(GuardNotClassConstructor, 1, true, 1)\ _(GuardArrayIsPacked, 1, true, 1)\ _(GuardArgumentsObjectFlags, 1 + 1, true, 1)\ +_(GuardObjectHasSameRealm, 1, true, 1)\ _(LoadObject, 1 + 1, true, 1)\ _(LoadProtoObject, 1 + 1 + 1, true, 1)\ _(LoadProto, 1 + 1, true, 1)\ @@ -110,6 +111,8 @@ _(TruncateDoubleToUInt32, 1 + 1, true, 4)\ _(DoubleToUint8Clamped, 1 + 1, true, 2)\ _(MegamorphicLoadSlotResult, 1 + 1, true, 4)\ _(MegamorphicLoadSlotByValueResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotPermissiveResult, 1 + 1, true, 4)\ +_(MegamorphicLoadSlotByValuePermissiveResult, 1 + 1, true, 4)\ _(MegamorphicStoreSlot, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicSetElement, 1 + 1 + 1 + 1, true, 5)\ _(MegamorphicHasPropResult, 1 + 1 + 1, true, 4)\ @@ -166,10 +169,14 @@ _(NewArrayIteratorResult, 1, true, 5)\ _(NewStringIteratorResult, 1, true, 5)\ _(NewRegExpStringIteratorResult, 1, true, 5)\ _(ObjectCreateResult, 1, true, 5)\ -_(NewArrayFromLengthResult, 1 + 1, true, 5)\ +_(NewArrayFromLengthResult, 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromLengthResult, 1 + 1, true, 5)\ _(NewTypedArrayFromArrayBufferResult, 1 + 1 + 1 + 1, true, 5)\ _(NewTypedArrayFromArrayResult, 1 + 1, true, 5)\ +_(NewMapObjectResult, 1, true, 5)\ +_(NewSetObjectResult, 1, true, 5)\ +_(NewMapObjectFromIterableResult, 1 + 1, true, 5)\ +_(NewSetObjectFromIterableResult, 1 + 1, true, 5)\ _(NewStringObjectResult, 1 + 1, true, 5)\ _(StringFromCharCodeResult, 1, true, 5)\ _(StringFromCodePointResult, 1, true, 5)\ @@ -192,6 +199,7 @@ _(MathSignNumberToInt32Result, 1, true, 2)\ _(MathImulResult, 1 + 1, true, 1)\ _(MathSqrtNumberResult, 1, true, 1)\ _(MathFRoundNumberResult, 1, true, 1)\ +_(MathF16RoundNumberResult, 1, true, 4)\ _(MathRandomResult, 1, true, 3)\ _(MathHypot2NumberResult, 1 + 1, true, 4)\ _(MathHypot3NumberResult, 1 + 1 + 1, true, 4)\ @@ -224,6 +232,7 @@ _(AtomicsXorResult, 1 + 1 + 1 + 1 + 1 + 1, true, 4)\ _(AtomicsLoadResult, 1 + 1 + 1 + 1, true, 2)\ _(AtomicsStoreResult, 1 + 1 + 1 + 1 + 1, true, 2)\ _(AtomicsIsLockFreeResult, 1, true, 1)\ +_(AtomicsPauseResult, 0, true, 1)\ _(CallNativeSetter, 1 + 1 + 1 + 1 + 1, true, 5)\ _(CallScriptedSetter, 1 + 1 + 1 + 1 + 1, true, 3)\ _(CallInlinedSetter, 1 + 1 + 1 + 1 + 1 + 1, true, 3)\ @@ -242,6 +251,7 @@ _(CallWasmFunction, 1 + 1 + 1 + 4 + 1 + 1, true, 3)\ _(GuardWasmArg, 1 + 1, true, 2)\ _(CallNativeFunction, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallDOMFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ +_(CallDOMFunctionWithAllocSite, 1 + 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallClassHook, 1 + 1 + 1 + 4 + 1, true, 4)\ _(CallInlinedFunction, 1 + 1 + 1 + 1 + 4, true, 4)\ _(CallScriptedProxyGetResult, 1 + 1 + 1 + 1 + 1 + 4, true, 4)\ @@ -272,6 +282,7 @@ _(LoadFunctionLengthResult, 1, true, 2)\ _(LoadFunctionNameResult, 1, true, 2)\ _(LoadBoundFunctionNumArgs, 1 + 1, true, 1)\ _(LoadBoundFunctionTarget, 1 + 1, true, 1)\ +_(LoadBoundFunctionArgument, 1 + 4 + 1, true, 2)\ _(GuardBoundFunctionIsConstructor, 1, true, 1)\ _(LoadArrayBufferByteLengthInt32Result, 1, true, 1)\ _(LoadArrayBufferByteLengthDoubleResult, 1, true, 1)\ @@ -332,6 +343,14 @@ _(BigIntMulResult, 1 + 1, true, 5)\ _(BigIntDivResult, 1 + 1, true, 5)\ _(BigIntModResult, 1 + 1, true, 5)\ _(BigIntPowResult, 1 + 1, true, 5)\ +_(BigIntToIntPtr, 1 + 1, true, 1)\ +_(IntPtrToBigIntResult, 1, true, 5)\ +_(BigIntPtrAdd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrSub, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMul, 1 + 1 + 1, true, 1)\ +_(BigIntPtrDiv, 1 + 1 + 1, true, 1)\ +_(BigIntPtrMod, 1 + 1 + 1, true, 1)\ +_(BigIntPtrPow, 1 + 1 + 1, true, 2)\ _(Int32BitOrResult, 1 + 1, true, 1)\ _(Int32BitXorResult, 1 + 1, true, 1)\ _(Int32BitAndResult, 1 + 1, true, 1)\ @@ -345,15 +364,24 @@ _(BigIntBitAndResult, 1 + 1, true, 5)\ _(BigIntLeftShiftResult, 1 + 1, true, 5)\ _(BigIntRightShiftResult, 1 + 1, true, 5)\ _(BigIntNotResult, 1, true, 5)\ +_(BigIntPtrBitOr, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitXor, 1 + 1 + 1, true, 1)\ +_(BigIntPtrBitAnd, 1 + 1 + 1, true, 1)\ +_(BigIntPtrLeftShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrRightShift, 1 + 1 + 1, true, 3)\ +_(BigIntPtrNot, 1 + 1, true, 1)\ _(Int32NegationResult, 1, true, 1)\ _(DoubleNegationResult, 1, true, 1)\ _(BigIntNegationResult, 1, true, 5)\ +_(BigIntPtrNegation, 1 + 1, true, 1)\ _(Int32IncResult, 1, true, 1)\ _(Int32DecResult, 1, true, 1)\ _(DoubleIncResult, 1, true, 1)\ _(DoubleDecResult, 1, true, 1)\ _(BigIntIncResult, 1, true, 5)\ _(BigIntDecResult, 1, true, 5)\ +_(BigIntPtrInc, 1 + 1, true, 1)\ +_(BigIntPtrDec, 1 + 1, true, 1)\ _(LoadInt32TruthyResult, 1, true, 2)\ _(LoadDoubleTruthyResult, 1, true, 2)\ _(LoadStringTruthyResult, 1, true, 2)\ @@ -364,7 +392,8 @@ _(LoadValueResult, 1, false, 1)\ _(LoadOperandResult, 1, true, 1)\ _(NewPlainObjectResult, 4 + 4 + 1 + 1 + 1, true, 4)\ _(NewArrayObjectResult, 4 + 1 + 1, true, 4)\ -_(CallStringConcatResult, 1 + 1, true, 5)\ +_(NewFunctionCloneResult, 1 + 1 + 1, true, 4)\ +_(ConcatStringsResult, 1 + 1 + 1, true, 5)\ _(CallStringObjectConcatResult, 1 + 1, false, 5)\ _(CallIsSuspendedGeneratorResult, 1, false, 2)\ _(CompareStringResult, 1 + 1 + 1, true, 5)\ @@ -388,6 +417,8 @@ _(SetHasStringResult, 1 + 1, true, 5)\ _(SetHasSymbolResult, 1 + 1, true, 3)\ _(SetHasBigIntResult, 1 + 1, true, 3)\ _(SetHasObjectResult, 1 + 1, true, 3)\ +_(SetDeleteResult, 1 + 1, true, 5)\ +_(SetAddResult, 1 + 1, true, 5)\ _(SetSizeResult, 1, true, 1)\ _(MapHasResult, 1 + 1, true, 5)\ _(MapHasNonGCThingResult, 1 + 1, true, 3)\ @@ -401,13 +432,20 @@ _(MapGetStringResult, 1 + 1, true, 5)\ _(MapGetSymbolResult, 1 + 1, true, 3)\ _(MapGetBigIntResult, 1 + 1, true, 3)\ _(MapGetObjectResult, 1 + 1, true, 3)\ +_(MapDeleteResult, 1 + 1, true, 5)\ +_(MapSetResult, 1 + 1 + 1, true, 5)\ _(MapSizeResult, 1, true, 1)\ +_(DateFillLocalTimeSlots, 1, true, 4)\ +_(DateHoursFromSecondsIntoYearResult, 1, true, 2)\ +_(DateMinutesFromSecondsIntoYearResult, 1, true, 2)\ +_(DateSecondsFromSecondsIntoYearResult, 1, true, 2)\ _(ArrayFromArgumentsObjectResult, 1 + 1, true, 5)\ _(CloseIterScriptedResult, 1 + 1 + 1 + 4, true, 5)\ _(CallPrintString, sizeof(uintptr_t), false, 1)\ _(Breakpoint, 0, false, 1)\ _(WrapResult, 0, false, 4)\ _(Bailout, 0, true, 0)\ +_(AssertFloat32Result, 1 + 1, true, 1)\ _(AssertRecoveredOnBailoutResult, 1 + 1, true, 1)\ _(AssertPropertyLookup, 1 + 1 + 1, true, 4) @@ -606,6 +644,12 @@ void hasClassResult(ObjOperandId obj, const void* clasp) {\ writeRawPointerField(clasp);\ assertLengthMatches();\ }\ +void hasShapeResult(ObjOperandId obj, Shape* shape) {\ + writeOp(CacheOp::HasShapeResult);\ + writeOperandId(obj);\ + writeShapeField(shape);\ + assertLengthMatches();\ +}\ void callRegExpMatcherResult(ObjOperandId regexp, StringOperandId input, Int32OperandId lastIndex, JitCode* stub) {\ writeOp(CacheOp::CallRegExpMatcherResult);\ writeOperandId(regexp);\ @@ -672,17 +716,6 @@ void stringSplitStringResult(StringOperandId str, StringOperandId separator) {\ writeOperandId(separator);\ assertLengthMatches();\ }\ -void regExpPrototypeOptimizableResult(ObjOperandId proto) {\ - writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ -void regExpInstanceOptimizableResult(ObjOperandId regexp, ObjOperandId proto) {\ - writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - writeOperandId(regexp);\ - writeOperandId(proto);\ - assertLengthMatches();\ -}\ void getFirstDollarIndexResult(StringOperandId str) {\ writeOp(CacheOp::GetFirstDollarIndexResult);\ writeOperandId(str);\ @@ -794,6 +827,12 @@ void guardSpecificInt32(Int32OperandId num, int32_t expected) {\ writeInt32Imm(expected);\ assertLengthMatches();\ }\ +void guardSpecificValue(ValOperandId val, const Value& expected) {\ + writeOp(CacheOp::GuardSpecificValue);\ + writeOperandId(val);\ + writeValueField(expected);\ + assertLengthMatches();\ +}\ void guardNoDenseElements(ObjOperandId obj) {\ writeOp(CacheOp::GuardNoDenseElements);\ writeOperandId(obj);\ @@ -981,6 +1020,11 @@ void guardArgumentsObjectFlags(ObjOperandId obj, uint32_t flags) {\ writeByteImm(flags);\ assertLengthMatches();\ }\ +void guardObjectHasSameRealm(ObjOperandId obj) {\ + writeOp(CacheOp::GuardObjectHasSameRealm);\ + writeOperandId(obj);\ + assertLengthMatches();\ +}\ ObjOperandId loadObject(JSObject* obj) {\ writeOp(CacheOp::LoadObject);\ ObjOperandId result(newOperandId());\ @@ -1080,6 +1124,18 @@ void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id) {\ writeOperandId(id);\ assertLengthMatches();\ }\ +void megamorphicLoadSlotPermissiveResult(ObjOperandId obj, jsid name) {\ + writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + writeOperandId(obj);\ + writeIdField(name);\ + assertLengthMatches();\ +}\ +void megamorphicLoadSlotByValuePermissiveResult(ObjOperandId obj, ValOperandId id) {\ + writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + writeOperandId(obj);\ + writeOperandId(id);\ + assertLengthMatches();\ +}\ void megamorphicStoreSlot(ObjOperandId obj, jsid name, ValOperandId rhs, bool strict) {\ writeOp(CacheOp::MegamorphicStoreSlot);\ writeOperandId(obj);\ @@ -1415,10 +1471,11 @@ void objectCreateResult(JSObject* templateObject) {\ writeObjectField(templateObject);\ assertLengthMatches();\ }\ -void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ +void newArrayFromLengthResult(JSObject* templateObject, Int32OperandId length, gc::AllocSite* site) {\ writeOp(CacheOp::NewArrayFromLengthResult);\ writeObjectField(templateObject);\ writeOperandId(length);\ + writeAllocSiteField(site);\ assertLengthMatches();\ }\ void newTypedArrayFromLengthResult(JSObject* templateObject, Int32OperandId length) {\ @@ -1441,6 +1498,28 @@ void newTypedArrayFromArrayResult(JSObject* templateObject, ObjOperandId array) writeOperandId(array);\ assertLengthMatches();\ }\ +void newMapObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewMapObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newSetObjectResult(JSObject* templateObject) {\ + writeOp(CacheOp::NewSetObjectResult);\ + writeObjectField(templateObject);\ + assertLengthMatches();\ +}\ +void newMapObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewMapObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ +void newSetObjectFromIterableResult(JSObject* templateObject, ValOperandId iterable) {\ + writeOp(CacheOp::NewSetObjectFromIterableResult);\ + writeObjectField(templateObject);\ + writeOperandId(iterable);\ + assertLengthMatches();\ +}\ void newStringObjectResult(JSObject* templateObject, StringOperandId str) {\ writeOp(CacheOp::NewStringObjectResult);\ writeObjectField(templateObject);\ @@ -1558,6 +1637,11 @@ void mathFRoundNumberResult(NumberOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +void mathF16RoundNumberResult(NumberOperandId input) {\ + writeOp(CacheOp::MathF16RoundNumberResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ void mathRandomResult(const void* rng) {\ writeOp(CacheOp::MathRandomResult);\ writeRawPointerField(rng);\ @@ -1785,6 +1869,10 @@ void atomicsIsLockFreeResult(Int32OperandId value) {\ writeOperandId(value);\ assertLengthMatches();\ }\ +void atomicsPauseResult() {\ + writeOp(CacheOp::AtomicsPauseResult);\ + assertLengthMatches();\ +}\ private:\ void callNativeSetter_(ObjOperandId receiver, JSObject* setter, ValOperandId rhs, bool sameRealm, uint32_t nargsAndFlags) {\ writeOp(CacheOp::CallNativeSetter);\ @@ -1906,13 +1994,13 @@ void callBoundScriptedFunction(ObjOperandId callee, ObjOperandId target, Int32Op writeUInt32Imm(numBoundArgs);\ assertLengthMatches();\ }\ -void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcExport, JSObject* instance) {\ +void callWasmFunction(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* funcType, JSObject* instance) {\ writeOp(CacheOp::CallWasmFunction);\ writeOperandId(callee);\ writeOperandId(argc);\ writeCallFlagsImm(flags);\ writeUInt32Imm(argcFixed);\ - writeRawPointerField(funcExport);\ + writeRawPointerField(funcType);\ writeObjectField(instance);\ assertLengthMatches();\ }\ @@ -1945,6 +2033,18 @@ void callDOMFunction_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thi }\ public:\ private:\ +void callDOMFunctionWithAllocSite_(ObjOperandId callee, Int32OperandId argc, ObjOperandId thisObj, CallFlags flags, uint32_t argcFixed, gc::AllocSite* site) {\ + writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + writeOperandId(callee);\ + writeOperandId(argc);\ + writeOperandId(thisObj);\ + writeCallFlagsImm(flags);\ + writeUInt32Imm(argcFixed);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +public:\ +private:\ void callClassHook_(ObjOperandId callee, Int32OperandId argc, CallFlags flags, uint32_t argcFixed, const void* target) {\ writeOp(CacheOp::CallClassHook);\ writeOperandId(callee);\ @@ -2167,6 +2267,15 @@ ObjOperandId loadBoundFunctionTarget(ObjOperandId obj) {\ assertLengthMatches();\ return result;\ }\ +ValOperandId loadBoundFunctionArgument(ObjOperandId obj, uint32_t index) {\ + writeOp(CacheOp::LoadBoundFunctionArgument);\ + writeOperandId(obj);\ + writeUInt32Imm(index);\ + ValOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void guardBoundFunctionIsConstructor(ObjOperandId obj) {\ writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ writeOperandId(obj);\ @@ -2546,6 +2655,73 @@ void bigIntPowResult(BigIntOperandId lhs, BigIntOperandId rhs) {\ writeOperandId(rhs);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntToIntPtr(BigIntOperandId input) {\ + writeOp(CacheOp::BigIntToIntPtr);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +void intPtrToBigIntResult(IntPtrOperandId input) {\ + writeOp(CacheOp::IntPtrToBigIntResult);\ + writeOperandId(input);\ + assertLengthMatches();\ +}\ +IntPtrOperandId bigIntPtrAdd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrAdd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrSub(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrSub);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMul(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMul);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDiv(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrDiv);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrMod(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrMod);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrPow(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrPow);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32BitOrResult(Int32OperandId lhs, Int32OperandId rhs) {\ writeOp(CacheOp::Int32BitOrResult);\ writeOperandId(lhs);\ @@ -2623,6 +2799,59 @@ void bigIntNotResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrBitOr(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitOr);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitXor(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitXor);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrBitAnd(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrBitAnd);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrLeftShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrLeftShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrRightShift(IntPtrOperandId lhs, IntPtrOperandId rhs) {\ + writeOp(CacheOp::BigIntPtrRightShift);\ + writeOperandId(lhs);\ + writeOperandId(rhs);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrNot(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNot);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32NegationResult(Int32OperandId input) {\ writeOp(CacheOp::Int32NegationResult);\ writeOperandId(input);\ @@ -2638,6 +2867,14 @@ void bigIntNegationResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrNegation(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrNegation);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void int32IncResult(Int32OperandId input) {\ writeOp(CacheOp::Int32IncResult);\ writeOperandId(input);\ @@ -2668,6 +2905,22 @@ void bigIntDecResult(BigIntOperandId input) {\ writeOperandId(input);\ assertLengthMatches();\ }\ +IntPtrOperandId bigIntPtrInc(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrInc);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ +IntPtrOperandId bigIntPtrDec(IntPtrOperandId input) {\ + writeOp(CacheOp::BigIntPtrDec);\ + writeOperandId(input);\ + IntPtrOperandId result(newOperandId());\ + writeOperandId(result);\ + assertLengthMatches();\ + return result;\ +}\ void loadInt32TruthyResult(ValOperandId input) {\ writeOp(CacheOp::LoadInt32TruthyResult);\ writeOperandId(input);\ @@ -2724,10 +2977,18 @@ void newArrayObjectResult(uint32_t arrayLength, Shape* shape, gc::AllocSite* sit writeAllocSiteField(site);\ assertLengthMatches();\ }\ -void callStringConcatResult(StringOperandId lhs, StringOperandId rhs) {\ - writeOp(CacheOp::CallStringConcatResult);\ +void newFunctionCloneResult(JSObject* canonical, gc::AllocKind allocKind, gc::AllocSite* site) {\ + writeOp(CacheOp::NewFunctionCloneResult);\ + writeObjectField(canonical);\ + writeAllocKindImm(allocKind);\ + writeAllocSiteField(site);\ + assertLengthMatches();\ +}\ +void concatStringsResult(StringOperandId lhs, StringOperandId rhs, JitCode* stub) {\ + writeOp(CacheOp::ConcatStringsResult);\ writeOperandId(lhs);\ writeOperandId(rhs);\ + writeJitCodeField(stub);\ assertLengthMatches();\ }\ void callStringObjectConcatResult(ValOperandId lhs, ValOperandId rhs) {\ @@ -2876,6 +3137,18 @@ void setHasObjectResult(ObjOperandId set, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void setDeleteResult(ObjOperandId set, ValOperandId val) {\ + writeOp(CacheOp::SetDeleteResult);\ + writeOperandId(set);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void setAddResult(ObjOperandId set, ValOperandId key) {\ + writeOp(CacheOp::SetAddResult);\ + writeOperandId(set);\ + writeOperandId(key);\ + assertLengthMatches();\ +}\ void setSizeResult(ObjOperandId set) {\ writeOp(CacheOp::SetSizeResult);\ writeOperandId(set);\ @@ -2953,11 +3226,44 @@ void mapGetObjectResult(ObjOperandId map, ObjOperandId obj) {\ writeOperandId(obj);\ assertLengthMatches();\ }\ +void mapDeleteResult(ObjOperandId map, ValOperandId val) {\ + writeOp(CacheOp::MapDeleteResult);\ + writeOperandId(map);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ +void mapSetResult(ObjOperandId map, ValOperandId key, ValOperandId val) {\ + writeOp(CacheOp::MapSetResult);\ + writeOperandId(map);\ + writeOperandId(key);\ + writeOperandId(val);\ + assertLengthMatches();\ +}\ void mapSizeResult(ObjOperandId map) {\ writeOp(CacheOp::MapSizeResult);\ writeOperandId(map);\ assertLengthMatches();\ }\ +void dateFillLocalTimeSlots(ObjOperandId date) {\ + writeOp(CacheOp::DateFillLocalTimeSlots);\ + writeOperandId(date);\ + assertLengthMatches();\ +}\ +void dateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ +void dateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYear) {\ + writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + writeOperandId(secondsIntoYear);\ + assertLengthMatches();\ +}\ void arrayFromArgumentsObjectResult(ObjOperandId obj, Shape* shape) {\ writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ writeOperandId(obj);\ @@ -2989,6 +3295,12 @@ void bailout() {\ writeOp(CacheOp::Bailout);\ assertLengthMatches();\ }\ +void assertFloat32Result(ValOperandId val, bool mustBeFloat32) {\ + writeOp(CacheOp::AssertFloat32Result);\ + writeOperandId(val);\ + writeBoolImm(mustBeFloat32);\ + assertLengthMatches();\ +}\ void assertRecoveredOnBailoutResult(ValOperandId val, bool mustBeRecovered) {\ writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ writeOperandId(val);\ @@ -3202,19 +3514,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -3487,6 +3786,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -3559,6 +3864,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -3837,11 +4156,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -3867,6 +4187,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -3994,6 +4340,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathHypot2NumberResult(NumberOperandId firstId, NumberOperandId secondId);\ [[nodiscard]] bool emitMathHypot2NumberResult(CacheIRReader& reader) {\ NumberOperandId firstId = reader.numberOperandId();\ @@ -4237,6 +4589,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallInt32ToString(Int32OperandId inputId, StringOperandId resultId);\ [[nodiscard]] bool emitCallInt32ToString(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4427,6 +4784,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -4775,6 +5140,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -4865,6 +5291,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4883,6 +5356,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -4919,6 +5399,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -4961,11 +5455,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadOperandResult(inputId);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCallIsSuspendedGeneratorResult(ValOperandId valId);\ @@ -5108,6 +5603,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -5184,12 +5693,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -5218,6 +5766,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -5268,6 +5823,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -5361,6 +5923,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificSymbol(symId, expectedOffset);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitLoadArgumentFixedSlot(ValOperandId resultId, uint8_t slotIndex);\ [[nodiscard]] bool emitLoadArgumentFixedSlot(CacheIRReader& reader) {\ ValOperandId resultId = reader.valOperandId();\ @@ -5600,15 +6169,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitCallNativeFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, bool ignoresReturnValue);\ @@ -5631,6 +6200,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -5804,6 +6384,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallStringObjectConcatResult(ValOperandId lhsId, ValOperandId rhsId);\ [[nodiscard]] bool emitCallStringObjectConcatResult(CacheIRReader& reader) {\ ValOperandId lhsId = reader.valOperandId();\ @@ -6054,6 +6642,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitHasClassResult(objId, claspOffset);\ }\ \ +[[nodiscard]] bool emitHasShapeResult(ObjOperandId objId, uint32_t shapeOffset);\ +[[nodiscard]] bool emitHasShapeResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t shapeOffset = reader.stubOffset();\ + return emitHasShapeResult(objId, shapeOffset);\ +}\ +\ [[nodiscard]] bool emitCallRegExpMatcherResult(ObjOperandId regexpId, StringOperandId inputId, Int32OperandId lastIndexId, uint32_t stubOffset);\ [[nodiscard]] bool emitCallRegExpMatcherResult(CacheIRReader& reader) {\ ObjOperandId regexpId = reader.objOperandId();\ @@ -6130,19 +6725,6 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitStringSplitStringResult(strId, separatorId);\ }\ \ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpPrototypeOptimizableResult(protoId);\ -}\ -\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(ObjOperandId regexpId, ObjOperandId protoId);\ -[[nodiscard]] bool emitRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - ObjOperandId regexpId = reader.objOperandId();\ - ObjOperandId protoId = reader.objOperandId();\ - return emitRegExpInstanceOptimizableResult(regexpId, protoId);\ -}\ -\ [[nodiscard]] bool emitGetFirstDollarIndexResult(StringOperandId strId);\ [[nodiscard]] bool emitGetFirstDollarIndexResult(CacheIRReader& reader) {\ StringOperandId strId = reader.stringOperandId();\ @@ -6261,6 +6843,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardSpecificInt32(numId, expected);\ }\ \ +[[nodiscard]] bool emitGuardSpecificValue(ValOperandId valId, uint32_t expectedOffset);\ +[[nodiscard]] bool emitGuardSpecificValue(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + uint32_t expectedOffset = reader.stubOffset();\ + return emitGuardSpecificValue(valId, expectedOffset);\ +}\ +\ [[nodiscard]] bool emitGuardNoDenseElements(ObjOperandId objId);\ [[nodiscard]] bool emitGuardNoDenseElements(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6446,6 +7035,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitGuardArgumentsObjectFlags(objId, flags);\ }\ \ +[[nodiscard]] bool emitGuardObjectHasSameRealm(ObjOperandId objId);\ +[[nodiscard]] bool emitGuardObjectHasSameRealm(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + return emitGuardObjectHasSameRealm(objId);\ +}\ +\ [[nodiscard]] bool emitLoadObject(ObjOperandId resultId, uint32_t objOffset);\ [[nodiscard]] bool emitLoadObject(CacheIRReader& reader) {\ ObjOperandId resultId = reader.objOperandId();\ @@ -6533,6 +7128,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMegamorphicLoadSlotByValueResult(objId, idId);\ }\ \ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(ObjOperandId objId, uint32_t nameOffset);\ +[[nodiscard]] bool emitMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t nameOffset = reader.stubOffset();\ + return emitMegamorphicLoadSlotPermissiveResult(objId, nameOffset);\ +}\ +\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(ObjOperandId objId, ValOperandId idId);\ +[[nodiscard]] bool emitMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + ValOperandId idId = reader.valOperandId();\ + return emitMegamorphicLoadSlotByValuePermissiveResult(objId, idId);\ +}\ +\ [[nodiscard]] bool emitMegamorphicStoreSlot(ObjOperandId objId, uint32_t nameOffset, ValOperandId rhsId, bool strict);\ [[nodiscard]] bool emitMegamorphicStoreSlot(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -6918,11 +7527,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitObjectCreateResult(templateObjectOffset);\ }\ \ -[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ +[[nodiscard]] bool emitNewArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId, uint32_t siteOffset);\ [[nodiscard]] bool emitNewArrayFromLengthResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ Int32OperandId lengthId = reader.int32OperandId();\ - return emitNewArrayFromLengthResult(templateObjectOffset, lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewArrayFromLengthResult(templateObjectOffset, lengthId, siteOffset);\ }\ \ [[nodiscard]] bool emitNewTypedArrayFromLengthResult(uint32_t templateObjectOffset, Int32OperandId lengthId);\ @@ -6948,6 +7558,32 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewTypedArrayFromArrayResult(templateObjectOffset, arrayId);\ }\ \ +[[nodiscard]] bool emitNewMapObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewMapObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewMapObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectResult(uint32_t templateObjectOffset);\ +[[nodiscard]] bool emitNewSetObjectResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + return emitNewSetObjectResult(templateObjectOffset);\ +}\ +\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewMapObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(uint32_t templateObjectOffset, ValOperandId iterableId);\ +[[nodiscard]] bool emitNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + uint32_t templateObjectOffset = reader.stubOffset();\ + ValOperandId iterableId = reader.valOperandId();\ + return emitNewSetObjectFromIterableResult(templateObjectOffset, iterableId);\ +}\ +\ [[nodiscard]] bool emitNewStringObjectResult(uint32_t templateObjectOffset, StringOperandId strId);\ [[nodiscard]] bool emitNewStringObjectResult(CacheIRReader& reader) {\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -7087,6 +7723,12 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMathFRoundNumberResult(inputId);\ }\ \ +[[nodiscard]] bool emitMathF16RoundNumberResult(NumberOperandId inputId);\ +[[nodiscard]] bool emitMathF16RoundNumberResult(CacheIRReader& reader) {\ + NumberOperandId inputId = reader.numberOperandId();\ + return emitMathF16RoundNumberResult(inputId);\ +}\ +\ [[nodiscard]] bool emitMathRandomResult(uint32_t rngOffset);\ [[nodiscard]] bool emitMathRandomResult(CacheIRReader& reader) {\ uint32_t rngOffset = reader.stubOffset();\ @@ -7342,6 +7984,11 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitAtomicsIsLockFreeResult(valueId);\ }\ \ +[[nodiscard]] bool emitAtomicsPauseResult();\ +[[nodiscard]] bool emitAtomicsPauseResult(CacheIRReader& reader) {\ + return emitAtomicsPauseResult();\ +}\ +\ [[nodiscard]] bool emitCallNativeSetter(ObjOperandId receiverId, uint32_t setterOffset, ValOperandId rhsId, bool sameRealm, uint32_t nargsAndFlagsOffset);\ [[nodiscard]] bool emitCallNativeSetter(CacheIRReader& reader) {\ ObjOperandId receiverId = reader.objOperandId();\ @@ -7463,15 +8110,15 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallBoundScriptedFunction(calleeId, targetId, argcId, flags, numBoundArgs);\ }\ \ -[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcExportOffset, uint32_t instanceOffset);\ +[[nodiscard]] bool emitCallWasmFunction(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t funcTypeOffset, uint32_t instanceOffset);\ [[nodiscard]] bool emitCallWasmFunction(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ Int32OperandId argcId = reader.int32OperandId();\ CallFlags flags = reader.callFlags();\ uint32_t argcFixed = reader.uint32Immediate();\ - uint32_t funcExportOffset = reader.stubOffset();\ + uint32_t funcTypeOffset = reader.stubOffset();\ uint32_t instanceOffset = reader.stubOffset();\ - return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcExportOffset, instanceOffset);\ + return emitCallWasmFunction(calleeId, argcId, flags, argcFixed, funcTypeOffset, instanceOffset);\ }\ \ [[nodiscard]] bool emitGuardWasmArg(ValOperandId argId, wasm::ValType::Kind type);\ @@ -7501,6 +8148,17 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitCallDOMFunction(calleeId, argcId, thisObjId, flags, argcFixed);\ }\ \ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(ObjOperandId calleeId, Int32OperandId argcId, ObjOperandId thisObjId, CallFlags flags, uint32_t argcFixed, uint32_t siteOffset);\ +[[nodiscard]] bool emitCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + ObjOperandId calleeId = reader.objOperandId();\ + Int32OperandId argcId = reader.int32OperandId();\ + ObjOperandId thisObjId = reader.objOperandId();\ + CallFlags flags = reader.callFlags();\ + uint32_t argcFixed = reader.uint32Immediate();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitCallDOMFunctionWithAllocSite(calleeId, argcId, thisObjId, flags, argcFixed, siteOffset);\ +}\ +\ [[nodiscard]] bool emitCallClassHook(ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, uint32_t targetOffset);\ [[nodiscard]] bool emitCallClassHook(CacheIRReader& reader) {\ ObjOperandId calleeId = reader.objOperandId();\ @@ -7736,6 +8394,14 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitLoadBoundFunctionTarget(objId, resultId);\ }\ \ +[[nodiscard]] bool emitLoadBoundFunctionArgument(ObjOperandId objId, uint32_t index, ValOperandId resultId);\ +[[nodiscard]] bool emitLoadBoundFunctionArgument(CacheIRReader& reader) {\ + ObjOperandId objId = reader.objOperandId();\ + uint32_t index = reader.uint32Immediate();\ + ValOperandId resultId = reader.valOperandId();\ + return emitLoadBoundFunctionArgument(objId, index, resultId);\ +}\ +\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(ObjOperandId objId);\ [[nodiscard]] bool emitGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8153,6 +8819,67 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntPowResult(lhsId, rhsId);\ }\ \ +[[nodiscard]] bool emitBigIntToIntPtr(BigIntOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntToIntPtr(CacheIRReader& reader) {\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntToIntPtr(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitIntPtrToBigIntResult(IntPtrOperandId inputId);\ +[[nodiscard]] bool emitIntPtrToBigIntResult(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + return emitIntPtrToBigIntResult(inputId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrAdd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrAdd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrAdd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrSub(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrSub(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrSub(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMul(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMul(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMul(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDiv(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDiv(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDiv(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrMod(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrMod(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrMod(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrPow(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrPow(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrPow(lhsId, rhsId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32BitOrResult(Int32OperandId lhsId, Int32OperandId rhsId);\ [[nodiscard]] bool emitInt32BitOrResult(CacheIRReader& reader) {\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -8243,6 +8970,53 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNotResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrBitOr(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitOr(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitOr(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitXor(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitXor(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitXor(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrBitAnd(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrBitAnd(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrBitAnd(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrLeftShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrLeftShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrLeftShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrRightShift(IntPtrOperandId lhsId, IntPtrOperandId rhsId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrRightShift(CacheIRReader& reader) {\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrRightShift(lhsId, rhsId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrNot(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNot(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNot(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32NegationResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32NegationResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8261,6 +9035,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntNegationResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrNegation(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrNegation(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrNegation(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitInt32IncResult(Int32OperandId inputId);\ [[nodiscard]] bool emitInt32IncResult(CacheIRReader& reader) {\ Int32OperandId inputId = reader.int32OperandId();\ @@ -8297,6 +9078,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBigIntDecResult(inputId);\ }\ \ +[[nodiscard]] bool emitBigIntPtrInc(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrInc(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrInc(inputId, resultId);\ +}\ +\ +[[nodiscard]] bool emitBigIntPtrDec(IntPtrOperandId inputId, IntPtrOperandId resultId);\ +[[nodiscard]] bool emitBigIntPtrDec(CacheIRReader& reader) {\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + return emitBigIntPtrDec(inputId, resultId);\ +}\ +\ [[nodiscard]] bool emitLoadInt32TruthyResult(ValOperandId inputId);\ [[nodiscard]] bool emitLoadInt32TruthyResult(CacheIRReader& reader) {\ ValOperandId inputId = reader.valOperandId();\ @@ -8357,11 +9152,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitNewArrayObjectResult(arrayLength, shapeOffset, siteOffset);\ }\ \ -[[nodiscard]] bool emitCallStringConcatResult(StringOperandId lhsId, StringOperandId rhsId);\ -[[nodiscard]] bool emitCallStringConcatResult(CacheIRReader& reader) {\ +[[nodiscard]] bool emitNewFunctionCloneResult(uint32_t canonicalOffset, gc::AllocKind allocKind, uint32_t siteOffset);\ +[[nodiscard]] bool emitNewFunctionCloneResult(CacheIRReader& reader) {\ + uint32_t canonicalOffset = reader.stubOffset();\ + gc::AllocKind allocKind = reader.allocKind();\ + uint32_t siteOffset = reader.stubOffset();\ + return emitNewFunctionCloneResult(canonicalOffset, allocKind, siteOffset);\ +}\ +\ +[[nodiscard]] bool emitConcatStringsResult(StringOperandId lhsId, StringOperandId rhsId, uint32_t stubOffset);\ +[[nodiscard]] bool emitConcatStringsResult(CacheIRReader& reader) {\ StringOperandId lhsId = reader.stringOperandId();\ StringOperandId rhsId = reader.stringOperandId();\ - return emitCallStringConcatResult(lhsId, rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + return emitConcatStringsResult(lhsId, rhsId, stubOffset);\ }\ \ [[nodiscard]] bool emitCompareStringResult(JSOp op, StringOperandId lhsId, StringOperandId rhsId);\ @@ -8520,6 +9324,20 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitSetHasObjectResult(setId, objId);\ }\ \ +[[nodiscard]] bool emitSetDeleteResult(ObjOperandId setId, ValOperandId valId);\ +[[nodiscard]] bool emitSetDeleteResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitSetDeleteResult(setId, valId);\ +}\ +\ +[[nodiscard]] bool emitSetAddResult(ObjOperandId setId, ValOperandId keyId);\ +[[nodiscard]] bool emitSetAddResult(CacheIRReader& reader) {\ + ObjOperandId setId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + return emitSetAddResult(setId, keyId);\ +}\ +\ [[nodiscard]] bool emitSetSizeResult(ObjOperandId setId);\ [[nodiscard]] bool emitSetSizeResult(CacheIRReader& reader) {\ ObjOperandId setId = reader.objOperandId();\ @@ -8610,12 +9428,51 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitMapGetObjectResult(mapId, objId);\ }\ \ +[[nodiscard]] bool emitMapDeleteResult(ObjOperandId mapId, ValOperandId valId);\ +[[nodiscard]] bool emitMapDeleteResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapDeleteResult(mapId, valId);\ +}\ +\ +[[nodiscard]] bool emitMapSetResult(ObjOperandId mapId, ValOperandId keyId, ValOperandId valId);\ +[[nodiscard]] bool emitMapSetResult(CacheIRReader& reader) {\ + ObjOperandId mapId = reader.objOperandId();\ + ValOperandId keyId = reader.valOperandId();\ + ValOperandId valId = reader.valOperandId();\ + return emitMapSetResult(mapId, keyId, valId);\ +}\ +\ [[nodiscard]] bool emitMapSizeResult(ObjOperandId mapId);\ [[nodiscard]] bool emitMapSizeResult(CacheIRReader& reader) {\ ObjOperandId mapId = reader.objOperandId();\ return emitMapSizeResult(mapId);\ }\ \ +[[nodiscard]] bool emitDateFillLocalTimeSlots(ObjOperandId dateId);\ +[[nodiscard]] bool emitDateFillLocalTimeSlots(CacheIRReader& reader) {\ + ObjOperandId dateId = reader.objOperandId();\ + return emitDateFillLocalTimeSlots(dateId);\ +}\ +\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateHoursFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateMinutesFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(ValOperandId secondsIntoYearId);\ +[[nodiscard]] bool emitDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + return emitDateSecondsFromSecondsIntoYearResult(secondsIntoYearId);\ +}\ +\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(ObjOperandId objId, uint32_t shapeOffset);\ [[nodiscard]] bool emitArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ ObjOperandId objId = reader.objOperandId();\ @@ -8637,6 +9494,13 @@ void assertPropertyLookup(ObjOperandId obj, jsid id, uint32_t slot) {\ return emitBailout();\ }\ \ +[[nodiscard]] bool emitAssertFloat32Result(ValOperandId valId, bool mustBeFloat32);\ +[[nodiscard]] bool emitAssertFloat32Result(CacheIRReader& reader) {\ + ValOperandId valId = reader.valOperandId();\ + bool mustBeFloat32 = reader.readBool();\ + return emitAssertFloat32Result(valId, mustBeFloat32);\ +}\ +\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(ValOperandId valId, bool mustBeRecovered);\ [[nodiscard]] bool emitAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ ValOperandId valId = reader.valOperandId();\ @@ -8684,6 +9548,7 @@ _(GuardFuse)\ _(GuardAnyClass)\ _(GuardGlobalGeneration)\ _(HasClassResult)\ +_(HasShapeResult)\ _(CallRegExpMatcherResult)\ _(CallRegExpSearcherResult)\ _(RegExpSearcherLastLimitResult)\ @@ -8694,8 +9559,6 @@ _(RegExpFlagResult)\ _(CallSubstringKernelResult)\ _(StringReplaceStringResult)\ _(StringSplitStringResult)\ -_(RegExpPrototypeOptimizableResult)\ -_(RegExpInstanceOptimizableResult)\ _(GetFirstDollarIndexResult)\ _(GuardIsExtensible)\ _(GuardIsNativeObject)\ @@ -8714,6 +9577,7 @@ _(GuardFunctionScript)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ +_(GuardSpecificValue)\ _(GuardNoDenseElements)\ _(GuardStringToIndex)\ _(GuardStringToInt32)\ @@ -8741,6 +9605,7 @@ _(GuardFunctionIsConstructor)\ _(GuardNotClassConstructor)\ _(GuardArrayIsPacked)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadObject)\ _(LoadProtoObject)\ _(LoadProto)\ @@ -8753,6 +9618,8 @@ _(TruncateDoubleToUInt32)\ _(DoubleToUint8Clamped)\ _(MegamorphicLoadSlotResult)\ _(MegamorphicLoadSlotByValueResult)\ +_(MegamorphicLoadSlotPermissiveResult)\ +_(MegamorphicLoadSlotByValuePermissiveResult)\ _(MegamorphicStoreSlot)\ _(MegamorphicSetElement)\ _(MegamorphicHasPropResult)\ @@ -8813,6 +9680,10 @@ _(NewArrayFromLengthResult)\ _(NewTypedArrayFromLengthResult)\ _(NewTypedArrayFromArrayBufferResult)\ _(NewTypedArrayFromArrayResult)\ +_(NewMapObjectResult)\ +_(NewSetObjectResult)\ +_(NewMapObjectFromIterableResult)\ +_(NewSetObjectFromIterableResult)\ _(NewStringObjectResult)\ _(StringFromCharCodeResult)\ _(StringFromCodePointResult)\ @@ -8835,6 +9706,7 @@ _(MathSignNumberToInt32Result)\ _(MathImulResult)\ _(MathSqrtNumberResult)\ _(MathFRoundNumberResult)\ +_(MathF16RoundNumberResult)\ _(MathRandomResult)\ _(MathHypot2NumberResult)\ _(MathHypot3NumberResult)\ @@ -8867,6 +9739,7 @@ _(AtomicsXorResult)\ _(AtomicsLoadResult)\ _(AtomicsStoreResult)\ _(AtomicsIsLockFreeResult)\ +_(AtomicsPauseResult)\ _(CallNativeSetter)\ _(CallScriptedSetter)\ _(CallInlinedSetter)\ @@ -8885,6 +9758,7 @@ _(CallWasmFunction)\ _(GuardWasmArg)\ _(CallNativeFunction)\ _(CallDOMFunction)\ +_(CallDOMFunctionWithAllocSite)\ _(CallClassHook)\ _(CallInlinedFunction)\ _(CallScriptedProxyGetResult)\ @@ -8915,6 +9789,7 @@ _(LoadFunctionLengthResult)\ _(LoadFunctionNameResult)\ _(LoadBoundFunctionNumArgs)\ _(LoadBoundFunctionTarget)\ +_(LoadBoundFunctionArgument)\ _(GuardBoundFunctionIsConstructor)\ _(LoadArrayBufferByteLengthInt32Result)\ _(LoadArrayBufferByteLengthDoubleResult)\ @@ -8975,6 +9850,14 @@ _(BigIntMulResult)\ _(BigIntDivResult)\ _(BigIntModResult)\ _(BigIntPowResult)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigIntResult)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ _(Int32BitOrResult)\ _(Int32BitXorResult)\ _(Int32BitAndResult)\ @@ -8988,15 +9871,24 @@ _(BigIntBitAndResult)\ _(BigIntLeftShiftResult)\ _(BigIntRightShiftResult)\ _(BigIntNotResult)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrLeftShift)\ +_(BigIntPtrRightShift)\ +_(BigIntPtrNot)\ _(Int32NegationResult)\ _(DoubleNegationResult)\ _(BigIntNegationResult)\ +_(BigIntPtrNegation)\ _(Int32IncResult)\ _(Int32DecResult)\ _(DoubleIncResult)\ _(DoubleDecResult)\ _(BigIntIncResult)\ _(BigIntDecResult)\ +_(BigIntPtrInc)\ +_(BigIntPtrDec)\ _(LoadInt32TruthyResult)\ _(LoadDoubleTruthyResult)\ _(LoadStringTruthyResult)\ @@ -9006,7 +9898,8 @@ _(LoadValueTruthyResult)\ _(LoadOperandResult)\ _(NewPlainObjectResult)\ _(NewArrayObjectResult)\ -_(CallStringConcatResult)\ +_(NewFunctionCloneResult)\ +_(ConcatStringsResult)\ _(CompareStringResult)\ _(CompareObjectResult)\ _(CompareSymbolResult)\ @@ -9028,6 +9921,8 @@ _(SetHasStringResult)\ _(SetHasSymbolResult)\ _(SetHasBigIntResult)\ _(SetHasObjectResult)\ +_(SetDeleteResult)\ +_(SetAddResult)\ _(SetSizeResult)\ _(MapHasResult)\ _(MapHasNonGCThingResult)\ @@ -9041,10 +9936,17 @@ _(MapGetStringResult)\ _(MapGetSymbolResult)\ _(MapGetBigIntResult)\ _(MapGetObjectResult)\ +_(MapDeleteResult)\ +_(MapSetResult)\ _(MapSizeResult)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYearResult)\ +_(DateMinutesFromSecondsIntoYearResult)\ +_(DateSecondsFromSecondsIntoYearResult)\ _(ArrayFromArgumentsObjectResult)\ _(CloseIterScriptedResult)\ _(Bailout)\ +_(AssertFloat32Result)\ _(AssertRecoveredOnBailoutResult)\ _(AssertPropertyLookup) @@ -9262,6 +10164,14 @@ void spewHasClassResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewHasShapeResult(CacheIRReader& reader) {\ + spewOp(CacheOp::HasShapeResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("shapeOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallRegExpMatcherResult(CacheIRReader& reader) {\ spewOp(CacheOp::CallRegExpMatcherResult);\ spewOperandId("regexpId", reader.objOperandId());\ @@ -9355,20 +10265,6 @@ void spewStringSplitStringResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewRegExpPrototypeOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpPrototypeOptimizableResult);\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ -void spewRegExpInstanceOptimizableResult(CacheIRReader& reader) {\ - spewOp(CacheOp::RegExpInstanceOptimizableResult);\ - spewOperandId("regexpId", reader.objOperandId());\ - spewArgSeparator();\ - spewOperandId("protoId", reader.objOperandId());\ - spewOpEnd();\ -}\ -\ void spewGetFirstDollarIndexResult(CacheIRReader& reader) {\ spewOp(CacheOp::GetFirstDollarIndexResult);\ spewOperandId("strId", reader.stringOperandId());\ @@ -9507,6 +10403,14 @@ void spewGuardSpecificInt32(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardSpecificValue(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardSpecificValue);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewField("expectedOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewGuardNoDenseElements(CacheIRReader& reader) {\ spewOp(CacheOp::GuardNoDenseElements);\ spewOperandId("objId", reader.objOperandId());\ @@ -9729,6 +10633,12 @@ void spewGuardArgumentsObjectFlags(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewGuardObjectHasSameRealm(CacheIRReader& reader) {\ + spewOp(CacheOp::GuardObjectHasSameRealm);\ + spewOperandId("objId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadObject(CacheIRReader& reader) {\ spewOp(CacheOp::LoadObject);\ spewOperandId("resultId", reader.objOperandId());\ @@ -9831,6 +10741,22 @@ void spewMegamorphicLoadSlotByValueResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewField("nameOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("idId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMegamorphicStoreSlot(CacheIRReader& reader) {\ spewOp(CacheOp::MegamorphicStoreSlot);\ spewOperandId("objId", reader.objOperandId());\ @@ -10270,6 +11196,8 @@ void spewNewArrayFromLengthResult(CacheIRReader& reader) {\ spewField("templateObjectOffset", reader.stubOffset());\ spewArgSeparator();\ spewOperandId("lengthId", reader.int32OperandId());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -10301,6 +11229,34 @@ void spewNewTypedArrayFromArrayResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewNewMapObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewNewMapObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewMapObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewNewSetObjectFromIterableResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewSetObjectFromIterableResult);\ + spewField("templateObjectOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewOperandId("iterableId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewNewStringObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::NewStringObjectResult);\ spewField("templateObjectOffset", reader.stubOffset());\ @@ -10447,6 +11403,12 @@ void spewMathFRoundNumberResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMathF16RoundNumberResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MathF16RoundNumberResult);\ + spewOperandId("inputId", reader.numberOperandId());\ + spewOpEnd();\ +}\ +\ void spewMathRandomResult(CacheIRReader& reader) {\ spewOp(CacheOp::MathRandomResult);\ spewField("rngOffset", reader.stubOffset());\ @@ -10765,6 +11727,11 @@ void spewAtomicsIsLockFreeResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAtomicsPauseResult(CacheIRReader& reader) {\ + spewOp(CacheOp::AtomicsPauseResult);\ + spewOpEnd();\ +}\ +\ void spewCallNativeSetter(CacheIRReader& reader) {\ spewOp(CacheOp::CallNativeSetter);\ spewOperandId("receiverId", reader.objOperandId());\ @@ -10933,7 +11900,7 @@ void spewCallWasmFunction(CacheIRReader& reader) {\ spewArgSeparator();\ spewUInt32Imm("argcFixed", reader.uint32Immediate());\ spewArgSeparator();\ - spewField("funcExportOffset", reader.stubOffset());\ + spewField("funcTypeOffset", reader.stubOffset());\ spewArgSeparator();\ spewField("instanceOffset", reader.stubOffset());\ spewOpEnd();\ @@ -10975,6 +11942,22 @@ void spewCallDOMFunction(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewCallDOMFunctionWithAllocSite(CacheIRReader& reader) {\ + spewOp(CacheOp::CallDOMFunctionWithAllocSite);\ + spewOperandId("calleeId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("argcId", reader.int32OperandId());\ + spewArgSeparator();\ + spewOperandId("thisObjId", reader.objOperandId());\ + spewArgSeparator();\ + spewCallFlagsImm("flags", reader.callFlags());\ + spewArgSeparator();\ + spewUInt32Imm("argcFixed", reader.uint32Immediate());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ void spewCallClassHook(CacheIRReader& reader) {\ spewOp(CacheOp::CallClassHook);\ spewOperandId("calleeId", reader.objOperandId());\ @@ -11265,6 +12248,16 @@ void spewLoadBoundFunctionTarget(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewLoadBoundFunctionArgument(CacheIRReader& reader) {\ + spewOp(CacheOp::LoadBoundFunctionArgument);\ + spewOperandId("objId", reader.objOperandId());\ + spewArgSeparator();\ + spewUInt32Imm("index", reader.uint32Immediate());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewGuardBoundFunctionIsConstructor(CacheIRReader& reader) {\ spewOp(CacheOp::GuardBoundFunctionIsConstructor);\ spewOperandId("objId", reader.objOperandId());\ @@ -11741,6 +12734,80 @@ void spewBigIntPowResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntToIntPtr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntToIntPtr);\ + spewOperandId("inputId", reader.bigIntOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewIntPtrToBigIntResult(CacheIRReader& reader) {\ + spewOp(CacheOp::IntPtrToBigIntResult);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrAdd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrAdd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrSub(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrSub);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMul(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMul);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDiv(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDiv);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrMod(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrMod);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrPow(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrPow);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32BitOrResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32BitOrResult);\ spewOperandId("lhsId", reader.int32OperandId());\ @@ -11843,6 +12910,64 @@ void spewBigIntNotResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrBitOr(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitOr);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitXor(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitXor);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrBitAnd(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrBitAnd);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrLeftShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrLeftShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrRightShift(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrRightShift);\ + spewOperandId("lhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("rhsId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrNot(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNot);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32NegationResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32NegationResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11861,6 +12986,14 @@ void spewBigIntNegationResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrNegation(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrNegation);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewInt32IncResult(CacheIRReader& reader) {\ spewOp(CacheOp::Int32IncResult);\ spewOperandId("inputId", reader.int32OperandId());\ @@ -11897,6 +13030,22 @@ void spewBigIntDecResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewBigIntPtrInc(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrInc);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ +void spewBigIntPtrDec(CacheIRReader& reader) {\ + spewOp(CacheOp::BigIntPtrDec);\ + spewOperandId("inputId", reader.intPtrOperandId());\ + spewArgSeparator();\ + spewOperandId("resultId", reader.intPtrOperandId());\ + spewOpEnd();\ +}\ +\ void spewLoadInt32TruthyResult(CacheIRReader& reader) {\ spewOp(CacheOp::LoadInt32TruthyResult);\ spewOperandId("inputId", reader.valOperandId());\ @@ -11969,11 +13118,23 @@ void spewNewArrayObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ -void spewCallStringConcatResult(CacheIRReader& reader) {\ - spewOp(CacheOp::CallStringConcatResult);\ +void spewNewFunctionCloneResult(CacheIRReader& reader) {\ + spewOp(CacheOp::NewFunctionCloneResult);\ + spewField("canonicalOffset", reader.stubOffset());\ + spewArgSeparator();\ + spewAllocKindImm("allocKind", reader.allocKind());\ + spewArgSeparator();\ + spewField("siteOffset", reader.stubOffset());\ + spewOpEnd();\ +}\ +\ +void spewConcatStringsResult(CacheIRReader& reader) {\ + spewOp(CacheOp::ConcatStringsResult);\ spewOperandId("lhsId", reader.stringOperandId());\ spewArgSeparator();\ spewOperandId("rhsId", reader.stringOperandId());\ + spewArgSeparator();\ + spewField("stubOffset", reader.stubOffset());\ spewOpEnd();\ }\ \ @@ -12177,6 +13338,22 @@ void spewSetHasObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewSetDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetDeleteResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewSetAddResult(CacheIRReader& reader) {\ + spewOp(CacheOp::SetAddResult);\ + spewOperandId("setId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewSetSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::SetSizeResult);\ spewOperandId("setId", reader.objOperandId());\ @@ -12279,12 +13456,54 @@ void spewMapGetObjectResult(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewMapDeleteResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapDeleteResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewMapSetResult(CacheIRReader& reader) {\ + spewOp(CacheOp::MapSetResult);\ + spewOperandId("mapId", reader.objOperandId());\ + spewArgSeparator();\ + spewOperandId("keyId", reader.valOperandId());\ + spewArgSeparator();\ + spewOperandId("valId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewMapSizeResult(CacheIRReader& reader) {\ spewOp(CacheOp::MapSizeResult);\ spewOperandId("mapId", reader.objOperandId());\ spewOpEnd();\ }\ \ +void spewDateFillLocalTimeSlots(CacheIRReader& reader) {\ + spewOp(CacheOp::DateFillLocalTimeSlots);\ + spewOperandId("dateId", reader.objOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateHoursFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ +void spewDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader) {\ + spewOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + spewOperandId("secondsIntoYearId", reader.valOperandId());\ + spewOpEnd();\ +}\ +\ void spewArrayFromArgumentsObjectResult(CacheIRReader& reader) {\ spewOp(CacheOp::ArrayFromArgumentsObjectResult);\ spewOperandId("objId", reader.objOperandId());\ @@ -12326,6 +13545,14 @@ void spewBailout(CacheIRReader& reader) {\ spewOpEnd();\ }\ \ +void spewAssertFloat32Result(CacheIRReader& reader) {\ + spewOp(CacheOp::AssertFloat32Result);\ + spewOperandId("valId", reader.valOperandId());\ + spewArgSeparator();\ + spewBoolImm("mustBeFloat32", reader.readBool());\ + spewOpEnd();\ +}\ +\ void spewAssertRecoveredOnBailoutResult(CacheIRReader& reader) {\ spewOp(CacheOp::AssertRecoveredOnBailoutResult);\ spewOperandId("valId", reader.valOperandId());\ @@ -12601,6 +13828,16 @@ void cloneHasClassResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneHasShapeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::HasShapeResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t shapeOffset = reader.stubOffset();\ + Shape* shape = getShapeField(shapeOffset);\ + writer.writeShapeField(shape);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallRegExpMatcherResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallRegExpMatcherResult);\ ObjOperandId regexpId = reader.objOperandId();\ @@ -12707,22 +13944,6 @@ void cloneStringSplitStringResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ -void cloneRegExpPrototypeOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpPrototypeOptimizableResult);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ -void cloneRegExpInstanceOptimizableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::RegExpInstanceOptimizableResult);\ - ObjOperandId regexpId = reader.objOperandId();\ - writer.writeOperandId(regexpId);\ - ObjOperandId protoId = reader.objOperandId();\ - writer.writeOperandId(protoId);\ - writer.assertLengthMatches();\ -}}\ -\ void cloneGetFirstDollarIndexResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GetFirstDollarIndexResult);\ StringOperandId strId = reader.stringOperandId();\ @@ -12890,6 +14111,16 @@ void cloneGuardSpecificInt32(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneGuardSpecificValue(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardSpecificValue);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + uint32_t expectedOffset = reader.stubOffset();\ + const Value expected = getValueField(expectedOffset);\ + writer.writeValueField(expected);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardNoDenseElements(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardNoDenseElements);\ ObjOperandId objId = reader.objOperandId();\ @@ -13161,6 +14392,13 @@ void cloneGuardArgumentsObjectFlags(CacheIRReader& reader, CacheIRWriter& writer writer.assertLengthMatches();\ }}\ \ +void cloneGuardObjectHasSameRealm(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::GuardObjectHasSameRealm);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadObject(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadObject);\ ObjOperandId resultId = reader.objOperandId();\ @@ -13288,6 +14526,25 @@ void cloneMegamorphicLoadSlotByValueResult(CacheIRReader& reader, CacheIRWriter& writer.assertLengthMatches();\ }}\ \ +void cloneMegamorphicLoadSlotPermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotPermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t nameOffset = reader.stubOffset();\ + jsid name = getIdField(nameOffset);\ + writer.writeIdField(name);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMegamorphicLoadSlotByValuePermissiveResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MegamorphicLoadSlotByValuePermissiveResult);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + ValOperandId idId = reader.valOperandId();\ + writer.writeOperandId(idId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMegamorphicStoreSlot(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MegamorphicStoreSlot);\ ObjOperandId objId = reader.objOperandId();\ @@ -13812,6 +15069,9 @@ void cloneNewArrayFromLengthResult(CacheIRReader& reader, CacheIRWriter& writer) writer.writeObjectField(templateObject);\ Int32OperandId lengthId = reader.int32OperandId();\ writer.writeOperandId(lengthId);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ writer.assertLengthMatches();\ }}\ \ @@ -13849,6 +15109,42 @@ void cloneNewTypedArrayFromArrayResult(CacheIRReader& reader, CacheIRWriter& wri writer.assertLengthMatches();\ }}\ \ +void cloneNewMapObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewMapObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewMapObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneNewSetObjectFromIterableResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewSetObjectFromIterableResult);\ + uint32_t templateObjectOffset = reader.stubOffset();\ + JSObject* templateObject = getObjectField(templateObjectOffset);\ + writer.writeObjectField(templateObject);\ + ValOperandId iterableId = reader.valOperandId();\ + writer.writeOperandId(iterableId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneNewStringObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::NewStringObjectResult);\ uint32_t templateObjectOffset = reader.stubOffset();\ @@ -14018,6 +15314,13 @@ void cloneMathFRoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) { writer.assertLengthMatches();\ }}\ \ +void cloneMathF16RoundNumberResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MathF16RoundNumberResult);\ + NumberOperandId inputId = reader.numberOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMathRandomResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MathRandomResult);\ uint32_t rngOffset = reader.stubOffset();\ @@ -14371,6 +15674,11 @@ void cloneAtomicsIsLockFreeResult(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneAtomicsPauseResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AtomicsPauseResult);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallNativeSetter(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallNativeSetter);\ ObjOperandId receiverId = reader.objOperandId();\ @@ -14565,9 +15873,9 @@ void cloneCallWasmFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeCallFlagsImm(flags);\ uint32_t argcFixed = reader.uint32Immediate();\ writer.writeUInt32Imm(argcFixed);\ - uint32_t funcExportOffset = reader.stubOffset();\ - const void* funcExport = getRawPointerField(funcExportOffset);\ - writer.writeRawPointerField(funcExport);\ + uint32_t funcTypeOffset = reader.stubOffset();\ + const void* funcType = getRawPointerField(funcTypeOffset);\ + writer.writeRawPointerField(funcType);\ uint32_t instanceOffset = reader.stubOffset();\ JSObject* instance = getObjectField(instanceOffset);\ writer.writeObjectField(instance);\ @@ -14613,6 +15921,24 @@ void cloneCallDOMFunction(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneCallDOMFunctionWithAllocSite(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::CallDOMFunctionWithAllocSite);\ + ObjOperandId calleeId = reader.objOperandId();\ + writer.writeOperandId(calleeId);\ + Int32OperandId argcId = reader.int32OperandId();\ + writer.writeOperandId(argcId);\ + ObjOperandId thisObjId = reader.objOperandId();\ + writer.writeOperandId(thisObjId);\ + CallFlags flags = reader.callFlags();\ + writer.writeCallFlagsImm(flags);\ + uint32_t argcFixed = reader.uint32Immediate();\ + writer.writeUInt32Imm(argcFixed);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneCallClassHook(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::CallClassHook);\ ObjOperandId calleeId = reader.objOperandId();\ @@ -14946,6 +16272,18 @@ void cloneLoadBoundFunctionTarget(CacheIRReader& reader, CacheIRWriter& writer) writer.assertLengthMatches();\ }}\ \ +void cloneLoadBoundFunctionArgument(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::LoadBoundFunctionArgument);\ + ObjOperandId objId = reader.objOperandId();\ + writer.writeOperandId(objId);\ + uint32_t index = reader.uint32Immediate();\ + writer.writeUInt32Imm(index);\ + ValOperandId resultId = reader.valOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneGuardBoundFunctionIsConstructor(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::GuardBoundFunctionIsConstructor);\ ObjOperandId objId = reader.objOperandId();\ @@ -15501,6 +16839,95 @@ void cloneBigIntPowResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntToIntPtr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntToIntPtr);\ + BigIntOperandId inputId = reader.bigIntOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneIntPtrToBigIntResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::IntPtrToBigIntResult);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrAdd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrAdd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrSub(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrSub);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMul(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMul);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDiv(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDiv);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrMod(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrMod);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrPow(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrPow);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32BitOrResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32BitOrResult);\ Int32OperandId lhsId = reader.int32OperandId();\ @@ -15616,6 +17043,76 @@ void cloneBigIntNotResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrBitOr(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitOr);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitXor(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitXor);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrBitAnd(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrBitAnd);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrLeftShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrLeftShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrRightShift(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrRightShift);\ + IntPtrOperandId lhsId = reader.intPtrOperandId();\ + writer.writeOperandId(lhsId);\ + IntPtrOperandId rhsId = reader.intPtrOperandId();\ + writer.writeOperandId(rhsId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrNot(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNot);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32NegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32NegationResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15637,6 +17134,16 @@ void cloneBigIntNegationResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrNegation(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrNegation);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneInt32IncResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::Int32IncResult);\ Int32OperandId inputId = reader.int32OperandId();\ @@ -15679,6 +17186,26 @@ void cloneBigIntDecResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneBigIntPtrInc(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrInc);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneBigIntPtrDec(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::BigIntPtrDec);\ + IntPtrOperandId inputId = reader.intPtrOperandId();\ + writer.writeOperandId(inputId);\ + IntPtrOperandId resultId = reader.intPtrOperandId();\ + writer.newOperandId();\ + writer.writeOperandId(resultId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneLoadInt32TruthyResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::LoadInt32TruthyResult);\ ValOperandId inputId = reader.valOperandId();\ @@ -15766,12 +17293,28 @@ void cloneNewArrayObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ -void cloneCallStringConcatResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ - writer.writeOp(CacheOp::CallStringConcatResult);\ +void cloneNewFunctionCloneResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::NewFunctionCloneResult);\ + uint32_t canonicalOffset = reader.stubOffset();\ + JSObject* canonical = getObjectField(canonicalOffset);\ + writer.writeObjectField(canonical);\ + gc::AllocKind allocKind = reader.allocKind();\ + writer.writeAllocKindImm(allocKind);\ + uint32_t siteOffset = reader.stubOffset();\ + gc::AllocSite* site = getAllocSiteField(siteOffset);\ + writer.writeAllocSiteField(site);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneConcatStringsResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::ConcatStringsResult);\ StringOperandId lhsId = reader.stringOperandId();\ writer.writeOperandId(lhsId);\ StringOperandId rhsId = reader.stringOperandId();\ writer.writeOperandId(rhsId);\ + uint32_t stubOffset = reader.stubOffset();\ + JitCode* stub = getJitCodeField(stubOffset);\ + writer.writeJitCodeField(stub);\ writer.assertLengthMatches();\ }}\ \ @@ -15998,6 +17541,24 @@ void cloneSetHasObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneSetDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetDeleteResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneSetAddResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::SetAddResult);\ + ObjOperandId setId = reader.objOperandId();\ + writer.writeOperandId(setId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneSetSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::SetSizeResult);\ ObjOperandId setId = reader.objOperandId();\ @@ -16113,6 +17674,26 @@ void cloneMapGetObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneMapDeleteResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapDeleteResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneMapSetResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::MapSetResult);\ + ObjOperandId mapId = reader.objOperandId();\ + writer.writeOperandId(mapId);\ + ValOperandId keyId = reader.valOperandId();\ + writer.writeOperandId(keyId);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::MapSizeResult);\ ObjOperandId mapId = reader.objOperandId();\ @@ -16120,6 +17701,34 @@ void cloneMapSizeResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneDateFillLocalTimeSlots(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateFillLocalTimeSlots);\ + ObjOperandId dateId = reader.objOperandId();\ + writer.writeOperandId(dateId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateHoursFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateHoursFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateMinutesFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateMinutesFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ +void cloneDateSecondsFromSecondsIntoYearResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::DateSecondsFromSecondsIntoYearResult);\ + ValOperandId secondsIntoYearId = reader.valOperandId();\ + writer.writeOperandId(secondsIntoYearId);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneArrayFromArgumentsObjectResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::ArrayFromArgumentsObjectResult);\ ObjOperandId objId = reader.objOperandId();\ @@ -16165,6 +17774,15 @@ void cloneBailout(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.assertLengthMatches();\ }}\ \ +void cloneAssertFloat32Result(CacheIRReader& reader, CacheIRWriter& writer) {{\ + writer.writeOp(CacheOp::AssertFloat32Result);\ + ValOperandId valId = reader.valOperandId();\ + writer.writeOperandId(valId);\ + bool mustBeFloat32 = reader.readBool();\ + writer.writeBoolImm(mustBeFloat32);\ + writer.assertLengthMatches();\ +}}\ +\ void cloneAssertRecoveredOnBailoutResult(CacheIRReader& reader, CacheIRWriter& writer) {{\ writer.writeOp(CacheOp::AssertRecoveredOnBailoutResult);\ ValOperandId valId = reader.valOperandId();\ diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/jit/LIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/windows/include/jit/LIROpsGenerated.h index d1a14641c21..732d434d9c5 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/jit/LIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/jit/LIROpsGenerated.h @@ -18,74 +18,54 @@ _(Pointer)\ _(Double)\ _(Float32)\ _(Value)\ -_(NurseryObject)\ _(Parameter)\ -_(Callee)\ -_(IsConstructing)\ _(Goto)\ _(NewArray)\ -_(NewArrayDynamicLength)\ _(NewIterator)\ _(NewTypedArray)\ -_(NewTypedArrayDynamicLength)\ -_(NewTypedArrayFromArray)\ -_(NewTypedArrayFromArrayBuffer)\ _(BindFunction)\ -_(NewBoundFunction)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ -_(NewNamedLambdaObject)\ _(NewCallObject)\ +_(NewMapObject)\ +_(NewSetObject)\ _(NewStringObject)\ _(InitElemGetterSetter)\ _(MutateProto)\ _(InitPropGetterSetter)\ -_(CheckOverRecursed)\ -_(WasmTrap)\ -_(WasmTrapIfNull)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ -_(WasmRefIsSubtypeOfConcreteAndBranch)\ -_(WasmRefIsSubtypeOfAbstractAndBranch)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefTestConcreteAndBranch)\ +_(WasmRefTestAbstractAndBranch)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ _(WasmNewStructObject)\ _(WasmNewArrayObject)\ -_(WasmReinterpret)\ -_(WasmReinterpretFromI64)\ -_(WasmReinterpretToI64)\ +_(ReinterpretCast)\ +_(ReinterpretCastFromI64)\ +_(ReinterpretCastToI64)\ _(Rotate)\ _(RotateI64)\ -_(InterruptCheck)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ _(WasmStackContinueOnSuspendable)\ _(WasmInterruptCheck)\ _(TypeOfV)\ _(TypeOfO)\ -_(TypeOfName)\ _(TypeOfIsNonPrimitiveV)\ _(TypeOfIsNonPrimitiveO)\ _(TypeOfIsPrimitive)\ _(ToAsyncIter)\ -_(ToPropertyKeyCache)\ -_(CreateThis)\ _(CreateArgumentsObject)\ _(CreateInlinedArgumentsObject)\ _(GetInlinedArgument)\ _(GetInlinedArgumentHole)\ -_(GetArgumentsObjectArg)\ -_(SetArgumentsObjectArg)\ -_(LoadArgumentsObjectArg)\ -_(LoadArgumentsObjectArgHole)\ -_(InArgumentsObjectArg)\ -_(ArgumentsObjectLength)\ -_(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ -_(BoundFunctionNumArgs)\ +_(GuardObjectHasSameRealm)\ _(GuardBoundFunctionIsConstructor)\ -_(ReturnFromCtor)\ _(BoxNonStrictThis)\ -_(ImplicitThis)\ _(StackArgT)\ _(StackArgV)\ _(CallGeneric)\ @@ -93,18 +73,14 @@ _(CallKnown)\ _(CallNative)\ _(CallDOMNative)\ _(CallClassHook)\ -_(Bail)\ _(Unreachable)\ -_(EncodeSnapshot)\ _(UnreachableResultV)\ _(UnreachableResultT)\ _(GetDOMProperty)\ _(GetDOMMemberV)\ _(GetDOMMemberT)\ _(SetDOMProperty)\ -_(LoadDOMExpandoValue)\ _(LoadDOMExpandoValueGuardGeneration)\ -_(LoadDOMExpandoValueIgnoreGeneration)\ _(GuardDOMExpandoMissingOrGuardShape)\ _(ApplyArgsGeneric)\ _(ApplyArgsObj)\ @@ -117,6 +93,7 @@ _(ApplyArrayNative)\ _(ConstructArgsNative)\ _(ConstructArrayNative)\ _(TestIAndBranch)\ +_(TestIPtrAndBranch)\ _(TestI64AndBranch)\ _(TestDAndBranch)\ _(TestFAndBranch)\ @@ -138,7 +115,9 @@ _(CompareBigInt)\ _(CompareBigIntInt32)\ _(CompareBigIntDouble)\ _(CompareBigIntString)\ +_(CompareBigIntInt32AndBranch)\ _(BitAndAndBranch)\ +_(BitAnd64AndBranch)\ _(IsNullOrLikeUndefinedV)\ _(IsNullOrLikeUndefinedT)\ _(IsNull)\ @@ -147,9 +126,8 @@ _(IsNullOrLikeUndefinedAndBranchV)\ _(IsNullOrLikeUndefinedAndBranchT)\ _(IsNullAndBranch)\ _(IsUndefinedAndBranch)\ -_(SameValueDouble)\ -_(SameValue)\ _(NotI)\ +_(NotIPtr)\ _(NotI64)\ _(NotD)\ _(NotF)\ @@ -163,11 +141,10 @@ _(BitOpI64)\ _(ShiftI)\ _(ShiftI64)\ _(SignExtendInt32)\ +_(SignExtendIntPtr)\ _(SignExtendInt64)\ _(UrshD)\ _(Return)\ -_(Throw)\ -_(ThrowWithStack)\ _(MinMaxI)\ _(MinMaxD)\ _(MinMaxF)\ @@ -199,6 +176,7 @@ _(PowOfTwoI)\ _(SignI)\ _(SignD)\ _(SignDI)\ +_(SignID)\ _(MathFunctionD)\ _(MathFunctionF)\ _(AddI)\ @@ -226,48 +204,42 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ -_(Int32ToStringWithBase)\ -_(NumberParseInt)\ -_(DoubleParseInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrDivPowTwo)\ +_(BigIntPtrMod)\ +_(BigIntPtrModPowTwo)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Concat)\ -_(LinearizeString)\ -_(LinearizeForCharAccess)\ -_(LinearizeForCodePointAccess)\ -_(ToRelativeStringIndex)\ -_(CharCodeAt)\ -_(CharCodeAtOrNegative)\ -_(CodePointAt)\ -_(CodePointAtOrNegative)\ -_(NegativeToNaN)\ -_(NegativeToUndefined)\ -_(FromCharCode)\ -_(FromCharCodeEmptyIfNegative)\ -_(FromCharCodeUndefinedIfNegative)\ -_(FromCodePoint)\ -_(StringIncludes)\ _(StringIncludesSIMD)\ -_(StringIndexOf)\ _(StringIndexOfSIMD)\ -_(StringLastIndexOf)\ -_(StringStartsWith)\ _(StringStartsWithInline)\ -_(StringEndsWith)\ _(StringEndsWithInline)\ _(StringToLowerCase)\ _(CharCodeToLowerCase)\ _(StringToUpperCase)\ _(CharCodeToUpperCase)\ -_(StringTrimStartIndex)\ -_(StringTrimEndIndex)\ -_(StringSplit)\ -_(Substr)\ _(Int32ToDouble)\ _(Float32ToDouble)\ _(DoubleToFloat32)\ _(Int32ToFloat32)\ +_(DoubleToFloat16)\ +_(DoubleToFloat32ToFloat16)\ +_(Float32ToFloat16)\ +_(Int32ToFloat16)\ _(ValueToDouble)\ _(ValueToFloat32)\ -_(ValueToInt32)\ +_(ValueToFloat16)\ +_(ValueToNumberInt32)\ +_(ValueTruncateToInt32)\ _(ValueToBigInt)\ _(DoubleToInt32)\ _(Float32ToInt32)\ @@ -290,45 +262,21 @@ _(OsrEnvironmentChain)\ _(OsrReturnValue)\ _(OsrArgumentsObject)\ _(RegExp)\ -_(RegExpMatcher)\ -_(RegExpSearcher)\ -_(RegExpSearcherLastLimit)\ -_(RegExpExecMatch)\ -_(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(BinaryValueCache)\ _(BinaryBoolCache)\ -_(UnaryCache)\ _(ModuleMetadata)\ _(DynamicImport)\ _(Lambda)\ _(FunctionWithProto)\ -_(SetFunName)\ _(KeepAliveObject)\ _(DebugEnterGCUnsafeRegion)\ _(DebugLeaveGCUnsafeRegion)\ -_(Slots)\ -_(Elements)\ -_(InitializedLength)\ -_(SetInitializedLength)\ -_(ArrayLength)\ -_(SetArrayLength)\ -_(FunctionLength)\ -_(FunctionName)\ _(GetNextEntryForIterator)\ -_(ArrayBufferByteLength)\ -_(ArrayBufferViewLength)\ -_(ArrayBufferViewByteOffset)\ -_(ArrayBufferViewElements)\ -_(TypedArrayElementSize)\ _(ResizableTypedArrayLength)\ -_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ _(ResizableDataViewByteLength)\ -_(GrowableSharedArrayBufferByteLength)\ _(GuardResizableArrayBufferViewInBounds)\ _(GuardResizableArrayBufferViewInBoundsOrDetached)\ _(GuardHasAttachedArrayBuffer)\ @@ -347,25 +295,22 @@ _(StoreHoleValueElement)\ _(StoreElementHoleV)\ _(StoreElementHoleT)\ _(ArrayPopShift)\ -_(ArrayPush)\ -_(ArraySlice)\ -_(ArgumentsSlice)\ _(FrameArgumentsSlice)\ _(InlineArgumentsSlice)\ -_(NormalizeSliceTerm)\ -_(ArrayJoin)\ _(ObjectKeys)\ _(ObjectKeysLength)\ _(LoadUnboxedScalar)\ -_(LoadUnboxedBigInt)\ +_(LoadUnboxedInt64)\ _(LoadDataViewElement)\ +_(LoadDataViewElement64)\ _(LoadTypedArrayElementHole)\ _(LoadTypedArrayElementHoleBigInt)\ _(StoreUnboxedScalar)\ -_(StoreUnboxedBigInt)\ +_(StoreUnboxedInt64)\ _(StoreDataViewElement)\ +_(StoreDataViewElement64)\ _(StoreTypedArrayElementHole)\ -_(StoreTypedArrayElementHoleBigInt)\ +_(StoreTypedArrayElementHoleInt64)\ _(AtomicIsLockFree)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ @@ -381,9 +326,6 @@ _(EffectiveAddress)\ _(ClampIToUint8)\ _(ClampDToUint8)\ _(ClampVToUint8)\ -_(LoadScriptedProxyHandler)\ -_(CheckScriptedProxyGetResult)\ -_(IdToStringOrSymbol)\ _(LoadFixedSlotV)\ _(LoadFixedSlotAndAtomize)\ _(LoadFixedSlotT)\ @@ -393,21 +335,14 @@ _(LoadElementAndUnbox)\ _(LoadFixedSlotUnboxAndAtomize)\ _(LoadDynamicSlotUnboxAndAtomize)\ _(AddAndStoreSlot)\ -_(AllocateAndStoreSlot)\ -_(AddSlotAndCallAddPropHook)\ _(StoreFixedSlotV)\ _(StoreFixedSlotT)\ -_(GetNameCache)\ -_(CallGetIntrinsicValue)\ _(GetPropSuperCache)\ _(GetPropertyCache)\ -_(BindNameCache)\ -_(CallBindVar)\ _(LoadDynamicSlotV)\ _(LoadDynamicSlotAndAtomize)\ _(StoreDynamicSlotV)\ _(StoreDynamicSlotT)\ -_(StringLength)\ _(Floor)\ _(FloorF)\ _(Ceil)\ @@ -418,9 +353,6 @@ _(Trunc)\ _(TruncF)\ _(NearbyInt)\ _(NearbyIntF)\ -_(FunctionEnvironment)\ -_(HomeObject)\ -_(HomeObjectSuperBase)\ _(NewLexicalEnvironmentObject)\ _(NewClassBodyEnvironmentObject)\ _(NewVarEnvironmentObject)\ @@ -430,20 +362,10 @@ _(CallDeleteElement)\ _(ObjectToIterator)\ _(ValueToIterator)\ _(IteratorHasIndicesAndBranch)\ -_(LoadSlotByIteratorIndex)\ -_(StoreSlotByIteratorIndex)\ _(SetPropertyCache)\ _(GetIteratorCache)\ -_(OptimizeSpreadCallCache)\ -_(IteratorMore)\ _(IsNoIterAndBranch)\ -_(IteratorEnd)\ _(CloseIterCache)\ -_(OptimizeGetIteratorCache)\ -_(ArgumentsLength)\ -_(GetFrameArgument)\ -_(GetFrameArgumentHole)\ -_(Rest)\ _(Int32ToIntPtr)\ _(NonNegativeIntPtrToInt32)\ _(IntPtrToDouble)\ @@ -453,6 +375,9 @@ _(StringToInt64)\ _(ValueToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Uint64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(PostWriteBarrierO)\ _(PostWriteBarrierS)\ _(PostWriteBarrierBI)\ @@ -467,11 +392,6 @@ _(GuardSpecificFunction)\ _(GuardSpecificAtom)\ _(GuardSpecificSymbol)\ _(GuardSpecificInt32)\ -_(GuardStringToIndex)\ -_(GuardStringToInt32)\ -_(GuardStringToDouble)\ -_(GuardShape)\ -_(GuardMultipleShapes)\ _(GuardProto)\ _(GuardNullProto)\ _(GuardIsNativeObject)\ @@ -480,17 +400,7 @@ _(GuardFuse)\ _(GuardIsProxy)\ _(GuardIsNotProxy)\ _(GuardIsNotDOMProxy)\ -_(ProxyGet)\ -_(ProxyGetByValue)\ _(ProxyHasProp)\ -_(ProxySet)\ -_(ProxySetByValue)\ -_(CallSetArrayLength)\ -_(MegamorphicLoadSlot)\ -_(MegamorphicLoadSlotByValue)\ -_(MegamorphicStoreSlot)\ -_(MegamorphicHasProp)\ -_(SmallObjectVariableKeyHasProp)\ _(GuardIsNotArrayBufferMaybeShared)\ _(GuardIsTypedArray)\ _(GuardIsFixedLengthTypedArray)\ @@ -500,26 +410,19 @@ _(GuardNoDenseElements)\ _(InCache)\ _(HasOwnCache)\ _(CheckPrivateFieldCache)\ -_(NewPrivateName)\ _(InstanceOfO)\ _(InstanceOfV)\ -_(InstanceOfCache)\ _(IsCallableO)\ _(IsCallableV)\ -_(IsConstructor)\ -_(IsCrossRealmArrayConstructor)\ _(IsArrayO)\ _(IsArrayV)\ _(IsTypedArray)\ -_(IsObject)\ _(IsObjectAndBranch)\ -_(IsNullOrUndefined)\ _(IsNullOrUndefinedAndBranch)\ _(HasClass)\ _(GuardToClass)\ _(GuardToEitherClass)\ _(GuardToFunction)\ -_(ObjectClassToString)\ _(WasmSelect)\ _(WasmSelectI64)\ _(WasmCompareAndSelect)\ @@ -527,7 +430,6 @@ _(WasmAddOffset)\ _(WasmAddOffset64)\ _(WasmBoundsCheck)\ _(WasmBoundsCheck64)\ -_(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ _(WasmAlignmentCheck)\ @@ -542,7 +444,6 @@ _(WasmStoreI64)\ _(AsmJSLoadHeap)\ _(AsmJSStoreHeap)\ _(WasmCompareExchangeHeap)\ -_(WasmFence)\ _(WasmAtomicExchangeHeap)\ _(WasmAtomicBinopHeap)\ _(WasmAtomicBinopHeapForEffect)\ @@ -552,6 +453,8 @@ _(WasmLoadSlotI64)\ _(WasmLoadElementI64)\ _(WasmStoreSlot)\ _(WasmStoreSlotI64)\ +_(WasmStoreStackResult)\ +_(WasmStoreStackResultI64)\ _(WasmStoreElement)\ _(WasmStoreElementI64)\ _(WasmStoreElementRef)\ @@ -559,8 +462,8 @@ _(WasmLoadTableElement)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmParameterI64)\ _(WasmReturn)\ @@ -571,7 +474,6 @@ _(WasmStackArgI64)\ _(WasmNullConstant)\ _(WasmCallIndirectAdjunctSafepoint)\ _(WasmCall)\ -_(WasmCallLandingPrePad)\ _(WasmRegisterResult)\ _(WasmRegisterPairResult)\ _(WasmStackResultArea)\ @@ -590,17 +492,12 @@ _(GuardFunctionFlags)\ _(GuardFunctionIsNonBuiltinCtor)\ _(GuardFunctionKind)\ _(GuardFunctionScript)\ -_(IncrementWarmUpCounter)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ -_(GlobalDeclInstantiation)\ _(MemoryBarrier)\ _(Debugger)\ -_(NewTarget)\ _(Random)\ -_(CheckReturn)\ -_(CheckIsObj)\ _(CheckObjCoercible)\ _(CheckClassHeritage)\ _(CheckThis)\ @@ -612,67 +509,22 @@ _(AsyncAwait)\ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(DebugCheckSelfHosted)\ -_(IsPackedArray)\ _(GuardArrayIsPacked)\ -_(GetPrototypeOf)\ -_(ObjectWithProto)\ _(ObjectStaticProto)\ -_(BuiltinObject)\ -_(SuperFunction)\ -_(InitHomeObject)\ -_(IsTypedArrayConstructor)\ -_(LoadValueTag)\ _(GuardTagNotEqual)\ -_(LoadWrapperTarget)\ _(GuardHasGetterSetter)\ _(GuardIsExtensible)\ _(GuardInt32IsNonNegative)\ _(GuardInt32Range)\ _(GuardIndexIsNotDenseElement)\ _(GuardIndexIsValidUpdateOrAdd)\ -_(CallAddOrUpdateSparseElement)\ -_(CallGetSparseElement)\ -_(CallNativeGetElement)\ -_(CallNativeGetElementSuper)\ -_(CallObjectHasSparseElement)\ -_(BigIntAsIntN)\ -_(BigIntAsIntN64)\ -_(BigIntAsIntN32)\ _(GuardNonGCThing)\ -_(ToHashableNonGCThing)\ -_(ToHashableString)\ -_(ToHashableValue)\ -_(HashNonGCThing)\ -_(HashString)\ -_(HashSymbol)\ -_(HashBigInt)\ -_(HashObject)\ -_(HashValue)\ -_(SetObjectHasNonBigInt)\ -_(SetObjectHasBigInt)\ -_(SetObjectHasValue)\ -_(SetObjectHasValueVMCall)\ -_(SetObjectSize)\ -_(MapObjectHasNonBigInt)\ -_(MapObjectHasBigInt)\ -_(MapObjectHasValue)\ -_(MapObjectHasValueVMCall)\ -_(MapObjectGetNonBigInt)\ -_(MapObjectGetBigInt)\ -_(MapObjectGetValue)\ -_(MapObjectGetValueVMCall)\ -_(MapObjectSize)\ -_(BigIntAsUintN)\ -_(BigIntAsUintN64)\ -_(BigIntAsUintN32)\ +_(CanonicalizeNaND)\ +_(CanonicalizeNaNF)\ _(IonToWasmCall)\ _(IonToWasmCallV)\ _(IonToWasmCallI64)\ -_(WasmAnyRefFromJSValue)\ -_(WasmAnyRefFromJSObject)\ -_(WasmAnyRefFromJSString)\ _(WasmNewI31Ref)\ -_(WasmI31RefGet)\ _(Simd128)\ _(WasmTernarySimd128)\ _(WasmBinarySimd128)\ @@ -686,7 +538,6 @@ _(WasmReplaceLaneSimd128)\ _(WasmReplaceInt64LaneSimd128)\ _(WasmScalarToSimd128)\ _(WasmInt64ToSimd128)\ -_(WasmUnarySimd128)\ _(WasmReduceSimd128)\ _(WasmReduceAndBranchSimd128)\ _(WasmReduceSimd128ToInt64)\ @@ -702,113 +553,290 @@ _(DivPowTwoI)\ _(ModPowTwoI)\ _(TableSwitch)\ _(TableSwitchV)\ -_(MulI) +_(MulI)\ +_(Callee)\ +_(IsConstructing)\ +_(Throw)\ +_(ThrowWithStack)\ +_(NewArrayDynamicLength)\ +_(NewTypedArrayDynamicLength)\ +_(NewTypedArrayFromArray)\ +_(NewTypedArrayFromArrayBuffer)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ +_(NewBoundFunction)\ +_(BoundFunctionNumArgs)\ +_(Bail)\ +_(EncodeSnapshot)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ +_(SameValueDouble)\ +_(SameValue)\ +_(CreateThis)\ +_(GetArgumentsObjectArg)\ +_(SetArgumentsObjectArg)\ +_(LoadArgumentsObjectArg)\ +_(LoadArgumentsObjectArgHole)\ +_(InArgumentsObjectArg)\ +_(ArgumentsObjectLength)\ +_(ArrayFromArgumentsObject)\ +_(LoadScriptedProxyHandler)\ +_(CheckScriptedProxyGetResult)\ +_(IdToStringOrSymbol)\ +_(ReturnFromCtor)\ +_(WasmAnyRefFromJSValue)\ +_(WasmAnyRefFromJSObject)\ +_(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ +_(WasmI31RefGet)\ +_(TypeOfName)\ +_(ToPropertyKeyCache)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(Int32ToStringWithBase)\ +_(NumberParseInt)\ +_(DoubleParseInt)\ +_(LinearizeString)\ +_(LinearizeForCharAccess)\ +_(LinearizeForCodePointAccess)\ +_(ToRelativeStringIndex)\ +_(CharCodeAt)\ +_(CharCodeAtOrNegative)\ +_(CodePointAt)\ +_(CodePointAtOrNegative)\ +_(NegativeToNaN)\ +_(NegativeToUndefined)\ +_(FromCharCode)\ +_(FromCharCodeEmptyIfNegative)\ +_(FromCharCodeUndefinedIfNegative)\ +_(FromCodePoint)\ +_(StringIncludes)\ +_(StringIndexOf)\ +_(StringLastIndexOf)\ +_(StringStartsWith)\ +_(StringEndsWith)\ +_(StringTrimStartIndex)\ +_(StringTrimEndIndex)\ +_(StringSplit)\ +_(ImplicitThis)\ +_(UnaryCache)\ +_(CheckOverRecursed)\ +_(InterruptCheck)\ +_(WasmTrap)\ +_(GlobalDeclInstantiation)\ +_(RegExpMatcher)\ +_(RegExpSearcher)\ +_(RegExpSearcherLastLimit)\ +_(RegExpExecMatch)\ +_(RegExpExecTest)\ +_(Substr)\ +_(SetFunName)\ +_(Slots)\ +_(Elements)\ +_(InitializedLength)\ +_(SetInitializedLength)\ +_(ArrayLength)\ +_(SetArrayLength)\ +_(FunctionLength)\ +_(FunctionName)\ +_(ArrayBufferByteLength)\ +_(ArrayBufferViewLength)\ +_(ArrayBufferViewByteOffset)\ +_(ArrayBufferViewElements)\ +_(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ +_(GrowableSharedArrayBufferByteLength)\ +_(TypedArrayElementSize)\ +_(ArrayPush)\ +_(ArraySlice)\ +_(ArgumentsSlice)\ +_(NormalizeSliceTerm)\ +_(ArrayJoin)\ +_(HomeObjectSuperBase)\ +_(BindNameCache)\ +_(CallBindVar)\ +_(GuardShape)\ +_(HasShape)\ +_(GuardMultipleShapes)\ +_(ProxyGet)\ +_(ProxyGetByValue)\ +_(ProxySet)\ +_(ProxySetByValue)\ +_(CallSetArrayLength)\ +_(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ +_(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ +_(MegamorphicStoreSlot)\ +_(MegamorphicHasProp)\ +_(SmallObjectVariableKeyHasProp)\ +_(NurseryObject)\ +_(GuardStringToIndex)\ +_(GuardStringToInt32)\ +_(GuardStringToDouble)\ +_(FunctionEnvironment)\ +_(HomeObject)\ +_(AllocateAndStoreSlot)\ +_(AddSlotAndCallAddPropHook)\ +_(GetNameCache)\ +_(CallGetIntrinsicValue)\ +_(LoadSlotByIteratorIndex)\ +_(StoreSlotByIteratorIndex)\ +_(LoadDOMExpandoValue)\ +_(LoadDOMExpandoValueIgnoreGeneration)\ +_(StringLength)\ +_(OptimizeSpreadCallCache)\ +_(IteratorMore)\ +_(IteratorEnd)\ +_(OptimizeGetIteratorCache)\ +_(NewPrivateName)\ +_(InstanceOfCache)\ +_(ArgumentsLength)\ +_(GetFrameArgument)\ +_(GetFrameArgumentHole)\ +_(NewTarget)\ +_(Rest)\ +_(NewNamedLambdaObject)\ +_(IsConstructor)\ +_(IsCrossRealmArrayConstructor)\ +_(IsObject)\ +_(IsNullOrUndefined)\ +_(ObjectClassToString)\ +_(CheckReturn)\ +_(IncrementWarmUpCounter)\ +_(AtomicPause)\ +_(CheckIsObj)\ +_(IsPackedArray)\ +_(GetPrototypeOf)\ +_(ObjectWithProto)\ +_(BuiltinObject)\ +_(SuperFunction)\ +_(InitHomeObject)\ +_(IsTypedArrayConstructor)\ +_(LoadValueTag)\ +_(LoadWrapperTarget)\ +_(CallAddOrUpdateSparseElement)\ +_(CallGetSparseElement)\ +_(CallNativeGetElement)\ +_(CallNativeGetElementSuper)\ +_(CallObjectHasSparseElement)\ +_(BigIntAsIntN)\ +_(BigIntAsUintN)\ +_(ToHashableNonGCThing)\ +_(ToHashableString)\ +_(ToHashableValue)\ +_(HashNonGCThing)\ +_(HashString)\ +_(HashSymbol)\ +_(HashBigInt)\ +_(HashObject)\ +_(HashValue)\ +_(SetObjectHasNonBigInt)\ +_(SetObjectHasBigInt)\ +_(SetObjectHasValue)\ +_(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ +_(SetObjectSize)\ +_(MapObjectHasNonBigInt)\ +_(MapObjectHasBigInt)\ +_(MapObjectHasValue)\ +_(MapObjectHasValueVMCall)\ +_(MapObjectGetNonBigInt)\ +_(MapObjectGetBigInt)\ +_(MapObjectGetValue)\ +_(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ +_(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ +_(WasmBoundsCheckRange32)\ +_(WasmClampTable64Address)\ +_(WasmFence)\ +_(WasmCallLandingPrePad)\ +_(WasmUnarySimd128) #define LIR_OPCODE_CLASS_GENERATED \ +class LBox : public LInstructionHelper {\ + MIRType type_;\ + public:\ + LIR_HEADER(Box)\ + static constexpr size_t PayloadIndex = 0;\ + explicit LBox(const LAllocation& payload, MIRType type) : LInstructionHelper(classOpcode), type_(type) {\ + setOperand(PayloadIndex, payload);\ + }\ + const LAllocation* payload() const { return getOperand(PayloadIndex); }\ + MIRType type() const { return type_; }\ + inline const char* extraName() const;\ +};\ class LInteger : public LInstructionHelper<1, 0, 0> {\ int32_t i32_;\ public:\ LIR_HEADER(Integer)\ explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {\ -\ }\ int32_t i32() const { return i32_; }\ -\ };\ -\ class LInteger64 : public LInstructionHelper {\ int64_t i64_;\ public:\ LIR_HEADER(Integer64)\ explicit LInteger64(int64_t i64) : LInstructionHelper(classOpcode), i64_(i64) {\ -\ }\ int64_t i64() const { return i64_; }\ -\ };\ -\ class LPointer : public LInstructionHelper<1, 0, 0> {\ gc::Cell* gcptr_;\ public:\ LIR_HEADER(Pointer)\ explicit LPointer(gc::Cell* gcptr) : LInstructionHelper(classOpcode), gcptr_(gcptr) {\ -\ }\ gc::Cell* gcptr() const { return gcptr_; }\ -\ };\ -\ class LDouble : public LInstructionHelper<1, 0, 0> {\ double value_;\ public:\ LIR_HEADER(Double)\ explicit LDouble(double value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ double value() const { return value_; }\ -\ };\ -\ class LFloat32 : public LInstructionHelper<1, 0, 0> {\ float value_;\ public:\ LIR_HEADER(Float32)\ explicit LFloat32(float value) : LInstructionHelper(classOpcode), value_(value) {\ -\ }\ float value() const { return value_; }\ -\ };\ -\ -class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NurseryObject)\ - explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ -};\ -\ class LParameter : public LInstructionHelper {\ public:\ LIR_HEADER(Parameter)\ explicit LParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LCallee : public LInstructionHelper<1, 0, 0> {\ +class LGoto : public LControlInstructionHelper<1, 0, 0> {\ public:\ - LIR_HEADER(Callee)\ - explicit LCallee() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Goto)\ + explicit LGoto(MBasicBlock* target) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, target);\ }\ -\ + MBasicBlock* target() const { return getSuccessor(0); }\ };\ -\ -class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ +class LNewArray : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(IsConstructing)\ - explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewArrayDynamicLength)\ - explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ + LIR_HEADER(NewArray)\ + explicit LNewArray(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ - const LAllocation* length() { return getOperand(0); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ + MNewArray* mir() const { return mir_->toNewArray(); };\ + inline const char* extraName() const;\ };\ -\ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewIterator)\ @@ -818,7 +846,6 @@ class LNewIterator : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewIterator* mir() const { return mir_->toNewIterator(); };\ };\ -\ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewTypedArray)\ @@ -830,71 +857,31 @@ class LNewTypedArray : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewTypedArray* mir() const { return mir_->toNewTypedArray(); };\ };\ -\ -class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(NewTypedArrayDynamicLength)\ - explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* length() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ -};\ -\ -class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArray)\ - explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ -};\ -\ -class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(NewTypedArrayFromArrayBuffer)\ - explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, arrayBuffer);\ - setBoxOperand(ByteOffsetIndex, byteOffset);\ - setBoxOperand(LengthIndex, length);\ - }\ - const LAllocation* arrayBuffer() { return getOperand(0); }\ - static const size_t ByteOffsetIndex = 1;\ -\ - static const size_t LengthIndex = 1 + BOX_PIECES * 1;\ - MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ -};\ -\ class LBindFunction : public LInstructionHelper<1, 1, 2> {\ public:\ LIR_HEADER(BindFunction)\ + static constexpr size_t TargetIndex = 0;\ explicit LBindFunction(const LAllocation& target, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, target);\ + setOperand(TargetIndex, target);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* target() { return getOperand(0); }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MBindFunction* mir() const { return mir_->toBindFunction(); };\ };\ -\ -class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ +class LNewObject : public LInstructionHelper<1, 0, 1> {\ public:\ - LIR_HEADER(NewBoundFunction)\ - explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(NewObject)\ + explicit LNewObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setTemp(0, temp0);\ }\ const LDefinition* temp0() { return getTemp(0); }\ - MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ + MNewObject* mir() const { return mir_->toNewObject(); };\ + inline const char* extraName() const;\ };\ -\ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ public:\ LIR_HEADER(NewPlainObject)\ @@ -908,7 +895,6 @@ class LNewPlainObject : public LInstructionHelper<1, 0, 3> {\ const LDefinition* temp2() { return getTemp(2); }\ MNewPlainObject* mir() const { return mir_->toNewPlainObject(); };\ };\ -\ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ public:\ LIR_HEADER(NewArrayObject)\ @@ -920,17 +906,6 @@ class LNewArrayObject : public LInstructionHelper<1, 0, 2> {\ const LDefinition* temp1() { return getTemp(1); }\ MNewArrayObject* mir() const { return mir_->toNewArrayObject(); };\ };\ -\ -class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(NewNamedLambdaObject)\ - explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ -};\ -\ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewCallObject)\ @@ -940,1489 +915,2310 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewCallObject* mir() const { return mir_->toNewCallObject(); };\ };\ -\ +class LNewMapObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewMapObject)\ + explicit LNewMapObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewMapObject* mir() const { return mir_->toNewMapObject(); };\ +};\ +class LNewSetObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewSetObject)\ + explicit LNewSetObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewSetObject* mir() const { return mir_->toNewSetObject(); };\ +};\ class LNewStringObject : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NewStringObject)\ + static constexpr size_t InputIndex = 0;\ explicit LNewStringObject(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNewStringObject* mir() const { return mir_->toNewStringObject(); };\ };\ -\ -class LInitElemGetterSetter : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ +class LInitElemGetterSetter : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InitElemGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IdIndex = 2;\ explicit LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ - setOperand(1, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - static const size_t IdIndex = 2;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); };\ };\ -\ -class LMutateProto : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LMutateProto : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(MutateProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMutateProto(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ class LInitPropGetterSetter : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(InitPropGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LInitPropGetterSetter(const LAllocation& object, const LAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); };\ };\ -\ -class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefAsNonNull : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(CheckOverRecursed)\ - explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmRefAsNonNull)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefAsNonNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ }\ -\ - MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + MWasmRefAsNonNull* mir() const { return mir_->toWasmRefAsNonNull(); };\ };\ -\ -class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ +class LWasmRefTestConcrete : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(WasmTrap)\ - explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ -};\ -\ -class LWasmTrapIfNull : public LInstructionHelper<0, 1, 0> {\ - public:\ - LIR_HEADER(WasmTrapIfNull)\ - explicit LWasmTrapIfNull(const LAllocation& ref) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - }\ - const LAllocation* ref() { return getOperand(0); }\ - MWasmTrapIfNull* mir() const { return mir_->toWasmTrapIfNull(); };\ -};\ -\ -class LWasmRefIsSubtypeOfConcrete : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(WasmRefIsSubtypeOfConcrete)\ - explicit LWasmRefIsSubtypeOfConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ - setOperand(1, superSTV);\ + LIR_HEADER(WasmRefTestConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* ref() { return getOperand(0); }\ - const LAllocation* superSTV() { return getOperand(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MWasmRefIsSubtypeOfConcrete* mir() const { return mir_->toWasmRefIsSubtypeOfConcrete(); };\ + MWasmRefTestConcrete* mir() const { return mir_->toWasmRefTestConcrete(); };\ };\ -\ -class LWasmRefIsSubtypeOfAbstract : public LInstructionHelper<1, 1, 1> {\ +class LWasmRefTestAbstract : public LInstructionHelper<1, 1, 1> {\ public:\ - LIR_HEADER(WasmRefIsSubtypeOfAbstract)\ - explicit LWasmRefIsSubtypeOfAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, ref);\ + LIR_HEADER(WasmRefTestAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ setTemp(0, temp0);\ }\ - const LAllocation* ref() { return getOperand(0); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MWasmRefIsSubtypeOfAbstract* mir() const { return mir_->toWasmRefIsSubtypeOfAbstract(); };\ + MWasmRefTestAbstract* mir() const { return mir_->toWasmRefTestAbstract(); };\ };\ -\ -class LWasmNewStructObject : public LInstructionHelper<1, 2, 2> {\ +class LWasmRefTestConcreteAndBranch : public LControlInstructionHelper<2, 2, 2> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestConcreteAndBranch)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefTestConcreteAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefTestAbstractAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + wasm::MaybeRefType sourceType_;\ + wasm::RefType destType_;\ + public:\ + LIR_HEADER(WasmRefTestAbstractAndBranch)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefTestAbstractAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& ref, const LDefinition& temp0, wasm::MaybeRefType sourceType, wasm::RefType destType) : LControlInstructionHelper(classOpcode), sourceType_(sourceType), destType_(destType) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::MaybeRefType sourceType() const { return sourceType_; }\ + wasm::RefType destType() const { return destType_; }\ +};\ +class LWasmRefCastConcrete : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(WasmRefCastConcrete)\ + static constexpr size_t RefIndex = 0;\ + static constexpr size_t SuperSTVIndex = 1;\ + explicit LWasmRefCastConcrete(const LAllocation& ref, const LAllocation& superSTV, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setOperand(SuperSTVIndex, superSTV);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LAllocation* superSTV() const { return getOperand(SuperSTVIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MWasmRefCastConcrete* mir() const { return mir_->toWasmRefCastConcrete(); };\ +};\ +class LWasmRefCastAbstract : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmRefCastAbstract)\ + static constexpr size_t RefIndex = 0;\ + explicit LWasmRefCastAbstract(const LAllocation& ref, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RefIndex, ref);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ref() const { return getOperand(RefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmRefCastAbstract* mir() const { return mir_->toWasmRefCastAbstract(); };\ +};\ +class LWasmNewStructObject : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmNewStructObject)\ - explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t AllocSiteIndex = 1;\ + explicit LWasmNewStructObject(const LAllocation& instance, const LAllocation& allocSite, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ - setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* typeDefData() { return getOperand(1); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ MWasmNewStructObject* mir() const { return mir_->toWasmNewStructObject(); };\ };\ -\ class LWasmNewArrayObject : public LInstructionHelper<1, 3, 2> {\ public:\ LIR_HEADER(WasmNewArrayObject)\ - explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& typeDefData, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ - setOperand(1, numElements);\ - setOperand(2, typeDefData);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t NumElementsIndex = 1;\ + static constexpr size_t AllocSiteIndex = 2;\ + explicit LWasmNewArrayObject(const LAllocation& instance, const LAllocation& numElements, const LAllocation& allocSite, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(NumElementsIndex, numElements);\ + setOperand(AllocSiteIndex, allocSite);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* numElements() { return getOperand(1); }\ - const LAllocation* typeDefData() { return getOperand(2); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* numElements() const { return getOperand(NumElementsIndex); }\ + const LAllocation* allocSite() const { return getOperand(AllocSiteIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MWasmNewArrayObject* mir() const { return mir_->toWasmNewArrayObject(); };\ };\ -\ -class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ +class LReinterpretCast : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(InterruptCheck)\ - explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(ReinterpretCast)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCast(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ };\ -\ -class LWasmStackSwitchToMain : public LInstructionHelper<0, 3, 0> {\ +class LReinterpretCastFromI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(ReinterpretCastFromI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastFromI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LReinterpretCastToI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(ReinterpretCastToI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LReinterpretCastToI64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MReinterpretCast* mir() const { return mir_->toReinterpretCast(); };\ +};\ +class LRotate : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Rotate)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t CountIndex = 1;\ + explicit LRotate() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LRotateI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(RotateI64)\ + static constexpr size_t CountIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LRotateI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setCount(const LAllocation& count) { setOperand(CountIndex, count); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + MRotate* mir() const { return mir_->toRotate(); };\ +};\ +class LWasmStackSwitchToMain : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToMain)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToMain(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ class LWasmStackSwitchToSuspendable : public LInstructionHelper<0, 3, 0> {\ public:\ LIR_HEADER(WasmStackSwitchToSuspendable)\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t FnIndex = 1;\ + static constexpr size_t DataIndex = 2;\ explicit LWasmStackSwitchToSuspendable(const LAllocation& suspender, const LAllocation& fn, const LAllocation& data) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ - setOperand(1, fn);\ - setOperand(2, data);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(FnIndex, fn);\ + setOperand(DataIndex, data);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ - const LAllocation* fn() { return getOperand(1); }\ - const LAllocation* data() { return getOperand(2); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* fn() const { return getOperand(FnIndex); }\ + const LAllocation* data() const { return getOperand(DataIndex); }\ };\ -\ -class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 1, 0> {\ +class LWasmStackContinueOnSuspendable : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmStackContinueOnSuspendable)\ - explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender) : LInstructionHelper(classOpcode) {\ + static constexpr size_t SuspenderIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ + explicit LWasmStackContinueOnSuspendable(const LAllocation& suspender, const LAllocation& result) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, suspender);\ + setOperand(SuspenderIndex, suspender);\ + setOperand(ResultIndex, result);\ }\ - const LAllocation* suspender() { return getOperand(0); }\ + const LAllocation* suspender() const { return getOperand(SuspenderIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ };\ -\ class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmInterruptCheck)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmInterruptCheck(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); };\ };\ -\ -class LTypeOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ class LTypeOfO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LTypeOfO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MTypeOf* mir() const { return mir_->toTypeOf(); };\ };\ -\ -class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypeOfName)\ - explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ -};\ -\ -class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LTypeOfIsNonPrimitiveV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveV)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveV(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ class LTypeOfIsNonPrimitiveO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TypeOfIsNonPrimitiveO)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsNonPrimitiveO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LTypeOfIsPrimitive : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LTypeOfIsPrimitive : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(TypeOfIsPrimitive)\ + static constexpr size_t InputIndex = 0;\ explicit LTypeOfIsPrimitive(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MTypeOfIs* mir() const { return mir_->toTypeOfIs(); };\ };\ -\ -class LToAsyncIter : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LToAsyncIter : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ToAsyncIter)\ + static constexpr size_t IteratorIndex = 0;\ + static constexpr size_t NextMethodIndex = 1;\ explicit LToAsyncIter(const LAllocation& iterator, const LBoxAllocation& nextMethod) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, iterator);\ + setOperand(IteratorIndex, iterator);\ setBoxOperand(NextMethodIndex, nextMethod);\ }\ - const LAllocation* iterator() { return getOperand(0); }\ - static const size_t NextMethodIndex = 1;\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation nextMethod() const { return getBoxOperand(NextMethodIndex); }\ };\ -\ -class LToPropertyKeyCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToPropertyKeyCache)\ - explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ - MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ -};\ -\ -class LCreateThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(CreateThis)\ - explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, newTarget);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* newTarget() { return getOperand(1); }\ - MCreateThis* mir() const { return mir_->toCreateThis(); };\ -};\ -\ class LCreateArgumentsObject : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(CreateArgumentsObject)\ + static constexpr size_t CallObjectIndex = 0;\ explicit LCreateArgumentsObject(const LAllocation& callObject, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callObject);\ + setOperand(CallObjectIndex, callObject);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* callObject() { return getOperand(0); }\ + const LAllocation* callObject() const { return getOperand(CallObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCreateArgumentsObject* mir() const { return mir_->toCreateArgumentsObject(); };\ };\ -\ -class LGetArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetArgumentsObjectArg)\ - explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ -};\ -\ -class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(SetArgumentsObjectArg)\ - explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ - MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ -};\ -\ -class LLoadArgumentsObjectArg : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArg)\ - explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadArgumentsObjectArgHole)\ - explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(InArgumentsObjectArg)\ - explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArgumentsObjectLength)\ - explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ -};\ -\ -class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayFromArgumentsObject)\ - explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, argsObject);\ - }\ - const LAllocation* argsObject() { return getOperand(0); }\ - MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ -};\ -\ class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardArgumentsObjectFlags)\ + static constexpr size_t ArgsObjectIndex = 0;\ explicit LGuardArgumentsObjectFlags(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, argsObject);\ + setOperand(ArgsObjectIndex, argsObject);\ setTemp(0, temp0);\ }\ - const LAllocation* argsObject() { return getOperand(0); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardArgumentsObjectFlags* mir() const { return mir_->toGuardArgumentsObjectFlags(); };\ };\ -\ -class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ +class LGuardObjectHasSameRealm : public LInstructionHelper<0, 1, 1> {\ public:\ - LIR_HEADER(BoundFunctionNumArgs)\ - explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + LIR_HEADER(GuardObjectHasSameRealm)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardObjectHasSameRealm(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardObjectHasSameRealm* mir() const { return mir_->toGuardObjectHasSameRealm(); };\ };\ -\ class LGuardBoundFunctionIsConstructor : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardBoundFunctionIsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardBoundFunctionIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LReturnFromCtor : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ReturnFromCtor)\ - explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ -};\ -\ -class LBoxNonStrictThis : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LBoxNonStrictThis : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(BoxNonStrictThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LBoxNonStrictThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); };\ };\ -\ -class LImplicitThis : public LInstructionHelper {\ - public:\ - LIR_HEADER(ImplicitThis)\ - explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, env);\ - }\ - const LAllocation* env() { return getOperand(0); }\ - MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ -};\ -\ class LStackArgT : public LInstructionHelper<0, 1, 0> {\ uint32_t argslot_;\ MIRType type_;\ public:\ LIR_HEADER(StackArgT)\ + static constexpr size_t ArgIndex = 0;\ explicit LStackArgT(const LAllocation& arg, uint32_t argslot, MIRType type) : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); } uint32_t argslot() const { return argslot_; }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ + uint32_t argslot() const { return argslot_; }\ MIRType type() const { return type_; }\ -\ };\ -\ -class LStackArgV : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LStackArgV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ uint32_t argslot_;\ public:\ LIR_HEADER(StackArgV)\ + static constexpr size_t ValueIndex = 0;\ explicit LStackArgV(const LBoxAllocation& value, uint32_t argslot) : LInstructionHelper(classOpcode), argslot_(argslot) {\ setBoxOperand(ValueIndex, value);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ uint32_t argslot() const { return argslot_; }\ -\ - static const size_t ValueIndex = 0;\ };\ -\ -class LBail : public LInstructionHelper<0, 0, 0> {\ +class LUnreachable : public LControlInstructionHelper<0, 0, 0> {\ public:\ - LIR_HEADER(Bail)\ - explicit LBail() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Unreachable)\ + explicit LUnreachable() : LControlInstructionHelper(classOpcode) {\ }\ -\ };\ -\ -class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ +class LUnreachableResultV : public LInstructionHelper {\ public:\ - LIR_HEADER(EncodeSnapshot)\ - explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(UnreachableResultV)\ + explicit LUnreachableResultV() : LInstructionHelper(classOpcode) {\ }\ -\ };\ -\ class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(UnreachableResultT)\ explicit LUnreachableResultT() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LGetDOMProperty : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMProperty(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); };\ +};\ +class LGetDOMMemberV : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetDOMMemberV)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGetDOMMemberV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ +};\ class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GetDOMMemberT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGetDOMMemberT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGetDOMMember* mir() const { return mir_->toGetDOMMember(); };\ };\ -\ -class LLoadDOMExpandoValue : public LInstructionHelper {\ +class LSetDOMProperty : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ public:\ - LIR_HEADER(LoadDOMExpandoValue)\ - explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + LIR_HEADER(SetDOMProperty)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetDOMProperty(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); };\ };\ -\ class LLoadDOMExpandoValueGuardGeneration : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDOMExpandoValueGuardGeneration)\ + static constexpr size_t ProxyIndex = 0;\ explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ MLoadDOMExpandoValueGuardGeneration* mir() const { return mir_->toLoadDOMExpandoValueGuardGeneration(); };\ };\ -\ -class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ - public:\ - LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ - explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ -};\ -\ -class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 1> {\ +class LGuardDOMExpandoMissingOrGuardShape : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MGuardDOMExpandoMissingOrGuardShape* mir() const { return mir_->toGuardDOMExpandoMissingOrGuardShape(); };\ };\ -\ +class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestIPtrAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestIPtrAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestIPtrAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestI64AndBranch : public LControlInstructionHelper<2, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(TestI64AndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ +};\ +class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestDAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestFAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {\ + public:\ + LIR_HEADER(TestBIAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestBIAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {\ + public:\ + LIR_HEADER(TestOAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestOAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LAllocation& input, const LDefinition& temp0) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LTestVAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TestVAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTruthy);\ + setSuccessor(1, ifFalsy);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + MBasicBlock* ifTruthy() const { return getSuccessor(0); }\ + MBasicBlock* ifFalsy() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LCompare : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(Compare)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompare(const LAllocation& left, const LAllocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64 : public LInstructionHelper<1, 0 + 2 * INT64_PIECES, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64(const LInt64Allocation& left, const LInt64Allocation& right, JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + JSOp jsop() const { return jsop_; }\ + MCompare* mir() const { return mir_->toCompare(); };\ + inline const char* extraName() const;\ +};\ +class LCompareI64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareI64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LCompareI64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ +class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(CompareAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir, JSOp jsop) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + JSOp jsop() const { return jsop_; }\ + MTest* mir() const { return mir_->toTest(); };\ + inline const char* extraName() const;\ +};\ class LCompareD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareD)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareD(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareF : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareF)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareF(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ +class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareDAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareDAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareFAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareFAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ class LCompareS : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareS)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareS(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSInline : public LInstructionHelper<1, 1, 0> {\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSInline)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSInline(const LAllocation& input, JSLinearString* constant) : LInstructionHelper(classOpcode), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); } JSLinearString* constant() const { return constant_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + JSLinearString* constant() const { return constant_; }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareSSingle : public LInstructionHelper<1, 1, 1> {\ JSOp jsop_;\ JSLinearString* constant_;\ public:\ LIR_HEADER(CompareSSingle)\ + static constexpr size_t InputIndex = 0;\ explicit LCompareSSingle(const LAllocation& input, const LDefinition& temp0, JSOp jsop, JSLinearString* constant) : LInstructionHelper(classOpcode), jsop_(jsop), constant_(constant) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSOp jsop() const { return jsop_; }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSOp jsop() const { return jsop_; }\ JSLinearString* constant() const { return constant_; }\ -\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigInt : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(CompareBigInt)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigInt(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(CompareBigIntInt32)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntInt32(const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntDouble : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntDouble(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LCompareBigIntString : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(CompareBigIntString)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ explicit LCompareBigIntString(const LAllocation& left, const LAllocation& right) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, left);\ - setOperand(1, right);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LCompareBigIntInt32AndBranch : public LControlInstructionHelper<2, 2, 2> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(CompareBigIntInt32AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LCompareBigIntInt32AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAndAndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& left, const LAllocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LBitAnd64AndBranch : public LControlInstructionHelper<2, 0 + 2 * INT64_PIECES, 0> {\ + Assembler::Condition cond_;\ + public:\ + LIR_HEADER(BitAnd64AndBranch)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * INT64_PIECES;\ + explicit LBitAnd64AndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LInt64Allocation& left, const LInt64Allocation& right, Assembler::Condition cond) : LControlInstructionHelper(classOpcode), cond_(cond) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setInt64Operand(LeftIndex, left);\ + setInt64Operand(RightIndex, right);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LInt64Allocation left() const { return getInt64Operand(LeftIndex); }\ + LInt64Allocation right() const { return getInt64Operand(RightIndex); }\ + Assembler::Condition cond() const { return cond_; }\ +};\ +class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsNullOrLikeUndefinedT)\ + static constexpr size_t InputIndex = 0;\ explicit LIsNullOrLikeUndefinedT(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsNull : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsNull : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsNull)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsNull(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LIsUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(IsUndefined)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCompare* mir() const { return mir_->toCompare(); };\ };\ -\ -class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ +class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 2> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValueDouble)\ - explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, left);\ - setOperand(1, right);\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchV(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ +};\ +class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1, 1> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrLikeUndefinedAndBranchT(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& value, const LDefinition& temp0, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* left() { return getOperand(0); }\ - const LAllocation* right() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + MCompare* cmpMir() const { return cmpMir_; }\ + MTest* mir() const { return mir_->toTest(); };\ };\ -\ -class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LIsNullAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ public:\ - LIR_HEADER(SameValue)\ - explicit LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setBoxOperand(LhsIndex, lhs);\ - setBoxOperand(RhsIndex, rhs);\ + LIR_HEADER(IsNullAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ +};\ +class LIsUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + MCompare* cmpMir_;\ + public:\ + LIR_HEADER(IsUndefinedAndBranch)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& value, MCompare* cmpMir) : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(ValueIndex, value);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCompare* cmpMir() const { return cmpMir_; }\ };\ -\ class LNotI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNotI64 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LNotIPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NotIPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LNotIPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LNotI64 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(NotI64)\ + static constexpr size_t InputI64Index = 0;\ explicit LNotI64(const LInt64Allocation& inputI64) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputI64Index, inputI64);\ }\ - const LInt64Allocation inputI64() { return getInt64Operand(InputI64Index); }\ - static const size_t InputI64Index = 0;\ + LInt64Allocation inputI64() const { return getInt64Operand(InputI64Index); }\ };\ -\ class LNotD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotD)\ + static constexpr size_t InputIndex = 0;\ explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotF)\ + static constexpr size_t InputIndex = 0;\ explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotBI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotBI)\ + static constexpr size_t InputIndex = 0;\ explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ class LNotO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NotO)\ + static constexpr size_t InputIndex = 0;\ explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ -class LNotV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LNotV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(NotV)\ + static constexpr size_t InputIndex = 0;\ explicit LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 0;\ MNot* mir() const { return mir_->toNot(); };\ };\ -\ +class LBitNotI : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BitNotI)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + void setInput(const LAllocation& input) { setOperand(InputIndex, input); }\ +};\ +class LBitNotI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(BitNotI64)\ + static constexpr size_t InputIndex = 0;\ + explicit LBitNotI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + void setInput(const LInt64Allocation& input) { setInt64Operand(InputIndex, input); }\ +};\ +class LBitOpI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBitOpI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LBitOpI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(BitOpI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LBitOpI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + inline const char* extraName() const;\ +};\ +class LShiftI : public LInstructionHelper<1, 2, 0> {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LShiftI(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ +class LShiftI64 : public LInstructionHelper {\ + JSOp bitop_;\ + public:\ + LIR_HEADER(ShiftI64)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ + explicit LShiftI64(JSOp bitop) : LInstructionHelper(classOpcode), bitop_(bitop) {\ + }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + JSOp bitop() const { return bitop_; }\ + MInstruction* mir() const { return mir_->toInstruction(); };\ + inline const char* extraName() const;\ +};\ class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {\ - MSignExtendInt32::Mode mode_;\ public:\ LIR_HEADER(SignExtendInt32)\ - explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode) : LInstructionHelper(classOpcode), mode_(mode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); } MSignExtendInt32::Mode mode() const { return mode_; }\ -\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendInt32* mir() const { return mir_->toSignExtendInt32(); };\ };\ -\ -class LThrow : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LSignExtendIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(Throw)\ - explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(SignExtendIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MSignExtendIntPtr* mir() const { return mir_->toSignExtendIntPtr(); };\ };\ -\ -class LThrowWithStack : public LInstructionHelper<0, 2 * BOX_PIECES + 0, 0> {\ +class LSignExtendInt64 : public LInstructionHelper {\ public:\ - LIR_HEADER(ThrowWithStack)\ - explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(ValueIndex, value);\ - setBoxOperand(StackIndex, stack);\ + LIR_HEADER(SignExtendInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignExtendInt64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t StackIndex = 0 + BOX_PIECES * 1;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); };\ +};\ +class LUrshD : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(UrshD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LUrshD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMinMaxI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxI)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxI(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxD)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxD(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxF : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MinMaxF)\ + static constexpr size_t FirstIndex = 0;\ + static constexpr size_t SecondIndex = 1;\ + explicit LMinMaxF(const LAllocation& first, const LAllocation& second) : LInstructionHelper(classOpcode) {\ + setOperand(FirstIndex, first);\ + setOperand(SecondIndex, second);\ + }\ + const LAllocation* first() const { return getOperand(FirstIndex); }\ + const LAllocation* second() const { return getOperand(SecondIndex); }\ + MMinMax* mir() const { return mir_->toMinMax(); };\ + inline const char* extraName() const;\ +};\ +class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayI)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ +};\ +class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(MinMaxArrayD)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LMinMaxArrayD(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ArrayIndex, array);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMinMaxArray* mir() const { return mir_->toMinMaxArray(); };\ };\ -\ class LNegI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegI)\ - explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LNegI64 : public LInstructionHelper {\ +class LNegI64 : public LInstructionHelper {\ public:\ LIR_HEADER(NegI64)\ - explicit LNegI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ };\ -\ class LNegD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegD)\ - explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNegF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NegF)\ - explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNegF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsI)\ - explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAbs* mir() const { return mir_->toAbs(); };\ };\ -\ class LAbsD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsD)\ - explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAbsF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AbsF)\ - explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LAbsF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LCopySignD : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignD() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ +};\ +class LCopySignF : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CopySignF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCopySignF() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + setTemp(1, LDefinition::BogusTemp());\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ + void setTemp1(const LDefinition& temp1) { setTemp(1, temp1); }\ };\ -\ class LClzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClzI)\ - explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ -class LClzI64 : public LInstructionHelper {\ +class LClzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(ClzI64)\ - explicit LClzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LClzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MClz* mir() const { return mir_->toClz(); };\ };\ -\ class LCtzI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CtzI)\ - explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ -class LCtzI64 : public LInstructionHelper {\ +class LCtzI64 : public LInstructionHelper {\ public:\ LIR_HEADER(CtzI64)\ - explicit LCtzI64(const LInt64Allocation& num) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCtzI64(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ - static const size_t NumIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MCtz* mir() const { return mir_->toCtz(); };\ };\ -\ class LPopcntI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(PopcntI)\ - explicit LPopcntI(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ -class LPopcntI64 : public LInstructionHelper {\ +class LPopcntI64 : public LInstructionHelper {\ public:\ LIR_HEADER(PopcntI64)\ - explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setInt64Operand(NumIndex, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LPopcntI64(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation num() { return getInt64Operand(NumIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t NumIndex = 0;\ MPopcnt* mir() const { return mir_->toPopcnt(); };\ };\ -\ class LSqrtD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtD)\ - explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSqrtF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SqrtF)\ - explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSqrtF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LAtan2D : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(Atan2D)\ + static constexpr size_t YIndex = 0;\ + static constexpr size_t XIndex = 1;\ + explicit LAtan2D(const LAllocation& y, const LAllocation& x) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(YIndex, y);\ + setOperand(XIndex, x);\ + }\ + const LAllocation* y() const { return getOperand(YIndex); }\ + const LAllocation* x() const { return getOperand(XIndex); }\ };\ -\ class LPowI : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowI)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowI(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowII : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(PowII)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowII(const LAllocation& value, const LAllocation& power, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MPow* mir() const { return mir_->toPow(); };\ };\ -\ class LPowD : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(PowD)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t PowerIndex = 1;\ explicit LPowD(const LAllocation& value, const LAllocation& power) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, value);\ - setOperand(1, power);\ + setOperand(ValueIndex, value);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* power() { return getOperand(1); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ };\ -\ class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {\ uint32_t base_;\ public:\ LIR_HEADER(PowOfTwoI)\ + static constexpr size_t PowerIndex = 0;\ explicit LPowOfTwoI(const LAllocation& power, uint32_t base) : LInstructionHelper(classOpcode), base_(base) {\ - setOperand(0, power);\ + setOperand(PowerIndex, power);\ }\ - const LAllocation* power() { return getOperand(0); } uint32_t base() const { return base_; }\ -\ + const LAllocation* power() const { return getOperand(PowerIndex); }\ + uint32_t base() const { return base_; }\ };\ -\ class LSignI : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignI)\ - explicit LSignI(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignD : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(SignD)\ - explicit LSignD(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LSignDI : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(SignDI)\ + static constexpr size_t InputIndex = 0;\ explicit LSignDI(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ +class LSignID : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(SignID)\ + static constexpr size_t InputIndex = 0;\ + explicit LSignID(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LMathFunctionD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionD)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LMathFunctionF : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MathFunctionF)\ + static constexpr size_t InputIndex = 0;\ + explicit LMathFunctionF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MMathFunction* mir() const { return mir_->toMathFunction(); };\ + inline const char* extraName() const;\ +};\ +class LAddI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AddI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LAddI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LSubI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(SubI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LSubI64() : LInstructionHelper(classOpcode) {\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ +};\ +class LMulI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(MulI64)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * INT64_PIECES;\ + explicit LMulI64() : LInstructionHelper(classOpcode) {\ + setTemp(0, LDefinition::BogusTemp());\ + }\ + LInt64Allocation lhs() const { return getInt64Operand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + void setLhs(const LInt64Allocation& lhs) { setInt64Operand(LhsIndex, lhs); }\ + void setRhs(const LInt64Allocation& rhs) { setInt64Operand(RhsIndex, rhs); }\ + const LDefinition* temp0() { return getTemp(0); }\ + void setTemp0(const LDefinition& temp0) { setTemp(0, temp0); }\ +};\ +class LMathD : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathD(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LMathF : public LInstructionHelper<1, 2, 0> {\ + JSOp jsop_;\ + public:\ + LIR_HEADER(MathF)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMathF(JSOp jsop) : LInstructionHelper(classOpcode), jsop_(jsop) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + JSOp jsop() const { return jsop_; }\ + inline const char* extraName() const;\ +};\ +class LModD : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModD(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LModPowTwoD : public LInstructionHelper<1, 1, 0> {\ + uint32_t divisor_;\ + public:\ + LIR_HEADER(ModPowTwoD)\ + static constexpr size_t LhsIndex = 0;\ + explicit LModPowTwoD(const LAllocation& lhs, uint32_t divisor) : LInstructionHelper(classOpcode), divisor_(divisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + uint32_t divisor() const { return divisor_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(WasmBuiltinModD)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + static constexpr size_t InstanceIndex = 2;\ explicit LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ - setOperand(2, instance);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ - const LAllocation* instance() { return getOperand(2); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); };\ };\ -\ -class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ +class LBigIntAdd : public LInstructionHelper<1, 2, 0> {\ public:\ - LIR_HEADER(Int32ToStringWithBase)\ - explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, base);\ + LIR_HEADER(BigIntAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntAdd* mir() const { return mir_->toBigIntAdd(); };\ +};\ +class LBigIntSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntSub* mir() const { return mir_->toBigIntSub(); };\ +};\ +class LBigIntMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMul* mir() const { return mir_->toBigIntMul(); };\ +};\ +class LBigIntDiv : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntDiv* mir() const { return mir_->toBigIntDiv(); };\ +};\ +class LBigIntMod : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntMod(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntMod* mir() const { return mir_->toBigIntMod(); };\ +};\ +class LBigIntPow : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPow(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPow* mir() const { return mir_->toBigIntPow(); };\ +};\ +class LBigIntBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitAnd* mir() const { return mir_->toBigIntBitAnd(); };\ +};\ +class LBigIntBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitOr* mir() const { return mir_->toBigIntBitOr(); };\ +};\ +class LBigIntBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntBitXor* mir() const { return mir_->toBigIntBitXor(); };\ +};\ +class LBigIntLsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntLsh* mir() const { return mir_->toBigIntLsh(); };\ +};\ +class LBigIntRsh : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntRsh* mir() const { return mir_->toBigIntRsh(); };\ +};\ +class LBigIntIncrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntIncrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntIncrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntIncrement* mir() const { return mir_->toBigIntIncrement(); };\ +};\ +class LBigIntDecrement : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntDecrement)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntDecrement(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntDecrement* mir() const { return mir_->toBigIntDecrement(); };\ +};\ +class LBigIntNegate : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BigIntNegate)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntNegate(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBigIntNegate* mir() const { return mir_->toBigIntNegate(); };\ +};\ +class LBigIntBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntBitNot* mir() const { return mir_->toBigIntBitNot(); };\ +};\ +class LBigIntPtrAdd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrAdd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrAdd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrAdd* mir() const { return mir_->toBigIntPtrAdd(); };\ +};\ +class LBigIntPtrSub : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrSub)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrSub(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrSub* mir() const { return mir_->toBigIntPtrSub(); };\ +};\ +class LBigIntPtrMul : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrMul)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMul(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrMul* mir() const { return mir_->toBigIntPtrMul(); };\ +};\ +class LBigIntPtrDiv : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrDiv)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrDiv(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ + MBigIntPtrDiv* mir() const { return mir_->toBigIntPtrDiv(); };\ };\ -\ -class LNumberParseInt : public LInstructionHelper {\ +class LBigIntPtrDivPowTwo : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + bool negativeDivisor_;\ public:\ - LIR_HEADER(NumberParseInt)\ - explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, radix);\ + LIR_HEADER(BigIntPtrDivPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrDivPowTwo(const LAllocation& lhs, int32_t shift, bool negativeDivisor) : LInstructionHelper(classOpcode), shift_(shift), negativeDivisor_(negativeDivisor) {\ + setOperand(LhsIndex, lhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + int32_t shift() const { return shift_; }\ + bool negativeDivisor() const { return negativeDivisor_; }\ +};\ +class LBigIntPtrMod : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrMod)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrMod* mir() const { return mir_->toBigIntPtrMod(); };\ +};\ +class LBigIntPtrModPowTwo : public LInstructionHelper<1, 1, 1> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(BigIntPtrModPowTwo)\ + static constexpr size_t LhsIndex = 0;\ + explicit LBigIntPtrModPowTwo(const LAllocation& lhs, const LDefinition& temp0, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* radix() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ + int32_t shift() const { return shift_; }\ };\ -\ -class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ +class LBigIntPtrPow : public LInstructionHelper<1, 2, 2> {\ public:\ - LIR_HEADER(DoubleParseInt)\ - explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, number);\ + LIR_HEADER(BigIntPtrPow)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrPow(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* number() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrPow* mir() const { return mir_->toBigIntPtrPow(); };\ +};\ +class LBigIntPtrBitAnd : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitAnd)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitAnd(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitAnd* mir() const { return mir_->toBigIntPtrBitAnd(); };\ +};\ +class LBigIntPtrBitOr : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitOr)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitOr(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitOr* mir() const { return mir_->toBigIntPtrBitOr(); };\ +};\ +class LBigIntPtrBitXor : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitXor)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrBitXor(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MBigIntPtrBitXor* mir() const { return mir_->toBigIntPtrBitXor(); };\ +};\ +class LBigIntPtrLsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrLsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrLsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrLsh* mir() const { return mir_->toBigIntPtrLsh(); };\ +};\ +class LBigIntPtrRsh : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(BigIntPtrRsh)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LBigIntPtrRsh(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MBigIntPtrRsh* mir() const { return mir_->toBigIntPtrRsh(); };\ +};\ +class LBigIntPtrBitNot : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntPtrBitNot)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntPtrBitNot(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntPtrBitNot* mir() const { return mir_->toBigIntPtrBitNot(); };\ };\ -\ class LConcat : public LInstructionHelper<1, 2, 5> {\ public:\ LIR_HEADER(Concat)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LConcat(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ const LDefinition* temp3() { return getTemp(3); }\ const LDefinition* temp4() { return getTemp(4); }\ };\ -\ -class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LinearizeString)\ - explicit LLinearizeString(const LAllocation& str) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ -};\ -\ -class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(LinearizeForCharAccess)\ - explicit LLinearizeForCharAccess(const LAllocation& str, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ -};\ -\ -class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(LinearizeForCodePointAccess)\ - explicit LLinearizeForCodePointAccess(const LAllocation& str, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ -};\ -\ -class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(ToRelativeStringIndex)\ - explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ -};\ -\ -class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAt)\ - explicit LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CharCodeAtOrNegative)\ - explicit LCharCodeAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAt)\ - explicit LCodePointAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CodePointAtOrNegative)\ - explicit LCodePointAtOrNegative(const LAllocation& str, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* str() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LNegativeToNaN : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToNaN)\ - explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LNegativeToUndefined : public LInstructionHelper {\ - public:\ - LIR_HEADER(NegativeToUndefined)\ - explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCode)\ - explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FromCharCodeEmptyIfNegative)\ - explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ - public:\ - LIR_HEADER(FromCharCodeUndefinedIfNegative)\ - explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ - }\ - const LAllocation* code() { return getOperand(0); }\ -};\ -\ -class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(FromCodePoint)\ - explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, codePoint);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* codePoint() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIncludes)\ - explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIncludesSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIncludesSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIncludesSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringIndexOf)\ - explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringIndexOfSIMD : public LInstructionHelper<1, 1, 3> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringIndexOfSIMD)\ + static constexpr size_t StringIndex = 0;\ explicit LStringIndexOfSIMD(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LDefinition* temp2() { return getTemp(2); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringLastIndexOf)\ - explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ -class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringStartsWith)\ - explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringStartsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringStartsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringStartsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ -class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringEndsWith)\ - explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, searchString);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* searchString() { return getOperand(1); }\ -};\ -\ class LStringEndsWithInline : public LInstructionHelper<1, 1, 1> {\ JSLinearString* searchString_;\ public:\ LIR_HEADER(StringEndsWithInline)\ + static constexpr size_t StringIndex = 0;\ explicit LStringEndsWithInline(const LAllocation& string, const LDefinition& temp0, JSLinearString* searchString) : LInstructionHelper(classOpcode), searchString_(searchString) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } JSLinearString* searchString() const { return searchString_; }\ -\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + JSLinearString* searchString() const { return searchString_; }\ };\ -\ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ public:\ LIR_HEADER(StringToLowerCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToLowerCase(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, const LDefinition& temp4) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ setTemp(3, temp3);\ setTemp(4, temp4);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ @@ -2430,363 +3226,401 @@ class LStringToLowerCase : public LInstructionHelper<1, 1, 5> {\ const LDefinition* temp4() { return getTemp(4); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToLowerCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToLowerCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToLowerCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ class LStringToUpperCase : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(StringToUpperCase)\ + static constexpr size_t StringIndex = 0;\ explicit LStringToUpperCase(const LAllocation& string) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ + setOperand(StringIndex, string);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ MStringConvertCase* mir() const { return mir_->toStringConvertCase(); };\ };\ -\ class LCharCodeToUpperCase : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(CharCodeToUpperCase)\ + static constexpr size_t CodeIndex = 0;\ explicit LCharCodeToUpperCase(const LAllocation& code, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, code);\ + setOperand(CodeIndex, code);\ setTemp(0, temp0);\ }\ - const LAllocation* code() { return getOperand(0); }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCharCodeConvertCase* mir() const { return mir_->toCharCodeConvertCase(); };\ };\ -\ -class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringTrimStartIndex)\ - explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringTrimEndIndex)\ - explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, start);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* start() { return getOperand(1); }\ -};\ -\ -class LStringSplit : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(StringSplit)\ - explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, separator);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - MStringSplit* mir() const { return mir_->toStringSplit(); };\ -};\ -\ -class LSubstr : public LInstructionHelper<1, 3, 3> {\ - public:\ - LIR_HEADER(Substr)\ - explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setOperand(1, begin);\ - setOperand(2, length);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MSubstr* mir() const { return mir_->toSubstr(); };\ -};\ -\ class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LFloat32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LValueToDouble : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LDoubleToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LDoubleToFloat32ToFloat16 : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(DoubleToFloat32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ +};\ +class LFloat32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Float32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LInt32ToFloat16 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(Int32ToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt32ToFloat16(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ +};\ +class LValueToDouble : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToDouble(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToDouble* mir() const { return mir_->toToDouble(); };\ };\ -\ -class LValueToFloat32 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToFloat32)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToFloat32(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToFloat32* mir() const { return mir_->toToFloat32(); };\ };\ -\ -class LValueToBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToFloat16 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToFloat16)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToFloat16(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToFloat16* mir() const { return mir_->toToFloat16(); };\ +};\ +class LValueToNumberInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ValueToNumberInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueToNumberInt32(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ +};\ +class LValueTruncateToInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ValueTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ + explicit LValueTruncateToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ +};\ +class LValueToBigInt : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToBigInt)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToBigInt(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MToBigInt* mir() const { return mir_->toToBigInt(); };\ };\ -\ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(DoubleToInt32)\ - explicit LDoubleToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LDoubleToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Float32ToInt32)\ - explicit LFloat32ToInt32(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloat32ToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToNumberInt32* mir() const { return mir_->toToNumberInt32(); };\ };\ -\ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateDToInt32)\ - explicit LTruncateDToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateDToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateDToInt32)\ - explicit LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateDToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(TruncateFToInt32)\ - explicit LTruncateFToInt32(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncateFToInt32(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); };\ };\ -\ class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(WasmBuiltinTruncateFToInt32)\ - explicit LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setOperand(1, instance);\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ + explicit LWasmBuiltinTruncateFToInt32(const LAllocation& input, const LAllocation& instance, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(InstanceIndex, instance);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MWasmBuiltinTruncateToInt32* mir() const { return mir_->toWasmBuiltinTruncateToInt32(); };\ };\ -\ class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmTruncateToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmTruncateToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); };\ };\ -\ -class LWrapInt64ToInt32 : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 0> {\ +class LWrapInt64ToInt32 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WrapInt64ToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LWrapInt64ToInt32(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ - static const size_t InputIndex = 0;\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ MWrapInt64ToInt32* mir() const { return mir_->toWrapInt64ToInt32(); };\ };\ -\ class LExtendInt32ToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ExtendInt32ToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LExtendInt32ToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MExtendInt32ToInt64* mir() const { return mir_->toExtendInt32ToInt64(); };\ };\ -\ class LBooleanToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(BooleanToString)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LIntToString : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntToString)\ + static constexpr size_t InputIndex = 0;\ explicit LIntToString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ class LDoubleToString : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(DoubleToString)\ + static constexpr size_t InputIndex = 0;\ explicit LDoubleToString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ -class LValueToString : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LValueToString : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ValueToString)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToString(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToString* mir() const { return mir_->toToString(); };\ };\ -\ +class LPowHalfD : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(PowHalfD)\ + static constexpr size_t InputIndex = 0;\ + explicit LPowHalfD(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MPowHalf* mir() const { return mir_->toPowHalf(); };\ +};\ class LNaNToZero : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(NaNToZero)\ + static constexpr size_t InputIndex = 0;\ explicit LNaNToZero(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MNaNToZero* mir() const { return mir_->toNaNToZero(); };\ };\ -\ class LOsrValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrValue* mir() const { return mir_->toOsrValue(); };\ };\ -\ class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrEnvironmentChain)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrEnvironmentChain(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrEnvironmentChain* mir() const { return mir_->toOsrEnvironmentChain(); };\ };\ -\ class LOsrReturnValue : public LInstructionHelper {\ public:\ LIR_HEADER(OsrReturnValue)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrReturnValue(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrReturnValue* mir() const { return mir_->toOsrReturnValue(); };\ };\ -\ class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(OsrArgumentsObject)\ + static constexpr size_t EntryIndex = 0;\ explicit LOsrArgumentsObject(const LAllocation& entry) : LInstructionHelper(classOpcode) {\ - setOperand(0, entry);\ + setOperand(EntryIndex, entry);\ }\ - const LAllocation* entry() { return getOperand(0); }\ + const LAllocation* entry() const { return getOperand(EntryIndex); }\ MOsrArgumentsObject* mir() const { return mir_->toOsrArgumentsObject(); };\ };\ -\ class LRegExp : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(RegExp)\ @@ -2796,257 +3630,142 @@ class LRegExp : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MRegExp* mir() const { return mir_->toRegExp(); };\ };\ -\ -class LRegExpMatcher : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpMatcher)\ - explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ -};\ -\ -class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ - public:\ - LIR_HEADER(RegExpSearcher)\ - explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - setOperand(2, lastIndex);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - const LAllocation* lastIndex() { return getOperand(2); }\ - MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ -};\ -\ -class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ - public:\ - LIR_HEADER(RegExpSearcherLastLimit)\ - explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRegExpExecMatch : public LInstructionHelper {\ - public:\ - LIR_HEADER(RegExpExecMatch)\ - explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ -};\ -\ -class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(RegExpExecTest)\ - explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, regexp);\ - setOperand(1, string);\ - }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* string() { return getOperand(1); }\ - MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ -};\ -\ class LRegExpHasCaptureGroups : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(RegExpHasCaptureGroups)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t InputIndex = 1;\ explicit LRegExpHasCaptureGroups(const LAllocation& regexp, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, regexp);\ - setOperand(1, input);\ + setOperand(RegexpIndex, regexp);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* regexp() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MRegExpHasCaptureGroups* mir() const { return mir_->toRegExpHasCaptureGroups(); };\ };\ -\ -class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(RegExpPrototypeOptimizable)\ - explicit LRegExpPrototypeOptimizable(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpPrototypeOptimizable* mir() const { return mir_->toRegExpPrototypeOptimizable(); };\ -};\ -\ -class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(RegExpInstanceOptimizable)\ - explicit LRegExpInstanceOptimizable(const LAllocation& object, const LAllocation& proto, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, proto);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* proto() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MRegExpInstanceOptimizable* mir() const { return mir_->toRegExpInstanceOptimizable(); };\ -};\ -\ class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(GetFirstDollarIndex)\ + static constexpr size_t StrIndex = 0;\ explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ };\ -\ class LStringReplace : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(StringReplace)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t PatternIndex = 1;\ + static constexpr size_t ReplacementIndex = 2;\ explicit LStringReplace(const LAllocation& string, const LAllocation& pattern, const LAllocation& replacement) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, string);\ - setOperand(1, pattern);\ - setOperand(2, replacement);\ + setOperand(StringIndex, string);\ + setOperand(PatternIndex, pattern);\ + setOperand(ReplacementIndex, replacement);\ }\ - const LAllocation* string() { return getOperand(0); }\ - const LAllocation* pattern() { return getOperand(1); }\ - const LAllocation* replacement() { return getOperand(2); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* pattern() const { return getOperand(PatternIndex); }\ + const LAllocation* replacement() const { return getOperand(ReplacementIndex); }\ MStringReplace* mir() const { return mir_->toStringReplace(); };\ };\ -\ -class LBinaryValueCache : public LInstructionHelper {\ +class LBinaryValueCache : public LInstructionHelper {\ public:\ LIR_HEADER(BinaryValueCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 2> {\ +class LBinaryBoolCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(BinaryBoolCache)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1 * BOX_PIECES;\ explicit LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(LhsIndex, lhs);\ setBoxOperand(RhsIndex, rhs);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t LhsIndex = 0;\ -\ - static const size_t RhsIndex = 0 + BOX_PIECES * 1;\ MBinaryCache* mir() const { return mir_->toBinaryCache(); };\ };\ -\ -class LUnaryCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(UnaryCache)\ - explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - }\ -\ - static const size_t InputIndex = 0;\ -};\ -\ class LModuleMetadata : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(ModuleMetadata)\ explicit LModuleMetadata() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MModuleMetadata* mir() const { return mir_->toModuleMetadata(); };\ };\ -\ -class LDynamicImport : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LDynamicImport : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DynamicImport)\ + static constexpr size_t SpecifierIndex = 0;\ + static constexpr size_t OptionsIndex = 1 * BOX_PIECES;\ explicit LDynamicImport(const LBoxAllocation& specifier, const LBoxAllocation& options) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(SpecifierIndex, specifier);\ setBoxOperand(OptionsIndex, options);\ }\ -\ - static const size_t SpecifierIndex = 0;\ -\ - static const size_t OptionsIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation specifier() const { return getBoxOperand(SpecifierIndex); }\ + LBoxAllocation options() const { return getBoxOperand(OptionsIndex); }\ MDynamicImport* mir() const { return mir_->toDynamicImport(); };\ };\ -\ class LLambda : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Lambda)\ + static constexpr size_t EnvironmentChainIndex = 0;\ explicit LLambda(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ + setOperand(EnvironmentChainIndex, environmentChain);\ setTemp(0, temp0);\ }\ - const LAllocation* environmentChain() { return getOperand(0); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLambda* mir() const { return mir_->toLambda(); };\ };\ -\ class LFunctionWithProto : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(FunctionWithProto)\ + static constexpr size_t EnvChainIndex = 0;\ + static constexpr size_t PrototypeIndex = 1;\ explicit LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, envChain);\ - setOperand(1, prototype);\ + setOperand(EnvChainIndex, envChain);\ + setOperand(PrototypeIndex, prototype);\ }\ - const LAllocation* envChain() { return getOperand(0); }\ - const LAllocation* prototype() { return getOperand(1); }\ + const LAllocation* envChain() const { return getOperand(EnvChainIndex); }\ + const LAllocation* prototype() const { return getOperand(PrototypeIndex); }\ MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); };\ };\ -\ -class LSetFunName : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetFunName)\ - explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, fun);\ - setBoxOperand(NameIndex, name);\ - }\ - const LAllocation* fun() { return getOperand(0); }\ - static const size_t NameIndex = 1;\ - MSetFunName* mir() const { return mir_->toSetFunName(); };\ -};\ -\ class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(KeepAliveObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LKeepAliveObject(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugEnterGCUnsafeRegion)\ @@ -3055,7 +3774,6 @@ class LDebugEnterGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(DebugLeaveGCUnsafeRegion)\ @@ -3064,1019 +3782,1096 @@ class LDebugLeaveGCUnsafeRegion : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LSlots : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Slots)\ - explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(Elements)\ - explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MElements* mir() const { return mir_->toElements(); };\ -};\ -\ -class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(InitializedLength)\ - explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetInitializedLength)\ - explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LArrayLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayLength)\ - explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ -};\ -\ -class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ - public:\ - LIR_HEADER(SetArrayLength)\ - explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionLength)\ - explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LFunctionName : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionName)\ - explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {\ public:\ LIR_HEADER(GetNextEntryForIterator)\ + static constexpr size_t IterIndex = 0;\ + static constexpr size_t ResultIndex = 1;\ explicit LGetNextEntryForIterator(const LAllocation& iter, const LAllocation& result, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ - setOperand(1, result);\ + setOperand(IterIndex, iter);\ + setOperand(ResultIndex, result);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* iter() { return getOperand(0); }\ - const LAllocation* result() { return getOperand(1); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ + const LAllocation* result() const { return getOperand(ResultIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGetNextEntryForIterator* mir() const { return mir_->toGetNextEntryForIterator(); };\ };\ -\ -class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferByteLength)\ - explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewLength)\ - explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ -};\ -\ -class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewByteOffset)\ - explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(ArrayBufferViewElements)\ - explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(TypedArrayElementSize)\ - explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LResizableTypedArrayLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableTypedArrayLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableTypedArrayLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ -};\ -\ -class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ - explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ class LResizableDataViewByteLength : public LInstructionHelper<1, 1, 1> {\ js::jit::Synchronization synchronization_;\ public:\ LIR_HEADER(ResizableDataViewByteLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LResizableDataViewByteLength(const LAllocation& object, const LDefinition& temp0, js::jit::Synchronization synchronization) : LInstructionHelper(classOpcode), synchronization_(synchronization) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); } js::jit::Synchronization synchronization() const { return synchronization_; }\ -\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + js::jit::Synchronization synchronization() const { return synchronization_; }\ };\ -\ -class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GrowableSharedArrayBufferByteLength)\ - explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LGuardResizableArrayBufferViewInBounds : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBounds)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardResizableArrayBufferViewInBoundsOrDetached : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardResizableArrayBufferViewInBoundsOrDetached(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasAttachedArrayBuffer : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardHasAttachedArrayBuffer)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasAttachedArrayBuffer(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNumberToIntPtrIndex : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(GuardNumberToIntPtrIndex)\ - explicit LGuardNumberToIntPtrIndex(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNumberToIntPtrIndex(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardNumberToIntPtrIndex* mir() const { return mir_->toGuardNumberToIntPtrIndex(); };\ };\ -\ class LBoundsCheck : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(BoundsCheck)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LBoundsCheck(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ +};\ +class LBoundsCheckRange : public LInstructionHelper<0, 2, 1> {\ + public:\ + LIR_HEADER(BoundsCheckRange)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LBoundsCheckRange(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MBoundsCheck* mir() const { return mir_->toBoundsCheck(); };\ };\ -\ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(BoundsCheckLower)\ + static constexpr size_t IndexIndex = 0;\ explicit LBoundsCheckLower(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MBoundsCheckLower* mir() const { return mir_->toBoundsCheckLower(); };\ };\ -\ class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(SpectreMaskIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ explicit LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ MSpectreMaskIndex* mir() const { return mir_->toSpectreMaskIndex(); };\ };\ -\ +class LLoadElementV : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadElementV(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadElement* mir() const { return mir_->toLoadElement(); };\ +};\ class LInArray : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(InArray)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ explicit LInArray(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, initLength);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* initLength() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ MInArray* mir() const { return mir_->toInArray(); };\ };\ -\ class LGuardElementNotHole : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardElementNotHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardElementNotHole(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LLoadElementHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t InitLengthIndex = 2;\ + explicit LLoadElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& initLength) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(InitLengthIndex, initLength);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* initLength() const { return getOperand(InitLengthIndex); }\ + MLoadElementHole* mir() const { return mir_->toLoadElementHole(); };\ +};\ +class LStoreElementV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreElementV)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementV(const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ +};\ +class LStoreElementT : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(StoreElementT)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreElementT(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MStoreElement* mir() const { return mir_->toStoreElement(); };\ + inline const char* extraName() const;\ };\ -\ class LStoreHoleValueElement : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreHoleValueElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LStoreHoleValueElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ -class LStoreElementHoleV : public LInstructionHelper<0, 1 * BOX_PIECES + 3, 1> {\ +class LStoreElementHoleV : public LInstructionHelper<0, 3 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(StoreElementHoleV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleV(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 3;\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreElementHoleT)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ElementsIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreElementHoleT(const LAllocation& object, const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, elements);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* elements() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreElementHole* mir() const { return mir_->toStoreElementHole(); };\ };\ -\ -class LArrayPush : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 2> {\ +class LArrayPopShift : public LInstructionHelper {\ public:\ - LIR_HEADER(ArrayPush)\ - explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ + LIR_HEADER(ArrayPopShift)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayPopShift(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MArrayPush* mir() const { return mir_->toArrayPush(); };\ + MArrayPopShift* mir() const { return mir_->toArrayPopShift(); };\ + inline const char* extraName() const;\ };\ -\ -class LArraySlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArraySlice)\ - explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArraySlice* mir() const { return mir_->toArraySlice(); };\ -};\ -\ -class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ - public:\ - LIR_HEADER(ArgumentsSlice)\ - explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, begin);\ - setOperand(2, end);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* begin() { return getOperand(1); }\ - const LAllocation* end() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ -};\ -\ class LFrameArgumentsSlice : public LInstructionHelper<1, 2, 1> {\ public:\ LIR_HEADER(FrameArgumentsSlice)\ + static constexpr size_t BeginIndex = 0;\ + static constexpr size_t CountIndex = 1;\ explicit LFrameArgumentsSlice(const LAllocation& begin, const LAllocation& count, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, begin);\ - setOperand(1, count);\ + setOperand(BeginIndex, begin);\ + setOperand(CountIndex, count);\ setTemp(0, temp0);\ }\ - const LAllocation* begin() { return getOperand(0); }\ - const LAllocation* count() { return getOperand(1); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* count() const { return getOperand(CountIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MFrameArgumentsSlice* mir() const { return mir_->toFrameArgumentsSlice(); };\ };\ -\ -class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(NormalizeSliceTerm)\ - explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - setOperand(1, length);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ -};\ -\ -class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ - public:\ - LIR_HEADER(ArrayJoin)\ - explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, array);\ - setOperand(1, separator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* array() { return getOperand(0); }\ - const LAllocation* separator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ -};\ -\ class LObjectKeys : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeys)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeys(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ class LObjectKeysLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectKeysLength)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectKeysLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1> {\ +class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 2> {\ public:\ LIR_HEADER(LoadUnboxedScalar)\ - explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ + setTemp(1, temp1);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ };\ -\ -class LLoadTypedArrayElementHole : public LInstructionHelper {\ +class LLoadUnboxedInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadUnboxedInt64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LLoadDataViewElement : public LInstructionHelper<1, 3, 2 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(LoadDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian, const LDefinition& temp0, const LDefinition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setInt64Temp(2 + 0 * INT64_PIECES, temp2);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + LInt64Definition temp2() { return getInt64Temp(2 + 0 * INT64_PIECES); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadDataViewElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + explicit LLoadDataViewElement64(const LAllocation& elements, const LAllocation& index, const LAllocation& littleEndian) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + MLoadDataViewElement* mir() const { return mir_->toLoadDataViewElement(); };\ +};\ +class LLoadTypedArrayElementHole : public LInstructionHelper {\ public:\ LIR_HEADER(LoadTypedArrayElementHole)\ - explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, length);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHole(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* length() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ };\ -\ -class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0> {\ +class LLoadTypedArrayElementHoleBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadTypedArrayElementHoleBigInt)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LLoadTypedArrayElementHoleBigInt(const LAllocation& elements, const LAllocation& index, const LAllocation& length, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MLoadTypedArrayElementHole* mir() const { return mir_->toLoadTypedArrayElementHole(); };\ +};\ +class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(StoreUnboxedScalar)\ - explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedScalar(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ };\ -\ +class LStoreUnboxedInt64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(StoreUnboxedInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreUnboxedInt64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LStoreDataViewElement : public LInstructionHelper<0, 4, 1 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + static constexpr size_t LittleEndianIndex = 3;\ + explicit LStoreDataViewElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LAllocation& littleEndian, const LDefinition& temp0, const LInt64Definition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setOperand(LittleEndianIndex, littleEndian);\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ +class LStoreDataViewElement64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(StoreDataViewElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t LittleEndianIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreDataViewElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LAllocation& littleEndian, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(LittleEndianIndex, littleEndian);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* littleEndian() const { return getOperand(LittleEndianIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MStoreDataViewElement* mir() const { return mir_->toStoreDataViewElement(); };\ +};\ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1> {\ public:\ LIR_HEADER(StoreTypedArrayElementHole)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ explicit LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, length);\ - setOperand(2, index);\ - setOperand(3, value);\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ +};\ +class LStoreTypedArrayElementHoleInt64 : public LInstructionHelper<0, 3 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(StoreTypedArrayElementHoleInt64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LStoreTypedArrayElementHoleInt64(const LAllocation& elements, const LAllocation& length, const LAllocation& index, const LInt64Allocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(LengthIndex, length);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MStoreTypedArrayElementHole* mir() const { return mir_->toStoreTypedArrayElementHole(); };\ };\ -\ class LAtomicIsLockFree : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AtomicIsLockFree)\ + static constexpr size_t ValueIndex = 0;\ explicit LAtomicIsLockFree(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ +};\ +class LCompareExchangeTypedArrayElement : public LInstructionHelper<1, 4, 1> {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 3;\ + explicit LCompareExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& oldval, const LAllocation& newval, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(OldvalIndex, oldval);\ + setOperand(NewvalIndex, newval);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* oldval() const { return getOperand(OldvalIndex); }\ + const LAllocation* newval() const { return getOperand(NewvalIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop(const LAllocation& elements, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect(const LAllocation& elements, const LAllocation& index, const LAllocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicLoad64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicLoad64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LAtomicLoad64(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLoadUnboxedScalar* mir() const { return mir_->toLoadUnboxedScalar(); };\ +};\ +class LAtomicStore64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(AtomicStore64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicStore64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MStoreUnboxedScalar* mir() const { return mir_->toStoreUnboxedScalar(); };\ +};\ +class LCompareExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(CompareExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t OldvalIndex = 2;\ + static constexpr size_t NewvalIndex = 2 + 1 * INT64_PIECES;\ + explicit LCompareExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& oldval, const LInt64Allocation& newval) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(OldvalIndex, oldval);\ + setInt64Operand(NewvalIndex, newval);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation oldval() const { return getInt64Operand(OldvalIndex); }\ + LInt64Allocation newval() const { return getInt64Operand(NewvalIndex); }\ + MCompareExchangeTypedArrayElement* mir() const { return mir_->toCompareExchangeTypedArrayElement(); };\ +};\ +class LAtomicExchangeTypedArrayElement64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicExchangeTypedArrayElement64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicExchangeTypedArrayElement64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MAtomicExchangeTypedArrayElement* mir() const { return mir_->toAtomicExchangeTypedArrayElement(); };\ +};\ +class LAtomicTypedArrayElementBinop64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinop64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinop64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ +};\ +class LAtomicTypedArrayElementBinopForEffect64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ + public:\ + LIR_HEADER(AtomicTypedArrayElementBinopForEffect64)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LAtomicTypedArrayElementBinopForEffect64(const LAllocation& elements, const LAllocation& index, const LInt64Allocation& value, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + setInt64Operand(ValueIndex, value);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ + MAtomicTypedArrayElementBinop* mir() const { return mir_->toAtomicTypedArrayElementBinop(); };\ };\ -\ class LEffectiveAddress : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(EffectiveAddress)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LEffectiveAddress(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ - setOperand(1, index);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MEffectiveAddress* mir() const { return mir_->toEffectiveAddress(); };\ };\ -\ class LClampIToUint8 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ClampIToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampIToUint8(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LClampDToUint8 : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(ClampDToUint8)\ - explicit LClampDToUint8(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LClampDToUint8(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LClampVToUint8 : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LClampVToUint8 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(ClampVToUint8)\ + static constexpr size_t InputIndex = 0;\ explicit LClampVToUint8(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MClampToUint8* mir() const { return mir_->toClampToUint8(); };\ };\ -\ -class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadScriptedProxyHandler)\ - explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ -};\ -\ -class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 3 * BOX_PIECES + 0, 2> {\ - public:\ - LIR_HEADER(CheckScriptedProxyGetResult)\ - explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setBoxOperand(TargetIndex, target);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t TargetIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ -\ - static const size_t ValueIndex = 0 + BOX_PIECES * 2;\ - MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ -};\ -\ -class LIdToStringOrSymbol : public LInstructionHelper {\ - public:\ - LIR_HEADER(IdToStringOrSymbol)\ - explicit LIdToStringOrSymbol(const LBoxAllocation& id, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t IdIndex = 0;\ - MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ -};\ -\ class LLoadFixedSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotV(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadFixedSlotAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndAtomize(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotT)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotT(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlot* mir() const { return mir_->toLoadFixedSlot(); };\ };\ -\ class LLoadFixedSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotAndUnbox)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotAndUnbox(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotAndUnbox : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotAndUnbox)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotAndUnbox(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ class LLoadElementAndUnbox : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(LoadElementAndUnbox)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LLoadElementAndUnbox(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ MLoadElementAndUnbox* mir() const { return mir_->toLoadElementAndUnbox(); };\ };\ -\ class LLoadFixedSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadFixedSlotUnboxAndAtomize)\ + static constexpr size_t ObjectIndex = 0;\ explicit LLoadFixedSlotUnboxAndAtomize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MLoadFixedSlotAndUnbox* mir() const { return mir_->toLoadFixedSlotAndUnbox(); };\ };\ -\ class LLoadDynamicSlotUnboxAndAtomize : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(LoadDynamicSlotUnboxAndAtomize)\ + static constexpr size_t SlotsIndex = 0;\ explicit LLoadDynamicSlotUnboxAndAtomize(const LAllocation& slots) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ }\ - const LAllocation* slots() { return getOperand(0); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ MLoadDynamicSlotAndUnbox* mir() const { return mir_->toLoadDynamicSlotAndUnbox(); };\ };\ -\ -class LAddAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAddAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AddAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAddAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MAddAndStoreSlot* mir() const { return mir_->toAddAndStoreSlot(); };\ };\ -\ -class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 2> {\ - public:\ - LIR_HEADER(AllocateAndStoreSlot)\ - explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 1;\ - MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ -};\ -\ -class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(AddSlotAndCallAddPropHook)\ - explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ - MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ -};\ -\ -class LStoreFixedSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreFixedSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreFixedSlotV)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreFixedSlotT)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreFixedSlotT(const LAllocation& obj, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ - setOperand(1, value);\ + setOperand(ObjIndex, obj);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreFixedSlot* mir() const { return mir_->toStoreFixedSlot(); };\ };\ -\ -class LGetNameCache : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetNameCache)\ - explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, envObj);\ - setTemp(0, temp0);\ - }\ - const LAllocation* envObj() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ -};\ -\ -class LCallGetIntrinsicValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetIntrinsicValue)\ - explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ -};\ -\ -class LGetPropSuperCache : public LInstructionHelper {\ +class LGetPropSuperCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropSuperCache)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t ReceiverIndex = 1;\ + static constexpr size_t IdIndex = 1 + 1 * BOX_PIECES;\ explicit LGetPropSuperCache(const LAllocation& obj, const LBoxAllocation& receiver, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, obj);\ + setOperand(ObjIndex, obj);\ setBoxOperand(ReceiverIndex, receiver);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t ReceiverIndex = 1;\ -\ - static const size_t IdIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropSuperCache* mir() const { return mir_->toGetPropSuperCache(); };\ };\ -\ -class LGetPropertyCache : public LInstructionHelper {\ +class LGetPropertyCache : public LInstructionHelper {\ public:\ LIR_HEADER(GetPropertyCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LGetPropertyCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MGetPropertyCache* mir() const { return mir_->toGetPropertyCache(); };\ };\ -\ -class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(BindNameCache)\ - explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - setTemp(0, temp0);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ -};\ -\ -class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(CallBindVar)\ - explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ - setOperand(0, environmentChain);\ - }\ - const LAllocation* environmentChain() { return getOperand(0); }\ - MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ -};\ -\ class LLoadDynamicSlotV : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotV)\ - explicit LLoadDynamicSlotV(const LAllocation& in) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotV(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ class LLoadDynamicSlotAndAtomize : public LInstructionHelper {\ public:\ LIR_HEADER(LoadDynamicSlotAndAtomize)\ - explicit LLoadDynamicSlotAndAtomize(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LLoadDynamicSlotAndAtomize(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MLoadDynamicSlot* mir() const { return mir_->toLoadDynamicSlot(); };\ };\ -\ -class LStoreDynamicSlotV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ +class LStoreDynamicSlotV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotV)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotV(const LAllocation& slots, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ + setOperand(SlotsIndex, slots);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ class LStoreDynamicSlotT : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(StoreDynamicSlotT)\ + static constexpr size_t SlotsIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LStoreDynamicSlotT(const LAllocation& slots, const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, slots);\ - setOperand(1, value);\ + setOperand(SlotsIndex, slots);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* slots() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* slots() const { return getOperand(SlotsIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MStoreDynamicSlot* mir() const { return mir_->toStoreDynamicSlot(); };\ };\ -\ -class LStringLength : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(StringLength)\ - explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ class LFloor : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Floor)\ - explicit LFloor(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloor(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LFloorF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(FloorF)\ - explicit LFloorF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LFloorF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeil : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Ceil)\ - explicit LCeil(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeil(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LCeilF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(CeilF)\ - explicit LCeilF(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ + static constexpr size_t InputIndex = 0;\ + explicit LCeilF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* string() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LRound : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(Round)\ - explicit LRound(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRound(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LRoundF : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(RoundF)\ - explicit LRoundF(const LAllocation& num, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LRoundF(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MRound* mir() const { return mir_->toRound(); };\ };\ -\ class LTrunc : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Trunc)\ - explicit LTrunc(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTrunc(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LTruncF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(TruncF)\ - explicit LTruncF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LTruncF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LNearbyInt : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyInt)\ - explicit LNearbyInt(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyInt(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ class LNearbyIntF : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NearbyIntF)\ - explicit LNearbyIntF(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + static constexpr size_t InputIndex = 0;\ + explicit LNearbyIntF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MNearbyInt* mir() const { return mir_->toNearbyInt(); };\ };\ -\ -class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(FunctionEnvironment)\ - explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HomeObject)\ - explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - }\ - const LAllocation* function() { return getOperand(0); }\ -};\ -\ -class LHomeObjectSuperBase : public LInstructionHelper {\ - public:\ - LIR_HEADER(HomeObjectSuperBase)\ - explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, homeObject);\ - }\ - const LAllocation* homeObject() { return getOperand(0); }\ -};\ -\ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewLexicalEnvironmentObject)\ @@ -4086,7 +4881,6 @@ class LNewLexicalEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewLexicalEnvironmentObject* mir() const { return mir_->toNewLexicalEnvironmentObject(); };\ };\ -\ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewClassBodyEnvironmentObject)\ @@ -4096,7 +4890,6 @@ class LNewClassBodyEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewClassBodyEnvironmentObject* mir() const { return mir_->toNewClassBodyEnvironmentObject(); };\ };\ -\ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(NewVarEnvironmentObject)\ @@ -4106,645 +4899,521 @@ class LNewVarEnvironmentObject : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MNewVarEnvironmentObject* mir() const { return mir_->toNewVarEnvironmentObject(); };\ };\ -\ -class LMegamorphicSetElement : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 3> {\ +class LMegamorphicSetElement : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3> {\ public:\ LIR_HEADER(MegamorphicSetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LMegamorphicSetElement(const LAllocation& object, const LBoxAllocation& index, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IndexIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MMegamorphicSetElement* mir() const { return mir_->toMegamorphicSetElement(); };\ };\ -\ -class LCallDeleteProperty : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCallDeleteProperty : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteProperty)\ + static constexpr size_t ValueIndex = 0;\ explicit LCallDeleteProperty(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MDeleteProperty* mir() const { return mir_->toDeleteProperty(); };\ };\ -\ -class LCallDeleteElement : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCallDeleteElement : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CallDeleteElement)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IndexIndex = 1 * BOX_PIECES;\ explicit LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IndexIndex, index);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IndexIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation index() const { return getBoxOperand(IndexIndex); }\ MDeleteElement* mir() const { return mir_->toDeleteElement(); };\ };\ -\ class LObjectToIterator : public LInstructionHelper<1, 1, 3> {\ public:\ LIR_HEADER(ObjectToIterator)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectToIterator(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MObjectToIterator* mir() const { return mir_->toObjectToIterator(); };\ };\ -\ -class LValueToIterator : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LValueToIterator : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(ValueToIterator)\ + static constexpr size_t ValueIndex = 0;\ explicit LValueToIterator(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MValueToIterator* mir() const { return mir_->toValueToIterator(); };\ };\ -\ -class LLoadSlotByIteratorIndex : public LInstructionHelper {\ +class LIteratorHasIndicesAndBranch : public LControlInstructionHelper<2, 2, 2> {\ public:\ - LIR_HEADER(LoadSlotByIteratorIndex)\ - explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ + LIR_HEADER(IteratorHasIndicesAndBranch)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LIteratorHasIndicesAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(StoreSlotByIteratorIndex)\ - explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, iterator);\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* iterator() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 2;\ - MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ -};\ -\ -class LSetPropertyCache : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 2> {\ +class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(SetPropertyCache)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ explicit LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(IdIndex, id);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t ValueIndex = 1 + BOX_PIECES * 1;\ MSetPropertyCache* mir() const { return mir_->toSetPropertyCache(); };\ };\ -\ -class LGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 2> {\ +class LGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(GetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ explicit LGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t ValueIndex = 0;\ MGetIteratorCache* mir() const { return mir_->toGetIteratorCache(); };\ };\ -\ -class LOptimizeSpreadCallCache : public LInstructionHelper {\ +class LIsNoIterAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(OptimizeSpreadCallCache)\ - explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ + LIR_HEADER(IsNoIterAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LIteratorMore : public LInstructionHelper {\ - public:\ - LIR_HEADER(IteratorMore)\ - explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iterator);\ - setTemp(0, temp0);\ - }\ - const LAllocation* iterator() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ -};\ -\ -class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ - public:\ - LIR_HEADER(IteratorEnd)\ - explicit LIteratorEnd(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ -};\ -\ class LCloseIterCache : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(CloseIterCache)\ + static constexpr size_t IterIndex = 0;\ explicit LCloseIterCache(const LAllocation& iter, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, iter);\ + setOperand(IterIndex, iter);\ setTemp(0, temp0);\ }\ - const LAllocation* iter() { return getOperand(0); }\ + const LAllocation* iter() const { return getOperand(IterIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MCloseIterCache* mir() const { return mir_->toCloseIterCache(); };\ };\ -\ -class LOptimizeGetIteratorCache : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(OptimizeGetIteratorCache)\ - explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ - MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ -};\ -\ -class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(ArgumentsLength)\ - explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ -};\ -\ -class LGetFrameArgument : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgument)\ - explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - }\ - const LAllocation* index() { return getOperand(0); }\ -};\ -\ -class LGetFrameArgumentHole : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetFrameArgumentHole)\ - explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setTemp(0, temp0);\ - }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LRest : public LInstructionHelper<1, 1, 4> {\ - public:\ - LIR_HEADER(Rest)\ - explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, numActuals);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* numActuals() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MRest* mir() const { return mir_->toRest(); };\ -};\ -\ class LInt32ToIntPtr : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(Int32ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ explicit LInt32ToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MInt32ToIntPtr* mir() const { return mir_->toInt32ToIntPtr(); };\ };\ -\ class LNonNegativeIntPtrToInt32 : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(NonNegativeIntPtrToInt32)\ + static constexpr size_t InputIndex = 0;\ explicit LNonNegativeIntPtrToInt32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LIntPtrToDouble : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IntPtrToDouble)\ + static constexpr size_t InputIndex = 0;\ explicit LIntPtrToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ class LAdjustDataViewLength : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(AdjustDataViewLength)\ + static constexpr size_t InputIndex = 0;\ explicit LAdjustDataViewLength(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAdjustDataViewLength* mir() const { return mir_->toAdjustDataViewLength(); };\ };\ -\ class LBooleanToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(BooleanToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LBooleanToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LStringToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(StringToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LStringToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ -class LValueToInt64 : public LInstructionHelper {\ +class LValueToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(ValueToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MToInt64* mir() const { return mir_->toToInt64(); };\ };\ -\ class LTruncateBigIntToInt64 : public LInstructionHelper {\ public:\ LIR_HEADER(TruncateBigIntToInt64)\ + static constexpr size_t InputIndex = 0;\ explicit LTruncateBigIntToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MTruncateBigIntToInt64* mir() const { return mir_->toTruncateBigIntToInt64(); };\ };\ -\ -class LInt64ToBigInt : public LInstructionHelper<1, 1 * INT64_PIECES + 0, 1> {\ +class LInt64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0 + 1 * INT64_PIECES> {\ public:\ LIR_HEADER(Int64ToBigInt)\ - explicit LInt64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToBigInt(const LInt64Allocation& input, const LInt64Definition& temp0) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + setInt64Temp(0 + 0 * INT64_PIECES, temp0);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + LInt64Definition temp0() { return getInt64Temp(0 + 0 * INT64_PIECES); }\ +};\ +class LUint64ToBigInt : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 1> {\ + public:\ + LIR_HEADER(Uint64ToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LUint64ToBigInt(const LInt64Allocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setInt64Operand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LInt64Allocation input() { return getInt64Operand(InputIndex); }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); };\ };\ -\ +class LInt64ToIntPtr : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(Int64ToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LInt64ToIntPtr(const LInt64Allocation& input) : LInstructionHelper(classOpcode) {\ + setInt64Operand(InputIndex, input);\ + }\ + LInt64Allocation input() const { return getInt64Operand(InputIndex); }\ + MInt64ToIntPtr* mir() const { return mir_->toInt64ToIntPtr(); };\ +};\ +class LIntPtrToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(IntPtrToInt64)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToInt64(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierO(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierS : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierS(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteBarrierBI : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(PostWriteBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierBI(const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ -class LPostWriteBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LPostWriteBarrierV : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LPostWriteBarrierV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ MPostWriteBarrier* mir() const { return mir_->toPostWriteBarrier(); };\ };\ -\ class LPostWriteElementBarrierO : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierO)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierO(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierS : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierS)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierS(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ class LPostWriteElementBarrierBI : public LInstructionHelper<0, 3, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierBI)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ explicit LPostWriteElementBarrierBI(const LAllocation& object, const LAllocation& value, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, value);\ - setOperand(2, index);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LPostWriteElementBarrierV : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 1> {\ +class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(PostWriteElementBarrierV)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ explicit LPostWriteElementBarrierV(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 2;\ MPostWriteElementBarrier* mir() const { return mir_->toPostWriteElementBarrier(); };\ };\ -\ -class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ +class LAssertCanElidePostWriteBarrier : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(AssertCanElidePostWriteBarrier)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAssertCanElidePostWriteBarrier(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 1;\ };\ -\ class LGuardObjectIdentity : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardObjectIdentity)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardObjectIdentity(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ MGuardObjectIdentity* mir() const { return mir_->toGuardObjectIdentity(); };\ };\ -\ class LGuardSpecificFunction : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardSpecificFunction)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardSpecificFunction(const LAllocation& input, const LAllocation& expected) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setOperand(1, expected);\ + setOperand(InputIndex, input);\ + setOperand(ExpectedIndex, expected);\ }\ - const LAllocation* input() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ };\ -\ class LGuardSpecificAtom : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardSpecificAtom)\ + static constexpr size_t StrIndex = 0;\ explicit LGuardSpecificAtom(const LAllocation& str, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, str);\ + setOperand(StrIndex, str);\ setTemp(0, temp0);\ }\ - const LAllocation* str() { return getOperand(0); }\ + const LAllocation* str() const { return getOperand(StrIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardSpecificAtom* mir() const { return mir_->toGuardSpecificAtom(); };\ };\ -\ class LGuardSpecificSymbol : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificSymbol)\ + static constexpr size_t SymbolIndex = 0;\ explicit LGuardSpecificSymbol(const LAllocation& symbol) : LInstructionHelper(classOpcode) {\ - setOperand(0, symbol);\ + setOperand(SymbolIndex, symbol);\ }\ - const LAllocation* symbol() { return getOperand(0); }\ + const LAllocation* symbol() const { return getOperand(SymbolIndex); }\ MGuardSpecificSymbol* mir() const { return mir_->toGuardSpecificSymbol(); };\ };\ -\ class LGuardSpecificInt32 : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardSpecificInt32)\ + static constexpr size_t NumIndex = 0;\ explicit LGuardSpecificInt32(const LAllocation& num) : LInstructionHelper(classOpcode) {\ - setOperand(0, num);\ + setOperand(NumIndex, num);\ }\ - const LAllocation* num() { return getOperand(0); }\ + const LAllocation* num() const { return getOperand(NumIndex); }\ MGuardSpecificInt32* mir() const { return mir_->toGuardSpecificInt32(); };\ };\ -\ -class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(GuardStringToIndex)\ - explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - }\ - const LAllocation* string() { return getOperand(0); }\ -};\ -\ -class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardStringToInt32)\ - explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ - public:\ - LIR_HEADER(GuardStringToDouble)\ - explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, string);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* string() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LGuardShape : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(GuardShape)\ - explicit LGuardShape(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ - setTemp(0, temp0);\ - }\ - const LAllocation* in() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MGuardShape* mir() const { return mir_->toGuardShape(); };\ -};\ -\ -class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ - public:\ - LIR_HEADER(GuardMultipleShapes)\ - explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, shapeList);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* shapeList() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ -};\ -\ class LGuardProto : public LInstructionHelper<0, 2, 1> {\ public:\ LIR_HEADER(GuardProto)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ExpectedIndex = 1;\ explicit LGuardProto(const LAllocation& object, const LAllocation& expected, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, expected);\ + setOperand(ObjectIndex, object);\ + setOperand(ExpectedIndex, expected);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* expected() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* expected() const { return getOperand(ExpectedIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardNullProto : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNullProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardNullProto(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNativeObject : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNativeObject)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNativeObject(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardGlobalGeneration)\ @@ -4754,7 +5423,6 @@ class LGuardGlobalGeneration : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardGlobalGeneration* mir() const { return mir_->toGuardGlobalGeneration(); };\ };\ -\ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(GuardFuse)\ @@ -4764,980 +5432,1015 @@ class LGuardFuse : public LInstructionHelper<0, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFuse* mir() const { return mir_->toGuardFuse(); };\ };\ -\ class LGuardIsProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotProxy)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotProxy(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsNotDOMProxy : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotDOMProxy)\ + static constexpr size_t ProxyIndex = 0;\ explicit LGuardIsNotDOMProxy(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setTemp(0, temp0);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LProxyGet : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGet)\ - explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MProxyGet* mir() const { return mir_->toProxyGet(); };\ -};\ -\ -class LProxyGetByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ProxyGetByValue)\ - explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -};\ -\ -class LProxyHasProp : public LInstructionHelper {\ +class LProxyHasProp : public LInstructionHelper {\ public:\ LIR_HEADER(ProxyHasProp)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdIndex = 1;\ explicit LProxyHasProp(const LAllocation& proxy, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, proxy);\ + setOperand(ProxyIndex, proxy);\ setBoxOperand(IdIndex, id);\ }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MProxyHasProp* mir() const { return mir_->toProxyHasProp(); };\ };\ -\ -class LProxySet : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 1> {\ - public:\ - LIR_HEADER(ProxySet)\ - explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t RhsIndex = 1;\ - MProxySet* mir() const { return mir_->toProxySet(); };\ -};\ -\ -class LProxySetByValue : public LInstructionHelper<0, 2 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(ProxySetByValue)\ - explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& id, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, proxy);\ - setBoxOperand(IdIndex, id);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* proxy() { return getOperand(0); }\ - static const size_t IdIndex = 1;\ -\ - static const size_t RhsIndex = 1 + BOX_PIECES * 1;\ - MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ -};\ -\ -class LCallSetArrayLength : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(CallSetArrayLength)\ - explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, obj);\ - setBoxOperand(RhsIndex, rhs);\ - }\ - const LAllocation* obj() { return getOperand(0); }\ - static const size_t RhsIndex = 1;\ - MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ -};\ -\ -class LMegamorphicLoadSlot : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlot)\ - explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ -};\ -\ -class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MegamorphicLoadSlotByValue)\ - explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ -};\ -\ -class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicStoreSlot)\ - explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(RhsIndex, rhs);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t RhsIndex = 1;\ - MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ -};\ -\ -class LMegamorphicHasProp : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 3> {\ - public:\ - LIR_HEADER(MegamorphicHasProp)\ - explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& id, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setBoxOperand(IdIndex, id);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - static const size_t IdIndex = 1;\ - MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ -};\ -\ -class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SmallObjectVariableKeyHasProp)\ - explicit LSmallObjectVariableKeyHasProp(const LAllocation& id) : LInstructionHelper(classOpcode) {\ - setOperand(0, id);\ - }\ - const LAllocation* id() { return getOperand(0); }\ - MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ -};\ -\ class LGuardIsNotArrayBufferMaybeShared : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsNotArrayBufferMaybeShared)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsNotArrayBufferMaybeShared(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsFixedLengthTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsFixedLengthTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsFixedLengthTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardIsResizableTypedArray : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsResizableTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsResizableTypedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardHasProxyHandler : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardHasProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MGuardHasProxyHandler* mir() const { return mir_->toGuardHasProxyHandler(); };\ };\ -\ class LGuardNoDenseElements : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardNoDenseElements)\ - explicit LGuardNoDenseElements(const LAllocation& in, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, in);\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardNoDenseElements(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* in() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LInCache : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 1> {\ +class LInCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(InCache)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ setTemp(0, temp0);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t LhsIndex = 1;\ MInCache* mir() const { return mir_->toInCache(); };\ };\ -\ -class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LHasOwnCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(HasOwnCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LHasOwnCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MHasOwnCache* mir() const { return mir_->toHasOwnCache(); };\ };\ -\ -class LCheckPrivateFieldCache : public LInstructionHelper<1, 2 * BOX_PIECES + 0, 0> {\ +class LCheckPrivateFieldCache : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckPrivateFieldCache)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ explicit LCheckPrivateFieldCache(const LBoxAllocation& value, const LBoxAllocation& id) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setBoxOperand(IdIndex, id);\ }\ -\ - static const size_t ValueIndex = 0;\ -\ - static const size_t IdIndex = 0 + BOX_PIECES * 1;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ MCheckPrivateFieldCache* mir() const { return mir_->toCheckPrivateFieldCache(); };\ };\ -\ -class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(NewPrivateName)\ - explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ -};\ -\ class LInstanceOfO : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(InstanceOfO)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LInstanceOfO(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ -class LInstanceOfV : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LInstanceOfV : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(InstanceOfV)\ + static constexpr size_t RhsIndex = 0;\ + static constexpr size_t LhsIndex = 1;\ explicit LInstanceOfV(const LBoxAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(RhsIndex, rhs);\ setBoxOperand(LhsIndex, lhs);\ - setOperand(0, rhs);\ }\ - const LAllocation* rhs() { return getOperand(0); }\ - static const size_t LhsIndex = 1;\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + LBoxAllocation lhs() const { return getBoxOperand(LhsIndex); }\ MInstanceOf* mir() const { return mir_->toInstanceOf(); };\ };\ -\ class LIsCallableO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsCallableO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsCallableV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsCallableV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsCallableV)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsCallableV(const LBoxAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ObjectIndex = 0;\ MIsCallable* mir() const { return mir_->toIsCallable(); };\ };\ -\ -class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsConstructor)\ - explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ -};\ -\ -class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsCrossRealmArrayConstructor)\ - explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ class LIsArrayO : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsArrayO)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsArrayO(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ -class LIsArrayV : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ +class LIsArrayV : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(IsArrayV)\ + static constexpr size_t ValueIndex = 0;\ explicit LIsArrayV(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - static const size_t ValueIndex = 0;\ MIsArray* mir() const { return mir_->toIsArray(); };\ };\ -\ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(IsTypedArray)\ + static constexpr size_t ObjectIndex = 0;\ explicit LIsTypedArray(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ MIsTypedArray* mir() const { return mir_->toIsTypedArray(); };\ };\ -\ -class LIsObject : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LIsObjectAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ public:\ - LIR_HEADER(IsObject)\ - explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ObjectIndex, object);\ - }\ -\ - static const size_t ObjectIndex = 0;\ - MIsObject* mir() const { return mir_->toIsObject(); };\ -};\ -\ -class LIsNullOrUndefined : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(IsNullOrUndefined)\ - explicit LIsNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + LIR_HEADER(IsObjectAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ - MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ +};\ +class LIsNullOrUndefinedAndBranch : public LControlInstructionHelper<2, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefinedAndBranch)\ + static constexpr size_t InputIndex = 0;\ + explicit LIsNullOrUndefinedAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) : LControlInstructionHelper(classOpcode) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setBoxOperand(InputIndex, input);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ class LHasClass : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(HasClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LHasClass(const LAllocation& lhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ MHasClass* mir() const { return mir_->toHasClass(); };\ };\ -\ class LGuardToClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToClass* mir() const { return mir_->toGuardToClass(); };\ };\ -\ class LGuardToEitherClass : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToEitherClass)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToEitherClass(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToEitherClass* mir() const { return mir_->toGuardToEitherClass(); };\ };\ -\ class LGuardToFunction : public LInstructionHelper<1, 1, 1> {\ public:\ LIR_HEADER(GuardToFunction)\ + static constexpr size_t LhsIndex = 0;\ explicit LGuardToFunction(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ + setOperand(LhsIndex, lhs);\ setTemp(0, temp0);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardToFunction* mir() const { return mir_->toGuardToFunction(); };\ };\ -\ -class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ +class LWasmSelect : public LInstructionHelper<1, 3, 0> {\ public:\ - LIR_HEADER(ObjectClassToString)\ - explicit LObjectClassToString(const LAllocation& lhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, lhs);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmSelect)\ + static constexpr size_t TrueExprIndex = 0;\ + static constexpr size_t FalseExprIndex = 1;\ + static constexpr size_t CondExprIndex = 2;\ + explicit LWasmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(TrueExprIndex, trueExpr);\ + setOperand(FalseExprIndex, falseExpr);\ + setOperand(CondExprIndex, condExpr);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ + const LAllocation* trueExpr() const { return getOperand(TrueExprIndex); }\ + const LAllocation* falseExpr() const { return getOperand(FalseExprIndex); }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmSelectI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmSelectI64)\ + static constexpr size_t CondExprIndex = 0;\ + static constexpr size_t TrueExprIndex = 1;\ + static constexpr size_t FalseExprIndex = 1 + 1 * INT64_PIECES;\ + explicit LWasmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr, const LAllocation& condExpr) : LInstructionHelper(classOpcode) {\ + setOperand(CondExprIndex, condExpr);\ + setInt64Operand(TrueExprIndex, trueExpr);\ + setInt64Operand(FalseExprIndex, falseExpr);\ + }\ + const LAllocation* condExpr() const { return getOperand(CondExprIndex); }\ + LInt64Allocation trueExpr() const { return getInt64Operand(TrueExprIndex); }\ + LInt64Allocation falseExpr() const { return getInt64Operand(FalseExprIndex); }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ +};\ +class LWasmCompareAndSelect : public LInstructionHelper<1, 4, 0> {\ + MCompare::CompareType compareType_;\ + JSOp jsop_;\ + public:\ + LIR_HEADER(WasmCompareAndSelect)\ + static constexpr size_t LeftExprIndex = 0;\ + static constexpr size_t RightExprIndex = 1;\ + static constexpr size_t IfTrueExprIndex = 2;\ + static constexpr size_t IfFalseExprIndex = 3;\ + explicit LWasmCompareAndSelect(const LAllocation& leftExpr, const LAllocation& rightExpr, const LAllocation& ifTrueExpr, const LAllocation& ifFalseExpr, MCompare::CompareType compareType, JSOp jsop) : LInstructionHelper(classOpcode), compareType_(compareType), jsop_(jsop) {\ + setOperand(LeftExprIndex, leftExpr);\ + setOperand(RightExprIndex, rightExpr);\ + setOperand(IfTrueExprIndex, ifTrueExpr);\ + setOperand(IfFalseExprIndex, ifFalseExpr);\ + }\ + const LAllocation* leftExpr() const { return getOperand(LeftExprIndex); }\ + const LAllocation* rightExpr() const { return getOperand(RightExprIndex); }\ + const LAllocation* ifTrueExpr() const { return getOperand(IfTrueExprIndex); }\ + const LAllocation* ifFalseExpr() const { return getOperand(IfFalseExprIndex); }\ + MCompare::CompareType compareType() const { return compareType_; }\ + JSOp jsop() const { return jsop_; }\ + MWasmSelect* mir() const { return mir_->toWasmSelect(); };\ };\ -\ class LWasmAddOffset : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmAddOffset)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset(const LAllocation& base) : LInstructionHelper(classOpcode) {\ - setOperand(0, base);\ + setOperand(BaseIndex, base);\ }\ - const LAllocation* base() { return getOperand(0); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ -class LWasmAddOffset64 : public LInstructionHelper {\ +class LWasmAddOffset64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmAddOffset64)\ + static constexpr size_t BaseIndex = 0;\ explicit LWasmAddOffset64(const LInt64Allocation& base) : LInstructionHelper(classOpcode) {\ setInt64Operand(BaseIndex, base);\ }\ - const LInt64Allocation base() { return getInt64Operand(BaseIndex); }\ - static const size_t BaseIndex = 0;\ + LInt64Allocation base() const { return getInt64Operand(BaseIndex); }\ MWasmAddOffset* mir() const { return mir_->toWasmAddOffset(); };\ };\ -\ class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmBoundsCheck)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ explicit LWasmBoundsCheck(const LAllocation& ptr, const LAllocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ -class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ +class LWasmBoundsCheck64 : public LInstructionHelper {\ public:\ - LIR_HEADER(WasmBoundsCheckRange32)\ - explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ - setOperand(1, length);\ - setOperand(2, limit);\ - setTemp(0, temp0);\ + LIR_HEADER(WasmBoundsCheck64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1 * INT64_PIECES;\ + explicit LWasmBoundsCheck64(const LInt64Allocation& ptr, const LInt64Allocation& boundsCheckLimit) : LInstructionHelper(classOpcode) {\ + setInt64Operand(PtrIndex, ptr);\ + setInt64Operand(BoundsCheckLimitIndex, boundsCheckLimit);\ }\ - const LAllocation* index() { return getOperand(0); }\ - const LAllocation* length() { return getOperand(1); }\ - const LAllocation* limit() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); }\ - MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ + LInt64Allocation boundsCheckLimit() const { return getInt64Operand(BoundsCheckLimitIndex); }\ + MWasmBoundsCheck* mir() const { return mir_->toWasmBoundsCheck(); };\ };\ -\ class LWasmExtendU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmExtendU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmExtendU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmExtendU32Index* mir() const { return mir_->toWasmExtendU32Index(); };\ };\ -\ class LWasmWrapU32Index : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmWrapU32Index)\ + static constexpr size_t InputIndex = 0;\ explicit LWasmWrapU32Index(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MWasmWrapU32Index* mir() const { return mir_->toWasmWrapU32Index(); };\ };\ -\ class LWasmAlignmentCheck : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck(const LAllocation& ptr) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ + setOperand(PtrIndex, ptr);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ -class LWasmAlignmentCheck64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmAlignmentCheck64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmAlignmentCheck64)\ + static constexpr size_t PtrIndex = 0;\ explicit LWasmAlignmentCheck64(const LInt64Allocation& ptr) : LInstructionHelper(classOpcode) {\ setInt64Operand(PtrIndex, ptr);\ }\ - const LInt64Allocation ptr() { return getInt64Operand(PtrIndex); }\ - static const size_t PtrIndex = 0;\ + LInt64Allocation ptr() const { return getInt64Operand(PtrIndex); }\ MWasmAlignmentCheck* mir() const { return mir_->toWasmAlignmentCheck(); };\ };\ -\ class LWasmLoadInstance : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmLoadInstance)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmLoadInstance64 : public LInstructionHelper {\ public:\ LIR_HEADER(WasmLoadInstance64)\ + static constexpr size_t InstanceIndex = 0;\ explicit LWasmLoadInstance64(const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, instance);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* instance() { return getOperand(0); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ MWasmLoadInstance* mir() const { return mir_->toWasmLoadInstance(); };\ };\ -\ class LWasmHeapReg : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmHeapReg)\ explicit LWasmHeapReg() : LInstructionHelper(classOpcode) {\ -\ }\ -\ MWasmHeapReg* mir() const { return mir_->toWasmHeapReg(); };\ };\ -\ +class LWasmLoad : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmLoad)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoad(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmLoadI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmLoadI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + explicit LWasmLoadI64(const LAllocation& ptr, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoad* mir() const { return mir_->toWasmLoad(); };\ +};\ +class LWasmStore : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmStore)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStore(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ +class LWasmStoreI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmStoreI64)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t MemoryBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreI64(const LAllocation& ptr, const LInt64Allocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + MWasmStore* mir() const { return mir_->toWasmStore(); };\ +};\ class LAsmJSLoadHeap : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(AsmJSLoadHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t BoundsCheckLimitIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ explicit LAsmJSLoadHeap(const LAllocation& ptr, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, boundsCheckLimit);\ - setOperand(2, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* boundsCheckLimit() { return getOperand(1); }\ - const LAllocation* memoryBase() { return getOperand(2); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSLoadHeap* mir() const { return mir_->toAsmJSLoadHeap(); };\ };\ -\ class LAsmJSStoreHeap : public LInstructionHelper<1, 4, 0> {\ public:\ LIR_HEADER(AsmJSStoreHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t BoundsCheckLimitIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ explicit LAsmJSStoreHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& boundsCheckLimit, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ - setOperand(0, ptr);\ - setOperand(1, value);\ - setOperand(2, boundsCheckLimit);\ - setOperand(3, memoryBase);\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(BoundsCheckLimitIndex, boundsCheckLimit);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ - const LAllocation* ptr() { return getOperand(0); }\ - const LAllocation* value() { return getOperand(1); }\ - const LAllocation* boundsCheckLimit() { return getOperand(2); }\ - const LAllocation* memoryBase() { return getOperand(3); }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* boundsCheckLimit() const { return getOperand(BoundsCheckLimitIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ MAsmJSStoreHeap* mir() const { return mir_->toAsmJSStoreHeap(); };\ };\ -\ -class LWasmFence : public LInstructionHelper<0, 0, 0> {\ +class LWasmCompareExchangeHeap : public LInstructionHelper<1, 4, 0> {\ public:\ - LIR_HEADER(WasmFence)\ - explicit LWasmFence() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(WasmCompareExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t OldValueIndex = 1;\ + static constexpr size_t NewValueIndex = 2;\ + static constexpr size_t MemoryBaseIndex = 3;\ + explicit LWasmCompareExchangeHeap(const LAllocation& ptr, const LAllocation& oldValue, const LAllocation& newValue, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(OldValueIndex, oldValue);\ + setOperand(NewValueIndex, newValue);\ + setOperand(MemoryBaseIndex, memoryBase);\ }\ -\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* oldValue() const { return getOperand(OldValueIndex); }\ + const LAllocation* newValue() const { return getOperand(NewValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmCompareExchangeHeap* mir() const { return mir_->toWasmCompareExchangeHeap(); };\ +};\ +class LWasmAtomicExchangeHeap : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicExchangeHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicExchangeHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicExchangeHeap* mir() const { return mir_->toWasmAtomicExchangeHeap(); };\ +};\ +class LWasmAtomicBinopHeap : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeap)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeap(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + setTemp(0, temp0);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ +};\ +class LWasmAtomicBinopHeapForEffect : public LInstructionHelper<0, 3, 0> {\ + public:\ + LIR_HEADER(WasmAtomicBinopHeapForEffect)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmAtomicBinopHeapForEffect(const LAllocation& ptr, const LAllocation& value, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(ValueIndex, value);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmAtomicBinopHeap* mir() const { return mir_->toWasmAtomicBinopHeap(); };\ };\ -\ class LWasmLoadSlot : public LInstructionHelper<1, 1, 0> {\ size_t offset_;\ MIRType type_;\ MWideningOp wideningOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlot)\ - explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlot(const LAllocation& containerRef, size_t offset, MIRType type, MWideningOp wideningOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), wideningOp_(wideningOp), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElement : public LInstructionHelper<1, 2, 1> {\ MIRType type_;\ MWideningOp wideningOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElement)\ - explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElement(const LAllocation& base, const LAllocation& index, const LDefinition& temp0, MIRType type, MWideningOp wideningOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), wideningOp_(wideningOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MWideningOp wideningOp() const { return wideningOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadSlotI64 : public LInstructionHelper {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadSlotI64)\ - explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ - setOperand(0, containerRef);\ + static constexpr size_t ContainerRefIndex = 0;\ + explicit LWasmLoadSlotI64(const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmLoadElementI64 : public LInstructionHelper {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmLoadElementI64)\ - explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmLoadElementI64(const LAllocation& base, const LAllocation& index, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreSlot : public LInstructionHelper<0, 2, 0> {\ size_t offset_;\ MIRType type_;\ MNarrowingOp narrowingOp_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlot)\ - explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ - setOperand(0, value);\ - setOperand(1, containerRef);\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t ContainerRefIndex = 1;\ + explicit LWasmStoreSlot(const LAllocation& value, const LAllocation& containerRef, size_t offset, MIRType type, MNarrowingOp narrowingOp, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), type_(type), narrowingOp_(narrowingOp), maybeTrap_(maybeTrap) {\ + setOperand(ValueIndex, value);\ + setOperand(ContainerRefIndex, containerRef);\ }\ - const LAllocation* value() { return getOperand(0); }\ - const LAllocation* containerRef() { return getOperand(1); } size_t offset() const { return offset_; }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + size_t offset() const { return offset_; }\ MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmStoreSlotI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ size_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreSlotI64)\ - explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + static constexpr size_t ContainerRefIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreSlotI64(const LInt64Allocation& value, const LAllocation& containerRef, size_t offset, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap) {\ + setOperand(ContainerRefIndex, containerRef);\ setInt64Operand(ValueIndex, value);\ - setOperand(0, containerRef);\ }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); }\ - const LAllocation* containerRef() { return getOperand(0); } size_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 1;\ + const LAllocation* containerRef() const { return getOperand(ContainerRefIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ +};\ +class LWasmStoreStackResult : public LInstructionHelper<0, 2, 0> {\ + size_t offset_;\ + MIRType type_;\ + public:\ + LIR_HEADER(WasmStoreStackResult)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackResultsAreaIndex = 1;\ + explicit LWasmStoreStackResult(const LAllocation& value, const LAllocation& stackResultsArea, size_t offset, MIRType type) : LInstructionHelper(classOpcode), offset_(offset), type_(type) {\ + setOperand(ValueIndex, value);\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + size_t offset() const { return offset_; }\ + MIRType type() const { return type_; }\ +};\ +class LWasmStoreStackResultI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ + size_t offset_;\ + public:\ + LIR_HEADER(WasmStoreStackResultI64)\ + static constexpr size_t StackResultsAreaIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LWasmStoreStackResultI64(const LInt64Allocation& value, const LAllocation& stackResultsArea, size_t offset) : LInstructionHelper(classOpcode), offset_(offset) {\ + setOperand(StackResultsAreaIndex, stackResultsArea);\ + setInt64Operand(ValueIndex, value);\ + }\ + const LAllocation* stackResultsArea() const { return getOperand(StackResultsAreaIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + size_t offset() const { return offset_; }\ };\ -\ class LWasmStoreElement : public LInstructionHelper<0, 3, 1> {\ MIRType type_;\ MNarrowingOp narrowingOp_;\ Scale scale_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElement)\ - explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ - setOperand(2, value);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElement(const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, MIRType type, MNarrowingOp narrowingOp, Scale scale, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), type_(type), narrowingOp_(narrowingOp), scale_(scale), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } MIRType type() const { return type_; }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIRType type() const { return type_; }\ MNarrowingOp narrowingOp() const { return narrowingOp_; }\ Scale scale() const { return scale_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ -class LWasmStoreElementI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 2, 0> {\ - MaybeTrapSiteInfo maybeTrap_;\ +class LWasmStoreElementI64 : public LInstructionHelper<0, 2 + 1 * INT64_PIECES, 0> {\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ public:\ LIR_HEADER(WasmStoreElementI64)\ - explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, MaybeTrapSiteInfo maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ - setOperand(0, base);\ - setOperand(1, index);\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreElementI64(const LAllocation& base, const LAllocation& index, const LInt64Allocation& value, wasm::MaybeTrapSiteDesc maybeTrap) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ setInt64Operand(ValueIndex, value);\ }\ - const LAllocation* base() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LInt64Allocation value() { return getInt64Operand(ValueIndex); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ -\ - static const size_t ValueIndex = 2;\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LInt64Allocation value() const { return getInt64Operand(ValueIndex); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ };\ -\ class LWasmStoreElementRef : public LInstructionHelper<0, 4, 2> {\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreElementRef)\ - explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, base);\ - setOperand(2, index);\ - setOperand(3, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + static constexpr size_t IndexIndex = 2;\ + static constexpr size_t ValueIndex = 3;\ + explicit LWasmStoreElementRef(const LAllocation& instance, const LAllocation& base, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, const LDefinition& temp1, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* base() { return getOperand(1); }\ - const LAllocation* index() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); } MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ };\ -\ class LWasmLoadTableElement : public LInstructionHelper<1, 2, 0> {\ public:\ LIR_HEADER(WasmLoadTableElement)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LWasmLoadTableElement(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, elements);\ - setOperand(1, index);\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* elements() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ +};\ +class LWasmDerivedPointer : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmDerivedPointer)\ + static constexpr size_t BaseIndex = 0;\ + explicit LWasmDerivedPointer(const LAllocation& base) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + MWasmDerivedPointer* mir() const { return mir_->toWasmDerivedPointer(); };\ +};\ +class LWasmDerivedIndexPointer : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmDerivedIndexPointer)\ + static constexpr size_t BaseIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LWasmDerivedIndexPointer(const LAllocation& base, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(BaseIndex, base);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MWasmDerivedIndexPointer* mir() const { return mir_->toWasmDerivedIndexPointer(); };\ };\ -\ class LWasmStoreRef : public LInstructionHelper<0, 3, 1> {\ uint32_t offset_;\ - MaybeTrapSiteInfo maybeTrap_;\ + wasm::MaybeTrapSiteDesc maybeTrap_;\ WasmPreBarrierKind preBarrierKind_;\ public:\ LIR_HEADER(WasmStoreRef)\ - explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, MaybeTrapSiteInfo maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ - setOperand(0, instance);\ - setOperand(1, valueBase);\ - setOperand(2, value);\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ValueBaseIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmStoreRef(const LAllocation& instance, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t offset, wasm::MaybeTrapSiteDesc maybeTrap, WasmPreBarrierKind preBarrierKind) : LInstructionHelper(classOpcode), offset_(offset), maybeTrap_(maybeTrap), preBarrierKind_(preBarrierKind) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* valueBase() { return getOperand(1); }\ - const LAllocation* value() { return getOperand(2); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t offset() const { return offset_; }\ - MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t offset() const { return offset_; }\ + wasm::MaybeTrapSiteDesc maybeTrap() const { return maybeTrap_; }\ WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }\ -\ MWasmStoreRef* mir() const { return mir_->toWasmStoreRef(); };\ };\ -\ -class LWasmPostWriteBarrierImmediate : public LInstructionHelper<0, 4, 1> {\ - uint32_t valueOffset_;\ +class LWasmPostWriteBarrierWholeCell : public LInstructionHelper<0, 3, 1> {\ public:\ - LIR_HEADER(WasmPostWriteBarrierImmediate)\ - explicit LWasmPostWriteBarrierImmediate(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& value, const LDefinition& temp0, uint32_t valueOffset) : LInstructionHelper(classOpcode), valueOffset_(valueOffset) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, value);\ + LIR_HEADER(WasmPostWriteBarrierWholeCell)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LWasmPostWriteBarrierWholeCell(const LAllocation& instance, const LAllocation& object, const LAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* value() { return getOperand(3); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t valueOffset() const { return valueOffset_; }\ -\ - MWasmPostWriteBarrierImmediate* mir() const { return mir_->toWasmPostWriteBarrierImmediate(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmPostWriteBarrierWholeCell* mir() const { return mir_->toWasmPostWriteBarrierWholeCell(); };\ };\ -\ -class LWasmPostWriteBarrierIndex : public LInstructionHelper<0, 5, 1> {\ +class LWasmPostWriteBarrierEdgeAtIndex : public LInstructionHelper<0, 5, 1> {\ uint32_t elemSize_;\ public:\ - LIR_HEADER(WasmPostWriteBarrierIndex)\ - explicit LWasmPostWriteBarrierIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ - setOperand(0, instance);\ - setOperand(1, object);\ - setOperand(2, valueBase);\ - setOperand(3, index);\ - setOperand(4, value);\ + LIR_HEADER(WasmPostWriteBarrierEdgeAtIndex)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t ObjectIndex = 1;\ + static constexpr size_t ValueBaseIndex = 2;\ + static constexpr size_t IndexIndex = 3;\ + static constexpr size_t ValueIndex = 4;\ + explicit LWasmPostWriteBarrierEdgeAtIndex(const LAllocation& instance, const LAllocation& object, const LAllocation& valueBase, const LAllocation& index, const LAllocation& value, const LDefinition& temp0, uint32_t elemSize) : LInstructionHelper(classOpcode), elemSize_(elemSize) {\ + setOperand(InstanceIndex, instance);\ + setOperand(ObjectIndex, object);\ + setOperand(ValueBaseIndex, valueBase);\ + setOperand(IndexIndex, index);\ + setOperand(ValueIndex, value);\ setTemp(0, temp0);\ }\ - const LAllocation* instance() { return getOperand(0); }\ - const LAllocation* object() { return getOperand(1); }\ - const LAllocation* valueBase() { return getOperand(2); }\ - const LAllocation* index() { return getOperand(3); }\ - const LAllocation* value() { return getOperand(4); }\ - const LDefinition* temp0() { return getTemp(0); } uint32_t elemSize() const { return elemSize_; }\ -\ - MWasmPostWriteBarrierIndex* mir() const { return mir_->toWasmPostWriteBarrierIndex(); };\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* valueBase() const { return getOperand(ValueBaseIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + uint32_t elemSize() const { return elemSize_; }\ + MWasmPostWriteBarrierEdgeAtIndex* mir() const { return mir_->toWasmPostWriteBarrierEdgeAtIndex(); };\ };\ -\ class LWasmParameter : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmParameter)\ explicit LWasmParameter() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ +class LWasmParameterI64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmParameterI64)\ + explicit LWasmParameterI64() : LInstructionHelper(classOpcode) {\ + }\ +};\ class LWasmReturn : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(WasmReturn)\ + static constexpr size_t RvalIndex = 0;\ + static constexpr size_t InstanceIndex = 1;\ explicit LWasmReturn(const LAllocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ - setOperand(1, instance);\ + setOperand(RvalIndex, rval);\ + setOperand(InstanceIndex, instance);\ }\ - const LAllocation* rval() { return getOperand(0); }\ - const LAllocation* instance() { return getOperand(1); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ };\ -\ -class LWasmReturnI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 1, 0> {\ +class LWasmReturnI64 : public LInstructionHelper<0, 1 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmReturnI64)\ + static constexpr size_t InstanceIndex = 0;\ + static constexpr size_t RvalIndex = 1;\ explicit LWasmReturnI64(const LInt64Allocation& rval, const LAllocation& instance) : LInstructionHelper(classOpcode) {\ + setOperand(InstanceIndex, instance);\ setInt64Operand(RvalIndex, rval);\ - setOperand(0, instance);\ }\ - const LInt64Allocation rval() { return getInt64Operand(RvalIndex); }\ - const LAllocation* instance() { return getOperand(0); }\ - static const size_t RvalIndex = 1;\ + const LAllocation* instance() const { return getOperand(InstanceIndex); }\ + LInt64Allocation rval() const { return getInt64Operand(RvalIndex); }\ };\ -\ class LWasmReturnVoid : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmReturnVoid)\ + static constexpr size_t RvalIndex = 0;\ explicit LWasmReturnVoid(const LAllocation& rval) : LInstructionHelper(classOpcode) {\ - setOperand(0, rval);\ + setOperand(RvalIndex, rval);\ }\ - const LAllocation* rval() { return getOperand(0); }\ + const LAllocation* rval() const { return getOperand(RvalIndex); }\ };\ -\ class LWasmStackArg : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(WasmStackArg)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArg(const LAllocation& arg) : LInstructionHelper(classOpcode) {\ - setOperand(0, arg);\ + setOperand(ArgIndex, arg);\ }\ - const LAllocation* arg() { return getOperand(0); }\ + const LAllocation* arg() const { return getOperand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ -class LWasmStackArgI64 : public LInstructionHelper<0, 1 * INT64_PIECES + 0, 0> {\ +class LWasmStackArgI64 : public LInstructionHelper<0, 0 + 1 * INT64_PIECES, 0> {\ public:\ LIR_HEADER(WasmStackArgI64)\ + static constexpr size_t ArgIndex = 0;\ explicit LWasmStackArgI64(const LInt64Allocation& arg) : LInstructionHelper(classOpcode) {\ setInt64Operand(ArgIndex, arg);\ }\ - const LInt64Allocation arg() { return getInt64Operand(ArgIndex); }\ - static const size_t ArgIndex = 0;\ + LInt64Allocation arg() const { return getInt64Operand(ArgIndex); }\ MWasmStackArg* mir() const { return mir_->toWasmStackArg(); };\ };\ -\ class LWasmNullConstant : public LInstructionHelper<1, 0, 0> {\ public:\ LIR_HEADER(WasmNullConstant)\ explicit LWasmNullConstant() : LInstructionHelper(classOpcode) {\ -\ }\ -\ };\ -\ -class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ - public:\ - LIR_HEADER(WasmCallLandingPrePad)\ - explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ -\ - }\ -\ - MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ -};\ -\ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ public:\ LIR_HEADER(WasmStackResultArea)\ @@ -5747,158 +6450,189 @@ class LWasmStackResultArea : public LInstructionHelper<1, 0, 1> {\ const LDefinition* temp0() { return getTemp(0); }\ MWasmStackResultArea* mir() const { return mir_->toWasmStackResultArea(); };\ };\ -\ +class LAssertRangeI : public LInstructionHelper<0, 1, 0> {\ + public:\ + LIR_HEADER(AssertRangeI)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeI(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeD : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(AssertRangeD)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeD(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeF : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(AssertRangeF)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeF(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ +class LAssertRangeV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(AssertRangeV)\ + static constexpr size_t InputIndex = 0;\ + explicit LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MAssertRange* mir() const { return mir_->toAssertRange(); };\ +};\ class LAssertClass : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(AssertClass)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertClass(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ setTemp(0, temp0);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MAssertClass* mir() const { return mir_->toAssertClass(); };\ };\ -\ class LAssertShape : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(AssertShape)\ + static constexpr size_t InputIndex = 0;\ explicit LAssertShape(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MAssertShape* mir() const { return mir_->toAssertShape(); };\ };\ -\ -class LGuardValue : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardValue : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 1> {\ public:\ LIR_HEADER(GuardValue)\ - explicit LGuardValue(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + static constexpr size_t InputIndex = 0;\ + explicit LGuardValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ MGuardValue* mir() const { return mir_->toGuardValue(); };\ };\ -\ -class LGuardNullOrUndefined : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNullOrUndefined : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNullOrUndefined)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNullOrUndefined(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardNullOrUndefined* mir() const { return mir_->toGuardNullOrUndefined(); };\ };\ -\ -class LGuardIsNotObject : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardIsNotObject : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardIsNotObject)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardIsNotObject(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MGuardIsNotObject* mir() const { return mir_->toGuardIsNotObject(); };\ };\ -\ class LGuardFunctionFlags : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionFlags)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionFlags(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionFlags* mir() const { return mir_->toGuardFunctionFlags(); };\ };\ -\ class LGuardFunctionIsNonBuiltinCtor : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionIsNonBuiltinCtor)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionIsNonBuiltinCtor(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardFunctionKind : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardFunctionKind)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionKind(const LAllocation& function, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ setTemp(0, temp0);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ MGuardFunctionKind* mir() const { return mir_->toGuardFunctionKind(); };\ };\ -\ class LGuardFunctionScript : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardFunctionScript)\ + static constexpr size_t FunctionIndex = 0;\ explicit LGuardFunctionScript(const LAllocation& function) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ + setOperand(FunctionIndex, function);\ }\ - const LAllocation* function() { return getOperand(0); }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ MGuardFunctionScript* mir() const { return mir_->toGuardFunctionScript(); };\ };\ -\ -class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ - public:\ - LIR_HEADER(IncrementWarmUpCounter)\ - explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ -};\ -\ -class LLexicalCheck : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LLexicalCheck : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(LexicalCheck)\ + static constexpr size_t InputIndex = 0;\ explicit LLexicalCheck(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ MLexicalCheck* mir() const { return mir_->toLexicalCheck(); };\ };\ -\ class LThrowRuntimeLexicalError : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowRuntimeLexicalError)\ explicit LThrowRuntimeLexicalError() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowRuntimeLexicalError* mir() const { return mir_->toThrowRuntimeLexicalError(); };\ };\ -\ class LThrowMsg : public LInstructionHelper<0, 0, 0> {\ public:\ LIR_HEADER(ThrowMsg)\ explicit LThrowMsg() : LInstructionHelper(classOpcode) {\ this->setIsCall();\ -\ }\ -\ MThrowMsg* mir() const { return mir_->toThrowMsg(); };\ };\ -\ -class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ +class LMemoryBarrier : public LInstructionHelper<0, 0, 0> {\ + jit::MemoryBarrier barrier_;\ public:\ - LIR_HEADER(GlobalDeclInstantiation)\ - explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(MemoryBarrier)\ + explicit LMemoryBarrier(jit::MemoryBarrier barrier) : LInstructionHelper(classOpcode), barrier_(barrier) {\ }\ -\ - MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ + jit::MemoryBarrier barrier() const { return barrier_; }\ };\ -\ class LDebugger : public LInstructionHelper<0, 0, 1> {\ public:\ LIR_HEADER(Debugger)\ @@ -5908,889 +6642,3353 @@ class LDebugger : public LInstructionHelper<0, 0, 1> {\ }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ -class LNewTarget : public LInstructionHelper {\ +class LRandom : public LInstructionHelper<1, 0, 1 + 2 * INT64_PIECES> {\ public:\ - LIR_HEADER(NewTarget)\ - explicit LNewTarget() : LInstructionHelper(classOpcode) {\ -\ + LIR_HEADER(Random)\ + explicit LRandom(const LDefinition& temp0, const LInt64Definition& temp1, const LInt64Definition& temp2) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + setInt64Temp(1 + 0 * INT64_PIECES, temp1);\ + setInt64Temp(1 + 1 * INT64_PIECES, temp2);\ }\ -\ + const LDefinition* temp0() { return getTemp(0); }\ + LInt64Definition temp1() { return getInt64Temp(1 + 0 * INT64_PIECES); }\ + LInt64Definition temp2() { return getInt64Temp(1 + 1 * INT64_PIECES); }\ + MRandom* mir() const { return mir_->toRandom(); };\ };\ -\ -class LCheckReturn : public LInstructionHelper {\ - public:\ - LIR_HEADER(CheckReturn)\ - explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ReturnValueIndex, returnValue);\ - setBoxOperand(ThisValueIndex, thisValue);\ - }\ -\ - static const size_t ReturnValueIndex = 0;\ -\ - static const size_t ThisValueIndex = 0 + BOX_PIECES * 1;\ -};\ -\ -class LCheckIsObj : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(CheckIsObj)\ - explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ - MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ -};\ -\ -class LCheckObjCoercible : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckObjCoercible : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckObjCoercible)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckObjCoercible(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckClassHeritage : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 2> {\ +class LCheckClassHeritage : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 2> {\ public:\ LIR_HEADER(CheckClassHeritage)\ + static constexpr size_t HeritageIndex = 0;\ explicit LCheckClassHeritage(const LBoxAllocation& heritage, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ setBoxOperand(HeritageIndex, heritage);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ + LBoxAllocation heritage() const { return getBoxOperand(HeritageIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ - static const size_t HeritageIndex = 0;\ };\ -\ -class LCheckThis : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThis : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThis)\ + static constexpr size_t ValueIndex = 0;\ explicit LCheckThis(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LCheckThisReinit : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LCheckThisReinit : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CheckThisReinit)\ + static constexpr size_t ThisValueIndex = 0;\ explicit LCheckThisReinit(const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ setBoxOperand(ThisValueIndex, thisValue);\ }\ -\ - static const size_t ThisValueIndex = 0;\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ };\ -\ class LGenerator : public LInstructionHelper<1, 3, 0> {\ public:\ LIR_HEADER(Generator)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t EnvironmentChainIndex = 1;\ + static constexpr size_t ArgsObjectIndex = 2;\ explicit LGenerator(const LAllocation& callee, const LAllocation& environmentChain, const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, callee);\ - setOperand(1, environmentChain);\ - setOperand(2, argsObject);\ + setOperand(CalleeIndex, callee);\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setOperand(ArgsObjectIndex, argsObject);\ }\ - const LAllocation* callee() { return getOperand(0); }\ - const LAllocation* environmentChain() { return getOperand(1); }\ - const LAllocation* argsObject() { return getOperand(2); }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ MGenerator* mir() const { return mir_->toGenerator(); };\ };\ -\ -class LAsyncResolve : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncResolve : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncResolve)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncResolve(const LAllocation& generator, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncResolve* mir() const { return mir_->toAsyncResolve(); };\ };\ -\ -class LAsyncReject : public LInstructionHelper<1, 2 * BOX_PIECES + 1, 0> {\ +class LAsyncReject : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncReject)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ReasonIndex = 1;\ + static constexpr size_t StackIndex = 1 + 1 * BOX_PIECES;\ explicit LAsyncReject(const LAllocation& generator, const LBoxAllocation& reason, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, generator);\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ReasonIndex, reason);\ setBoxOperand(StackIndex, stack);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ReasonIndex = 1;\ -\ - static const size_t StackIndex = 1 + BOX_PIECES * 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation reason() const { return getBoxOperand(ReasonIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ MAsyncReject* mir() const { return mir_->toAsyncReject(); };\ };\ -\ -class LAsyncAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ +class LAsyncAwait : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(AsyncAwait)\ + static constexpr size_t GeneratorIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LAsyncAwait(const LBoxAllocation& value, const LAllocation& generator) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(GeneratorIndex, generator);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, generator);\ }\ - const LAllocation* generator() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* generator() const { return getOperand(GeneratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MAsyncAwait* mir() const { return mir_->toAsyncAwait(); };\ };\ -\ -class LCanSkipAwait : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ +class LCanSkipAwait : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(CanSkipAwait)\ + static constexpr size_t ValueIndex = 0;\ explicit LCanSkipAwait(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MCanSkipAwait* mir() const { return mir_->toCanSkipAwait(); };\ };\ -\ -class LMaybeExtractAwaitValue : public LInstructionHelper {\ +class LMaybeExtractAwaitValue : public LInstructionHelper {\ public:\ LIR_HEADER(MaybeExtractAwaitValue)\ + static constexpr size_t CanSkipIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ explicit LMaybeExtractAwaitValue(const LBoxAllocation& value, const LAllocation& canSkip) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ + setOperand(CanSkipIndex, canSkip);\ setBoxOperand(ValueIndex, value);\ - setOperand(0, canSkip);\ }\ - const LAllocation* canSkip() { return getOperand(0); }\ - static const size_t ValueIndex = 1;\ + const LAllocation* canSkip() const { return getOperand(CanSkipIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ MMaybeExtractAwaitValue* mir() const { return mir_->toMaybeExtractAwaitValue(); };\ };\ -\ -class LDebugCheckSelfHosted : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LDebugCheckSelfHosted : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(DebugCheckSelfHosted)\ + static constexpr size_t ValueIndex = 0;\ explicit LDebugCheckSelfHosted(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ setBoxOperand(ValueIndex, value);\ }\ -\ - static const size_t ValueIndex = 0;\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ };\ -\ -class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(IsPackedArray)\ - explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setTemp(0, temp0);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ class LGuardArrayIsPacked : public LInstructionHelper<0, 1, 2> {\ public:\ LIR_HEADER(GuardArrayIsPacked)\ + static constexpr size_t ArrayIndex = 0;\ explicit LGuardArrayIsPacked(const LAllocation& array, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, array);\ + setOperand(ArrayIndex, array);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* array() { return getOperand(0); }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ MGuardArrayIsPacked* mir() const { return mir_->toGuardArrayIsPacked(); };\ };\ -\ -class LGetPrototypeOf : public LInstructionHelper {\ - public:\ - LIR_HEADER(GetPrototypeOf)\ - explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ - setOperand(0, target);\ - }\ - const LAllocation* target() { return getOperand(0); }\ -};\ -\ -class LObjectWithProto : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(ObjectWithProto)\ - explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setBoxOperand(PrototypeIndex, prototype);\ - }\ -\ - static const size_t PrototypeIndex = 0;\ -};\ -\ class LObjectStaticProto : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(ObjectStaticProto)\ + static constexpr size_t ObjectIndex = 0;\ explicit LObjectStaticProto(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ };\ -\ -class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ - public:\ - LIR_HEADER(BuiltinObject)\ - explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ -\ - }\ -\ - MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ -};\ -\ -class LSuperFunction : public LInstructionHelper {\ - public:\ - LIR_HEADER(SuperFunction)\ - explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, callee);\ - setTemp(0, temp0);\ - }\ - const LAllocation* callee() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LInitHomeObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(InitHomeObject)\ - explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, function);\ - setBoxOperand(HomeObjectIndex, homeObject);\ - }\ - const LAllocation* function() { return getOperand(0); }\ - static const size_t HomeObjectIndex = 1;\ -};\ -\ -class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(IsTypedArrayConstructor)\ - explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ -};\ -\ -class LLoadValueTag : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 0> {\ - public:\ - LIR_HEADER(LoadValueTag)\ - explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - setBoxOperand(ValueIndex, value);\ - }\ -\ - static const size_t ValueIndex = 0;\ -};\ -\ class LGuardTagNotEqual : public LInstructionHelper<0, 2, 0> {\ public:\ LIR_HEADER(GuardTagNotEqual)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ explicit LGuardTagNotEqual(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ - setOperand(0, lhs);\ - setOperand(1, rhs);\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ }\ - const LAllocation* lhs() { return getOperand(0); }\ - const LAllocation* rhs() { return getOperand(1); }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ };\ -\ -class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(LoadWrapperTarget)\ - explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ -};\ -\ class LGuardHasGetterSetter : public LInstructionHelper<0, 1, 3> {\ public:\ LIR_HEADER(GuardHasGetterSetter)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardHasGetterSetter(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ this->setIsCall();\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ setTemp(1, temp1);\ setTemp(2, temp2);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ const LDefinition* temp2() { return getTemp(2); }\ MGuardHasGetterSetter* mir() const { return mir_->toGuardHasGetterSetter(); };\ };\ -\ class LGuardIsExtensible : public LInstructionHelper<0, 1, 1> {\ public:\ LIR_HEADER(GuardIsExtensible)\ + static constexpr size_t ObjectIndex = 0;\ explicit LGuardIsExtensible(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ + setOperand(ObjectIndex, object);\ setTemp(0, temp0);\ }\ - const LAllocation* object() { return getOperand(0); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ };\ -\ class LGuardInt32IsNonNegative : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32IsNonNegative)\ + static constexpr size_t IndexIndex = 0;\ explicit LGuardInt32IsNonNegative(const LAllocation& index) : LInstructionHelper(classOpcode) {\ - setOperand(0, index);\ + setOperand(IndexIndex, index);\ }\ - const LAllocation* index() { return getOperand(0); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ };\ -\ class LGuardInt32Range : public LInstructionHelper<0, 1, 0> {\ public:\ LIR_HEADER(GuardInt32Range)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardInt32Range(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ MGuardInt32Range* mir() const { return mir_->toGuardInt32Range(); };\ };\ -\ class LGuardIndexIsNotDenseElement : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsNotDenseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsNotDenseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ class LGuardIndexIsValidUpdateOrAdd : public LInstructionHelper<0, 2, 2> {\ public:\ LIR_HEADER(GuardIndexIsValidUpdateOrAdd)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ explicit LGuardIndexIsValidUpdateOrAdd(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, object);\ - setOperand(1, index);\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ setTemp(0, temp0);\ setTemp(1, temp1);\ }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ const LDefinition* temp0() { return getTemp(0); }\ const LDefinition* temp1() { return getTemp(1); }\ };\ -\ -class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 1 * BOX_PIECES + 2, 0> {\ - public:\ - LIR_HEADER(CallAddOrUpdateSparseElement)\ - explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ValueIndex, value);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ValueIndex = 2;\ - MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ -};\ -\ -class LCallGetSparseElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallGetSparseElement)\ - explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElement : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElement)\ - explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ -};\ -\ -class LCallNativeGetElementSuper : public LInstructionHelper {\ - public:\ - LIR_HEADER(CallNativeGetElementSuper)\ - explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setBoxOperand(ReceiverIndex, receiver);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - static const size_t ReceiverIndex = 2;\ -};\ -\ -class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ - public:\ - LIR_HEADER(CallObjectHasSparseElement)\ - explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, object);\ - setOperand(1, index);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* object() { return getOperand(0); }\ - const LAllocation* index() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ -};\ -\ -class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsIntN)\ - explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LGuardNonGCThing : public LInstructionHelper<0, 1 * BOX_PIECES + 0, 0> {\ +class LGuardNonGCThing : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ public:\ LIR_HEADER(GuardNonGCThing)\ + static constexpr size_t InputIndex = 0;\ explicit LGuardNonGCThing(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ setBoxOperand(InputIndex, input);\ }\ -\ - static const size_t InputIndex = 0;\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ };\ -\ -class LToHashableNonGCThing : public LInstructionHelper {\ +class LCanonicalizeNaND : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableNonGCThing)\ - explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ + LIR_HEADER(CanonicalizeNaND)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaND(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableString : public LInstructionHelper<1, 1, 0> {\ +class LCanonicalizeNaNF : public LInstructionHelper<1, 1, 0> {\ public:\ - LIR_HEADER(ToHashableString)\ - explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ + LIR_HEADER(CanonicalizeNaNF)\ + static constexpr size_t InputIndex = 0;\ + explicit LCanonicalizeNaNF(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ }\ - const LAllocation* input() { return getOperand(0); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ };\ -\ -class LToHashableValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(ToHashableValue)\ - explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashNonGCThing : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(HashNonGCThing)\ - explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LHashString : public LInstructionHelper<1, 1, 1> {\ - public:\ - LIR_HEADER(HashString)\ - explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ -};\ -\ -class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(HashSymbol)\ - explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ - public:\ - LIR_HEADER(HashBigInt)\ - explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - }\ - const LAllocation* input() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ -};\ -\ -class LHashObject : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashObject)\ - explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LHashValue : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 4> {\ - public:\ - LIR_HEADER(HashValue)\ - explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(SetObjectHasNonBigInt)\ - explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasBigInt)\ - explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(SetObjectHasValue)\ - explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(SetObjectHasValueVMCall)\ - explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, setObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(SetObjectSize)\ - explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, setObject);\ - }\ - const LAllocation* setObject() { return getOperand(0); }\ -};\ -\ -class LMapObjectHasNonBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 2> {\ - public:\ - LIR_HEADER(MapObjectHasNonBigInt)\ - explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasBigInt : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasBigInt)\ - explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValue : public LInstructionHelper<1, 1 * BOX_PIECES + 2, 4> {\ - public:\ - LIR_HEADER(MapObjectHasValue)\ - explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 * BOX_PIECES + 1, 0> {\ - public:\ - LIR_HEADER(MapObjectHasValueVMCall)\ - explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectGetNonBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetNonBigInt)\ - explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetBigInt : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetBigInt)\ - explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValue : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValue)\ - explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& input, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - setOperand(1, hash);\ - setTemp(0, temp0);\ - setTemp(1, temp1);\ - setTemp(2, temp2);\ - setTemp(3, temp3);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - const LAllocation* hash() { return getOperand(1); }\ - const LDefinition* temp0() { return getTemp(0); }\ - const LDefinition* temp1() { return getTemp(1); }\ - const LDefinition* temp2() { return getTemp(2); }\ - const LDefinition* temp3() { return getTemp(3); }\ - static const size_t InputIndex = 2;\ -};\ -\ -class LMapObjectGetValueVMCall : public LInstructionHelper {\ - public:\ - LIR_HEADER(MapObjectGetValueVMCall)\ - explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, mapObject);\ - setBoxOperand(InputIndex, input);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ - static const size_t InputIndex = 1;\ -};\ -\ -class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(MapObjectSize)\ - explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ - setOperand(0, mapObject);\ - }\ - const LAllocation* mapObject() { return getOperand(0); }\ -};\ -\ -class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ - public:\ - LIR_HEADER(BigIntAsUintN)\ - explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ - this->setIsCall();\ - setOperand(0, bits);\ - setOperand(1, input);\ - }\ - const LAllocation* bits() { return getOperand(0); }\ - const LAllocation* input() { return getOperand(1); }\ -};\ -\ -class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 1 * BOX_PIECES + 0, 1> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSValue)\ - explicit LWasmAnyRefFromJSValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ - setBoxOperand(InputIndex, input);\ - setTemp(0, temp0);\ - }\ - const LDefinition* temp0() { return getTemp(0); }\ - static const size_t InputIndex = 0;\ -};\ -\ -class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSObject)\ - explicit LWasmAnyRefFromJSObject(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ -class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmAnyRefFromJSString)\ - explicit LWasmAnyRefFromJSString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ - setOperand(0, input);\ - }\ - const LAllocation* input() { return getOperand(0); }\ -};\ -\ class LWasmNewI31Ref : public LInstructionHelper<1, 1, 0> {\ public:\ LIR_HEADER(WasmNewI31Ref)\ + static constexpr size_t ValueIndex = 0;\ explicit LWasmNewI31Ref(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ + setOperand(ValueIndex, value);\ }\ - const LAllocation* value() { return getOperand(0); }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ MWasmNewI31Ref* mir() const { return mir_->toWasmNewI31Ref(); };\ };\ -\ -class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ - public:\ - LIR_HEADER(WasmI31RefGet)\ - explicit LWasmI31RefGet(const LAllocation& value) : LInstructionHelper(classOpcode) {\ - setOperand(0, value);\ - }\ - const LAllocation* value() { return getOperand(0); }\ - MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ -};\ -\ class LSimd128 : public LInstructionHelper<1, 0, 0> {\ SimdConstant simd128_;\ public:\ LIR_HEADER(Simd128)\ explicit LSimd128(SimdConstant simd128) : LInstructionHelper(classOpcode), simd128_(simd128) {\ -\ }\ SimdConstant simd128() const { return simd128_; }\ -\ };\ - +class LWasmTernarySimd128 : public LInstructionHelper<1, 3, 1> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmTernarySimd128)\ + static constexpr size_t V0Index = 0;\ + static constexpr size_t V1Index = 1;\ + static constexpr size_t V2Index = 2;\ + explicit LWasmTernarySimd128(const LAllocation& v0, const LAllocation& v1, const LAllocation& v2, const LDefinition& temp0, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(V0Index, v0);\ + setOperand(V1Index, v1);\ + setOperand(V2Index, v2);\ + setTemp(0, temp0);\ + }\ + const LAllocation* v0() const { return getOperand(V0Index); }\ + const LAllocation* v1() const { return getOperand(V1Index); }\ + const LAllocation* v2() const { return getOperand(V2Index); }\ + const LDefinition* temp0() { return getTemp(0); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128 : public LInstructionHelper<1, 2, 2> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmBinarySimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmBinarySimd128(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, wasm::SimdOp simdOp) : LInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmBinarySimd128WithConstant : public LInstructionHelper<1, 1, 1> {\ + SimdConstant rhs_;\ + public:\ + LIR_HEADER(WasmBinarySimd128WithConstant)\ + static constexpr size_t LhsIndex = 0;\ + explicit LWasmBinarySimd128WithConstant(const LAllocation& lhs, const LDefinition& temp0, SimdConstant rhs) : LInstructionHelper(classOpcode), rhs_(rhs) {\ + setOperand(LhsIndex, lhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + SimdConstant rhs() const { return rhs_; }\ + MWasmBinarySimd128WithConstant* mir() const { return mir_->toWasmBinarySimd128WithConstant(); };\ +};\ +class LWasmVariableShiftSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmVariableShiftSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmVariableShiftSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmConstantShiftSimd128 : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(WasmConstantShiftSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmConstantShiftSimd128(const LAllocation& src, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + int32_t shift() const { return shift_; }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmSignReplicationSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmSignReplicationSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmSignReplicationSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmShiftSimd128* mir() const { return mir_->toWasmShiftSimd128(); };\ +};\ +class LWasmShuffleSimd128 : public LInstructionHelper<1, 2, 0> {\ + SimdShuffleOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmShuffleSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmShuffleSimd128(const LAllocation& lhs, const LAllocation& rhs, SimdShuffleOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + SimdShuffleOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmPermuteSimd128 : public LInstructionHelper<1, 1, 0> {\ + SimdPermuteOp op_;\ + SimdConstant control_;\ + public:\ + LIR_HEADER(WasmPermuteSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmPermuteSimd128(const LAllocation& src, SimdPermuteOp op, SimdConstant control) : LInstructionHelper(classOpcode), op_(op), control_(control) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + SimdPermuteOp op() const { return op_; }\ + SimdConstant control() const { return control_; }\ +};\ +class LWasmReplaceLaneSimd128 : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(WasmReplaceLaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceLaneSimd128(const LAllocation& lhs, const LAllocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmReplaceInt64LaneSimd128 : public LInstructionHelper<1, 1 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmReplaceInt64LaneSimd128)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LWasmReplaceInt64LaneSimd128(const LAllocation& lhs, const LInt64Allocation& rhs) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setInt64Operand(RhsIndex, rhs);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + LInt64Allocation rhs() const { return getInt64Operand(RhsIndex); }\ + MWasmReplaceLaneSimd128* mir() const { return mir_->toWasmReplaceLaneSimd128(); };\ +};\ +class LWasmScalarToSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmScalarToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmScalarToSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmInt64ToSimd128 : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmInt64ToSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmInt64ToSimd128(const LInt64Allocation& src) : LInstructionHelper(classOpcode) {\ + setInt64Operand(SrcIndex, src);\ + }\ + LInt64Allocation src() const { return getInt64Operand(SrcIndex); }\ + MWasmScalarToSimd128* mir() const { return mir_->toWasmScalarToSimd128(); };\ +};\ +class LWasmReduceSimd128 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmReduceSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmReduceAndBranchSimd128 : public LControlInstructionHelper<2, 1, 0> {\ + wasm::SimdOp simdOp_;\ + public:\ + LIR_HEADER(WasmReduceAndBranchSimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceAndBranchSimd128(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LAllocation& src, wasm::SimdOp simdOp) : LControlInstructionHelper(classOpcode), simdOp_(simdOp) {\ + setSuccessor(0, ifTrue);\ + setSuccessor(1, ifFalse);\ + setOperand(SrcIndex, src);\ + }\ + MBasicBlock* ifTrue() const { return getSuccessor(0); }\ + MBasicBlock* ifFalse() const { return getSuccessor(1); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + wasm::SimdOp simdOp() const { return simdOp_; }\ +};\ +class LWasmReduceSimd128ToInt64 : public LInstructionHelper {\ + public:\ + LIR_HEADER(WasmReduceSimd128ToInt64)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmReduceSimd128ToInt64(const LAllocation& src) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + MWasmReduceSimd128* mir() const { return mir_->toWasmReduceSimd128(); };\ +};\ +class LWasmLoadLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmLoadLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmLoadLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmLoadLaneSimd128* mir() const { return mir_->toWasmLoadLaneSimd128(); };\ +};\ +class LWasmStoreLaneSimd128 : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(WasmStoreLaneSimd128)\ + static constexpr size_t PtrIndex = 0;\ + static constexpr size_t SrcIndex = 1;\ + static constexpr size_t MemoryBaseIndex = 2;\ + explicit LWasmStoreLaneSimd128(const LAllocation& ptr, const LAllocation& src, const LAllocation& memoryBase) : LInstructionHelper(classOpcode) {\ + setOperand(PtrIndex, ptr);\ + setOperand(SrcIndex, src);\ + setOperand(MemoryBaseIndex, memoryBase);\ + }\ + const LAllocation* ptr() const { return getOperand(PtrIndex); }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LAllocation* memoryBase() const { return getOperand(MemoryBaseIndex); }\ + MWasmStoreLaneSimd128* mir() const { return mir_->toWasmStoreLaneSimd128(); };\ +};\ +class LUnboxFloatingPoint : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(UnboxFloatingPoint)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnboxFloatingPoint(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnbox* mir() const { return mir_->toUnbox(); };\ +};\ +class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToDouble)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToDouble(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmUint32ToFloat32)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmUint32ToFloat32(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ +};\ +class LDivI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(DivI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LDivI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDiv* mir() const { return mir_->toDiv(); };\ + inline const char* extraName() const;\ +};\ +class LModI : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ModI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LModI(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LhsIndex, lhs);\ + setOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MMod* mir() const { return mir_->toMod(); };\ + inline const char* extraName() const;\ +};\ +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(DivPowTwoI)\ + static constexpr size_t NumeratorIndex = 0;\ + explicit LDivPowTwoI(const LAllocation& numerator, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(NumeratorIndex, numerator);\ + }\ + const LAllocation* numerator() const { return getOperand(NumeratorIndex); }\ + int32_t shift() const { return shift_; }\ + MDiv* mir() const { return mir_->toDiv(); };\ +};\ +class LModPowTwoI : public LInstructionHelper<1, 1, 0> {\ + int32_t shift_;\ + public:\ + LIR_HEADER(ModPowTwoI)\ + static constexpr size_t InputIndex = 0;\ + explicit LModPowTwoI(const LAllocation& input, int32_t shift) : LInstructionHelper(classOpcode), shift_(shift) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + int32_t shift() const { return shift_; }\ + MMod* mir() const { return mir_->toMod(); };\ +};\ +class LTableSwitch : public LInstructionHelper<0, 1, 2> {\ + public:\ + LIR_HEADER(TableSwitch)\ + static constexpr size_t IndexIndex = 0;\ + explicit LTableSwitch(const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LTableSwitchV : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(TableSwitchV)\ + static constexpr size_t InputIndex = 0;\ + explicit LTableSwitchV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MTableSwitch* mir() const { return mir_->toTableSwitch(); };\ +};\ +class LMulI : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(MulI)\ + static constexpr size_t LhsIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMulI() : LInstructionHelper(classOpcode) {\ + }\ + const LAllocation* lhs() const { return getOperand(LhsIndex); }\ + const LAllocation* rhs() const { return getOperand(RhsIndex); }\ + void setLhs(const LAllocation& lhs) { setOperand(LhsIndex, lhs); }\ + void setRhs(const LAllocation& rhs) { setOperand(RhsIndex, rhs); }\ + MMul* mir() const { return mir_->toMul(); };\ + inline const char* extraName() const;\ +};\ +class LCallee : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(Callee)\ + explicit LCallee() : LInstructionHelper(classOpcode) {\ + }\ + MCallee* mir() const { return mir_->toCallee(); };\ +};\ +class LIsConstructing : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(IsConstructing)\ + explicit LIsConstructing() : LInstructionHelper(classOpcode) {\ + }\ + MIsConstructing* mir() const { return mir_->toIsConstructing(); };\ +};\ +class LThrow : public LInstructionHelper<0, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(Throw)\ + static constexpr size_t ValueIndex = 0;\ + explicit LThrow(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MThrow* mir() const { return mir_->toThrow(); };\ +};\ +class LThrowWithStack : public LInstructionHelper<0, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ThrowWithStack)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t StackIndex = 1 * BOX_PIECES;\ + explicit LThrowWithStack(const LBoxAllocation& value, const LBoxAllocation& stack) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(ValueIndex, value);\ + setBoxOperand(StackIndex, stack);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + LBoxAllocation stack() const { return getBoxOperand(StackIndex); }\ + MThrowWithStack* mir() const { return mir_->toThrowWithStack(); };\ +};\ +class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewArrayDynamicLength* mir() const { return mir_->toNewArrayDynamicLength(); };\ +};\ +class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(NewTypedArrayDynamicLength)\ + static constexpr size_t LengthIndex = 0;\ + explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewTypedArrayDynamicLength* mir() const { return mir_->toNewTypedArrayDynamicLength(); };\ +};\ +class LNewTypedArrayFromArray : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArray)\ + static constexpr size_t ArrayIndex = 0;\ + explicit LNewTypedArrayFromArray(const LAllocation& array) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + MNewTypedArrayFromArray* mir() const { return mir_->toNewTypedArrayFromArray(); };\ +};\ +class LNewTypedArrayFromArrayBuffer : public LInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(NewTypedArrayFromArrayBuffer)\ + static constexpr size_t ArrayBufferIndex = 0;\ + static constexpr size_t ByteOffsetIndex = 1;\ + static constexpr size_t LengthIndex = 1 + 1 * BOX_PIECES;\ + explicit LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer, const LBoxAllocation& byteOffset, const LBoxAllocation& length) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayBufferIndex, arrayBuffer);\ + setBoxOperand(ByteOffsetIndex, byteOffset);\ + setBoxOperand(LengthIndex, length);\ + }\ + const LAllocation* arrayBuffer() const { return getOperand(ArrayBufferIndex); }\ + LBoxAllocation byteOffset() const { return getBoxOperand(ByteOffsetIndex); }\ + LBoxAllocation length() const { return getBoxOperand(LengthIndex); }\ + MNewTypedArrayFromArrayBuffer* mir() const { return mir_->toNewTypedArrayFromArrayBuffer(); };\ +};\ +class LNewMapObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewMapObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewMapObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewMapObjectFromIterable* mir() const { return mir_->toNewMapObjectFromIterable(); };\ +};\ +class LNewSetObjectFromIterable : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(NewSetObjectFromIterable)\ + static constexpr size_t IterableIndex = 0;\ + explicit LNewSetObjectFromIterable(const LBoxAllocation& iterable, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(IterableIndex, iterable);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation iterable() const { return getBoxOperand(IterableIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MNewSetObjectFromIterable* mir() const { return mir_->toNewSetObjectFromIterable(); };\ +};\ +class LNewBoundFunction : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewBoundFunction)\ + explicit LNewBoundFunction(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewBoundFunction* mir() const { return mir_->toNewBoundFunction(); };\ +};\ +class LBoundFunctionNumArgs : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BoundFunctionNumArgs)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LBoundFunctionNumArgs(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MBoundFunctionNumArgs* mir() const { return mir_->toBoundFunctionNumArgs(); };\ +};\ +class LBail : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(Bail)\ + explicit LBail() : LInstructionHelper(classOpcode) {\ + }\ + MBail* mir() const { return mir_->toBail(); };\ +};\ +class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(EncodeSnapshot)\ + explicit LEncodeSnapshot() : LInstructionHelper(classOpcode) {\ + }\ + MEncodeSnapshot* mir() const { return mir_->toEncodeSnapshot(); };\ +};\ +class LStrictConstantCompareInt32 : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StrictConstantCompareInt32)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareInt32(const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStrictConstantCompareInt32* mir() const { return mir_->toStrictConstantCompareInt32(); };\ +};\ +class LStrictConstantCompareBoolean : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(StrictConstantCompareBoolean)\ + static constexpr size_t ValueIndex = 0;\ + explicit LStrictConstantCompareBoolean(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MStrictConstantCompareBoolean* mir() const { return mir_->toStrictConstantCompareBoolean(); };\ +};\ +class LSameValueDouble : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(SameValueDouble)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1;\ + explicit LSameValueDouble(const LAllocation& left, const LAllocation& right, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(LeftIndex, left);\ + setOperand(RightIndex, right);\ + setTemp(0, temp0);\ + }\ + const LAllocation* left() const { return getOperand(LeftIndex); }\ + const LAllocation* right() const { return getOperand(RightIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSameValueDouble* mir() const { return mir_->toSameValueDouble(); };\ +};\ +class LSameValue : public LInstructionHelper<1, 0 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SameValue)\ + static constexpr size_t LeftIndex = 0;\ + static constexpr size_t RightIndex = 1 * BOX_PIECES;\ + explicit LSameValue(const LBoxAllocation& left, const LBoxAllocation& right) : LInstructionHelper(classOpcode) {\ + setBoxOperand(LeftIndex, left);\ + setBoxOperand(RightIndex, right);\ + }\ + LBoxAllocation left() const { return getBoxOperand(LeftIndex); }\ + LBoxAllocation right() const { return getBoxOperand(RightIndex); }\ + MSameValue* mir() const { return mir_->toSameValue(); };\ +};\ +class LCreateThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(CreateThis)\ + static constexpr size_t CalleeIndex = 0;\ + static constexpr size_t NewTargetIndex = 1;\ + explicit LCreateThis(const LAllocation& callee, const LAllocation& newTarget) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(CalleeIndex, callee);\ + setOperand(NewTargetIndex, newTarget);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LAllocation* newTarget() const { return getOperand(NewTargetIndex); }\ + MCreateThis* mir() const { return mir_->toCreateThis(); };\ +};\ +class LGetArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LGetArgumentsObjectArg(const LAllocation& argsObject, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetArgumentsObjectArg* mir() const { return mir_->toGetArgumentsObjectArg(); };\ +};\ +class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(SetArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetArgumentsObjectArg(const LAllocation& argsObject, const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSetArgumentsObjectArg* mir() const { return mir_->toSetArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArg : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArg* mir() const { return mir_->toLoadArgumentsObjectArg(); };\ +};\ +class LLoadArgumentsObjectArgHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadArgumentsObjectArgHole)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLoadArgumentsObjectArgHole(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLoadArgumentsObjectArgHole* mir() const { return mir_->toLoadArgumentsObjectArgHole(); };\ +};\ +class LInArgumentsObjectArg : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(InArgumentsObjectArg)\ + static constexpr size_t ArgsObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LInArgumentsObjectArg(const LAllocation& argsObject, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MInArgumentsObjectArg* mir() const { return mir_->toInArgumentsObjectArg(); };\ +};\ +class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArgumentsObjectLength)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArgumentsObjectLength(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArgumentsObjectLength* mir() const { return mir_->toArgumentsObjectLength(); };\ +};\ +class LArrayFromArgumentsObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayFromArgumentsObject)\ + static constexpr size_t ArgsObjectIndex = 0;\ + explicit LArrayFromArgumentsObject(const LAllocation& argsObject) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArgsObjectIndex, argsObject);\ + }\ + const LAllocation* argsObject() const { return getOperand(ArgsObjectIndex); }\ + MArrayFromArgumentsObject* mir() const { return mir_->toArrayFromArgumentsObject(); };\ +};\ +class LLoadScriptedProxyHandler : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadScriptedProxyHandler)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadScriptedProxyHandler(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadScriptedProxyHandler* mir() const { return mir_->toLoadScriptedProxyHandler(); };\ +};\ +class LCheckScriptedProxyGetResult : public LInstructionHelper<0, 0 + 3 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(CheckScriptedProxyGetResult)\ + static constexpr size_t TargetIndex = 0;\ + static constexpr size_t IdIndex = 1 * BOX_PIECES;\ + static constexpr size_t ValueIndex = 2 * BOX_PIECES;\ + explicit LCheckScriptedProxyGetResult(const LBoxAllocation& target, const LBoxAllocation& id, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(TargetIndex, target);\ + setBoxOperand(IdIndex, id);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation target() const { return getBoxOperand(TargetIndex); }\ + LBoxAllocation id() const { return getBoxOperand(IdIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCheckScriptedProxyGetResult* mir() const { return mir_->toCheckScriptedProxyGetResult(); };\ +};\ +class LIdToStringOrSymbol : public LInstructionHelper {\ + public:\ + LIR_HEADER(IdToStringOrSymbol)\ + static constexpr size_t IdValIndex = 0;\ + explicit LIdToStringOrSymbol(const LBoxAllocation& idVal, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIdToStringOrSymbol* mir() const { return mir_->toIdToStringOrSymbol(); };\ +};\ +class LReturnFromCtor : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ReturnFromCtor)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MReturnFromCtor* mir() const { return mir_->toReturnFromCtor(); };\ +};\ +class LWasmAnyRefFromJSValue : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSValue)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSValue(const LBoxAllocation& def, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(DefIndex, def);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation def() const { return getBoxOperand(DefIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefFromJSValue* mir() const { return mir_->toWasmAnyRefFromJSValue(); };\ +};\ +class LWasmAnyRefFromJSObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSObject)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSObject(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSObject* mir() const { return mir_->toWasmAnyRefFromJSObject(); };\ +};\ +class LWasmAnyRefFromJSString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmAnyRefFromJSString)\ + static constexpr size_t DefIndex = 0;\ + explicit LWasmAnyRefFromJSString(const LAllocation& def) : LInstructionHelper(classOpcode) {\ + setOperand(DefIndex, def);\ + }\ + const LAllocation* def() const { return getOperand(DefIndex); }\ + MWasmAnyRefFromJSString* mir() const { return mir_->toWasmAnyRefFromJSString(); };\ +};\ +class LWasmAnyRefIsJSString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefIsJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefIsJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefIsJSString* mir() const { return mir_->toWasmAnyRefIsJSString(); };\ +};\ +class LWasmTrapIfAnyRefIsNotJSString : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmTrapIfAnyRefIsNotJSString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmTrapIfAnyRefIsNotJSString* mir() const { return mir_->toWasmTrapIfAnyRefIsNotJSString(); };\ +};\ +class LWasmAnyRefJSStringLength : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmAnyRefJSStringLength)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmAnyRefJSStringLength(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmAnyRefJSStringLength* mir() const { return mir_->toWasmAnyRefJSStringLength(); };\ +};\ +class LWasmI31RefGet : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(WasmI31RefGet)\ + static constexpr size_t InputIndex = 0;\ + explicit LWasmI31RefGet(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MWasmI31RefGet* mir() const { return mir_->toWasmI31RefGet(); };\ +};\ +class LTypeOfName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypeOfName)\ + static constexpr size_t InputIndex = 0;\ + explicit LTypeOfName(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MTypeOfName* mir() const { return mir_->toTypeOfName(); };\ +};\ +class LToPropertyKeyCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToPropertyKeyCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LToPropertyKeyCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MToPropertyKeyCache* mir() const { return mir_->toToPropertyKeyCache(); };\ +};\ +class LBigIntToIntPtr : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(BigIntToIntPtr)\ + static constexpr size_t InputIndex = 0;\ + explicit LBigIntToIntPtr(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntToIntPtr* mir() const { return mir_->toBigIntToIntPtr(); };\ +};\ +class LIntPtrToBigInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IntPtrToBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LIntPtrToBigInt(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIntPtrToBigInt* mir() const { return mir_->toIntPtrToBigInt(); };\ +};\ +class LInt32ToStringWithBase : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(Int32ToStringWithBase)\ + static constexpr size_t InputIndex = 0;\ + static constexpr size_t BaseIndex = 1;\ + explicit LInt32ToStringWithBase(const LAllocation& input, const LAllocation& base, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setOperand(BaseIndex, base);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LAllocation* base() const { return getOperand(BaseIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MInt32ToStringWithBase* mir() const { return mir_->toInt32ToStringWithBase(); };\ +};\ +class LNumberParseInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(NumberParseInt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t RadixIndex = 1;\ + explicit LNumberParseInt(const LAllocation& string, const LAllocation& radix, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(RadixIndex, radix);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* radix() const { return getOperand(RadixIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNumberParseInt* mir() const { return mir_->toNumberParseInt(); };\ +};\ +class LDoubleParseInt : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(DoubleParseInt)\ + static constexpr size_t NumberIndex = 0;\ + explicit LDoubleParseInt(const LAllocation& number, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(NumberIndex, number);\ + setTemp(0, temp0);\ + }\ + const LAllocation* number() const { return getOperand(NumberIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDoubleParseInt* mir() const { return mir_->toDoubleParseInt(); };\ +};\ +class LLinearizeString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LinearizeString)\ + static constexpr size_t StringIndex = 0;\ + explicit LLinearizeString(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MLinearizeString* mir() const { return mir_->toLinearizeString(); };\ +};\ +class LLinearizeForCharAccess : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(LinearizeForCharAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCharAccess(const LAllocation& string, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MLinearizeForCharAccess* mir() const { return mir_->toLinearizeForCharAccess(); };\ +};\ +class LLinearizeForCodePointAccess : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(LinearizeForCodePointAccess)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LLinearizeForCodePointAccess(const LAllocation& string, const LAllocation& index, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MLinearizeForCodePointAccess* mir() const { return mir_->toLinearizeForCodePointAccess(); };\ +};\ +class LToRelativeStringIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(ToRelativeStringIndex)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LToRelativeStringIndex(const LAllocation& index, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MToRelativeStringIndex* mir() const { return mir_->toToRelativeStringIndex(); };\ +};\ +class LCharCodeAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAt* mir() const { return mir_->toCharCodeAt(); };\ +};\ +class LCharCodeAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CharCodeAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCharCodeAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCharCodeAtOrNegative* mir() const { return mir_->toCharCodeAtOrNegative(); };\ +};\ +class LCodePointAt : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAt)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAt(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAt* mir() const { return mir_->toCodePointAt(); };\ +};\ +class LCodePointAtOrNegative : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CodePointAtOrNegative)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCodePointAtOrNegative(const LAllocation& string, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCodePointAtOrNegative* mir() const { return mir_->toCodePointAtOrNegative(); };\ +};\ +class LNegativeToNaN : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToNaN)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToNaN(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToNaN* mir() const { return mir_->toNegativeToNaN(); };\ +};\ +class LNegativeToUndefined : public LInstructionHelper {\ + public:\ + LIR_HEADER(NegativeToUndefined)\ + static constexpr size_t InputIndex = 0;\ + explicit LNegativeToUndefined(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MNegativeToUndefined* mir() const { return mir_->toNegativeToUndefined(); };\ +};\ +class LFromCharCode : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCode)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCode(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCode* mir() const { return mir_->toFromCharCode(); };\ +};\ +class LFromCharCodeEmptyIfNegative : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FromCharCodeEmptyIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeEmptyIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeEmptyIfNegative* mir() const { return mir_->toFromCharCodeEmptyIfNegative(); };\ +};\ +class LFromCharCodeUndefinedIfNegative : public LInstructionHelper {\ + public:\ + LIR_HEADER(FromCharCodeUndefinedIfNegative)\ + static constexpr size_t CodeIndex = 0;\ + explicit LFromCharCodeUndefinedIfNegative(const LAllocation& code) : LInstructionHelper(classOpcode) {\ + setOperand(CodeIndex, code);\ + }\ + const LAllocation* code() const { return getOperand(CodeIndex); }\ + MFromCharCodeUndefinedIfNegative* mir() const { return mir_->toFromCharCodeUndefinedIfNegative(); };\ +};\ +class LFromCodePoint : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(FromCodePoint)\ + static constexpr size_t CodePointIndex = 0;\ + explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(CodePointIndex, codePoint);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* codePoint() const { return getOperand(CodePointIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MFromCodePoint* mir() const { return mir_->toFromCodePoint(); };\ +};\ +class LStringIncludes : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIncludes)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIncludes(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIncludes* mir() const { return mir_->toStringIncludes(); };\ +};\ +class LStringIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringIndexOf* mir() const { return mir_->toStringIndexOf(); };\ +};\ +class LStringLastIndexOf : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringLastIndexOf)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringLastIndexOf(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringLastIndexOf* mir() const { return mir_->toStringLastIndexOf(); };\ +};\ +class LStringStartsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringStartsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringStartsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringStartsWith* mir() const { return mir_->toStringStartsWith(); };\ +};\ +class LStringEndsWith : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringEndsWith)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SearchStringIndex = 1;\ + explicit LStringEndsWith(const LAllocation& string, const LAllocation& searchString) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SearchStringIndex, searchString);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* searchString() const { return getOperand(SearchStringIndex); }\ + MStringEndsWith* mir() const { return mir_->toStringEndsWith(); };\ +};\ +class LStringTrimStartIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringTrimStartIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringTrimStartIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringTrimStartIndex* mir() const { return mir_->toStringTrimStartIndex(); };\ +};\ +class LStringTrimEndIndex : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringTrimEndIndex)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t StartIndex = 1;\ + explicit LStringTrimEndIndex(const LAllocation& string, const LAllocation& start) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(StartIndex, start);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* start() const { return getOperand(StartIndex); }\ + MStringTrimEndIndex* mir() const { return mir_->toStringTrimEndIndex(); };\ +};\ +class LStringSplit : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(StringSplit)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LStringSplit(const LAllocation& string, const LAllocation& separator) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(StringIndex, string);\ + setOperand(SeparatorIndex, separator);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + MStringSplit* mir() const { return mir_->toStringSplit(); };\ +};\ +class LImplicitThis : public LInstructionHelper {\ + public:\ + LIR_HEADER(ImplicitThis)\ + static constexpr size_t EnvIndex = 0;\ + explicit LImplicitThis(const LAllocation& env) : LInstructionHelper(classOpcode) {\ + setOperand(EnvIndex, env);\ + }\ + const LAllocation* env() const { return getOperand(EnvIndex); }\ + MImplicitThis* mir() const { return mir_->toImplicitThis(); };\ +};\ +class LUnaryCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(UnaryCache)\ + static constexpr size_t InputIndex = 0;\ + explicit LUnaryCache(const LBoxAllocation& input) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + MUnaryCache* mir() const { return mir_->toUnaryCache(); };\ +};\ +class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(CheckOverRecursed)\ + explicit LCheckOverRecursed() : LInstructionHelper(classOpcode) {\ + }\ + MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); };\ +};\ +class LInterruptCheck : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(InterruptCheck)\ + explicit LInterruptCheck() : LInstructionHelper(classOpcode) {\ + }\ + MInterruptCheck* mir() const { return mir_->toInterruptCheck(); };\ +};\ +class LWasmTrap : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmTrap)\ + explicit LWasmTrap() : LInstructionHelper(classOpcode) {\ + }\ + MWasmTrap* mir() const { return mir_->toWasmTrap(); };\ +};\ +class LGlobalDeclInstantiation : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(GlobalDeclInstantiation)\ + explicit LGlobalDeclInstantiation() : LInstructionHelper(classOpcode) {\ + }\ + MGlobalDeclInstantiation* mir() const { return mir_->toGlobalDeclInstantiation(); };\ +};\ +class LRegExpMatcher : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpMatcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpMatcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); };\ +};\ +class LRegExpSearcher : public LInstructionHelper<1, 3, 0> {\ + public:\ + LIR_HEADER(RegExpSearcher)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + static constexpr size_t LastIndexIndex = 2;\ + explicit LRegExpSearcher(const LAllocation& regexp, const LAllocation& string, const LAllocation& lastIndex) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + setOperand(LastIndexIndex, lastIndex);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* lastIndex() const { return getOperand(LastIndexIndex); }\ + MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); };\ +};\ +class LRegExpSearcherLastLimit : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(RegExpSearcherLastLimit)\ + explicit LRegExpSearcherLastLimit(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MRegExpSearcherLastLimit* mir() const { return mir_->toRegExpSearcherLastLimit(); };\ +};\ +class LRegExpExecMatch : public LInstructionHelper {\ + public:\ + LIR_HEADER(RegExpExecMatch)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecMatch(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecMatch* mir() const { return mir_->toRegExpExecMatch(); };\ +};\ +class LRegExpExecTest : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(RegExpExecTest)\ + static constexpr size_t RegexpIndex = 0;\ + static constexpr size_t StringIndex = 1;\ + explicit LRegExpExecTest(const LAllocation& regexp, const LAllocation& string) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(RegexpIndex, regexp);\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* regexp() const { return getOperand(RegexpIndex); }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MRegExpExecTest* mir() const { return mir_->toRegExpExecTest(); };\ +};\ +class LSubstr : public LInstructionHelper<1, 3, 3> {\ + public:\ + LIR_HEADER(Substr)\ + static constexpr size_t StringIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t LengthIndex = 2;\ + explicit LSubstr(const LAllocation& string, const LAllocation& begin, const LAllocation& length, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setOperand(BeginIndex, begin);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MSubstr* mir() const { return mir_->toSubstr(); };\ +};\ +class LSetFunName : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetFunName)\ + static constexpr size_t FunIndex = 0;\ + static constexpr size_t NameIndex = 1;\ + explicit LSetFunName(const LAllocation& fun, const LBoxAllocation& name) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(FunIndex, fun);\ + setBoxOperand(NameIndex, name);\ + }\ + const LAllocation* fun() const { return getOperand(FunIndex); }\ + LBoxAllocation name() const { return getBoxOperand(NameIndex); }\ + MSetFunName* mir() const { return mir_->toSetFunName(); };\ +};\ +class LSlots : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Slots)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MSlots* mir() const { return mir_->toSlots(); };\ +};\ +class LElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(Elements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MElements* mir() const { return mir_->toElements(); };\ +};\ +class LInitializedLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(InitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LInitializedLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MInitializedLength* mir() const { return mir_->toInitializedLength(); };\ +};\ +class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetInitializedLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetInitializedLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetInitializedLength* mir() const { return mir_->toSetInitializedLength(); };\ +};\ +class LArrayLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + explicit LArrayLength(const LAllocation& elements) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + MArrayLength* mir() const { return mir_->toArrayLength(); };\ +};\ +class LSetArrayLength : public LInstructionHelper<0, 2, 0> {\ + public:\ + LIR_HEADER(SetArrayLength)\ + static constexpr size_t ElementsIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LSetArrayLength(const LAllocation& elements, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(ElementsIndex, elements);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* elements() const { return getOperand(ElementsIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MSetArrayLength* mir() const { return mir_->toSetArrayLength(); };\ +};\ +class LFunctionLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionLength)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionLength(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionLength* mir() const { return mir_->toFunctionLength(); };\ +};\ +class LFunctionName : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionName)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionName(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionName* mir() const { return mir_->toFunctionName(); };\ +};\ +class LArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferByteLength* mir() const { return mir_->toArrayBufferByteLength(); };\ +};\ +class LArrayBufferViewLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewLength* mir() const { return mir_->toArrayBufferViewLength(); };\ +};\ +class LArrayBufferViewByteOffset : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewByteOffset)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewByteOffset(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewByteOffset* mir() const { return mir_->toArrayBufferViewByteOffset(); };\ +};\ +class LArrayBufferViewElements : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ArrayBufferViewElements)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LArrayBufferViewElements(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MArrayBufferViewElements* mir() const { return mir_->toArrayBufferViewElements(); };\ +};\ +class LResizableTypedArrayByteOffsetMaybeOutOfBounds : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ResizableTypedArrayByteOffsetMaybeOutOfBounds)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LResizableTypedArrayByteOffsetMaybeOutOfBounds(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MResizableTypedArrayByteOffsetMaybeOutOfBounds* mir() const { return mir_->toResizableTypedArrayByteOffsetMaybeOutOfBounds(); };\ +};\ +class LGrowableSharedArrayBufferByteLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GrowableSharedArrayBufferByteLength)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGrowableSharedArrayBufferByteLength(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MGrowableSharedArrayBufferByteLength* mir() const { return mir_->toGrowableSharedArrayBufferByteLength(); };\ +};\ +class LTypedArrayElementSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(TypedArrayElementSize)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LTypedArrayElementSize(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MTypedArrayElementSize* mir() const { return mir_->toTypedArrayElementSize(); };\ +};\ +class LArrayPush : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(ArrayPush)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LArrayPush(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArrayPush* mir() const { return mir_->toArrayPush(); };\ +};\ +class LArraySlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArraySlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArraySlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArraySlice* mir() const { return mir_->toArraySlice(); };\ +};\ +class LArgumentsSlice : public LInstructionHelper<1, 3, 2> {\ + public:\ + LIR_HEADER(ArgumentsSlice)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t BeginIndex = 1;\ + static constexpr size_t EndIndex = 2;\ + explicit LArgumentsSlice(const LAllocation& object, const LAllocation& begin, const LAllocation& end, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(BeginIndex, begin);\ + setOperand(EndIndex, end);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* begin() const { return getOperand(BeginIndex); }\ + const LAllocation* end() const { return getOperand(EndIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MArgumentsSlice* mir() const { return mir_->toArgumentsSlice(); };\ +};\ +class LNormalizeSliceTerm : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(NormalizeSliceTerm)\ + static constexpr size_t ValueIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LNormalizeSliceTerm(const LAllocation& value, const LAllocation& length) : LInstructionHelper(classOpcode) {\ + setOperand(ValueIndex, value);\ + setOperand(LengthIndex, length);\ + }\ + const LAllocation* value() const { return getOperand(ValueIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + MNormalizeSliceTerm* mir() const { return mir_->toNormalizeSliceTerm(); };\ +};\ +class LArrayJoin : public LInstructionHelper<1, 2, 1> {\ + public:\ + LIR_HEADER(ArrayJoin)\ + static constexpr size_t ArrayIndex = 0;\ + static constexpr size_t SeparatorIndex = 1;\ + explicit LArrayJoin(const LAllocation& array, const LAllocation& separator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ArrayIndex, array);\ + setOperand(SeparatorIndex, separator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* array() const { return getOperand(ArrayIndex); }\ + const LAllocation* separator() const { return getOperand(SeparatorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MArrayJoin* mir() const { return mir_->toArrayJoin(); };\ +};\ +class LHomeObjectSuperBase : public LInstructionHelper {\ + public:\ + LIR_HEADER(HomeObjectSuperBase)\ + static constexpr size_t HomeObjectIndex = 0;\ + explicit LHomeObjectSuperBase(const LAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* homeObject() const { return getOperand(HomeObjectIndex); }\ + MHomeObjectSuperBase* mir() const { return mir_->toHomeObjectSuperBase(); };\ +};\ +class LBindNameCache : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(BindNameCache)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LBindNameCache(const LAllocation& environmentChain, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + setTemp(0, temp0);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MBindNameCache* mir() const { return mir_->toBindNameCache(); };\ +};\ +class LCallBindVar : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(CallBindVar)\ + static constexpr size_t EnvironmentChainIndex = 0;\ + explicit LCallBindVar(const LAllocation& environmentChain) : LInstructionHelper(classOpcode) {\ + setOperand(EnvironmentChainIndex, environmentChain);\ + }\ + const LAllocation* environmentChain() const { return getOperand(EnvironmentChainIndex); }\ + MCallBindVar* mir() const { return mir_->toCallBindVar(); };\ +};\ +class LGuardShape : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LGuardShape(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardShape* mir() const { return mir_->toGuardShape(); };\ +};\ +class LHasShape : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HasShape)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LHasShape(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MHasShape* mir() const { return mir_->toHasShape(); };\ +};\ +class LGuardMultipleShapes : public LInstructionHelper<1, 2, 4> {\ + public:\ + LIR_HEADER(GuardMultipleShapes)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ShapeListIndex = 1;\ + explicit LGuardMultipleShapes(const LAllocation& object, const LAllocation& shapeList, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(ShapeListIndex, shapeList);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* shapeList() const { return getOperand(ShapeListIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MGuardMultipleShapes* mir() const { return mir_->toGuardMultipleShapes(); };\ +};\ +class LProxyGet : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGet)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LProxyGet(const LAllocation& proxy, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxyGet* mir() const { return mir_->toProxyGet(); };\ +};\ +class LProxyGetByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ProxyGetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LProxyGetByValue(const LAllocation& proxy, const LBoxAllocation& idVal) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + MProxyGetByValue* mir() const { return mir_->toProxyGetByValue(); };\ +};\ +class LProxySet : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(ProxySet)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LProxySet(const LAllocation& proxy, const LBoxAllocation& rhs, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MProxySet* mir() const { return mir_->toProxySet(); };\ +};\ +class LProxySetByValue : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ProxySetByValue)\ + static constexpr size_t ProxyIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + static constexpr size_t RhsIndex = 1 + 1 * BOX_PIECES;\ + explicit LProxySetByValue(const LAllocation& proxy, const LBoxAllocation& idVal, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ProxyIndex, proxy);\ + setBoxOperand(IdValIndex, idVal);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MProxySetByValue* mir() const { return mir_->toProxySetByValue(); };\ +};\ +class LCallSetArrayLength : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallSetArrayLength)\ + static constexpr size_t ObjIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LCallSetArrayLength(const LAllocation& obj, const LBoxAllocation& rhs) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjIndex, obj);\ + setBoxOperand(RhsIndex, rhs);\ + }\ + const LAllocation* obj() const { return getOperand(ObjIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + MCallSetArrayLength* mir() const { return mir_->toCallSetArrayLength(); };\ +};\ +class LMegamorphicLoadSlot : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlot)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlot(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlot* mir() const { return mir_->toMegamorphicLoadSlot(); };\ +};\ +class LMegamorphicLoadSlotPermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotPermissive)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LMegamorphicLoadSlotPermissive(const LAllocation& object, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotPermissive* mir() const { return mir_->toMegamorphicLoadSlotPermissive(); };\ +};\ +class LMegamorphicLoadSlotByValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValue)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValue(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicLoadSlotByValue* mir() const { return mir_->toMegamorphicLoadSlotByValue(); };\ +};\ +class LMegamorphicLoadSlotByValuePermissive : public LInstructionHelper {\ + public:\ + LIR_HEADER(MegamorphicLoadSlotByValuePermissive)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicLoadSlotByValuePermissive(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMegamorphicLoadSlotByValuePermissive* mir() const { return mir_->toMegamorphicLoadSlotByValuePermissive(); };\ +};\ +class LMegamorphicStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t RhsIndex = 1;\ + explicit LMegamorphicStoreSlot(const LAllocation& object, const LBoxAllocation& rhs, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(RhsIndex, rhs);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation rhs() const { return getBoxOperand(RhsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicStoreSlot* mir() const { return mir_->toMegamorphicStoreSlot(); };\ +};\ +class LMegamorphicHasProp : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 3> {\ + public:\ + LIR_HEADER(MegamorphicHasProp)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IdValIndex = 1;\ + explicit LMegamorphicHasProp(const LAllocation& object, const LBoxAllocation& idVal, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(IdValIndex, idVal);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation idVal() const { return getBoxOperand(IdValIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MMegamorphicHasProp* mir() const { return mir_->toMegamorphicHasProp(); };\ +};\ +class LSmallObjectVariableKeyHasProp : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SmallObjectVariableKeyHasProp)\ + static constexpr size_t IdStrIndex = 0;\ + explicit LSmallObjectVariableKeyHasProp(const LAllocation& idStr) : LInstructionHelper(classOpcode) {\ + setOperand(IdStrIndex, idStr);\ + }\ + const LAllocation* idStr() const { return getOperand(IdStrIndex); }\ + MSmallObjectVariableKeyHasProp* mir() const { return mir_->toSmallObjectVariableKeyHasProp(); };\ +};\ +class LNurseryObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NurseryObject)\ + explicit LNurseryObject() : LInstructionHelper(classOpcode) {\ + }\ + MNurseryObject* mir() const { return mir_->toNurseryObject(); };\ +};\ +class LGuardStringToIndex : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(GuardStringToIndex)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToIndex(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MGuardStringToIndex* mir() const { return mir_->toGuardStringToIndex(); };\ +};\ +class LGuardStringToInt32 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(GuardStringToInt32)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToInt32(const LAllocation& string, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGuardStringToInt32* mir() const { return mir_->toGuardStringToInt32(); };\ +};\ +class LGuardStringToDouble : public LInstructionHelper<1, 1, 2> {\ + public:\ + LIR_HEADER(GuardStringToDouble)\ + static constexpr size_t StringIndex = 0;\ + explicit LGuardStringToDouble(const LAllocation& string, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MGuardStringToDouble* mir() const { return mir_->toGuardStringToDouble(); };\ +};\ +class LFunctionEnvironment : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(FunctionEnvironment)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LFunctionEnvironment(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MFunctionEnvironment* mir() const { return mir_->toFunctionEnvironment(); };\ +};\ +class LHomeObject : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + explicit LHomeObject(const LAllocation& function) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + MHomeObject* mir() const { return mir_->toHomeObject(); };\ +};\ +class LAllocateAndStoreSlot : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(AllocateAndStoreSlot)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAllocateAndStoreSlot(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MAllocateAndStoreSlot* mir() const { return mir_->toAllocateAndStoreSlot(); };\ +};\ +class LAddSlotAndCallAddPropHook : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(AddSlotAndCallAddPropHook)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LAddSlotAndCallAddPropHook(const LAllocation& object, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MAddSlotAndCallAddPropHook* mir() const { return mir_->toAddSlotAndCallAddPropHook(); };\ +};\ +class LGetNameCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetNameCache)\ + static constexpr size_t EnvObjIndex = 0;\ + explicit LGetNameCache(const LAllocation& envObj, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(EnvObjIndex, envObj);\ + setTemp(0, temp0);\ + }\ + const LAllocation* envObj() const { return getOperand(EnvObjIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetNameCache* mir() const { return mir_->toGetNameCache(); };\ +};\ +class LCallGetIntrinsicValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetIntrinsicValue)\ + explicit LCallGetIntrinsicValue() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MCallGetIntrinsicValue* mir() const { return mir_->toCallGetIntrinsicValue(); };\ +};\ +class LLoadSlotByIteratorIndex : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + explicit LLoadSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MLoadSlotByIteratorIndex* mir() const { return mir_->toLoadSlotByIteratorIndex(); };\ +};\ +class LStoreSlotByIteratorIndex : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(StoreSlotByIteratorIndex)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IteratorIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LStoreSlotByIteratorIndex(const LAllocation& object, const LAllocation& iterator, const LBoxAllocation& value, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setOperand(IteratorIndex, iterator);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MStoreSlotByIteratorIndex* mir() const { return mir_->toStoreSlotByIteratorIndex(); };\ +};\ +class LLoadDOMExpandoValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValue)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValue(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValue* mir() const { return mir_->toLoadDOMExpandoValue(); };\ +};\ +class LLoadDOMExpandoValueIgnoreGeneration : public LInstructionHelper {\ + public:\ + LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)\ + static constexpr size_t ProxyIndex = 0;\ + explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy) : LInstructionHelper(classOpcode) {\ + setOperand(ProxyIndex, proxy);\ + }\ + const LAllocation* proxy() const { return getOperand(ProxyIndex); }\ + MLoadDOMExpandoValueIgnoreGeneration* mir() const { return mir_->toLoadDOMExpandoValueIgnoreGeneration(); };\ +};\ +class LStringLength : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(StringLength)\ + static constexpr size_t StringIndex = 0;\ + explicit LStringLength(const LAllocation& string) : LInstructionHelper(classOpcode) {\ + setOperand(StringIndex, string);\ + }\ + const LAllocation* string() const { return getOperand(StringIndex); }\ + MStringLength* mir() const { return mir_->toStringLength(); };\ +};\ +class LOptimizeSpreadCallCache : public LInstructionHelper {\ + public:\ + LIR_HEADER(OptimizeSpreadCallCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeSpreadCallCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeSpreadCallCache* mir() const { return mir_->toOptimizeSpreadCallCache(); };\ +};\ +class LIteratorMore : public LInstructionHelper {\ + public:\ + LIR_HEADER(IteratorMore)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorMore(const LAllocation& iterator, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIteratorMore* mir() const { return mir_->toIteratorMore(); };\ +};\ +class LIteratorEnd : public LInstructionHelper<0, 1, 3> {\ + public:\ + LIR_HEADER(IteratorEnd)\ + static constexpr size_t IteratorIndex = 0;\ + explicit LIteratorEnd(const LAllocation& iterator, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(IteratorIndex, iterator);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* iterator() const { return getOperand(IteratorIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MIteratorEnd* mir() const { return mir_->toIteratorEnd(); };\ +};\ +class LOptimizeGetIteratorCache : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(OptimizeGetIteratorCache)\ + static constexpr size_t ValueIndex = 0;\ + explicit LOptimizeGetIteratorCache(const LBoxAllocation& value, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MOptimizeGetIteratorCache* mir() const { return mir_->toOptimizeGetIteratorCache(); };\ +};\ +class LNewPrivateName : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(NewPrivateName)\ + explicit LNewPrivateName() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MNewPrivateName* mir() const { return mir_->toNewPrivateName(); };\ +};\ +class LInstanceOfCache : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InstanceOfCache)\ + static constexpr size_t ProtoIndex = 0;\ + static constexpr size_t ObjIndex = 1;\ + explicit LInstanceOfCache(const LBoxAllocation& obj, const LAllocation& proto) : LInstructionHelper(classOpcode) {\ + setOperand(ProtoIndex, proto);\ + setBoxOperand(ObjIndex, obj);\ + }\ + const LAllocation* proto() const { return getOperand(ProtoIndex); }\ + LBoxAllocation obj() const { return getBoxOperand(ObjIndex); }\ + MInstanceOfCache* mir() const { return mir_->toInstanceOfCache(); };\ +};\ +class LArgumentsLength : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(ArgumentsLength)\ + explicit LArgumentsLength() : LInstructionHelper(classOpcode) {\ + }\ + MArgumentsLength* mir() const { return mir_->toArgumentsLength(); };\ +};\ +class LGetFrameArgument : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgument)\ + static constexpr size_t IndexIndex = 0;\ + explicit LGetFrameArgument(const LAllocation& index) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MGetFrameArgument* mir() const { return mir_->toGetFrameArgument(); };\ +};\ +class LGetFrameArgumentHole : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetFrameArgumentHole)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + explicit LGetFrameArgumentHole(const LAllocation& index, const LAllocation& length, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MGetFrameArgumentHole* mir() const { return mir_->toGetFrameArgumentHole(); };\ +};\ +class LNewTarget : public LInstructionHelper {\ + public:\ + LIR_HEADER(NewTarget)\ + explicit LNewTarget() : LInstructionHelper(classOpcode) {\ + }\ + MNewTarget* mir() const { return mir_->toNewTarget(); };\ +};\ +class LRest : public LInstructionHelper<1, 1, 4> {\ + public:\ + LIR_HEADER(Rest)\ + static constexpr size_t NumActualsIndex = 0;\ + explicit LRest(const LAllocation& numActuals, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(NumActualsIndex, numActuals);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* numActuals() const { return getOperand(NumActualsIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MRest* mir() const { return mir_->toRest(); };\ +};\ +class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {\ + public:\ + LIR_HEADER(NewNamedLambdaObject)\ + explicit LNewNamedLambdaObject(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); };\ +};\ +class LIsConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsConstructor* mir() const { return mir_->toIsConstructor(); };\ +};\ +class LIsCrossRealmArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsCrossRealmArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsCrossRealmArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsCrossRealmArrayConstructor* mir() const { return mir_->toIsCrossRealmArrayConstructor(); };\ +};\ +class LIsObject : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsObject)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsObject(const LBoxAllocation& object) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ObjectIndex, object);\ + }\ + LBoxAllocation object() const { return getBoxOperand(ObjectIndex); }\ + MIsObject* mir() const { return mir_->toIsObject(); };\ +};\ +class LIsNullOrUndefined : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(IsNullOrUndefined)\ + static constexpr size_t ValueIndex = 0;\ + explicit LIsNullOrUndefined(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MIsNullOrUndefined* mir() const { return mir_->toIsNullOrUndefined(); };\ +};\ +class LObjectClassToString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(ObjectClassToString)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LObjectClassToString(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MObjectClassToString* mir() const { return mir_->toObjectClassToString(); };\ +};\ +class LCheckReturn : public LInstructionHelper {\ + public:\ + LIR_HEADER(CheckReturn)\ + static constexpr size_t ReturnValueIndex = 0;\ + static constexpr size_t ThisValueIndex = 1 * BOX_PIECES;\ + explicit LCheckReturn(const LBoxAllocation& returnValue, const LBoxAllocation& thisValue) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ReturnValueIndex, returnValue);\ + setBoxOperand(ThisValueIndex, thisValue);\ + }\ + LBoxAllocation returnValue() const { return getBoxOperand(ReturnValueIndex); }\ + LBoxAllocation thisValue() const { return getBoxOperand(ThisValueIndex); }\ + MCheckReturn* mir() const { return mir_->toCheckReturn(); };\ +};\ +class LIncrementWarmUpCounter : public LInstructionHelper<0, 0, 1> {\ + public:\ + LIR_HEADER(IncrementWarmUpCounter)\ + explicit LIncrementWarmUpCounter(const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setTemp(0, temp0);\ + }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIncrementWarmUpCounter* mir() const { return mir_->toIncrementWarmUpCounter(); };\ +};\ +class LAtomicPause : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(AtomicPause)\ + explicit LAtomicPause() : LInstructionHelper(classOpcode) {\ + }\ + MAtomicPause* mir() const { return mir_->toAtomicPause(); };\ +};\ +class LCheckIsObj : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CheckIsObj)\ + static constexpr size_t ValueIndex = 0;\ + explicit LCheckIsObj(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCheckIsObj* mir() const { return mir_->toCheckIsObj(); };\ +};\ +class LIsPackedArray : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(IsPackedArray)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsPackedArray(const LAllocation& object, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + setTemp(0, temp0);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MIsPackedArray* mir() const { return mir_->toIsPackedArray(); };\ +};\ +class LGetPrototypeOf : public LInstructionHelper {\ + public:\ + LIR_HEADER(GetPrototypeOf)\ + static constexpr size_t TargetIndex = 0;\ + explicit LGetPrototypeOf(const LAllocation& target) : LInstructionHelper(classOpcode) {\ + setOperand(TargetIndex, target);\ + }\ + const LAllocation* target() const { return getOperand(TargetIndex); }\ + MGetPrototypeOf* mir() const { return mir_->toGetPrototypeOf(); };\ +};\ +class LObjectWithProto : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(ObjectWithProto)\ + static constexpr size_t PrototypeIndex = 0;\ + explicit LObjectWithProto(const LBoxAllocation& prototype) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setBoxOperand(PrototypeIndex, prototype);\ + }\ + LBoxAllocation prototype() const { return getBoxOperand(PrototypeIndex); }\ + MObjectWithProto* mir() const { return mir_->toObjectWithProto(); };\ +};\ +class LBuiltinObject : public LInstructionHelper<1, 0, 0> {\ + public:\ + LIR_HEADER(BuiltinObject)\ + explicit LBuiltinObject() : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + }\ + MBuiltinObject* mir() const { return mir_->toBuiltinObject(); };\ +};\ +class LSuperFunction : public LInstructionHelper {\ + public:\ + LIR_HEADER(SuperFunction)\ + static constexpr size_t CalleeIndex = 0;\ + explicit LSuperFunction(const LAllocation& callee, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(CalleeIndex, callee);\ + setTemp(0, temp0);\ + }\ + const LAllocation* callee() const { return getOperand(CalleeIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MSuperFunction* mir() const { return mir_->toSuperFunction(); };\ +};\ +class LInitHomeObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(InitHomeObject)\ + static constexpr size_t FunctionIndex = 0;\ + static constexpr size_t HomeObjectIndex = 1;\ + explicit LInitHomeObject(const LAllocation& function, const LBoxAllocation& homeObject) : LInstructionHelper(classOpcode) {\ + setOperand(FunctionIndex, function);\ + setBoxOperand(HomeObjectIndex, homeObject);\ + }\ + const LAllocation* function() const { return getOperand(FunctionIndex); }\ + LBoxAllocation homeObject() const { return getBoxOperand(HomeObjectIndex); }\ + MInitHomeObject* mir() const { return mir_->toInitHomeObject(); };\ +};\ +class LIsTypedArrayConstructor : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(IsTypedArrayConstructor)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LIsTypedArrayConstructor(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MIsTypedArrayConstructor* mir() const { return mir_->toIsTypedArrayConstructor(); };\ +};\ +class LLoadValueTag : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(LoadValueTag)\ + static constexpr size_t ValueIndex = 0;\ + explicit LLoadValueTag(const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + setBoxOperand(ValueIndex, value);\ + }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MLoadValueTag* mir() const { return mir_->toLoadValueTag(); };\ +};\ +class LLoadWrapperTarget : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(LoadWrapperTarget)\ + static constexpr size_t ObjectIndex = 0;\ + explicit LLoadWrapperTarget(const LAllocation& object) : LInstructionHelper(classOpcode) {\ + setOperand(ObjectIndex, object);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + MLoadWrapperTarget* mir() const { return mir_->toLoadWrapperTarget(); };\ +};\ +class LCallAddOrUpdateSparseElement : public LInstructionHelper<0, 2 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(CallAddOrUpdateSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LCallAddOrUpdateSparseElement(const LAllocation& object, const LAllocation& index, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MCallAddOrUpdateSparseElement* mir() const { return mir_->toCallAddOrUpdateSparseElement(); };\ +};\ +class LCallGetSparseElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallGetSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallGetSparseElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallGetSparseElement* mir() const { return mir_->toCallGetSparseElement(); };\ +};\ +class LCallNativeGetElement : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallNativeGetElement(const LAllocation& object, const LAllocation& index) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + MCallNativeGetElement* mir() const { return mir_->toCallNativeGetElement(); };\ +};\ +class LCallNativeGetElementSuper : public LInstructionHelper {\ + public:\ + LIR_HEADER(CallNativeGetElementSuper)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + static constexpr size_t ReceiverIndex = 2;\ + explicit LCallNativeGetElementSuper(const LAllocation& object, const LAllocation& index, const LBoxAllocation& receiver) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setBoxOperand(ReceiverIndex, receiver);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + LBoxAllocation receiver() const { return getBoxOperand(ReceiverIndex); }\ + MCallNativeGetElementSuper* mir() const { return mir_->toCallNativeGetElementSuper(); };\ +};\ +class LCallObjectHasSparseElement : public LInstructionHelper<1, 2, 2> {\ + public:\ + LIR_HEADER(CallObjectHasSparseElement)\ + static constexpr size_t ObjectIndex = 0;\ + static constexpr size_t IndexIndex = 1;\ + explicit LCallObjectHasSparseElement(const LAllocation& object, const LAllocation& index, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(ObjectIndex, object);\ + setOperand(IndexIndex, index);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* object() const { return getOperand(ObjectIndex); }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MCallObjectHasSparseElement* mir() const { return mir_->toCallObjectHasSparseElement(); };\ +};\ +class LBigIntAsIntN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsIntN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsIntN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsIntN* mir() const { return mir_->toBigIntAsIntN(); };\ +};\ +class LBigIntAsUintN : public LInstructionHelper<1, 2, 0> {\ + public:\ + LIR_HEADER(BigIntAsUintN)\ + static constexpr size_t BitsIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LBigIntAsUintN(const LAllocation& bits, const LAllocation& input) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(BitsIndex, bits);\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* bits() const { return getOperand(BitsIndex); }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MBigIntAsUintN* mir() const { return mir_->toBigIntAsUintN(); };\ +};\ +class LToHashableNonGCThing : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableNonGCThing* mir() const { return mir_->toToHashableNonGCThing(); };\ +};\ +class LToHashableString : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(ToHashableString)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableString(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MToHashableString* mir() const { return mir_->toToHashableString(); };\ +};\ +class LToHashableValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(ToHashableValue)\ + static constexpr size_t InputIndex = 0;\ + explicit LToHashableValue(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MToHashableValue* mir() const { return mir_->toToHashableValue(); };\ +};\ +class LHashNonGCThing : public LInstructionHelper<1, 0 + 1 * BOX_PIECES, 1> {\ + public:\ + LIR_HEADER(HashNonGCThing)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashNonGCThing(const LBoxAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashNonGCThing* mir() const { return mir_->toHashNonGCThing(); };\ +};\ +class LHashString : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(HashString)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashString(const LAllocation& input, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MHashString* mir() const { return mir_->toHashString(); };\ +};\ +class LHashSymbol : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(HashSymbol)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashSymbol(const LAllocation& input) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + MHashSymbol* mir() const { return mir_->toHashSymbol(); };\ +};\ +class LHashBigInt : public LInstructionHelper<1, 1, 3> {\ + public:\ + LIR_HEADER(HashBigInt)\ + static constexpr size_t InputIndex = 0;\ + explicit LHashBigInt(const LAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2) : LInstructionHelper(classOpcode) {\ + setOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + }\ + const LAllocation* input() const { return getOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + MHashBigInt* mir() const { return mir_->toHashBigInt(); };\ +};\ +class LHashObject : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashObject)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashObject(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashObject* mir() const { return mir_->toHashObject(); };\ +};\ +class LHashValue : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(HashValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t InputIndex = 1;\ + explicit LHashValue(const LAllocation& setObject, const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(InputIndex, input);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation input() const { return getBoxOperand(InputIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MHashValue* mir() const { return mir_->toHashValue(); };\ +};\ +class LSetObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(SetObjectHasNonBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasNonBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MSetObjectHasNonBigInt* mir() const { return mir_->toSetObjectHasNonBigInt(); };\ +};\ +class LSetObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasBigInt)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasBigInt(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasBigInt* mir() const { return mir_->toSetObjectHasBigInt(); };\ +};\ +class LSetObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(SetObjectHasValue)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LSetObjectHasValue(const LAllocation& setObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MSetObjectHasValue* mir() const { return mir_->toSetObjectHasValue(); };\ +};\ +class LSetObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectHasValueVMCall)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LSetObjectHasValueVMCall(const LAllocation& setObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MSetObjectHasValueVMCall* mir() const { return mir_->toSetObjectHasValueVMCall(); };\ +};\ +class LSetObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectDelete)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectDelete(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectDelete* mir() const { return mir_->toSetObjectDelete(); };\ +};\ +class LSetObjectAdd : public LInstructionHelper<0, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(SetObjectAdd)\ + static constexpr size_t SetObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LSetObjectAdd(const LAllocation& setObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(SetObjectIndex, setObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MSetObjectAdd* mir() const { return mir_->toSetObjectAdd(); };\ +};\ +class LSetObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(SetObjectSize)\ + static constexpr size_t SetObjectIndex = 0;\ + explicit LSetObjectSize(const LAllocation& setObject) : LInstructionHelper(classOpcode) {\ + setOperand(SetObjectIndex, setObject);\ + }\ + const LAllocation* setObject() const { return getOperand(SetObjectIndex); }\ + MSetObjectSize* mir() const { return mir_->toSetObjectSize(); };\ +};\ +class LMapObjectHasNonBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 2> {\ + public:\ + LIR_HEADER(MapObjectHasNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectHasNonBigInt* mir() const { return mir_->toMapObjectHasNonBigInt(); };\ +};\ +class LMapObjectHasBigInt : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasBigInt* mir() const { return mir_->toMapObjectHasBigInt(); };\ +};\ +class LMapObjectHasValue : public LInstructionHelper<1, 2 + 1 * BOX_PIECES, 4> {\ + public:\ + LIR_HEADER(MapObjectHasValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectHasValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectHasValue* mir() const { return mir_->toMapObjectHasValue(); };\ +};\ +class LMapObjectHasValueVMCall : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectHasValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectHasValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectHasValueVMCall* mir() const { return mir_->toMapObjectHasValueVMCall(); };\ +};\ +class LMapObjectGetNonBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetNonBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetNonBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MMapObjectGetNonBigInt* mir() const { return mir_->toMapObjectGetNonBigInt(); };\ +};\ +class LMapObjectGetBigInt : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetBigInt)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetBigInt(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetBigInt* mir() const { return mir_->toMapObjectGetBigInt(); };\ +};\ +class LMapObjectGetValue : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValue)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t HashIndex = 1;\ + static constexpr size_t ValueIndex = 2;\ + explicit LMapObjectGetValue(const LAllocation& mapObject, const LBoxAllocation& value, const LAllocation& hash, const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + setOperand(HashIndex, hash);\ + setBoxOperand(ValueIndex, value);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + setTemp(2, temp2);\ + setTemp(3, temp3);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + const LAllocation* hash() const { return getOperand(HashIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + const LDefinition* temp2() { return getTemp(2); }\ + const LDefinition* temp3() { return getTemp(3); }\ + MMapObjectGetValue* mir() const { return mir_->toMapObjectGetValue(); };\ +};\ +class LMapObjectGetValueVMCall : public LInstructionHelper {\ + public:\ + LIR_HEADER(MapObjectGetValueVMCall)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t ValueIndex = 1;\ + explicit LMapObjectGetValueVMCall(const LAllocation& mapObject, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectGetValueVMCall* mir() const { return mir_->toMapObjectGetValueVMCall(); };\ +};\ +class LMapObjectDelete : public LInstructionHelper<1, 1 + 1 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectDelete)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + explicit LMapObjectDelete(const LAllocation& mapObject, const LBoxAllocation& key) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + MMapObjectDelete* mir() const { return mir_->toMapObjectDelete(); };\ +};\ +class LMapObjectSet : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 0> {\ + public:\ + LIR_HEADER(MapObjectSet)\ + static constexpr size_t MapObjectIndex = 0;\ + static constexpr size_t KeyIndex = 1;\ + static constexpr size_t ValueIndex = 1 + 1 * BOX_PIECES;\ + explicit LMapObjectSet(const LAllocation& mapObject, const LBoxAllocation& key, const LBoxAllocation& value) : LInstructionHelper(classOpcode) {\ + this->setIsCall();\ + setOperand(MapObjectIndex, mapObject);\ + setBoxOperand(KeyIndex, key);\ + setBoxOperand(ValueIndex, value);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + LBoxAllocation key() const { return getBoxOperand(KeyIndex); }\ + LBoxAllocation value() const { return getBoxOperand(ValueIndex); }\ + MMapObjectSet* mir() const { return mir_->toMapObjectSet(); };\ +};\ +class LMapObjectSize : public LInstructionHelper<1, 1, 0> {\ + public:\ + LIR_HEADER(MapObjectSize)\ + static constexpr size_t MapObjectIndex = 0;\ + explicit LMapObjectSize(const LAllocation& mapObject) : LInstructionHelper(classOpcode) {\ + setOperand(MapObjectIndex, mapObject);\ + }\ + const LAllocation* mapObject() const { return getOperand(MapObjectIndex); }\ + MMapObjectSize* mir() const { return mir_->toMapObjectSize(); };\ +};\ +class LDateFillLocalTimeSlots : public LInstructionHelper<0, 1, 1> {\ + public:\ + LIR_HEADER(DateFillLocalTimeSlots)\ + static constexpr size_t DateIndex = 0;\ + explicit LDateFillLocalTimeSlots(const LAllocation& date, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(DateIndex, date);\ + setTemp(0, temp0);\ + }\ + const LAllocation* date() const { return getOperand(DateIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MDateFillLocalTimeSlots* mir() const { return mir_->toDateFillLocalTimeSlots(); };\ +};\ +class LDateHoursFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateHoursFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateHoursFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateHoursFromSecondsIntoYear* mir() const { return mir_->toDateHoursFromSecondsIntoYear(); };\ +};\ +class LDateMinutesFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateMinutesFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateMinutesFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateMinutesFromSecondsIntoYear* mir() const { return mir_->toDateMinutesFromSecondsIntoYear(); };\ +};\ +class LDateSecondsFromSecondsIntoYear : public LInstructionHelper {\ + public:\ + LIR_HEADER(DateSecondsFromSecondsIntoYear)\ + static constexpr size_t SecondsIntoYearIndex = 0;\ + explicit LDateSecondsFromSecondsIntoYear(const LBoxAllocation& secondsIntoYear, const LDefinition& temp0, const LDefinition& temp1) : LInstructionHelper(classOpcode) {\ + setBoxOperand(SecondsIntoYearIndex, secondsIntoYear);\ + setTemp(0, temp0);\ + setTemp(1, temp1);\ + }\ + LBoxAllocation secondsIntoYear() const { return getBoxOperand(SecondsIntoYearIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + const LDefinition* temp1() { return getTemp(1); }\ + MDateSecondsFromSecondsIntoYear* mir() const { return mir_->toDateSecondsFromSecondsIntoYear(); };\ +};\ +class LWasmBoundsCheckRange32 : public LInstructionHelper<1, 3, 1> {\ + public:\ + LIR_HEADER(WasmBoundsCheckRange32)\ + static constexpr size_t IndexIndex = 0;\ + static constexpr size_t LengthIndex = 1;\ + static constexpr size_t LimitIndex = 2;\ + explicit LWasmBoundsCheckRange32(const LAllocation& index, const LAllocation& length, const LAllocation& limit, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(IndexIndex, index);\ + setOperand(LengthIndex, length);\ + setOperand(LimitIndex, limit);\ + setTemp(0, temp0);\ + }\ + const LAllocation* index() const { return getOperand(IndexIndex); }\ + const LAllocation* length() const { return getOperand(LengthIndex); }\ + const LAllocation* limit() const { return getOperand(LimitIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmBoundsCheckRange32* mir() const { return mir_->toWasmBoundsCheckRange32(); };\ +};\ +class LWasmClampTable64Address : public LInstructionHelper<1, 0 + 1 * INT64_PIECES, 0> {\ + public:\ + LIR_HEADER(WasmClampTable64Address)\ + static constexpr size_t AddressIndex = 0;\ + explicit LWasmClampTable64Address(const LInt64Allocation& address) : LInstructionHelper(classOpcode) {\ + setInt64Operand(AddressIndex, address);\ + }\ + LInt64Allocation address() const { return getInt64Operand(AddressIndex); }\ + MWasmClampTable64Address* mir() const { return mir_->toWasmClampTable64Address(); };\ +};\ +class LWasmFence : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmFence)\ + explicit LWasmFence() : LInstructionHelper(classOpcode) {\ + }\ + MWasmFence* mir() const { return mir_->toWasmFence(); };\ +};\ +class LWasmCallLandingPrePad : public LInstructionHelper<0, 0, 0> {\ + public:\ + LIR_HEADER(WasmCallLandingPrePad)\ + explicit LWasmCallLandingPrePad() : LInstructionHelper(classOpcode) {\ + }\ + MWasmCallLandingPrePad* mir() const { return mir_->toWasmCallLandingPrePad(); };\ +};\ +class LWasmUnarySimd128 : public LInstructionHelper<1, 1, 1> {\ + public:\ + LIR_HEADER(WasmUnarySimd128)\ + static constexpr size_t SrcIndex = 0;\ + explicit LWasmUnarySimd128(const LAllocation& src, const LDefinition& temp0) : LInstructionHelper(classOpcode) {\ + setOperand(SrcIndex, src);\ + setTemp(0, temp0);\ + }\ + const LAllocation* src() const { return getOperand(SrcIndex); }\ + const LDefinition* temp0() { return getTemp(0); }\ + MWasmUnarySimd128* mir() const { return mir_->toWasmUnarySimd128(); };\ +}; diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/jit/MIROpsGenerated.h b/src/third_party/mozjs/platform/x86_64/windows/include/jit/MIROpsGenerated.h index f182c3f70ac..7f50b9a7919 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/jit/MIROpsGenerated.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/jit/MIROpsGenerated.h @@ -12,6 +12,8 @@ _(Start)\ _(OsrEntry)\ _(Nop)\ _(LimitedTruncate)\ +_(IntPtrLimitedTruncate)\ +_(Int64LimitedTruncate)\ _(Constant)\ _(WasmNullConstant)\ _(WasmFloatConstant)\ @@ -30,6 +32,10 @@ _(NewTypedArray)\ _(NewTypedArrayDynamicLength)\ _(NewTypedArrayFromArray)\ _(NewTypedArrayFromArrayBuffer)\ +_(NewMapObject)\ +_(NewSetObject)\ +_(NewMapObjectFromIterable)\ +_(NewSetObjectFromIterable)\ _(NewObject)\ _(NewPlainObject)\ _(NewArrayObject)\ @@ -56,6 +62,8 @@ _(EncodeSnapshot)\ _(AssertRecoveredOnBailout)\ _(AssertFloat32)\ _(Compare)\ +_(StrictConstantCompareInt32)\ +_(StrictConstantCompareBoolean)\ _(SameValueDouble)\ _(SameValue)\ _(Box)\ @@ -76,12 +84,14 @@ _(InArgumentsObjectArg)\ _(ArgumentsObjectLength)\ _(ArrayFromArgumentsObject)\ _(GuardArgumentsObjectFlags)\ +_(GuardObjectHasSameRealm)\ _(LoadScriptedProxyHandler)\ _(CheckScriptedProxyGetResult)\ _(IdToStringOrSymbol)\ _(ReturnFromCtor)\ _(ToDouble)\ _(ToFloat32)\ +_(ToFloat16)\ _(WasmUnsignedToDouble)\ _(WasmUnsignedToFloat32)\ _(WrapInt64ToInt32)\ @@ -92,6 +102,9 @@ _(WasmTruncateToInt32)\ _(WasmAnyRefFromJSValue)\ _(WasmAnyRefFromJSObject)\ _(WasmAnyRefFromJSString)\ +_(WasmAnyRefIsJSString)\ +_(WasmTrapIfAnyRefIsNotJSString)\ +_(WasmAnyRefJSStringLength)\ _(WasmNewI31Ref)\ _(WasmI31RefGet)\ _(Int32ToIntPtr)\ @@ -108,6 +121,8 @@ _(ToBigInt)\ _(ToInt64)\ _(TruncateBigIntToInt64)\ _(Int64ToBigInt)\ +_(Int64ToIntPtr)\ +_(IntPtrToInt64)\ _(ToString)\ _(BitNot)\ _(TypeOf)\ @@ -123,6 +138,7 @@ _(Rsh)\ _(Ursh)\ _(SignExtendInt32)\ _(SignExtendInt64)\ +_(SignExtendIntPtr)\ _(MinMax)\ _(MinMaxArray)\ _(Abs)\ @@ -161,6 +177,20 @@ _(BigIntIncrement)\ _(BigIntDecrement)\ _(BigIntNegate)\ _(BigIntBitNot)\ +_(BigIntToIntPtr)\ +_(IntPtrToBigInt)\ +_(BigIntPtrAdd)\ +_(BigIntPtrSub)\ +_(BigIntPtrMul)\ +_(BigIntPtrDiv)\ +_(BigIntPtrMod)\ +_(BigIntPtrPow)\ +_(BigIntPtrBitAnd)\ +_(BigIntPtrBitOr)\ +_(BigIntPtrBitXor)\ +_(BigIntPtrLsh)\ +_(BigIntPtrRsh)\ +_(BigIntPtrBitNot)\ _(Int32ToStringWithBase)\ _(NumberParseInt)\ _(DoubleParseInt)\ @@ -204,7 +234,6 @@ _(CheckOverRecursed)\ _(InterruptCheck)\ _(WasmInterruptCheck)\ _(WasmTrap)\ -_(WasmTrapIfNull)\ _(LexicalCheck)\ _(ThrowRuntimeLexicalError)\ _(ThrowMsg)\ @@ -216,8 +245,6 @@ _(RegExpSearcherLastLimit)\ _(RegExpExecMatch)\ _(RegExpExecTest)\ _(RegExpHasCaptureGroups)\ -_(RegExpPrototypeOptimizable)\ -_(RegExpInstanceOptimizable)\ _(GetFirstDollarIndex)\ _(StringReplace)\ _(Substr)\ @@ -289,6 +316,7 @@ _(GetPropSuperCache)\ _(BindNameCache)\ _(CallBindVar)\ _(GuardShape)\ +_(HasShape)\ _(GuardFuse)\ _(GuardMultipleShapes)\ _(GuardProto)\ @@ -305,7 +333,9 @@ _(ProxySet)\ _(ProxySetByValue)\ _(CallSetArrayLength)\ _(MegamorphicLoadSlot)\ +_(MegamorphicLoadSlotPermissive)\ _(MegamorphicLoadSlotByValue)\ +_(MegamorphicLoadSlotByValuePermissive)\ _(MegamorphicStoreSlot)\ _(MegamorphicHasProp)\ _(SmallObjectVariableKeyHasProp)\ @@ -416,6 +446,7 @@ _(CanSkipAwait)\ _(MaybeExtractAwaitValue)\ _(IncrementWarmUpCounter)\ _(AtomicIsLockFree)\ +_(AtomicPause)\ _(CompareExchangeTypedArrayElement)\ _(AtomicExchangeTypedArrayElement)\ _(AtomicTypedArrayElementBinop)\ @@ -463,6 +494,8 @@ _(SetObjectHasNonBigInt)\ _(SetObjectHasBigInt)\ _(SetObjectHasValue)\ _(SetObjectHasValueVMCall)\ +_(SetObjectDelete)\ +_(SetObjectAdd)\ _(SetObjectSize)\ _(MapObjectHasNonBigInt)\ _(MapObjectHasBigInt)\ @@ -472,8 +505,15 @@ _(MapObjectGetNonBigInt)\ _(MapObjectGetBigInt)\ _(MapObjectGetValue)\ _(MapObjectGetValueVMCall)\ +_(MapObjectDelete)\ +_(MapObjectSet)\ _(MapObjectSize)\ +_(DateFillLocalTimeSlots)\ +_(DateHoursFromSecondsIntoYear)\ +_(DateMinutesFromSecondsIntoYear)\ +_(DateSecondsFromSecondsIntoYear)\ _(PostIntPtrConversion)\ +_(CanonicalizeNaN)\ _(WasmNeg)\ _(WasmBinaryBitwise)\ _(WasmLoadInstance)\ @@ -483,6 +523,7 @@ _(WasmBoundsCheck)\ _(WasmBoundsCheckRange32)\ _(WasmExtendU32Index)\ _(WasmWrapU32Index)\ +_(WasmClampTable64Address)\ _(WasmAddOffset)\ _(WasmAlignmentCheck)\ _(WasmLoad)\ @@ -502,8 +543,8 @@ _(WasmStoreStackResult)\ _(WasmDerivedPointer)\ _(WasmDerivedIndexPointer)\ _(WasmStoreRef)\ -_(WasmPostWriteBarrierImmediate)\ -_(WasmPostWriteBarrierIndex)\ +_(WasmPostWriteBarrierWholeCell)\ +_(WasmPostWriteBarrierEdgeAtIndex)\ _(WasmParameter)\ _(WasmReturn)\ _(WasmReturnVoid)\ @@ -518,7 +559,7 @@ _(WasmCallUncatchable)\ _(WasmCallLandingPrePad)\ _(WasmReturnCall)\ _(WasmSelect)\ -_(WasmReinterpret)\ +_(ReinterpretCast)\ _(Rotate)\ _(WasmStackSwitchToMain)\ _(WasmStackSwitchToSuspendable)\ @@ -537,14 +578,17 @@ _(WasmStoreLaneSimd128)\ _(UnreachableResult)\ _(IonToWasmCall)\ _(WasmLoadField)\ -_(WasmLoadFieldKA)\ -_(WasmLoadElementKA)\ -_(WasmStoreFieldKA)\ -_(WasmStoreFieldRefKA)\ -_(WasmStoreElementKA)\ -_(WasmStoreElementRefKA)\ -_(WasmRefIsSubtypeOfConcrete)\ -_(WasmRefIsSubtypeOfAbstract)\ +_(WasmLoadElement)\ +_(WasmStoreField)\ +_(WasmStoreFieldRef)\ +_(WasmStoreElement)\ +_(WasmStoreElementRef)\ +_(WasmRefAsNonNull)\ +_(WasmRefTestConcrete)\ +_(WasmRefTestAbstract)\ +_(WasmRefCastConcrete)\ +_(WasmRefCastAbstract)\ +_(WasmRefConvertAnyExtern)\ _(WasmNewStructObject)\ _(WasmNewArrayObject) @@ -686,6 +730,56 @@ class MNewTypedArrayFromArrayBuffer : public MTernaryInstruction, public MixPoli bool possiblyCalls() const override { return true; }\ };\ \ +class MNewMapObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObject : public MNullaryInstruction {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObject(JSObject* templateObject) : MNullaryInstruction(classOpcode), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObject)\ + TRIVIAL_NEW_WRAPPERS\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewMapObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewMapObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewMapObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MNewSetObjectFromIterable : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + CompilerGCPointer templateObject_;\ + explicit MNewSetObjectFromIterable(MDefinition* iterable, JSObject* templateObject) : MUnaryInstruction(classOpcode, iterable), templateObject_(templateObject) {\ + setResultType(MIRType::Object);\ + }\ + public:\ + JSObject* templateObject() const { return templateObject_; }\ + INSTRUCTION_HEADER(NewSetObjectFromIterable)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, iterable))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MNewBoundFunction : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ explicit MNewBoundFunction(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ @@ -765,6 +859,44 @@ class MEncodeSnapshot : public MNullaryInstruction {\ TRIVIAL_NEW_WRAPPERS\ };\ \ +class MStrictConstantCompareInt32 : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + int32_t constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareInt32(MDefinition* value, int32_t constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + int32_t constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareInt32)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ +class MStrictConstantCompareBoolean : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + bool constant_;\ + JSOp jsop_;\ + explicit MStrictConstantCompareBoolean(MDefinition* value, bool constant, JSOp jsop) : MUnaryInstruction(classOpcode, value), constant_(constant), jsop_(jsop) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + bool constant() const { return constant_; }\ + JSOp jsop() const { return jsop_; }\ + INSTRUCTION_HEADER(StrictConstantCompareBoolean)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, value))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ +};\ +\ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, DoublePolicy<1>>::Data {\ explicit MSameValueDouble(MDefinition* left, MDefinition* right) : MBinaryInstruction(classOpcode, left, right) {\ setMovable();\ @@ -775,6 +907,7 @@ class MSameValueDouble : public MBinaryInstruction, public MixPolicy, Box TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, left), (1, right))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ ALLOW_CLONE(MSameValue)\ };\ @@ -913,6 +1047,20 @@ class MGuardArgumentsObjectFlags : public MUnaryInstruction, public ObjectPolicy bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MGuardObjectHasSameRealm : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MGuardObjectHasSameRealm(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ + setGuard();\ + setMovable();\ + setResultType(MIRType::Object);\ + }\ + public:\ + INSTRUCTION_HEADER(GuardObjectHasSameRealm)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MLoadScriptedProxyHandler : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ explicit MLoadScriptedProxyHandler(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ setGuard();\ @@ -975,6 +1123,7 @@ class MWasmUnsignedToDouble : public MUnaryInstruction, public NoTypePolicy::Dat AliasSet getAliasSet() const override { return AliasSet::None(); }\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmUnsignedToDouble)\ };\ \ class MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1013,17 +1162,53 @@ class MWasmAnyRefFromJSString : public MUnaryInstruction, public NoTypePolicy::D bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ -class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ +class MWasmAnyRefIsJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmAnyRefIsJSString(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ setMovable();\ - setResultType(MIRType::WasmAnyRef);\ + setResultType(MIRType::Int32);\ }\ public:\ - INSTRUCTION_HEADER(WasmNewI31Ref)\ + INSTRUCTION_HEADER(WasmAnyRefIsJSString)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefIsJSString)\ +};\ +\ +class MWasmTrapIfAnyRefIsNotJSString : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmTrapIfAnyRefIsNotJSString(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmTrapIfAnyRefIsNotJSString)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmTrapIfAnyRefIsNotJSString)\ +};\ +\ +class MWasmAnyRefJSStringLength : public MUnaryInstruction, public NoTypePolicy::Data {\ + wasm::Trap trap_;\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmAnyRefJSStringLength(MDefinition* input, wasm::Trap trap, wasm::TrapSiteDesc trapSiteDesc) : MUnaryInstruction(classOpcode, input), trap_(trap), trapSiteDesc_(trapSiteDesc) {\ + setGuard();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + wasm::Trap trap() const { return trap_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ + INSTRUCTION_HEADER(WasmAnyRefJSStringLength)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + ALLOW_CLONE(MWasmAnyRefJSStringLength)\ };\ \ class MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy::Data {\ @@ -1126,6 +1311,42 @@ class MRandom : public MNullaryInstruction {\ ALLOW_CLONE(MRandom)\ };\ \ +class MBigIntToIntPtr : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ + explicit MBigIntToIntPtr(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::IntPtr);\ + }\ + public:\ + INSTRUCTION_HEADER(BigIntToIntPtr)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MBigIntToIntPtr)\ +};\ +\ +class MIntPtrToBigInt : public MUnaryInstruction, public IntPtrPolicy<0>::Data {\ + explicit MIntPtrToBigInt(MDefinition* input) : MUnaryInstruction(classOpcode, input) {\ + setMovable();\ + setResultType(MIRType::BigInt);\ + }\ + public:\ + INSTRUCTION_HEADER(IntPtrToBigInt)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, input))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ + [[nodiscard]] bool writeRecoverData(\ + CompactBufferWriter& writer) const override;\ + bool canRecoverOnBailout() const override { return true; }\ + ALLOW_CLONE(MIntPtrToBigInt)\ +};\ +\ class MInt32ToStringWithBase : public MBinaryInstruction, public MixPolicy, UnboxedInt32Policy<1>>::Data {\ bool lowerCase_;\ explicit MInt32ToStringWithBase(MDefinition* input, MDefinition* base, bool lowerCase) : MBinaryInstruction(classOpcode, input, base), lowerCase_(lowerCase) {\ @@ -1497,16 +1718,13 @@ class MBoxNonStrictThis : public MUnaryInstruction, public BoxPolicy<0>::Data {\ };\ \ class MImplicitThis : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - CompilerGCPointer name_;\ - explicit MImplicitThis(MDefinition* envChain, PropertyName* name) : MUnaryInstruction(classOpcode, envChain), name_(name) {\ + explicit MImplicitThis(MDefinition* env) : MUnaryInstruction(classOpcode, env) {\ setResultType(MIRType::Value);\ }\ public:\ - PropertyName* name() const { return name_; }\ INSTRUCTION_HEADER(ImplicitThis)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ - bool possiblyCalls() const override { return true; }\ + NAMED_OPERANDS((0, env))\ };\ \ class MUnaryCache : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -1539,21 +1757,6 @@ class MInterruptCheck : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ -class MWasmTrapIfNull : public MUnaryInstruction, public NoTypePolicy::Data {\ - wasm::Trap trap_;\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmTrapIfNull(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_(bytecodeOffset) {\ - setGuard();\ - setResultType(MIRType::None);\ - }\ - public:\ - wasm::Trap trap() const { return trap_; }\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ - INSTRUCTION_HEADER(WasmTrapIfNull)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, ref))\ -};\ -\ class MThrowRuntimeLexicalError : public MNullaryInstruction {\ unsigned errorNumber_;\ explicit MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction(classOpcode), errorNumber_(errorNumber) {\ @@ -1655,28 +1858,6 @@ class MRegExpHasCaptureGroups : public MBinaryInstruction, public MixPolicy::Data {\ - explicit MRegExpPrototypeOptimizable(MDefinition* object) : MUnaryInstruction(classOpcode, object) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpPrototypeOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ -class MRegExpInstanceOptimizable : public MBinaryInstruction, public MixPolicy, ObjectPolicy<1>>::Data {\ - explicit MRegExpInstanceOptimizable(MDefinition* object, MDefinition* proto) : MBinaryInstruction(classOpcode, object, proto) {\ - setResultType(MIRType::Boolean);\ - }\ - public:\ - INSTRUCTION_HEADER(RegExpInstanceOptimizable)\ - TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, object), (1, proto))\ - AliasSet getAliasSet() const override { return AliasSet::None(); }\ -};\ -\ class MSubstr : public MTernaryInstruction, public MixPolicy, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data {\ explicit MSubstr(MDefinition* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction(classOpcode, string, begin, length) {\ setResultType(MIRType::String);\ @@ -2110,13 +2291,13 @@ class MNormalizeSliceTerm : public MBinaryInstruction, public MixPolicy, StringPolicy<1>>::Data {\ - explicit MArrayJoin(MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode, array, sep) {\ + explicit MArrayJoin(MDefinition* array, MDefinition* separator) : MBinaryInstruction(classOpcode, array, separator) {\ setResultType(MIRType::String);\ }\ public:\ INSTRUCTION_HEADER(ArrayJoin)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, array), (1, sep))\ + NAMED_OPERANDS((0, array), (1, separator))\ MDefinition* foldsTo(TempAllocator& alloc) override;\ bool possiblyCalls() const override { return true; }\ };\ @@ -2161,13 +2342,13 @@ class MHomeObjectSuperBase : public MUnaryInstruction, public ObjectPolicy<0>::D };\ \ class MBindNameCache : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode, envChain) {\ + explicit MBindNameCache(MDefinition* environmentChain) : MUnaryInstruction(classOpcode, environmentChain) {\ setResultType(MIRType::Object);\ }\ public:\ INSTRUCTION_HEADER(BindNameCache)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, envChain))\ + NAMED_OPERANDS((0, environmentChain))\ };\ \ class MCallBindVar : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ @@ -2200,6 +2381,21 @@ class MGuardShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ bool congruentTo(const MDefinition* ins) const override;\ };\ \ +class MHasShape : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + CompilerGCPointer shape_;\ + explicit MHasShape(MDefinition* object, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_(shape) {\ + setMovable();\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + Shape* shape() const { return shape_; }\ + INSTRUCTION_HEADER(HasShape)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override;\ +};\ +\ class MGuardFuse : public MNullaryInstruction {\ RealmFuses::FuseIndex fuseIndex_;\ explicit MGuardFuse(RealmFuses::FuseIndex fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex) {\ @@ -2394,6 +2590,20 @@ class MMegamorphicLoadSlot : public MUnaryInstruction, public ObjectPolicy<0>::D bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotPermissive : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + PropertyKey name_;\ + explicit MMegamorphicLoadSlotPermissive(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode, object), name_(name) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + PropertyKey name() const { return name_; }\ + INSTRUCTION_HEADER(MegamorphicLoadSlotPermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ explicit MMegamorphicLoadSlotByValue(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ setGuard();\ @@ -2409,6 +2619,19 @@ class MMegamorphicLoadSlotByValue : public MBinaryInstruction, public MixPolicy< bool possiblyCalls() const override { return true; }\ };\ \ +class MMegamorphicLoadSlotByValuePermissive : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMegamorphicLoadSlotByValuePermissive(MDefinition* object, MDefinition* idVal) : MBinaryInstruction(classOpcode, object, idVal) {\ + setGuard();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(MegamorphicLoadSlotByValuePermissive)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, object), (1, idVal))\ + MDefinition* foldsTo(TempAllocator& alloc) override;\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMegamorphicStoreSlot : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ PropertyKey name_;\ bool strict_;\ @@ -3125,11 +3348,13 @@ class MAssertCanElidePostWriteBarrier : public MBinaryInstruction, public MixPol \ class MNewNamedLambdaObject : public MNullaryInstruction {\ CompilerGCPointer templateObj_;\ - explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_(templateObj) {\ + gc::Heap initialHeap_;\ + explicit MNewNamedLambdaObject(NamedLambdaObject* templateObj, gc::Heap initialHeap) : MNullaryInstruction(classOpcode), templateObj_(templateObj), initialHeap_(initialHeap) {\ setResultType(MIRType::Object);\ }\ public:\ NamedLambdaObject* templateObj() const { return templateObj_; }\ + gc::Heap initialHeap() const { return initialHeap_; }\ INSTRUCTION_HEADER(NewNamedLambdaObject)\ TRIVIAL_NEW_WRAPPERS\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ @@ -3306,6 +3531,16 @@ class MIncrementWarmUpCounter : public MNullaryInstruction {\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ +class MAtomicPause : public MNullaryInstruction {\ + explicit MAtomicPause() : MNullaryInstruction(classOpcode) {\ + setGuard();\ + }\ + public:\ + INSTRUCTION_HEADER(AtomicPause)\ + TRIVIAL_NEW_WRAPPERS\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ +};\ +\ class MCheckIsObj : public MUnaryInstruction, public BoxPolicy<0>::Data {\ uint8_t checkKind_;\ explicit MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction(classOpcode, value), checkKind_(checkKind) {\ @@ -3644,6 +3879,7 @@ class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy::Data NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3723,7 +3959,6 @@ class MToHashableValue : public MUnaryInstruction, public BoxPolicy<0>::Data {\ NAMED_OPERANDS((0, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ - bool possiblyCalls() const override { return true; }\ };\ \ class MHashNonGCThing : public MUnaryInstruction, public BoxPolicy<0>::Data {\ @@ -3779,219 +4014,311 @@ class MHashBigInt : public MUnaryInstruction, public BigIntPolicy<0>::Data {\ };\ \ class MHashObject : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashObject(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashObject)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MHashValue : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MHashValue(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode, set, input) {\ + explicit MHashValue(MDefinition* setObject, MDefinition* input) : MBinaryInstruction(classOpcode, setObject, input) {\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(HashValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, input))\ + NAMED_OPERANDS((0, setObject), (1, input))\ AliasSet getAliasSet() const override { return AliasSet::None(); }\ };\ \ class MSetObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasNonBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasBigInt(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasBigInt(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MSetObjectHasValue(MDefinition* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, set, value, hash) {\ + explicit MSetObjectHasValue(MDefinition* setObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, setObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value), (2, hash))\ + NAMED_OPERANDS((0, setObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MSetObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition* value) : MBinaryInstruction(classOpcode, set, value) {\ + explicit MSetObjectHasValueVMCall(MDefinition* setObject, MDefinition* value) : MBinaryInstruction(classOpcode, setObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(SetObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set), (1, value))\ + NAMED_OPERANDS((0, setObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MSetObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectDelete(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MSetObjectAdd : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MSetObjectAdd(MDefinition* setObject, MDefinition* key) : MBinaryInstruction(classOpcode, setObject, key) {\ + }\ + public:\ + INSTRUCTION_HEADER(SetObjectAdd)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, setObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MSetObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode, set) {\ + explicit MSetObjectSize(MDefinition* setObject) : MUnaryInstruction(classOpcode, setObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(SetObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, set))\ + NAMED_OPERANDS((0, setObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectHasValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectHasValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectHasValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectHasValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Boolean);\ }\ public:\ INSTRUCTION_HEADER(MapObjectHasValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ class MMapObjectGetNonBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetNonBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetNonBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetBigInt : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetBigInt(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetBigInt(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetBigInt)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValue : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, UnboxedInt32Policy<2>>::Data {\ - explicit MMapObjectGetValue(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, map, value, hash) {\ + explicit MMapObjectGetValue(MDefinition* mapObject, MDefinition* value, MDefinition* hash) : MTernaryInstruction(classOpcode, mapObject, value, hash) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValue)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value), (2, hash))\ + NAMED_OPERANDS((0, mapObject), (1, value), (2, hash))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ class MMapObjectGetValueVMCall : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ - explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition* value) : MBinaryInstruction(classOpcode, map, value) {\ + explicit MMapObjectGetValueVMCall(MDefinition* mapObject, MDefinition* value) : MBinaryInstruction(classOpcode, mapObject, value) {\ setMovable();\ setResultType(MIRType::Value);\ }\ public:\ INSTRUCTION_HEADER(MapObjectGetValueVMCall)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map), (1, value))\ + NAMED_OPERANDS((0, mapObject), (1, value))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ bool possiblyCalls() const override { return true; }\ };\ \ +class MMapObjectDelete : public MBinaryInstruction, public MixPolicy, BoxPolicy<1>>::Data {\ + explicit MMapObjectDelete(MDefinition* mapObject, MDefinition* key) : MBinaryInstruction(classOpcode, mapObject, key) {\ + setResultType(MIRType::Boolean);\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectDelete)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ +class MMapObjectSet : public MTernaryInstruction, public MixPolicy, BoxPolicy<1>, BoxPolicy<2>>::Data {\ + explicit MMapObjectSet(MDefinition* mapObject, MDefinition* key, MDefinition* value) : MTernaryInstruction(classOpcode, mapObject, key, value) {\ + }\ + public:\ + INSTRUCTION_HEADER(MapObjectSet)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, mapObject), (1, key), (2, value))\ + bool possiblyCalls() const override { return true; }\ +};\ +\ class MMapObjectSize : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ - explicit MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode, map) {\ + explicit MMapObjectSize(MDefinition* mapObject) : MUnaryInstruction(classOpcode, mapObject) {\ setMovable();\ setResultType(MIRType::Int32);\ }\ public:\ INSTRUCTION_HEADER(MapObjectSize)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, map))\ + NAMED_OPERANDS((0, mapObject))\ AliasSet getAliasSet() const override;\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MDateFillLocalTimeSlots : public MUnaryInstruction, public ObjectPolicy<0>::Data {\ + explicit MDateFillLocalTimeSlots(MDefinition* date) : MUnaryInstruction(classOpcode, date) {\ + }\ + public:\ + INSTRUCTION_HEADER(DateFillLocalTimeSlots)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, date))\ + AliasSet getAliasSet() const override;\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateHoursFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateHoursFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateHoursFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateMinutesFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateMinutesFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateMinutesFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ +class MDateSecondsFromSecondsIntoYear : public MUnaryInstruction, public BoxPolicy<0>::Data {\ + explicit MDateSecondsFromSecondsIntoYear(MDefinition* secondsIntoYear) : MUnaryInstruction(classOpcode, secondsIntoYear) {\ + setMovable();\ + setResultType(MIRType::Value);\ + }\ + public:\ + INSTRUCTION_HEADER(DateSecondsFromSecondsIntoYear)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, secondsIntoYear))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmBoundsCheckRange32 : public MTernaryInstruction, public NoTypePolicy::Data {\ - wasm::BytecodeOffset bytecodeOffset_;\ - explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_(bytecodeOffset) {\ + wasm::TrapSiteDesc trapSiteDesc_;\ + explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition* length, MDefinition* limit, wasm::TrapSiteDesc trapSiteDesc) : MTernaryInstruction(classOpcode, index, length, limit), trapSiteDesc_(trapSiteDesc) {\ setResultType(MIRType::Int32);\ }\ public:\ - wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }\ + wasm::TrapSiteDesc trapSiteDesc() const { return trapSiteDesc_; }\ INSTRUCTION_HEADER(WasmBoundsCheckRange32)\ TRIVIAL_NEW_WRAPPERS\ NAMED_OPERANDS((0, index), (1, length), (2, limit))\ @@ -4026,6 +4353,19 @@ class MWasmWrapU32Index : public MUnaryInstruction, public NoTypePolicy::Data {\ bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ };\ \ +class MWasmClampTable64Address : public MUnaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmClampTable64Address(MDefinition* address) : MUnaryInstruction(classOpcode, address) {\ + setMovable();\ + setResultType(MIRType::Int32);\ + }\ + public:\ + INSTRUCTION_HEADER(WasmClampTable64Address)\ + TRIVIAL_NEW_WRAPPERS\ + NAMED_OPERANDS((0, address))\ + AliasSet getAliasSet() const override { return AliasSet::None(); }\ + bool congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual(ins); }\ +};\ +\ class MWasmFence : public MNullaryInstruction {\ explicit MWasmFence() : MNullaryInstruction(classOpcode) {\ setGuard();\ @@ -4039,6 +4379,7 @@ class MWasmFence : public MNullaryInstruction {\ \ class MWasmStackSwitchToMain : public MTernaryInstruction, public NoTypePolicy::Data {\ explicit MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn, MDefinition* data) : MTernaryInstruction(classOpcode, suspender, fn, data) {\ + setResultType(MIRType::WasmAnyRef);\ }\ public:\ INSTRUCTION_HEADER(WasmStackSwitchToMain)\ @@ -4055,13 +4396,13 @@ class MWasmStackSwitchToSuspendable : public MTernaryInstruction, public NoTypeP NAMED_OPERANDS((0, suspender), (1, fn), (2, data))\ };\ \ -class MWasmStackContinueOnSuspendable : public MUnaryInstruction, public NoTypePolicy::Data {\ - explicit MWasmStackContinueOnSuspendable(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender) {\ +class MWasmStackContinueOnSuspendable : public MBinaryInstruction, public NoTypePolicy::Data {\ + explicit MWasmStackContinueOnSuspendable(MDefinition* suspender, MDefinition* result) : MBinaryInstruction(classOpcode, suspender, result) {\ }\ public:\ INSTRUCTION_HEADER(WasmStackContinueOnSuspendable)\ TRIVIAL_NEW_WRAPPERS\ - NAMED_OPERANDS((0, suspender))\ + NAMED_OPERANDS((0, suspender), (1, result))\ };\ \ class MWasmShiftSimd128 : public MBinaryInstruction, public NoTypePolicy::Data {\ @@ -4117,6 +4458,7 @@ class MWasmUnarySimd128 : public MUnaryInstruction, public NoTypePolicy::Data {\ static_assert(!std::is_base_of_v, "Ensure that BuiltinObjectKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that FunctionFlags::FunctionKind is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that JSOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that MemoryBarrierRequirement is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that PropertyKey is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that RealmFuses::FuseIndex is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ @@ -4131,10 +4473,10 @@ static_assert(!std::is_base_of_v, "Ensure that uint16_t is a static_assert(!std::is_base_of_v, "Ensure that uint32_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that uint8_t is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that unsigned is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::BytecodeOffset is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::FieldWideningOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ static_assert(!std::is_base_of_v, "Ensure that wasm::SimdOp is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ -static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py."); +static_assert(!std::is_base_of_v, "Ensure that wasm::Trap is added to the gc_pointer_types list in GenerateMIRFiles.py.");\ +static_assert(!std::is_base_of_v, "Ensure that wasm::TrapSiteDesc is added to the gc_pointer_types list in GenerateMIRFiles.py."); diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/js-confdefs.h b/src/third_party/mozjs/platform/x86_64/windows/include/js-confdefs.h index 0ecd699d685..b80bd9875a7 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/js-confdefs.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/js-confdefs.h @@ -9,20 +9,24 @@ // Expands to all the defines from configure. #define CROSS_COMPILE #define ENABLE_SHARED_MEMORY 1 -#define ENABLE_WASM_GC 1 #define ENABLE_WASM_JS_STRING_BUILTINS 1 +#define ENABLE_WASM_MEMORY64 1 #define ENABLE_WASM_MULTI_MEMORY 1 -#define ENABLE_WASM_TAIL_CALLS 1 +#define FMT_API MFBT_API +#define FMT_ENFORCE_COMPILE_STRING 1 +#define FMT_USE_EXCEPTIONS 0 +#define FMT_USE_LOCALE 0 +#define FMT_USE_WRITE_CONSOLE 1 #define HAVE_64BIT_BUILD 1 #define HAVE_CPUID_H 1 -#define HAVE_FORCEINLINE 1 #define HAVE_INTTYPES_H 1 +#define HAVE_IO_H 1 #define HAVE_LOCALECONV 1 #define HAVE_MALLOC_H 1 +#define HAVE_SEH_EXCEPTIONS 1 #define HAVE_STDINT_H 1 #define HAVE_SYS_TYPES_H 1 #define HAVE__GETC_NOLOCK 1 -#define HAVE__MSIZE 1 #define JS_64BIT 1 #define JS_CODEGEN_NONE 1 #define JS_DEFAULT_JITREPORT_GRANULARITY 3 @@ -31,12 +35,10 @@ #define JS_WITHOUT_NSPR 1 #define MALLOC_H #define MALLOC_USABLE_SIZE_CONST_PTR -#define MOZILLA_UAVERSION "128.0" -#define MOZILLA_VERSION "128.12.0" -#define MOZILLA_VERSION_U 128.12.0 -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 -#define MOZ_AARCH64_JSCVT 0 +#define MOZILLA_UAVERSION "140.0" +#define MOZILLA_VERSION "140.3.0" +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 #define MOZ_BUILD_APP js #define MOZ_DLL_PREFIX "" #define MOZ_DLL_SUFFIX ".dll" @@ -46,6 +48,7 @@ #define NO_NSPR_10_SUPPORT 1 #define RELEASE_OR_BETA 1 #define STDC_HEADERS 1 +#define TARGET_XPCOM_ABI "x86_64-msvc" #define U_STATIC_IMPLEMENTATION 1 #define WASM_HAS_HEAPREG 1 #define WIN32_LEAN_AND_MEAN 1 diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/js-config.h b/src/third_party/mozjs/platform/x86_64/windows/include/js-config.h index e6a4e862c32..40e58b01272 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/js-config.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/js-config.h @@ -41,9 +41,6 @@ /* Define to 1 if SpiderMonkey should include support for the Intl API. */ /* #undef JS_HAS_INTL_API */ -/* Define to 1 if SpiderMonkey should include support for the Temporal API. */ -/* #undef JS_HAS_TEMPORAL_API */ - /* Define to 1 if SpiderMonkey should include a breakpoint function for * artificial OOMs. */ /* #undef JS_OOM_BREAKPOINT */ @@ -61,17 +58,20 @@ /* Define to 1 if SpiderMonkey is in PUNBOX64 mode. */ #define JS_PUNBOX64 1 -/* Define to 1 if SpiderMonkey should support SmooshMonkey parser. */ -/* #undef JS_ENABLE_SMOOSH */ - /* Experimental WASM features */ /* #undef ENABLE_WASM_EXCEPTIONS */ /* #undef ENABLE_WASM_FUNCTION_REFERENCES */ -#define ENABLE_WASM_GC 1 +/* #undef ENABLE_WASM_GC */ /* #undef ENABLE_WASM_SIMD */ /* MOZILLA JSAPI version number components */ -#define MOZJS_MAJOR_VERSION 128 -#define MOZJS_MINOR_VERSION 12 +#define MOZJS_MAJOR_VERSION 140 +#define MOZJS_MINOR_VERSION 3 + +/* MONGODB MODIFICATION: Define based on platform */ +#define XP_WIN 1 +/* #undef XP_UNIX */ +/* #undef XP_DARWIN */ + #endif /* js_config_h */ diff --git a/src/third_party/mozjs/platform/x86_64/windows/include/selfhosted.out.h b/src/third_party/mozjs/platform/x86_64/windows/include/selfhosted.out.h index 61dcac32173..f92431e839c 100644 --- a/src/third_party/mozjs/platform/x86_64/windows/include/selfhosted.out.h +++ b/src/third_party/mozjs/platform/x86_64/windows/include/selfhosted.out.h @@ -4,16 +4,16 @@ namespace js { namespace selfhosted { - static const unsigned char data[] = { 120, 156, 237, 125, 253, 119, 27, 55, 174, 232, 239, 254, 43, 38, 58, 189, 173, 188, 150, 189, 150, 147, 126, 108, 236, 164, 235, 186, 73, 215, 111, 147, 56, 199, 78, 119, 207, 185, 126, 57, 185, 19, 105, 236, 204, 90, 214, 168, 51, 82, 28, 183, 205, 251, 219, 31, 65, 130, 36, 192, 143, 153, 145, 44, 39, 182, 111, 114, 78, 235, 209, 12, 9, 130, 32, 0, 130, 32, 8, 158, 204, 198, 131, 105, 94, 140, 147, 113, 118, 241, 230, 48, 27, 20, 229, 176, 187, 154, 252, 177, 146, 36, 101, 54, 157, 149, 227, 164, 154, 14, 223, 28, 188, 253, 79, 54, 152, 190, 25, 148, 89, 58, 205, 186, 227, 217, 104, 180, 186, 189, 242, 113, 229, 68, 215, 125, 85, 252, 84, 20, 163, 44, 29, 119, 223, 179, 186, 247, 238, 189, 119, 202, 189, 152, 157, 191, 205, 74, 167, 216, 26, 47, 117, 148, 158, 103, 255, 74, 71, 179, 236, 191, 179, 178, 232, 126, 232, 37, 151, 172, 244, 135, 228, 209, 163, 71, 201, 101, 242, 231, 159, 73, 247, 67, 114, 79, 60, 127, 72, 190, 254, 90, 188, 128, 199, 75, 142, 216, 47, 217, 244, 121, 54, 125, 87, 12, 187, 255, 234, 37, 47, 21, 152, 237, 109, 241, 191, 247, 105, 153, 64, 169, 228, 81, 242, 175, 227, 151, 175, 225, 85, 126, 146, 116, 247, 171, 23, 162, 115, 7, 229, 175, 227, 97, 118, 146, 143, 179, 97, 23, 10, 173, 170, 138, 6, 131, 153, 254, 10, 213, 62, 98, 213, 123, 251, 213, 94, 58, 26, 165, 111, 71, 25, 175, 244, 234, 93, 89, 92, 188, 186, 156, 100, 79, 202, 178, 40, 187, 253, 173, 94, 50, 21, 191, 138, 19, 137, 192, 170, 134, 129, 176, 225, 29, 235, 194, 126, 245, 178, 44, 38, 89, 57, 189, 252, 103, 118, 217, 77, 203, 211, 217, 121, 54, 158, 42, 224, 208, 11, 128, 37, 122, 129, 32, 245, 247, 109, 11, 81, 21, 16, 180, 233, 84, 211, 50, 31, 159, 118, 128, 114, 228, 229, 229, 249, 219, 98, 212, 225, 35, 48, 201, 6, 121, 86, 237, 21, 99, 81, 101, 54, 152, 10, 180, 139, 183, 255, 233, 37, 162, 219, 233, 108, 52, 37, 239, 29, 146, 194, 43, 129, 140, 40, 188, 49, 176, 133, 52, 117, 213, 87, 209, 168, 33, 160, 67, 88, 31, 190, 67, 97, 197, 136, 18, 80, 140, 190, 223, 126, 215, 75, 58, 133, 44, 247, 77, 149, 124, 67, 208, 248, 38, 153, 32, 37, 59, 134, 234, 128, 116, 37, 48, 134, 239, 199, 130, 91, 126, 154, 229, 163, 105, 62, 62, 146, 68, 233, 118, 42, 69, 136, 206, 106, 13, 135, 84, 46, 123, 212, 247, 98, 159, 145, 213, 86, 134, 111, 149, 228, 97, 75, 87, 248, 119, 152, 77, 138, 114, 250, 107, 149, 158, 102, 123, 197, 108, 60, 21, 210, 227, 55, 208, 75, 238, 203, 46, 169, 102, 172, 236, 234, 134, 29, 26, 201, 50, 253, 7, 61, 249, 183, 243, 247, 191, 99, 55, 13, 125, 18, 193, 73, 134, 132, 132, 130, 29, 81, 193, 19, 48, 11, 118, 99, 99, 67, 240, 95, 165, 112, 159, 150, 151, 216, 135, 129, 16, 139, 167, 88, 161, 11, 234, 68, 255, 120, 147, 78, 38, 163, 203, 158, 131, 93, 207, 178, 71, 47, 145, 240, 100, 47, 4, 152, 233, 224, 93, 210, 205, 28, 106, 103, 186, 143, 219, 46, 98, 187, 167, 167, 101, 118, 42, 52, 214, 18, 176, 227, 176, 150, 134, 226, 62, 140, 231, 56, 29, 45, 1, 67, 6, 106, 57, 8, 2, 167, 155, 134, 69, 21, 242, 105, 175, 152, 92, 254, 156, 78, 83, 212, 77, 130, 121, 186, 83, 209, 78, 54, 237, 37, 85, 49, 43, 7, 89, 47, 201, 62, 12, 70, 179, 97, 54, 220, 159, 102, 231, 21, 209, 19, 219, 53, 162, 36, 171, 58, 242, 68, 69, 245, 164, 44, 206, 133, 180, 190, 42, 80, 17, 96, 5, 173, 126, 206, 178, 75, 16, 102, 31, 185, 131, 82, 16, 251, 224, 98, 44, 84, 168, 69, 20, 128, 185, 104, 106, 220, 20, 36, 33, 140, 114, 178, 11, 226, 115, 34, 148, 89, 23, 90, 205, 5, 254, 98, 82, 74, 54, 183, 241, 113, 71, 34, 178, 49, 202, 198, 167, 211, 119, 248, 114, 109, 77, 67, 65, 68, 69, 5, 40, 117, 44, 191, 190, 222, 54, 58, 0, 197, 254, 222, 187, 180, 18, 8, 3, 34, 30, 41, 191, 254, 26, 11, 121, 156, 129, 19, 181, 150, 227, 253, 234, 201, 88, 76, 7, 37, 76, 74, 186, 191, 2, 224, 170, 172, 110, 85, 204, 207, 146, 252, 132, 98, 151, 134, 70, 178, 121, 168, 120, 44, 158, 94, 19, 29, 243, 113, 165, 150, 27, 126, 29, 159, 8, 69, 154, 149, 98, 80, 57, 95, 16, 70, 184, 57, 60, 128, 22, 205, 231, 30, 250, 69, 135, 115, 137, 35, 89, 204, 96, 130, 97, 246, 150, 249, 150, 143, 199, 230, 155, 249, 218, 57, 41, 138, 142, 164, 11, 83, 29, 187, 101, 153, 94, 62, 121, 159, 149, 151, 178, 87, 111, 211, 193, 217, 201, 56, 177, 86, 203, 1, 29, 193, 233, 187, 188, 50, 227, 39, 72, 39, 191, 61, 147, 36, 236, 30, 32, 45, 205, 240, 236, 162, 133, 83, 97, 129, 85, 57, 86, 155, 49, 107, 224, 219, 94, 178, 41, 12, 2, 137, 207, 134, 32, 228, 180, 0, 211, 103, 35, 3, 212, 172, 25, 224, 26, 112, 22, 231, 58, 51, 238, 103, 97, 46, 159, 79, 242, 81, 38, 112, 234, 138, 86, 104, 45, 202, 177, 175, 68, 135, 124, 180, 31, 39, 253, 228, 71, 57, 79, 225, 167, 110, 127, 53, 121, 200, 141, 75, 195, 104, 103, 138, 201, 206, 4, 131, 9, 122, 136, 7, 203, 84, 146, 103, 197, 224, 36, 7, 150, 15, 100, 127, 0, 29, 97, 35, 76, 5, 104, 195, 85, 22, 69, 49, 109, 244, 146, 131, 227, 179, 215, 130, 53, 196, 3, 97, 34, 59, 242, 233, 168, 202, 182, 241, 237, 71, 194, 48, 214, 182, 44, 103, 25, 140, 251, 145, 152, 202, 170, 253, 241, 40, 31, 3, 249, 158, 1, 203, 153, 38, 45, 43, 8, 162, 112, 6, 57, 42, 206, 179, 155, 201, 31, 149, 192, 236, 110, 179, 199, 149, 185, 67, 141, 125, 13, 115, 32, 251, 180, 224, 14, 224, 3, 143, 57, 158, 22, 229, 147, 116, 240, 238, 102, 242, 199, 137, 66, 238, 238, 178, 200, 124, 236, 177, 29, 26, 127, 130, 71, 11, 30, 192, 225, 246, 216, 224, 121, 58, 185, 153, 44, 112, 158, 78, 110, 254, 240, 67, 237, 93, 89, 27, 196, 12, 151, 245, 202, 141, 115, 208, 3, 66, 173, 94, 133, 73, 160, 138, 32, 195, 36, 27, 74, 127, 13, 172, 163, 23, 96, 155, 160, 217, 178, 43, 139, 16, 224, 97, 30, 219, 109, 197, 91, 130, 135, 124, 245, 34, 237, 211, 155, 201, 90, 202, 118, 190, 237, 220, 181, 25, 224, 173, 94, 50, 45, 230, 231, 177, 51, 205, 94, 192, 59, 154, 105, 90, 78, 98, 170, 110, 96, 26, 11, 51, 221, 180, 88, 91, 211, 149, 12, 127, 6, 167, 183, 118, 172, 167, 216, 204, 227, 190, 195, 108, 56, 27, 220, 80, 219, 167, 148, 184, 125, 42, 238, 83, 42, 7, 127, 164, 131, 193, 236, 124, 54, 74, 137, 211, 48, 200, 153, 186, 93, 82, 94, 128, 225, 204, 170, 60, 30, 153, 176, 65, 8, 119, 73, 10, 82, 154, 36, 201, 20, 112, 247, 104, 179, 197, 252, 105, 18, 209, 151, 101, 86, 9, 208, 162, 33, 98, 24, 15, 11, 102, 85, 185, 220, 155, 208, 106, 212, 98, 74, 146, 183, 66, 80, 206, 28, 14, 75, 46, 222, 9, 138, 37, 221, 181, 53, 20, 143, 85, 187, 58, 188, 167, 33, 205, 135, 58, 39, 145, 16, 160, 181, 181, 215, 108, 29, 219, 94, 20, 57, 168, 144, 236, 153, 206, 17, 33, 52, 239, 172, 75, 202, 188, 34, 16, 237, 75, 57, 65, 88, 250, 145, 15, 248, 20, 158, 10, 24, 239, 184, 75, 81, 37, 111, 135, 249, 233, 187, 233, 23, 161, 83, 66, 7, 253, 90, 79, 250, 95, 68, 143, 139, 222, 250, 250, 89, 242, 248, 17, 78, 94, 203, 149, 188, 245, 117, 95, 242, 30, 171, 201, 112, 125, 253, 142, 10, 222, 211, 124, 60, 236, 78, 4, 119, 231, 3, 97, 22, 220, 32, 129, 19, 4, 25, 198, 197, 205, 96, 60, 143, 180, 145, 74, 159, 110, 241, 22, 177, 143, 98, 214, 145, 193, 177, 206, 56, 194, 129, 85, 95, 151, 177, 182, 19, 180, 14, 24, 224, 227, 225, 62, 120, 64, 191, 176, 199, 53, 175, 237, 155, 249, 32, 232, 233, 209, 92, 16, 100, 128, 245, 126, 235, 145, 151, 131, 236, 13, 63, 56, 232, 255, 157, 139, 145, 29, 219, 29, 2, 241, 32, 254, 100, 227, 97, 226, 237, 17, 47, 206, 19, 240, 189, 204, 132, 122, 202, 223, 103, 175, 100, 75, 178, 40, 236, 151, 157, 138, 5, 160, 106, 220, 148, 132, 229, 201, 138, 234, 61, 171, 178, 147, 108, 34, 89, 126, 148, 33, 17, 207, 211, 233, 187, 55, 231, 233, 7, 57, 173, 173, 57, 165, 97, 237, 131, 165, 31, 146, 210, 162, 171, 110, 57, 109, 226, 81, 36, 143, 128, 12, 12, 71, 73, 24, 83, 78, 109, 128, 48, 36, 85, 149, 150, 56, 30, 41, 50, 55, 161, 136, 197, 66, 24, 62, 145, 35, 36, 199, 137, 238, 230, 139, 102, 161, 165, 135, 4, 243, 76, 10, 62, 226, 45, 184, 100, 228, 32, 14, 144, 90, 162, 45, 138, 54, 35, 45, 11, 81, 148, 7, 176, 103, 46, 144, 101, 165, 21, 38, 235, 184, 133, 162, 12, 161, 105, 97, 52, 136, 36, 240, 14, 176, 194, 215, 95, 195, 255, 119, 20, 201, 215, 20, 48, 45, 32, 184, 15, 69, 63, 105, 123, 42, 81, 171, 92, 241, 63, 239, 3, 90, 25, 234, 237, 99, 106, 12, 153, 150, 93, 51, 230, 224, 120, 90, 188, 150, 202, 29, 62, 155, 245, 47, 51, 176, 224, 223, 48, 27, 101, 66, 135, 202, 226, 220, 184, 81, 200, 174, 175, 235, 183, 211, 194, 62, 75, 76, 244, 207, 143, 174, 225, 246, 25, 209, 93, 91, 179, 232, 218, 103, 31, 93, 171, 147, 14, 66, 230, 199, 104, 36, 84, 164, 156, 228, 42, 148, 171, 205, 107, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 89, 153, 202, 182, 217, 156, 6, 179, 149, 232, 196, 123, 109, 157, 68, 89, 64, 249, 162, 36, 35, 236, 79, 179, 50, 53, 129, 76, 103, 96, 144, 152, 65, 207, 229, 183, 108, 168, 134, 157, 114, 128, 40, 108, 104, 144, 35, 4, 241, 253, 69, 118, 193, 129, 202, 66, 191, 142, 171, 244, 36, 19, 83, 226, 161, 88, 44, 148, 239, 179, 225, 209, 168, 152, 118, 117, 53, 105, 102, 240, 150, 90, 213, 234, 107, 71, 90, 83, 193, 45, 236, 214, 182, 165, 134, 254, 232, 203, 133, 198, 252, 69, 246, 97, 218, 181, 148, 16, 253, 5, 189, 37, 248, 94, 235, 66, 27, 116, 5, 180, 144, 65, 119, 170, 208, 47, 179, 180, 28, 190, 42, 60, 226, 174, 174, 70, 54, 207, 121, 180, 2, 242, 2, 88, 84, 12, 132, 10, 215, 219, 63, 249, 119, 41, 93, 191, 122, 13, 2, 40, 233, 231, 142, 215, 131, 142, 252, 194, 172, 170, 84, 160, 168, 40, 246, 139, 67, 49, 201, 0, 155, 68, 48, 170, 217, 8, 6, 253, 15, 197, 80, 15, 105, 232, 204, 176, 24, 139, 23, 114, 205, 9, 27, 220, 138, 36, 105, 160, 131, 0, 99, 3, 74, 179, 181, 38, 118, 92, 125, 166, 216, 233, 184, 129, 26, 12, 251, 148, 241, 206, 255, 153, 75, 185, 53, 229, 133, 144, 222, 223, 122, 42, 180, 164, 95, 113, 139, 170, 44, 141, 243, 126, 245, 178, 168, 170, 252, 237, 232, 18, 9, 11, 166, 234, 80, 18, 178, 155, 26, 155, 79, 233, 184, 104, 73, 84, 125, 41, 89, 26, 7, 22, 245, 240, 58, 10, 226, 31, 105, 245, 115, 54, 77, 7, 239, 178, 225, 79, 179, 147, 19, 161, 102, 82, 230, 148, 117, 173, 243, 239, 127, 8, 57, 97, 233, 84, 226, 232, 229, 148, 234, 101, 109, 186, 43, 114, 63, 150, 62, 15, 221, 90, 88, 156, 20, 115, 144, 136, 144, 57, 7, 183, 6, 170, 16, 100, 133, 199, 26, 142, 173, 196, 204, 140, 173, 32, 98, 223, 225, 167, 247, 184, 170, 75, 89, 164, 72, 176, 93, 15, 214, 22, 93, 31, 78, 210, 28, 212, 150, 2, 211, 51, 240, 94, 111, 135, 90, 131, 194, 53, 45, 109, 43, 253, 194, 170, 72, 112, 68, 239, 232, 26, 45, 22, 8, 84, 140, 233, 26, 225, 43, 249, 85, 46, 64, 43, 30, 143, 18, 82, 234, 82, 61, 72, 178, 202, 38, 247, 210, 113, 49, 22, 171, 155, 209, 139, 244, 60, 235, 82, 80, 98, 165, 39, 145, 174, 58, 222, 130, 228, 201, 120, 90, 230, 237, 27, 219, 90, 245, 181, 170, 12, 45, 106, 89, 127, 51, 80, 31, 4, 122, 183, 186, 28, 15, 186, 41, 252, 95, 134, 123, 201, 77, 176, 147, 49, 53, 87, 122, 82, 29, 138, 133, 97, 216, 134, 217, 35, 42, 92, 175, 23, 36, 212, 189, 81, 81, 205, 74, 201, 81, 240, 51, 129, 165, 241, 99, 194, 38, 176, 219, 150, 143, 1, 170, 106, 242, 30, 181, 16, 172, 204, 235, 98, 194, 56, 166, 107, 98, 89, 135, 8, 115, 96, 69, 252, 170, 56, 146, 193, 90, 186, 172, 235, 231, 155, 85, 2, 238, 46, 118, 93, 79, 182, 150, 20, 129, 0, 221, 148, 22, 198, 48, 93, 133, 101, 8, 150, 163, 182, 147, 112, 131, 78, 151, 29, 244, 142, 106, 11, 71, 90, 190, 23, 10, 122, 246, 221, 10, 126, 205, 58, 229, 248, 125, 159, 80, 212, 82, 105, 213, 213, 152, 220, 240, 14, 117, 162, 150, 196, 185, 75, 93, 210, 203, 163, 122, 242, 134, 91, 115, 72, 102, 173, 254, 48, 216, 8, 237, 34, 212, 59, 138, 17, 111, 126, 242, 89, 196, 62, 18, 70, 104, 51, 194, 96, 38, 181, 238, 136, 222, 68, 229, 129, 225, 123, 171, 201, 143, 6, 143, 110, 32, 8, 124, 175, 151, 116, 187, 253, 100, 103, 39, 233, 127, 39, 236, 50, 161, 143, 86, 123, 54, 86, 219, 117, 247, 136, 210, 123, 171, 224, 64, 58, 54, 131, 200, 54, 223, 224, 31, 216, 220, 233, 69, 154, 79, 149, 83, 105, 44, 52, 178, 242, 43, 194, 185, 130, 209, 168, 184, 64, 160, 208, 33, 240, 220, 88, 167, 51, 209, 86, 124, 228, 25, 141, 122, 113, 174, 192, 47, 108, 192, 252, 224, 2, 131, 209, 54, 227, 1, 212, 71, 124, 176, 155, 195, 18, 164, 14, 50, 170, 180, 103, 161, 11, 59, 154, 240, 128, 11, 74, 81, 136, 188, 243, 217, 101, 174, 128, 6, 248, 7, 195, 112, 6, 118, 129, 43, 17, 187, 104, 205, 192, 119, 253, 205, 110, 63, 219, 146, 210, 226, 149, 38, 90, 126, 150, 209, 5, 12, 225, 235, 109, 83, 210, 53, 153, 116, 69, 106, 58, 213, 241, 229, 146, 248, 81, 173, 246, 86, 113, 61, 168, 108, 81, 187, 229, 233, 176, 39, 58, 34, 244, 182, 104, 56, 60, 64, 141, 141, 233, 15, 9, 22, 240, 153, 9, 185, 198, 140, 193, 143, 88, 187, 13, 171, 24, 183, 249, 170, 169, 254, 144, 121, 203, 231, 228, 0, 103, 252, 213, 152, 146, 177, 71, 67, 158, 143, 253, 71, 98, 112, 185, 83, 124, 55, 98, 92, 72, 27, 113, 9, 38, 69, 163, 165, 208, 218, 78, 104, 242, 155, 247, 17, 89, 223, 103, 142, 8, 107, 148, 164, 78, 33, 179, 76, 222, 110, 58, 195, 73, 196, 141, 66, 103, 208, 216, 25, 29, 111, 198, 9, 204, 54, 129, 153, 198, 221, 12, 200, 233, 92, 243, 241, 211, 8, 28, 155, 0, 28, 249, 50, 123, 9, 205, 106, 31, 121, 40, 214, 249, 54, 162, 86, 35, 100, 175, 28, 77, 76, 36, 204, 211, 255, 17, 33, 131, 8, 158, 112, 228, 88, 72, 163, 50, 153, 90, 169, 209, 165, 185, 81, 163, 109, 149, 104, 108, 68, 87, 20, 21, 150, 170, 70, 87, 20, 141, 124, 85, 58, 247, 38, 162, 146, 156, 51, 194, 39, 117, 195, 217, 52, 152, 158, 174, 228, 154, 178, 181, 158, 132, 161, 241, 85, 34, 141, 197, 226, 234, 78, 152, 118, 242, 184, 35, 241, 110, 201, 49, 138, 58, 120, 241, 56, 168, 44, 180, 241, 159, 34, 31, 19, 245, 16, 62, 217, 25, 242, 107, 145, 99, 27, 83, 196, 160, 167, 96, 186, 39, 61, 67, 100, 3, 240, 182, 184, 223, 165, 103, 133, 168, 149, 97, 199, 70, 242, 135, 144, 196, 98, 2, 101, 232, 25, 43, 218, 91, 170, 183, 67, 76, 235, 238, 159, 122, 46, 29, 125, 210, 163, 67, 37, 228, 36, 47, 171, 233, 147, 81, 118, 174, 226, 43, 36, 164, 227, 205, 215, 186, 161, 67, 235, 120, 242, 78, 212, 146, 154, 134, 148, 135, 2, 6, 54, 64, 151, 43, 135, 18, 91, 236, 47, 242, 79, 144, 110, 4, 230, 198, 148, 145, 169, 199, 80, 197, 163, 79, 180, 39, 85, 54, 73, 245, 164, 209, 233, 117, 60, 145, 233, 199, 69, 6, 20, 146, 75, 3, 45, 55, 135, 201, 218, 35, 11, 219, 174, 14, 3, 147, 13, 1, 67, 244, 168, 4, 224, 118, 62, 220, 125, 2, 192, 235, 61, 5, 174, 205, 108, 171, 16, 9, 63, 30, 50, 134, 251, 138, 198, 116, 114, 159, 134, 98, 168, 168, 163, 5, 235, 244, 146, 14, 236, 155, 30, 171, 121, 119, 3, 143, 152, 190, 246, 253, 46, 60, 110, 180, 40, 243, 83, 112, 248, 203, 79, 82, 181, 1, 111, 90, 206, 222, 38, 108, 42, 53, 129, 224, 212, 117, 195, 170, 70, 61, 108, 82, 199, 152, 32, 185, 82, 137, 12, 184, 43, 198, 76, 115, 82, 15, 162, 54, 128, 88, 237, 208, 249, 102, 111, 226, 22, 150, 143, 120, 87, 22, 85, 117, 152, 165, 163, 115, 220, 247, 166, 69, 218, 226, 160, 192, 163, 218, 178, 213, 0, 173, 189, 198, 115, 203, 170, 250, 158, 164, 149, 45, 75, 17, 81, 46, 245, 142, 191, 249, 31, 68, 136, 46, 133, 247, 2, 203, 254, 230, 186, 186, 75, 123, 181, 199, 193, 107, 169, 113, 207, 165, 118, 204, 162, 124, 32, 56, 145, 12, 86, 224, 16, 120, 139, 105, 248, 254, 42, 221, 87, 105, 158, 143, 21, 182, 158, 9, 62, 74, 167, 112, 158, 65, 206, 109, 165, 174, 213, 42, 234, 69, 157, 114, 124, 214, 16, 251, 226, 216, 217, 164, 145, 121, 2, 85, 220, 154, 174, 229, 125, 125, 193, 226, 64, 32, 65, 208, 253, 241, 84, 109, 44, 129, 45, 112, 208, 179, 157, 151, 190, 249, 190, 139, 161, 176, 51, 232, 232, 4, 140, 1, 128, 219, 93, 18, 157, 161, 212, 48, 155, 76, 223, 189, 152, 157, 203, 233, 97, 37, 22, 119, 36, 196, 159, 146, 68, 104, 169, 160, 11, 136, 0, 179, 187, 175, 188, 34, 27, 130, 165, 16, 81, 55, 26, 39, 156, 7, 70, 20, 196, 72, 29, 241, 132, 167, 188, 205, 19, 192, 133, 31, 114, 231, 121, 5, 59, 5, 15, 206, 80, 173, 36, 122, 225, 182, 98, 135, 67, 129, 221, 199, 77, 49, 9, 131, 77, 195, 170, 9, 253, 93, 216, 176, 244, 197, 142, 197, 128, 125, 224, 49, 80, 180, 70, 62, 102, 135, 145, 245, 108, 158, 153, 153, 92, 125, 61, 38, 117, 152, 235, 211, 145, 15, 226, 119, 218, 182, 62, 29, 11, 173, 54, 94, 51, 68, 32, 253, 79, 251, 27, 200, 43, 132, 74, 95, 17, 44, 253, 215, 230, 133, 227, 20, 70, 102, 127, 87, 204, 70, 67, 28, 104, 30, 92, 171, 122, 42, 71, 145, 199, 125, 36, 94, 45, 61, 187, 34, 110, 94, 75, 146, 252, 180, 142, 235, 229, 195, 138, 142, 208, 225, 91, 238, 148, 146, 100, 97, 220, 18, 98, 83, 94, 178, 129, 126, 182, 245, 158, 87, 213, 163, 170, 34, 200, 122, 210, 15, 16, 214, 13, 112, 129, 126, 83, 92, 33, 212, 247, 67, 255, 132, 254, 171, 117, 80, 127, 251, 125, 63, 224, 139, 174, 61, 228, 77, 177, 78, 220, 241, 96, 157, 178, 17, 53, 225, 131, 189, 182, 164, 175, 77, 119, 167, 106, 71, 117, 153, 97, 51, 122, 56, 173, 6, 204, 49, 108, 16, 87, 167, 90, 205, 242, 10, 143, 201, 58, 5, 140, 117, 246, 213, 91, 78, 232, 176, 247, 181, 64, 185, 21, 29, 122, 189, 147, 108, 130, 255, 254, 204, 217, 47, 142, 229, 254, 209, 129, 39, 210, 240, 111, 177, 225, 185, 59, 245, 44, 224, 87, 197, 33, 156, 71, 175, 178, 97, 119, 25, 36, 221, 197, 112, 183, 197, 220, 0, 24, 214, 166, 130, 226, 206, 108, 224, 154, 254, 102, 67, 141, 73, 120, 87, 116, 21, 111, 106, 184, 171, 223, 240, 138, 93, 152, 97, 130, 8, 96, 141, 164, 101, 118, 130, 180, 151, 33, 172, 250, 149, 179, 209, 226, 248, 22, 109, 205, 136, 185, 243, 61, 155, 73, 23, 167, 177, 244, 145, 44, 76, 231, 0, 185, 208, 169, 118, 166, 98, 113, 153, 165, 11, 184, 236, 176, 232, 0, 29, 220, 115, 94, 57, 84, 245, 92, 17, 18, 183, 55, 85, 1, 225, 96, 216, 132, 165, 81, 56, 90, 255, 89, 90, 77, 111, 108, 72, 54, 32, 247, 105, 194, 178, 173, 63, 124, 9, 193, 217, 250, 172, 77, 232, 192, 199, 226, 1, 252, 254, 126, 196, 245, 135, 241, 195, 0, 4, 67, 249, 225, 195, 205, 14, 231, 55, 24, 222, 49, 6, 154, 135, 83, 174, 53, 208, 223, 16, 152, 49, 8, 108, 75, 233, 178, 50, 220, 240, 125, 58, 34, 14, 29, 18, 50, 116, 158, 253, 146, 141, 89, 144, 140, 40, 42, 6, 19, 92, 88, 29, 71, 91, 81, 168, 114, 140, 230, 7, 43, 207, 112, 133, 224, 234, 77, 141, 253, 161, 32, 103, 46, 148, 115, 208, 253, 197, 235, 152, 38, 150, 219, 69, 83, 122, 217, 125, 52, 197, 15, 37, 144, 249, 33, 171, 34, 10, 180, 10, 39, 10, 19, 17, 118, 36, 51, 19, 166, 170, 50, 76, 246, 84, 168, 165, 27, 129, 171, 247, 237, 72, 201, 13, 27, 194, 170, 237, 69, 104, 86, 69, 137, 146, 210, 27, 54, 65, 83, 196, 201, 74, 43, 174, 82, 221, 107, 2, 64, 227, 251, 191, 180, 110, 207, 180, 73, 79, 8, 26, 223, 156, 130, 22, 223, 11, 132, 244, 132, 174, 2, 209, 117, 130, 242, 135, 81, 206, 78, 222, 56, 68, 225, 231, 188, 52, 161, 185, 127, 172, 184, 184, 168, 104, 220, 176, 158, 12, 160, 33, 139, 83, 13, 6, 76, 105, 40, 13, 57, 29, 225, 69, 200, 213, 100, 11, 206, 163, 55, 105, 45, 199, 142, 65, 197, 134, 189, 124, 8, 141, 171, 85, 152, 173, 163, 126, 147, 0, 93, 120, 241, 209, 37, 20, 99, 69, 69, 45, 21, 147, 90, 46, 72, 52, 29, 17, 126, 77, 52, 34, 165, 130, 36, 105, 17, 2, 247, 48, 34, 136, 152, 8, 213, 83, 251, 122, 127, 72, 180, 102, 105, 220, 37, 2, 74, 202, 198, 54, 31, 180, 104, 200, 64, 215, 247, 116, 211, 85, 129, 84, 10, 162, 52, 170, 102, 230, 184, 94, 28, 169, 6, 58, 90, 129, 38, 66, 214, 74, 168, 27, 240, 229, 194, 236, 97, 108, 87, 218, 154, 240, 200, 100, 16, 249, 139, 69, 85, 236, 5, 246, 238, 99, 124, 2, 249, 71, 54, 18, 156, 246, 194, 161, 167, 182, 135, 194, 97, 246, 7, 42, 200, 254, 128, 132, 216, 251, 32, 187, 7, 11, 132, 217, 251, 96, 90, 4, 219, 171, 179, 51, 248, 163, 19, 233, 93, 32, 254, 254, 84, 79, 26, 209, 40, 119, 89, 231, 64, 129, 134, 83, 36, 204, 193, 78, 251, 176, 15, 129, 185, 227, 42, 31, 248, 19, 109, 207, 182, 99, 71, 177, 126, 52, 14, 61, 38, 188, 91, 227, 161, 250, 247, 89, 70, 68, 53, 189, 192, 152, 24, 227, 230, 110, 14, 137, 236, 222, 103, 25, 17, 217, 242, 92, 3, 98, 183, 167, 252, 243, 81, 201, 163, 128, 237, 97, 22, 115, 225, 253, 167, 249, 247, 157, 184, 13, 146, 51, 74, 226, 217, 171, 192, 104, 155, 245, 36, 37, 170, 219, 51, 107, 201, 234, 46, 153, 70, 161, 250, 2, 90, 167, 230, 100, 22, 51, 97, 20, 150, 56, 144, 234, 143, 129, 225, 140, 43, 175, 226, 155, 215, 127, 153, 167, 91, 102, 12, 71, 98, 109, 102, 252, 0, 202, 112, 201, 134, 210, 54, 39, 135, 90, 108, 206, 225, 203, 60, 27, 97, 124, 54, 45, 72, 54, 8, 228, 242, 148, 76, 225, 96, 6, 24, 35, 154, 29, 47, 179, 72, 25, 36, 204, 92, 123, 15, 170, 201, 179, 53, 250, 205, 124, 112, 148, 80, 49, 91, 66, 31, 74, 145, 144, 223, 211, 112, 177, 80, 151, 225, 159, 1, 39, 222, 203, 142, 199, 66, 154, 96, 8, 105, 204, 36, 183, 27, 34, 132, 82, 39, 150, 228, 41, 198, 145, 38, 47, 200, 138, 41, 110, 209, 143, 46, 156, 178, 33, 91, 28, 196, 132, 23, 115, 154, 97, 234, 221, 43, 75, 176, 129, 51, 135, 12, 219, 58, 215, 35, 197, 170, 139, 33, 142, 55, 45, 223, 90, 81, 110, 209, 183, 47, 242, 220, 66, 158, 229, 33, 205, 232, 98, 94, 211, 50, 32, 201, 116, 5, 225, 43, 5, 214, 246, 199, 0, 14, 159, 71, 232, 95, 165, 103, 89, 119, 148, 159, 231, 211, 121, 229, 93, 173, 188, 206, 211, 124, 172, 98, 185, 237, 222, 155, 2, 167, 117, 130, 45, 179, 227, 56, 94, 15, 211, 241, 41, 42, 131, 239, 254, 214, 191, 38, 145, 135, 14, 134, 132, 194, 160, 117, 123, 37, 190, 185, 107, 215, 44, 240, 219, 132, 1, 30, 131, 95, 217, 252, 180, 254, 229, 171, 232, 3, 197, 243, 168, 18, 2, 11, 244, 232, 89, 176, 101, 205, 228, 209, 106, 75, 23, 86, 162, 79, 194, 158, 188, 214, 117, 99, 146, 254, 115, 89, 76, 238, 180, 164, 67, 7, 239, 168, 164, 55, 119, 205, 12, 233, 141, 19, 236, 182, 210, 204, 101, 216, 30, 106, 97, 170, 235, 78, 89, 26, 159, 83, 223, 180, 50, 14, 118, 43, 185, 33, 151, 13, 95, 166, 121, 89, 117, 23, 209, 27, 203, 19, 111, 142, 140, 47, 13, 183, 87, 186, 27, 123, 182, 52, 225, 94, 186, 60, 245, 200, 37, 38, 75, 18, 173, 158, 190, 247, 228, 154, 100, 76, 231, 177, 144, 213, 95, 223, 28, 97, 227, 225, 221, 119, 205, 127, 134, 189, 187, 139, 62, 180, 230, 174, 45, 119, 114, 94, 108, 246, 93, 68, 44, 151, 51, 205, 217, 51, 128, 181, 219, 228, 141, 30, 50, 39, 195, 128, 188, 80, 40, 122, 214, 84, 129, 227, 219, 122, 74, 254, 109, 189, 207, 185, 26, 175, 11, 122, 192, 244, 238, 42, 169, 115, 153, 196, 84, 65, 205, 238, 116, 84, 45, 32, 204, 121, 244, 130, 169, 66, 21, 67, 171, 124, 207, 44, 43, 145, 199, 174, 33, 30, 208, 29, 148, 251, 224, 54, 225, 89, 48, 86, 2, 138, 204, 23, 41, 161, 106, 216, 113, 136, 154, 164, 46, 44, 126, 61, 34, 207, 167, 204, 229, 128, 5, 12, 55, 38, 185, 94, 241, 152, 250, 125, 148, 159, 13, 45, 86, 131, 208, 227, 52, 197, 62, 225, 48, 234, 157, 38, 47, 171, 115, 32, 167, 179, 68, 70, 169, 0, 141, 110, 56, 105, 115, 29, 51, 99, 146, 183, 176, 241, 248, 71, 187, 144, 4, 149, 106, 8, 152, 90, 237, 157, 211, 24, 218, 99, 115, 106, 148, 89, 34, 139, 211, 53, 30, 94, 139, 118, 9, 213, 75, 132, 38, 185, 138, 168, 173, 167, 134, 190, 150, 72, 71, 39, 47, 71, 170, 231, 75, 235, 78, 211, 33, 92, 129, 253, 226, 46, 210, 113, 68, 137, 55, 233, 61, 121, 161, 215, 237, 167, 76, 131, 3, 57, 68, 29, 63, 172, 166, 140, 196, 220, 154, 107, 177, 234, 8, 169, 174, 206, 187, 27, 148, 188, 55, 55, 45, 61, 98, 186, 115, 249, 138, 67, 230, 6, 145, 133, 28, 244, 119, 131, 150, 87, 229, 74, 98, 238, 121, 107, 25, 137, 127, 32, 109, 66, 83, 82, 208, 8, 33, 238, 247, 146, 142, 124, 234, 64, 28, 42, 130, 237, 232, 4, 124, 252, 10, 230, 113, 122, 158, 233, 248, 57, 241, 8, 159, 240, 149, 250, 227, 164, 170, 69, 184, 50, 93, 45, 162, 11, 229, 204, 26, 230, 188, 58, 69, 104, 231, 89, 5, 199, 122, 225, 131, 122, 41, 255, 239, 130, 99, 144, 68, 9, 51, 228, 166, 245, 78, 199, 9, 33, 17, 165, 116, 7, 228, 145, 64, 4, 235, 149, 211, 221, 33, 44, 43, 129, 174, 37, 157, 135, 73, 71, 252, 145, 128, 98, 163, 0, 249, 86, 94, 149, 105, 62, 18, 207, 98, 225, 38, 254, 100, 60, 24, 185, 241, 110, 96, 6, 78, 5, 130, 247, 196, 140, 187, 10, 8, 252, 223, 113, 199, 137, 151, 12, 198, 48, 227, 136, 31, 205, 170, 73, 38, 168, 54, 228, 241, 192, 110, 114, 28, 26, 227, 15, 97, 58, 226, 149, 169, 64, 191, 5, 99, 11, 253, 243, 145, 32, 113, 166, 126, 36, 24, 135, 135, 227, 72, 171, 199, 254, 232, 176, 94, 117, 240, 189, 103, 67, 58, 56, 10, 81, 7, 219, 127, 24, 193, 53, 158, 43, 22, 244, 145, 9, 15, 244, 161, 239, 87, 135, 179, 49, 120, 97, 93, 192, 142, 240, 60, 248, 206, 217, 67, 176, 107, 204, 57, 162, 201, 147, 192, 149, 207, 114, 152, 90, 246, 214, 20, 131, 84, 15, 164, 4, 237, 158, 186, 9, 37, 211, 214, 129, 207, 76, 78, 228, 250, 93, 225, 38, 18, 212, 181, 56, 59, 41, 226, 137, 22, 62, 51, 195, 152, 99, 2, 55, 130, 99, 220, 35, 9, 119, 133, 101, 104, 104, 230, 242, 84, 144, 28, 193, 79, 165, 124, 228, 70, 226, 123, 200, 5, 223, 136, 64, 45, 219, 149, 238, 33, 146, 207, 201, 120, 176, 23, 90, 78, 4, 46, 100, 164, 0, 233, 238, 41, 36, 75, 144, 152, 218, 132, 241, 194, 126, 131, 211, 246, 88, 67, 123, 78, 229, 209, 97, 157, 123, 25, 245, 111, 189, 248, 89, 216, 84, 93, 123, 160, 80, 50, 91, 195, 162, 146, 188, 82, 127, 154, 135, 212, 162, 135, 121, 44, 89, 208, 36, 110, 121, 12, 42, 224, 127, 140, 158, 247, 209, 103, 110, 100, 167, 124, 183, 211, 78, 178, 133, 195, 26, 206, 46, 198, 161, 111, 208, 19, 8, 206, 39, 253, 211, 38, 31, 107, 200, 198, 16, 7, 29, 47, 164, 127, 210, 34, 214, 243, 98, 100, 189, 246, 160, 80, 192, 249, 133, 37, 28, 235, 209, 230, 214, 14, 29, 8, 82, 169, 198, 243, 74, 174, 105, 122, 201, 185, 58, 25, 97, 181, 40, 125, 129, 89, 195, 85, 89, 43, 73, 231, 250, 20, 134, 0, 139, 103, 70, 36, 208, 70, 55, 15, 219, 38, 118, 90, 210, 186, 3, 106, 60, 111, 221, 64, 238, 195, 182, 96, 246, 217, 32, 240, 189, 21, 5, 80, 29, 11, 34, 109, 18, 40, 60, 63, 183, 60, 77, 88, 22, 231, 52, 39, 109, 215, 111, 196, 142, 116, 0, 3, 194, 43, 206, 81, 18, 39, 51, 68, 123, 2, 123, 253, 215, 10, 217, 57, 51, 23, 116, 198, 219, 3, 46, 1, 238, 51, 114, 17, 225, 63, 72, 89, 41, 215, 125, 24, 64, 15, 171, 36, 248, 11, 43, 37, 56, 80, 43, 22, 172, 181, 39, 161, 52, 124, 115, 28, 138, 98, 108, 70, 76, 53, 253, 230, 141, 60, 167, 251, 230, 205, 67, 217, 148, 146, 34, 46, 83, 205, 199, 190, 188, 173, 31, 213, 72, 76, 78, 48, 107, 136, 92, 203, 75, 226, 151, 25, 208, 69, 45, 147, 104, 38, 189, 248, 114, 87, 197, 203, 144, 90, 96, 108, 88, 218, 200, 68, 5, 157, 74, 173, 122, 107, 157, 220, 45, 233, 204, 71, 255, 156, 156, 149, 106, 206, 114, 74, 169, 175, 123, 229, 159, 166, 58, 231, 231, 168, 8, 131, 137, 70, 212, 20, 77, 239, 116, 156, 143, 255, 62, 206, 205, 131, 64, 27, 219, 72, 156, 64, 6, 142, 239, 206, 45, 181, 127, 219, 155, 165, 100, 54, 220, 131, 224, 9, 212, 8, 155, 28, 160, 66, 49, 94, 134, 102, 134, 127, 151, 86, 251, 227, 106, 154, 142, 7, 58, 9, 53, 159, 114, 72, 178, 200, 188, 122, 169, 15, 171, 31, 156, 40, 38, 183, 163, 106, 62, 117, 59, 86, 221, 114, 57, 89, 33, 147, 12, 105, 214, 49, 28, 40, 15, 104, 78, 186, 80, 190, 46, 181, 53, 12, 134, 237, 211, 2, 54, 215, 242, 161, 81, 132, 77, 27, 180, 8, 129, 237, 204, 186, 120, 181, 173, 222, 119, 5, 126, 133, 239, 236, 98, 97, 54, 166, 33, 164, 157, 139, 109, 230, 57, 76, 20, 164, 193, 2, 167, 137, 66, 112, 218, 92, 111, 19, 235, 78, 224, 4, 17, 225, 218, 240, 1, 162, 3, 122, 213, 13, 99, 216, 104, 249, 190, 123, 200, 168, 238, 192, 39, 145, 189, 134, 1, 193, 69, 221, 221, 25, 146, 232, 65, 187, 246, 131, 98, 114, 181, 182, 59, 213, 222, 242, 252, 43, 59, 48, 156, 248, 158, 42, 124, 79, 78, 181, 170, 217, 197, 81, 159, 115, 29, 132, 15, 104, 88, 114, 248, 117, 177, 65, 119, 34, 84, 22, 24, 110, 14, 161, 205, 64, 251, 200, 47, 116, 110, 207, 140, 112, 8, 193, 248, 9, 214, 72, 16, 48, 71, 234, 74, 130, 244, 249, 105, 122, 133, 243, 169, 237, 168, 26, 56, 133, 218, 64, 215, 120, 204, 150, 68, 38, 76, 219, 107, 179, 94, 174, 39, 14, 172, 217, 88, 49, 121, 48, 132, 25, 208, 38, 56, 140, 80, 207, 13, 156, 2, 154, 211, 89, 130, 196, 135, 213, 216, 1, 10, 129, 250, 248, 174, 86, 130, 68, 121, 196, 95, 46, 255, 101, 1, 204, 45, 91, 84, 138, 189, 246, 4, 193, 71, 153, 228, 162, 134, 56, 176, 96, 13, 179, 159, 25, 138, 74, 242, 107, 216, 229, 67, 40, 50, 201, 100, 34, 161, 235, 131, 129, 74, 100, 75, 131, 41, 234, 247, 27, 97, 171, 137, 185, 110, 120, 130, 14, 226, 255, 51, 145, 96, 243, 196, 128, 245, 52, 70, 136, 171, 138, 228, 82, 160, 212, 27, 141, 241, 26, 230, 84, 253, 24, 52, 219, 213, 9, 71, 155, 114, 233, 6, 10, 236, 50, 147, 72, 93, 159, 216, 134, 15, 27, 186, 252, 111, 209, 186, 105, 194, 59, 47, 254, 95, 68, 152, 136, 112, 149, 141, 132, 72, 68, 133, 152, 100, 14, 107, 146, 99, 153, 220, 21, 161, 217, 62, 122, 103, 33, 62, 182, 23, 241, 248, 121, 198, 207, 33, 220, 42, 44, 77, 158, 149, 122, 6, 56, 37, 228, 42, 105, 193, 52, 227, 129, 115, 130, 234, 94, 151, 149, 150, 249, 73, 219, 30, 164, 186, 62, 97, 15, 157, 51, 116, 69, 133, 226, 125, 227, 164, 189, 77, 7, 2, 71, 169, 110, 133, 172, 243, 131, 119, 44, 187, 97, 109, 125, 187, 56, 212, 113, 69, 203, 80, 15, 158, 232, 2, 122, 235, 235, 17, 4, 147, 228, 109, 153, 165, 44, 115, 96, 64, 164, 227, 7, 23, 191, 136, 244, 162, 34, 29, 58, 80, 120, 171, 68, 186, 77, 7, 110, 171, 72, 47, 75, 24, 153, 106, 88, 95, 135, 52, 192, 155, 13, 179, 108, 216, 108, 174, 61, 153, 116, 19, 140, 230, 155, 190, 202, 141, 28, 17, 186, 37, 43, 221, 249, 176, 191, 93, 178, 118, 27, 86, 187, 230, 180, 211, 190, 21, 184, 200, 54, 147, 106, 175, 39, 201, 28, 171, 253, 130, 177, 57, 253, 98, 120, 157, 16, 161, 254, 152, 149, 165, 4, 133, 211, 139, 53, 184, 234, 170, 31, 247, 48, 214, 28, 150, 126, 195, 41, 169, 155, 160, 150, 150, 117, 218, 170, 89, 49, 57, 231, 177, 8, 87, 235, 238, 55, 28, 207, 178, 50, 176, 174, 72, 62, 207, 65, 166, 196, 21, 161, 101, 207, 98, 26, 252, 14, 157, 192, 56, 86, 236, 40, 162, 69, 71, 95, 138, 202, 131, 40, 120, 213, 240, 94, 133, 58, 46, 69, 133, 147, 30, 145, 114, 36, 117, 109, 45, 96, 150, 7, 176, 14, 159, 44, 139, 159, 172, 242, 215, 183, 145, 227, 84, 159, 203, 20, 174, 103, 77, 236, 212, 241, 198, 198, 198, 124, 131, 255, 58, 188, 237, 30, 61, 61, 117, 19, 164, 125, 241, 83, 29, 237, 100, 252, 154, 166, 169, 182, 199, 65, 92, 94, 15, 42, 101, 121, 132, 235, 139, 127, 245, 186, 199, 172, 69, 210, 254, 186, 225, 91, 224, 184, 153, 55, 210, 234, 140, 217, 151, 161, 254, 20, 67, 125, 111, 153, 99, 221, 124, 26, 46, 176, 111, 50, 30, 126, 25, 234, 91, 39, 213, 117, 107, 123, 177, 158, 35, 23, 96, 238, 143, 115, 196, 77, 16, 211, 142, 175, 88, 77, 144, 161, 149, 118, 230, 112, 40, 251, 45, 190, 108, 84, 89, 48, 85, 189, 44, 82, 55, 12, 56, 166, 170, 156, 103, 45, 2, 93, 4, 201, 206, 227, 167, 26, 1, 197, 240, 169, 13, 93, 183, 230, 112, 194, 183, 189, 164, 35, 250, 222, 97, 161, 253, 33, 162, 75, 244, 228, 162, 182, 103, 112, 58, 222, 124, 77, 126, 244, 95, 251, 243, 224, 115, 25, 233, 35, 141, 20, 0, 250, 54, 29, 156, 193, 92, 106, 111, 115, 113, 238, 111, 132, 30, 63, 143, 138, 207, 115, 21, 129, 241, 220, 70, 96, 8, 248, 230, 219, 220, 193, 23, 162, 114, 139, 136, 11, 130, 55, 249, 74, 110, 18, 236, 216, 78, 58, 129, 24, 46, 43, 88, 80, 243, 136, 37, 173, 69, 229, 50, 131, 124, 48, 89, 229, 198, 66, 42, 239, 235, 228, 13, 126, 238, 37, 207, 237, 73, 206, 116, 162, 84, 152, 40, 119, 40, 29, 28, 144, 97, 73, 0, 56, 29, 21, 111, 83, 160, 71, 224, 51, 84, 190, 120, 39, 208, 73, 186, 114, 21, 77, 86, 243, 16, 244, 164, 22, 64, 114, 73, 155, 78, 158, 136, 54, 47, 5, 45, 180, 162, 236, 26, 36, 194, 77, 147, 109, 47, 158, 113, 194, 241, 131, 171, 230, 206, 178, 75, 37, 106, 1, 72, 120, 91, 54, 207, 201, 18, 41, 218, 199, 162, 81, 72, 137, 98, 163, 218, 82, 125, 94, 42, 36, 50, 1, 142, 55, 106, 74, 244, 69, 143, 12, 8, 140, 116, 148, 213, 12, 130, 104, 75, 5, 215, 135, 63, 131, 183, 141, 202, 28, 245, 52, 44, 24, 219, 68, 160, 44, 18, 216, 68, 170, 183, 137, 106, 114, 112, 14, 4, 52, 45, 204, 187, 24, 17, 248, 47, 126, 204, 170, 230, 168, 105, 59, 206, 62, 168, 229, 105, 73, 93, 202, 210, 58, 69, 199, 63, 229, 89, 36, 27, 146, 181, 63, 158, 222, 223, 130, 240, 105, 55, 54, 107, 139, 184, 171, 180, 51, 82, 203, 138, 5, 196, 119, 143, 140, 59, 182, 65, 70, 112, 245, 239, 129, 234, 183, 7, 213, 231, 160, 116, 53, 115, 101, 171, 169, 127, 28, 197, 37, 70, 64, 1, 251, 53, 21, 253, 101, 138, 169, 98, 132, 13, 173, 32, 40, 97, 241, 19, 142, 188, 245, 178, 174, 16, 159, 48, 148, 224, 23, 187, 11, 214, 152, 243, 90, 119, 91, 163, 205, 165, 238, 224, 103, 46, 139, 217, 228, 39, 147, 117, 133, 76, 7, 230, 36, 146, 31, 203, 42, 11, 199, 102, 25, 28, 163, 111, 31, 104, 249, 115, 167, 28, 85, 91, 127, 205, 85, 106, 153, 128, 57, 218, 49, 98, 180, 252, 153, 175, 31, 159, 249, 246, 146, 232, 213, 235, 198, 150, 177, 246, 218, 56, 187, 72, 246, 236, 126, 196, 89, 123, 51, 213, 161, 226, 182, 149, 72, 53, 21, 53, 41, 125, 223, 58, 61, 35, 82, 141, 55, 202, 70, 39, 112, 121, 7, 173, 180, 183, 68, 107, 100, 166, 180, 245, 66, 247, 95, 39, 97, 96, 21, 5, 214, 75, 142, 85, 182, 191, 213, 160, 16, 7, 50, 254, 232, 54, 205, 61, 184, 21, 222, 44, 232, 92, 80, 36, 255, 127, 70, 28, 213, 54, 197, 67, 58, 97, 146, 243, 98, 118, 254, 54, 43, 223, 228, 149, 88, 76, 9, 50, 119, 199, 179, 115, 203, 207, 104, 18, 139, 119, 234, 224, 207, 88, 22, 118, 15, 110, 134, 100, 20, 170, 172, 203, 255, 75, 221, 24, 110, 242, 69, 250, 98, 153, 237, 221, 147, 146, 113, 30, 110, 75, 167, 6, 86, 32, 67, 77, 138, 215, 173, 91, 37, 187, 237, 254, 70, 59, 54, 177, 205, 176, 3, 232, 235, 182, 78, 156, 40, 71, 98, 66, 250, 60, 200, 202, 220, 32, 46, 166, 247, 232, 212, 86, 51, 0, 235, 221, 238, 86, 242, 151, 191, 36, 223, 222, 95, 133, 59, 29, 87, 97, 87, 87, 195, 248, 250, 107, 243, 40, 222, 178, 114, 252, 40, 155, 52, 33, 44, 99, 152, 190, 99, 27, 140, 113, 94, 21, 234, 167, 46, 184, 26, 6, 101, 217, 58, 10, 13, 139, 212, 3, 84, 6, 154, 208, 118, 7, 23, 99, 45, 142, 63, 103, 213, 160, 204, 39, 66, 225, 85, 244, 212, 149, 74, 45, 99, 46, 6, 61, 176, 42, 47, 187, 212, 215, 235, 30, 102, 39, 16, 94, 246, 166, 184, 24, 255, 83, 188, 237, 234, 3, 101, 210, 232, 177, 96, 193, 84, 250, 200, 148, 164, 201, 38, 214, 195, 75, 70, 1, 40, 42, 129, 109, 252, 138, 119, 243, 230, 252, 194, 120, 171, 47, 161, 138, 74, 55, 74, 140, 117, 104, 85, 124, 171, 239, 167, 58, 86, 200, 245, 32, 50, 165, 172, 47, 89, 210, 78, 70, 171, 117, 186, 140, 116, 19, 181, 33, 188, 113, 246, 43, 112, 172, 72, 217, 240, 168, 144, 115, 102, 246, 14, 60, 172, 76, 233, 125, 202, 139, 154, 65, 194, 107, 2, 61, 208, 251, 213, 147, 15, 98, 94, 169, 114, 60, 83, 201, 0, 179, 19, 148, 192, 229, 180, 165, 220, 173, 25, 128, 254, 102, 90, 60, 43, 196, 60, 145, 121, 233, 137, 232, 18, 161, 230, 232, 202, 193, 198, 212, 100, 193, 57, 8, 182, 32, 167, 5, 209, 83, 134, 184, 123, 105, 173, 95, 237, 93, 90, 17, 6, 232, 254, 139, 85, 87, 31, 187, 255, 82, 203, 41, 94, 255, 43, 5, 64, 18, 89, 140, 11, 204, 222, 115, 15, 134, 202, 130, 16, 54, 219, 60, 240, 104, 189, 153, 243, 182, 204, 108, 163, 197, 143, 20, 54, 178, 24, 67, 201, 155, 168, 145, 6, 21, 162, 167, 19, 12, 169, 154, 141, 104, 29, 105, 180, 170, 40, 90, 170, 180, 146, 9, 68, 11, 242, 39, 245, 146, 74, 254, 96, 170, 68, 20, 76, 66, 215, 12, 187, 166, 29, 86, 141, 152, 117, 247, 239, 43, 132, 166, 48, 87, 208, 137, 65, 105, 4, 51, 179, 64, 22, 39, 122, 198, 23, 184, 218, 251, 134, 115, 78, 240, 91, 37, 141, 232, 142, 176, 78, 95, 21, 154, 125, 132, 134, 83, 169, 172, 132, 169, 106, 82, 90, 169, 222, 27, 14, 147, 72, 171, 238, 42, 123, 23, 52, 130, 124, 216, 252, 176, 181, 185, 153, 252, 41, 254, 110, 246, 213, 159, 45, 60, 78, 105, 206, 85, 171, 142, 169, 103, 88, 64, 174, 72, 19, 216, 227, 106, 213, 228, 47, 148, 224, 167, 139, 19, 252, 180, 153, 224, 167, 119, 139, 224, 167, 132, 204, 150, 248, 53, 4, 127, 86, 20, 103, 179, 9, 225, 240, 86, 132, 254, 172, 84, 26, 22, 212, 177, 166, 230, 196, 216, 108, 168, 55, 189, 145, 138, 206, 188, 40, 103, 51, 51, 1, 234, 55, 176, 94, 254, 90, 145, 152, 166, 145, 32, 243, 220, 241, 150, 201, 254, 173, 51, 0, 135, 239, 21, 249, 72, 134, 208, 49, 43, 78, 189, 25, 81, 188, 85, 108, 168, 157, 136, 88, 239, 158, 246, 39, 69, 135, 239, 151, 47, 195, 55, 215, 240, 245, 111, 202, 240, 213, 27, 113, 19, 75, 70, 59, 172, 237, 41, 198, 1, 88, 95, 27, 161, 90, 168, 219, 38, 81, 243, 116, 90, 86, 187, 227, 33, 250, 225, 144, 180, 26, 12, 251, 10, 228, 238, 111, 186, 107, 16, 77, 123, 244, 35, 34, 229, 181, 171, 228, 162, 204, 167, 160, 164, 31, 38, 247, 238, 249, 208, 54, 31, 24, 159, 74, 38, 184, 78, 237, 221, 68, 138, 246, 77, 209, 65, 49, 62, 201, 79, 103, 117, 133, 183, 86, 157, 83, 199, 52, 83, 209, 31, 90, 135, 58, 216, 86, 230, 205, 22, 190, 105, 141, 84, 107, 148, 62, 6, 216, 227, 160, 68, 118, 115, 38, 6, 119, 112, 123, 114, 176, 242, 183, 179, 41, 184, 202, 64, 130, 7, 83, 187, 36, 93, 206, 197, 220, 164, 57, 162, 55, 232, 219, 136, 250, 240, 138, 248, 90, 196, 135, 18, 81, 38, 76, 34, 30, 134, 249, 219, 244, 214, 210, 164, 201, 187, 247, 67, 208, 187, 183, 69, 201, 138, 9, 237, 61, 1, 209, 46, 50, 76, 187, 161, 47, 140, 48, 235, 111, 227, 53, 211, 63, 212, 12, 77, 92, 173, 234, 92, 148, 243, 18, 122, 210, 177, 76, 214, 17, 43, 69, 138, 140, 142, 174, 147, 24, 252, 249, 136, 124, 218, 176, 149, 4, 245, 164, 125, 240, 16, 254, 252, 64, 253, 141, 29, 202, 149, 115, 192, 166, 213, 20, 244, 45, 9, 189, 191, 201, 160, 171, 68, 171, 13, 96, 165, 198, 208, 107, 91, 69, 52, 210, 18, 217, 128, 38, 84, 213, 193, 38, 166, 37, 173, 68, 230, 104, 44, 212, 47, 13, 70, 245, 233, 129, 236, 211, 22, 239, 147, 24, 182, 230, 70, 182, 116, 35, 102, 144, 73, 35, 167, 25, 217, 151, 8, 88, 169, 32, 15, 88, 239, 94, 216, 93, 233, 112, 239, 119, 63, 40, 251, 181, 227, 44, 200, 37, 190, 213, 92, 248, 86, 1, 124, 171, 24, 190, 149, 197, 183, 154, 27, 223, 42, 140, 175, 66, 202, 153, 182, 249, 135, 62, 157, 207, 93, 208, 91, 4, 166, 81, 231, 173, 180, 102, 165, 87, 24, 122, 105, 103, 20, 40, 29, 127, 205, 132, 20, 53, 170, 103, 245, 59, 99, 110, 24, 196, 187, 196, 70, 87, 127, 30, 168, 61, 66, 91, 52, 80, 2, 63, 82, 3, 38, 224, 159, 241, 123, 196, 239, 189, 8, 68, 105, 153, 220, 96, 139, 16, 10, 93, 243, 114, 97, 225, 82, 105, 78, 80, 196, 225, 79, 30, 13, 204, 200, 194, 176, 213, 12, 72, 102, 190, 171, 76, 163, 114, 11, 223, 49, 105, 180, 122, 38, 29, 150, 41, 170, 60, 116, 97, 159, 242, 137, 218, 209, 151, 161, 39, 174, 235, 209, 113, 25, 78, 96, 131, 54, 22, 182, 18, 9, 89, 129, 58, 13, 225, 42, 170, 228, 198, 137, 69, 134, 71, 175, 68, 89, 74, 111, 59, 78, 212, 198, 160, 59, 200, 225, 62, 255, 67, 249, 156, 14, 122, 201, 203, 6, 79, 43, 119, 82, 189, 212, 201, 186, 124, 243, 248, 203, 126, 158, 179, 159, 167, 200, 73, 60, 96, 3, 25, 235, 208, 197, 5, 198, 13, 218, 183, 227, 235, 203, 179, 184, 125, 120, 22, 183, 11, 207, 154, 236, 193, 51, 101, 7, 218, 101, 161, 179, 91, 8, 73, 234, 196, 199, 215, 118, 34, 107, 218, 18, 140, 137, 196, 103, 218, 11, 116, 37, 77, 128, 62, 207, 171, 236, 13, 158, 103, 234, 22, 227, 167, 234, 201, 74, 220, 68, 21, 137, 6, 176, 224, 247, 186, 244, 249, 216, 10, 36, 205, 199, 134, 34, 249, 243, 97, 123, 25, 183, 232, 233, 222, 50, 54, 209, 139, 109, 61, 107, 248, 138, 183, 77, 54, 170, 233, 187, 76, 119, 167, 167, 146, 242, 226, 175, 144, 111, 207, 246, 92, 119, 132, 84, 135, 161, 31, 147, 202, 9, 3, 231, 126, 101, 3, 217, 37, 96, 86, 193, 146, 215, 108, 255, 158, 206, 255, 206, 161, 190, 144, 152, 20, 182, 47, 238, 5, 173, 238, 64, 33, 61, 14, 179, 170, 24, 189, 207, 186, 123, 44, 7, 43, 153, 126, 194, 33, 158, 178, 238, 6, 160, 221, 75, 12, 229, 13, 218, 1, 31, 8, 191, 80, 90, 51, 161, 250, 211, 165, 132, 98, 253, 23, 138, 166, 162, 135, 228, 110, 35, 1, 84, 38, 102, 213, 147, 32, 1, 26, 242, 144, 69, 218, 138, 50, 46, 159, 212, 84, 92, 218, 179, 188, 146, 230, 129, 244, 211, 60, 203, 207, 178, 167, 69, 41, 180, 126, 101, 247, 174, 140, 64, 168, 237, 195, 87, 5, 30, 188, 18, 5, 80, 127, 152, 213, 46, 148, 120, 156, 116, 191, 221, 220, 76, 254, 146, 8, 11, 57, 126, 66, 188, 223, 255, 27, 19, 221, 145, 64, 3, 167, 18, 229, 49, 18, 160, 86, 217, 164, 145, 203, 105, 68, 252, 209, 155, 149, 118, 163, 50, 160, 235, 0, 158, 152, 62, 229, 92, 126, 156, 123, 38, 3, 124, 102, 196, 208, 142, 52, 121, 95, 68, 119, 154, 150, 50, 136, 3, 131, 255, 228, 17, 49, 97, 142, 153, 147, 103, 162, 54, 115, 104, 24, 53, 160, 42, 206, 19, 36, 170, 107, 56, 19, 182, 118, 26, 176, 38, 27, 172, 136, 239, 77, 84, 222, 255, 176, 122, 255, 211, 49, 31, 176, 155, 27, 178, 155, 230, 245, 171, 226, 168, 152, 149, 131, 204, 105, 142, 91, 18, 109, 175, 218, 104, 67, 59, 220, 18, 219, 175, 246, 199, 163, 92, 30, 248, 124, 6, 181, 12, 92, 54, 26, 116, 31, 76, 127, 24, 104, 253, 109, 134, 138, 53, 144, 240, 209, 33, 202, 190, 97, 128, 30, 52, 15, 144, 138, 237, 190, 120, 37, 95, 107, 198, 247, 15, 37, 62, 78, 182, 116, 35, 166, 180, 115, 230, 80, 175, 18, 3, 104, 154, 42, 113, 147, 218, 195, 117, 171, 151, 144, 106, 100, 81, 75, 231, 19, 138, 203, 212, 116, 225, 211, 49, 158, 25, 184, 249, 152, 79, 58, 184, 132, 86, 194, 92, 233, 251, 213, 75, 97, 241, 101, 67, 165, 42, 28, 185, 20, 6, 27, 123, 131, 74, 74, 70, 146, 16, 205, 132, 205, 255, 200, 11, 227, 219, 135, 77, 218, 209, 229, 231, 36, 169, 46, 114, 153, 183, 31, 208, 212, 122, 209, 156, 76, 19, 244, 223, 124, 232, 76, 30, 154, 18, 174, 86, 215, 28, 109, 7, 115, 219, 66, 233, 47, 12, 69, 138, 72, 37, 214, 81, 20, 220, 214, 213, 193, 225, 67, 159, 193, 189, 191, 68, 184, 248, 176, 197, 26, 120, 112, 29, 13, 224, 195, 125, 214, 210, 183, 215, 218, 18, 62, 60, 96, 77, 126, 247, 105, 154, 196, 135, 111, 89, 219, 223, 127, 226, 182, 241, 225, 59, 134, 196, 15, 159, 11, 9, 124, 248, 158, 97, 243, 183, 207, 142, 13, 62, 252, 192, 208, 234, 47, 174, 81, 150, 142, 23, 62, 252, 141, 35, 184, 4, 101, 181, 116, 4, 53, 64, 174, 7, 251, 203, 84, 132, 203, 71, 85, 63, 25, 37, 43, 214, 47, 169, 88, 144, 56, 72, 27, 11, 162, 9, 91, 255, 188, 151, 54, 172, 134, 243, 58, 54, 177, 233, 171, 184, 54, 117, 62, 249, 0, 58, 167, 177, 29, 105, 221, 49, 111, 83, 218, 185, 254, 136, 27, 81, 45, 118, 25, 93, 115, 143, 245, 47, 186, 65, 30, 66, 39, 216, 161, 119, 105, 181, 28, 220, 3, 182, 151, 170, 16, 48, 186, 68, 163, 190, 185, 133, 224, 131, 70, 62, 221, 1, 205, 199, 198, 80, 12, 15, 80, 168, 63, 201, 245, 118, 8, 182, 153, 218, 117, 168, 209, 56, 199, 30, 171, 0, 10, 137, 254, 209, 76, 222, 121, 233, 119, 170, 231, 88, 239, 46, 213, 84, 149, 99, 82, 131, 103, 127, 248, 234, 48, 59, 125, 242, 97, 242, 116, 148, 158, 86, 44, 210, 17, 172, 219, 195, 168, 135, 236, 176, 142, 125, 15, 235, 78, 27, 31, 50, 251, 217, 120, 71, 58, 29, 221, 200, 225, 134, 188, 36, 97, 152, 15, 236, 134, 28, 22, 91, 19, 229, 134, 29, 74, 198, 195, 13, 117, 98, 43, 80, 240, 212, 41, 152, 159, 142, 139, 50, 219, 75, 171, 44, 80, 56, 119, 10, 159, 139, 15, 112, 181, 99, 168, 236, 185, 83, 118, 88, 76, 119, 71, 33, 12, 42, 167, 224, 108, 156, 15, 138, 97, 8, 228, 44, 92, 82, 44, 71, 67, 36, 120, 239, 148, 174, 166, 249, 224, 236, 50, 80, 240, 178, 227, 112, 131, 77, 68, 229, 7, 127, 122, 140, 128, 49, 169, 39, 240, 134, 199, 163, 170, 162, 129, 251, 72, 175, 159, 97, 38, 144, 142, 169, 84, 62, 31, 108, 94, 16, 64, 10, 155, 113, 238, 75, 140, 121, 9, 249, 138, 110, 172, 116, 254, 10, 55, 124, 106, 104, 107, 248, 91, 22, 171, 35, 143, 189, 174, 211, 222, 155, 74, 73, 179, 59, 124, 15, 119, 123, 168, 47, 251, 16, 156, 222, 61, 194, 187, 173, 137, 227, 202, 120, 175, 170, 217, 100, 162, 220, 222, 105, 41, 247, 2, 212, 218, 27, 227, 223, 143, 244, 42, 241, 235, 175, 209, 42, 112, 220, 28, 170, 153, 55, 192, 42, 47, 139, 124, 60, 221, 21, 186, 193, 54, 247, 56, 217, 252, 112, 34, 254, 173, 240, 107, 58, 20, 244, 181, 164, 47, 254, 99, 237, 59, 186, 20, 186, 251, 28, 28, 117, 93, 181, 33, 97, 71, 185, 252, 16, 29, 230, 242, 67, 237, 181, 89, 31, 234, 6, 90, 212, 165, 35, 125, 68, 71, 16, 81, 208, 13, 238, 87, 136, 159, 60, 13, 122, 48, 153, 230, 231, 249, 239, 42, 43, 148, 69, 128, 178, 66, 195, 17, 201, 242, 3, 63, 35, 169, 148, 138, 168, 119, 239, 94, 87, 129, 192, 48, 36, 235, 28, 225, 122, 7, 91, 19, 29, 250, 85, 137, 174, 91, 183, 191, 233, 58, 106, 85, 15, 126, 193, 3, 167, 130, 206, 162, 27, 18, 145, 163, 30, 5, 20, 218, 181, 87, 85, 113, 219, 224, 201, 135, 108, 160, 234, 185, 186, 159, 140, 161, 232, 229, 197, 203, 84, 204, 51, 186, 96, 120, 168, 157, 98, 102, 196, 61, 137, 42, 63, 16, 145, 50, 89, 52, 66, 204, 153, 143, 7, 163, 217, 80, 154, 84, 80, 1, 148, 74, 199, 221, 51, 86, 24, 4, 58, 226, 19, 181, 125, 51, 51, 181, 15, 35, 48, 29, 165, 213, 116, 159, 222, 95, 15, 96, 119, 19, 122, 189, 253, 88, 127, 138, 28, 78, 55, 243, 84, 16, 85, 157, 13, 82, 149, 113, 206, 54, 219, 157, 113, 117, 96, 74, 112, 190, 20, 128, 135, 201, 46, 29, 90, 117, 196, 16, 198, 96, 90, 50, 74, 75, 168, 214, 69, 18, 240, 43, 239, 10, 91, 186, 103, 42, 19, 140, 44, 60, 118, 255, 49, 122, 183, 9, 85, 140, 255, 156, 82, 203, 50, 44, 39, 33, 25, 16, 44, 0, 30, 171, 176, 230, 179, 192, 76, 209, 135, 164, 229, 53, 147, 66, 76, 254, 127, 188, 182, 22, 88, 4, 180, 19, 19, 195, 171, 222, 104, 207, 201, 1, 184, 171, 32, 168, 1, 26, 72, 235, 224, 26, 222, 152, 20, 85, 142, 233, 20, 21, 178, 71, 89, 90, 14, 222, 9, 75, 10, 209, 116, 41, 10, 67, 99, 43, 61, 130, 172, 112, 115, 50, 11, 237, 15, 111, 243, 153, 248, 34, 147, 202, 118, 143, 136, 62, 35, 140, 117, 52, 123, 171, 148, 41, 12, 143, 198, 130, 224, 152, 172, 155, 183, 203, 228, 184, 235, 102, 32, 220, 235, 49, 31, 30, 235, 49, 12, 108, 238, 237, 234, 42, 31, 27, 120, 175, 118, 154, 161, 139, 9, 85, 204, 159, 3, 99, 7, 25, 85, 121, 25, 29, 205, 78, 31, 147, 219, 196, 84, 145, 14, 157, 185, 149, 117, 64, 234, 202, 200, 106, 130, 21, 249, 180, 170, 141, 6, 245, 78, 95, 58, 198, 251, 208, 75, 226, 53, 228, 187, 141, 76, 40, 58, 57, 150, 234, 165, 58, 7, 4, 205, 190, 1, 21, 184, 226, 30, 152, 80, 165, 14, 179, 201, 40, 21, 139, 159, 10, 77, 165, 82, 253, 38, 209, 97, 159, 223, 138, 136, 75, 185, 154, 115, 84, 135, 210, 17, 246, 69, 148, 97, 169, 39, 73, 135, 76, 157, 188, 172, 166, 63, 23, 162, 72, 169, 25, 93, 101, 123, 148, 125, 243, 32, 90, 22, 177, 176, 184, 222, 119, 218, 208, 147, 140, 125, 173, 205, 195, 199, 52, 215, 66, 0, 13, 193, 95, 79, 157, 183, 33, 240, 52, 216, 240, 6, 26, 88, 240, 46, 74, 69, 163, 0, 112, 72, 31, 39, 223, 110, 242, 195, 13, 54, 240, 229, 167, 180, 194, 116, 28, 79, 240, 215, 211, 66, 232, 205, 243, 183, 195, 52, 68, 22, 11, 220, 240, 167, 134, 178, 202, 27, 8, 154, 118, 136, 168, 32, 161, 110, 173, 203, 170, 192, 252, 212, 115, 222, 28, 185, 47, 176, 91, 238, 107, 138, 173, 251, 77, 153, 65, 206, 75, 141, 56, 123, 205, 250, 249, 113, 197, 127, 170, 237, 21, 24, 99, 102, 162, 67, 52, 57, 98, 137, 181, 20, 41, 92, 57, 158, 46, 179, 222, 115, 102, 195, 134, 198, 229, 100, 70, 233, 201, 105, 201, 8, 22, 160, 97, 140, 126, 30, 237, 92, 60, 205, 39, 175, 87, 245, 232, 230, 144, 72, 121, 14, 106, 125, 52, 210, 80, 195, 249, 172, 73, 121, 18, 119, 142, 209, 241, 27, 106, 26, 146, 186, 230, 156, 241, 160, 163, 65, 8, 239, 141, 68, 120, 28, 34, 68, 143, 47, 136, 92, 100, 154, 169, 29, 94, 49, 33, 8, 179, 24, 90, 161, 125, 65, 180, 89, 31, 124, 252, 189, 225, 194, 215, 126, 151, 106, 38, 80, 138, 128, 106, 94, 182, 71, 154, 118, 27, 14, 54, 235, 53, 218, 118, 93, 199, 20, 245, 92, 235, 59, 59, 143, 210, 181, 155, 49, 131, 124, 245, 126, 197, 69, 94, 216, 200, 231, 78, 198, 74, 101, 111, 121, 3, 155, 227, 54, 129, 11, 166, 247, 169, 174, 115, 253, 231, 229, 31, 11, 88, 212, 136, 99, 207, 32, 180, 182, 230, 68, 120, 73, 51, 194, 157, 20, 131, 169, 205, 218, 44, 35, 111, 223, 242, 208, 132, 92, 232, 36, 206, 217, 240, 144, 123, 143, 117, 134, 67, 229, 123, 127, 105, 151, 101, 60, 210, 151, 4, 109, 105, 98, 179, 200, 45, 51, 214, 56, 38, 199, 57, 73, 48, 49, 222, 75, 39, 66, 85, 100, 58, 5, 134, 76, 66, 114, 158, 126, 232, 90, 26, 201, 90, 38, 218, 98, 61, 233, 235, 187, 17, 201, 232, 200, 180, 245, 209, 193, 49, 197, 20, 72, 153, 56, 75, 86, 34, 102, 170, 183, 246, 100, 216, 32, 57, 237, 187, 124, 44, 48, 212, 25, 89, 16, 69, 229, 39, 52, 170, 209, 132, 116, 111, 174, 16, 61, 171, 184, 95, 42, 19, 240, 19, 90, 238, 241, 109, 228, 63, 255, 244, 173, 79, 127, 246, 48, 160, 140, 52, 9, 75, 76, 93, 49, 240, 225, 208, 126, 37, 179, 8, 185, 146, 1, 254, 33, 45, 130, 83, 139, 89, 208, 154, 55, 102, 192, 26, 167, 155, 176, 202, 142, 168, 109, 66, 33, 39, 200, 217, 38, 219, 76, 32, 88, 89, 252, 217, 121, 100, 177, 216, 134, 133, 38, 181, 111, 100, 202, 211, 116, 242, 194, 240, 219, 241, 216, 28, 189, 213, 89, 75, 197, 215, 200, 249, 33, 248, 103, 216, 8, 10, 18, 99, 78, 155, 36, 250, 175, 196, 41, 61, 207, 134, 132, 133, 145, 19, 78, 225, 20, 65, 69, 87, 210, 188, 96, 180, 117, 115, 106, 129, 149, 15, 88, 69, 116, 212, 41, 253, 93, 243, 195, 48, 244, 227, 71, 1, 89, 182, 77, 251, 90, 96, 205, 30, 23, 98, 62, 14, 31, 138, 245, 123, 64, 118, 167, 64, 35, 107, 46, 171, 88, 206, 79, 194, 26, 198, 0, 92, 163, 130, 235, 175, 171, 2, 149, 69, 71, 29, 87, 133, 155, 173, 94, 119, 209, 49, 86, 148, 132, 4, 8, 177, 210, 138, 6, 122, 169, 20, 36, 65, 196, 48, 137, 74, 170, 149, 81, 34, 157, 82, 46, 169, 68, 50, 89, 188, 170, 237, 50, 176, 92, 236, 79, 235, 250, 163, 81, 160, 114, 10, 8, 204, 187, 186, 96, 207, 169, 2, 211, 47, 118, 133, 135, 252, 54, 75, 117, 92, 162, 155, 164, 25, 107, 133, 4, 58, 106, 56, 212, 117, 192, 212, 55, 49, 162, 77, 226, 95, 187, 212, 240, 245, 66, 228, 132, 136, 14, 59, 52, 244, 161, 42, 131, 7, 30, 18, 126, 55, 221, 38, 159, 194, 185, 80, 89, 129, 250, 101, 176, 119, 183, 182, 133, 171, 80, 131, 32, 25, 231, 147, 63, 137, 160, 90, 97, 191, 87, 201, 47, 162, 117, 121, 68, 228, 141, 232, 158, 253, 209, 191, 134, 190, 110, 221, 220, 190, 218, 31, 91, 215, 208, 241, 251, 183, 164, 227, 246, 199, 253, 107, 160, 194, 131, 219, 72, 5, 251, 227, 193, 50, 73, 66, 247, 19, 230, 84, 213, 205, 123, 46, 117, 181, 233, 50, 180, 149, 229, 54, 39, 252, 144, 117, 199, 28, 48, 238, 136, 55, 158, 200, 224, 62, 47, 114, 70, 82, 55, 30, 136, 153, 106, 209, 51, 119, 130, 171, 177, 79, 61, 183, 143, 48, 110, 164, 209, 148, 79, 103, 150, 55, 13, 85, 148, 81, 165, 254, 112, 22, 9, 120, 127, 28, 171, 165, 231, 227, 22, 55, 176, 158, 186, 211, 175, 180, 177, 208, 192, 74, 216, 166, 157, 191, 177, 98, 34, 75, 198, 254, 44, 143, 187, 5, 235, 106, 81, 221, 218, 28, 104, 49, 227, 215, 204, 247, 238, 108, 95, 163, 33, 26, 245, 67, 92, 59, 68, 116, 131, 89, 87, 243, 215, 97, 9, 167, 242, 109, 165, 219, 200, 182, 59, 175, 127, 166, 142, 232, 71, 119, 38, 95, 188, 79, 91, 55, 169, 79, 250, 209, 157, 175, 23, 239, 222, 253, 27, 218, 61, 253, 232, 206, 201, 139, 247, 244, 193, 205, 239, 169, 126, 116, 103, 221, 5, 58, 77, 93, 130, 209, 165, 32, 91, 181, 109, 214, 174, 218, 182, 91, 76, 188, 99, 211, 129, 177, 61, 189, 89, 95, 195, 40, 206, 53, 240, 3, 178, 89, 190, 117, 197, 45, 61, 193, 183, 156, 4, 91, 3, 190, 31, 154, 217, 201, 188, 200, 249, 103, 57, 115, 122, 112, 214, 91, 124, 159, 204, 110, 101, 52, 198, 222, 205, 21, 28, 180, 168, 151, 249, 147, 196, 8, 121, 94, 255, 121, 226, 129, 106, 60, 103, 203, 242, 155, 249, 14, 190, 32, 193, 12, 214, 182, 203, 164, 35, 143, 172, 87, 237, 134, 133, 17, 17, 242, 83, 155, 255, 174, 248, 248, 66, 27, 252, 43, 173, 119, 32, 213, 214, 249, 181, 201, 101, 81, 230, 167, 144, 56, 64, 245, 133, 6, 158, 168, 17, 15, 70, 158, 244, 87, 221, 234, 79, 113, 227, 19, 3, 190, 77, 114, 58, 212, 132, 50, 171, 78, 101, 132, 233, 31, 206, 7, 178, 245, 119, 13, 186, 194, 243, 57, 59, 219, 65, 100, 59, 208, 197, 152, 111, 225, 205, 173, 116, 26, 212, 78, 144, 243, 231, 83, 62, 238, 22, 216, 252, 209, 136, 73, 139, 157, 49, 119, 195, 193, 183, 131, 26, 172, 160, 152, 13, 20, 180, 128, 188, 253, 168, 176, 61, 99, 173, 25, 147, 186, 140, 238, 31, 201, 71, 58, 122, 206, 150, 179, 140, 125, 109, 26, 186, 232, 22, 116, 100, 232, 182, 195, 163, 98, 44, 186, 54, 36, 135, 124, 108, 219, 97, 174, 163, 251, 140, 180, 24, 229, 152, 186, 157, 147, 232, 118, 97, 120, 141, 76, 204, 95, 190, 99, 88, 187, 65, 72, 199, 218, 25, 152, 79, 60, 95, 90, 137, 111, 59, 93, 178, 113, 225, 215, 55, 221, 212, 153, 146, 98, 246, 231, 35, 205, 19, 118, 3, 16, 11, 181, 83, 235, 96, 255, 154, 198, 156, 169, 225, 207, 63, 93, 80, 117, 161, 137, 210, 146, 102, 179, 131, 172, 77, 54, 174, 173, 122, 51, 71, 90, 15, 211, 139, 46, 111, 181, 199, 97, 4, 34, 43, 239, 152, 117, 64, 131, 26, 231, 178, 16, 72, 48, 226, 173, 52, 22, 62, 203, 164, 255, 101, 126, 112, 230, 135, 230, 176, 92, 204, 162, 53, 81, 17, 191, 106, 220, 189, 12, 116, 80, 139, 239, 247, 90, 240, 178, 114, 77, 248, 197, 246, 54, 249, 193, 231, 43, 168, 106, 191, 58, 113, 34, 240, 143, 132, 35, 59, 121, 213, 233, 40, 208, 136, 217, 123, 245, 189, 93, 108, 190, 244, 103, 76, 39, 118, 54, 100, 207, 4, 230, 205, 200, 86, 200, 151, 25, 244, 203, 12, 154, 124, 153, 65, 155, 98, 216, 231, 156, 62, 253, 77, 166, 219, 226, 12, 251, 50, 215, 45, 52, 215, 93, 71, 252, 222, 28, 251, 165, 148, 86, 145, 105, 198, 223, 62, 85, 133, 23, 92, 141, 197, 3, 48, 123, 225, 14, 224, 219, 47, 203, 183, 207, 49, 249, 220, 17, 245, 28, 62, 68, 210, 82, 61, 135, 79, 33, 199, 195, 231, 23, 58, 65, 103, 143, 101, 28, 148, 71, 50, 245, 7, 215, 241, 93, 155, 37, 255, 135, 85, 179, 111, 196, 107, 208, 144, 190, 90, 38, 136, 87, 149, 195, 24, 152, 48, 184, 158, 144, 195, 120, 68, 184, 132, 26, 193, 209, 19, 27, 115, 122, 46, 107, 188, 150, 117, 248, 135, 177, 103, 113, 45, 71, 20, 171, 160, 88, 215, 123, 60, 227, 205, 59, 141, 251, 176, 105, 203, 142, 134, 169, 15, 167, 142, 205, 216, 76, 92, 54, 201, 102, 164, 208, 10, 78, 3, 119, 79, 142, 231, 217, 197, 248, 34, 197, 203, 145, 226, 121, 172, 182, 26, 139, 109, 89, 34, 108, 98, 163, 34, 198, 93, 155, 83, 55, 53, 70, 93, 173, 57, 28, 183, 236, 62, 133, 134, 104, 227, 7, 160, 86, 90, 99, 152, 219, 10, 26, 89, 95, 84, 77, 221, 33, 216, 150, 11, 186, 248, 17, 135, 47, 234, 231, 139, 250, 185, 149, 234, 103, 193, 224, 210, 229, 132, 244, 182, 92, 154, 206, 165, 240, 230, 140, 235, 253, 162, 25, 169, 89, 124, 195, 18, 200, 169, 29, 129, 236, 125, 94, 204, 170, 103, 132, 195, 41, 195, 123, 46, 178, 253, 234, 191, 179, 18, 146, 245, 28, 137, 209, 150, 44, 209, 245, 96, 232, 115, 190, 178, 71, 78, 205, 136, 84, 177, 27, 244, 234, 211, 13, 125, 253, 181, 77, 8, 184, 35, 244, 242, 247, 39, 39, 39, 53, 71, 212, 221, 21, 147, 62, 130, 92, 135, 156, 135, 158, 215, 69, 84, 112, 124, 39, 99, 193, 60, 48, 120, 218, 44, 56, 225, 196, 167, 135, 8, 74, 124, 199, 193, 73, 119, 25, 8, 246, 87, 228, 225, 249, 238, 122, 62, 240, 56, 83, 55, 87, 181, 236, 94, 155, 60, 64, 6, 176, 206, 202, 82, 72, 125, 29, 55, 202, 113, 179, 204, 231, 214, 8, 33, 16, 225, 185, 32, 5, 53, 15, 70, 38, 65, 164, 221, 186, 123, 249, 18, 159, 129, 2, 169, 179, 142, 38, 163, 124, 234, 102, 157, 218, 91, 66, 242, 172, 189, 105, 81, 38, 143, 98, 215, 39, 209, 236, 89, 208, 204, 158, 156, 91, 108, 205, 249, 18, 116, 217, 122, 27, 38, 1, 214, 182, 171, 88, 111, 126, 94, 46, 57, 22, 38, 43, 215, 8, 220, 20, 55, 73, 39, 71, 110, 202, 2, 114, 52, 140, 178, 221, 177, 183, 100, 52, 183, 114, 212, 243, 33, 210, 182, 43, 169, 193, 79, 183, 64, 62, 3, 236, 133, 253, 170, 175, 96, 227, 150, 55, 68, 59, 75, 255, 172, 52, 50, 37, 121, 43, 104, 112, 154, 149, 154, 156, 4, 53, 147, 244, 100, 126, 157, 233, 52, 19, 217, 220, 225, 154, 85, 106, 84, 166, 172, 171, 249, 227, 33, 224, 159, 238, 82, 120, 27, 175, 194, 237, 59, 221, 236, 255, 147, 237, 6, 39, 12, 2, 168, 212, 83, 138, 107, 214, 215, 167, 166, 9, 81, 98, 129, 172, 49, 202, 96, 190, 120, 170, 3, 59, 244, 17, 237, 182, 128, 46, 59, 100, 170, 210, 128, 104, 164, 136, 215, 117, 183, 16, 164, 30, 86, 105, 154, 245, 220, 69, 136, 19, 77, 248, 191, 39, 120, 23, 36, 175, 103, 224, 49, 41, 227, 153, 45, 149, 205, 176, 75, 55, 244, 4, 63, 107, 190, 12, 48, 190, 238, 146, 248, 4, 149, 100, 18, 97, 248, 183, 237, 45, 189, 100, 1, 5, 225, 241, 227, 199, 142, 15, 87, 55, 136, 173, 240, 29, 14, 154, 138, 81, 215, 168, 242, 223, 129, 41, 105, 50, 62, 121, 137, 172, 124, 77, 43, 71, 228, 9, 243, 97, 115, 243, 71, 147, 19, 141, 160, 120, 134, 49, 55, 43, 36, 31, 55, 11, 89, 78, 223, 4, 234, 170, 189, 190, 190, 25, 168, 252, 127, 56, 161, 230, 166, 61, 198, 25, 34, 206, 111, 48, 115, 7, 244, 220, 139, 130, 172, 141, 168, 254, 19, 246, 226, 189, 72, 248, 50, 197, 30, 64, 226, 62, 237, 111, 194, 174, 4, 98, 83, 171, 82, 8, 244, 239, 219, 33, 162, 219, 118, 109, 183, 127, 243, 173, 79, 70, 254, 223, 152, 229, 247, 27, 186, 234, 65, 207, 254, 6, 203, 26, 218, 54, 252, 11, 110, 63, 101, 173, 162, 140, 127, 79, 236, 69, 225, 102, 44, 163, 108, 243, 187, 231, 36, 168, 65, 251, 247, 246, 91, 202, 64, 143, 223, 237, 242, 220, 118, 124, 158, 206, 254, 38, 84, 196, 239, 199, 155, 175, 89, 132, 115, 68, 161, 50, 59, 239, 183, 109, 175, 123, 30, 239, 54, 119, 236, 55, 25, 155, 196, 117, 109, 108, 243, 241, 55, 184, 105, 244, 55, 186, 201, 152, 128, 14, 19, 211, 182, 123, 183, 178, 234, 154, 241, 105, 249, 248, 123, 121, 233, 148, 10, 152, 112, 102, 91, 28, 49, 142, 86, 157, 92, 162, 250, 236, 57, 177, 234, 2, 40, 4, 167, 235, 75, 205, 176, 148, 74, 34, 75, 115, 81, 238, 74, 188, 133, 254, 243, 50, 232, 177, 140, 190, 160, 45, 51, 91, 247, 247, 128, 82, 145, 147, 149, 180, 62, 14, 78, 26, 179, 80, 253, 30, 78, 64, 165, 160, 64, 6, 44, 67, 9, 20, 254, 92, 30, 141, 115, 192, 83, 70, 104, 160, 206, 239, 250, 70, 67, 100, 40, 77, 137, 0, 113, 26, 9, 228, 19, 137, 114, 14, 85, 165, 70, 43, 234, 245, 203, 196, 149, 173, 6, 180, 59, 120, 91, 43, 149, 167, 57, 249, 64, 206, 79, 134, 21, 200, 226, 104, 55, 96, 131, 59, 150, 186, 231, 26, 169, 187, 65, 1, 20, 165, 187, 94, 58, 116, 151, 75, 204, 120, 65, 138, 65, 226, 90, 234, 90, 216, 63, 249, 119, 153, 78, 38, 246, 204, 194, 161, 126, 192, 197, 1, 254, 234, 4, 113, 118, 110, 115, 174, 51, 235, 163, 249, 234, 15, 35, 89, 232, 95, 101, 213, 116, 46, 154, 212, 44, 76, 230, 184, 85, 162, 21, 254, 128, 248, 211, 162, 148, 40, 250, 248, 127, 165, 215, 25, 114, 1, 131, 119, 98, 232, 75, 88, 36, 242, 241, 91, 37, 176, 18, 94, 184, 113, 124, 36, 175, 114, 222, 168, 212, 219, 215, 236, 130, 9, 227, 35, 2, 149, 183, 59, 26, 125, 89, 90, 95, 101, 105, 189, 18, 94, 40, 107, 226, 126, 38, 199, 101, 197, 83, 55, 46, 127, 153, 204, 150, 106, 58, 238, 185, 236, 37, 158, 195, 169, 153, 219, 76, 10, 136, 69, 150, 148, 11, 44, 128, 17, 87, 178, 114, 108, 183, 73, 198, 20, 188, 65, 182, 211, 225, 136, 196, 22, 155, 182, 213, 22, 75, 178, 64, 197, 141, 118, 72, 26, 68, 80, 255, 206, 177, 18, 61, 237, 172, 10, 198, 146, 62, 212, 135, 176, 204, 249, 115, 126, 16, 51, 4, 209, 223, 148, 32, 124, 234, 174, 111, 57, 19, 156, 186, 143, 20, 117, 152, 178, 184, 132, 17, 151, 2, 211, 25, 158, 18, 212, 234, 185, 12, 55, 10, 187, 87, 107, 192, 149, 217, 105, 246, 97, 210, 211, 243, 83, 28, 160, 28, 97, 123, 201, 14, 191, 110, 39, 71, 112, 162, 47, 47, 178, 139, 96, 67, 178, 219, 138, 31, 133, 182, 102, 108, 168, 107, 203, 165, 154, 66, 168, 85, 233, 190, 70, 187, 85, 233, 45, 221, 185, 86, 165, 239, 107, 127, 203, 159, 56, 98, 225, 10, 202, 174, 212, 181, 228, 175, 7, 61, 62, 190, 43, 206, 45, 65, 88, 56, 236, 212, 101, 52, 123, 145, 125, 96, 158, 53, 50, 113, 127, 234, 107, 14, 174, 226, 28, 245, 250, 68, 58, 82, 188, 253, 79, 84, 241, 203, 59, 201, 133, 101, 214, 85, 133, 126, 153, 165, 229, 240, 85, 17, 100, 46, 40, 186, 26, 243, 173, 215, 27, 110, 28, 82, 196, 140, 3, 4, 29, 219, 205, 239, 86, 192, 124, 51, 27, 20, 127, 36, 242, 226, 251, 135, 52, 121, 195, 176, 24, 139, 23, 114, 26, 87, 23, 192, 187, 145, 9, 70, 123, 251, 44, 7, 119, 44, 42, 110, 211, 236, 229, 31, 242, 183, 206, 24, 220, 76, 128, 6, 129, 218, 165, 94, 157, 5, 119, 115, 20, 222, 32, 132, 20, 5, 53, 38, 222, 12, 194, 145, 217, 92, 33, 155, 180, 74, 52, 91, 76, 92, 28, 70, 159, 194, 104, 57, 143, 113, 8, 247, 41, 132, 218, 251, 16, 218, 69, 244, 59, 81, 24, 196, 93, 134, 145, 237, 115, 121, 126, 145, 139, 12, 182, 73, 178, 101, 249, 134, 157, 51, 105, 171, 20, 80, 80, 91, 28, 76, 65, 93, 223, 87, 162, 130, 40, 251, 213, 35, 198, 2, 214, 222, 82, 181, 79, 2, 7, 81, 98, 177, 47, 102, 165, 137, 180, 53, 191, 217, 222, 36, 190, 101, 174, 147, 123, 241, 232, 150, 218, 208, 22, 19, 243, 97, 166, 124, 90, 97, 231, 17, 114, 39, 174, 229, 77, 17, 8, 255, 118, 130, 90, 156, 249, 49, 16, 6, 14, 129, 224, 214, 37, 70, 2, 208, 131, 110, 159, 154, 121, 196, 227, 12, 248, 247, 128, 254, 88, 239, 155, 31, 196, 37, 16, 19, 111, 245, 205, 17, 113, 74, 165, 208, 109, 32, 209, 120, 25, 215, 83, 230, 142, 129, 44, 132, 199, 48, 130, 199, 44, 26, 67, 243, 93, 136, 161, 240, 124, 53, 70, 1, 103, 84, 237, 0, 69, 99, 245, 45, 45, 174, 56, 50, 116, 186, 119, 6, 200, 59, 158, 184, 116, 22, 176, 1, 93, 146, 17, 222, 227, 149, 55, 146, 212, 219, 230, 155, 199, 8, 122, 75, 31, 117, 125, 211, 214, 147, 241, 161, 67, 121, 102, 120, 59, 39, 48, 194, 253, 147, 215, 2, 115, 3, 175, 129, 20, 132, 12, 134, 4, 235, 68, 91, 234, 217, 10, 133, 141, 69, 1, 48, 177, 53, 106, 60, 44, 150, 243, 35, 209, 167, 42, 123, 174, 217, 213, 23, 57, 211, 3, 231, 98, 1, 45, 116, 100, 98, 208, 197, 116, 180, 138, 35, 63, 0, 9, 44, 21, 127, 61, 228, 12, 25, 243, 89, 66, 208, 209, 220, 7, 98, 180, 180, 153, 230, 232, 169, 24, 139, 3, 145, 180, 0, 219, 152, 150, 45, 59, 50, 89, 185, 210, 184, 168, 213, 84, 88, 30, 188, 75, 91, 61, 67, 188, 155, 226, 205, 191, 204, 235, 131, 134, 169, 249, 214, 228, 145, 177, 171, 91, 93, 229, 216, 218, 234, 202, 25, 213, 237, 200, 66, 157, 213, 215, 140, 71, 69, 165, 96, 204, 30, 182, 116, 239, 30, 150, 114, 214, 141, 251, 213, 203, 162, 170, 242, 183, 163, 75, 52, 96, 153, 159, 202, 224, 205, 186, 172, 134, 85, 26, 248, 255, 72, 171, 23, 133, 186, 154, 212, 154, 232, 170, 114, 237, 90, 67, 21, 177, 91, 247, 4, 100, 172, 202, 145, 185, 226, 21, 169, 171, 96, 8, 12, 108, 33, 2, 166, 71, 209, 168, 165, 187, 166, 80, 55, 74, 105, 184, 228, 154, 128, 94, 117, 24, 64, 125, 210, 55, 34, 222, 150, 197, 87, 160, 70, 13, 175, 17, 56, 178, 163, 43, 238, 210, 77, 122, 218, 246, 199, 112, 91, 122, 58, 21, 252, 148, 169, 133, 145, 12, 13, 85, 82, 255, 94, 17, 196, 113, 201, 137, 101, 179, 30, 90, 149, 2, 175, 103, 21, 154, 170, 21, 98, 190, 55, 18, 47, 84, 83, 86, 226, 246, 171, 23, 66, 31, 29, 148, 191, 106, 41, 144, 32, 184, 55, 48, 128, 35, 246, 82, 161, 201, 38, 138, 188, 122, 169, 238, 37, 62, 210, 107, 19, 237, 39, 196, 57, 16, 226, 80, 148, 106, 235, 104, 198, 148, 77, 221, 235, 186, 85, 33, 104, 48, 44, 56, 102, 240, 238, 249, 248, 99, 15, 87, 172, 209, 204, 213, 132, 24, 49, 236, 132, 158, 192, 162, 99, 232, 78, 11, 49, 141, 193, 150, 193, 174, 111, 205, 56, 147, 116, 115, 134, 100, 60, 15, 36, 115, 227, 155, 50, 208, 118, 128, 46, 113, 17, 162, 157, 22, 38, 197, 212, 4, 239, 62, 21, 63, 72, 165, 238, 145, 99, 38, 96, 212, 141, 174, 80, 223, 81, 91, 208, 239, 8, 61, 42, 47, 157, 98, 93, 210, 142, 226, 185, 38, 228, 253, 59, 128, 221, 88, 80, 162, 134, 66, 68, 39, 131, 252, 161, 110, 128, 149, 211, 243, 40, 46, 48, 224, 72, 95, 170, 204, 8, 128, 174, 216, 224, 204, 23, 97, 100, 26, 55, 98, 166, 78, 231, 27, 95, 201, 163, 25, 64, 226, 120, 98, 120, 43, 155, 147, 174, 14, 28, 93, 211, 239, 247, 61, 11, 88, 162, 219, 236, 153, 53, 188, 172, 26, 225, 119, 39, 7, 155, 218, 18, 101, 12, 141, 130, 201, 56, 22, 148, 100, 9, 239, 147, 10, 179, 113, 204, 248, 18, 93, 39, 34, 246, 2, 178, 26, 28, 100, 99, 173, 24, 92, 245, 27, 15, 4, 96, 192, 191, 194, 204, 155, 140, 112, 248, 38, 233, 80, 244, 241, 131, 178, 105, 197, 154, 36, 31, 141, 142, 208, 12, 21, 159, 158, 140, 135, 87, 150, 2, 5, 6, 246, 145, 212, 19, 236, 36, 193, 227, 209, 52, 45, 167, 161, 9, 197, 217, 80, 98, 116, 204, 199, 211, 231, 26, 91, 106, 140, 155, 46, 80, 79, 153, 120, 35, 35, 14, 74, 39, 68, 139, 1, 81, 110, 11, 241, 195, 81, 69, 226, 165, 70, 202, 120, 228, 129, 58, 25, 67, 206, 210, 203, 40, 59, 93, 136, 221, 82, 230, 3, 245, 16, 121, 156, 116, 187, 253, 100, 103, 39, 185, 191, 9, 97, 16, 91, 156, 176, 135, 233, 248, 212, 200, 205, 38, 163, 23, 52, 168, 186, 202, 224, 173, 99, 191, 52, 242, 98, 13, 53, 30, 192, 65, 10, 116, 100, 233, 190, 248, 158, 92, 100, 141, 50, 155, 8, 78, 213, 103, 73, 160, 180, 122, 238, 234, 6, 255, 138, 175, 77, 240, 198, 159, 214, 89, 25, 110, 109, 141, 30, 41, 65, 152, 176, 124, 213, 16, 255, 203, 129, 168, 105, 138, 60, 4, 52, 165, 233, 57, 44, 85, 197, 162, 40, 216, 162, 51, 115, 68, 176, 82, 227, 18, 20, 142, 55, 21, 176, 105, 88, 68, 96, 75, 46, 233, 176, 189, 115, 70, 76, 11, 69, 113, 57, 236, 93, 6, 37, 77, 218, 218, 49, 241, 124, 147, 141, 35, 34, 186, 180, 246, 37, 77, 107, 215, 47, 250, 146, 228, 187, 184, 130, 193, 131, 76, 13, 107, 24, 203, 183, 114, 143, 240, 164, 44, 206, 117, 148, 77, 112, 27, 79, 31, 168, 211, 213, 254, 41, 204, 185, 108, 212, 213, 42, 89, 235, 102, 18, 13, 165, 64, 110, 74, 49, 10, 124, 30, 225, 192, 109, 18, 57, 243, 25, 166, 212, 183, 89, 203, 112, 67, 76, 62, 237, 223, 188, 112, 21, 171, 70, 211, 43, 96, 212, 160, 93, 143, 11, 0, 130, 3, 91, 5, 132, 236, 124, 195, 96, 117, 150, 62, 1, 232, 154, 251, 136, 20, 183, 18, 24, 17, 106, 6, 158, 88, 10, 6, 206, 252, 166, 130, 174, 218, 75, 88, 187, 74, 242, 106, 110, 176, 110, 97, 62, 40, 128, 71, 94, 33, 74, 16, 45, 50, 102, 245, 69, 111, 234, 38, 212, 119, 164, 68, 65, 210, 119, 184, 210, 24, 142, 30, 107, 54, 114, 21, 45, 154, 178, 225, 203, 198, 23, 110, 42, 124, 175, 56, 155, 245, 38, 69, 85, 27, 69, 63, 204, 62, 28, 156, 144, 45, 120, 2, 223, 78, 43, 69, 229, 109, 234, 233, 25, 69, 148, 163, 205, 1, 34, 142, 47, 81, 86, 168, 97, 4, 63, 179, 60, 239, 164, 104, 221, 248, 82, 87, 200, 238, 218, 52, 205, 71, 47, 101, 239, 0, 191, 53, 86, 203, 57, 93, 59, 206, 46, 142, 12, 170, 180, 71, 198, 129, 105, 74, 152, 248, 17, 230, 13, 164, 159, 153, 134, 147, 24, 170, 19, 159, 134, 236, 182, 240, 218, 35, 77, 144, 109, 198, 192, 198, 48, 171, 92, 108, 37, 103, 98, 199, 118, 88, 105, 31, 211, 181, 16, 46, 88, 185, 199, 91, 90, 215, 239, 221, 53, 34, 161, 76, 84, 73, 202, 152, 169, 107, 215, 147, 237, 215, 127, 84, 154, 131, 139, 192, 80, 1, 190, 18, 36, 37, 110, 231, 114, 144, 16, 45, 186, 32, 252, 162, 235, 183, 87, 174, 160, 121, 119, 181, 225, 183, 184, 242, 85, 21, 172, 180, 199, 53, 84, 170, 182, 57, 126, 186, 116, 99, 191, 251, 61, 6, 197, 116, 95, 88, 187, 7, 39, 112, 72, 226, 57, 110, 64, 153, 99, 64, 38, 238, 195, 38, 243, 35, 217, 5, 234, 82, 248, 193, 158, 8, 201, 47, 16, 138, 93, 9, 204, 29, 230, 139, 36, 139, 254, 69, 73, 133, 239, 52, 22, 242, 39, 225, 47, 214, 236, 78, 224, 126, 8, 239, 102, 12, 210, 31, 90, 121, 219, 101, 253, 72, 166, 248, 218, 60, 241, 225, 92, 117, 129, 28, 241, 161, 46, 134, 146, 223, 25, 199, 130, 236, 54, 237, 188, 229, 242, 163, 81, 46, 3, 56, 172, 62, 15, 82, 149, 15, 186, 75, 87, 161, 229, 121, 1, 218, 86, 169, 211, 228, 177, 22, 189, 244, 4, 110, 27, 9, 75, 51, 65, 57, 113, 155, 143, 132, 0, 108, 120, 152, 234, 111, 7, 220, 14, 159, 242, 120, 144, 80, 120, 70, 115, 58, 205, 1, 120, 125, 118, 39, 184, 192, 62, 155, 107, 83, 99, 62, 131, 187, 184, 102, 83, 3, 214, 114, 219, 73, 209, 225, 206, 237, 59, 105, 26, 208, 141, 39, 213, 213, 216, 226, 80, 213, 88, 154, 123, 27, 17, 248, 228, 123, 66, 154, 175, 231, 223, 20, 170, 240, 16, 94, 75, 95, 178, 166, 48, 209, 233, 6, 194, 252, 54, 131, 174, 122, 21, 95, 114, 195, 238, 80, 128, 211, 91, 108, 15, 177, 188, 39, 205, 155, 68, 235, 91, 203, 219, 29, 186, 170, 215, 219, 140, 208, 28, 62, 111, 194, 72, 50, 197, 192, 157, 212, 143, 208, 179, 38, 143, 22, 42, 5, 149, 103, 33, 155, 164, 24, 165, 77, 82, 45, 92, 73, 59, 72, 20, 2, 43, 31, 84, 5, 240, 62, 232, 152, 128, 50, 145, 145, 226, 103, 167, 141, 155, 9, 81, 15, 66, 211, 133, 107, 78, 142, 51, 86, 70, 145, 128, 246, 136, 240, 245, 108, 43, 36, 70, 208, 63, 227, 23, 115, 132, 133, 48, 12, 170, 54, 221, 207, 58, 39, 152, 70, 196, 85, 110, 246, 40, 62, 93, 22, 153, 113, 141, 114, 9, 85, 111, 26, 198, 2, 234, 205, 28, 212, 37, 109, 42, 218, 41, 142, 242, 85, 67, 120, 7, 92, 78, 203, 90, 88, 212, 176, 5, 177, 193, 212, 0, 254, 153, 254, 68, 158, 193, 35, 11, 39, 62, 114, 193, 19, 254, 166, 107, 199, 175, 169, 65, 174, 84, 62, 29, 189, 56, 81, 142, 143, 88, 213, 24, 63, 225, 225, 239, 94, 114, 40, 9, 99, 68, 163, 6, 231, 22, 88, 112, 28, 136, 118, 240, 249, 25, 154, 14, 107, 2, 98, 162, 166, 229, 84, 90, 168, 75, 208, 3, 26, 234, 188, 123, 125, 163, 192, 246, 29, 238, 1, 202, 189, 67, 89, 113, 95, 48, 225, 41, 28, 129, 135, 55, 116, 155, 80, 238, 23, 65, 15, 156, 52, 41, 63, 74, 184, 15, 73, 85, 232, 165, 174, 120, 34, 83, 251, 35, 116, 187, 94, 205, 149, 143, 195, 44, 94, 53, 10, 224, 141, 151, 187, 0, 28, 128, 106, 187, 182, 186, 40, 18, 168, 92, 22, 231, 110, 69, 139, 81, 207, 0, 183, 174, 194, 194, 93, 86, 71, 139, 71, 246, 35, 204, 102, 134, 220, 117, 16, 58, 181, 16, 43, 15, 248, 189, 138, 135, 116, 228, 57, 208, 253, 106, 127, 60, 18, 208, 196, 176, 62, 75, 203, 211, 204, 221, 98, 50, 99, 188, 186, 29, 225, 42, 205, 82, 116, 121, 116, 117, 174, 90, 96, 251, 184, 137, 117, 48, 173, 135, 207, 118, 146, 149, 18, 18, 36, 74, 121, 74, 214, 162, 76, 229, 108, 96, 154, 134, 119, 72, 94, 16, 139, 76, 144, 185, 96, 93, 42, 192, 154, 0, 24, 234, 183, 13, 214, 21, 220, 98, 25, 83, 158, 42, 231, 30, 108, 176, 207, 136, 135, 54, 198, 157, 153, 102, 77, 60, 42, 174, 97, 74, 104, 117, 123, 91, 146, 151, 12, 102, 127, 170, 184, 100, 210, 232, 220, 12, 21, 224, 166, 65, 1, 27, 184, 16, 117, 217, 191, 58, 19, 41, 96, 243, 48, 17, 180, 182, 139, 17, 159, 120, 227, 124, 119, 53, 152, 43, 166, 226, 91, 253, 225, 74, 129, 125, 7, 49, 234, 166, 89, 49, 99, 235, 122, 221, 205, 213, 213, 102, 120, 91, 115, 193, 139, 125, 234, 175, 6, 24, 71, 201, 4, 188, 55, 215, 20, 231, 210, 237, 38, 254, 236, 36, 30, 58, 219, 144, 83, 193, 245, 193, 249, 78, 77, 218, 108, 174, 13, 17, 235, 52, 177, 149, 218, 122, 63, 222, 84, 224, 255, 89, 238, 4, 6, 16, 111, 197, 228, 37, 167, 15, 174, 31, 118, 228, 86, 49, 252, 251, 209, 219, 78, 22, 227, 79, 39, 50, 44, 247, 48, 166, 81, 232, 76, 5, 19, 143, 110, 8, 144, 21, 205, 68, 27, 192, 169, 46, 0, 88, 126, 161, 96, 171, 73, 58, 118, 213, 161, 153, 145, 180, 34, 108, 55, 147, 73, 80, 243, 104, 28, 24, 229, 128, 194, 81, 81, 48, 221, 65, 49, 27, 47, 97, 81, 164, 160, 133, 152, 41, 110, 11, 143, 25, 175, 40, 68, 180, 46, 26, 211, 9, 197, 11, 20, 194, 140, 102, 102, 203, 73, 20, 255, 11, 73, 203, 249, 200, 139, 56, 106, 19, 114, 100, 67, 28, 164, 155, 26, 146, 97, 58, 96, 224, 132, 130, 193, 254, 149, 113, 216, 75, 189, 177, 189, 77, 151, 121, 80, 155, 100, 183, 122, 37, 29, 165, 212, 136, 30, 11, 171, 222, 100, 127, 145, 53, 108, 233, 35, 90, 154, 31, 7, 114, 28, 235, 68, 113, 188, 10, 233, 140, 220, 156, 167, 158, 107, 128, 237, 222, 21, 54, 107, 206, 76, 152, 112, 109, 243, 91, 37, 201, 208, 13, 153, 15, 124, 196, 229, 203, 150, 92, 193, 79, 135, 171, 18, 115, 159, 11, 63, 106, 85, 176, 239, 72, 94, 240, 180, 53, 199, 224, 202, 39, 146, 157, 14, 45, 116, 22, 153, 195, 104, 115, 10, 217, 239, 68, 36, 125, 76, 211, 169, 80, 117, 46, 139, 168, 116, 231, 240, 113, 248, 52, 168, 172, 101, 69, 39, 144, 97, 110, 254, 243, 207, 202, 250, 196, 67, 182, 52, 213, 208, 220, 231, 151, 225, 0, 211, 203, 34, 151, 59, 79, 177, 237, 95, 83, 102, 119, 42, 99, 183, 115, 150, 247, 125, 240, 46, 45, 247, 64, 127, 9, 8, 125, 161, 37, 186, 22, 228, 99, 204, 220, 87, 195, 144, 138, 58, 8, 83, 212, 54, 208, 144, 55, 217, 177, 164, 24, 130, 48, 65, 236, 233, 86, 123, 146, 155, 122, 182, 103, 148, 203, 173, 137, 209, 60, 123, 80, 142, 9, 45, 129, 166, 98, 22, 24, 188, 41, 211, 11, 153, 224, 226, 72, 8, 80, 98, 133, 99, 80, 20, 103, 50, 193, 186, 201, 21, 174, 11, 217, 240, 225, 244, 130, 125, 151, 53, 54, 196, 91, 107, 111, 72, 161, 28, 29, 101, 167, 210, 12, 99, 7, 213, 210, 11, 55, 158, 210, 43, 29, 48, 96, 49, 90, 164, 166, 134, 107, 189, 218, 141, 227, 244, 66, 159, 177, 227, 70, 164, 111, 0, 146, 162, 198, 174, 164, 135, 231, 250, 219, 228, 231, 142, 219, 77, 242, 209, 90, 155, 122, 235, 85, 215, 241, 108, 83, 234, 185, 33, 88, 173, 69, 236, 82, 3, 75, 219, 167, 31, 87, 106, 235, 66, 151, 76, 29, 75, 5, 198, 86, 218, 168, 245, 231, 162, 183, 249, 233, 156, 211, 80, 200, 206, 16, 80, 92, 35, 67, 15, 235, 142, 248, 246, 184, 67, 109, 127, 89, 12, 82, 123, 238, 252, 85, 126, 11, 162, 37, 184, 255, 108, 25, 136, 1, 156, 56, 106, 240, 53, 142, 156, 250, 26, 68, 175, 24, 13, 151, 129, 157, 0, 19, 71, 46, 142, 88, 24, 169, 147, 252, 67, 182, 12, 172, 36, 156, 40, 90, 211, 105, 20, 47, 248, 20, 182, 119, 82, 97, 237, 86, 75, 64, 13, 33, 69, 145, 203, 163, 184, 229, 97, 212, 170, 115, 161, 251, 150, 128, 152, 132, 19, 69, 75, 126, 141, 162, 134, 95, 131, 232, 137, 63, 103, 217, 50, 240, 147, 128, 226, 8, 202, 207, 113, 12, 241, 115, 196, 139, 187, 12, 252, 102, 111, 227, 200, 205, 226, 162, 32, 191, 133, 209, 154, 44, 5, 173, 73, 13, 90, 147, 26, 180, 38, 14, 90, 79, 170, 65, 58, 201, 118, 167, 162, 232, 219, 217, 20, 243, 212, 191, 183, 179, 114, 62, 158, 204, 64, 77, 211, 201, 234, 61, 91, 127, 78, 131, 49, 85, 186, 94, 47, 249, 166, 243, 77, 47, 233, 124, 253, 219, 172, 152, 110, 119, 130, 14, 247, 116, 60, 120, 39, 140, 91, 56, 210, 121, 117, 210, 40, 96, 237, 151, 150, 216, 141, 111, 118, 82, 121, 166, 244, 81, 231, 27, 65, 170, 32, 85, 20, 126, 107, 162, 67, 143, 161, 204, 145, 34, 105, 26, 81, 122, 197, 120, 58, 40, 70, 5, 172, 84, 71, 58, 191, 222, 149, 180, 159, 6, 184, 64, 215, 160, 110, 34, 43, 215, 116, 15, 241, 116, 251, 7, 117, 227, 93, 4, 75, 186, 107, 205, 233, 171, 118, 16, 32, 45, 218, 63, 168, 91, 211, 61, 133, 100, 251, 222, 201, 137, 126, 86, 142, 174, 222, 177, 208, 84, 223, 138, 31, 223, 149, 217, 73, 77, 143, 36, 114, 141, 236, 152, 77, 73, 90, 193, 253, 113, 142, 43, 90, 147, 74, 89, 197, 131, 76, 201, 186, 84, 197, 43, 14, 229, 14, 170, 248, 178, 33, 158, 201, 114, 213, 4, 90, 202, 34, 49, 79, 0, 4, 177, 226, 174, 175, 42, 167, 59, 206, 172, 91, 21, 149, 15, 101, 70, 163, 226, 2, 119, 82, 97, 17, 97, 113, 212, 240, 67, 91, 173, 18, 50, 236, 179, 78, 123, 22, 28, 182, 196, 73, 240, 180, 40, 159, 164, 131, 119, 114, 69, 241, 54, 29, 156, 157, 140, 213, 120, 8, 227, 54, 241, 118, 17, 245, 216, 132, 215, 233, 71, 106, 149, 126, 68, 214, 232, 58, 131, 149, 248, 54, 255, 226, 92, 111, 81, 215, 174, 200, 9, 222, 228, 171, 192, 222, 46, 217, 77, 39, 157, 165, 186, 59, 108, 22, 84, 221, 216, 253, 156, 1, 31, 231, 163, 76, 180, 209, 221, 236, 37, 180, 22, 229, 97, 185, 206, 12, 159, 64, 200, 166, 111, 212, 87, 122, 103, 138, 24, 43, 181, 72, 20, 197, 76, 8, 142, 202, 89, 114, 228, 125, 130, 74, 145, 80, 86, 92, 174, 139, 245, 9, 172, 53, 69, 213, 39, 227, 105, 121, 41, 40, 96, 92, 37, 186, 109, 191, 69, 178, 255, 13, 96, 106, 226, 80, 77, 15, 149, 36, 56, 112, 204, 245, 210, 193, 79, 9, 205, 101, 30, 226, 222, 0, 47, 246, 84, 107, 230, 207, 145, 207, 204, 95, 137, 190, 206, 153, 174, 214, 214, 168, 201, 85, 107, 211, 107, 249, 227, 32, 186, 162, 66, 150, 252, 79, 93, 182, 204, 215, 159, 61, 199, 215, 65, 84, 156, 14, 148, 56, 29, 48, 113, 50, 131, 120, 176, 144, 64, 205, 229, 234, 226, 56, 7, 252, 92, 115, 179, 172, 90, 231, 131, 54, 170, 117, 78, 1, 75, 219, 220, 124, 205, 12, 125, 16, 229, 101, 73, 81, 202, 202, 232, 24, 61, 255, 103, 46, 55, 80, 26, 220, 109, 7, 54, 81, 171, 117, 81, 88, 25, 177, 128, 168, 175, 195, 108, 79, 213, 74, 134, 227, 143, 54, 183, 181, 155, 186, 199, 193, 202, 161, 158, 138, 215, 44, 174, 164, 89, 232, 212, 24, 24, 87, 24, 237, 23, 126, 66, 162, 135, 162, 201, 84, 9, 54, 149, 130, 155, 19, 124, 113, 131, 162, 28, 42, 119, 237, 31, 30, 59, 43, 7, 109, 80, 173, 66, 70, 97, 233, 219, 141, 167, 20, 134, 218, 204, 91, 148, 94, 28, 41, 231, 167, 248, 178, 1, 22, 140, 102, 151, 241, 236, 28, 191, 172, 97, 33, 205, 8, 250, 139, 74, 69, 47, 159, 169, 71, 200, 128, 12, 199, 240, 184, 56, 63, 16, 42, 3, 141, 178, 142, 41, 174, 143, 164, 56, 163, 91, 87, 247, 69, 250, 194, 212, 34, 29, 132, 93, 53, 213, 13, 187, 179, 163, 145, 182, 94, 91, 85, 166, 102, 135, 231, 187, 191, 109, 49, 186, 189, 75, 43, 164, 153, 120, 10, 217, 46, 226, 117, 116, 246, 131, 52, 51, 226, 123, 135, 65, 60, 203, 46, 53, 72, 120, 12, 193, 132, 247, 181, 64, 161, 64, 199, 93, 175, 253, 1, 140, 252, 80, 102, 156, 146, 22, 236, 67, 77, 147, 30, 244, 162, 167, 26, 254, 232, 242, 161, 86, 10, 32, 203, 38, 194, 13, 88, 211, 170, 92, 168, 184, 63, 53, 71, 219, 253, 40, 92, 40, 46, 59, 35, 165, 13, 126, 136, 63, 244, 72, 13, 178, 180, 6, 212, 176, 233, 35, 216, 27, 159, 108, 203, 113, 78, 215, 101, 184, 186, 69, 154, 232, 143, 174, 33, 251, 235, 24, 48, 47, 166, 239, 178, 114, 225, 169, 197, 124, 107, 55, 177, 68, 76, 52, 12, 232, 147, 168, 244, 228, 36, 34, 113, 227, 60, 35, 191, 30, 66, 128, 187, 163, 58, 100, 7, 182, 253, 113, 10, 15, 172, 6, 227, 213, 128, 137, 66, 212, 210, 63, 55, 192, 4, 182, 243, 143, 190, 186, 18, 236, 255, 201, 165, 232, 176, 231, 91, 142, 90, 223, 255, 206, 167, 239, 228, 4, 174, 65, 247, 88, 155, 204, 38, 247, 108, 62, 97, 148, 235, 120, 23, 223, 42, 175, 13, 92, 144, 243, 83, 86, 86, 153, 2, 120, 51, 199, 153, 162, 184, 200, 112, 31, 201, 165, 86, 36, 231, 187, 248, 104, 67, 170, 205, 16, 142, 179, 11, 168, 214, 181, 81, 7, 2, 41, 84, 155, 193, 33, 80, 225, 82, 7, 70, 150, 77, 249, 157, 71, 6, 203, 13, 247, 206, 160, 118, 150, 252, 1, 49, 20, 230, 54, 140, 130, 214, 252, 210, 236, 249, 144, 69, 31, 185, 161, 167, 165, 93, 223, 198, 200, 80, 173, 134, 52, 172, 161, 180, 212, 227, 150, 238, 176, 90, 125, 239, 156, 93, 109, 35, 75, 239, 201, 57, 74, 22, 107, 77, 103, 225, 249, 53, 202, 18, 148, 130, 212, 60, 78, 80, 122, 176, 63, 146, 18, 7, 84, 45, 204, 71, 2, 174, 78, 28, 50, 52, 41, 151, 159, 243, 147, 147, 172, 204, 198, 131, 236, 134, 170, 22, 139, 224, 34, 138, 37, 162, 241, 63, 179, 190, 40, 169, 132, 126, 81, 26, 159, 66, 105, 12, 179, 81, 54, 205, 110, 163, 222, 104, 213, 29, 87, 7, 180, 146, 253, 163, 203, 243, 243, 108, 90, 230, 131, 207, 165, 4, 176, 135, 237, 61, 126, 74, 47, 224, 143, 78, 184, 11, 1, 103, 197, 157, 183, 57, 23, 154, 91, 22, 99, 44, 190, 186, 157, 127, 118, 106, 197, 153, 251, 21, 4, 112, 10, 126, 58, 185, 161, 179, 146, 69, 112, 145, 89, 105, 225, 169, 231, 113, 120, 230, 137, 101, 67, 158, 199, 122, 253, 95, 236, 135, 54, 57, 75, 174, 50, 239, 184, 99, 224, 113, 186, 10, 162, 243, 249, 124, 2, 43, 167, 155, 205, 233, 26, 197, 79, 202, 235, 59, 243, 241, 250, 124, 218, 123, 201, 179, 116, 36, 235, 77, 131, 2, 94, 144, 101, 126, 206, 171, 255, 64, 60, 34, 244, 237, 182, 205, 215, 28, 251, 133, 167, 234, 47, 107, 253, 187, 103, 182, 251, 210, 112, 179, 237, 242, 5, 215, 243, 13, 221, 172, 17, 254, 127, 229, 217, 69, 54, 220, 45, 203, 244, 242, 167, 25, 88, 187, 251, 39, 135, 89, 126, 146, 67, 200, 69, 10, 111, 85, 51, 38, 33, 237, 219, 217, 73, 18, 187, 210, 74, 85, 208, 81, 232, 244, 220, 158, 81, 24, 162, 58, 92, 162, 7, 80, 244, 109, 59, 44, 125, 202, 207, 217, 52, 29, 188, 203, 134, 10, 23, 40, 126, 146, 145, 136, 30, 245, 59, 166, 86, 152, 250, 222, 214, 98, 106, 42, 105, 21, 69, 58, 171, 27, 136, 106, 42, 111, 70, 104, 121, 149, 149, 130, 219, 75, 238, 211, 64, 19, 114, 39, 213, 15, 234, 86, 244, 77, 119, 183, 97, 119, 170, 250, 79, 113, 164, 227, 128, 67, 160, 250, 211, 60, 118, 154, 6, 49, 194, 198, 246, 207, 190, 183, 199, 120, 16, 119, 85, 161, 5, 186, 40, 40, 108, 195, 60, 214, 49, 21, 136, 67, 67, 228, 198, 213, 172, 204, 0, 17, 85, 16, 36, 135, 214, 72, 203, 83, 26, 36, 100, 47, 196, 88, 85, 57, 73, 108, 77, 249, 82, 119, 47, 210, 62, 20, 217, 38, 163, 173, 187, 236, 79, 79, 48, 57, 89, 216, 193, 57, 42, 213, 17, 34, 157, 58, 186, 192, 228, 196, 187, 108, 193, 6, 46, 45, 53, 91, 159, 70, 254, 6, 234, 0, 14, 236, 142, 13, 108, 65, 61, 206, 131, 166, 211, 250, 4, 56, 92, 213, 107, 201, 69, 247, 67, 249, 28, 15, 101, 235, 54, 90, 59, 133, 44, 247, 77, 149, 124, 67, 48, 250, 38, 153, 224, 221, 208, 220, 190, 147, 83, 161, 248, 30, 202, 46, 164, 250, 79, 238, 80, 9, 164, 162, 112, 211, 147, 180, 238, 208, 62, 35, 172, 133, 115, 152, 77, 138, 114, 250, 107, 149, 158, 102, 242, 104, 7, 28, 142, 236, 9, 173, 113, 31, 206, 151, 245, 191, 131, 67, 233, 247, 87, 87, 105, 147, 149, 6, 27, 218, 157, 235, 227, 137, 172, 206, 223, 255, 142, 253, 49, 132, 72, 212, 182, 179, 162, 21, 33, 149, 207, 19, 66, 193, 231, 195, 116, 154, 57, 221, 241, 57, 159, 238, 129, 171, 15, 78, 21, 59, 73, 68, 100, 64, 147, 137, 75, 1, 77, 70, 225, 93, 70, 19, 109, 2, 74, 71, 203, 254, 35, 117, 117, 16, 175, 28, 85, 66, 212, 194, 112, 49, 12, 140, 194, 183, 127, 251, 46, 38, 96, 42, 178, 6, 116, 10, 158, 203, 32, 131, 192, 243, 4, 168, 41, 253, 194, 86, 77, 106, 110, 182, 149, 216, 80, 80, 225, 23, 230, 142, 58, 217, 171, 192, 16, 179, 6, 237, 49, 27, 121, 172, 55, 74, 86, 236, 137, 95, 87, 30, 161, 201, 224, 180, 38, 207, 15, 231, 145, 235, 123, 221, 117, 123, 48, 150, 103, 53, 181, 128, 27, 233, 138, 35, 203, 232, 170, 167, 194, 183, 151, 211, 236, 224, 228, 68, 26, 106, 215, 77, 107, 108, 83, 61, 219, 118, 23, 29, 135, 249, 169, 191, 16, 245, 132, 5, 161, 114, 104, 181, 35, 227, 167, 38, 223, 205, 33, 153, 158, 41, 93, 121, 206, 62, 100, 231, 147, 81, 26, 16, 102, 184, 20, 188, 118, 166, 213, 85, 41, 42, 53, 154, 99, 207, 52, 209, 22, 69, 28, 83, 1, 221, 96, 185, 66, 41, 205, 217, 20, 153, 244, 26, 58, 128, 120, 236, 213, 10, 102, 219, 78, 185, 28, 219, 162, 119, 215, 209, 39, 23, 141, 96, 231, 98, 157, 130, 37, 177, 13, 241, 116, 253, 29, 77, 22, 233, 65, 43, 110, 63, 160, 61, 80, 120, 203, 207, 52, 226, 112, 43, 138, 224, 251, 172, 188, 36, 49, 172, 201, 85, 48, 109, 63, 165, 88, 71, 71, 67, 250, 17, 119, 70, 249, 86, 30, 244, 238, 252, 151, 133, 248, 95, 27, 38, 219, 228, 70, 6, 189, 233, 184, 182, 230, 53, 197, 76, 219, 192, 115, 191, 15, 143, 147, 190, 88, 137, 242, 44, 36, 9, 9, 30, 101, 30, 189, 179, 68, 38, 30, 57, 83, 211, 169, 120, 224, 169, 70, 206, 48, 233, 125, 114, 112, 124, 246, 218, 186, 114, 166, 89, 101, 179, 31, 182, 14, 76, 62, 195, 212, 206, 103, 214, 47, 36, 169, 100, 161, 45, 224, 237, 59, 170, 57, 81, 236, 176, 26, 141, 51, 182, 159, 224, 230, 146, 46, 6, 75, 87, 152, 79, 100, 179, 135, 57, 138, 156, 229, 6, 95, 64, 168, 67, 81, 127, 254, 9, 169, 229, 200, 156, 193, 78, 116, 52, 56, 6, 27, 214, 94, 220, 63, 248, 158, 230, 27, 86, 105, 89, 240, 7, 228, 25, 194, 199, 14, 239, 89, 192, 105, 72, 101, 139, 45, 187, 235, 87, 179, 84, 196, 34, 50, 37, 57, 70, 197, 11, 11, 88, 182, 16, 132, 254, 18, 177, 59, 211, 145, 192, 127, 3, 226, 153, 95, 253, 77, 203, 121, 138, 233, 94, 21, 63, 229, 167, 251, 130, 129, 237, 254, 179, 227, 217, 210, 229, 94, 204, 206, 223, 102, 37, 45, 183, 162, 55, 20, 71, 233, 52, 127, 159, 53, 101, 138, 57, 195, 36, 44, 188, 124, 67, 202, 23, 86, 56, 158, 247, 197, 41, 70, 179, 180, 232, 79, 87, 72, 177, 230, 32, 142, 41, 100, 218, 160, 141, 217, 100, 234, 145, 102, 137, 101, 106, 92, 85, 109, 156, 55, 7, 206, 194, 117, 97, 223, 77, 45, 23, 34, 85, 2, 185, 223, 108, 71, 84, 2, 21, 169, 246, 228, 23, 166, 248, 64, 215, 137, 250, 146, 153, 156, 85, 195, 65, 100, 42, 19, 162, 6, 11, 236, 187, 50, 151, 157, 200, 238, 124, 170, 201, 236, 213, 194, 211, 152, 114, 109, 79, 48, 194, 241, 205, 179, 188, 34, 33, 142, 131, 116, 34, 198, 76, 166, 131, 216, 188, 226, 156, 23, 243, 217, 211, 105, 238, 149, 51, 193, 217, 185, 12, 48, 60, 214, 216, 172, 173, 1, 111, 169, 146, 124, 98, 131, 182, 119, 131, 150, 163, 107, 164, 31, 244, 76, 231, 156, 253, 57, 213, 51, 88, 28, 235, 2, 226, 151, 237, 222, 238, 241, 88, 182, 14, 8, 141, 221, 244, 150, 187, 237, 167, 83, 197, 238, 177, 249, 84, 40, 251, 137, 104, 57, 135, 235, 193, 110, 187, 28, 140, 135, 113, 41, 48, 157, 156, 71, 8, 72, 165, 27, 98, 208, 197, 152, 219, 96, 26, 51, 225, 60, 107, 45, 196, 213, 248, 137, 32, 219, 158, 201, 228, 84, 23, 97, 49, 117, 207, 247, 109, 225, 51, 164, 147, 96, 55, 124, 218, 52, 246, 90, 13, 235, 201, 62, 54, 156, 197, 188, 109, 76, 56, 15, 183, 1, 143, 70, 121, 45, 200, 102, 235, 253, 249, 248, 75, 95, 55, 31, 98, 50, 239, 188, 239, 13, 231, 49, 173, 203, 44, 64, 202, 78, 120, 176, 247, 14, 173, 79, 91, 175, 59, 9, 27, 57, 83, 222, 34, 90, 73, 17, 50, 204, 51, 251, 234, 190, 27, 188, 159, 224, 201, 72, 222, 153, 162, 82, 41, 234, 44, 76, 155, 55, 97, 37, 201, 241, 195, 151, 6, 203, 192, 82, 18, 59, 230, 232, 162, 54, 11, 70, 119, 181, 89, 107, 186, 107, 223, 126, 40, 137, 214, 122, 159, 50, 24, 207, 228, 104, 80, 183, 27, 244, 58, 107, 40, 89, 3, 136, 87, 61, 175, 229, 255, 206, 202, 226, 96, 124, 48, 155, 30, 156, 252, 84, 8, 126, 168, 32, 190, 199, 64, 81, 153, 21, 31, 203, 100, 197, 181, 248, 156, 177, 210, 6, 119, 96, 223, 177, 183, 110, 133, 183, 106, 41, 54, 182, 83, 240, 25, 61, 157, 152, 32, 227, 51, 29, 71, 22, 45, 174, 44, 108, 91, 56, 106, 245, 242, 232, 17, 31, 228, 185, 244, 103, 128, 179, 255, 79, 1, 185, 141, 77, 42, 245, 27, 193, 195, 58, 53, 190, 207, 174, 128, 237, 117, 243, 170, 10, 105, 154, 200, 144, 160, 96, 62, 121, 56, 178, 216, 235, 200, 197, 123, 52, 21, 125, 140, 217, 109, 198, 56, 137, 135, 186, 112, 225, 42, 220, 204, 239, 109, 112, 155, 11, 221, 117, 139, 119, 22, 67, 239, 228, 186, 57, 89, 199, 124, 138, 38, 8, 5, 80, 203, 20, 123, 109, 74, 139, 82, 5, 66, 153, 111, 44, 13, 191, 46, 200, 23, 44, 192, 229, 125, 100, 105, 192, 206, 179, 87, 177, 26, 51, 88, 145, 217, 15, 229, 77, 85, 98, 4, 214, 188, 86, 216, 44, 167, 186, 189, 67, 69, 88, 86, 109, 217, 105, 123, 227, 2, 145, 147, 195, 136, 152, 252, 51, 187, 252, 252, 14, 247, 205, 152, 195, 29, 110, 192, 10, 78, 81, 201, 162, 2, 29, 182, 82, 30, 243, 51, 254, 81, 153, 111, 41, 245, 92, 238, 35, 179, 87, 226, 88, 20, 246, 125, 39, 72, 128, 14, 126, 39, 129, 246, 159, 96, 142, 173, 195, 229, 166, 76, 171, 49, 139, 205, 78, 183, 78, 134, 115, 161, 226, 80, 63, 44, 111, 226, 213, 202, 65, 77, 167, 204, 143, 41, 0, 142, 173, 70, 194, 198, 113, 42, 53, 83, 228, 99, 101, 54, 174, 175, 127, 178, 25, 242, 121, 58, 185, 125, 107, 133, 200, 226, 243, 60, 157, 220, 14, 231, 95, 107, 127, 25, 115, 252, 182, 240, 147, 156, 75, 122, 107, 103, 73, 11, 223, 159, 179, 200, 0, 95, 155, 244, 34, 19, 64, 139, 251, 219, 4, 111, 133, 23, 28, 135, 217, 112, 54, 200, 238, 12, 223, 149, 178, 59, 159, 130, 245, 152, 74, 132, 24, 203, 134, 91, 37, 220, 126, 240, 100, 33, 198, 88, 135, 31, 233, 96, 48, 59, 159, 141, 48, 163, 120, 107, 222, 22, 12, 180, 182, 246, 154, 41, 49, 159, 53, 57, 236, 154, 75, 74, 253, 108, 95, 222, 245, 164, 4, 150, 126, 37, 153, 88, 47, 64, 204, 75, 62, 59, 33, 247, 146, 218, 17, 133, 168, 120, 243, 48, 63, 125, 55, 189, 61, 12, 138, 125, 158, 195, 81, 87, 218, 110, 126, 178, 180, 105, 203, 231, 94, 50, 129, 95, 141, 135, 215, 215, 57, 15, 123, 19, 241, 237, 98, 225, 247, 112, 152, 171, 123, 19, 214, 187, 29, 15, 173, 79, 177, 194, 61, 207, 135, 195, 81, 70, 13, 186, 147, 81, 81, 200, 75, 153, 146, 191, 98, 206, 47, 51, 167, 142, 138, 11, 185, 5, 44, 6, 92, 61, 194, 81, 0, 5, 1, 223, 240, 73, 118, 38, 250, 90, 26, 230, 83, 85, 214, 245, 21, 21, 6, 160, 221, 177, 144, 63, 73, 24, 138, 172, 111, 63, 203, 159, 248, 89, 23, 134, 24, 14, 83, 74, 127, 82, 5, 161, 97, 3, 223, 97, 141, 216, 62, 239, 81, 240, 74, 156, 54, 103, 201, 56, 151, 28, 44, 141, 69, 14, 230, 8, 8, 145, 216, 183, 227, 26, 87, 223, 214, 176, 200, 151, 16, 139, 101, 134, 88, 200, 157, 107, 188, 216, 193, 191, 142, 78, 136, 199, 25, 189, 13, 163, 253, 126, 49, 187, 235, 70, 53, 240, 56, 217, 164, 210, 40, 175, 237, 25, 50, 128, 63, 229, 211, 139, 188, 202, 20, 215, 11, 40, 187, 210, 194, 181, 176, 144, 213, 85, 77, 187, 128, 170, 139, 192, 8, 48, 146, 137, 134, 183, 91, 216, 248, 2, 207, 255, 153, 48, 13, 26, 85, 191, 123, 60, 86, 123, 233, 214, 112, 130, 127, 193, 211, 97, 187, 49, 113, 46, 206, 239, 142, 241, 92, 137, 206, 220, 165, 253, 157, 79, 21, 127, 88, 19, 126, 104, 175, 114, 113, 24, 10, 227, 18, 219, 174, 223, 128, 207, 194, 11, 184, 87, 197, 179, 66, 32, 155, 161, 255, 114, 36, 127, 84, 52, 242, 176, 151, 20, 19, 168, 196, 94, 90, 70, 77, 49, 52, 190, 45, 179, 166, 38, 46, 189, 61, 195, 218, 58, 237, 125, 214, 39, 121, 89, 77, 159, 24, 239, 173, 4, 81, 235, 32, 150, 160, 66, 99, 73, 33, 109, 76, 25, 189, 122, 172, 25, 121, 139, 175, 134, 77, 156, 242, 224, 134, 143, 122, 157, 29, 166, 211, 78, 229, 20, 175, 101, 50, 106, 41, 251, 224, 245, 134, 6, 80, 176, 239, 225, 188, 152, 3, 209, 175, 124, 76, 25, 138, 187, 178, 13, 37, 66, 68, 32, 240, 61, 26, 144, 111, 171, 174, 141, 27, 115, 84, 31, 205, 222, 202, 78, 116, 223, 102, 167, 249, 216, 177, 101, 218, 220, 49, 117, 47, 122, 36, 107, 153, 70, 175, 194, 174, 222, 168, 193, 158, 4, 34, 93, 219, 196, 36, 234, 115, 98, 109, 66, 27, 201, 196, 200, 15, 153, 153, 67, 128, 229, 224, 153, 190, 21, 180, 217, 223, 169, 107, 99, 205, 159, 76, 68, 63, 111, 202, 188, 102, 21, 180, 241, 240, 19, 80, 136, 89, 93, 146, 102, 166, 156, 252, 133, 155, 207, 204, 138, 81, 21, 163, 118, 140, 237, 202, 26, 175, 210, 108, 207, 96, 49, 3, 193, 224, 130, 187, 51, 58, 93, 171, 141, 206, 182, 239, 89, 31, 37, 238, 140, 44, 156, 76, 107, 180, 119, 127, 161, 224, 245, 136, 250, 230, 158, 88, 44, 147, 109, 237, 106, 119, 54, 213, 151, 59, 5, 120, 184, 198, 180, 10, 156, 16, 129, 127, 144, 132, 85, 243, 46, 57, 108, 148, 184, 125, 241, 153, 181, 217, 78, 181, 67, 18, 179, 86, 51, 140, 104, 153, 199, 96, 13, 13, 116, 123, 179, 213, 31, 228, 113, 118, 97, 100, 192, 189, 12, 87, 33, 183, 78, 134, 205, 185, 15, 175, 134, 224, 148, 206, 134, 202, 236, 64, 23, 167, 176, 122, 105, 176, 89, 137, 159, 79, 222, 157, 170, 107, 221, 110, 138, 2, 36, 60, 148, 71, 226, 49, 118, 93, 95, 83, 195, 41, 216, 154, 133, 92, 72, 169, 232, 96, 21, 203, 101, 252, 246, 57, 19, 237, 192, 43, 184, 145, 15, 236, 171, 196, 52, 28, 5, 225, 151, 91, 33, 49, 17, 242, 144, 64, 56, 6, 131, 217, 148, 100, 214, 19, 125, 146, 179, 115, 91, 251, 108, 119, 26, 182, 206, 32, 68, 12, 246, 233, 110, 77, 156, 97, 139, 120, 86, 232, 207, 45, 140, 105, 213, 14, 202, 144, 75, 241, 22, 6, 182, 194, 40, 212, 243, 220, 255, 134, 0, 87, 211, 207, 219, 26, 228, 90, 199, 149, 55, 43, 210, 213, 144, 154, 114, 221, 87, 182, 140, 228, 240, 207, 31, 187, 210, 95, 13, 95, 64, 226, 34, 42, 116, 156, 202, 240, 212, 137, 69, 98, 14, 70, 179, 161, 232, 208, 29, 12, 197, 84, 61, 251, 156, 65, 35, 94, 246, 160, 198, 112, 204, 79, 21, 35, 73, 60, 134, 196, 92, 128, 186, 71, 130, 143, 36, 239, 192, 66, 204, 101, 11, 144, 63, 95, 242, 184, 251, 39, 1, 63, 129, 99, 104, 24, 63, 80, 104, 137, 45, 175, 170, 149, 121, 231, 170, 98, 86, 14, 132, 188, 159, 167, 147, 147, 49, 119, 238, 212, 94, 33, 181, 231, 91, 161, 244, 24, 249, 94, 84, 29, 62, 48, 87, 103, 237, 49, 229, 7, 209, 8, 242, 182, 84, 5, 79, 225, 115, 47, 228, 175, 112, 85, 176, 44, 74, 72, 212, 164, 128, 251, 216, 91, 126, 211, 43, 182, 159, 216, 91, 146, 217, 160, 219, 207, 30, 135, 189, 66, 82, 8, 216, 154, 159, 102, 21, 185, 47, 24, 86, 27, 146, 202, 129, 4, 60, 230, 174, 112, 155, 129, 135, 215, 189, 231, 46, 17, 253, 207, 212, 33, 224, 210, 134, 149, 142, 211, 232, 251, 190, 63, 73, 41, 156, 57, 145, 36, 120, 77, 10, 39, 253, 19, 31, 126, 245, 21, 53, 151, 6, 101, 154, 7, 56, 248, 152, 184, 196, 18, 61, 242, 116, 170, 128, 102, 138, 51, 229, 135, 144, 233, 119, 166, 184, 95, 234, 73, 253, 96, 50, 205, 207, 213, 178, 184, 171, 87, 143, 212, 103, 31, 81, 82, 8, 127, 219, 148, 171, 81, 78, 193, 178, 83, 152, 248, 32, 63, 99, 82, 147, 35, 100, 175, 151, 236, 217, 125, 22, 84, 180, 45, 252, 208, 168, 179, 117, 19, 42, 172, 7, 121, 237, 236, 181, 133, 245, 209, 60, 105, 245, 161, 171, 232, 50, 31, 91, 14, 76, 116, 76, 94, 166, 131, 179, 165, 15, 202, 156, 4, 84, 237, 210, 107, 176, 145, 217, 201, 12, 149, 203, 132, 149, 20, 91, 211, 128, 97, 249, 237, 150, 228, 114, 210, 215, 130, 27, 124, 31, 111, 246, 123, 85, 200, 19, 159, 90, 187, 114, 49, 180, 190, 91, 197, 73, 170, 54, 185, 0, 222, 200, 113, 76, 186, 44, 145, 2, 185, 180, 246, 156, 92, 90, 91, 92, 134, 93, 162, 146, 54, 194, 41, 87, 176, 118, 59, 134, 100, 11, 30, 213, 49, 194, 138, 126, 252, 26, 42, 19, 67, 241, 31, 131, 142, 118, 169, 175, 249, 65, 214, 85, 83, 229, 33, 91, 4, 121, 242, 224, 132, 185, 57, 1, 181, 108, 104, 181, 70, 151, 94, 219, 103, 249, 153, 58, 193, 207, 149, 152, 99, 161, 104, 23, 157, 169, 66, 217, 175, 253, 224, 44, 54, 40, 115, 239, 85, 25, 44, 217, 158, 85, 221, 136, 204, 61, 30, 124, 52, 234, 199, 130, 38, 205, 176, 227, 80, 99, 178, 28, 156, 116, 201, 106, 83, 13, 129, 183, 86, 210, 244, 92, 186, 137, 50, 206, 46, 150, 61, 58, 10, 164, 34, 14, 93, 220, 157, 185, 187, 37, 170, 32, 35, 14, 153, 37, 231, 188, 51, 209, 171, 88, 115, 117, 162, 205, 20, 202, 85, 27, 92, 156, 39, 234, 157, 203, 117, 132, 106, 215, 152, 211, 185, 181, 124, 130, 220, 35, 235, 244, 228, 37, 126, 213, 42, 25, 30, 148, 180, 220, 181, 87, 92, 107, 229, 190, 51, 44, 31, 48, 135, 177, 104, 79, 215, 101, 185, 251, 141, 122, 62, 126, 109, 80, 212, 6, 122, 36, 245, 249, 88, 93, 5, 16, 219, 240, 122, 110, 187, 64, 117, 58, 239, 135, 147, 104, 214, 237, 5, 220, 32, 7, 69, 58, 158, 137, 5, 111, 55, 26, 178, 166, 255, 44, 77, 194, 159, 211, 105, 250, 18, 147, 29, 154, 196, 194, 249, 218, 154, 218, 122, 219, 224, 89, 71, 144, 47, 84, 49, 198, 74, 196, 228, 89, 60, 142, 136, 230, 164, 230, 75, 240, 185, 179, 82, 147, 234, 109, 22, 170, 177, 248, 34, 183, 91, 1, 95, 142, 151, 234, 227, 32, 198, 117, 52, 203, 7, 213, 62, 166, 9, 112, 240, 47, 28, 130, 36, 119, 139, 191, 132, 33, 181, 12, 67, 82, 123, 39, 177, 56, 36, 73, 75, 26, 139, 132, 25, 92, 3, 233, 206, 14, 122, 177, 219, 202, 200, 192, 118, 86, 105, 195, 111, 234, 12, 81, 149, 56, 80, 253, 95, 33, 105, 170, 230, 21, 178, 48, 93, 67, 34, 204, 159, 48, 213, 47, 166, 79, 54, 111, 194, 2, 5, 72, 172, 174, 6, 215, 126, 30, 59, 27, 80, 113, 69, 100, 179, 126, 126, 116, 87, 189, 20, 17, 104, 149, 105, 57, 236, 142, 131, 89, 115, 107, 15, 184, 190, 35, 100, 177, 94, 13, 178, 14, 137, 31, 207, 106, 214, 18, 164, 7, 228, 212, 149, 75, 164, 87, 66, 151, 152, 67, 87, 74, 69, 180, 164, 213, 138, 214, 215, 134, 76, 98, 76, 14, 162, 10, 228, 91, 166, 64, 210, 193, 116, 150, 142, 158, 133, 156, 223, 97, 173, 98, 169, 171, 57, 197, 130, 216, 209, 236, 22, 107, 251, 59, 205, 144, 61, 219, 240, 146, 52, 225, 96, 86, 150, 66, 8, 158, 53, 42, 68, 104, 70, 41, 186, 29, 82, 137, 78, 187, 126, 124, 33, 156, 169, 66, 188, 73, 59, 40, 228, 250, 64, 139, 109, 19, 174, 230, 129, 73, 209, 18, 75, 110, 59, 29, 244, 180, 86, 144, 45, 244, 44, 219, 5, 12, 45, 45, 141, 53, 105, 210, 129, 101, 184, 181, 229, 145, 207, 79, 181, 253, 21, 157, 143, 230, 179, 216, 252, 154, 109, 76, 182, 175, 142, 222, 165, 37, 227, 166, 121, 47, 215, 142, 212, 111, 211, 184, 95, 119, 41, 150, 133, 7, 118, 161, 91, 47, 92, 32, 87, 177, 50, 194, 29, 13, 4, 253, 40, 139, 193, 43, 254, 197, 110, 184, 75, 118, 131, 55, 188, 215, 111, 61, 160, 247, 66, 155, 14, 106, 141, 26, 21, 23, 180, 30, 92, 137, 225, 147, 122, 180, 90, 100, 94, 252, 110, 179, 205, 172, 110, 144, 211, 182, 4, 153, 64, 15, 240, 242, 240, 3, 16, 120, 175, 249, 234, 121, 118, 94, 148, 151, 176, 83, 130, 133, 233, 134, 164, 135, 76, 235, 137, 182, 78, 24, 85, 59, 243, 207, 181, 223, 109, 214, 206, 181, 94, 147, 116, 202, 146, 29, 99, 243, 149, 6, 196, 39, 172, 184, 87, 192, 245, 77, 0, 201, 224, 93, 36, 83, 179, 189, 229, 192, 50, 177, 32, 83, 52, 199, 255, 156, 73, 155, 67, 233, 222, 35, 232, 190, 42, 240, 240, 208, 240, 166, 29, 106, 178, 152, 125, 138, 115, 77, 252, 224, 132, 51, 136, 11, 156, 23, 134, 45, 79, 19, 15, 112, 198, 79, 49, 193, 55, 27, 157, 2, 191, 208, 45, 136, 71, 132, 205, 119, 199, 72, 138, 157, 90, 128, 145, 87, 1, 89, 250, 102, 160, 27, 48, 146, 44, 82, 141, 101, 170, 237, 112, 204, 63, 197, 232, 182, 141, 99, 83, 122, 195, 132, 157, 213, 71, 180, 145, 194, 141, 177, 109, 188, 108, 77, 148, 155, 100, 173, 155, 149, 50, 151, 45, 52, 154, 163, 152, 15, 236, 38, 191, 85, 224, 170, 231, 24, 188, 71, 95, 9, 130, 250, 107, 18, 169, 218, 15, 211, 241, 169, 89, 250, 240, 3, 170, 215, 33, 172, 90, 32, 207, 36, 33, 41, 138, 63, 34, 145, 30, 146, 80, 178, 5, 37, 85, 88, 6, 69, 57, 21, 186, 22, 54, 125, 197, 132, 116, 50, 182, 162, 106, 94, 181, 219, 127, 183, 16, 218, 239, 193, 195, 1, 30, 91, 141, 175, 168, 63, 77, 32, 217, 178, 71, 15, 199, 65, 15, 12, 61, 11, 77, 146, 206, 120, 23, 141, 217, 230, 223, 84, 5, 88, 216, 187, 148, 50, 181, 131, 249, 239, 44, 61, 123, 158, 78, 200, 84, 13, 219, 155, 202, 123, 46, 198, 197, 46, 175, 206, 211, 137, 163, 166, 210, 225, 80, 250, 116, 196, 23, 184, 198, 141, 172, 187, 204, 168, 202, 34, 117, 65, 109, 184, 69, 162, 202, 105, 68, 217, 237, 108, 251, 211, 236, 60, 116, 57, 155, 69, 209, 97, 41, 226, 55, 135, 186, 113, 126, 122, 240, 173, 88, 129, 98, 255, 185, 251, 60, 228, 176, 151, 40, 202, 160, 143, 158, 193, 235, 120, 243, 53, 249, 209, 127, 141, 61, 112, 200, 43, 239, 250, 109, 34, 175, 138, 255, 15, 145, 87, 124, 217, 16, 207, 215, 68, 222, 232, 229, 119, 62, 125, 107, 168, 34, 239, 160, 224, 151, 251, 10, 50, 252, 127, 27, 8, 248, 46 }; + static const unsigned char data[] = { 120, 156, 237, 125, 107, 83, 28, 71, 178, 232, 119, 126, 69, 51, 225, 99, 15, 102, 224, 48, 72, 246, 122, 133, 36, 47, 198, 146, 151, 176, 36, 20, 140, 118, 55, 226, 112, 21, 58, 173, 153, 6, 122, 25, 186, 199, 221, 61, 2, 108, 235, 252, 246, 91, 89, 207, 204, 122, 244, 99, 24, 36, 96, 165, 8, 155, 158, 238, 170, 172, 172, 172, 204, 172, 172, 172, 172, 172, 227, 121, 54, 174, 210, 60, 139, 178, 228, 226, 221, 97, 50, 206, 139, 73, 127, 45, 250, 99, 37, 138, 138, 164, 154, 23, 89, 84, 86, 147, 119, 7, 239, 255, 157, 140, 171, 119, 227, 34, 137, 171, 164, 159, 205, 167, 211, 181, 157, 149, 143, 43, 199, 170, 238, 155, 252, 167, 60, 159, 38, 113, 214, 255, 64, 234, 174, 174, 126, 176, 202, 189, 154, 159, 191, 79, 10, 171, 216, 58, 45, 53, 138, 207, 147, 127, 198, 211, 121, 242, 63, 73, 145, 247, 47, 7, 209, 21, 41, 125, 25, 61, 121, 242, 36, 186, 138, 254, 252, 51, 234, 95, 70, 171, 236, 249, 50, 250, 250, 107, 246, 2, 30, 175, 40, 98, 191, 36, 213, 203, 164, 58, 205, 39, 253, 127, 14, 162, 215, 2, 204, 206, 14, 251, 223, 135, 184, 136, 160, 84, 244, 36, 250, 231, 209, 235, 183, 240, 42, 61, 142, 250, 251, 229, 43, 214, 185, 131, 226, 31, 217, 36, 57, 78, 179, 100, 210, 135, 66, 107, 162, 162, 198, 96, 174, 190, 66, 181, 143, 178, 234, 234, 126, 185, 23, 79, 167, 241, 251, 105, 66, 43, 189, 57, 45, 242, 139, 55, 87, 179, 228, 89, 81, 228, 69, 127, 184, 61, 136, 42, 246, 43, 63, 230, 8, 172, 41, 24, 18, 54, 188, 35, 93, 216, 47, 95, 23, 249, 44, 41, 170, 171, 95, 147, 171, 126, 92, 156, 204, 207, 147, 172, 18, 192, 161, 23, 0, 139, 245, 66, 130, 84, 223, 119, 12, 68, 81, 128, 209, 166, 87, 86, 69, 154, 157, 244, 128, 114, 232, 229, 213, 249, 251, 124, 218, 163, 35, 48, 75, 198, 105, 82, 238, 229, 25, 171, 50, 31, 87, 12, 237, 252, 253, 191, 7, 17, 235, 118, 60, 159, 86, 232, 189, 69, 82, 120, 197, 144, 97, 133, 55, 199, 166, 144, 162, 174, 248, 202, 26, 213, 4, 180, 8, 235, 194, 183, 40, 44, 24, 145, 3, 10, 209, 247, 187, 239, 7, 81, 47, 231, 229, 190, 41, 163, 111, 16, 26, 223, 68, 51, 73, 201, 158, 166, 58, 32, 93, 50, 140, 225, 251, 17, 227, 150, 159, 230, 233, 180, 74, 179, 17, 39, 74, 191, 87, 10, 66, 244, 214, 106, 56, 164, 180, 217, 163, 190, 23, 251, 132, 172, 78, 229, 82, 149, 181, 186, 197, 203, 12, 31, 14, 248, 223, 222, 223, 254, 38, 49, 211, 93, 138, 216, 224, 235, 94, 163, 78, 247, 88, 5, 71, 38, 12, 216, 205, 205, 77, 198, 50, 165, 64, 162, 42, 174, 36, 50, 99, 198, 201, 207, 101, 133, 62, 104, 0, 245, 227, 93, 60, 155, 77, 175, 6, 22, 118, 3, 51, 162, 131, 136, 195, 227, 189, 96, 96, 170, 241, 105, 212, 79, 172, 62, 38, 170, 143, 59, 54, 98, 187, 39, 39, 69, 114, 194, 148, 204, 18, 176, 163, 176, 150, 134, 226, 126, 86, 37, 69, 22, 79, 151, 128, 33, 1, 181, 28, 4, 129, 57, 117, 195, 172, 10, 250, 180, 151, 207, 174, 126, 142, 171, 88, 170, 19, 198, 60, 253, 138, 181, 147, 84, 131, 168, 204, 231, 197, 56, 25, 68, 201, 229, 120, 58, 159, 36, 147, 253, 42, 57, 47, 145, 104, 239, 212, 112, 63, 175, 106, 113, 49, 150, 174, 227, 34, 63, 103, 2, 246, 38, 151, 178, 43, 43, 40, 141, 113, 150, 92, 129, 252, 185, 200, 29, 20, 140, 216, 7, 23, 25, 211, 122, 6, 81, 0, 102, 163, 169, 112, 19, 144, 152, 118, 225, 243, 147, 23, 159, 99, 166, 127, 250, 208, 106, 202, 240, 103, 243, 72, 180, 181, 35, 31, 31, 115, 68, 54, 167, 73, 118, 82, 157, 202, 151, 235, 235, 10, 138, 68, 148, 85, 128, 82, 71, 252, 43, 215, 8, 162, 101, 254, 16, 69, 171, 167, 113, 201, 16, 6, 68, 28, 82, 126, 253, 181, 44, 228, 112, 134, 156, 91, 149, 28, 239, 151, 207, 50, 166, 193, 11, 152, 71, 84, 127, 25, 192, 53, 94, 93, 225, 19, 69, 63, 115, 242, 35, 138, 93, 105, 26, 241, 230, 161, 226, 17, 123, 122, 187, 38, 208, 252, 200, 41, 80, 203, 13, 255, 200, 142, 153, 238, 75, 10, 54, 168, 148, 47, 16, 35, 220, 30, 30, 144, 70, 200, 231, 30, 250, 69, 135, 115, 137, 35, 153, 207, 217, 160, 81, 155, 77, 127, 75, 179, 76, 127, 211, 95, 123, 199, 121, 222, 227, 116, 33, 170, 99, 183, 40, 226, 171, 103, 31, 146, 226, 138, 247, 234, 125, 60, 62, 59, 206, 34, 99, 104, 28, 224, 17, 172, 78, 211, 82, 143, 31, 35, 29, 255, 246, 130, 147, 176, 127, 32, 105, 169, 135, 103, 87, 26, 37, 165, 44, 176, 198, 199, 106, 43, 52, 129, 127, 55, 136, 182, 216, 28, 206, 241, 217, 100, 132, 172, 114, 176, 86, 54, 19, 64, 205, 204, 220, 182, 205, 101, 112, 174, 179, 188, 126, 102, 22, 238, 249, 44, 157, 38, 12, 167, 62, 107, 5, 215, 194, 28, 251, 134, 117, 200, 69, 251, 105, 52, 140, 126, 228, 243, 148, 252, 212, 31, 174, 69, 143, 168, 61, 168, 25, 237, 76, 48, 217, 25, 99, 48, 70, 15, 246, 96, 152, 138, 243, 44, 27, 156, 232, 192, 240, 1, 239, 15, 160, 195, 204, 131, 138, 129, 214, 92, 101, 80, 100, 211, 198, 32, 58, 56, 58, 123, 203, 88, 131, 61, 32, 38, 50, 35, 31, 79, 203, 100, 71, 190, 253, 136, 24, 198, 152, 131, 197, 60, 129, 113, 31, 177, 169, 172, 220, 207, 166, 105, 6, 228, 123, 1, 44, 167, 155, 52, 172, 192, 136, 66, 25, 100, 148, 159, 39, 183, 147, 63, 74, 134, 217, 253, 102, 143, 107, 115, 135, 24, 251, 26, 230, 144, 236, 211, 130, 59, 128, 15, 28, 230, 120, 158, 23, 207, 226, 241, 233, 237, 228, 143, 99, 129, 220, 253, 101, 145, 110, 236, 177, 227, 27, 127, 132, 71, 11, 30, 144, 195, 237, 176, 193, 203, 120, 118, 59, 89, 224, 60, 158, 221, 254, 225, 135, 218, 187, 96, 14, 197, 217, 193, 172, 74, 207, 211, 223, 19, 33, 113, 98, 197, 215, 103, 35, 254, 35, 247, 202, 240, 183, 125, 70, 40, 0, 129, 139, 236, 9, 63, 205, 193, 0, 200, 186, 118, 29, 150, 130, 42, 140, 104, 179, 100, 194, 29, 50, 176, 80, 94, 128, 201, 188, 70, 206, 46, 47, 130, 128, 251, 57, 114, 183, 21, 39, 50, 142, 115, 149, 17, 183, 102, 111, 39, 35, 10, 75, 251, 158, 240, 226, 209, 219, 32, 255, 109, 121, 184, 111, 16, 85, 121, 119, 46, 60, 83, 12, 8, 220, 165, 216, 170, 229, 164, 40, 234, 122, 166, 69, 63, 91, 86, 249, 250, 186, 170, 164, 57, 216, 59, 93, 182, 99, 78, 193, 136, 14, 127, 30, 38, 147, 249, 248, 150, 218, 82, 5, 199, 237, 83, 241, 167, 80, 74, 242, 71, 60, 30, 207, 207, 231, 211, 24, 249, 13, 189, 188, 171, 218, 69, 229, 25, 24, 202, 206, 194, 131, 146, 48, 155, 6, 113, 23, 167, 32, 166, 73, 20, 85, 128, 187, 67, 155, 109, 164, 145, 36, 162, 175, 139, 164, 100, 160, 89, 67, 200, 208, 158, 228, 196, 74, 179, 185, 55, 194, 213, 176, 5, 22, 69, 239, 153, 160, 156, 89, 28, 22, 93, 156, 50, 138, 69, 253, 245, 117, 41, 30, 107, 102, 181, 185, 170, 32, 117, 67, 157, 146, 136, 9, 208, 250, 250, 91, 178, 46, 110, 47, 138, 20, 148, 79, 246, 116, 231, 144, 16, 234, 119, 198, 197, 165, 95, 33, 136, 230, 37, 159, 66, 12, 253, 208, 7, 249, 228, 159, 44, 8, 239, 216, 75, 91, 33, 111, 135, 233, 201, 105, 245, 69, 232, 132, 208, 65, 191, 54, 162, 225, 23, 209, 163, 162, 183, 177, 113, 22, 61, 125, 34, 39, 175, 229, 74, 222, 198, 134, 43, 121, 79, 197, 100, 184, 177, 113, 79, 5, 239, 121, 154, 77, 250, 51, 198, 221, 233, 152, 153, 5, 183, 72, 224, 24, 65, 38, 97, 113, 211, 24, 119, 145, 54, 84, 233, 211, 45, 6, 3, 246, 81, 200, 58, 210, 56, 214, 25, 71, 114, 96, 197, 215, 101, 172, 21, 25, 173, 61, 38, 122, 54, 217, 7, 143, 234, 23, 246, 184, 97, 95, 65, 51, 31, 120, 61, 71, 138, 11, 188, 12, 176, 49, 108, 61, 242, 124, 144, 157, 225, 7, 135, 255, 191, 82, 54, 178, 153, 217, 113, 96, 15, 236, 79, 146, 77, 34, 103, 155, 120, 113, 158, 128, 239, 69, 194, 212, 83, 250, 33, 121, 195, 91, 226, 69, 97, 255, 237, 132, 45, 17, 69, 227, 186, 36, 44, 79, 86, 68, 239, 73, 149, 199, 209, 150, 36, 139, 88, 127, 191, 140, 171, 211, 119, 231, 241, 37, 159, 214, 214, 173, 210, 176, 246, 145, 165, 31, 161, 210, 172, 171, 118, 57, 101, 226, 97, 36, 71, 64, 6, 130, 35, 39, 140, 46, 39, 54, 84, 8, 146, 162, 74, 75, 28, 71, 130, 204, 77, 40, 202, 98, 62, 12, 159, 241, 17, 226, 227, 132, 55, 244, 89, 179, 208, 210, 35, 132, 121, 194, 5, 95, 226, 205, 184, 100, 106, 33, 14, 144, 90, 162, 205, 138, 54, 35, 205, 11, 97, 148, 199, 249, 156, 27, 0, 164, 180, 192, 100, 67, 110, 201, 8, 67, 168, 202, 181, 6, 225, 4, 126, 12, 172, 240, 245, 215, 240, 255, 199, 130, 228, 235, 2, 152, 18, 16, 185, 175, 133, 63, 41, 123, 42, 18, 171, 92, 246, 63, 231, 131, 180, 50, 196, 219, 167, 216, 24, 210, 45, 219, 102, 204, 193, 81, 149, 191, 229, 202, 29, 62, 235, 245, 47, 49, 176, 224, 223, 36, 153, 38, 76, 135, 242, 226, 212, 184, 17, 200, 110, 108, 168, 183, 85, 110, 158, 57, 38, 234, 231, 71, 219, 112, 251, 140, 232, 174, 175, 27, 116, 205, 179, 139, 174, 209, 73, 7, 62, 243, 99, 58, 101, 42, 146, 79, 114, 165, 148, 171, 173, 27, 85, 49, 77, 210, 123, 246, 69, 116, 91, 136, 46, 90, 153, 242, 182, 201, 156, 6, 179, 21, 235, 196, 7, 101, 157, 4, 89, 64, 248, 162, 56, 35, 236, 87, 73, 17, 235, 88, 166, 51, 48, 72, 244, 160, 167, 252, 91, 50, 17, 195, 142, 57, 128, 21, 214, 52, 72, 37, 4, 246, 253, 85, 114, 65, 129, 242, 66, 255, 200, 202, 248, 56, 97, 83, 226, 33, 91, 44, 20, 31, 146, 201, 104, 154, 87, 125, 85, 141, 155, 25, 180, 165, 86, 181, 134, 202, 145, 214, 84, 112, 91, 118, 107, 199, 80, 67, 125, 116, 229, 66, 97, 254, 42, 185, 172, 250, 134, 18, 172, 191, 160, 183, 24, 223, 43, 93, 104, 226, 174, 128, 22, 60, 238, 78, 20, 250, 101, 30, 23, 147, 55, 185, 67, 220, 181, 181, 192, 102, 60, 141, 126, 144, 188, 0, 22, 21, 1, 33, 34, 246, 246, 143, 255, 85, 112, 231, 176, 90, 131, 0, 74, 234, 185, 231, 244, 160, 199, 191, 16, 171, 42, 102, 40, 10, 138, 253, 98, 81, 140, 51, 192, 22, 18, 140, 114, 62, 133, 65, 255, 67, 48, 212, 35, 28, 138, 51, 201, 51, 246, 130, 175, 57, 97, 195, 92, 144, 36, 246, 116, 16, 96, 108, 66, 105, 178, 214, 148, 29, 23, 159, 49, 118, 42, 14, 161, 6, 195, 33, 102, 188, 243, 95, 83, 46, 183, 186, 60, 19, 210, 7, 219, 207, 153, 150, 116, 43, 110, 99, 149, 165, 112, 222, 47, 95, 231, 101, 153, 190, 159, 94, 73, 194, 130, 169, 58, 17, 155, 8, 177, 182, 249, 132, 142, 11, 150, 148, 170, 47, 70, 75, 99, 207, 162, 30, 94, 7, 65, 252, 61, 46, 127, 78, 170, 120, 124, 154, 76, 126, 154, 31, 31, 51, 53, 19, 19, 167, 172, 101, 70, 127, 191, 165, 150, 212, 196, 9, 139, 167, 18, 75, 47, 199, 88, 47, 43, 211, 93, 144, 251, 41, 247, 121, 168, 214, 252, 226, 36, 152, 3, 69, 152, 116, 28, 220, 26, 168, 76, 144, 5, 30, 235, 114, 108, 57, 102, 122, 108, 25, 17, 135, 22, 63, 125, 144, 171, 186, 152, 68, 158, 120, 219, 117, 96, 109, 227, 245, 225, 44, 78, 65, 109, 9, 48, 3, 13, 239, 237, 142, 175, 53, 40, 92, 211, 210, 142, 208, 47, 164, 10, 7, 135, 244, 142, 170, 209, 98, 129, 128, 197, 24, 175, 17, 190, 226, 95, 249, 2, 180, 164, 241, 45, 62, 165, 206, 213, 3, 39, 43, 111, 114, 47, 206, 242, 140, 173, 110, 166, 175, 226, 243, 164, 143, 65, 177, 149, 30, 71, 186, 236, 57, 11, 146, 103, 89, 85, 164, 237, 27, 219, 94, 115, 181, 42, 15, 85, 106, 89, 127, 203, 83, 31, 4, 122, 183, 188, 202, 198, 253, 24, 254, 207, 195, 199, 248, 54, 217, 113, 134, 205, 149, 1, 87, 135, 108, 97, 232, 183, 97, 246, 144, 10, 87, 235, 5, 14, 117, 111, 154, 151, 243, 130, 115, 20, 252, 140, 96, 105, 252, 20, 177, 9, 236, 199, 165, 25, 64, 21, 77, 174, 98, 11, 193, 200, 188, 42, 198, 140, 99, 188, 38, 230, 117, 144, 48, 123, 86, 196, 111, 242, 17, 15, 254, 82, 101, 109, 63, 223, 188, 100, 112, 119, 101, 215, 213, 100, 107, 72, 225, 137, 209, 141, 113, 97, 25, 169, 43, 176, 244, 193, 178, 212, 118, 228, 111, 208, 234, 178, 133, 222, 168, 182, 112, 160, 229, 85, 95, 220, 179, 235, 86, 112, 107, 214, 41, 199, 191, 12, 17, 69, 13, 149, 214, 108, 141, 73, 13, 111, 95, 39, 106, 73, 156, 218, 212, 69, 189, 28, 213, 147, 215, 223, 154, 69, 50, 99, 245, 251, 193, 6, 104, 23, 160, 222, 40, 68, 188, 238, 228, 51, 136, 125, 68, 140, 208, 102, 132, 193, 76, 106, 221, 17, 181, 205, 74, 99, 195, 247, 96, 115, 85, 135, 114, 219, 222, 155, 189, 65, 180, 7, 238, 160, 35, 61, 36, 100, 43, 13, 254, 129, 5, 29, 95, 196, 105, 37, 92, 68, 25, 211, 175, 194, 75, 8, 7, 5, 166, 211, 252, 66, 194, 4, 244, 192, 15, 99, 92, 200, 72, 247, 208, 113, 36, 61, 30, 132, 199, 88, 126, 33, 228, 119, 131, 9, 52, 70, 59, 100, 68, 165, 118, 161, 67, 215, 28, 134, 192, 53, 138, 86, 140, 3, 3, 157, 89, 197, 104, 68, 109, 80, 130, 66, 232, 157, 59, 248, 157, 2, 24, 224, 31, 12, 195, 25, 204, 242, 54, 127, 239, 74, 219, 4, 190, 171, 111, 102, 51, 217, 148, 228, 246, 43, 55, 184, 210, 179, 4, 47, 71, 16, 151, 238, 232, 146, 182, 1, 164, 42, 98, 67, 104, 113, 46, 19, 75, 50, 185, 102, 51, 65, 39, 6, 40, 98, 58, 233, 44, 80, 91, 151, 254, 45, 124, 65, 113, 141, 37, 218, 208, 119, 89, 68, 242, 130, 166, 236, 143, 178, 118, 27, 6, 208, 174, 237, 53, 93, 253, 17, 241, 104, 119, 28, 87, 107, 84, 197, 72, 161, 17, 149, 198, 54, 29, 209, 143, 200, 40, 178, 167, 225, 126, 192, 0, 224, 118, 220, 18, 166, 253, 198, 217, 188, 245, 92, 222, 228, 219, 30, 74, 100, 93, 191, 182, 68, 88, 161, 196, 53, 5, 154, 9, 210, 118, 83, 142, 84, 244, 118, 228, 57, 129, 166, 145, 245, 206, 10, 158, 25, 193, 51, 27, 216, 14, 251, 20, 207, 7, 31, 175, 37, 70, 88, 89, 91, 82, 163, 189, 248, 205, 42, 90, 114, 70, 168, 75, 109, 4, 168, 70, 116, 222, 88, 90, 19, 201, 141, 163, 171, 3, 162, 3, 177, 51, 254, 168, 46, 159, 246, 35, 146, 178, 82, 163, 247, 82, 173, 242, 218, 42, 188, 208, 56, 173, 72, 42, 52, 171, 188, 21, 209, 115, 87, 237, 117, 222, 148, 19, 92, 126, 134, 70, 191, 110, 144, 154, 134, 200, 209, 107, 84, 171, 181, 214, 105, 64, 112, 87, 125, 225, 216, 38, 170, 154, 152, 169, 196, 79, 16, 34, 111, 17, 167, 124, 208, 97, 42, 79, 88, 242, 66, 155, 255, 206, 211, 12, 137, 178, 255, 176, 164, 207, 79, 132, 142, 85, 84, 18, 131, 129, 128, 105, 31, 158, 244, 145, 13, 192, 155, 226, 110, 151, 94, 228, 172, 86, 34, 59, 54, 229, 63, 152, 124, 229, 51, 40, 131, 207, 64, 225, 222, 98, 29, 235, 99, 69, 123, 63, 210, 113, 145, 168, 147, 24, 61, 204, 247, 199, 105, 81, 86, 207, 166, 201, 185, 136, 87, 224, 144, 142, 182, 222, 170, 134, 14, 141, 35, 199, 57, 164, 138, 106, 106, 82, 30, 50, 24, 178, 1, 108, 254, 31, 114, 108, 101, 127, 37, 255, 120, 233, 134, 96, 110, 86, 132, 76, 3, 130, 170, 60, 154, 132, 123, 82, 38, 179, 88, 41, 248, 222, 160, 231, 136, 204, 48, 44, 50, 160, 102, 108, 26, 40, 185, 57, 140, 214, 159, 24, 216, 102, 181, 229, 153, 24, 16, 24, 164, 29, 57, 0, 187, 243, 254, 238, 35, 0, 78, 239, 49, 112, 101, 232, 26, 53, 135, 248, 241, 144, 48, 220, 87, 36, 116, 146, 248, 8, 4, 67, 5, 29, 23, 178, 206, 32, 234, 193, 62, 228, 145, 152, 35, 55, 229, 17, 208, 183, 174, 31, 131, 198, 97, 230, 69, 122, 2, 14, 116, 254, 137, 107, 54, 224, 77, 195, 217, 59, 136, 77, 185, 38, 96, 156, 186, 161, 89, 85, 171, 135, 45, 236, 104, 98, 36, 23, 42, 145, 0, 119, 14, 179, 98, 205, 137, 61, 114, 220, 209, 44, 107, 34, 237, 204, 90, 33, 240, 236, 67, 196, 202, 198, 241, 84, 53, 194, 97, 205, 202, 204, 172, 97, 239, 138, 188, 44, 15, 147, 120, 122, 46, 55, 158, 113, 145, 182, 72, 11, 240, 82, 207, 153, 106, 128, 208, 94, 227, 217, 97, 81, 125, 143, 19, 215, 148, 197, 136, 8, 159, 118, 207, 221, 125, 247, 34, 132, 215, 162, 123, 158, 117, 119, 115, 93, 213, 165, 189, 218, 35, 217, 181, 212, 88, 181, 169, 29, 50, 23, 31, 50, 214, 69, 99, 233, 57, 136, 173, 52, 120, 227, 172, 44, 112, 112, 172, 230, 105, 92, 193, 177, 3, 62, 197, 21, 170, 86, 171, 96, 18, 113, 24, 241, 69, 67, 72, 137, 101, 26, 163, 70, 186, 196, 127, 216, 53, 109, 99, 249, 115, 70, 105, 3, 9, 25, 201, 247, 179, 74, 236, 232, 128, 209, 112, 48, 48, 228, 225, 78, 241, 161, 221, 7, 102, 144, 224, 237, 38, 143, 213, 0, 112, 251, 75, 26, 9, 40, 53, 73, 102, 213, 233, 171, 249, 57, 159, 71, 86, 66, 1, 63, 76, 236, 49, 209, 152, 58, 243, 250, 94, 16, 48, 179, 237, 73, 43, 146, 65, 250, 68, 100, 86, 104, 133, 73, 235, 128, 97, 5, 101, 16, 13, 123, 146, 7, 186, 245, 19, 192, 133, 31, 124, 83, 120, 69, 118, 27, 30, 172, 193, 92, 137, 212, 122, 109, 197, 12, 152, 0, 187, 47, 247, 171, 56, 12, 50, 163, 139, 38, 212, 119, 102, 14, 227, 23, 143, 13, 6, 228, 3, 13, 79, 194, 53, 210, 140, 156, 59, 86, 134, 65, 162, 141, 2, 241, 245, 8, 213, 33, 94, 73, 75, 198, 144, 19, 105, 199, 56, 104, 12, 180, 218, 80, 74, 31, 129, 212, 63, 229, 102, 64, 175, 36, 84, 252, 10, 97, 233, 190, 214, 47, 44, 127, 173, 20, 135, 211, 124, 62, 157, 200, 129, 166, 113, 175, 162, 167, 124, 20, 105, 72, 70, 228, 212, 82, 19, 181, 196, 205, 105, 137, 147, 31, 215, 177, 93, 118, 178, 162, 37, 150, 242, 45, 245, 48, 113, 178, 16, 110, 241, 177, 41, 45, 217, 64, 63, 211, 250, 192, 169, 234, 80, 85, 16, 100, 35, 26, 122, 8, 107, 199, 158, 64, 191, 49, 174, 16, 133, 123, 57, 60, 198, 255, 106, 125, 199, 223, 253, 245, 59, 143, 155, 184, 246, 60, 55, 198, 58, 178, 199, 131, 116, 202, 4, 187, 248, 207, 240, 154, 146, 174, 190, 221, 173, 196, 102, 231, 50, 35, 90, 212, 112, 26, 29, 153, 202, 136, 62, 185, 208, 85, 138, 152, 86, 120, 138, 150, 60, 96, 247, 147, 175, 206, 202, 68, 69, 164, 175, 123, 202, 173, 168, 168, 232, 199, 209, 22, 184, 214, 207, 172, 173, 220, 80, 102, 30, 21, 19, 194, 215, 16, 45, 246, 34, 119, 43, 199, 152, 126, 147, 31, 194, 209, 243, 50, 153, 244, 151, 65, 210, 93, 25, 137, 182, 152, 71, 65, 70, 156, 137, 120, 181, 51, 19, 83, 166, 190, 153, 40, 96, 20, 121, 21, 116, 8, 232, 26, 182, 25, 230, 95, 252, 231, 69, 197, 136, 0, 22, 77, 92, 36, 199, 146, 246, 60, 186, 84, 189, 178, 246, 64, 44, 151, 162, 169, 25, 48, 153, 254, 66, 230, 218, 197, 105, 204, 221, 45, 11, 211, 217, 67, 46, 233, 117, 59, 19, 97, 178, 196, 6, 6, 92, 30, 147, 141, 123, 21, 119, 115, 94, 90, 84, 117, 188, 26, 28, 183, 119, 101, 14, 145, 90, 178, 9, 67, 35, 127, 32, 253, 139, 184, 172, 110, 109, 180, 52, 32, 247, 105, 34, 166, 141, 27, 124, 9, 113, 211, 234, 24, 140, 239, 44, 198, 226, 177, 245, 238, 54, 196, 205, 71, 216, 195, 0, 120, 163, 236, 225, 195, 237, 142, 180, 215, 24, 222, 51, 6, 234, 194, 41, 55, 26, 131, 175, 9, 76, 24, 4, 118, 163, 84, 89, 30, 9, 248, 33, 158, 34, 223, 16, 138, 230, 57, 79, 126, 73, 50, 18, 191, 194, 138, 178, 193, 4, 111, 88, 207, 210, 86, 24, 42, 31, 163, 238, 96, 249, 241, 42, 31, 92, 181, 235, 177, 63, 97, 228, 76, 153, 114, 246, 122, 210, 104, 29, 221, 196, 114, 187, 168, 75, 47, 187, 143, 186, 248, 33, 7, 210, 29, 178, 40, 34, 64, 139, 72, 31, 63, 17, 97, 35, 50, 209, 17, 164, 34, 255, 227, 64, 68, 65, 218, 193, 177, 106, 187, 14, 149, 220, 52, 209, 165, 202, 94, 132, 102, 69, 0, 39, 42, 189, 105, 114, 49, 5, 252, 181, 184, 226, 26, 214, 189, 58, 54, 51, 188, 237, 139, 235, 14, 116, 155, 248, 240, 158, 246, 218, 9, 104, 225, 45, 64, 72, 30, 104, 43, 16, 85, 199, 43, 127, 50, 0, 217, 74, 17, 39, 81, 248, 57, 45, 116, 212, 236, 31, 43, 54, 46, 34, 80, 214, 175, 39, 61, 104, 240, 226, 88, 131, 1, 83, 106, 74, 67, 198, 69, 120, 225, 115, 87, 153, 130, 93, 244, 38, 174, 101, 217, 49, 82, 177, 201, 94, 62, 130, 198, 197, 42, 204, 212, 17, 191, 81, 236, 44, 188, 248, 104, 19, 138, 176, 162, 160, 150, 8, 23, 45, 22, 36, 154, 10, 214, 190, 33, 26, 161, 82, 94, 146, 180, 136, 78, 123, 20, 16, 68, 153, 166, 212, 81, 251, 106, 171, 137, 181, 102, 104, 220, 71, 2, 138, 202, 134, 246, 49, 148, 104, 240, 24, 212, 15, 120, 87, 86, 128, 20, 10, 162, 208, 170, 102, 110, 185, 94, 44, 169, 6, 58, 26, 129, 70, 66, 214, 74, 168, 27, 240, 165, 194, 236, 96, 108, 86, 218, 138, 240, 146, 201, 32, 40, 87, 22, 21, 33, 23, 178, 119, 31, 195, 19, 200, 223, 147, 41, 227, 180, 87, 22, 61, 149, 61, 228, 143, 128, 63, 16, 241, 239, 7, 40, 250, 221, 5, 217, 63, 88, 32, 2, 222, 5, 211, 34, 14, 94, 28, 107, 145, 63, 122, 129, 222, 121, 66, 227, 79, 212, 164, 17, 12, 64, 231, 117, 14, 4, 104, 56, 224, 129, 61, 145, 164, 15, 251, 16, 51, 155, 149, 233, 216, 157, 104, 7, 166, 29, 51, 138, 245, 163, 113, 232, 48, 225, 253, 26, 15, 209, 191, 207, 50, 34, 162, 233, 5, 198, 68, 27, 55, 247, 115, 72, 120, 247, 62, 203, 136, 240, 150, 59, 13, 136, 217, 226, 114, 143, 46, 69, 79, 60, 182, 135, 94, 204, 249, 247, 176, 186, 239, 93, 81, 27, 36, 37, 148, 148, 199, 162, 60, 163, 173, 215, 147, 152, 168, 118, 207, 140, 37, 171, 186, 164, 27, 133, 234, 11, 104, 157, 154, 67, 83, 196, 132, 17, 88, 202, 129, 20, 127, 52, 12, 107, 92, 105, 21, 215, 188, 254, 182, 75, 183, 244, 24, 78, 217, 218, 76, 251, 1, 132, 225, 146, 76, 184, 109, 142, 206, 155, 152, 244, 194, 87, 105, 50, 149, 161, 211, 184, 32, 218, 32, 224, 203, 83, 52, 133, 131, 25, 160, 141, 104, 114, 242, 203, 32, 165, 145, 208, 115, 237, 42, 84, 227, 199, 94, 212, 155, 110, 112, 132, 80, 17, 91, 66, 157, 23, 225, 144, 63, 224, 120, 50, 95, 151, 225, 159, 6, 199, 222, 243, 142, 135, 162, 163, 96, 8, 113, 168, 36, 181, 27, 2, 132, 18, 135, 137, 248, 1, 195, 169, 34, 47, 200, 138, 46, 110, 208, 15, 46, 156, 146, 9, 89, 28, 132, 132, 87, 38, 36, 147, 89, 118, 175, 45, 193, 26, 78, 7, 25, 54, 117, 110, 70, 138, 69, 23, 125, 28, 175, 91, 190, 179, 162, 220, 162, 111, 95, 228, 185, 133, 60, 243, 243, 147, 193, 197, 188, 162, 165, 71, 146, 241, 10, 194, 85, 10, 164, 237, 143, 30, 28, 62, 143, 208, 191, 137, 207, 146, 254, 52, 61, 79, 171, 174, 242, 46, 86, 94, 231, 113, 154, 137, 16, 110, 179, 247, 38, 192, 41, 157, 96, 202, 60, 182, 28, 175, 135, 113, 118, 162, 78, 81, 254, 245, 135, 27, 18, 121, 232, 160, 79, 40, 52, 90, 119, 87, 226, 155, 187, 118, 195, 2, 191, 131, 24, 224, 41, 248, 149, 245, 79, 227, 95, 190, 142, 62, 16, 60, 47, 85, 130, 103, 129, 30, 60, 166, 181, 172, 153, 60, 88, 109, 233, 194, 138, 244, 137, 223, 147, 215, 186, 110, 72, 210, 127, 46, 242, 217, 189, 150, 116, 232, 224, 61, 149, 244, 230, 174, 233, 33, 189, 117, 130, 221, 86, 154, 169, 12, 155, 179, 44, 68, 117, 221, 43, 75, 227, 115, 234, 155, 86, 198, 193, 110, 201, 55, 228, 146, 201, 235, 56, 45, 202, 254, 34, 122, 99, 121, 226, 77, 145, 113, 165, 225, 238, 74, 119, 99, 207, 150, 38, 220, 75, 151, 167, 1, 186, 175, 100, 73, 162, 53, 80, 87, 156, 220, 144, 140, 169, 20, 19, 188, 250, 219, 219, 35, 108, 52, 68, 252, 190, 249, 207, 100, 239, 238, 163, 15, 173, 185, 107, 203, 157, 156, 23, 155, 125, 23, 17, 203, 229, 76, 115, 230, 56, 97, 237, 54, 121, 163, 135, 204, 74, 23, 192, 239, 14, 10, 30, 70, 21, 224, 232, 182, 158, 144, 127, 83, 239, 115, 174, 198, 235, 130, 30, 100, 230, 117, 145, 111, 185, 136, 66, 170, 160, 102, 119, 58, 168, 22, 36, 204, 46, 122, 65, 87, 193, 138, 161, 85, 42, 102, 146, 48, 200, 97, 87, 31, 15, 168, 14, 242, 125, 112, 147, 139, 204, 27, 43, 1, 69, 186, 69, 74, 136, 26, 102, 28, 130, 38, 169, 13, 235, 1, 169, 68, 83, 29, 83, 57, 32, 1, 195, 141, 249, 167, 87, 28, 166, 254, 16, 228, 103, 77, 139, 53, 47, 244, 48, 77, 101, 159, 228, 48, 170, 157, 38, 39, 225, 178, 39, 221, 50, 71, 70, 168, 0, 133, 174, 63, 159, 114, 29, 51, 203, 252, 107, 126, 227, 241, 143, 118, 33, 9, 34, 11, 16, 48, 181, 216, 59, 199, 49, 180, 71, 250, 0, 42, 177, 68, 22, 167, 107, 56, 188, 86, 218, 37, 88, 47, 33, 154, 164, 34, 162, 182, 158, 26, 234, 6, 34, 21, 157, 188, 28, 169, 238, 150, 113, 29, 103, 65, 184, 6, 251, 133, 93, 164, 89, 64, 137, 55, 233, 61, 126, 119, 215, 221, 167, 76, 131, 3, 217, 71, 29, 55, 172, 166, 8, 196, 220, 234, 27, 176, 234, 8, 41, 110, 201, 187, 31, 148, 92, 237, 76, 75, 135, 152, 246, 92, 190, 98, 145, 185, 65, 100, 33, 61, 252, 253, 160, 229, 117, 185, 18, 153, 123, 206, 90, 134, 227, 239, 201, 192, 208, 148, 175, 51, 64, 136, 7, 131, 168, 199, 159, 122, 16, 135, 42, 193, 246, 84, 110, 60, 122, 65, 114, 22, 159, 39, 42, 126, 142, 61, 194, 39, 249, 74, 252, 177, 178, 200, 74, 184, 60, 147, 172, 68, 23, 202, 233, 53, 204, 121, 121, 34, 161, 157, 39, 101, 25, 159, 112, 128, 226, 37, 255, 191, 13, 142, 64, 98, 37, 244, 144, 235, 214, 123, 61, 43, 132, 132, 149, 82, 29, 224, 71, 2, 37, 88, 167, 156, 234, 14, 98, 89, 14, 116, 61, 234, 61, 138, 122, 236, 15, 7, 20, 26, 5, 72, 200, 242, 166, 136, 211, 41, 123, 102, 11, 55, 246, 39, 161, 193, 200, 141, 215, 0, 19, 112, 34, 16, 124, 192, 102, 220, 53, 64, 224, 255, 101, 61, 43, 94, 210, 27, 195, 44, 71, 124, 52, 47, 103, 9, 163, 218, 132, 198, 3, 219, 57, 113, 112, 140, 63, 132, 233, 176, 87, 186, 2, 254, 230, 141, 45, 116, 207, 71, 130, 196, 233, 250, 129, 96, 28, 26, 142, 195, 173, 30, 243, 163, 71, 122, 213, 147, 239, 29, 27, 210, 194, 145, 137, 58, 216, 254, 147, 0, 174, 225, 52, 174, 160, 143, 116, 120, 160, 11, 125, 191, 60, 156, 103, 224, 133, 181, 1, 91, 194, 243, 240, 123, 107, 15, 193, 172, 49, 59, 68, 147, 71, 158, 219, 157, 249, 48, 181, 236, 173, 46, 6, 89, 35, 80, 9, 220, 61, 113, 73, 73, 162, 172, 3, 151, 153, 172, 200, 245, 251, 194, 77, 40, 168, 107, 113, 118, 18, 196, 99, 45, 124, 102, 134, 209, 199, 4, 110, 5, 199, 216, 71, 18, 238, 11, 203, 224, 208, 204, 229, 169, 32, 62, 130, 159, 74, 249, 240, 141, 196, 15, 144, 166, 189, 17, 129, 90, 182, 43, 236, 67, 36, 159, 147, 241, 96, 47, 180, 152, 49, 92, 208, 72, 1, 210, 253, 19, 72, 150, 192, 49, 53, 185, 220, 153, 253, 6, 167, 237, 101, 13, 229, 57, 229, 71, 135, 85, 90, 100, 169, 127, 235, 197, 207, 192, 198, 234, 218, 1, 37, 37, 179, 53, 44, 44, 201, 43, 245, 167, 121, 80, 45, 124, 152, 199, 144, 69, 154, 196, 45, 143, 65, 121, 252, 143, 193, 243, 62, 234, 204, 13, 239, 148, 235, 118, 122, 28, 109, 203, 97, 245, 39, 42, 163, 208, 55, 241, 9, 4, 235, 147, 250, 105, 242, 152, 213, 102, 99, 8, 3, 14, 21, 81, 63, 137, 240, 207, 85, 222, 5, 188, 118, 240, 31, 16, 242, 56, 189, 100, 9, 203, 106, 52, 233, 174, 125, 7, 129, 68, 246, 239, 180, 228, 107, 153, 65, 116, 46, 78, 68, 24, 237, 137, 95, 200, 68, 222, 162, 172, 145, 160, 115, 117, 250, 130, 129, 149, 103, 69, 56, 208, 70, 247, 14, 217, 30, 182, 90, 82, 58, 3, 106, 188, 108, 221, 64, 234, 194, 54, 96, 246, 201, 0, 208, 61, 21, 1, 80, 28, 7, 66, 109, 34, 40, 52, 101, 54, 63, 69, 88, 228, 231, 56, 177, 108, 223, 109, 196, 140, 178, 7, 3, 196, 37, 214, 17, 18, 43, 35, 68, 123, 2, 59, 253, 87, 138, 216, 58, 43, 231, 117, 194, 155, 131, 45, 30, 238, 211, 242, 16, 224, 63, 200, 80, 201, 215, 123, 50, 112, 30, 86, 71, 240, 23, 86, 72, 112, 144, 150, 45, 84, 107, 79, 64, 41, 248, 250, 24, 20, 198, 88, 143, 152, 104, 250, 221, 59, 126, 62, 247, 221, 187, 71, 188, 41, 33, 65, 84, 158, 154, 143, 123, 57, 91, 62, 162, 145, 144, 156, 200, 108, 33, 124, 13, 207, 137, 95, 36, 64, 23, 177, 60, 194, 201, 248, 194, 203, 92, 17, 39, 131, 106, 129, 145, 97, 104, 195, 19, 20, 244, 74, 177, 218, 173, 117, 110, 183, 164, 51, 29, 253, 115, 116, 70, 170, 57, 169, 41, 166, 190, 234, 149, 123, 138, 234, 156, 158, 159, 66, 12, 198, 26, 17, 83, 51, 190, 102, 177, 27, 255, 125, 236, 204, 131, 64, 27, 211, 72, 152, 64, 26, 142, 235, 198, 45, 148, 95, 219, 153, 157, 120, 242, 219, 3, 239, 201, 211, 0, 155, 28, 72, 133, 162, 189, 11, 205, 12, 127, 26, 151, 251, 89, 89, 197, 217, 88, 101, 146, 166, 83, 13, 202, 55, 153, 150, 175, 213, 33, 245, 131, 99, 193, 228, 102, 84, 245, 167, 126, 207, 168, 91, 42, 39, 43, 104, 146, 65, 205, 90, 6, 3, 230, 1, 197, 73, 23, 194, 199, 37, 182, 132, 193, 160, 125, 158, 195, 166, 90, 58, 209, 138, 176, 105, 99, 86, 66, 32, 59, 178, 54, 94, 109, 171, 15, 109, 129, 95, 161, 59, 186, 178, 48, 25, 83, 31, 210, 214, 93, 51, 93, 14, 17, 121, 105, 176, 192, 41, 34, 31, 156, 54, 55, 206, 132, 186, 227, 57, 57, 132, 184, 214, 127, 112, 232, 0, 223, 62, 67, 24, 54, 88, 126, 104, 31, 46, 170, 59, 232, 137, 100, 175, 97, 64, 228, 98, 238, 254, 12, 73, 240, 128, 93, 251, 65, 209, 233, 94, 219, 157, 102, 111, 121, 238, 149, 28, 20, 142, 92, 15, 149, 124, 143, 78, 179, 138, 217, 197, 82, 159, 157, 14, 192, 123, 52, 44, 58, 244, 186, 216, 160, 91, 145, 41, 11, 12, 55, 133, 208, 102, 160, 93, 228, 23, 58, 175, 167, 71, 216, 135, 96, 248, 228, 106, 32, 248, 151, 34, 117, 45, 65, 250, 252, 52, 189, 198, 185, 212, 118, 84, 245, 156, 62, 109, 160, 107, 56, 86, 139, 35, 227, 167, 237, 141, 89, 47, 55, 19, 255, 213, 108, 172, 232, 252, 23, 204, 12, 104, 19, 20, 134, 168, 103, 7, 76, 1, 205, 241, 44, 129, 226, 194, 106, 236, 0, 129, 64, 125, 92, 87, 43, 65, 194, 60, 226, 46, 151, 191, 93, 0, 115, 195, 22, 165, 96, 175, 61, 70, 240, 105, 194, 185, 168, 33, 254, 203, 91, 67, 239, 99, 250, 162, 145, 220, 26, 102, 249, 224, 139, 72, 210, 25, 72, 240, 250, 128, 95, 93, 201, 173, 58, 29, 68, 81, 191, 207, 8, 91, 76, 196, 101, 67, 19, 115, 32, 191, 159, 142, 0, 235, 18, 251, 53, 80, 24, 73, 92, 69, 4, 151, 0, 37, 222, 40, 140, 215, 101, 182, 213, 143, 94, 179, 93, 156, 108, 52, 169, 150, 110, 161, 192, 46, 51, 121, 212, 205, 137, 173, 255, 144, 161, 205, 255, 6, 173, 219, 38, 188, 93, 241, 255, 34, 194, 72, 132, 203, 100, 202, 68, 34, 40, 196, 40, 99, 88, 147, 28, 243, 164, 174, 18, 154, 233, 163, 115, 6, 226, 99, 123, 17, 15, 159, 99, 252, 28, 194, 45, 194, 209, 248, 25, 169, 23, 128, 83, 132, 110, 119, 102, 76, 147, 141, 173, 147, 83, 171, 125, 82, 154, 231, 37, 109, 123, 128, 234, 230, 132, 221, 119, 190, 208, 22, 21, 140, 247, 173, 147, 246, 54, 29, 240, 28, 161, 186, 19, 178, 78, 15, 220, 145, 172, 134, 181, 245, 205, 226, 80, 197, 19, 45, 67, 61, 56, 162, 11, 232, 109, 108, 4, 16, 140, 162, 247, 69, 18, 147, 140, 129, 30, 145, 14, 31, 88, 252, 34, 210, 139, 138, 180, 239, 32, 225, 157, 18, 233, 54, 29, 184, 171, 34, 189, 44, 97, 36, 170, 97, 99, 3, 210, 255, 110, 53, 204, 178, 126, 179, 185, 246, 68, 210, 109, 48, 154, 111, 251, 42, 55, 112, 52, 232, 142, 172, 116, 187, 97, 127, 183, 100, 237, 46, 172, 118, 245, 41, 167, 125, 35, 112, 129, 109, 38, 209, 222, 128, 147, 57, 84, 251, 21, 97, 115, 252, 69, 243, 58, 34, 66, 253, 241, 42, 67, 9, 12, 103, 16, 106, 112, 205, 86, 63, 246, 33, 172, 14, 150, 126, 195, 233, 168, 219, 160, 150, 150, 117, 202, 170, 89, 49, 89, 231, 176, 16, 87, 171, 238, 55, 28, 203, 50, 50, 176, 33, 72, 222, 229, 0, 83, 100, 139, 208, 178, 103, 49, 5, 254, 49, 158, 192, 40, 86, 228, 8, 162, 65, 71, 221, 129, 74, 131, 40, 104, 85, 255, 94, 133, 56, 38, 133, 133, 19, 31, 141, 178, 36, 117, 125, 221, 99, 150, 123, 176, 246, 159, 40, 11, 159, 168, 114, 215, 183, 129, 99, 84, 159, 203, 20, 174, 103, 77, 217, 169, 163, 205, 205, 205, 110, 131, 255, 214, 191, 237, 30, 60, 53, 117, 27, 164, 125, 241, 211, 28, 237, 100, 252, 134, 166, 169, 182, 199, 64, 108, 94, 247, 42, 101, 126, 116, 235, 139, 127, 245, 166, 199, 172, 69, 178, 254, 186, 225, 91, 224, 152, 153, 51, 210, 226, 108, 217, 151, 161, 254, 20, 67, 189, 186, 204, 177, 110, 62, 5, 231, 217, 55, 201, 38, 95, 134, 250, 206, 73, 117, 221, 218, 158, 173, 231, 208, 149, 152, 251, 89, 42, 113, 99, 196, 52, 227, 203, 86, 19, 104, 104, 185, 157, 57, 153, 240, 126, 179, 47, 155, 101, 226, 77, 81, 207, 139, 212, 13, 131, 28, 83, 81, 206, 177, 22, 129, 46, 140, 100, 231, 225, 211, 140, 128, 162, 255, 180, 134, 170, 91, 115, 40, 225, 187, 65, 212, 99, 125, 239, 145, 144, 126, 31, 209, 57, 122, 124, 81, 59, 208, 56, 29, 109, 189, 69, 63, 134, 111, 221, 121, 240, 37, 143, 244, 225, 70, 10, 0, 125, 31, 143, 207, 96, 46, 53, 183, 184, 88, 55, 59, 66, 143, 95, 6, 197, 231, 165, 136, 192, 120, 105, 34, 48, 24, 124, 253, 173, 115, 240, 5, 171, 220, 34, 226, 2, 225, 141, 190, 162, 27, 4, 123, 166, 147, 86, 32, 134, 205, 10, 6, 84, 23, 177, 196, 181, 176, 92, 38, 144, 7, 38, 41, 237, 88, 72, 225, 125, 157, 189, 147, 159, 7, 209, 75, 115, 130, 51, 158, 9, 21, 198, 202, 29, 114, 7, 7, 100, 86, 98, 0, 78, 166, 249, 251, 24, 232, 225, 249, 12, 149, 47, 78, 25, 58, 81, 159, 175, 162, 209, 106, 30, 130, 158, 196, 2, 136, 47, 105, 227, 217, 51, 214, 230, 21, 163, 133, 82, 148, 125, 141, 132, 191, 105, 180, 237, 69, 51, 77, 88, 126, 112, 209, 220, 89, 114, 37, 68, 205, 3, 73, 94, 184, 77, 115, 177, 4, 138, 14, 101, 209, 32, 164, 72, 176, 81, 109, 169, 33, 45, 229, 19, 25, 15, 199, 107, 53, 197, 250, 162, 70, 6, 4, 134, 59, 202, 106, 6, 129, 181, 37, 130, 235, 253, 159, 193, 219, 134, 101, 14, 123, 26, 22, 140, 109, 66, 80, 22, 9, 108, 66, 213, 219, 68, 53, 89, 56, 123, 2, 154, 22, 230, 93, 25, 17, 248, 79, 122, 188, 170, 230, 136, 105, 59, 206, 62, 168, 229, 105, 78, 93, 204, 210, 42, 53, 199, 175, 252, 12, 146, 9, 201, 218, 207, 170, 7, 219, 16, 62, 237, 15, 28, 197, 110, 86, 35, 43, 6, 16, 221, 61, 210, 238, 216, 6, 25, 145, 171, 127, 7, 212, 176, 61, 168, 33, 5, 165, 170, 233, 171, 90, 117, 253, 163, 32, 46, 33, 2, 50, 216, 111, 177, 232, 47, 83, 76, 5, 35, 108, 42, 5, 129, 9, 43, 63, 201, 145, 55, 94, 214, 21, 228, 19, 134, 18, 244, 110, 120, 198, 26, 29, 111, 134, 55, 53, 218, 220, 11, 15, 126, 230, 34, 159, 207, 126, 210, 217, 86, 208, 116, 160, 79, 34, 185, 177, 172, 188, 112, 104, 150, 145, 99, 244, 221, 67, 37, 127, 246, 148, 35, 106, 171, 175, 169, 72, 41, 227, 49, 71, 123, 90, 140, 150, 63, 243, 13, 195, 51, 223, 94, 20, 188, 140, 93, 219, 50, 198, 94, 203, 146, 139, 104, 207, 236, 71, 156, 181, 55, 83, 45, 42, 238, 24, 137, 20, 83, 81, 147, 210, 119, 173, 211, 51, 36, 213, 242, 38, 217, 224, 4, 206, 239, 158, 229, 246, 22, 107, 13, 205, 148, 166, 158, 239, 102, 236, 200, 15, 172, 196, 192, 6, 209, 145, 200, 242, 183, 230, 21, 98, 79, 166, 31, 213, 166, 190, 255, 182, 148, 55, 10, 90, 23, 19, 241, 255, 159, 33, 71, 181, 73, 237, 16, 207, 136, 228, 188, 154, 159, 191, 79, 138, 119, 105, 201, 22, 83, 140, 204, 253, 108, 126, 110, 248, 89, 154, 196, 236, 157, 56, 248, 147, 241, 194, 246, 129, 77, 159, 140, 66, 149, 13, 254, 127, 174, 27, 253, 77, 190, 138, 95, 45, 179, 189, 85, 46, 25, 231, 254, 182, 84, 74, 96, 1, 210, 215, 36, 123, 221, 186, 85, 180, 219, 238, 110, 180, 203, 38, 118, 8, 118, 0, 125, 195, 212, 9, 19, 101, 196, 38, 164, 207, 131, 44, 207, 9, 98, 99, 186, 138, 167, 182, 154, 1, 216, 232, 247, 183, 163, 111, 191, 141, 190, 123, 176, 6, 119, 57, 174, 193, 174, 174, 130, 241, 245, 215, 250, 145, 189, 37, 229, 232, 81, 54, 110, 66, 24, 198, 208, 125, 151, 109, 16, 198, 121, 147, 139, 159, 170, 224, 154, 31, 148, 97, 235, 32, 52, 89, 164, 30, 160, 48, 208, 152, 182, 59, 184, 200, 148, 56, 254, 156, 148, 227, 34, 157, 49, 133, 87, 226, 83, 87, 34, 165, 140, 190, 16, 244, 192, 168, 188, 228, 74, 93, 171, 123, 152, 28, 67, 120, 217, 187, 252, 34, 251, 149, 189, 237, 171, 3, 101, 220, 232, 49, 96, 193, 84, 250, 72, 148, 164, 206, 34, 54, 144, 151, 139, 2, 80, 169, 4, 118, 228, 87, 121, 39, 111, 74, 47, 138, 55, 250, 18, 170, 136, 52, 163, 200, 88, 135, 86, 217, 183, 250, 126, 138, 99, 133, 84, 15, 74, 166, 228, 245, 57, 75, 154, 201, 104, 173, 78, 151, 161, 110, 74, 109, 8, 111, 172, 253, 10, 57, 86, 168, 172, 127, 84, 208, 57, 51, 115, 247, 157, 172, 140, 233, 125, 66, 139, 234, 65, 146, 215, 3, 58, 160, 247, 203, 103, 151, 108, 94, 41, 83, 121, 166, 146, 0, 38, 39, 40, 129, 203, 113, 75, 169, 93, 211, 3, 253, 93, 149, 191, 200, 217, 60, 145, 56, 105, 137, 240, 18, 161, 230, 232, 202, 193, 102, 165, 179, 223, 28, 120, 91, 224, 211, 2, 235, 41, 65, 220, 190, 172, 214, 173, 118, 26, 151, 136, 1, 250, 255, 36, 213, 197, 199, 254, 63, 197, 114, 138, 214, 255, 74, 0, 224, 68, 102, 227, 2, 179, 119, 231, 193, 16, 217, 15, 252, 102, 155, 3, 94, 90, 111, 250, 188, 45, 49, 219, 112, 241, 145, 192, 134, 23, 35, 40, 57, 19, 181, 164, 65, 41, 209, 83, 137, 133, 68, 205, 70, 180, 70, 10, 173, 50, 136, 150, 40, 45, 100, 66, 162, 5, 121, 147, 6, 81, 201, 127, 16, 85, 194, 10, 70, 190, 235, 133, 109, 211, 78, 86, 13, 152, 117, 15, 30, 8, 132, 42, 152, 43, 240, 196, 32, 52, 130, 158, 89, 32, 123, 19, 62, 227, 11, 92, 237, 124, 147, 115, 142, 247, 91, 201, 141, 232, 30, 179, 78, 223, 228, 138, 125, 152, 134, 19, 41, 172, 152, 169, 170, 83, 89, 137, 222, 107, 14, 227, 72, 139, 238, 10, 123, 23, 52, 2, 127, 216, 186, 220, 222, 218, 138, 254, 100, 127, 183, 134, 226, 207, 182, 60, 78, 169, 207, 85, 139, 142, 137, 103, 88, 64, 174, 112, 19, 216, 225, 106, 209, 228, 47, 152, 224, 39, 139, 19, 252, 164, 153, 224, 39, 247, 139, 224, 39, 136, 204, 134, 248, 53, 4, 127, 145, 231, 103, 243, 25, 226, 240, 86, 132, 254, 172, 84, 154, 228, 216, 177, 38, 230, 196, 208, 108, 168, 54, 189, 37, 21, 173, 121, 145, 207, 102, 122, 2, 84, 111, 96, 189, 252, 181, 32, 49, 78, 35, 129, 230, 185, 163, 109, 157, 245, 91, 101, 254, 245, 223, 39, 242, 17, 13, 161, 101, 86, 156, 56, 51, 34, 123, 43, 216, 80, 57, 17, 101, 189, 85, 229, 79, 10, 14, 223, 47, 95, 134, 175, 211, 240, 13, 111, 203, 240, 213, 27, 113, 51, 67, 70, 51, 172, 237, 41, 70, 1, 24, 95, 27, 162, 154, 175, 219, 58, 65, 115, 85, 21, 229, 110, 54, 145, 126, 56, 73, 90, 5, 134, 124, 5, 114, 15, 183, 236, 53, 136, 162, 189, 244, 35, 74, 202, 43, 87, 201, 69, 145, 86, 160, 164, 31, 69, 171, 171, 46, 180, 173, 135, 218, 167, 146, 48, 174, 19, 123, 55, 129, 162, 67, 93, 116, 156, 103, 199, 233, 201, 188, 174, 240, 246, 154, 117, 234, 24, 103, 40, 250, 67, 233, 80, 11, 219, 82, 191, 217, 150, 111, 90, 35, 213, 26, 165, 143, 30, 246, 56, 40, 36, 187, 89, 19, 131, 61, 184, 3, 62, 88, 233, 251, 121, 5, 174, 50, 144, 224, 113, 101, 150, 164, 203, 185, 144, 27, 53, 135, 244, 6, 126, 27, 80, 31, 78, 17, 87, 139, 184, 80, 2, 202, 132, 72, 196, 35, 63, 127, 235, 222, 26, 154, 52, 121, 247, 126, 240, 122, 247, 182, 49, 89, 101, 34, 123, 71, 64, 148, 139, 76, 166, 221, 80, 23, 69, 232, 245, 183, 246, 154, 169, 31, 98, 134, 70, 174, 86, 113, 46, 202, 122, 9, 61, 233, 25, 38, 235, 177, 149, 34, 70, 70, 69, 215, 113, 12, 254, 124, 130, 62, 109, 154, 74, 140, 122, 220, 62, 120, 4, 127, 126, 192, 254, 198, 30, 230, 202, 14, 176, 113, 53, 1, 125, 155, 67, 31, 110, 17, 232, 34, 193, 106, 3, 88, 174, 49, 212, 218, 86, 16, 13, 181, 132, 54, 160, 17, 85, 85, 176, 137, 110, 73, 41, 145, 14, 141, 249, 250, 165, 192, 136, 62, 61, 228, 125, 218, 166, 125, 98, 195, 214, 220, 200, 182, 106, 68, 15, 50, 106, 228, 36, 65, 251, 18, 30, 43, 21, 228, 65, 214, 91, 245, 187, 43, 45, 238, 253, 254, 7, 97, 191, 246, 172, 5, 57, 199, 183, 236, 132, 111, 233, 193, 183, 12, 225, 91, 26, 124, 203, 206, 248, 150, 126, 124, 5, 82, 214, 180, 77, 63, 12, 241, 124, 110, 131, 222, 38, 110, 85, 169, 206, 91, 105, 205, 82, 173, 48, 212, 210, 78, 43, 80, 60, 254, 138, 9, 49, 106, 88, 207, 170, 119, 218, 220, 208, 136, 247, 145, 141, 46, 254, 60, 20, 123, 132, 166, 168, 167, 132, 252, 136, 13, 24, 143, 127, 198, 237, 17, 189, 239, 194, 19, 165, 165, 115, 131, 45, 66, 40, 233, 154, 231, 11, 11, 155, 74, 29, 65, 33, 135, 63, 122, 212, 48, 3, 11, 195, 86, 51, 32, 154, 249, 174, 51, 141, 242, 45, 124, 203, 164, 81, 234, 25, 117, 152, 167, 168, 114, 208, 133, 125, 202, 103, 98, 71, 159, 135, 158, 216, 174, 71, 203, 101, 56, 131, 13, 218, 80, 216, 74, 32, 100, 5, 234, 52, 132, 171, 136, 146, 155, 199, 6, 25, 26, 189, 18, 100, 41, 181, 237, 56, 19, 27, 131, 246, 32, 251, 251, 252, 119, 225, 115, 58, 24, 68, 175, 27, 60, 173, 212, 73, 245, 90, 37, 235, 114, 205, 227, 47, 251, 121, 214, 126, 158, 32, 39, 242, 128, 141, 121, 172, 67, 95, 46, 48, 110, 209, 190, 29, 93, 95, 158, 133, 237, 195, 179, 176, 93, 120, 214, 100, 15, 158, 9, 59, 208, 44, 11, 173, 221, 66, 72, 82, 199, 62, 190, 53, 19, 89, 211, 150, 96, 72, 36, 62, 211, 94, 160, 45, 105, 12, 244, 121, 90, 38, 239, 228, 121, 166, 126, 158, 61, 23, 79, 70, 226, 102, 162, 72, 48, 128, 69, 126, 175, 75, 155, 47, 91, 129, 100, 249, 178, 161, 64, 222, 124, 216, 94, 150, 91, 244, 120, 111, 89, 54, 49, 8, 109, 61, 43, 248, 130, 183, 117, 54, 170, 234, 52, 81, 221, 25, 136, 100, 188, 242, 151, 207, 183, 103, 122, 174, 58, 130, 170, 195, 208, 103, 168, 114, 68, 192, 217, 95, 201, 64, 246, 17, 152, 53, 176, 228, 21, 219, 127, 192, 243, 191, 117, 168, 207, 39, 38, 185, 233, 139, 125, 49, 171, 61, 80, 146, 30, 135, 73, 153, 79, 63, 36, 253, 61, 146, 131, 21, 77, 63, 254, 16, 79, 94, 119, 19, 208, 30, 68, 154, 242, 26, 109, 143, 15, 132, 94, 36, 173, 152, 80, 252, 233, 99, 66, 145, 254, 51, 69, 83, 226, 67, 114, 119, 145, 0, 34, 3, 179, 232, 137, 151, 0, 13, 121, 200, 2, 109, 5, 25, 151, 78, 106, 34, 46, 237, 69, 90, 114, 243, 128, 251, 105, 94, 164, 103, 201, 243, 188, 96, 90, 191, 52, 123, 87, 90, 32, 196, 246, 225, 155, 92, 30, 188, 98, 5, 164, 254, 208, 171, 93, 40, 241, 52, 234, 127, 183, 181, 21, 125, 27, 49, 11, 57, 124, 66, 124, 56, 252, 43, 17, 221, 41, 67, 67, 78, 37, 194, 99, 196, 64, 173, 145, 73, 35, 229, 211, 8, 251, 163, 54, 43, 205, 70, 165, 71, 215, 1, 60, 54, 125, 242, 185, 252, 40, 117, 76, 6, 248, 76, 136, 161, 28, 105, 252, 158, 136, 126, 21, 23, 60, 136, 67, 6, 255, 241, 35, 98, 204, 28, 211, 39, 207, 88, 109, 226, 208, 208, 106, 64, 84, 236, 18, 36, 170, 106, 88, 19, 182, 114, 26, 144, 38, 27, 172, 136, 191, 232, 168, 188, 255, 37, 245, 254, 183, 167, 63, 200, 110, 110, 242, 110, 234, 215, 111, 242, 81, 62, 47, 198, 137, 213, 28, 181, 36, 218, 94, 177, 209, 134, 118, 114, 75, 108, 191, 220, 207, 166, 41, 63, 240, 249, 2, 106, 105, 184, 100, 52, 240, 62, 152, 250, 48, 86, 250, 91, 15, 21, 105, 32, 162, 163, 131, 148, 125, 195, 0, 61, 108, 30, 32, 17, 219, 125, 241, 134, 191, 86, 140, 239, 30, 74, 124, 26, 109, 171, 70, 116, 105, 235, 204, 161, 90, 37, 122, 208, 212, 85, 194, 38, 181, 131, 235, 246, 32, 66, 213, 208, 162, 22, 207, 39, 24, 151, 74, 119, 225, 211, 49, 158, 30, 184, 110, 204, 199, 29, 92, 76, 43, 201, 28, 233, 251, 229, 107, 102, 241, 37, 19, 161, 42, 44, 185, 100, 6, 27, 121, 35, 149, 20, 143, 36, 65, 154, 73, 54, 255, 35, 45, 44, 223, 62, 106, 210, 142, 54, 63, 71, 81, 121, 145, 242, 124, 253, 128, 166, 210, 139, 250, 100, 26, 163, 255, 214, 35, 107, 242, 80, 148, 176, 181, 186, 226, 104, 51, 152, 59, 6, 202, 112, 97, 40, 92, 68, 74, 182, 142, 194, 224, 182, 175, 15, 78, 62, 12, 9, 220, 7, 75, 132, 43, 31, 182, 73, 3, 15, 111, 162, 1, 249, 240, 128, 180, 244, 221, 141, 182, 36, 31, 30, 146, 38, 191, 255, 52, 77, 202, 135, 239, 72, 219, 127, 249, 196, 109, 203, 135, 239, 9, 18, 63, 124, 46, 36, 228, 195, 95, 8, 54, 127, 253, 236, 216, 200, 135, 31, 8, 90, 195, 197, 53, 202, 210, 241, 146, 15, 127, 165, 8, 46, 65, 89, 45, 29, 65, 5, 144, 234, 193, 225, 50, 21, 225, 242, 81, 85, 79, 90, 201, 178, 245, 75, 204, 22, 36, 22, 210, 218, 130, 104, 194, 214, 61, 239, 165, 12, 171, 73, 87, 199, 166, 108, 250, 58, 174, 77, 149, 79, 222, 131, 206, 73, 104, 71, 90, 117, 204, 217, 148, 182, 174, 61, 162, 70, 84, 139, 93, 70, 219, 220, 35, 253, 11, 110, 144, 251, 208, 241, 118, 232, 52, 46, 151, 131, 187, 199, 246, 18, 21, 60, 70, 23, 107, 212, 53, 183, 36, 120, 175, 145, 143, 119, 64, 211, 76, 27, 138, 254, 1, 242, 245, 39, 186, 217, 14, 193, 54, 83, 187, 14, 53, 26, 231, 178, 199, 34, 128, 130, 163, 63, 154, 243, 187, 46, 221, 78, 13, 44, 235, 221, 166, 154, 168, 114, 132, 106, 208, 236, 15, 95, 29, 38, 39, 207, 46, 103, 207, 167, 241, 73, 73, 34, 29, 193, 186, 61, 12, 122, 200, 14, 235, 216, 247, 176, 238, 180, 241, 33, 177, 159, 181, 119, 164, 215, 83, 141, 28, 110, 242, 75, 18, 38, 233, 216, 108, 200, 201, 98, 235, 172, 220, 164, 135, 201, 120, 184, 41, 78, 108, 121, 10, 158, 88, 5, 211, 147, 44, 47, 146, 189, 184, 76, 60, 133, 83, 171, 240, 57, 251, 0, 87, 58, 250, 202, 158, 91, 101, 39, 121, 181, 59, 245, 97, 80, 90, 5, 231, 89, 58, 206, 39, 62, 144, 115, 127, 73, 182, 28, 245, 145, 224, 131, 85, 186, 172, 210, 241, 217, 149, 167, 224, 85, 207, 226, 6, 147, 136, 202, 13, 254, 116, 24, 65, 198, 164, 30, 195, 27, 26, 143, 42, 138, 122, 238, 33, 189, 121, 134, 153, 65, 58, 166, 66, 248, 124, 100, 243, 140, 0, 92, 216, 180, 115, 159, 99, 76, 75, 240, 87, 120, 99, 165, 247, 223, 112, 179, 167, 130, 182, 46, 127, 243, 98, 117, 228, 49, 215, 116, 154, 251, 82, 49, 105, 118, 39, 31, 224, 110, 15, 241, 101, 31, 130, 211, 251, 35, 121, 167, 53, 114, 92, 105, 239, 85, 57, 159, 205, 132, 219, 59, 46, 248, 94, 128, 88, 123, 203, 248, 247, 145, 90, 37, 126, 253, 181, 180, 10, 44, 55, 135, 104, 230, 29, 176, 202, 235, 60, 205, 170, 93, 166, 27, 76, 115, 79, 163, 173, 203, 99, 246, 111, 133, 94, 211, 33, 160, 175, 71, 67, 246, 31, 105, 223, 210, 165, 208, 221, 151, 224, 168, 235, 139, 13, 9, 51, 202, 197, 101, 112, 152, 139, 203, 218, 107, 179, 46, 235, 6, 154, 213, 197, 35, 61, 194, 35, 40, 81, 80, 13, 178, 246, 102, 85, 122, 158, 254, 14, 110, 26, 129, 170, 139, 0, 102, 133, 134, 35, 146, 197, 229, 32, 82, 158, 15, 115, 122, 150, 213, 91, 93, 237, 11, 16, 50, 12, 201, 56, 71, 168, 222, 145, 173, 177, 14, 253, 67, 136, 174, 93, 119, 184, 37, 110, 58, 196, 239, 126, 216, 178, 157, 183, 162, 43, 191, 200, 67, 168, 140, 246, 172, 155, 28, 185, 209, 0, 3, 247, 237, 228, 139, 170, 114, 43, 225, 217, 101, 50, 22, 245, 236, 249, 0, 141, 43, 235, 249, 197, 235, 152, 205, 61, 170, 160, 127, 248, 173, 98, 154, 11, 28, 41, 43, 46, 145, 152, 233, 204, 26, 62, 134, 77, 179, 241, 116, 62, 225, 102, 22, 84, 0, 69, 211, 179, 247, 145, 5, 6, 158, 142, 184, 132, 110, 223, 204, 188, 199, 71, 161, 125, 133, 15, 98, 51, 135, 117, 109, 26, 151, 213, 190, 58, 182, 162, 228, 119, 23, 206, 164, 234, 107, 156, 50, 245, 41, 112, 194, 93, 79, 118, 222, 190, 169, 148, 146, 162, 140, 117, 64, 218, 108, 175, 139, 83, 87, 76, 124, 184, 20, 61, 138, 118, 49, 47, 136, 115, 138, 48, 104, 85, 65, 134, 134, 67, 53, 126, 22, 143, 115, 122, 151, 25, 228, 3, 93, 25, 97, 100, 224, 145, 203, 147, 165, 139, 28, 81, 69, 59, 225, 49, 181, 12, 135, 83, 18, 162, 17, 148, 5, 192, 237, 229, 87, 159, 6, 152, 46, 250, 8, 181, 188, 174, 243, 144, 241, 255, 103, 235, 235, 158, 149, 68, 59, 185, 210, 204, 237, 140, 118, 71, 14, 144, 91, 19, 140, 26, 160, 198, 148, 34, 175, 225, 141, 89, 94, 166, 50, 39, 163, 64, 118, 148, 196, 197, 248, 148, 153, 99, 18, 77, 155, 162, 48, 52, 166, 210, 19, 72, 45, 215, 145, 89, 112, 127, 104, 155, 47, 216, 23, 158, 153, 182, 63, 66, 74, 17, 49, 214, 104, 254, 94, 104, 100, 24, 30, 133, 5, 194, 49, 218, 208, 111, 151, 201, 113, 55, 205, 64, 114, 195, 72, 127, 120, 170, 198, 208, 179, 67, 184, 171, 170, 124, 108, 197, 123, 135, 201, 108, 26, 179, 5, 65, 41, 205, 135, 66, 252, 70, 17, 83, 159, 127, 102, 13, 51, 173, 208, 185, 162, 67, 241, 84, 246, 133, 149, 33, 233, 24, 81, 135, 116, 157, 180, 40, 171, 159, 115, 86, 164, 80, 227, 38, 50, 32, 242, 190, 57, 16, 205, 20, 96, 96, 81, 53, 102, 181, 161, 116, 166, 121, 173, 76, 166, 167, 56, 255, 128, 7, 13, 102, 10, 60, 183, 222, 250, 192, 227, 0, 188, 91, 104, 116, 192, 187, 32, 21, 53, 63, 203, 33, 125, 26, 125, 183, 69, 3, 254, 77, 48, 200, 79, 113, 41, 83, 84, 60, 147, 191, 158, 231, 76, 13, 156, 191, 159, 196, 62, 178, 24, 224, 154, 63, 21, 148, 53, 218, 128, 215, 180, 145, 136, 50, 114, 170, 214, 250, 164, 10, 168, 219, 129, 245, 102, 100, 191, 144, 221, 178, 95, 99, 108, 237, 111, 98, 86, 183, 94, 42, 196, 201, 107, 210, 207, 143, 43, 238, 83, 109, 175, 192, 182, 208, 122, 91, 162, 73, 17, 139, 140, 165, 132, 225, 242, 241, 180, 153, 117, 213, 82, 238, 13, 141, 115, 221, 140, 233, 73, 105, 73, 8, 230, 161, 97, 136, 126, 14, 237, 108, 60, 245, 39, 167, 87, 245, 232, 166, 144, 92, 184, 3, 181, 62, 106, 105, 168, 225, 124, 210, 36, 63, 157, 218, 97, 116, 220, 134, 154, 134, 164, 174, 57, 107, 60, 240, 104, 32, 194, 59, 35, 225, 31, 135, 0, 209, 195, 11, 2, 27, 153, 102, 106, 251, 87, 12, 18, 132, 94, 12, 172, 224, 190, 72, 180, 73, 31, 92, 252, 157, 225, 146, 175, 221, 46, 249, 214, 34, 30, 4, 68, 243, 188, 61, 212, 180, 221, 176, 183, 89, 167, 209, 182, 235, 26, 162, 168, 59, 173, 111, 204, 60, 138, 215, 46, 250, 20, 132, 171, 222, 63, 245, 34, 199, 111, 228, 82, 79, 93, 41, 82, 160, 188, 131, 29, 102, 147, 5, 69, 230, 200, 41, 111, 114, 253, 227, 36, 241, 242, 88, 148, 18, 199, 129, 70, 104, 125, 221, 10, 147, 226, 118, 135, 61, 139, 122, 243, 131, 181, 89, 70, 221, 189, 229, 145, 142, 91, 80, 153, 144, 147, 201, 33, 117, 193, 170, 52, 129, 194, 129, 253, 218, 44, 75, 104, 184, 44, 138, 124, 82, 196, 38, 225, 79, 122, 172, 229, 152, 28, 165, 40, 75, 67, 182, 23, 207, 152, 110, 73, 84, 30, 9, 158, 201, 227, 60, 190, 236, 27, 26, 241, 90, 58, 100, 97, 35, 26, 170, 11, 6, 209, 232, 240, 220, 239, 193, 193, 209, 197, 4, 72, 158, 125, 138, 87, 66, 118, 173, 179, 246, 34, 216, 72, 114, 154, 119, 105, 198, 48, 84, 105, 77, 36, 138, 194, 217, 166, 117, 169, 142, 139, 222, 90, 65, 138, 89, 112, 63, 215, 62, 224, 108, 51, 220, 227, 26, 213, 76, 114, 91, 76, 55, 26, 148, 150, 38, 102, 186, 137, 60, 253, 151, 135, 230, 43, 154, 118, 208, 189, 6, 240, 79, 210, 194, 59, 23, 233, 5, 157, 126, 163, 7, 172, 113, 126, 242, 235, 248, 128, 158, 71, 20, 178, 34, 133, 77, 198, 202, 8, 34, 126, 217, 159, 199, 79, 12, 22, 59, 176, 208, 194, 6, 17, 207, 27, 26, 207, 94, 105, 126, 59, 202, 244, 249, 85, 149, 250, 147, 125, 13, 28, 194, 129, 127, 154, 141, 160, 32, 178, 254, 148, 13, 163, 254, 114, 156, 226, 243, 100, 130, 88, 88, 114, 194, 9, 132, 226, 151, 120, 37, 73, 11, 6, 91, 215, 161, 255, 164, 188, 199, 140, 194, 163, 142, 233, 111, 219, 43, 154, 161, 159, 62, 241, 200, 178, 105, 218, 213, 2, 235, 230, 204, 13, 89, 227, 187, 80, 204, 186, 31, 82, 36, 121, 26, 89, 183, 89, 197, 112, 126, 228, 215, 48, 26, 224, 58, 22, 92, 119, 33, 230, 169, 204, 58, 106, 45, 213, 237, 148, 239, 170, 139, 150, 117, 35, 36, 196, 67, 136, 149, 86, 52, 80, 107, 43, 47, 9, 2, 150, 76, 80, 82, 141, 140, 34, 233, 228, 114, 137, 37, 146, 200, 226, 117, 141, 157, 177, 225, 98, 119, 90, 87, 31, 181, 2, 229, 83, 128, 103, 222, 85, 5, 7, 86, 21, 152, 126, 101, 87, 104, 220, 108, 179, 84, 135, 37, 186, 73, 154, 101, 45, 159, 64, 7, 13, 135, 186, 14, 232, 250, 58, 208, 178, 73, 252, 107, 215, 38, 174, 94, 8, 28, 179, 80, 177, 123, 154, 62, 88, 101, 208, 232, 61, 196, 239, 186, 219, 232, 147, 63, 161, 40, 41, 80, 191, 110, 118, 46, 168, 54, 112, 5, 106, 16, 105, 98, 125, 114, 39, 17, 169, 86, 200, 239, 53, 244, 11, 105, 93, 26, 86, 120, 43, 186, 103, 126, 12, 111, 160, 175, 219, 183, 183, 175, 230, 199, 246, 13, 116, 252, 193, 29, 233, 184, 249, 241, 224, 6, 168, 240, 240, 46, 82, 193, 252, 120, 184, 76, 146, 96, 127, 122, 71, 85, 221, 188, 231, 80, 87, 27, 47, 67, 91, 89, 110, 29, 225, 251, 172, 59, 226, 177, 177, 71, 188, 241, 88, 3, 117, 146, 161, 131, 134, 170, 113, 79, 224, 81, 139, 158, 217, 19, 92, 141, 125, 234, 248, 137, 152, 113, 195, 141, 166, 180, 154, 27, 222, 212, 84, 17, 70, 149, 248, 67, 89, 196, 227, 46, 178, 172, 150, 129, 139, 91, 216, 192, 122, 110, 79, 191, 220, 198, 146, 6, 86, 68, 54, 173, 220, 157, 24, 29, 158, 145, 185, 179, 188, 220, 94, 216, 16, 139, 234, 214, 230, 64, 139, 25, 191, 102, 190, 183, 103, 251, 26, 13, 209, 168, 31, 194, 218, 33, 160, 27, 244, 186, 154, 190, 246, 75, 56, 150, 111, 35, 221, 90, 182, 237, 121, 253, 51, 117, 68, 61, 218, 51, 249, 226, 125, 218, 190, 77, 125, 82, 143, 246, 124, 189, 120, 247, 30, 220, 210, 238, 169, 71, 123, 78, 94, 188, 167, 15, 111, 127, 79, 213, 163, 61, 235, 46, 208, 105, 236, 18, 12, 46, 5, 201, 170, 109, 171, 118, 213, 182, 211, 98, 226, 205, 116, 7, 50, 115, 4, 178, 190, 134, 86, 156, 235, 224, 7, 36, 179, 124, 235, 138, 219, 106, 130, 111, 57, 9, 182, 6, 252, 192, 55, 179, 163, 121, 145, 242, 207, 114, 230, 116, 239, 172, 183, 248, 198, 154, 217, 251, 88, 40, 128, 173, 83, 192, 204, 162, 158, 231, 79, 18, 55, 227, 236, 4, 116, 137, 145, 169, 241, 166, 45, 203, 151, 230, 58, 253, 188, 4, 211, 88, 155, 46, 163, 142, 60, 49, 158, 182, 91, 22, 90, 131, 200, 143, 215, 1, 247, 197, 239, 231, 139, 18, 88, 105, 189, 141, 41, 246, 223, 219, 202, 106, 103, 185, 204, 139, 244, 4, 78, 228, 139, 190, 224, 232, 21, 49, 226, 222, 240, 149, 225, 154, 93, 253, 185, 220, 61, 149, 145, 212, 58, 235, 155, 212, 142, 60, 93, 77, 169, 133, 233, 239, 214, 7, 180, 29, 120, 3, 186, 194, 241, 67, 91, 91, 68, 104, 139, 208, 198, 152, 110, 235, 117, 86, 58, 13, 106, 199, 203, 249, 221, 148, 143, 189, 45, 214, 61, 66, 47, 106, 177, 91, 102, 111, 66, 184, 182, 81, 131, 101, 20, 178, 139, 188, 86, 145, 179, 71, 229, 183, 113, 140, 133, 163, 115, 130, 225, 61, 37, 254, 136, 71, 207, 218, 134, 230, 241, 160, 77, 67, 23, 220, 150, 14, 12, 221, 142, 127, 84, 180, 149, 215, 134, 228, 144, 232, 108, 199, 207, 117, 120, 239, 17, 23, 195, 28, 83, 183, 155, 18, 220, 66, 244, 175, 155, 145, 73, 76, 119, 17, 107, 55, 13, 241, 88, 91, 3, 243, 137, 231, 75, 35, 241, 109, 167, 75, 50, 46, 244, 94, 164, 219, 58, 83, 98, 204, 254, 124, 162, 120, 194, 108, 10, 202, 66, 237, 212, 58, 216, 196, 186, 49, 107, 106, 248, 243, 79, 27, 84, 93, 124, 35, 183, 174, 201, 236, 192, 107, 163, 205, 108, 163, 222, 244, 89, 209, 195, 248, 162, 79, 91, 29, 80, 24, 158, 240, 204, 123, 102, 29, 224, 200, 200, 78, 22, 2, 138, 104, 188, 147, 198, 194, 103, 153, 244, 191, 204, 15, 214, 252, 208, 28, 219, 43, 211, 83, 205, 68, 216, 176, 24, 119, 39, 181, 27, 212, 162, 123, 192, 6, 60, 175, 92, 19, 146, 177, 179, 131, 126, 208, 249, 10, 170, 154, 175, 86, 236, 8, 252, 67, 49, 205, 86, 194, 114, 60, 10, 56, 236, 118, 181, 190, 183, 139, 205, 151, 238, 140, 105, 5, 224, 250, 236, 25, 207, 188, 25, 216, 30, 249, 50, 131, 126, 153, 65, 163, 47, 51, 104, 83, 32, 124, 199, 233, 211, 221, 120, 186, 177, 121, 244, 203, 92, 119, 27, 230, 186, 155, 136, 233, 235, 176, 135, 138, 105, 21, 152, 102, 220, 45, 85, 81, 120, 193, 213, 88, 56, 40, 115, 224, 239, 128, 124, 251, 101, 249, 246, 57, 38, 159, 123, 162, 158, 253, 39, 81, 90, 170, 103, 255, 201, 220, 112, 72, 253, 66, 199, 240, 204, 217, 142, 131, 98, 196, 115, 106, 80, 29, 223, 55, 233, 231, 127, 88, 211, 123, 73, 180, 6, 14, 243, 171, 101, 130, 112, 85, 62, 140, 158, 9, 131, 234, 9, 62, 140, 35, 196, 37, 216, 8, 14, 158, 226, 232, 232, 185, 172, 241, 90, 214, 225, 239, 199, 158, 196, 186, 140, 48, 86, 94, 177, 174, 247, 120, 134, 155, 183, 26, 119, 97, 227, 150, 45, 13, 83, 31, 98, 29, 154, 177, 137, 184, 108, 161, 13, 74, 166, 21, 172, 6, 238, 159, 28, 119, 217, 197, 248, 34, 197, 203, 145, 226, 46, 86, 91, 141, 197, 182, 44, 17, 214, 241, 82, 1, 227, 174, 205, 73, 156, 26, 163, 174, 214, 28, 14, 91, 118, 159, 66, 67, 180, 241, 3, 96, 43, 173, 49, 244, 109, 69, 26, 89, 95, 84, 77, 221, 73, 218, 150, 11, 186, 240, 177, 135, 47, 234, 231, 139, 250, 185, 147, 234, 103, 193, 128, 211, 229, 132, 249, 182, 92, 154, 118, 82, 120, 29, 99, 125, 191, 104, 70, 108, 22, 223, 178, 204, 108, 98, 71, 32, 249, 144, 230, 243, 242, 5, 226, 112, 204, 240, 142, 139, 108, 191, 252, 159, 164, 200, 97, 0, 217, 104, 115, 150, 232, 59, 48, 212, 217, 95, 222, 35, 171, 102, 64, 170, 200, 213, 116, 181, 153, 91, 32, 55, 187, 206, 180, 247, 152, 233, 229, 191, 28, 31, 31, 215, 28, 91, 183, 87, 76, 234, 88, 114, 29, 114, 14, 122, 78, 23, 165, 130, 163, 59, 25, 11, 38, 147, 145, 39, 208, 188, 19, 78, 120, 122, 8, 160, 68, 119, 28, 172, 60, 146, 158, 3, 0, 130, 60, 52, 105, 220, 192, 5, 30, 102, 234, 230, 170, 134, 221, 107, 19, 10, 240, 160, 214, 121, 81, 48, 169, 175, 227, 70, 62, 110, 134, 249, 236, 26, 62, 4, 2, 60, 231, 165, 160, 226, 193, 192, 36, 40, 105, 183, 97, 223, 106, 68, 103, 32, 151, 84, 179, 41, 91, 10, 171, 100, 82, 83, 88, 24, 223, 38, 45, 240, 94, 222, 104, 84, 229, 133, 216, 30, 244, 93, 113, 36, 122, 98, 18, 99, 4, 110, 74, 130, 1, 69, 240, 204, 38, 178, 17, 105, 125, 3, 67, 189, 152, 243, 66, 123, 188, 139, 24, 65, 249, 161, 207, 169, 72, 207, 102, 64, 196, 171, 236, 189, 249, 170, 110, 225, 162, 54, 34, 196, 234, 114, 79, 34, 55, 135, 248, 176, 148, 48, 72, 85, 82, 168, 97, 64, 24, 235, 28, 31, 221, 165, 219, 106, 38, 176, 13, 65, 117, 0, 151, 125, 162, 86, 202, 238, 59, 247, 240, 79, 117, 201, 191, 225, 84, 202, 141, 38, 213, 236, 255, 241, 118, 189, 170, 13, 1, 42, 148, 242, 179, 13, 208, 250, 76, 44, 62, 74, 116, 74, 146, 178, 163, 53, 124, 150, 92, 60, 87, 33, 8, 234, 128, 113, 91, 64, 87, 61, 164, 84, 21, 32, 28, 211, 224, 116, 221, 46, 4, 217, 103, 69, 166, 94, 165, 101, 17, 113, 130, 57, 223, 247, 6, 17, 220, 1, 117, 57, 208, 240, 136, 116, 210, 188, 132, 98, 118, 219, 197, 91, 79, 140, 159, 21, 95, 122, 24, 95, 117, 137, 125, 130, 74, 60, 143, 44, 252, 219, 113, 22, 9, 188, 128, 128, 240, 244, 233, 83, 203, 219, 168, 26, 148, 173, 80, 95, 60, 78, 164, 167, 106, 148, 233, 239, 192, 148, 56, 247, 28, 191, 71, 148, 191, 198, 149, 3, 242, 36, 83, 34, 211, 137, 90, 145, 83, 78, 215, 225, 132, 90, 118, 78, 63, 58, 110, 6, 50, 159, 104, 16, 212, 53, 115, 131, 121, 51, 80, 254, 127, 127, 58, 196, 45, 115, 8, 209, 71, 156, 223, 96, 142, 241, 168, 191, 87, 57, 178, 226, 177, 90, 100, 150, 205, 106, 32, 208, 22, 99, 15, 32, 229, 142, 226, 111, 204, 2, 2, 98, 99, 251, 135, 9, 244, 239, 59, 62, 162, 155, 118, 77, 183, 127, 115, 237, 36, 66, 254, 223, 136, 141, 242, 155, 116, 42, 131, 158, 253, 13, 12, 112, 220, 54, 252, 243, 110, 148, 36, 173, 226, 97, 127, 143, 204, 93, 209, 122, 44, 131, 108, 243, 187, 179, 156, 173, 65, 251, 247, 246, 155, 159, 64, 143, 223, 205, 66, 210, 116, 188, 75, 103, 127, 99, 42, 226, 119, 182, 154, 37, 177, 184, 1, 133, 74, 44, 146, 223, 118, 156, 238, 57, 188, 219, 220, 177, 223, 120, 20, 13, 213, 181, 161, 109, 178, 223, 224, 178, 201, 223, 240, 118, 24, 191, 224, 157, 205, 181, 246, 245, 186, 162, 107, 218, 251, 226, 226, 239, 164, 97, 19, 42, 96, 70, 153, 109, 113, 196, 40, 90, 117, 114, 41, 213, 231, 192, 138, 170, 102, 64, 33, 140, 90, 221, 107, 37, 75, 137, 20, 160, 56, 245, 226, 46, 199, 155, 233, 63, 39, 97, 28, 201, 199, 10, 218, 50, 49, 117, 127, 247, 40, 21, 62, 89, 113, 235, 227, 224, 184, 49, 135, 210, 239, 254, 244, 73, 2, 10, 228, 111, 210, 148, 144, 194, 159, 242, 131, 93, 22, 120, 204, 8, 13, 212, 249, 93, 93, 106, 39, 25, 74, 81, 194, 67, 156, 70, 2, 185, 68, 194, 156, 131, 85, 169, 214, 138, 202, 210, 158, 217, 178, 213, 128, 118, 79, 94, 216, 137, 229, 169, 35, 31, 240, 249, 73, 179, 2, 50, 227, 119, 61, 182, 251, 187, 89, 145, 87, 57, 152, 149, 239, 132, 48, 90, 139, 248, 186, 36, 250, 252, 8, 214, 126, 73, 140, 219, 67, 59, 117, 54, 49, 94, 36, 197, 32, 79, 171, 212, 111, 73, 117, 154, 79, 246, 143, 255, 85, 196, 179, 153, 137, 174, 63, 84, 15, 114, 81, 33, 127, 245, 188, 56, 91, 23, 250, 214, 45, 7, 130, 233, 201, 15, 3, 73, 199, 223, 36, 101, 213, 137, 38, 53, 11, 154, 14, 23, 11, 180, 194, 31, 16, 127, 158, 23, 28, 69, 23, 255, 175, 212, 218, 140, 175, 97, 228, 181, 8, 234, 30, 14, 142, 124, 248, 98, 1, 89, 73, 222, 185, 112, 52, 226, 183, 249, 110, 150, 226, 237, 91, 114, 199, 0, 154, 166, 118, 167, 211, 207, 228, 3, 42, 105, 102, 188, 207, 176, 254, 35, 139, 13, 21, 99, 90, 12, 34, 103, 113, 223, 232, 253, 113, 150, 132, 250, 72, 254, 34, 139, 164, 5, 150, 116, 18, 119, 180, 22, 106, 183, 65, 65, 84, 150, 70, 182, 215, 163, 136, 132, 150, 79, 166, 213, 22, 139, 12, 79, 197, 205, 118, 72, 106, 68, 164, 70, 233, 176, 182, 58, 233, 173, 49, 78, 228, 254, 171, 71, 96, 184, 255, 217, 29, 196, 92, 130, 24, 110, 113, 16, 46, 117, 55, 182, 45, 149, 45, 46, 89, 148, 82, 41, 108, 8, 102, 150, 196, 192, 138, 154, 199, 24, 181, 6, 54, 3, 78, 253, 174, 173, 26, 112, 69, 114, 146, 92, 206, 6, 74, 227, 134, 1, 154, 172, 20, 214, 255, 248, 76, 46, 193, 177, 190, 188, 74, 46, 188, 13, 241, 110, 11, 126, 100, 250, 135, 176, 161, 170, 205, 23, 31, 2, 161, 86, 165, 135, 10, 237, 86, 165, 183, 85, 231, 90, 149, 126, 160, 60, 8, 127, 202, 17, 243, 87, 16, 150, 146, 170, 197, 127, 201, 59, 235, 53, 229, 86, 172, 171, 79, 100, 97, 159, 67, 141, 80, 236, 85, 114, 89, 161, 107, 109, 196, 149, 242, 126, 157, 202, 175, 36, 102, 179, 114, 95, 20, 250, 101, 30, 23, 147, 55, 185, 119, 24, 160, 232, 90, 200, 3, 88, 63, 105, 83, 72, 129, 41, 28, 16, 180, 230, 109, 183, 91, 158, 169, 91, 187, 81, 255, 136, 248, 189, 215, 143, 240, 177, 243, 73, 158, 177, 23, 60, 77, 173, 184, 255, 217, 222, 63, 213, 122, 206, 29, 28, 184, 98, 77, 140, 139, 26, 8, 247, 40, 178, 89, 136, 75, 151, 39, 52, 8, 212, 46, 148, 101, 238, 245, 57, 11, 188, 129, 93, 49, 10, 98, 76, 28, 93, 75, 145, 217, 90, 65, 91, 73, 130, 137, 91, 168, 120, 10, 99, 136, 97, 180, 212, 248, 20, 194, 3, 12, 161, 54, 245, 251, 226, 7, 243, 173, 253, 99, 228, 62, 145, 49, 185, 157, 60, 129, 146, 179, 116, 15, 162, 104, 219, 240, 18, 137, 144, 87, 6, 234, 107, 101, 52, 162, 9, 184, 175, 61, 177, 45, 34, 233, 165, 130, 28, 10, 169, 145, 152, 186, 213, 3, 51, 172, 172, 189, 45, 106, 31, 123, 34, 231, 67, 155, 245, 122, 193, 33, 73, 170, 127, 147, 205, 20, 249, 150, 172, 160, 87, 195, 219, 241, 181, 123, 241, 122, 147, 90, 207, 147, 184, 194, 227, 39, 146, 81, 229, 146, 14, 45, 146, 126, 180, 119, 225, 173, 73, 197, 19, 183, 10, 145, 171, 198, 51, 130, 34, 102, 189, 171, 255, 26, 229, 235, 48, 4, 252, 123, 136, 127, 108, 12, 245, 15, 180, 50, 12, 73, 186, 248, 102, 73, 59, 166, 146, 239, 14, 132, 224, 6, 191, 237, 48, 177, 199, 128, 23, 146, 113, 227, 222, 184, 240, 198, 88, 98, 27, 162, 47, 158, 88, 140, 145, 199, 39, 81, 59, 64, 193, 224, 98, 67, 139, 107, 142, 12, 158, 35, 173, 1, 114, 206, 83, 45, 157, 5, 76, 4, 10, 103, 132, 15, 242, 162, 15, 78, 234, 29, 253, 205, 97, 4, 181, 7, 41, 213, 126, 211, 14, 132, 118, 165, 66, 121, 98, 173, 90, 33, 227, 254, 254, 241, 11, 66, 169, 85, 212, 64, 10, 68, 6, 77, 130, 13, 164, 36, 213, 196, 37, 133, 141, 108, 91, 18, 177, 213, 218, 219, 47, 150, 221, 145, 24, 98, 77, 221, 105, 162, 117, 69, 78, 247, 192, 202, 142, 174, 132, 14, 205, 7, 170, 152, 218, 94, 183, 228, 7, 32, 129, 209, 226, 46, 34, 172, 33, 35, 174, 43, 136, 146, 232, 28, 193, 175, 164, 77, 55, 135, 195, 248, 13, 14, 72, 210, 60, 108, 163, 91, 54, 236, 72, 100, 229, 90, 227, 34, 150, 32, 126, 121, 112, 174, 111, 212, 214, 171, 154, 106, 245, 229, 239, 130, 186, 212, 70, 213, 223, 44, 155, 83, 95, 62, 64, 24, 147, 47, 9, 85, 149, 35, 179, 120, 23, 62, 137, 126, 143, 23, 234, 173, 189, 37, 60, 202, 42, 121, 131, 140, 100, 75, 171, 171, 178, 148, 181, 216, 218, 47, 95, 231, 101, 153, 190, 159, 94, 73, 91, 150, 172, 207, 53, 222, 164, 203, 220, 117, 177, 159, 193, 21, 185, 113, 197, 170, 38, 194, 28, 230, 97, 75, 98, 128, 63, 136, 214, 45, 31, 7, 91, 86, 244, 4, 75, 244, 68, 202, 166, 129, 225, 93, 81, 139, 182, 35, 215, 148, 28, 113, 201, 145, 134, 184, 251, 229, 43, 198, 122, 7, 197, 63, 84, 135, 57, 8, 234, 94, 241, 224, 40, 137, 39, 208, 36, 58, 33, 45, 95, 139, 203, 40, 71, 202, 34, 85, 142, 23, 169, 238, 96, 231, 89, 112, 113, 79, 81, 158, 55, 181, 218, 183, 171, 130, 75, 35, 206, 164, 205, 37, 165, 128, 155, 98, 98, 4, 95, 228, 249, 217, 124, 214, 95, 211, 134, 216, 170, 219, 25, 217, 221, 21, 99, 44, 145, 3, 193, 138, 26, 172, 165, 26, 239, 138, 40, 228, 56, 189, 201, 74, 7, 25, 47, 74, 211, 34, 226, 40, 149, 79, 121, 147, 177, 164, 36, 167, 170, 16, 100, 82, 91, 23, 133, 216, 212, 241, 148, 217, 184, 71, 106, 157, 200, 225, 115, 106, 142, 243, 233, 65, 246, 186, 128, 109, 167, 244, 67, 178, 151, 207, 51, 126, 123, 174, 59, 199, 233, 94, 219, 238, 21, 237, 79, 8, 116, 220, 235, 155, 212, 101, 0, 99, 207, 208, 215, 27, 223, 88, 137, 179, 73, 178, 210, 241, 115, 207, 217, 15, 1, 68, 92, 250, 57, 178, 38, 62, 25, 78, 160, 42, 4, 168, 168, 20, 139, 46, 232, 118, 6, 159, 86, 229, 190, 145, 62, 106, 71, 112, 89, 155, 14, 184, 247, 89, 218, 33, 89, 72, 205, 248, 136, 143, 184, 232, 178, 142, 131, 132, 255, 107, 20, 214, 13, 224, 132, 93, 170, 122, 96, 0, 109, 13, 33, 185, 51, 32, 166, 84, 70, 229, 132, 224, 176, 48, 94, 170, 202, 201, 13, 5, 41, 132, 240, 22, 150, 20, 22, 4, 75, 173, 14, 135, 67, 135, 231, 57, 186, 205, 78, 58, 205, 211, 162, 17, 122, 15, 168, 183, 169, 109, 86, 70, 211, 200, 123, 38, 254, 230, 245, 20, 107, 122, 249, 170, 138, 247, 231, 126, 104, 43, 237, 82, 113, 85, 86, 157, 252, 155, 91, 146, 106, 112, 224, 141, 181, 146, 92, 65, 80, 25, 112, 44, 3, 138, 5, 102, 43, 118, 72, 173, 228, 203, 89, 60, 97, 125, 188, 20, 38, 40, 91, 66, 164, 211, 233, 72, 90, 141, 236, 211, 179, 108, 114, 109, 241, 22, 96, 96, 115, 69, 60, 193, 246, 10, 60, 142, 170, 184, 168, 124, 70, 129, 181, 203, 66, 232, 152, 102, 213, 75, 133, 45, 182, 157, 117, 23, 176, 143, 139, 189, 225, 251, 196, 133, 21, 88, 67, 128, 8, 47, 3, 251, 97, 233, 88, 246, 82, 33, 165, 189, 206, 64, 157, 132, 32, 103, 232, 165, 53, 185, 42, 68, 110, 70, 114, 129, 58, 136, 60, 141, 250, 253, 97, 244, 248, 113, 244, 96, 11, 54, 175, 183, 41, 97, 15, 227, 236, 68, 43, 132, 45, 66, 47, 104, 80, 116, 149, 192, 219, 144, 253, 82, 200, 179, 37, 79, 54, 134, 64, 109, 233, 119, 82, 125, 113, 125, 176, 146, 53, 138, 100, 198, 56, 85, 197, 170, 67, 105, 241, 220, 87, 13, 254, 183, 124, 173, 183, 220, 255, 52, 110, 70, 127, 107, 235, 56, 100, 93, 194, 132, 213, 166, 130, 248, 95, 22, 68, 69, 83, 201, 67, 64, 83, 124, 252, 223, 80, 149, 173, 97, 188, 45, 90, 83, 98, 0, 43, 49, 46, 94, 225, 120, 87, 2, 155, 250, 69, 4, 182, 157, 162, 30, 217, 241, 36, 196, 52, 80, 4, 151, 195, 126, 157, 87, 210, 248, 146, 36, 36, 158, 239, 146, 44, 32, 162, 75, 107, 159, 211, 148, 54, 175, 71, 137, 239, 250, 28, 23, 249, 185, 138, 4, 240, 110, 204, 168, 227, 41, 170, 218, 175, 204, 58, 75, 166, 125, 165, 128, 148, 38, 66, 17, 27, 2, 228, 22, 103, 26, 207, 231, 169, 68, 115, 11, 113, 149, 75, 158, 66, 93, 48, 203, 67, 162, 100, 122, 87, 55, 183, 249, 117, 140, 19, 9, 205, 103, 155, 200, 149, 136, 92, 178, 32, 28, 200, 186, 101, 25, 43, 19, 4, 59, 184, 60, 193, 101, 234, 231, 126, 92, 178, 141, 1, 160, 110, 213, 137, 8, 153, 5, 71, 5, 175, 144, 68, 231, 120, 168, 77, 64, 128, 184, 243, 152, 162, 55, 182, 11, 52, 156, 86, 134, 129, 191, 123, 55, 98, 29, 40, 196, 186, 144, 166, 165, 197, 32, 0, 142, 156, 66, 184, 119, 74, 61, 234, 69, 51, 190, 65, 24, 177, 160, 165, 47, 5, 36, 117, 183, 36, 142, 101, 24, 144, 102, 3, 87, 100, 74, 106, 251, 47, 65, 94, 184, 41, 255, 125, 199, 100, 162, 155, 229, 101, 109, 184, 243, 36, 185, 60, 56, 70, 59, 203, 8, 190, 153, 73, 242, 210, 217, 129, 83, 147, 8, 43, 135, 155, 3, 68, 44, 111, 31, 175, 80, 195, 8, 110, 2, 107, 218, 73, 214, 186, 246, 118, 174, 160, 173, 176, 42, 78, 167, 175, 121, 239, 0, 191, 117, 82, 203, 58, 176, 151, 37, 23, 35, 141, 42, 238, 145, 118, 49, 234, 18, 58, 44, 130, 248, 235, 240, 103, 162, 230, 57, 134, 226, 16, 153, 38, 187, 41, 188, 254, 68, 17, 100, 135, 48, 176, 182, 197, 74, 27, 91, 206, 153, 178, 99, 143, 73, 105, 23, 211, 117, 31, 46, 178, 242, 128, 182, 180, 161, 222, 219, 235, 93, 68, 153, 224, 76, 193, 99, 135, 110, 124, 178, 104, 191, 150, 245, 233, 42, 178, 160, 245, 43, 51, 188, 170, 69, 37, 238, 230, 210, 22, 17, 173, 121, 113, 251, 101, 150, 251, 143, 157, 229, 22, 154, 115, 118, 149, 149, 187, 248, 180, 35, 42, 24, 61, 23, 214, 205, 177, 216, 130, 249, 233, 202, 14, 79, 30, 14, 8, 20, 221, 125, 102, 218, 31, 28, 67, 28, 255, 75, 185, 57, 166, 79, 170, 232, 240, 20, 147, 25, 13, 29, 213, 174, 203, 135, 6, 251, 53, 232, 176, 182, 47, 196, 198, 51, 107, 234, 47, 56, 14, 150, 144, 74, 190, 83, 88, 240, 159, 136, 123, 73, 179, 143, 61, 201, 246, 157, 107, 6, 80, 127, 112, 229, 29, 91, 176, 2, 105, 183, 107, 147, 110, 251, 19, 127, 121, 18, 110, 251, 186, 232, 203, 36, 166, 189, 40, 188, 219, 184, 243, 134, 203, 71, 211, 148, 199, 148, 152, 153, 204, 75, 85, 58, 232, 54, 93, 217, 252, 70, 11, 224, 182, 10, 149, 115, 140, 180, 232, 156, 245, 182, 219, 136, 200, 153, 125, 204, 137, 59, 116, 36, 24, 96, 205, 195, 120, 230, 178, 192, 61, 166, 147, 61, 141, 101, 242, 207, 229, 86, 167, 41, 0, 167, 207, 246, 212, 238, 217, 3, 148, 252, 43, 58, 179, 52, 87, 180, 0, 247, 101, 171, 202, 154, 27, 197, 145, 163, 6, 7, 112, 41, 207, 37, 181, 244, 0, 75, 82, 227, 25, 80, 67, 184, 69, 14, 96, 133, 211, 117, 60, 192, 55, 181, 105, 69, 18, 34, 52, 111, 93, 109, 108, 47, 111, 207, 234, 186, 238, 106, 61, 250, 93, 156, 213, 165, 56, 0, 158, 204, 98, 25, 52, 139, 206, 128, 95, 75, 234, 1, 174, 207, 98, 151, 34, 14, 239, 189, 11, 106, 40, 211, 78, 148, 49, 11, 107, 135, 145, 236, 135, 23, 180, 42, 92, 115, 78, 149, 140, 164, 228, 8, 232, 9, 98, 191, 129, 105, 5, 133, 162, 185, 39, 138, 66, 46, 45, 31, 134, 203, 113, 104, 41, 172, 66, 42, 204, 148, 104, 50, 243, 85, 185, 86, 138, 12, 232, 131, 136, 162, 172, 88, 193, 72, 142, 70, 51, 71, 146, 177, 101, 175, 235, 122, 216, 154, 115, 18, 209, 105, 10, 70, 75, 171, 222, 237, 205, 205, 168, 53, 125, 24, 178, 145, 22, 245, 27, 242, 252, 160, 146, 82, 114, 130, 89, 189, 61, 149, 199, 175, 221, 115, 211, 17, 63, 231, 132, 44, 127, 202, 175, 222, 83, 212, 186, 107, 71, 111, 241, 152, 137, 57, 4, 243, 108, 120, 183, 254, 104, 68, 170, 134, 164, 72, 30, 176, 29, 68, 135, 156, 48, 90, 59, 212, 224, 220, 2, 11, 138, 3, 50, 116, 92, 41, 134, 166, 253, 202, 16, 217, 88, 113, 81, 113, 19, 107, 9, 170, 80, 65, 237, 186, 51, 55, 245, 108, 182, 201, 29, 59, 190, 211, 199, 43, 238, 51, 38, 60, 129, 99, 198, 240, 6, 111, 234, 241, 221, 29, 232, 129, 149, 138, 226, 71, 14, 247, 17, 170, 10, 189, 84, 21, 143, 121, 162, 111, 9, 221, 44, 184, 82, 225, 158, 208, 171, 47, 133, 2, 236, 38, 240, 93, 12, 10, 64, 180, 93, 91, 157, 21, 241, 84, 46, 242, 115, 187, 162, 193, 104, 160, 129, 27, 47, 95, 110, 175, 11, 131, 197, 3, 251, 41, 122, 51, 134, 239, 154, 176, 153, 36, 103, 166, 51, 252, 94, 147, 199, 70, 248, 89, 187, 253, 114, 63, 155, 50, 104, 108, 88, 95, 196, 197, 73, 98, 111, 8, 233, 49, 198, 7, 236, 200, 55, 197, 82, 216, 190, 191, 62, 87, 45, 176, 217, 219, 196, 58, 50, 117, 130, 203, 118, 156, 149, 34, 20, 129, 137, 121, 138, 215, 194, 76, 101, 109, 55, 234, 134, 31, 163, 220, 11, 6, 25, 47, 115, 193, 194, 138, 129, 213, 113, 56, 216, 229, 234, 173, 203, 184, 197, 48, 38, 63, 185, 75, 157, 207, 96, 148, 33, 231, 106, 136, 59, 19, 197, 154, 242, 56, 174, 130, 201, 161, 213, 237, 205, 113, 94, 210, 152, 253, 41, 130, 126, 81, 163, 157, 25, 202, 195, 77, 227, 28, 182, 91, 33, 164, 113, 120, 125, 38, 18, 192, 186, 48, 17, 180, 182, 43, 195, 41, 229, 157, 212, 253, 53, 111, 62, 142, 146, 110, 204, 251, 43, 121, 182, 12, 216, 168, 235, 102, 153, 53, 160, 234, 245, 183, 214, 214, 154, 225, 109, 119, 130, 23, 250, 52, 92, 243, 48, 142, 144, 9, 120, 175, 47, 50, 77, 185, 223, 136, 253, 121, 28, 57, 232, 236, 192, 185, 117, 219, 137, 228, 122, 229, 112, 179, 169, 50, 114, 204, 170, 223, 84, 106, 191, 124, 7, 7, 198, 114, 39, 48, 128, 120, 39, 38, 47, 62, 125, 80, 253, 240, 152, 111, 117, 195, 191, 31, 157, 237, 112, 54, 254, 120, 34, 147, 229, 30, 133, 52, 10, 158, 169, 96, 226, 81, 13, 1, 178, 172, 153, 96, 3, 114, 170, 243, 0, 230, 95, 48, 216, 114, 22, 103, 182, 58, 212, 51, 146, 82, 132, 237, 102, 50, 14, 170, 139, 198, 129, 81, 246, 40, 28, 17, 179, 210, 31, 131, 69, 188, 148, 237, 156, 196, 175, 113, 194, 182, 112, 70, 120, 69, 32, 162, 116, 81, 134, 39, 20, 39, 172, 71, 102, 141, 210, 187, 69, 172, 248, 183, 40, 73, 223, 19, 39, 62, 168, 77, 128, 144, 9, 209, 224, 126, 86, 72, 141, 103, 129, 129, 240, 127, 141, 253, 27, 237, 113, 230, 122, 99, 103, 7, 175, 205, 160, 54, 202, 32, 244, 134, 123, 250, 176, 17, 157, 49, 171, 94, 103, 216, 224, 53, 76, 233, 17, 46, 77, 207, 218, 88, 158, 97, 164, 56, 222, 248, 116, 70, 170, 79, 248, 118, 26, 96, 179, 237, 36, 155, 213, 7, 18, 116, 128, 188, 254, 45, 18, 17, 168, 134, 244, 7, 58, 226, 252, 101, 75, 174, 160, 231, 149, 69, 137, 206, 39, 149, 71, 173, 10, 14, 45, 201, 243, 158, 255, 165, 24, 92, 251, 228, 175, 213, 161, 133, 206, 252, 82, 24, 109, 78, 251, 186, 157, 8, 164, 232, 104, 58, 114, 41, 14, 61, 33, 149, 110, 29, 242, 245, 31, 181, 228, 181, 140, 232, 120, 178, 120, 117, 63, 103, 44, 172, 79, 121, 112, 21, 167, 115, 233, 124, 78, 24, 78, 7, 189, 206, 83, 190, 117, 18, 218, 185, 213, 101, 118, 43, 30, 66, 158, 146, 44, 208, 227, 211, 184, 224, 174, 5, 6, 97, 200, 180, 68, 223, 128, 124, 42, 179, 163, 213, 48, 164, 160, 142, 132, 201, 106, 107, 104, 146, 55, 201, 153, 159, 16, 130, 48, 65, 236, 169, 86, 7, 156, 155, 6, 166, 103, 152, 203, 141, 137, 209, 60, 123, 96, 142, 241, 45, 129, 42, 54, 11, 140, 223, 21, 241, 5, 79, 185, 48, 98, 2, 20, 25, 225, 24, 231, 249, 25, 79, 183, 172, 51, 7, 171, 66, 38, 216, 55, 190, 32, 223, 121, 141, 77, 246, 214, 216, 27, 92, 40, 167, 163, 228, 132, 155, 97, 228, 20, 88, 124, 97, 71, 63, 58, 165, 61, 6, 172, 12, 244, 168, 169, 97, 91, 175, 102, 231, 51, 190, 80, 7, 216, 168, 17, 233, 26, 128, 168, 168, 182, 43, 241, 201, 180, 225, 14, 250, 249, 216, 238, 38, 250, 104, 172, 77, 181, 119, 168, 234, 56, 182, 41, 246, 220, 32, 172, 214, 3, 118, 169, 134, 165, 236, 211, 143, 43, 181, 117, 161, 75, 186, 142, 161, 2, 97, 171, 112, 88, 201, 251, 244, 164, 227, 52, 228, 179, 51, 24, 20, 219, 200, 80, 195, 250, 152, 125, 123, 218, 195, 182, 63, 47, 6, 233, 19, 31, 255, 55, 255, 230, 69, 139, 113, 255, 217, 50, 16, 3, 56, 97, 212, 224, 107, 24, 57, 241, 213, 139, 94, 62, 157, 44, 3, 59, 6, 38, 140, 92, 24, 49, 63, 82, 199, 233, 101, 178, 12, 172, 56, 156, 32, 90, 85, 21, 196, 11, 62, 249, 237, 157, 152, 89, 187, 229, 18, 80, 147, 144, 130, 200, 165, 65, 220, 82, 63, 106, 229, 57, 211, 125, 75, 64, 140, 195, 9, 162, 197, 191, 6, 81, 147, 95, 189, 232, 177, 63, 103, 201, 50, 240, 227, 128, 194, 8, 242, 207, 97, 12, 229, 231, 128, 23, 119, 25, 248, 205, 223, 135, 145, 155, 135, 69, 129, 127, 243, 163, 53, 91, 10, 90, 179, 26, 180, 102, 53, 104, 205, 44, 180, 158, 149, 227, 120, 150, 236, 86, 172, 232, 251, 121, 37, 179, 86, 127, 48, 179, 114, 154, 205, 230, 160, 166, 241, 100, 245, 129, 172, 63, 253, 65, 65, 170, 222, 32, 250, 166, 247, 205, 32, 234, 125, 253, 219, 60, 175, 118, 122, 94, 135, 123, 156, 141, 79, 153, 113, 11, 135, 104, 175, 79, 26, 1, 172, 253, 210, 82, 118, 227, 155, 199, 49, 63, 197, 251, 164, 247, 13, 35, 149, 151, 42, 2, 191, 117, 214, 161, 167, 80, 102, 36, 72, 26, 7, 148, 94, 158, 85, 227, 124, 154, 195, 74, 117, 170, 114, 128, 93, 75, 251, 41, 128, 11, 116, 13, 234, 70, 188, 114, 77, 247, 36, 158, 118, 255, 160, 110, 184, 139, 96, 73, 247, 141, 57, 125, 221, 14, 2, 164, 69, 251, 7, 117, 107, 186, 39, 144, 108, 223, 59, 62, 209, 207, 139, 233, 245, 59, 230, 155, 234, 91, 241, 227, 105, 145, 28, 215, 244, 136, 35, 215, 200, 142, 73, 133, 210, 223, 237, 103, 169, 92, 209, 234, 116, 181, 34, 192, 164, 66, 235, 82, 17, 112, 55, 225, 187, 179, 236, 203, 38, 123, 70, 203, 85, 29, 41, 200, 139, 132, 60, 1, 16, 127, 42, 247, 186, 69, 57, 213, 113, 98, 221, 138, 128, 122, 40, 51, 157, 230, 23, 114, 39, 21, 22, 17, 6, 71, 5, 223, 183, 213, 202, 33, 195, 62, 107, 53, 48, 224, 100, 75, 148, 4, 207, 243, 226, 89, 60, 62, 229, 43, 138, 247, 241, 248, 236, 56, 19, 227, 193, 140, 219, 200, 217, 69, 84, 99, 227, 95, 167, 143, 196, 42, 125, 132, 214, 232, 42, 83, 20, 251, 214, 125, 113, 174, 182, 191, 107, 87, 228, 8, 111, 244, 149, 97, 111, 150, 236, 186, 147, 214, 82, 221, 30, 54, 3, 170, 110, 236, 126, 78, 128, 143, 211, 105, 194, 218, 232, 111, 13, 34, 92, 11, 243, 48, 95, 103, 250, 15, 15, 36, 213, 59, 241, 21, 223, 160, 192, 198, 74, 44, 18, 89, 49, 29, 119, 35, 18, 130, 140, 156, 79, 80, 41, 16, 139, 41, 151, 235, 108, 125, 2, 107, 77, 86, 245, 89, 86, 21, 87, 140, 2, 218, 85, 162, 218, 118, 91, 68, 251, 223, 0, 166, 38, 144, 82, 247, 80, 72, 130, 5, 71, 95, 54, 235, 253, 20, 225, 124, 209, 62, 238, 245, 240, 226, 64, 180, 166, 255, 140, 92, 102, 254, 138, 245, 181, 99, 74, 80, 83, 163, 38, 31, 168, 201, 93, 229, 142, 3, 235, 138, 136, 83, 114, 63, 245, 201, 50, 95, 125, 118, 28, 95, 7, 65, 113, 58, 16, 226, 116, 64, 196, 73, 15, 226, 193, 66, 2, 213, 201, 213, 69, 113, 246, 248, 185, 58, 179, 172, 88, 231, 131, 54, 170, 117, 78, 1, 75, 155, 28, 120, 205, 12, 125, 16, 228, 101, 78, 81, 204, 202, 210, 49, 122, 254, 107, 202, 55, 80, 26, 220, 109, 7, 38, 219, 168, 113, 81, 24, 25, 49, 128, 176, 175, 67, 111, 79, 213, 74, 134, 229, 143, 214, 119, 55, 235, 186, 71, 222, 202, 190, 158, 178, 215, 36, 174, 164, 89, 232, 196, 24, 104, 87, 24, 238, 151, 252, 36, 137, 78, 18, 215, 104, 255, 4, 148, 32, 83, 41, 184, 57, 193, 23, 55, 206, 139, 137, 112, 215, 254, 225, 176, 179, 112, 208, 122, 213, 42, 36, 197, 229, 190, 221, 112, 86, 92, 168, 77, 188, 69, 241, 197, 72, 56, 63, 217, 151, 77, 176, 96, 20, 187, 100, 243, 115, 249, 101, 93, 22, 82, 140, 160, 190, 136, 116, 223, 252, 25, 123, 132, 52, 72, 127, 12, 143, 141, 243, 67, 166, 50, 164, 81, 214, 211, 197, 213, 105, 18, 107, 116, 235, 234, 190, 138, 95, 233, 90, 168, 131, 176, 171, 38, 186, 97, 118, 118, 20, 210, 198, 107, 43, 202, 212, 236, 240, 124, 255, 215, 191, 18, 186, 157, 198, 165, 164, 25, 123, 242, 217, 46, 236, 117, 112, 246, 131, 196, 62, 236, 123, 143, 64, 60, 75, 174, 20, 72, 120, 244, 193, 132, 247, 181, 64, 161, 64, 207, 94, 175, 253, 1, 140, 252, 136, 167, 115, 226, 22, 236, 35, 69, 147, 1, 244, 98, 32, 26, 254, 104, 243, 161, 82, 10, 32, 203, 58, 122, 14, 88, 211, 168, 92, 168, 184, 95, 233, 131, 232, 110, 244, 45, 20, 231, 157, 225, 210, 6, 63, 216, 31, 124, 38, 68, 178, 180, 2, 212, 176, 233, 195, 216, 91, 62, 153, 150, 195, 156, 174, 202, 80, 117, 43, 105, 162, 62, 218, 134, 236, 63, 50, 192, 60, 175, 78, 147, 98, 225, 169, 69, 127, 107, 55, 177, 4, 76, 52, 25, 208, 199, 81, 25, 240, 73, 132, 227, 70, 121, 134, 127, 101, 116, 21, 106, 29, 169, 14, 222, 129, 29, 119, 156, 252, 3, 171, 192, 56, 53, 96, 162, 96, 181, 212, 207, 77, 48, 129, 205, 252, 163, 46, 178, 3, 251, 127, 118, 197, 58, 236, 248, 150, 131, 214, 247, 191, 210, 234, 148, 79, 224, 10, 244, 128, 180, 73, 108, 114, 199, 230, 99, 70, 185, 138, 119, 113, 173, 242, 218, 192, 5, 62, 63, 37, 69, 153, 8, 128, 183, 115, 156, 49, 138, 139, 12, 247, 136, 47, 181, 2, 57, 204, 217, 71, 147, 192, 92, 15, 97, 150, 92, 64, 181, 190, 137, 58, 96, 72, 73, 181, 233, 29, 2, 17, 46, 117, 160, 101, 89, 151, 127, 252, 68, 99, 185, 105, 223, 203, 210, 206, 146, 63, 64, 134, 66, 103, 195, 200, 107, 205, 47, 205, 158, 247, 89, 244, 129, 91, 80, 90, 218, 245, 109, 140, 12, 209, 170, 79, 195, 106, 74, 115, 61, 110, 232, 14, 171, 213, 15, 206, 233, 194, 102, 89, 250, 128, 14, 2, 146, 8, 115, 60, 11, 119, 215, 40, 75, 80, 10, 92, 243, 88, 161, 248, 222, 254, 112, 74, 28, 96, 181, 208, 141, 4, 84, 157, 88, 100, 104, 82, 46, 63, 167, 199, 199, 73, 145, 100, 227, 228, 150, 170, 22, 131, 224, 34, 138, 37, 160, 241, 63, 179, 190, 40, 176, 132, 126, 81, 26, 159, 66, 105, 76, 146, 105, 82, 37, 119, 81, 111, 180, 234, 142, 173, 3, 90, 201, 254, 232, 234, 252, 60, 169, 138, 116, 252, 185, 148, 128, 236, 97, 123, 143, 159, 208, 11, 242, 71, 207, 223, 5, 143, 179, 226, 222, 219, 156, 11, 205, 45, 139, 49, 22, 93, 221, 118, 159, 157, 90, 113, 230, 126, 9, 1, 156, 140, 159, 142, 111, 233, 172, 100, 16, 92, 100, 86, 90, 120, 234, 121, 234, 159, 121, 66, 169, 134, 187, 88, 175, 255, 193, 126, 104, 157, 110, 228, 58, 243, 142, 61, 6, 14, 167, 139, 32, 58, 151, 207, 103, 176, 114, 186, 221, 156, 174, 80, 252, 164, 188, 254, 184, 27, 175, 119, 211, 222, 75, 158, 165, 3, 9, 107, 26, 20, 240, 130, 44, 243, 115, 90, 254, 27, 226, 17, 161, 111, 119, 109, 190, 166, 216, 47, 60, 85, 127, 89, 235, 223, 63, 179, 221, 149, 134, 219, 109, 151, 47, 184, 158, 111, 232, 102, 141, 240, 255, 51, 77, 46, 146, 201, 110, 81, 196, 87, 63, 205, 193, 218, 221, 63, 62, 76, 210, 227, 20, 66, 46, 98, 120, 43, 154, 209, 233, 99, 223, 207, 143, 163, 208, 213, 81, 162, 130, 138, 66, 199, 231, 246, 180, 194, 96, 213, 225, 90, 55, 128, 162, 174, 178, 33, 119, 34, 252, 156, 84, 241, 248, 52, 153, 8, 92, 160, 248, 113, 130, 34, 122, 196, 239, 144, 90, 33, 234, 123, 71, 137, 169, 174, 164, 84, 20, 234, 172, 106, 32, 168, 169, 156, 25, 161, 229, 149, 81, 2, 238, 32, 122, 128, 3, 77, 240, 61, 79, 226, 230, 233, 45, 123, 183, 97, 183, 18, 253, 199, 56, 226, 113, 144, 67, 32, 250, 211, 60, 118, 138, 6, 33, 194, 6, 246, 25, 190, 151, 23, 88, 33, 198, 17, 21, 90, 160, 43, 5, 133, 108, 152, 135, 58, 38, 2, 113, 112, 136, 92, 86, 206, 139, 4, 16, 17, 5, 65, 114, 112, 141, 184, 56, 193, 65, 66, 230, 182, 9, 153, 96, 193, 212, 228, 47, 85, 247, 2, 237, 67, 145, 29, 52, 218, 170, 203, 238, 244, 4, 147, 147, 129, 237, 157, 163, 98, 21, 33, 210, 171, 163, 11, 76, 78, 180, 203, 6, 172, 231, 10, 77, 189, 245, 169, 229, 111, 44, 14, 224, 192, 238, 216, 216, 20, 84, 227, 60, 110, 58, 173, 143, 128, 195, 117, 168, 134, 92, 120, 63, 148, 206, 241, 99, 156, 201, 193, 179, 209, 218, 203, 121, 185, 111, 202, 232, 27, 132, 209, 55, 209, 76, 222, 191, 75, 237, 59, 62, 21, 178, 239, 158, 235, 73, 100, 140, 4, 186, 160, 196, 147, 115, 195, 78, 148, 214, 186, 67, 251, 132, 176, 14, 156, 82, 149, 245, 109, 185, 13, 229, 49, 171, 222, 223, 254, 38, 145, 212, 189, 139, 196, 94, 178, 32, 0, 234, 191, 59, 208, 76, 107, 167, 147, 184, 74, 44, 28, 93, 118, 198, 27, 219, 226, 131, 85, 197, 104, 254, 0, 99, 171, 190, 83, 214, 198, 25, 38, 156, 235, 91, 130, 77, 64, 233, 96, 217, 191, 199, 182, 98, 161, 149, 131, 154, 5, 155, 13, 54, 134, 158, 81, 248, 126, 123, 43, 36, 53, 34, 92, 6, 20, 133, 60, 108, 129, 6, 129, 30, 254, 23, 243, 244, 133, 169, 26, 213, 92, 160, 202, 177, 193, 160, 252, 47, 244, 173, 110, 188, 87, 158, 33, 38, 13, 154, 179, 51, 252, 172, 110, 144, 172, 178, 39, 110, 93, 126, 46, 38, 129, 35, 152, 52, 107, 153, 67, 174, 161, 234, 186, 57, 237, 138, 148, 57, 1, 220, 72, 87, 57, 178, 132, 174, 106, 126, 123, 127, 85, 37, 7, 199, 199, 220, 250, 186, 105, 90, 203, 54, 197, 179, 105, 119, 209, 113, 232, 78, 253, 133, 168, 199, 204, 2, 145, 241, 167, 29, 25, 63, 53, 249, 110, 15, 201, 212, 244, 103, 203, 115, 114, 153, 156, 207, 166, 177, 71, 152, 225, 222, 233, 218, 233, 83, 85, 197, 168, 212, 104, 142, 61, 221, 68, 91, 20, 229, 152, 50, 232, 26, 203, 21, 76, 105, 202, 166, 146, 73, 111, 160, 3, 18, 143, 189, 90, 193, 108, 219, 41, 155, 99, 91, 244, 238, 38, 250, 100, 163, 225, 237, 92, 168, 83, 176, 206, 53, 113, 155, 182, 19, 163, 201, 204, 60, 104, 197, 237, 7, 184, 7, 2, 111, 254, 25, 135, 17, 110, 7, 17, 252, 144, 20, 87, 40, 48, 53, 186, 14, 166, 237, 167, 20, 227, 189, 104, 200, 41, 98, 27, 122, 223, 241, 211, 219, 189, 255, 50, 16, 255, 107, 115, 166, 114, 254, 109, 38, 208, 155, 158, 109, 64, 222, 80, 32, 180, 137, 38, 119, 251, 240, 52, 26, 178, 229, 37, 77, 45, 18, 161, 136, 80, 226, 166, 59, 139, 120, 54, 145, 51, 49, 157, 178, 7, 154, 63, 228, 76, 38, 161, 143, 14, 142, 206, 222, 26, 255, 76, 149, 148, 38, 143, 97, 235, 104, 227, 51, 153, 112, 248, 204, 56, 123, 56, 149, 12, 180, 5, 92, 120, 163, 154, 99, 194, 22, 171, 225, 224, 97, 243, 233, 57, 51, 192, 97, 78, 186, 39, 108, 120, 204, 187, 243, 169, 248, 240, 205, 194, 28, 40, 92, 77, 51, 25, 113, 244, 238, 69, 90, 162, 144, 163, 113, 60, 99, 131, 204, 143, 103, 111, 93, 147, 93, 67, 62, 52, 204, 161, 111, 44, 222, 52, 108, 8, 24, 30, 41, 108, 214, 215, 193, 65, 39, 74, 82, 158, 132, 182, 119, 189, 74, 223, 158, 95, 15, 6, 186, 115, 150, 191, 92, 244, 12, 236, 90, 85, 128, 253, 50, 221, 219, 61, 202, 120, 235, 128, 80, 102, 167, 155, 219, 109, 47, 9, 130, 221, 67, 162, 144, 77, 250, 51, 214, 114, 10, 151, 235, 220, 117, 57, 200, 38, 97, 41, 208, 157, 236, 34, 4, 168, 210, 45, 209, 197, 33, 230, 214, 152, 134, 180, 175, 163, 104, 125, 92, 45, 63, 33, 100, 219, 51, 25, 79, 144, 20, 96, 49, 113, 169, 237, 93, 225, 51, 73, 39, 198, 110, 242, 105, 75, 239, 187, 212, 176, 30, 239, 99, 195, 217, 168, 187, 198, 132, 93, 184, 13, 120, 52, 200, 107, 94, 54, 219, 24, 118, 227, 47, 117, 183, 178, 143, 201, 156, 243, 119, 183, 156, 199, 148, 46, 51, 0, 49, 59, 201, 131, 118, 247, 200, 180, 108, 109, 50, 34, 54, 178, 166, 188, 69, 180, 146, 32, 164, 159, 103, 126, 77, 174, 62, 255, 82, 41, 232, 225, 123, 25, 207, 238, 30, 55, 7, 212, 227, 121, 60, 187, 27, 230, 105, 107, 139, 78, 185, 23, 219, 206, 228, 231, 156, 222, 106, 58, 111, 97, 157, 90, 98, 0, 214, 224, 25, 88, 131, 8, 208, 226, 22, 33, 227, 45, 191, 72, 28, 38, 147, 249, 56, 185, 55, 124, 87, 240, 238, 124, 10, 214, 83, 46, 106, 142, 44, 236, 202, 53, 228, 33, 181, 251, 177, 77, 152, 248, 44, 66, 247, 201, 196, 227, 241, 252, 124, 62, 149, 57, 232, 90, 243, 54, 99, 32, 182, 122, 209, 60, 234, 103, 77, 10, 187, 230, 94, 22, 247, 124, 184, 115, 35, 11, 130, 165, 94, 113, 38, 86, 235, 42, 253, 146, 154, 72, 146, 123, 81, 237, 128, 66, 20, 188, 121, 152, 158, 156, 86, 119, 135, 65, 187, 155, 146, 133, 233, 230, 39, 59, 104, 191, 124, 238, 5, 104, 27, 34, 159, 228, 245, 120, 120, 99, 131, 242, 240, 83, 161, 102, 55, 54, 238, 34, 11, 143, 188, 57, 115, 219, 4, 155, 173, 146, 237, 208, 3, 123, 31, 55, 20, 90, 214, 176, 123, 207, 122, 98, 174, 143, 2, 164, 228, 15, 200, 76, 173, 216, 212, 194, 222, 226, 201, 192, 86, 172, 45, 94, 1, 121, 18, 65, 221, 140, 98, 233, 135, 164, 41, 91, 239, 153, 76, 132, 75, 203, 55, 164, 221, 37, 133, 195, 185, 119, 173, 98, 56, 83, 174, 250, 116, 141, 52, 247, 22, 226, 50, 141, 111, 27, 180, 101, 70, 223, 122, 164, 157, 228, 190, 99, 153, 249, 209, 205, 87, 207, 68, 242, 12, 167, 203, 108, 239, 192, 34, 201, 112, 69, 3, 79, 141, 210, 227, 33, 14, 192, 29, 19, 2, 240, 167, 180, 186, 72, 203, 68, 112, 61, 131, 178, 203, 13, 26, 3, 75, 178, 186, 168, 105, 214, 140, 146, 104, 158, 244, 252, 3, 31, 35, 233, 157, 117, 227, 83, 147, 47, 100, 128, 32, 76, 124, 188, 58, 222, 161, 223, 61, 202, 132, 115, 207, 204, 147, 240, 207, 27, 62, 182, 27, 18, 231, 252, 252, 254, 216, 74, 37, 235, 204, 125, 90, 112, 126, 170, 189, 140, 154, 173, 12, 147, 235, 213, 98, 40, 185, 199, 209, 214, 92, 7, 62, 243, 219, 235, 111, 242, 23, 57, 67, 86, 221, 207, 59, 229, 63, 32, 216, 8, 37, 3, 201, 103, 80, 137, 188, 52, 140, 26, 203, 109, 246, 182, 204, 106, 2, 236, 218, 51, 44, 13, 202, 211, 118, 134, 53, 133, 153, 52, 168, 66, 113, 22, 101, 245, 108, 170, 110, 16, 228, 32, 100, 40, 173, 14, 10, 35, 23, 185, 172, 168, 41, 222, 30, 75, 12, 105, 179, 34, 244, 26, 144, 102, 200, 181, 190, 232, 22, 152, 168, 55, 232, 57, 76, 55, 244, 51, 221, 33, 191, 224, 79, 213, 53, 28, 7, 241, 171, 118, 111, 176, 71, 151, 124, 247, 39, 206, 24, 179, 126, 165, 25, 102, 40, 157, 238, 228, 144, 164, 69, 245, 17, 1, 193, 119, 104, 128, 190, 173, 217, 38, 205, 97, 72, 243, 205, 223, 243, 78, 244, 223, 39, 39, 105, 102, 217, 50, 109, 146, 80, 175, 6, 195, 187, 174, 107, 209, 224, 152, 121, 129, 93, 189, 81, 35, 123, 226, 137, 159, 111, 19, 113, 170, 98, 206, 106, 194, 116, 53, 24, 52, 49, 210, 128, 53, 29, 37, 88, 140, 245, 181, 33, 182, 20, 253, 79, 82, 228, 7, 217, 193, 188, 58, 56, 254, 137, 77, 160, 147, 82, 215, 150, 53, 127, 210, 209, 1, 180, 41, 253, 154, 84, 80, 198, 195, 79, 64, 33, 98, 117, 113, 154, 233, 114, 252, 151, 204, 17, 76, 172, 24, 81, 49, 104, 199, 152, 174, 172, 211, 42, 205, 246, 140, 44, 166, 33, 104, 92, 18, 193, 164, 42, 159, 139, 217, 233, 53, 239, 73, 31, 57, 238, 132, 44, 148, 76, 235, 184, 119, 223, 98, 240, 106, 68, 93, 115, 143, 173, 141, 76, 195, 251, 229, 238, 188, 82, 217, 159, 61, 60, 220, 45, 218, 4, 254, 65, 150, 22, 197, 187, 40, 112, 41, 178, 251, 226, 50, 107, 179, 157, 106, 134, 36, 100, 173, 38, 210, 197, 222, 197, 96, 245, 13, 116, 123, 179, 213, 29, 228, 44, 185, 240, 92, 157, 35, 110, 203, 17, 200, 109, 160, 97, 179, 18, 230, 183, 138, 89, 66, 84, 38, 193, 97, 148, 194, 226, 165, 198, 102, 37, 28, 192, 188, 91, 137, 188, 239, 183, 69, 1, 34, 30, 226, 120, 121, 148, 222, 174, 237, 90, 104, 136, 168, 173, 89, 200, 249, 148, 138, 202, 41, 110, 184, 140, 166, 167, 63, 83, 100, 161, 21, 158, 34, 163, 0, 230, 88, 242, 149, 99, 138, 15, 174, 40, 47, 195, 186, 167, 156, 4, 127, 198, 175, 75, 97, 196, 230, 110, 3, 88, 34, 81, 18, 19, 155, 18, 205, 122, 172, 79, 124, 118, 110, 107, 159, 237, 86, 126, 235, 12, 246, 172, 224, 98, 220, 59, 179, 241, 217, 98, 131, 29, 250, 115, 7, 55, 217, 149, 63, 202, 231, 65, 186, 131, 59, 237, 48, 10, 245, 60, 247, 159, 176, 227, 174, 251, 121, 87, 119, 221, 235, 184, 242, 118, 109, 189, 107, 82, 99, 174, 251, 202, 148, 225, 28, 254, 249, 119, 83, 135, 107, 254, 12, 165, 54, 162, 76, 199, 137, 35, 160, 61, 191, 20, 141, 248, 69, 34, 252, 84, 112, 153, 207, 139, 49, 35, 246, 121, 60, 59, 206, 232, 202, 186, 54, 193, 239, 158, 107, 2, 224, 120, 224, 189, 32, 47, 62, 212, 137, 141, 247, 8, 231, 193, 206, 159, 188, 160, 13, 224, 9, 124, 188, 23, 182, 218, 252, 207, 139, 34, 206, 104, 226, 254, 161, 236, 45, 189, 135, 67, 182, 31, 153, 59, 108, 200, 124, 108, 62, 59, 167, 7, 223, 72, 82, 48, 216, 74, 157, 204, 75, 116, 155, 11, 152, 122, 156, 202, 158, 227, 81, 250, 38, 39, 115, 62, 138, 214, 93, 181, 237, 115, 247, 51, 94, 141, 217, 180, 33, 165, 195, 52, 250, 203, 208, 213, 16, 2, 103, 74, 36, 14, 94, 145, 194, 58, 156, 71, 135, 95, 222, 141, 44, 47, 15, 150, 160, 200, 249, 35, 249, 24, 217, 196, 98, 61, 114, 24, 90, 93, 216, 12, 255, 136, 101, 41, 33, 227, 239, 68, 106, 252, 55, 152, 203, 178, 216, 97, 26, 48, 17, 37, 252, 29, 93, 174, 198, 86, 244, 150, 173, 64, 235, 192, 233, 249, 186, 195, 30, 123, 131, 104, 207, 56, 185, 197, 191, 54, 78, 64, 241, 79, 55, 33, 182, 208, 37, 175, 157, 189, 53, 176, 62, 234, 39, 229, 186, 83, 85, 168, 99, 184, 121, 96, 130, 99, 242, 58, 30, 159, 45, 125, 80, 58, 18, 80, 180, 139, 47, 41, 146, 204, 110, 150, 180, 89, 202, 211, 9, 96, 108, 117, 3, 154, 229, 119, 90, 146, 203, 74, 46, 2, 62, 200, 125, 153, 119, 253, 77, 206, 227, 127, 149, 118, 165, 98, 104, 28, 103, 130, 147, 68, 109, 116, 61, 151, 219, 115, 36, 102, 254, 3, 46, 18, 104, 59, 174, 33, 38, 161, 104, 29, 241, 139, 27, 208, 33, 37, 94, 147, 229, 71, 175, 43, 146, 43, 85, 26, 123, 188, 166, 171, 60, 34, 102, 162, 195, 180, 86, 220, 135, 162, 173, 143, 254, 74, 237, 114, 191, 214, 139, 244, 76, 100, 191, 165, 154, 198, 90, 213, 41, 39, 134, 174, 130, 121, 100, 49, 82, 119, 246, 209, 235, 182, 137, 175, 190, 142, 206, 157, 169, 76, 105, 92, 79, 97, 124, 240, 192, 80, 215, 239, 13, 229, 214, 194, 193, 113, 31, 89, 217, 130, 176, 238, 117, 173, 55, 101, 29, 100, 201, 197, 178, 71, 71, 128, 20, 196, 193, 70, 237, 153, 237, 37, 22, 5, 9, 113, 208, 4, 213, 49, 153, 188, 83, 177, 38, 167, 188, 73, 161, 64, 181, 10, 100, 20, 103, 245, 206, 185, 131, 196, 58, 74, 142, 238, 115, 244, 114, 15, 175, 51, 224, 217, 205, 205, 85, 196, 198, 127, 147, 218, 166, 130, 109, 40, 60, 176, 134, 229, 82, 38, 119, 97, 237, 169, 186, 36, 169, 153, 214, 140, 71, 111, 53, 138, 106, 19, 51, 144, 19, 42, 19, 57, 210, 66, 142, 254, 151, 166, 11, 88, 157, 210, 126, 88, 25, 56, 236, 94, 64, 106, 109, 40, 210, 115, 172, 27, 120, 187, 217, 144, 78, 234, 103, 110, 141, 253, 28, 87, 241, 107, 121, 96, 92, 103, 92, 73, 215, 215, 197, 150, 195, 166, 73, 27, 136, 88, 73, 20, 163, 172, 132, 204, 141, 142, 188, 228, 214, 108, 195, 76, 95, 141, 78, 227, 130, 88, 57, 93, 239, 67, 8, 212, 111, 211, 184, 45, 190, 35, 6, 17, 222, 5, 14, 132, 154, 12, 9, 70, 123, 48, 214, 8, 230, 7, 232, 120, 54, 212, 119, 170, 60, 160, 4, 223, 228, 163, 188, 168, 146, 73, 159, 223, 79, 83, 36, 199, 153, 57, 228, 175, 95, 181, 91, 175, 24, 8, 237, 215, 44, 176, 219, 108, 170, 209, 53, 239, 167, 241, 122, 184, 1, 21, 214, 8, 118, 12, 27, 149, 1, 159, 202, 33, 133, 227, 180, 158, 154, 80, 44, 39, 109, 142, 105, 254, 93, 153, 67, 52, 203, 46, 166, 140, 37, 110, 52, 178, 225, 95, 76, 140, 95, 198, 179, 230, 235, 124, 216, 84, 137, 200, 201, 109, 13, 121, 157, 15, 251, 2, 73, 137, 240, 180, 22, 47, 239, 58, 31, 166, 230, 207, 219, 221, 230, 227, 42, 59, 168, 27, 230, 167, 135, 223, 49, 225, 148, 253, 167, 58, 207, 167, 101, 229, 189, 64, 172, 179, 3, 141, 23, 191, 85, 66, 255, 24, 170, 251, 40, 45, 242, 142, 254, 83, 111, 75, 250, 255, 46, 4, 227, 16 }; static const unsigned char * const compressedSources = reinterpret_cast(data); uint32_t GetCompressedSize() { - return 20960; + return 19520; } uint32_t GetRawScriptsSize() { - return 144873; + return 134068; } } // selfhosted } // js